1 /** 2 * Win32 CAPI EntropySource 3 * 4 * Copyright: 5 * (C) 1999-2007,2015 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.entropy.es_capi; 12 13 version(Windows): 14 import botan.constants; 15 static if (BOTAN_HAS_ENTROPY_SRC_CAPI): 16 17 import botan.entropy.entropy_src; 18 import botan.utils.types; 19 import botan.utils.parsing; 20 21 /** 22 * Win32 CAPI Entropy Source 23 */ 24 final class Win32CAPIEntropySource : EntropySource 25 { 26 public: 27 @property string name() const { return "Win32 CryptoGenRandom"; } 28 29 /* 30 * Gather Entropy from Win32 CAPI 31 */ 32 void poll(ref EntropyAccumulator accum) 33 { 34 m_buf.length = 32; 35 36 foreach (prov_type; m_prov_types[]) 37 { 38 auto csp = new CSPHandle(prov_type); 39 scope(exit) csp.destroy(); 40 41 if (size_t got = csp.genRandom(m_buf.ptr, m_buf.length)) 42 { 43 accum.add(m_buf.ptr, got, 6); 44 break; 45 } 46 } 47 } 48 49 /** 50 * Win32_Capi_Entropysource Constructor 51 * Params: 52 * provs = list of providers, separated by ':' 53 */ 54 this(in string provs = "") 55 { 56 Vector!string capi_provs = splitter(provs, ':'); 57 58 foreach (capi_prov; capi_provs[]) 59 { 60 if (capi_prov == "RSA_FULL") m_prov_types.pushBack(PROV_RSA_FULL); 61 if (capi_prov == "INTEL_SEC") m_prov_types.pushBack(PROV_INTEL_SEC); 62 if (capi_prov == "FORTEZZA") m_prov_types.pushBack(PROV_FORTEZZA); 63 if (capi_prov == "RNG") m_prov_types.pushBack(PROV_RNG); 64 } 65 66 if (m_prov_types.length == 0) 67 m_prov_types.pushBack(PROV_RSA_FULL); 68 } 69 70 private: 71 Vector!( ulong ) m_prov_types; 72 SecureVector!ubyte m_buf; 73 } 74 75 final class CSPHandle 76 { 77 public: 78 this(ulong capi_provider) 79 { 80 DWORD prov_type = cast(DWORD)capi_provider; 81 82 if (CryptAcquireContext(&m_handle, null, null, prov_type, cast(DWORD) CRYPT_VERIFYCONTEXT)) 83 m_valid = true; 84 } 85 86 ~this() 87 { 88 if (isValid()) 89 CryptReleaseContext(m_handle, 0); 90 } 91 92 size_t genRandom(ubyte* output, size_t length) const 93 { 94 if (isValid() && CryptGenRandom(m_handle, cast(DWORD) length, output)) 95 return length; 96 return 0; 97 } 98 99 bool isValid() const { return m_valid; } 100 101 HCRYPTPROV getHandle() const { return m_handle; } 102 private: 103 HCRYPTPROV m_handle; 104 bool m_valid; 105 } 106 107 private: 108 109 alias ULONG = uint; 110 alias DWORD = ULONG; 111 alias HCRYPTPROV = ULONG; 112 alias PBYTE = ubyte*; 113 enum { 114 PROV_RSA_FULL = 1, 115 PROV_FORTEZZA = 4, 116 PROV_RNG = 21, 117 PROV_INTEL_SEC = 22 118 } 119 alias BOOL = int; 120 alias LPCSTR = const(char)*; 121 alias LPCWSTR = const(wchar)*; 122 enum { 123 CRYPT_VERIFYCONTEXT = 0xF0000000, 124 } 125 126 extern (Windows) { 127 BOOL CryptReleaseContext(HCRYPTPROV, DWORD); 128 BOOL CryptGenRandom(HCRYPTPROV, DWORD, PBYTE); 129 130 version(Unicode) { 131 BOOL CryptAcquireContextW(HCRYPTPROV*, LPCWSTR, LPCWSTR, DWORD, DWORD); 132 alias CryptAcquireContext = CryptAcquireContextW; 133 } 134 else { 135 BOOL CryptAcquireContextA(HCRYPTPROV*, LPCSTR, LPCSTR, DWORD, DWORD); 136 alias CryptAcquireContext = CryptAcquireContextA; 137 } 138 }