Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion include/wolfprovider/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,44 @@ int wp_provctx_lock_rng(WOLFPROV_CTX* provCtx);
void wp_provctx_unlock_rng(WOLFPROV_CTX* provCtx);

#ifdef HAVE_FIPS
wolfSSL_Mutex *wp_get_cast_mutex(void);
/* CAST self-test algorithm categories */
#define WP_CAST_ALGO_AES 0
#define WP_CAST_ALGO_HMAC 1
#define WP_CAST_ALGO_DRBG 2
#define WP_CAST_ALGO_RSA 3
#define WP_CAST_ALGO_ECDSA 4
#define WP_CAST_ALGO_ECDH 5
#define WP_CAST_ALGO_DH 6
#define WP_CAST_ALGO_COUNT 7

int wp_init_cast(int algo);

/**
* Check FIPS CAST for algorithm. Returns 0 on failure.
* Use at function entry points that return int (1=success, 0=failure).
*/
#define WP_CHECK_FIPS_ALGO(algo) \
do { \
if (wp_init_cast(algo) != 1) { \
return 0; \
} \
} while (0)

/**
* Check FIPS CAST for algorithm. Returns NULL on failure.
* Use at function entry points that return pointers (NULL=failure).
*/
#define WP_CHECK_FIPS_ALGO_PTR(algo) \
do { \
if (wp_init_cast(algo) != 1) { \
return NULL; \
} \
} while (0)

#else
/* Non-FIPS: no-op */
#define WP_CHECK_FIPS_ALGO(algo) do { } while (0)
#define WP_CHECK_FIPS_ALGO_PTR(algo) do { } while (0)
#endif
#endif

Expand Down
3 changes: 3 additions & 0 deletions include/wolfprovider/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@
#define WP_HAVE_GMAC
#endif

