/src/openssl41/crypto/rand/prov_seed.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2020-2026 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 "rand_local.h" |
11 | | #include "crypto/evp.h" |
12 | | #include "crypto/rand.h" |
13 | | #include "crypto/rand_pool.h" |
14 | | #include "internal/core.h" |
15 | | #include <openssl/core_dispatch.h> |
16 | | #include <openssl/err.h> |
17 | | #include <string.h> |
18 | | |
19 | | size_t ossl_rand_get_entropy(ossl_unused OSSL_LIB_CTX *ctx, |
20 | | unsigned char **pout, int entropy, |
21 | | size_t min_len, size_t max_len) |
22 | 1.30k | { |
23 | 1.30k | size_t ret = 0; |
24 | 1.30k | size_t entropy_available; |
25 | 1.30k | RAND_POOL *pool; |
26 | | |
27 | 1.30k | pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); |
28 | 1.30k | if (pool == NULL) { |
29 | 0 | ERR_raise(ERR_LIB_RAND, ERR_R_RAND_LIB); |
30 | 0 | return 0; |
31 | 0 | } |
32 | | |
33 | | /* Get entropy by polling system entropy sources. */ |
34 | 1.30k | entropy_available = ossl_pool_acquire_entropy(pool); |
35 | | |
36 | 1.30k | if (entropy_available > 0) { |
37 | 1.30k | ret = ossl_rand_pool_length(pool); |
38 | 1.30k | *pout = ossl_rand_pool_detach(pool); |
39 | 1.30k | } |
40 | | |
41 | 1.30k | ossl_rand_pool_free(pool); |
42 | 1.30k | return ret; |
43 | 1.30k | } |
44 | | |
45 | | /* |
46 | | * Copy the seed into a buffer of our own and hand the original straight back |
47 | | * to the seed source. Otherwise ossl_rand_cleanup_user_entropy() would have |
48 | | * to work out who allocated |buf|, but a seed source may be created between |
49 | | * taking entropy from the operating system sources and cleaning it up, so |
50 | | * the seed source present at cleanup time does not tell. |
51 | | */ |
52 | | static size_t rand_get_seed_copy(EVP_RAND_CTX *rng, unsigned char **pout, |
53 | | int entropy, size_t min_len, size_t max_len) |
54 | 238 | { |
55 | 238 | unsigned char *seed = NULL, *buf; |
56 | 238 | size_t ret; |
57 | | |
58 | 238 | ret = evp_rand_get_seed(rng, &seed, entropy, min_len, max_len, |
59 | 238 | 0, NULL, 0); |
60 | 238 | if (ret == 0) |
61 | 0 | return 0; |
62 | 238 | buf = OPENSSL_secure_malloc(ret); |
63 | 238 | if (buf != NULL) |
64 | 238 | memcpy(buf, seed, ret); |
65 | 238 | evp_rand_clear_seed(rng, seed, ret); |
66 | 238 | if (buf == NULL) |
67 | 0 | return 0; |
68 | 238 | *pout = buf; |
69 | 238 | return ret; |
70 | 238 | } |
71 | | |
72 | | size_t ossl_rand_get_user_entropy(OSSL_LIB_CTX *ctx, |
73 | | unsigned char **pout, int entropy, |
74 | | size_t min_len, size_t max_len) |
75 | 637 | { |
76 | 637 | EVP_RAND_CTX *rng; |
77 | | |
78 | 637 | if (ossl_rand_seed_source_strict(ctx)) { |
79 | | /* |
80 | | * With strict seeding the seed source must be used, even when the |
81 | | * request arrives before anything instantiated it: create it now |
82 | | * and fail instead of silently substituting the operating system |
83 | | * entropy sources. |
84 | | */ |
85 | 0 | rng = ossl_rand_get0_seed(ctx); |
86 | 0 | if (rng == NULL || !evp_rand_can_seed(rng)) { |
87 | 0 | ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY); |
88 | 0 | return 0; |
89 | 0 | } |
90 | 637 | } else { |
91 | 637 | rng = ossl_rand_get0_seed_noncreating(ctx); |
92 | 637 | if (rng == NULL || !evp_rand_can_seed(rng)) |
93 | 399 | return ossl_rand_get_entropy(ctx, pout, entropy, min_len, max_len); |
94 | 637 | } |
95 | 238 | return rand_get_seed_copy(rng, pout, entropy, min_len, max_len); |
96 | 637 | } |
97 | | |
98 | | void ossl_rand_cleanup_entropy(ossl_unused OSSL_LIB_CTX *ctx, |
99 | | unsigned char *buf, size_t len) |
100 | 637 | { |
101 | 637 | OPENSSL_secure_clear_free(buf, len); |
102 | 637 | } |
103 | | |
104 | | /* See rand_get_seed_copy() */ |
105 | | void ossl_rand_cleanup_user_entropy(OSSL_LIB_CTX *ctx, |
106 | | unsigned char *buf, size_t len) |
107 | 637 | { |
108 | 637 | ossl_rand_cleanup_entropy(ctx, buf, len); |
109 | 637 | } |
110 | | |
111 | | size_t ossl_rand_get_nonce(ossl_unused OSSL_LIB_CTX *ctx, |
112 | | unsigned char **pout, |
113 | | size_t min_len, ossl_unused size_t max_len, |
114 | | const void *salt, size_t salt_len) |
115 | 629 | { |
116 | 629 | size_t ret = 0; |
117 | 629 | RAND_POOL *pool; |
118 | | |
119 | 629 | pool = ossl_rand_pool_new(0, 0, min_len, max_len); |
120 | 629 | if (pool == NULL) { |
121 | 0 | ERR_raise(ERR_LIB_RAND, ERR_R_RAND_LIB); |
122 | 0 | return 0; |
123 | 0 | } |
124 | | |
125 | 629 | if (!ossl_pool_add_nonce_data(pool)) |
126 | 0 | goto err; |
127 | | |
128 | 629 | if (salt != NULL && !ossl_rand_pool_add(pool, salt, salt_len, 0)) |
129 | 0 | goto err; |
130 | 629 | ret = ossl_rand_pool_length(pool); |
131 | 629 | *pout = ossl_rand_pool_detach(pool); |
132 | 629 | err: |
133 | 629 | ossl_rand_pool_free(pool); |
134 | 629 | return ret; |
135 | 629 | } |
136 | | |
137 | | size_t ossl_rand_get_user_nonce(OSSL_LIB_CTX *ctx, |
138 | | unsigned char **pout, |
139 | | size_t min_len, size_t max_len, |
140 | | const void *salt, size_t salt_len) |
141 | 306 | { |
142 | 306 | unsigned char *buf; |
143 | 306 | EVP_RAND_CTX *rng; |
144 | | |
145 | 306 | if (ossl_rand_seed_source_strict(ctx)) { |
146 | | /* See ossl_rand_get_user_entropy() */ |
147 | 0 | rng = ossl_rand_get0_seed(ctx); |
148 | 0 | if (rng == NULL) { |
149 | 0 | ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_NONCE); |
150 | 0 | return 0; |
151 | 0 | } |
152 | 306 | } else { |
153 | 306 | rng = ossl_rand_get0_seed_noncreating(ctx); |
154 | 306 | if (rng == NULL) |
155 | 188 | return ossl_rand_get_nonce(ctx, pout, min_len, max_len, |
156 | 188 | salt, salt_len); |
157 | 306 | } |
158 | | |
159 | 118 | if ((buf = OPENSSL_malloc(min_len)) == NULL) |
160 | 0 | return 0; |
161 | | |
162 | 118 | if (!EVP_RAND_generate(rng, buf, min_len, 0, 0, salt, salt_len)) { |
163 | 0 | OPENSSL_free(buf); |
164 | 0 | return 0; |
165 | 0 | } |
166 | 118 | *pout = buf; |
167 | 118 | return min_len; |
168 | 118 | } |
169 | | |
170 | | void ossl_rand_cleanup_nonce(ossl_unused OSSL_LIB_CTX *ctx, |
171 | | unsigned char *buf, size_t len) |
172 | 0 | { |
173 | 0 | OPENSSL_clear_free(buf, len); |
174 | 0 | } |
175 | | |
176 | | void ossl_rand_cleanup_user_nonce(ossl_unused OSSL_LIB_CTX *ctx, |
177 | | unsigned char *buf, size_t len) |
178 | 763 | { |
179 | 763 | OPENSSL_clear_free(buf, len); |
180 | 763 | } |