Botan
1.11.15
|
00001 /* 00002 * Win32 CryptoAPI EntropySource 00003 * (C) 1999-2009 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/es_capi.h> 00009 #include <botan/parsing.h> 00010 #include <windows.h> 00011 #include <wincrypt.h> 00012 #undef min 00013 #undef max 00014 00015 namespace Botan { 00016 00017 namespace { 00018 00019 class CSP_Handle 00020 { 00021 public: 00022 CSP_Handle(u64bit capi_provider) 00023 { 00024 valid = false; 00025 DWORD prov_type = (DWORD)capi_provider; 00026 00027 if(CryptAcquireContext(&handle, 0, 0, 00028 prov_type, CRYPT_VERIFYCONTEXT)) 00029 valid = true; 00030 } 00031 00032 ~CSP_Handle() 00033 { 00034 if(is_valid()) 00035 CryptReleaseContext(handle, 0); 00036 } 00037 00038 size_t gen_random(byte out[], size_t n) const 00039 { 00040 if(is_valid() && CryptGenRandom(handle, static_cast<DWORD>(n), out)) 00041 return n; 00042 return 0; 00043 } 00044 00045 bool is_valid() const { return valid; } 00046 00047 HCRYPTPROV get_handle() const { return handle; } 00048 private: 00049 HCRYPTPROV handle; 00050 bool valid; 00051 }; 00052 00053 } 00054 00055 /* 00056 * Gather Entropy from Win32 CAPI 00057 */ 00058 void Win32_CAPI_EntropySource::poll(Entropy_Accumulator& accum) 00059 { 00060 secure_vector<byte>& io_buffer = accum.get_io_buffer(32); 00061 00062 for(size_t i = 0; i != prov_types.size(); ++i) 00063 { 00064 CSP_Handle csp(prov_types[i]); 00065 00066 size_t got = csp.gen_random(&io_buffer[0], io_buffer.size()); 00067 00068 if(got) 00069 { 00070 accum.add(&io_buffer[0], io_buffer.size(), 6); 00071 break; 00072 } 00073 } 00074 } 00075 00076 /* 00077 * Win32_Capi_Entropysource Constructor 00078 */ 00079 Win32_CAPI_EntropySource::Win32_CAPI_EntropySource(const std::string& provs) 00080 { 00081 std::vector<std::string> capi_provs = split_on(provs, ':'); 00082 00083 for(size_t i = 0; i != capi_provs.size(); ++i) 00084 { 00085 if(capi_provs[i] == "RSA_FULL") prov_types.push_back(PROV_RSA_FULL); 00086 if(capi_provs[i] == "INTEL_SEC") prov_types.push_back(PROV_INTEL_SEC); 00087 if(capi_provs[i] == "FORTEZZA") prov_types.push_back(PROV_FORTEZZA); 00088 if(capi_provs[i] == "RNG") prov_types.push_back(PROV_RNG); 00089 } 00090 00091 if(prov_types.size() == 0) 00092 prov_types.push_back(PROV_RSA_FULL); 00093 } 00094 00095 }