1194ea909SVictor Perevertkin #include <stdint.h>
2194ea909SVictor Perevertkin #include <string.h>
3194ea909SVictor Perevertkin
4194ea909SVictor Perevertkin // Public domain code from https://github.com/amosnier/sha-2
5194ea909SVictor Perevertkin
6194ea909SVictor Perevertkin // FIXME - x86 SHA extensions
7194ea909SVictor Perevertkin
8194ea909SVictor Perevertkin #define CHUNK_SIZE 64
9194ea909SVictor Perevertkin #define TOTAL_LEN_LEN 8
10194ea909SVictor Perevertkin
11194ea909SVictor Perevertkin /*
12194ea909SVictor Perevertkin * ABOUT bool: this file does not use bool in order to be as pre-C99 compatible as possible.
13194ea909SVictor Perevertkin */
14194ea909SVictor Perevertkin
15194ea909SVictor Perevertkin /*
16194ea909SVictor Perevertkin * Comments from pseudo-code at https://en.wikipedia.org/wiki/SHA-2 are reproduced here.
17194ea909SVictor Perevertkin * When useful for clarification, portions of the pseudo-code are reproduced here too.
18194ea909SVictor Perevertkin */
19194ea909SVictor Perevertkin
20194ea909SVictor Perevertkin /*
21194ea909SVictor Perevertkin * Initialize array of round constants:
22194ea909SVictor Perevertkin * (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
23194ea909SVictor Perevertkin */
24194ea909SVictor Perevertkin static const uint32_t k[] = {
25194ea909SVictor Perevertkin 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
26194ea909SVictor Perevertkin 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
27194ea909SVictor Perevertkin 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
28194ea909SVictor Perevertkin 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
29194ea909SVictor Perevertkin 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
30194ea909SVictor Perevertkin 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
31194ea909SVictor Perevertkin 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
32194ea909SVictor Perevertkin 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
33194ea909SVictor Perevertkin };
34194ea909SVictor Perevertkin
35194ea909SVictor Perevertkin struct buffer_state {
36194ea909SVictor Perevertkin const uint8_t * p;
37194ea909SVictor Perevertkin size_t len;
38194ea909SVictor Perevertkin size_t total_len;
39194ea909SVictor Perevertkin int single_one_delivered; /* bool */
40194ea909SVictor Perevertkin int total_len_delivered; /* bool */
41194ea909SVictor Perevertkin };
42194ea909SVictor Perevertkin
right_rot(uint32_t value,unsigned int count)43194ea909SVictor Perevertkin static inline uint32_t right_rot(uint32_t value, unsigned int count)
44194ea909SVictor Perevertkin {
45194ea909SVictor Perevertkin /*
46194ea909SVictor Perevertkin * Defined behaviour in standard C for all count where 0 < count < 32,
47194ea909SVictor Perevertkin * which is what we need here.
48194ea909SVictor Perevertkin */
49194ea909SVictor Perevertkin return value >> count | value << (32 - count);
50194ea909SVictor Perevertkin }
51194ea909SVictor Perevertkin
init_buf_state(struct buffer_state * state,const void * input,size_t len)52194ea909SVictor Perevertkin static void init_buf_state(struct buffer_state * state, const void * input, size_t len)
53194ea909SVictor Perevertkin {
54194ea909SVictor Perevertkin state->p = input;
55194ea909SVictor Perevertkin state->len = len;
56194ea909SVictor Perevertkin state->total_len = len;
57194ea909SVictor Perevertkin state->single_one_delivered = 0;
58194ea909SVictor Perevertkin state->total_len_delivered = 0;
59194ea909SVictor Perevertkin }
60194ea909SVictor Perevertkin
61194ea909SVictor Perevertkin /* Return value: bool */
calc_chunk(uint8_t chunk[CHUNK_SIZE],struct buffer_state * state)62194ea909SVictor Perevertkin static int calc_chunk(uint8_t chunk[CHUNK_SIZE], struct buffer_state * state)
63194ea909SVictor Perevertkin {
64194ea909SVictor Perevertkin size_t space_in_chunk;
65194ea909SVictor Perevertkin
66194ea909SVictor Perevertkin if (state->total_len_delivered) {
67194ea909SVictor Perevertkin return 0;
68194ea909SVictor Perevertkin }
69194ea909SVictor Perevertkin
70194ea909SVictor Perevertkin if (state->len >= CHUNK_SIZE) {
71194ea909SVictor Perevertkin memcpy(chunk, state->p, CHUNK_SIZE);
72194ea909SVictor Perevertkin state->p += CHUNK_SIZE;
73194ea909SVictor Perevertkin state->len -= CHUNK_SIZE;
74194ea909SVictor Perevertkin return 1;
75194ea909SVictor Perevertkin }
76194ea909SVictor Perevertkin
77194ea909SVictor Perevertkin memcpy(chunk, state->p, state->len);
78194ea909SVictor Perevertkin chunk += state->len;
79194ea909SVictor Perevertkin space_in_chunk = CHUNK_SIZE - state->len;
80194ea909SVictor Perevertkin state->p += state->len;
81194ea909SVictor Perevertkin state->len = 0;
82194ea909SVictor Perevertkin
83194ea909SVictor Perevertkin /* If we are here, space_in_chunk is one at minimum. */
84194ea909SVictor Perevertkin if (!state->single_one_delivered) {
85194ea909SVictor Perevertkin *chunk++ = 0x80;
86194ea909SVictor Perevertkin space_in_chunk -= 1;
87194ea909SVictor Perevertkin state->single_one_delivered = 1;
88194ea909SVictor Perevertkin }
89194ea909SVictor Perevertkin
90194ea909SVictor Perevertkin /*
91194ea909SVictor Perevertkin * Now:
92194ea909SVictor Perevertkin * - either there is enough space left for the total length, and we can conclude,
93194ea909SVictor Perevertkin * - or there is too little space left, and we have to pad the rest of this chunk with zeroes.
94194ea909SVictor Perevertkin * In the latter case, we will conclude at the next invokation of this function.
95194ea909SVictor Perevertkin */
96194ea909SVictor Perevertkin if (space_in_chunk >= TOTAL_LEN_LEN) {
97194ea909SVictor Perevertkin const size_t left = space_in_chunk - TOTAL_LEN_LEN;
98194ea909SVictor Perevertkin size_t len = state->total_len;
99194ea909SVictor Perevertkin int i;
100194ea909SVictor Perevertkin memset(chunk, 0x00, left);
101194ea909SVictor Perevertkin chunk += left;
102194ea909SVictor Perevertkin
103194ea909SVictor Perevertkin /* Storing of len * 8 as a big endian 64-bit without overflow. */
104194ea909SVictor Perevertkin chunk[7] = (uint8_t) (len << 3);
105194ea909SVictor Perevertkin len >>= 5;
106194ea909SVictor Perevertkin for (i = 6; i >= 0; i--) {
107194ea909SVictor Perevertkin chunk[i] = (uint8_t) len;
108194ea909SVictor Perevertkin len >>= 8;
109194ea909SVictor Perevertkin }
110194ea909SVictor Perevertkin state->total_len_delivered = 1;
111194ea909SVictor Perevertkin } else {
112194ea909SVictor Perevertkin memset(chunk, 0x00, space_in_chunk);
113194ea909SVictor Perevertkin }
114194ea909SVictor Perevertkin
115194ea909SVictor Perevertkin return 1;
116194ea909SVictor Perevertkin }
117194ea909SVictor Perevertkin
118194ea909SVictor Perevertkin /*
119194ea909SVictor Perevertkin * Limitations:
120194ea909SVictor Perevertkin * - Since input is a pointer in RAM, the data to hash should be in RAM, which could be a problem
121194ea909SVictor Perevertkin * for large data sizes.
122194ea909SVictor Perevertkin * - SHA algorithms theoretically operate on bit strings. However, this implementation has no support
123194ea909SVictor Perevertkin * for bit string lengths that are not multiples of eight, and it really operates on arrays of bytes.
124194ea909SVictor Perevertkin * In particular, the len parameter is a number of bytes.
125194ea909SVictor Perevertkin */
calc_sha256(uint8_t * hash,const void * input,size_t len)126194ea909SVictor Perevertkin void calc_sha256(uint8_t* hash, const void* input, size_t len)
127194ea909SVictor Perevertkin {
128194ea909SVictor Perevertkin /*
129194ea909SVictor Perevertkin * Note 1: All integers (expect indexes) are 32-bit unsigned integers and addition is calculated modulo 2^32.
130194ea909SVictor Perevertkin * Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 = i = 63
131194ea909SVictor Perevertkin * Note 3: The compression function uses 8 working variables, a through h
132194ea909SVictor Perevertkin * Note 4: Big-endian convention is used when expressing the constants in this pseudocode,
133194ea909SVictor Perevertkin * and when parsing message block data from bytes to words, for example,
134194ea909SVictor Perevertkin * the first word of the input message "abc" after padding is 0x61626380
135194ea909SVictor Perevertkin */
136194ea909SVictor Perevertkin
137194ea909SVictor Perevertkin /*
138194ea909SVictor Perevertkin * Initialize hash values:
139194ea909SVictor Perevertkin * (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
140194ea909SVictor Perevertkin */
141194ea909SVictor Perevertkin uint32_t h[] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
142194ea909SVictor Perevertkin unsigned i, j;
143194ea909SVictor Perevertkin
144194ea909SVictor Perevertkin /* 512-bit chunks is what we will operate on. */
145194ea909SVictor Perevertkin uint8_t chunk[64];
146194ea909SVictor Perevertkin
147194ea909SVictor Perevertkin struct buffer_state state;
148194ea909SVictor Perevertkin
149194ea909SVictor Perevertkin init_buf_state(&state, input, len);
150194ea909SVictor Perevertkin
151194ea909SVictor Perevertkin while (calc_chunk(chunk, &state)) {
152194ea909SVictor Perevertkin uint32_t ah[8];
153194ea909SVictor Perevertkin
154194ea909SVictor Perevertkin const uint8_t *p = chunk;
155194ea909SVictor Perevertkin
156194ea909SVictor Perevertkin /* Initialize working variables to current hash value: */
157194ea909SVictor Perevertkin for (i = 0; i < 8; i++)
158194ea909SVictor Perevertkin ah[i] = h[i];
159194ea909SVictor Perevertkin
160194ea909SVictor Perevertkin /* Compression function main loop: */
161194ea909SVictor Perevertkin for (i = 0; i < 4; i++) {
162194ea909SVictor Perevertkin /*
163194ea909SVictor Perevertkin * The w-array is really w[64], but since we only need
164194ea909SVictor Perevertkin * 16 of them at a time, we save stack by calculating
165194ea909SVictor Perevertkin * 16 at a time.
166194ea909SVictor Perevertkin *
167194ea909SVictor Perevertkin * This optimization was not there initially and the
168194ea909SVictor Perevertkin * rest of the comments about w[64] are kept in their
169194ea909SVictor Perevertkin * initial state.
170194ea909SVictor Perevertkin */
171194ea909SVictor Perevertkin
172194ea909SVictor Perevertkin /*
173194ea909SVictor Perevertkin * create a 64-entry message schedule array w[0..63] of 32-bit words
174194ea909SVictor Perevertkin * (The initial values in w[0..63] don't matter, so many implementations zero them here)
175194ea909SVictor Perevertkin * copy chunk into first 16 words w[0..15] of the message schedule array
176194ea909SVictor Perevertkin */
177194ea909SVictor Perevertkin uint32_t w[16];
178194ea909SVictor Perevertkin
179194ea909SVictor Perevertkin for (j = 0; j < 16; j++) {
180194ea909SVictor Perevertkin if (i == 0) {
181194ea909SVictor Perevertkin w[j] = (uint32_t) p[0] << 24 | (uint32_t) p[1] << 16 |
182194ea909SVictor Perevertkin (uint32_t) p[2] << 8 | (uint32_t) p[3];
183194ea909SVictor Perevertkin p += 4;
184194ea909SVictor Perevertkin } else {
185194ea909SVictor Perevertkin /* Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array: */
186194ea909SVictor Perevertkin const uint32_t s0 = right_rot(w[(j + 1) & 0xf], 7) ^ right_rot(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3);
187194ea909SVictor Perevertkin const uint32_t s1 = right_rot(w[(j + 14) & 0xf], 17) ^ right_rot(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10);
188194ea909SVictor Perevertkin w[j] = w[j] + s0 + w[(j + 9) & 0xf] + s1;
189194ea909SVictor Perevertkin }
190*3ba42399SVictor Perevertkin {
191194ea909SVictor Perevertkin const uint32_t s1 = right_rot(ah[4], 6) ^ right_rot(ah[4], 11) ^ right_rot(ah[4], 25);
192194ea909SVictor Perevertkin const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]);
193194ea909SVictor Perevertkin const uint32_t temp1 = ah[7] + s1 + ch + k[i << 4 | j] + w[j];
194194ea909SVictor Perevertkin const uint32_t s0 = right_rot(ah[0], 2) ^ right_rot(ah[0], 13) ^ right_rot(ah[0], 22);
195194ea909SVictor Perevertkin const uint32_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]);
196194ea909SVictor Perevertkin const uint32_t temp2 = s0 + maj;
197194ea909SVictor Perevertkin
198194ea909SVictor Perevertkin ah[7] = ah[6];
199194ea909SVictor Perevertkin ah[6] = ah[5];
200194ea909SVictor Perevertkin ah[5] = ah[4];
201194ea909SVictor Perevertkin ah[4] = ah[3] + temp1;
202194ea909SVictor Perevertkin ah[3] = ah[2];
203194ea909SVictor Perevertkin ah[2] = ah[1];
204194ea909SVictor Perevertkin ah[1] = ah[0];
205194ea909SVictor Perevertkin ah[0] = temp1 + temp2;
206194ea909SVictor Perevertkin }
207194ea909SVictor Perevertkin }
208*3ba42399SVictor Perevertkin }
209194ea909SVictor Perevertkin
210194ea909SVictor Perevertkin /* Add the compressed chunk to the current hash value: */
211194ea909SVictor Perevertkin for (i = 0; i < 8; i++)
212194ea909SVictor Perevertkin h[i] += ah[i];
213194ea909SVictor Perevertkin }
214194ea909SVictor Perevertkin
215194ea909SVictor Perevertkin /* Produce the final hash value (big-endian): */
216194ea909SVictor Perevertkin for (i = 0, j = 0; i < 8; i++)
217194ea909SVictor Perevertkin {
218194ea909SVictor Perevertkin hash[j++] = (uint8_t) (h[i] >> 24);
219194ea909SVictor Perevertkin hash[j++] = (uint8_t) (h[i] >> 16);
220194ea909SVictor Perevertkin hash[j++] = (uint8_t) (h[i] >> 8);
221194ea909SVictor Perevertkin hash[j++] = (uint8_t) h[i];
222194ea909SVictor Perevertkin }
223194ea909SVictor Perevertkin }
224