1/* 2 * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include "internal/cryptlib.h" 11#include <openssl/rand.h> 12#include "crypto/rand_pool.h" 13#include "crypto/rand.h" 14#include "prov/seeding.h" 15 16#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 17 18# ifndef OPENSSL_RAND_SEED_OS 19# error "Unsupported seeding method configured; must be os" 20# endif 21 22# include <windows.h> 23/* On Windows Vista or higher use BCrypt instead of the legacy CryptoAPI */ 24# if defined(_MSC_VER) && _MSC_VER > 1500 /* 1500 = Visual Studio 2008 */ \ 25 && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 26# define USE_BCRYPTGENRANDOM 27# endif 28 29# ifdef USE_BCRYPTGENRANDOM 30# include <bcrypt.h> 31# ifdef _MSC_VER 32# pragma comment(lib, "bcrypt.lib") 33# endif 34# ifndef STATUS_SUCCESS 35# define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 36# endif 37# else 38# include <wincrypt.h> 39/* 40 * Intel hardware RNG CSP -- available from 41 * http://developer.intel.com/design/security/rng/redist_license.htm 42 */ 43# define PROV_INTEL_SEC 22 44# define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" 45# endif 46 47size_t ossl_pool_acquire_entropy(RAND_POOL *pool) 48{ 49# ifndef USE_BCRYPTGENRANDOM 50 HCRYPTPROV hProvider; 51# endif 52 unsigned char *buffer; 53 size_t bytes_needed; 54 size_t entropy_available = 0; 55 56 57# ifdef OPENSSL_RAND_SEED_RDTSC 58 entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); 59 if (entropy_available > 0) 60 return entropy_available; 61# endif 62 63# ifdef OPENSSL_RAND_SEED_RDCPU 64 entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); 65 if (entropy_available > 0) 66 return entropy_available; 67# endif 68 69# ifdef USE_BCRYPTGENRANDOM 70 bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); 71 buffer = ossl_rand_pool_add_begin(pool, bytes_needed); 72 if (buffer != NULL) { 73 size_t bytes = 0; 74 if (BCryptGenRandom(NULL, buffer, bytes_needed, 75 BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) 76 bytes = bytes_needed; 77 78 ossl_rand_pool_add_end(pool, bytes, 8 * bytes); 79 entropy_available = ossl_rand_pool_entropy_available(pool); 80 } 81 if (entropy_available > 0) 82 return entropy_available; 83# else 84 bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); 85 buffer = ossl_rand_pool_add_begin(pool, bytes_needed); 86 if (buffer != NULL) { 87 size_t bytes = 0; 88 /* poll the CryptoAPI PRNG */ 89 if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, 90 CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { 91 if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) 92 bytes = bytes_needed; 93 94 CryptReleaseContext(hProvider, 0); 95 } 96 97 ossl_rand_pool_add_end(pool, bytes, 8 * bytes); 98 entropy_available = ossl_rand_pool_entropy_available(pool); 99 } 100 if (entropy_available > 0) 101 return entropy_available; 102 103 bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); 104 buffer = ossl_rand_pool_add_begin(pool, bytes_needed); 105 if (buffer != NULL) { 106 size_t bytes = 0; 107 /* poll the Pentium PRG with CryptoAPI */ 108 if (CryptAcquireContextW(&hProvider, NULL, 109 INTEL_DEF_PROV, PROV_INTEL_SEC, 110 CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { 111 if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) 112 bytes = bytes_needed; 113 114 CryptReleaseContext(hProvider, 0); 115 } 116 ossl_rand_pool_add_end(pool, bytes, 8 * bytes); 117 entropy_available = ossl_rand_pool_entropy_available(pool); 118 } 119 if (entropy_available > 0) 120 return entropy_available; 121# endif 122 123 return ossl_rand_pool_entropy_available(pool); 124} 125 126 127int ossl_pool_add_nonce_data(RAND_POOL *pool) 128{ 129 struct { 130 DWORD pid; 131 DWORD tid; 132 FILETIME time; 133 } data; 134 135 /* Erase the entire structure including any padding */ 136 memset(&data, 0, sizeof(data)); 137 138 /* 139 * Add process id, thread id, and a high resolution timestamp to 140 * ensure that the nonce is unique with high probability for 141 * different process instances. 142 */ 143 data.pid = GetCurrentProcessId(); 144 data.tid = GetCurrentThreadId(); 145 GetSystemTimeAsFileTime(&data.time); 146 147 return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); 148} 149 150int ossl_rand_pool_add_additional_data(RAND_POOL *pool) 151{ 152 struct { 153 DWORD tid; 154 LARGE_INTEGER time; 155 } data; 156 157 /* Erase the entire structure including any padding */ 158 memset(&data, 0, sizeof(data)); 159 160 /* 161 * Add some noise from the thread id and a high resolution timer. 162 * The thread id adds a little randomness if the drbg is accessed 163 * concurrently (which is the case for the <master> drbg). 164 */ 165 data.tid = GetCurrentThreadId(); 166 QueryPerformanceCounter(&data.time); 167 return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); 168} 169 170int ossl_rand_pool_init(void) 171{ 172 return 1; 173} 174 175void ossl_rand_pool_cleanup(void) 176{ 177} 178 179void ossl_rand_pool_keep_random_devices_open(int keep) 180{ 181} 182 183#endif 184