我想在 openssl v3 中使用我的种子提供程序。我实现了提供程序,但 api 只允许使用“EVP_RAND_generate”函数。
我想将我的种子提供程序注入 openssl 默认值中。当我使用“RAND_bytes”时,它必须使用我的种子提供程序。
我该怎么做?
#include <openssl/rand.h>
#include <openssl/core_dispatch.h>
#include <openssl/e_os2.h>
#include <openssl/params.h>
#include <openssl/core_names.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/randerr.h>
#include <openssl/proverr.h>
#include <openssl/provider.h>
#include <cstring>
#include <unistd.h>
const int RandomNumberBlockSize = 32;
const int OsslRandStrength = 1024;
const int OsslRandMaxRequest = 128;
OSSL_FUNC_rand_newctx_fn seedSrcNew;
OSSL_FUNC_rand_freectx_fn seedSrcFree;
OSSL_FUNC_rand_instantiate_fn seedSrcInstantiate;
OSSL_FUNC_rand_uninstantiate_fn seedSrcUninstantiate;
OSSL_FUNC_rand_generate_fn seedSrcGenerate;
OSSL_FUNC_rand_reseed_fn seedSrcReseed;
OSSL_FUNC_rand_gettable_ctx_params_fn seedSrcGettableCtxParams;
OSSL_FUNC_rand_get_ctx_params_fn seedSrcGetCtxParams;
OSSL_FUNC_rand_verify_zeroization_fn seedSrcVerifyZeroization;
OSSL_FUNC_rand_enable_locking_fn seedSrcEnableLocking;
OSSL_FUNC_rand_lock_fn seedSrcLock;
OSSL_FUNC_rand_unlock_fn seedSrcUnlock;
OSSL_FUNC_rand_get_seed_fn seedGetSeed;
OSSL_FUNC_rand_clear_seed_fn seedClearSeed;
typedef struct {
void* provCtx;
int state;
} ProvSeedSrc;
void* seedSrcNew(void* provCtx, void* parent, const OSSL_DISPATCH*)
{
printf("TRNG-SEED: seedSrcNew\n");
ProvSeedSrc *seedSrc;
if (parent != nullptr) {
ERR_raise(ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT);
return nullptr;
}
seedSrc = reinterpret_cast<ProvSeedSrc*>(OPENSSL_zalloc(sizeof(*seedSrc)));
if (!seedSrc) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return nullptr;
}
seedSrc->provCtx = provCtx;
seedSrc->state = EVP_RAND_STATE_UNINITIALISED;
return seedSrc;
}
void seedSrcFree(void* seed)
{
printf("TRNG-SEED: seedSrcFree\n");
OPENSSL_free(seed);
}
int seedSrcInstantiate(void* seed, unsigned int, int, const unsigned char*, size_t, ossl_unused const OSSL_PARAM[])
{
printf("TRNG-SEED: seedSrcInstantiate\n");
ProvSeedSrc *seedSrc = (ProvSeedSrc*)seed;
seedSrc->state = EVP_RAND_STATE_READY;
return 1;
}
int seedSrcUninstantiate(void* seed)
{
printf("TRNG-SEED: seedSrcUninstantiate\n");
ProvSeedSrc *seedSrc = (ProvSeedSrc*)seed;
seedSrc->state = EVP_RAND_STATE_UNINITIALISED;
return 1;
}
int seedSrcGenerate(void* seed, unsigned char* out, size_t outlen, unsigned int strength, ossl_unused int predictionResistance, ossl_unused const unsigned char* adin, ossl_unused size_t adinLength)
{
printf("TRNG-SEED: seedSrcGenerate - %d\n", outlen);
srand(time(nullptr));
for (size_t i = 0; i < outlen; i++)
out[i] = rand() % 255;
return 1;
}
int seedSrcReseed(void* seed, ossl_unused int, ossl_unused const unsigned char*, ossl_unused size_t, ossl_unused const unsigned char*, ossl_unused size_t)
{
printf("TRNG-SEED: seedSrcReseed\n");
ProvSeedSrc *seedSrc = (ProvSeedSrc*)seed;
if (seedSrc->state != EVP_RAND_STATE_READY) {
ERR_raise(ERR_LIB_PROV, seedSrc->state == EVP_RAND_STATE_ERROR ? PROV_R_IN_ERROR_STATE : PROV_R_NOT_INSTANTIATED);
return 0;
}
return 1;
}
int seedSrcGetCtxParams(void* seed, OSSL_PARAM params[])
{
// printf("TRNG-SEED: seedSrcGetCtxParams\n");
ProvSeedSrc *seedSrc = (ProvSeedSrc*)seed;
OSSL_PARAM* p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
if (p != nullptr && !OSSL_PARAM_set_int(p, seedSrc->state))
return 0;
p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
if (p != nullptr && !OSSL_PARAM_set_int(p, OsslRandStrength))
return 0;
p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
if (p != nullptr && !OSSL_PARAM_set_size_t(p, OsslRandMaxRequest))
return 0;
return 1;
}
const OSSL_PARAM *seedSrcGettableCtxParams(ossl_unused void* seed, ossl_unused void*)
{
printf("TRNG-SEED: seedSrcGettableCtxParams\n");
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, nullptr),
OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, nullptr),
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, nullptr),
OSSL_PARAM_END
};
return known_gettable_ctx_params;
}
int seedSrcVerifyZeroization(ossl_unused void* seed)
{
printf("TRNG-SEED: seedSrcVerifyZeroization\n");
return 1;
}
size_t seedGetSeed(void* seed, unsigned char** pout, int entropy, size_t minLength, size_t maxLength, int predictionResistance, const unsigned char* adin, size_t adinLength)
{
printf("TRNG-SEED: seedGetSeed\n");
size_t bytesNeeded;
unsigned char *buffer;
bytesNeeded = entropy >= 0 ? (entropy + 7) / 8 : 0;
if (bytesNeeded < minLength)
bytesNeeded = minLength;
if (bytesNeeded > maxLength) {
ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK);
return 0;
}
buffer = reinterpret_cast<unsigned char *>(OPENSSL_secure_malloc(bytesNeeded));
if (!buffer) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
if (seedSrcGenerate(seed, buffer, bytesNeeded, 0, predictionResistance, adin, adinLength) != 0) {
*pout = buffer;
return bytesNeeded;
}
OPENSSL_secure_clear_free(buffer, bytesNeeded);
return 0;
}
void seedClearSeed(ossl_unused void*, unsigned char* out, size_t outlen)
{
printf("TRNG-SEED: seedClearSeed\n");
OPENSSL_secure_clear_free(out, outlen);
}
int seedSrcEnableLocking(ossl_unused void*)
{
printf("TRNG-SEED: seedSrcEnableLocking\n");
return 1;
}
int seedSrcLock(ossl_unused void*)
{
printf("TRNG-SEED: seedSrcLock\n");
return 1;
}
void seedSrcUnlock(ossl_unused void*)
{
printf("TRNG-SEED: seedSrcUnlock\n");
}
const OSSL_DISPATCH seedSrcFunctions[] = {
{ OSSL_FUNC_RAND_NEWCTX, (void(*)(void))seedSrcNew },
{ OSSL_FUNC_RAND_FREECTX, (void(*)(void))seedSrcFree },
{ OSSL_FUNC_RAND_INSTANTIATE, (void(*)(void))seedSrcInstantiate },
{ OSSL_FUNC_RAND_UNINSTANTIATE, (void(*)(void))seedSrcUninstantiate },
{ OSSL_FUNC_RAND_GENERATE, (void(*)(void))seedSrcGenerate },
{ OSSL_FUNC_RAND_RESEED, (void(*)(void))seedSrcReseed },
// { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))seedSrcEnableLocking },
// { OSSL_FUNC_RAND_LOCK, (void(*)(void))seedSrcLock },
// { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))seedSrcUnlock },
{ OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS, (void(*)(void))seedSrcGettableCtxParams },
{ OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))seedSrcGetCtxParams },
{ OSSL_FUNC_RAND_VERIFY_ZEROIZATION, (void(*)(void))seedSrcVerifyZeroization },
{ OSSL_FUNC_RAND_GET_SEED, (void(*)(void))seedGetSeed },
{ OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))seedClearSeed },
{ 0, nullptr }
};
const OSSL_ALGORITHM seedProviderAlgorithm[] = {
{ "TRNG-SEED", "provider=trng-seed", seedSrcFunctions },
{ nullptr, nullptr, nullptr }
};
const OSSL_ALGORITHM* seedProviderOperation(void* provCtx, int operationId, int* noCache)
{
printf("TRNG-SEED: seedProviderOperation\n");
*noCache = 0;
switch (operationId) {
case OSSL_OP_RAND:
return seedProviderAlgorithm;
}
return nullptr;
}
/* The function that tears down this provider */
void seedTeardown(void *provCtx)
{
printf("TRNG-SEED: seedTeardown\n");
seedSrcFree(provCtx);
}
/* The base dispatch table */
const OSSL_DISPATCH providerFunctions[] = {
{ OSSL_FUNC_PROVIDER_TEARDOWN, (void(*)(void))seedTeardown },
{ OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void(*)(void))seedProviderOperation },
{ 0, nullptr }
};
int seedProviderInit(const OSSL_CORE_HANDLE*, const OSSL_DISPATCH* in, const OSSL_DISPATCH** out, void** provCtx)
{
if ((*provCtx = seedSrcNew(provCtx, nullptr, in)) == nullptr)
return 0;
printf("TRNG-SEED: Seed source trng is initialized successfully\n");
*out = providerFunctions;
return 1;
}
int main(){
const char* name = "trng-seed";
OSSL_LIB_CTX* ctx = OSSL_LIB_CTX_new();
OSSL_PROVIDER_add_builtin(ctx, name, seedProviderInit);
//RAND_set_seed_source_type(ctx, "fake", nullptr);
OSSL_PROVIDER* seedProvider = OSSL_PROVIDER_load(ctx, name);
if(seedProvider == nullptr){
printf("TRNG-SEED: DRBG set trng seed provider error\n");
return 0;
}
if(OSSL_PROVIDER_available(ctx, name) != 1){
printf("TRNG-SEED: DRBG trng seed provider is not available\n");
return 0;
}
if(OSSL_PROVIDER_self_test(seedProvider) != 1){
printf("TRNG-SEED: DRBG trng seed provider selftest failed\n");
return 0;
}
/* Create a seed source */
EVP_RAND* rand = EVP_RAND_fetch(ctx, name, nullptr);
EVP_RAND_CTX* seed = EVP_RAND_CTX_new(rand, nullptr);
EVP_RAND_free(rand);
/* Feed this into a DRBG */
rand = EVP_RAND_fetch(nullptr, "CTR-DRBG", nullptr);
EVP_RAND_CTX* rctx = EVP_RAND_CTX_new(rand, seed);
EVP_RAND_free(rand);
OSSL_PARAM params[2], *p = params;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, SN_aes_256_ctr, 0);
*p = OSSL_PARAM_construct_end();
unsigned int strength = 128;
EVP_RAND_instantiate(rctx, strength, 0, nullptr, 0, params);
uint8_t bytes[1000000];
EVP_RAND* rand2 = EVP_RAND_fetch(ctx, name, nullptr);
const OSSL_PROVIDER* prov = EVP_RAND_get0_provider(rand2);
// char provName[100];
// const char* pProvName = provName;
// pProvName = OSSL_PROVIDER_get0_name(prov);
// printf("Provider Name: %s\n", pProvName);
while(1){
RAND_bytes(bytes, sizeof(bytes));
//RAND_priv_bytes(bytes, sizeof(bytes));
//EVP_RAND_generate(rctx, bytes, sizeof(bytes), 0, 0, nullptr, 0);
//sleep(1);
}
// std::cout << "Random bytes: ";
// for(auto byte : bytes)
// std::cout << std::hex << std::setfill('0') << std::setw(2) << (unsigned)byte;
// std::cout << "\n");
EVP_RAND_CTX_free(seed);
EVP_RAND_CTX_free(rctx);
OSSL_PROVIDER_unload(seedProvider);
return 0;
}
如果我使用“EVP_RAND_generate”,我可以使用我的种子提供商。
默认种子源的名称可以通过
RAND_set_seed_source_type
函数设置:
https://www.openssl.org/docs/man3.2/man3/RAND_set_seed_source_type.html
如果您的应用程序调用此函数并指定类型为“TRNG-SEED”实现,则 OpenSSL 将使用它而不是默认实现。
默认实现称为“SEED-SRC”,因此另一种方法是将您的实现也称为“SEED-SRC”,并确保您的提供程序实现通过全局属性优先于默认实现使用,例如通过将全局属性设置为“?provider=myprov”,OpenSSL 将优先选择“myprov”提供商的实现,而不是其他任何地方的实现(“?”表示偏好)。