1 // SPDX-License-Identifier: Apache-2.0
2 /*
3 * FIPS-180-2 compliant SHA-384/512 implementation
4 *
5 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21 /*
22 * The SHA-512 Secure Hash Standard was published by NIST in 2002.
23 *
24 * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
25 */
26
27 #ifndef USE_HOSTCC
28 #include <common.h>
29 #include <linux/string.h>
30 #else
31 #include <string.h>
32 #endif /* USE_HOSTCC */
33 #include <u-boot/sha512.h>
34
35 #if defined(_MSC_VER) || defined(__WATCOMC__)
36 #define UL64(x) x##ui64
37 #else
38 #define UL64(x) x##ULL
39 #endif
40
41 /*
42 * 64-bit integer manipulation macros (big endian)
43 */
44 #ifndef GET_UINT64_BE
45 #define GET_UINT64_BE(n,b,i) \
46 { \
47 (n) = ((uint64_t)(b)[(i) ] << 56) \
48 | ((uint64_t)(b)[(i) + 1] << 48) \
49 | ((uint64_t)(b)[(i) + 2] << 40) \
50 | ((uint64_t)(b)[(i) + 3] << 32) \
51 | ((uint64_t)(b)[(i) + 4] << 24) \
52 | ((uint64_t)(b)[(i) + 5] << 16) \
53 | ((uint64_t)(b)[(i) + 6] << 8) \
54 | ((uint64_t)(b)[(i) + 7] ); \
55 }
56 #endif /* GET_UINT64_BE */
57
58 #ifndef PUT_UINT64_BE
59 #define PUT_UINT64_BE(n,b,i) \
60 { \
61 (b)[(i) ] = (unsigned char) ((n) >> 56); \
62 (b)[(i) + 1] = (unsigned char) ((n) >> 48); \
63 (b)[(i) + 2] = (unsigned char) ((n) >> 40); \
64 (b)[(i) + 3] = (unsigned char) ((n) >> 32); \
65 (b)[(i) + 4] = (unsigned char) ((n) >> 24); \
66 (b)[(i) + 5] = (unsigned char) ((n) >> 16); \
67 (b)[(i) + 6] = (unsigned char) ((n) >> 8); \
68 (b)[(i) + 7] = (unsigned char) ((n) ); \
69 }
70 #endif /* PUT_UINT64_BE */
71
72 /*
73 * SHA-512 context setup
74 */
__sha512_starts(sha512_context * ctx,int is384)75 static int __sha512_starts(sha512_context *ctx, int is384)
76 {
77 ctx->total[0] = 0;
78 ctx->total[1] = 0;
79
80 if (is384 == 0) {
81 /* SHA-512 */
82 ctx->state[0] = UL64(0x6A09E667F3BCC908);
83 ctx->state[1] = UL64(0xBB67AE8584CAA73B);
84 ctx->state[2] = UL64(0x3C6EF372FE94F82B);
85 ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
86 ctx->state[4] = UL64(0x510E527FADE682D1);
87 ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
88 ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
89 ctx->state[7] = UL64(0x5BE0CD19137E2179);
90 } else {
91 /* SHA-384 */
92 ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
93 ctx->state[1] = UL64(0x629A292A367CD507);
94 ctx->state[2] = UL64(0x9159015A3070DD17);
95 ctx->state[3] = UL64(0x152FECD8F70E5939);
96 ctx->state[4] = UL64(0x67332667FFC00B31);
97 ctx->state[5] = UL64(0x8EB44A8768581511);
98 ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
99 ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
100 }
101
102 ctx->is384 = is384;
103
104 return(0);
105 }
106
sha512_starts(sha512_context * ctx)107 int sha512_starts(sha512_context *ctx)
108 {
109 return __sha512_starts(ctx, 0);
110 }
111
112 /*
113 * Round constants
114 */
115 static const uint64_t K[80] = {
116 UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
117 UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
118 UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
119 UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
120 UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
121 UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
122 UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
123 UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
124 UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
125 UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
126 UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
127 UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
128 UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
129 UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
130 UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
131 UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
132 UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
133 UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
134 UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
135 UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
136 UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
137 UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
138 UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
139 UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
140 UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
141 UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
142 UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
143 UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
144 UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
145 UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
146 UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
147 UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
148 UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
149 UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
150 UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
151 UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
152 UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
153 UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
154 UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
155 UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
156 };
157
sha512_process(sha512_context * ctx,const unsigned char data[128])158 static int sha512_process(sha512_context *ctx, const unsigned char data[128])
159 {
160 int i;
161 uint64_t temp1, temp2, W[80];
162 uint64_t A, B, C, D, E, F, G, H;
163
164 #define SHR(x,n) (x >> n)
165 #define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
166
167 #define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
168 #define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
169
170 #define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
171 #define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
172
173 #define F0(x,y,z) ((x & y) | (z & (x | y)))
174 #define F1(x,y,z) (z ^ (x & (y ^ z)))
175
176 #define P(a,b,c,d,e,f,g,h,x,K) \
177 { \
178 temp1 = h + S3(e) + F1(e,f,g) + K + x; \
179 temp2 = S2(a) + F0(a,b,c); \
180 d += temp1; h = temp1 + temp2; \
181 }
182
183 for (i = 0; i < 16; i++) {
184 GET_UINT64_BE(W[i], data, i << 3);
185 }
186
187 for (; i < 80; i++) {
188 W[i] = S1(W[i - 2]) + W[i - 7] +
189 S0(W[i - 15]) + W[i - 16];
190 }
191
192 A = ctx->state[0];
193 B = ctx->state[1];
194 C = ctx->state[2];
195 D = ctx->state[3];
196 E = ctx->state[4];
197 F = ctx->state[5];
198 G = ctx->state[6];
199 H = ctx->state[7];
200 i = 0;
201
202 do {
203 P(A, B, C, D, E, F, G, H, W[i], K[i]);
204 i++;
205 P(H, A, B, C, D, E, F, G, W[i], K[i]);
206 i++;
207 P(G, H, A, B, C, D, E, F, W[i], K[i]);
208 i++;
209 P(F, G, H, A, B, C, D, E, W[i], K[i]);
210 i++;
211 P(E, F, G, H, A, B, C, D, W[i], K[i]);
212 i++;
213 P(D, E, F, G, H, A, B, C, W[i], K[i]);
214 i++;
215 P(C, D, E, F, G, H, A, B, W[i], K[i]);
216 i++;
217 P(B, C, D, E, F, G, H, A, W[i], K[i]);
218 i++;
219 } while (i < 80);
220
221 ctx->state[0] += A;
222 ctx->state[1] += B;
223 ctx->state[2] += C;
224 ctx->state[3] += D;
225 ctx->state[4] += E;
226 ctx->state[5] += F;
227 ctx->state[6] += G;
228 ctx->state[7] += H;
229
230 return(0);
231 }
232
233 /*
234 * SHA-512 process buffer
235 */
sha512_update(sha512_context * ctx,const unsigned char * input,size_t ilen)236 int sha512_update(sha512_context *ctx, const unsigned char *input, size_t ilen)
237 {
238 int ret;
239 size_t fill;
240 unsigned int left;
241
242 if (ilen == 0)
243 return(0);
244
245 left = (unsigned int)(ctx->total[0] & 0x7F);
246 fill = 128 - left;
247
248 ctx->total[0] += (uint64_t)ilen;
249
250 if (ctx->total[0] < (uint64_t)ilen)
251 ctx->total[1]++;
252
253 if (left && ilen >= fill) {
254 memcpy((void *)(ctx->buffer + left), input, fill);
255
256 if ((ret = sha512_process(ctx, ctx->buffer)) != 0)
257 return(ret);
258
259 input += fill;
260 ilen -= fill;
261 left = 0;
262 }
263
264 while (ilen >= 128) {
265 if ((ret = sha512_process(ctx, input)) != 0)
266 return(ret);
267
268 input += 128;
269 ilen -= 128;
270 }
271
272 if (ilen > 0)
273 memcpy((void *)(ctx->buffer + left), input, ilen);
274
275 return(0);
276 }
277
278 /*
279 * SHA-512 final digest
280 */
sha512_finish(sha512_context * ctx,unsigned char output[64])281 int sha512_finish(sha512_context *ctx, unsigned char output[64])
282 {
283 int ret;
284 unsigned used;
285 uint64_t high, low;
286
287 /*
288 * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
289 */
290 used = ctx->total[0] & 0x7F;
291
292 ctx->buffer[used++] = 0x80;
293
294 if (used <= 112) {
295 /* Enough room for padding + length in current block */
296 memset(ctx->buffer + used, 0, 112 - used);
297 } else {
298 /* We'll need an extra block */
299 memset(ctx->buffer + used, 0, 128 - used);
300
301 if ((ret = sha512_process(ctx, ctx->buffer)) != 0)
302 return(ret);
303
304 memset(ctx->buffer, 0, 112);
305 }
306
307 /*
308 * Add message length
309 */
310 high = (ctx->total[0] >> 61)
311 | (ctx->total[1] << 3);
312 low = (ctx->total[0] << 3);
313
314 PUT_UINT64_BE(high, ctx->buffer, 112);
315 PUT_UINT64_BE(low, ctx->buffer, 120);
316
317 if ((ret = sha512_process(ctx, ctx->buffer)) != 0)
318 return(ret);
319
320 /*
321 * Output final state
322 */
323 PUT_UINT64_BE(ctx->state[0], output, 0);
324 PUT_UINT64_BE(ctx->state[1], output, 8);
325 PUT_UINT64_BE(ctx->state[2], output, 16);
326 PUT_UINT64_BE(ctx->state[3], output, 24);
327 PUT_UINT64_BE(ctx->state[4], output, 32);
328 PUT_UINT64_BE(ctx->state[5], output, 40);
329
330 if (ctx->is384 == 0) {
331 PUT_UINT64_BE(ctx->state[6], output, 48);
332 PUT_UINT64_BE(ctx->state[7], output, 56);
333 }
334
335 return(0);
336 }
337
sha512_csum(const unsigned char * input,unsigned int ilen,unsigned char output[64])338 void sha512_csum(const unsigned char *input, unsigned int ilen,
339 unsigned char output[64])
340 {
341 sha512_context ctx;
342
343 sha512_starts(&ctx);
344 sha512_update(&ctx, input, ilen);
345 sha512_finish(&ctx, output);
346 }
347