xref: /OK3568_Linux_fs/u-boot/lib/sha512.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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