如何设置我的种子提供程序 openssl 默认值?

问题描述 投票:0回答:1

我想在 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”,我可以使用我的种子提供商。

openssl random-seed
1个回答
0
投票

默认种子源的名称可以通过

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”提供商的实现,而不是其他任何地方的实现(“?”表示偏好)。

© www.soinside.com 2019 - 2024. All rights reserved.