From 53b18b079189cce355767ce4fde4fc586f0d3248 Mon Sep 17 00:00:00 2001 From: Marc Tiehuis Date: Sat, 18 Aug 2018 12:15:39 +1200 Subject: [PATCH] Add secureZero function This is identical to `mem.set(u8, slice, 0)` except that it will never be optimized out by the compiler. Intended usage is for clearing secret data. The resulting assembly has been manually verified in --release-* modes. It would be valuable to test the 'never be optimized out' claim in tests but this is harder than initially expected due to how much Zig appears to know locally. May be doable with @intToPtr, @ptrToInt to get around known data dependencies but I could not work it out right now. --- std/mem.zig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/std/mem.zig b/std/mem.zig index dc5fc8a539..f05b43ee56 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -175,6 +175,24 @@ pub fn set(comptime T: type, dest: []T, value: T) void { d.* = value; } +pub fn secureZero(comptime T: type, s: []T) void { + // NOTE: We do not use a volatile slice cast here since LLVM cannot + // see that it can be replaced by a memset. + const ptr = @ptrCast([*]volatile u8, s.ptr); + const len = s.len * @sizeOf(T); + @memset(ptr, 0, len); +} + +test "mem.secureZero" { + var a = []u8{0xfe} ** 8; + var b = []u8{0xfe} ** 8; + + set(u8, a[0..], 0); + secureZero(u8, b[0..]); + + assert(eql(u8, a[0..], b[0..])); +} + pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare { const n = math.min(lhs.len, rhs.len); var i: usize = 0;