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