aboutsummaryrefslogtreecommitdiffstats
path: root/modules/es_capi/es_capi.cpp
blob: 95bc3d969a029cdb29b381b67dc5997ee8594e7d (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*************************************************
* Win32 CryptoAPI EntropySource Source File      *
* (C) 1999-2006 The Botan Project                *
*************************************************/

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

namespace Botan {

namespace {

/*************************************************
* CSP Handle                                     *
*************************************************/
class CSP_Handle
   {
   public:
      CSP_Handle(u64bit);
      ~CSP_Handle();

      void gen_random(byte[], u32bit) const;
      bool is_valid() const { return valid; }

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

/*************************************************
* Call CryptGenRandom                            *
*************************************************/
void CSP_Handle::gen_random(byte out[], u32bit n) const
   {
   CryptGenRandom(handle, n, out);
   }

/*************************************************
* Initialize a CSP Handle                        *
*************************************************/
CSP_Handle::CSP_Handle(u64bit capi_provider)
   {
   valid = false;
   DWORD prov_type = (DWORD)capi_provider;

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

/*************************************************
* Destroy a CSP Handle                           *
*************************************************/
CSP_Handle::~CSP_Handle()
   {
   if(valid)
      CryptReleaseContext(handle, 0);
   }

}

/*************************************************
* Gather Entropy from Win32 CAPI                 *
*************************************************/
u32bit Win32_CAPI_EntropySource::slow_poll(byte output[], u32bit length)
   {
   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;

   if(provs == "")
      capi_provs = Config::get_list("rng/ms_capi_prov_type");
   else
      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);
   }

}