From bc0e32ee7d038c38cff7d59ed188ef95376f9a3b Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sat, 3 Nov 2018 17:08:44 +0900 Subject: [PATCH] std.mem: function for comparing two slices in constant type for cryptographic primitives; --- std/mem.zig | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/std/mem.zig b/std/mem.zig index ca961874798d..b32c4d0b09a3 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -246,6 +246,7 @@ test "mem.lessThan" { } /// Compares two slices and returns whether they are equal. +/// Use `constant_time_eql` inside cryptographic primitives pub fn eql(comptime T: type, a: []const T, b: []const T) bool { if (a.len != b.len) return false; for (a) |item, index| { @@ -254,6 +255,27 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { return true; } +/// Compares two slices and returns whether they are equal in constant time. +pub fn constant_time_eql(comptime T: type, a: []const T, b: []const T) T { + //TODO: https://github.com/ziglang/zig/issues/640 + return @noInlineCall(noinline__constant_time_eql, T, a, b); +} + +fn noinline__constant_time_eql(comptime T: type, a: []const T, b: []const T) T { + if (a.len != b.len) return 1; + var tmp: T = 0; + var count: usize = a.len - 1; + while (count != 0) : (count -= 1) { + tmp |= a[count] ^ b[count]; + } + return tmp; +} + +test "mem.constant_time_eql" { + assert(constant_time_eql(u8, "abc", "abc") == 0); + assert(constant_time_eql(u8, "abc", "abd") != 0); +} + pub fn len(comptime T: type, ptr: [*]const T) usize { var count: usize = 0; while (ptr[count] != 0) : (count += 1) {}