summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2022-01-28 13:16:12 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2022-01-28 13:16:12 +0900
commitb5a049b0edd34d92d9b8a1bc1078bfed9a2d0815 (patch)
treec098888dbe19b12e80045bec73d773848df89494
parentc586924ff007071bc7f6c65a43f408fa1551a928 (diff)
downloadlibgcrypt-b5a049b0edd34d92d9b8a1bc1078bfed9a2d0815.tar.gz
kdf: Implement blake2b_vl_hash function.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--cipher/blake2.c51
-rw-r--r--cipher/kdf-internal.h3
-rw-r--r--cipher/kdf.c127
3 files changed, 89 insertions, 92 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;
diff --git a/cipher/kdf-internal.h b/cipher/kdf-internal.h
index 7079860e..9e9a432e 100644
--- a/cipher/kdf-internal.h
+++ b/cipher/kdf-internal.h
@@ -36,5 +36,8 @@ _gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen,
unsigned long iterations,
size_t dklen, unsigned char *dk);
+/*-- blake2.c --*/
+gcry_err_code_t
+blake2b_vl_hash (const void *in, size_t inlen, size_t outputlen, void *output);
#endif /*GCRY_KDF_INTERNAL_H*/
diff --git a/cipher/kdf.c b/cipher/kdf.c
index 3a027c53..9463d2ff 100644
--- a/cipher/kdf.c
+++ b/cipher/kdf.c
@@ -358,7 +358,6 @@ struct argon2_context {
unsigned int l;
unsigned int t;
- gcry_md_hd_t hd;
u64 *block;
struct argon2_thread_data *thread_data;
@@ -386,115 +385,75 @@ xor_block (u64 *dst, const u64 *src)
dst[i] ^= src[i];
}
-static void
-hash (gcry_md_hd_t hd, const void *input, unsigned int inputlen,
- void *output, unsigned int outputlen)
-{
- unsigned char buf[4];
- const unsigned char *digest;
-
- _gcry_md_reset (hd);
-
- if (outputlen <= 64)
- {
- buf_put_le32 (buf, outputlen);
- _gcry_md_write (hd, buf, 4);
- _gcry_md_write (hd, input, inputlen);
- digest = _gcry_md_read (hd, GCRY_MD_BLAKE2B_512);
- memcpy (output, digest, outputlen);
- }
- else
- {
- int i, r;
- unsigned int remained;
- unsigned char d[64];
-
- i = 0;
- r = (outputlen-1)/32;
-
- buf_put_le32 (buf, outputlen);
- _gcry_md_write (hd, buf, 4);
- _gcry_md_write (hd, input, inputlen);
-
- while (1)
- {
- digest = _gcry_md_read (hd, GCRY_MD_BLAKE2B_512);
- memcpy (d, digest, 64);
- memcpy ((unsigned char *)output+i*32, d, 32);
-
- if (++i >= r)
- break;
-
- _gcry_md_reset (hd);
- _gcry_md_write (hd, d, 64);
- }
-
- remained = outputlen - 32*r;
- if (remained)
- memcpy ((unsigned char *)output+r*32, d+32, remained);
- }
-}
-
-static void
+static gpg_err_code_t
argon2_fill_first_blocks (argon2_ctx_t a)
{
+ gpg_err_code_t ec;
unsigned char h0_01_i[72];
const unsigned char *digest;
unsigned char buf[4];
int i;
+ gcry_md_hd_t hd;
+
+ ec = _gcry_md_open (&hd, GCRY_MD_BLAKE2B_512, 0);
+ if (ec)
+ return ec;
/* Generate H0. */
buf_put_le32 (buf, a->lanes);
- _gcry_md_write (a->hd, buf, 4);
+ _gcry_md_write (hd, buf, 4);
buf_put_le32 (buf, a->outlen);
- _gcry_md_write (a->hd, buf, 4);
+ _gcry_md_write (hd, buf, 4);
buf_put_le32 (buf, a->m_cost);
- _gcry_md_write (a->hd, buf, 4);
+ _gcry_md_write (hd, buf, 4);
buf_put_le32 (buf, a->passes);
- _gcry_md_write (a->hd, buf, 4);
+ _gcry_md_write (hd, buf, 4);
buf_put_le32 (buf, ARGON2_VERSION);
- _gcry_md_write (a->hd, buf, 4);
+ _gcry_md_write (hd, buf, 4);
buf_put_le32 (buf, a->hash_type);
- _gcry_md_write (a->hd, buf, 4);
+ _gcry_md_write (hd, buf, 4);
buf_put_le32 (buf, a->passwordlen);
- _gcry_md_write (a->hd, buf, 4);
- _gcry_md_write (a->hd, a->password, a->passwordlen);
+ _gcry_md_write (hd, buf, 4);
+ _gcry_md_write (hd, a->password, a->passwordlen);
buf_put_le32 (buf, a->saltlen);
- _gcry_md_write (a->hd, buf, 4);
- _gcry_md_write (a->hd, a->salt, a->saltlen);
+ _gcry_md_write (hd, buf, 4);
+ _gcry_md_write (hd, a->salt, a->saltlen);
buf_put_le32 (buf, a->keylen);
- _gcry_md_write (a->hd, buf, 4);
+ _gcry_md_write (hd, buf, 4);
if (a->key)
- _gcry_md_write (a->hd, a->key, a->keylen);
+ _gcry_md_write (hd, a->key, a->keylen);
buf_put_le32 (buf, a->adlen);
- _gcry_md_write (a->hd, buf, 4);
+ _gcry_md_write (hd, buf, 4);
if (a->ad)
- _gcry_md_write (a->hd, a->ad, a->adlen);
+ _gcry_md_write (hd, a->ad, a->adlen);
- digest = _gcry_md_read (a->hd, GCRY_MD_BLAKE2B_512);
+ digest = _gcry_md_read (hd, GCRY_MD_BLAKE2B_512);
memcpy (h0_01_i, digest, 64);
+ _gcry_md_close (hd);
+
for (i = 0; i < a->lanes; i++)
{
memset (h0_01_i+64, 0, 4);
buf_put_le32 (h0_01_i+64+4, i);
- hash (a->hd, h0_01_i, 72,
- &a->block[i*a->lane_length*ARGON2_WORDS_IN_BLOCK], 1024);
+ blake2b_vl_hash (h0_01_i, 72, 1024,
+ &a->block[i*a->lane_length*ARGON2_WORDS_IN_BLOCK]);
buf_put_le32 (h0_01_i+64, 1);
- hash (a->hd, h0_01_i, 72,
- &a->block[(i*a->lane_length+1)*ARGON2_WORDS_IN_BLOCK], 1024);
+ blake2b_vl_hash (h0_01_i, 72, 1024,
+ &a->block[(i*a->lane_length+1)*ARGON2_WORDS_IN_BLOCK]);
}
+ return 0;
}
static gpg_err_code_t
@@ -504,7 +463,6 @@ argon2_init (argon2_ctx_t a, unsigned int parallelism,
gpg_err_code_t ec = 0;
unsigned int memory_blocks;
unsigned int segment_length;
- gcry_md_hd_t hd;
void *block;
struct argon2_thread_data *thread_data;
@@ -524,19 +482,13 @@ argon2_init (argon2_ctx_t a, unsigned int parallelism,
a->r = a->s = a->l = a->t = 0;
a->step = ARGON2_ITERATOR_STEP0;
- a->hd = NULL;
a->block = NULL;
a->thread_data = NULL;
- ec = _gcry_md_open (&hd, GCRY_MD_BLAKE2B_512, 0);
- if (ec)
- return ec;
-
block = xtrymalloc (1024 * memory_blocks);
if (!block)
{
ec = gpg_err_code_from_errno (errno);
- _gcry_md_close (hd);
return ec;
}
memset (block, 0, 1024 * memory_blocks);
@@ -546,13 +498,11 @@ argon2_init (argon2_ctx_t a, unsigned int parallelism,
{
ec = gpg_err_code_from_errno (errno);
xfree (block);
- _gcry_md_close (hd);
return ec;
}
memset (thread_data, 0, a->n_threads * sizeof (struct argon2_thread_data));
- a->hd = hd;
a->block = block;
a->thread_data = thread_data;
return 0;
@@ -574,10 +524,14 @@ static gpg_err_code_t
argon2_iterator (argon2_ctx_t a, int *action_p,
struct gcry_kdf_pt_head **t_p)
{
+ gpg_err_code_t ec;
+
switch (a->step)
{
case ARGON2_ITERATOR_STEP0:
- argon2_fill_first_blocks (a);
+ ec = argon2_fill_first_blocks (a);
+ if (ec)
+ return ec;
/* continue */
*action_p = 3;
*t_p = NULL;
@@ -859,7 +813,7 @@ argon2_final (argon2_ctx_t a, size_t resultlen, void *result)
xor_block (a->block, last_block);
}
- hash (a->hd, a->block, 1024, result, a->outlen);
+ blake2b_vl_hash (a->block, 1024, a->outlen, result);
return 0;
}
@@ -870,9 +824,6 @@ argon2_close (argon2_ctx_t a)
n = offsetof (struct argon2_context, out) + a->outlen;
- if (a->hd)
- _gcry_md_close (a->hd);
-
if (a->block)
{
wipememory (a->block, 1024 * a->memory_blocks);
@@ -927,14 +878,6 @@ argon2_open (gcry_kdf_hd_t *hd, int subalgo,
if (n_threads > parallelism)
n_threads = parallelism;
}
-
- if (!(taglen == 64 || taglen == 48
- || taglen % 32 == 0 || taglen % 32 == 20))
- /*
- * FIXME: To support arbitrary taglen, we need to expose
- * internal API of Blake2b.
- */
- return GPG_ERR_NOT_IMPLEMENTED;
}
n = offsetof (struct argon2_context, out) + taglen;