blob: 50b0b511834fb840075f327b3e97b771a853cc2c [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Jean-Christophe PLAGNIOL-VILLARDc58a6b82008-06-07 12:29:52 +02002/*
3 * FIPS-180-2 compliant SHA-256 implementation
4 *
5 * Copyright (C) 2001-2003 Christophe Devine
Jean-Christophe PLAGNIOL-VILLARDc58a6b82008-06-07 12:29:52 +02006 */
7
8#ifndef USE_HOSTCC
9#include <common.h>
Andreas Bießmann511740c2014-04-20 10:34:15 +020010#include <linux/string.h>
11#else
12#include <string.h>
Jean-Christophe PLAGNIOL-VILLARDc58a6b82008-06-07 12:29:52 +020013#endif /* USE_HOSTCC */
14#include <watchdog.h>
Jeroen Hofsteebfe88fe2014-06-12 22:27:12 +020015#include <u-boot/sha256.h>
Jean-Christophe PLAGNIOL-VILLARDc58a6b82008-06-07 12:29:52 +020016
Loic Poulain179b2112022-06-01 20:26:30 +020017#include <linux/compiler_attributes.h>
18
Andrew Duda3db9ff02016-11-08 18:53:40 +000019const uint8_t sha256_der_prefix[SHA256_DER_LEN] = {
20 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
21 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
22 0x00, 0x04, 0x20
23};
24
Jean-Christophe PLAGNIOL-VILLARDc58a6b82008-06-07 12:29:52 +020025/*
26 * 32-bit integer manipulation macros (big endian)
27 */
28#ifndef GET_UINT32_BE
29#define GET_UINT32_BE(n,b,i) { \
30 (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
31 | ( (unsigned long) (b)[(i) + 1] << 16 ) \
32 | ( (unsigned long) (b)[(i) + 2] << 8 ) \
33 | ( (unsigned long) (b)[(i) + 3] ); \
34}
35#endif
36#ifndef PUT_UINT32_BE
37#define PUT_UINT32_BE(n,b,i) { \
38 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
39 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
40 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
41 (b)[(i) + 3] = (unsigned char) ( (n) ); \
42}
43#endif
44
45void sha256_starts(sha256_context * ctx)
46{
47 ctx->total[0] = 0;
48 ctx->total[1] = 0;
49
50 ctx->state[0] = 0x6A09E667;
51 ctx->state[1] = 0xBB67AE85;
52 ctx->state[2] = 0x3C6EF372;
53 ctx->state[3] = 0xA54FF53A;
54 ctx->state[4] = 0x510E527F;
55 ctx->state[5] = 0x9B05688C;
56 ctx->state[6] = 0x1F83D9AB;
57 ctx->state[7] = 0x5BE0CD19;
58}
59
Loic Poulain179b2112022-06-01 20:26:30 +020060static void sha256_process_one(sha256_context *ctx, const uint8_t data[64])
Jean-Christophe PLAGNIOL-VILLARDc58a6b82008-06-07 12:29:52 +020061{
62 uint32_t temp1, temp2;
63 uint32_t W[64];
64 uint32_t A, B, C, D, E, F, G, H;
65
66 GET_UINT32_BE(W[0], data, 0);
67 GET_UINT32_BE(W[1], data, 4);
68 GET_UINT32_BE(W[2], data, 8);
69 GET_UINT32_BE(W[3], data, 12);
70 GET_UINT32_BE(W[4], data, 16);
71 GET_UINT32_BE(W[5], data, 20);
72 GET_UINT32_BE(W[6], data, 24);
73 GET_UINT32_BE(W[7], data, 28);
74 GET_UINT32_BE(W[8], data, 32);
75 GET_UINT32_BE(W[9], data, 36);
76 GET_UINT32_BE(W[10], data, 40);
77 GET_UINT32_BE(W[11], data, 44);
78 GET_UINT32_BE(W[12], data, 48);
79 GET_UINT32_BE(W[13], data, 52);
80 GET_UINT32_BE(W[14], data, 56);
81 GET_UINT32_BE(W[15], data, 60);
82
83#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
84#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
85
86#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
87#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
88
89#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
90#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
91
92#define F0(x,y,z) ((x & y) | (z & (x | y)))
93#define F1(x,y,z) (z ^ (x & (y ^ z)))
94
95#define R(t) \
96( \
97 W[t] = S1(W[t - 2]) + W[t - 7] + \
98 S0(W[t - 15]) + W[t - 16] \
99)
100
101#define P(a,b,c,d,e,f,g,h,x,K) { \
102 temp1 = h + S3(e) + F1(e,f,g) + K + x; \
103 temp2 = S2(a) + F0(a,b,c); \
104 d += temp1; h = temp1 + temp2; \
105}
106
107 A = ctx->state[0];
108 B = ctx->state[1];
109 C = ctx->state[2];
110 D = ctx->state[3];
111 E = ctx->state[4];
112 F = ctx->state[5];
113 G = ctx->state[6];
114 H = ctx->state[7];
115
116 P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98);
117 P(H, A, B, C, D, E, F, G, W[1], 0x71374491);
118 P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF);
119 P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5);
120 P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B);
121 P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1);
122 P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4);
123 P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5);
124 P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98);
125 P(H, A, B, C, D, E, F, G, W[9], 0x12835B01);
126 P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
127 P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
128 P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
129 P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
130 P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
131 P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
132 P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
133 P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
134 P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
135 P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
136 P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
137 P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
138 P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
139 P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
140 P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
141 P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
142 P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
143 P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
144 P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
145 P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
146 P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
147 P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
148 P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
149 P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
150 P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
151 P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
152 P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
153 P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
154 P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
155 P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
156 P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
157 P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
158 P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
159 P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
160 P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
161 P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
162 P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
163 P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
164 P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
165 P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
166 P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
167 P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
168 P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
169 P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
170 P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
171 P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
172 P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
173 P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
174 P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
175 P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
176 P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
177 P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
178 P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
179 P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
180
181 ctx->state[0] += A;
182 ctx->state[1] += B;
183 ctx->state[2] += C;
184 ctx->state[3] += D;
185 ctx->state[4] += E;
186 ctx->state[5] += F;
187 ctx->state[6] += G;
188 ctx->state[7] += H;
189}
190
Loic Poulain179b2112022-06-01 20:26:30 +0200191__weak void sha256_process(sha256_context *ctx, const unsigned char *data,
192 unsigned int blocks)
193{
194 if (!blocks)
195 return;
196
197 while (blocks--) {
198 sha256_process_one(ctx, data);
199 data += 64;
200 }
201}
202
Simon Glass0df82432012-12-05 14:46:34 +0000203void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
Jean-Christophe PLAGNIOL-VILLARDc58a6b82008-06-07 12:29:52 +0200204{
205 uint32_t left, fill;
206
207 if (!length)
208 return;
209
210 left = ctx->total[0] & 0x3F;
211 fill = 64 - left;
212
213 ctx->total[0] += length;
214 ctx->total[0] &= 0xFFFFFFFF;
215
216 if (ctx->total[0] < length)
217 ctx->total[1]++;
218
219 if (left && length >= fill) {
220 memcpy((void *) (ctx->buffer + left), (void *) input, fill);
Loic Poulain179b2112022-06-01 20:26:30 +0200221 sha256_process(ctx, ctx->buffer, 1);
Jean-Christophe PLAGNIOL-VILLARDc58a6b82008-06-07 12:29:52 +0200222 length -= fill;
223 input += fill;
224 left = 0;
225 }
226
Loic Poulain179b2112022-06-01 20:26:30 +0200227 sha256_process(ctx, input, length / 64);
228 input += length / 64 * 64;
229 length = length % 64;
Jean-Christophe PLAGNIOL-VILLARDc58a6b82008-06-07 12:29:52 +0200230
231 if (length)
232 memcpy((void *) (ctx->buffer + left), (void *) input, length);
233}
234
235static uint8_t sha256_padding[64] = {
236 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
237 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
238 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
240};
241
242void sha256_finish(sha256_context * ctx, uint8_t digest[32])
243{
244 uint32_t last, padn;
245 uint32_t high, low;
246 uint8_t msglen[8];
247
248 high = ((ctx->total[0] >> 29)
249 | (ctx->total[1] << 3));
250 low = (ctx->total[0] << 3);
251
252 PUT_UINT32_BE(high, msglen, 0);
253 PUT_UINT32_BE(low, msglen, 4);
254
255 last = ctx->total[0] & 0x3F;
256 padn = (last < 56) ? (56 - last) : (120 - last);
257
258 sha256_update(ctx, sha256_padding, padn);
259 sha256_update(ctx, msglen, 8);
260
261 PUT_UINT32_BE(ctx->state[0], digest, 0);
262 PUT_UINT32_BE(ctx->state[1], digest, 4);
263 PUT_UINT32_BE(ctx->state[2], digest, 8);
264 PUT_UINT32_BE(ctx->state[3], digest, 12);
265 PUT_UINT32_BE(ctx->state[4], digest, 16);
266 PUT_UINT32_BE(ctx->state[5], digest, 20);
267 PUT_UINT32_BE(ctx->state[6], digest, 24);
268 PUT_UINT32_BE(ctx->state[7], digest, 28);
269}
Simon Glass0df82432012-12-05 14:46:34 +0000270
271/*
272 * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz'
273 * bytes of input processed.
274 */
275void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
276 unsigned char *output, unsigned int chunk_sz)
277{
278 sha256_context ctx;
279#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
Heiko Schocher8ae33802014-03-03 12:19:25 +0100280 const unsigned char *end;
281 unsigned char *curr;
Simon Glass0df82432012-12-05 14:46:34 +0000282 int chunk;
283#endif
284
285 sha256_starts(&ctx);
286
287#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
Heiko Schocher8ae33802014-03-03 12:19:25 +0100288 curr = (unsigned char *)input;
Simon Glass0df82432012-12-05 14:46:34 +0000289 end = input + ilen;
290 while (curr < end) {
291 chunk = end - curr;
292 if (chunk > chunk_sz)
293 chunk = chunk_sz;
294 sha256_update(&ctx, curr, chunk);
295 curr += chunk;
296 WATCHDOG_RESET();
297 }
298#else
299 sha256_update(&ctx, input, ilen);
300#endif
301
302 sha256_finish(&ctx, output);
303}