Botan  1.11.15
src/lib/entropy/cryptoapi_rng/es_capi.cpp
Go to the documentation of this file.
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 }