aboutsummaryrefslogtreecommitdiffstats
path: root/src/entropy/cryptoapi_rng/es_capi.cpp
blob: ca0e1b95e50f475e7699e72a61d1ee78b37fa7e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*************************************************
* Win32 CryptoAPI EntropySource Source File      *
* (C) 1999-2007 Jack Lloyd                       *
*************************************************/

#include <botan/es_capi.h>
#include <botan/parsing.h>
#include <windows.h>
#include <wincrypt.h>

namespace Botan {

/**
* Gather Entropy from Win32 CAPI
*/
u32bit Win32_CAPI_EntropySource::slow_poll(byte output[], u32bit length)
   {
   return fast_poll(output, length);
   }

/**
* Gather Entropy from Win32 CAPI
*/
u32bit Win32_CAPI_EntropySource::fast_poll(byte output[], u32bit length)
   {
   class CSP_Handle
      {
      public:
         CSP_Handle(u64bit capi_provider)
            {
            valid = false;
            DWORD prov_type = (DWORD)capi_provider;

            if(CryptAcquireContext(&handle, 0, 0,
                                   prov_type, CRYPT_VERIFYCONTEXT))
               valid = true;
            }

         ~CSP_Handle()
            {
            if(is_valid())
               CryptReleaseContext(handle, 0);
            }

         void gen_random(byte out[], u32bit n) const
            {
            if(is_valid())
               CryptGenRandom(handle, n, out);
            }

         bool is_valid() const { return valid; }

         HCRYPTPROV get_handle() const { return handle; }
      private:
         HCRYPTPROV handle;
         bool valid;
      };


   if(length > 64)
      length = 64;

   for(u32bit j = 0; j != prov_types.size(); ++j)
      {
      CSP_Handle csp(prov_types[j]);
      if(!csp.is_valid())
         continue;

      csp.gen_random(output, length);
      break;
      }
   return length;
   }

/*************************************************
* Gather Entropy from Win32 CAPI                 *
*************************************************/
Win32_CAPI_EntropySource::Win32_CAPI_EntropySource(const std::string& provs)
   {
   std::vector<std::string> capi_provs = split_on(provs, ':');

   for(u32bit j = 0; j != capi_provs.size(); ++j)
      {
      if(capi_provs[j] == "RSA_FULL")  prov_types.push_back(PROV_RSA_FULL);
      if(capi_provs[j] == "INTEL_SEC") prov_types.push_back(PROV_INTEL_SEC);
      if(capi_provs[j] == "FORTEZZA")  prov_types.push_back(PROV_FORTEZZA);
      if(capi_provs[j] == "RNG")       prov_types.push_back(PROV_RNG);
      }

   if(prov_types.size() == 0)
      prov_types.push_back(PROV_RSA_FULL);
   }

}