1
0
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:
Simon Tatham 2019-01-13 13:48:19 +00:00
parent dfdb73e103
commit c507e9c964
3 changed files with 63 additions and 28 deletions

12
ssh.h
View File

@ -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;

View File

@ -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

View File

@ -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},