diff options
Diffstat (limited to 'gba/source/blake2.c')
-rw-r--r-- | gba/source/blake2.c | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/gba/source/blake2.c b/gba/source/blake2.c new file mode 100644 index 0000000..4a09c71 --- /dev/null +++ b/gba/source/blake2.c | |||
@@ -0,0 +1,322 @@ | |||
1 | /* | ||
2 | BLAKE2 reference source code package - reference C implementations | ||
3 | |||
4 | Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the | ||
5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at | ||
6 | your option. The terms of these licenses can be found at: | ||
7 | |||
8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 | ||
9 | - OpenSSL license : https://www.openssl.org/source/license.html | ||
10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | |||
12 | More information about the BLAKE2 hash function can be found at | ||
13 | https://blake2.net. | ||
14 | */ | ||
15 | |||
16 | #include <stdint.h> | ||
17 | #include <string.h> | ||
18 | #include <stdio.h> | ||
19 | |||
20 | #include "blake2.h" | ||
21 | |||
22 | #define BLAKE2_INLINE | ||
23 | |||
24 | static BLAKE2_INLINE uint32_t load32( const void *src ) | ||
25 | { | ||
26 | uint32_t w; | ||
27 | memcpy(&w, src, sizeof w); | ||
28 | return w; | ||
29 | } | ||
30 | |||
31 | static BLAKE2_INLINE void store16( void *dst, uint16_t w ) | ||
32 | { | ||
33 | memcpy(dst, &w, sizeof w); | ||
34 | } | ||
35 | |||
36 | static BLAKE2_INLINE void store32( void *dst, uint32_t w ) | ||
37 | { | ||
38 | memcpy(dst, &w, sizeof w); | ||
39 | } | ||
40 | |||
41 | static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) | ||
42 | { | ||
43 | return ( w >> c ) | ( w << ( 32 - c ) ); | ||
44 | } | ||
45 | |||
46 | /* prevents compiler optimizing out memset() */ | ||
47 | static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) | ||
48 | { | ||
49 | static void *(*const volatile memset_v)(void *, int, size_t) = &memset; | ||
50 | memset_v(v, 0, n); | ||
51 | } | ||
52 | |||
53 | static const uint32_t blake2s_IV[8] = | ||
54 | { | ||
55 | 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, | ||
56 | 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL | ||
57 | }; | ||
58 | |||
59 | static const uint8_t blake2s_sigma[10][16] = | ||
60 | { | ||
61 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , | ||
62 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , | ||
63 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , | ||
64 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , | ||
65 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , | ||
66 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , | ||
67 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , | ||
68 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , | ||
69 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , | ||
70 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , | ||
71 | }; | ||
72 | |||
73 | static void blake2s_set_lastnode( blake2s_state *S ) | ||
74 | { | ||
75 | S->f[1] = (uint32_t)-1; | ||
76 | } | ||
77 | |||
78 | /* Some helper functions, not necessarily useful */ | ||
79 | static int blake2s_is_lastblock( const blake2s_state *S ) | ||
80 | { | ||
81 | return S->f[0] != 0; | ||
82 | } | ||
83 | |||
84 | static void blake2s_set_lastblock( blake2s_state *S ) | ||
85 | { | ||
86 | if( S->last_node ) blake2s_set_lastnode( S ); | ||
87 | |||
88 | S->f[0] = (uint32_t)-1; | ||
89 | } | ||
90 | |||
91 | static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc ) | ||
92 | { | ||
93 | S->t[0] += inc; | ||
94 | S->t[1] += ( S->t[0] < inc ); | ||
95 | } | ||
96 | |||
97 | static void blake2s_init0( blake2s_state *S ) | ||
98 | { | ||
99 | size_t i; | ||
100 | memset( S, 0, sizeof( blake2s_state ) ); | ||
101 | |||
102 | for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; | ||
103 | } | ||
104 | |||
105 | /* init2 xors IV with input parameter block */ | ||
106 | int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) | ||
107 | { | ||
108 | const unsigned char *p = ( const unsigned char * )( P ); | ||
109 | size_t i; | ||
110 | |||
111 | blake2s_init0( S ); | ||
112 | |||
113 | /* IV XOR ParamBlock */ | ||
114 | for( i = 0; i < 8; ++i ) | ||
115 | S->h[i] ^= load32( &p[i * 4] ); | ||
116 | |||
117 | S->outlen = P->digest_length; | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | |||
122 | /* Sequential blake2s initialization */ | ||
123 | int blake2s_init( blake2s_state *S, size_t outlen ) | ||
124 | { | ||
125 | blake2s_param P[1]; | ||
126 | |||
127 | /* Move interval verification here? */ | ||
128 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; | ||
129 | |||
130 | P->digest_length = (uint8_t)outlen; | ||
131 | P->key_length = 0; | ||
132 | P->fanout = 1; | ||
133 | P->depth = 1; | ||
134 | store32( &P->leaf_length, 0 ); | ||
135 | store32( &P->node_offset, 0 ); | ||
136 | store16( &P->xof_length, 0 ); | ||
137 | P->node_depth = 0; | ||
138 | P->inner_length = 0; | ||
139 | /* memset(P->reserved, 0, sizeof(P->reserved) ); */ | ||
140 | memset( P->salt, 0, sizeof( P->salt ) ); | ||
141 | memset( P->personal, 0, sizeof( P->personal ) ); | ||
142 | return blake2s_init_param( S, P ); | ||
143 | } | ||
144 | |||
145 | int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ) | ||
146 | { | ||
147 | blake2s_param P[1]; | ||
148 | |||
149 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; | ||
150 | |||
151 | if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; | ||
152 | |||
153 | P->digest_length = (uint8_t)outlen; | ||
154 | P->key_length = (uint8_t)keylen; | ||
155 | P->fanout = 1; | ||
156 | P->depth = 1; | ||
157 | store32( &P->leaf_length, 0 ); | ||
158 | store32( &P->node_offset, 0 ); | ||
159 | store16( &P->xof_length, 0 ); | ||
160 | P->node_depth = 0; | ||
161 | P->inner_length = 0; | ||
162 | /* memset(P->reserved, 0, sizeof(P->reserved) ); */ | ||
163 | memset( P->salt, 0, sizeof( P->salt ) ); | ||
164 | memset( P->personal, 0, sizeof( P->personal ) ); | ||
165 | |||
166 | if( blake2s_init_param( S, P ) < 0 ) return -1; | ||
167 | |||
168 | { | ||
169 | uint8_t block[BLAKE2S_BLOCKBYTES]; | ||
170 | memset( block, 0, BLAKE2S_BLOCKBYTES ); | ||
171 | memcpy( block, key, keylen ); | ||
172 | blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); | ||
173 | secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ | ||
174 | } | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | #define G(r,i,a,b,c,d) \ | ||
179 | do { \ | ||
180 | a = a + b + m[blake2s_sigma[r][2*i+0]]; \ | ||
181 | d = rotr32(d ^ a, 16); \ | ||
182 | c = c + d; \ | ||
183 | b = rotr32(b ^ c, 12); \ | ||
184 | a = a + b + m[blake2s_sigma[r][2*i+1]]; \ | ||
185 | d = rotr32(d ^ a, 8); \ | ||
186 | c = c + d; \ | ||
187 | b = rotr32(b ^ c, 7); \ | ||
188 | } while(0) | ||
189 | |||
190 | #define ROUND(r) \ | ||
191 | do { \ | ||
192 | G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ | ||
193 | G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ | ||
194 | G(r,2,v[ 2],v[ 6],v[10],v[14]); \ | ||
195 | G(r,3,v[ 3],v[ 7],v[11],v[15]); \ | ||
196 | G(r,4,v[ 0],v[ 5],v[10],v[15]); \ | ||
197 | G(r,5,v[ 1],v[ 6],v[11],v[12]); \ | ||
198 | G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ | ||
199 | G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ | ||
200 | } while(0) | ||
201 | |||
202 | static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] ) | ||
203 | { | ||
204 | uint32_t m[16]; | ||
205 | uint32_t v[16]; | ||
206 | size_t i; | ||
207 | |||
208 | for( i = 0; i < 16; ++i ) { | ||
209 | m[i] = load32( in + i * sizeof( m[i] ) ); | ||
210 | } | ||
211 | |||
212 | for( i = 0; i < 8; ++i ) { | ||
213 | v[i] = S->h[i]; | ||
214 | } | ||
215 | |||
216 | v[ 8] = blake2s_IV[0]; | ||
217 | v[ 9] = blake2s_IV[1]; | ||
218 | v[10] = blake2s_IV[2]; | ||
219 | v[11] = blake2s_IV[3]; | ||
220 | v[12] = S->t[0] ^ blake2s_IV[4]; | ||
221 | v[13] = S->t[1] ^ blake2s_IV[5]; | ||
222 | v[14] = S->f[0] ^ blake2s_IV[6]; | ||
223 | v[15] = S->f[1] ^ blake2s_IV[7]; | ||
224 | |||
225 | ROUND( 0 ); | ||
226 | ROUND( 1 ); | ||
227 | ROUND( 2 ); | ||
228 | ROUND( 3 ); | ||
229 | ROUND( 4 ); | ||
230 | ROUND( 5 ); | ||
231 | ROUND( 6 ); | ||
232 | ROUND( 7 ); | ||
233 | ROUND( 8 ); | ||
234 | ROUND( 9 ); | ||
235 | |||
236 | for( i = 0; i < 8; ++i ) { | ||
237 | S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | #undef G | ||
242 | #undef ROUND | ||
243 | |||
244 | int blake2s_update( blake2s_state *S, const void *pin, size_t inlen ) | ||
245 | { | ||
246 | const unsigned char * in = (const unsigned char *)pin; | ||
247 | if( inlen > 0 ) | ||
248 | { | ||
249 | size_t left = S->buflen; | ||
250 | size_t fill = BLAKE2S_BLOCKBYTES - left; | ||
251 | if( inlen > fill ) | ||
252 | { | ||
253 | S->buflen = 0; | ||
254 | memcpy( S->buf + left, in, fill ); /* Fill buffer */ | ||
255 | blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); | ||
256 | blake2s_compress( S, S->buf ); /* Compress */ | ||
257 | in += fill; inlen -= fill; | ||
258 | while(inlen > BLAKE2S_BLOCKBYTES) { | ||
259 | blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES); | ||
260 | blake2s_compress( S, in ); | ||
261 | in += BLAKE2S_BLOCKBYTES; | ||
262 | inlen -= BLAKE2S_BLOCKBYTES; | ||
263 | } | ||
264 | } | ||
265 | memcpy( S->buf + S->buflen, in, inlen ); | ||
266 | S->buflen += inlen; | ||
267 | } | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | int blake2s_final( blake2s_state *S, void *out, size_t outlen ) | ||
272 | { | ||
273 | uint8_t buffer[BLAKE2S_OUTBYTES] = {0}; | ||
274 | size_t i; | ||
275 | |||
276 | if( out == NULL || outlen < S->outlen ) | ||
277 | return -1; | ||
278 | |||
279 | if( blake2s_is_lastblock( S ) ) | ||
280 | return -1; | ||
281 | |||
282 | blake2s_increment_counter( S, ( uint32_t )S->buflen ); | ||
283 | blake2s_set_lastblock( S ); | ||
284 | memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */ | ||
285 | blake2s_compress( S, S->buf ); | ||
286 | |||
287 | for( i = 0; i < 8; ++i ) // Output full hash to temp buffer | ||
288 | store32( buffer + sizeof( S->h[i] ) * i, S->h[i] ); | ||
289 | |||
290 | memcpy( out, buffer, outlen ); | ||
291 | //secure_zero_memory(buffer, sizeof(buffer)); | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) | ||
296 | { | ||
297 | blake2s_state S[1]; | ||
298 | |||
299 | /* Verify parameters */ | ||
300 | if ( NULL == in && inlen > 0 ) return -1; | ||
301 | |||
302 | if ( NULL == out ) return -1; | ||
303 | |||
304 | if ( NULL == key && keylen > 0) return -1; | ||
305 | |||
306 | if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; | ||
307 | |||
308 | if( keylen > BLAKE2S_KEYBYTES ) return -1; | ||
309 | |||
310 | if( keylen > 0 ) | ||
311 | { | ||
312 | if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; | ||
313 | } | ||
314 | else | ||
315 | { | ||
316 | if( blake2s_init( S, outlen ) < 0 ) return -1; | ||
317 | } | ||
318 | |||
319 | blake2s_update( S, ( const uint8_t * )in, inlen ); | ||
320 | blake2s_final( S, out, outlen ); | ||
321 | return 0; | ||
322 | } | ||