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 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 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 66 static void seed_src_free(void *vseed) 67 { 68 OPENSSL_free(vseed); 69 } 70 71 static 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 82 static 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 90 static 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 123 static 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 141 static 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 160 static 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 172 static int seed_src_verify_zeroization(ossl_unused void *vseed) 173 { 174 return 1; 175 } 176 177 static 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 213 static 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 219 static int seed_src_enable_locking(ossl_unused void *vseed) 220 { 221 return 1; 222 } 223 224 int seed_src_lock(ossl_unused void *vctx) 225 { 226 return 1; 227 } 228 229 void seed_src_unlock(ossl_unused void *vctx) 230 { 231 } 232 233 const 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