1*993229b6Sjkunz /*
2*993229b6Sjkunz * File: Random.cpp
3*993229b6Sjkunz *
4*993229b6Sjkunz * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5*993229b6Sjkunz * See included license file for license details.
6*993229b6Sjkunz */
7*993229b6Sjkunz
8*993229b6Sjkunz #include "Random.h"
9*993229b6Sjkunz #include <stdexcept>
10*993229b6Sjkunz
11*993229b6Sjkunz #ifdef WIN32
12*993229b6Sjkunz #ifndef _WIN32_WINNT
13*993229b6Sjkunz #define _WIN32_WINNT 0x0400
14*993229b6Sjkunz #endif
15*993229b6Sjkunz #include <windows.h>
16*993229b6Sjkunz #include <wincrypt.h>
17*993229b6Sjkunz #else // WIN32
18*993229b6Sjkunz #include <errno.h>
19*993229b6Sjkunz #include <fcntl.h>
20*993229b6Sjkunz #include <unistd.h>
21*993229b6Sjkunz #endif // WIN32
22*993229b6Sjkunz
23*993229b6Sjkunz
24*993229b6Sjkunz
25*993229b6Sjkunz #ifdef WIN32
26*993229b6Sjkunz
MicrosoftCryptoProvider()27*993229b6Sjkunz MicrosoftCryptoProvider::MicrosoftCryptoProvider()
28*993229b6Sjkunz {
29*993229b6Sjkunz if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
30*993229b6Sjkunz {
31*993229b6Sjkunz throw std::runtime_error("CryptAcquireContext");
32*993229b6Sjkunz }
33*993229b6Sjkunz }
34*993229b6Sjkunz
~MicrosoftCryptoProvider()35*993229b6Sjkunz MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
36*993229b6Sjkunz {
37*993229b6Sjkunz CryptReleaseContext(m_hProvider, 0);
38*993229b6Sjkunz }
39*993229b6Sjkunz
40*993229b6Sjkunz #endif // WIN32
41*993229b6Sjkunz
RandomNumberGenerator()42*993229b6Sjkunz RandomNumberGenerator::RandomNumberGenerator()
43*993229b6Sjkunz {
44*993229b6Sjkunz #ifndef WIN32
45*993229b6Sjkunz m_fd = open("/dev/urandom",O_RDONLY);
46*993229b6Sjkunz if (m_fd == -1)
47*993229b6Sjkunz {
48*993229b6Sjkunz throw std::runtime_error("open /dev/urandom");
49*993229b6Sjkunz }
50*993229b6Sjkunz #endif // WIN32
51*993229b6Sjkunz }
52*993229b6Sjkunz
~RandomNumberGenerator()53*993229b6Sjkunz RandomNumberGenerator::~RandomNumberGenerator()
54*993229b6Sjkunz {
55*993229b6Sjkunz #ifndef WIN32
56*993229b6Sjkunz close(m_fd);
57*993229b6Sjkunz #endif // WIN32
58*993229b6Sjkunz }
59*993229b6Sjkunz
generateByte()60*993229b6Sjkunz uint8_t RandomNumberGenerator::generateByte()
61*993229b6Sjkunz {
62*993229b6Sjkunz uint8_t result;
63*993229b6Sjkunz generateBlock(&result, 1);
64*993229b6Sjkunz return result;
65*993229b6Sjkunz }
66*993229b6Sjkunz
generateBlock(uint8_t * output,unsigned count)67*993229b6Sjkunz void RandomNumberGenerator::generateBlock(uint8_t * output, unsigned count)
68*993229b6Sjkunz {
69*993229b6Sjkunz #ifdef WIN32
70*993229b6Sjkunz # ifdef WORKAROUND_MS_BUG_Q258000
71*993229b6Sjkunz static MicrosoftCryptoProvider m_provider;
72*993229b6Sjkunz # endif
73*993229b6Sjkunz if (!CryptGenRandom(m_provider.GetProviderHandle(), count, output))
74*993229b6Sjkunz {
75*993229b6Sjkunz throw std::runtime_error("CryptGenRandom");
76*993229b6Sjkunz }
77*993229b6Sjkunz #else // WIN32
78*993229b6Sjkunz if (read(m_fd, output, count) != count)
79*993229b6Sjkunz {
80*993229b6Sjkunz throw std::runtime_error("read /dev/urandom");
81*993229b6Sjkunz }
82*993229b6Sjkunz #endif // WIN32
83*993229b6Sjkunz }
84*993229b6Sjkunz
85*993229b6Sjkunz
86