authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-08-18 12:15:39+12:00
committergravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-08-18 12:15:39+12:00
log53b18b079189cce355767ce4fde4fc586f0d3248
tree73602f288599dd105b544b3ea7b4af02cf161623
parent1da93caced5511d5b2d666fe40c5db108580e2aa

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.

1 files changed, 18 insertions(+), 0 deletions(-)

std/mem.zig+18
......@@ -175,6 +175,24 @@ pub fn set(comptime T: type, dest: []T, value: T) void {
175175 d.* = value;
176176}
177177
178pub fn secureZero(comptime T: type, s: []T) void {
179 // NOTE: We do not use a volatile slice cast here since LLVM cannot
180 // see that it can be replaced by a memset.
181 const ptr = @ptrCast([*]volatile u8, s.ptr);
182 const len = s.len * @sizeOf(T);
183 @memset(ptr, 0, len);
184}
185
186test "mem.secureZero" {
187 var a = []u8{0xfe} ** 8;
188 var b = []u8{0xfe} ** 8;
189
190 set(u8, a[0..], 0);
191 secureZero(u8, b[0..]);
192
193 assert(eql(u8, a[0..], b[0..]));
194}
195
178196pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {
179197 const n = math.min(lhs.len, rhs.len);
180198 var i: usize = 0;