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 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 35 MicrosoftCryptoProvider::~MicrosoftCryptoProvider() 36 { 37 CryptReleaseContext(m_hProvider, 0); 38 } 39 40 #endif // WIN32 41 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 53 RandomNumberGenerator::~RandomNumberGenerator() 54 { 55 #ifndef WIN32 56 close(m_fd); 57 #endif // WIN32 58 } 59 60 uint8_t RandomNumberGenerator::generateByte() 61 { 62 uint8_t result; 63 generateBlock(&result, 1); 64 return result; 65 } 66 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