1/* 2 * Copyright 2020-2023 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{- 10use OpenSSL::paramnames qw(produce_param_decoder); 11-} 12 13#include <string.h> 14#include <openssl/rand.h> 15#include <openssl/core_dispatch.h> 16#include <openssl/e_os2.h> 17#include <openssl/params.h> 18#include <openssl/core_names.h> 19#include <openssl/evp.h> 20#include <openssl/err.h> 21#include <openssl/randerr.h> 22#include <openssl/proverr.h> 23#include "internal/common.h" 24#include "prov/implementations.h" 25#include "prov/provider_ctx.h" 26#include "crypto/rand.h" 27#include "crypto/rand_pool.h" 28 29static OSSL_FUNC_rand_newctx_fn seed_src_new; 30static OSSL_FUNC_rand_freectx_fn seed_src_free; 31static OSSL_FUNC_rand_instantiate_fn seed_src_instantiate; 32static OSSL_FUNC_rand_uninstantiate_fn seed_src_uninstantiate; 33static OSSL_FUNC_rand_generate_fn seed_src_generate; 34static OSSL_FUNC_rand_reseed_fn seed_src_reseed; 35static OSSL_FUNC_rand_gettable_ctx_params_fn seed_src_gettable_ctx_params; 36static OSSL_FUNC_rand_get_ctx_params_fn seed_src_get_ctx_params; 37static OSSL_FUNC_rand_verify_zeroization_fn seed_src_verify_zeroization; 38static OSSL_FUNC_rand_enable_locking_fn seed_src_enable_locking; 39static OSSL_FUNC_rand_lock_fn seed_src_lock; 40static OSSL_FUNC_rand_unlock_fn seed_src_unlock; 41static OSSL_FUNC_rand_get_seed_fn seed_get_seed; 42static OSSL_FUNC_rand_clear_seed_fn seed_clear_seed; 43 44typedef struct { 45 void *provctx; 46 int state; 47} PROV_SEED_SRC; 48 49static void *seed_src_new(void *provctx, void *parent, 50 const OSSL_DISPATCH *parent_dispatch) 51{ 52 PROV_SEED_SRC *s; 53 54 if (parent != NULL) { 55 ERR_raise(ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT); 56 return NULL; 57 } 58 59 s = OPENSSL_zalloc(sizeof(*s)); 60 if (s == NULL) 61 return NULL; 62 63 s->provctx = provctx; 64 s->state = EVP_RAND_STATE_UNINITIALISED; 65 return s; 66} 67 68static void seed_src_free(void *vseed) 69{ 70 OPENSSL_free(vseed); 71} 72 73static int seed_src_instantiate(void *vseed, unsigned int strength, 74 int prediction_resistance, 75 const unsigned char *pstr, size_t pstr_len, 76 ossl_unused const OSSL_PARAM params[]) 77{ 78 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 79 80 s->state = EVP_RAND_STATE_READY; 81 return 1; 82} 83 84static int seed_src_uninstantiate(void *vseed) 85{ 86 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 87 88 s->state = EVP_RAND_STATE_UNINITIALISED; 89 return 1; 90} 91 92static int seed_src_generate(void *vseed, unsigned char *out, size_t outlen, 93 unsigned int strength, 94 ossl_unused int prediction_resistance, 95 const unsigned char *adin, 96 size_t adin_len) 97{ 98 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 99 size_t entropy_available; 100 RAND_POOL *pool; 101 102 if (s->state != EVP_RAND_STATE_READY) { 103 ERR_raise(ERR_LIB_PROV, 104 s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE 105 : PROV_R_NOT_INSTANTIATED); 106 return 0; 107 } 108 109 pool = ossl_rand_pool_new(strength, 1, outlen, outlen); 110 if (pool == NULL) { 111 ERR_raise(ERR_LIB_PROV, ERR_R_RAND_LIB); 112 return 0; 113 } 114 115 /* Get entropy by polling system entropy sources. */ 116 entropy_available = ossl_pool_acquire_entropy(pool); 117 118 if (entropy_available > 0) { 119 if (!ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { 120 ossl_rand_pool_free(pool); 121 return 0; 122 } 123 memcpy(out, ossl_rand_pool_buffer(pool), ossl_rand_pool_length(pool)); 124 } 125 126 ossl_rand_pool_free(pool); 127 return entropy_available > 0; 128} 129 130static int seed_src_reseed(void *vseed, 131 ossl_unused int prediction_resistance, 132 ossl_unused const unsigned char *ent, 133 ossl_unused size_t ent_len, 134 ossl_unused const unsigned char *adin, 135 ossl_unused size_t adin_len) 136{ 137 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 138 139 if (s->state != EVP_RAND_STATE_READY) { 140 ERR_raise(ERR_LIB_PROV, 141 s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE 142 : PROV_R_NOT_INSTANTIATED); 143 return 0; 144 } 145 return 1; 146} 147 148{- produce_param_decoder('seed_src_get_ctx_params', 149 (['RAND_PARAM_STATE', 'state', 'int'], 150 ['RAND_PARAM_STRENGTH', 'str', 'uint'], 151 ['RAND_PARAM_MAX_REQUEST', 'maxreq', 'size_t'], 152 )); -} 153 154static int seed_src_get_ctx_params(void *vseed, OSSL_PARAM params[]) 155{ 156 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 157 struct seed_src_get_ctx_params_st p; 158 159 if (s == NULL || !seed_src_get_ctx_params_decoder(params, &p)) 160 return 0; 161 162 if (p.state != NULL && !OSSL_PARAM_set_int(p.state, s->state)) 163 return 0; 164 165 if (p.str != NULL && !OSSL_PARAM_set_uint(p.str, 1024)) 166 return 0; 167 168 if (p.maxreq != NULL && !OSSL_PARAM_set_size_t(p.maxreq, 128)) 169 return 0; 170 return 1; 171} 172 173static const OSSL_PARAM *seed_src_gettable_ctx_params(ossl_unused void *vseed, 174 ossl_unused void *provctx) 175{ 176 return seed_src_get_ctx_params_list; 177} 178 179static int seed_src_verify_zeroization(ossl_unused void *vseed) 180{ 181 return 1; 182} 183 184static size_t seed_get_seed(void *vseed, unsigned char **pout, 185 int entropy, size_t min_len, size_t max_len, 186 int prediction_resistance, 187 const unsigned char *adin, size_t adin_len) 188{ 189 size_t ret = 0; 190 size_t entropy_available = 0; 191 RAND_POOL *pool; 192 193 pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); 194 if (pool == NULL) { 195 ERR_raise(ERR_LIB_PROV, ERR_R_RAND_LIB); 196 return 0; 197 } 198 199 /* Get entropy by polling system entropy sources. */ 200 entropy_available = ossl_pool_acquire_entropy(pool); 201 202 if (entropy_available > 0 203 && ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { 204 ret = ossl_rand_pool_length(pool); 205 *pout = ossl_rand_pool_detach(pool); 206 } else { 207 ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK); 208 } 209 ossl_rand_pool_free(pool); 210 return ret; 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 OSSL_DISPATCH_END 253}; 254