diff --git a/src/ssl.c b/src/ssl.c index c37b72572..373eb7d19 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -89,6 +89,7 @@ #include #include #include + #include #ifndef WOLFCRYPT_ONLY #include #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 */ /******************************************************************************* diff --git a/tests/api.c b/tests/api.c index 2cabd2a7a..c7f930d22 100644 --- a/tests/api.c +++ b/tests/api.c @@ -303,6 +303,7 @@ #include #include #include + #include #ifdef OPENSSL_ALL #include #include @@ -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(); diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 724e86a8c..35ee476bf 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -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); diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index e6b043d3b..bed43f0ec 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -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, diff --git a/wolfssl/openssl/fips_rand.h b/wolfssl/openssl/fips_rand.h new file mode 100644 index 000000000..d6b2f021d --- /dev/null +++ b/wolfssl/openssl/fips_rand.h @@ -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 +#include + +#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_ */ diff --git a/wolfssl/openssl/include.am b/wolfssl/openssl/include.am index e4ae651cd..8f224e323 100644 --- a/wolfssl/openssl/include.am +++ b/wolfssl/openssl/include.am @@ -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 \