/src/openssl36/providers/implementations/rands/seed_src.c
Line | Count | Source |
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 | | /* clang-format off */ |
10 | | |
11 | | /* clang-format on */ |
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 "internal/common.h" |
24 | | #include "prov/implementations.h" |
25 | | #include "prov/provider_ctx.h" |
26 | | #include "crypto/rand.h" |
27 | | #include "crypto/rand_pool.h" |
28 | | |
29 | | static OSSL_FUNC_rand_newctx_fn seed_src_new; |
30 | | static OSSL_FUNC_rand_freectx_fn seed_src_free; |
31 | | static OSSL_FUNC_rand_instantiate_fn seed_src_instantiate; |
32 | | static OSSL_FUNC_rand_uninstantiate_fn seed_src_uninstantiate; |
33 | | static OSSL_FUNC_rand_generate_fn seed_src_generate; |
34 | | static OSSL_FUNC_rand_reseed_fn seed_src_reseed; |
35 | | static OSSL_FUNC_rand_gettable_ctx_params_fn seed_src_gettable_ctx_params; |
36 | | static OSSL_FUNC_rand_get_ctx_params_fn seed_src_get_ctx_params; |
37 | | static OSSL_FUNC_rand_verify_zeroization_fn seed_src_verify_zeroization; |
38 | | static OSSL_FUNC_rand_enable_locking_fn seed_src_enable_locking; |
39 | | static OSSL_FUNC_rand_lock_fn seed_src_lock; |
40 | | static OSSL_FUNC_rand_unlock_fn seed_src_unlock; |
41 | | static OSSL_FUNC_rand_get_seed_fn seed_get_seed; |
42 | | static OSSL_FUNC_rand_clear_seed_fn seed_clear_seed; |
43 | | |
44 | | typedef struct { |
45 | | void *provctx; |
46 | | int state; |
47 | | } PROV_SEED_SRC; |
48 | | |
49 | | static void *seed_src_new(void *provctx, void *parent, |
50 | | const OSSL_DISPATCH *parent_dispatch) |
51 | 84 | { |
52 | 84 | PROV_SEED_SRC *s; |
53 | | |
54 | 84 | if (parent != NULL) { |
55 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT); |
56 | 0 | return NULL; |
57 | 0 | } |
58 | | |
59 | 84 | s = OPENSSL_zalloc(sizeof(*s)); |
60 | 84 | if (s == NULL) |
61 | 0 | return NULL; |
62 | | |
63 | 84 | s->provctx = provctx; |
64 | 84 | s->state = EVP_RAND_STATE_UNINITIALISED; |
65 | 84 | return s; |
66 | 84 | } |
67 | | |
68 | | static void seed_src_free(void *vseed) |
69 | 66 | { |
70 | 66 | OPENSSL_free(vseed); |
71 | 66 | } |
72 | | |
73 | | static int seed_src_instantiate(void *vseed, unsigned int strength, |
74 | | int prediction_resistance, |
75 | | const unsigned char *pstr, size_t pstr_len, |
76 | | ossl_unused const OSSL_PARAM params[]) |
77 | 78 | { |
78 | 78 | PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; |
79 | | |
80 | 78 | s->state = EVP_RAND_STATE_READY; |
81 | 78 | return 1; |
82 | 78 | } |
83 | | |
84 | | static int seed_src_uninstantiate(void *vseed) |
85 | 0 | { |
86 | 0 | PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; |
87 | |
|
88 | 0 | s->state = EVP_RAND_STATE_UNINITIALISED; |
89 | 0 | return 1; |
90 | 0 | } |
91 | | |
92 | | static int seed_src_generate(void *vseed, unsigned char *out, size_t outlen, |
93 | | unsigned int strength, |
94 | | ossl_unused int prediction_resistance, |
95 | | const unsigned char *adin, |
96 | | size_t adin_len) |
97 | 46 | { |
98 | 46 | PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; |
99 | 46 | size_t entropy_available; |
100 | 46 | RAND_POOL *pool; |
101 | | |
102 | 46 | if (s->state != EVP_RAND_STATE_READY) { |
103 | 4 | ERR_raise(ERR_LIB_PROV, |
104 | 4 | s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE |
105 | 4 | : PROV_R_NOT_INSTANTIATED); |
106 | 4 | return 0; |
107 | 4 | } |
108 | | |
109 | 42 | pool = ossl_rand_pool_new(strength, 1, outlen, outlen); |
110 | 42 | if (pool == NULL) { |
111 | 0 | ERR_raise(ERR_LIB_PROV, ERR_R_RAND_LIB); |
112 | 0 | return 0; |
113 | 0 | } |
114 | | |
115 | | /* Get entropy by polling system entropy sources. */ |
116 | 42 | entropy_available = ossl_pool_acquire_entropy(pool); |
117 | | |
118 | 42 | if (entropy_available > 0) { |
119 | 42 | if (!ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { |
120 | 0 | ossl_rand_pool_free(pool); |
121 | 0 | return 0; |
122 | 0 | } |
123 | 42 | memcpy(out, ossl_rand_pool_buffer(pool), ossl_rand_pool_length(pool)); |
124 | 42 | } |
125 | | |
126 | 42 | ossl_rand_pool_free(pool); |
127 | 42 | return entropy_available > 0; |
128 | 42 | } |
129 | | |
130 | | static int seed_src_reseed(void *vseed, |
131 | | ossl_unused int prediction_resistance, |
132 | | ossl_unused const unsigned char *ent, |
133 | | ossl_unused size_t ent_len, |
134 | | ossl_unused const unsigned char *adin, |
135 | | ossl_unused size_t adin_len) |
136 | 0 | { |
137 | 0 | PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; |
138 | |
|
139 | 0 | if (s->state != EVP_RAND_STATE_READY) { |
140 | 0 | ERR_raise(ERR_LIB_PROV, |
141 | 0 | s->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE |
142 | 0 | : PROV_R_NOT_INSTANTIATED); |
143 | 0 | return 0; |
144 | 0 | } |
145 | 0 | return 1; |
146 | 0 | } |
147 | | |
148 | | /* clang-format off */ |
149 | | /* Machine generated by util/perl/OpenSSL/paramnames.pm */ |
150 | | #ifndef seed_src_get_ctx_params_list |
151 | | static const OSSL_PARAM seed_src_get_ctx_params_list[] = { |
152 | | OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL), |
153 | | OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), |
154 | | OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), |
155 | | OSSL_PARAM_END |
156 | | }; |
157 | | #endif |
158 | | |
159 | | #ifndef seed_src_get_ctx_params_st |
160 | | struct seed_src_get_ctx_params_st { |
161 | | OSSL_PARAM *maxreq; |
162 | | OSSL_PARAM *state; |
163 | | OSSL_PARAM *str; |
164 | | }; |
165 | | #endif |
166 | | |
167 | | #ifndef seed_src_get_ctx_params_decoder |
168 | | static int seed_src_get_ctx_params_decoder |
169 | | (const OSSL_PARAM *p, struct seed_src_get_ctx_params_st *r) |
170 | 92 | { |
171 | 92 | const char *s; |
172 | | |
173 | 92 | memset(r, 0, sizeof(*r)); |
174 | 92 | if (p != NULL) |
175 | 184 | for (; (s = p->key) != NULL; p++) |
176 | 92 | switch(s[0]) { |
177 | 30 | default: |
178 | 30 | break; |
179 | 44 | case 'm': |
180 | 44 | if (ossl_likely(strcmp("ax_request", s + 1) == 0)) { |
181 | | /* OSSL_RAND_PARAM_MAX_REQUEST */ |
182 | 44 | if (ossl_unlikely(r->maxreq != NULL)) { |
183 | 0 | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
184 | 0 | "param %s is repeated", s); |
185 | 0 | return 0; |
186 | 0 | } |
187 | 44 | r->maxreq = (OSSL_PARAM *)p; |
188 | 44 | } |
189 | 44 | break; |
190 | 44 | case 's': |
191 | 18 | switch(s[1]) { |
192 | 0 | default: |
193 | 0 | break; |
194 | 18 | case 't': |
195 | 18 | switch(s[2]) { |
196 | 0 | default: |
197 | 0 | break; |
198 | 0 | case 'a': |
199 | 0 | if (ossl_likely(strcmp("te", s + 3) == 0)) { |
200 | | /* OSSL_RAND_PARAM_STATE */ |
201 | 0 | if (ossl_unlikely(r->state != NULL)) { |
202 | 0 | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
203 | 0 | "param %s is repeated", s); |
204 | 0 | return 0; |
205 | 0 | } |
206 | 0 | r->state = (OSSL_PARAM *)p; |
207 | 0 | } |
208 | 0 | break; |
209 | 18 | case 'r': |
210 | 18 | if (ossl_likely(strcmp("ength", s + 3) == 0)) { |
211 | | /* OSSL_RAND_PARAM_STRENGTH */ |
212 | 18 | if (ossl_unlikely(r->str != NULL)) { |
213 | 0 | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
214 | 0 | "param %s is repeated", s); |
215 | 0 | return 0; |
216 | 0 | } |
217 | 18 | r->str = (OSSL_PARAM *)p; |
218 | 18 | } |
219 | 18 | } |
220 | 18 | } |
221 | 92 | } |
222 | 92 | return 1; |
223 | 92 | } |
224 | | #endif |
225 | | /* End of machine generated */ |
226 | | /* clang-format on */ |
227 | | |
228 | | static int seed_src_get_ctx_params(void *vseed, OSSL_PARAM params[]) |
229 | 92 | { |
230 | 92 | PROV_SEED_SRC *s = (PROV_SEED_SRC *)vseed; |
231 | 92 | struct seed_src_get_ctx_params_st p; |
232 | | |
233 | 92 | if (s == NULL || !seed_src_get_ctx_params_decoder(params, &p)) |
234 | 0 | return 0; |
235 | | |
236 | 92 | if (p.state != NULL && !OSSL_PARAM_set_int(p.state, s->state)) |
237 | 0 | return 0; |
238 | | |
239 | 92 | if (p.str != NULL && !OSSL_PARAM_set_uint(p.str, 1024)) |
240 | 0 | return 0; |
241 | | |
242 | 92 | if (p.maxreq != NULL && !OSSL_PARAM_set_size_t(p.maxreq, 128)) |
243 | 0 | return 0; |
244 | 92 | return 1; |
245 | 92 | } |
246 | | |
247 | | static const OSSL_PARAM *seed_src_gettable_ctx_params(ossl_unused void *vseed, |
248 | | ossl_unused void *provctx) |
249 | 0 | { |
250 | 0 | return seed_src_get_ctx_params_list; |
251 | 0 | } |
252 | | |
253 | | static int seed_src_verify_zeroization(ossl_unused void *vseed) |
254 | 0 | { |
255 | 0 | return 1; |
256 | 0 | } |
257 | | |
258 | | static size_t seed_get_seed(void *vseed, unsigned char **pout, |
259 | | int entropy, size_t min_len, size_t max_len, |
260 | | int prediction_resistance, |
261 | | const unsigned char *adin, size_t adin_len) |
262 | 105 | { |
263 | 105 | size_t ret = 0; |
264 | 105 | size_t entropy_available = 0; |
265 | 105 | RAND_POOL *pool; |
266 | | |
267 | 105 | pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); |
268 | 105 | if (pool == NULL) { |
269 | 0 | ERR_raise(ERR_LIB_PROV, ERR_R_RAND_LIB); |
270 | 0 | return 0; |
271 | 0 | } |
272 | | |
273 | | /* Get entropy by polling system entropy sources. */ |
274 | 105 | entropy_available = ossl_pool_acquire_entropy(pool); |
275 | | |
276 | 105 | if (entropy_available > 0 |
277 | 105 | && ossl_rand_pool_adin_mix_in(pool, adin, adin_len)) { |
278 | 105 | ret = ossl_rand_pool_length(pool); |
279 | 105 | *pout = ossl_rand_pool_detach(pool); |
280 | 105 | } else { |
281 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK); |
282 | 0 | } |
283 | 105 | ossl_rand_pool_free(pool); |
284 | 105 | return ret; |
285 | 105 | } |
286 | | |
287 | | static void seed_clear_seed(ossl_unused void *vdrbg, |
288 | | unsigned char *out, size_t outlen) |
289 | 161 | { |
290 | 161 | OPENSSL_secure_clear_free(out, outlen); |
291 | 161 | } |
292 | | |
293 | | static int seed_src_enable_locking(ossl_unused void *vseed) |
294 | 17 | { |
295 | 17 | return 1; |
296 | 17 | } |
297 | | |
298 | | int seed_src_lock(ossl_unused void *vctx) |
299 | 562 | { |
300 | 562 | return 1; |
301 | 562 | } |
302 | | |
303 | | void seed_src_unlock(ossl_unused void *vctx) |
304 | 562 | { |
305 | 562 | } |
306 | | |
307 | | const OSSL_DISPATCH ossl_seed_src_functions[] = { |
308 | | { OSSL_FUNC_RAND_NEWCTX, (void (*)(void))seed_src_new }, |
309 | | { OSSL_FUNC_RAND_FREECTX, (void (*)(void))seed_src_free }, |
310 | | { OSSL_FUNC_RAND_INSTANTIATE, |
311 | | (void (*)(void))seed_src_instantiate }, |
312 | | { OSSL_FUNC_RAND_UNINSTANTIATE, |
313 | | (void (*)(void))seed_src_uninstantiate }, |
314 | | { OSSL_FUNC_RAND_GENERATE, (void (*)(void))seed_src_generate }, |
315 | | { OSSL_FUNC_RAND_RESEED, (void (*)(void))seed_src_reseed }, |
316 | | { OSSL_FUNC_RAND_ENABLE_LOCKING, (void (*)(void))seed_src_enable_locking }, |
317 | | { OSSL_FUNC_RAND_LOCK, (void (*)(void))seed_src_lock }, |
318 | | { OSSL_FUNC_RAND_UNLOCK, (void (*)(void))seed_src_unlock }, |
319 | | { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS, |
320 | | (void (*)(void))seed_src_gettable_ctx_params }, |
321 | | { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void (*)(void))seed_src_get_ctx_params }, |
322 | | { OSSL_FUNC_RAND_VERIFY_ZEROIZATION, |
323 | | (void (*)(void))seed_src_verify_zeroization }, |
324 | | { OSSL_FUNC_RAND_GET_SEED, (void (*)(void))seed_get_seed }, |
325 | | { OSSL_FUNC_RAND_CLEAR_SEED, (void (*)(void))seed_clear_seed }, |
326 | | OSSL_DISPATCH_END |
327 | | }; |