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