From 2fddfd7f8f3750c131a5a98a3e74cead84df43b4 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 10 Jan 2023 16:32:03 +0800 Subject: [PATCH 01/24] Add AESCE confige options Signed-off-by: Jerry Yu --- include/mbedtls/check_config.h | 10 ++++++++++ include/mbedtls/mbedtls_config.h | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 1efabdc1fd4..055bfa7aa9a 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -70,6 +70,16 @@ #error "MBEDTLS_AESNI_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_AESCE_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESCE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_AESCE_C) && \ + (defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)) +#error "MBEDTLS_AESCE_C defined, MBEDTLS_SHA512_USE_A64_CRYPTO_* MUST be disabled for known fail." +#endif + #if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" #endif diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 9ae51c964a9..6cea0501152 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2065,6 +2065,25 @@ */ #define MBEDTLS_AESNI_C +/** + * \def MBEDTLS_AESCE_C + * + * Enable AES crypto engine support on Arm64. + * + * Module: library/aesce.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM, MBEDTLS_AES_C + * + * \note The code uses Neon intrinsics, so \c CFLAGS must be set to a minimum + * of \c -march=armv8-a+crypto . + * + * \warning `MBEDTLS_SHA512_USE_A64_CRYPTO_*` should be disabled when enabled + * + * This modules adds support for the AES crypto instructions on Arm64 + */ +#define MBEDTLS_AESCE_C + /** * \def MBEDTLS_AES_C * From 49231319fd56389866199cd16dddae2f9129fefd Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 10 Jan 2023 16:57:21 +0800 Subject: [PATCH 02/24] Add empty aesce files For time being, we only support gcc and clang Signed-off-by: Jerry Yu --- library/CMakeLists.txt | 1 + library/Makefile | 1 + library/aesce.c | 50 ++++++++++++++++++++++++++++++++++++++++++ library/aesce.h | 50 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 library/aesce.c create mode 100644 library/aesce.h diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index c9714bbfbe4..bef2e1c4bde 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -13,6 +13,7 @@ endif() set(src_crypto aes.c aesni.c + aesce.c aria.c asn1parse.c asn1write.c diff --git a/library/Makefile b/library/Makefile index dd16d061588..ed5e1e17299 100644 --- a/library/Makefile +++ b/library/Makefile @@ -78,6 +78,7 @@ endif OBJS_CRYPTO= \ aes.o \ aesni.o \ + aesce.o \ aria.o \ asn1parse.o \ asn1write.o \ diff --git a/library/aesce.c b/library/aesce.c new file mode 100644 index 00000000000..608e5e367e3 --- /dev/null +++ b/library/aesce.c @@ -0,0 +1,50 @@ +/* + * Arm64 crypto engine support functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "common.h" + +#if defined(MBEDTLS_AESCE_C) + +#include "aesce.h" + +#if defined(MBEDTLS_HAVE_ARM64) + +#if defined(__clang__) +# if __clang_major__ < 4 +# error "A more recent Clang is required for MBEDTLS_AES_C" +# endif +#elif defined(__GNUC__) +# if __GNUC__ < 6 +# error "A more recent GCC is required for MBEDTLS_AES_C" +# endif +#else +# error "Only GCC and Clang supported for MBEDTLS_AES_C" +#endif + +#if !defined(__ARM_FEATURE_CRYPTO) +# error "`crypto` feature moddifier MUST be enabled for MBEDTLS_AESCE_C." +# error "Typical option for GCC and Clang is `-march=armv8-a+crypto`." +#endif /* !__ARM_FEATURE_CRYPTO */ + +#include + +#endif /* MBEDTLS_HAVE_ARM64 */ + +#endif /* MBEDTLS_AESCE_C */ diff --git a/library/aesce.h b/library/aesce.h new file mode 100644 index 00000000000..4968feda910 --- /dev/null +++ b/library/aesce.h @@ -0,0 +1,50 @@ +/** + * \file aesce.h + * + * \brief AES-CE for hardware AES acceleration on ARMv8 processors with crypto + * engine. + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_AESCE_H +#define MBEDTLS_AESCE_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/aes.h" + + +#if !defined(MBEDTLS_HAVE_ARM64) && \ + (defined(__aarch64__) || defined(_M_ARM64)) +#define MBEDTLS_HAVE_ARM64 +#endif + +#if defined(MBEDTLS_HAVE_ARM64) + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_ARM64 */ + +#endif /* MBEDTLS_AESCE_H */ From b95c776c435b56905b0e2e10ab19737abf739797 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 10 Jan 2023 16:59:51 +0800 Subject: [PATCH 03/24] Add linux runtime detection Signed-off-by: Jerry Yu --- library/aesce.c | 20 ++++++++++++++++++++ library/aesce.h | 12 ++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/library/aesce.c b/library/aesce.c index 608e5e367e3..f33d593427a 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -45,6 +45,26 @@ #include +#if defined(__linux__) +#include +#include +#endif + +/* + * AES instruction support detection routine + */ +int mbedtls_aesce_has_support(void) +{ +#if defined(__linux__) + unsigned long auxval = getauxval(AT_HWCAP); + return (auxval & (HWCAP_ASIMD | HWCAP_AES)) == + (HWCAP_ASIMD | HWCAP_AES); +#else + /* Suppose aes instructions are supported. */ + return 1; +#endif +} + #endif /* MBEDTLS_HAVE_ARM64 */ #endif /* MBEDTLS_AESCE_C */ diff --git a/library/aesce.h b/library/aesce.h index 4968feda910..2d5dde985f1 100644 --- a/library/aesce.h +++ b/library/aesce.h @@ -31,8 +31,8 @@ #include "mbedtls/aes.h" -#if !defined(MBEDTLS_HAVE_ARM64) && \ - (defined(__aarch64__) || defined(_M_ARM64)) +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + defined(__aarch64__) && !defined(MBEDTLS_HAVE_ARM64) #define MBEDTLS_HAVE_ARM64 #endif @@ -41,6 +41,14 @@ #ifdef __cplusplus extern "C" { #endif + +/** + * \brief Internal function to detect the crypto engine in CPUs. + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesce_has_support(void); + #ifdef __cplusplus } #endif From 3f2fb71072678d494b88e477c74273c3fa7fa654 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 10 Jan 2023 17:05:42 +0800 Subject: [PATCH 04/24] Add key expansion for encrypt Signed-off-by: Jerry Yu --- library/aes.c | 9 ++++ library/aesce.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++ library/aesce.h | 14 +++++++ 3 files changed, 131 insertions(+) diff --git a/library/aes.c b/library/aes.c index 566e74715fe..f0ade214900 100644 --- a/library/aes.c +++ b/library/aes.c @@ -39,6 +39,9 @@ #if defined(MBEDTLS_AESNI_C) #include "aesni.h" #endif +#if defined(MBEDTLS_AESCE_C) +#include "aesce.h" +#endif #include "mbedtls/platform.h" @@ -544,6 +547,12 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, } #endif +#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) + if (mbedtls_aesce_has_support()) { + return mbedtls_aesce_setkey_enc((unsigned char *) RK, key, keybits); + } +#endif + for (i = 0; i < (keybits >> 5); i++) { RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2); } diff --git a/library/aesce.c b/library/aesce.c index f33d593427a..4b0f9d74499 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -65,6 +65,114 @@ int mbedtls_aesce_has_support(void) #endif } + +static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36 }; + +static inline uint32_t ror32_8(uint32_t word) +{ + return (word << (32 - 8)) | (word >> 8); +} + +static inline uint32_t aes_sub(uint32_t in) +{ + uint32x4_t _in = vdupq_n_u32(in); + uint32x4_t v; + uint8x16_t zero = vdupq_n_u8(0); + v = vreinterpretq_u32_u8(vaeseq_u8(zero, vreinterpretq_u8_u32(_in))); + return vgetq_lane_u32(v, 0); +} + +/* + * Key expansion, 128-bit case + */ +static void aesce_setkey_enc_128(unsigned char *rk, + const unsigned char *key) +{ + uint32_t *rki; + uint32_t *rko; + uint32_t *rk_u32 = (uint32_t *) rk; + memcpy(rk, key, (128 / 8)); + + for (size_t i = 0; i < sizeof(rcon); i++) { + rki = rk_u32 + i * (128 / 32); + rko = rki + (128 / 32); + rko[0] = ror32_8(aes_sub(rki[(128 / 32) - 1])) ^ rcon[i] ^ rki[0]; + rko[1] = rko[0] ^ rki[1]; + rko[2] = rko[1] ^ rki[2]; + rko[3] = rko[2] ^ rki[3]; + } +} + +/* + * Key expansion, 192-bit case + */ +static void aesce_setkey_enc_192(unsigned char *rk, + const unsigned char *key) +{ + uint32_t *rki; + uint32_t *rko; + uint32_t *rk_u32 = (uint32_t *) rk; + memcpy(rk, key, (192 / 8)); + + for (size_t i = 0; i < 8; i++) { + rki = rk_u32 + i * (192 / 32); + rko = rki + (192 / 32); + rko[0] = ror32_8(aes_sub(rki[(192 / 32) - 1])) ^ rcon[i] ^ rki[0]; + rko[1] = rko[0] ^ rki[1]; + rko[2] = rko[1] ^ rki[2]; + rko[3] = rko[2] ^ rki[3]; + if (i < 7) { + rko[4] = rko[3] ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + } + } +} + +/* + * Key expansion, 256-bit case + */ +static void aesce_setkey_enc_256(unsigned char *rk, + const unsigned char *key) +{ + uint32_t *rki; + uint32_t *rko; + uint32_t *rk_u32 = (uint32_t *) rk; + memcpy(rk, key, (256 / 8)); + + for (size_t i = 0; i < 7; i++) { + rki = rk_u32 + i * (256 / 32); + rko = rki + (256 / 32); + rko[0] = ror32_8(aes_sub(rki[(256 / 32) - 1])) ^ rcon[i] ^ rki[0]; + rko[1] = rko[0] ^ rki[1]; + rko[2] = rko[1] ^ rki[2]; + rko[3] = rko[2] ^ rki[3]; + if (i < 6) { + rko[4] = aes_sub(rko[3]) ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + rko[6] = rko[5] ^ rki[6]; + rko[7] = rko[6] ^ rki[7]; + } + } +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + size_t bits) +{ + switch (bits) { + case 128: aesce_setkey_enc_128(rk, key); break; + case 192: aesce_setkey_enc_192(rk, key); break; + case 256: aesce_setkey_enc_256(rk, key); break; + default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + return 0; +} + #endif /* MBEDTLS_HAVE_ARM64 */ #endif /* MBEDTLS_AESCE_C */ diff --git a/library/aesce.h b/library/aesce.h index 2d5dde985f1..7fc0cfa0ebc 100644 --- a/library/aesce.h +++ b/library/aesce.h @@ -49,6 +49,20 @@ extern "C" { */ int mbedtls_aesce_has_support(void); + +/** + * \brief Internal key expansion for encryption + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + size_t bits); + #ifdef __cplusplus } #endif From e096da1af61efc6a35e9bcd4f2fd35690299f17e Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 10 Jan 2023 17:07:01 +0800 Subject: [PATCH 05/24] Add inverse key function Signed-off-by: Jerry Yu --- library/aes.c | 10 ++++++++++ library/aesce.c | 18 ++++++++++++++++++ library/aesce.h | 12 ++++++++++++ 3 files changed, 40 insertions(+) diff --git a/library/aes.c b/library/aes.c index f0ade214900..6306fecf84b 100644 --- a/library/aes.c +++ b/library/aes.c @@ -661,6 +661,16 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, } #endif +#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) + if (mbedtls_aesce_has_support()) { + mbedtls_aesce_inverse_key( + (unsigned char *) RK, + (const unsigned char *) (cty.buf + cty.rk_offset), + ctx->nr); + goto exit; + } +#endif + SK = cty.buf + cty.rk_offset + cty.nr * 4; *RK++ = *SK++; diff --git a/library/aesce.c b/library/aesce.c index 4b0f9d74499..ba9adc95cb6 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -66,6 +66,24 @@ int mbedtls_aesce_has_support(void) } +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesce_inverse_key(unsigned char *invkey, + const unsigned char *fwdkey, + int nr) +{ + int i, j; + j = nr; + vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16)); + for (i = 1, j--; j > 0; i++, j--) { + vst1q_u8(invkey + i * 16, + vaesimcq_u8(vld1q_u8(fwdkey + j * 16))); + } + vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16)); + +} + static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; diff --git a/library/aesce.h b/library/aesce.h index 7fc0cfa0ebc..d0e02a49d8c 100644 --- a/library/aesce.h +++ b/library/aesce.h @@ -50,6 +50,18 @@ extern "C" { int mbedtls_aesce_has_support(void); +/** + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesce_inverse_key(unsigned char *invkey, + const unsigned char *fwdkey, + int nr); + /** * \brief Internal key expansion for encryption * From 2bb3d8101f19aa9395498dd49746c3764ff739d3 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 10 Jan 2023 17:38:26 +0800 Subject: [PATCH 06/24] Add en(de)crypt routine Signed-off-by: Jerry Yu --- library/aes.c | 6 +++++ library/aesce.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ library/aesce.h | 15 +++++++++++++ 3 files changed, 81 insertions(+) diff --git a/library/aes.c b/library/aes.c index 6306fecf84b..64392fc56b5 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 ba9adc95cb6..e6b675a3d21 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 d0e02a49d8c..741519cfe48 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 From e51eddce38ada83236a2d1f62c4d226ebd925fce Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Wed, 11 Jan 2023 14:16:08 +0800 Subject: [PATCH 07/24] disable aesce when ASM not available Change-Id: Icd53a620cc3aed437b0e0e022ca5a36f29caeea1 Signed-off-by: Jerry Yu --- tests/scripts/all.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 883d58b6f6a..a769da2acad 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1972,6 +1972,7 @@ component_build_module_alt () { # aesni.c and padlock.c reference mbedtls_aes_context fields directly. scripts/config.py unset MBEDTLS_AESNI_C scripts/config.py unset MBEDTLS_PADLOCK_C + scripts/config.py unset MBEDTLS_AESCE_C # MBEDTLS_ECP_RESTARTABLE is documented as incompatible. scripts/config.py unset MBEDTLS_ECP_RESTARTABLE # You can only have one threading implementation: alt or pthread, not both. @@ -3336,6 +3337,7 @@ component_test_have_int32 () { scripts/config.py unset MBEDTLS_HAVE_ASM scripts/config.py unset MBEDTLS_AESNI_C scripts/config.py unset MBEDTLS_PADLOCK_C + scripts/config.py unset MBEDTLS_AESCE_C make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT32' msg "test: gcc, force 32-bit bignum limbs" @@ -3347,6 +3349,7 @@ component_test_have_int64 () { scripts/config.py unset MBEDTLS_HAVE_ASM scripts/config.py unset MBEDTLS_AESNI_C scripts/config.py unset MBEDTLS_PADLOCK_C + scripts/config.py unset MBEDTLS_AESCE_C make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64' msg "test: gcc, force 64-bit bignum limbs" From 32f977e82057b7753f4ec883f25eaee203fe233b Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Wed, 11 Jan 2023 22:48:51 +0800 Subject: [PATCH 08/24] Add arm64 tests on travis ci Due to time limitation of travis, the job is spited into two job Signed-off-by: Jerry Yu --- .travis.yml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/.travis.yml b/.travis.yml index 54df7760602..41bb44cd139 100644 --- a/.travis.yml +++ b/.travis.yml @@ -80,6 +80,55 @@ jobs: - sleep 5 - scripts/windows_msbuild.bat v141 # Visual Studio 2017 + - name: full configuration on arm64 + os: linux + dist: focal + arch: arm64 + addons: + apt: + packages: + - gcc + script: + # See above + - scripts/config.py full + - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT + - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY + - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT + - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY + - make generated_files + - make CFLAGS='-march=armv8-a+crypto -O3 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all' LDFLAGS='-Werror -fsanitize=address,undefined -fno-sanitize-recover=all' + - make test + - programs/test/selftest + - tests/scripts/test_psa_constant_names.py + # Modern OpenSSL does not support fixed ECDH or null ciphers. + - tests/compat.sh -p OpenSSL -e 'NULL\|ECDH-' + - tests/scripts/travis-log-failure.sh + - tests/context-info.sh + + - name: full configuration(GnuTLS compat tests) on arm64 + os: linux + dist: focal + arch: arm64 + addons: + apt: + packages: + - clang + - gnutls-bin + script: + # See above + - scripts/config.py full + - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT + - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY + - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT + - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY + - make generated_files + - make CC=clang CFLAGS='-march=armv8-a+crypto -O3 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all' LDFLAGS='-Werror -fsanitize=address,undefined -fno-sanitize-recover=all' + # GnuTLS supports CAMELLIA but compat.sh doesn't properly enable it. + - tests/compat.sh -p GnuTLS -e 'CAMELLIA' + - tests/scripts/travis-log-failure.sh + - tests/context-info.sh + + after_failure: - tests/scripts/travis-log-failure.sh From e908c57f95d05cac83bb9532ba50a82e925e3df1 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Fri, 13 Jan 2023 21:37:11 +0800 Subject: [PATCH 09/24] Disable clang tests Signed-off-by: Jerry Yu --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 41bb44cd139..3b1d7055157 100644 --- a/.travis.yml +++ b/.travis.yml @@ -112,7 +112,7 @@ jobs: addons: apt: packages: - - clang + - gcc - gnutls-bin script: # See above @@ -122,7 +122,7 @@ jobs: - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY - make generated_files - - make CC=clang CFLAGS='-march=armv8-a+crypto -O3 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all' LDFLAGS='-Werror -fsanitize=address,undefined -fno-sanitize-recover=all' + - make CFLAGS='-march=armv8-a+crypto -O3 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all' LDFLAGS='-Werror -fsanitize=address,undefined -fno-sanitize-recover=all' # GnuTLS supports CAMELLIA but compat.sh doesn't properly enable it. - tests/compat.sh -p GnuTLS -e 'CAMELLIA' - tests/scripts/travis-log-failure.sh From b3b85ddf4ac738947b088f2f2e50d85637a440fc Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Mon, 30 Jan 2023 15:22:12 +0800 Subject: [PATCH 10/24] Disable macro conflict check It cause full configuration test fail Signed-off-by: Jerry Yu --- include/mbedtls/check_config.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 055bfa7aa9a..ac374d2a4b3 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -74,12 +74,6 @@ #error "MBEDTLS_AESCE_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_AESCE_C) && \ - (defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ - defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)) -#error "MBEDTLS_AESCE_C defined, MBEDTLS_SHA512_USE_A64_CRYPTO_* MUST be disabled for known fail." -#endif - #if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" #endif From 837e9cfc77009df92354b9020d3716422e2ef938 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Wed, 8 Feb 2023 10:57:23 +0800 Subject: [PATCH 11/24] fix wrong typo Signed-off-by: Jerry Yu --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3b1d7055157..a97a3c2ef8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -101,7 +101,7 @@ jobs: - programs/test/selftest - tests/scripts/test_psa_constant_names.py # Modern OpenSSL does not support fixed ECDH or null ciphers. - - tests/compat.sh -p OpenSSL -e 'NULL\|ECDH-' + - tests/compat.sh -p OpenSSL -e 'NULL\|ECDH_' - tests/scripts/travis-log-failure.sh - tests/context-info.sh From b2783f66b505cc62634ea6a5f92114fb5d90ffab Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Mon, 13 Feb 2023 18:03:25 +0800 Subject: [PATCH 12/24] fix typo issue The error message is wrong Signed-off-by: Jerry Yu --- library/aesce.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/aesce.c b/library/aesce.c index e6b675a3d21..18322a62a6e 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -28,14 +28,14 @@ #if defined(__clang__) # if __clang_major__ < 4 -# error "A more recent Clang is required for MBEDTLS_AES_C" +# error "A more recent Clang is required for MBEDTLS_AESCE_C" # endif #elif defined(__GNUC__) # if __GNUC__ < 6 -# error "A more recent GCC is required for MBEDTLS_AES_C" +# error "A more recent GCC is required for MBEDTLS_AESCE_C" # endif #else -# error "Only GCC and Clang supported for MBEDTLS_AES_C" +# error "Only GCC and Clang supported for MBEDTLS_AESCE_C" #endif #if !defined(__ARM_FEATURE_CRYPTO) From 751e76bb04727f5aeb55c8b85ac7df8f77fdfdf6 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Thu, 16 Feb 2023 10:48:15 +0800 Subject: [PATCH 13/24] Replace `crypto engine` with `crypto extension` Signed-off-by: Jerry Yu --- include/mbedtls/mbedtls_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 6cea0501152..3dea18ca10f 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2068,7 +2068,7 @@ /** * \def MBEDTLS_AESCE_C * - * Enable AES crypto engine support on Arm64. + * Enable AES crypto extension support on Arm64. * * Module: library/aesce.c * Caller: library/aes.c From c8bcdc8b91244200f306809217ad917f053c8c0b Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 21 Feb 2023 14:49:02 +0800 Subject: [PATCH 14/24] fix various issues - Improve some function names - Improve comments - improve readability Signed-off-by: Jerry Yu --- include/mbedtls/mbedtls_config.h | 2 +- library/aesce.c | 51 ++++++++++++++++++++++---------- library/aesce.h | 4 +-- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 3dea18ca10f..5f7aed26cc3 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2080,7 +2080,7 @@ * * \warning `MBEDTLS_SHA512_USE_A64_CRYPTO_*` should be disabled when enabled * - * This modules adds support for the AES crypto instructions on Arm64 + * This module adds support for the AES crypto instructions on Arm64 */ #define MBEDTLS_AESCE_C diff --git a/library/aesce.c b/library/aesce.c index 18322a62a6e..29a4ce0183b 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -1,5 +1,5 @@ /* - * Arm64 crypto engine support functions + * Arm64 crypto extension support functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 @@ -70,15 +70,18 @@ static uint8x16_t aesce_encrypt_block(uint8x16_t block, int rounds) { for (int i = 0; i < rounds - 1; i++) { + /* AES AddRoundKey, SubBytes, ShiftRows (in this order). + * AddRoundKey adds the round key for the previous round. */ block = vaeseq_u8(block, vld1q_u8(keys + i * 16)); /* AES mix columns */ block = vaesmcq_u8(block); } - /* AES single round encryption */ + /* AES AddRoundKey for the previous round. + * SubBytes, ShiftRows for the final round. */ block = vaeseq_u8(block, vld1q_u8(keys + (rounds -1) * 16)); - /* Final Add (bitwise Xor) */ + /* Final round: no MixColumns */ block = veorq_u8(block, vld1q_u8(keys + rounds * 16)); return block; @@ -90,15 +93,28 @@ static uint8x16_t aesce_decrypt_block(uint8x16_t block, { for (int i = 0; i < rounds - 1; i++) { + /* AES AddRoundKey, SubBytes, ShiftRows */ block = vaesdq_u8(block, vld1q_u8(keys + i * 16)); - /* AES inverse mix columns */ + /* AES inverse MixColumns for the next round. + * + * This means that we switch the order of the inverse AddRoundKey and + * inverse MixColumns operations. We have to do this as AddRoundKey is + * done in an atomic instruction together with the inverses of SubBytes + * and ShiftRows. + * + * It works because MixColumns is a linear operation over GF(2^8) and + * AddRoundKey is an exclusive or, which is equivalent to addition over + * GF(2^8). (The inverse of MixColumns needs to be applied to the + * affected round keys separately which has been done when the + * decryption round keys were calculated.) */ block = vaesimcq_u8(block); } - /* AES single round encryption */ + /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the + * last full round. */ block = vaesdq_u8(block, vld1q_u8(keys + (rounds - 1) * 16)); - /* Final Add (bitwise Xor) */ + /* Inverse AddRoundKey for inverting the initial round key addition. */ block = veorq_u8(block, vld1q_u8(keys + rounds * 16)); return block; @@ -147,18 +163,20 @@ void mbedtls_aesce_inverse_key(unsigned char *invkey, static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; -static inline uint32_t ror32_8(uint32_t word) +static inline uint32_t aes_rot_word(uint32_t word) { return (word << (32 - 8)) | (word >> 8); } -static inline uint32_t aes_sub(uint32_t in) +static inline uint32_t aes_sub_word(uint32_t in) { - uint32x4_t _in = vdupq_n_u32(in); - uint32x4_t v; + uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in)); uint8x16_t zero = vdupq_n_u8(0); - v = vreinterpretq_u32_u8(vaeseq_u8(zero, vreinterpretq_u8_u32(_in))); - return vgetq_lane_u32(v, 0); + + /* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields + * the correct result as ShiftRows doesn't change the first row. */ + v = vaeseq_u8(zero, v); + return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0); } /* @@ -170,12 +188,13 @@ static void aesce_setkey_enc_128(unsigned char *rk, uint32_t *rki; uint32_t *rko; uint32_t *rk_u32 = (uint32_t *) rk; + memcpy(rk, key, (128 / 8)); for (size_t i = 0; i < sizeof(rcon); i++) { rki = rk_u32 + i * (128 / 32); rko = rki + (128 / 32); - rko[0] = ror32_8(aes_sub(rki[(128 / 32) - 1])) ^ rcon[i] ^ rki[0]; + rko[0] = aes_rot_word(aes_sub_word(rki[(128 / 32) - 1])) ^ rcon[i] ^ rki[0]; rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; @@ -196,7 +215,7 @@ static void aesce_setkey_enc_192(unsigned char *rk, for (size_t i = 0; i < 8; i++) { rki = rk_u32 + i * (192 / 32); rko = rki + (192 / 32); - rko[0] = ror32_8(aes_sub(rki[(192 / 32) - 1])) ^ rcon[i] ^ rki[0]; + rko[0] = aes_rot_word(aes_sub_word(rki[(192 / 32) - 1])) ^ rcon[i] ^ rki[0]; rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; @@ -221,12 +240,12 @@ static void aesce_setkey_enc_256(unsigned char *rk, for (size_t i = 0; i < 7; i++) { rki = rk_u32 + i * (256 / 32); rko = rki + (256 / 32); - rko[0] = ror32_8(aes_sub(rki[(256 / 32) - 1])) ^ rcon[i] ^ rki[0]; + rko[0] = aes_rot_word(aes_sub_word(rki[(256 / 32) - 1])) ^ rcon[i] ^ rki[0]; rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; if (i < 6) { - rko[4] = aes_sub(rko[3]) ^ rki[4]; + rko[4] = aes_sub_word(rko[3]) ^ rki[4]; rko[5] = rko[4] ^ rki[5]; rko[6] = rko[5] ^ rki[6]; rko[7] = rko[6] ^ rki[7]; diff --git a/library/aesce.h b/library/aesce.h index 741519cfe48..0d6d09e5078 100644 --- a/library/aesce.h +++ b/library/aesce.h @@ -2,7 +2,7 @@ * \file aesce.h * * \brief AES-CE for hardware AES acceleration on ARMv8 processors with crypto - * engine. + * extension. * * \warning These functions are only for internal use by other library * functions; you must not call them directly. @@ -43,7 +43,7 @@ extern "C" { #endif /** - * \brief Internal function to detect the crypto engine in CPUs. + * \brief Internal function to detect the crypto extension in CPUs. * * \return 1 if CPU has support for the feature, 0 otherwise */ From 330e6ae11152b23ecf1bb4a8d0b290e72aee9ea6 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 21 Feb 2023 14:51:38 +0800 Subject: [PATCH 15/24] Add document about runtime detection of AESCE Signed-off-by: Jerry Yu --- include/mbedtls/mbedtls_config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 5f7aed26cc3..cba133c4f60 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2080,6 +2080,9 @@ * * \warning `MBEDTLS_SHA512_USE_A64_CRYPTO_*` should be disabled when enabled * + * \warning Runtime detection only works on linux. For non-linux operation + * system, crypto extension MUST be supported by CPU. + * * This module adds support for the AES crypto instructions on Arm64 */ #define MBEDTLS_AESCE_C From 97b31d8ca304d97bbc2c4e7435e4ce621ff1fc7d Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 21 Feb 2023 14:52:33 +0800 Subject: [PATCH 16/24] Revert "Disable clang tests" This reverts commit e908c57f95d05cac83bb9532ba50a82e925e3df1. Signed-off-by: Jerry Yu --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a97a3c2ef8b..3d735bb5c76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -112,7 +112,7 @@ jobs: addons: apt: packages: - - gcc + - clang - gnutls-bin script: # See above @@ -122,7 +122,7 @@ jobs: - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT - scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY - make generated_files - - make CFLAGS='-march=armv8-a+crypto -O3 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all' LDFLAGS='-Werror -fsanitize=address,undefined -fno-sanitize-recover=all' + - make CC=clang CFLAGS='-march=armv8-a+crypto -O3 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all' LDFLAGS='-Werror -fsanitize=address,undefined -fno-sanitize-recover=all' # GnuTLS supports CAMELLIA but compat.sh doesn't properly enable it. - tests/compat.sh -p GnuTLS -e 'CAMELLIA' - tests/scripts/travis-log-failure.sh From baae4012bf9a175bd8d2bf202db493f387e3f1b3 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 21 Feb 2023 15:26:13 +0800 Subject: [PATCH 17/24] merge setkey_enc* functions Signed-off-by: Jerry Yu --- library/aesce.c | 104 +++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 67 deletions(-) diff --git a/library/aesce.c b/library/aesce.c index 29a4ce0183b..b4ebdadc0ac 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -160,9 +160,6 @@ void mbedtls_aesce_inverse_key(unsigned char *invkey, } -static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, - 0x20, 0x40, 0x80, 0x1b, 0x36 }; - static inline uint32_t aes_rot_word(uint32_t word) { return (word << (32 - 8)) | (word >> 8); @@ -180,75 +177,47 @@ static inline uint32_t aes_sub_word(uint32_t in) } /* - * Key expansion, 128-bit case - */ -static void aesce_setkey_enc_128(unsigned char *rk, - const unsigned char *key) -{ - uint32_t *rki; - uint32_t *rko; - uint32_t *rk_u32 = (uint32_t *) rk; - - memcpy(rk, key, (128 / 8)); - - for (size_t i = 0; i < sizeof(rcon); i++) { - rki = rk_u32 + i * (128 / 32); - rko = rki + (128 / 32); - rko[0] = aes_rot_word(aes_sub_word(rki[(128 / 32) - 1])) ^ rcon[i] ^ rki[0]; - rko[1] = rko[0] ^ rki[1]; - rko[2] = rko[1] ^ rki[2]; - rko[3] = rko[2] ^ rki[3]; - } -} - -/* - * Key expansion, 192-bit case + * Key expansion function */ -static void aesce_setkey_enc_192(unsigned char *rk, - const unsigned char *key) -{ - uint32_t *rki; - uint32_t *rko; - uint32_t *rk_u32 = (uint32_t *) rk; - memcpy(rk, key, (192 / 8)); - - for (size_t i = 0; i < 8; i++) { - rki = rk_u32 + i * (192 / 32); - rko = rki + (192 / 32); - rko[0] = aes_rot_word(aes_sub_word(rki[(192 / 32) - 1])) ^ rcon[i] ^ rki[0]; - rko[1] = rko[0] ^ rki[1]; - rko[2] = rko[1] ^ rki[2]; - rko[3] = rko[2] ^ rki[3]; - if (i < 7) { - rko[4] = rko[3] ^ rki[4]; - rko[5] = rko[4] ^ rki[5]; - } - } -} - -/* - * Key expansion, 256-bit case - */ -static void aesce_setkey_enc_256(unsigned char *rk, - const unsigned char *key) +static void aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + const size_t key_bit_length) { uint32_t *rki; uint32_t *rko; uint32_t *rk_u32 = (uint32_t *) rk; - memcpy(rk, key, (256 / 8)); - - for (size_t i = 0; i < 7; i++) { - rki = rk_u32 + i * (256 / 32); - rko = rki + (256 / 32); - rko[0] = aes_rot_word(aes_sub_word(rki[(256 / 32) - 1])) ^ rcon[i] ^ rki[0]; + const uint32_t key_len_in_words = key_bit_length / 32; + const uint32_t key_len_in_bytes = key_bit_length / 8; + static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36 }; + const uint32_t rounds = + key_bit_length == 128 ? sizeof(rcon) : key_bit_length == 192 ? 8 : 7; + + memcpy(rk, key, key_len_in_bytes); + + for (size_t i = 0; i < rounds; i++) { + rki = rk_u32 + i * key_len_in_words; + rko = rki + key_len_in_words; + rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1])); + rko[0] ^= rcon[i] ^ rki[0]; rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; - if (i < 6) { - rko[4] = aes_sub_word(rko[3]) ^ rki[4]; - rko[5] = rko[4] ^ rki[5]; - rko[6] = rko[5] ^ rki[6]; - rko[7] = rko[6] ^ rki[7]; + switch (key_bit_length) { + case 192: + if (i < 7) { + rko[4] = rko[3] ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + } + break; + case 256: + if (i < 6) { + rko[4] = aes_sub_word(rko[3]) ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + rko[6] = rko[5] ^ rki[6]; + rko[7] = rko[6] ^ rki[7]; + } + break; } } } @@ -261,9 +230,10 @@ int mbedtls_aesce_setkey_enc(unsigned char *rk, size_t bits) { switch (bits) { - case 128: aesce_setkey_enc_128(rk, key); break; - case 192: aesce_setkey_enc_192(rk, key); break; - case 256: aesce_setkey_enc_256(rk, key); break; + case 128: + case 192: + case 256: + aesce_setkey_enc(rk, key, bits); break; default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } From 3304c204bab34d823da7f125d233c1f3ab3388da Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Wed, 22 Feb 2023 14:37:11 +0800 Subject: [PATCH 18/24] Improve readabilities - Add more comments - Adjust setkey_enc Signed-off-by: Jerry Yu --- library/aesce.c | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/library/aesce.c b/library/aesce.c index b4ebdadc0ac..64811227c74 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -82,6 +82,8 @@ static uint8x16_t aesce_encrypt_block(uint8x16_t block, block = vaeseq_u8(block, vld1q_u8(keys + (rounds -1) * 16)); /* Final round: no MixColumns */ + + /* Final AddRoundKey */ block = veorq_u8(block, vld1q_u8(keys + rounds * 16)); return block; @@ -183,40 +185,47 @@ static void aesce_setkey_enc(unsigned char *rk, const unsigned char *key, const size_t key_bit_length) { - uint32_t *rki; - uint32_t *rko; - uint32_t *rk_u32 = (uint32_t *) rk; + const uint32_t key_len_in_words = key_bit_length / 32; - const uint32_t key_len_in_bytes = key_bit_length / 8; + const size_t round_key_len_in_words = 4; static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; - const uint32_t rounds = - key_bit_length == 128 ? sizeof(rcon) : key_bit_length == 192 ? 8 : 7; + /* Require max(key_len_in_words, round_key_len_len_in_words) + 7 */ + const size_t round_keys_needed = key_len_in_words + 7; + const size_t key_expansion_size_in_words = + round_keys_needed * round_key_len_in_words; + const uint32_t *rko_end = (uint32_t *) rk + key_expansion_size_in_words; + + memcpy(rk, key, key_len_in_words * 4); - memcpy(rk, key, key_len_in_bytes); + for (uint32_t *rki = (uint32_t *) rk; + rki + key_len_in_words < rko_end; + rki += key_len_in_words) { - for (size_t i = 0; i < rounds; i++) { - rki = rk_u32 + i * key_len_in_words; + size_t iteration = (rki- (uint32_t *) rk)/key_len_in_words; + uint32_t *rko; rko = rki + key_len_in_words; rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1])); - rko[0] ^= rcon[i] ^ rki[0]; + rko[0] ^= rcon[iteration] ^ rki[0]; rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; + if (rko+key_len_in_words > rko_end) { + /* Do not write overflow words.*/ + continue; + } switch (key_bit_length) { + case 128: + break; case 192: - if (i < 7) { - rko[4] = rko[3] ^ rki[4]; - rko[5] = rko[4] ^ rki[5]; - } + rko[4] = rko[3] ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; break; case 256: - if (i < 6) { - rko[4] = aes_sub_word(rko[3]) ^ rki[4]; - rko[5] = rko[4] ^ rki[5]; - rko[6] = rko[5] ^ rki[6]; - rko[7] = rko[6] ^ rki[7]; - } + rko[4] = aes_sub_word(rko[3]) ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + rko[6] = rko[5] ^ rki[6]; + rko[7] = rko[6] ^ rki[7]; break; } } From fac5a54f8ad5ae52ea10f22b86faa1ffea9db4ef Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Thu, 23 Feb 2023 10:13:40 +0800 Subject: [PATCH 19/24] fix code style issues Signed-off-by: Jerry Yu --- library/aesce.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/aesce.c b/library/aesce.c index 64811227c74..356d0a3af1c 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -193,7 +193,7 @@ static void aesce_setkey_enc(unsigned char *rk, /* Require max(key_len_in_words, round_key_len_len_in_words) + 7 */ const size_t round_keys_needed = key_len_in_words + 7; const size_t key_expansion_size_in_words = - round_keys_needed * round_key_len_in_words; + round_keys_needed * round_key_len_in_words; const uint32_t *rko_end = (uint32_t *) rk + key_expansion_size_in_words; memcpy(rk, key, key_len_in_words * 4); @@ -202,7 +202,7 @@ static void aesce_setkey_enc(unsigned char *rk, rki + key_len_in_words < rko_end; rki += key_len_in_words) { - size_t iteration = (rki- (uint32_t *) rk)/key_len_in_words; + size_t iteration = (rki - (uint32_t *) rk) / key_len_in_words; uint32_t *rko; rko = rki + key_len_in_words; rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1])); @@ -210,7 +210,7 @@ static void aesce_setkey_enc(unsigned char *rk, rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; - if (rko+key_len_in_words > rko_end) { + if (rko + key_len_in_words > rko_end) { /* Do not write overflow words.*/ continue; } From 947bf969e0b40e11b187c92557672bc07064975f Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Thu, 23 Feb 2023 11:07:57 +0800 Subject: [PATCH 20/24] Improve readability of expansion size Signed-off-by: Jerry Yu --- library/aesce.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/library/aesce.c b/library/aesce.c index 356d0a3af1c..e47665a50cc 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -185,15 +185,17 @@ static void aesce_setkey_enc(unsigned char *rk, const unsigned char *key, const size_t key_bit_length) { - - const uint32_t key_len_in_words = key_bit_length / 32; - const size_t round_key_len_in_words = 4; static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; - /* Require max(key_len_in_words, round_key_len_len_in_words) + 7 */ - const size_t round_keys_needed = key_len_in_words + 7; + /* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf + * - Section 5, Nr = Nk + 6 + * - Section 5.2, the key expansion size is Nb*(Nr+1) + */ + const uint32_t key_len_in_words = key_bit_length / 32; /* Nk */ + const size_t round_key_len_in_words = 4; /* Nb */ + const size_t round_keys_needed = key_len_in_words + 6; /* Nr */ const size_t key_expansion_size_in_words = - round_keys_needed * round_key_len_in_words; + round_key_len_in_words * (round_keys_needed + 1); /* Nb*(Nr+1) */ const uint32_t *rko_end = (uint32_t *) rk + key_expansion_size_in_words; memcpy(rk, key, key_len_in_words * 4); From ba1e78f1c206d1fabc21394c0fffbda9896f028d Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Fri, 24 Feb 2023 11:18:16 +0800 Subject: [PATCH 21/24] fix code style and comment issues Signed-off-by: Jerry Yu --- library/aesce.c | 9 +++++---- library/aesce.h | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/aesce.c b/library/aesce.c index e47665a50cc..ee0c8e12cf9 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -60,7 +60,7 @@ int mbedtls_aesce_has_support(void) return (auxval & (HWCAP_ASIMD | HWCAP_AES)) == (HWCAP_ASIMD | HWCAP_AES); #else - /* Suppose aes instructions are supported. */ + /* Assume AES instructions are supported. */ return 1; #endif } @@ -143,7 +143,6 @@ int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, return 0; } - /* * Compute decryption round keys from encryption round keys */ @@ -244,8 +243,10 @@ int mbedtls_aesce_setkey_enc(unsigned char *rk, case 128: case 192: case 256: - aesce_setkey_enc(rk, key, bits); break; - default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + aesce_setkey_enc(rk, key, bits); + break; + default: + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } return 0; diff --git a/library/aesce.h b/library/aesce.h index 0d6d09e5078..1e72e5ba463 100644 --- a/library/aesce.h +++ b/library/aesce.h @@ -64,7 +64,6 @@ int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); - /** * \brief Internal round key inversion. This function computes * decryption round keys from the encryption round keys. From aa18c4bf9627204dc0629d9d3fa5e694c2474cba Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Fri, 24 Feb 2023 11:18:41 +0800 Subject: [PATCH 22/24] Add comments about travis test. Signed-off-by: Jerry Yu --- .travis.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3d735bb5c76..2e9bdb4ede4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,7 +89,9 @@ jobs: packages: - gcc script: - # See above + # Do a manual build+test sequence rather than using all.sh, because + # there's no all.sh component that does what we want. We should set + # CFLAGS for arm64 host CC. - scripts/config.py full - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY @@ -115,7 +117,9 @@ jobs: - clang - gnutls-bin script: - # See above + # Do a manual build+test sequence rather than using all.sh, because + # there's no all.sh component that does what we want. We should set + # CFLAGS for arm64 host CC. - scripts/config.py full - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT - scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY @@ -128,7 +132,6 @@ jobs: - tests/scripts/travis-log-failure.sh - tests/context-info.sh - after_failure: - tests/scripts/travis-log-failure.sh From c66deda4c59d23e07f9e8d850d980021190b0c45 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Fri, 24 Feb 2023 11:42:07 +0800 Subject: [PATCH 23/24] Add explanation for aesce limitation Signed-off-by: Jerry Yu --- include/mbedtls/mbedtls_config.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index cba133c4f60..774fc948a18 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2079,6 +2079,10 @@ * of \c -march=armv8-a+crypto . * * \warning `MBEDTLS_SHA512_USE_A64_CRYPTO_*` should be disabled when enabled + * because unexpected instruction will be generated in AESCE module. + * `MBEDTLS_SHA512_USE_A64_CRYPTO_*` requires \c -march=armv8.2-a+sha3, + * compiler optimizes the code with `eor3` that is part of sha3 + * extension and unexpected in AESCE. * * \warning Runtime detection only works on linux. For non-linux operation * system, crypto extension MUST be supported by CPU. From 608e1093de045e927f8af8fa261a0e33581edd34 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Tue, 28 Feb 2023 12:50:00 +0800 Subject: [PATCH 24/24] Improve comment about conflicts between aesce and sha512-crypto Signed-off-by: Jerry Yu --- include/mbedtls/mbedtls_config.h | 12 +++++++----- library/aesce.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 774fc948a18..4f51d0a9f3d 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -2078,11 +2078,13 @@ * \note The code uses Neon intrinsics, so \c CFLAGS must be set to a minimum * of \c -march=armv8-a+crypto . * - * \warning `MBEDTLS_SHA512_USE_A64_CRYPTO_*` should be disabled when enabled - * because unexpected instruction will be generated in AESCE module. - * `MBEDTLS_SHA512_USE_A64_CRYPTO_*` requires \c -march=armv8.2-a+sha3, - * compiler optimizes the code with `eor3` that is part of sha3 - * extension and unexpected in AESCE. + * \warning If the target architecture is set to something that includes the + * SHA3 feature (e.g. `-march=armv8.2-a+sha3`), for example because + * `MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT` is desired, compilers + * generate code for `MBEDTLS_AESCE_C` that includes instructions + * only present with the (optional) SHA3 feature. This will lead to an + * undefined instruction exception if the code is run on a CPU without + * that feature. * * \warning Runtime detection only works on linux. For non-linux operation * system, crypto extension MUST be supported by CPU. diff --git a/library/aesce.h b/library/aesce.h index 1e72e5ba463..da424469971 100644 --- a/library/aesce.h +++ b/library/aesce.h @@ -31,7 +31,7 @@ #include "mbedtls/aes.h" -#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ defined(__aarch64__) && !defined(MBEDTLS_HAVE_ARM64) #define MBEDTLS_HAVE_ARM64 #endif