Commit e17998b396

Frank Denis <124872+jedisct1@users.noreply.github.com>
2023-03-14 22:40:02
Argon2: properly handle outputs > 64 bytes in blake2Long() (#14914)
Fixes #14912
1 parent d6e48ab
Changed files (1)
lib
std
crypto
lib/std/crypto/argon2.zig
@@ -138,40 +138,39 @@ fn initHash(
 }
 
 fn blake2bLong(out: []u8, in: []const u8) void {
-    var b2 = Blake2b512.init(.{ .expected_out_bits = math.min(512, out.len * 8) });
-
-    var buffer: [Blake2b512.digest_length]u8 = undefined;
-    mem.writeIntLittle(u32, buffer[0..4], @intCast(u32, out.len));
-    b2.update(buffer[0..4]);
-    b2.update(in);
-    b2.final(&buffer);
-
-    if (out.len <= Blake2b512.digest_length) {
-        mem.copy(u8, out, buffer[0..out.len]);
+    const H = Blake2b512;
+    var outlen_bytes: [4]u8 = undefined;
+    mem.writeIntLittle(u32, &outlen_bytes, @intCast(u32, out.len));
+
+    var out_buf: [H.digest_length]u8 = undefined;
+
+    if (out.len <= H.digest_length) {
+        var h = H.init(.{ .expected_out_bits = out.len * 8 });
+        h.update(&outlen_bytes);
+        h.update(in);
+        h.final(&out_buf);
+        mem.copy(u8, out, out_buf[0..out.len]);
         return;
     }
 
-    b2 = Blake2b512.init(.{});
-    mem.copy(u8, out, buffer[0..32]);
-    var out_slice = out[32..];
-    while (out_slice.len > Blake2b512.digest_length) : ({
-        out_slice = out_slice[32..];
-        b2 = Blake2b512.init(.{});
-    }) {
-        b2.update(&buffer);
-        b2.final(&buffer);
-        mem.copy(u8, out_slice, buffer[0..32]);
-    }
-
-    var r = Blake2b512.digest_length;
-    if (out.len % Blake2b512.digest_length > 0) {
-        r = ((out.len + 31) / 32) - 2;
-        b2 = Blake2b512.init(.{ .expected_out_bits = r * 8 });
+    var h = H.init(.{});
+    h.update(&outlen_bytes);
+    h.update(in);
+    h.final(&out_buf);
+    var out_slice = out;
+    mem.copy(u8, out_slice, out_buf[0 .. H.digest_length / 2]);
+    out_slice = out_slice[H.digest_length / 2 ..];
+
+    var in_buf: [H.digest_length]u8 = undefined;
+    while (out_slice.len > H.digest_length) {
+        mem.copy(u8, &in_buf, &out_buf);
+        H.hash(&in_buf, &out_buf, .{});
+        mem.copy(u8, out_slice, out_buf[0 .. H.digest_length / 2]);
+        out_slice = out_slice[H.digest_length / 2 ..];
     }
-
-    b2.update(&buffer);
-    b2.final(&buffer);
-    mem.copy(u8, out_slice, buffer[0..r]);
+    mem.copy(u8, &in_buf, &out_buf);
+    H.hash(&in_buf, &out_buf, .{ .expected_out_bits = out_slice.len * 8 });
+    mem.copy(u8, out_slice, out_buf[0..out_slice.len]);
 }
 
 fn initBlocks(