Skip to content

Commit

Permalink
Merge pull request #7384 from yuhaoth/pr/add-aes-accelerator-only-mode
Browse files Browse the repository at this point in the history
AES: Add accelerator only mode
  • Loading branch information
daverodgman authored Aug 18, 2023
2 parents 505dffd + 0a6272d commit 1fdc884
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 38 deletions.
24 changes: 24 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,30 @@ jobs:
- tests/scripts/travis-log-failure.sh
- tests/context-info.sh

- name: Arm64 accelerators tests on arm64 host
os: linux
dist: focal
arch: arm64
addons:
apt:
packages:
- gcc
script:
# Do a manual build+test sequence rather than using all.sh.
#
# This is arm64 host only test for no runtime detection case. Internal
# and Open CI do not include Arm64 host, and they check if components
# are be tested. As result, it will always fail on `pre-test-check` in
# them.
- scripts/config.py unset MBEDTLS_AESNI_C
- scripts/config.py unset MBEDTLS_PADLOCK_C
- scripts/config.py set MBEDTLS_AESCE_C
- scripts/config.py set MBEDTLS_AES_USE_HARDWARE_ONLY
- make generated_files
- make
- programs/test/selftest aes | grep "using AESCE"
- tests/context-info.sh

after_failure:
- tests/scripts/travis-log-failure.sh

Expand Down
6 changes: 6 additions & 0 deletions ChangeLog.d/add-aes-hardware-only-option.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Features
* New configuration option MBEDTLS_AES_USE_HARDWARE_ONLY introduced. When
using CPU-accelerated AES (e.g., Arm Crypto Extensions), this option
disables the plain C implementation and the run-time detection for the
CPU feature, which reduces code size and avoids the vulnerability of the
plain C implementation.
4 changes: 0 additions & 4 deletions include/mbedtls/check_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,6 @@
#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites"
#endif

#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
#endif

#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C)
#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites"
#endif
Expand Down
14 changes: 14 additions & 0 deletions include/mbedtls/mbedtls_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -4016,4 +4016,18 @@
*/
//#define MBEDTLS_ECP_WITH_MPI_UINT

/*
* Disable plain C implementation for AES.
*
* When the plain C implementation is enabled, and an implementation using a
* special CPU feature (such as MBEDTLS_AESCE_C) is also enabled, runtime
* detection will be used to select between them.
*
* If only one implementation is present, runtime detection will not be used.
* This configuration will crash at runtime if running on a CPU without the
* necessary features. It will not build unless at least one of MBEDTLS_AESCE_C
* and/or MBEDTLS_AESNI_C is enabled & present in the build.
*/
//#define MBEDTLS_AES_USE_HARDWARE_ONLY

/** \} name SECTION: Module configuration options */
86 changes: 64 additions & 22 deletions library/aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,36 @@
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"

#if defined(__aarch64__)
#if !defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
#endif
#endif

#if defined(__amd64__) || defined(__x86_64__) || \
((defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC))
#if !defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
#endif
#endif

#if defined(__i386__) || defined(_M_IX86)
#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) && !defined(MBEDTLS_AESNI_C)
#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
#endif

#if defined(MBEDTLS_PADLOCK_C)
#if !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
#error "MBEDTLS_AES_USE_HARDWARE_ONLY cannot be defined when " \
"MBEDTLS_PADLOCK_C is set"
#endif
#endif
#endif

#if defined(MBEDTLS_PADLOCK_C)
#include "padlock.h"
#endif
Expand All @@ -47,7 +77,7 @@

#if !defined(MBEDTLS_AES_ALT)

#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
static int aes_padlock_ace = -1;
#endif

Expand Down Expand Up @@ -542,7 +572,7 @@ void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx)
* Note that the offset is in units of elements of buf, i.e. 32-bit words,
* i.e. an offset of 1 means 4 bytes and so on.
*/
#if (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) || \
#if (defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)) || \
(defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2)
#define MAY_NEED_TO_ALIGN
#endif
Expand All @@ -554,7 +584,7 @@ static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
#if defined(MAY_NEED_TO_ALIGN)
int align_16_bytes = 0;

