blake2b 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,379 @@
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
+ #include "blake2-impl.h"
22
+
23
+ static const uint64_t blake2b_IV[8] =
24
+ {
25
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
26
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
27
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
28
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
29
+ };
30
+
31
+ static const uint8_t blake2b_sigma[12][16] =
32
+ {
33
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
34
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
35
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
36
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
37
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
38
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
39
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
40
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
41
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
42
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
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
+ };
46
+
47
+
48
+ static void blake2b_set_lastnode( blake2b_state *S )
49
+ {
50
+ S->f[1] = (uint64_t)-1;
51
+ }
52
+
53
+ /* Some helper functions, not necessarily useful */
54
+ static int blake2b_is_lastblock( const blake2b_state *S )
55
+ {
56
+ return S->f[0] != 0;
57
+ }
58
+
59
+ static void blake2b_set_lastblock( blake2b_state *S )
60
+ {
61
+ if( S->last_node ) blake2b_set_lastnode( S );
62
+
63
+ S->f[0] = (uint64_t)-1;
64
+ }
65
+
66
+ static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
67
+ {
68
+ S->t[0] += inc;
69
+ S->t[1] += ( S->t[0] < inc );
70
+ }
71
+
72
+ static void blake2b_init0( blake2b_state *S )
73
+ {
74
+ size_t i;
75
+ memset( S, 0, sizeof( blake2b_state ) );
76
+
77
+ for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
78
+ }
79
+
80
+ /* init xors IV with input parameter block */
81
+ int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
82
+ {
83
+ const uint8_t *p = ( const uint8_t * )( P );
84
+ size_t i;
85
+
86
+ blake2b_init0( S );
87
+
88
+ /* IV XOR ParamBlock */
89
+ for( i = 0; i < 8; ++i )
90
+ S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
91
+
92
+ S->outlen = P->digest_length;
93
+ return 0;
94
+ }
95
+
96
+
97
+
98
+ int blake2b_init( blake2b_state *S, size_t outlen )
99
+ {
100
+ blake2b_param P[1];
101
+
102
+ if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
103
+
104
+ P->digest_length = (uint8_t)outlen;
105
+ P->key_length = 0;
106
+ P->fanout = 1;
107
+ P->depth = 1;
108
+ store32( &P->leaf_length, 0 );
109
+ store32( &P->node_offset, 0 );
110
+ store32( &P->xof_length, 0 );
111
+ P->node_depth = 0;
112
+ P->inner_length = 0;
113
+ memset( P->reserved, 0, sizeof( P->reserved ) );
114
+ memset( P->salt, 0, sizeof( P->salt ) );
115
+ memset( P->personal, 0, sizeof( P->personal ) );
116
+ return blake2b_init_param( S, P );
117
+ }
118
+
119
+
120
+ int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
121
+ {
122
+ blake2b_param P[1];
123
+
124
+ if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
125
+
126
+ if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
127
+
128
+ P->digest_length = (uint8_t)outlen;
129
+ P->key_length = (uint8_t)keylen;
130
+ P->fanout = 1;
131
+ P->depth = 1;
132
+ store32( &P->leaf_length, 0 );
133
+ store32( &P->node_offset, 0 );
134
+ store32( &P->xof_length, 0 );
135
+ P->node_depth = 0;
136
+ P->inner_length = 0;
137
+ memset( P->reserved, 0, sizeof( P->reserved ) );
138
+ memset( P->salt, 0, sizeof( P->salt ) );
139
+ memset( P->personal, 0, sizeof( P->personal ) );
140
+
141
+ if( blake2b_init_param( S, P ) < 0 ) return -1;
142
+
143
+ {
144
+ uint8_t block[BLAKE2B_BLOCKBYTES];
145
+ memset( block, 0, BLAKE2B_BLOCKBYTES );
146
+ memcpy( block, key, keylen );
147
+ blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
148
+ secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
149
+ }
150
+ return 0;
151
+ }
152
+
153
+ #define G(r,i,a,b,c,d) \
154
+ do { \
155
+ a = a + b + m[blake2b_sigma[r][2*i+0]]; \
156
+ d = rotr64(d ^ a, 32); \
157
+ c = c + d; \
158
+ b = rotr64(b ^ c, 24); \
159
+ a = a + b + m[blake2b_sigma[r][2*i+1]]; \
160
+ d = rotr64(d ^ a, 16); \
161
+ c = c + d; \
162
+ b = rotr64(b ^ c, 63); \
163
+ } while(0)
164
+
165
+ #define ROUND(r) \
166
+ do { \
167
+ G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
168
+ G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
169
+ G(r,2,v[ 2],v[ 6],v[10],v[14]); \
170
+ G(r,3,v[ 3],v[ 7],v[11],v[15]); \
171
+ G(r,4,v[ 0],v[ 5],v[10],v[15]); \
172
+ G(r,5,v[ 1],v[ 6],v[11],v[12]); \
173
+ G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
174
+ G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
175
+ } while(0)
176
+
177
+ static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
178
+ {
179
+ uint64_t m[16];
180
+ uint64_t v[16];
181
+ size_t i;
182
+
183
+ for( i = 0; i < 16; ++i ) {
184
+ m[i] = load64( block + i * sizeof( m[i] ) );
185
+ }
186
+
187
+ for( i = 0; i < 8; ++i ) {
188
+ v[i] = S->h[i];
189
+ }
190
+
191
+ v[ 8] = blake2b_IV[0];
192
+ v[ 9] = blake2b_IV[1];
193
+ v[10] = blake2b_IV[2];
194
+ v[11] = blake2b_IV[3];
195
+ v[12] = blake2b_IV[4] ^ S->t[0];
196
+ v[13] = blake2b_IV[5] ^ S->t[1];
197
+ v[14] = blake2b_IV[6] ^ S->f[0];
198
+ v[15] = blake2b_IV[7] ^ S->f[1];
199
+
200
+ ROUND( 0 );
201
+ ROUND( 1 );
202
+ ROUND( 2 );
203
+ ROUND( 3 );
204
+ ROUND( 4 );
205
+ ROUND( 5 );
206
+ ROUND( 6 );
207
+ ROUND( 7 );
208
+ ROUND( 8 );
209
+ ROUND( 9 );
210
+ ROUND( 10 );
211
+ ROUND( 11 );
212
+
213
+ for( i = 0; i < 8; ++i ) {
214
+ S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
215
+ }
216
+ }
217
+
218
+ #undef G
219
+ #undef ROUND
220
+
221
+ int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
222
+ {
223
+ const unsigned char * in = (const unsigned char *)pin;
224
+ if( inlen > 0 )
225
+ {
226
+ size_t left = S->buflen;
227
+ size_t fill = BLAKE2B_BLOCKBYTES - left;
228
+ if( inlen > fill )
229
+ {
230
+ S->buflen = 0;
231
+ memcpy( S->buf + left, in, fill ); /* Fill buffer */
232
+ blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
233
+ blake2b_compress( S, S->buf ); /* Compress */
234
+ in += fill; inlen -= fill;
235
+ while(inlen > BLAKE2B_BLOCKBYTES) {
236
+ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
237
+ blake2b_compress( S, in );
238
+ in += BLAKE2B_BLOCKBYTES;
239
+ inlen -= BLAKE2B_BLOCKBYTES;
240
+ }
241
+ }
242
+ memcpy( S->buf + S->buflen, in, inlen );
243
+ S->buflen += inlen;
244
+ }
245
+ return 0;
246
+ }
247
+
248
+ int blake2b_final( blake2b_state *S, void *out, size_t outlen )
249
+ {
250
+ uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
251
+ size_t i;
252
+
253
+ if( out == NULL || outlen < S->outlen )
254
+ return -1;
255
+
256
+ if( blake2b_is_lastblock( S ) )
257
+ return -1;
258
+
259
+ blake2b_increment_counter( S, S->buflen );
260
+ blake2b_set_lastblock( S );
261
+ memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
262
+ blake2b_compress( S, S->buf );
263
+
264
+ for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
265
+ store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
266
+
267
+ memcpy( out, buffer, S->outlen );
268
+ secure_zero_memory(buffer, sizeof(buffer));
269
+ return 0;
270
+ }
271
+
272
+ /* inlen, at least, should be uint64_t. Others can be size_t. */
273
+ int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
274
+ {
275
+ blake2b_state S[1];
276
+
277
+ /* Verify parameters */
278
+ if ( NULL == in && inlen > 0 ) return -1;
279
+
280
+ if ( NULL == out ) return -1;
281
+
282
+ if( NULL == key && keylen > 0 ) return -1;
283
+
284
+ if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
285
+
286
+ if( keylen > BLAKE2B_KEYBYTES ) return -1;
287
+
288
+ if( keylen > 0 )
289
+ {
290
+ if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
291
+ }
292
+ else
293
+ {
294
+ if( blake2b_init( S, outlen ) < 0 ) return -1;
295
+ }
296
+
297
+ blake2b_update( S, ( const uint8_t * )in, inlen );
298
+ blake2b_final( S, out, outlen );
299
+ return 0;
300
+ }
301
+
302
+ int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
303
+ return blake2b(out, outlen, in, inlen, key, keylen);
304
+ }
305
+
306
+ #if defined(SUPERCOP)
307
+ int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
308
+ {
309
+ return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
310
+ }
311
+ #endif
312
+
313
+ #if defined(BLAKE2B_SELFTEST)
314
+ #include <string.h>
315
+ #include "blake2-kat.h"
316
+ int main( void )
317
+ {
318
+ uint8_t key[BLAKE2B_KEYBYTES];
319
+ uint8_t buf[BLAKE2_KAT_LENGTH];
320
+ size_t i, step;
321
+
322
+ for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
323
+ key[i] = ( uint8_t )i;
324
+
325
+ for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
326
+ buf[i] = ( uint8_t )i;
327
+
328
+ /* Test simple API */
329
+ for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
330
+ {
331
+ uint8_t hash[BLAKE2B_OUTBYTES];
332
+ blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
333
+
334
+ if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
335
+ {
336
+ goto fail;
337
+ }
338
+ }
339
+
340
+ /* Test streaming API */
341
+ for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
342
+ for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
343
+ uint8_t hash[BLAKE2B_OUTBYTES];
344
+ blake2b_state S;
345
+ uint8_t * p = buf;
346
+ size_t mlen = i;
347
+ int err = 0;
348
+
349
+ if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
350
+ goto fail;
351
+ }
352
+
353
+ while (mlen >= step) {
354
+ if ( (err = blake2b_update(&S, p, step)) < 0 ) {
355
+ goto fail;
356
+ }
357
+ mlen -= step;
358
+ p += step;
359
+ }
360
+ if ( (err = blake2b_update(&S, p, mlen)) < 0) {
361
+ goto fail;
362
+ }
363
+ if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
364
+ goto fail;
365
+ }
366
+
367
+ if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
368
+ goto fail;
369
+ }
370
+ }
371
+ }
372
+
373
+ puts( "ok" );
374
+ return 0;
375
+ fail:
376
+ puts("error");
377
+ return -1;
378
+ }
379
+ #endif
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+ $CFLAGS += ' -std=c99'
3
+ create_makefile 'blake2b_ext'
@@ -0,0 +1,108 @@
1
+ #include <ruby/ruby.h>
2
+ #include <ruby/encoding.h>
3
+ #include "blake2.h"
4
+
5
+ typedef struct {
6
+ size_t key_length;
7
+ uint8_t *key_bytes;
8
+
9
+ size_t output_length;
10
+ uint8_t *output;
11
+
12
+ VALUE to_hex;
13
+ VALUE to_bytes;
14
+ } Blake2;
15
+
16
+ VALUE cBlake2;
17
+
18
+ static void blake2_free(Blake2 *blake2) {
19
+ free(blake2->key_bytes);
20
+ free(blake2->output);
21
+
22
+ rb_gc_mark(blake2->to_hex);
23
+ rb_gc_mark(blake2->to_bytes);
24
+
25
+ ruby_xfree(blake2);
26
+ }
27
+
28
+ static VALUE blake2_alloc(VALUE klass) {
29
+ Blake2 *blake2_obj = (Blake2 *)ruby_xmalloc(sizeof(Blake2));
30
+
31
+ return Data_Wrap_Struct(klass, NULL, blake2_free, blake2_obj);
32
+ }
33
+
34
+ VALUE m_blake2_initialize(VALUE self, VALUE _len, VALUE _key) {
35
+ Blake2 *blake2;
36
+ Data_Get_Struct(self, Blake2, blake2);
37
+ int i;
38
+
39
+ ID bytes_method = rb_intern("bytes");
40
+ blake2->to_hex = ID2SYM(rb_intern("to_hex"));
41
+ blake2->to_bytes = ID2SYM(rb_intern("to_bytes"));
42
+
43
+ VALUE key_bytes_ary = rb_funcall(_key, bytes_method, 0);
44
+ blake2->key_length = RARRAY_LEN(key_bytes_ary);
45
+ blake2->key_bytes = (uint8_t*)malloc(blake2->key_length * sizeof(uint8_t));
46
+
47
+ for(i = 0; (unsigned)i < blake2->key_length; i++) {
48
+ VALUE byte = rb_ary_entry(key_bytes_ary, i);
49
+ blake2->key_bytes[i] = NUM2INT(byte);
50
+ }
51
+
52
+ blake2->output_length = NUM2INT(_len);
53
+ blake2->output = (uint8_t*)malloc(blake2->output_length * sizeof(uint8_t));
54
+
55
+ return Qnil;
56
+ }
57
+
58
+
59
+ VALUE m_blake2_digest(VALUE self, VALUE _input, VALUE _representation) {
60
+ Blake2 *blake2;
61
+
62
+ char *input = RSTRING_PTR(_input);
63
+ uint64_t input_length = RSTRING_LEN(_input);
64
+ int i;
65
+
66
+ Data_Get_Struct(self, Blake2, blake2);
67
+
68
+ blake2b(blake2->output, blake2->output_length, input, input_length,
69
+ blake2->key_bytes, blake2->key_length);
70
+
71
+ VALUE result;
72
+
73
+ if(_representation == blake2->to_bytes) {
74
+ result = rb_ary_new2(blake2->output_length);
75
+
76
+ for(i = 0; (unsigned)i < blake2->output_length; i++) {
77
+ rb_ary_push(result, INT2NUM(blake2->output[i]));
78
+ }
79
+ } else if(_representation == blake2->to_hex) {
80
+ unsigned long ary_len = blake2->output_length * (unsigned)sizeof(char) * 2;
81
+ char *c_str = (char*)malloc(ary_len + 1);
82
+
83
+ for(i = 0; (unsigned)i < blake2->output_length; i++) {
84
+ sprintf(c_str + (i * 2), "%02x", blake2->output[i]);
85
+ }
86
+ c_str[ary_len] = 0;
87
+
88
+ result = rb_str_new(c_str, ary_len);
89
+
90
+ if((unsigned long)RSTRING_LEN(result) != ary_len) {
91
+ rb_raise(rb_eRuntimeError, "m_blake2_digest: sizes don't match. Ary: %lu != %lu", RSTRING_LEN(result), ary_len);
92
+ }
93
+
94
+ free(c_str);
95
+ } else {
96
+ rb_raise(rb_eArgError, "unknown representation :%"PRIsVALUE"", _representation);
97
+ }
98
+
99
+ return result;
100
+ }
101
+
102
+ void Init_blake2b_ext() {
103
+ cBlake2 = rb_define_class("Blake2b", rb_cObject);
104
+ rb_define_alloc_func(cBlake2, blake2_alloc);
105
+
106
+ rb_define_private_method(cBlake2, "initialize", RUBY_METHOD_FUNC(m_blake2_initialize), 2);
107
+ rb_define_method(cBlake2, "digest", RUBY_METHOD_FUNC(m_blake2_digest), 2);
108
+ }