diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index b28c33a3c27..8ad0c4cfa79 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -218,6 +218,7 @@ CRYP_HEADERWIDTHUNIT_BYTE CRYP_KEYIVCONFIG_ONCE CRYP_KEYSIZE_192B CSM_UNSUPPORTED_ALGS +CTAO_CRYPT_AES_H CTYPE_USER CURVED448_SMALL CUSTOM_ENTROPY_TIMEHIRES @@ -717,6 +718,7 @@ WC_ASYNC_THREAD_BIND WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS WC_CACHE_RESISTANT_BASE64_TABLE WC_DISABLE_RADIX_ZERO_PAD +WC_FIPS_AESGCM_ONE_SHOT_EXT_IV_ALLOWED WC_FLAG_DONT_USE_AESNI WC_FORCE_LINUXKM_FORTIFY_SOURCE WC_HASH_CUSTOM_MAX_BLOCK_SIZE @@ -1061,12 +1063,15 @@ WOLFSSL_ZEPHYR WOLF_ALLOW_BUILTIN WOLF_CRYPTO_CB_CMD WOLF_CRYPTO_DEV +WOLF_CRYPT_FIPS_H WOLF_NO_TRAILING_ENUM_COMMAS WindowsCE XGETPASSWD XMSS_CALL_PRF_KEYGEN XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_CORTEXA72_0_TIMESTAMP_CLK_FREQ XSECURE_CACHE_DISABLE +fipsCastStatus_get +wc_Des3_SetKey _ABI64 _ABIO64 _ARCH_PPC64 diff --git a/configure.ac b/configure.ac index 3535570b1f1..316cb47e11b 100644 --- a/configure.ac +++ b/configure.ac @@ -1571,9 +1571,9 @@ then enable_aesgcm_stream=no fi -# All wolfCrypt features: +# All wolfCrypt features except quantum-resistant asymmetric: AC_ARG_ENABLE([all-crypto], - [AS_HELP_STRING([--enable-all-crypto],[Enable all wolfcrypt algorithms (default: disabled)])], + [AS_HELP_STRING([--enable-all-crypto],[Enable all wolfcrypt algorithms except quantum-resistant asymmetric (default: disabled)])], [ ENABLED_ALL_CRYPT=$enableval ], [ ENABLED_ALL_CRYPT=no ] ) @@ -1713,6 +1713,21 @@ then AM_CFLAGS="$AM_CFLAGS -DWC_KDF_NIST_SP_800_56C" fi +# All native quantum-resistant asymmetric algorithms: +AC_ARG_ENABLE([all-quantum-crypto], + [AS_HELP_STRING([--enable-all-quantum-crypto],[Enable all quantum-resistant asymmetric algorithms (default: disabled)])], + [ ENABLED_ALL_QUANTUM_CRYPT=$enableval ], + [ ENABLED_ALL_QUANTUM_CRYPT=no ] + ) +if test "$ENABLED_ALL_QUANTUM_CRYPT" = "yes" +then + test "$enable_mlkem" = "" && enable_mlkem=yes + test "$enable_mldsa" = "" && enable_mldsa=yes + test "$enable_xmss" = "" && enable_xmss=yes + test "$enable_lms" = "" && enable_lms=yes + test "$enable_slhdsa" = "" && enable_slhdsa='yes,sha2' +fi + # kernel-appropriate settings, also in enable-all-crypto above: if test "$KERNEL_MODE_DEFAULTS" = "yes" && test "$ENABLED_ALL_CRYPT" != "yes" then diff --git a/linuxkm/lkcapi_aes_glue.c b/linuxkm/lkcapi_aes_glue.c index bd2776365d0..bd362226242 100644 --- a/linuxkm/lkcapi_aes_glue.c +++ b/linuxkm/lkcapi_aes_glue.c @@ -1121,6 +1121,16 @@ static int km_AesGcmSetAuthsize_Rfc4106(struct crypto_aead *tfm, unsigned int au #ifdef WOLFSSL_AESGCM_STREAM +/* Don't incur the FIPS check overhead inside the loop -- the Final() call will + * check and error if the module entered degraded state during the loop. + */ +#if defined(HAVE_FIPS) && !defined(FIPS_NO_WRAPPERS) + #undef wc_AesGcmDecryptUpdate + #undef wc_AesGcmEncryptUpdate + typeof(wc_AesGcmDecryptUpdate_fips) wc_AesGcmDecryptUpdate; + typeof(wc_AesGcmEncryptUpdate_fips) wc_AesGcmEncryptUpdate; +#endif + static int AesGcmCrypt_1(struct aead_request *req, int decrypt_p, int rfc4106_p) { struct crypto_aead * tfm = NULL; @@ -1340,6 +1350,11 @@ static int AesGcmCrypt_1(struct aead_request *req, int decrypt_p, int rfc4106_p) return err; } +#if defined(HAVE_FIPS) && !defined(FIPS_NO_WRAPPERS) + #define wc_AesGcmDecryptUpdate wc_AesGcmDecryptUpdate_fips + #define wc_AesGcmEncryptUpdate wc_AesGcmEncryptUpdate_fips +#endif + #else /* !WOLFSSL_AESGCM_STREAM */ static int AesGcmCrypt_1(struct aead_request *req, int decrypt_p, int rfc4106_p) @@ -2205,6 +2220,16 @@ static int km_AesXtsSetKey(struct crypto_skcipher *tfm, const u8 *in_key, /* see /usr/src/linux/drivers/md/dm-crypt.c */ +/* Don't incur the FIPS check overhead inside the loop -- the Final() call will + * check and error if the module entered degraded state during the loop. + */ +#if defined(HAVE_FIPS) && !defined(FIPS_NO_WRAPPERS) + #undef wc_AesXtsDecryptUpdate + #undef wc_AesXtsEncryptUpdate + typeof(wc_AesXtsDecryptUpdate_fips) wc_AesXtsDecryptUpdate; + typeof(wc_AesXtsEncryptUpdate_fips) wc_AesXtsEncryptUpdate; +#endif + static int km_AesXtsEncrypt(struct skcipher_request *req) { int err; @@ -2507,6 +2532,11 @@ static int km_AesXtsDecrypt(struct skcipher_request *req) return err; } +#if defined(HAVE_FIPS) && !defined(FIPS_NO_WRAPPERS) + #define wc_AesXtsDecryptUpdate wc_AesXtsDecryptUpdate_fips + #define wc_AesXtsEncryptUpdate wc_AesXtsEncryptUpdate_fips +#endif + static struct skcipher_alg xtsAesAlg = { .base.cra_name = WOLFKM_AESXTS_NAME, .base.cra_driver_name = WOLFKM_AESXTS_DRIVER, diff --git a/src/internal.c b/src/internal.c index 0ea1b04f2b7..5d6af2a7e7a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -28447,6 +28447,8 @@ static const char* wolfSSL_ERR_reason_error_string_OpenSSL(unsigned long e) } #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER || HAVE_MEMCACHED */ +wc_static_assert((int)WC_LAST_E <= (int)WOLFSSL_LAST_E); + const char* wolfSSL_ERR_reason_error_string(unsigned long e) { #ifdef NO_ERROR_STRINGS @@ -42275,8 +42277,8 @@ static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz, * @return MEMORY_E when dynamic memory allocation fails. * @return Other value when encryption/decryption fails. */ -static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz, - byte* in, int inLen, byte* out, int* outLen, byte* tag, +static int TicketEncDec(const byte* key, int keyLen, const byte* iv, const byte* aad, int aadSz, + const byte* in, int inLen, byte* out, int* outLen, byte* tag, void* heap, int enc) { int ret; @@ -42293,7 +42295,7 @@ static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz, ret = wc_AesGcmSetKey(aes, key, keyLen); } if (ret == 0) { - ret = wc_AesGcmEncrypt(aes, in, out, inLen, iv, GCM_NONCE_MID_SZ, + ret = wc_AesGcmEncrypt(aes, out, in, inLen, iv, GCM_NONCE_MID_SZ, tag, WC_AES_BLOCK_SIZE, aad, aadSz); } wc_AesFree(aes); @@ -42304,7 +42306,7 @@ static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz, ret = wc_AesGcmSetKey(aes, key, keyLen); } if (ret == 0) { - ret = wc_AesGcmDecrypt(aes, in, out, inLen, iv, GCM_NONCE_MID_SZ, + ret = wc_AesGcmDecrypt(aes, out, in, inLen, iv, GCM_NONCE_MID_SZ, tag, WC_AES_BLOCK_SIZE, aad, aadSz); } wc_AesFree(aes); diff --git a/tests/api/test_aes.c b/tests/api/test_aes.c index 6c2adab96f3..afcf7f26cf1 100644 --- a/tests/api/test_aes.c +++ b/tests/api/test_aes.c @@ -3399,7 +3399,8 @@ int test_wc_AesGcmEncryptDecrypt(void) * bound on the IV length. */ #if (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) && \ - !defined(WOLFSSL_AES_GCM_FIXED_IV_AAD) + !defined(WOLFSSL_AES_GCM_FIXED_IV_AAD) && \ + !defined(WC_TEST_AES_GCM_ENCRYPT_NO_NONSTD_IV) ExpectIntEQ(wc_AesGcmEncrypt(&aes, enc, vector, sizeof(vector), longIV, sizeof(longIV)/sizeof(byte), resultT, sizeof(resultT), a, sizeof(a)), 0); diff --git a/tests/api/test_ed25519.c b/tests/api/test_ed25519.c index d9ff72b18e5..dcbca22902a 100644 --- a/tests/api/test_ed25519.c +++ b/tests/api/test_ed25519.c @@ -979,6 +979,7 @@ int test_wc_ed25519_sign_verify_ctx_ph(void) &verify_ok, &key, ctx, sizeof(ctx)), 0); ExpectIntEQ(verify_ok, 1); +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GT(6,0,0) /* Ed25519ph length check true side: wrong-size "hash" input. */ sigLen = sizeof(sig); ExpectIntEQ(wc_ed25519_sign_msg_ex(hash, sizeof(hash) - 1, sig, &sigLen, @@ -988,6 +989,7 @@ int test_wc_ed25519_sign_verify_ctx_ph(void) ExpectIntEQ(wc_ed25519_verify_msg_ex(sig, sizeof(sig), hash, sizeof(hash) - 1, &verify_ok, &key, (byte)Ed25519ph, ctx, sizeof(ctx)), WC_NO_ERR_TRACE(BAD_LENGTH_E)); +#endif /* context==NULL && contextLen!=0 compound: TRUE side, direct low-level * calls (the ctx/ph wrappers above always pass a real, non-NULL @@ -1054,8 +1056,10 @@ int test_wc_ed25519_verify_streaming(void) /* init: NULL args. */ ExpectIntEQ(wc_ed25519_verify_msg_init(NULL, sigLen, &key, (byte)Ed25519, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GT(6,0,0) ExpectIntEQ(wc_ed25519_verify_msg_init(sig, sigLen, NULL, (byte)Ed25519, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#endif /* init: sigLen wrong. */ ExpectIntEQ(wc_ed25519_verify_msg_init(sig, sigLen - 1, &key, (byte)Ed25519, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); @@ -1069,8 +1073,10 @@ int test_wc_ed25519_verify_streaming(void) /* update: NULL msgSegment, then NULL key (independent operand). */ ExpectIntEQ(wc_ed25519_verify_msg_update(NULL, 4, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GT(6,0,0) ExpectIntEQ(wc_ed25519_verify_msg_update(msg, 4, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#endif /* init: context==NULL/contextLen!=0 compound, explicit both-sides * pairing within this function (type left as plain Ed25519 so the @@ -1092,8 +1098,10 @@ int test_wc_ed25519_verify_streaming(void) WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_ed25519_verify_msg_final(sig, sigLen, NULL, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GT(6,0,0) ExpectIntEQ(wc_ed25519_verify_msg_final(sig, sigLen, &verify_ok, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#endif /* final: sigLen wrong. */ ExpectIntEQ(wc_ed25519_verify_msg_final(sig, sigLen - 1, &verify_ok, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 7f7379b3002..04f86015a87 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -80,6 +80,7 @@ #include #include #include +#include #ifdef WOLFSSL_LINUXKM /* remap current_time() -- collides with a function in kernel linux/fs.h */ diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index d085b9cc2b4..4bd3a051a7d 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -673,16 +673,18 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #define AESNI_ALIGN 16 #endif - /* Accessed with the wolfSSL atomic APIs so the one-time detection is free of - * data races. Writes are also idempotent (all callers compute the same - * value), so a benign concurrent double-write is harmless. */ - static wolfSSL_Atomic_Uint checkedAESNI = WOLFSSL_ATOMIC_INITIALIZER(0); - static wolfSSL_Atomic_Uint haveAESNI = WOLFSSL_ATOMIC_INITIALIZER(0); - static cpuid_flags_atomic_t intel_flags = WC_CPUID_ATOMIC_INITIALIZER; + /* Note that all write access to these static variables must be idempotent, + * as arranged by Check_CPU_support_AES(), else they will be susceptible to + * data races. Don't use wolfSSL_Atomic_Uint here, to avoid atomic access + * overhead on subsequent calls. + */ + static int checkedAESNI = 0; + static int haveAESNI = 0; + static cpuid_flags_t intel_flags = WC_CPUID_INITIALIZER; static WARN_UNUSED_RESULT int Check_CPU_support_AES(void) { - cpuid_get_flags_atomic(&intel_flags); + cpuid_get_flags_ex(&intel_flags); return IS_INTEL_AESNI(intel_flags) != 0; } @@ -1086,11 +1088,12 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #elif defined(WOLFSSL_ARMASM) #if defined(__aarch64__) && !defined(WOLFSSL_ARMASM_NO_HW_CRYPTO) -static cpuid_flags_atomic_t cpuid_flags = WC_CPUID_ATOMIC_INITIALIZER; +static cpuid_flags_t cpuid_flags = WC_CPUID_INITIALIZER; static void Check_CPU_support_HwCrypto(Aes* aes) { - cpuid_get_flags_atomic(&cpuid_flags); + if (cpuid_flags == WC_CPUID_INITIALIZER) + cpuid_get_flags_ex(&cpuid_flags); aes->use_aes_hw_crypto = IS_AARCH64_AES(cpuid_flags); #ifdef HAVE_AESGCM aes->use_pmull_hw_crypto = IS_AARCH64_PMULL(cpuid_flags); @@ -1177,21 +1180,22 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, * branches that also call these names are #if'd out, so only the live PPC call * sites are redirected. */ -/* Resolved dispatch decision (0 = base, 1 = vector-crypto), accessed with the - * wolfSSL atomic APIs so the one-time detection is free of data races. The - * master cpuid flags read by cpuid_get_flags() are themselves atomic; the write - * here is idempotent so a benign concurrent double-write is harmless. */ -static wolfSSL_Atomic_Uint aes_ppc64_use_crypto = WOLFSSL_ATOMIC_INITIALIZER(0); +/* Resolved dispatch decision (0 = base, 1 = vector-crypto). The write here is + * idempotent so a benign concurrent double-write is harmless. Avoid atomic for + * this, as for intel_flags above, to avoid unnecessary expensive reads. */ +static int aes_ppc64_use_crypto = 0; /* True when the CPU supports the vector-crypto instructions. */ -#define AES_PPC64_USE_CRYPTO() (WOLFSSL_ATOMIC_LOAD(aes_ppc64_use_crypto) != 0) +#define AES_PPC64_USE_CRYPTO() (aes_ppc64_use_crypto != 0) /* Check and set the decision together (as Check_CPU_support_AES/HwCrypto do); * called from the key-setup path before any AES_*_crypto use. */ static void Aes_SetCrypto(void) { - WOLFSSL_ATOMIC_STORE(aes_ppc64_use_crypto, - (unsigned int)(IS_PPC64_VEC_CRYPTO(cpuid_get_flags()) != 0)); + static cpuid_flags_t cpu_flags = WC_CPUID_INITIALIZER; + if (cpu_flags == WC_CPUID_INITIALIZER) + cpuid_get_flags_ex(&cpu_flags); + aes_ppc64_use_crypto = (IS_PPC64_VEC_CRYPTO(cpu_flags) != 0); } #define AES_set_encrypt_key(key, len, ks) \ @@ -5648,11 +5652,11 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) * function correctly with default build settings. */ - if (WOLFSSL_ATOMIC_LOAD(checkedAESNI) == 0) { - WOLFSSL_ATOMIC_STORE(haveAESNI, Check_CPU_support_AES()); - WOLFSSL_ATOMIC_STORE(checkedAESNI, 1); + if (checkedAESNI == 0) { + haveAESNI = Check_CPU_support_AES(); + checkedAESNI = 1; } - if (WOLFSSL_ATOMIC_LOAD(haveAESNI) + if (haveAESNI #if defined(WC_FLAG_DONT_USE_VECTOR_OPS) && !defined(WC_C_DYNAMIC_FALLBACK) && (aes->use_aesni != WC_FLAG_DONT_USE_VECTOR_OPS) #endif @@ -18893,7 +18897,7 @@ static AesGcmSivPolyvalFn AesGcmSivPolyvalAsm(void) static AesGcmSivPolyvalFn AesGcmSivPolyvalAsm(void) { #ifndef WOLFSSL_ARMASM_NO_HW_CRYPTO - cpuid_get_flags_atomic(&cpuid_flags); + cpuid_get_flags_ex(&cpuid_flags); if (IS_AARCH64_PMULL(cpuid_flags)) { return &AES_GCMSIV_polyval_pmull; } @@ -18912,7 +18916,7 @@ static AesGcmSivPolyvalFn AesGcmSivPolyvalAsm(void) * AES-NI gates the base path (matching wolfSSL's AES-GCM). */ static AesGcmSivPolyvalFn AesGcmSivPolyvalAsm(void) { - cpuid_get_flags_atomic(&intel_flags); + cpuid_get_flags_ex(&intel_flags); if (!IS_INTEL_AESNI(intel_flags)) { return NULL; } @@ -18957,7 +18961,7 @@ static AesGcmSivCtrFn AesGcmSivCtrAsm(void) static AesGcmSivCtrFn AesGcmSivCtrAsm(void) { #ifndef WOLFSSL_ARMASM_NO_HW_CRYPTO - cpuid_get_flags_atomic(&cpuid_flags); + cpuid_get_flags_ex(&cpuid_flags); if (IS_AARCH64_AES(cpuid_flags)) { return &AES_GCMSIV_ctr_aarch64; } @@ -18975,7 +18979,7 @@ static AesGcmSivCtrFn AesGcmSivCtrAsm(void) * the base; AVX1/VAES/AVX512 are progressively wider pipelines. */ static AesGcmSivCtrFn AesGcmSivCtrAsm(void) { - cpuid_get_flags_atomic(&intel_flags); + cpuid_get_flags_ex(&intel_flags); if (!IS_INTEL_AESNI(intel_flags)) { return NULL; } diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 3cf8d807fec..0a962e04e91 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -86,7 +86,8 @@ static const byte ed25519Ctx[ED25519CTX_SIZE + 1] = ED25519CTX_SNC_MESSAGE; #endif -static int ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha) +static int WC_ARG_NOT_NULL(1) WC_ARG_NOT_NULL(2) + ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha) { int ret; @@ -108,7 +109,7 @@ static int ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha) } #ifdef WOLFSSL_ED25519_PERSISTENT_SHA -static int ed25519_hash_reset(ed25519_key* key) +static int WC_ARG_NOT_NULL(1) ed25519_hash_reset(ed25519_key* key) { int ret; @@ -132,8 +133,9 @@ static int ed25519_hash_reset(ed25519_key* key) } #endif /* WOLFSSL_ED25519_PERSISTENT_SHA */ -static int ed25519_hash_update(ed25519_key* key, wc_Sha512 *sha, - const byte* data, word32 len) +static int WC_ARG_NOT_NULL(1) + ed25519_hash_update(ed25519_key* key, wc_Sha512 *sha, + const byte* data, word32 len) { #ifdef WOLFSSL_ED25519_PERSISTENT_SHA if (key->sha_clean_flag) { @@ -145,7 +147,8 @@ static int ed25519_hash_update(ed25519_key* key, wc_Sha512 *sha, return wc_Sha512Update(sha, data, len); } -static int ed25519_hash_final(ed25519_key* key, wc_Sha512 *sha, byte* hash) +static int WC_ARG_NOT_NULL(1) + ed25519_hash_final(ed25519_key* key, wc_Sha512 *sha, byte* hash) { int ret = wc_Sha512Final(sha, hash); #ifdef WOLFSSL_ED25519_PERSISTENT_SHA @@ -158,7 +161,8 @@ static int ed25519_hash_final(ed25519_key* key, wc_Sha512 *sha, byte* hash) return ret; } -static void ed25519_hash_free(ed25519_key* key, wc_Sha512 *sha) +static void WC_ARG_NOT_NULL(1) + ed25519_hash_free(ed25519_key* key, wc_Sha512 *sha) { wc_Sha512Free(sha); #ifdef WOLFSSL_ED25519_PERSISTENT_SHA @@ -934,18 +938,24 @@ static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen, int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key, byte type, const byte* context, byte contextLen) { + if (key == NULL) + return BAD_FUNC_ARG; return ed25519_verify_msg_init_with_sha(sig, sigLen, key, &key->sha, type, context, contextLen); } int wc_ed25519_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, ed25519_key* key) { + if (key == NULL) + return BAD_FUNC_ARG; return ed25519_verify_msg_update_with_sha(msgSegment, msgSegmentLen, key, &key->sha); } int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res, ed25519_key* key) { + if (key == NULL) + return BAD_FUNC_ARG; return ed25519_verify_msg_final_with_sha(sig, sigLen, res, key, &key->sha); } diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 0cca67dc0cf..234a803e064 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -32,6 +32,10 @@ #include #endif +wc_static_assert((int)WC_LAST_E <= (int)WC_SPAN2_LAST_E); +wc_static_assert((int)MIN_CODE_E <= (int)WC_LAST_E); +wc_static_assert((int)MIN_CODE_E <= (int)WC_SPAN2_MIN_CODE_E); + WOLFSSL_ABI const char* wc_GetErrorString(int error) { @@ -620,6 +624,9 @@ const char* wc_GetErrorString(int error) case KEY_EXHAUSTED_E: return "Key no longer usable for operation"; + case ML_KEM_KAT_FIPS_E: + return "wolfCrypt FIPS ML-KEM Known Answer Test Failure"; + case FIPS_INVALID_VER_E: return "Invalid FIPS version defined, check length"; @@ -644,6 +651,15 @@ const char* wc_GetErrorString(int error) case WC_KEY_MISMATCH_E: return "key values mismatch"; + case ML_DSA_KAT_FIPS_E: + return "wolfCrypt FIPS ML-DSA Known Answer Test Failure"; + + case LMS_KAT_FIPS_E: + return "wolfCrypt FIPS LMS Known Answer Test Failure"; + + case XMSS_KAT_FIPS_E: + return "wolfCrypt FIPS XMSS Known Answer Test Failure"; + case DEADLOCK_AVERTED_E: return "Deadlock averted -- retry the call"; @@ -668,33 +684,6 @@ const char* wc_GetErrorString(int error) case ALREADY_E: return "Operation was redundant or preempted"; - case ML_KEM_KAT_FIPS_E: - return "wolfCrypt FIPS ML-KEM Known Answer Test Failure"; - - case ML_DSA_KAT_FIPS_E: - return "wolfCrypt FIPS ML-DSA Known Answer Test Failure"; - - case LMS_KAT_FIPS_E: - return "wolfCrypt FIPS LMS Known Answer Test Failure"; - - case XMSS_KAT_FIPS_E: - return "wolfCrypt FIPS XMSS Known Answer Test Failure"; - - case ML_KEM_PCT_E: - return "wolfcrypt ML-KEM Pairwise Consistency Test Failure"; - - case ML_DSA_PCT_E: - return "wolfcrypt ML-DSA Pairwise Consistency Test Failure"; - - case DRBG_SHA512_KAT_FIPS_E: - return "SHA-512 DRBG Known Answer Test check FIPS error"; - - case SLH_DSA_KAT_FIPS_E: - return "SLH-DSA Known Answer Test check FIPS error"; - - case TSP_VERIFY_E: - return "TSP token invalid or response doesn't match request error"; - case SEQ_OVERFLOW_E: return "Sequence counter would overflow"; @@ -716,6 +705,24 @@ const char* wc_GetErrorString(int error) case PUF_IDENTITY_E: return "PUF identity retrieval failed"; + case ML_KEM_PCT_E: + return "wolfcrypt ML-KEM Pairwise Consistency Test Failure"; + + case ML_DSA_PCT_E: + return "wolfcrypt ML-DSA Pairwise Consistency Test Failure"; + + case DRBG_SHA512_KAT_FIPS_E: + return "SHA-512 DRBG Known Answer Test check FIPS error"; + + case SLH_DSA_KAT_FIPS_E: + return "SLH-DSA Known Answer Test check FIPS error"; + + case TSP_VERIFY_E: + return "TSP token invalid or response doesn't match request error"; + + case FIPS_WRONG_API_E: + return "Requested API is not allowed in FIPS mode"; + case MAX_CODE_E: case WC_SPAN1_MIN_CODE_E: case MIN_CODE_E: diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 23f576781b7..ced8033430f 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -54,6 +54,8 @@ #include #endif +#include + static const struct s_ent { const enum wc_HashType macType; const int nid; diff --git a/wolfcrypt/src/hpke.c b/wolfcrypt/src/hpke.c index e117e9e813a..ff74e1cd932 100644 --- a/wolfcrypt/src/hpke.c +++ b/wolfcrypt/src/hpke.c @@ -45,6 +45,8 @@ #include #endif +#include + static const char* KEM_STR = "KEM"; static const int KEM_STR_LEN = 3; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 858b5c1baab..f76afe6f988 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -101,6 +101,8 @@ #include #endif +#include + /* direction for processing, encoding or decoding */ typedef enum { WC_PKCS7_ENCODE, diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e346fc47f4b..fd3d76e305d 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -57,6 +57,8 @@ #include #endif +#include + #if defined(HAVE_WOLFCRYPT_TEST_OPTIONS) #include #define err_sys err_sys_remap /* remap err_sys */ diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 2783f00813b..68e952cdc99 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -255,8 +255,6 @@ enum wolfSSL_ErrorCodes { /* codes -1000 to -1999 are reserved for wolfCrypt. */ }; -wc_static_assert((int)WC_LAST_E <= (int)WOLFSSL_LAST_E); - #ifndef WOLFSSL_NO_DILITHIUM_LEGACY_NAMES /* Legacy alias for code written against the pre-standardization * Dilithium name. Will be removed alongside the dilithium.h shim. */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index b5a0fb4a07a..9d92c273b0a 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -38,6 +38,7 @@ #include #include #include +#include #if defined(HAVE_OCSP) || defined(HAVE_CRL) || (defined(WOLFSSL_CUSTOM_OID) && \ defined(WOLFSSL_ASN_TEMPLATE) && defined(HAVE_OID_DECODING)) || \ diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 8d21f44a7e4..98280640ed5 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -620,11 +620,19 @@ WOLFSSL_LOCAL int wc_local_AesGcmCheckTagSz(word32 authTagSz); word32 kup); #endif WOLFSSL_API int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len); - WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, - const byte* in, word32 sz, - const byte* iv, word32 ivSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz); +#if defined(HAVE_FIPS) && !defined(WC_FIPS_AESGCM_ONE_SHOT_EXT_IV_ALLOWED) +#ifndef _WC_BUILDING_AES_C + WC_DEPRECATED("wc_AesGcmEncrypt() is not approved for FIPS usage.") +#endif + WOLFSSL_LOCAL +#else + WOLFSSL_API +#endif + int wc_AesGcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); WOLFSSL_API WARN_UNUSED_RESULT int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 9bc5ff7bec9..8f9a01f36eb 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -31,7 +31,10 @@ the error status. #ifndef WOLF_CRYPT_ERROR_H #define WOLF_CRYPT_ERROR_H -#include +/* Avoid wolfcrypt/types.h here, to mitigate circular dependencies via + * wc_compat.h. + */ +#include #ifdef __cplusplus extern "C" { @@ -330,9 +333,10 @@ enum wolfCrypt_ErrorCodes { TSP_VERIFY_E = -1019, /* TSP token invalid or response doesn't * match request */ + FIPS_WRONG_API_E = -1020, /* Requested API is not allowed in FIPS mode */ - WC_SPAN2_LAST_E = -1019, /* Update to indicate last used error code */ - WC_LAST_E = -1019, /* the last code used either here or in + WC_SPAN2_LAST_E = -1020, /* Update to indicate last used error code */ + WC_LAST_E = -1020, /* the last code used either here or in * error-ssl.h */ WC_SPAN2_MIN_CODE_E = -1999, /* Last usable code in span 2 */ @@ -344,10 +348,6 @@ enum wolfCrypt_ErrorCodes { wolfcrypt/src/error.c !!! */ }; -wc_static_assert((int)WC_LAST_E <= (int)WC_SPAN2_LAST_E); -wc_static_assert((int)MIN_CODE_E <= (int)WC_LAST_E); -wc_static_assert((int)MIN_CODE_E <= (int)WC_SPAN2_MIN_CODE_E); - #ifdef NO_ERROR_STRINGS #define wc_GetErrorString(error) "no support for error strings built in" #define wc_ErrorString(err, buf) \ diff --git a/wolfssl/wolfcrypt/fips_test.h b/wolfssl/wolfcrypt/fips_test.h index de2b506df2c..aa04b468e29 100644 --- a/wolfssl/wolfcrypt/fips_test.h +++ b/wolfssl/wolfcrypt/fips_test.h @@ -82,6 +82,7 @@ enum FipsCastId { FIPS_CAST_SLH_DSA = 25, FIPS_CAST_COUNT = 26 }; +#define WC_FIPS_ENUM_CAST_ID_DEFINED enum FipsCastStateId { FIPS_CAST_STATE_INIT = 0, diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index c9fd93ae6e9..e00e8a3d355 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -86,7 +86,8 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/wc_xmss.h \ wolfssl/wolfcrypt/wc_slhdsa.h \ wolfssl/wolfcrypt/puf.h \ - wolfssl/wolfcrypt/oid_sum.h + wolfssl/wolfcrypt/oid_sum.h \ + wolfssl/wolfcrypt/wc_compat.h noinst_HEADERS+= \ wolfssl/wolfcrypt/port/aria/aria-crypt.h \ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index aad0ad68b4d..2ef7bd198e9 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -2561,4 +2561,8 @@ enum Max_ASN { } /* extern "C" */ #endif +#ifndef BUILDING_WOLFSSL + #include +#endif + #endif /* WOLF_CRYPT_TYPES_H */ diff --git a/wolfssl/wolfcrypt/wc_compat.h b/wolfssl/wolfcrypt/wc_compat.h new file mode 100644 index 00000000000..9a820f49a91 --- /dev/null +++ b/wolfssl/wolfcrypt/wc_compat.h @@ -0,0 +1,132 @@ +/* wolfcrypt/wc_compat.h + * + * Copyright (C) 2006-2026 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 3 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 + */ +/*! + \file ../wolfssl/wolfcrypt/wc_compat.h + \brief Header file containing wolfCrypt compatibility shims +*/ + +#if (defined(WOLF_CRYPT_SHA256_H) && !defined(NO_SHA256) && \ + !defined(WC_SHA256_TYPE_DEFINED) && !defined(SHA256_NOINLINE)) || \ + (defined(WOLF_CRYPT_SHA512_H) && \ + (defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)) && \ + !defined(WC_SHA512_TYPE_DEFINED) && !defined(WC_SHA384_TYPE_DEFINED) && \ + !defined(SHA512_NOINLINE)) || \ + (defined(WOLF_CRYPT_AES_H) && !defined(NO_AES) && \ + !defined(WC_AES_TYPE_DEFINED) && !defined(CTAO_CRYPT_AES_H)) || \ + (defined(WOLF_CRYPT_RANDOM_H) && !defined(WC_RNG_TYPE_DEFINED)) || \ + (defined(WOLF_CRYPT_FIPS_H) && \ + !defined(fipsCastStatus_get) && !defined(wc_Des3_SetKey) && \ + !defined(WC_DES3_TYPE_DEFINED)) || \ + (defined(WOLF_CRYPT_FIPS_TEST_H) && \ + !defined(WC_FIPS_ENUM_CAST_ID_DEFINED) && !defined(WOLF_CRYPT_FIPS_H)) + + /* Inhibit wc_compat.h during inclusion of sha256.h, sha512.h, aes.h, + * random.h, fips.h, and fips_test.h, to mitigate circular dependencies. + */ + +#else /* Circular dependency deferral check passed */ + +#ifndef wolfSSL_WOLFCRYPT_WC_COMPAT_H +#define wolfSSL_WOLFCRYPT_WC_COMPAT_H + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(HAVE_FIPS) && defined(HAVE_AESGCM) && \ + !defined(WC_FIPS_AESGCM_ONE_SHOT_EXT_IV_ALLOWED) && \ + !defined(FIPS_NO_WRAPPERS) + + /* Unless WC_FIPS_AESGCM_ONE_SHOT_EXT_IV_ALLOWED, wc_AesGcmEncrypt() is a + * non-FIPS API hardwired to FIPS_WRONG_API_E in fips.c. But we can emulate + * it with FIPS calls as below. + */ + + #undef wc_AesGcmEncrypt + #include + #undef wc_AesGcmEncrypt + + #define wc_AesGcmEncrypt wc_AesGcmEncrypt_compat_shim + + #ifdef WOLFSSL_AESGCM_STREAM + + static WC_INLINE int wc_AesGcmEncrypt_compat_shim(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + int ret; + + #if FIPS_VERSION3_EQ(6,0,0) + /* FIPS v6 doesn't robustly validate authTagSz in wc_AesGcmEncryptFinal(). */ + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) + return BAD_FUNC_ARG; + #endif + ret = wc_AesGcmInit(aes, NULL /* key */, 0 /* len */, iv, ivSz); + if (ret) + return ret; + ret = wc_AesGcmEncryptUpdate(aes, out, in, sz, authIn, authInSz); + if (ret) + return ret; + return wc_AesGcmEncryptFinal(aes, authTag, authTagSz); + } + + #else /* ! WOLFSSL_AESGCM_STREAM */ + + /* Note this variant of the shim can't handle nonstandard-size IVs. */ + #define WC_TEST_AES_GCM_ENCRYPT_NO_NONSTD_IV + + static WC_INLINE int wc_AesGcmEncrypt_compat_shim(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + int ret; + byte scratch[16]; /* FIPS v2 doesn't have GCM_NONCE_MAX_SZ */ + + if (ivSz > sizeof(scratch)) + return BAD_LENGTH_E; + + ret = wc_AesGcmSetExtIV(aes, iv, ivSz); + if (ret != 0) + return ret; + ret = wc_AesGcmEncrypt_ex(aes, out, in, sz, scratch, ivSz, authTag, + authTagSz, authIn, authInSz); + if (ret != 0) + return ret; + return wc_AesGcmSetExtIV(aes, iv, ivSz); + } + #endif /* ! WOLFSSL_AESGCM_STREAM */ +#endif /* HAVE_FIPS && HAVE_AESGCM && */ + /* !WC_FIPS_AESGCM_ONE_SHOT_EXT_IV_ALLOWED && */ + /* !FIPS_NO_WRAPPERS && !WOLF_CRYPT_FIPS_TEST_H */ + + +#ifdef __cplusplus + } +#endif + +#endif /* !wolfSSL_WOLFCRYPT_WC_COMPAT_H */ + +#endif /* Circular dependency deferral check passed */