1 | /*
|
---|
2 | * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
|
---|
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>
|
---|
16 | #include <openssl/evp.h>
|
---|
17 | #include <openssl/core_dispatch.h>
|
---|
18 | #include <openssl/params.h>
|
---|
19 | #include <openssl/self_test.h>
|
---|
20 | #include "prov/providercommon.h"
|
---|
21 | #include "prov/provider_ctx.h"
|
---|
22 | #include "internal/cryptlib.h"
|
---|
23 | #include "crypto/rand_pool.h"
|
---|
24 | #include "drbg_local.h"
|
---|
25 | #include "prov/seeding.h"
|
---|
26 | #include "crypto/context.h"
|
---|
27 |
|
---|
28 | typedef struct crng_test_global_st {
|
---|
29 | unsigned char crngt_prev[EVP_MAX_MD_SIZE];
|
---|
30 | EVP_MD *md;
|
---|
31 | int preloaded;
|
---|
32 | CRYPTO_RWLOCK *lock;
|
---|
33 | } CRNG_TEST_GLOBAL;
|
---|
34 |
|
---|
35 | static int crngt_get_entropy(PROV_CTX *provctx, const EVP_MD *digest,
|
---|
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 |
|
---|
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);
|
---|
46 | if (r != 0)
|
---|
47 | memcpy(buf, p, CRNGT_BUFSIZ);
|
---|
48 | ossl_prov_cleanup_entropy(provctx, p, n);
|
---|
49 | return r != 0;
|
---|
50 | }
|
---|
51 | if (n != 0)
|
---|
52 | ossl_prov_cleanup_entropy(provctx, p, n);
|
---|
53 | return 0;
|
---|
54 | }
|
---|
55 |
|
---|
56 | void ossl_rand_crng_ctx_free(void *vcrngt_glob)
|
---|
57 | {
|
---|
58 | CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob;
|
---|
59 |
|
---|
60 | CRYPTO_THREAD_lock_free(crngt_glob->lock);
|
---|
61 | EVP_MD_free(crngt_glob->md);
|
---|
62 | OPENSSL_free(crngt_glob);
|
---|
63 | }
|
---|
64 |
|
---|
65 | void *ossl_rand_crng_ctx_new(OSSL_LIB_CTX *ctx)
|
---|
66 | {
|
---|
67 | CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob));
|
---|
68 |
|
---|
69 | if (crngt_glob == NULL)
|
---|
70 | return NULL;
|
---|
71 |
|
---|
72 | if ((crngt_glob->md = EVP_MD_fetch(ctx, "SHA256", "")) == NULL) {
|
---|
73 | OPENSSL_free(crngt_glob);
|
---|
74 | return NULL;
|
---|
75 | }
|
---|
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;
|
---|
81 | }
|
---|
82 |
|
---|
83 | return crngt_glob;
|
---|
84 | }
|
---|
85 |
|
---|
86 | static int prov_crngt_compare_previous(const unsigned char *prev,
|
---|
87 | const unsigned char *cur,
|
---|
88 | size_t sz)
|
---|
89 | {
|
---|
90 | const int res = memcmp(prev, cur, sz) != 0;
|
---|
91 |
|
---|
92 | if (!res)
|
---|
93 | ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG);
|
---|
94 | return res;
|
---|
95 | }
|
---|
96 |
|
---|
97 | size_t ossl_crngt_get_entropy(PROV_DRBG *drbg,
|
---|
98 | unsigned char **pout,
|
---|
99 | int entropy, size_t min_len, size_t max_len,
|
---|
100 | int prediction_resistance)
|
---|
101 | {
|
---|
102 | unsigned char md[EVP_MAX_MD_SIZE];
|
---|
103 | unsigned char buf[CRNGT_BUFSIZ];
|
---|
104 | unsigned char *ent, *entp, *entbuf;
|
---|
105 | unsigned int sz;
|
---|
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);
|
---|
110 | CRNG_TEST_GLOBAL *crngt_glob
|
---|
111 | = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_RAND_CRNGT_INDEX);
|
---|
112 | OSSL_CALLBACK *stcb = NULL;
|
---|
113 | void *stcbarg = NULL;
|
---|
114 | OSSL_SELF_TEST *st = NULL;
|
---|
115 |
|
---|
116 | if (crngt_glob == NULL)
|
---|
117 | return 0;
|
---|
118 |
|
---|
119 | if (!CRYPTO_THREAD_write_lock(crngt_glob->lock))
|
---|
120 | return 0;
|
---|
121 |
|
---|
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 |
|
---|
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 |
|
---|
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))
|
---|
159 | goto err;
|
---|
160 | if (t < CRNGT_BUFSIZ)
|
---|
161 | memcpy(entp, buf, t);
|
---|
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 | }
|
---|
169 | /* Update for next block */
|
---|
170 | memcpy(crngt_glob->crngt_prev, md, sz);
|
---|
171 | entp += s;
|
---|
172 | t -= s;
|
---|
173 | }
|
---|
174 | r = bytes_needed;
|
---|
175 | *pout = ent;
|
---|
176 | ent = NULL;
|
---|
177 |
|
---|
178 | err:
|
---|
179 | OSSL_SELF_TEST_onend(st, crng_test_pass);
|
---|
180 | OSSL_SELF_TEST_free(st);
|
---|
181 | OPENSSL_secure_clear_free(ent, bytes_needed);
|
---|
182 |
|
---|
183 | unlock_return:
|
---|
184 | CRYPTO_THREAD_unlock(crngt_glob->lock);
|
---|
185 | return r;
|
---|
186 | }
|
---|
187 |
|
---|
188 | void ossl_crngt_cleanup_entropy(ossl_unused PROV_DRBG *drbg,
|
---|
189 | unsigned char *out, size_t outlen)
|
---|
190 | {
|
---|
191 | OPENSSL_secure_clear_free(out, outlen);
|
---|
192 | }
|
---|