1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License");
5e1051a39Sopenharmony_ci * you may not use this file except in compliance with the License.
6e1051a39Sopenharmony_ci * You may obtain a copy of the License at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci * or in the file LICENSE in the source distribution.
9e1051a39Sopenharmony_ci */
10e1051a39Sopenharmony_ci
11e1051a39Sopenharmony_ci#include <openssl/core_names.h>
12e1051a39Sopenharmony_ci#include <openssl/rand.h>
13e1051a39Sopenharmony_ci#include <openssl/provider.h>
14e1051a39Sopenharmony_ci#include "fuzzer.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_cistatic OSSL_FUNC_rand_newctx_fn fuzz_rand_newctx;
17e1051a39Sopenharmony_cistatic OSSL_FUNC_rand_freectx_fn fuzz_rand_freectx;
18e1051a39Sopenharmony_cistatic OSSL_FUNC_rand_instantiate_fn fuzz_rand_instantiate;
19e1051a39Sopenharmony_cistatic OSSL_FUNC_rand_uninstantiate_fn fuzz_rand_uninstantiate;
20e1051a39Sopenharmony_cistatic OSSL_FUNC_rand_generate_fn fuzz_rand_generate;
21e1051a39Sopenharmony_cistatic OSSL_FUNC_rand_gettable_ctx_params_fn fuzz_rand_gettable_ctx_params;
22e1051a39Sopenharmony_cistatic OSSL_FUNC_rand_get_ctx_params_fn fuzz_rand_get_ctx_params;
23e1051a39Sopenharmony_cistatic OSSL_FUNC_rand_enable_locking_fn fuzz_rand_enable_locking;
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_cistatic void *fuzz_rand_newctx(
26e1051a39Sopenharmony_ci         void *provctx, void *parent, const OSSL_DISPATCH *parent_dispatch)
27e1051a39Sopenharmony_ci{
28e1051a39Sopenharmony_ci    int *st = OPENSSL_malloc(sizeof(*st));
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_ci    if (st != NULL)
31e1051a39Sopenharmony_ci        *st = EVP_RAND_STATE_UNINITIALISED;
32e1051a39Sopenharmony_ci    return st;
33e1051a39Sopenharmony_ci}
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_cistatic void fuzz_rand_freectx(ossl_unused void *vrng)
36e1051a39Sopenharmony_ci{
37e1051a39Sopenharmony_ci    OPENSSL_free(vrng);
38e1051a39Sopenharmony_ci}
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_cistatic int fuzz_rand_instantiate(ossl_unused void *vrng,
41e1051a39Sopenharmony_ci                                 ossl_unused unsigned int strength,
42e1051a39Sopenharmony_ci                                 ossl_unused int prediction_resistance,
43e1051a39Sopenharmony_ci                                 ossl_unused const unsigned char *pstr,
44e1051a39Sopenharmony_ci                                 ossl_unused size_t pstr_len,
45e1051a39Sopenharmony_ci                                 ossl_unused const OSSL_PARAM params[])
46e1051a39Sopenharmony_ci{
47e1051a39Sopenharmony_ci    *(int *)vrng = EVP_RAND_STATE_READY;
48e1051a39Sopenharmony_ci    return 1;
49e1051a39Sopenharmony_ci}
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_cistatic int fuzz_rand_uninstantiate(ossl_unused void *vrng)
52e1051a39Sopenharmony_ci{
53e1051a39Sopenharmony_ci    *(int *)vrng = EVP_RAND_STATE_UNINITIALISED;
54e1051a39Sopenharmony_ci    return 1;
55e1051a39Sopenharmony_ci}
56e1051a39Sopenharmony_ci
57e1051a39Sopenharmony_cistatic int fuzz_rand_generate(ossl_unused void *vdrbg,
58e1051a39Sopenharmony_ci                              unsigned char *out, size_t outlen,
59e1051a39Sopenharmony_ci                              ossl_unused unsigned int strength,
60e1051a39Sopenharmony_ci                              ossl_unused int prediction_resistance,
61e1051a39Sopenharmony_ci                              ossl_unused const unsigned char *adin,
62e1051a39Sopenharmony_ci                              ossl_unused size_t adinlen)
63e1051a39Sopenharmony_ci{
64e1051a39Sopenharmony_ci    unsigned char val = 1;
65e1051a39Sopenharmony_ci    size_t i;
66e1051a39Sopenharmony_ci
67e1051a39Sopenharmony_ci    for (i = 0; i < outlen; i++)
68e1051a39Sopenharmony_ci        out[i] = val++;
69e1051a39Sopenharmony_ci    return 1;
70e1051a39Sopenharmony_ci}
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_cistatic int fuzz_rand_enable_locking(ossl_unused void *vrng)
73e1051a39Sopenharmony_ci{
74e1051a39Sopenharmony_ci    return 1;
75e1051a39Sopenharmony_ci}
76e1051a39Sopenharmony_ci
77e1051a39Sopenharmony_cistatic int fuzz_rand_get_ctx_params(void *vrng, OSSL_PARAM params[])
78e1051a39Sopenharmony_ci{
79e1051a39Sopenharmony_ci    OSSL_PARAM *p;
80e1051a39Sopenharmony_ci
81e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
82e1051a39Sopenharmony_ci    if (p != NULL && !OSSL_PARAM_set_int(p, *(int *)vrng))
83e1051a39Sopenharmony_ci        return 0;
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
86e1051a39Sopenharmony_ci    if (p != NULL && !OSSL_PARAM_set_int(p, 500))
87e1051a39Sopenharmony_ci        return 0;
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
90e1051a39Sopenharmony_ci    if (p != NULL && !OSSL_PARAM_set_size_t(p, INT_MAX))
91e1051a39Sopenharmony_ci        return 0;
92e1051a39Sopenharmony_ci    return 1;
93e1051a39Sopenharmony_ci}
94e1051a39Sopenharmony_ci
95e1051a39Sopenharmony_cistatic const OSSL_PARAM *fuzz_rand_gettable_ctx_params(ossl_unused void *vrng,
96e1051a39Sopenharmony_ci                                                       ossl_unused void *provctx)
97e1051a39Sopenharmony_ci{
98e1051a39Sopenharmony_ci    static const OSSL_PARAM known_gettable_ctx_params[] = {
99e1051a39Sopenharmony_ci        OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL),
100e1051a39Sopenharmony_ci        OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
101e1051a39Sopenharmony_ci        OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
102e1051a39Sopenharmony_ci        OSSL_PARAM_END
103e1051a39Sopenharmony_ci    };
104e1051a39Sopenharmony_ci    return known_gettable_ctx_params;
105e1051a39Sopenharmony_ci}
106e1051a39Sopenharmony_ci
107e1051a39Sopenharmony_cistatic const OSSL_DISPATCH fuzz_rand_functions[] = {
108e1051a39Sopenharmony_ci    { OSSL_FUNC_RAND_NEWCTX, (void (*)(void))fuzz_rand_newctx },
109e1051a39Sopenharmony_ci    { OSSL_FUNC_RAND_FREECTX, (void (*)(void))fuzz_rand_freectx },
110e1051a39Sopenharmony_ci    { OSSL_FUNC_RAND_INSTANTIATE, (void (*)(void))fuzz_rand_instantiate },
111e1051a39Sopenharmony_ci    { OSSL_FUNC_RAND_UNINSTANTIATE, (void (*)(void))fuzz_rand_uninstantiate },
112e1051a39Sopenharmony_ci    { OSSL_FUNC_RAND_GENERATE, (void (*)(void))fuzz_rand_generate },
113e1051a39Sopenharmony_ci    { OSSL_FUNC_RAND_ENABLE_LOCKING, (void (*)(void))fuzz_rand_enable_locking },
114e1051a39Sopenharmony_ci    { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
115e1051a39Sopenharmony_ci      (void(*)(void))fuzz_rand_gettable_ctx_params },
116e1051a39Sopenharmony_ci    { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))fuzz_rand_get_ctx_params },
117e1051a39Sopenharmony_ci    { 0, NULL }
118e1051a39Sopenharmony_ci};
119e1051a39Sopenharmony_ci
120e1051a39Sopenharmony_cistatic const OSSL_ALGORITHM fuzz_rand_rand[] = {
121e1051a39Sopenharmony_ci    { "fuzz", "provider=fuzz-rand", fuzz_rand_functions },
122e1051a39Sopenharmony_ci    { NULL, NULL, NULL }
123e1051a39Sopenharmony_ci};
124e1051a39Sopenharmony_ci
125e1051a39Sopenharmony_cistatic const OSSL_ALGORITHM *fuzz_rand_query(void *provctx,
126e1051a39Sopenharmony_ci                                             int operation_id,
127e1051a39Sopenharmony_ci                                             int *no_cache)
128e1051a39Sopenharmony_ci{
129e1051a39Sopenharmony_ci    *no_cache = 0;
130e1051a39Sopenharmony_ci    switch (operation_id) {
131e1051a39Sopenharmony_ci    case OSSL_OP_RAND:
132e1051a39Sopenharmony_ci        return fuzz_rand_rand;
133e1051a39Sopenharmony_ci    }
134e1051a39Sopenharmony_ci    return NULL;
135e1051a39Sopenharmony_ci}
136e1051a39Sopenharmony_ci
137e1051a39Sopenharmony_ci/* Functions we provide to the core */
138e1051a39Sopenharmony_cistatic const OSSL_DISPATCH fuzz_rand_method[] = {
139e1051a39Sopenharmony_ci    { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free },
140e1051a39Sopenharmony_ci    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fuzz_rand_query },
141e1051a39Sopenharmony_ci    { 0, NULL }
142e1051a39Sopenharmony_ci};
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_cistatic int fuzz_rand_provider_init(const OSSL_CORE_HANDLE *handle,
145e1051a39Sopenharmony_ci                                   const OSSL_DISPATCH *in,
146e1051a39Sopenharmony_ci                                   const OSSL_DISPATCH **out, void **provctx)
147e1051a39Sopenharmony_ci{
148e1051a39Sopenharmony_ci    *provctx = OSSL_LIB_CTX_new();
149e1051a39Sopenharmony_ci    if (*provctx == NULL)
150e1051a39Sopenharmony_ci        return 0;
151e1051a39Sopenharmony_ci    *out = fuzz_rand_method;
152e1051a39Sopenharmony_ci    return 1;
153e1051a39Sopenharmony_ci}
154e1051a39Sopenharmony_ci
155e1051a39Sopenharmony_cistatic OSSL_PROVIDER *r_prov;
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_civoid FuzzerSetRand(void)
158e1051a39Sopenharmony_ci{
159e1051a39Sopenharmony_ci    if (!OSSL_PROVIDER_add_builtin(NULL, "fuzz-rand", fuzz_rand_provider_init)
160e1051a39Sopenharmony_ci        || !RAND_set_DRBG_type(NULL, "fuzz", NULL, NULL, NULL)
161e1051a39Sopenharmony_ci        || (r_prov = OSSL_PROVIDER_try_load(NULL, "fuzz-rand", 1)) == NULL)
162e1051a39Sopenharmony_ci        exit(1);
163e1051a39Sopenharmony_ci}
164e1051a39Sopenharmony_ci
165e1051a39Sopenharmony_civoid FuzzerClearRand(void)
166e1051a39Sopenharmony_ci{
167e1051a39Sopenharmony_ci    OSSL_PROVIDER_unload(r_prov);
168e1051a39Sopenharmony_ci}
169