xref: /optee_os/lib/libmbedtls/mbedtls/library/sha256.c (revision cb03400251f98aed22a2664509e3ed9e183800b0)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  FIPS-180-2 compliant SHA-256 implementation
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
5b0563631STom 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 
13b0563631STom Van Eyck #if defined(__clang__) &&  (__clang_major__ >= 4)
14b0563631STom Van Eyck 
15b0563631STom Van Eyck /* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if,
16b0563631STom Van Eyck  * but that is defined by build_info.h, and we need this block to happen first. */
17b0563631STom Van Eyck #if defined(__ARM_ARCH) && (__ARM_ARCH_PROFILE == 'A')
18b0563631STom Van Eyck #if __ARM_ARCH >= 8
19b0563631STom Van Eyck #define MBEDTLS_SHA256_ARCH_IS_ARMV8_A
20b0563631STom Van Eyck #endif
21b0563631STom Van Eyck #endif
22b0563631STom Van Eyck 
23b0563631STom 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  *
31b0563631STom 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 
44b0563631STom Van Eyck #endif /* defined(__clang__) &&  (__clang_major__ >= 4) */
45b0563631STom Van Eyck 
46b0563631STom Van Eyck /* Ensure that SIG_SETMASK is defined when -std=c99 is used. */
47*cb034002SJerome Forissier #if !defined(_GNU_SOURCE)
48b0563631STom Van Eyck #define _GNU_SOURCE
49*cb034002SJerome Forissier #endif
50b0563631STom Van Eyck 
517901324dSJerome Forissier #include "common.h"
52817466cbSJens Wiklander 
5332b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)
54817466cbSJens Wiklander 
55817466cbSJens Wiklander #include "mbedtls/sha256.h"
563d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
5711fa71b9SJerome Forissier #include "mbedtls/error.h"
58817466cbSJens Wiklander 
59817466cbSJens Wiklander #include <string.h>
60817466cbSJens Wiklander 
61817466cbSJens Wiklander #include "mbedtls/platform.h"
62817466cbSJens Wiklander 
63b0563631STom Van Eyck #if defined(MBEDTLS_ARCH_IS_ARMV8_A)
64b0563631STom Van Eyck 
65b0563631STom Van Eyck #  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
66b0563631STom Van Eyck     defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
67b0563631STom Van Eyck #       if !defined(MBEDTLS_HAVE_NEON_INTRINSICS)
68b0563631STom Van Eyck #           if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
69b0563631STom Van Eyck #               warning "Target does not support NEON instructions"
70b0563631STom Van Eyck #               undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
71b0563631STom Van Eyck #           else
72b0563631STom Van Eyck #               error "Target does not support NEON instructions"
73b0563631STom Van Eyck #           endif
74b0563631STom Van Eyck #       endif
75b0563631STom Van Eyck #   endif
76b0563631STom Van Eyck 
77b0563631STom Van Eyck #  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
78b0563631STom Van Eyck     defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
7932b31808SJens Wiklander /* *INDENT-OFF* */
80b0563631STom Van Eyck 
8132b31808SJens Wiklander #   if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
82b0563631STom Van Eyck #      if defined(__ARMCOMPILER_VERSION)
83b0563631STom Van Eyck #        if __ARMCOMPILER_VERSION <= 6090000
84b0563631STom Van Eyck #          error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
85b0563631STom Van Eyck #        endif
86b0563631STom Van Eyck #          pragma clang attribute push (__attribute__((target("sha2"))), apply_to=function)
87b0563631STom Van Eyck #          define MBEDTLS_POP_TARGET_PRAGMA
88b0563631STom Van Eyck #      elif defined(__clang__)
8932b31808SJens Wiklander #        if __clang_major__ < 4
90b0563631STom Van Eyck #          error "A more recent Clang is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
9132b31808SJens Wiklander #        endif
9232b31808SJens Wiklander #        pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
9332b31808SJens Wiklander #        define MBEDTLS_POP_TARGET_PRAGMA
9432b31808SJens Wiklander #      elif defined(__GNUC__)
9532b31808SJens Wiklander          /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some
9632b31808SJens Wiklander           *        intrinsics are missing. Missing intrinsics could be worked around.
9732b31808SJens Wiklander           */
9832b31808SJens Wiklander #        if __GNUC__ < 6
99b0563631STom Van Eyck #          error "A more recent GCC is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
10032b31808SJens Wiklander #        else
10132b31808SJens Wiklander #          pragma GCC push_options
10232b31808SJens Wiklander #          pragma GCC target ("arch=armv8-a+crypto")
10332b31808SJens Wiklander #          define MBEDTLS_POP_TARGET_PRAGMA
10432b31808SJens Wiklander #        endif
10532b31808SJens Wiklander #      else
106b0563631STom Van Eyck #        error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
10732b31808SJens Wiklander #      endif
10832b31808SJens Wiklander #    endif
10932b31808SJens Wiklander /* *INDENT-ON* */
110b0563631STom Van Eyck 
11132b31808SJens Wiklander #  endif
112b0563631STom Van Eyck #  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
11332b31808SJens Wiklander #    if defined(__unix__)
11432b31808SJens Wiklander #      if defined(__linux__)
11532b31808SJens Wiklander /* Our preferred method of detection is getauxval() */
11632b31808SJens Wiklander #        include <sys/auxv.h>
117b0563631STom Van Eyck /* These are not always defined via sys/auxv.h */
118b0563631STom Van Eyck #        if !defined(HWCAP_SHA2)
119b0563631STom Van Eyck #          define HWCAP_SHA2  (1 << 6)
120b0563631STom Van Eyck #        endif
121b0563631STom Van Eyck #        if !defined(HWCAP2_SHA2)
122b0563631STom Van Eyck #          define HWCAP2_SHA2 (1 << 3)
123b0563631STom Van Eyck #        endif
12432b31808SJens Wiklander #      endif
12532b31808SJens Wiklander /* Use SIGILL on Unix, and fall back to it on Linux */
12632b31808SJens Wiklander #      include <signal.h>
12732b31808SJens Wiklander #    endif
12832b31808SJens Wiklander #  endif
129b0563631STom Van Eyck #elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
130b0563631STom Van Eyck #  undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY
131b0563631STom Van Eyck #  undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
13232b31808SJens Wiklander #endif
13332b31808SJens Wiklander 
134b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
13532b31808SJens Wiklander /*
13632b31808SJens Wiklander  * Capability detection code comes early, so we can disable
137b0563631STom Van Eyck  * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT if no detection mechanism found
13832b31808SJens Wiklander  */
139b0563631STom Van Eyck #if defined(MBEDTLS_ARCH_IS_ARM64) && defined(HWCAP_SHA2)
mbedtls_a64_crypto_sha256_determine_support(void)14032b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void)
14132b31808SJens Wiklander {
14232b31808SJens Wiklander     return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0;
14332b31808SJens Wiklander }
144b0563631STom Van Eyck #elif defined(MBEDTLS_ARCH_IS_ARM32) && defined(HWCAP2_SHA2)
mbedtls_a64_crypto_sha256_determine_support(void)145b0563631STom Van Eyck static int mbedtls_a64_crypto_sha256_determine_support(void)
146b0563631STom Van Eyck {
147b0563631STom Van Eyck     return (getauxval(AT_HWCAP2) & HWCAP2_SHA2) ? 1 : 0;
148b0563631STom Van Eyck }
14932b31808SJens Wiklander #elif defined(__APPLE__)
mbedtls_a64_crypto_sha256_determine_support(void)15032b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void)
15132b31808SJens Wiklander {
15232b31808SJens Wiklander     return 1;
15332b31808SJens Wiklander }
154b0563631STom Van Eyck #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
155*cb034002SJerome Forissier #ifndef WIN32_LEAN_AND_MEAN
15632b31808SJens Wiklander #define WIN32_LEAN_AND_MEAN
157*cb034002SJerome Forissier #endif
15832b31808SJens Wiklander #include <Windows.h>
15932b31808SJens Wiklander #include <processthreadsapi.h>
16032b31808SJens Wiklander 
mbedtls_a64_crypto_sha256_determine_support(void)16132b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void)
16232b31808SJens Wiklander {
16332b31808SJens Wiklander     return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ?
16432b31808SJens Wiklander            1 : 0;
16532b31808SJens Wiklander }
16632b31808SJens Wiklander #elif defined(__unix__) && defined(SIG_SETMASK)
16732b31808SJens Wiklander /* Detection with SIGILL, setjmp() and longjmp() */
16832b31808SJens Wiklander #include <signal.h>
16932b31808SJens Wiklander #include <setjmp.h>
17032b31808SJens Wiklander 
17132b31808SJens Wiklander static jmp_buf return_from_sigill;
17232b31808SJens Wiklander 
17332b31808SJens Wiklander /*
174b0563631STom Van Eyck  * Armv8-A SHA256 support detection via SIGILL
17532b31808SJens Wiklander  */
sigill_handler(int signal)17632b31808SJens Wiklander static void sigill_handler(int signal)
17732b31808SJens Wiklander {
17832b31808SJens Wiklander     (void) signal;
17932b31808SJens Wiklander     longjmp(return_from_sigill, 1);
18032b31808SJens Wiklander }
18132b31808SJens Wiklander 
mbedtls_a64_crypto_sha256_determine_support(void)18232b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void)
18332b31808SJens Wiklander {
18432b31808SJens Wiklander     struct sigaction old_action, new_action;
18532b31808SJens Wiklander 
18632b31808SJens Wiklander     sigset_t old_mask;
18732b31808SJens Wiklander     if (sigprocmask(0, NULL, &old_mask)) {
18832b31808SJens Wiklander         return 0;
18932b31808SJens Wiklander     }
19032b31808SJens Wiklander 
19132b31808SJens Wiklander     sigemptyset(&new_action.sa_mask);
19232b31808SJens Wiklander     new_action.sa_flags = 0;
19332b31808SJens Wiklander     new_action.sa_handler = sigill_handler;
19432b31808SJens Wiklander 
19532b31808SJens Wiklander     sigaction(SIGILL, &new_action, &old_action);
19632b31808SJens Wiklander 
19732b31808SJens Wiklander     static int ret = 0;
19832b31808SJens Wiklander 
19932b31808SJens Wiklander     if (setjmp(return_from_sigill) == 0) {         /* First return only */
20032b31808SJens Wiklander         /* If this traps, we will return a second time from setjmp() with 1 */
201b0563631STom Van Eyck #if defined(MBEDTLS_ARCH_IS_ARM64)
202b0563631STom Van Eyck         asm volatile ("sha256h q0, q0, v0.4s" : : : "v0");
203b0563631STom Van Eyck #else
204b0563631STom Van Eyck         asm volatile ("sha256h.32 q0, q0, q0" : : : "q0");
205b0563631STom Van Eyck #endif
20632b31808SJens Wiklander         ret = 1;
20732b31808SJens Wiklander     }
20832b31808SJens Wiklander 
20932b31808SJens Wiklander     sigaction(SIGILL, &old_action, NULL);
21032b31808SJens Wiklander     sigprocmask(SIG_SETMASK, &old_mask, NULL);
21132b31808SJens Wiklander 
21232b31808SJens Wiklander     return ret;
21332b31808SJens Wiklander }
21432b31808SJens Wiklander #else
215b0563631STom Van Eyck #warning "No mechanism to detect ARMV8_CRYPTO found, using C code only"
216b0563631STom Van Eyck #undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
21732b31808SJens Wiklander #endif  /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */
21832b31808SJens Wiklander 
219b0563631STom Van Eyck #endif  /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */
220817466cbSJens Wiklander 
2213d3b0591SJens Wiklander #if !defined(MBEDTLS_SHA256_ALT)
222817466cbSJens Wiklander 
22332b31808SJens Wiklander #define SHA256_BLOCK_SIZE 64
22432b31808SJens Wiklander 
mbedtls_sha256_init(mbedtls_sha256_context * ctx)225817466cbSJens Wiklander void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
226817466cbSJens Wiklander {
227817466cbSJens Wiklander     memset(ctx, 0, sizeof(mbedtls_sha256_context));
228817466cbSJens Wiklander }
229817466cbSJens Wiklander 
mbedtls_sha256_free(mbedtls_sha256_context * ctx)230817466cbSJens Wiklander void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
231817466cbSJens Wiklander {
23232b31808SJens Wiklander     if (ctx == NULL) {
233817466cbSJens Wiklander         return;
23432b31808SJens Wiklander     }
235817466cbSJens Wiklander 
2363d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha256_context));
237817466cbSJens Wiklander }
238817466cbSJens Wiklander 
mbedtls_sha256_clone(mbedtls_sha256_context * dst,const mbedtls_sha256_context * src)239817466cbSJens Wiklander void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
240817466cbSJens Wiklander                           const mbedtls_sha256_context *src)
241817466cbSJens Wiklander {
242817466cbSJens Wiklander     *dst = *src;
243817466cbSJens Wiklander }
244817466cbSJens Wiklander 
245817466cbSJens Wiklander /*
246817466cbSJens Wiklander  * SHA-256 context setup
247817466cbSJens Wiklander  */
mbedtls_sha256_starts(mbedtls_sha256_context * ctx,int is224)24832b31808SJens Wiklander int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
249817466cbSJens Wiklander {
25032b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
25132b31808SJens Wiklander     if (is224 != 0 && is224 != 1) {
25232b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
25332b31808SJens Wiklander     }
25432b31808SJens Wiklander #elif defined(MBEDTLS_SHA256_C)
25532b31808SJens Wiklander     if (is224 != 0) {
25632b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
25732b31808SJens Wiklander     }
25832b31808SJens Wiklander #else /* defined MBEDTLS_SHA224_C only */
25932b31808SJens Wiklander     if (is224 == 0) {
26032b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
26132b31808SJens Wiklander     }
26232b31808SJens Wiklander #endif
2633d3b0591SJens Wiklander 
264817466cbSJens Wiklander     ctx->total[0] = 0;
265817466cbSJens Wiklander     ctx->total[1] = 0;
266817466cbSJens Wiklander 
26732b31808SJens Wiklander     if (is224 == 0) {
26832b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C)
269817466cbSJens Wiklander         ctx->state[0] = 0x6A09E667;
270817466cbSJens Wiklander         ctx->state[1] = 0xBB67AE85;
271817466cbSJens Wiklander         ctx->state[2] = 0x3C6EF372;
272817466cbSJens Wiklander         ctx->state[3] = 0xA54FF53A;
273817466cbSJens Wiklander         ctx->state[4] = 0x510E527F;
274817466cbSJens Wiklander         ctx->state[5] = 0x9B05688C;
275817466cbSJens Wiklander         ctx->state[6] = 0x1F83D9AB;
276817466cbSJens Wiklander         ctx->state[7] = 0x5BE0CD19;
27732b31808SJens Wiklander #endif
27832b31808SJens Wiklander     } else {
27932b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
280817466cbSJens Wiklander         ctx->state[0] = 0xC1059ED8;
281817466cbSJens Wiklander         ctx->state[1] = 0x367CD507;
282817466cbSJens Wiklander         ctx->state[2] = 0x3070DD17;
283817466cbSJens Wiklander         ctx->state[3] = 0xF70E5939;
284817466cbSJens Wiklander         ctx->state[4] = 0xFFC00B31;
285817466cbSJens Wiklander         ctx->state[5] = 0x68581511;
286817466cbSJens Wiklander         ctx->state[6] = 0x64F98FA7;
287817466cbSJens Wiklander         ctx->state[7] = 0xBEFA4FA4;
2883d3b0591SJens Wiklander #endif
28932b31808SJens Wiklander     }
29032b31808SJens Wiklander 
29132b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
29232b31808SJens Wiklander     ctx->is224 = is224;
29332b31808SJens Wiklander #endif
29432b31808SJens Wiklander 
29532b31808SJens Wiklander     return 0;
29632b31808SJens Wiklander }
2973d3b0591SJens Wiklander 
298817466cbSJens Wiklander #if !defined(MBEDTLS_SHA256_PROCESS_ALT)
299817466cbSJens Wiklander static const uint32_t K[] =
300817466cbSJens Wiklander {
301817466cbSJens Wiklander     0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
302817466cbSJens Wiklander     0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
303817466cbSJens Wiklander     0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
304817466cbSJens Wiklander     0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
305817466cbSJens Wiklander     0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
306817466cbSJens Wiklander     0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
307817466cbSJens Wiklander     0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
308817466cbSJens Wiklander     0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
309817466cbSJens Wiklander     0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
310817466cbSJens Wiklander     0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
311817466cbSJens Wiklander     0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
312817466cbSJens Wiklander     0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
313817466cbSJens Wiklander     0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
314817466cbSJens Wiklander     0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
315817466cbSJens Wiklander     0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
316817466cbSJens Wiklander     0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
317817466cbSJens Wiklander };
318817466cbSJens Wiklander 
31932b31808SJens Wiklander #endif
32032b31808SJens Wiklander 
321b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
322b0563631STom Van Eyck     defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
32332b31808SJens Wiklander 
324b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
32532b31808SJens Wiklander #  define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many
32632b31808SJens Wiklander #  define mbedtls_internal_sha256_process_a64_crypto      mbedtls_internal_sha256_process
32732b31808SJens Wiklander #endif
32832b31808SJens Wiklander 
mbedtls_internal_sha256_process_many_a64_crypto(mbedtls_sha256_context * ctx,const uint8_t * msg,size_t len)32932b31808SJens Wiklander static size_t mbedtls_internal_sha256_process_many_a64_crypto(
33032b31808SJens Wiklander     mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len)
33132b31808SJens Wiklander {
33232b31808SJens Wiklander     uint32x4_t abcd = vld1q_u32(&ctx->state[0]);
33332b31808SJens Wiklander     uint32x4_t efgh = vld1q_u32(&ctx->state[4]);
33432b31808SJens Wiklander 
33532b31808SJens Wiklander     size_t processed = 0;
33632b31808SJens Wiklander 
33732b31808SJens Wiklander     for (;
33832b31808SJens Wiklander          len >= SHA256_BLOCK_SIZE;
33932b31808SJens Wiklander          processed += SHA256_BLOCK_SIZE,
34032b31808SJens Wiklander          msg += SHA256_BLOCK_SIZE,
34132b31808SJens Wiklander          len -= SHA256_BLOCK_SIZE) {
34232b31808SJens Wiklander         uint32x4_t tmp, abcd_prev;
34332b31808SJens Wiklander 
34432b31808SJens Wiklander         uint32x4_t abcd_orig = abcd;
34532b31808SJens Wiklander         uint32x4_t efgh_orig = efgh;
34632b31808SJens Wiklander 
347b0563631STom Van Eyck         uint32x4_t sched0 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 0));
348b0563631STom Van Eyck         uint32x4_t sched1 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 1));
349b0563631STom Van Eyck         uint32x4_t sched2 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 2));
350b0563631STom Van Eyck         uint32x4_t sched3 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 3));
35132b31808SJens Wiklander 
35232b31808SJens Wiklander #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* Will be true if not defined */
35332b31808SJens Wiklander                                                /* Untested on BE */
35432b31808SJens Wiklander         sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0)));
35532b31808SJens Wiklander         sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1)));
35632b31808SJens Wiklander         sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2)));
35732b31808SJens Wiklander         sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3)));
35832b31808SJens Wiklander #endif
35932b31808SJens Wiklander 
36032b31808SJens Wiklander         /* Rounds 0 to 3 */
36132b31808SJens Wiklander         tmp = vaddq_u32(sched0, vld1q_u32(&K[0]));
36232b31808SJens Wiklander         abcd_prev = abcd;
36332b31808SJens Wiklander         abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
36432b31808SJens Wiklander         efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
36532b31808SJens Wiklander 
36632b31808SJens Wiklander         /* Rounds 4 to 7 */
36732b31808SJens Wiklander         tmp = vaddq_u32(sched1, vld1q_u32(&K[4]));
36832b31808SJens Wiklander         abcd_prev = abcd;
36932b31808SJens Wiklander         abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
37032b31808SJens Wiklander         efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
37132b31808SJens Wiklander 
37232b31808SJens Wiklander         /* Rounds 8 to 11 */
37332b31808SJens Wiklander         tmp = vaddq_u32(sched2, vld1q_u32(&K[8]));
37432b31808SJens Wiklander         abcd_prev = abcd;
37532b31808SJens Wiklander         abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
37632b31808SJens Wiklander         efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
37732b31808SJens Wiklander 
37832b31808SJens Wiklander         /* Rounds 12 to 15 */
37932b31808SJens Wiklander         tmp = vaddq_u32(sched3, vld1q_u32(&K[12]));
38032b31808SJens Wiklander         abcd_prev = abcd;
38132b31808SJens Wiklander         abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
38232b31808SJens Wiklander         efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
38332b31808SJens Wiklander 
38432b31808SJens Wiklander         for (int t = 16; t < 64; t += 16) {
38532b31808SJens Wiklander             /* Rounds t to t + 3 */
38632b31808SJens Wiklander             sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3);
38732b31808SJens Wiklander             tmp = vaddq_u32(sched0, vld1q_u32(&K[t]));
38832b31808SJens Wiklander             abcd_prev = abcd;
38932b31808SJens Wiklander             abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
39032b31808SJens Wiklander             efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
39132b31808SJens Wiklander 
39232b31808SJens Wiklander             /* Rounds t + 4 to t + 7 */
39332b31808SJens Wiklander             sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0);
39432b31808SJens Wiklander             tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4]));
39532b31808SJens Wiklander             abcd_prev = abcd;
39632b31808SJens Wiklander             abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
39732b31808SJens Wiklander             efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
39832b31808SJens Wiklander 
39932b31808SJens Wiklander             /* Rounds t + 8 to t + 11 */
40032b31808SJens Wiklander             sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1);
40132b31808SJens Wiklander             tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8]));
40232b31808SJens Wiklander             abcd_prev = abcd;
40332b31808SJens Wiklander             abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
40432b31808SJens Wiklander             efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
40532b31808SJens Wiklander 
40632b31808SJens Wiklander             /* Rounds t + 12 to t + 15 */
40732b31808SJens Wiklander             sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2);
40832b31808SJens Wiklander             tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12]));
40932b31808SJens Wiklander             abcd_prev = abcd;
41032b31808SJens Wiklander             abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
41132b31808SJens Wiklander             efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
41232b31808SJens Wiklander         }
41332b31808SJens Wiklander 
41432b31808SJens Wiklander         abcd = vaddq_u32(abcd, abcd_orig);
41532b31808SJens Wiklander         efgh = vaddq_u32(efgh, efgh_orig);
41632b31808SJens Wiklander     }
41732b31808SJens Wiklander 
41832b31808SJens Wiklander     vst1q_u32(&ctx->state[0], abcd);
41932b31808SJens Wiklander     vst1q_u32(&ctx->state[4], efgh);
42032b31808SJens Wiklander 
42132b31808SJens Wiklander     return processed;
42232b31808SJens Wiklander }
42332b31808SJens Wiklander 
424b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
42532b31808SJens Wiklander /*
426b0563631STom Van Eyck  * This function is for internal use only if we are building both C and Armv8-A
42732b31808SJens Wiklander  * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
42832b31808SJens Wiklander  */
42932b31808SJens Wiklander static
43032b31808SJens Wiklander #endif
mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context * ctx,const unsigned char data[SHA256_BLOCK_SIZE])43132b31808SJens Wiklander int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,
43232b31808SJens Wiklander                                                const unsigned char data[SHA256_BLOCK_SIZE])
43332b31808SJens Wiklander {
43432b31808SJens Wiklander     return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data,
43532b31808SJens Wiklander                                                             SHA256_BLOCK_SIZE) ==
43632b31808SJens Wiklander             SHA256_BLOCK_SIZE) ? 0 : -1;
43732b31808SJens Wiklander }
43832b31808SJens Wiklander 
439b0563631STom Van Eyck #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */
440b0563631STom Van Eyck 
44132b31808SJens Wiklander #if defined(MBEDTLS_POP_TARGET_PRAGMA)
44232b31808SJens Wiklander #if defined(__clang__)
44332b31808SJens Wiklander #pragma clang attribute pop
44432b31808SJens Wiklander #elif defined(__GNUC__)
44532b31808SJens Wiklander #pragma GCC pop_options
44632b31808SJens Wiklander #endif
44732b31808SJens Wiklander #undef MBEDTLS_POP_TARGET_PRAGMA
44832b31808SJens Wiklander #endif
44932b31808SJens Wiklander 
450b0563631STom Van Eyck #if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
45132b31808SJens Wiklander #define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many
45232b31808SJens Wiklander #define mbedtls_internal_sha256_process_c      mbedtls_internal_sha256_process
45332b31808SJens Wiklander #endif
45432b31808SJens Wiklander 
45532b31808SJens Wiklander 
45632b31808SJens Wiklander #if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \
457b0563631STom Van Eyck     !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
45832b31808SJens Wiklander 
4595b25c76aSJerome Forissier #define  SHR(x, n) (((x) & 0xFFFFFFFF) >> (n))
4605b25c76aSJerome Forissier #define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n))))
461817466cbSJens Wiklander 
462817466cbSJens Wiklander #define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^  SHR(x, 3))
463817466cbSJens Wiklander #define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^  SHR(x, 10))
464817466cbSJens Wiklander 
465817466cbSJens Wiklander #define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
466817466cbSJens Wiklander #define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
467817466cbSJens Wiklander 
4685b25c76aSJerome Forissier #define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
4695b25c76aSJerome Forissier #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
470817466cbSJens Wiklander 
471817466cbSJens Wiklander #define R(t)                                                        \
472817466cbSJens Wiklander     (                                                               \
4737901324dSJerome Forissier         local.W[t] = S1(local.W[(t) -  2]) + local.W[(t) -  7] +    \
4747901324dSJerome Forissier                      S0(local.W[(t) - 15]) + local.W[(t) - 16]      \
475817466cbSJens Wiklander     )
476817466cbSJens Wiklander 
477817466cbSJens Wiklander #define P(a, b, c, d, e, f, g, h, x, K)                                      \
4785b25c76aSJerome Forissier     do                                                              \
479817466cbSJens Wiklander     {                                                               \
4807901324dSJerome Forissier         local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x);    \
4817901324dSJerome Forissier         local.temp2 = S2(a) + F0((a), (b), (c));                      \
4827901324dSJerome Forissier         (d) += local.temp1; (h) = local.temp1 + local.temp2;        \
4835b25c76aSJerome Forissier     } while (0)
484817466cbSJens Wiklander 
485b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
48632b31808SJens Wiklander /*
487b0563631STom Van Eyck  * This function is for internal use only if we are building both C and Armv8
48832b31808SJens Wiklander  * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
48932b31808SJens Wiklander  */
49032b31808SJens Wiklander static
49132b31808SJens Wiklander #endif
mbedtls_internal_sha256_process_c(mbedtls_sha256_context * ctx,const unsigned char data[SHA256_BLOCK_SIZE])49232b31808SJens Wiklander int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx,
49332b31808SJens Wiklander                                       const unsigned char data[SHA256_BLOCK_SIZE])
494817466cbSJens Wiklander {
49532b31808SJens Wiklander     struct {
496817466cbSJens Wiklander         uint32_t temp1, temp2, W[64];
497817466cbSJens Wiklander         uint32_t A[8];
4987901324dSJerome Forissier     } local;
4997901324dSJerome Forissier 
500817466cbSJens Wiklander     unsigned int i;
501817466cbSJens Wiklander 
50232b31808SJens Wiklander     for (i = 0; i < 8; i++) {
5037901324dSJerome Forissier         local.A[i] = ctx->state[i];
50432b31808SJens Wiklander     }
505817466cbSJens Wiklander 
506817466cbSJens Wiklander #if defined(MBEDTLS_SHA256_SMALLER)
50732b31808SJens Wiklander     for (i = 0; i < 64; i++) {
50832b31808SJens Wiklander         if (i < 16) {
509039e02dfSJerome Forissier             local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);
51032b31808SJens Wiklander         } else {
511817466cbSJens Wiklander             R(i);
51232b31808SJens Wiklander         }
513817466cbSJens Wiklander 
5147901324dSJerome Forissier         P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
5157901324dSJerome Forissier           local.A[5], local.A[6], local.A[7], local.W[i], K[i]);
516817466cbSJens Wiklander 
5177901324dSJerome Forissier         local.temp1 = local.A[7]; local.A[7] = local.A[6];
5187901324dSJerome Forissier         local.A[6] = local.A[5]; local.A[5] = local.A[4];
5197901324dSJerome Forissier         local.A[4] = local.A[3]; local.A[3] = local.A[2];
5207901324dSJerome Forissier         local.A[2] = local.A[1]; local.A[1] = local.A[0];
5217901324dSJerome Forissier         local.A[0] = local.temp1;
522817466cbSJens Wiklander     }
523817466cbSJens Wiklander #else /* MBEDTLS_SHA256_SMALLER */
52432b31808SJens Wiklander     for (i = 0; i < 16; i++) {
525039e02dfSJerome Forissier         local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);
52632b31808SJens Wiklander     }
527817466cbSJens Wiklander 
52832b31808SJens Wiklander     for (i = 0; i < 16; i += 8) {
5297901324dSJerome Forissier         P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
5307901324dSJerome Forissier           local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0]);
5317901324dSJerome Forissier         P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
5327901324dSJerome Forissier           local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1]);
5337901324dSJerome Forissier         P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
5347901324dSJerome Forissier           local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2]);
5357901324dSJerome Forissier         P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
5367901324dSJerome Forissier           local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3]);
5377901324dSJerome Forissier         P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
5387901324dSJerome Forissier           local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4]);
5397901324dSJerome Forissier         P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
5407901324dSJerome Forissier           local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5]);
5417901324dSJerome Forissier         P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
5427901324dSJerome Forissier           local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6]);
5437901324dSJerome Forissier         P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
5447901324dSJerome Forissier           local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7]);
545817466cbSJens Wiklander     }
546817466cbSJens Wiklander 
54732b31808SJens Wiklander     for (i = 16; i < 64; i += 8) {
5487901324dSJerome Forissier         P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
5497901324dSJerome Forissier           local.A[5], local.A[6], local.A[7], R(i+0), K[i+0]);
5507901324dSJerome Forissier         P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
5517901324dSJerome Forissier           local.A[4], local.A[5], local.A[6], R(i+1), K[i+1]);
5527901324dSJerome Forissier         P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
5537901324dSJerome Forissier           local.A[3], local.A[4], local.A[5], R(i+2), K[i+2]);
5547901324dSJerome Forissier         P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
5557901324dSJerome Forissier           local.A[2], local.A[3], local.A[4], R(i+3), K[i+3]);
5567901324dSJerome Forissier         P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
5577901324dSJerome Forissier           local.A[1], local.A[2], local.A[3], R(i+4), K[i+4]);
5587901324dSJerome Forissier         P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
5597901324dSJerome Forissier           local.A[0], local.A[1], local.A[2], R(i+5), K[i+5]);
5607901324dSJerome Forissier         P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
5617901324dSJerome Forissier           local.A[7], local.A[0], local.A[1], R(i+6), K[i+6]);
5627901324dSJerome Forissier         P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
5637901324dSJerome Forissier           local.A[6], local.A[7], local.A[0], R(i+7), K[i+7]);
564817466cbSJens Wiklander     }
565817466cbSJens Wiklander #endif /* MBEDTLS_SHA256_SMALLER */
566817466cbSJens Wiklander 
56732b31808SJens Wiklander     for (i = 0; i < 8; i++) {
5687901324dSJerome Forissier         ctx->state[i] += local.A[i];
56932b31808SJens Wiklander     }
5707901324dSJerome Forissier 
5717901324dSJerome Forissier     /* Zeroise buffers and variables to clear sensitive data from memory. */
5727901324dSJerome Forissier     mbedtls_platform_zeroize(&local, sizeof(local));
5733d3b0591SJens Wiklander 
57432b31808SJens Wiklander     return 0;
575817466cbSJens Wiklander }
5763d3b0591SJens Wiklander 
577b0563631STom Van Eyck #endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */
57832b31808SJens Wiklander 
57932b31808SJens Wiklander 
580b0563631STom Van Eyck #if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
58132b31808SJens Wiklander 
mbedtls_internal_sha256_process_many_c(mbedtls_sha256_context * ctx,const uint8_t * data,size_t len)58232b31808SJens Wiklander static size_t mbedtls_internal_sha256_process_many_c(
58332b31808SJens Wiklander     mbedtls_sha256_context *ctx, const uint8_t *data, size_t len)
5843d3b0591SJens Wiklander {
58532b31808SJens Wiklander     size_t processed = 0;
58632b31808SJens Wiklander 
58732b31808SJens Wiklander     while (len >= SHA256_BLOCK_SIZE) {
58832b31808SJens Wiklander         if (mbedtls_internal_sha256_process_c(ctx, data) != 0) {
58932b31808SJens Wiklander             return 0;
5903d3b0591SJens Wiklander         }
59132b31808SJens Wiklander 
59232b31808SJens Wiklander         data += SHA256_BLOCK_SIZE;
59332b31808SJens Wiklander         len  -= SHA256_BLOCK_SIZE;
59432b31808SJens Wiklander 
59532b31808SJens Wiklander         processed += SHA256_BLOCK_SIZE;
59632b31808SJens Wiklander     }
59732b31808SJens Wiklander 
59832b31808SJens Wiklander     return processed;
59932b31808SJens Wiklander }
60032b31808SJens Wiklander 
601b0563631STom Van Eyck #endif /* !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */
60232b31808SJens Wiklander 
60332b31808SJens Wiklander 
604b0563631STom Van Eyck #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
60532b31808SJens Wiklander 
mbedtls_a64_crypto_sha256_has_support(void)60632b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_has_support(void)
60732b31808SJens Wiklander {
60832b31808SJens Wiklander     static int done = 0;
60932b31808SJens Wiklander     static int supported = 0;
61032b31808SJens Wiklander 
61132b31808SJens Wiklander     if (!done) {
61232b31808SJens Wiklander         supported = mbedtls_a64_crypto_sha256_determine_support();
61332b31808SJens Wiklander         done = 1;
61432b31808SJens Wiklander     }
61532b31808SJens Wiklander 
61632b31808SJens Wiklander     return supported;
61732b31808SJens Wiklander }
61832b31808SJens Wiklander 
mbedtls_internal_sha256_process_many(mbedtls_sha256_context * ctx,const uint8_t * msg,size_t len)61932b31808SJens Wiklander static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx,
62032b31808SJens Wiklander                                                    const uint8_t *msg, size_t len)
62132b31808SJens Wiklander {
62232b31808SJens Wiklander     if (mbedtls_a64_crypto_sha256_has_support()) {
62332b31808SJens Wiklander         return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len);
62432b31808SJens Wiklander     } else {
62532b31808SJens Wiklander         return mbedtls_internal_sha256_process_many_c(ctx, msg, len);
62632b31808SJens Wiklander     }
62732b31808SJens Wiklander }
62832b31808SJens Wiklander 
mbedtls_internal_sha256_process(mbedtls_sha256_context * ctx,const unsigned char data[SHA256_BLOCK_SIZE])62932b31808SJens Wiklander int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,
63032b31808SJens Wiklander                                     const unsigned char data[SHA256_BLOCK_SIZE])
63132b31808SJens Wiklander {
63232b31808SJens Wiklander     if (mbedtls_a64_crypto_sha256_has_support()) {
63332b31808SJens Wiklander         return mbedtls_internal_sha256_process_a64_crypto(ctx, data);
63432b31808SJens Wiklander     } else {
63532b31808SJens Wiklander         return mbedtls_internal_sha256_process_c(ctx, data);
63632b31808SJens Wiklander     }
63732b31808SJens Wiklander }
63832b31808SJens Wiklander 
639b0563631STom Van Eyck #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */
64032b31808SJens Wiklander 
641817466cbSJens Wiklander 
642817466cbSJens Wiklander /*
643817466cbSJens Wiklander  * SHA-256 process buffer
644817466cbSJens Wiklander  */
mbedtls_sha256_update(mbedtls_sha256_context * ctx,const unsigned char * input,size_t ilen)64532b31808SJens Wiklander int mbedtls_sha256_update(mbedtls_sha256_context *ctx,
6463d3b0591SJens Wiklander                           const unsigned char *input,
647817466cbSJens Wiklander                           size_t ilen)
648817466cbSJens Wiklander {
64911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
650817466cbSJens Wiklander     size_t fill;
651817466cbSJens Wiklander     uint32_t left;
652817466cbSJens Wiklander 
65332b31808SJens Wiklander     if (ilen == 0) {
65432b31808SJens Wiklander         return 0;
65532b31808SJens Wiklander     }
656817466cbSJens Wiklander 
657817466cbSJens Wiklander     left = ctx->total[0] & 0x3F;
65832b31808SJens Wiklander     fill = SHA256_BLOCK_SIZE - left;
659817466cbSJens Wiklander 
660817466cbSJens Wiklander     ctx->total[0] += (uint32_t) ilen;
661817466cbSJens Wiklander     ctx->total[0] &= 0xFFFFFFFF;
662817466cbSJens Wiklander 
66332b31808SJens Wiklander     if (ctx->total[0] < (uint32_t) ilen) {
664817466cbSJens Wiklander         ctx->total[1]++;
66532b31808SJens Wiklander     }
666817466cbSJens Wiklander 
66732b31808SJens Wiklander     if (left && ilen >= fill) {
668817466cbSJens Wiklander         memcpy((void *) (ctx->buffer + left), input, fill);
6693d3b0591SJens Wiklander 
67032b31808SJens Wiklander         if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
67132b31808SJens Wiklander             return ret;
67232b31808SJens Wiklander         }
6733d3b0591SJens Wiklander 
674817466cbSJens Wiklander         input += fill;
675817466cbSJens Wiklander         ilen  -= fill;
676817466cbSJens Wiklander         left = 0;
677817466cbSJens Wiklander     }
678817466cbSJens Wiklander 
67932b31808SJens Wiklander     while (ilen >= SHA256_BLOCK_SIZE) {
68032b31808SJens Wiklander         size_t processed =
68132b31808SJens Wiklander             mbedtls_internal_sha256_process_many(ctx, input, ilen);
68232b31808SJens Wiklander         if (processed < SHA256_BLOCK_SIZE) {
68332b31808SJens Wiklander             return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
684817466cbSJens Wiklander         }
685817466cbSJens Wiklander 
68632b31808SJens Wiklander         input += processed;
68732b31808SJens Wiklander         ilen  -= processed;
68832b31808SJens Wiklander     }
68932b31808SJens Wiklander 
69032b31808SJens Wiklander     if (ilen > 0) {
691817466cbSJens Wiklander         memcpy((void *) (ctx->buffer + left), input, ilen);
692817466cbSJens Wiklander     }
693817466cbSJens Wiklander 
69432b31808SJens Wiklander     return 0;
6953d3b0591SJens Wiklander }
696817466cbSJens Wiklander 
697817466cbSJens Wiklander /*
698817466cbSJens Wiklander  * SHA-256 final digest
699817466cbSJens Wiklander  */
mbedtls_sha256_finish(mbedtls_sha256_context * ctx,unsigned char * output)70032b31808SJens Wiklander int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
70132b31808SJens Wiklander                           unsigned char *output)
702817466cbSJens Wiklander {
70311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
7043d3b0591SJens Wiklander     uint32_t used;
705817466cbSJens Wiklander     uint32_t high, low;
706b0563631STom Van Eyck     int truncated = 0;
707817466cbSJens Wiklander 
7083d3b0591SJens Wiklander     /*
7093d3b0591SJens Wiklander      * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
7103d3b0591SJens Wiklander      */
7113d3b0591SJens Wiklander     used = ctx->total[0] & 0x3F;
7123d3b0591SJens Wiklander 
7133d3b0591SJens Wiklander     ctx->buffer[used++] = 0x80;
7143d3b0591SJens Wiklander 
71532b31808SJens Wiklander     if (used <= 56) {
7163d3b0591SJens Wiklander         /* Enough room for padding + length in current block */
7173d3b0591SJens Wiklander         memset(ctx->buffer + used, 0, 56 - used);
71832b31808SJens Wiklander     } else {
7193d3b0591SJens Wiklander         /* We'll need an extra block */
72032b31808SJens Wiklander         memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used);
7213d3b0591SJens Wiklander 
72232b31808SJens Wiklander         if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
723b0563631STom Van Eyck             goto exit;
72432b31808SJens Wiklander         }
7253d3b0591SJens Wiklander 
7263d3b0591SJens Wiklander         memset(ctx->buffer, 0, 56);
7273d3b0591SJens Wiklander     }
7283d3b0591SJens Wiklander 
7293d3b0591SJens Wiklander     /*
7303d3b0591SJens Wiklander      * Add message length
7313d3b0591SJens Wiklander      */
732817466cbSJens Wiklander     high = (ctx->total[0] >> 29)
733817466cbSJens Wiklander            | (ctx->total[1] <<  3);
734817466cbSJens Wiklander     low  = (ctx->total[0] <<  3);
735817466cbSJens Wiklander 
736039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56);
737039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(low,  ctx->buffer, 60);
738817466cbSJens Wiklander 
73932b31808SJens Wiklander     if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
740b0563631STom Van Eyck         goto exit;
74132b31808SJens Wiklander     }
742817466cbSJens Wiklander 
7433d3b0591SJens Wiklander     /*
7443d3b0591SJens Wiklander      * Output final state
7453d3b0591SJens Wiklander      */
746039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[0], output,  0);
747039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[1], output,  4);
748039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[2], output,  8);
749039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12);
750039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16);
751039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20);
752039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24);
753817466cbSJens Wiklander 
75432b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
75532b31808SJens Wiklander     truncated = ctx->is224;
7563d3b0591SJens Wiklander #endif
75732b31808SJens Wiklander     if (!truncated) {
75832b31808SJens Wiklander         MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28);
75932b31808SJens Wiklander     }
76032b31808SJens Wiklander 
761b0563631STom Van Eyck     ret = 0;
762b0563631STom Van Eyck 
763b0563631STom Van Eyck exit:
764b0563631STom Van Eyck     mbedtls_sha256_free(ctx);
765b0563631STom Van Eyck     return ret;
76632b31808SJens Wiklander }
7673d3b0591SJens Wiklander 
768817466cbSJens Wiklander #endif /* !MBEDTLS_SHA256_ALT */
769817466cbSJens Wiklander 
770817466cbSJens Wiklander /*
771817466cbSJens Wiklander  * output = SHA-256( input buffer )
772817466cbSJens Wiklander  */
mbedtls_sha256(const unsigned char * input,size_t ilen,unsigned char * output,int is224)77332b31808SJens Wiklander int mbedtls_sha256(const unsigned char *input,
7743d3b0591SJens Wiklander                    size_t ilen,
77532b31808SJens Wiklander                    unsigned char *output,
7763d3b0591SJens Wiklander                    int is224)
777817466cbSJens Wiklander {
77811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
779817466cbSJens Wiklander     mbedtls_sha256_context ctx;
780817466cbSJens Wiklander 
78132b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
78232b31808SJens Wiklander     if (is224 != 0 && is224 != 1) {
78332b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
78432b31808SJens Wiklander     }
78532b31808SJens Wiklander #elif defined(MBEDTLS_SHA256_C)
78632b31808SJens Wiklander     if (is224 != 0) {
78732b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
78832b31808SJens Wiklander     }
78932b31808SJens Wiklander #else /* defined MBEDTLS_SHA224_C only */
79032b31808SJens Wiklander     if (is224 == 0) {
79132b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
79232b31808SJens Wiklander     }
79332b31808SJens Wiklander #endif
7943d3b0591SJens Wiklander 
795817466cbSJens Wiklander     mbedtls_sha256_init(&ctx);
7963d3b0591SJens Wiklander 
79732b31808SJens Wiklander     if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {
7983d3b0591SJens Wiklander         goto exit;
79932b31808SJens Wiklander     }
8003d3b0591SJens Wiklander 
80132b31808SJens Wiklander     if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) {
8023d3b0591SJens Wiklander         goto exit;
80332b31808SJens Wiklander     }
8043d3b0591SJens Wiklander 
80532b31808SJens Wiklander     if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) {
8063d3b0591SJens Wiklander         goto exit;
80732b31808SJens Wiklander     }
8083d3b0591SJens Wiklander 
8093d3b0591SJens Wiklander exit:
810817466cbSJens Wiklander     mbedtls_sha256_free(&ctx);
8113d3b0591SJens Wiklander 
81232b31808SJens Wiklander     return ret;
813817466cbSJens Wiklander }
814817466cbSJens Wiklander 
815817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
816817466cbSJens Wiklander /*
817817466cbSJens Wiklander  * FIPS-180-2 test vectors
818817466cbSJens Wiklander  */
81932b31808SJens Wiklander static const unsigned char sha_test_buf[3][57] =
820817466cbSJens Wiklander {
821817466cbSJens Wiklander     { "abc" },
822817466cbSJens Wiklander     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
823817466cbSJens Wiklander     { "" }
824817466cbSJens Wiklander };
825817466cbSJens Wiklander 
82632b31808SJens Wiklander static const size_t sha_test_buflen[3] =
827817466cbSJens Wiklander {
828817466cbSJens Wiklander     3, 56, 1000
829817466cbSJens Wiklander };
830817466cbSJens Wiklander 
83132b31808SJens Wiklander typedef const unsigned char (sha_test_sum_t)[32];
83232b31808SJens Wiklander 
833817466cbSJens Wiklander /*
834817466cbSJens Wiklander  * SHA-224 test vectors
835817466cbSJens Wiklander  */
83632b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
83732b31808SJens Wiklander static sha_test_sum_t sha224_test_sum[] =
83832b31808SJens Wiklander {
839817466cbSJens Wiklander     { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
840817466cbSJens Wiklander       0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
841817466cbSJens Wiklander       0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
842817466cbSJens Wiklander       0xE3, 0x6C, 0x9D, 0xA7 },
843817466cbSJens Wiklander     { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
844817466cbSJens Wiklander       0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
845817466cbSJens Wiklander       0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
846817466cbSJens Wiklander       0x52, 0x52, 0x25, 0x25 },
847817466cbSJens Wiklander     { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
848817466cbSJens Wiklander       0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
849817466cbSJens Wiklander       0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
85032b31808SJens Wiklander       0x4E, 0xE7, 0xAD, 0x67 }
85132b31808SJens Wiklander };
85232b31808SJens Wiklander #endif
853817466cbSJens Wiklander 
854817466cbSJens Wiklander /*
855817466cbSJens Wiklander  * SHA-256 test vectors
856817466cbSJens Wiklander  */
85732b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C)
85832b31808SJens Wiklander static sha_test_sum_t sha256_test_sum[] =
85932b31808SJens Wiklander {
860817466cbSJens Wiklander     { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
861817466cbSJens Wiklander       0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
862817466cbSJens Wiklander       0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
863817466cbSJens Wiklander       0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
864817466cbSJens Wiklander     { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
865817466cbSJens Wiklander       0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
866817466cbSJens Wiklander       0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
867817466cbSJens Wiklander       0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
868817466cbSJens Wiklander     { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
869817466cbSJens Wiklander       0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
870817466cbSJens Wiklander       0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
871817466cbSJens Wiklander       0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
872817466cbSJens Wiklander };
87332b31808SJens Wiklander #endif
874817466cbSJens Wiklander 
875817466cbSJens Wiklander /*
876817466cbSJens Wiklander  * Checkup routine
877817466cbSJens Wiklander  */
mbedtls_sha256_common_self_test(int verbose,int is224)87832b31808SJens Wiklander static int mbedtls_sha256_common_self_test(int verbose, int is224)
879817466cbSJens Wiklander {
88032b31808SJens Wiklander     int i, buflen, ret = 0;
881817466cbSJens Wiklander     unsigned char *buf;
882817466cbSJens Wiklander     unsigned char sha256sum[32];
883817466cbSJens Wiklander     mbedtls_sha256_context ctx;
884817466cbSJens Wiklander 
88532b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
88632b31808SJens Wiklander     sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum;
88732b31808SJens Wiklander #elif defined(MBEDTLS_SHA256_C)
88832b31808SJens Wiklander     sha_test_sum_t *sha_test_sum = sha256_test_sum;
88932b31808SJens Wiklander #else
89032b31808SJens Wiklander     sha_test_sum_t *sha_test_sum = sha224_test_sum;
89132b31808SJens Wiklander #endif
892817466cbSJens Wiklander 
89332b31808SJens Wiklander     buf = mbedtls_calloc(1024, sizeof(unsigned char));
89432b31808SJens Wiklander     if (NULL == buf) {
89532b31808SJens Wiklander         if (verbose != 0) {
89632b31808SJens Wiklander             mbedtls_printf("Buffer allocation failed\n");
89732b31808SJens Wiklander         }
89832b31808SJens Wiklander 
89932b31808SJens Wiklander         return 1;
900817466cbSJens Wiklander     }
901817466cbSJens Wiklander 
902817466cbSJens Wiklander     mbedtls_sha256_init(&ctx);
903817466cbSJens Wiklander 
90432b31808SJens Wiklander     for (i = 0; i < 3; i++) {
90532b31808SJens Wiklander         if (verbose != 0) {
90632b31808SJens Wiklander             mbedtls_printf("  SHA-%d test #%d: ", 256 - is224 * 32, i + 1);
90732b31808SJens Wiklander         }
908817466cbSJens Wiklander 
90932b31808SJens Wiklander         if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {
9103d3b0591SJens Wiklander             goto fail;
91132b31808SJens Wiklander         }
912817466cbSJens Wiklander 
91332b31808SJens Wiklander         if (i == 2) {
914817466cbSJens Wiklander             memset(buf, 'a', buflen = 1000);
915817466cbSJens Wiklander 
91632b31808SJens Wiklander             for (int j = 0; j < 1000; j++) {
91732b31808SJens Wiklander                 ret = mbedtls_sha256_update(&ctx, buf, buflen);
91832b31808SJens Wiklander                 if (ret != 0) {
91932b31808SJens Wiklander                     goto fail;
92032b31808SJens Wiklander                 }
92132b31808SJens Wiklander             }
92232b31808SJens Wiklander 
92332b31808SJens Wiklander         } else {
92432b31808SJens Wiklander             ret = mbedtls_sha256_update(&ctx, sha_test_buf[i],
92532b31808SJens Wiklander                                         sha_test_buflen[i]);
92632b31808SJens Wiklander             if (ret != 0) {
92732b31808SJens Wiklander                 goto fail;
92832b31808SJens Wiklander             }
92932b31808SJens Wiklander         }
93032b31808SJens Wiklander 
93132b31808SJens Wiklander         if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) {
9323d3b0591SJens Wiklander             goto fail;
9333d3b0591SJens Wiklander         }
9343d3b0591SJens Wiklander 
935817466cbSJens Wiklander 
93632b31808SJens Wiklander         if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 4) != 0) {
937817466cbSJens Wiklander             ret = 1;
9383d3b0591SJens Wiklander             goto fail;
939817466cbSJens Wiklander         }
940817466cbSJens Wiklander 
94132b31808SJens Wiklander         if (verbose != 0) {
942817466cbSJens Wiklander             mbedtls_printf("passed\n");
943817466cbSJens Wiklander         }
94432b31808SJens Wiklander     }
945817466cbSJens Wiklander 
94632b31808SJens Wiklander     if (verbose != 0) {
947817466cbSJens Wiklander         mbedtls_printf("\n");
94832b31808SJens Wiklander     }
949817466cbSJens Wiklander 
9503d3b0591SJens Wiklander     goto exit;
9513d3b0591SJens Wiklander 
9523d3b0591SJens Wiklander fail:
95332b31808SJens Wiklander     if (verbose != 0) {
9543d3b0591SJens Wiklander         mbedtls_printf("failed\n");
95532b31808SJens Wiklander     }
9563d3b0591SJens Wiklander 
957817466cbSJens Wiklander exit:
958817466cbSJens Wiklander     mbedtls_sha256_free(&ctx);
959817466cbSJens Wiklander     mbedtls_free(buf);
960817466cbSJens Wiklander 
96132b31808SJens Wiklander     return ret;
962817466cbSJens Wiklander }
963817466cbSJens Wiklander 
96432b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C)
mbedtls_sha256_self_test(int verbose)96532b31808SJens Wiklander int mbedtls_sha256_self_test(int verbose)
96632b31808SJens Wiklander {
96732b31808SJens Wiklander     return mbedtls_sha256_common_self_test(verbose, 0);
96832b31808SJens Wiklander }
96932b31808SJens Wiklander #endif /* MBEDTLS_SHA256_C */
97032b31808SJens Wiklander 
97132b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
mbedtls_sha224_self_test(int verbose)97232b31808SJens Wiklander int mbedtls_sha224_self_test(int verbose)
97332b31808SJens Wiklander {
97432b31808SJens Wiklander     return mbedtls_sha256_common_self_test(verbose, 1);
97532b31808SJens Wiklander }
97632b31808SJens Wiklander #endif /* MBEDTLS_SHA224_C */
97732b31808SJens Wiklander 
978817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
979817466cbSJens Wiklander 
98032b31808SJens Wiklander #endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */
981