diff --git a/BUILDING.md b/BUILDING.md index 3fb7ea6ecf..a8988a3fd2 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -218,7 +218,7 @@ Both sets of tests may also be run with `ninja -C build run_tests`, but CMake If your project is unable to take on a Go or Perl dependency, the AWS-LC repository provides generated build files. These can be used in place of the files that would -normally be generated by these dependencies. +normally be generated by these dependencies. It is still recommended to have both Go and Perl installed to be able to run the full range of unit tests, as well as running valgrind and SDE tests. Building without Go now @@ -228,12 +228,46 @@ More information on this can be found in [INCORPORATING.md](/INCORPORATING.md). # Snapsafe Detection -AWS-LC supports Snapsafe-type uniqueness breaking event detection -on Linux using SysGenID (https://lkml.org/lkml/2021/3/8/677). This mechanism -is used for security hardening. If a SysGenID interface is not found, then the -mechanism is ignored. +AWS-LC supports Snapsafe-type uniqueness breaking event detection +on Linux using SysGenID (https://lkml.org/lkml/2021/3/8/677). This mechanism +is used for security hardening. If a SysGenID interface is not found, then the +mechanism is ignored. ## Snapsafe Prerequisites -Snapshots taken on active hosts can potentially be unsafe to use. +Snapshots taken on active hosts can potentially be unsafe to use. See "Snapshot Safety Prerequisites" here: https://lkml.org/lkml/2021/3/8/677 + +# Data Independent Timing on AArch64 + +The Data Independent Timing (DIT) flag on Arm64 processors, when +enabled, ensures the following as per [Arm A-profile Architecture +Registers +Document](https://developer.arm.com/documentation/ddi0601/2023-12/AArch64-Registers/DIT--Data-Independent-Timing): +- The timing of every load and store instruction is insensitive to the + value of the data being loaded or stored. +- For certain data processing instructions, the instruction takes a + time which is independent of the data in the registers and the NZCV + flags. + +It is also expected to disable the Data Memory-dependent Prefetcher +(DMP) feature of Apple M-series CPUs starting at M3 as per [this +article](https://appleinsider.com/articles/24/03/21/apple-silicon-vulnerability-leaks-encryption-keys-and-cant-be-patched-easily). + +Building with the option `-DENABLE_DATA_INDEPENDENT_TIMING_AARCH64=ON` +will enable the macro `SET_DIT_AUTO_DISABLE`. This macro is present at +the entry of functions that process/load/store secret data to enable +the DIT flag and then set it to its original value on entry. With +this build option, there is an effect on performance that varies by +function and by processor architecture. The effect is mostly due to +enabling and disabling the DIT flag. If it remains enabled over many +calls, the effect can be largely mitigated. Hence, the macro can be +inserted in the caller's application at the beginning of the code +scope that makes repeated calls to AWS-LC cryptographic +functions. Alternatively, the functions `armv8_enable_dit` and +`armv8_restore_dit` can be placed at the beginning and the end of +the code section, respectively. +An example of that usage is present in the benchmarking function +`Speed()` in `tool/speed.cc` when the `-dit` option is used + + ./tool/bssl speed -dit \ No newline at end of file diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h index 49c9d9dd2e..fbe6e21957 100644 --- a/include/openssl/crypto.h +++ b/include/openssl/crypto.h @@ -89,10 +89,22 @@ OPENSSL_EXPORT int CRYPTO_needs_hwcap2_workaround(void); #if defined(OPENSSL_AARCH64) && !defined(OPENSSL_WINDOWS) && defined(MAKE_DIT_AVAILABLE) // (TODO): See if we can detect the DIT capability in Windows environment +// armv8_enable_dit sets the DIT flag to 1 and returns its original value +// before it was called. uint64_t armv8_enable_dit(void); -void armv8_restore_dit(volatile uint64_t *original_dit); +// armv8_restore_dit takes as input a value to restore the DIT flag to. +void armv8_restore_dit(volatile uint64_t *original_dit); +// SET_DIT_AUTO_DISABLE can be inserted in the caller's application at +// the beginning of the code section that makes repeated calls to AWS-LC functions. +// The flag will be automatically restored to its original value at the end of the +// scope. +// This can minimise the effect on performance of repeatedly setting and +// disabling DIT. +// Instead of the macro, the functions above can be used. +// An example of their usage is present in the benchmarking function +// `Speed()` in `tool/speed.cc` when the option `-dit` is passed in. #define SET_DIT_AUTO_DISABLE \ volatile uint64_t _dit_restore_orig \ __attribute__((cleanup(armv8_restore_dit))) \ diff --git a/tool/speed.cc b/tool/speed.cc index cd7a9dcac0..5b1efcdaf7 100644 --- a/tool/speed.cc +++ b/tool/speed.cc @@ -93,6 +93,9 @@ static inline void *BM_memset(void *dst, int c, size_t n) { // g_print_json is true if printed output is JSON formatted. static bool g_print_json = false; +// g_dit is true if the DIT macro is to be enabled before benchmarking +static bool g_dit = false; + static std::string ChunkLenSuffix(size_t chunk_len) { char buf[32]; snprintf(buf, sizeof(buf), " (%zu byte%s)", chunk_len, @@ -2531,6 +2534,12 @@ static const argument_t kArguments[] = { "there is no information about the bytes per call for an operation, " "the JSON field for bytesPerCall will be omitted.", }, + { + "-dit", + kBooleanArgument, + "If this flag is set, the DIT flag is enabled before benchmarking and" + "disabled at the end." + }, { "", kOptionalArgument, @@ -2584,7 +2593,6 @@ static bool parseStringVectorToIntegerVector( } bool Speed(const std::vector &args) { - //SET_DIT_AUTO_DISABLE; #if AWSLC_API_VERSION > 27 OPENSSL_BEGIN_ALLOW_DEPRECATED // We started marking this as deprecated. @@ -2607,6 +2615,10 @@ bool Speed(const std::vector &args) { } } + if (args_map.count("-dit") != 0) { + g_dit = true; + } + if (args_map.count("-json") != 0) { g_print_json = true; } @@ -2659,6 +2671,12 @@ bool Speed(const std::vector &args) { } } + uint64_t original_dit = 0; + if (g_dit) + { + original_dit = armv8_enable_dit(); + } + // kTLSADLen is the number of bytes of additional data that TLS passes to // AEADs. static const size_t kTLSADLen = 13; @@ -2807,5 +2825,9 @@ bool Speed(const std::vector &args) { puts("\n]"); } + if (g_dit) + { + armv8_restore_dit(&original_dit); + } return true; }