710e707234d6f6f0ff58cca86a64e3bd8eee7f41
[openssl.git] / test / testutil / fake_random.c
1 /*
2  * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * https://www.openssl.org/source/license.html
8  * or in the file LICENSE in the source distribution.
9  */
10
11 #include <string.h>
12 #include <openssl/core_names.h>
13 #include <openssl/rand.h>
14 #include <openssl/provider.h>
15 #include "../testutil.h"
16
17 typedef struct {
18     int (*cb)(unsigned char *out, size_t outlen);
19     int state;
20 } FAKE_RAND;
21
22 static FAKE_RAND fake_rand;
23
24 static OSSL_FUNC_rand_newctx_fn fake_rand_newctx;
25 static OSSL_FUNC_rand_freectx_fn fake_rand_freectx;
26 static OSSL_FUNC_rand_instantiate_fn fake_rand_instantiate;
27 static OSSL_FUNC_rand_uninstantiate_fn fake_rand_uninstantiate;
28 static OSSL_FUNC_rand_generate_fn fake_rand_generate;
29 static OSSL_FUNC_rand_gettable_ctx_params_fn fake_rand_gettable_ctx_params;
30 static OSSL_FUNC_rand_get_ctx_params_fn fake_rand_get_ctx_params;
31 static OSSL_FUNC_rand_enable_locking_fn fake_rand_enable_locking;
32
33 static void *fake_rand_newctx(void *provctx, void *parent,
34                               const OSSL_DISPATCH *parent_dispatch)
35 {
36     fake_rand.cb = NULL;
37     fake_rand.state = EVP_RAND_STATE_UNINITIALISED;
38     return &fake_rand;
39 }
40
41 static void fake_rand_freectx(void *vrng)
42 {
43     FAKE_RAND *frng = (FAKE_RAND *)vrng;
44
45     frng->cb = NULL;
46     frng->state = EVP_RAND_STATE_UNINITIALISED;
47 }
48
49 static int fake_rand_instantiate(void *vrng, ossl_unused unsigned int strength,
50                                  ossl_unused  int prediction_resistance,
51                                  ossl_unused const unsigned char *pstr,
52                                  size_t pstr_len)
53 {
54     FAKE_RAND *frng = (FAKE_RAND *)vrng;
55
56     frng->state = EVP_RAND_STATE_READY;
57     return 1;
58 }
59
60 static int fake_rand_uninstantiate(void *vrng)
61 {
62     FAKE_RAND *frng = (FAKE_RAND *)vrng;
63
64     frng->state = EVP_RAND_STATE_UNINITIALISED;
65     return 1;
66 }
67
68 static int fake_rand_generate(void *vrng, unsigned char *out, size_t outlen,
69                               unsigned int strength, int prediction_resistance,
70                               const unsigned char *adin, size_t adinlen)
71 {
72     FAKE_RAND *frng = (FAKE_RAND *)vrng;
73     size_t l;
74     uint32_t r;
75
76     if (frng->cb != NULL)
77         return (*frng->cb)(out, outlen);
78     while (outlen > 0) {
79         r = test_random();
80         l = outlen < sizeof(r) ? outlen : sizeof(r);
81
82         memcpy(out, &r, l);
83         out += l;
84         outlen -= l;
85     }
86     return 1;
87 }
88
89 static int fake_rand_enable_locking(void *vrng)
90 {
91     return 1;
92 }
93
94 static int fake_rand_get_ctx_params(ossl_unused void *vrng, OSSL_PARAM params[])
95 {
96     FAKE_RAND *frng = (FAKE_RAND *)vrng;
97     OSSL_PARAM *p;
98
99     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
100     if (p != NULL && !OSSL_PARAM_set_int(p, frng->state))
101         return 0;
102
103     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
104     if (p != NULL && !OSSL_PARAM_set_int(p, 256))
105         return 0;
106
107     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
108     if (p != NULL && !OSSL_PARAM_set_size_t(p, INT_MAX))
109         return 0;
110     return 1;
111 }
112
113 static const OSSL_PARAM *fake_rand_gettable_ctx_params(void *vrng)
114 {
115     static const OSSL_PARAM known_gettable_ctx_params[] = {
116         OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL),
117         OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
118         OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
119         OSSL_PARAM_END
120     };
121     return known_gettable_ctx_params;
122 }
123
124 static const OSSL_DISPATCH fake_rand_functions[] = {
125     { OSSL_FUNC_RAND_NEWCTX, (void (*)(void))fake_rand_newctx },
126     { OSSL_FUNC_RAND_FREECTX, (void (*)(void))fake_rand_freectx },
127     { OSSL_FUNC_RAND_INSTANTIATE, (void (*)(void))fake_rand_instantiate },
128     { OSSL_FUNC_RAND_UNINSTANTIATE, (void (*)(void))fake_rand_uninstantiate },
129     { OSSL_FUNC_RAND_GENERATE, (void (*)(void))fake_rand_generate },
130     { OSSL_FUNC_RAND_ENABLE_LOCKING, (void (*)(void))fake_rand_enable_locking },
131     { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
132       (void(*)(void))fake_rand_gettable_ctx_params },
133     { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))fake_rand_get_ctx_params },
134     { 0, NULL }
135 };
136
137 static const OSSL_ALGORITHM fake_rand_rand[] = {
138     { "FAKE", "provider=fake", fake_rand_functions },
139     { NULL, NULL, NULL }
140 };
141
142 static const OSSL_ALGORITHM *fake_rand_query(void *provctx,
143                                              int operation_id,
144                                              int *no_cache)
145 {
146     *no_cache = 0;
147     switch (operation_id) {
148     case OSSL_OP_RAND:
149         return fake_rand_rand;
150     }
151     return NULL;
152 }
153
154 /* Functions we provide to the core */
155 static const OSSL_DISPATCH fake_rand_method[] = {
156     { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free },
157     { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fake_rand_query },
158     { 0, NULL }
159 };
160
161 static int fake_rand_provider_init(const OSSL_CORE_HANDLE *handle,
162                                    const OSSL_DISPATCH *in,
163                                    const OSSL_DISPATCH **out, void **provctx)
164 {
165     if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new()))
166         return 0;
167     *out = fake_rand_method;
168     return 1;
169 }
170
171 OSSL_PROVIDER *fake_rand_start(OSSL_LIB_CTX *libctx)
172 {
173     OSSL_PROVIDER *p;
174
175     if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, "fake-rand",
176                                              fake_rand_provider_init))
177             || !TEST_true(RAND_set_DRBG_type(libctx, "fake", NULL, NULL, NULL))
178             || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, "fake-rand", 1)))
179         return NULL;
180
181     /* Ensure that the fake rand is initialized. */
182     if (!TEST_ptr(RAND_get0_private(libctx))
183             || !TEST_ptr(RAND_get0_public(libctx))) {
184         OSSL_PROVIDER_unload(p);
185         return NULL;
186     }
187
188     return p;
189 }
190
191 void fake_rand_finish(OSSL_PROVIDER *p)
192 {
193     OSSL_PROVIDER_unload(p);
194 }
195
196 void fake_rand_set_callback(int (*cb)(unsigned char *out, size_t outlen))
197 {
198     fake_rand.cb = cb;
199 }
200