2 * SHA-512 algorithm as described at
4 * http://csrc.nist.gov/cryptval/shs.html
12 * Arithmetic implementations. Note that AND, XOR and NOT can
13 * overlap destination with one source, but the others can't.
15 #define add(r,x,y) ( r.lo = y.lo + x.lo, \
16 r.hi = y.hi + x.hi + ((uint32)r.lo < (uint32)y.lo) )
17 #define rorB(r,x,y) ( r.lo = ((uint32)x.hi >> ((y)-32)) | ((uint32)x.lo << (64-(y))), \
18 r.hi = ((uint32)x.lo >> ((y)-32)) | ((uint32)x.hi << (64-(y))) )
19 #define rorL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
20 r.hi = ((uint32)x.hi >> (y)) | ((uint32)x.lo << (32-(y))) )
21 #define shrB(r,x,y) ( r.lo = (uint32)x.hi >> ((y)-32), r.hi = 0 )
22 #define shrL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
23 r.hi = (uint32)x.hi >> (y) )
24 #define and(r,x,y) ( r.lo = x.lo & y.lo, r.hi = x.hi & y.hi )
25 #define xor(r,x,y) ( r.lo = x.lo ^ y.lo, r.hi = x.hi ^ y.hi )
26 #define not(r,x) ( r.lo = ~x.lo, r.hi = ~x.hi )
27 #define INIT(h,l) { h, l }
28 #define BUILD(r,h,l) ( r.hi = h, r.lo = l )
29 #define EXTRACT(h,l,r) ( h = r.hi, l = r.lo )
31 /* ----------------------------------------------------------------------
32 * Core SHA512 algorithm: processes 16-doubleword blocks into a
36 #define Ch(r,t,x,y,z) ( not(t,x), and(r,t,z), and(t,x,y), xor(r,r,t) )
37 #define Maj(r,t,x,y,z) ( and(r,x,y), and(t,x,z), xor(r,r,t), \
38 and(t,y,z), xor(r,r,t) )
39 #define bigsigma0(r,t,x) ( rorL(r,x,28), rorB(t,x,34), xor(r,r,t), \
40 rorB(t,x,39), xor(r,r,t) )
41 #define bigsigma1(r,t,x) ( rorL(r,x,14), rorL(t,x,18), xor(r,r,t), \
42 rorB(t,x,41), xor(r,r,t) )
43 #define smallsigma0(r,t,x) ( rorL(r,x,1), rorL(t,x,8), xor(r,r,t), \
44 shrL(t,x,7), xor(r,r,t) )
45 #define smallsigma1(r,t,x) ( rorL(r,x,19), rorB(t,x,61), xor(r,r,t), \
46 shrL(t,x,6), xor(r,r,t) )
48 static void SHA512_Core_Init(SHA512_State *s) {
49 static const uint64 iv[] = {
50 INIT(0x6a09e667, 0xf3bcc908),
51 INIT(0xbb67ae85, 0x84caa73b),
52 INIT(0x3c6ef372, 0xfe94f82b),
53 INIT(0xa54ff53a, 0x5f1d36f1),
54 INIT(0x510e527f, 0xade682d1),
55 INIT(0x9b05688c, 0x2b3e6c1f),
56 INIT(0x1f83d9ab, 0xfb41bd6b),
57 INIT(0x5be0cd19, 0x137e2179),
60 for (i = 0; i < 8; i++)
64 static void SHA512_Block(SHA512_State *s, uint64 *block) {
66 uint64 a,b,c,d,e,f,g,h;
67 static const uint64 k[] = {
68 INIT(0x428a2f98, 0xd728ae22), INIT(0x71374491, 0x23ef65cd),
69 INIT(0xb5c0fbcf, 0xec4d3b2f), INIT(0xe9b5dba5, 0x8189dbbc),
70 INIT(0x3956c25b, 0xf348b538), INIT(0x59f111f1, 0xb605d019),
71 INIT(0x923f82a4, 0xaf194f9b), INIT(0xab1c5ed5, 0xda6d8118),
72 INIT(0xd807aa98, 0xa3030242), INIT(0x12835b01, 0x45706fbe),
73 INIT(0x243185be, 0x4ee4b28c), INIT(0x550c7dc3, 0xd5ffb4e2),
74 INIT(0x72be5d74, 0xf27b896f), INIT(0x80deb1fe, 0x3b1696b1),
75 INIT(0x9bdc06a7, 0x25c71235), INIT(0xc19bf174, 0xcf692694),
76 INIT(0xe49b69c1, 0x9ef14ad2), INIT(0xefbe4786, 0x384f25e3),
77 INIT(0x0fc19dc6, 0x8b8cd5b5), INIT(0x240ca1cc, 0x77ac9c65),
78 INIT(0x2de92c6f, 0x592b0275), INIT(0x4a7484aa, 0x6ea6e483),
79 INIT(0x5cb0a9dc, 0xbd41fbd4), INIT(0x76f988da, 0x831153b5),
80 INIT(0x983e5152, 0xee66dfab), INIT(0xa831c66d, 0x2db43210),
81 INIT(0xb00327c8, 0x98fb213f), INIT(0xbf597fc7, 0xbeef0ee4),
82 INIT(0xc6e00bf3, 0x3da88fc2), INIT(0xd5a79147, 0x930aa725),
83 INIT(0x06ca6351, 0xe003826f), INIT(0x14292967, 0x0a0e6e70),
84 INIT(0x27b70a85, 0x46d22ffc), INIT(0x2e1b2138, 0x5c26c926),
85 INIT(0x4d2c6dfc, 0x5ac42aed), INIT(0x53380d13, 0x9d95b3df),
86 INIT(0x650a7354, 0x8baf63de), INIT(0x766a0abb, 0x3c77b2a8),
87 INIT(0x81c2c92e, 0x47edaee6), INIT(0x92722c85, 0x1482353b),
88 INIT(0xa2bfe8a1, 0x4cf10364), INIT(0xa81a664b, 0xbc423001),
89 INIT(0xc24b8b70, 0xd0f89791), INIT(0xc76c51a3, 0x0654be30),
90 INIT(0xd192e819, 0xd6ef5218), INIT(0xd6990624, 0x5565a910),
91 INIT(0xf40e3585, 0x5771202a), INIT(0x106aa070, 0x32bbd1b8),
92 INIT(0x19a4c116, 0xb8d2d0c8), INIT(0x1e376c08, 0x5141ab53),
93 INIT(0x2748774c, 0xdf8eeb99), INIT(0x34b0bcb5, 0xe19b48a8),
94 INIT(0x391c0cb3, 0xc5c95a63), INIT(0x4ed8aa4a, 0xe3418acb),
95 INIT(0x5b9cca4f, 0x7763e373), INIT(0x682e6ff3, 0xd6b2b8a3),
96 INIT(0x748f82ee, 0x5defb2fc), INIT(0x78a5636f, 0x43172f60),
97 INIT(0x84c87814, 0xa1f0ab72), INIT(0x8cc70208, 0x1a6439ec),
98 INIT(0x90befffa, 0x23631e28), INIT(0xa4506ceb, 0xde82bde9),
99 INIT(0xbef9a3f7, 0xb2c67915), INIT(0xc67178f2, 0xe372532b),
100 INIT(0xca273ece, 0xea26619c), INIT(0xd186b8c7, 0x21c0c207),
101 INIT(0xeada7dd6, 0xcde0eb1e), INIT(0xf57d4f7f, 0xee6ed178),
102 INIT(0x06f067aa, 0x72176fba), INIT(0x0a637dc5, 0xa2c898a6),
103 INIT(0x113f9804, 0xbef90dae), INIT(0x1b710b35, 0x131c471b),
104 INIT(0x28db77f5, 0x23047d84), INIT(0x32caab7b, 0x40c72493),
105 INIT(0x3c9ebe0a, 0x15c9bebc), INIT(0x431d67c4, 0x9c100d4c),
106 INIT(0x4cc5d4be, 0xcb3e42b6), INIT(0x597f299c, 0xfc657e2a),
107 INIT(0x5fcb6fab, 0x3ad6faec), INIT(0x6c44198c, 0x4a475817),
112 for (t = 0; t < 16; t++)
115 for (t = 16; t < 80; t++) {
117 smallsigma1(p, tmp, w[t-2]);
118 smallsigma0(q, tmp, w[t-15]);
121 add(w[t], p, w[t-16]);
124 a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];
125 e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];
127 for (t = 0; t < 80; t+=8) {
130 #define ROUND(j,a,b,c,d,e,f,g,h) \
131 bigsigma1(p, tmp, e); \
132 Ch(q, tmp, e, f, g); \
137 bigsigma0(p, tmp, a); \
138 Maj(tmp, q, a, b, c); \
144 ROUND(t+0, a,b,c,d,e,f,g,h);
145 ROUND(t+1, h,a,b,c,d,e,f,g);
146 ROUND(t+2, g,h,a,b,c,d,e,f);
147 ROUND(t+3, f,g,h,a,b,c,d,e);
148 ROUND(t+4, e,f,g,h,a,b,c,d);
149 ROUND(t+5, d,e,f,g,h,a,b,c);
150 ROUND(t+6, c,d,e,f,g,h,a,b);
151 ROUND(t+7, b,c,d,e,f,g,h,a);
156 #define UPDATE(state, local) ( tmp = state, add(state, tmp, local) )
157 UPDATE(s->h[0], a); UPDATE(s->h[1], b);
158 UPDATE(s->h[2], c); UPDATE(s->h[3], d);
159 UPDATE(s->h[4], e); UPDATE(s->h[5], f);
160 UPDATE(s->h[6], g); UPDATE(s->h[7], h);
164 /* ----------------------------------------------------------------------
165 * Outer SHA512 algorithm: take an arbitrary length byte string,
166 * convert it into 16-doubleword blocks with the prescribed padding
167 * at the end, and pass those blocks to the core SHA512 algorithm.
170 void SHA512_Init(SHA512_State *s) {
174 for (i = 0; i < 4; i++)
178 void SHA512_Bytes(SHA512_State *s, const void *p, int len) {
179 unsigned char *q = (unsigned char *)p;
180 uint64 wordblock[16];
185 * Update the length field.
187 for (i = 0; i < 4; i++) {
189 lenw = (s->len[i] < lenw);
192 if (s->blkused && s->blkused+len < BLKSIZE) {
194 * Trivial case: just add to the block.
196 memcpy(s->block + s->blkused, q, len);
200 * We must complete and process at least one block.
202 while (s->blkused + len >= BLKSIZE) {
203 memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
204 q += BLKSIZE - s->blkused;
205 len -= BLKSIZE - s->blkused;
206 /* Now process the block. Gather bytes big-endian into words */
207 for (i = 0; i < 16; i++) {
209 h = ( ((uint32)s->block[i*8+0]) << 24 ) |
210 ( ((uint32)s->block[i*8+1]) << 16 ) |
211 ( ((uint32)s->block[i*8+2]) << 8 ) |
212 ( ((uint32)s->block[i*8+3]) << 0 );
213 l = ( ((uint32)s->block[i*8+4]) << 24 ) |
214 ( ((uint32)s->block[i*8+5]) << 16 ) |
215 ( ((uint32)s->block[i*8+6]) << 8 ) |
216 ( ((uint32)s->block[i*8+7]) << 0 );
217 BUILD(wordblock[i], h, l);
219 SHA512_Block(s, wordblock);
222 memcpy(s->block, q, len);
227 void SHA512_Final(SHA512_State *s, unsigned char *digest) {
230 unsigned char c[BLKSIZE];
233 if (s->blkused >= BLKSIZE-16)
234 pad = (BLKSIZE-16) + BLKSIZE - s->blkused;
236 pad = (BLKSIZE-16) - s->blkused;
239 uint32 lenhi = s->len[i];
240 uint32 lenlo = i > 0 ? s->len[i-1] : 0;
241 len[i] = (lenhi << 3) | (lenlo >> (32-3));
246 SHA512_Bytes(s, &c, pad);
248 for (i = 0; i < 4; i++) {
249 c[i*4+0] = (len[3-i] >> 24) & 0xFF;
250 c[i*4+1] = (len[3-i] >> 16) & 0xFF;
251 c[i*4+2] = (len[3-i] >> 8) & 0xFF;
252 c[i*4+3] = (len[3-i] >> 0) & 0xFF;
255 SHA512_Bytes(s, &c, 16);
257 for (i = 0; i < 8; i++) {
259 EXTRACT(h, l, s->h[i]);
260 digest[i*8+0] = (h >> 24) & 0xFF;
261 digest[i*8+1] = (h >> 16) & 0xFF;
262 digest[i*8+2] = (h >> 8) & 0xFF;
263 digest[i*8+3] = (h >> 0) & 0xFF;
264 digest[i*8+4] = (l >> 24) & 0xFF;
265 digest[i*8+5] = (l >> 16) & 0xFF;
266 digest[i*8+6] = (l >> 8) & 0xFF;
267 digest[i*8+7] = (l >> 0) & 0xFF;
271 void SHA512_Simple(const void *p, int len, unsigned char *output) {
275 SHA512_Bytes(&s, p, len);
276 SHA512_Final(&s, output);
277 smemclr(&s, sizeof(s));
287 unsigned char digest[64];
291 const char *teststring;
292 unsigned char digest512[64];
295 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
296 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
297 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
298 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
299 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
300 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
301 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
302 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
304 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
305 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", {
306 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
307 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
308 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
309 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
310 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
311 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
312 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
313 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,
316 0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,
317 0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,
318 0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,
319 0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,
320 0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,
321 0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,
322 0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,
323 0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b,
329 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
330 if (tests[i].teststring) {
331 SHA512_Simple(tests[i].teststring,
332 strlen(tests[i].teststring), digest);
337 for (n = 0; n < 1000000 / 40; n++)
338 SHA512_Bytes(&s, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
340 SHA512_Final(&s, digest);
342 for (j = 0; j < 64; j++) {
343 if (digest[j] != tests[i].digest512[j]) {
345 "\"%s\" digest512 byte %d should be 0x%02x, is 0x%02x\n",
346 tests[i].teststring, j, tests[i].digest512[j],
354 printf("%d errors\n", errors);