diff --git a/library/aes.c b/library/aes.c index 6306fecf84..64392fc56b 100644 --- a/library/aes.c +++ b/library/aes.c @@ -963,6 +963,12 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, } #endif +#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) + if (mbedtls_aesce_has_support()) { + return mbedtls_aesce_crypt_ecb(ctx, mode, input, output); + } +#endif + #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) if (aes_padlock_ace > 0) { if (mbedtls_padlock_xcryptecb(ctx, mode, input, output) == 0) { diff --git a/library/aesce.c b/library/aesce.c index ba9adc95cb..e6b675a3d2 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -65,6 +65,66 @@ int mbedtls_aesce_has_support(void) #endif } +static uint8x16_t aesce_encrypt_block(uint8x16_t block, + unsigned char *keys, + int rounds) +{ + for (int i = 0; i < rounds - 1; i++) { + block = vaeseq_u8(block, vld1q_u8(keys + i * 16)); + /* AES mix columns */ + block = vaesmcq_u8(block); + } + + /* AES single round encryption */ + block = vaeseq_u8(block, vld1q_u8(keys + (rounds -1) * 16)); + + /* Final Add (bitwise Xor) */ + block = veorq_u8(block, vld1q_u8(keys + rounds * 16)); + + return block; +} + +static uint8x16_t aesce_decrypt_block(uint8x16_t block, + unsigned char *keys, + int rounds) +{ + + for (int i = 0; i < rounds - 1; i++) { + block = vaesdq_u8(block, vld1q_u8(keys + i * 16)); + /* AES inverse mix columns */ + block = vaesimcq_u8(block); + } + + /* AES single round encryption */ + block = vaesdq_u8(block, vld1q_u8(keys + (rounds - 1) * 16)); + + /* Final Add (bitwise Xor) */ + block = veorq_u8(block, vld1q_u8(keys + rounds * 16)); + + return block; +} + +/* + * AES-ECB block en(de)cryption + */ +int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]) +{ + uint8x16_t block = vld1q_u8(&input[0]); + unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset); + + if (mode == MBEDTLS_AES_ENCRYPT) { + block = aesce_encrypt_block(block, keys, ctx->nr); + } else { + block = aesce_decrypt_block(block, keys, ctx->nr); + } + vst1q_u8(&output[0], block); + + return 0; +} + /* * Compute decryption round keys from encryption round keys diff --git a/library/aesce.h b/library/aesce.h index d0e02a49d8..741519cfe4 100644 --- a/library/aesce.h +++ b/library/aesce.h @@ -49,6 +49,21 @@ extern "C" { */ int mbedtls_aesce_has_support(void); +/** + * \brief Internal AES-ECB block encryption and decryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]); + /** * \brief Internal round key inversion. This function computes