]>
Commit | Line | Data |
---|---|---|
d69226a3 | 1 | /* |
fecb3aae | 2 | * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. |
d69226a3 P |
3 | * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. |
4 | * | |
5 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
6 | * this file except in compliance with the License. You can obtain a copy | |
7 | * in the file LICENSE in the source distribution or at | |
8 | * https://www.openssl.org/source/license.html | |
9 | */ | |
10 | ||
11 | /* | |
12 | * Implementation of the FIPS 140-2 section 4.9.2 Conditional Tests. | |
13 | */ | |
14 | ||
15 | #include <string.h> | |
8094a694 | 16 | #include <openssl/evp.h> |
363b1e5d | 17 | #include <openssl/core_dispatch.h> |
4bffc025 | 18 | #include <openssl/params.h> |
35e6ea3b | 19 | #include <openssl/self_test.h> |
4bffc025 P |
20 | #include "prov/providercommon.h" |
21 | #include "prov/provider_ctx.h" | |
4e297b74 | 22 | #include "internal/cryptlib.h" |
08edd447 | 23 | #include "crypto/rand_pool.h" |
714a1bb3 | 24 | #include "drbg_local.h" |
f000e828 | 25 | #include "prov/seeding.h" |
927d0566 | 26 | #include "crypto/context.h" |
d69226a3 | 27 | |
4e297b74 MC |
28 | typedef struct crng_test_global_st { |
29 | unsigned char crngt_prev[EVP_MAX_MD_SIZE]; | |
08edd447 P |
30 | EVP_MD *md; |
31 | int preloaded; | |
32 | CRYPTO_RWLOCK *lock; | |
4e297b74 | 33 | } CRNG_TEST_GLOBAL; |
d69226a3 | 34 | |
08edd447 | 35 | static int crngt_get_entropy(PROV_CTX *provctx, const EVP_MD *digest, |
714a1bb3 P |
36 | unsigned char *buf, unsigned char *md, |
37 | unsigned int *md_size) | |
38 | { | |
39 | int r; | |
40 | size_t n; | |
41 | unsigned char *p; | |
42 | ||
08edd447 P |
43 | n = ossl_prov_get_entropy(provctx, &p, 0, CRNGT_BUFSIZ, CRNGT_BUFSIZ); |
44 | if (n == CRNGT_BUFSIZ) { | |
45 | r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, digest, NULL); | |
714a1bb3 P |
46 | if (r != 0) |
47 | memcpy(buf, p, CRNGT_BUFSIZ); | |
08edd447 P |
48 | ossl_prov_cleanup_entropy(provctx, p, n); |
49 | return r != 0; | |
714a1bb3 | 50 | } |
08edd447 P |
51 | if (n != 0) |
52 | ossl_prov_cleanup_entropy(provctx, p, n); | |
714a1bb3 P |
53 | return 0; |
54 | } | |
d69226a3 | 55 | |
927d0566 | 56 | void ossl_rand_crng_ctx_free(void *vcrngt_glob) |
d69226a3 | 57 | { |
4e297b74 | 58 | CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob; |
d69226a3 | 59 | |
08edd447 P |
60 | CRYPTO_THREAD_lock_free(crngt_glob->lock); |
61 | EVP_MD_free(crngt_glob->md); | |
4e297b74 | 62 | OPENSSL_free(crngt_glob); |
d69226a3 P |
63 | } |
64 | ||
927d0566 | 65 | void *ossl_rand_crng_ctx_new(OSSL_LIB_CTX *ctx) |
d69226a3 | 66 | { |
4e297b74 | 67 | CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob)); |
8094a694 | 68 | |
4e297b74 MC |
69 | if (crngt_glob == NULL) |
70 | return NULL; | |
71 | ||
08edd447 | 72 | if ((crngt_glob->md = EVP_MD_fetch(ctx, "SHA256", "")) == NULL) { |
4e297b74 MC |
73 | OPENSSL_free(crngt_glob); |
74 | return NULL; | |
75 | } | |
08edd447 P |
76 | |
77 | if ((crngt_glob->lock = CRYPTO_THREAD_lock_new()) == NULL) { | |
78 | EVP_MD_free(crngt_glob->md); | |
79 | OPENSSL_free(crngt_glob); | |
80 | return NULL; | |
8094a694 | 81 | } |
08edd447 P |
82 | |
83 | return crngt_glob; | |
d69226a3 P |
84 | } |
85 | ||
801ed9ed | 86 | static int prov_crngt_compare_previous(const unsigned char *prev, |
7f9e7440 SL |
87 | const unsigned char *cur, |
88 | size_t sz) | |
801ed9ed P |
89 | { |
90 | const int res = memcmp(prev, cur, sz) != 0; | |
91 | ||
92 | if (!res) | |
35e6ea3b | 93 | ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG); |
801ed9ed P |
94 | return res; |
95 | } | |
96 | ||
1dc188ba | 97 | size_t ossl_crngt_get_entropy(PROV_DRBG *drbg, |
d69226a3 P |
98 | unsigned char **pout, |
99 | int entropy, size_t min_len, size_t max_len, | |
100 | int prediction_resistance) | |
101 | { | |
08edd447 P |
102 | unsigned char md[EVP_MAX_MD_SIZE]; |
103 | unsigned char buf[CRNGT_BUFSIZ]; | |
104 | unsigned char *ent, *entp, *entbuf; | |
8094a694 | 105 | unsigned int sz; |
08edd447 P |
106 | size_t bytes_needed; |
107 | size_t r = 0, s, t; | |
108 | int crng_test_pass = 1; | |
109 | OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx); | |
4e297b74 | 110 | CRNG_TEST_GLOBAL *crngt_glob |
927d0566 | 111 | = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_RAND_CRNGT_INDEX); |
7f9e7440 SL |
112 | OSSL_CALLBACK *stcb = NULL; |
113 | void *stcbarg = NULL; | |
114 | OSSL_SELF_TEST *st = NULL; | |
d69226a3 | 115 | |
4e297b74 | 116 | if (crngt_glob == NULL) |
d69226a3 P |
117 | return 0; |
118 | ||
08edd447 | 119 | if (!CRYPTO_THREAD_write_lock(crngt_glob->lock)) |
d69226a3 P |
120 | return 0; |
121 | ||
08edd447 P |
122 | if (!crngt_glob->preloaded) { |
123 | if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, buf, | |
124 | crngt_glob->crngt_prev, NULL)) { | |
125 | OPENSSL_cleanse(buf, sizeof(buf)); | |
126 | goto unlock_return; | |
127 | } | |
128 | crngt_glob->preloaded = 1; | |
129 | } | |
130 | ||
131 | /* | |
132 | * Calculate how many bytes of seed material we require, rounded up | |
133 | * to the nearest byte. If the entropy is of less than full quality, | |
134 | * the amount required should be scaled up appropriately here. | |
135 | */ | |
136 | bytes_needed = (entropy + 7) / 8; | |
137 | if (bytes_needed < min_len) | |
138 | bytes_needed = min_len; | |
139 | if (bytes_needed > max_len) | |
140 | goto unlock_return; | |
141 | entp = ent = OPENSSL_secure_malloc(bytes_needed); | |
142 | if (ent == NULL) | |
143 | goto unlock_return; | |
144 | ||
7f9e7440 SL |
145 | OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg); |
146 | if (stcb != NULL) { | |
147 | st = OSSL_SELF_TEST_new(stcb, stcbarg); | |
148 | if (st == NULL) | |
149 | goto err; | |
150 | OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_CRNG, | |
151 | OSSL_SELF_TEST_DESC_RNG); | |
152 | } | |
153 | ||
08edd447 P |
154 | for (t = bytes_needed; t > 0;) { |
155 | /* Care needs to be taken to avoid overrunning the buffer */ | |
156 | s = t >= CRNGT_BUFSIZ ? CRNGT_BUFSIZ : t; | |
157 | entbuf = t >= CRNGT_BUFSIZ ? entp : buf; | |
158 | if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, entbuf, md, &sz)) | |
7f9e7440 | 159 | goto err; |
08edd447 P |
160 | if (t < CRNGT_BUFSIZ) |
161 | memcpy(entp, buf, t); | |
7f9e7440 SL |
162 | /* Force a failure here if the callback returns 1 */ |
163 | if (OSSL_SELF_TEST_oncorrupt_byte(st, md)) | |
164 | memcpy(md, crngt_glob->crngt_prev, sz); | |
165 | if (!prov_crngt_compare_previous(crngt_glob->crngt_prev, md, sz)) { | |
166 | crng_test_pass = 0; | |
167 | goto err; | |
168 | } | |
08edd447 | 169 | /* Update for next block */ |
4e297b74 | 170 | memcpy(crngt_glob->crngt_prev, md, sz); |
08edd447 P |
171 | entp += s; |
172 | t -= s; | |
d69226a3 | 173 | } |
08edd447 P |
174 | r = bytes_needed; |
175 | *pout = ent; | |
176 | ent = NULL; | |
177 | ||
178 | err: | |
7f9e7440 SL |
179 | OSSL_SELF_TEST_onend(st, crng_test_pass); |
180 | OSSL_SELF_TEST_free(st); | |
08edd447 P |
181 | OPENSSL_secure_clear_free(ent, bytes_needed); |
182 | ||
183 | unlock_return: | |
184 | CRYPTO_THREAD_unlock(crngt_glob->lock); | |
d69226a3 P |
185 | return r; |
186 | } | |
187 | ||
08edd447 | 188 | void ossl_crngt_cleanup_entropy(ossl_unused PROV_DRBG *drbg, |
d69226a3 P |
189 | unsigned char *out, size_t outlen) |
190 | { | |
191 | OPENSSL_secure_clear_free(out, outlen); | |
192 | } |