mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
testcrypt: test both hardware and software AES.
The new explicit vtables for the hardware and software implementations are now exposed by name in the testcrypt protocol, and cryptsuite.py runs all the AES tests separately on both. (When hardware AES is compiled out, ssh2_cipher_new("aes128_hw") and similar calls will return None, and cryptsuite.py will respond by skipping those tests.)
This commit is contained in:
parent
dfdb73e103
commit
c507e9c964
12
ssh.h
12
ssh.h
@ -860,11 +860,23 @@ extern const ssh2_cipheralg ssh_3des_ssh2;
|
||||
extern const ssh2_cipheralg ssh_des_ssh2;
|
||||
extern const ssh2_cipheralg ssh_des_sshcom_ssh2;
|
||||
extern const ssh2_cipheralg ssh_aes256_sdctr;
|
||||
extern const ssh2_cipheralg ssh_aes256_sdctr_hw;
|
||||
extern const ssh2_cipheralg ssh_aes256_sdctr_sw;
|
||||
extern const ssh2_cipheralg ssh_aes256_cbc;
|
||||
extern const ssh2_cipheralg ssh_aes256_cbc_hw;
|
||||
extern const ssh2_cipheralg ssh_aes256_cbc_sw;
|
||||
extern const ssh2_cipheralg ssh_aes192_sdctr;
|
||||
extern const ssh2_cipheralg ssh_aes192_sdctr_hw;
|
||||
extern const ssh2_cipheralg ssh_aes192_sdctr_sw;
|
||||
extern const ssh2_cipheralg ssh_aes192_cbc;
|
||||
extern const ssh2_cipheralg ssh_aes192_cbc_hw;
|
||||
extern const ssh2_cipheralg ssh_aes192_cbc_sw;
|
||||
extern const ssh2_cipheralg ssh_aes128_sdctr;
|
||||
extern const ssh2_cipheralg ssh_aes128_sdctr_hw;
|
||||
extern const ssh2_cipheralg ssh_aes128_sdctr_sw;
|
||||
extern const ssh2_cipheralg ssh_aes128_cbc;
|
||||
extern const ssh2_cipheralg ssh_aes128_cbc_hw;
|
||||
extern const ssh2_cipheralg ssh_aes128_cbc_sw;
|
||||
extern const ssh2_cipheralg ssh_blowfish_ssh2_ctr;
|
||||
extern const ssh2_cipheralg ssh_blowfish_ssh2;
|
||||
extern const ssh2_cipheralg ssh_arcfour256_ssh2;
|
||||
|
@ -768,12 +768,16 @@ class crypt(MyTestBase):
|
||||
# independent in that it was written by me.)
|
||||
|
||||
def vector(cipher, key, iv, plaintext, ciphertext):
|
||||
c = ssh2_cipher_new(cipher)
|
||||
ssh2_cipher_setkey(c, key)
|
||||
ssh2_cipher_setiv(c, iv)
|
||||
self.assertEqualBin(ssh2_cipher_encrypt(c, plaintext), ciphertext)
|
||||
ssh2_cipher_setiv(c, iv)
|
||||
self.assertEqualBin(ssh2_cipher_decrypt(c, ciphertext), plaintext)
|
||||
for suffix in "hw", "sw":
|
||||
c = ssh2_cipher_new("{}_{}".format(cipher, suffix))
|
||||
if c is None: return # skip test if HW AES not available
|
||||
ssh2_cipher_setkey(c, key)
|
||||
ssh2_cipher_setiv(c, iv)
|
||||
self.assertEqualBin(
|
||||
ssh2_cipher_encrypt(c, plaintext), ciphertext)
|
||||
ssh2_cipher_setiv(c, iv)
|
||||
self.assertEqualBin(
|
||||
ssh2_cipher_decrypt(c, ciphertext), plaintext)
|
||||
|
||||
# Tests of CBC mode.
|
||||
|
||||
@ -848,11 +852,12 @@ class crypt(MyTestBase):
|
||||
# feeding them to an AES-CBC cipher object with its IV set to
|
||||
# zero.
|
||||
|
||||
def increment(keylen, iv):
|
||||
def increment(keylen, suffix, iv):
|
||||
key = b'\xab' * (keylen//8)
|
||||
sdctr = ssh2_cipher_new("aes{}_ctr".format(keylen))
|
||||
sdctr = ssh2_cipher_new("aes{}_ctr_{}".format(keylen, suffix))
|
||||
if sdctr is None: return # skip test if HW AES not available
|
||||
ssh2_cipher_setkey(sdctr, key)
|
||||
cbc = ssh2_cipher_new("aes{}".format(keylen))
|
||||
cbc = ssh2_cipher_new("aes{}_{}".format(keylen, suffix))
|
||||
ssh2_cipher_setkey(cbc, key)
|
||||
|
||||
ssh2_cipher_setiv(sdctr, iv)
|
||||
@ -865,14 +870,15 @@ class crypt(MyTestBase):
|
||||
self.assertEqualBin(iv, dc0)
|
||||
return dc1
|
||||
|
||||
def test(keylen, ivInteger):
|
||||
def test(keylen, suffix, ivInteger):
|
||||
mask = (1 << 128) - 1
|
||||
ivInteger &= mask
|
||||
ivBinary = unhex("{:032x}".format(ivInteger))
|
||||
ivIntegerInc = (ivInteger + 1) & mask
|
||||
ivBinaryInc = unhex("{:032x}".format((ivIntegerInc)))
|
||||
actualResult = increment(keylen, ivBinary)
|
||||
self.assertEqualBin(actualResult, ivBinaryInc)
|
||||
actualResult = increment(keylen, suffix, ivBinary)
|
||||
if actualResult is not None:
|
||||
self.assertEqualBin(actualResult, ivBinaryInc)
|
||||
|
||||
# Check every input IV you can make by gluing together 32-bit
|
||||
# pieces of the form 0, 1 or -1. This should test all the
|
||||
@ -882,29 +888,34 @@ class crypt(MyTestBase):
|
||||
# We also test this at all three AES key lengths, in case the
|
||||
# core cipher routines are written separately for each one.
|
||||
|
||||
for keylen in [128, 192, 256]:
|
||||
hexTestValues = ["00000000", "00000001", "ffffffff"]
|
||||
for ivHexBytes in itertools.product(*([hexTestValues] * 4)):
|
||||
ivInteger = int("".join(ivHexBytes), 16)
|
||||
test(keylen, ivInteger)
|
||||
for suffix in "hw", "sw":
|
||||
for keylen in [128, 192, 256]:
|
||||
hexTestValues = ["00000000", "00000001", "ffffffff"]
|
||||
for ivHexBytes in itertools.product(*([hexTestValues] * 4)):
|
||||
ivInteger = int("".join(ivHexBytes), 16)
|
||||
test(keylen, suffix, ivInteger)
|
||||
|
||||
class standard_test_vectors(MyTestBase):
|
||||
def testAES(self):
|
||||
def vector(cipher, key, plaintext, ciphertext):
|
||||
c = ssh2_cipher_new(cipher)
|
||||
ssh2_cipher_setkey(c, key)
|
||||
for suffix in "hw", "sw":
|
||||
c = ssh2_cipher_new("{}_{}".format(cipher, suffix))
|
||||
if c is None: return # skip test if HW AES not available
|
||||
ssh2_cipher_setkey(c, key)
|
||||
|
||||
# The AES test vectors are implicitly in ECB mode, because
|
||||
# they're testing the cipher primitive rather than any
|
||||
# mode layered on top of it. We fake this by using PuTTY's
|
||||
# CBC setting, and clearing the IV to all zeroes before
|
||||
# each operation.
|
||||
# The AES test vectors are implicitly in ECB mode,
|
||||
# because they're testing the cipher primitive rather
|
||||
# than any mode layered on top of it. We fake this by
|
||||
# using PuTTY's CBC setting, and clearing the IV to
|
||||
# all zeroes before each operation.
|
||||
|
||||
ssh2_cipher_setiv(c, b'\x00' * 16)
|
||||
self.assertEqualBin(ssh2_cipher_encrypt(c, plaintext), ciphertext)
|
||||
ssh2_cipher_setiv(c, b'\x00' * 16)
|
||||
self.assertEqualBin(
|
||||
ssh2_cipher_encrypt(c, plaintext), ciphertext)
|
||||
|
||||
ssh2_cipher_setiv(c, b'\x00' * 16)
|
||||
self.assertEqualBin(ssh2_cipher_decrypt(c, ciphertext), plaintext)
|
||||
ssh2_cipher_setiv(c, b'\x00' * 16)
|
||||
self.assertEqualBin(
|
||||
ssh2_cipher_decrypt(c, ciphertext), plaintext)
|
||||
|
||||
# The test vectors from FIPS 197 appendix C: the key bytes go
|
||||
# 00 01 02 03 ... for as long as needed, and the plaintext
|
||||
|
12
testcrypt.c
12
testcrypt.c
@ -270,11 +270,23 @@ static const ssh2_cipheralg *get_ssh2_cipheralg(BinarySource *in)
|
||||
{"des", &ssh_des_ssh2},
|
||||
{"des_sshcom", &ssh_des_sshcom_ssh2},
|
||||
{"aes256_ctr", &ssh_aes256_sdctr},
|
||||
{"aes256_ctr_hw", &ssh_aes256_sdctr_hw},
|
||||
{"aes256_ctr_sw", &ssh_aes256_sdctr_sw},
|
||||
{"aes256", &ssh_aes256_cbc},
|
||||
{"aes256_hw", &ssh_aes256_cbc_hw},
|
||||
{"aes256_sw", &ssh_aes256_cbc_sw},
|
||||
{"aes192_ctr", &ssh_aes192_sdctr},
|
||||
{"aes192_ctr_hw", &ssh_aes192_sdctr_hw},
|
||||
{"aes192_ctr_sw", &ssh_aes192_sdctr_sw},
|
||||
{"aes192", &ssh_aes192_cbc},
|
||||
{"aes192_hw", &ssh_aes192_cbc_hw},
|
||||
{"aes192_sw", &ssh_aes192_cbc_sw},
|
||||
{"aes128_ctr", &ssh_aes128_sdctr},
|
||||
{"aes128_ctr_hw", &ssh_aes128_sdctr_hw},
|
||||
{"aes128_ctr_sw", &ssh_aes128_sdctr_sw},
|
||||
{"aes128", &ssh_aes128_cbc},
|
||||
{"aes128_hw", &ssh_aes128_cbc_hw},
|
||||
{"aes128_sw", &ssh_aes128_cbc_sw},
|
||||
{"blowfish", &ssh_blowfish_ssh2_ctr},
|
||||
{"blowfish", &ssh_blowfish_ssh2},
|
||||
{"arcfour256", &ssh_arcfour256_ssh2},
|
||||
|
Loading…
Reference in New Issue
Block a user