/src/openssl/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 | 0 | { |
23 | 0 | size_t ret = 0; |
24 | 0 | size_t entropy_available; |
25 | 0 | RAND_POOL *pool; |
26 | |
|
27 | 0 | pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); |
28 | 0 | 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 | 0 | entropy_available = ossl_pool_acquire_entropy(pool); |
35 | |
|
36 | 0 | if (entropy_available > 0) { |
37 | 0 | ret = ossl_rand_pool_length(pool); |
38 | 0 | *pout = ossl_rand_pool_detach(pool); |
39 | 0 | } |
40 | |
|
41 | 0 | ossl_rand_pool_free(pool); |
42 | 0 | return ret; |
43 | 0 | } |
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 | 0 | { |
55 | 0 | unsigned char *seed = NULL, *buf; |
56 | 0 | size_t ret; |
57 | |
|
58 | 0 | ret = evp_rand_get_seed(rng, &seed, entropy, min_len, max_len, |
59 | 0 | 0, NULL, 0); |
60 | 0 | if (ret == 0) |
61 | 0 | return 0; |
62 | 0 | buf = OPENSSL_secure_malloc(ret); |
63 | 0 | if (buf != NULL) |
64 | 0 | memcpy(buf, seed, ret); |
65 | 0 | evp_rand_clear_seed(rng, seed, ret); |
66 | 0 | if (buf == NULL) |
67 | 0 | return 0; |
68 | 0 | *pout = buf; |
69 | 0 | return ret; |
70 | 0 | } |
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 | 0 | { |
76 | 0 | EVP_RAND_CTX *rng; |
77 | |
|
78 | 0 | if (ossl_rand_seed_source_strict(ctx)) { |
79 | | /* |
80 | | * With strict seeding the configured seed source must be used, |
81 | | * even when the request arrives before anything instantiated it. |
82 | | */ |
83 | 0 | rng = ossl_rand_get0_seed(ctx); |
84 | 0 | if (rng == NULL || !evp_rand_can_seed(rng)) { |
85 | 0 | ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY); |
86 | 0 | return 0; |
87 | 0 | } |
88 | 0 | } else { |
89 | 0 | rng = ossl_rand_get0_seed_noncreating(ctx); |
90 | 0 | if (rng == NULL || !evp_rand_can_seed(rng)) |
91 | 0 | return ossl_rand_get_entropy(ctx, pout, entropy, min_len, max_len); |
92 | 0 | } |
93 | 0 | return rand_get_seed_copy(rng, pout, entropy, min_len, max_len); |
94 | 0 | } |
95 | | |
96 | | void ossl_rand_cleanup_entropy(ossl_unused OSSL_LIB_CTX *ctx, |
97 | | unsigned char *buf, size_t len) |
98 | 0 | { |
99 | 0 | OPENSSL_secure_clear_free(buf, len); |
100 | 0 | } |
101 | | |
102 | | /* See rand_get_seed_copy() */ |
103 | | void ossl_rand_cleanup_user_entropy(OSSL_LIB_CTX *ctx, |
104 | | unsigned char *buf, size_t len) |
105 | 0 | { |
106 | 0 | ossl_rand_cleanup_entropy(ctx, buf, len); |
107 | 0 | } |
108 | | |
109 | | size_t ossl_rand_get_nonce(ossl_unused OSSL_LIB_CTX *ctx, |
110 | | unsigned char **pout, |
111 | | size_t min_len, ossl_unused size_t max_len, |
112 | | const void *salt, size_t salt_len) |
113 | 0 | { |
114 | 0 | size_t ret = 0; |
115 | 0 | RAND_POOL *pool; |
116 | |
|
117 | 0 | pool = ossl_rand_pool_new(0, 0, min_len, max_len); |
118 | 0 | if (pool == NULL) { |
119 | 0 | ERR_raise(ERR_LIB_RAND, ERR_R_RAND_LIB); |
120 | 0 | return 0; |
121 | 0 | } |
122 | | |
123 | 0 | if (!ossl_pool_add_nonce_data(pool)) |
124 | 0 | goto err; |
125 | | |
126 | 0 | if (salt != NULL && !ossl_rand_pool_add(pool, salt, salt_len, 0)) |
127 | 0 | goto err; |
128 | 0 | ret = ossl_rand_pool_length(pool); |
129 | 0 | *pout = ossl_rand_pool_detach(pool); |
130 | 0 | err: |
131 | 0 | ossl_rand_pool_free(pool); |
132 | 0 | return ret; |
133 | 0 | } |
134 | | |
135 | | size_t ossl_rand_get_user_nonce(OSSL_LIB_CTX *ctx, |
136 | | unsigned char **pout, |
137 | | size_t min_len, size_t max_len, |
138 | | const void *salt, size_t salt_len) |
139 | 0 | { |
140 | 0 | unsigned char *buf; |
141 | 0 | EVP_RAND_CTX *rng; |
142 | |
|
143 | 0 | if (ossl_rand_seed_source_strict(ctx)) { |
144 | | /* See ossl_rand_get_user_entropy() */ |
145 | 0 | rng = ossl_rand_get0_seed(ctx); |
146 | 0 | if (rng == NULL) { |
147 | 0 | ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_NONCE); |
148 | 0 | return 0; |
149 | 0 | } |
150 | 0 | } else { |
151 | 0 | rng = ossl_rand_get0_seed_noncreating(ctx); |
152 | 0 | if (rng == NULL) |
153 | 0 | return ossl_rand_get_nonce(ctx, pout, min_len, max_len, |
154 | 0 | salt, salt_len); |
155 | 0 | } |
156 | | |
157 | 0 | if ((buf = OPENSSL_malloc(min_len)) == NULL) |
158 | 0 | return 0; |
159 | | |
160 | 0 | if (!EVP_RAND_generate(rng, buf, min_len, 0, 0, salt, salt_len)) { |
161 | 0 | OPENSSL_free(buf); |
162 | 0 | return 0; |
163 | 0 | } |
164 | 0 | *pout = buf; |
165 | 0 | return min_len; |
166 | 0 | } |
167 | | |
168 | | void ossl_rand_cleanup_nonce(ossl_unused OSSL_LIB_CTX *ctx, |
169 | | unsigned char *buf, size_t len) |
170 | 0 | { |
171 | 0 | OPENSSL_clear_free(buf, len); |
172 | 0 | } |
173 | | |
174 | | void ossl_rand_cleanup_user_nonce(ossl_unused OSSL_LIB_CTX *ctx, |
175 | | unsigned char *buf, size_t len) |
176 | 0 | { |
177 | 0 | OPENSSL_clear_free(buf, len); |
178 | 0 | } |