ReactOS  0.4.15-dev-1070-ge1a01de
sha256.c
Go to the documentation of this file.
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 */
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) {
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 
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 }
static void init_buf_state(struct buffer_state *state, const void *input, size_t len)
Definition: sha256.c:52
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
static uint32_t right_rot(uint32_t value, unsigned int count)
Definition: sha256.c:43
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
static int calc_chunk(uint8_t chunk[CHUNK_SIZE], struct buffer_state *state)
Definition: sha256.c:62
GLuint GLuint GLsizei count
Definition: gl.h:1545
size_t len
Definition: sha256.c:37
const uint8_t * p
Definition: sha256.c:36
#define TOTAL_LEN_LEN
Definition: sha256.c:9
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
struct S1 s1
int single_one_delivered
Definition: sha256.c:39
int total_len_delivered
Definition: sha256.c:40
GLint left
Definition: glext.h:7726
static int state
Definition: maze.c:121
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
static const uint32_t k[]
Definition: sha256.c:24
size_t total_len
Definition: sha256.c:38
GLenum GLenum GLenum input
Definition: glext.h:9031
#define uint8_t
Definition: nsiface.idl:59
UINT32 uint32_t
Definition: types.h:75
GLfloat GLfloat p
Definition: glext.h:8902
#define uint32_t
Definition: nsiface.idl:61
#define CHUNK_SIZE
Definition: sha256.c:8
Definition: _hash_fun.h:40
#define memset(x, y, z)
Definition: compat.h:39