1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * SHA2-256: https://csrc.nist.gov/pubs/fips/180-2/upd1/final
4 *
5 * Originally derived from Linux. Modified substantially to optimise for size
6 * and Xen's expected usecases.
7 */
8 #include <xen/bitops.h>
9 #include <xen/sha2.h>
10 #include <xen/string.h>
11 #include <xen/unaligned.h>
12
choose(uint32_t x,uint32_t y,uint32_t z)13 static uint32_t choose(uint32_t x, uint32_t y, uint32_t z)
14 {
15 return z ^ (x & (y ^ z));
16 }
17
majority(uint32_t x,uint32_t y,uint32_t z)18 static uint32_t majority(uint32_t x, uint32_t y, uint32_t z)
19 {
20 return (x & y) | (z & (x | y));
21 }
22
e0(uint32_t x)23 static uint32_t e0(uint32_t x)
24 {
25 return ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22);
26 }
27
e1(uint32_t x)28 static uint32_t e1(uint32_t x)
29 {
30 return ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25);
31 }
32
s0(uint32_t x)33 static uint32_t s0(uint32_t x)
34 {
35 return ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3);
36 }
37
s1(uint32_t x)38 static uint32_t s1(uint32_t x)
39 {
40 return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
41 }
42
blend(uint32_t W[16],unsigned int i)43 static uint32_t blend(uint32_t W[16], unsigned int i)
44 {
45 #define W(i) W[(i) & 15]
46
47 return W(i) += s1(W(i - 2)) + W(i - 7) + s0(W(i - 15));
48
49 #undef W
50 }
51
52 static const uint32_t K[] = {
53 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U,
54 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
55 0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U,
56 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
57 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
58 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
59 0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,
60 0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,
61 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U,
62 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
63 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U,
64 0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,
65 0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U,
66 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
67 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
68 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U,
69 };
70
sha2_256_transform(uint32_t * state,const void * _input)71 static void sha2_256_transform(uint32_t *state, const void *_input)
72 {
73 const uint32_t *input = _input;
74 uint32_t a, b, c, d, e, f, g, h, t1, t2;
75 uint32_t W[16];
76 unsigned int i;
77
78 for ( i = 0; i < 16; i++ )
79 W[i] = get_unaligned_be32(&input[i]);
80
81 a = state[0]; b = state[1]; c = state[2]; d = state[3];
82 e = state[4]; f = state[5]; g = state[6]; h = state[7];
83
84 for ( i = 0; i < 16; i += 8 )
85 {
86 t1 = h + e1(e) + choose(e, f, g) + K[i + 0] + W[i + 0];
87 t2 = e0(a) + majority(a, b, c); d += t1; h = t1 + t2;
88 t1 = g + e1(d) + choose(d, e, f) + K[i + 1] + W[i + 1];
89 t2 = e0(h) + majority(h, a, b); c += t1; g = t1 + t2;
90 t1 = f + e1(c) + choose(c, d, e) + K[i + 2] + W[i + 2];
91 t2 = e0(g) + majority(g, h, a); b += t1; f = t1 + t2;
92 t1 = e + e1(b) + choose(b, c, d) + K[i + 3] + W[i + 3];
93 t2 = e0(f) + majority(f, g, h); a += t1; e = t1 + t2;
94 t1 = d + e1(a) + choose(a, b, c) + K[i + 4] + W[i + 4];
95 t2 = e0(e) + majority(e, f, g); h += t1; d = t1 + t2;
96 t1 = c + e1(h) + choose(h, a, b) + K[i + 5] + W[i + 5];
97 t2 = e0(d) + majority(d, e, f); g += t1; c = t1 + t2;
98 t1 = b + e1(g) + choose(g, h, a) + K[i + 6] + W[i + 6];
99 t2 = e0(c) + majority(c, d, e); f += t1; b = t1 + t2;
100 t1 = a + e1(f) + choose(f, g, h) + K[i + 7] + W[i + 7];
101 t2 = e0(b) + majority(b, c, d); e += t1; a = t1 + t2;
102 }
103
104 for ( ; i < 64; i += 8 )
105 {
106 t1 = h + e1(e) + choose(e, f, g) + K[i + 0] + blend(W, i + 0);
107 t2 = e0(a) + majority(a, b, c); d += t1; h = t1 + t2;
108 t1 = g + e1(d) + choose(d, e, f) + K[i + 1] + blend(W, i + 1);
109 t2 = e0(h) + majority(h, a, b); c += t1; g = t1 + t2;
110 t1 = f + e1(c) + choose(c, d, e) + K[i + 2] + blend(W, i + 2);
111 t2 = e0(g) + majority(g, h, a); b += t1; f = t1 + t2;
112 t1 = e + e1(b) + choose(b, c, d) + K[i + 3] + blend(W, i + 3);
113 t2 = e0(f) + majority(f, g, h); a += t1; e = t1 + t2;
114 t1 = d + e1(a) + choose(a, b, c) + K[i + 4] + blend(W, i + 4);
115 t2 = e0(e) + majority(e, f, g); h += t1; d = t1 + t2;
116 t1 = c + e1(h) + choose(h, a, b) + K[i + 5] + blend(W, i + 5);
117 t2 = e0(d) + majority(d, e, f); g += t1; c = t1 + t2;
118 t1 = b + e1(g) + choose(g, h, a) + K[i + 6] + blend(W, i + 6);
119 t2 = e0(c) + majority(c, d, e); f += t1; b = t1 + t2;
120 t1 = a + e1(f) + choose(f, g, h) + K[i + 7] + blend(W, i + 7);
121 t2 = e0(b) + majority(b, c, d); e += t1; a = t1 + t2;
122 }
123
124 state[0] += a; state[1] += b; state[2] += c; state[3] += d;
125 state[4] += e; state[5] += f; state[6] += g; state[7] += h;
126 }
127
sha2_256_init(struct sha2_256_state * s)128 void sha2_256_init(struct sha2_256_state *s)
129 {
130 *s = (struct sha2_256_state){
131 .state = {
132 0x6a09e667UL,
133 0xbb67ae85UL,
134 0x3c6ef372UL,
135 0xa54ff53aUL,
136 0x510e527fUL,
137 0x9b05688cUL,
138 0x1f83d9abUL,
139 0x5be0cd19UL,
140 },
141 };
142 }
143
sha2_256_update(struct sha2_256_state * s,const void * msg,size_t len)144 void sha2_256_update(struct sha2_256_state *s, const void *msg, size_t len)
145 {
146 unsigned int partial = s->count & 63;
147
148 s->count += len;
149
150 if ( (partial + len) >= 64 )
151 {
152 if ( partial )
153 {
154 unsigned int rem = 64 - partial;
155
156 /* Fill the partial block. */
157 memcpy(s->buf + partial, msg, rem);
158 msg += rem;
159 len -= rem;
160
161 sha2_256_transform(s->state, s->buf);
162 partial = 0;
163 }
164
165 for ( ; len >= 64; msg += 64, len -= 64 )
166 sha2_256_transform(s->state, msg);
167 }
168
169 /* Remaining data becomes partial. */
170 memcpy(s->buf + partial, msg, len);
171 }
172
sha2_256_final(struct sha2_256_state * s,uint8_t digest[SHA2_256_DIGEST_SIZE])173 void sha2_256_final(struct sha2_256_state *s, uint8_t digest[SHA2_256_DIGEST_SIZE])
174 {
175 uint32_t *dst = (uint32_t *)digest;
176 unsigned int i, partial = s->count & 63;
177
178 /* Start padding */
179 s->buf[partial++] = 0x80;
180
181 if ( partial > 56 )
182 {
183 /* Need one extra block - pad to 64 */
184 memset(s->buf + partial, 0, 64 - partial);
185 sha2_256_transform(s->state, s->buf);
186 partial = 0;
187 }
188 /* Pad to 56 */
189 memset(s->buf + partial, 0, 56 - partial);
190
191 /* Append the bit count */
192 put_unaligned_be64((uint64_t)s->count << 3, &s->buf[56]);
193 sha2_256_transform(s->state, s->buf);
194
195 /* Store state in digest */
196 for ( i = 0; i < 8; i++ )
197 put_unaligned_be32(s->state[i], &dst[i]);
198 }
199
sha2_256_digest(uint8_t digest[SHA2_256_DIGEST_SIZE],const void * msg,size_t len)200 void sha2_256_digest(uint8_t digest[SHA2_256_DIGEST_SIZE],
201 const void *msg, size_t len)
202 {
203 struct sha2_256_state s;
204
205 sha2_256_init(&s);
206 sha2_256_update(&s, msg, len);
207 sha2_256_final(&s, digest);
208 }
209
210 #ifdef CONFIG_SELF_TESTS
211
212 #include <xen/init.h>
213 #include <xen/lib.h>
214
215 static const struct test {
216 const char *msg;
217 uint8_t digest[SHA2_256_DIGEST_SIZE];
218 } tests[] __initconst = {
219 {
220 .msg = "abc",
221 .digest = {
222 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
223 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
224 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
225 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
226 },
227 },
228 {
229 .msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
230 .digest = {
231 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
232 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
233 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
234 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
235 },
236 },
237 };
238
test_sha2_256(void)239 static void __init __constructor test_sha2_256(void)
240 {
241 for ( unsigned int i = 0; i < ARRAY_SIZE(tests); ++i )
242 {
243 const struct test *t = &tests[i];
244 uint8_t res[SHA2_256_DIGEST_SIZE] = {};
245
246 sha2_256_digest(res, t->msg, strlen(t->msg));
247
248 if ( memcmp(res, t->digest, sizeof(t->digest)) == 0 )
249 continue;
250
251 panic("%s() msg '%s' failed\n"
252 " expected %" STR(SHA2_256_DIGEST_SIZE) "phN\n"
253 " got %" STR(SHA2_256_DIGEST_SIZE) "phN\n",
254 __func__, t->msg, t->digest, res);
255 }
256 }
257 #endif /* CONFIG_SELF_TESTS */
258