1 /* 2 * Copyright 2020-2025 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 <stdlib.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 "prov/securitycheck.h" 20 #include "prov/providercommon.h" 21 #include "prov/provider_ctx.h" 22 #include "prov/provider_util.h" 23 #include "prov/implementations.h" 24 25 static OSSL_FUNC_rand_newctx_fn test_rng_new; 26 static OSSL_FUNC_rand_freectx_fn test_rng_free; 27 static OSSL_FUNC_rand_instantiate_fn test_rng_instantiate; 28 static OSSL_FUNC_rand_uninstantiate_fn test_rng_uninstantiate; 29 static OSSL_FUNC_rand_generate_fn test_rng_generate; 30 static OSSL_FUNC_rand_reseed_fn test_rng_reseed; 31 static OSSL_FUNC_rand_nonce_fn test_rng_nonce; 32 static OSSL_FUNC_rand_settable_ctx_params_fn test_rng_settable_ctx_params; 33 static OSSL_FUNC_rand_set_ctx_params_fn test_rng_set_ctx_params; 34 static OSSL_FUNC_rand_gettable_ctx_params_fn test_rng_gettable_ctx_params; 35 static OSSL_FUNC_rand_get_ctx_params_fn test_rng_get_ctx_params; 36 static OSSL_FUNC_rand_verify_zeroization_fn test_rng_verify_zeroization; 37 static OSSL_FUNC_rand_enable_locking_fn test_rng_enable_locking; 38 static OSSL_FUNC_rand_lock_fn test_rng_lock; 39 static OSSL_FUNC_rand_unlock_fn test_rng_unlock; 40 static OSSL_FUNC_rand_get_seed_fn test_rng_get_seed; 41 42 typedef struct { 43 void *provctx; 44 unsigned int generate; 45 int state; 46 unsigned int strength; 47 size_t max_request; 48 unsigned char *entropy, *nonce; 49 size_t entropy_len, entropy_pos, nonce_len; 50 CRYPTO_RWLOCK *lock; 51 uint32_t seed; 52 } PROV_TEST_RNG; 53 54 static void *test_rng_new(void *provctx, void *parent, 55 const OSSL_DISPATCH *parent_dispatch) 56 { 57 PROV_TEST_RNG *t; 58 59 t = OPENSSL_zalloc(sizeof(*t)); 60 if (t == NULL) 61 return NULL; 62 63 t->max_request = INT_MAX; 64 t->provctx = provctx; 65 t->state = EVP_RAND_STATE_UNINITIALISED; 66 return t; 67 } 68 69 static void test_rng_free(void *vtest) 70 { 71 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 72 73 if (t == NULL) 74 return; 75 OPENSSL_free(t->entropy); 76 OPENSSL_free(t->nonce); 77 CRYPTO_THREAD_lock_free(t->lock); 78 OPENSSL_free(t); 79 } 80 81 static int test_rng_instantiate(void *vtest, unsigned int strength, 82 int prediction_resistance, 83 const unsigned char *pstr, size_t pstr_len, 84 const OSSL_PARAM params[]) 85 { 86 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 87 88 if (!test_rng_set_ctx_params(t, params) || strength > t->strength) 89 return 0; 90 91 t->state = EVP_RAND_STATE_READY; 92 t->entropy_pos = 0; 93 t->seed = 221953166; /* Value doesn't matter, so long as it isn't zero */ 94 95 return 1; 96 } 97 98 static int test_rng_uninstantiate(void *vtest) 99 { 100 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 101 102 t->entropy_pos = 0; 103 t->state = EVP_RAND_STATE_UNINITIALISED; 104 return 1; 105 } 106 107 static unsigned char gen_byte(PROV_TEST_RNG *t) 108 { 109 uint32_t n; 110 111 /* 112 * Implement the 32 bit xorshift as suggested by George Marsaglia in: 113 * https://doi.org/10.18637/jss.v008.i14 114 * 115 * This is a very fast PRNG so there is no need to extract bytes one at a 116 * time and use the entire value each time. 117 */ 118 n = t->seed; 119 n ^= n << 13; 120 n ^= n >> 17; 121 n ^= n << 5; 122 t->seed = n; 123 124 return n & 0xff; 125 } 126 127 static int test_rng_generate(void *vtest, unsigned char *out, size_t outlen, 128 unsigned int strength, int prediction_resistance, 129 const unsigned char *adin, size_t adin_len) 130 { 131 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 132 size_t i; 133 134 if (strength > t->strength) 135 return 0; 136 if (t->generate) { 137 for (i = 0; i < outlen; i++) 138 out[i] = gen_byte(t); 139 } else { 140 if (t->entropy_len - t->entropy_pos < outlen) 141 return 0; 142 143 memcpy(out, t->entropy + t->entropy_pos, outlen); 144 t->entropy_pos += outlen; 145 } 146 return 1; 147 } 148 149 static int test_rng_reseed(ossl_unused void *vtest, 150 ossl_unused int prediction_resistance, 151 ossl_unused const unsigned char *ent, 152 ossl_unused size_t ent_len, 153 ossl_unused const unsigned char *adin, 154 ossl_unused size_t adin_len) 155 { 156 return 1; 157 } 158 159 static size_t test_rng_nonce(void *vtest, unsigned char *out, 160 unsigned int strength, size_t min_noncelen, 161 size_t max_noncelen) 162 { 163 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 164 size_t i; 165 166 if (strength > t->strength) 167 return 0; 168 169 if (t->generate) { 170 for (i = 0; i < min_noncelen; i++) 171 out[i] = gen_byte(t); 172 return min_noncelen; 173 } 174 175 if (t->nonce == NULL) 176 return 0; 177 i = t->nonce_len > max_noncelen ? max_noncelen : t->nonce_len; 178 if (out != NULL) 179 memcpy(out, t->nonce, i); 180 return i; 181 } 182 183 static int test_rng_get_ctx_params(void *vtest, OSSL_PARAM params[]) 184 { 185 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 186 OSSL_PARAM *p; 187 188 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE); 189 if (p != NULL && !OSSL_PARAM_set_int(p, t->state)) 190 return 0; 191 192 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH); 193 if (p != NULL && !OSSL_PARAM_set_int(p, t->strength)) 194 return 0; 195 196 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST); 197 if (p != NULL && !OSSL_PARAM_set_size_t(p, t->max_request)) 198 return 0; 199 200 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_GENERATE); 201 if (p != NULL && !OSSL_PARAM_set_uint(p, t->generate)) 202 return 0; 203 204 #ifdef FIPS_MODULE 205 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_FIPS_APPROVED_INDICATOR); 206 if (p != NULL && !OSSL_PARAM_set_int(p, 0)) 207 return 0; 208 #endif /* FIPS_MODULE */ 209 return 1; 210 } 211 212 static const OSSL_PARAM *test_rng_gettable_ctx_params(ossl_unused void *vtest, 213 ossl_unused void *provctx) 214 { 215 static const OSSL_PARAM known_gettable_ctx_params[] = { 216 OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL), 217 OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), 218 OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), 219 OSSL_PARAM_uint(OSSL_RAND_PARAM_GENERATE, NULL), 220 OSSL_FIPS_IND_GETTABLE_CTX_PARAM() 221 OSSL_PARAM_END 222 }; 223 return known_gettable_ctx_params; 224 } 225 226 static int test_rng_set_ctx_params(void *vtest, const OSSL_PARAM params[]) 227 { 228 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 229 const OSSL_PARAM *p; 230 void *ptr = NULL; 231 size_t size = 0; 232 233 if (ossl_param_is_empty(params)) 234 return 1; 235 236 p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_STRENGTH); 237 if (p != NULL && !OSSL_PARAM_get_uint(p, &t->strength)) 238 return 0; 239 240 p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_TEST_ENTROPY); 241 if (p != NULL) { 242 if (!OSSL_PARAM_get_octet_string(p, &ptr, 0, &size)) 243 return 0; 244 OPENSSL_free(t->entropy); 245 t->entropy = ptr; 246 t->entropy_len = size; 247 t->entropy_pos = 0; 248 ptr = NULL; 249 } 250 251 p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_TEST_NONCE); 252 if (p != NULL) { 253 if (!OSSL_PARAM_get_octet_string(p, &ptr, 0, &size)) 254 return 0; 255 OPENSSL_free(t->nonce); 256 t->nonce = ptr; 257 t->nonce_len = size; 258 } 259 260 p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_MAX_REQUEST); 261 if (p != NULL && !OSSL_PARAM_get_size_t(p, &t->max_request)) 262 return 0; 263 264 p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_GENERATE); 265 if (p != NULL && !OSSL_PARAM_get_uint(p, &t->generate)) 266 return 0; 267 return 1; 268 } 269 270 static const OSSL_PARAM *test_rng_settable_ctx_params(ossl_unused void *vtest, 271 ossl_unused void *provctx) 272 { 273 static const OSSL_PARAM known_settable_ctx_params[] = { 274 OSSL_PARAM_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, NULL, 0), 275 OSSL_PARAM_octet_string(OSSL_RAND_PARAM_TEST_NONCE, NULL, 0), 276 OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), 277 OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), 278 OSSL_PARAM_uint(OSSL_RAND_PARAM_GENERATE, NULL), 279 OSSL_PARAM_END 280 }; 281 return known_settable_ctx_params; 282 } 283 284 static int test_rng_verify_zeroization(ossl_unused void *vtest) 285 { 286 return 1; 287 } 288 289 static size_t test_rng_get_seed(void *vtest, unsigned char **pout, 290 int entropy, size_t min_len, size_t max_len, 291 ossl_unused int prediction_resistance, 292 ossl_unused const unsigned char *adin, 293 ossl_unused size_t adin_len) 294 { 295 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 296 297 *pout = t->entropy; 298 return t->entropy_len > max_len ? max_len : t->entropy_len; 299 } 300 301 static int test_rng_enable_locking(void *vtest) 302 { 303 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 304 305 if (t != NULL && t->lock == NULL) { 306 t->lock = CRYPTO_THREAD_lock_new(); 307 if (t->lock == NULL) { 308 ERR_raise(ERR_LIB_PROV, RAND_R_FAILED_TO_CREATE_LOCK); 309 return 0; 310 } 311 } 312 return 1; 313 } 314 315 static int test_rng_lock(void *vtest) 316 { 317 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 318 319 if (t == NULL || t->lock == NULL) 320 return 1; 321 return CRYPTO_THREAD_write_lock(t->lock); 322 } 323 324 static void test_rng_unlock(void *vtest) 325 { 326 PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; 327 328 if (t != NULL && t->lock != NULL) 329 CRYPTO_THREAD_unlock(t->lock); 330 } 331 332 const OSSL_DISPATCH ossl_test_rng_functions[] = { 333 { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))test_rng_new }, 334 { OSSL_FUNC_RAND_FREECTX, (void(*)(void))test_rng_free }, 335 { OSSL_FUNC_RAND_INSTANTIATE, 336 (void(*)(void))test_rng_instantiate }, 337 { OSSL_FUNC_RAND_UNINSTANTIATE, 338 (void(*)(void))test_rng_uninstantiate }, 339 { OSSL_FUNC_RAND_GENERATE, (void(*)(void))test_rng_generate }, 340 { OSSL_FUNC_RAND_RESEED, (void(*)(void))test_rng_reseed }, 341 { OSSL_FUNC_RAND_NONCE, (void(*)(void))test_rng_nonce }, 342 { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))test_rng_enable_locking }, 343 { OSSL_FUNC_RAND_LOCK, (void(*)(void))test_rng_lock }, 344 { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))test_rng_unlock }, 345 { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS, 346 (void(*)(void))test_rng_settable_ctx_params }, 347 { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))test_rng_set_ctx_params }, 348 { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS, 349 (void(*)(void))test_rng_gettable_ctx_params }, 350 { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))test_rng_get_ctx_params }, 351 { OSSL_FUNC_RAND_VERIFY_ZEROIZATION, 352 (void(*)(void))test_rng_verify_zeroization }, 353 { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))test_rng_get_seed }, 354 OSSL_DISPATCH_END 355 }; 356