xref: /optee_os/lib/libmbedtls/mbedtls/library/sha256.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  FIPS-180-2 compliant SHA-256 implementation
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander /*
20817466cbSJens Wiklander  *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
21817466cbSJens Wiklander  *
22817466cbSJens Wiklander  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
23817466cbSJens Wiklander  */
24817466cbSJens Wiklander 
25*32b31808SJens Wiklander #if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \
26*32b31808SJens Wiklander     defined(__clang__) && __clang_major__ >= 4
27*32b31808SJens Wiklander /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
28*32b31808SJens Wiklander  *
29*32b31808SJens Wiklander  * The intrinsic declaration are guarded by predefined ACLE macros in clang:
30*32b31808SJens Wiklander  * these are normally only enabled by the -march option on the command line.
31*32b31808SJens Wiklander  * By defining the macros ourselves we gain access to those declarations without
32*32b31808SJens Wiklander  * requiring -march on the command line.
33*32b31808SJens Wiklander  *
34*32b31808SJens Wiklander  * `arm_neon.h` could be included by any header file, so we put these defines
35*32b31808SJens Wiklander  * at the top of this file, before any includes.
36*32b31808SJens Wiklander  */
37*32b31808SJens Wiklander #define __ARM_FEATURE_CRYPTO 1
38*32b31808SJens Wiklander /* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions
39*32b31808SJens Wiklander  *
40*32b31808SJens Wiklander  * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it
41*32b31808SJens Wiklander  * for older compilers.
42*32b31808SJens Wiklander  */
43*32b31808SJens Wiklander #define __ARM_FEATURE_SHA2   1
44*32b31808SJens Wiklander #define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG
45*32b31808SJens Wiklander #endif
46*32b31808SJens Wiklander 
477901324dSJerome Forissier #include "common.h"
48817466cbSJens Wiklander 
49*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)
50817466cbSJens Wiklander 
51817466cbSJens Wiklander #include "mbedtls/sha256.h"
523d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
5311fa71b9SJerome Forissier #include "mbedtls/error.h"
54817466cbSJens Wiklander 
55817466cbSJens Wiklander #include <string.h>
56817466cbSJens Wiklander 
57817466cbSJens Wiklander #include "mbedtls/platform.h"
58817466cbSJens Wiklander 
59*32b31808SJens Wiklander #if defined(__aarch64__)
60*32b31808SJens Wiklander #  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
61*32b31808SJens Wiklander     defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
62*32b31808SJens Wiklander /* *INDENT-OFF* */
63*32b31808SJens Wiklander #    if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
64*32b31808SJens Wiklander #      if defined(__clang__)
65*32b31808SJens Wiklander #        if __clang_major__ < 4
66*32b31808SJens Wiklander #          error "A more recent Clang is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
67*32b31808SJens Wiklander #        endif
68*32b31808SJens Wiklander #        pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
69*32b31808SJens Wiklander #        define MBEDTLS_POP_TARGET_PRAGMA
70*32b31808SJens Wiklander #      elif defined(__GNUC__)
71*32b31808SJens Wiklander          /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some
72*32b31808SJens Wiklander           *        intrinsics are missing. Missing intrinsics could be worked around.
73*32b31808SJens Wiklander           */
74*32b31808SJens Wiklander #        if __GNUC__ < 6
75*32b31808SJens Wiklander #          error "A more recent GCC is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
76*32b31808SJens Wiklander #        else
77*32b31808SJens Wiklander #          pragma GCC push_options
78*32b31808SJens Wiklander #          pragma GCC target ("arch=armv8-a+crypto")
79*32b31808SJens Wiklander #          define MBEDTLS_POP_TARGET_PRAGMA
80*32b31808SJens Wiklander #        endif
81*32b31808SJens Wiklander #      else
82*32b31808SJens Wiklander #        error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
83*32b31808SJens Wiklander #      endif
84*32b31808SJens Wiklander #    endif
85*32b31808SJens Wiklander /* *INDENT-ON* */
86*32b31808SJens Wiklander #    include <arm_neon.h>
87*32b31808SJens Wiklander #  endif
88*32b31808SJens Wiklander #  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
89*32b31808SJens Wiklander #    if defined(__unix__)
90*32b31808SJens Wiklander #      if defined(__linux__)
91*32b31808SJens Wiklander /* Our preferred method of detection is getauxval() */
92*32b31808SJens Wiklander #        include <sys/auxv.h>
93*32b31808SJens Wiklander #      endif
94*32b31808SJens Wiklander /* Use SIGILL on Unix, and fall back to it on Linux */
95*32b31808SJens Wiklander #      include <signal.h>
96*32b31808SJens Wiklander #    endif
97*32b31808SJens Wiklander #  endif
98*32b31808SJens Wiklander #elif defined(_M_ARM64)
99*32b31808SJens Wiklander #  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
100*32b31808SJens Wiklander     defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
101*32b31808SJens Wiklander #    include <arm64_neon.h>
102*32b31808SJens Wiklander #  endif
103*32b31808SJens Wiklander #else
104*32b31808SJens Wiklander #  undef MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY
105*32b31808SJens Wiklander #  undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
106*32b31808SJens Wiklander #endif
107*32b31808SJens Wiklander 
108*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
109*32b31808SJens Wiklander /*
110*32b31808SJens Wiklander  * Capability detection code comes early, so we can disable
111*32b31808SJens Wiklander  * MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found
112*32b31808SJens Wiklander  */
113*32b31808SJens Wiklander #if defined(HWCAP_SHA2)
114*32b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void)
115*32b31808SJens Wiklander {
116*32b31808SJens Wiklander     return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0;
117*32b31808SJens Wiklander }
118*32b31808SJens Wiklander #elif defined(__APPLE__)
119*32b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void)
120*32b31808SJens Wiklander {
121*32b31808SJens Wiklander     return 1;
122*32b31808SJens Wiklander }
123*32b31808SJens Wiklander #elif defined(_M_ARM64)
124*32b31808SJens Wiklander #define WIN32_LEAN_AND_MEAN
125*32b31808SJens Wiklander #include <Windows.h>
126*32b31808SJens Wiklander #include <processthreadsapi.h>
127*32b31808SJens Wiklander 
128*32b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void)
129*32b31808SJens Wiklander {
130*32b31808SJens Wiklander     return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ?
131*32b31808SJens Wiklander            1 : 0;
132*32b31808SJens Wiklander }
133*32b31808SJens Wiklander #elif defined(__unix__) && defined(SIG_SETMASK)
134*32b31808SJens Wiklander /* Detection with SIGILL, setjmp() and longjmp() */
135*32b31808SJens Wiklander #include <signal.h>
136*32b31808SJens Wiklander #include <setjmp.h>
137*32b31808SJens Wiklander 
138*32b31808SJens Wiklander static jmp_buf return_from_sigill;
139*32b31808SJens Wiklander 
140*32b31808SJens Wiklander /*
141*32b31808SJens Wiklander  * A64 SHA256 support detection via SIGILL
142*32b31808SJens Wiklander  */
143*32b31808SJens Wiklander static void sigill_handler(int signal)
144*32b31808SJens Wiklander {
145*32b31808SJens Wiklander     (void) signal;
146*32b31808SJens Wiklander     longjmp(return_from_sigill, 1);
147*32b31808SJens Wiklander }
148*32b31808SJens Wiklander 
149*32b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_determine_support(void)
150*32b31808SJens Wiklander {
151*32b31808SJens Wiklander     struct sigaction old_action, new_action;
152*32b31808SJens Wiklander 
153*32b31808SJens Wiklander     sigset_t old_mask;
154*32b31808SJens Wiklander     if (sigprocmask(0, NULL, &old_mask)) {
155*32b31808SJens Wiklander         return 0;
156*32b31808SJens Wiklander     }
157*32b31808SJens Wiklander 
158*32b31808SJens Wiklander     sigemptyset(&new_action.sa_mask);
159*32b31808SJens Wiklander     new_action.sa_flags = 0;
160*32b31808SJens Wiklander     new_action.sa_handler = sigill_handler;
161*32b31808SJens Wiklander 
162*32b31808SJens Wiklander     sigaction(SIGILL, &new_action, &old_action);
163*32b31808SJens Wiklander 
164*32b31808SJens Wiklander     static int ret = 0;
165*32b31808SJens Wiklander 
166*32b31808SJens Wiklander     if (setjmp(return_from_sigill) == 0) {         /* First return only */
167*32b31808SJens Wiklander         /* If this traps, we will return a second time from setjmp() with 1 */
168*32b31808SJens Wiklander         asm ("sha256h q0, q0, v0.4s" : : : "v0");
169*32b31808SJens Wiklander         ret = 1;
170*32b31808SJens Wiklander     }
171*32b31808SJens Wiklander 
172*32b31808SJens Wiklander     sigaction(SIGILL, &old_action, NULL);
173*32b31808SJens Wiklander     sigprocmask(SIG_SETMASK, &old_mask, NULL);
174*32b31808SJens Wiklander 
175*32b31808SJens Wiklander     return ret;
176*32b31808SJens Wiklander }
177*32b31808SJens Wiklander #else
178*32b31808SJens Wiklander #warning "No mechanism to detect A64_CRYPTO found, using C code only"
179*32b31808SJens Wiklander #undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
180*32b31808SJens Wiklander #endif  /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */
181*32b31808SJens Wiklander 
182*32b31808SJens Wiklander #endif  /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
183817466cbSJens Wiklander 
1843d3b0591SJens Wiklander #if !defined(MBEDTLS_SHA256_ALT)
185817466cbSJens Wiklander 
186*32b31808SJens Wiklander #define SHA256_BLOCK_SIZE 64
187*32b31808SJens Wiklander 
188817466cbSJens Wiklander void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
189817466cbSJens Wiklander {
190817466cbSJens Wiklander     memset(ctx, 0, sizeof(mbedtls_sha256_context));
191817466cbSJens Wiklander }
192817466cbSJens Wiklander 
193817466cbSJens Wiklander void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
194817466cbSJens Wiklander {
195*32b31808SJens Wiklander     if (ctx == NULL) {
196817466cbSJens Wiklander         return;
197*32b31808SJens Wiklander     }
198817466cbSJens Wiklander 
1993d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha256_context));
200817466cbSJens Wiklander }
201817466cbSJens Wiklander 
202817466cbSJens Wiklander void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
203817466cbSJens Wiklander                           const mbedtls_sha256_context *src)
204817466cbSJens Wiklander {
205817466cbSJens Wiklander     *dst = *src;
206817466cbSJens Wiklander }
207817466cbSJens Wiklander 
208817466cbSJens Wiklander /*
209817466cbSJens Wiklander  * SHA-256 context setup
210817466cbSJens Wiklander  */
211*32b31808SJens Wiklander int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
212817466cbSJens Wiklander {
213*32b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
214*32b31808SJens Wiklander     if (is224 != 0 && is224 != 1) {
215*32b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
216*32b31808SJens Wiklander     }
217*32b31808SJens Wiklander #elif defined(MBEDTLS_SHA256_C)
218*32b31808SJens Wiklander     if (is224 != 0) {
219*32b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
220*32b31808SJens Wiklander     }
221*32b31808SJens Wiklander #else /* defined MBEDTLS_SHA224_C only */
222*32b31808SJens Wiklander     if (is224 == 0) {
223*32b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
224*32b31808SJens Wiklander     }
225*32b31808SJens Wiklander #endif
2263d3b0591SJens Wiklander 
227817466cbSJens Wiklander     ctx->total[0] = 0;
228817466cbSJens Wiklander     ctx->total[1] = 0;
229817466cbSJens Wiklander 
230*32b31808SJens Wiklander     if (is224 == 0) {
231*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C)
232817466cbSJens Wiklander         ctx->state[0] = 0x6A09E667;
233817466cbSJens Wiklander         ctx->state[1] = 0xBB67AE85;
234817466cbSJens Wiklander         ctx->state[2] = 0x3C6EF372;
235817466cbSJens Wiklander         ctx->state[3] = 0xA54FF53A;
236817466cbSJens Wiklander         ctx->state[4] = 0x510E527F;
237817466cbSJens Wiklander         ctx->state[5] = 0x9B05688C;
238817466cbSJens Wiklander         ctx->state[6] = 0x1F83D9AB;
239817466cbSJens Wiklander         ctx->state[7] = 0x5BE0CD19;
240*32b31808SJens Wiklander #endif
241*32b31808SJens Wiklander     } else {
242*32b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
243817466cbSJens Wiklander         ctx->state[0] = 0xC1059ED8;
244817466cbSJens Wiklander         ctx->state[1] = 0x367CD507;
245817466cbSJens Wiklander         ctx->state[2] = 0x3070DD17;
246817466cbSJens Wiklander         ctx->state[3] = 0xF70E5939;
247817466cbSJens Wiklander         ctx->state[4] = 0xFFC00B31;
248817466cbSJens Wiklander         ctx->state[5] = 0x68581511;
249817466cbSJens Wiklander         ctx->state[6] = 0x64F98FA7;
250817466cbSJens Wiklander         ctx->state[7] = 0xBEFA4FA4;
2513d3b0591SJens Wiklander #endif
252*32b31808SJens Wiklander     }
253*32b31808SJens Wiklander 
254*32b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
255*32b31808SJens Wiklander     ctx->is224 = is224;
256*32b31808SJens Wiklander #endif
257*32b31808SJens Wiklander 
258*32b31808SJens Wiklander     return 0;
259*32b31808SJens Wiklander }
2603d3b0591SJens Wiklander 
261817466cbSJens Wiklander #if !defined(MBEDTLS_SHA256_PROCESS_ALT)
262817466cbSJens Wiklander static const uint32_t K[] =
263817466cbSJens Wiklander {
264817466cbSJens Wiklander     0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
265817466cbSJens Wiklander     0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
266817466cbSJens Wiklander     0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
267817466cbSJens Wiklander     0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
268817466cbSJens Wiklander     0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
269817466cbSJens Wiklander     0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
270817466cbSJens Wiklander     0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
271817466cbSJens Wiklander     0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
272817466cbSJens Wiklander     0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
273817466cbSJens Wiklander     0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
274817466cbSJens Wiklander     0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
275817466cbSJens Wiklander     0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
276817466cbSJens Wiklander     0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
277817466cbSJens Wiklander     0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
278817466cbSJens Wiklander     0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
279817466cbSJens Wiklander     0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
280817466cbSJens Wiklander };
281817466cbSJens Wiklander 
282*32b31808SJens Wiklander #endif
283*32b31808SJens Wiklander 
284*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
285*32b31808SJens Wiklander     defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
286*32b31808SJens Wiklander 
287*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
288*32b31808SJens Wiklander #  define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many
289*32b31808SJens Wiklander #  define mbedtls_internal_sha256_process_a64_crypto      mbedtls_internal_sha256_process
290*32b31808SJens Wiklander #endif
291*32b31808SJens Wiklander 
292*32b31808SJens Wiklander static size_t mbedtls_internal_sha256_process_many_a64_crypto(
293*32b31808SJens Wiklander     mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len)
294*32b31808SJens Wiklander {
295*32b31808SJens Wiklander     uint32x4_t abcd = vld1q_u32(&ctx->state[0]);
296*32b31808SJens Wiklander     uint32x4_t efgh = vld1q_u32(&ctx->state[4]);
297*32b31808SJens Wiklander 
298*32b31808SJens Wiklander     size_t processed = 0;
299*32b31808SJens Wiklander 
300*32b31808SJens Wiklander     for (;
301*32b31808SJens Wiklander          len >= SHA256_BLOCK_SIZE;
302*32b31808SJens Wiklander          processed += SHA256_BLOCK_SIZE,
303*32b31808SJens Wiklander          msg += SHA256_BLOCK_SIZE,
304*32b31808SJens Wiklander          len -= SHA256_BLOCK_SIZE) {
305*32b31808SJens Wiklander         uint32x4_t tmp, abcd_prev;
306*32b31808SJens Wiklander 
307*32b31808SJens Wiklander         uint32x4_t abcd_orig = abcd;
308*32b31808SJens Wiklander         uint32x4_t efgh_orig = efgh;
309*32b31808SJens Wiklander 
310*32b31808SJens Wiklander         uint32x4_t sched0 = (uint32x4_t) vld1q_u8(msg + 16 * 0);
311*32b31808SJens Wiklander         uint32x4_t sched1 = (uint32x4_t) vld1q_u8(msg + 16 * 1);
312*32b31808SJens Wiklander         uint32x4_t sched2 = (uint32x4_t) vld1q_u8(msg + 16 * 2);
313*32b31808SJens Wiklander         uint32x4_t sched3 = (uint32x4_t) vld1q_u8(msg + 16 * 3);
314*32b31808SJens Wiklander 
315*32b31808SJens Wiklander #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* Will be true if not defined */
316*32b31808SJens Wiklander                                                /* Untested on BE */
317*32b31808SJens Wiklander         sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0)));
318*32b31808SJens Wiklander         sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1)));
319*32b31808SJens Wiklander         sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2)));
320*32b31808SJens Wiklander         sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3)));
321*32b31808SJens Wiklander #endif
322*32b31808SJens Wiklander 
323*32b31808SJens Wiklander         /* Rounds 0 to 3 */
324*32b31808SJens Wiklander         tmp = vaddq_u32(sched0, vld1q_u32(&K[0]));
325*32b31808SJens Wiklander         abcd_prev = abcd;
326*32b31808SJens Wiklander         abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
327*32b31808SJens Wiklander         efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
328*32b31808SJens Wiklander 
329*32b31808SJens Wiklander         /* Rounds 4 to 7 */
330*32b31808SJens Wiklander         tmp = vaddq_u32(sched1, vld1q_u32(&K[4]));
331*32b31808SJens Wiklander         abcd_prev = abcd;
332*32b31808SJens Wiklander         abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
333*32b31808SJens Wiklander         efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
334*32b31808SJens Wiklander 
335*32b31808SJens Wiklander         /* Rounds 8 to 11 */
336*32b31808SJens Wiklander         tmp = vaddq_u32(sched2, vld1q_u32(&K[8]));
337*32b31808SJens Wiklander         abcd_prev = abcd;
338*32b31808SJens Wiklander         abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
339*32b31808SJens Wiklander         efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
340*32b31808SJens Wiklander 
341*32b31808SJens Wiklander         /* Rounds 12 to 15 */
342*32b31808SJens Wiklander         tmp = vaddq_u32(sched3, vld1q_u32(&K[12]));
343*32b31808SJens Wiklander         abcd_prev = abcd;
344*32b31808SJens Wiklander         abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
345*32b31808SJens Wiklander         efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
346*32b31808SJens Wiklander 
347*32b31808SJens Wiklander         for (int t = 16; t < 64; t += 16) {
348*32b31808SJens Wiklander             /* Rounds t to t + 3 */
349*32b31808SJens Wiklander             sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3);
350*32b31808SJens Wiklander             tmp = vaddq_u32(sched0, vld1q_u32(&K[t]));
351*32b31808SJens Wiklander             abcd_prev = abcd;
352*32b31808SJens Wiklander             abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
353*32b31808SJens Wiklander             efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
354*32b31808SJens Wiklander 
355*32b31808SJens Wiklander             /* Rounds t + 4 to t + 7 */
356*32b31808SJens Wiklander             sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0);
357*32b31808SJens Wiklander             tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4]));
358*32b31808SJens Wiklander             abcd_prev = abcd;
359*32b31808SJens Wiklander             abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
360*32b31808SJens Wiklander             efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
361*32b31808SJens Wiklander 
362*32b31808SJens Wiklander             /* Rounds t + 8 to t + 11 */
363*32b31808SJens Wiklander             sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1);
364*32b31808SJens Wiklander             tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8]));
365*32b31808SJens Wiklander             abcd_prev = abcd;
366*32b31808SJens Wiklander             abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
367*32b31808SJens Wiklander             efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
368*32b31808SJens Wiklander 
369*32b31808SJens Wiklander             /* Rounds t + 12 to t + 15 */
370*32b31808SJens Wiklander             sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2);
371*32b31808SJens Wiklander             tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12]));
372*32b31808SJens Wiklander             abcd_prev = abcd;
373*32b31808SJens Wiklander             abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
374*32b31808SJens Wiklander             efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
375*32b31808SJens Wiklander         }
376*32b31808SJens Wiklander 
377*32b31808SJens Wiklander         abcd = vaddq_u32(abcd, abcd_orig);
378*32b31808SJens Wiklander         efgh = vaddq_u32(efgh, efgh_orig);
379*32b31808SJens Wiklander     }
380*32b31808SJens Wiklander 
381*32b31808SJens Wiklander     vst1q_u32(&ctx->state[0], abcd);
382*32b31808SJens Wiklander     vst1q_u32(&ctx->state[4], efgh);
383*32b31808SJens Wiklander 
384*32b31808SJens Wiklander     return processed;
385*32b31808SJens Wiklander }
386*32b31808SJens Wiklander 
387*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
388*32b31808SJens Wiklander /*
389*32b31808SJens Wiklander  * This function is for internal use only if we are building both C and A64
390*32b31808SJens Wiklander  * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
391*32b31808SJens Wiklander  */
392*32b31808SJens Wiklander static
393*32b31808SJens Wiklander #endif
394*32b31808SJens Wiklander int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,
395*32b31808SJens Wiklander                                                const unsigned char data[SHA256_BLOCK_SIZE])
396*32b31808SJens Wiklander {
397*32b31808SJens Wiklander     return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data,
398*32b31808SJens Wiklander                                                             SHA256_BLOCK_SIZE) ==
399*32b31808SJens Wiklander             SHA256_BLOCK_SIZE) ? 0 : -1;
400*32b31808SJens Wiklander }
401*32b31808SJens Wiklander 
402*32b31808SJens Wiklander #if defined(MBEDTLS_POP_TARGET_PRAGMA)
403*32b31808SJens Wiklander #if defined(__clang__)
404*32b31808SJens Wiklander #pragma clang attribute pop
405*32b31808SJens Wiklander #elif defined(__GNUC__)
406*32b31808SJens Wiklander #pragma GCC pop_options
407*32b31808SJens Wiklander #endif
408*32b31808SJens Wiklander #undef MBEDTLS_POP_TARGET_PRAGMA
409*32b31808SJens Wiklander #endif
410*32b31808SJens Wiklander 
411*32b31808SJens Wiklander #endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
412*32b31808SJens Wiklander 
413*32b31808SJens Wiklander #if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
414*32b31808SJens Wiklander #define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many
415*32b31808SJens Wiklander #define mbedtls_internal_sha256_process_c      mbedtls_internal_sha256_process
416*32b31808SJens Wiklander #endif
417*32b31808SJens Wiklander 
418*32b31808SJens Wiklander 
419*32b31808SJens Wiklander #if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \
420*32b31808SJens Wiklander     !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
421*32b31808SJens Wiklander 
4225b25c76aSJerome Forissier #define  SHR(x, n) (((x) & 0xFFFFFFFF) >> (n))
4235b25c76aSJerome Forissier #define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n))))
424817466cbSJens Wiklander 
425817466cbSJens Wiklander #define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^  SHR(x, 3))
426817466cbSJens Wiklander #define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^  SHR(x, 10))
427817466cbSJens Wiklander 
428817466cbSJens Wiklander #define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
429817466cbSJens Wiklander #define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
430817466cbSJens Wiklander 
4315b25c76aSJerome Forissier #define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
4325b25c76aSJerome Forissier #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
433817466cbSJens Wiklander 
434817466cbSJens Wiklander #define R(t)                                                        \
435817466cbSJens Wiklander     (                                                               \
4367901324dSJerome Forissier         local.W[t] = S1(local.W[(t) -  2]) + local.W[(t) -  7] +    \
4377901324dSJerome Forissier                      S0(local.W[(t) - 15]) + local.W[(t) - 16]      \
438817466cbSJens Wiklander     )
439817466cbSJens Wiklander 
440817466cbSJens Wiklander #define P(a, b, c, d, e, f, g, h, x, K)                                      \
4415b25c76aSJerome Forissier     do                                                              \
442817466cbSJens Wiklander     {                                                               \
4437901324dSJerome Forissier         local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x);    \
4447901324dSJerome Forissier         local.temp2 = S2(a) + F0((a), (b), (c));                      \
4457901324dSJerome Forissier         (d) += local.temp1; (h) = local.temp1 + local.temp2;        \
4465b25c76aSJerome Forissier     } while (0)
447817466cbSJens Wiklander 
448*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
449*32b31808SJens Wiklander /*
450*32b31808SJens Wiklander  * This function is for internal use only if we are building both C and A64
451*32b31808SJens Wiklander  * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
452*32b31808SJens Wiklander  */
453*32b31808SJens Wiklander static
454*32b31808SJens Wiklander #endif
455*32b31808SJens Wiklander int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx,
456*32b31808SJens Wiklander                                       const unsigned char data[SHA256_BLOCK_SIZE])
457817466cbSJens Wiklander {
458*32b31808SJens Wiklander     struct {
459817466cbSJens Wiklander         uint32_t temp1, temp2, W[64];
460817466cbSJens Wiklander         uint32_t A[8];
4617901324dSJerome Forissier     } local;
4627901324dSJerome Forissier 
463817466cbSJens Wiklander     unsigned int i;
464817466cbSJens Wiklander 
465*32b31808SJens Wiklander     for (i = 0; i < 8; i++) {
4667901324dSJerome Forissier         local.A[i] = ctx->state[i];
467*32b31808SJens Wiklander     }
468817466cbSJens Wiklander 
469817466cbSJens Wiklander #if defined(MBEDTLS_SHA256_SMALLER)
470*32b31808SJens Wiklander     for (i = 0; i < 64; i++) {
471*32b31808SJens Wiklander         if (i < 16) {
472039e02dfSJerome Forissier             local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);
473*32b31808SJens Wiklander         } else {
474817466cbSJens Wiklander             R(i);
475*32b31808SJens Wiklander         }
476817466cbSJens Wiklander 
4777901324dSJerome Forissier         P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
4787901324dSJerome Forissier           local.A[5], local.A[6], local.A[7], local.W[i], K[i]);
479817466cbSJens Wiklander 
4807901324dSJerome Forissier         local.temp1 = local.A[7]; local.A[7] = local.A[6];
4817901324dSJerome Forissier         local.A[6] = local.A[5]; local.A[5] = local.A[4];
4827901324dSJerome Forissier         local.A[4] = local.A[3]; local.A[3] = local.A[2];
4837901324dSJerome Forissier         local.A[2] = local.A[1]; local.A[1] = local.A[0];
4847901324dSJerome Forissier         local.A[0] = local.temp1;
485817466cbSJens Wiklander     }
486817466cbSJens Wiklander #else /* MBEDTLS_SHA256_SMALLER */
487*32b31808SJens Wiklander     for (i = 0; i < 16; i++) {
488039e02dfSJerome Forissier         local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);
489*32b31808SJens Wiklander     }
490817466cbSJens Wiklander 
491*32b31808SJens Wiklander     for (i = 0; i < 16; i += 8) {
4927901324dSJerome Forissier         P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
4937901324dSJerome Forissier           local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0]);
4947901324dSJerome Forissier         P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
4957901324dSJerome Forissier           local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1]);
4967901324dSJerome Forissier         P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
4977901324dSJerome Forissier           local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2]);
4987901324dSJerome Forissier         P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
4997901324dSJerome Forissier           local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3]);
5007901324dSJerome Forissier         P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
5017901324dSJerome Forissier           local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4]);
5027901324dSJerome Forissier         P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
5037901324dSJerome Forissier           local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5]);
5047901324dSJerome Forissier         P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
5057901324dSJerome Forissier           local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6]);
5067901324dSJerome Forissier         P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
5077901324dSJerome Forissier           local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7]);
508817466cbSJens Wiklander     }
509817466cbSJens Wiklander 
510*32b31808SJens Wiklander     for (i = 16; i < 64; i += 8) {
5117901324dSJerome Forissier         P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
5127901324dSJerome Forissier           local.A[5], local.A[6], local.A[7], R(i+0), K[i+0]);
5137901324dSJerome Forissier         P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
5147901324dSJerome Forissier           local.A[4], local.A[5], local.A[6], R(i+1), K[i+1]);
5157901324dSJerome Forissier         P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
5167901324dSJerome Forissier           local.A[3], local.A[4], local.A[5], R(i+2), K[i+2]);
5177901324dSJerome Forissier         P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
5187901324dSJerome Forissier           local.A[2], local.A[3], local.A[4], R(i+3), K[i+3]);
5197901324dSJerome Forissier         P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
5207901324dSJerome Forissier           local.A[1], local.A[2], local.A[3], R(i+4), K[i+4]);
5217901324dSJerome Forissier         P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
5227901324dSJerome Forissier           local.A[0], local.A[1], local.A[2], R(i+5), K[i+5]);
5237901324dSJerome Forissier         P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
5247901324dSJerome Forissier           local.A[7], local.A[0], local.A[1], R(i+6), K[i+6]);
5257901324dSJerome Forissier         P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
5267901324dSJerome Forissier           local.A[6], local.A[7], local.A[0], R(i+7), K[i+7]);
527817466cbSJens Wiklander     }
528817466cbSJens Wiklander #endif /* MBEDTLS_SHA256_SMALLER */
529817466cbSJens Wiklander 
530*32b31808SJens Wiklander     for (i = 0; i < 8; i++) {
5317901324dSJerome Forissier         ctx->state[i] += local.A[i];
532*32b31808SJens Wiklander     }
5337901324dSJerome Forissier 
5347901324dSJerome Forissier     /* Zeroise buffers and variables to clear sensitive data from memory. */
5357901324dSJerome Forissier     mbedtls_platform_zeroize(&local, sizeof(local));
5363d3b0591SJens Wiklander 
537*32b31808SJens Wiklander     return 0;
538817466cbSJens Wiklander }
5393d3b0591SJens Wiklander 
540*32b31808SJens Wiklander #endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
541*32b31808SJens Wiklander 
542*32b31808SJens Wiklander 
543*32b31808SJens Wiklander #if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
544*32b31808SJens Wiklander 
545*32b31808SJens Wiklander static size_t mbedtls_internal_sha256_process_many_c(
546*32b31808SJens Wiklander     mbedtls_sha256_context *ctx, const uint8_t *data, size_t len)
5473d3b0591SJens Wiklander {
548*32b31808SJens Wiklander     size_t processed = 0;
549*32b31808SJens Wiklander 
550*32b31808SJens Wiklander     while (len >= SHA256_BLOCK_SIZE) {
551*32b31808SJens Wiklander         if (mbedtls_internal_sha256_process_c(ctx, data) != 0) {
552*32b31808SJens Wiklander             return 0;
5533d3b0591SJens Wiklander         }
554*32b31808SJens Wiklander 
555*32b31808SJens Wiklander         data += SHA256_BLOCK_SIZE;
556*32b31808SJens Wiklander         len  -= SHA256_BLOCK_SIZE;
557*32b31808SJens Wiklander 
558*32b31808SJens Wiklander         processed += SHA256_BLOCK_SIZE;
559*32b31808SJens Wiklander     }
560*32b31808SJens Wiklander 
561*32b31808SJens Wiklander     return processed;
562*32b31808SJens Wiklander }
563*32b31808SJens Wiklander 
564*32b31808SJens Wiklander #endif /* !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
565*32b31808SJens Wiklander 
566*32b31808SJens Wiklander 
567*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
568*32b31808SJens Wiklander 
569*32b31808SJens Wiklander static int mbedtls_a64_crypto_sha256_has_support(void)
570*32b31808SJens Wiklander {
571*32b31808SJens Wiklander     static int done = 0;
572*32b31808SJens Wiklander     static int supported = 0;
573*32b31808SJens Wiklander 
574*32b31808SJens Wiklander     if (!done) {
575*32b31808SJens Wiklander         supported = mbedtls_a64_crypto_sha256_determine_support();
576*32b31808SJens Wiklander         done = 1;
577*32b31808SJens Wiklander     }
578*32b31808SJens Wiklander 
579*32b31808SJens Wiklander     return supported;
580*32b31808SJens Wiklander }
581*32b31808SJens Wiklander 
582*32b31808SJens Wiklander static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx,
583*32b31808SJens Wiklander                                                    const uint8_t *msg, size_t len)
584*32b31808SJens Wiklander {
585*32b31808SJens Wiklander     if (mbedtls_a64_crypto_sha256_has_support()) {
586*32b31808SJens Wiklander         return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len);
587*32b31808SJens Wiklander     } else {
588*32b31808SJens Wiklander         return mbedtls_internal_sha256_process_many_c(ctx, msg, len);
589*32b31808SJens Wiklander     }
590*32b31808SJens Wiklander }
591*32b31808SJens Wiklander 
592*32b31808SJens Wiklander int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,
593*32b31808SJens Wiklander                                     const unsigned char data[SHA256_BLOCK_SIZE])
594*32b31808SJens Wiklander {
595*32b31808SJens Wiklander     if (mbedtls_a64_crypto_sha256_has_support()) {
596*32b31808SJens Wiklander         return mbedtls_internal_sha256_process_a64_crypto(ctx, data);
597*32b31808SJens Wiklander     } else {
598*32b31808SJens Wiklander         return mbedtls_internal_sha256_process_c(ctx, data);
599*32b31808SJens Wiklander     }
600*32b31808SJens Wiklander }
601*32b31808SJens Wiklander 
602*32b31808SJens Wiklander #endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
603*32b31808SJens Wiklander 
604817466cbSJens Wiklander 
605817466cbSJens Wiklander /*
606817466cbSJens Wiklander  * SHA-256 process buffer
607817466cbSJens Wiklander  */
608*32b31808SJens Wiklander int mbedtls_sha256_update(mbedtls_sha256_context *ctx,
6093d3b0591SJens Wiklander                           const unsigned char *input,
610817466cbSJens Wiklander                           size_t ilen)
611817466cbSJens Wiklander {
61211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
613817466cbSJens Wiklander     size_t fill;
614817466cbSJens Wiklander     uint32_t left;
615817466cbSJens Wiklander 
616*32b31808SJens Wiklander     if (ilen == 0) {
617*32b31808SJens Wiklander         return 0;
618*32b31808SJens Wiklander     }
619817466cbSJens Wiklander 
620817466cbSJens Wiklander     left = ctx->total[0] & 0x3F;
621*32b31808SJens Wiklander     fill = SHA256_BLOCK_SIZE - left;
622817466cbSJens Wiklander 
623817466cbSJens Wiklander     ctx->total[0] += (uint32_t) ilen;
624817466cbSJens Wiklander     ctx->total[0] &= 0xFFFFFFFF;
625817466cbSJens Wiklander 
626*32b31808SJens Wiklander     if (ctx->total[0] < (uint32_t) ilen) {
627817466cbSJens Wiklander         ctx->total[1]++;
628*32b31808SJens Wiklander     }
629817466cbSJens Wiklander 
630*32b31808SJens Wiklander     if (left && ilen >= fill) {
631817466cbSJens Wiklander         memcpy((void *) (ctx->buffer + left), input, fill);
6323d3b0591SJens Wiklander 
633*32b31808SJens Wiklander         if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
634*32b31808SJens Wiklander             return ret;
635*32b31808SJens Wiklander         }
6363d3b0591SJens Wiklander 
637817466cbSJens Wiklander         input += fill;
638817466cbSJens Wiklander         ilen  -= fill;
639817466cbSJens Wiklander         left = 0;
640817466cbSJens Wiklander     }
641817466cbSJens Wiklander 
642*32b31808SJens Wiklander     while (ilen >= SHA256_BLOCK_SIZE) {
643*32b31808SJens Wiklander         size_t processed =
644*32b31808SJens Wiklander             mbedtls_internal_sha256_process_many(ctx, input, ilen);
645*32b31808SJens Wiklander         if (processed < SHA256_BLOCK_SIZE) {
646*32b31808SJens Wiklander             return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
647817466cbSJens Wiklander         }
648817466cbSJens Wiklander 
649*32b31808SJens Wiklander         input += processed;
650*32b31808SJens Wiklander         ilen  -= processed;
651*32b31808SJens Wiklander     }
652*32b31808SJens Wiklander 
653*32b31808SJens Wiklander     if (ilen > 0) {
654817466cbSJens Wiklander         memcpy((void *) (ctx->buffer + left), input, ilen);
655817466cbSJens Wiklander     }
656817466cbSJens Wiklander 
657*32b31808SJens Wiklander     return 0;
6583d3b0591SJens Wiklander }
659817466cbSJens Wiklander 
660817466cbSJens Wiklander /*
661817466cbSJens Wiklander  * SHA-256 final digest
662817466cbSJens Wiklander  */
663*32b31808SJens Wiklander int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
664*32b31808SJens Wiklander                           unsigned char *output)
665817466cbSJens Wiklander {
66611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
6673d3b0591SJens Wiklander     uint32_t used;
668817466cbSJens Wiklander     uint32_t high, low;
669817466cbSJens Wiklander 
6703d3b0591SJens Wiklander     /*
6713d3b0591SJens Wiklander      * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
6723d3b0591SJens Wiklander      */
6733d3b0591SJens Wiklander     used = ctx->total[0] & 0x3F;
6743d3b0591SJens Wiklander 
6753d3b0591SJens Wiklander     ctx->buffer[used++] = 0x80;
6763d3b0591SJens Wiklander 
677*32b31808SJens Wiklander     if (used <= 56) {
6783d3b0591SJens Wiklander         /* Enough room for padding + length in current block */
6793d3b0591SJens Wiklander         memset(ctx->buffer + used, 0, 56 - used);
680*32b31808SJens Wiklander     } else {
6813d3b0591SJens Wiklander         /* We'll need an extra block */
682*32b31808SJens Wiklander         memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used);
6833d3b0591SJens Wiklander 
684*32b31808SJens Wiklander         if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
685*32b31808SJens Wiklander             return ret;
686*32b31808SJens Wiklander         }
6873d3b0591SJens Wiklander 
6883d3b0591SJens Wiklander         memset(ctx->buffer, 0, 56);
6893d3b0591SJens Wiklander     }
6903d3b0591SJens Wiklander 
6913d3b0591SJens Wiklander     /*
6923d3b0591SJens Wiklander      * Add message length
6933d3b0591SJens Wiklander      */
694817466cbSJens Wiklander     high = (ctx->total[0] >> 29)
695817466cbSJens Wiklander            | (ctx->total[1] <<  3);
696817466cbSJens Wiklander     low  = (ctx->total[0] <<  3);
697817466cbSJens Wiklander 
698039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56);
699039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(low,  ctx->buffer, 60);
700817466cbSJens Wiklander 
701*32b31808SJens Wiklander     if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
702*32b31808SJens Wiklander         return ret;
703*32b31808SJens Wiklander     }
704817466cbSJens Wiklander 
7053d3b0591SJens Wiklander     /*
7063d3b0591SJens Wiklander      * Output final state
7073d3b0591SJens Wiklander      */
708039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[0], output,  0);
709039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[1], output,  4);
710039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[2], output,  8);
711039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12);
712039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16);
713039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20);
714039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24);
715817466cbSJens Wiklander 
716*32b31808SJens Wiklander     int truncated = 0;
717*32b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
718*32b31808SJens Wiklander     truncated = ctx->is224;
7193d3b0591SJens Wiklander #endif
720*32b31808SJens Wiklander     if (!truncated) {
721*32b31808SJens Wiklander         MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28);
722*32b31808SJens Wiklander     }
723*32b31808SJens Wiklander 
724*32b31808SJens Wiklander     return 0;
725*32b31808SJens Wiklander }
7263d3b0591SJens Wiklander 
727817466cbSJens Wiklander #endif /* !MBEDTLS_SHA256_ALT */
728817466cbSJens Wiklander 
729817466cbSJens Wiklander /*
730817466cbSJens Wiklander  * output = SHA-256( input buffer )
731817466cbSJens Wiklander  */
732*32b31808SJens Wiklander int mbedtls_sha256(const unsigned char *input,
7333d3b0591SJens Wiklander                    size_t ilen,
734*32b31808SJens Wiklander                    unsigned char *output,
7353d3b0591SJens Wiklander                    int is224)
736817466cbSJens Wiklander {
73711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
738817466cbSJens Wiklander     mbedtls_sha256_context ctx;
739817466cbSJens Wiklander 
740*32b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
741*32b31808SJens Wiklander     if (is224 != 0 && is224 != 1) {
742*32b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
743*32b31808SJens Wiklander     }
744*32b31808SJens Wiklander #elif defined(MBEDTLS_SHA256_C)
745*32b31808SJens Wiklander     if (is224 != 0) {
746*32b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
747*32b31808SJens Wiklander     }
748*32b31808SJens Wiklander #else /* defined MBEDTLS_SHA224_C only */
749*32b31808SJens Wiklander     if (is224 == 0) {
750*32b31808SJens Wiklander         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
751*32b31808SJens Wiklander     }
752*32b31808SJens Wiklander #endif
7533d3b0591SJens Wiklander 
754817466cbSJens Wiklander     mbedtls_sha256_init(&ctx);
7553d3b0591SJens Wiklander 
756*32b31808SJens Wiklander     if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {
7573d3b0591SJens Wiklander         goto exit;
758*32b31808SJens Wiklander     }
7593d3b0591SJens Wiklander 
760*32b31808SJens Wiklander     if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) {
7613d3b0591SJens Wiklander         goto exit;
762*32b31808SJens Wiklander     }
7633d3b0591SJens Wiklander 
764*32b31808SJens Wiklander     if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) {
7653d3b0591SJens Wiklander         goto exit;
766*32b31808SJens Wiklander     }
7673d3b0591SJens Wiklander 
7683d3b0591SJens Wiklander exit:
769817466cbSJens Wiklander     mbedtls_sha256_free(&ctx);
7703d3b0591SJens Wiklander 
771*32b31808SJens Wiklander     return ret;
772817466cbSJens Wiklander }
773817466cbSJens Wiklander 
774817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
775817466cbSJens Wiklander /*
776817466cbSJens Wiklander  * FIPS-180-2 test vectors
777817466cbSJens Wiklander  */
778*32b31808SJens Wiklander static const unsigned char sha_test_buf[3][57] =
779817466cbSJens Wiklander {
780817466cbSJens Wiklander     { "abc" },
781817466cbSJens Wiklander     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
782817466cbSJens Wiklander     { "" }
783817466cbSJens Wiklander };
784817466cbSJens Wiklander 
785*32b31808SJens Wiklander static const size_t sha_test_buflen[3] =
786817466cbSJens Wiklander {
787817466cbSJens Wiklander     3, 56, 1000
788817466cbSJens Wiklander };
789817466cbSJens Wiklander 
790*32b31808SJens Wiklander typedef const unsigned char (sha_test_sum_t)[32];
791*32b31808SJens Wiklander 
792817466cbSJens Wiklander /*
793817466cbSJens Wiklander  * SHA-224 test vectors
794817466cbSJens Wiklander  */
795*32b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
796*32b31808SJens Wiklander static sha_test_sum_t sha224_test_sum[] =
797*32b31808SJens Wiklander {
798817466cbSJens Wiklander     { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
799817466cbSJens Wiklander       0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
800817466cbSJens Wiklander       0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
801817466cbSJens Wiklander       0xE3, 0x6C, 0x9D, 0xA7 },
802817466cbSJens Wiklander     { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
803817466cbSJens Wiklander       0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
804817466cbSJens Wiklander       0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
805817466cbSJens Wiklander       0x52, 0x52, 0x25, 0x25 },
806817466cbSJens Wiklander     { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
807817466cbSJens Wiklander       0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
808817466cbSJens Wiklander       0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
809*32b31808SJens Wiklander       0x4E, 0xE7, 0xAD, 0x67 }
810*32b31808SJens Wiklander };
811*32b31808SJens Wiklander #endif
812817466cbSJens Wiklander 
813817466cbSJens Wiklander /*
814817466cbSJens Wiklander  * SHA-256 test vectors
815817466cbSJens Wiklander  */
816*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C)
817*32b31808SJens Wiklander static sha_test_sum_t sha256_test_sum[] =
818*32b31808SJens Wiklander {
819817466cbSJens Wiklander     { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
820817466cbSJens Wiklander       0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
821817466cbSJens Wiklander       0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
822817466cbSJens Wiklander       0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
823817466cbSJens Wiklander     { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
824817466cbSJens Wiklander       0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
825817466cbSJens Wiklander       0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
826817466cbSJens Wiklander       0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
827817466cbSJens Wiklander     { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
828817466cbSJens Wiklander       0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
829817466cbSJens Wiklander       0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
830817466cbSJens Wiklander       0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
831817466cbSJens Wiklander };
832*32b31808SJens Wiklander #endif
833817466cbSJens Wiklander 
834817466cbSJens Wiklander /*
835817466cbSJens Wiklander  * Checkup routine
836817466cbSJens Wiklander  */
837*32b31808SJens Wiklander static int mbedtls_sha256_common_self_test(int verbose, int is224)
838817466cbSJens Wiklander {
839*32b31808SJens Wiklander     int i, buflen, ret = 0;
840817466cbSJens Wiklander     unsigned char *buf;
841817466cbSJens Wiklander     unsigned char sha256sum[32];
842817466cbSJens Wiklander     mbedtls_sha256_context ctx;
843817466cbSJens Wiklander 
844*32b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
845*32b31808SJens Wiklander     sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum;
846*32b31808SJens Wiklander #elif defined(MBEDTLS_SHA256_C)
847*32b31808SJens Wiklander     sha_test_sum_t *sha_test_sum = sha256_test_sum;
848*32b31808SJens Wiklander #else
849*32b31808SJens Wiklander     sha_test_sum_t *sha_test_sum = sha224_test_sum;
850*32b31808SJens Wiklander #endif
851817466cbSJens Wiklander 
852*32b31808SJens Wiklander     buf = mbedtls_calloc(1024, sizeof(unsigned char));
853*32b31808SJens Wiklander     if (NULL == buf) {
854*32b31808SJens Wiklander         if (verbose != 0) {
855*32b31808SJens Wiklander             mbedtls_printf("Buffer allocation failed\n");
856*32b31808SJens Wiklander         }
857*32b31808SJens Wiklander 
858*32b31808SJens Wiklander         return 1;
859817466cbSJens Wiklander     }
860817466cbSJens Wiklander 
861817466cbSJens Wiklander     mbedtls_sha256_init(&ctx);
862817466cbSJens Wiklander 
863*32b31808SJens Wiklander     for (i = 0; i < 3; i++) {
864*32b31808SJens Wiklander         if (verbose != 0) {
865*32b31808SJens Wiklander             mbedtls_printf("  SHA-%d test #%d: ", 256 - is224 * 32, i + 1);
866*32b31808SJens Wiklander         }
867817466cbSJens Wiklander 
868*32b31808SJens Wiklander         if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {
8693d3b0591SJens Wiklander             goto fail;
870*32b31808SJens Wiklander         }
871817466cbSJens Wiklander 
872*32b31808SJens Wiklander         if (i == 2) {
873817466cbSJens Wiklander             memset(buf, 'a', buflen = 1000);
874817466cbSJens Wiklander 
875*32b31808SJens Wiklander             for (int j = 0; j < 1000; j++) {
876*32b31808SJens Wiklander                 ret = mbedtls_sha256_update(&ctx, buf, buflen);
877*32b31808SJens Wiklander                 if (ret != 0) {
878*32b31808SJens Wiklander                     goto fail;
879*32b31808SJens Wiklander                 }
880*32b31808SJens Wiklander             }
881*32b31808SJens Wiklander 
882*32b31808SJens Wiklander         } else {
883*32b31808SJens Wiklander             ret = mbedtls_sha256_update(&ctx, sha_test_buf[i],
884*32b31808SJens Wiklander                                         sha_test_buflen[i]);
885*32b31808SJens Wiklander             if (ret != 0) {
886*32b31808SJens Wiklander                 goto fail;
887*32b31808SJens Wiklander             }
888*32b31808SJens Wiklander         }
889*32b31808SJens Wiklander 
890*32b31808SJens Wiklander         if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) {
8913d3b0591SJens Wiklander             goto fail;
8923d3b0591SJens Wiklander         }
8933d3b0591SJens Wiklander 
894817466cbSJens Wiklander 
895*32b31808SJens Wiklander         if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 4) != 0) {
896817466cbSJens Wiklander             ret = 1;
8973d3b0591SJens Wiklander             goto fail;
898817466cbSJens Wiklander         }
899817466cbSJens Wiklander 
900*32b31808SJens Wiklander         if (verbose != 0) {
901817466cbSJens Wiklander             mbedtls_printf("passed\n");
902817466cbSJens Wiklander         }
903*32b31808SJens Wiklander     }
904817466cbSJens Wiklander 
905*32b31808SJens Wiklander     if (verbose != 0) {
906817466cbSJens Wiklander         mbedtls_printf("\n");
907*32b31808SJens Wiklander     }
908817466cbSJens Wiklander 
9093d3b0591SJens Wiklander     goto exit;
9103d3b0591SJens Wiklander 
9113d3b0591SJens Wiklander fail:
912*32b31808SJens Wiklander     if (verbose != 0) {
9133d3b0591SJens Wiklander         mbedtls_printf("failed\n");
914*32b31808SJens Wiklander     }
9153d3b0591SJens Wiklander 
916817466cbSJens Wiklander exit:
917817466cbSJens Wiklander     mbedtls_sha256_free(&ctx);
918817466cbSJens Wiklander     mbedtls_free(buf);
919817466cbSJens Wiklander 
920*32b31808SJens Wiklander     return ret;
921817466cbSJens Wiklander }
922817466cbSJens Wiklander 
923*32b31808SJens Wiklander #if defined(MBEDTLS_SHA256_C)
924*32b31808SJens Wiklander int mbedtls_sha256_self_test(int verbose)
925*32b31808SJens Wiklander {
926*32b31808SJens Wiklander     return mbedtls_sha256_common_self_test(verbose, 0);
927*32b31808SJens Wiklander }
928*32b31808SJens Wiklander #endif /* MBEDTLS_SHA256_C */
929*32b31808SJens Wiklander 
930*32b31808SJens Wiklander #if defined(MBEDTLS_SHA224_C)
931*32b31808SJens Wiklander int mbedtls_sha224_self_test(int verbose)
932*32b31808SJens Wiklander {
933*32b31808SJens Wiklander     return mbedtls_sha256_common_self_test(verbose, 1);
934*32b31808SJens Wiklander }
935*32b31808SJens Wiklander #endif /* MBEDTLS_SHA224_C */
936*32b31808SJens Wiklander 
937817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
938817466cbSJens Wiklander 
939*32b31808SJens Wiklander #endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */
940