status update, probably last commit
[rofl0r-kripto.git] / lib / hash / blake2s.c
blob22bbaf80556d3787808f4334eb14d8a95c8312e9
1 /*
2 * Written in 2013 by Gregor Pintar <grpintar@gmail.com>
4 * To the extent possible under law, the author(s) have dedicated
5 * all copyright and related and neighboring rights to this software
6 * to the public domain worldwide.
7 *
8 * This software is distributed without any warranty.
10 * You should have received a copy of the CC0 Public Domain Dedication.
11 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
14 #include <stdint.h>
15 #include <stddef.h>
16 #include <stdlib.h>
17 #include <limits.h>
18 #include <assert.h>
20 #include <kripto/cast.h>
21 #include <kripto/loadstore.h>
22 #include <kripto/rotate.h>
23 #include <kripto/memwipe.h>
24 #include <kripto/hash.h>
25 #include <kripto/desc/hash.h>
26 #include <kripto/object/hash.h>
28 #include <kripto/hash/blake2s.h>
30 struct kripto_hash
32 struct kripto_hash_object obj;
33 unsigned int r;
34 uint32_t h[8];
35 uint32_t len[2];
36 uint32_t f;
37 uint8_t buf[64];
38 unsigned int i;
41 static const uint8_t sigma[10][16] =
43 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
44 {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
45 {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
46 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
47 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
48 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
49 {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
50 {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
51 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
52 {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}
55 static const uint32_t iv[8] =
57 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
58 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
61 static kripto_hash *blake2s_recreate
63 kripto_hash *s,
64 unsigned int r,
65 size_t len
68 s->r = r;
69 if(!s->r) s->r = 10;
71 s->f = s->len[0] = s->len[1] = s->i = 0;
73 /* s->h[0] = iv[0] ^ 0x01010020; */
74 s->h[0] = iv[0] ^ 0x01010000 ^ (uint8_t)len;
75 s->h[1] = iv[1];
76 s->h[2] = iv[2];
77 s->h[3] = iv[3];
78 s->h[4] = iv[4];
79 s->h[5] = iv[5];
80 s->h[6] = iv[6];
81 s->h[7] = iv[7];
83 return s;
86 #define G(A, B, C, D, M0, M1) \
87 { \
88 A += B + (M0); \
89 D = ROR32_16(D ^ A); \
90 C += D; \
91 B = ROR32_12(B ^ C); \
93 A += B + (M1); \
94 D = ROR32_08(D ^ A); \
95 C += D; \
96 B = ROR32_07(B ^ C); \
99 static void blake2s_process(kripto_hash *s, const uint8_t *data)
101 uint32_t x0;
102 uint32_t x1;
103 uint32_t x2;
104 uint32_t x3;
105 uint32_t x4;
106 uint32_t x5;
107 uint32_t x6;
108 uint32_t x7;
109 uint32_t x8;
110 uint32_t x9;
111 uint32_t x10;
112 uint32_t x11;
113 uint32_t x12;
114 uint32_t x13;
115 uint32_t x14;
116 uint32_t x15;
117 uint32_t m[16];
118 unsigned int r;
119 unsigned int i;
121 m[0] = LOAD32L(data);
122 m[1] = LOAD32L(data + 4);
123 m[2] = LOAD32L(data + 8);
124 m[3] = LOAD32L(data + 12);
125 m[4] = LOAD32L(data + 16);
126 m[5] = LOAD32L(data + 20);
127 m[6] = LOAD32L(data + 24);
128 m[7] = LOAD32L(data + 28);
129 m[8] = LOAD32L(data + 32);
130 m[9] = LOAD32L(data + 36);
131 m[10] = LOAD32L(data + 40);
132 m[11] = LOAD32L(data + 44);
133 m[12] = LOAD32L(data + 48);
134 m[13] = LOAD32L(data + 52);
135 m[14] = LOAD32L(data + 56);
136 m[15] = LOAD32L(data + 60);
138 x0 = s->h[0];
139 x1 = s->h[1];
140 x2 = s->h[2];
141 x3 = s->h[3];
142 x4 = s->h[4];
143 x5 = s->h[5];
144 x6 = s->h[6];
145 x7 = s->h[7];
146 x8 = iv[0];
147 x9 = iv[1];
148 x10 = iv[2];
149 x11 = iv[3];
150 x12 = iv[4] ^ s->len[0];
151 x13 = iv[5] ^ s->len[1];
152 x14 = iv[6] ^ s->f;
153 x15 = iv[7];
155 for(r = 0, i = 0; r < s->r; r++, i++)
157 if(i == 10) i = 0;
159 G(x0, x4, x8, x12, m[sigma[i][0]], m[sigma[i][1]]);
160 G(x1, x5, x9, x13, m[sigma[i][2]], m[sigma[i][3]]);
161 G(x2, x6, x10, x14, m[sigma[i][4]], m[sigma[i][5]]);
162 G(x3, x7, x11, x15, m[sigma[i][6]], m[sigma[i][7]]);
164 G(x0, x5, x10, x15, m[sigma[i][8]], m[sigma[i][9]]);
165 G(x1, x6, x11, x12, m[sigma[i][10]], m[sigma[i][11]]);
166 G(x2, x7, x8, x13, m[sigma[i][12]], m[sigma[i][13]]);
167 G(x3, x4, x9, x14, m[sigma[i][14]], m[sigma[i][15]]);
170 kripto_memwipe(m, 64);
172 s->h[0] ^= x0 ^ x8;
173 s->h[1] ^= x1 ^ x9;
174 s->h[2] ^= x2 ^ x10;
175 s->h[3] ^= x3 ^ x11;
176 s->h[4] ^= x4 ^ x12;
177 s->h[5] ^= x5 ^ x13;
178 s->h[6] ^= x6 ^ x14;
179 s->h[7] ^= x7 ^ x15;
182 static void blake2s_input
184 kripto_hash *s,
185 const void *in,
186 size_t len
189 size_t i;
191 for(i = 0; i < len; i++)
193 if(s->i == 64)
195 s->len[0] += 64;
196 if(!s->len[0])
198 s->len[1]++;
199 assert(s->len[1]);
202 blake2s_process(s, s->buf);
203 s->i = 0;
206 s->buf[s->i++] = CU8(in)[i];
210 static void blake2s_finish(kripto_hash *s)
212 s->len[0] += s->i;
213 if(s->len[0] < s->i) s->len[1]++;
215 while(s->i < 64) s->buf[s->i++] = 0;
217 s->f = 0xFFFFFFFF;
219 blake2s_process(s, s->buf);
221 s->i = 0;
224 static void blake2s_output(kripto_hash *s, void *out, size_t len)
226 unsigned int i;
228 if(!s->f) blake2s_finish(s);
230 /* little endian */
231 for(i = 0; i < len; s->i++, i++)
233 U8(out)[i] = s->h[s->i >> 2];
234 s->h[s->i >> 2] >>= 8;
238 static kripto_hash *blake2s_create(unsigned int r, size_t len)
240 kripto_hash *s;
242 s = malloc(sizeof(kripto_hash));
243 if(!s) return 0;
245 s->obj.desc = kripto_hash_blake2s;
247 (void)blake2s_recreate(s, r, len);
249 return s;
252 static void blake2s_destroy(kripto_hash *s)
254 kripto_memwipe(s, sizeof(kripto_hash));
255 free(s);
258 static int blake2s_hash
260 unsigned int r,
261 const void *in,
262 size_t in_len,
263 void *out,
264 size_t out_len
267 kripto_hash s;
269 (void)blake2s_recreate(&s, r, out_len);
270 blake2s_input(&s, in, in_len);
271 blake2s_output(&s, out, out_len);
273 kripto_memwipe(&s, sizeof(kripto_hash));
275 return 0;
278 static const kripto_hash_desc blake2s =
280 &blake2s_create,
281 &blake2s_recreate,
282 &blake2s_input,
283 &blake2s_output,
284 &blake2s_destroy,
285 &blake2s_hash,
286 32, /* max output */
287 64 /* block_size */
290 const kripto_hash_desc *const kripto_hash_blake2s = &blake2s;