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