1 /*
2 * Derived from Botan's Mlock Allocator
3 * 
4 * This is a more advanced base allocator.
5 * 
6 * (C) 2012,2014 Jack Lloyd
7 * (C) 2014-2015 Etienne Cimon
8 * (C) 2014,2015 Etienne Cimon
9 *
10 * Distributed under the terms of the Simplified BSD License (see Botan's license.txt)
11 */
12 module memutils.cryptosafe;
13 import memutils.constants;
14 static if (HasBotan || HasCryptoSafe):
15 pragma(msg, "Enhanced memory security is enabled.");
16 
17 import memutils.allocators;
18 import memutils.securepool;
19 import memutils.debugger;
20 
21 final class SecureAllocator(Base : Allocator) : Allocator
22 {
23 private:
24 	Base m_secondary;
25 	static if (HasBotan || HasSecurePool) {
26 		
27 		__gshared SecurePool ms_zeroise;	
28 		shared static this() { 
29 			//logDebug("Shared static this() SecurePool");
30 			if (!ms_zeroise) ms_zeroise = new SecurePool();
31 		}
32 		shared static ~this() { 
33 			if (ms_zeroise) destroy(ms_zeroise);
34 		}
35 	}
36 
37 public:	
38 	this() {
39 		m_secondary = getAllocator!Base();
40 	}
41 	
42 	void[] alloc(size_t n)
43 	{
44 		static if (HasBotan || HasSecurePool) {
45 			//logDebug("CryptoSafe alloc ", n);
46 			if (void[] p = ms_zeroise.alloc(n)) {
47 				//logDebug("alloc P: ", p.length, " & ", p.ptr);
48 				return p;
49 			}
50 		}
51 		//logDebug("secondary alloc");
52 		void[] p = m_secondary.alloc(n);
53 
54 		//logDebug("FALLBACK alloc P: ", p.length, " & ", p.ptr);
55 		return p;
56 	}
57 
58 	void[] realloc(void[] mem, size_t n)
59 	{
60 		//logTrace("realloc P: ", mem.length, " & ", mem.ptr);
61 		if (n <= mem.length)
62 			return mem;
63 		import std.c.string : memmove, memset;
64 
65 		static if (HasBotan || HasSecurePool) {
66 			if (ms_zeroise.has(mem)) {
67 				void[] p = ms_zeroise.alloc(n);
68 				if (!p) 
69 					p = m_secondary.alloc(n);
70 				memmove(p.ptr, mem.ptr, mem.length);
71 				memset(mem.ptr, 0, mem.length);
72 				ms_zeroise.free(mem);
73 				return p;
74 			}
75 		}
76 
77 		return m_secondary.realloc(mem, n);
78 	}
79 
80 	void free(void[] mem)
81 	{
82 		//logTrace("free P: ", mem.length, " & ", mem.ptr);
83 		import std.c.string : memset;
84 		memset(mem.ptr, 0, mem.length);
85 		static if (HasBotan || HasSecurePool)
86 			if (ms_zeroise.free(mem))
87 				return;
88 		m_secondary.free(mem);
89 	}
90 
91 }