Home | History | Annotate | Line # | Download | only in argon2
      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