xref: /optee_os/lib/libmbedtls/mbedtls/library/sha256.c (revision b0563631928755fe864b97785160fb3088e9efdc)
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