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