diff --git a/ssh.h b/ssh.h index 03c3294f..afb2c606 100644 --- a/ssh.h +++ b/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; diff --git a/test/cryptsuite.py b/test/cryptsuite.py index f8815fde..65a413a7 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -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 diff --git a/testcrypt.c b/testcrypt.c index 16494fa4..30f068e7 100644 --- a/testcrypt.c +++ b/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},