1 #include <stdint.h> 2 #include <string.h> 3 4 // Public domain code from https://github.com/amosnier/sha-2 5 6 // FIXME - x86 SHA extensions 7 8 #define CHUNK_SIZE 64 9 #define TOTAL_LEN_LEN 8 10 11 /* 12 * ABOUT bool: this file does not use bool in order to be as pre-C99 compatible as possible. 13 */ 14 15 /* 16 * Comments from pseudo-code at https://en.wikipedia.org/wiki/SHA-2 are reproduced here. 17 * When useful for clarification, portions of the pseudo-code are reproduced here too. 18 */ 19 20 /* 21 * Initialize array of round constants: 22 * (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): 23 */ 24 static const uint32_t k[] = { 25 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 26 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 27 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 28 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 29 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 30 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 31 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 32 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 33 }; 34 35 struct buffer_state { 36 const uint8_t * p; 37 size_t len; 38 size_t total_len; 39 int single_one_delivered; /* bool */ 40 int total_len_delivered; /* bool */ 41 }; 42 43 static inline uint32_t right_rot(uint32_t value, unsigned int count) 44 { 45 /* 46 * Defined behaviour in standard C for all count where 0 < count < 32, 47 * which is what we need here. 48 */ 49 return value >> count | value << (32 - count); 50 } 51 52 static void init_buf_state(struct buffer_state * state, const void * input, size_t len) 53 { 54 state->p = input; 55 state->len = len; 56 state->total_len = len; 57 state->single_one_delivered = 0; 58 state->total_len_delivered = 0; 59 } 60 61 /* Return value: bool */ 62 static int calc_chunk(uint8_t chunk[CHUNK_SIZE], struct buffer_state * state) 63 { 64 size_t space_in_chunk; 65 66 if (state->total_len_delivered) { 67 return 0; 68 } 69 70 if (state->len >= CHUNK_SIZE) { 71 memcpy(chunk, state->p, CHUNK_SIZE); 72 state->p += CHUNK_SIZE; 73 state->len -= CHUNK_SIZE; 74 return 1; 75 } 76 77 memcpy(chunk, state->p, state->len); 78 chunk += state->len; 79 space_in_chunk = CHUNK_SIZE - state->len; 80 state->p += state->len; 81 state->len = 0; 82 83 /* If we are here, space_in_chunk is one at minimum. */ 84 if (!state->single_one_delivered) { 85 *chunk++ = 0x80; 86 space_in_chunk -= 1; 87 state->single_one_delivered = 1; 88 } 89 90 /* 91 * Now: 92 * - either there is enough space left for the total length, and we can conclude, 93 * - or there is too little space left, and we have to pad the rest of this chunk with zeroes. 94 * In the latter case, we will conclude at the next invokation of this function. 95 */ 96 if (space_in_chunk >= TOTAL_LEN_LEN) { 97 const size_t left = space_in_chunk - TOTAL_LEN_LEN; 98 size_t len = state->total_len; 99 int i; 100 memset(chunk, 0x00, left); 101 chunk += left; 102 103 /* Storing of len * 8 as a big endian 64-bit without overflow. */ 104 chunk[7] = (uint8_t) (len << 3); 105 len >>= 5; 106 for (i = 6; i >= 0; i--) { 107 chunk[i] = (uint8_t) len; 108 len >>= 8; 109 } 110 state->total_len_delivered = 1; 111 } else { 112 memset(chunk, 0x00, space_in_chunk); 113 } 114 115 return 1; 116 } 117 118 /* 119 * Limitations: 120 * - Since input is a pointer in RAM, the data to hash should be in RAM, which could be a problem 121 * for large data sizes. 122 * - SHA algorithms theoretically operate on bit strings. However, this implementation has no support 123 * for bit string lengths that are not multiples of eight, and it really operates on arrays of bytes. 124 * In particular, the len parameter is a number of bytes. 125 */ 126 void calc_sha256(uint8_t* hash, const void* input, size_t len) 127 { 128 /* 129 * Note 1: All integers (expect indexes) are 32-bit unsigned integers and addition is calculated modulo 2^32. 130 * 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 131 * Note 3: The compression function uses 8 working variables, a through h 132 * Note 4: Big-endian convention is used when expressing the constants in this pseudocode, 133 * and when parsing message block data from bytes to words, for example, 134 * the first word of the input message "abc" after padding is 0x61626380 135 */ 136 137 /* 138 * Initialize hash values: 139 * (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): 140 */ 141 uint32_t h[] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; 142 unsigned i, j; 143 144 /* 512-bit chunks is what we will operate on. */ 145 uint8_t chunk[64]; 146 147 struct buffer_state state; 148 149 init_buf_state(&state, input, len); 150 151 while (calc_chunk(chunk, &state)) { 152 uint32_t ah[8]; 153 154 const uint8_t *p = chunk; 155 156 /* Initialize working variables to current hash value: */ 157 for (i = 0; i < 8; i++) 158 ah[i] = h[i]; 159 160 /* Compression function main loop: */ 161 for (i = 0; i < 4; i++) { 162 /* 163 * The w-array is really w[64], but since we only need 164 * 16 of them at a time, we save stack by calculating 165 * 16 at a time. 166 * 167 * This optimization was not there initially and the 168 * rest of the comments about w[64] are kept in their 169 * initial state. 170 */ 171 172 /* 173 * create a 64-entry message schedule array w[0..63] of 32-bit words 174 * (The initial values in w[0..63] don't matter, so many implementations zero them here) 175 * copy chunk into first 16 words w[0..15] of the message schedule array 176 */ 177 uint32_t w[16]; 178 179 for (j = 0; j < 16; j++) { 180 if (i == 0) { 181 w[j] = (uint32_t) p[0] << 24 | (uint32_t) p[1] << 16 | 182 (uint32_t) p[2] << 8 | (uint32_t) p[3]; 183 p += 4; 184 } else { 185 /* Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array: */ 186 const uint32_t s0 = right_rot(w[(j + 1) & 0xf], 7) ^ right_rot(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3); 187 const uint32_t s1 = right_rot(w[(j + 14) & 0xf], 17) ^ right_rot(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10); 188 w[j] = w[j] + s0 + w[(j + 9) & 0xf] + s1; 189 } 190 { 191 const uint32_t s1 = right_rot(ah[4], 6) ^ right_rot(ah[4], 11) ^ right_rot(ah[4], 25); 192 const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]); 193 const uint32_t temp1 = ah[7] + s1 + ch + k[i << 4 | j] + w[j]; 194 const uint32_t s0 = right_rot(ah[0], 2) ^ right_rot(ah[0], 13) ^ right_rot(ah[0], 22); 195 const uint32_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]); 196 const uint32_t temp2 = s0 + maj; 197 198 ah[7] = ah[6]; 199 ah[6] = ah[5]; 200 ah[5] = ah[4]; 201 ah[4] = ah[3] + temp1; 202 ah[3] = ah[2]; 203 ah[2] = ah[1]; 204 ah[1] = ah[0]; 205 ah[0] = temp1 + temp2; 206 } 207 } 208 } 209 210 /* Add the compressed chunk to the current hash value: */ 211 for (i = 0; i < 8; i++) 212 h[i] += ah[i]; 213 } 214 215 /* Produce the final hash value (big-endian): */ 216 for (i = 0, j = 0; i < 8; i++) 217 { 218 hash[j++] = (uint8_t) (h[i] >> 24); 219 hash[j++] = (uint8_t) (h[i] >> 16); 220 hash[j++] = (uint8_t) (h[i] >> 8); 221 hash[j++] = (uint8_t) h[i]; 222 } 223 } 224