Merge pull request #4720 from dgarske/fips_compat

This commit is contained in:
Chris Conlon 2022-02-07 09:56:24 -07:00 committed by GitHub
commit 4c8f0709fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 386 additions and 7 deletions

196
src/ssl.c
View File

@ -89,6 +89,7 @@
#include <wolfssl/openssl/buffer.h>
#include <wolfssl/openssl/dh.h>
#include <wolfssl/openssl/rsa.h>
#include <wolfssl/openssl/fips_rand.h>
#ifndef WOLFCRYPT_ONLY
#include <wolfssl/openssl/pem.h>
#endif
@ -5308,14 +5309,18 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
#endif /* !NO_SESSION_CACHE */
#if defined(OPENSSL_EXTRA) || \
(defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA))
#if !defined(WC_NO_RNG) && (defined(OPENSSL_EXTRA) || \
(defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)))
#define HAVE_GLOBAL_RNG /* consolidate flags for using globalRNG */
static WC_RNG globalRNG;
static int initGlobalRNG = 0;
static wolfSSL_Mutex globalRNGMutex;
static int globalRNGMutex_valid = 0;
#if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG)
static WOLFSSL_DRBG_CTX* gDrbgDefCtx = NULL;
#endif
#endif
#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB)
@ -15082,7 +15087,13 @@ int wolfSSL_Cleanup(void)
ret = BAD_MUTEX_E;
}
globalRNGMutex_valid = 0;
#if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG)
wolfSSL_FIPS_drbg_free(gDrbgDefCtx);
gDrbgDefCtx = NULL;
#endif
#endif
return ret;
}
@ -63992,6 +64003,187 @@ int wolfSSL_PKCS12_verify_mac(WC_PKCS12 *pkcs12, const char *psw,
#endif /* !NO_CERTS */
/*******************************************************************************
* BEGIN OPENSSL FIPS DRBG APIs
******************************************************************************/
#if defined(OPENSSL_EXTRA) && !defined(WC_NO_RNG) && defined(HAVE_HASHDRBG)
int wolfSSL_FIPS_drbg_init(WOLFSSL_DRBG_CTX *ctx, int type, unsigned int flags)
{
int ret = WOLFSSL_FAILURE;
if (ctx != NULL) {
XMEMSET(ctx, 0, sizeof(WOLFSSL_DRBG_CTX));
ctx->type = type;
ctx->xflags = flags;
ctx->status = DRBG_STATUS_UNINITIALISED;
ret = WOLFSSL_SUCCESS;
}
return ret;
}
WOLFSSL_DRBG_CTX* wolfSSL_FIPS_drbg_new(int type, unsigned int flags)
{
int ret = WOLFSSL_FAILURE;
WOLFSSL_DRBG_CTX* ctx = (WOLFSSL_DRBG_CTX*)XMALLOC(sizeof(WOLFSSL_DRBG_CTX),
NULL, DYNAMIC_TYPE_OPENSSL);
ret = wolfSSL_FIPS_drbg_init(ctx, type, flags);
if (ret == WOLFSSL_SUCCESS && type != 0) {
ret = wolfSSL_FIPS_drbg_instantiate(ctx, NULL, 0);
}
if (ret != WOLFSSL_SUCCESS) {
WOLFSSL_ERROR(ret);
wolfSSL_FIPS_drbg_free(ctx);
ctx = NULL;
}
return ctx;
}
int wolfSSL_FIPS_drbg_instantiate(WOLFSSL_DRBG_CTX* ctx,
const unsigned char* pers, size_t perslen)
{
int ret = WOLFSSL_FAILURE;
if (ctx != NULL && ctx->rng == NULL) {
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS) && FIPS_VERSION_GE(5,0)))
ctx->rng = wc_rng_new((byte*)pers, (word32)perslen, NULL);
#else
ctx->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
if (ctx->rng != NULL) {
#if defined(HAVE_FIPS) && FIPS_VERSION_GE(2,0)
ret = wc_InitRngNonce(ctx->rng, (byte*)pers, (word32)perslen);
#else
ret = wc_InitRng(ctx->rng);
(void)pers;
(void)perslen;
#endif
if (ret != 0) {
WOLFSSL_ERROR(ret);
XFREE(ctx->rng, NULL, DYNAMIC_TYPE_RNG);
ctx->rng = NULL;
}
}
#endif
}
if (ctx != NULL && ctx->rng != NULL) {
ctx->status = DRBG_STATUS_READY;
ret = WOLFSSL_SUCCESS;
}
return ret;
}
int wolfSSL_FIPS_drbg_set_callbacks(WOLFSSL_DRBG_CTX* ctx,
drbg_entropy_get entropy_get, drbg_entropy_clean entropy_clean,
size_t entropy_blocklen,
drbg_nonce_get none_get, drbg_nonce_clean nonce_clean)
{
int ret = WOLFSSL_FAILURE;
if (ctx != NULL) {
ctx->entropy_get = entropy_get;
ctx->entropy_clean = entropy_clean;
ctx->entropy_blocklen = entropy_blocklen;
ctx->none_get = none_get;
ctx->nonce_clean = nonce_clean;
ret = WOLFSSL_SUCCESS;
}
return ret;
}
void wolfSSL_FIPS_rand_add(const void* buf, int num, double entropy)
{
/* not implemented */
(void)buf;
(void)num;
(void)entropy;
}
int wolfSSL_FIPS_drbg_reseed(WOLFSSL_DRBG_CTX* ctx, const unsigned char* adin,
size_t adinlen)
{
int ret = WOLFSSL_FAILURE;
if (ctx != NULL && ctx->rng != NULL) {
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS) && FIPS_VERSION_GE(2,0)))
if (wc_RNG_DRBG_Reseed(ctx->rng, adin, (word32)adinlen) == 0) {
ret = WOLFSSL_SUCCESS;
}
#else
ret = WOLFSSL_SUCCESS;
(void)adin;
(void)adinlen;
#endif
}
return ret;
}
int wolfSSL_FIPS_drbg_generate(WOLFSSL_DRBG_CTX* ctx, unsigned char* out,
size_t outlen, int prediction_resistance, const unsigned char* adin,
size_t adinlen)
{
int ret = WOLFSSL_FAILURE;
if (ctx != NULL && ctx->rng != NULL) {
ret = wc_RNG_GenerateBlock(ctx->rng, out, (word32)outlen);
if (ret == 0) {
ret = WOLFSSL_SUCCESS;
}
}
(void)prediction_resistance;
(void)adin;
(void)adinlen;
return ret;
}
int wolfSSL_FIPS_drbg_uninstantiate(WOLFSSL_DRBG_CTX *ctx)
{
if (ctx != NULL && ctx->rng != NULL) {
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS) && FIPS_VERSION_GE(5,0)))
wc_rng_free(ctx->rng);
#else
wc_FreeRng(ctx->rng);
XFREE(ctx->rng, NULL, DYNAMIC_TYPE_RNG);
#endif
ctx->rng = NULL;
ctx->status = DRBG_STATUS_UNINITIALISED;
}
return WOLFSSL_SUCCESS;
}
void wolfSSL_FIPS_drbg_free(WOLFSSL_DRBG_CTX *ctx)
{
if (ctx != NULL) {
/* As saftey check if free'ing the default drbg, then mark global NULL.
* Technically the user should not call free on the default drbg. */
if (ctx == gDrbgDefCtx) {
gDrbgDefCtx = NULL;
}
wolfSSL_FIPS_drbg_uninstantiate(ctx);
XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
}
}
WOLFSSL_DRBG_CTX* wolfSSL_FIPS_get_default_drbg(void)
{
if (gDrbgDefCtx == NULL) {
gDrbgDefCtx = wolfSSL_FIPS_drbg_new(0, 0);
}
return gDrbgDefCtx;
}
void wolfSSL_FIPS_get_timevec(unsigned char* buf, unsigned long* pctr)
{
/* not implemented */
(void)buf;
(void)pctr;
}
void* wolfSSL_FIPS_drbg_get_app_data(WOLFSSL_DRBG_CTX *ctx)
{
if (ctx != NULL) {
return ctx->app_data;
}
return NULL;
}
void wolfSSL_FIPS_drbg_set_app_data(WOLFSSL_DRBG_CTX *ctx, void *app_data)
{
if (ctx != NULL) {
ctx->app_data = app_data;
}
}
#endif
/*******************************************************************************
* END OF OPENSSL FIPS DRBG APIs
******************************************************************************/
#endif /* !WOLFCRYPT_ONLY */
/*******************************************************************************

View File

@ -303,6 +303,7 @@
#include <wolfssl/openssl/objects.h>
#include <wolfssl/openssl/rand.h>
#include <wolfssl/openssl/modes.h>
#include <wolfssl/openssl/fips_rand.h>
#ifdef OPENSSL_ALL
#include <wolfssl/openssl/txt_db.h>
#include <wolfssl/openssl/lhash.h>
@ -52031,6 +52032,45 @@ static void test_wolfSSL_CTX_StaticMemory(void)
#endif
}
static void test_openssl_FIPS_drbg(void)
{
#if defined(OPENSSL_EXTRA) && !defined(WC_NO_RNG) && defined(HAVE_HASHDRBG)
DRBG_CTX* dctx;
byte data1[32], data2[32], zeroData[32];
byte testSeed[16];
size_t dlen = sizeof(data1);
int i;
XMEMSET(data1, 0, dlen);
XMEMSET(data2, 0, dlen);
XMEMSET(zeroData, 0, sizeof(zeroData));
for (i=0; i<(int)sizeof(testSeed); i++) {
testSeed[i] = (byte)i;
}
printf(testingFmt, "test_openssl_FIPS_drbg()");
AssertNotNull(dctx = FIPS_get_default_drbg());
AssertIntEQ(FIPS_drbg_init(dctx, 0, 0), WOLFSSL_SUCCESS);
AssertIntEQ(FIPS_drbg_set_callbacks(dctx, NULL, NULL, 20, NULL, NULL),
WOLFSSL_SUCCESS);
AssertIntEQ(FIPS_drbg_instantiate(dctx, NULL, 0), WOLFSSL_SUCCESS);
AssertIntEQ(FIPS_drbg_generate(dctx, data1, dlen, 0, NULL, 0),
WOLFSSL_SUCCESS);
AssertIntNE(XMEMCMP(data1, zeroData, dlen), 0);
AssertIntEQ(FIPS_drbg_reseed(dctx, testSeed, sizeof(testSeed)),
WOLFSSL_SUCCESS);
AssertIntEQ(FIPS_drbg_generate(dctx, data2, dlen, 0, NULL, 0),
WOLFSSL_SUCCESS);
AssertIntNE(XMEMCMP(data1, zeroData, dlen), 0);
AssertIntNE(XMEMCMP(data1, data2, dlen), 0);
AssertIntEQ(FIPS_drbg_uninstantiate(dctx), WOLFSSL_SUCCESS);
printf(resultFmt, passed);
#endif
}
/*----------------------------------------------------------------------------*
@ -52888,11 +52928,9 @@ void ApiTest(void)
test_wc_PKCS7_SetOriEncryptCtx();
test_wc_PKCS7_SetOriDecryptCtx();
test_wc_PKCS7_DecodeCompressedData();
test_wc_i2d_PKCS12();
test_wolfSSL_CTX_LoadCRL();
test_openssl_FIPS_drbg();
test_wc_CryptoCb();
test_wolfSSL_CTX_StaticMemory();

View File

@ -430,6 +430,10 @@ static int Hash_DRBG_Reseed(DRBG_internal* drbg, const byte* seed, word32 seedSz
{
byte newV[DRBG_SEED_LEN];
if (drbg == NULL) {
return DRBG_FAILURE;
}
XMEMSET(newV, 0, DRBG_SEED_LEN);
if (Hash_df(drbg, newV, sizeof(newV), drbgReseed,
@ -458,6 +462,16 @@ int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz)
return BAD_FUNC_ARG;
}
if (rng->drbg == NULL) {
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
if (IS_INTEL_RDRAND(intel_flags)) {
/* using RDRAND not DRBG, so return success */
return 0;
}
return BAD_FUNC_ARG;
#endif
}
return Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, seed, seedSz);
}
@ -597,6 +611,10 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz)
byte type;
word32 reseedCtr;
if (drbg == NULL) {
return DRBG_FAILURE;
}
if (drbg->reseedCtr == RESEED_INTERVAL) {
return DRBG_NEED_RESEED;
} else {
@ -1008,8 +1026,8 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
if (ret == DRBG_SUCCESS)
ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, newSeed + SEED_BLOCK_SZ,
SEED_SZ);
ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg,
newSeed + SEED_BLOCK_SZ, SEED_SZ);
if (ret == DRBG_SUCCESS)
ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz);

