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