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 { 15 uint8_t *out = (uint8_t *) pout; 16 crypto_generichash_blake2b_state blake_state; 17 uint8_t outlen_bytes[4 /* sizeof(uint32_t) */] = { 0 }; 18 int ret = -1; 19 20 if (outlen > UINT32_MAX) { 21 goto fail; /* LCOV_EXCL_LINE */ 22 } 23 24 /* Ensure little-endian byte order! */ 25 STORE32_LE(outlen_bytes, (uint32_t) outlen); 26 27 #define TRY(statement) \ 28 do { \ 29 ret = statement; \ 30 if (ret < 0) { \ 31 goto fail; \ 32 } \ 33 } while ((void) 0, 0) 34 35 if (outlen <= crypto_generichash_blake2b_BYTES_MAX) { 36 TRY(crypto_generichash_blake2b_init(&blake_state, NULL, 0U, outlen)); 37 TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes, 38 sizeof(outlen_bytes))); 39 TRY(crypto_generichash_blake2b_update( 40 &blake_state, (const unsigned char *) in, inlen)); 41 TRY(crypto_generichash_blake2b_final(&blake_state, out, outlen)); 42 } else { 43 uint32_t toproduce; 44 uint8_t out_buffer[crypto_generichash_blake2b_BYTES_MAX]; 45 uint8_t in_buffer[crypto_generichash_blake2b_BYTES_MAX]; 46 TRY(crypto_generichash_blake2b_init( 47 &blake_state, NULL, 0U, crypto_generichash_blake2b_BYTES_MAX)); 48 TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes, 49 sizeof(outlen_bytes))); 50 TRY(crypto_generichash_blake2b_update( 51 &blake_state, (const unsigned char *) in, inlen)); 52 TRY(crypto_generichash_blake2b_final( 53 &blake_state, out_buffer, crypto_generichash_blake2b_BYTES_MAX)); 54 memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2); 55 out += crypto_generichash_blake2b_BYTES_MAX / 2; 56 toproduce = 57 (uint32_t) outlen - crypto_generichash_blake2b_BYTES_MAX / 2; 58 59 while (toproduce > crypto_generichash_blake2b_BYTES_MAX) { 60 memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX); 61 TRY(crypto_generichash_blake2b( 62 out_buffer, crypto_generichash_blake2b_BYTES_MAX, in_buffer, 63 crypto_generichash_blake2b_BYTES_MAX, NULL, 0U)); 64 memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2); 65 out += crypto_generichash_blake2b_BYTES_MAX / 2; 66 toproduce -= crypto_generichash_blake2b_BYTES_MAX / 2; 67 } 68 69 memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX); 70 TRY(crypto_generichash_blake2b(out_buffer, toproduce, in_buffer, 71 crypto_generichash_blake2b_BYTES_MAX, 72 NULL, 0U)); 73 memcpy(out, out_buffer, toproduce); 74 } 75 fail: 76 sodium_memzero(&blake_state, sizeof(blake_state)); 77 return ret; 78 #undef TRY 79 } 80