Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmlibarchive/libarchive/archive_blake2sp_ref.c
3153 views
1
/*
2
BLAKE2 reference source code package - reference C implementations
3
4
Copyright 2012, Samuel Neves <[email protected]>. 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 "archive_platform.h"
17
18
#include <stdlib.h>
19
#include <string.h>
20
#include <stdio.h>
21
22
#if defined(_OPENMP)
23
#include <omp.h>
24
#endif
25
26
#include "archive_blake2.h"
27
#include "archive_blake2_impl.h"
28
29
#define PARALLELISM_DEGREE 8
30
31
/* Remove system-defined preprocessor defintions that conflict with us. */
32
#undef FS
33
34
/*
35
blake2sp_init_param defaults to setting the expecting output length
36
from the digest_length parameter block field.
37
38
In some cases, however, we do not want this, as the output length
39
of these instances is given by inner_length instead.
40
*/
41
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
42
{
43
int err = blake2s_init_param(S, P);
44
S->outlen = P->inner_length;
45
return err;
46
}
47
48
static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint32_t offset )
49
{
50
blake2s_param P[1];
51
P->digest_length = (uint8_t)outlen;
52
P->key_length = (uint8_t)keylen;
53
P->fanout = PARALLELISM_DEGREE;
54
P->depth = 2;
55
store32( &P->leaf_length, 0 );
56
store32( &P->node_offset, offset );
57
store16( &P->xof_length, 0 );
58
P->node_depth = 0;
59
P->inner_length = BLAKE2S_OUTBYTES;
60
memset( P->salt, 0, sizeof( P->salt ) );
61
memset( P->personal, 0, sizeof( P->personal ) );
62
return blake2sp_init_leaf_param( S, P );
63
}
64
65
static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
66
{
67
blake2s_param P[1];
68
P->digest_length = (uint8_t)outlen;
69
P->key_length = (uint8_t)keylen;
70
P->fanout = PARALLELISM_DEGREE;
71
P->depth = 2;
72
store32( &P->leaf_length, 0 );
73
store32( &P->node_offset, 0 );
74
store16( &P->xof_length, 0 );
75
P->node_depth = 1;
76
P->inner_length = BLAKE2S_OUTBYTES;
77
memset( P->salt, 0, sizeof( P->salt ) );
78
memset( P->personal, 0, sizeof( P->personal ) );
79
return blake2s_init_param( S, P );
80
}
81
82
83
int blake2sp_init( blake2sp_state *S, size_t outlen )
84
{
85
size_t i;
86
87
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
88
89
memset( S->buf, 0, sizeof( S->buf ) );
90
S->buflen = 0;
91
S->outlen = outlen;
92
93
if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )
94
return -1;
95
96
for( i = 0; i < PARALLELISM_DEGREE; ++i )
97
if( blake2sp_init_leaf( S->S[i], outlen, 0, (uint32_t)i ) < 0 ) return -1;
98
99
S->R->last_node = 1;
100
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
101
return 0;
102
}
103
104
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
105
{
106
size_t i;
107
108
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
109
110
if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
111
112
memset( S->buf, 0, sizeof( S->buf ) );
113
S->buflen = 0;
114
S->outlen = outlen;
115
116
if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )
117
return -1;
118
119
for( i = 0; i < PARALLELISM_DEGREE; ++i )
120
if( blake2sp_init_leaf( S->S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
121
122
S->R->last_node = 1;
123
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
124
{
125
uint8_t block[BLAKE2S_BLOCKBYTES];
126
memset( block, 0, BLAKE2S_BLOCKBYTES );
127
memcpy( block, key, keylen );
128
129
for( i = 0; i < PARALLELISM_DEGREE; ++i )
130
blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
131
132
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
133
}
134
return 0;
135
}
136
137
138
int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
139
{
140
const unsigned char * in = (const unsigned char *)pin;
141
size_t left = S->buflen;
142
size_t fill = sizeof( S->buf ) - left;
143
size_t i;
144
145
if( left && inlen >= fill )
146
{
147
memcpy( S->buf + left, in, fill );
148
149
for( i = 0; i < PARALLELISM_DEGREE; ++i )
150
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
151
152
in += fill;
153
inlen -= fill;
154
left = 0;
155
}
156
157
#if defined(_OPENMP)
158
#pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
159
#else
160
for( i = 0; i < PARALLELISM_DEGREE; ++i )
161
#endif
162
{
163
#if defined(_OPENMP)
164
size_t i = omp_get_thread_num();
165
#endif
166
size_t inlen__ = inlen;
167
const unsigned char *in__ = ( const unsigned char * )in;
168
in__ += i * BLAKE2S_BLOCKBYTES;
169
170
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
171
{
172
blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
173
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
174
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
175
}
176
}
177
178
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
179
inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
180
181
if( inlen > 0 )
182
memcpy( S->buf + left, in, inlen );
183
184
S->buflen = left + inlen;
185
return 0;
186
}
187
188
189
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
190
{
191
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
192
size_t i;
193
194
if(out == NULL || outlen < S->outlen) {
195
return -1;
196
}
197
198
for( i = 0; i < PARALLELISM_DEGREE; ++i )
199
{
200
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
201
{
202
size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
203
204
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
205
206
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
207
}
208
209
blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
210
}
211
212
for( i = 0; i < PARALLELISM_DEGREE; ++i )
213
blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
214
215
return blake2s_final( S->R, out, S->outlen );
216
}
217
218
219
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
220
{
221
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
222
blake2s_state S[PARALLELISM_DEGREE][1];
223
blake2s_state FS[1];
224
size_t i;
225
226
/* Verify parameters */
227
if ( NULL == in && inlen > 0 ) return -1;
228
229
if ( NULL == out ) return -1;
230
231
if ( NULL == key && keylen > 0) return -1;
232
233
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
234
235
if( keylen > BLAKE2S_KEYBYTES ) return -1;
236
237
for( i = 0; i < PARALLELISM_DEGREE; ++i )
238
if( blake2sp_init_leaf( S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
239
240
S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
241
242
if( keylen > 0 )
243
{
244
uint8_t block[BLAKE2S_BLOCKBYTES];
245
memset( block, 0, BLAKE2S_BLOCKBYTES );
246
memcpy( block, key, keylen );
247
248
for( i = 0; i < PARALLELISM_DEGREE; ++i )
249
blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
250
251
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
252
}
253
254
#if defined(_OPENMP)
255
#pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
256
#else
257
258
for( i = 0; i < PARALLELISM_DEGREE; ++i )
259
#endif
260
{
261
#if defined(_OPENMP)
262
size_t i = omp_get_thread_num();
263
#endif
264
size_t inlen__ = inlen;
265
const unsigned char *in__ = ( const unsigned char * )in;
266
in__ += i * BLAKE2S_BLOCKBYTES;
267
268
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
269
{
270
blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
271
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
272
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
273
}
274
275
if( inlen__ > i * BLAKE2S_BLOCKBYTES )
276
{
277
const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
278
const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
279
blake2s_update( S[i], in__, len );
280
}
281
282
blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
283
}
284
285
if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
286
return -1;
287
288
FS->last_node = 1;
289
290
for( i = 0; i < PARALLELISM_DEGREE; ++i )
291
blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
292
293
return blake2s_final( FS, out, outlen );
294
}
295
296
297
298
#if defined(BLAKE2SP_SELFTEST)
299
#include <string.h>
300
#include "blake2-kat.h"
301
int main( void )
302
{
303
uint8_t key[BLAKE2S_KEYBYTES];
304
uint8_t buf[BLAKE2_KAT_LENGTH];
305
size_t i, step;
306
307
for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
308
key[i] = ( uint8_t )i;
309
310
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
311
buf[i] = ( uint8_t )i;
312
313
/* Test simple API */
314
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
315
{
316
uint8_t hash[BLAKE2S_OUTBYTES];
317
blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
318
319
if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
320
{
321
goto fail;
322
}
323
}
324
325
/* Test streaming API */
326
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
327
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
328
uint8_t hash[BLAKE2S_OUTBYTES];
329
blake2sp_state S;
330
uint8_t * p = buf;
331
size_t mlen = i;
332
int err = 0;
333
334
if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
335
goto fail;
336
}
337
338
while (mlen >= step) {
339
if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
340
goto fail;
341
}
342
mlen -= step;
343
p += step;
344
}
345
if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
346
goto fail;
347
}
348
if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
349
goto fail;
350
}
351
352
if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) {
353
goto fail;
354
}
355
}
356
}
357
358
puts( "ok" );
359
return 0;
360
fail:
361
puts("error");
362
return -1;
363
}
364
#endif
365
366