b348b40d82110d9b902c5a8ab1e13bfeaf3e4f12
[openssl.git] / providers / implementations / rands / rand_crng_test.c
1 /*
2  * Copyright 2019 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 "crypto/rand.h"
18 #include "internal/thread_once.h"
19 #include "internal/cryptlib.h"
20 #include "crypto/rand_pool.h"
21 #include "drbg_local.h"
22 #include "crypto/rand_pool.h"
23 #include "seeding/seeding.h"
24
25 typedef struct crng_test_global_st {
26     unsigned char crngt_prev[EVP_MAX_MD_SIZE];
27     RAND_POOL *crngt_pool;
28 } CRNG_TEST_GLOBAL;
29
30 static int crngt_get_entropy(OPENSSL_CTX *ctx, RAND_POOL *pool,
31                              unsigned char *buf, unsigned char *md,
32                              unsigned int *md_size)
33 {
34     int r;
35     size_t n;
36     unsigned char *p;
37
38     if (pool == NULL)
39         return 0;
40
41     n = prov_pool_acquire_entropy(pool);
42     if (n >= CRNGT_BUFSIZ) {
43         EVP_MD *fmd = EVP_MD_fetch(ctx, "SHA256", "");
44         if (fmd == NULL)
45             return 0;
46         p = rand_pool_detach(pool);
47         r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, fmd, NULL);
48         if (r != 0)
49             memcpy(buf, p, CRNGT_BUFSIZ);
50         rand_pool_reattach(pool, p);
51         EVP_MD_free(fmd);
52         return r;
53     }
54     return 0;
55 }
56
57 static void rand_crng_ossl_ctx_free(void *vcrngt_glob)
58 {
59     CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob;
60
61     rand_pool_free(crngt_glob->crngt_pool);
62     OPENSSL_free(crngt_glob);
63 }
64
65 static void *rand_crng_ossl_ctx_new(OPENSSL_CTX *ctx)
66 {
67     unsigned char buf[CRNGT_BUFSIZ];
68     CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob));
69
70     if (crngt_glob == NULL)
71         return NULL;
72
73     if ((crngt_glob->crngt_pool
74          = rand_pool_new(0, 1, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) {
75         OPENSSL_free(crngt_glob);
76         return NULL;
77     }
78     if (crngt_get_entropy(ctx, crngt_glob->crngt_pool, buf,
79                           crngt_glob->crngt_prev, NULL)) {
80         OPENSSL_cleanse(buf, sizeof(buf));
81         return crngt_glob;
82     }
83     rand_pool_free(crngt_glob->crngt_pool);
84     OPENSSL_free(crngt_glob);
85     return NULL;
86 }
87
88 static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = {
89     rand_crng_ossl_ctx_new,
90     rand_crng_ossl_ctx_free,
91 };
92
93 int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx,
94                               RAND_POOL *pool,
95                               unsigned char *buf,
96                               unsigned char *md,
97                               unsigned int *md_size)
98 {
99     int r;
100     size_t n;
101     unsigned char *p;
102
103     if (pool == NULL)
104         return 0;
105
106     n = rand_pool_acquire_entropy(pool);
107     if (n >= CRNGT_BUFSIZ) {
108         EVP_MD *fmd = EVP_MD_fetch(ctx, "SHA256", "");
109         if (fmd == NULL)
110             return 0;
111         p = rand_pool_detach(pool);
112         r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, fmd, NULL);
113         if (r != 0)
114             memcpy(buf, p, CRNGT_BUFSIZ);
115         rand_pool_reattach(pool, p);
116         EVP_MD_free(fmd);
117         return r;
118     }
119     return 0;
120 }
121
122 size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
123                               unsigned char **pout,
124                               int entropy, size_t min_len, size_t max_len,
125                               int prediction_resistance)
126 {
127     unsigned char buf[CRNGT_BUFSIZ], md[EVP_MAX_MD_SIZE];
128     unsigned int sz;
129     RAND_POOL *pool;
130     size_t q, r = 0, s, t = 0;
131     int attempts = 3;
132     CRNG_TEST_GLOBAL *crngt_glob
133         = openssl_ctx_get_data(drbg->libctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
134                                &rand_crng_ossl_ctx_method);
135
136     if (crngt_glob == NULL)
137         return 0;
138
139     if ((pool = rand_pool_new(entropy, 1, min_len, max_len)) == NULL)
140         return 0;
141
142     while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
143         s = q > sizeof(buf) ? sizeof(buf) : q;
144         if (!crngt_get_entropy(drbg->libctx, crngt_glob->crngt_pool, buf, md,
145                                &sz)
146             || memcmp(crngt_glob->crngt_prev, md, sz) == 0
147             || !rand_pool_add(pool, buf, s, s * 8))
148             goto err;
149         memcpy(crngt_glob->crngt_prev, md, sz);
150         t += s;
151         attempts++;
152     }
153     r = t;
154     *pout = rand_pool_detach(pool);
155 err:
156     OPENSSL_cleanse(buf, sizeof(buf));
157     rand_pool_free(pool);
158     return r;
159 }
160
161 void rand_crngt_cleanup_entropy(RAND_DRBG *drbg,
162                                 unsigned char *out, size_t outlen)
163 {
164     OPENSSL_secure_clear_free(out, outlen);
165 }
166
167 #if 0
168 const OSSL_DISPATCH crngt_functions[] = {
169     { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))crngt_new },
170     { OSSL_FUNC_RAND_FREECTX, (void(*)(void))crngt_free },
171     { OSSL_FUNC_RAND_INSTANTIATE, (void(*)(void))crngt_instantiate },
172     { OSSL_FUNC_RAND_UNINSTANTIATE, (void(*)(void))crngt_uninstantiate },
173     { OSSL_FUNC_RAND_GENERATE, (void(*)(void))crngt_generate },
174     { OSSL_FUNC_RAND_RESEED, (void(*)(void))crngt_reseed },
175     { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))drbg_enable_locking },
176     { OSSL_FUNC_RAND_LOCK, (void(*)(void))drbg_lock },
177     { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))drbg_unlock },
178     { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
179       (void(*)(void))crngt_settable_ctx_params },
180     { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))crngt_set_ctx_params },
181     { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
182       (void(*)(void))crngt_gettable_ctx_params },
183     { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))crngt_get_ctx_params },
184     { 0, NULL }
185 };
186 #endif