1/* 2 * Copyright 2024-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{- 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 <openssl/self_test.h> 24#include "internal/common.h" 25#include "prov/implementations.h" 26#include "prov/provider_ctx.h" 27#include "prov/providercommon.h" 28#include "crypto/rand.h" 29#include "crypto/rand_pool.h" 30 31#ifndef OPENSSL_NO_JITTER 32# include <jitterentropy.h> 33 34# define JITTER_MAX_NUM_TRIES 3 35 36static OSSL_FUNC_rand_newctx_fn jitter_new; 37static OSSL_FUNC_rand_freectx_fn jitter_free; 38static OSSL_FUNC_rand_instantiate_fn jitter_instantiate; 39static OSSL_FUNC_rand_uninstantiate_fn jitter_uninstantiate; 40static OSSL_FUNC_rand_generate_fn jitter_generate; 41static OSSL_FUNC_rand_reseed_fn jitter_reseed; 42static OSSL_FUNC_rand_gettable_ctx_params_fn jitter_gettable_ctx_params; 43static OSSL_FUNC_rand_get_ctx_params_fn jitter_get_ctx_params; 44static OSSL_FUNC_rand_verify_zeroization_fn jitter_verify_zeroization; 45static OSSL_FUNC_rand_enable_locking_fn jitter_enable_locking; 46static OSSL_FUNC_rand_lock_fn jitter_lock; 47static OSSL_FUNC_rand_unlock_fn jitter_unlock; 48static OSSL_FUNC_rand_get_seed_fn jitter_get_seed; 49static OSSL_FUNC_rand_clear_seed_fn jitter_clear_seed; 50 51typedef struct { 52 void *provctx; 53 int state; 54} PROV_JITTER; 55 56static size_t get_jitter_random_value(PROV_JITTER *s, unsigned char *buf, size_t len); 57 58/* 59 * Acquire entropy from jitterentropy library 60 * 61 * Returns the total entropy count, if it exceeds the requested 62 * entropy count. Otherwise, returns an entropy count of 0. 63 */ 64static size_t ossl_prov_acquire_entropy_from_jitter(PROV_JITTER *s, 65 RAND_POOL *pool) 66{ 67 size_t bytes_needed; 68 unsigned char *buffer; 69 70 bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /* entropy_factor */); 71 if (bytes_needed > 0) { 72 buffer = ossl_rand_pool_add_begin(pool, bytes_needed); 73 74 if (buffer != NULL) { 75 if (get_jitter_random_value(s, buffer, bytes_needed) == bytes_needed) { 76 ossl_rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); 77 } else { 78 ossl_rand_pool_add_end(pool, 0, 0); 79 } 80 } 81 } 82 83 return ossl_rand_pool_entropy_available(pool); 84} 85 86/* Obtain random bytes from the jitter library */ 87static size_t get_jitter_random_value(PROV_JITTER *s, 88 unsigned char *buf, size_t len) 89{ 90 struct rand_data *jitter_ec = NULL; 91 ssize_t result = 0; 92 size_t num_tries; 93 94 /* Retry intermittent failures, then give up */ 95 for (num_tries = 0; num_tries < JITTER_MAX_NUM_TRIES; num_tries++) { 96 /* Allocate a fresh collector */ 97 jitter_ec = jent_entropy_collector_alloc(0, JENT_FORCE_FIPS); 98 if (jitter_ec == NULL) 99 continue; 100 101 /* Do not use _safe API as per typical security policies */ 102 result = jent_read_entropy(jitter_ec, (char *) buf, len); 103 jent_entropy_collector_free(jitter_ec); 104 105 /* 106 * Permanent Failure 107 * https://github.com/smuellerDD/jitterentropy-library/blob/master/doc/jitterentropy.3#L234 108 */ 109 if (result < -5) { 110 ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG); 111 break; 112 } 113 114 /* Success */ 115 if (result >= 0 && (size_t)result == len) 116 return len; 117 } 118 119 /* Permanent failure or too many intermittent failures */ 120 s->state = EVP_RAND_STATE_ERROR; 121 ERR_raise_data(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY, 122 "jent_read_entropy (%d)", result); 123 return 0; 124} 125 126static void *jitter_new(void *provctx, void *parent, 127 const OSSL_DISPATCH *parent_dispatch) 128{ 129 PROV_JITTER *s; 130 131 if (parent != NULL) { 132 ERR_raise(ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT); 133 return NULL; 134 } 135 136 s = OPENSSL_zalloc(sizeof(*s)); 137 if (s == NULL) 138 return NULL; 139 140 s->provctx = provctx; 141 s->state = EVP_RAND_STATE_UNINITIALISED; 142 return s; 143} 144 145static void jitter_free(void *vseed) 146{ 147 OPENSSL_free(vseed); 148} 149 150static int jitter_instantiate(void *vseed, unsigned int strength, 151 int prediction_resistance, 152 const unsigned char *pstr, 153 size_t pstr_len, 154 ossl_unused const OSSL_PARAM params[]) 155{ 156 PROV_JITTER *s = (PROV_JITTER *)vseed; 157 int ret; 158 159 if ((ret = jent_entropy_init_ex(0, JENT_FORCE_FIPS)) != 0) { 160 ERR_raise_data(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY, 161 "jent_entropy_init_ex (%d)", ret); 162 s->state = EVP_RAND_STATE_ERROR; 163 return 0; 164 } 165 166 s->state = EVP_RAND_STATE_READY; 167 return 1; 168} 169 170static int jitter_uninstantiate(void *vseed) 171{ 172 PROV_JITTER *s = (PROV_JITTER *)vseed; 173 174 s->state = EVP_RAND_STATE_UNINITIALISED; 175 return 1; 176} 177 178static int jitter_generate(void *vseed, unsigned char *out, size_t outlen, 179 unsigned int strength, 180 ossl_unused int prediction_resistance, 181 ossl_unused const unsigned char *adin, 182 ossl_unused size_t adin_len) 183{ 184 PROV_JITTER *s = (PROV_JITTER *)vseed; 185 size_t entropy_available; 186 RAND_POOL *pool; 187 188 if (s->state != EVP_RAND_STATE_READY) { 189 ERR_raise(ERR_LIB_PROV, 190 s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE 191 : PROV_R_NOT_INSTANTIATED); 192 return 0; 193 } 194 195 pool = ossl_rand_pool_new(strength, 1, outlen, outlen); 196 if (pool == NULL) { 197 ERR_raise(ERR_LIB_PROV, ERR_R_RAND_LIB); 198 return 0; 199 } 200 201 /* Get entropy from jitter entropy library. */ 202 entropy_available = ossl_prov_acquire_entropy_from_jitter(s, pool); 203 204 if (entropy_available > 0) { 205 if (!ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { 206 ossl_rand_pool_free(pool); 207 return 0; 208 } 209 memcpy(out, ossl_rand_pool_buffer(pool), ossl_rand_pool_length(pool)); 210 } 211 212 ossl_rand_pool_free(pool); 213 return entropy_available > 0; 214} 215 216static int jitter_reseed(void *vseed, 217 ossl_unused int prediction_resistance, 218 ossl_unused const unsigned char *ent, 219 ossl_unused size_t ent_len, 220 ossl_unused const unsigned char *adin, 221 ossl_unused size_t adin_len) 222{ 223 PROV_JITTER *s = (PROV_JITTER *)vseed; 224 225 if (s->state != EVP_RAND_STATE_READY) { 226 ERR_raise(ERR_LIB_PROV, 227 s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE 228 : PROV_R_NOT_INSTANTIATED); 229 return 0; 230 } 231 return 1; 232} 233 234{- produce_param_decoder('jitter_get_ctx_params', 235 (['RAND_PARAM_STATE', 'state', 'int'], 236 ['RAND_PARAM_STRENGTH', 'str', 'uint'], 237 ['RAND_PARAM_MAX_REQUEST', 'maxreq', 'size_t'], 238 )); -} 239 240static int jitter_get_ctx_params(void *vseed, OSSL_PARAM params[]) 241{ 242 PROV_JITTER *s = (PROV_JITTER *)vseed; 243 struct jitter_get_ctx_params_st p; 244 245 if (s == NULL || !jitter_get_ctx_params_decoder(params, &p)) 246 return 0; 247 248 if (p.state != NULL && !OSSL_PARAM_set_int(p.state, s->state)) 249 return 0; 250 251 if (p.str != NULL && !OSSL_PARAM_set_uint(p.str, 1024)) 252 return 0; 253 254 if (p.maxreq != NULL && !OSSL_PARAM_set_size_t(p.maxreq, 128)) 255 return 0; 256 return 1; 257} 258 259static const OSSL_PARAM *jitter_gettable_ctx_params(ossl_unused void *vseed, 260 ossl_unused void *provctx) 261{ 262 return jitter_get_ctx_params_list; 263} 264 265static int jitter_verify_zeroization(ossl_unused void *vseed) 266{ 267 return 1; 268} 269 270static size_t jitter_get_seed(void *vseed, unsigned char **pout, 271 int entropy, size_t min_len, 272 size_t max_len, 273 int prediction_resistance, 274 const unsigned char *adin, 275 size_t adin_len) 276{ 277 size_t ret = 0; 278 size_t entropy_available = 0; 279 RAND_POOL *pool; 280 PROV_JITTER *s = (PROV_JITTER *)vseed; 281 282 pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); 283 if (pool == NULL) { 284 ERR_raise(ERR_LIB_PROV, ERR_R_RAND_LIB); 285 return 0; 286 } 287 288 /* Get entropy from jitter entropy library. */ 289 entropy_available = ossl_prov_acquire_entropy_from_jitter(s, pool); 290 291 if (entropy_available > 0 292 && ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { 293 ret = ossl_rand_pool_length(pool); 294 *pout = ossl_rand_pool_detach(pool); 295 } else { 296 ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK); 297 } 298 ossl_rand_pool_free(pool); 299 return ret; 300} 301 302# ifndef OPENSSL_NO_FIPS_JITTER 303size_t ossl_rand_jitter_get_seed(unsigned char **pout, int entropy, size_t min_len, size_t max_len) 304{ 305 size_t ret = 0; 306 OSSL_PARAM params[1] = { OSSL_PARAM_END }; 307 PROV_JITTER *s = jitter_new(NULL, NULL, NULL); 308 309 if (s == NULL) 310 return ret; 311 if (!jitter_instantiate(s, 0, 0, NULL, 0, params)) 312 goto end; 313 ret = jitter_get_seed(s, pout, entropy, min_len, max_len, 0, NULL, 0); 314 end: 315 jitter_free(s); 316 return ret; 317} 318# endif 319 320static void jitter_clear_seed(ossl_unused void *vdrbg, 321 unsigned char *out, size_t outlen) 322{ 323 OPENSSL_secure_clear_free(out, outlen); 324} 325 326static int jitter_enable_locking(ossl_unused void *vseed) 327{ 328 return 1; 329} 330 331int jitter_lock(ossl_unused void *vctx) 332{ 333 return 1; 334} 335 336void jitter_unlock(ossl_unused void *vctx) 337{ 338} 339 340const OSSL_DISPATCH ossl_jitter_functions[] = { 341 { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))jitter_new }, 342 { OSSL_FUNC_RAND_FREECTX, (void(*)(void))jitter_free }, 343 { OSSL_FUNC_RAND_INSTANTIATE, 344 (void(*)(void))jitter_instantiate }, 345 { OSSL_FUNC_RAND_UNINSTANTIATE, 346 (void(*)(void))jitter_uninstantiate }, 347 { OSSL_FUNC_RAND_GENERATE, (void(*)(void))jitter_generate }, 348 { OSSL_FUNC_RAND_RESEED, (void(*)(void))jitter_reseed }, 349 { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))jitter_enable_locking }, 350 { OSSL_FUNC_RAND_LOCK, (void(*)(void))jitter_lock }, 351 { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))jitter_unlock }, 352 { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS, 353 (void(*)(void))jitter_gettable_ctx_params }, 354 { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))jitter_get_ctx_params }, 355 { OSSL_FUNC_RAND_VERIFY_ZEROIZATION, 356 (void(*)(void))jitter_verify_zeroization }, 357 { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))jitter_get_seed }, 358 { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))jitter_clear_seed }, 359 OSSL_DISPATCH_END 360}; 361#else 362NON_EMPTY_TRANSLATION_UNIT 363#endif 364