#if defined(__clang__) && (__clang_major__ >= 4)
#if defined(__ARM_ARCH) && (__ARM_ARCH_PROFILE == 'A')
#if __ARM_ARCH >= 8
#define MBEDTLS_SHA256_ARCH_IS_ARMV8_A
#endif
#endif
#if defined(MBEDTLS_SHA256_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO)
#define __ARM_FEATURE_CRYPTO …
#define __ARM_FEATURE_SHA2 …
#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG
#endif
#endif
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#include "common.h"
#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)
#include "mbedtls/sha256.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#include "mbedtls/platform.h"
#if defined(MBEDTLS_ARCH_IS_ARMV8_A)
# if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
# if !defined(MBEDTLS_HAVE_NEON_INTRINSICS)
# if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
# warning "Target does not support NEON instructions"
# undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
# else
# error "Target does not support NEON instructions"
# endif
# endif
# endif
# if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
# if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
# if defined(__ARMCOMPILER_VERSION)
# if __ARMCOMPILER_VERSION <= 6090000
# error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
# endif
# pragma clang attribute push (__attribute__((target("sha2"))), apply_to=function)
#define MBEDTLS_POP_TARGET_PRAGMA
# elif defined(__clang__)
# if __clang_major__ < 4
# error "A more recent Clang is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
# endif
# pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
#define MBEDTLS_POP_TARGET_PRAGMA
# elif defined(__GNUC__)
# if __GNUC__ < 6
# error "A more recent GCC is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
# else
# pragma GCC push_options
# pragma GCC target ("arch=armv8-a+crypto")
#define MBEDTLS_POP_TARGET_PRAGMA
# endif
# else
# error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
# endif
# endif
# endif
# if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
# if defined(__unix__)
# if defined(__linux__)
# include <sys/auxv.h>
# if !defined(HWCAP_SHA2)
#define HWCAP_SHA2 …
# endif
# if !defined(HWCAP2_SHA2)
#define HWCAP2_SHA2 …
# endif
# endif
# include <signal.h>
# endif
# endif
#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
# undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY
# undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
#endif
#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
#if defined(MBEDTLS_ARCH_IS_ARM64) && defined(HWCAP_SHA2)
static int mbedtls_a64_crypto_sha256_determine_support(void)
{
return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0;
}
#elif defined(MBEDTLS_ARCH_IS_ARM32) && defined(HWCAP2_SHA2)
static int mbedtls_a64_crypto_sha256_determine_support(void)
{
return (getauxval(AT_HWCAP2) & HWCAP2_SHA2) ? 1 : 0;
}
#elif defined(__APPLE__)
static int mbedtls_a64_crypto_sha256_determine_support(void)
{
return 1;
}
#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <processthreadsapi.h>
static int mbedtls_a64_crypto_sha256_determine_support(void)
{
return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ?
1 : 0;
}
#elif defined(__unix__) && defined(SIG_SETMASK)
#include <signal.h>
#include <setjmp.h>
static jmp_buf return_from_sigill;
static void sigill_handler(int signal)
{
(void) signal;
longjmp(return_from_sigill, 1);
}
static int mbedtls_a64_crypto_sha256_determine_support(void)
{
struct sigaction old_action, new_action;
sigset_t old_mask;
if (sigprocmask(0, NULL, &old_mask)) {
return 0;
}
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
new_action.sa_handler = sigill_handler;
sigaction(SIGILL, &new_action, &old_action);
static int ret = 0;
if (setjmp(return_from_sigill) == 0) {
#if defined(MBEDTLS_ARCH_IS_ARM64)
asm volatile ("sha256h q0, q0, v0.4s" : : : "v0");
#else
asm volatile ("sha256h.32 q0, q0, q0" : : : "q0");
#endif
ret = 1;
}
sigaction(SIGILL, &old_action, NULL);
sigprocmask(SIG_SETMASK, &old_mask, NULL);
return ret;
}
#else
#warning "No mechanism to detect ARMV8_CRYPTO found, using C code only"
#undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
#endif
#endif
#if !defined(MBEDTLS_SHA256_ALT)
#define SHA256_BLOCK_SIZE …
void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
{ … }
void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
{ … }
void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src)
{ … }
int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
{ … }
#if !defined(MBEDTLS_SHA256_PROCESS_ALT)
static const uint32_t K[] = …;
#endif
#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
#define mbedtls_internal_sha256_process_many_a64_crypto …
#define mbedtls_internal_sha256_process_a64_crypto …
#endif
static size_t mbedtls_internal_sha256_process_many_a64_crypto(
mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len)
{
uint32x4_t abcd = vld1q_u32(&ctx->state[0]);
uint32x4_t efgh = vld1q_u32(&ctx->state[4]);
size_t processed = 0;
for (;
len >= SHA256_BLOCK_SIZE;
processed += SHA256_BLOCK_SIZE,
msg += SHA256_BLOCK_SIZE,
len -= SHA256_BLOCK_SIZE) {
uint32x4_t tmp, abcd_prev;
uint32x4_t abcd_orig = abcd;
uint32x4_t efgh_orig = efgh;
uint32x4_t sched0 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 0));
uint32x4_t sched1 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 1));
uint32x4_t sched2 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 2));
uint32x4_t sched3 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 3));
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0)));
sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1)));
sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2)));
sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3)));
#endif
tmp = vaddq_u32(sched0, vld1q_u32(&K[0]));
abcd_prev = abcd;
abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
tmp = vaddq_u32(sched1, vld1q_u32(&K[4]));
abcd_prev = abcd;
abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
tmp = vaddq_u32(sched2, vld1q_u32(&K[8]));
abcd_prev = abcd;
abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
tmp = vaddq_u32(sched3, vld1q_u32(&K[12]));
abcd_prev = abcd;
abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
for (int t = 16; t < 64; t += 16) {
sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3);
tmp = vaddq_u32(sched0, vld1q_u32(&K[t]));
abcd_prev = abcd;
abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0);
tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4]));
abcd_prev = abcd;
abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1);
tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8]));
abcd_prev = abcd;
abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2);
tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12]));
abcd_prev = abcd;
abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
}
abcd = vaddq_u32(abcd, abcd_orig);
efgh = vaddq_u32(efgh, efgh_orig);
}
vst1q_u32(&ctx->state[0], abcd);
vst1q_u32(&ctx->state[4], efgh);
return processed;
}
#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
static
#endif
int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,
const unsigned char data[SHA256_BLOCK_SIZE])
{
return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data,
SHA256_BLOCK_SIZE) ==
SHA256_BLOCK_SIZE) ? 0 : -1;
}
#endif
#if defined(MBEDTLS_POP_TARGET_PRAGMA)
#if defined(__clang__)
#pragma clang attribute pop
#elif defined(__GNUC__)
#pragma GCC pop_options
#endif
#undef MBEDTLS_POP_TARGET_PRAGMA
#endif
#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
#define mbedtls_internal_sha256_process_many_c …
#define mbedtls_internal_sha256_process_c …
#endif
#if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \
!defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
#define SHR(x, n) …
#define ROTR(x, n) …
#define S0(x) …
#define S1(x) …
#define S2(x) …
#define S3(x) …
#define F0(x, y, z) …
#define F1(x, y, z) …
#define R(t) …
#define P(a, b, c, d, e, f, g, h, x, K) …
#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
static
#endif
int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx,
const unsigned char data[SHA256_BLOCK_SIZE])
{ … }
#endif
#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
static size_t mbedtls_internal_sha256_process_many_c(
mbedtls_sha256_context *ctx, const uint8_t *data, size_t len)
{ … }
#endif
#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
static int mbedtls_a64_crypto_sha256_has_support(void)
{
static int done = 0;
static int supported = 0;
if (!done) {
supported = mbedtls_a64_crypto_sha256_determine_support();
done = 1;
}
return supported;
}
static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx,
const uint8_t *msg, size_t len)
{
if (mbedtls_a64_crypto_sha256_has_support()) {
return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len);
} else {
return mbedtls_internal_sha256_process_many_c(ctx, msg, len);
}
}
int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,
const unsigned char data[SHA256_BLOCK_SIZE])
{
if (mbedtls_a64_crypto_sha256_has_support()) {
return mbedtls_internal_sha256_process_a64_crypto(ctx, data);
} else {
return mbedtls_internal_sha256_process_c(ctx, data);
}
}
#endif
int mbedtls_sha256_update(mbedtls_sha256_context *ctx,
const unsigned char *input,
size_t ilen)
{ … }
int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
unsigned char *output)
{ … }
#endif
int mbedtls_sha256(const unsigned char *input,
size_t ilen,
unsigned char *output,
int is224)
{ … }
#if defined(MBEDTLS_SELF_TEST)
static const unsigned char sha_test_buf[3][57] = …;
static const size_t sha_test_buflen[3] = …;
sha_test_sum_t;
#if defined(MBEDTLS_SHA224_C)
static sha_test_sum_t sha224_test_sum[] = …;
#endif
#if defined(MBEDTLS_SHA256_C)
static sha_test_sum_t sha256_test_sum[] = …;
#endif
static int mbedtls_sha256_common_self_test(int verbose, int is224)
{ … }
#if defined(MBEDTLS_SHA256_C)
int mbedtls_sha256_self_test(int verbose)
{ … }
#endif
#if defined(MBEDTLS_SHA224_C)
int mbedtls_sha224_self_test(int verbose)
{ … }
#endif
#endif
#endif