summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2022-01-27 17:04:09 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2022-01-27 17:04:09 +0900
commit7eaa88713db17d11b0126ec676b1e29f3aab4a4f (patch)
tree26466077bb8fab38419310998f10f58928d13a49
parent026d798e8b41f6f3c955212641612a79f3347492 (diff)
downloadlibgcrypt-7eaa88713db17d11b0126ec676b1e29f3aab4a4f.tar.gz
kdf: Let implement ARGON2D first.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--cipher/kdf.c191
-rw-r--r--tests/t-kdf.c16
2 files changed, 182 insertions, 25 deletions
diff --git a/cipher/kdf.c b/cipher/kdf.c
index df043071..d5cc011f 100644
--- a/cipher/kdf.c
+++ b/cipher/kdf.c
@@ -387,8 +387,8 @@ xor_block (u64 *dst, const u64 *src)
}
static gpg_err_code_t
-hash (gcry_md_hd_t hd, const unsigned char *input, unsigned int inputlen,
- unsigned char *output, unsigned int outputlen)
+hash (gcry_md_hd_t hd, const void *input, unsigned int inputlen,
+ void *output, unsigned int outputlen)
{
gpg_err_code_t ec = 0;
unsigned char buf[4];
@@ -441,17 +441,18 @@ hash (gcry_md_hd_t hd, const unsigned char *input, unsigned int inputlen,
_gcry_md_write (hd, buf, 4);
_gcry_md_write (hd, input, inputlen);
- do
+ while (1)
{
digest = _gcry_md_read (hd, GCRY_MD_BLAKE2B_512);
memcpy (d, digest, 64);
- memcpy (output+i*32, digest, 32);
- i++;
+ memcpy ((unsigned char *)output+i*32, digest, 32);
+
+ if (++i >= r)
+ break;
_gcry_md_reset (hd);
_gcry_md_write (hd, d, 64);
}
- while (i < r);
remained = outputlen - 32*r;
if (remained)
@@ -467,7 +468,7 @@ hash (gcry_md_hd_t hd, const unsigned char *input, unsigned int inputlen,
_gcry_md_write (hd1, d, 64);
digest = _gcry_md_read (hd1, algo);
- memcpy (output+r*32, digest, remained);
+ memcpy ((unsigned char *)output+r*32, digest, remained);
_gcry_md_close (hd1);
}
}
@@ -476,7 +477,7 @@ hash (gcry_md_hd_t hd, const unsigned char *input, unsigned int inputlen,
}
static gpg_err_code_t
-argon2_genh0_first_blocks (argon2_ctx_t a)
+argon2_fill_first_blocks (argon2_ctx_t a)
{
gpg_err_code_t ec = 0;
unsigned char h0_01_i[72];
@@ -484,6 +485,7 @@ argon2_genh0_first_blocks (argon2_ctx_t a)
unsigned char buf[4];
int i;
+ /* Generate H0. */
buf_put_le32 (buf, a->lanes);
_gcry_md_write (a->hd, buf, 4);
@@ -526,16 +528,16 @@ argon2_genh0_first_blocks (argon2_ctx_t a)
for (i = 0; i < a->lanes; i++)
{
- /*FIXME*/
memset (h0_01_i+64, 0, 4);
buf_put_le32 (h0_01_i+64+4, i);
- ec = hash (a->hd, h0_01_i, 72, (unsigned char *)a->block+1024*i, 1024);
+ ec = hash (a->hd, h0_01_i, 72,
+ &a->block[i*a->lane_length*ARGON2_WORDS_IN_BLOCK], 1024);
if (ec)
break;
buf_put_le32 (h0_01_i+64, 1);
- ec = hash (a->hd, h0_01_i, 72, (unsigned char *)a->block+1024*(i+a->lanes),
- 1024);
+ ec = hash (a->hd, h0_01_i, 72,
+ &a->block[(i*a->lane_length+1)*ARGON2_WORDS_IN_BLOCK], 1024);
if (ec)
break;
}
@@ -623,7 +625,7 @@ argon2_iterator (argon2_ctx_t a, int *action_p,
switch (a->step)
{
case ARGON2_ITERATOR_STEP0:
- argon2_genh0_first_blocks (a);
+ argon2_fill_first_blocks (a);
/* continue */
*action_p = 3;
*t_p = NULL;
@@ -703,6 +705,125 @@ argon2_pseudo_rand_gen (argon2_ctx_t a, const struct argon2_thread_data *t,
(void)random_index;
}
+static u64 fBlaMka (u64 x, u64 y)
+{
+ const u64 m = U64_C(0xFFFFFFFF);
+ return x + y + 2 * (x & m) * (y & m);
+}
+
+static u64 rotr64 (uint64_t w, unsigned int c)
+{
+ return (w >> c) | (w << (64 - c));
+}
+
+#define G(a, b, c, d) \
+ do { \
+ a = fBlaMka(a, b); \
+ d = rotr64(d ^ a, 32); \
+ c = fBlaMka(c, d); \
+ b = rotr64(b ^ c, 24); \
+ a = fBlaMka(a, b); \
+ d = rotr64(d ^ a, 16); \
+ c = fBlaMka(c, d); \
+ b = rotr64(b ^ c, 63); \
+ } while ((void)0, 0)
+
+#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
+ v12, v13, v14, v15) \
+ do { \
+ G(v0, v4, v8, v12); \
+ G(v1, v5, v9, v13); \
+ G(v2, v6, v10, v14); \
+ G(v3, v7, v11, v15); \
+ G(v0, v5, v10, v15); \
+ G(v1, v6, v11, v12); \
+ G(v2, v7, v8, v13); \
+ G(v3, v4, v9, v14); \
+ } while ((void)0, 0)
+
+static void
+fill_block (const u64 *prev_block, const u64 *ref_block, u64 *curr_block,
+ int with_xor)
+{
+ u64 block_r[ARGON2_WORDS_IN_BLOCK];
+ u64 block_tmp[ARGON2_WORDS_IN_BLOCK];
+ int i;
+
+ memcpy (block_r, ref_block, ARGON2_WORDS_IN_BLOCK);
+ xor_block (block_r, prev_block);
+ memcpy (block_tmp, block_r, ARGON2_WORDS_IN_BLOCK);
+
+ if (with_xor)
+ xor_block (block_tmp, curr_block);
+
+ for (i = 0; i < 8; ++i)
+ BLAKE2_ROUND_NOMSG
+ (block_r[16 * i], block_r[16 * i + 1], block_r[16 * i + 2],
+ block_r[16 * i + 3], block_r[16 * i + 4], block_r[16 * i + 5],
+ block_r[16 * i + 6], block_r[16 * i + 7], block_r[16 * i + 8],
+ block_r[16 * i + 9], block_r[16 * i + 10], block_r[16 * i + 11],
+ block_r[16 * i + 12], block_r[16 * i + 13], block_r[16 * i + 14],
+ block_r[16 * i + 15]);
+
+ for (i = 0; i < 8; i++)
+ BLAKE2_ROUND_NOMSG
+ (block_r[2 * i], block_r[2 * i + 1], block_r[2 * i + 16],
+ block_r[2 * i + 17], block_r[2 * i + 32], block_r[2 * i + 33],
+ block_r[2 * i + 48], block_r[2 * i + 49], block_r[2 * i + 64],
+ block_r[2 * i + 65], block_r[2 * i + 80], block_r[2 * i + 81],
+ block_r[2 * i + 96], block_r[2 * i + 97], block_r[2 * i + 112],
+ block_r[2 * i + 113]);
+
+ memcpy (curr_block, block_tmp, ARGON2_WORDS_IN_BLOCK);
+ xor_block (curr_block, block_r);
+}
+
+static u32
+index_alpha (argon2_ctx_t a, const struct argon2_thread_data *t,
+ int segment_index, u32 random, int same_lane)
+{
+ u32 reference_area_size;
+ u64 relative_position;
+ u32 start_position;
+
+ if (t->pass == 0)
+ {
+ if (t->slice == 0)
+ reference_area_size = segment_index - 1;
+ else
+ {
+ if (same_lane)
+ reference_area_size = t->slice * a->segment_length
+ + segment_index - 1;
+ else
+ reference_area_size = t->slice * a->segment_length +
+ ((segment_index == 0) ? -1 : 0);
+ }
+ }
+ else
+ {
+ if (same_lane)
+ reference_area_size = a->lane_length
+ - a->segment_length + segment_index - 1;
+ else
+ reference_area_size = a->lane_length
+ - a->segment_length + ((segment_index == 0) ? -1 : 0);
+ }
+
+ relative_position = (random * (u64)random) >> 32;
+ relative_position = reference_area_size - 1 -
+ ((reference_area_size * relative_position) >> 32);
+
+ if (t->pass == 0)
+ start_position = 0;
+ else
+ start_position = (t->slice == 4 - 1)
+ ? 0
+ : (t->slice + 1) * a->segment_length;
+
+ return (start_position + relative_position) % a->lane_length;
+}
+
static gpg_err_code_t
argon2_compute_segment (argon2_ctx_t a, const struct argon2_thread_data *t)
{
@@ -710,6 +831,7 @@ argon2_compute_segment (argon2_ctx_t a, const struct argon2_thread_data *t)
u32 *random_index = NULL;
int i;
int prev_offset, curr_offset;
+ u32 ref_index, ref_lane;
if (a->hash_type == GCRY_KDF_ARGON2I
|| (a->hash_type == GCRY_KDF_ARGON2ID && t->pass == 0 && t->slice < 2))
@@ -733,7 +855,33 @@ argon2_compute_segment (argon2_ctx_t a, const struct argon2_thread_data *t)
for (; i < a->segment_length; i++, curr_offset++, prev_offset++)
{
- /* Not yet implemented. */;
+ void *pseudo_rand;
+ u64 *ref_block, *curr_block;
+
+ if ((curr_offset % a->lane_length) == 1)
+ prev_offset = curr_offset - 1;
+
+ if (random_index)
+ {
+ /* not yet implemented */
+ pseudo_rand = &a->block[prev_offset*ARGON2_WORDS_IN_BLOCK];
+ }
+ else
+ pseudo_rand = &a->block[prev_offset*ARGON2_WORDS_IN_BLOCK];
+
+ if (t->pass == 0 && t->slice == 0)
+ ref_lane = t->lane;
+ else
+ ref_lane = buf_get_le32 ((unsigned char *)pseudo_rand+4) % a->lanes;
+
+ ref_index = index_alpha (a, t, i, buf_get_le32 (pseudo_rand),
+ ref_lane == t->lane);
+ ref_block =
+ &a->block[(a->lane_length * ref_lane + ref_index)* ARGON2_WORDS_IN_BLOCK];
+
+ curr_block = &a->block[curr_offset * ARGON2_WORDS_IN_BLOCK];
+ fill_block (&a->block[prev_offset * ARGON2_WORDS_IN_BLOCK], ref_block,
+ curr_block, t->pass != 0);
}
xfree (random_index);
@@ -745,7 +893,7 @@ static gpg_err_code_t
argon2_final (argon2_ctx_t a, size_t resultlen, void *result)
{
gpg_err_code_t ec;
- int i, j;
+ int i;
if (resultlen != a->outlen)
return GPG_ERR_INV_VALUE;
@@ -753,17 +901,14 @@ argon2_final (argon2_ctx_t a, size_t resultlen, void *result)
memset (a->block, 0, 1024);
for (i = 0; i < a->lanes; i++)
{
- u64 *p0;
- u64 *p1; /*FIXME*/
-
- p0 = a->block;
- p1 = p0 + (a->lane_length * i + (a->segment_length - 1)*1024)/8;
+ u64 *last_block;
- xor_block (p0, p1);
+ last_block = &a->block[(a->lane_length * i + (a->lane_length - 1))
+ * ARGON2_WORDS_IN_BLOCK];
+ xor_block (a->block, last_block);
}
- ec = hash (a->hd, (unsigned char *)a->block,
- 1024, result, a->outlen);
+ ec = hash (a->hd, a->block, 1024, result, a->outlen);
return ec;
}
diff --git a/tests/t-kdf.c b/tests/t-kdf.c
index 3af9c621..7963b36d 100644
--- a/tests/t-kdf.c
+++ b/tests/t-kdf.c
@@ -1376,15 +1376,27 @@ check_argon2 (void)
const unsigned char ad[12] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
unsigned char out[32];
unsigned char expected[32] = {
+#if 1
+ 0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97,
+ 0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94,
+ 0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1,
+ 0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb
+#elif 0 /* GCRY_KDF_ARGON2I */
+ 0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa,
+ 0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1,
+ 0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2,
+ 0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8
+#else /* GCRY_KDF_ARGON2ID */
0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c,
0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9,
0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e,
0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59
+#endif
};
int i;
err = my_kdf_derive (0,
- GCRY_KDF_ARGON2, GCRY_KDF_ARGON2ID, param, 4,
+ GCRY_KDF_ARGON2, GCRY_KDF_ARGON2D, param, 4,
pass, 32, salt, 16, key, 8, ad, 12,
32, out);
if (err)
@@ -1400,7 +1412,7 @@ check_argon2 (void)
#ifdef HAVE_PTHREAD
err = my_kdf_derive (1,
- GCRY_KDF_ARGON2, GCRY_KDF_ARGON2ID, param, 5,
+ GCRY_KDF_ARGON2, GCRY_KDF_ARGON2D, param, 5,
pass, 32, salt, 16, key, 8, ad, 12,
32, out);
if (err)