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