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 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 25 static OSSL_FUNC_rand_newctx_fn seed_src_new; 26 static OSSL_FUNC_rand_freectx_fn seed_src_free; 27 static OSSL_FUNC_rand_instantiate_fn seed_src_instantiate; 28 static OSSL_FUNC_rand_uninstantiate_fn seed_src_uninstantiate; 29 static OSSL_FUNC_rand_generate_fn seed_src_generate; 30 static OSSL_FUNC_rand_reseed_fn seed_src_reseed; 31 static OSSL_FUNC_rand_gettable_ctx_params_fn seed_src_gettable_ctx_params; 32 static OSSL_FUNC_rand_get_ctx_params_fn seed_src_get_ctx_params; 33 static OSSL_FUNC_rand_verify_zeroization_fn seed_src_verify_zeroization; 34 static OSSL_FUNC_rand_enable_locking_fn seed_src_enable_locking; 35 static OSSL_FUNC_rand_lock_fn seed_src_lock; 36 static OSSL_FUNC_rand_unlock_fn seed_src_unlock; 37 static OSSL_FUNC_rand_get_seed_fn seed_get_seed; 38 static OSSL_FUNC_rand_clear_seed_fn seed_clear_seed; 39 40 typedef struct { 41 void *provctx; 42 int state; 43 } PROV_SEED_SRC; 44 45 static 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 return NULL; 58 59 s->provctx = provctx; 60 s->state = EVP_RAND_STATE_UNINITIALISED; 61 return s; 62 } 63 64 static void seed_src_free(void *vseed) 65 { 66 OPENSSL_free(vseed); 67 } 68 69 static int seed_src_instantiate(void *vseed, unsigned int strength, 70 int prediction_resistance, 71 const unsigned char *pstr, size_t pstr_len, 72 ossl_unused const OSSL_PARAM params[]) 73 { 74 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 75 76 s->state = EVP_RAND_STATE_READY; 77 return 1; 78 } 79 80 static int seed_src_uninstantiate(void *vseed) 81 { 82 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 83 84 s->state = EVP_RAND_STATE_UNINITIALISED; 85 return 1; 86 } 87 88 static int seed_src_generate(void *vseed, unsigned char *out, size_t outlen, 89 unsigned int strength, 90 ossl_unused int prediction_resistance, 91 const unsigned char *adin, 92 size_t adin_len) 93 { 94 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 95 size_t entropy_available; 96 RAND_POOL *pool; 97 98 if (s->state != EVP_RAND_STATE_READY) { 99 ERR_raise(ERR_LIB_PROV, 100 s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE 101 : PROV_R_NOT_INSTANTIATED); 102 return 0; 103 } 104 105 pool = ossl_rand_pool_new(strength, 1, outlen, outlen); 106 if (pool == NULL) { 107 ERR_raise(ERR_LIB_PROV, ERR_R_RAND_LIB); 108 return 0; 109 } 110 111 /* Get entropy by polling system entropy sources. */ 112 entropy_available = ossl_pool_acquire_entropy(pool); 113 114 if (entropy_available > 0) { 115 if (!ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { 116 ossl_rand_pool_free(pool); 117 return 0; 118 } 119 memcpy(out, ossl_rand_pool_buffer(pool), ossl_rand_pool_length(pool)); 120 } 121 122 ossl_rand_pool_free(pool); 123 return entropy_available > 0; 124 } 125 126 static int seed_src_reseed(void *vseed, 127 ossl_unused int prediction_resistance, 128 ossl_unused const unsigned char *ent, 129 ossl_unused size_t ent_len, 130 ossl_unused const unsigned char *adin, 131 ossl_unused size_t adin_len) 132 { 133 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 134 135 if (s->state != EVP_RAND_STATE_READY) { 136 ERR_raise(ERR_LIB_PROV, 137 s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE 138 : PROV_R_NOT_INSTANTIATED); 139 return 0; 140 } 141 return 1; 142 } 143 144 static int seed_src_get_ctx_params(void *vseed, OSSL_PARAM params[]) 145 { 146 PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; 147 OSSL_PARAM *p; 148 149 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE); 150 if (p != NULL && !OSSL_PARAM_set_int(p, s->state)) 151 return 0; 152 153 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH); 154 if (p != NULL && !OSSL_PARAM_set_int(p, 1024)) 155 return 0; 156 157 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST); 158 if (p != NULL && !OSSL_PARAM_set_size_t(p, 128)) 159 return 0; 160 return 1; 161 } 162 163 static const OSSL_PARAM *seed_src_gettable_ctx_params(ossl_unused void *vseed, 164 ossl_unused void *provctx) 165 { 166 static const OSSL_PARAM known_gettable_ctx_params[] = { 167 OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL), 168 OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), 169 OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), 170 OSSL_PARAM_END 171 }; 172 return known_gettable_ctx_params; 173 } 174 175 static int seed_src_verify_zeroization(ossl_unused void *vseed) 176 { 177 return 1; 178 } 179 180 static size_t seed_get_seed(void *vseed, unsigned char **pout, 181 int entropy, size_t min_len, size_t max_len, 182 int prediction_resistance, 183 const unsigned char *adin, size_t adin_len) 184 { 185 size_t ret = 0; 186 size_t entropy_available = 0; 187 RAND_POOL *pool; 188 189 pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); 190 if (pool == NULL) { 191 ERR_raise(ERR_LIB_PROV, ERR_R_RAND_LIB); 192 return 0; 193 } 194 195 /* Get entropy by polling system entropy sources. */ 196 entropy_available = ossl_pool_acquire_entropy(pool); 197 198 if (entropy_available > 0 199 && ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { 200 ret = ossl_rand_pool_length(pool); 201 *pout = ossl_rand_pool_detach(pool); 202 } else { 203 ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK); 204 } 205 ossl_rand_pool_free(pool); 206 return ret; 207 } 208 209 static void seed_clear_seed(ossl_unused void *vdrbg, 210 unsigned char *out, size_t outlen) 211 { 212 OPENSSL_secure_clear_free(out, outlen); 213 } 214 215 static int seed_src_enable_locking(ossl_unused void *vseed) 216 { 217 return 1; 218 } 219 220 int seed_src_lock(ossl_unused void *vctx) 221 { 222 return 1; 223 } 224 225 void seed_src_unlock(ossl_unused void *vctx) 226 { 227 } 228 229 const OSSL_DISPATCH ossl_seed_src_functions[] = { 230 { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))seed_src_new }, 231 { OSSL_FUNC_RAND_FREECTX, (void(*)(void))seed_src_free }, 232 { OSSL_FUNC_RAND_INSTANTIATE, 233 (void(*)(void))seed_src_instantiate }, 234 { OSSL_FUNC_RAND_UNINSTANTIATE, 235 (void(*)(void))seed_src_uninstantiate }, 236 { OSSL_FUNC_RAND_GENERATE, (void(*)(void))seed_src_generate }, 237 { OSSL_FUNC_RAND_RESEED, (void(*)(void))seed_src_reseed }, 238 { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))seed_src_enable_locking }, 239 { OSSL_FUNC_RAND_LOCK, (void(*)(void))seed_src_lock }, 240 { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))seed_src_unlock }, 241 { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS, 242 (void(*)(void))seed_src_gettable_ctx_params }, 243 { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))seed_src_get_ctx_params }, 244 { OSSL_FUNC_RAND_VERIFY_ZEROIZATION, 245 (void(*)(void))seed_src_verify_zeroization }, 246 { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))seed_get_seed }, 247 { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))seed_clear_seed }, 248 OSSL_DISPATCH_END 249 }; 250