diff --git a/CMakeLists.txt b/CMakeLists.txt index f3092326b72..d0d5ba9f3e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1168,6 +1168,24 @@ else() list(APPEND WOLFSSL_DEFINITIONS "-DWC_NO_HARDEN") endif() +# AES table cache-line touching: aes.c turns it on for RISC-V by default, and +# "no" clears that default without the rest of WOLFSSL_HARDEN=no. Raw cache +# STRING as for WOLFSSL_HARDEN_TLS: the option shares the macro's name, so +# "default" is blanked below to keep the #cmakedefine in options.h.in from +# seeing a true value when neither macro is emitted. +set(WOLFSSL_AES_TOUCH_LINES "default" CACHE STRING + "Touch every AES table cache line per lookup for cache-timing resistance, one of default/yes/no (default: aes.c decides, on for RISC-V)") +set_property(CACHE WOLFSSL_AES_TOUCH_LINES PROPERTY STRINGS "default;yes;no") +if(WOLFSSL_AES_TOUCH_LINES STREQUAL "yes") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_AES_TOUCH_LINES") +elseif(WOLFSSL_AES_TOUCH_LINES STREQUAL "no") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_AES_NO_TOUCH_LINES") +elseif(WOLFSSL_AES_TOUCH_LINES STREQUAL "default") + set(WOLFSSL_AES_TOUCH_LINES "") +else() + message(FATAL_ERROR "Invalid value for WOLFSSL_AES_TOUCH_LINES -- must be default, yes, or no.") +endif() + add_option(WOLFSSL_OPENSSLEXTRA "Enable extra OpenSSL API, size+ (default: disabled)" "no" "yes;no") diff --git a/cmake/options.h.in b/cmake/options.h.in index b59a84629ac..1f66e60a285 100644 --- a/cmake/options.h.in +++ b/cmake/options.h.in @@ -301,6 +301,10 @@ extern "C" { #cmakedefine WOLFSSL_AES_OFB #undef WOLFSSL_AES_SIV #cmakedefine WOLFSSL_AES_SIV +#undef WOLFSSL_AES_TOUCH_LINES +#cmakedefine WOLFSSL_AES_TOUCH_LINES +#undef WOLFSSL_AES_NO_TOUCH_LINES +#cmakedefine WOLFSSL_AES_NO_TOUCH_LINES #undef HAVE_AES_ECB #cmakedefine HAVE_AES_ECB #undef WOLFSSL_AES_CTS diff --git a/configure.ac b/configure.ac index d256bd1dae3..f8f0ceda449 100644 --- a/configure.ac +++ b/configure.ac @@ -3595,6 +3595,21 @@ else AM_CFLAGS="$AM_CFLAGS -DWC_NO_HARDEN -DWC_NO_CACHE_RESISTANT" fi +# AES table cache-line touching (WOLFSSL_AES_TOUCH_LINES). aes.c turns it on +# for RISC-V; "no" clears that default without the rest of --disable-harden. +AC_ARG_ENABLE([aes-touch-lines], + [AS_HELP_STRING([--enable-aes-touch-lines],[Touch every AES table cache line per lookup for cache-timing resistance (default: enabled on RISC-V, disabled elsewhere)])], + [ENABLED_AES_TOUCH_LINES=$enableval], + [ENABLED_AES_TOUCH_LINES=default]) + +if test "$ENABLED_AES_TOUCH_LINES" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_TOUCH_LINES" +elif test "$ENABLED_AES_TOUCH_LINES" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_NO_TOUCH_LINES" +fi + # Fault protection hardening AC_ARG_ENABLE([faultharden], [AS_HELP_STRING([--enable-faultharden],[Enable Fault Hardened build (default: disabled)])], @@ -15132,6 +15147,7 @@ echo " * Distro Build: $ENABLED_DISTRO" echo " * Enterprise Build: $ENABLED_ENTERPRISE" echo " * Reproducible Build: $ENABLED_REPRODUCIBLE_BUILD" echo " * Side-channel Hardening: $ENABLED_HARDEN" +echo " * AES touch lines: $ENABLED_AES_TOUCH_LINES" echo " * Single Precision Math: $ENABLED_SP" if test "$ENABLED_SP_MATH_ALL" != "no" diff --git a/doc/ALGORITHM_DEFINES.md b/doc/ALGORITHM_DEFINES.md index 20182dc90b1..e5cdf7d806f 100644 --- a/doc/ALGORITHM_DEFINES.md +++ b/doc/ALGORITHM_DEFINES.md @@ -167,6 +167,7 @@ Size and side channels: | `WOLFSSL_AES_SMALL_TABLES` | 256-byte tables instead of 4 × 1 kB | | `WOLFSSL_AES_NO_UNROLL` | Do not unroll the round loop | | `WOLFSSL_AES_TOUCH_LINES` | Touch every cache line — cache-timing resistance | +| `WOLFSSL_AES_NO_TOUCH_LINES` | Clear the RISC-V touch-lines default on its own; `WC_NO_CACHE_RESISTANT` also drops the ECC/RSA cache resistance | | `WC_AES_BITSLICED` | Bitsliced implementation, constant time by construction | | `AES_GCM_GMULT_NCT` | Non-constant-time GHASH. Faster, weaker | | `WOLFSSL_AESGCM_STREAM` | Streaming GCM API for data that does not fit in memory | diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 5e5c347a49e..f9f8b4c45a4 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -6994,9 +6994,14 @@ void bench_aesofb(int useDeviceID) #ifdef WOLFSSL_AES_XTS -void bench_aesxts(void) +#ifdef WOLFSSL_AESXTS_STREAM +static void bench_aesxts_key(const byte* key, word32 keySz, const char* encLbl, + const char* decLbl, const char* streamEncLbl, const char* streamDecLbl) +#else +static void bench_aesxts_key(const byte* key, word32 keySz, const char* encLbl, + const char* decLbl) +#endif { -#ifdef WOLFSSL_AES_128 WC_DECLARE_VAR(aes, XtsAes, 1, HEAP_HINT); double start; int i, count, ret; @@ -7016,13 +7021,6 @@ void bench_aesxts(void) #endif DECLARE_MULTI_VALUE_STATS_VARS() - static const unsigned char k1[] = { - 0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35, - 0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62, - 0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18, - 0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f - }; - static const unsigned char i1[] = { 0x4f, 0xae, 0xf7, 0x11, 0x7c, 0xda, 0x59, 0xc6, 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5 @@ -7033,7 +7031,7 @@ void bench_aesxts(void) WC_ALLOC_VAR(aes, XtsAes, 1, HEAP_HINT); - ret = wc_AesXtsSetKey(aes, k1, sizeof(k1), AES_ENCRYPTION, + ret = wc_AesXtsSetKey(aes, key, keySz, AES_ENCRYPTION, HEAP_HINT, devId); if (ret != 0) { printf("wc_AesXtsSetKey failed, ret = %d\n", ret); @@ -7057,7 +7055,7 @@ void bench_aesxts(void) #endif ); - bench_stats_sym_finish("AES-XTS-enc", 0, count, bench_size, start, ret); + bench_stats_sym_finish(encLbl, 0, count, bench_size, start, ret); #ifdef MULTI_VALUE_STATISTICS bench_multi_value_stats(max, min, sum, squareSum, runs); #endif @@ -7111,7 +7109,7 @@ void bench_aesxts(void) #endif ); - bench_stats_sym_finish("AES-XTS-stream-enc", 0, count, bench_size, + bench_stats_sym_finish(streamEncLbl, 0, count, bench_size, start, ret); #ifdef MULTI_VALUE_STATISTICS bench_multi_value_stats(max, min, sum, squareSum, runs); @@ -7121,7 +7119,7 @@ void bench_aesxts(void) wc_AesXtsFree(aes); /* decryption benchmark */ - ret = wc_AesXtsSetKey(aes, k1, sizeof(k1), AES_DECRYPTION, + ret = wc_AesXtsSetKey(aes, key, keySz, AES_DECRYPTION, HEAP_HINT, devId); if (ret != 0) { printf("wc_AesXtsSetKey failed, ret = %d\n", ret); @@ -7148,7 +7146,7 @@ void bench_aesxts(void) #endif ); - bench_stats_sym_finish("AES-XTS-dec", 0, count, bench_size, start, ret); + bench_stats_sym_finish(decLbl, 0, count, bench_size, start, ret); #ifdef MULTI_VALUE_STATISTICS bench_multi_value_stats(max, min, sum, squareSum, runs); #endif @@ -7192,7 +7190,7 @@ void bench_aesxts(void) #endif ); - bench_stats_sym_finish("AES-XTS-stream-dec", 0, count, bench_size, + bench_stats_sym_finish(streamDecLbl, 0, count, bench_size, start, ret); #ifdef MULTI_VALUE_STATISTICS bench_multi_value_stats(max, min, sum, squareSum, runs); @@ -7205,8 +7203,49 @@ void bench_aesxts(void) wc_AesXtsFree(aes); WC_FREE_VAR(aes, HEAP_HINT); -#else - printf("AES-XTS benchmark is with 128-bit keys only\n"); +} + +void bench_aesxts(void) +{ +#ifdef WOLFSSL_AES_128 + static const unsigned char k1[] = { + 0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35, + 0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62, + 0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18, + 0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f + }; +#endif +#ifdef WOLFSSL_AES_256 + static const unsigned char k2[] = { + 0x1e, 0xa6, 0x61, 0xc5, 0x8d, 0x94, 0x3a, 0x0e, + 0x48, 0x01, 0xe4, 0x2f, 0x4b, 0x09, 0x47, 0x14, + 0x9e, 0x7f, 0x9f, 0x8e, 0x3e, 0x68, 0xd0, 0xc7, + 0x50, 0x52, 0x10, 0xbd, 0x31, 0x1a, 0x0e, 0x7c, + 0xd6, 0xe1, 0x3f, 0xfd, 0xf2, 0x41, 0x8d, 0x8d, + 0x19, 0x11, 0xc0, 0x04, 0xcd, 0xa5, 0x8d, 0xa3, + 0xd6, 0x19, 0xb7, 0xe2, 0xb9, 0x14, 0x1e, 0x58, + 0x31, 0x8e, 0xea, 0x39, 0x2c, 0xf4, 0x1b, 0x08 + }; +#endif + +#ifdef WOLFSSL_AES_128 + bench_aesxts_key(k1, (word32)sizeof(k1), "AES-128-XTS-enc", + "AES-128-XTS-dec" +#ifdef WOLFSSL_AESXTS_STREAM + , "AES-128-XTS-stream-enc", "AES-128-XTS-stream-dec" +#endif + ); +#endif +#ifdef WOLFSSL_AES_256 + bench_aesxts_key(k2, (word32)sizeof(k2), "AES-256-XTS-enc", + "AES-256-XTS-dec" +#ifdef WOLFSSL_AESXTS_STREAM + , "AES-256-XTS-stream-enc", "AES-256-XTS-stream-dec" +#endif + ); +#endif +#if !defined(WOLFSSL_AES_128) && !defined(WOLFSSL_AES_256) + printf("AES-XTS benchmark needs WOLFSSL_AES_128 or WOLFSSL_AES_256\n"); #endif } #endif /* WOLFSSL_AES_XTS */ diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 893d9871f06..709cc51e7ad 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -2034,9 +2034,11 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, #ifdef NEED_AES_TABLES #ifndef WC_AES_BITSLICED -/* RISC-V defaults touch-lines on; set it here, before the alignment below. */ +/* RISC-V defaults touch-lines on; set it here, before the alignment below. + * WOLFSSL_AES_NO_TOUCH_LINES clears only this default and leaves the rest of + * the hardening in place. */ #if defined(__riscv) && !defined(WC_NO_CACHE_RESISTANT) && \ - !defined(WOLFSSL_AES_TOUCH_LINES) + !defined(WOLFSSL_AES_NO_TOUCH_LINES) && !defined(WOLFSSL_AES_TOUCH_LINES) #define WOLFSSL_AES_TOUCH_LINES #endif /* Define the stride before the tables so they can be aligned to it: the masked