summaryrefslogtreecommitdiff
path: root/cipher/blake2.c
diff options
context:
space:
mode:
Diffstat (limited to 'cipher/blake2.c')
-rw-r--r--cipher/blake2.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/cipher/blake2.c b/cipher/blake2.c
index 642c5bfd..8a93a7ef 100644
--- a/cipher/blake2.c
+++ b/cipher/blake2.c
@@ -474,6 +474,57 @@ static gcry_err_code_t blake2b_init_ctx(void *ctx, unsigned int flags,
return blake2b_init(c, key, keylen);
}
+/* Variable-length Hash Function H'. */
+gcry_err_code_t
+blake2b_vl_hash (const void *in, size_t inlen, size_t outputlen, void *output)
+{
+ gcry_err_code_t ec;
+ BLAKE2B_CONTEXT ctx;
+ unsigned char buf[4];
+
+ ec = blake2b_init_ctx (&ctx, 0, NULL, 0,
+ (outputlen < 64 ? outputlen: 64)*8);
+ if (ec)
+ return ec;
+
+ buf_put_le32 (buf, outputlen);
+ blake2b_write (&ctx, buf, 4);
+ blake2b_write (&ctx, in, inlen);
+ blake2b_final (&ctx);
+
+ if (outputlen <= 64)
+ memcpy (output, ctx.buf, outputlen);
+ else
+ {
+ int r = (outputlen-1)/32;
+ unsigned int remained = outputlen - 32*r;
+ int i;
+ unsigned char d[64];
+
+ i = 0;
+ while (1)
+ {
+ memcpy (d, ctx.buf, 64);
+ memcpy ((unsigned char *)output+i*32, d, 32);
+
+ if (++i >= r)
+ break;
+
+ ec = blake2b_init_ctx (&ctx, 0, NULL, 0, 64*8);
+ if (ec)
+ return ec;
+
+ blake2b_write (&ctx, d, 64);
+ blake2b_final (&ctx);
+ }
+
+ if (remained)
+ memcpy ((unsigned char *)output+r*32, d+32, remained);
+ }
+
+ return 0;
+}
+
static inline void blake2s_set_lastblock(BLAKE2S_STATE *S)
{
S->f[0] = 0xFFFFFFFFUL;