Skip to content

Commit

Permalink
Merge pull request #5632 from tom-cosgrove-arm/seclib-667-sha512-acce…
Browse files Browse the repository at this point in the history
…leration-mbedtls-internal

SECLIB-667: Accelerate SHA-512 with A64 crypto extensions
  • Loading branch information
daverodgman authored Mar 29, 2022
2 parents 63d97ad + 226aca1 commit 1c41501
Show file tree
Hide file tree
Showing 7 changed files with 563 additions and 19 deletions.
2 changes: 2 additions & 0 deletions ChangeLog.d/mbedtls_sha512_a64_crypto_acceleration.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Features
* A64 crypto extension support for SHA-512
55 changes: 55 additions & 0 deletions include/mbedtls/check_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,61 @@
#error "MBEDTLS_SHA384_C defined without MBEDTLS_SHA512_C"
#endif

#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) && \
defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
#error "Must only define one of MBEDTLS_SHA512_USE_A64_CRYPTO_*"
#endif

#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
#if !defined(MBEDTLS_SHA512_C)
#error "MBEDTLS_SHA512_USE_A64_CRYPTO_* defined without MBEDTLS_SHA512_C"
#endif
#if defined(MBEDTLS_SHA512_ALT) || defined(MBEDTLS_SHA512_PROCESS_ALT)
#error "MBEDTLS_SHA512_*ALT can't be used with MBEDTLS_SHA512_USE_A64_CRYPTO_*"
#endif
/*
* Best performance comes from most recent compilers, with intrinsics and -O3.
* Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and
* can't always detect __ARM_FEATURE_SHA512 (notably clang 7-12).
*
* GCC < 8 won't work at all (lacks the sha512 instructions)
* GCC >= 8 uses intrinsics, sets __ARM_FEATURE_SHA512
*
* Clang < 7 won't work at all (lacks the sha512 instructions)
* Clang 7-12 don't have intrinsics (but we work around that with inline
* assembler) or __ARM_FEATURE_SHA512
* Clang == 13.0.0 same as clang 12 (only seen on macOS)
* Clang >= 13.0.1 has __ARM_FEATURE_SHA512 and intrinsics
*/
#if defined(__aarch64__) && !defined(__ARM_FEATURE_SHA512)
/* Test Clang first, as it defines __GNUC__ */
# if defined(__clang__)
# if __clang_major__ < 7
# error "A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
# elif __clang_major__ < 13 || \
(__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0)
/* We implement the intrinsics with inline assembler, so don't error */
# else
# error "Must use minimum -march=armv8.2-a+sha3 for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
# endif
# elif defined(__GNUC__)
# if __GNUC__ < 8
# error "A more recent GCC is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
# else
# error "Must use minimum -march=armv8.2-a+sha3 for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
# endif
# else
# error "Only GCC and Clang supported for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
# endif
#endif

#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */

#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) && !defined(__aarch64__)
#error "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system"
#endif

#if defined(MBEDTLS_SHA224_C) && !defined(MBEDTLS_SHA256_C)
#error "MBEDTLS_SHA224_C defined without MBEDTLS_SHA256_C"
#endif
Expand Down
54 changes: 54 additions & 0 deletions include/mbedtls/mbedtls_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -2840,6 +2840,60 @@
*/
#define MBEDTLS_SHA512_C

/**
* \def MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
*
* Enable acceleration of the SHA-512 cryptographic hash algorithm with the
* Arm A64 cryptographic extensions if they are available at runtime. If not,
* it will fall back to the C implementation.
*
* \note If MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT is defined when building
* for a non-Aarch64 build it will be silently ignored.
*
* \note The code uses the SHA-512 Neon intrinsics, so requires GCC >= 8 or
* Clang >= 7, and \c CFLAGS must be set to a minimum of
* \c -march=armv8.2-a+sha3. An optimisation level of \c -O3 generates the
* fastest code.
*
* \warning MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT cannot be defined at the
* same time as MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY.
*
* Requires: MBEDTLS_SHA512_C.
*
* Module: library/sha512.c
*
* Uncomment to have the library check for the A64 SHA-512 crypto extensions
* and use them if available.
*/
//#define MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT

/**
* \def MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
*
* Enable acceleration of the SHA-512 cryptographic hash algorithm with the
* Arm A64 cryptographic extensions, which must be available at runtime (or
* an illegal instruction fault will occur).
*
* \note This allows builds with a smaller code size than with
* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
*
* \note The code uses the SHA-512 Neon intrinsics, so requires GCC >= 8 or
* Clang >= 7, and \c CFLAGS must be set to a minimum of
* \c -march=armv8.2-a+sha3. An optimisation level of \c -O3 generates the
* fastest code.
*
* \warning MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY cannot be defined at the same
* time as MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT.
*
* Requires: MBEDTLS_SHA512_C.
*
* Module: library/sha512.c
*
* Uncomment to have the library use the A64 SHA-512 crypto extensions
* unconditionally.
*/
//#define MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY

/**
* \def MBEDTLS_SSL_CACHE_C
*
Expand Down
19 changes: 13 additions & 6 deletions library/sha256.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,15 @@
defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
# include <arm_neon.h>
# endif
# if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) && defined(__linux__)
# include <sys/auxv.h>
# if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
# if defined(__unix__)
# if defined(__linux__)
/* Our preferred method of detection is getauxval() */
# include <sys/auxv.h>
# endif
/* Use SIGILL on Unix, and fall back to it on Linux */
# include <signal.h>
# endif
# endif
#elif defined(_M_ARM64)
# if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
Expand Down Expand Up @@ -272,10 +279,10 @@ static size_t mbedtls_internal_sha256_process_many_a64_crypto(
uint32x4_t abcd_orig = abcd;
uint32x4_t efgh_orig = efgh;

uint32x4_t sched0 = vld1q_u32( (const uint32_t *)( msg + 16 * 0 ) );
uint32x4_t sched1 = vld1q_u32( (const uint32_t *)( msg + 16 * 1 ) );
uint32x4_t sched2 = vld1q_u32( (const uint32_t *)( msg + 16 * 2 ) );
uint32x4_t sched3 = vld1q_u32( (const uint32_t *)( msg + 16 * 3 ) );
uint32x4_t sched0 = (uint32x4_t) vld1q_u8( msg + 16 * 0 );
uint32x4_t sched1 = (uint32x4_t) vld1q_u8( msg + 16 * 1 );
uint32x4_t sched2 = (uint32x4_t) vld1q_u8( msg + 16 * 2 );
uint32x4_t sched3 = (uint32x4_t) vld1q_u8( msg + 16 * 3 );

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* Will be true if not defined */
/* Untested on BE */
Expand Down
Loading

0 comments on commit 1c41501

Please sign in to comment.