View File

@ -232,6 +232,11 @@ enum {
NID_md4 = 257,
NID_md5 = 40,
NID_hmac = 855,
NID_hmacWithSHA1 = 163,
NID_hmacWithSHA224 = 798,
NID_hmacWithSHA256 = 799,
NID_hmacWithSHA384 = 800,
NID_hmacWithSHA512 = 801,
NID_cmac = 894,
NID_dhKeyAgreement= 28,
NID_rc4 = 5,

125
wolfssl/openssl/fips_rand.h Normal file
View File

@ -0,0 +1,125 @@
/* fips_rand.h
*
* Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* fips_rand.h for openSSL compatibility */
#ifndef WOLFSSL_OPENSSL_FIPS_RAND_H_
#define WOLFSSL_OPENSSL_FIPS_RAND_H_
#include <wolfssl/openssl/ssl.h>
#include <wolfssl/wolfcrypt/random.h>
#if !defined(WC_NO_RNG) && defined(HAVE_HASHDRBG)
struct WOLFSSL_DRBG_CTX;
typedef size_t (*drbg_entropy_get)(struct WOLFSSL_DRBG_CTX* ctx, unsigned char** pout,
int entropy, size_t min_len, size_t max_len);
typedef void (*drbg_entropy_clean)(struct WOLFSSL_DRBG_CTX* ctx, unsigned char* out,
size_t olen);
typedef size_t (*drbg_nonce_get)(struct WOLFSSL_DRBG_CTX* ctx, unsigned char** pout,
int entropy, size_t min_len, size_t max_len);
typedef void (*drbg_nonce_clean)(struct WOLFSSL_DRBG_CTX* ctx, unsigned char* out,
size_t olen);
typedef struct WOLFSSL_DRBG_CTX {
WC_RNG* rng;
drbg_entropy_get entropy_get;
drbg_entropy_clean entropy_clean;
size_t entropy_blocklen;
drbg_nonce_get none_get;
drbg_nonce_clean nonce_clean;
int type;
int status;
int xflags;
void* app_data;
} WOLFSSL_DRBG_CTX;
#define DRBG_FLAG_CTR_USE_DF 0x1
#define DRBG_FLAG_TEST 0x2
#define DRBG_FLAG_NOERR 0x1
#define DRBG_CUSTOM_RESEED 0x2
#define DRBG_STATUS_UNINITIALISED 0
#define DRBG_STATUS_READY 1
#define DRBG_STATUS_RESEED 2
#define DRBG_STATUS_ERROR 3
WOLFSSL_API WOLFSSL_DRBG_CTX* wolfSSL_FIPS_drbg_new(int type,
unsigned int flags);
WOLFSSL_API int wolfSSL_FIPS_drbg_init(WOLFSSL_DRBG_CTX *ctx,
int type, unsigned int flags);
WOLFSSL_API int wolfSSL_FIPS_drbg_instantiate(WOLFSSL_DRBG_CTX* ctx,
const unsigned char* pers, size_t perslen);
WOLFSSL_API int wolfSSL_FIPS_drbg_set_callbacks(WOLFSSL_DRBG_CTX* ctx,
drbg_entropy_get entropy_get, drbg_entropy_clean entropy_clean,
size_t entropy_blocklen,
drbg_nonce_get none_get, drbg_nonce_clean nonce_clean);
WOLFSSL_API void wolfSSL_FIPS_rand_add(const void* buf, int num,
double entropy);
WOLFSSL_API int wolfSSL_FIPS_drbg_reseed(WOLFSSL_DRBG_CTX* ctx,
const unsigned char* adin, size_t adinlen);
WOLFSSL_API int wolfSSL_FIPS_drbg_generate(WOLFSSL_DRBG_CTX* ctx,
unsigned char* out, size_t outlen, int prediction_resistance,
const unsigned char* adin, size_t adinlen);
WOLFSSL_API int wolfSSL_FIPS_drbg_uninstantiate(WOLFSSL_DRBG_CTX *ctx);
WOLFSSL_API void wolfSSL_FIPS_drbg_free(WOLFSSL_DRBG_CTX *ctx);
WOLFSSL_API WOLFSSL_DRBG_CTX* wolfSSL_FIPS_get_default_drbg(void);
WOLFSSL_API void wolfSSL_FIPS_get_timevec(unsigned char* buf,
unsigned long* pctr);
WOLFSSL_API void* wolfSSL_FIPS_drbg_get_app_data(WOLFSSL_DRBG_CTX *ctx);
WOLFSSL_API void wolfSSL_FIPS_drbg_set_app_data(WOLFSSL_DRBG_CTX *ctx,
void *app_data);
/* compatibility mapping */
typedef WOLFSSL_DRBG_CTX DRBG_CTX;
#define FIPS_drbg_init wolfSSL_FIPS_drbg_init
#define FIPS_drbg_new wolfSSL_FIPS_drbg_new
#define FIPS_drbg_instantiate wolfSSL_FIPS_drbg_instantiate
#define FIPS_drbg_set_callbacks wolfSSL_FIPS_drbg_set_callbacks
#define FIPS_rand_add wolfSSL_FIPS_rand_add
#define FIPS_drbg_reseed wolfSSL_FIPS_drbg_reseed
#define FIPS_drbg_generate wolfSSL_FIPS_drbg_generate
#define FIPS_drbg_uninstantiate wolfSSL_FIPS_drbg_uninstantiate
#define FIPS_drbg_free wolfSSL_FIPS_drbg_free
#define FIPS_get_default_drbg wolfSSL_FIPS_get_default_drbg
#define FIPS_get_timevec wolfSSL_FIPS_get_timevec
#define FIPS_drbg_get_app_data wolfSSL_FIPS_drbg_get_app_data
#define FIPS_drbg_set_app_data wolfSSL_FIPS_drbg_set_app_data
#endif /* !WC_NO_RNG && HAVE_HASHDRBG */
#endif /* WOLFSSL_OPENSSL_FIPS_RAND_H_ */

View File

@ -27,6 +27,7 @@ nobase_include_HEADERS+= \
wolfssl/openssl/engine.h \
wolfssl/openssl/err.h \
wolfssl/openssl/evp.h \
wolfssl/openssl/fips_rand.h \
wolfssl/openssl/hmac.h \
wolfssl/openssl/lhash.h \
wolfssl/openssl/md4.h \