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