#ifndef NO_AES
#define WP_HAVE_AES
#endif
#ifdef HAVE_AES_ECB
#define WP_HAVE_AESECB
#endif
Expand Down
9 changes: 9 additions & 0 deletions src/wp_aes_aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,9 @@ static int wp_aesgcm_einit(wp_AeadCtx* ctx, const unsigned char *key,
if (!wolfssl_prov_is_running()) {
ok = 0;
}
if (ok) {
WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_AES);
}
#ifdef WOLFSSL_AESGCM_STREAM
if (ok) {
int rc;
Expand Down Expand Up @@ -1108,6 +1111,9 @@ static int wp_aesgcm_dinit(wp_AeadCtx *ctx, const unsigned char *key,
if (!wolfssl_prov_is_running()) {
ok = 0;
}
if (ok) {
WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_AES);
}
#ifdef WOLFSSL_AESGCM_STREAM
if (ok && key != NULL) {
int rc = wc_AesGcmDecryptInit(aes, key, (word32)keyLen, iv, (word32)ivLen);
Expand Down Expand Up @@ -1754,6 +1760,9 @@ static int wp_aesccm_init(wp_AeadCtx* ctx, const unsigned char *key,
if (!wolfssl_prov_is_running()) {
ok = 0;
}
if (ok) {
WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_AES);
}
if (ok && (key != NULL)) {
rc = wc_AesCcmSetKey(&ctx->aes, key, (word32)keyLen);
if (rc != 0) {
Expand Down
4 changes: 3 additions & 1 deletion src/wp_aes_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,9 @@ static int wp_aes_block_init(wp_AesBlockCtx *ctx, const unsigned char *key,
ok = 0;
}
if (ok) {
int rc = wc_AesSetKey(&ctx->aes, key, (word32)ctx->keyLen, ctx->iv,
int rc;
WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_AES);
rc = wc_AesSetKey(&ctx->aes, key, (word32)ctx->keyLen, ctx->iv,
enc ? AES_ENCRYPTION : AES_DECRYPTION);
if (rc != 0) {
WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_LEVEL_DEBUG, "wc_AesSetKey", rc);
Expand Down
4 changes: 3 additions & 1 deletion src/wp_aes_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,12 +314,14 @@ static int wp_aes_stream_init(wp_AesStreamCtx *ctx, const unsigned char *key,
ok = 0;
}
if (ok) {
int rc;
#if defined(WP_HAVE_AESCTS)
if (ctx->mode == EVP_CIPH_CBC_MODE && !enc) {
dir = AES_DECRYPTION;
}
#endif
int rc = wc_AesSetKey(&ctx->aes, key, (word32)ctx->keyLen, iv,
WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_AES);
rc = wc_AesSetKey(&ctx->aes, key, (word32)ctx->keyLen, iv,
dir);
if (rc != 0) {
WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_LEVEL_DEBUG, "wc_AesSetKey", rc);
Expand Down
4 changes: 3 additions & 1 deletion src/wp_aes_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,9 @@ static int wp_aes_wrap_init(wp_AesWrapCtx *ctx, const unsigned char *key,
}
if (ok) {
#if LIBWOLFSSL_VERSION_HEX >= 0x05000000
int rc = wc_AesSetKey(&ctx->aes, key, (word32)ctx->keyLen, iv,
int rc;
WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_AES);
rc = wc_AesSetKey(&ctx->aes, key, (word32)ctx->keyLen, iv,
wrap ? AES_ENCRYPTION : AES_DECRYPTION);
if (rc != 0) {
WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_LEVEL_DEBUG, "wc_AesSetKey", rc);
Expand Down
9 changes: 9 additions & 0 deletions src/wp_dh_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,9 @@ static int wp_dh_import(wp_Dh* dh, int selection, const OSSL_PARAM params[])
if (!wolfssl_prov_is_running()) {
ok = 0;
}
if (ok) {
WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_DH);
}
if (ok && (dh == NULL)) {
ok = 0;
}
Expand Down Expand Up @@ -1832,6 +1835,8 @@ static wp_Dh* wp_dh_gen(wp_DhGenCtx *ctx, OSSL_CALLBACK *cb, void *cbArg)
(void)cb;
(void)cbArg;

WP_CHECK_FIPS_ALGO_PTR(WP_CAST_ALGO_DH);

/* Create a new DH key object to hold generated data. */
dh = wp_dh_new(ctx->provCtx);
if (dh != NULL) {
Expand Down Expand Up @@ -2064,6 +2069,8 @@ static int wp_dh_decode_spki(wp_Dh* dh, unsigned char* data, word32 len)

WOLFPROV_ENTER_SILENT(WP_LOG_COMP_DH, WOLFPROV_FUNC_NAME);

WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_DH);

rc = wc_DhPublicKeyDecode(data, &idx, &dh->key, len);
if (rc != 0) {
ok = 0;
Expand Down Expand Up @@ -2127,6 +2134,8 @@ static int wp_dh_decode_pki(wp_Dh* dh, unsigned char* data, word32 len)

WOLFPROV_ENTER_SILENT(WP_LOG_COMP_DH, WOLFPROV_FUNC_NAME);

WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_DH);

rc = wc_DhKeyDecode(data, &idx, &dh->key, len);
if (rc != 0) {
ok = 0;
Expand Down
3 changes: 3 additions & 0 deletions src/wp_ecc_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1767,6 +1767,9 @@ static wp_Ecc* wp_ecc_gen(wp_EccGenCtx *ctx, OSSL_CALLBACK *cb, void *cbArg)
(void)cb;
(void)cbArg;

WP_CHECK_FIPS_ALGO_PTR(WP_CAST_ALGO_ECDSA);
WP_CHECK_FIPS_ALGO_PTR(WP_CAST_ALGO_ECDH);

if (ctx->curveName[0] != '\0') {
ecc = wp_ecc_new(ctx->provCtx);
}
Expand Down
3 changes: 3 additions & 0 deletions src/wp_ecdh_exch.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ static int wp_ecdh_init(wp_EcdhCtx* ctx, wp_Ecc* ecc, const OSSL_PARAM params[])
if (!wolfssl_prov_is_running()) {
ok = 0;
}
if (ok) {
WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_ECDH);
}
if (ok && (ctx->key != ecc)) {
/* Free old key and up reference new key. */
wp_ecc_free(ctx->key);
Expand Down
5 changes: 4 additions & 1 deletion src/wp_ecdsa_sig.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,10 @@ static int wp_ecdsa_signverify_init(wp_EcdsaSigCtx *ctx, wp_Ecc* ecc,
if (ctx == NULL || (ecc == NULL && ctx->ecc == NULL)) {
ok = 0;
}
else if (ecc != NULL) {
if (ok) {
WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_ECDSA);
}
if (ok && (ecc != NULL)) {
if (!wp_ecc_up_ref(ecc)) {
ok = 0;
}
Expand Down
2 changes: 2 additions & 0 deletions src/wp_hmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ static int wp_hmac_set_key(wp_HmacCtx* macCtx, const unsigned char* key,

WOLFPROV_ENTER(WP_LOG_COMP_MAC, "wp_hmac_set_key");

WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_HMAC);

if (macCtx->keyLen > 0) {
OPENSSL_secure_clear_free(macCtx->key, macCtx->keyLen);
}
Expand Down
129 changes: 123 additions & 6 deletions src/wp_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,140 @@
#include <wolfssl/wolfcrypt/pwdbased.h>

#if defined(HAVE_FIPS) && (!defined(WP_SINGLE_THREADED))
static wolfSSL_Mutex castMutex;
/**
* Structure to hold CAST self-test state for each algorithm.
*/
typedef struct wp_cast_algo_state {
/** Mutex for the algorithm's CAST self-test. */
wolfSSL_Mutex mutex;
/** Initialization state: 0 = not initialized, 1 = initialized. */
int init;
} wp_cast_algo_state;

static wp_cast_algo_state castAlgos[WP_CAST_ALGO_COUNT];

/**
* Initialize the cast mutex on library load.
* Initialize the cast mutexes on library load.
*
* This constructor runs when libwolfprov.so is loaded via dlopen() or at
* program startup. It ensures the castMutex is initialized under lock.
* program startup. It ensures the castAlgos are initialized before any
* wolfProvider functions are called.
*/
__attribute__((constructor))
static void wolfprov_init_cast_mutex(void)
{
wc_InitMutex(&castMutex);
int i;
for (i = 0; i < WP_CAST_ALGO_COUNT; i++) {
wc_InitMutex(&castAlgos[i].mutex);
castAlgos[i].init = 0;
}
}

wolfSSL_Mutex *wp_get_cast_mutex()

/**
* Initialize a CAST self-test for a specific algorithm.
*
* Runs the algorithm-specific CAST self-test if not already initialized.
* Uses mutex to ensure thread safety.
*
* @param [in] algo Algorithm category (WP_CAST_ALGO_*).
* @return 1 on success or already initialized.
* @return 0 on failure.
*/
int wp_init_cast(int algo)
{
return &castMutex;
int ok = 1;

if (algo < 0 || algo >= WP_CAST_ALGO_COUNT) {
WOLFPROV_ERROR_MSG(WP_LOG_COMP_PROVIDER,
"FIPS CAST initialization failed: invalid algorithm");
return 0;
}

if (castAlgos[algo].init == 0) {
if (wp_lock(&castAlgos[algo].mutex) != 1) {
WOLFPROV_ERROR_MSG(WP_LOG_COMP_PROVIDER,
"FIPS CAST initialization failed: unable to acquire lock");
return 0;
}
/* Make sure another thread did not complete already while we waited
* to acquire per algo lock */
if (castAlgos[algo].init == 0) {
switch (algo) {
#ifdef WP_HAVE_AES
case WP_CAST_ALGO_AES:
if (wc_RunCast_fips(FIPS_CAST_AES_CBC) != 0 ||
wc_RunCast_fips(FIPS_CAST_AES_GCM) != 0) {
ok = 0;
}
break;
#endif
#ifdef WP_HAVE_HMAC
case WP_CAST_ALGO_HMAC:
if (wc_RunCast_fips(FIPS_CAST_HMAC_SHA1) != 0 ||
wc_RunCast_fips(FIPS_CAST_HMAC_SHA2_256) != 0 ||
wc_RunCast_fips(FIPS_CAST_HMAC_SHA2_512) != 0 ||
wc_RunCast_fips(FIPS_CAST_HMAC_SHA3_256) != 0) {
ok = 0;
}
break;
#endif
#ifdef WP_HAVE_RSA
case WP_CAST_ALGO_RSA:
if (wc_RunCast_fips(FIPS_CAST_RSA_SIGN_PKCS1v15) != 0) {
ok = 0;
}
break;
#endif
#ifdef WP_HAVE_ECDSA
case WP_CAST_ALGO_ECDSA:
if (wc_RunCast_fips(FIPS_CAST_ECDSA) != 0) {
ok = 0;
}
break;
#endif
#ifdef WP_HAVE_ECDH
case WP_CAST_ALGO_ECDH:
if (wc_RunCast_fips(FIPS_CAST_ECC_CDH) != 0 ||
wc_RunCast_fips(FIPS_CAST_ECC_PRIMITIVE_Z) != 0) {
ok = 0;
}
break;
#endif
#ifdef WP_HAVE_DH
case WP_CAST_ALGO_DH:
if (wc_RunCast_fips(FIPS_CAST_DH_PRIMITIVE_Z) != 0) {
ok = 0;
}
break;
#endif
#ifdef WP_HAVE_RANDOM
case WP_CAST_ALGO_DRBG:
if (wc_RunCast_fips(FIPS_CAST_DRBG) != 0) {
ok = 0;
}
break;
#endif
default:
ok = 0;
break;
}

if (ok) {
castAlgos[algo].init = 1;
}
}
if (wp_unlock(&castAlgos[algo].mutex) != 1) {
ok = 0;
}
}

if (!ok) {
WOLFPROV_ERROR_MSG(WP_LOG_COMP_PROVIDER,
"FIPS CAST initialization failed");
}

return ok;
}
#endif

Expand Down
2 changes: 2 additions & 0 deletions src/wp_rsa_asym.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ static int wp_rsaa_init(wp_RsaAsymCtx* ctx, wp_Rsa* rsa,

WOLFPROV_ENTER(WP_LOG_COMP_RSA, "wp_rsaa_init");

WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_RSA);

if (ctx->rsa != rsa) {
if (wp_rsa_get_type(rsa) != RSA_FLAG_TYPE_RSA) {
ERR_raise_data(ERR_LIB_PROV,
Expand Down
2 changes: 2 additions & 0 deletions src/wp_rsa_kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ static int wp_rsakem_init(wp_RsaKemCtx* ctx, wp_Rsa* rsa,
/* TODO: check key type and size with operation. */
(void)operation;

WP_CHECK_FIPS_ALGO(WP_CAST_ALGO_RSA);

if (rsa != ctx->rsa) {
wp_rsa_free(ctx->rsa);
ctx->rsa = NULL;
Expand Down
3 changes: 1 addition & 2 deletions src/wp_rsa_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,7 @@ static wp_Rsa* wp_rsa_gen(wp_RsaGenCtx* ctx, OSSL_CALLBACK* cb, void* cbArg)
(void)cbArg;

if (wolfssl_prov_is_running() && wp_rsagen_check_key_size(ctx)) {
WP_CHECK_FIPS_ALGO_PTR(WP_CAST_ALGO_RSA);
rsa = wp_rsa_base_new(ctx->provCtx, ctx->type);
if (rsa != NULL) {
/* wolfCrypt FIPS RSA keygen has a small chance it simply will not
Expand Down Expand Up @@ -2236,7 +2237,6 @@ static int wp_rsa_decode_spki(wp_Rsa* rsa, unsigned char* data, word32 len)
if (!wolfssl_prov_is_running()) {
ok = 0;
}

if (ok) {
rc = wc_RsaPublicKeyDecode(data, &idx, &rsa->key, len);
if (rc != 0) {
Expand Down Expand Up @@ -2283,7 +2283,6 @@ static int wp_rsa_decode_pki(wp_Rsa* rsa, unsigned char* data, word32 len)
if (!wolfssl_prov_is_running()) {
ok = 0;
}

if (ok) {
rc = wc_RsaPrivateKeyDecode(data, &idx, &rsa->key, len);
if (rc != 0) {
Expand Down
Loading
Loading