1 | /*
|
---|
2 | * Copyright 2019-2021 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 |
|
---|
27 | typedef struct crng_test_global_st {
|
---|
28 | unsigned char crngt_prev[EVP_MAX_MD_SIZE];
|
---|
29 | EVP_MD *md;
|
---|
30 | int preloaded;
|
---|
31 | CRYPTO_RWLOCK *lock;
|
---|
32 | } CRNG_TEST_GLOBAL;
|
---|
33 |
|
---|
34 | static int crngt_get_entropy(PROV_CTX *provctx, const EVP_MD *digest,
|
---|
35 | unsigned char *buf, unsigned char *md,
|
---|
36 | unsigned int *md_size)
|
---|
37 | {
|
---|
38 | int r;
|
---|
39 | size_t n;
|
---|
40 | unsigned char *p;
|
---|
41 |
|
---|
42 | n = ossl_prov_get_entropy(provctx, &p, 0, CRNGT_BUFSIZ, CRNGT_BUFSIZ);
|
---|
43 | if (n == CRNGT_BUFSIZ) {
|
---|
44 | r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, digest, NULL);
|
---|
45 | if (r != 0)
|
---|
46 | memcpy(buf, p, CRNGT_BUFSIZ);
|
---|
47 | ossl_prov_cleanup_entropy(provctx, p, n);
|
---|
48 | return r != 0;
|
---|
49 | }
|
---|
50 | if (n != 0)
|
---|
51 | ossl_prov_cleanup_entropy(provctx, p, n);
|
---|
52 | return 0;
|
---|
53 | }
|
---|
54 |
|
---|
55 | static void rand_crng_ossl_ctx_free(void *vcrngt_glob)
|
---|
56 | {
|
---|
57 | CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob;
|
---|
58 |
|
---|
59 | CRYPTO_THREAD_lock_free(crngt_glob->lock);
|
---|
60 | EVP_MD_free(crngt_glob->md);
|
---|
61 | OPENSSL_free(crngt_glob);
|
---|
62 | }
|
---|
63 |
|
---|
64 | static void *rand_crng_ossl_ctx_new(OSSL_LIB_CTX *ctx)
|
---|
65 | {
|
---|
66 | CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob));
|
---|
67 |
|
---|
68 | if (crngt_glob == NULL)
|
---|
69 | return NULL;
|
---|
70 |
|
---|
71 | if ((crngt_glob->md = EVP_MD_fetch(ctx, "SHA256", "")) == NULL) {
|
---|
72 | OPENSSL_free(crngt_glob);
|
---|
73 | return NULL;
|
---|
74 | }
|
---|
75 |
|
---|
76 | if ((crngt_glob->lock = CRYPTO_THREAD_lock_new()) == NULL) {
|
---|
77 | EVP_MD_free(crngt_glob->md);
|
---|
78 | OPENSSL_free(crngt_glob);
|
---|
79 | return NULL;
|
---|
80 | }
|
---|
81 |
|
---|
82 | return crngt_glob;
|
---|
83 | }
|
---|
84 |
|
---|
85 | static const OSSL_LIB_CTX_METHOD rand_crng_ossl_ctx_method = {
|
---|
86 | OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
|
---|
87 | rand_crng_ossl_ctx_new,
|
---|
88 | rand_crng_ossl_ctx_free,
|
---|
89 | };
|
---|
90 |
|
---|
91 | static int prov_crngt_compare_previous(const unsigned char *prev,
|
---|
92 | const unsigned char *cur,
|
---|
93 | size_t sz)
|
---|
94 | {
|
---|
95 | const int res = memcmp(prev, cur, sz) != 0;
|
---|
96 |
|
---|
97 | if (!res)
|
---|
98 | ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG);
|
---|
99 | return res;
|
---|
100 | }
|
---|
101 |
|
---|
102 | size_t ossl_crngt_get_entropy(PROV_DRBG *drbg,
|
---|
103 | unsigned char **pout,
|
---|
104 | int entropy, size_t min_len, size_t max_len,
|
---|
105 | int prediction_resistance)
|
---|
106 | {
|
---|
107 | unsigned char md[EVP_MAX_MD_SIZE];
|
---|
108 | unsigned char buf[CRNGT_BUFSIZ];
|
---|
109 | unsigned char *ent, *entp, *entbuf;
|
---|
110 | unsigned int sz;
|
---|
111 | size_t bytes_needed;
|
---|
112 | size_t r = 0, s, t;
|
---|
113 | int crng_test_pass = 1;
|
---|
114 | OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx);
|
---|
115 | CRNG_TEST_GLOBAL *crngt_glob
|
---|
116 | = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_RAND_CRNGT_INDEX,
|
---|
117 | &rand_crng_ossl_ctx_method);
|
---|
118 | OSSL_CALLBACK *stcb = NULL;
|
---|
119 | void *stcbarg = NULL;
|
---|
120 | OSSL_SELF_TEST *st = NULL;
|
---|
121 |
|
---|
122 | if (crngt_glob == NULL)
|
---|
123 | return 0;
|
---|
124 |
|
---|
125 | if (!CRYPTO_THREAD_write_lock(crngt_glob->lock))
|
---|
126 | return 0;
|
---|
127 |
|
---|
128 | if (!crngt_glob->preloaded) {
|
---|
129 | if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, buf,
|
---|
130 | crngt_glob->crngt_prev, NULL)) {
|
---|
131 | OPENSSL_cleanse(buf, sizeof(buf));
|
---|
132 | goto unlock_return;
|
---|
133 | }
|
---|
134 | crngt_glob->preloaded = 1;
|
---|
135 | }
|
---|
136 |
|
---|
137 | /*
|
---|
138 | * Calculate how many bytes of seed material we require, rounded up
|
---|
139 | * to the nearest byte. If the entropy is of less than full quality,
|
---|
140 | * the amount required should be scaled up appropriately here.
|
---|
141 | */
|
---|
142 | bytes_needed = (entropy + 7) / 8;
|
---|
143 | if (bytes_needed < min_len)
|
---|
144 | bytes_needed = min_len;
|
---|
145 | if (bytes_needed > max_len)
|
---|
146 | goto unlock_return;
|
---|
147 | entp = ent = OPENSSL_secure_malloc(bytes_needed);
|
---|
148 | if (ent == NULL)
|
---|
149 | goto unlock_return;
|
---|
150 |
|
---|
151 | OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg);
|
---|
152 | if (stcb != NULL) {
|
---|
153 | st = OSSL_SELF_TEST_new(stcb, stcbarg);
|
---|
154 | if (st == NULL)
|
---|
155 | goto err;
|
---|
156 | OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_CRNG,
|
---|
157 | OSSL_SELF_TEST_DESC_RNG);
|
---|
158 | }
|
---|
159 |
|
---|
160 | for (t = bytes_needed; t > 0;) {
|
---|
161 | /* Care needs to be taken to avoid overrunning the buffer */
|
---|
162 | s = t >= CRNGT_BUFSIZ ? CRNGT_BUFSIZ : t;
|
---|
163 | entbuf = t >= CRNGT_BUFSIZ ? entp : buf;
|
---|
164 | if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, entbuf, md, &sz))
|
---|
165 | goto err;
|
---|
166 | if (t < CRNGT_BUFSIZ)
|
---|
167 | memcpy(entp, buf, t);
|
---|
168 | /* Force a failure here if the callback returns 1 */
|
---|
169 | if (OSSL_SELF_TEST_oncorrupt_byte(st, md))
|
---|
170 | memcpy(md, crngt_glob->crngt_prev, sz);
|
---|
171 | if (!prov_crngt_compare_previous(crngt_glob->crngt_prev, md, sz)) {
|
---|
172 | crng_test_pass = 0;
|
---|
173 | goto err;
|
---|
174 | }
|
---|
175 | /* Update for next block */
|
---|
176 | memcpy(crngt_glob->crngt_prev, md, sz);
|
---|
177 | entp += s;
|
---|
178 | t -= s;
|
---|
179 | }
|
---|
180 | r = bytes_needed;
|
---|
181 | *pout = ent;
|
---|
182 | ent = NULL;
|
---|
183 |
|
---|
184 | err:
|
---|
185 | OSSL_SELF_TEST_onend(st, crng_test_pass);
|
---|
186 | OSSL_SELF_TEST_free(st);
|
---|
187 | OPENSSL_secure_clear_free(ent, bytes_needed);
|
---|
188 |
|
---|
189 | unlock_return:
|
---|
190 | CRYPTO_THREAD_unlock(crngt_glob->lock);
|
---|
191 | return r;
|
---|
192 | }
|
---|
193 |
|
---|
194 | void ossl_crngt_cleanup_entropy(ossl_unused PROV_DRBG *drbg,
|
---|
195 | unsigned char *out, size_t outlen)
|
---|
196 | {
|
---|
197 | OPENSSL_secure_clear_free(out, outlen);
|
---|
198 | }
|
---|