1// Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include <string.h> 16 17#include <openssl/mem.h> 18#include <openssl/span.h> 19 20#include "../../internal.h" 21#include "../bcm_interface.h" 22#include "../digest/md32_common.h" 23#include "../service_indicator/internal.h" 24#include "internal.h" 25 26 27bcm_infallible BCM_sha224_init(SHA256_CTX *sha) { 28 OPENSSL_memset(sha, 0, sizeof(SHA256_CTX)); 29 sha->h[0] = 0xc1059ed8UL; 30 sha->h[1] = 0x367cd507UL; 31 sha->h[2] = 0x3070dd17UL; 32 sha->h[3] = 0xf70e5939UL; 33 sha->h[4] = 0xffc00b31UL; 34 sha->h[5] = 0x68581511UL; 35 sha->h[6] = 0x64f98fa7UL; 36 sha->h[7] = 0xbefa4fa4UL; 37 sha->md_len = BCM_SHA224_DIGEST_LENGTH; 38 return bcm_infallible::approved; 39} 40 41bcm_infallible BCM_sha256_init(SHA256_CTX *sha) { 42 OPENSSL_memset(sha, 0, sizeof(SHA256_CTX)); 43 sha->h[0] = 0x6a09e667UL; 44 sha->h[1] = 0xbb67ae85UL; 45 sha->h[2] = 0x3c6ef372UL; 46 sha->h[3] = 0xa54ff53aUL; 47 sha->h[4] = 0x510e527fUL; 48 sha->h[5] = 0x9b05688cUL; 49 sha->h[6] = 0x1f83d9abUL; 50 sha->h[7] = 0x5be0cd19UL; 51 sha->md_len = BCM_SHA256_DIGEST_LENGTH; 52 return bcm_infallible::approved; 53} 54 55#if !defined(SHA256_ASM) 56static void sha256_block_data_order(uint32_t state[8], const uint8_t *in, 57 size_t num); 58#endif 59 60bcm_infallible BCM_sha256_transform(SHA256_CTX *c, 61 const uint8_t data[BCM_SHA256_CBLOCK]) { 62 sha256_block_data_order(c->h, data, 1); 63 return bcm_infallible::approved; 64} 65 66namespace { 67struct SHA256Traits { 68 using HashContext = SHA256_CTX; 69 static constexpr size_t kBlockSize = BCM_SHA256_CBLOCK; 70 static constexpr bool kLengthIsBigEndian = true; 71 static void HashBlocks(uint32_t *state, const uint8_t *data, 72 size_t num_blocks) { 73 sha256_block_data_order(state, data, num_blocks); 74 } 75}; 76} // namespace 77 78bcm_infallible BCM_sha256_update(SHA256_CTX *c, const void *data, size_t len) { 79 bssl::crypto_md32_update<SHA256Traits>( 80 c, bssl::Span(static_cast<const uint8_t *>(data), len)); 81 return bcm_infallible::approved; 82} 83 84bcm_infallible BCM_sha224_update(SHA256_CTX *ctx, const void *data, 85 size_t len) { 86 return BCM_sha256_update(ctx, data, len); 87} 88 89static void sha256_final_impl(uint8_t *out, size_t md_len, SHA256_CTX *c) { 90 bssl::crypto_md32_final<SHA256Traits>(c); 91 92 BSSL_CHECK(md_len <= BCM_SHA256_DIGEST_LENGTH); 93 94 assert(md_len % 4 == 0); 95 const size_t out_words = md_len / 4; 96 for (size_t i = 0; i < out_words; i++) { 97 CRYPTO_store_u32_be(out, c->h[i]); 98 out += 4; 99 } 100 101 FIPS_service_indicator_update_state(); 102} 103 104bcm_infallible BCM_sha256_final(uint8_t out[BCM_SHA256_DIGEST_LENGTH], 105 SHA256_CTX *c) { 106 // Ideally we would assert |sha->md_len| is |BCM_SHA256_DIGEST_LENGTH| to 107 // match the size hint, but calling code often pairs |SHA224_Init| with 108 // |SHA256_Final| and expects |sha->md_len| to carry the size over. 109 // 110 // TODO(davidben): Add an assert and fix code to match them up. 111 sha256_final_impl(out, c->md_len, c); 112 return bcm_infallible::approved; 113} 114 115bcm_infallible BCM_sha224_final(uint8_t out[BCM_SHA224_DIGEST_LENGTH], 116 SHA256_CTX *ctx) { 117 // This function must be paired with |SHA224_Init|, which sets |ctx->md_len| 118 // to |BCM_SHA224_DIGEST_LENGTH|. 119 assert(ctx->md_len == BCM_SHA224_DIGEST_LENGTH); 120 sha256_final_impl(out, BCM_SHA224_DIGEST_LENGTH, ctx); 121 return bcm_infallible::approved; 122} 123 124#if !defined(SHA256_ASM) 125 126#if !defined(SHA256_ASM_NOHW) 127static const uint32_t K256[64] = { 128 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 129 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 130 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 131 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 132 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 133 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 134 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 135 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 136 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 137 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 138 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 139 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 140 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL}; 141 142// See FIPS 180-4, section 4.1.2. 143#define Sigma0(x) \ 144 (CRYPTO_rotr_u32((x), 2) ^ CRYPTO_rotr_u32((x), 13) ^ \ 145 CRYPTO_rotr_u32((x), 22)) 146#define Sigma1(x) \ 147 (CRYPTO_rotr_u32((x), 6) ^ CRYPTO_rotr_u32((x), 11) ^ \ 148 CRYPTO_rotr_u32((x), 25)) 149#define sigma0(x) \ 150 (CRYPTO_rotr_u32((x), 7) ^ CRYPTO_rotr_u32((x), 18) ^ ((x) >> 3)) 151#define sigma1(x) \ 152 (CRYPTO_rotr_u32((x), 17) ^ CRYPTO_rotr_u32((x), 19) ^ ((x) >> 10)) 153 154#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z))) 155#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 156 157#define ROUND_00_15(i, a, b, c, d, e, f, g, h) \ 158 do { \ 159 T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; \ 160 h = Sigma0(a) + Maj(a, b, c); \ 161 d += T1; \ 162 h += T1; \ 163 } while (0) 164 165#define ROUND_16_63(i, a, b, c, d, e, f, g, h, X) \ 166 do { \ 167 s0 = X[(i + 1) & 0x0f]; \ 168 s0 = sigma0(s0); \ 169 s1 = X[(i + 14) & 0x0f]; \ 170 s1 = sigma1(s1); \ 171 T1 = X[(i) & 0x0f] += s0 + s1 + X[(i + 9) & 0x0f]; \ 172 ROUND_00_15(i, a, b, c, d, e, f, g, h); \ 173 } while (0) 174 175static void sha256_block_data_order_nohw(uint32_t state[8], const uint8_t *data, 176 size_t num) { 177 uint32_t a, b, c, d, e, f, g, h, s0, s1, T1; 178 uint32_t X[16]; 179 int i; 180 181 while (num--) { 182 a = state[0]; 183 b = state[1]; 184 c = state[2]; 185 d = state[3]; 186 e = state[4]; 187 f = state[5]; 188 g = state[6]; 189 h = state[7]; 190 191 T1 = X[0] = CRYPTO_load_u32_be(data); 192 data += 4; 193 ROUND_00_15(0, a, b, c, d, e, f, g, h); 194 T1 = X[1] = CRYPTO_load_u32_be(data); 195 data += 4; 196 ROUND_00_15(1, h, a, b, c, d, e, f, g); 197 T1 = X[2] = CRYPTO_load_u32_be(data); 198 data += 4; 199 ROUND_00_15(2, g, h, a, b, c, d, e, f); 200 T1 = X[3] = CRYPTO_load_u32_be(data); 201 data += 4; 202 ROUND_00_15(3, f, g, h, a, b, c, d, e); 203 T1 = X[4] = CRYPTO_load_u32_be(data); 204 data += 4; 205 ROUND_00_15(4, e, f, g, h, a, b, c, d); 206 T1 = X[5] = CRYPTO_load_u32_be(data); 207 data += 4; 208 ROUND_00_15(5, d, e, f, g, h, a, b, c); 209 T1 = X[6] = CRYPTO_load_u32_be(data); 210 data += 4; 211 ROUND_00_15(6, c, d, e, f, g, h, a, b); 212 T1 = X[7] = CRYPTO_load_u32_be(data); 213 data += 4; 214 ROUND_00_15(7, b, c, d, e, f, g, h, a); 215 T1 = X[8] = CRYPTO_load_u32_be(data); 216 data += 4; 217 ROUND_00_15(8, a, b, c, d, e, f, g, h); 218 T1 = X[9] = CRYPTO_load_u32_be(data); 219 data += 4; 220 ROUND_00_15(9, h, a, b, c, d, e, f, g); 221 T1 = X[10] = CRYPTO_load_u32_be(data); 222 data += 4; 223 ROUND_00_15(10, g, h, a, b, c, d, e, f); 224 T1 = X[11] = CRYPTO_load_u32_be(data); 225 data += 4; 226 ROUND_00_15(11, f, g, h, a, b, c, d, e); 227 T1 = X[12] = CRYPTO_load_u32_be(data); 228 data += 4; 229 ROUND_00_15(12, e, f, g, h, a, b, c, d); 230 T1 = X[13] = CRYPTO_load_u32_be(data); 231 data += 4; 232 ROUND_00_15(13, d, e, f, g, h, a, b, c); 233 T1 = X[14] = CRYPTO_load_u32_be(data); 234 data += 4; 235 ROUND_00_15(14, c, d, e, f, g, h, a, b); 236 T1 = X[15] = CRYPTO_load_u32_be(data); 237 data += 4; 238 ROUND_00_15(15, b, c, d, e, f, g, h, a); 239 240 for (i = 16; i < 64; i += 8) { 241 ROUND_16_63(i + 0, a, b, c, d, e, f, g, h, X); 242 ROUND_16_63(i + 1, h, a, b, c, d, e, f, g, X); 243 ROUND_16_63(i + 2, g, h, a, b, c, d, e, f, X); 244 ROUND_16_63(i + 3, f, g, h, a, b, c, d, e, X); 245 ROUND_16_63(i + 4, e, f, g, h, a, b, c, d, X); 246 ROUND_16_63(i + 5, d, e, f, g, h, a, b, c, X); 247 ROUND_16_63(i + 6, c, d, e, f, g, h, a, b, X); 248 ROUND_16_63(i + 7, b, c, d, e, f, g, h, a, X); 249 } 250 251 state[0] += a; 252 state[1] += b; 253 state[2] += c; 254 state[3] += d; 255 state[4] += e; 256 state[5] += f; 257 state[6] += g; 258 state[7] += h; 259 } 260} 261 262#endif // !defined(SHA256_ASM_NOHW) 263 264static void sha256_block_data_order(uint32_t state[8], const uint8_t *data, 265 size_t num) { 266#if defined(SHA256_ASM_HW) 267 if (sha256_hw_capable()) { 268 sha256_block_data_order_hw(state, data, num); 269 return; 270 } 271#endif 272#if defined(SHA256_ASM_AVX) 273 if (sha256_avx_capable()) { 274 sha256_block_data_order_avx(state, data, num); 275 return; 276 } 277#endif 278#if defined(SHA256_ASM_SSSE3) 279 if (sha256_ssse3_capable()) { 280 sha256_block_data_order_ssse3(state, data, num); 281 return; 282 } 283#endif 284#if defined(SHA256_ASM_NEON) 285 if (CRYPTO_is_NEON_capable()) { 286 sha256_block_data_order_neon(state, data, num); 287 return; 288 } 289#endif 290 sha256_block_data_order_nohw(state, data, num); 291} 292 293#endif // !defined(SHA256_ASM) 294 295 296bcm_infallible BCM_sha256_transform_blocks(uint32_t state[8], 297 const uint8_t *data, 298 size_t num_blocks) { 299 sha256_block_data_order(state, data, num_blocks); 300 return bcm_infallible::approved; 301} 302 303#undef Sigma0 304#undef Sigma1 305#undef sigma0 306#undef sigma1 307#undef Ch 308#undef Maj 309#undef ROUND_00_15 310#undef ROUND_16_63 311