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