Contiki-NG
Loading...
Searching...
No Matches
sha-256.c
1/*
2 * Copyright 2005 Colin Percival
3 * Copyright (c) 2021, Uppsala universitet.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include "lib/sha-256.h"
29#include "net/ipv6/uip.h"
30#include "sys/cc.h"
31#include <string.h>
32
33/* HMAC-related */
34struct data_chunk {
35 const uint8_t *data;
36 size_t data_len;
37};
38
39#if UIP_BYTE_ORDER != UIP_LITTLE_ENDIAN
40/* Copy a vector of big-endian uint32_t into a vector of bytes */
41#define be32enc_vect memcpy
42
43/* Copy a vector of bytes into a vector of big-endian uint32_t */
44#define be32dec_vect memcpy
45
46static void
47be64enc(uint8_t *p, uint64_t u)
48{
49 memcpy(p, &u, sizeof(uint64_t));
50}
51
52#else /* UIP_BYTE_ORDER != UIP_LITTLE_ENDIAN */
53static uint32_t
54be32dec(uint8_t const *p)
55{
56 return ((uint32_t)p[0] << 24)
57 | ((uint32_t)p[1] << 16)
58 | ((uint32_t)p[2] << 8)
59 | p[3];
60}
61
62static void
63be32enc(uint8_t *p, uint32_t u)
64{
65 p[0] = (u >> 24) & 0xff;
66 p[1] = (u >> 16) & 0xff;
67 p[2] = (u >> 8) & 0xff;
68 p[3] = u & 0xff;
69}
70
71static void
72be64enc(uint8_t *p, uint64_t u)
73{
74 be32enc(p, (uint32_t)(u >> 32));
75 be32enc(p + 4, (uint32_t)(u & 0xffffffffU));
76}
77
78/*
79 * Encode a length len/4 vector of (uint32_t) into a length len vector of
80 * (unsigned char) in big-endian form. Assumes len is a multiple of 4.
81 */
82static void
83be32enc_vect(uint8_t *dst, const uint32_t *src, size_t len)
84{
85 size_t i;
86
87 for(i = 0; i < len / 4; i++) {
88 be32enc(dst + i * 4, src[i]);
89 }
90}
91
92/*
93 * Decode a big-endian length len vector of (unsigned char) into a length
94 * len/4 vector of (uint32_t). Assumes len is a multiple of 4.
95 */
96static void
97be32dec_vect(uint32_t *dst, const uint8_t *src, size_t len)
98{
99 size_t i;
100
101 for(i = 0; i < len / 4; i++) {
102 dst[i] = be32dec(src + i * 4);
103 }
104}
105#endif /* UIP_BYTE_ORDER != UIP_LITTLE_ENDIAN */
106
107static const uint32_t K[64] = {
108 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
109 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
110 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
111 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
112 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
113 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
114 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
115 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
116 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
117 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
118 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
119 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
120 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
121 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
122 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
123 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
124};
125
126/* Elementary functions used by SHA-256 */
127#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
128#define Maj(x, y, z) ((x & (y | z)) | (y & z))
129#define SHR(x, n) (x >> n)
130#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
131#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
132#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
133#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
134#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
135
136/* SHA256 round function */
137#define RND(a, b, c, d, e, f, g, h, k) \
138 h += S1(e) + Ch(e, f, g) + k; \
139 d += h; \
140 h += S0(a) + Maj(a, b, c);
141
142/* Adjusted round function for rotating state */
143#define RNDr(S, W, i, ii) \
144 RND(S[(64 - i) % 8], S[(65 - i) % 8], \
145 S[(66 - i) % 8], S[(67 - i) % 8], \
146 S[(68 - i) % 8], S[(69 - i) % 8], \
147 S[(70 - i) % 8], S[(71 - i) % 8], \
148 W[i + ii] + K[i + ii])
149
150/* Message schedule computation */
151#define MSCH(W, ii, i) \
152 W[i + ii + 16] = \
153 s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
154
155static sha_256_checkpoint_t checkpoint;
156
157/*---------------------------------------------------------------------------*/
158/*
159 * SHA-256 block compression function. The 256-bit state is transformed via
160 * the 512-bit input block to produce a new state.
161 */
162static void
163transform(const uint8_t block[static SHA_256_BLOCK_SIZE])
164{
165 uint32_t W[64];
166 uint32_t S[8];
167 uint_fast8_t i;
168
169 /* 1. Prepare the first part of the message schedule W. */
170 be32dec_vect(W, block, 64);
171
172 /* 2. Initialize working variables. */
173 memcpy(S, checkpoint.state, 32);
174
175 /* 3. Mix. */
176 for(i = 0; i < 64; i += 16) {
177 RNDr(S, W, 0, i);
178 RNDr(S, W, 1, i);
179 RNDr(S, W, 2, i);
180 RNDr(S, W, 3, i);
181 RNDr(S, W, 4, i);
182 RNDr(S, W, 5, i);
183 RNDr(S, W, 6, i);
184 RNDr(S, W, 7, i);
185 RNDr(S, W, 8, i);
186 RNDr(S, W, 9, i);
187 RNDr(S, W, 10, i);
188 RNDr(S, W, 11, i);
189 RNDr(S, W, 12, i);
190 RNDr(S, W, 13, i);
191 RNDr(S, W, 14, i);
192 RNDr(S, W, 15, i);
193
194 if(i == 48) {
195 break;
196 }
197 MSCH(W, 0, i);
198 MSCH(W, 1, i);
199 MSCH(W, 2, i);
200 MSCH(W, 3, i);
201 MSCH(W, 4, i);
202 MSCH(W, 5, i);
203 MSCH(W, 6, i);
204 MSCH(W, 7, i);
205 MSCH(W, 8, i);
206 MSCH(W, 9, i);
207 MSCH(W, 10, i);
208 MSCH(W, 11, i);
209 MSCH(W, 12, i);
210 MSCH(W, 13, i);
211 MSCH(W, 14, i);
212 MSCH(W, 15, i);
213 }
214
215 /* 4. Mix local working variables into global state */
216 for(i = 0; i < 8; i++) {
217 checkpoint.state[i] += S[i];
218 }
219}
220/*---------------------------------------------------------------------------*/
221/* Add padding and terminating bit-count. */
222static void
223sha_256_pad(void)
224{
225 static const unsigned char PAD[64] = {
226 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
227 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
230 };
231
232 /* Pad to 56 mod 64, transforming if we finish a block en route. */
233 if(checkpoint.buf_len < 56) {
234 /* Pad to 56 mod 64. */
235 memcpy(&checkpoint.buf[checkpoint.buf_len], PAD, 56 - checkpoint.buf_len);
236 } else {
237 /* Finish the current block and mix. */
238 memcpy(&checkpoint.buf[checkpoint.buf_len], PAD, SHA_256_BLOCK_SIZE - checkpoint.buf_len);
239 transform(checkpoint.buf);
240
241 /* The start of the final block is all zeroes. */
242 memset(&checkpoint.buf[0], 0, 56);
243 }
244
245 /* Add the terminating bit-count. */
246 be64enc(&checkpoint.buf[56], checkpoint.bit_count);
247
248 /* Mix in the final block. */
249 transform(checkpoint.buf);
250}
251/*---------------------------------------------------------------------------*/
252/* SHA-256 initialization. Begins a SHA-256 operation. */
253static void
254init(void)
255{
256 /* Zero bits processed so far */
257 checkpoint.bit_count = 0;
258 checkpoint.buf_len = 0;
259
260 /* Magic initialization constants */
261 checkpoint.state[0] = 0x6A09E667;
262 checkpoint.state[1] = 0xBB67AE85;
263 checkpoint.state[2] = 0x3C6EF372;
264 checkpoint.state[3] = 0xA54FF53A;
265 checkpoint.state[4] = 0x510E527F;
266 checkpoint.state[5] = 0x9B05688C;
267 checkpoint.state[6] = 0x1F83D9AB;
268 checkpoint.state[7] = 0x5BE0CD19;
269}
270/*---------------------------------------------------------------------------*/
271/* Add bytes into the hash */
272static void
273update(const uint8_t *data, size_t len)
274{
275 uint64_t bitlen;
276
277 /* Convert the length into a number of bits */
278 bitlen = len << 3;
279
280 /* Update number of bits */
281 checkpoint.bit_count += bitlen;
282
283 /* Handle the case where we don't need to perform any transforms */
284 if(len < SHA_256_BLOCK_SIZE - checkpoint.buf_len) {
285 memcpy(&checkpoint.buf[checkpoint.buf_len], data, len);
286 checkpoint.buf_len += len;
287 return;
288 }
289
290 /* Finish the current block */
291 memcpy(&checkpoint.buf[checkpoint.buf_len],
292 data,
293 SHA_256_BLOCK_SIZE - checkpoint.buf_len);
294 transform(checkpoint.buf);
295 data += SHA_256_BLOCK_SIZE - checkpoint.buf_len;
296 len -= SHA_256_BLOCK_SIZE - checkpoint.buf_len;
297 checkpoint.buf_len = 0;
298
299 /* Perform complete blocks */
300 while(len >= 64) {
301 transform(data);
302 data += SHA_256_BLOCK_SIZE;
303 len -= SHA_256_BLOCK_SIZE;
304 }
305
306 /* Copy left over data into buffer */
307 memcpy(checkpoint.buf, data, len);
308 checkpoint.buf_len += len;
309}
310/*---------------------------------------------------------------------------*/
311/*
312 * SHA-256 finalization. Pads the input data, exports the hash value,
313 * and clears the context state.
314 */
315static void
316finalize(uint8_t digest[static SHA_256_DIGEST_LENGTH])
317{
318 /* Add padding */
319 sha_256_pad();
320
321 /* Write the hash */
322 be32enc_vect(digest, checkpoint.state, SHA_256_DIGEST_LENGTH);
323
324 /* Clear the context state */
325 memset(&checkpoint, 0, sizeof(checkpoint));
326}
327/*---------------------------------------------------------------------------*/
328static void
329create_checkpoint(sha_256_checkpoint_t *cp)
330{
331 memcpy(cp, &checkpoint, sizeof(*cp));
332}
333/*---------------------------------------------------------------------------*/
334static void
335restore_checkpoint(const sha_256_checkpoint_t *cp)
336{
337 memcpy(&checkpoint, cp, sizeof(checkpoint));
338}
339/*---------------------------------------------------------------------------*/
340void
341sha_256_hash(const uint8_t *data, size_t len,
342 uint8_t digest[static SHA_256_DIGEST_LENGTH])
343{
344 SHA_256.init();
345 SHA_256.update(data, len);
346 SHA_256.finalize(digest);
347}
348/*---------------------------------------------------------------------------*/
349static void
350hmac_over_data_chunks(const uint8_t *key, size_t key_len,
351 struct data_chunk *chunks, uint_fast8_t chunks_count,
352 uint8_t hmac[static SHA_256_DIGEST_LENGTH])
353{
354 uint8_t hashed_key[SHA_256_DIGEST_LENGTH];
355 uint8_t ipad[SHA_256_BLOCK_SIZE];
356 uint8_t opad[SHA_256_BLOCK_SIZE];
357 uint_fast8_t i;
358 uint_fast8_t j;
359
360 if(key_len > SHA_256_BLOCK_SIZE) {
361 SHA_256.hash(key, key_len, hashed_key);
362 key_len = SHA_256_DIGEST_LENGTH;
363 key = hashed_key;
364 }
365 for(i = 0; i < key_len; i++) {
366 ipad[i] = key[i] ^ 0x36;
367 opad[i] = key[i] ^ 0x5c;
368 }
369 for(; i < SHA_256_BLOCK_SIZE; i++) {
370 ipad[i] = 0x36;
371 opad[i] = 0x5c;
372 }
373
374 SHA_256.init();
375 SHA_256.update(ipad, SHA_256_BLOCK_SIZE);
376 for(j = 0; j < chunks_count; j++) {
377 if(chunks[j].data && chunks[j].data_len) {
378 SHA_256.update(chunks[j].data, chunks[j].data_len);
379 }
380 }
381 SHA_256.finalize(hmac);
382
383 SHA_256.init();
384 SHA_256.update(opad, SHA_256_BLOCK_SIZE);
385 SHA_256.update(hmac, SHA_256_DIGEST_LENGTH);
386 SHA_256.finalize(hmac);
387}
388/*---------------------------------------------------------------------------*/
389void
390sha_256_hmac(const uint8_t *key, size_t key_len,
391 const uint8_t *data, size_t data_len,
392 uint8_t hmac[static SHA_256_DIGEST_LENGTH])
393{
394 struct data_chunk chunk;
395
396 chunk.data = data;
397 chunk.data_len = data_len;
398 hmac_over_data_chunks(key, key_len, &chunk, 1, hmac);
399}
400/*---------------------------------------------------------------------------*/
401void
402sha_256_hkdf_extract(const uint8_t *salt, size_t salt_len,
403 const uint8_t *ikm, size_t ikm_len,
404 uint8_t prk[static SHA_256_DIGEST_LENGTH])
405{
406 sha_256_hmac(salt, salt_len, ikm, ikm_len, prk);
407}
408/*---------------------------------------------------------------------------*/
409void
410sha_256_hkdf_expand(const uint8_t *prk, size_t prk_len,
411 const uint8_t *info, size_t info_len,
412 uint8_t *okm, uint_fast16_t okm_len)
413{
414 struct data_chunk chunks[3];
415 uint_fast8_t n;
416 uint8_t i;
417 uint8_t t_i[SHA_256_DIGEST_LENGTH];
418
419 okm_len = MIN(okm_len, 255 * SHA_256_DIGEST_LENGTH);
420 n = okm_len / SHA_256_DIGEST_LENGTH
421 + (okm_len % SHA_256_DIGEST_LENGTH ? 1 : 0);
422
423 chunks[0].data = t_i;
424 chunks[0].data_len = SHA_256_DIGEST_LENGTH;
425 chunks[1].data = info;
426 chunks[1].data_len = info_len;
427 chunks[2].data = &i;
428 chunks[2].data_len = 1;
429
430 for(i = 1; i <= n; i++) {
431 hmac_over_data_chunks(prk, prk_len,
432 chunks + (i == 1), 3 - (i == 1),
433 t_i);
434 memcpy(okm + ((i - 1) * SHA_256_DIGEST_LENGTH),
435 t_i,
436 MIN(SHA_256_DIGEST_LENGTH, okm_len));
437 okm_len -= SHA_256_DIGEST_LENGTH;
438 }
439}
440/*---------------------------------------------------------------------------*/
441void
442sha_256_hkdf(const uint8_t *salt, size_t salt_len,
443 const uint8_t *ikm, size_t ikm_len,
444 const uint8_t *info, size_t info_len,
445 uint8_t *okm, uint_fast16_t okm_len)
446{
447 uint8_t prk[SHA_256_DIGEST_LENGTH];
448
449 sha_256_hkdf_extract(salt, salt_len, ikm, ikm_len, prk);
450 sha_256_hkdf_expand(prk, sizeof(prk), info, info_len, okm, okm_len);
451}
452/*---------------------------------------------------------------------------*/
453const struct sha_256_driver sha_256_driver = {
454 init,
455 update,
456 finalize,
460};
461/*---------------------------------------------------------------------------*/
Default definitions of C compiler quirk work-arounds.
Platform-independent SHA-256 API.
void sha_256_hash(const uint8_t *data, size_t len, uint8_t digest[static 32])
Generic implementation of sha_256_driver::hash.
Structure of SHA-256 drivers.
Definition sha-256.h:66
void(* create_checkpoint)(sha_256_checkpoint_t *checkpoint)
Saves the hash session, e.g., before pausing a protothread.
Definition sha-256.h:89
void(* finalize)(uint8_t digest[static 32])
Terminates the hash session and produces the digest.
Definition sha-256.h:84
void(* init)(void)
Starts a hash session.
Definition sha-256.h:71
void(* restore_checkpoint)(const sha_256_checkpoint_t *checkpoint)
Restores a hash session, e.g., after resuming a protothread.
Definition sha-256.h:94
void(* update)(const uint8_t *data, size_t len)
Processes a chunk of data.
Definition sha-256.h:78
Header file for the uIP TCP/IP stack.