authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2021-04-26 22:32:22+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2021-04-26 22:32:22+02:00
logd3361c41db638dc606c2e7259900cd281c5e95e4
tree15cef3824b63989cfb5c52846dcddcfa8e4dbf26
parent0747591c3d7469cf3ac5c1a6a80b6058386e337a

Change timingSafeCompare() to accept slices


1 files changed, 37 insertions(+), 43 deletions(-)

lib/std/crypto/utils.zig+37-43
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const debug = std.debug;
2const mem = std.mem;3const mem = std.mem;
3const testing = std.testing;4const testing = std.testing;
45
...@@ -43,44 +44,37 @@ pub fn timingSafeEql(comptime T: type, a: T, b: T) bool {...@@ -43,44 +44,37 @@ pub fn timingSafeEql(comptime T: type, a: T, b: T) bool {
4344
44/// Compare two integers serialized as arrays of the same size, in constant time.45/// Compare two integers serialized as arrays of the same size, in constant time.
45/// Returns .lt if a<b, .gt if a>b and .eq if a=b46/// Returns .lt if a<b, .gt if a>b and .eq if a=b
46pub fn timingSafeCompare(comptime T: type, a: T, b: T, endian: Endian) Order {47pub fn timingSafeCompare(comptime T: type, a: []const T, b: []const T, endian: Endian) Order {
47 switch (@typeInfo(T)) {48 debug.assert(a.len == b.len);
48 .Array => |info| {49 const bits = switch (@typeInfo(T)) {
49 const C = info.child;50 .Int => |cinfo| if (cinfo.signedness != .unsigned) @compileError("Elements to be compared must be unsigned") else cinfo.bits,
50 const bits = switch (@typeInfo(C)) {51 else => @compileError("Elements to be compared must be integers"),
51 .Int => |cinfo| if (cinfo.signedness != .unsigned) @compileError("Elements to be compared must be unsigned") else cinfo.bits,52 };
52 else => @compileError("Elements to be compared must be integers"),53 comptime const Cext = std.meta.Int(.unsigned, bits + 1);
53 };54 var gt: T = 0;
54 comptime const Cext = std.meta.Int(.unsigned, bits + 1);55 var eq: T = 1;
55 var gt: C = 0;56 if (endian == .Little) {
56 var eq: C = 1;57 var i = a.len;
57 if (endian == .Little) {58 while (i != 0) {
58 var i = a.len;59 i -= 1;
59 while (i != 0) {60 const x1 = a[i];
60 i -= 1;61 const x2 = b[i];
61 const x1 = a[i];62 gt |= @truncate(T, (@as(Cext, x2) -% @as(Cext, x1)) >> bits) & eq;
62 const x2 = b[i];63 eq &= @truncate(T, (@as(Cext, (x2 ^ x1)) -% 1) >> bits);
63 gt |= @truncate(C, (@as(Cext, x2) -% @as(Cext, x1)) >> bits) & eq;64 }
64 eq &= @truncate(C, (@as(Cext, (x2 ^ x1)) -% 1) >> bits);65 } else {
65 }66 for (a) |x1, i| {
66 } else {67 const x2 = b[i];
67 for (a) |x1, i| {68 gt |= @truncate(T, (@as(Cext, x2) -% @as(Cext, x1)) >> bits) & eq;
68 const x2 = b[i];69 eq &= @truncate(T, (@as(Cext, (x2 ^ x1)) -% 1) >> bits);
69 gt |= @truncate(C, (@as(Cext, x2) -% @as(Cext, x1)) >> bits) & eq;70 }
70 eq &= @truncate(C, (@as(Cext, (x2 ^ x1)) -% 1) >> bits);71 }
71 }72 if (gt != 0) {
72 }73 return Order.gt;
73 if (gt != 0) {74 } else if (eq != 0) {
74 return Order.gt;75 return Order.eq;
75 } else if (eq != 0) {
76 return Order.eq;
77 }
78 return Order.lt;
79 },
80 else => {
81 @compileError("Only arrays can be compared");
82 },
83 }76 }
77 return Order.lt;
84}78}
8579
86/// Sets a slice to zeroes.80/// Sets a slice to zeroes.
...@@ -118,14 +112,14 @@ test "crypto.utils.timingSafeEql (vectors)" {...@@ -118,14 +112,14 @@ test "crypto.utils.timingSafeEql (vectors)" {
118test "crypto.utils.timingSafeCompare" {112test "crypto.utils.timingSafeCompare" {
119 var a = [_]u8{10} ** 32;113 var a = [_]u8{10} ** 32;
120 var b = [_]u8{10} ** 32;114 var b = [_]u8{10} ** 32;
121 testing.expectEqual(timingSafeCompare([32]u8, a, b, .Big), .eq);115 testing.expectEqual(timingSafeCompare(u8, &a, &b, .Big), .eq);
122 testing.expectEqual(timingSafeCompare([32]u8, a, b, .Little), .eq);116 testing.expectEqual(timingSafeCompare(u8, &a, &b, .Little), .eq);
123 a[31] = 1;117 a[31] = 1;
124 testing.expectEqual(timingSafeCompare([32]u8, a, b, .Big), .lt);118 testing.expectEqual(timingSafeCompare(u8, &a, &b, .Big), .lt);
125 testing.expectEqual(timingSafeCompare([32]u8, a, b, .Little), .lt);119 testing.expectEqual(timingSafeCompare(u8, &a, &b, .Little), .lt);
126 a[0] = 20;120 a[0] = 20;
127 testing.expectEqual(timingSafeCompare([32]u8, a, b, .Big), .gt);121 testing.expectEqual(timingSafeCompare(u8, &a, &b, .Big), .gt);
128 testing.expectEqual(timingSafeCompare([32]u8, a, b, .Little), .lt);122 testing.expectEqual(timingSafeCompare(u8, &a, &b, .Little), .lt);
129}123}
130124
131test "crypto.utils.secureZero" {125test "crypto.utils.secureZero" {