better standard compliance
[rofl0r-kripto.git] / lib / hash / blake512.c
blobc37a14a959f24e1079b1694887c84c9929ad90e1
1 /*
2 * Copyright (C) 2013 Gregor Pintar <grpintar@gmail.com>
4 * Permission is granted to deal in this work without any restriction,
5 * including unlimited rights to use, publicly perform, publish,
6 * reproduce, relicence, modify, merge, and/or distribute in any form,
7 * for any purpose, with or without fee, and by any means.
9 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind,
10 * to the utmost extent permitted by applicable law. In no event
11 * shall a licensor, author or contributor be held liable for any
12 * issues arising in any way out of dealing in the work.
15 #include <stdint.h>
16 #include <stddef.h>
17 #include <stdlib.h>
18 #include <limits.h>
19 #include <assert.h>
21 #include <kripto/cast.h>
22 #include <kripto/loadstore.h>
23 #include <kripto/rotate.h>
24 #include <kripto/memwipe.h>
25 #include <kripto/hash.h>
26 #include <kripto/desc/hash.h>
27 #include <kripto/object/hash.h>
29 #include <kripto/hash/blake512.h>
31 struct kripto_hash
33 struct kripto_hash_object obj;
34 unsigned int r;
35 uint64_t h[8];
36 /* uint64_t s[4]; */
37 uint64_t len[2];
38 uint8_t buf[128];
39 unsigned int i;
40 unsigned int o; /* output length, 0 after finish */
43 static const uint8_t sigma[10][16] =
45 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
46 {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
47 {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
48 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
49 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
50 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
51 {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
52 {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
53 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
54 {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}
57 static const uint64_t k[16] =
59 0x243F6A8885A308D3, 0x13198A2E03707344,
60 0xA4093822299F31D0, 0x082EFA98EC4E6C89,
61 0x452821E638D01377, 0xBE5466CF34E90C6C,
62 0xC0AC29B7C97C50DD, 0x3F84D5B5B5470917,
63 0x9216D5D98979FB1B, 0xD1310BA698DFB5AC,
64 0x2FFD72DBD01ADFB7, 0xB8E1AFED6A267E96,
65 0xBA7C9045F12C7F99, 0x24A19947B3916CF7,
66 0x0801F2E2858EFC16, 0x636920D871574E69
69 static kripto_hash *blake512_recreate
71 kripto_hash *s,
72 unsigned int r,
73 size_t len
76 s->len[0] = s->len[1] = s->i = 0;
77 s->o = len;
79 s->r = r;
80 if(!s->r) s->r = 16;
82 if(len > 48)
84 /* 512 */
85 s->h[0] = 0x6A09E667F3BCC908;
86 s->h[1] = 0xBB67AE8584CAA73B;
87 s->h[2] = 0x3C6EF372FE94F82B;
88 s->h[3] = 0xA54FF53A5F1D36F1;
89 s->h[4] = 0x510E527FADE682D1;
90 s->h[5] = 0x9B05688C2B3E6C1F;
91 s->h[6] = 0x1F83D9ABFB41BD6B;
92 s->h[7] = 0x5BE0CD19137E2179;
94 else
96 /* 384 */
97 s->h[0] = 0xCBBB9D5DC1059ED8;
98 s->h[1] = 0x629A292A367CD507;
99 s->h[2] = 0x9159015A3070DD17;
100 s->h[3] = 0x152FECD8F70E5939;
101 s->h[4] = 0x67332667FFC00B31;
102 s->h[5] = 0x8EB44A8768581511;
103 s->h[6] = 0xDB0C2E0D64F98FA7;
104 s->h[7] = 0x47B5481DBEFA4FA4;
107 return s;
110 #define G(A, B, C, D, M, S0, S1) \
112 A += B + ((M)[(S0)] ^ k[(S1)]); \
113 D = ROR64(D ^ A, 32); \
114 C += D; \
115 B = ROR64(B ^ C, 25); \
117 A += B + ((M)[(S1)] ^ k[(S0)]); \
118 D = ROR64(D ^ A, 16); \
119 C += D; \
120 B = ROR64(B ^ C, 11); \
123 static void blake512_process(kripto_hash *s, const uint8_t *data)
125 uint64_t x0;
126 uint64_t x1;
127 uint64_t x2;
128 uint64_t x3;
129 uint64_t x4;
130 uint64_t x5;
131 uint64_t x6;
132 uint64_t x7;
133 uint64_t x8;
134 uint64_t x9;
135 uint64_t x10;
136 uint64_t x11;
137 uint64_t x12;
138 uint64_t x13;
139 uint64_t x14;
140 uint64_t x15;
141 uint64_t m[16];
142 unsigned int r;
143 unsigned int i;
145 m[0] = LOAD64B(data);
146 m[1] = LOAD64B(data + 8);
147 m[2] = LOAD64B(data + 16);
148 m[3] = LOAD64B(data + 24);
149 m[4] = LOAD64B(data + 32);
150 m[5] = LOAD64B(data + 40);
151 m[6] = LOAD64B(data + 48);
152 m[7] = LOAD64B(data + 56);
153 m[8] = LOAD64B(data + 64);
154 m[9] = LOAD64B(data + 72);
155 m[10] = LOAD64B(data + 80);
156 m[11] = LOAD64B(data + 88);
157 m[12] = LOAD64B(data + 96);
158 m[13] = LOAD64B(data + 104);
159 m[14] = LOAD64B(data + 112);
160 m[15] = LOAD64B(data + 120);
162 x0 = s->h[0];
163 x1 = s->h[1];
164 x2 = s->h[2];
165 x3 = s->h[3];
166 x4 = s->h[4];
167 x5 = s->h[5];
168 x6 = s->h[6];
169 x7 = s->h[7];
170 x8 = k[0]; /* ^ s->s[0] */
171 x9 = k[1]; /* ^ s->s[1] */
172 x10 = k[2]; /* ^ s->s[2] */
173 x11 = k[3]; /* ^ s->s[3] */
174 x12 = k[4] ^ s->len[0];
175 x13 = k[5] ^ s->len[0];
176 x14 = k[6] ^ s->len[1];
177 x15 = k[7] ^ s->len[1];
179 for(r = 0, i = 0; r < s->r; r++, i++)
181 if(i == 10) i = 0;
183 G(x0, x4, x8, x12, m, sigma[i][0], sigma[i][1]);
184 G(x1, x5, x9, x13, m, sigma[i][2], sigma[i][3]);
185 G(x2, x6, x10, x14, m, sigma[i][4], sigma[i][5]);
186 G(x3, x7, x11, x15, m, sigma[i][6], sigma[i][7]);
188 G(x0, x5, x10, x15, m, sigma[i][8], sigma[i][9]);
189 G(x1, x6, x11, x12, m, sigma[i][10], sigma[i][11]);
190 G(x2, x7, x8, x13, m, sigma[i][12], sigma[i][13]);
191 G(x3, x4, x9, x14, m, sigma[i][14], sigma[i][15]);
194 kripto_memwipe(m, 128);
196 s->h[0] ^= x0 ^ x8; /* ^ s->s[0] */
197 s->h[1] ^= x1 ^ x9; /* ^ s->s[1] */
198 s->h[2] ^= x2 ^ x10; /* ^ s->s[2] */
199 s->h[3] ^= x3 ^ x11; /* ^ s->s[3] */
200 s->h[4] ^= x4 ^ x12; /* ^ s->s[0] */
201 s->h[5] ^= x5 ^ x13; /* ^ s->s[1] */
202 s->h[6] ^= x6 ^ x14; /* ^ s->s[2] */
203 s->h[7] ^= x7 ^ x15; /* ^ s->s[3] */
206 static void blake512_input
208 kripto_hash *s,
209 const void *in,
210 size_t len
213 size_t i;
215 for(i = 0; i < len; i++)
217 s->buf[s->i++] = CU8(in)[i];
219 if(s->i == 128)
221 s->len[0] += 1024;
222 if(!s->len[0])
224 s->len[1]++;
225 assert(s->len[1]);
228 blake512_process(s, s->buf);
229 s->i = 0;
234 static void blake512_finish(kripto_hash *s)
236 s->len[0] += s->i << 3;
237 if(s->len[0] < (s->i << 3)) s->len[1]++;
239 /* pad */
240 s->buf[s->i++] = 0x80;
242 if(s->i > 112) /* not enough space for length */
244 while(s->i < 128) s->buf[s->i++] = 0;
245 blake512_process(s, s->buf);
246 s->i = 0;
249 while(s->i < 112) s->buf[s->i++] = 0;
251 if(s->o > 48) s->buf[111] ^= 0x01; /* 512 */
253 /* add length */
254 STORE64B(s->len[1], s->buf + 112);
255 STORE64B(s->len[0], s->buf + 120);
257 if(!s->i) s->len[0] = s->len[1] = 0;
259 blake512_process(s, s->buf);
261 s->o = s->i = 0;
264 static void blake512_output(kripto_hash *s, void *out, size_t len)
266 unsigned int i;
268 if(s->o) blake512_finish(s);
270 /* big endian */
271 for(i = 0; i < len; s->i++, i++)
272 U8(out)[i] = s->h[s->i >> 3] >> (56 - ((s->i & 7) << 3));
275 static kripto_hash *blake512_create(unsigned int r, size_t len)
277 kripto_hash *s;
279 s = malloc(sizeof(kripto_hash));
280 if(!s) return 0;
282 s->obj.desc = kripto_hash_blake512;
284 (void)blake512_recreate(s, r, len);
286 return s;
289 static void blake512_destroy(kripto_hash *s)
291 kripto_memwipe(s, sizeof(kripto_hash));
292 free(s);
295 static int blake512_hash
297 unsigned int r,
298 const void *in,
299 size_t in_len,
300 void *out,
301 size_t out_len
304 kripto_hash s;
306 (void)blake512_recreate(&s, r, out_len);
307 blake512_input(&s, in, in_len);
308 blake512_output(&s, out, out_len);
310 kripto_memwipe(&s, sizeof(kripto_hash));
312 return 0;
315 static const kripto_hash_desc blake512 =
317 &blake512_create,
318 &blake512_recreate,
319 &blake512_input,
320 &blake512_output,
321 &blake512_destroy,
322 &blake512_hash,
323 64, /* max output */
324 128 /* block_size */
327 const kripto_hash_desc *const kripto_hash_blake512 = &blake512;