From 50b1e0f274a1493ac3aac3965fad66e544187666 Mon Sep 17 00:00:00 2001 From: Loup Vaillant Date: Thu, 27 Jul 2023 12:36:13 +0200 Subject: [PATCH] Fix Argon2 multiple lanes bug Argon2 failed to conform to the reference implementation when used with multiple lanes, rendering it useless for this compatibility use case. The error came from the way we select the reference set: - On the first slice of the first pass, only the current lane is valid. - When selecting other lanes, only fully completed segments are valid. - The previous block of *all* lanes must be excluded. Fixes #263 --- src/monocypher.c | 12 +++++++++--- tests/gen/vectors/argon2 | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/monocypher.c b/src/monocypher.c index 11de568..9423b08 100644 --- a/src/monocypher.c +++ b/src/monocypher.c @@ -863,16 +863,22 @@ void crypto_argon2(u8 *hash, u32 hash_size, void *work_area, u32 next_slice = ((slice + 1) % 4) * segment_size; u32 window_start = pass == 0 ? 0 : next_slice; u32 nb_segments = pass == 0 ? slice : 3; - u32 window_size = nb_segments * segment_size + block - 1; + u64 lane = + pass == 0 && slice == 0 + ? segment + : (index_seed >> 32) % config.nb_lanes; + u32 window_size = + nb_segments * segment_size + + (lane == segment ? block-1 : + block == 0 ? (u32)-1 : 0); // Find reference block u64 j1 = index_seed & 0xffffffff; // block selector - u64 j2 = index_seed >> 32; // lane selector u64 x = (j1 * j1) >> 32; u64 y = (window_size * x) >> 32; u64 z = (window_size - 1) - y; u64 ref = (window_start + z) % lane_size; - u32 index = (j2%config.nb_lanes)*lane_size + (u32)ref; + u32 index = lane * lane_size + (u32)ref; blk *reference = blocks + index; // Shuffle the previous & reference block diff --git a/tests/gen/vectors/argon2 b/tests/gen/vectors/argon2 index d57614e..c111670 100644 --- a/tests/gen/vectors/argon2 +++ b/tests/gen/vectors/argon2 @@ -60,3 +60,17 @@ c814d9d1dc7f37aa13f0d77f2494bda1c8de6b016dd388d29952a4c4672b6ce8: 0303030303030303: 040404040404040404040404: 0d640df58d78766c08c037a34a8b53c9d01ef0452d75b65eb52520e96b01e659: + +# +# This one was modified from the RFC (Argon2d) to 2 lanes, +# which is enough to trigger the reference set error +# +0000000000000000: +2000000000000000: +0300000000000000: +0200000000000000: +0101010101010101010101010101010101010101010101010101010101010101: +02020202020202020202020202020202: +0303030303030303: +040404040404040404040404: +c53c3e988d88e8c37b322e3302d273f4847eb058bf06449f647ea6396f14e87c: -- 2.47.3