Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/providers/implementations/rands/seed_src_jitter.c
48383 views
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
ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG);
107
break;
108
}
109
110
/* Success */
111
if (result >= 0 && (size_t)result == len)
112
return len;
113
}
114
115
/* Permanent failure or too many intermittent failures */
116
s->state = EVP_RAND_STATE_ERROR;
117
ERR_raise_data(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY,
118
"jent_read_entropy (%d)", result);
119
return 0;
120
}
121
122
static void *jitter_new(void *provctx, void *parent,
123
const OSSL_DISPATCH *parent_dispatch)
124
{
125
PROV_JITTER *s;
126
127
if (parent != NULL) {
128
ERR_raise(ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT);
129
return NULL;
130
}
131
132
s = OPENSSL_zalloc(sizeof(*s));
133
if (s == NULL)
134
return NULL;
135
136
s->provctx = provctx;
137
s->state = EVP_RAND_STATE_UNINITIALISED;
138
return s;
139
}
140
141
static void jitter_free(void *vseed)
142
{
143
OPENSSL_free(vseed);
144
}
145
146
static int jitter_instantiate(void *vseed, unsigned int strength,
147
int prediction_resistance,
148
const unsigned char *pstr,
149
size_t pstr_len,
150
ossl_unused const OSSL_PARAM params[])
151
{
152
PROV_JITTER *s = (PROV_JITTER *)vseed;
153
int ret;
154
155
if ((ret = jent_entropy_init_ex(0, JENT_FORCE_FIPS)) != 0) {
156
ERR_raise_data(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY,
157
"jent_entropy_init_ex (%d)", ret);
158
s->state = EVP_RAND_STATE_ERROR;
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
361