/src/libsodium/src/libsodium/crypto_pwhash/argon2/blake2b-long.c
Line | Count | Source |
1 | | #include <limits.h> |
2 | | #include <stdint.h> |
3 | | #include <stdlib.h> |
4 | | #include <string.h> |
5 | | |
6 | | #include "crypto_generichash_blake2b.h" |
7 | | #include "private/common.h" |
8 | | #include "utils.h" |
9 | | |
10 | | #include "blake2b-long.h" |
11 | | |
12 | | int |
13 | | blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) |
14 | 0 | { |
15 | 0 | uint8_t *out = (uint8_t *) pout; |
16 | 0 | crypto_generichash_blake2b_state blake_state; |
17 | 0 | uint8_t outlen_bytes[4 /* sizeof(uint32_t) */] = { 0 }; |
18 | 0 | int ret = -1; |
19 | |
|
20 | 0 | if (outlen > UINT32_MAX) { |
21 | 0 | goto fail; /* LCOV_EXCL_LINE */ |
22 | 0 | } |
23 | | |
24 | | /* Ensure little-endian byte order! */ |
25 | 0 | STORE32_LE(outlen_bytes, (uint32_t) outlen); |
26 | |
|
27 | 0 | #define TRY(statement) \ |
28 | 0 | do { \ |
29 | 0 | ret = statement; \ |
30 | 0 | if (ret < 0) { \ |
31 | 0 | goto fail; \ |
32 | 0 | } \ |
33 | 0 | } while ((void) 0, 0) |
34 | |
|
35 | 0 | if (outlen <= crypto_generichash_blake2b_BYTES_MAX) { |
36 | 0 | TRY(crypto_generichash_blake2b_init(&blake_state, NULL, 0U, outlen)); |
37 | 0 | TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes, |
38 | 0 | sizeof(outlen_bytes))); |
39 | 0 | TRY(crypto_generichash_blake2b_update( |
40 | 0 | &blake_state, (const unsigned char *) in, inlen)); |
41 | 0 | TRY(crypto_generichash_blake2b_final(&blake_state, out, outlen)); |
42 | 0 | } else { |
43 | 0 | uint32_t toproduce; |
44 | 0 | uint8_t out_buffer[crypto_generichash_blake2b_BYTES_MAX]; |
45 | 0 | uint8_t in_buffer[crypto_generichash_blake2b_BYTES_MAX]; |
46 | 0 | TRY(crypto_generichash_blake2b_init( |
47 | 0 | &blake_state, NULL, 0U, crypto_generichash_blake2b_BYTES_MAX)); |
48 | 0 | TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes, |
49 | 0 | sizeof(outlen_bytes))); |
50 | 0 | TRY(crypto_generichash_blake2b_update( |
51 | 0 | &blake_state, (const unsigned char *) in, inlen)); |
52 | 0 | TRY(crypto_generichash_blake2b_final( |
53 | 0 | &blake_state, out_buffer, crypto_generichash_blake2b_BYTES_MAX)); |
54 | 0 | memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2); |
55 | 0 | out += crypto_generichash_blake2b_BYTES_MAX / 2; |
56 | 0 | toproduce = |
57 | 0 | (uint32_t) outlen - crypto_generichash_blake2b_BYTES_MAX / 2; |
58 | |
|
59 | 0 | while (toproduce > crypto_generichash_blake2b_BYTES_MAX) { |
60 | 0 | memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX); |
61 | 0 | TRY(crypto_generichash_blake2b( |
62 | 0 | out_buffer, crypto_generichash_blake2b_BYTES_MAX, in_buffer, |
63 | 0 | crypto_generichash_blake2b_BYTES_MAX, NULL, 0U)); |
64 | 0 | memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2); |
65 | 0 | out += crypto_generichash_blake2b_BYTES_MAX / 2; |
66 | 0 | toproduce -= crypto_generichash_blake2b_BYTES_MAX / 2; |
67 | 0 | } |
68 | | |
69 | 0 | memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX); |
70 | 0 | TRY(crypto_generichash_blake2b(out_buffer, toproduce, in_buffer, |
71 | 0 | crypto_generichash_blake2b_BYTES_MAX, |
72 | 0 | NULL, 0U)); |
73 | 0 | memcpy(out, out_buffer, toproduce); |
74 | 0 | } |
75 | 0 | fail: |
76 | 0 | sodium_memzero(&blake_state, sizeof(blake_state)); |
77 | 0 | return ret; |
78 | 0 | #undef TRY |
79 | 0 | } |