1/* 2 * Copyright 2020-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 <string.h> 11#include <openssl/rand.h> 12#include <openssl/core_dispatch.h> 13#include <openssl/e_os2.h> 14#include <openssl/params.h> 15#include <openssl/core_names.h> 16#include <openssl/evp.h> 17#include <openssl/err.h> 18#include <openssl/randerr.h> 19#include <openssl/proverr.h> 20#include "prov/implementations.h" 21#include "prov/provider_ctx.h" 22#include "crypto/rand.h" 23#include "crypto/rand_pool.h" 24 25static OSSL_FUNC_rand_newctx_fn seed_src_new; 26static OSSL_FUNC_rand_freectx_fn seed_src_free; 27static OSSL_FUNC_rand_instantiate_fn seed_src_instantiate; 28static OSSL_FUNC_rand_uninstantiate_fn seed_src_uninstantiate; 29static OSSL_FUNC_rand_generate_fn seed_src_generate; 30static OSSL_FUNC_rand_reseed_fn seed_src_reseed; 31static OSSL_FUNC_rand_gettable_ctx_params_fn seed_src_gettable_ctx_params; 32static OSSL_FUNC_rand_get_ctx_params_fn seed_src_get_ctx_params; 33static OSSL_FUNC_rand_verify_zeroization_fn seed_src_verify_zeroization; 34static OSSL_FUNC_rand_enable_locking_fn seed_src_enable_locking; 35static OSSL_FUNC_rand_lock_fn seed_src_lock; 36static OSSL_FUNC_rand_unlock_fn seed_src_unlock; 37static OSSL_FUNC_rand_get_seed_fn seed_get_seed; 38static OSSL_FUNC_rand_clear_seed_fn seed_clear_seed; 39 40typedef struct { 41 void *provctx; 42 int state; 43} PROV_SEED_SRC; 44 45static void *seed_src_new(void *provctx, void *parent, 46 const OSSL_DISPATCH *parent_dispatch) 47{ 48 PROV_SEED_SRC *s; 49 50 if (parent != NULL) { 51 ERR_raise(ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT); 52 return NULL; 53 } 54 55 s = OPENSSL_zalloc(sizeof(*s)); 56 if (s == NULL) { 57 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); 58 return NULL; 59 } 60 61 s->provctx = provctx; 62 s->state = EVP_RAND_STATE_UNINITIALISED; 63 return s; 64} 65 66static void seed_src_free(void *vseed) 67{ 68 OPENSSL_free(vseed); 69} 70 71static int seed_src_instantiate(void *vseed, unsigned int strength, 72 int prediction_resistance, 73 const unsigned char *pstr, size_t pstr_len, 74 ossl_unused const OSSL_PARAM params[]) 75{ 76 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 77 78 s->state = EVP_RAND_STATE_READY; 79 return 1; 80} 81 82static int seed_src_uninstantiate(void *vseed) 83{ 84 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 85 86 s->state = EVP_RAND_STATE_UNINITIALISED; 87 return 1; 88} 89 90static int seed_src_generate(void *vseed, unsigned char *out, size_t outlen, 91 unsigned int strength, 92 ossl_unused int prediction_resistance, 93 ossl_unused const unsigned char *adin, 94 ossl_unused size_t adin_len) 95{ 96 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 97 size_t entropy_available; 98 RAND_POOL *pool; 99 100 if (s->state != EVP_RAND_STATE_READY) { 101 ERR_raise(ERR_LIB_PROV, 102 s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE 103 : PROV_R_NOT_INSTANTIATED); 104 return 0; 105 } 106 107 pool = ossl_rand_pool_new(strength, 1, outlen, outlen); 108 if (pool == NULL) { 109 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); 110 return 0; 111 } 112 113 /* Get entropy by polling system entropy sources. */ 114 entropy_available = ossl_pool_acquire_entropy(pool); 115 116 if (entropy_available > 0) 117 memcpy(out, ossl_rand_pool_buffer(pool), ossl_rand_pool_length(pool)); 118 119 ossl_rand_pool_free(pool); 120 return entropy_available > 0; 121} 122 123static int seed_src_reseed(void *vseed, 124 ossl_unused int prediction_resistance, 125 ossl_unused const unsigned char *ent, 126 ossl_unused size_t ent_len, 127 ossl_unused const unsigned char *adin, 128 ossl_unused size_t adin_len) 129{ 130 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 131 132 if (s->state != EVP_RAND_STATE_READY) { 133 ERR_raise(ERR_LIB_PROV, 134 s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE 135 : PROV_R_NOT_INSTANTIATED); 136 return 0; 137 } 138 return 1; 139} 140 141static int seed_src_get_ctx_params(void *vseed, OSSL_PARAM params[]) 142{ 143 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 144 OSSL_PARAM *p; 145 146 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE); 147 if (p != NULL && !OSSL_PARAM_set_int(p, s->state)) 148 return 0; 149 150 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH); 151 if (p != NULL && !OSSL_PARAM_set_int(p, 1024)) 152 return 0; 153 154 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST); 155 if (p != NULL && !OSSL_PARAM_set_size_t(p, 128)) 156 return 0; 157 return 1; 158} 159 160static const OSSL_PARAM *seed_src_gettable_ctx_params(ossl_unused void *vseed, 161 ossl_unused void *provctx) 162{ 163 static const OSSL_PARAM known_gettable_ctx_params[] = { 164 OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL), 165 OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), 166 OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), 167 OSSL_PARAM_END 168 }; 169 return known_gettable_ctx_params; 170} 171 172static int seed_src_verify_zeroization(ossl_unused void *vseed) 173{ 174 return 1; 175} 176 177static size_t seed_get_seed(void *vseed, unsigned char **pout, 178 int entropy, size_t min_len, size_t max_len, 179 int prediction_resistance, 180 const unsigned char *adin, size_t adin_len) 181{ 182 size_t bytes_needed; 183 unsigned char *p; 184 185 /* 186 * Figure out how many bytes we need. 187 * This assumes that the seed sources provide eight bits of entropy 188 * per byte. For lower quality sources, the formula will need to be 189 * different. 190 */ 191 bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0; 192 if (bytes_needed < min_len) 193 bytes_needed = min_len; 194 if (bytes_needed > max_len) { 195 ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK); 196 return 0; 197 } 198 199 p = OPENSSL_secure_malloc(bytes_needed); 200 if (p == NULL) { 201 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); 202 return 0; 203 } 204 if (seed_src_generate(vseed, p, bytes_needed, 0, prediction_resistance, 205 adin, adin_len) != 0) { 206 *pout = p; 207 return bytes_needed; 208 } 209 OPENSSL_secure_clear_free(p, bytes_needed); 210 return 0; 211} 212 213static void seed_clear_seed(ossl_unused void *vdrbg, 214 unsigned char *out, size_t outlen) 215{ 216 OPENSSL_secure_clear_free(out, outlen); 217} 218 219static int seed_src_enable_locking(ossl_unused void *vseed) 220{ 221 return 1; 222} 223 224int seed_src_lock(ossl_unused void *vctx) 225{ 226 return 1; 227} 228 229void seed_src_unlock(ossl_unused void *vctx) 230{ 231} 232 233const OSSL_DISPATCH ossl_seed_src_functions[] = { 234 { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))seed_src_new }, 235 { OSSL_FUNC_RAND_FREECTX, (void(*)(void))seed_src_free }, 236 { OSSL_FUNC_RAND_INSTANTIATE, 237 (void(*)(void))seed_src_instantiate }, 238 { OSSL_FUNC_RAND_UNINSTANTIATE, 239 (void(*)(void))seed_src_uninstantiate }, 240 { OSSL_FUNC_RAND_GENERATE, (void(*)(void))seed_src_generate }, 241 { OSSL_FUNC_RAND_RESEED, (void(*)(void))seed_src_reseed }, 242 { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))seed_src_enable_locking }, 243 { OSSL_FUNC_RAND_LOCK, (void(*)(void))seed_src_lock }, 244 { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))seed_src_unlock }, 245 { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS, 246 (void(*)(void))seed_src_gettable_ctx_params }, 247 { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))seed_src_get_ctx_params }, 248 { OSSL_FUNC_RAND_VERIFY_ZEROIZATION, 249 (void(*)(void))seed_src_verify_zeroization }, 250 { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))seed_get_seed }, 251 { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))seed_clear_seed }, 252 { 0, NULL } 253}; 254