xref: /netbsd-src/external/bsd/elftosb/dist/common/Random.cpp (revision 993229b6fea628ff8b1fa09146c80b0cfb2768eb)
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