1 |
//$Header$ |
2 |
//------------------------------------------------------------------------------------------------- |
3 |
//This file is part of "David T. Ashley's Shared Source Code", a set of shared components |
4 |
//integrated into many of David T. Ashley's projects. |
5 |
//------------------------------------------------------------------------------------------------- |
6 |
//This source code and any program in which it is compiled/used is provided under the MIT License, |
7 |
//reproduced below. |
8 |
//------------------------------------------------------------------------------------------------- |
9 |
//Permission is hereby granted, free of charge, to any person obtaining a copy of |
10 |
//this software and associated documentation files(the "Software"), to deal in the |
11 |
//Software without restriction, including without limitation the rights to use, |
12 |
//copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the |
13 |
//Software, and to permit persons to whom the Software is furnished to do so, |
14 |
//subject to the following conditions : |
15 |
// |
16 |
//The above copyright notice and this permission notice shall be included in all |
17 |
//copies or substantial portions of the Software. |
18 |
// |
19 |
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
20 |
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 |
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE |
22 |
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 |
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
24 |
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
25 |
//SOFTWARE. |
26 |
//------------------------------------------------------------------------------------------------- |
27 |
#define MODULE_ESRG_SHA512 |
28 |
|
29 |
#include <assert.h> |
30 |
#include <stddef.h> |
31 |
#include <string.h> |
32 |
|
33 |
#include "charfunc.h" |
34 |
#include "esrg_sha512.h" |
35 |
|
36 |
//This is a right rotation macro for efficiency. This |
37 |
//macro rotates a 64-bit quantity x right (cyclically) by |
38 |
//n bits. Nomenclature from FIPS 180-3. |
39 |
#define ESRG_SHA512_FUNC_ROTR(x, n) (((x) >> (n)) | ((x) << (64-(n)))) |
40 |
|
41 |
//This is a right shift macro for efficiency. This |
42 |
//macro shifts a 64-bit quantity x right by |
43 |
//n bits. Nomenclature from FIPS 180-3. |
44 |
#define ESRG_SHA512_FUNC_SHR(x, n) ((x) >> (n)) |
45 |
|
46 |
//These functions come directly from FIPS 180-3. |
47 |
#define ESRG_SHA512_FUNC_CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) |
48 |
#define ESRG_SHA512_FUNC_MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) |
49 |
#define ESRG_SHA512_FUNC_SIGMABIG_0(x) (ESRG_SHA512_FUNC_ROTR(x, 28) ^ ESRG_SHA512_FUNC_ROTR(x, 34) ^ ESRG_SHA512_FUNC_ROTR(x, 39)) |
50 |
#define ESRG_SHA512_FUNC_SIGMABIG_1(x) (ESRG_SHA512_FUNC_ROTR(x, 14) ^ ESRG_SHA512_FUNC_ROTR(x, 18) ^ ESRG_SHA512_FUNC_ROTR(x, 41)) |
51 |
#define ESRG_SHA512_FUNC_SIGMASMALL_0(x) (ESRG_SHA512_FUNC_ROTR(x, 1) ^ ESRG_SHA512_FUNC_ROTR(x, 8) ^ ESRG_SHA512_FUNC_SHR(x, 7)) |
52 |
#define ESRG_SHA512_FUNC_SIGMASMALL_1(x) (ESRG_SHA512_FUNC_ROTR(x, 19) ^ ESRG_SHA512_FUNC_ROTR(x, 61) ^ ESRG_SHA512_FUNC_SHR(x, 6)) |
53 |
|
54 |
//Constants, from FIPS 180-3. |
55 |
const unsigned __int64 ESRG_SHA512_K[80] = |
56 |
{0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, |
57 |
0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL, |
58 |
0x3956c25bf348b538UL, 0x59f111f1b605d019UL, |
59 |
0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL, |
60 |
0xd807aa98a3030242UL, 0x12835b0145706fbeUL, |
61 |
0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL, |
62 |
0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, |
63 |
0x9bdc06a725c71235UL, 0xc19bf174cf692694UL, |
64 |
0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, |
65 |
0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL, |
66 |
0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, |
67 |
0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL, |
68 |
0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, |
69 |
0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL, |
70 |
0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, |
71 |
0x06ca6351e003826fUL, 0x142929670a0e6e70UL, |
72 |
0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, |
73 |
0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL, |
74 |
0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, |
75 |
0x81c2c92e47edaee6UL, 0x92722c851482353bUL, |
76 |
0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, |
77 |
0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL, |
78 |
0xd192e819d6ef5218UL, 0xd69906245565a910UL, |
79 |
0xf40e35855771202aUL, 0x106aa07032bbd1b8UL, |
80 |
0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, |
81 |
0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL, |
82 |
0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, |
83 |
0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL, |
84 |
0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, |
85 |
0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL, |
86 |
0x90befffa23631e28UL, 0xa4506cebde82bde9UL, |
87 |
0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL, |
88 |
0xca273eceea26619cUL, 0xd186b8c721c0c207UL, |
89 |
0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL, |
90 |
0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, |
91 |
0x113f9804bef90daeUL, 0x1b710b35131c471bUL, |
92 |
0x28db77f523047d84UL, 0x32caab7b40c72493UL, |
93 |
0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL, |
94 |
0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, |
95 |
0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL}; |
96 |
|
97 |
|
98 |
void ESRG_SHA512_Sha512StateStructOpen(struct ESRG_SHA512_Sha512StateStruct *arg) |
99 |
{ |
100 |
assert(arg != NULL); |
101 |
|
102 |
memset(arg, 0, sizeof(struct ESRG_SHA512_Sha512StateStruct)); |
103 |
//Everything to zero, processed bitcount automatically set to zero. |
104 |
|
105 |
//This assignment comes directly from FIPS 180-3. |
106 |
arg->H0 = 0x6a09e667f3bcc908UL; |
107 |
arg->H1 = 0xbb67ae8584caa73bUL; |
108 |
arg->H2 = 0x3c6ef372fe94f82bUL; |
109 |
arg->H3 = 0xa54ff53a5f1d36f1UL; |
110 |
arg->H4 = 0x510e527fade682d1UL; |
111 |
arg->H5 = 0x9b05688c2b3e6c1fUL; |
112 |
arg->H6 = 0x1f83d9abfb41bd6bUL; |
113 |
arg->H7 = 0x5be0cd19137e2179UL; |
114 |
} |
115 |
|
116 |
|
117 |
//Copies the byte buffer to the word buffer within the state block. |
118 |
//This is done in a way which hides big-endian/little-endian concerns. |
119 |
// |
120 |
static void ESRG_SHA512_CopyBytesToWords(struct ESRG_SHA512_Sha512StateStruct *arg) |
121 |
{ |
122 |
unsigned int i; |
123 |
|
124 |
assert(arg != NULL); |
125 |
|
126 |
//Copy the buffer contents into the words. We need to be careful |
127 |
//to do this correctly, because of big-endian/little-endian concerns. |
128 |
//From FIPS 180-3 (alluded to, not really stated), the message is |
129 |
//loaded in from M[0] down to M[15]. Additionally, per the other |
130 |
//conventions in the document, the first byte is uppermost in each |
131 |
//word. |
132 |
for (i=0; i<16; i++) |
133 |
{ |
134 |
assert((i * 8 + 3) < 128); |
135 |
arg->M[i] = (((unsigned __int64)(arg->buf[i*8+0])) << 56) |
136 |
+ |
137 |
(((unsigned __int64)(arg->buf[i*8+1])) << 48) |
138 |
+ |
139 |
(((unsigned __int64)(arg->buf[i*8+2])) << 40) |
140 |
+ |
141 |
(((unsigned __int64)(arg->buf[i*8+3])) << 32) |
142 |
+ |
143 |
(((unsigned __int64)(arg->buf[i*8+4])) << 24) |
144 |
+ |
145 |
(((unsigned __int64)(arg->buf[i*8+5])) << 16) |
146 |
+ |
147 |
(((unsigned __int64)(arg->buf[i*8+6])) << 8) |
148 |
+ |
149 |
(((unsigned __int64)(arg->buf[i*8+7]))); |
150 |
} |
151 |
} |
152 |
|
153 |
|
154 |
//Copies the buffer of words into a string buffer of string length 128, and also places |
155 |
//the zero terminator, which means that the string supplied by the caller must be of size |
156 |
//129 or larger. |
157 |
// |
158 |
static void ESRG_SHA512_CopyWordsToStringBuffer(struct ESRG_SHA512_Sha512ResultStruct *arg) |
159 |
{ |
160 |
unsigned int i, j; |
161 |
unsigned char *puc; |
162 |
unsigned __int64 woi; |
163 |
|
164 |
assert(arg != NULL); |
165 |
|
166 |
//Copy the buffer contents into the words. We need to be careful |
167 |
//to do this correctly, because of big-endian/little-endian concerns. |
168 |
//From FIPS 180-3 (alluded to, not really stated), the message is |
169 |
//loaded in from M[0] down to M[15]. Additionally, per the other |
170 |
//conventions in the document, the first byte is uppermost in each |
171 |
//word. |
172 |
for (i=0; i<8; i++) |
173 |
{ |
174 |
woi = arg->sha512_words[i]; |
175 |
|
176 |
//Form a pointer to the buffer location of interest. We work |
177 |
//backwards. |
178 |
puc = (unsigned char *)(arg->sha512_chars) + (i * 16) + 15; |
179 |
|
180 |
//Fill in the buffer. |
181 |
for (j=0; j<16; j++) |
182 |
{ |
183 |
*puc = (unsigned char)CHARFUNC_nibble_to_lc_hex_digit((int)(woi & 0xF)); |
184 |
woi >>= 4; |
185 |
puc--; |
186 |
} |
187 |
} |
188 |
|
189 |
//Place the zero string terminator. |
190 |
arg->sha512_chars[128] = 0; |
191 |
} |
192 |
|
193 |
|
194 |
//Does the SHA-512 rounds as specified by FIPS 180-3. |
195 |
|
196 |
static void ESRG_SHA512_DoSha512Rounds(struct ESRG_SHA512_Sha512StateStruct *arg) |
197 |
{ |
198 |
int i; |
199 |
//Iteration variable. |
200 |
unsigned __int64 T1, T2; |
201 |
//Temporary variables. Nomenclature is from FIPS 180-3. |
202 |
unsigned __int64 M[16]; |
203 |
//Buffer of message block to avoid repeated dereferences. |
204 |
unsigned __int64 H[8]; |
205 |
//Buffer of hash state to avoid repeated dereferences. |
206 |
unsigned __int64 W[80]; |
207 |
//Working variable. Nomenclature directly from FIPS 180-3. |
208 |
unsigned __int64 a, b, c, d, e, f, g, h; |
209 |
//Nomenclature above directly from FIPS 180-3. |
210 |
|
211 |
assert(arg != NULL); |
212 |
|
213 |
//Copy bytes into words. |
214 |
ESRG_SHA512_CopyBytesToWords(arg); |
215 |
|
216 |
//Copy out the message buffer for speed. This should avoid repeated |
217 |
//dereferences. |
218 |
M[ 0] = arg->M[ 0]; |
219 |
M[ 1] = arg->M[ 1]; |
220 |
M[ 2] = arg->M[ 2]; |
221 |
M[ 3] = arg->M[ 3]; |
222 |
M[ 4] = arg->M[ 4]; |
223 |
M[ 5] = arg->M[ 5]; |
224 |
M[ 6] = arg->M[ 6]; |
225 |
M[ 7] = arg->M[ 7]; |
226 |
M[ 8] = arg->M[ 8]; |
227 |
M[ 9] = arg->M[ 9]; |
228 |
M[10] = arg->M[10]; |
229 |
M[11] = arg->M[11]; |
230 |
M[12] = arg->M[12]; |
231 |
M[13] = arg->M[13]; |
232 |
M[14] = arg->M[14]; |
233 |
M[15] = arg->M[15]; |
234 |
|
235 |
//Copy out the hash state for speed. This should avoid repeated dereferences. |
236 |
H[0] = arg->H0; |
237 |
H[1] = arg->H1; |
238 |
H[2] = arg->H2; |
239 |
H[3] = arg->H3; |
240 |
H[4] = arg->H4; |
241 |
H[5] = arg->H5; |
242 |
H[6] = arg->H6; |
243 |
H[7] = arg->H7; |
244 |
|
245 |
//Prepare the message schedule. The nomenclature comes directly from FIPS 180-3. |
246 |
W[ 0] = M[ 0]; |
247 |
W[ 1] = M[ 1]; |
248 |
W[ 2] = M[ 2]; |
249 |
W[ 3] = M[ 3]; |
250 |
W[ 4] = M[ 4]; |
251 |
W[ 5] = M[ 5]; |
252 |
W[ 6] = M[ 6]; |
253 |
W[ 7] = M[ 7]; |
254 |
W[ 8] = M[ 8]; |
255 |
W[ 9] = M[ 9]; |
256 |
W[10] = M[10]; |
257 |
W[11] = M[11]; |
258 |
W[12] = M[12]; |
259 |
W[13] = M[13]; |
260 |
W[14] = M[14]; |
261 |
W[15] = M[15]; |
262 |
|
263 |
for (i=16; i<80; i++) |
264 |
{ |
265 |
W[i] = ESRG_SHA512_FUNC_SIGMASMALL_1(W[i-2]) |
266 |
+ W[i-7] |
267 |
+ ESRG_SHA512_FUNC_SIGMASMALL_0(W[i-15]) |
268 |
+ W[i-16]; |
269 |
} |
270 |
|
271 |
//Initialize the 8 working variables as specified in FIPS 180-3. |
272 |
a = H[0]; |
273 |
b = H[1]; |
274 |
c = H[2]; |
275 |
d = H[3]; |
276 |
e = H[4]; |
277 |
f = H[5]; |
278 |
g = H[6]; |
279 |
h = H[7]; |
280 |
|
281 |
//Perform the rounds as specified in FIPS 180-3. Nomenclature below comes from |
282 |
//FIPS 180-3. |
283 |
for (i=0; i<80; i++) |
284 |
{ |
285 |
T1 = h |
286 |
+ ESRG_SHA512_FUNC_SIGMABIG_1(e) |
287 |
+ ESRG_SHA512_FUNC_CH(e, f, g) |
288 |
+ ESRG_SHA512_K[i] |
289 |
+ W[i]; |
290 |
// |
291 |
T2 = ESRG_SHA512_FUNC_SIGMABIG_0(a) |
292 |
+ ESRG_SHA512_FUNC_MAJ(a, b, c); |
293 |
// |
294 |
h = g; |
295 |
// |
296 |
g = f; |
297 |
// |
298 |
f = e; |
299 |
// |
300 |
e = d + T1; |
301 |
// |
302 |
d = c; |
303 |
// |
304 |
c = b; |
305 |
// |
306 |
b = a; |
307 |
// |
308 |
a = T1 + T2; |
309 |
} |
310 |
|
311 |
//Compute the next hash value. The nomenclature comes from FIPS 180-3. |
312 |
H[0] = a + H[0]; |
313 |
H[1] = b + H[1]; |
314 |
H[2] = c + H[2]; |
315 |
H[3] = d + H[3]; |
316 |
H[4] = e + H[4]; |
317 |
H[5] = f + H[5]; |
318 |
H[6] = g + H[6]; |
319 |
H[7] = h + H[7]; |
320 |
|
321 |
//Place the local variables back in the structure. This the only state that |
322 |
//gets preserved between the operation of doing the rounds. |
323 |
arg->H0 = H[0]; |
324 |
arg->H1 = H[1]; |
325 |
arg->H2 = H[2]; |
326 |
arg->H3 = H[3]; |
327 |
arg->H4 = H[4]; |
328 |
arg->H5 = H[5]; |
329 |
arg->H6 = H[6]; |
330 |
arg->H7 = H[7]; |
331 |
} |
332 |
|
333 |
|
334 |
void ESRG_SHA512_Sha512StateStructAddData(struct ESRG_SHA512_Sha512StateStruct *arg, |
335 |
void *pointer_in, |
336 |
unsigned len) |
337 |
{ |
338 |
unsigned int low_32; |
339 |
unsigned int byte_offset; |
340 |
unsigned char *data; |
341 |
|
342 |
assert(arg != NULL); |
343 |
assert(pointer_in != NULL); |
344 |
|
345 |
data = (unsigned char *)pointer_in; |
346 |
//It is easier to do it this way, rather than cast all the time. |
347 |
|
348 |
low_32 = (unsigned int)arg->bit_count; |
349 |
//Copy off the least significant bits. Easier to do once. We only |
350 |
//need the 32 least significant because the block size is 0 modulo 1024. |
351 |
|
352 |
byte_offset = low_32 >> 3; |
353 |
//This gives our byte offset, up to 500+Mb or so. |
354 |
|
355 |
while(len--) |
356 |
{ |
357 |
//We process rounds AFTER a byte is added to the buffer. So |
358 |
//it is always safe to add a byte first. |
359 |
arg->buf[byte_offset & 0x7F] = *data; |
360 |
|
361 |
//Nothing to do unless this was the final byte of the buffer. |
362 |
if ((byte_offset & 0x7F) == 127) |
363 |
{ |
364 |
ESRG_SHA512_DoSha512Rounds(arg); |
365 |
} |
366 |
|
367 |
//Increment. |
368 |
data++; |
369 |
byte_offset++; |
370 |
arg->bit_count += 8; |
371 |
} |
372 |
} |
373 |
|
374 |
|
375 |
void ESRG_SHA512_Sha512StateStructClose(struct ESRG_SHA512_Sha512StateStruct *state, |
376 |
struct ESRG_SHA512_Sha512ResultStruct *result) |
377 |
{ |
378 |
unsigned __int64 msglen; |
379 |
//Used to hold message length before we pad the message. |
380 |
unsigned char c80 = 0x80; |
381 |
//Used to append the "1" per FIPS 180-3. |
382 |
unsigned char c00 = 0x00; |
383 |
//Used to add 0's per FIPS 180-3. |
384 |
unsigned char length_buf[16]; |
385 |
//Buffer used to form the message length and append it to the message per FIPS 180-3. |
386 |
|
387 |
//Be sure the input pointers aren't obviously invalid. |
388 |
assert(state != NULL); |
389 |
assert(result != NULL); |
390 |
|
391 |
//Snapshot the message length. We'll be changing it when we pad the message. |
392 |
msglen = state->bit_count; |
393 |
|
394 |
//Add the required "1" to the end of the message, per FIPS 180-3. Because |
395 |
//this software module only allows the addition of bytes (not bits), adding the |
396 |
//"1" will always involve adding the byte 0x80. |
397 |
ESRG_SHA512_Sha512StateStructAddData(state, &c80, 1); |
398 |
|
399 |
//Add enough 0's to the message so that we have exactly room for 16 bytes (128 bits) |
400 |
//of length information at the end of the message. |
401 |
while ((state->bit_count & 0x3FF) != 896) |
402 |
ESRG_SHA512_Sha512StateStructAddData(state, &c00, 1); |
403 |
|
404 |
//Calculate the length as a series of bytes. |
405 |
length_buf[ 0] = 0; |
406 |
length_buf[ 1] = 0; |
407 |
length_buf[ 2] = 0; |
408 |
length_buf[ 3] = 0; |
409 |
length_buf[ 4] = 0; |
410 |
length_buf[ 5] = 0; |
411 |
length_buf[ 6] = 0; |
412 |
length_buf[ 7] = 0; |
413 |
length_buf[ 8] = (unsigned char)((msglen >> 56) & 0xFF); |
414 |
length_buf[ 9] = (unsigned char)((msglen >> 48) & 0xFF); |
415 |
length_buf[10] = (unsigned char)((msglen >> 40) & 0xFF); |
416 |
length_buf[11] = (unsigned char)((msglen >> 32) & 0xFF); |
417 |
length_buf[12] = (unsigned char)((msglen >> 24) & 0xFF); |
418 |
length_buf[13] = (unsigned char)((msglen >> 16) & 0xFF); |
419 |
length_buf[14] = (unsigned char)((msglen >> 8) & 0xFF); |
420 |
length_buf[15] = (unsigned char)((msglen) & 0xFF); |
421 |
|
422 |
//Add the length to the message. This should work out to generate the |
423 |
//final manipulation round. |
424 |
ESRG_SHA512_Sha512StateStructAddData(state, length_buf, 16); |
425 |
|
426 |
//Copy the words from the state vector to the result vector. |
427 |
result->sha512_words[0] = state->H0; |
428 |
result->sha512_words[1] = state->H1; |
429 |
result->sha512_words[2] = state->H2; |
430 |
result->sha512_words[3] = state->H3; |
431 |
result->sha512_words[4] = state->H4; |
432 |
result->sha512_words[5] = state->H5; |
433 |
result->sha512_words[6] = state->H6; |
434 |
result->sha512_words[7] = state->H7; |
435 |
|
436 |
//Form a string from the hash vector. |
437 |
ESRG_SHA512_CopyWordsToStringBuffer(result); |
438 |
|
439 |
//Destroy the state, which may contain sensitive information. |
440 |
//This idea came from Rivest's sample code. |
441 |
memset(state, 0, sizeof(struct ESRG_SHA512_Sha512StateStruct)); |
442 |
} |
443 |
|
444 |
|
445 |
//Returns version control string for file. |
446 |
// |
447 |
const char *ESRG_SHA512_cvcinfo(void) |
448 |
{ |
449 |
return ("$Header$"); |
450 |
} |
451 |
|
452 |
|
453 |
//Returns version control string for associated .H file. |
454 |
// |
455 |
const char *ESRG_SHA512_hvcinfo(void) |
456 |
{ |
457 |
return (ESRG_SHA512_H_VERSION); |
458 |
} |
459 |
|
460 |
//End of esrg_sha512.c. |