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 "../include/crypto/evp.h" 16#include "../../crypto/evp/evp_local.h" 17#include "../testutil.h" 18 19typedef struct { 20 fake_random_generate_cb *cb; 21 int state; 22 const char *name; 23 EVP_RAND_CTX *ctx; 24} FAKE_RAND; 25 26static OSSL_FUNC_rand_newctx_fn fake_rand_newctx; 27static OSSL_FUNC_rand_freectx_fn fake_rand_freectx; 28static OSSL_FUNC_rand_instantiate_fn fake_rand_instantiate; 29static OSSL_FUNC_rand_uninstantiate_fn fake_rand_uninstantiate; 30static OSSL_FUNC_rand_generate_fn fake_rand_generate; 31static OSSL_FUNC_rand_gettable_ctx_params_fn fake_rand_gettable_ctx_params; 32static OSSL_FUNC_rand_get_ctx_params_fn fake_rand_get_ctx_params; 33static OSSL_FUNC_rand_enable_locking_fn fake_rand_enable_locking; 34 35static void *fake_rand_newctx(void *provctx, void *parent, 36 const OSSL_DISPATCH *parent_dispatch) 37{ 38 FAKE_RAND *r = OPENSSL_zalloc(sizeof(*r)); 39 40 if (r != NULL) 41 r->state = EVP_RAND_STATE_UNINITIALISED; 42 return r; 43} 44 45static void fake_rand_freectx(void *vrng) 46{ 47 OPENSSL_free(vrng); 48} 49 50static int fake_rand_instantiate(void *vrng, ossl_unused unsigned int strength, 51 ossl_unused int prediction_resistance, 52 ossl_unused const unsigned char *pstr, 53 size_t pstr_len, 54 ossl_unused const OSSL_PARAM params[]) 55{ 56 FAKE_RAND *frng = (FAKE_RAND *)vrng; 57 58 frng->state = EVP_RAND_STATE_READY; 59 return 1; 60} 61 62static int fake_rand_uninstantiate(void *vrng) 63{ 64 FAKE_RAND *frng = (FAKE_RAND *)vrng; 65 66 frng->state = EVP_RAND_STATE_UNINITIALISED; 67 return 1; 68} 69 70static int fake_rand_generate(void *vrng, unsigned char *out, size_t outlen, 71 unsigned int strength, int prediction_resistance, 72 const unsigned char *adin, size_t adinlen) 73{ 74 FAKE_RAND *frng = (FAKE_RAND *)vrng; 75 size_t l; 76 uint32_t r; 77 78 if (frng->cb != NULL) 79 return (*frng->cb)(out, outlen, frng->name, frng->ctx); 80 while (outlen > 0) { 81 r = test_random(); 82 l = outlen < sizeof(r) ? outlen : sizeof(r); 83 84 memcpy(out, &r, l); 85 out += l; 86 outlen -= l; 87 } 88 return 1; 89} 90 91static int fake_rand_enable_locking(void *vrng) 92{ 93 return 1; 94} 95 96static int fake_rand_get_ctx_params(ossl_unused void *vrng, OSSL_PARAM params[]) 97{ 98 FAKE_RAND *frng = (FAKE_RAND *)vrng; 99 OSSL_PARAM *p; 100 101 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE); 102 if (p != NULL && !OSSL_PARAM_set_int(p, frng->state)) 103 return 0; 104 105 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH); 106 if (p != NULL && !OSSL_PARAM_set_int(p, 256)) 107 return 0; 108 109 p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST); 110 if (p != NULL && !OSSL_PARAM_set_size_t(p, INT_MAX)) 111 return 0; 112 return 1; 113} 114 115static const OSSL_PARAM *fake_rand_gettable_ctx_params(ossl_unused void *vrng, 116 ossl_unused void *provctx) 117{ 118 static const OSSL_PARAM known_gettable_ctx_params[] = { 119 OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL), 120 OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), 121 OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), 122 OSSL_PARAM_END 123 }; 124 return known_gettable_ctx_params; 125} 126 127static const OSSL_DISPATCH fake_rand_functions[] = { 128 { OSSL_FUNC_RAND_NEWCTX, (void (*)(void))fake_rand_newctx }, 129 { OSSL_FUNC_RAND_FREECTX, (void (*)(void))fake_rand_freectx }, 130 { OSSL_FUNC_RAND_INSTANTIATE, (void (*)(void))fake_rand_instantiate }, 131 { OSSL_FUNC_RAND_UNINSTANTIATE, (void (*)(void))fake_rand_uninstantiate }, 132 { OSSL_FUNC_RAND_GENERATE, (void (*)(void))fake_rand_generate }, 133 { OSSL_FUNC_RAND_ENABLE_LOCKING, (void (*)(void))fake_rand_enable_locking }, 134 { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS, 135 (void(*)(void))fake_rand_gettable_ctx_params }, 136 { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))fake_rand_get_ctx_params }, 137 { 0, NULL } 138}; 139 140static const OSSL_ALGORITHM fake_rand_rand[] = { 141 { "FAKE", "provider=fake", fake_rand_functions }, 142 { NULL, NULL, NULL } 143}; 144 145static const OSSL_ALGORITHM *fake_rand_query(void *provctx, 146 int operation_id, 147 int *no_cache) 148{ 149 *no_cache = 0; 150 switch (operation_id) { 151 case OSSL_OP_RAND: 152 return fake_rand_rand; 153 } 154 return NULL; 155} 156 157/* Functions we provide to the core */ 158static const OSSL_DISPATCH fake_rand_method[] = { 159 { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free }, 160 { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fake_rand_query }, 161 { 0, NULL } 162}; 163 164static int fake_rand_provider_init(const OSSL_CORE_HANDLE *handle, 165 const OSSL_DISPATCH *in, 166 const OSSL_DISPATCH **out, void **provctx) 167{ 168 if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new())) 169 return 0; 170 *out = fake_rand_method; 171 return 1; 172} 173 174static int check_rng(EVP_RAND_CTX *rng, const char *name) 175{ 176 FAKE_RAND *f; 177 178 if (!TEST_ptr(rng)) { 179 TEST_info("random: %s", name); 180 return 0; 181 } 182 f = rng->algctx; 183 f->name = name; 184 f->ctx = rng; 185 return 1; 186} 187 188OSSL_PROVIDER *fake_rand_start(OSSL_LIB_CTX *libctx) 189{ 190 OSSL_PROVIDER *p; 191 192 if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, "fake-rand", 193 fake_rand_provider_init)) 194 || !TEST_true(RAND_set_DRBG_type(libctx, "fake", NULL, NULL, NULL)) 195 || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, "fake-rand", 1))) 196 return NULL; 197 198 /* Ensure that the fake rand is initialized. */ 199 if (!TEST_true(check_rng(RAND_get0_primary(libctx), "primary")) 200 || !TEST_true(check_rng(RAND_get0_private(libctx), "private")) 201 || !TEST_true(check_rng(RAND_get0_public(libctx), "public"))) { 202 OSSL_PROVIDER_unload(p); 203 return NULL; 204 } 205 206 return p; 207} 208 209void fake_rand_finish(OSSL_PROVIDER *p) 210{ 211 OSSL_PROVIDER_unload(p); 212} 213 214void fake_rand_set_callback(EVP_RAND_CTX *rng, 215 int (*cb)(unsigned char *out, size_t outlen, 216 const char *name, EVP_RAND_CTX *ctx)) 217{ 218 if (rng != NULL) 219 ((FAKE_RAND *)rng->algctx)->cb = cb; 220} 221 222void fake_rand_set_public_private_callbacks(OSSL_LIB_CTX *libctx, 223 int (*cb)(unsigned char *out, 224 size_t outlen, 225 const char *name, 226 EVP_RAND_CTX *ctx)) 227{ 228 fake_rand_set_callback(RAND_get0_private(libctx), cb); 229 fake_rand_set_callback(RAND_get0_public(libctx), cb); 230} 231 232