]> git.codecow.com Git - Monocypher.git/commitdiff
Fix Argon2 multiple lanes bug
authorLoup Vaillant <loup@loup-vaillant.fr>
Thu, 27 Jul 2023 10:36:13 +0000 (12:36 +0200)
committerLoup Vaillant <loup@loup-vaillant.fr>
Thu, 27 Jul 2023 10:36:13 +0000 (12:36 +0200)
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
tests/gen/vectors/argon2

index 11de5689bd756a6bb23a5b7bcc93a5fb7919baff..9423b083a5ed169c79525235d21bef44692ce322 100644 (file)
@@ -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
index d57614ecfee02d94d4d50a1595a19da40cb128ba..c1116702c507fe74ca254d456238961c89319a79 100644 (file)
@@ -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: