Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmlibarchive/libarchive/archive_blake2sp_ref.c
Line
Count
Source
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 "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
0
#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
0
{
43
0
  int err = blake2s_init_param(S, P);
44
0
  S->outlen = P->inner_length;
45
0
  return err;
46
0
}
47
48
static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint32_t offset )
49
0
{
50
0
  blake2s_param P[1];
51
0
  P->digest_length = (uint8_t)outlen;
52
0
  P->key_length = (uint8_t)keylen;
53
0
  P->fanout = PARALLELISM_DEGREE;
54
0
  P->depth = 2;
55
0
  store32( &P->leaf_length, 0 );
56
0
  store32( &P->node_offset, offset );
57
0
  store16( &P->xof_length, 0 );
58
0
  P->node_depth = 0;
59
0
  P->inner_length = BLAKE2S_OUTBYTES;
60
0
  memset( P->salt, 0, sizeof( P->salt ) );
61
0
  memset( P->personal, 0, sizeof( P->personal ) );
62
0
  return blake2sp_init_leaf_param( S, P );
63
0
}
64
65
static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
66
0
{
67
0
  blake2s_param P[1];
68
0
  P->digest_length = (uint8_t)outlen;
69
0
  P->key_length = (uint8_t)keylen;
70
0
  P->fanout = PARALLELISM_DEGREE;
71
0
  P->depth = 2;
72
0
  store32( &P->leaf_length, 0 );
73
0
  store32( &P->node_offset, 0 );
74
0
  store16( &P->xof_length, 0 );
75
0
  P->node_depth = 1;
76
0
  P->inner_length = BLAKE2S_OUTBYTES;
77
0
  memset( P->salt, 0, sizeof( P->salt ) );
78
0
  memset( P->personal, 0, sizeof( P->personal ) );
79
0
  return blake2s_init_param( S, P );
80
0
}
81
82
83
int blake2sp_init( blake2sp_state *S, size_t outlen )
84
0
{
85
0
  size_t i;
86
87
0
  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
88
89
0
  memset( S->buf, 0, sizeof( S->buf ) );
90
0
  S->buflen = 0;
91
0
  S->outlen = outlen;
92
93
0
  if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )
94
0
    return -1;
95
96
0
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
97
0
    if( blake2sp_init_leaf( S->S[i], outlen, 0, (uint32_t)i ) < 0 ) return -1;
98
99
0
  S->R->last_node = 1;
100
0
  S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
101
0
  return 0;
102
0
}
103
104
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
105
0
{
106
0
  size_t i;
107
108
0
  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
109
110
0
  if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
111
112
0
  memset( S->buf, 0, sizeof( S->buf ) );
113
0
  S->buflen = 0;
114
0
  S->outlen = outlen;
115
116
0
  if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )
117
0
    return -1;
118
119
0
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
120
0
    if( blake2sp_init_leaf( S->S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
121
122
0
  S->R->last_node = 1;
123
0
  S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
124
0
  {
125
0
    uint8_t block[BLAKE2S_BLOCKBYTES];
126
0
    memset( block, 0, BLAKE2S_BLOCKBYTES );
127
0
    memcpy( block, key, keylen );
128
129
0
    for( i = 0; i < PARALLELISM_DEGREE; ++i )
130
0
      blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
131
132
0
    secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
133
0
  }
134
0
  return 0;
135
0
}
136
137
138
int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
139
0
{
140
0
  const unsigned char * in = (const unsigned char *)pin;
141
0
  size_t left = S->buflen;
142
0
  size_t fill = sizeof( S->buf ) - left;
143
0
  size_t i;
144
145
0
  if( left && inlen >= fill )
146
0
  {
147
0
    memcpy( S->buf + left, in, fill );
148
149
0
    for( i = 0; i < PARALLELISM_DEGREE; ++i )
150
0
      blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
151
152
0
    in += fill;
153
0
    inlen -= fill;
154
0
    left = 0;
155
0
  }
156
157
#if defined(_OPENMP)
158
  #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
159
#else
160
0
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
161
0
#endif
162
0
  {
163
#if defined(_OPENMP)
164
    size_t      i = omp_get_thread_num();
165
#endif
166
0
    size_t inlen__ = inlen;
167
0
    const unsigned char *in__ = ( const unsigned char * )in;
168
0
    in__ += i * BLAKE2S_BLOCKBYTES;
169
170
0
    while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
171
0
    {
172
0
      blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
173
0
      in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
174
0
      inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
175
0
    }
176
0
  }
177
178
0
  in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
179
0
  inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
180
181
0
  if( inlen > 0 )
182
0
    memcpy( S->buf + left, in, inlen );
183
184
0
  S->buflen = left + inlen;
185
0
  return 0;
186
0
}
187
188
189
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
190
0
{
191
0
  uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
192
0
  size_t i;
193
194
0
  if(out == NULL || outlen < S->outlen) {
195
0
    return -1;
196
0
  }
197
198
0
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
199
0
  {
200
0
    if( S->buflen > i * BLAKE2S_BLOCKBYTES )
201
0
    {
202
0
      size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
203
204
0
      if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
205
206
0
      blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
207
0
    }
208
209
0
    blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
210
0
  }
211
212
0
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
213
0
    blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
214
215
0
  return blake2s_final( S->R, out, S->outlen );
216
0
}
217
218
219
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
220
0
{
221
0
  uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
222
0
  blake2s_state S[PARALLELISM_DEGREE][1];
223
0
  blake2s_state FS[1];
224
0
  size_t i;
225
226
  /* Verify parameters */
227
0
  if ( NULL == in && inlen > 0 ) return -1;
228
229
0
  if ( NULL == out ) return -1;
230
231
0
  if ( NULL == key && keylen > 0) return -1;
232
233
0
  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
234
235
0
  if( keylen > BLAKE2S_KEYBYTES ) return -1;
236
237
0
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
238
0
    if( blake2sp_init_leaf( S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
239
240
0
  S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
241
242
0
  if( keylen > 0 )
243
0
  {
244
0
    uint8_t block[BLAKE2S_BLOCKBYTES];
245
0
    memset( block, 0, BLAKE2S_BLOCKBYTES );
246
0
    memcpy( block, key, keylen );
247
248
0
    for( i = 0; i < PARALLELISM_DEGREE; ++i )
249
0
      blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
250
251
0
    secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
252
0
  }
253
254
#if defined(_OPENMP)
255
  #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
256
#else
257
258
0
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
259
0
#endif
260
0
  {
261
#if defined(_OPENMP)
262
    size_t      i = omp_get_thread_num();
263
#endif
264
0
    size_t inlen__ = inlen;
265
0
    const unsigned char *in__ = ( const unsigned char * )in;
266
0
    in__ += i * BLAKE2S_BLOCKBYTES;
267
268
0
    while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
269
0
    {
270
0
      blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
271
0
      in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
272
0
      inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
273
0
    }
274
275
0
    if( inlen__ > i * BLAKE2S_BLOCKBYTES )
276
0
    {
277
0
      const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
278
0
      const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
279
0
      blake2s_update( S[i], in__, len );
280
0
    }
281
282
0
    blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
283
0
  }
284
285
0
  if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
286
0
    return -1;
287
288
0
  FS->last_node = 1;
289
290
0
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
291
0
    blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
292
293
0
  return blake2s_final( FS, out, outlen );
294
0
}
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