1 module dcrypt.util; 2 3 import core.vararg; 4 import std.traits; 5 import std.algorithm; 6 7 /// TODO: neat variadic implementation of `wipe()` 8 9 /// Clears data in memory. 10 @safe @nogc nothrow 11 void wipe(T)(ref T t) { 12 static if(isArray!T) { 13 t[] = 0; 14 assert(all!"a == 0"(t[]), "Failed to wipe ubyte[]."); 15 } else static if ( is(typeof( {T a = T.init;} ))) { 16 t = T.init; 17 } else { 18 static assert(false, "Type not supported for wiping: " ~ T.stringof); 19 } 20 } 21 22 23 @safe @nogc nothrow 24 void wipe(T...)(ref T ts) { 25 foreach(ref t; ts) { 26 wipe(t); 27 } 28 } 29 30 // test static arrays 31 unittest { 32 ubyte[4] buf1 = [1,2,3,4]; 33 uint[4] buf2 = [1,2,3,4]; 34 size_t[4] buf3 = [1,2,3,4]; 35 36 wipe(buf1); 37 wipe(buf2); 38 wipe(buf3); 39 40 assert(all!"a == 0"(buf1[]), "Failed to wipe ubyte[]."); 41 assert(all!"a == 0"(buf2[]), "Failed to wipe ubyte[]."); 42 assert(all!"a == 0"(buf3[]), "Failed to wipe ubyte[]."); 43 } 44 45 // test dynamic arrays 46 unittest { 47 ubyte[] buf1 = [1,2,3,4]; 48 uint[] buf2 = [1,2,3,4]; 49 size_t[] buf3 = [1,2,3,4]; 50 51 wipe(buf1, buf2, buf3); 52 53 assert(all!"a == 0"(buf1), "Failed to wipe ubyte[]."); 54 assert(all!"a == 0"(buf2), "Failed to wipe ubyte[]."); 55 assert(all!"a == 0"(buf3), "Failed to wipe ubyte[]."); 56 } 57 58 unittest { 59 int a = 42; 60 int b = 84; 61 ubyte c = 1; 62 63 wipe(a, b, c); 64 65 assert(a == 0 && b == 0 && c == 0, "Wiping integer failed!"); 66 } 67 68 /// Compares a and b in constant time. 69 /// 70 /// Returns: 0 if a == b, some other value if a != b. 71 bool crypto_equals(T)(in T[] a, in T[] b) pure nothrow @safe @nogc 72 in { 73 assert(a.length == b.length, "Unequal length."); 74 } body { 75 T result = 0; 76 size_t i = 0; 77 78 while(i < a.length) { 79 result |= a[i] ^ b[i]; 80 ++i; 81 } 82 83 if(i != a.length) { 84 // Just to be sure that the compiler optimization does not destroy const time. 85 assert(false); 86 } 87 88 return result == 0; 89 } 90 91 // test crypto_equals 92 unittest { 93 ubyte[32] f = 0; 94 immutable ubyte[32] zero = 0; 95 assert(crypto_equals(f[], zero[])); 96 f[8] = 1; 97 assert(!crypto_equals(f[], zero[])); 98 }