#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
if (aes_padlock_ace == -1) {
aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
}
Expand Down Expand Up @@ -595,7 +625,6 @@ static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits)
{
unsigned int i;
uint32_t *RK;

switch (keybits) {
Expand Down Expand Up @@ -629,14 +658,15 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
}
#endif

for (i = 0; i < (keybits >> 5); i++) {
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
for (unsigned int i = 0; i < (keybits >> 5); i++) {
RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2);
}

switch (ctx->nr) {
case 10:

for (i = 0; i < 10; i++, RK += 4) {
for (unsigned int i = 0; i < 10; i++, RK += 4) {
RK[4] = RK[0] ^ RCON[i] ^
((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^
((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] << 8) ^
Expand All @@ -652,7 +682,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
case 12:

for (i = 0; i < 8; i++, RK += 6) {
for (unsigned int i = 0; i < 8; i++, RK += 6) {
RK[6] = RK[0] ^ RCON[i] ^
((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^
((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] << 8) ^
Expand All @@ -669,7 +699,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,

case 14:

for (i = 0; i < 7; i++, RK += 8) {
for (unsigned int i = 0; i < 7; i++, RK += 8) {
RK[8] = RK[0] ^ RCON[i] ^
((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^
((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] << 8) ^
Expand All @@ -695,6 +725,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
}

return 0;
#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
}
#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */

Expand All @@ -705,10 +736,13 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits)
{
int i, j, ret;
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
uint32_t *SK;
#endif
int ret;
mbedtls_aes_context cty;
uint32_t *RK;
uint32_t *SK;


mbedtls_aes_init(&cty);

Expand Down Expand Up @@ -740,15 +774,16 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
}
#endif

#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
SK = cty.buf + cty.rk_offset + cty.nr * 4;

*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;

for (i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8) {
for (j = 0; j < 4; j++, SK++) {
SK -= 8;
for (int i = ctx->nr - 1; i > 0; i--, SK -= 8) {
for (int j = 0; j < 4; j++, SK++) {
*RK++ = AES_RT0(FSb[MBEDTLS_BYTE_0(*SK)]) ^
AES_RT1(FSb[MBEDTLS_BYTE_1(*SK)]) ^
AES_RT2(FSb[MBEDTLS_BYTE_2(*SK)]) ^
Expand All @@ -760,7 +795,7 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;

#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
exit:
mbedtls_aes_free(&cty);

Expand Down Expand Up @@ -1062,17 +1097,20 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,
}
#endif

#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
if (aes_padlock_ace > 0) {
return mbedtls_padlock_xcryptecb(ctx, mode, input, output);
}
#endif

#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
if (mode == MBEDTLS_AES_ENCRYPT) {
return mbedtls_internal_aes_encrypt(ctx, input, output);
} else {
return mbedtls_internal_aes_decrypt(ctx, input, output);
}
#endif

}

#if defined(MBEDTLS_CIPHER_MODE_CBC)
Expand Down Expand Up @@ -1103,7 +1141,7 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}

#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
if (aes_padlock_ace > 0) {
if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) {
return 0;
Expand Down Expand Up @@ -1855,11 +1893,6 @@ int mbedtls_aes_self_test(int verbose)
#if defined(MBEDTLS_AES_ALT)
mbedtls_printf(" AES note: alternative implementation.\n");
#else /* MBEDTLS_AES_ALT */
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
mbedtls_printf(" AES note: using VIA Padlock.\n");
} else
#endif
#if defined(MBEDTLS_AESNI_HAVE_CODE)
#if MBEDTLS_AESNI_HAVE_CODE == 1
mbedtls_printf(" AES note: AESNI code present (assembly implementation).\n");
Expand All @@ -1872,12 +1905,21 @@ int mbedtls_aes_self_test(int verbose)
mbedtls_printf(" AES note: using AESNI.\n");
} else
#endif
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
mbedtls_printf(" AES note: using VIA Padlock.\n");
} else
#endif
#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
if (mbedtls_aesce_has_support()) {
mbedtls_printf(" AES note: using AESCE.\n");
} else
#endif
mbedtls_printf(" AES note: built-in implementation.\n");
{
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
mbedtls_printf(" AES note: built-in implementation.\n");
#endif
}
#endif /* MBEDTLS_AES_ALT */
}

Expand Down
2 changes: 2 additions & 0 deletions library/aesce.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
#include <sys/auxv.h>
#endif

#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
/*
* AES instruction support detection routine
*/
Expand All @@ -113,6 +114,7 @@ int mbedtls_aesce_has_support(void)
return 1;
#endif
}
#endif

/* Single round of AESCE encryption */
#define AESCE_ENCRYPT_ROUND \
Expand Down
5 changes: 5 additions & 0 deletions library/aesce.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ extern "C" {
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
int mbedtls_aesce_has_support(void);
#else
#define mbedtls_aesce_has_support() 1
#endif


/**
* \brief Internal AES-ECB block encryption and decryption
Expand Down
2 changes: 2 additions & 0 deletions library/aesni.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <immintrin.h>
#endif

#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
/*
* AES-NI support detection routine
*/
Expand Down Expand Up @@ -70,6 +71,7 @@ int mbedtls_aesni_has_support(unsigned int what)

return (c & what) != 0;
}
#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */

#if MBEDTLS_AESNI_HAVE_CODE == 2

Expand Down
26 changes: 21 additions & 5 deletions library/aesni.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,20 @@
/* Can we do AESNI with inline assembly?
* (Only implemented with gas syntax, only for 64-bit.)
*/
#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
(defined(__amd64__) || defined(__x86_64__)) && \
!defined(MBEDTLS_HAVE_X86_64)
#if !defined(MBEDTLS_HAVE_X86_64) && \
(defined(__amd64__) || defined(__x86_64__) || \
defined(_M_X64) || defined(_M_AMD64)) && \
!defined(_M_ARM64EC)
#define MBEDTLS_HAVE_X86_64
#endif

#if defined(MBEDTLS_AESNI_C)
#if !defined(MBEDTLS_HAVE_X86) && \
(defined(__i386__) || defined(_M_IX86))
#define MBEDTLS_HAVE_X86
#endif

#if defined(MBEDTLS_AESNI_C) && \
(defined(MBEDTLS_HAVE_X86_64) || defined(MBEDTLS_HAVE_X86))

/* Can we do AESNI with intrinsics?
* (Only implemented with certain compilers, only for certain targets.)
Expand All @@ -67,8 +74,13 @@
* In the long run, we will likely remove the assembly implementation. */
#if defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics
#elif defined(MBEDTLS_HAVE_X86_64)
#elif defined(MBEDTLS_HAVE_ASM) && \
defined(__GNUC__) && defined(MBEDTLS_HAVE_X86_64)
#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
#elif defined(__GNUC__)
# error "Must use `-mpclmul -msse2 -maes` for MBEDTLS_AESNI_C"
#else
#error "MBEDTLS_AESNI_C defined, but neither intrinsics nor assembly available"
#endif

#if defined(MBEDTLS_AESNI_HAVE_CODE)
Expand All @@ -88,7 +100,11 @@ extern "C" {
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
int mbedtls_aesni_has_support(unsigned int what);
#else
#define mbedtls_aesni_has_support(what) 1
#endif

/**
* \brief Internal AES-NI AES-ECB block encryption and decryption
Expand Down
Loading

0 comments on commit 1fdc884

Please sign in to comment.