diff --git a/src/hsm/cmd_cipher_sym.c b/src/hsm/cmd_cipher_sym.c index b929c0a..dbb29fd 100644 --- a/src/hsm/cmd_cipher_sym.c +++ b/src/hsm/cmd_cipher_sym.c @@ -458,9 +458,9 @@ int cmd_cipher_sym() { uint8_t aes_algo = oid[8], mode = (algo == ALGO_EXT_CIPHER_ENCRYPT ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT); - if ((aes_algo >= 0x01 && aes_algo <= 0x06 && key_size != 16) || - (aes_algo >= 0x15 && aes_algo <= 0x1A && key_size != 24) || - (aes_algo >= 0x29 && aes_algo <= 0x2E && key_size != 32)) { + if ((aes_algo >= 0x01 && aes_algo <= 0x09 && key_size != 16) || + (aes_algo >= 0x15 && aes_algo <= 0x1D && key_size != 24) || + (aes_algo >= 0x29 && aes_algo <= 0x31 && key_size != 32)) { return SW_WRONG_DATA(); } mbedtls_aes_context ctx; @@ -565,6 +565,18 @@ int cmd_cipher_sym() { return SW_EXEC_ERROR(); } } + else if (aes_algo == 0x09 || aes_algo == 0x1D || aes_algo == 0x31) { /* CTR */ + size_t iv_off = 0; + uint8_t stream_block[16]; + r = mbedtls_aes_setkey_enc(&ctx, kdata, key_size * 8); + mbedtls_platform_zeroize(kdata, sizeof(kdata)); + r = mbedtls_aes_crypt_ctr(&ctx, enc_len, &iv_off, iv, stream_block, enc, res_APDU); + mbedtls_aes_free(&ctx); + if (r != 0) { + return SW_EXEC_ERROR(); + } + res_APDU_size = enc_len; + } } else if (memcmp(oid, OID_IEEE_ALG, 8) == 0) { if (oid_len != 9) { diff --git a/src/hsm/oid.h b/src/hsm/oid.h index 87e83d6..d9dcb81 100644 --- a/src/hsm/oid.h +++ b/src/hsm/oid.h @@ -151,16 +151,19 @@ #define OID_AES128_OFB OID_NIST_AES "\x03" #define OID_AES128_CFB OID_NIST_AES "\x04" #define OID_AES128_GCM OID_NIST_AES "\x06" +#define OID_AES128_CTR OID_NIST_AES "\x09" // Not existing #define OID_AES192_ECB OID_NIST_AES "\x15" #define OID_AES192_CBC OID_NIST_AES "\x16" #define OID_AES192_OFB OID_NIST_AES "\x17" #define OID_AES192_CFB OID_NIST_AES "\x18" #define OID_AES192_GCM OID_NIST_AES "\x1A" +#define OID_AES192_CTR OID_NIST_AES "\x1D" // Not existing #define OID_AES256_ECB OID_NIST_AES "\x29" #define OID_AES256_CBC OID_NIST_AES "\x2A" #define OID_AES256_OFB OID_NIST_AES "\x2B" #define OID_AES256_CFB OID_NIST_AES "\x2C" #define OID_AES256_GCM OID_NIST_AES "\x2E" +#define OID_AES256_CTR OID_NIST_AES "\x31" // Not existing #define OID_IEEE_ALG "\x2B\x6F\x02\x8C\x53\x00\x00\x01" #define OID_AES128_XTS OID_IEEE_ALG "\x01" diff --git a/tests/pico-hsm/test_052_aes_ext.py b/tests/pico-hsm/test_052_aes_ext.py index 03bcd89..30e95f1 100644 --- a/tests/pico-hsm/test_052_aes_ext.py +++ b/tests/pico-hsm/test_052_aes_ext.py @@ -259,3 +259,43 @@ def test_aes_xts_iv(device, size): assert(dtA == dtB) assert(dtA == MESSAGE) device.delete_key(keyid) + +@pytest.mark.parametrize( + "size", [128, 192, 256] +) +def test_aes_ctr_no_iv(device, size): + pkey, keyid = generate_key(device, size) + ctA = device.aes(keyid, EncryptionMode.ENCRYPT, AES.CTR, MESSAGE) + + iv = b'\x00' * 16 + cipher = Cipher(algorithms.AES(pkey), modes.CTR(iv)) + encryptor = cipher.encryptor() + ctB = encryptor.update(MESSAGE) + encryptor.finalize() + assert(ctA == ctB) + + dtA = device.aes(keyid, EncryptionMode.DECRYPT, AES.CTR, ctA) + decryptor = cipher.decryptor() + dtB = decryptor.update(ctB) + decryptor.finalize() + assert(dtA == dtB) + assert(dtA == MESSAGE) + device.delete_key(keyid) + +@pytest.mark.parametrize( + "size", [128, 192, 256] +) +def test_aes_ctr_iv(device, size): + pkey, keyid = generate_key(device, size) + iv = os.urandom(16) + ctA = device.aes(keyid, EncryptionMode.ENCRYPT, AES.CTR, MESSAGE, iv=iv) + + cipher = Cipher(algorithms.AES(pkey), modes.CTR(iv)) + encryptor = cipher.encryptor() + ctB = encryptor.update(MESSAGE) + encryptor.finalize() + assert(ctA == ctB) + + dtA = device.aes(keyid, EncryptionMode.DECRYPT, AES.CTR, ctA, iv=iv) + decryptor = cipher.decryptor() + dtB = decryptor.update(ctB) + decryptor.finalize() + assert(dtA == dtB) + assert(dtA == MESSAGE) + device.delete_key(keyid)