1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * FIPS-180-2 compliant SHA-256 implementation 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 5*b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6817466cbSJens Wiklander */ 7817466cbSJens Wiklander /* 8817466cbSJens Wiklander * The SHA-256 Secure Hash Standard was published by NIST in 2002. 9817466cbSJens Wiklander * 10817466cbSJens Wiklander * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf 11817466cbSJens Wiklander */ 12817466cbSJens Wiklander 13*b0563631STom Van Eyck #if defined(__clang__) && (__clang_major__ >= 4) 14*b0563631STom Van Eyck 15*b0563631STom Van Eyck /* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if, 16*b0563631STom Van Eyck * but that is defined by build_info.h, and we need this block to happen first. */ 17*b0563631STom Van Eyck #if defined(__ARM_ARCH) && (__ARM_ARCH_PROFILE == 'A') 18*b0563631STom Van Eyck #if __ARM_ARCH >= 8 19*b0563631STom Van Eyck #define MBEDTLS_SHA256_ARCH_IS_ARMV8_A 20*b0563631STom Van Eyck #endif 21*b0563631STom Van Eyck #endif 22*b0563631STom Van Eyck 23*b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO) 2432b31808SJens Wiklander /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. 2532b31808SJens Wiklander * 2632b31808SJens Wiklander * The intrinsic declaration are guarded by predefined ACLE macros in clang: 2732b31808SJens Wiklander * these are normally only enabled by the -march option on the command line. 2832b31808SJens Wiklander * By defining the macros ourselves we gain access to those declarations without 2932b31808SJens Wiklander * requiring -march on the command line. 3032b31808SJens Wiklander * 31*b0563631STom Van Eyck * `arm_neon.h` is included by common.h, so we put these defines 3232b31808SJens Wiklander * at the top of this file, before any includes. 3332b31808SJens Wiklander */ 3432b31808SJens Wiklander #define __ARM_FEATURE_CRYPTO 1 3532b31808SJens Wiklander /* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions 3632b31808SJens Wiklander * 3732b31808SJens Wiklander * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it 3832b31808SJens Wiklander * for older compilers. 3932b31808SJens Wiklander */ 4032b31808SJens Wiklander #define __ARM_FEATURE_SHA2 1 4132b31808SJens Wiklander #define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG 4232b31808SJens Wiklander #endif 4332b31808SJens Wiklander 44*b0563631STom Van Eyck #endif /* defined(__clang__) && (__clang_major__ >= 4) */ 45*b0563631STom Van Eyck 46*b0563631STom Van Eyck /* Ensure that SIG_SETMASK is defined when -std=c99 is used. */ 47*b0563631STom Van Eyck #define _GNU_SOURCE 48*b0563631STom Van Eyck 497901324dSJerome Forissier #include "common.h" 50817466cbSJens Wiklander 5132b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C) 52817466cbSJens Wiklander 53817466cbSJens Wiklander #include "mbedtls/sha256.h" 543d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 5511fa71b9SJerome Forissier #include "mbedtls/error.h" 56817466cbSJens Wiklander 57817466cbSJens Wiklander #include <string.h> 58817466cbSJens Wiklander 59817466cbSJens Wiklander #include "mbedtls/platform.h" 60817466cbSJens Wiklander 61*b0563631STom Van Eyck #if defined(MBEDTLS_ARCH_IS_ARMV8_A) 62*b0563631STom Van Eyck 63*b0563631STom Van Eyck # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ 64*b0563631STom Van Eyck defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) 65*b0563631STom Van Eyck # if !defined(MBEDTLS_HAVE_NEON_INTRINSICS) 66*b0563631STom Van Eyck # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) 67*b0563631STom Van Eyck # warning "Target does not support NEON instructions" 68*b0563631STom Van Eyck # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT 69*b0563631STom Van Eyck # else 70*b0563631STom Van Eyck # error "Target does not support NEON instructions" 71*b0563631STom Van Eyck # endif 72*b0563631STom Van Eyck # endif 73*b0563631STom Van Eyck # endif 74*b0563631STom Van Eyck 75*b0563631STom Van Eyck # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ 76*b0563631STom Van Eyck defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) 7732b31808SJens Wiklander /* *INDENT-OFF* */ 78*b0563631STom Van Eyck 7932b31808SJens Wiklander # if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) 80*b0563631STom Van Eyck # if defined(__ARMCOMPILER_VERSION) 81*b0563631STom Van Eyck # if __ARMCOMPILER_VERSION <= 6090000 82*b0563631STom Van Eyck # error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" 83*b0563631STom Van Eyck # endif 84*b0563631STom Van Eyck # pragma clang attribute push (__attribute__((target("sha2"))), apply_to=function) 85*b0563631STom Van Eyck # define MBEDTLS_POP_TARGET_PRAGMA 86*b0563631STom Van Eyck # elif defined(__clang__) 8732b31808SJens Wiklander # if __clang_major__ < 4 88*b0563631STom Van Eyck # error "A more recent Clang is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" 8932b31808SJens Wiklander # endif 9032b31808SJens Wiklander # pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function) 9132b31808SJens Wiklander # define MBEDTLS_POP_TARGET_PRAGMA 9232b31808SJens Wiklander # elif defined(__GNUC__) 9332b31808SJens Wiklander /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some 9432b31808SJens Wiklander * intrinsics are missing. Missing intrinsics could be worked around. 9532b31808SJens Wiklander */ 9632b31808SJens Wiklander # if __GNUC__ < 6 97*b0563631STom Van Eyck # error "A more recent GCC is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" 9832b31808SJens Wiklander # else 9932b31808SJens Wiklander # pragma GCC push_options 10032b31808SJens Wiklander # pragma GCC target ("arch=armv8-a+crypto") 10132b31808SJens Wiklander # define MBEDTLS_POP_TARGET_PRAGMA 10232b31808SJens Wiklander # endif 10332b31808SJens Wiklander # else 104*b0563631STom Van Eyck # error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" 10532b31808SJens Wiklander # endif 10632b31808SJens Wiklander # endif 10732b31808SJens Wiklander /* *INDENT-ON* */ 108*b0563631STom Van Eyck 10932b31808SJens Wiklander # endif 110*b0563631STom Van Eyck # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) 11132b31808SJens Wiklander # if defined(__unix__) 11232b31808SJens Wiklander # if defined(__linux__) 11332b31808SJens Wiklander /* Our preferred method of detection is getauxval() */ 11432b31808SJens Wiklander # include <sys/auxv.h> 115*b0563631STom Van Eyck /* These are not always defined via sys/auxv.h */ 116*b0563631STom Van Eyck # if !defined(HWCAP_SHA2) 117*b0563631STom Van Eyck # define HWCAP_SHA2 (1 << 6) 118*b0563631STom Van Eyck # endif 119*b0563631STom Van Eyck # if !defined(HWCAP2_SHA2) 120*b0563631STom Van Eyck # define HWCAP2_SHA2 (1 << 3) 121*b0563631STom Van Eyck # endif 12232b31808SJens Wiklander # endif 12332b31808SJens Wiklander /* Use SIGILL on Unix, and fall back to it on Linux */ 12432b31808SJens Wiklander # include <signal.h> 12532b31808SJens Wiklander # endif 12632b31808SJens Wiklander # endif 127*b0563631STom Van Eyck #elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) 128*b0563631STom Van Eyck # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY 129*b0563631STom Van Eyck # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT 13032b31808SJens Wiklander #endif 13132b31808SJens Wiklander 132*b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) 13332b31808SJens Wiklander /* 13432b31808SJens Wiklander * Capability detection code comes early, so we can disable 135*b0563631STom Van Eyck * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT if no detection mechanism found 13632b31808SJens Wiklander */ 137*b0563631STom Van Eyck #if defined(MBEDTLS_ARCH_IS_ARM64) && defined(HWCAP_SHA2) 13832b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void) 13932b31808SJens Wiklander { 14032b31808SJens Wiklander return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0; 14132b31808SJens Wiklander } 142*b0563631STom Van Eyck #elif defined(MBEDTLS_ARCH_IS_ARM32) && defined(HWCAP2_SHA2) 143*b0563631STom Van Eyck static int mbedtls_a64_crypto_sha256_determine_support(void) 144*b0563631STom Van Eyck { 145*b0563631STom Van Eyck return (getauxval(AT_HWCAP2) & HWCAP2_SHA2) ? 1 : 0; 146*b0563631STom Van Eyck } 14732b31808SJens Wiklander #elif defined(__APPLE__) 14832b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void) 14932b31808SJens Wiklander { 15032b31808SJens Wiklander return 1; 15132b31808SJens Wiklander } 152*b0563631STom Van Eyck #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) 15332b31808SJens Wiklander #define WIN32_LEAN_AND_MEAN 15432b31808SJens Wiklander #include <Windows.h> 15532b31808SJens Wiklander #include <processthreadsapi.h> 15632b31808SJens Wiklander 15732b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void) 15832b31808SJens Wiklander { 15932b31808SJens Wiklander return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 16032b31808SJens Wiklander 1 : 0; 16132b31808SJens Wiklander } 16232b31808SJens Wiklander #elif defined(__unix__) && defined(SIG_SETMASK) 16332b31808SJens Wiklander /* Detection with SIGILL, setjmp() and longjmp() */ 16432b31808SJens Wiklander #include <signal.h> 16532b31808SJens Wiklander #include <setjmp.h> 16632b31808SJens Wiklander 16732b31808SJens Wiklander static jmp_buf return_from_sigill; 16832b31808SJens Wiklander 16932b31808SJens Wiklander /* 170*b0563631STom Van Eyck * Armv8-A SHA256 support detection via SIGILL 17132b31808SJens Wiklander */ 17232b31808SJens Wiklander static void sigill_handler(int signal) 17332b31808SJens Wiklander { 17432b31808SJens Wiklander (void) signal; 17532b31808SJens Wiklander longjmp(return_from_sigill, 1); 17632b31808SJens Wiklander } 17732b31808SJens Wiklander 17832b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void) 17932b31808SJens Wiklander { 18032b31808SJens Wiklander struct sigaction old_action, new_action; 18132b31808SJens Wiklander 18232b31808SJens Wiklander sigset_t old_mask; 18332b31808SJens Wiklander if (sigprocmask(0, NULL, &old_mask)) { 18432b31808SJens Wiklander return 0; 18532b31808SJens Wiklander } 18632b31808SJens Wiklander 18732b31808SJens Wiklander sigemptyset(&new_action.sa_mask); 18832b31808SJens Wiklander new_action.sa_flags = 0; 18932b31808SJens Wiklander new_action.sa_handler = sigill_handler; 19032b31808SJens Wiklander 19132b31808SJens Wiklander sigaction(SIGILL, &new_action, &old_action); 19232b31808SJens Wiklander 19332b31808SJens Wiklander static int ret = 0; 19432b31808SJens Wiklander 19532b31808SJens Wiklander if (setjmp(return_from_sigill) == 0) { /* First return only */ 19632b31808SJens Wiklander /* If this traps, we will return a second time from setjmp() with 1 */ 197*b0563631STom Van Eyck #if defined(MBEDTLS_ARCH_IS_ARM64) 198*b0563631STom Van Eyck asm volatile ("sha256h q0, q0, v0.4s" : : : "v0"); 199*b0563631STom Van Eyck #else 200*b0563631STom Van Eyck asm volatile ("sha256h.32 q0, q0, q0" : : : "q0"); 201*b0563631STom Van Eyck #endif 20232b31808SJens Wiklander ret = 1; 20332b31808SJens Wiklander } 20432b31808SJens Wiklander 20532b31808SJens Wiklander sigaction(SIGILL, &old_action, NULL); 20632b31808SJens Wiklander sigprocmask(SIG_SETMASK, &old_mask, NULL); 20732b31808SJens Wiklander 20832b31808SJens Wiklander return ret; 20932b31808SJens Wiklander } 21032b31808SJens Wiklander #else 211*b0563631STom Van Eyck #warning "No mechanism to detect ARMV8_CRYPTO found, using C code only" 212*b0563631STom Van Eyck #undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT 21332b31808SJens Wiklander #endif /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */ 21432b31808SJens Wiklander 215*b0563631STom Van Eyck #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ 216817466cbSJens Wiklander 2173d3b0591SJens Wiklander #if !defined(MBEDTLS_SHA256_ALT) 218817466cbSJens Wiklander 21932b31808SJens Wiklander #define SHA256_BLOCK_SIZE 64 22032b31808SJens Wiklander 221817466cbSJens Wiklander void mbedtls_sha256_init(mbedtls_sha256_context *ctx) 222817466cbSJens Wiklander { 223817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_sha256_context)); 224817466cbSJens Wiklander } 225817466cbSJens Wiklander 226817466cbSJens Wiklander void mbedtls_sha256_free(mbedtls_sha256_context *ctx) 227817466cbSJens Wiklander { 22832b31808SJens Wiklander if (ctx == NULL) { 229817466cbSJens Wiklander return; 23032b31808SJens Wiklander } 231817466cbSJens Wiklander 2323d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha256_context)); 233817466cbSJens Wiklander } 234817466cbSJens Wiklander 235817466cbSJens Wiklander void mbedtls_sha256_clone(mbedtls_sha256_context *dst, 236817466cbSJens Wiklander const mbedtls_sha256_context *src) 237817466cbSJens Wiklander { 238817466cbSJens Wiklander *dst = *src; 239817466cbSJens Wiklander } 240817466cbSJens Wiklander 241817466cbSJens Wiklander /* 242817466cbSJens Wiklander * SHA-256 context setup 243817466cbSJens Wiklander */ 24432b31808SJens Wiklander int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224) 245817466cbSJens Wiklander { 24632b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) 24732b31808SJens Wiklander if (is224 != 0 && is224 != 1) { 24832b31808SJens Wiklander return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; 24932b31808SJens Wiklander } 25032b31808SJens Wiklander #elif defined(MBEDTLS_SHA256_C) 25132b31808SJens Wiklander if (is224 != 0) { 25232b31808SJens Wiklander return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; 25332b31808SJens Wiklander } 25432b31808SJens Wiklander #else /* defined MBEDTLS_SHA224_C only */ 25532b31808SJens Wiklander if (is224 == 0) { 25632b31808SJens Wiklander return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; 25732b31808SJens Wiklander } 25832b31808SJens Wiklander #endif 2593d3b0591SJens Wiklander 260817466cbSJens Wiklander ctx->total[0] = 0; 261817466cbSJens Wiklander ctx->total[1] = 0; 262817466cbSJens Wiklander 26332b31808SJens Wiklander if (is224 == 0) { 26432b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C) 265817466cbSJens Wiklander ctx->state[0] = 0x6A09E667; 266817466cbSJens Wiklander ctx->state[1] = 0xBB67AE85; 267817466cbSJens Wiklander ctx->state[2] = 0x3C6EF372; 268817466cbSJens Wiklander ctx->state[3] = 0xA54FF53A; 269817466cbSJens Wiklander ctx->state[4] = 0x510E527F; 270817466cbSJens Wiklander ctx->state[5] = 0x9B05688C; 271817466cbSJens Wiklander ctx->state[6] = 0x1F83D9AB; 272817466cbSJens Wiklander ctx->state[7] = 0x5BE0CD19; 27332b31808SJens Wiklander #endif 27432b31808SJens Wiklander } else { 27532b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) 276817466cbSJens Wiklander ctx->state[0] = 0xC1059ED8; 277817466cbSJens Wiklander ctx->state[1] = 0x367CD507; 278817466cbSJens Wiklander ctx->state[2] = 0x3070DD17; 279817466cbSJens Wiklander ctx->state[3] = 0xF70E5939; 280817466cbSJens Wiklander ctx->state[4] = 0xFFC00B31; 281817466cbSJens Wiklander ctx->state[5] = 0x68581511; 282817466cbSJens Wiklander ctx->state[6] = 0x64F98FA7; 283817466cbSJens Wiklander ctx->state[7] = 0xBEFA4FA4; 2843d3b0591SJens Wiklander #endif 28532b31808SJens Wiklander } 28632b31808SJens Wiklander 28732b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) 28832b31808SJens Wiklander ctx->is224 = is224; 28932b31808SJens Wiklander #endif 29032b31808SJens Wiklander 29132b31808SJens Wiklander return 0; 29232b31808SJens Wiklander } 2933d3b0591SJens Wiklander 294817466cbSJens Wiklander #if !defined(MBEDTLS_SHA256_PROCESS_ALT) 295817466cbSJens Wiklander static const uint32_t K[] = 296817466cbSJens Wiklander { 297817466cbSJens Wiklander 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 298817466cbSJens Wiklander 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 299817466cbSJens Wiklander 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 300817466cbSJens Wiklander 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 301817466cbSJens Wiklander 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 302817466cbSJens Wiklander 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 303817466cbSJens Wiklander 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 304817466cbSJens Wiklander 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 305817466cbSJens Wiklander 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 306817466cbSJens Wiklander 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 307817466cbSJens Wiklander 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 308817466cbSJens Wiklander 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 309817466cbSJens Wiklander 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 310817466cbSJens Wiklander 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 311817466cbSJens Wiklander 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 312817466cbSJens Wiklander 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, 313817466cbSJens Wiklander }; 314817466cbSJens Wiklander 31532b31808SJens Wiklander #endif 31632b31808SJens Wiklander 317*b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ 318*b0563631STom Van Eyck defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) 31932b31808SJens Wiklander 320*b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) 32132b31808SJens Wiklander # define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many 32232b31808SJens Wiklander # define mbedtls_internal_sha256_process_a64_crypto mbedtls_internal_sha256_process 32332b31808SJens Wiklander #endif 32432b31808SJens Wiklander 32532b31808SJens Wiklander static size_t mbedtls_internal_sha256_process_many_a64_crypto( 32632b31808SJens Wiklander mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len) 32732b31808SJens Wiklander { 32832b31808SJens Wiklander uint32x4_t abcd = vld1q_u32(&ctx->state[0]); 32932b31808SJens Wiklander uint32x4_t efgh = vld1q_u32(&ctx->state[4]); 33032b31808SJens Wiklander 33132b31808SJens Wiklander size_t processed = 0; 33232b31808SJens Wiklander 33332b31808SJens Wiklander for (; 33432b31808SJens Wiklander len >= SHA256_BLOCK_SIZE; 33532b31808SJens Wiklander processed += SHA256_BLOCK_SIZE, 33632b31808SJens Wiklander msg += SHA256_BLOCK_SIZE, 33732b31808SJens Wiklander len -= SHA256_BLOCK_SIZE) { 33832b31808SJens Wiklander uint32x4_t tmp, abcd_prev; 33932b31808SJens Wiklander 34032b31808SJens Wiklander uint32x4_t abcd_orig = abcd; 34132b31808SJens Wiklander uint32x4_t efgh_orig = efgh; 34232b31808SJens Wiklander 343*b0563631STom Van Eyck uint32x4_t sched0 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 0)); 344*b0563631STom Van Eyck uint32x4_t sched1 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 1)); 345*b0563631STom Van Eyck uint32x4_t sched2 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 2)); 346*b0563631STom Van Eyck uint32x4_t sched3 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 3)); 34732b31808SJens Wiklander 34832b31808SJens Wiklander #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* Will be true if not defined */ 34932b31808SJens Wiklander /* Untested on BE */ 35032b31808SJens Wiklander sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0))); 35132b31808SJens Wiklander sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1))); 35232b31808SJens Wiklander sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2))); 35332b31808SJens Wiklander sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3))); 35432b31808SJens Wiklander #endif 35532b31808SJens Wiklander 35632b31808SJens Wiklander /* Rounds 0 to 3 */ 35732b31808SJens Wiklander tmp = vaddq_u32(sched0, vld1q_u32(&K[0])); 35832b31808SJens Wiklander abcd_prev = abcd; 35932b31808SJens Wiklander abcd = vsha256hq_u32(abcd_prev, efgh, tmp); 36032b31808SJens Wiklander efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); 36132b31808SJens Wiklander 36232b31808SJens Wiklander /* Rounds 4 to 7 */ 36332b31808SJens Wiklander tmp = vaddq_u32(sched1, vld1q_u32(&K[4])); 36432b31808SJens Wiklander abcd_prev = abcd; 36532b31808SJens Wiklander abcd = vsha256hq_u32(abcd_prev, efgh, tmp); 36632b31808SJens Wiklander efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); 36732b31808SJens Wiklander 36832b31808SJens Wiklander /* Rounds 8 to 11 */ 36932b31808SJens Wiklander tmp = vaddq_u32(sched2, vld1q_u32(&K[8])); 37032b31808SJens Wiklander abcd_prev = abcd; 37132b31808SJens Wiklander abcd = vsha256hq_u32(abcd_prev, efgh, tmp); 37232b31808SJens Wiklander efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); 37332b31808SJens Wiklander 37432b31808SJens Wiklander /* Rounds 12 to 15 */ 37532b31808SJens Wiklander tmp = vaddq_u32(sched3, vld1q_u32(&K[12])); 37632b31808SJens Wiklander abcd_prev = abcd; 37732b31808SJens Wiklander abcd = vsha256hq_u32(abcd_prev, efgh, tmp); 37832b31808SJens Wiklander efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); 37932b31808SJens Wiklander 38032b31808SJens Wiklander for (int t = 16; t < 64; t += 16) { 38132b31808SJens Wiklander /* Rounds t to t + 3 */ 38232b31808SJens Wiklander sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3); 38332b31808SJens Wiklander tmp = vaddq_u32(sched0, vld1q_u32(&K[t])); 38432b31808SJens Wiklander abcd_prev = abcd; 38532b31808SJens Wiklander abcd = vsha256hq_u32(abcd_prev, efgh, tmp); 38632b31808SJens Wiklander efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); 38732b31808SJens Wiklander 38832b31808SJens Wiklander /* Rounds t + 4 to t + 7 */ 38932b31808SJens Wiklander sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0); 39032b31808SJens Wiklander tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4])); 39132b31808SJens Wiklander abcd_prev = abcd; 39232b31808SJens Wiklander abcd = vsha256hq_u32(abcd_prev, efgh, tmp); 39332b31808SJens Wiklander efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); 39432b31808SJens Wiklander 39532b31808SJens Wiklander /* Rounds t + 8 to t + 11 */ 39632b31808SJens Wiklander sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1); 39732b31808SJens Wiklander tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8])); 39832b31808SJens Wiklander abcd_prev = abcd; 39932b31808SJens Wiklander abcd = vsha256hq_u32(abcd_prev, efgh, tmp); 40032b31808SJens Wiklander efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); 40132b31808SJens Wiklander 40232b31808SJens Wiklander /* Rounds t + 12 to t + 15 */ 40332b31808SJens Wiklander sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2); 40432b31808SJens Wiklander tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12])); 40532b31808SJens Wiklander abcd_prev = abcd; 40632b31808SJens Wiklander abcd = vsha256hq_u32(abcd_prev, efgh, tmp); 40732b31808SJens Wiklander efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); 40832b31808SJens Wiklander } 40932b31808SJens Wiklander 41032b31808SJens Wiklander abcd = vaddq_u32(abcd, abcd_orig); 41132b31808SJens Wiklander efgh = vaddq_u32(efgh, efgh_orig); 41232b31808SJens Wiklander } 41332b31808SJens Wiklander 41432b31808SJens Wiklander vst1q_u32(&ctx->state[0], abcd); 41532b31808SJens Wiklander vst1q_u32(&ctx->state[4], efgh); 41632b31808SJens Wiklander 41732b31808SJens Wiklander return processed; 41832b31808SJens Wiklander } 41932b31808SJens Wiklander 420*b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) 42132b31808SJens Wiklander /* 422*b0563631STom Van Eyck * This function is for internal use only if we are building both C and Armv8-A 42332b31808SJens Wiklander * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() 42432b31808SJens Wiklander */ 42532b31808SJens Wiklander static 42632b31808SJens Wiklander #endif 42732b31808SJens Wiklander int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx, 42832b31808SJens Wiklander const unsigned char data[SHA256_BLOCK_SIZE]) 42932b31808SJens Wiklander { 43032b31808SJens Wiklander return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data, 43132b31808SJens Wiklander SHA256_BLOCK_SIZE) == 43232b31808SJens Wiklander SHA256_BLOCK_SIZE) ? 0 : -1; 43332b31808SJens Wiklander } 43432b31808SJens Wiklander 435*b0563631STom Van Eyck #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ 436*b0563631STom Van Eyck 43732b31808SJens Wiklander #if defined(MBEDTLS_POP_TARGET_PRAGMA) 43832b31808SJens Wiklander #if defined(__clang__) 43932b31808SJens Wiklander #pragma clang attribute pop 44032b31808SJens Wiklander #elif defined(__GNUC__) 44132b31808SJens Wiklander #pragma GCC pop_options 44232b31808SJens Wiklander #endif 44332b31808SJens Wiklander #undef MBEDTLS_POP_TARGET_PRAGMA 44432b31808SJens Wiklander #endif 44532b31808SJens Wiklander 446*b0563631STom Van Eyck #if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) 44732b31808SJens Wiklander #define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many 44832b31808SJens Wiklander #define mbedtls_internal_sha256_process_c mbedtls_internal_sha256_process 44932b31808SJens Wiklander #endif 45032b31808SJens Wiklander 45132b31808SJens Wiklander 45232b31808SJens Wiklander #if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \ 453*b0563631STom Van Eyck !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) 45432b31808SJens Wiklander 4555b25c76aSJerome Forissier #define SHR(x, n) (((x) & 0xFFFFFFFF) >> (n)) 4565b25c76aSJerome Forissier #define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n)))) 457817466cbSJens Wiklander 458817466cbSJens Wiklander #define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) 459817466cbSJens Wiklander #define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) 460817466cbSJens Wiklander 461817466cbSJens Wiklander #define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) 462817466cbSJens Wiklander #define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) 463817466cbSJens Wiklander 4645b25c76aSJerome Forissier #define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y)))) 4655b25c76aSJerome Forissier #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) 466817466cbSJens Wiklander 467817466cbSJens Wiklander #define R(t) \ 468817466cbSJens Wiklander ( \ 4697901324dSJerome Forissier local.W[t] = S1(local.W[(t) - 2]) + local.W[(t) - 7] + \ 4707901324dSJerome Forissier S0(local.W[(t) - 15]) + local.W[(t) - 16] \ 471817466cbSJens Wiklander ) 472817466cbSJens Wiklander 473817466cbSJens Wiklander #define P(a, b, c, d, e, f, g, h, x, K) \ 4745b25c76aSJerome Forissier do \ 475817466cbSJens Wiklander { \ 4767901324dSJerome Forissier local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x); \ 4777901324dSJerome Forissier local.temp2 = S2(a) + F0((a), (b), (c)); \ 4787901324dSJerome Forissier (d) += local.temp1; (h) = local.temp1 + local.temp2; \ 4795b25c76aSJerome Forissier } while (0) 480817466cbSJens Wiklander 481*b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) 48232b31808SJens Wiklander /* 483*b0563631STom Van Eyck * This function is for internal use only if we are building both C and Armv8 48432b31808SJens Wiklander * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() 48532b31808SJens Wiklander */ 48632b31808SJens Wiklander static 48732b31808SJens Wiklander #endif 48832b31808SJens Wiklander int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx, 48932b31808SJens Wiklander const unsigned char data[SHA256_BLOCK_SIZE]) 490817466cbSJens Wiklander { 49132b31808SJens Wiklander struct { 492817466cbSJens Wiklander uint32_t temp1, temp2, W[64]; 493817466cbSJens Wiklander uint32_t A[8]; 4947901324dSJerome Forissier } local; 4957901324dSJerome Forissier 496817466cbSJens Wiklander unsigned int i; 497817466cbSJens Wiklander 49832b31808SJens Wiklander for (i = 0; i < 8; i++) { 4997901324dSJerome Forissier local.A[i] = ctx->state[i]; 50032b31808SJens Wiklander } 501817466cbSJens Wiklander 502817466cbSJens Wiklander #if defined(MBEDTLS_SHA256_SMALLER) 50332b31808SJens Wiklander for (i = 0; i < 64; i++) { 50432b31808SJens Wiklander if (i < 16) { 505039e02dfSJerome Forissier local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i); 50632b31808SJens Wiklander } else { 507817466cbSJens Wiklander R(i); 50832b31808SJens Wiklander } 509817466cbSJens Wiklander 5107901324dSJerome Forissier P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], 5117901324dSJerome Forissier local.A[5], local.A[6], local.A[7], local.W[i], K[i]); 512817466cbSJens Wiklander 5137901324dSJerome Forissier local.temp1 = local.A[7]; local.A[7] = local.A[6]; 5147901324dSJerome Forissier local.A[6] = local.A[5]; local.A[5] = local.A[4]; 5157901324dSJerome Forissier local.A[4] = local.A[3]; local.A[3] = local.A[2]; 5167901324dSJerome Forissier local.A[2] = local.A[1]; local.A[1] = local.A[0]; 5177901324dSJerome Forissier local.A[0] = local.temp1; 518817466cbSJens Wiklander } 519817466cbSJens Wiklander #else /* MBEDTLS_SHA256_SMALLER */ 52032b31808SJens Wiklander for (i = 0; i < 16; i++) { 521039e02dfSJerome Forissier local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i); 52232b31808SJens Wiklander } 523817466cbSJens Wiklander 52432b31808SJens Wiklander for (i = 0; i < 16; i += 8) { 5257901324dSJerome Forissier P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], 5267901324dSJerome Forissier local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0]); 5277901324dSJerome Forissier P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], 5287901324dSJerome Forissier local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1]); 5297901324dSJerome Forissier P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], 5307901324dSJerome Forissier local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2]); 5317901324dSJerome Forissier P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], 5327901324dSJerome Forissier local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3]); 5337901324dSJerome Forissier P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], 5347901324dSJerome Forissier local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4]); 5357901324dSJerome Forissier P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], 5367901324dSJerome Forissier local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5]); 5377901324dSJerome Forissier P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], 5387901324dSJerome Forissier local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6]); 5397901324dSJerome Forissier P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], 5407901324dSJerome Forissier local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7]); 541817466cbSJens Wiklander } 542817466cbSJens Wiklander 54332b31808SJens Wiklander for (i = 16; i < 64; i += 8) { 5447901324dSJerome Forissier P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], 5457901324dSJerome Forissier local.A[5], local.A[6], local.A[7], R(i+0), K[i+0]); 5467901324dSJerome Forissier P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], 5477901324dSJerome Forissier local.A[4], local.A[5], local.A[6], R(i+1), K[i+1]); 5487901324dSJerome Forissier P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], 5497901324dSJerome Forissier local.A[3], local.A[4], local.A[5], R(i+2), K[i+2]); 5507901324dSJerome Forissier P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], 5517901324dSJerome Forissier local.A[2], local.A[3], local.A[4], R(i+3), K[i+3]); 5527901324dSJerome Forissier P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], 5537901324dSJerome Forissier local.A[1], local.A[2], local.A[3], R(i+4), K[i+4]); 5547901324dSJerome Forissier P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], 5557901324dSJerome Forissier local.A[0], local.A[1], local.A[2], R(i+5), K[i+5]); 5567901324dSJerome Forissier P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], 5577901324dSJerome Forissier local.A[7], local.A[0], local.A[1], R(i+6), K[i+6]); 5587901324dSJerome Forissier P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], 5597901324dSJerome Forissier local.A[6], local.A[7], local.A[0], R(i+7), K[i+7]); 560817466cbSJens Wiklander } 561817466cbSJens Wiklander #endif /* MBEDTLS_SHA256_SMALLER */ 562817466cbSJens Wiklander 56332b31808SJens Wiklander for (i = 0; i < 8; i++) { 5647901324dSJerome Forissier ctx->state[i] += local.A[i]; 56532b31808SJens Wiklander } 5667901324dSJerome Forissier 5677901324dSJerome Forissier /* Zeroise buffers and variables to clear sensitive data from memory. */ 5687901324dSJerome Forissier mbedtls_platform_zeroize(&local, sizeof(local)); 5693d3b0591SJens Wiklander 57032b31808SJens Wiklander return 0; 571817466cbSJens Wiklander } 5723d3b0591SJens Wiklander 573*b0563631STom Van Eyck #endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ 57432b31808SJens Wiklander 57532b31808SJens Wiklander 576*b0563631STom Van Eyck #if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) 57732b31808SJens Wiklander 57832b31808SJens Wiklander static size_t mbedtls_internal_sha256_process_many_c( 57932b31808SJens Wiklander mbedtls_sha256_context *ctx, const uint8_t *data, size_t len) 5803d3b0591SJens Wiklander { 58132b31808SJens Wiklander size_t processed = 0; 58232b31808SJens Wiklander 58332b31808SJens Wiklander while (len >= SHA256_BLOCK_SIZE) { 58432b31808SJens Wiklander if (mbedtls_internal_sha256_process_c(ctx, data) != 0) { 58532b31808SJens Wiklander return 0; 5863d3b0591SJens Wiklander } 58732b31808SJens Wiklander 58832b31808SJens Wiklander data += SHA256_BLOCK_SIZE; 58932b31808SJens Wiklander len -= SHA256_BLOCK_SIZE; 59032b31808SJens Wiklander 59132b31808SJens Wiklander processed += SHA256_BLOCK_SIZE; 59232b31808SJens Wiklander } 59332b31808SJens Wiklander 59432b31808SJens Wiklander return processed; 59532b31808SJens Wiklander } 59632b31808SJens Wiklander 597*b0563631STom Van Eyck #endif /* !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ 59832b31808SJens Wiklander 59932b31808SJens Wiklander 600*b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) 60132b31808SJens Wiklander 60232b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_has_support(void) 60332b31808SJens Wiklander { 60432b31808SJens Wiklander static int done = 0; 60532b31808SJens Wiklander static int supported = 0; 60632b31808SJens Wiklander 60732b31808SJens Wiklander if (!done) { 60832b31808SJens Wiklander supported = mbedtls_a64_crypto_sha256_determine_support(); 60932b31808SJens Wiklander done = 1; 61032b31808SJens Wiklander } 61132b31808SJens Wiklander 61232b31808SJens Wiklander return supported; 61332b31808SJens Wiklander } 61432b31808SJens Wiklander 61532b31808SJens Wiklander static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx, 61632b31808SJens Wiklander const uint8_t *msg, size_t len) 61732b31808SJens Wiklander { 61832b31808SJens Wiklander if (mbedtls_a64_crypto_sha256_has_support()) { 61932b31808SJens Wiklander return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len); 62032b31808SJens Wiklander } else { 62132b31808SJens Wiklander return mbedtls_internal_sha256_process_many_c(ctx, msg, len); 62232b31808SJens Wiklander } 62332b31808SJens Wiklander } 62432b31808SJens Wiklander 62532b31808SJens Wiklander int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, 62632b31808SJens Wiklander const unsigned char data[SHA256_BLOCK_SIZE]) 62732b31808SJens Wiklander { 62832b31808SJens Wiklander if (mbedtls_a64_crypto_sha256_has_support()) { 62932b31808SJens Wiklander return mbedtls_internal_sha256_process_a64_crypto(ctx, data); 63032b31808SJens Wiklander } else { 63132b31808SJens Wiklander return mbedtls_internal_sha256_process_c(ctx, data); 63232b31808SJens Wiklander } 63332b31808SJens Wiklander } 63432b31808SJens Wiklander 635*b0563631STom Van Eyck #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ 63632b31808SJens Wiklander 637817466cbSJens Wiklander 638817466cbSJens Wiklander /* 639817466cbSJens Wiklander * SHA-256 process buffer 640817466cbSJens Wiklander */ 64132b31808SJens Wiklander int mbedtls_sha256_update(mbedtls_sha256_context *ctx, 6423d3b0591SJens Wiklander const unsigned char *input, 643817466cbSJens Wiklander size_t ilen) 644817466cbSJens Wiklander { 64511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 646817466cbSJens Wiklander size_t fill; 647817466cbSJens Wiklander uint32_t left; 648817466cbSJens Wiklander 64932b31808SJens Wiklander if (ilen == 0) { 65032b31808SJens Wiklander return 0; 65132b31808SJens Wiklander } 652817466cbSJens Wiklander 653817466cbSJens Wiklander left = ctx->total[0] & 0x3F; 65432b31808SJens Wiklander fill = SHA256_BLOCK_SIZE - left; 655817466cbSJens Wiklander 656817466cbSJens Wiklander ctx->total[0] += (uint32_t) ilen; 657817466cbSJens Wiklander ctx->total[0] &= 0xFFFFFFFF; 658817466cbSJens Wiklander 65932b31808SJens Wiklander if (ctx->total[0] < (uint32_t) ilen) { 660817466cbSJens Wiklander ctx->total[1]++; 66132b31808SJens Wiklander } 662817466cbSJens Wiklander 66332b31808SJens Wiklander if (left && ilen >= fill) { 664817466cbSJens Wiklander memcpy((void *) (ctx->buffer + left), input, fill); 6653d3b0591SJens Wiklander 66632b31808SJens Wiklander if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { 66732b31808SJens Wiklander return ret; 66832b31808SJens Wiklander } 6693d3b0591SJens Wiklander 670817466cbSJens Wiklander input += fill; 671817466cbSJens Wiklander ilen -= fill; 672817466cbSJens Wiklander left = 0; 673817466cbSJens Wiklander } 674817466cbSJens Wiklander 67532b31808SJens Wiklander while (ilen >= SHA256_BLOCK_SIZE) { 67632b31808SJens Wiklander size_t processed = 67732b31808SJens Wiklander mbedtls_internal_sha256_process_many(ctx, input, ilen); 67832b31808SJens Wiklander if (processed < SHA256_BLOCK_SIZE) { 67932b31808SJens Wiklander return MBEDTLS_ERR_ERROR_GENERIC_ERROR; 680817466cbSJens Wiklander } 681817466cbSJens Wiklander 68232b31808SJens Wiklander input += processed; 68332b31808SJens Wiklander ilen -= processed; 68432b31808SJens Wiklander } 68532b31808SJens Wiklander 68632b31808SJens Wiklander if (ilen > 0) { 687817466cbSJens Wiklander memcpy((void *) (ctx->buffer + left), input, ilen); 688817466cbSJens Wiklander } 689817466cbSJens Wiklander 69032b31808SJens Wiklander return 0; 6913d3b0591SJens Wiklander } 692817466cbSJens Wiklander 693817466cbSJens Wiklander /* 694817466cbSJens Wiklander * SHA-256 final digest 695817466cbSJens Wiklander */ 69632b31808SJens Wiklander int mbedtls_sha256_finish(mbedtls_sha256_context *ctx, 69732b31808SJens Wiklander unsigned char *output) 698817466cbSJens Wiklander { 69911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 7003d3b0591SJens Wiklander uint32_t used; 701817466cbSJens Wiklander uint32_t high, low; 702*b0563631STom Van Eyck int truncated = 0; 703817466cbSJens Wiklander 7043d3b0591SJens Wiklander /* 7053d3b0591SJens Wiklander * Add padding: 0x80 then 0x00 until 8 bytes remain for the length 7063d3b0591SJens Wiklander */ 7073d3b0591SJens Wiklander used = ctx->total[0] & 0x3F; 7083d3b0591SJens Wiklander 7093d3b0591SJens Wiklander ctx->buffer[used++] = 0x80; 7103d3b0591SJens Wiklander 71132b31808SJens Wiklander if (used <= 56) { 7123d3b0591SJens Wiklander /* Enough room for padding + length in current block */ 7133d3b0591SJens Wiklander memset(ctx->buffer + used, 0, 56 - used); 71432b31808SJens Wiklander } else { 7153d3b0591SJens Wiklander /* We'll need an extra block */ 71632b31808SJens Wiklander memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used); 7173d3b0591SJens Wiklander 71832b31808SJens Wiklander if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { 719*b0563631STom Van Eyck goto exit; 72032b31808SJens Wiklander } 7213d3b0591SJens Wiklander 7223d3b0591SJens Wiklander memset(ctx->buffer, 0, 56); 7233d3b0591SJens Wiklander } 7243d3b0591SJens Wiklander 7253d3b0591SJens Wiklander /* 7263d3b0591SJens Wiklander * Add message length 7273d3b0591SJens Wiklander */ 728817466cbSJens Wiklander high = (ctx->total[0] >> 29) 729817466cbSJens Wiklander | (ctx->total[1] << 3); 730817466cbSJens Wiklander low = (ctx->total[0] << 3); 731817466cbSJens Wiklander 732039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56); 733039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(low, ctx->buffer, 60); 734817466cbSJens Wiklander 73532b31808SJens Wiklander if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { 736*b0563631STom Van Eyck goto exit; 73732b31808SJens Wiklander } 738817466cbSJens Wiklander 7393d3b0591SJens Wiklander /* 7403d3b0591SJens Wiklander * Output final state 7413d3b0591SJens Wiklander */ 742039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->state[0], output, 0); 743039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->state[1], output, 4); 744039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->state[2], output, 8); 745039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12); 746039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16); 747039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20); 748039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24); 749817466cbSJens Wiklander 75032b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) 75132b31808SJens Wiklander truncated = ctx->is224; 7523d3b0591SJens Wiklander #endif 75332b31808SJens Wiklander if (!truncated) { 75432b31808SJens Wiklander MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28); 75532b31808SJens Wiklander } 75632b31808SJens Wiklander 757*b0563631STom Van Eyck ret = 0; 758*b0563631STom Van Eyck 759*b0563631STom Van Eyck exit: 760*b0563631STom Van Eyck mbedtls_sha256_free(ctx); 761*b0563631STom Van Eyck return ret; 76232b31808SJens Wiklander } 7633d3b0591SJens Wiklander 764817466cbSJens Wiklander #endif /* !MBEDTLS_SHA256_ALT */ 765817466cbSJens Wiklander 766817466cbSJens Wiklander /* 767817466cbSJens Wiklander * output = SHA-256( input buffer ) 768817466cbSJens Wiklander */ 76932b31808SJens Wiklander int mbedtls_sha256(const unsigned char *input, 7703d3b0591SJens Wiklander size_t ilen, 77132b31808SJens Wiklander unsigned char *output, 7723d3b0591SJens Wiklander int is224) 773817466cbSJens Wiklander { 77411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 775817466cbSJens Wiklander mbedtls_sha256_context ctx; 776817466cbSJens Wiklander 77732b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) 77832b31808SJens Wiklander if (is224 != 0 && is224 != 1) { 77932b31808SJens Wiklander return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; 78032b31808SJens Wiklander } 78132b31808SJens Wiklander #elif defined(MBEDTLS_SHA256_C) 78232b31808SJens Wiklander if (is224 != 0) { 78332b31808SJens Wiklander return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; 78432b31808SJens Wiklander } 78532b31808SJens Wiklander #else /* defined MBEDTLS_SHA224_C only */ 78632b31808SJens Wiklander if (is224 == 0) { 78732b31808SJens Wiklander return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; 78832b31808SJens Wiklander } 78932b31808SJens Wiklander #endif 7903d3b0591SJens Wiklander 791817466cbSJens Wiklander mbedtls_sha256_init(&ctx); 7923d3b0591SJens Wiklander 79332b31808SJens Wiklander if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { 7943d3b0591SJens Wiklander goto exit; 79532b31808SJens Wiklander } 7963d3b0591SJens Wiklander 79732b31808SJens Wiklander if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) { 7983d3b0591SJens Wiklander goto exit; 79932b31808SJens Wiklander } 8003d3b0591SJens Wiklander 80132b31808SJens Wiklander if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) { 8023d3b0591SJens Wiklander goto exit; 80332b31808SJens Wiklander } 8043d3b0591SJens Wiklander 8053d3b0591SJens Wiklander exit: 806817466cbSJens Wiklander mbedtls_sha256_free(&ctx); 8073d3b0591SJens Wiklander 80832b31808SJens Wiklander return ret; 809817466cbSJens Wiklander } 810817466cbSJens Wiklander 811817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 812817466cbSJens Wiklander /* 813817466cbSJens Wiklander * FIPS-180-2 test vectors 814817466cbSJens Wiklander */ 81532b31808SJens Wiklander static const unsigned char sha_test_buf[3][57] = 816817466cbSJens Wiklander { 817817466cbSJens Wiklander { "abc" }, 818817466cbSJens Wiklander { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, 819817466cbSJens Wiklander { "" } 820817466cbSJens Wiklander }; 821817466cbSJens Wiklander 82232b31808SJens Wiklander static const size_t sha_test_buflen[3] = 823817466cbSJens Wiklander { 824817466cbSJens Wiklander 3, 56, 1000 825817466cbSJens Wiklander }; 826817466cbSJens Wiklander 82732b31808SJens Wiklander typedef const unsigned char (sha_test_sum_t)[32]; 82832b31808SJens Wiklander 829817466cbSJens Wiklander /* 830817466cbSJens Wiklander * SHA-224 test vectors 831817466cbSJens Wiklander */ 83232b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) 83332b31808SJens Wiklander static sha_test_sum_t sha224_test_sum[] = 83432b31808SJens Wiklander { 835817466cbSJens Wiklander { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, 836817466cbSJens Wiklander 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, 837817466cbSJens Wiklander 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, 838817466cbSJens Wiklander 0xE3, 0x6C, 0x9D, 0xA7 }, 839817466cbSJens Wiklander { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, 840817466cbSJens Wiklander 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, 841817466cbSJens Wiklander 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, 842817466cbSJens Wiklander 0x52, 0x52, 0x25, 0x25 }, 843817466cbSJens Wiklander { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, 844817466cbSJens Wiklander 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, 845817466cbSJens Wiklander 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, 84632b31808SJens Wiklander 0x4E, 0xE7, 0xAD, 0x67 } 84732b31808SJens Wiklander }; 84832b31808SJens Wiklander #endif 849817466cbSJens Wiklander 850817466cbSJens Wiklander /* 851817466cbSJens Wiklander * SHA-256 test vectors 852817466cbSJens Wiklander */ 85332b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C) 85432b31808SJens Wiklander static sha_test_sum_t sha256_test_sum[] = 85532b31808SJens Wiklander { 856817466cbSJens Wiklander { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 857817466cbSJens Wiklander 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, 858817466cbSJens Wiklander 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, 859817466cbSJens Wiklander 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, 860817466cbSJens Wiklander { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 861817466cbSJens Wiklander 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, 862817466cbSJens Wiklander 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 863817466cbSJens Wiklander 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, 864817466cbSJens Wiklander { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, 865817466cbSJens Wiklander 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, 866817466cbSJens Wiklander 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, 867817466cbSJens Wiklander 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } 868817466cbSJens Wiklander }; 86932b31808SJens Wiklander #endif 870817466cbSJens Wiklander 871817466cbSJens Wiklander /* 872817466cbSJens Wiklander * Checkup routine 873817466cbSJens Wiklander */ 87432b31808SJens Wiklander static int mbedtls_sha256_common_self_test(int verbose, int is224) 875817466cbSJens Wiklander { 87632b31808SJens Wiklander int i, buflen, ret = 0; 877817466cbSJens Wiklander unsigned char *buf; 878817466cbSJens Wiklander unsigned char sha256sum[32]; 879817466cbSJens Wiklander mbedtls_sha256_context ctx; 880817466cbSJens Wiklander 88132b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) 88232b31808SJens Wiklander sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum; 88332b31808SJens Wiklander #elif defined(MBEDTLS_SHA256_C) 88432b31808SJens Wiklander sha_test_sum_t *sha_test_sum = sha256_test_sum; 88532b31808SJens Wiklander #else 88632b31808SJens Wiklander sha_test_sum_t *sha_test_sum = sha224_test_sum; 88732b31808SJens Wiklander #endif 888817466cbSJens Wiklander 88932b31808SJens Wiklander buf = mbedtls_calloc(1024, sizeof(unsigned char)); 89032b31808SJens Wiklander if (NULL == buf) { 89132b31808SJens Wiklander if (verbose != 0) { 89232b31808SJens Wiklander mbedtls_printf("Buffer allocation failed\n"); 89332b31808SJens Wiklander } 89432b31808SJens Wiklander 89532b31808SJens Wiklander return 1; 896817466cbSJens Wiklander } 897817466cbSJens Wiklander 898817466cbSJens Wiklander mbedtls_sha256_init(&ctx); 899817466cbSJens Wiklander 90032b31808SJens Wiklander for (i = 0; i < 3; i++) { 90132b31808SJens Wiklander if (verbose != 0) { 90232b31808SJens Wiklander mbedtls_printf(" SHA-%d test #%d: ", 256 - is224 * 32, i + 1); 90332b31808SJens Wiklander } 904817466cbSJens Wiklander 90532b31808SJens Wiklander if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { 9063d3b0591SJens Wiklander goto fail; 90732b31808SJens Wiklander } 908817466cbSJens Wiklander 90932b31808SJens Wiklander if (i == 2) { 910817466cbSJens Wiklander memset(buf, 'a', buflen = 1000); 911817466cbSJens Wiklander 91232b31808SJens Wiklander for (int j = 0; j < 1000; j++) { 91332b31808SJens Wiklander ret = mbedtls_sha256_update(&ctx, buf, buflen); 91432b31808SJens Wiklander if (ret != 0) { 91532b31808SJens Wiklander goto fail; 91632b31808SJens Wiklander } 91732b31808SJens Wiklander } 91832b31808SJens Wiklander 91932b31808SJens Wiklander } else { 92032b31808SJens Wiklander ret = mbedtls_sha256_update(&ctx, sha_test_buf[i], 92132b31808SJens Wiklander sha_test_buflen[i]); 92232b31808SJens Wiklander if (ret != 0) { 92332b31808SJens Wiklander goto fail; 92432b31808SJens Wiklander } 92532b31808SJens Wiklander } 92632b31808SJens Wiklander 92732b31808SJens Wiklander if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) { 9283d3b0591SJens Wiklander goto fail; 9293d3b0591SJens Wiklander } 9303d3b0591SJens Wiklander 931817466cbSJens Wiklander 93232b31808SJens Wiklander if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 4) != 0) { 933817466cbSJens Wiklander ret = 1; 9343d3b0591SJens Wiklander goto fail; 935817466cbSJens Wiklander } 936817466cbSJens Wiklander 93732b31808SJens Wiklander if (verbose != 0) { 938817466cbSJens Wiklander mbedtls_printf("passed\n"); 939817466cbSJens Wiklander } 94032b31808SJens Wiklander } 941817466cbSJens Wiklander 94232b31808SJens Wiklander if (verbose != 0) { 943817466cbSJens Wiklander mbedtls_printf("\n"); 94432b31808SJens Wiklander } 945817466cbSJens Wiklander 9463d3b0591SJens Wiklander goto exit; 9473d3b0591SJens Wiklander 9483d3b0591SJens Wiklander fail: 94932b31808SJens Wiklander if (verbose != 0) { 9503d3b0591SJens Wiklander mbedtls_printf("failed\n"); 95132b31808SJens Wiklander } 9523d3b0591SJens Wiklander 953817466cbSJens Wiklander exit: 954817466cbSJens Wiklander mbedtls_sha256_free(&ctx); 955817466cbSJens Wiklander mbedtls_free(buf); 956817466cbSJens Wiklander 95732b31808SJens Wiklander return ret; 958817466cbSJens Wiklander } 959817466cbSJens Wiklander 96032b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C) 96132b31808SJens Wiklander int mbedtls_sha256_self_test(int verbose) 96232b31808SJens Wiklander { 96332b31808SJens Wiklander return mbedtls_sha256_common_self_test(verbose, 0); 96432b31808SJens Wiklander } 96532b31808SJens Wiklander #endif /* MBEDTLS_SHA256_C */ 96632b31808SJens Wiklander 96732b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) 96832b31808SJens Wiklander int mbedtls_sha224_self_test(int verbose) 96932b31808SJens Wiklander { 97032b31808SJens Wiklander return mbedtls_sha256_common_self_test(verbose, 1); 97132b31808SJens Wiklander } 97232b31808SJens Wiklander #endif /* MBEDTLS_SHA224_C */ 97332b31808SJens Wiklander 974817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 975817466cbSJens Wiklander 97632b31808SJens Wiklander #endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */ 977