Home | History | Annotate | Line # | Download | only in seeding
      1 /*
      2  * Copyright 1995-2021 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 
     47 size_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 #ifdef OPENSSL_RAND_SEED_RDTSC
     57     entropy_available = ossl_prov_acquire_entropy_from_tsc(pool);
     58     if (entropy_available > 0)
     59         return entropy_available;
     60 #endif
     61 
     62 #ifdef OPENSSL_RAND_SEED_RDCPU
     63     entropy_available = ossl_prov_acquire_entropy_from_cpu(pool);
     64     if (entropy_available > 0)
     65         return entropy_available;
     66 #endif
     67 
     68 #ifdef USE_BCRYPTGENRANDOM
     69     bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     70     buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
     71     if (buffer != NULL) {
     72         size_t bytes = 0;
     73         if (BCryptGenRandom(NULL, buffer, bytes_needed,
     74                 BCRYPT_USE_SYSTEM_PREFERRED_RNG)
     75             == 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)
     91             != 0) {
     92             if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0)
     93                 bytes = bytes_needed;
     94 
     95             CryptReleaseContext(hProvider, 0);
     96         }
     97 
     98         ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
     99         entropy_available = ossl_rand_pool_entropy_available(pool);
    100     }
    101     if (entropy_available > 0)
    102         return entropy_available;
    103 
    104     bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
    105     buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
    106     if (buffer != NULL) {
    107         size_t bytes = 0;
    108         /* poll the Pentium PRG with CryptoAPI */
    109         if (CryptAcquireContextW(&hProvider, NULL,
    110                 INTEL_DEF_PROV, PROV_INTEL_SEC,
    111                 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
    112             != 0) {
    113             if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0)
    114                 bytes = bytes_needed;
    115 
    116             CryptReleaseContext(hProvider, 0);
    117         }
    118         ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
    119         entropy_available = ossl_rand_pool_entropy_available(pool);
    120     }
    121     if (entropy_available > 0)
    122         return entropy_available;
    123 #endif
    124 
    125     return ossl_rand_pool_entropy_available(pool);
    126 }
    127 
    128 int ossl_pool_add_nonce_data(RAND_POOL *pool)
    129 {
    130     struct {
    131         DWORD pid;
    132         DWORD tid;
    133         FILETIME time;
    134     } data;
    135 
    136     /* Erase the entire structure including any padding */
    137     memset(&data, 0, sizeof(data));
    138 
    139     /*
    140      * Add process id, thread id, and a high resolution timestamp to
    141      * ensure that the nonce is unique with high probability for
    142      * different process instances.
    143      */
    144     data.pid = GetCurrentProcessId();
    145     data.tid = GetCurrentThreadId();
    146     GetSystemTimeAsFileTime(&data.time);
    147 
    148     return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
    149 }
    150 
    151 int ossl_rand_pool_init(void)
    152 {
    153     return 1;
    154 }
    155 
    156 void ossl_rand_pool_cleanup(void)
    157 {
    158 }
    159 
    160 void ossl_rand_pool_keep_random_devices_open(int keep)
    161 {
    162 }
    163 
    164 #endif
    165