From 02a49693e2bf63b76a95cba060bf5c9594af296d Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Fri, 30 May 2025 10:20:02 -0600 Subject: [PATCH 01/16] Fix bug in ParseCRL_Extensions --- src/crl.c | 66 +++++++++++++++++++-- src/x509.c | 127 +++++++++++++++++++++++++++------------- tests/api.c | 13 ++-- wolfcrypt/src/asn.c | 115 +++++++++++++++++------------------- wolfssl/internal.h | 8 ++- wolfssl/ssl.h | 3 +- wolfssl/wolfcrypt/asn.h | 12 +++- 7 files changed, 228 insertions(+), 116 deletions(-) diff --git a/src/crl.c b/src/crl.c index 28233208a..597e2e8de 100644 --- a/src/crl.c +++ b/src/crl.c @@ -135,7 +135,10 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, #endif dcrl->certs = NULL; crle->totalCerts = dcrl->totalCerts; - crle->crlNumber = dcrl->crlNumber; + crle->crlNumberSet = dcrl->crlNumberSet; + if (crle->crlNumberSet) { + XMEMCPY(crle->crlNumber, dcrl->crlNumber, CRL_MAX_NUM_SZ); + } crle->verified = verified; if (!verified) { crle->tbsSz = dcrl->sigIndex - dcrl->certBegin; @@ -587,7 +590,9 @@ static void SetCrlInfo(CRL_Entry* entry, CrlInfo *info) info->nextDate = (byte *)entry->nextDate; info->nextDateMaxLen = MAX_DATE_SIZE; info->nextDateFormat = entry->nextDateFormat; - info->crlNumber = (sword32)entry->crlNumber; + info->crlNumberSet = entry->crlNumberSet; + if (info->crlNumberSet) + XMEMCPY(info->crlNumber, entry->crlNumber, CRL_MAX_NUM_SZ); } static void SetCrlInfoFromDecoded(DecodedCRL* entry, CrlInfo *info) @@ -600,10 +605,55 @@ static void SetCrlInfoFromDecoded(DecodedCRL* entry, CrlInfo *info) info->nextDate = (byte *)entry->nextDate; info->nextDateMaxLen = MAX_DATE_SIZE; info->nextDateFormat = entry->nextDateFormat; - info->crlNumber = (sword32)entry->crlNumber; + info->crlNumberSet = entry->crlNumberSet; + if (info->crlNumberSet) + XMEMCPY(info->crlNumber, entry->crlNumber, CRL_MAX_NUM_SZ); } #endif +/* Returns MP_GT if prev crlNumber is smaller + * MP_EQ if equal + * MP_LT if prev crlNumber is larger */ +static int CompareCRLnumber(CRL_Entry* prev, CRL_Entry* curr) +{ + int ret = 0; + DECL_MP_INT_SIZE_DYN(prev_num, CRL_MAX_NUM_SZ * CHAR_BIT, + CRL_MAX_NUM_SZ * CHAR_BIT); + DECL_MP_INT_SIZE_DYN(curr_num, CRL_MAX_NUM_SZ * CHAR_BIT, + CRL_MAX_NUM_SZ * CHAR_BIT); + + NEW_MP_INT_SIZE(prev_num, CRL_MAX_NUM_SZ * CHAR_BIT, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + NEW_MP_INT_SIZE(curr_num, CRL_MAX_NUM_SZ * CHAR_BIT, NULL, + DYNAMIC_TYPE_TMP_BUFFER); +#ifdef MP_INT_SIZE_CHECK_NULL + if ((prev_num == NULL) || (curr_num == NULL)) { + ret = MEMORY_E; + } +#endif + + if (ret == 0 && ((INIT_MP_INT_SIZE(prev_num, CRL_MAX_NUM_SZ * CHAR_BIT) + != MP_OKAY) || (INIT_MP_INT_SIZE(curr_num, + CRL_MAX_NUM_SZ * CHAR_BIT)) != MP_OKAY)) { + ret = MP_INIT_E; + } + + if (ret == 0 && (mp_read_radix(prev_num, (char*)prev->crlNumber, + MP_RADIX_HEX) != MP_OKAY || + mp_read_radix(curr_num, (char*)curr->crlNumber, + MP_RADIX_HEX) != MP_OKAY)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) + ret = mp_cmp(prev_num, curr_num); + + FREE_MP_INT_SIZE(prev_num, NULL, DYNAMIC_TYPE_TMP_BUFFER); + FREE_MP_INT_SIZE(curr_num, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + /* Add Decoded CRL, 0 on success */ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, int verified) @@ -615,6 +665,7 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, CrlInfo old; CrlInfo cnew; #endif + int ret = 0; WOLFSSL_ENTER("AddCRL"); @@ -645,12 +696,19 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, for (curr = crl->crlList; curr != NULL; curr = curr->next) { if (XMEMCMP(curr->issuerHash, crle->issuerHash, CRL_DIGEST_SIZE) == 0) { - if (crle->crlNumber <= curr->crlNumber) { + ret = CompareCRLnumber(crle, curr); + /* Error out if the CRL we're attempting to add isn't more + * authoritative than the existing entry */ + if (ret == MP_LT || ret == MP_EQ) { WOLFSSL_MSG("Same or newer CRL entry already exists"); CRL_Entry_free(crle, crl->heap); wc_UnLockRwLock(&crl->crlLock); return BAD_FUNC_ARG; } + else if (ret < 0) { + WOLFSSL_MSG("Error comparing CRL Numbers"); + return ret; + } crle->next = curr->next; if (prev != NULL) { diff --git a/src/x509.c b/src/x509.c index eda280e73..6afd8e497 100644 --- a/src/x509.c +++ b/src/x509.c @@ -6414,8 +6414,7 @@ static int X509PrintSerial_ex(WOLFSSL_BIO* bio, byte* serial, int sz, scratch + scratchLen, scratchSz - scratchLen, "%02x%s", serial[i], (i < sz - 1) ? (delimiter ? ":" : "") : "\n")) - >= scratchSz - scratchLen) - { + >= scratchSz - scratchLen) { WOLFSSL_MSG("buffer overrun"); return WOLFSSL_FAILURE; } @@ -6428,10 +6427,8 @@ static int X509PrintSerial_ex(WOLFSSL_BIO* bio, byte* serial, int sz, /* if serial can fit into byte then print on the same line */ else { - if ((scratchLen = XSNPRINTF( - scratch, MAX_WIDTH, " %d (0x%x)\n", serial[0], serial[0])) - >= MAX_WIDTH) - { + if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH, " %d (0x%x)\n", + (char)serial[0], serial[0])) >= MAX_WIDTH) { WOLFSSL_MSG("buffer overrun"); return WOLFSSL_FAILURE; } @@ -8870,85 +8867,135 @@ static int X509CRLPrintExtensions(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl, int indent) { char tmp[MAX_WIDTH]; /* buffer for XSNPRINTF */ + int ret = 0; if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%s\n", indent, "", "CRL extensions:") >= MAX_WIDTH) { - return WOLFSSL_FAILURE; + ret = WOLFSSL_FAILURE; } - if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { - return WOLFSSL_FAILURE; + if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + ret = WOLFSSL_FAILURE; } - if (crl->crlList->crlNumber) { - if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%s\n", indent + 4, "", + if (ret == 0 && crl->crlList->crlNumberSet) { + char dec_string[49]; /* 20 octets can express numbers up to approx + 49 decimal digits */ + int freeMp = 0; + #ifdef WOLFSSL_SMALL_STACK + mp_int* dec_num = (mp_int*)XMALLOC(sizeof(*dec_num), NULL, + DYNAMIC_TYPE_BIGINT); + if (dec_num == NULL) { + ret = MEMORY_E; + } + #else + mp_int dec_num[1]; + #endif + + if (ret == 0 && (mp_init(dec_num) != MP_OKAY)) { + ret = MP_INIT_E; + } + else if (ret == 0) { + freeMp = 1; + } + + if (ret == 0 && mp_read_radix(dec_num, (char *)crl->crlList->crlNumber, + MP_RADIX_HEX) != MP_OKAY) { + ret = WOLFSSL_FAILURE; + } + + if (ret == 0 && mp_toradix(dec_num, dec_string, MP_RADIX_DEC) + != MP_OKAY) { + ret = WOLFSSL_FAILURE; + } + + if (ret == 0 && XSNPRINTF(tmp, MAX_WIDTH, "%*s%s\n", indent + 4, "", "X509v3 CRL Number:") >= MAX_WIDTH) { - return WOLFSSL_FAILURE; + ret = WOLFSSL_FAILURE; } - if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { - return WOLFSSL_FAILURE; + if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + ret = WOLFSSL_FAILURE; } - if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%d\n", indent + 8, "", - crl->crlList->crlNumber) >= MAX_WIDTH) - { - return WOLFSSL_FAILURE; + if (ret == 0 && XSNPRINTF(tmp, MAX_WIDTH, "%*s%s\n", indent + 8, "", + dec_string) >= MAX_WIDTH) { + ret = WOLFSSL_FAILURE; } - if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { - return WOLFSSL_FAILURE; + + if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + ret = WOLFSSL_FAILURE; } + XMEMSET(tmp, 0, sizeof(tmp)); + + if (freeMp) { + mp_free(dec_num); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(dec_num, NULL, DYNAMIC_TYPE_BIGINT); + #endif } #if !defined(NO_SKID) - if (crl->crlList->extAuthKeyIdSet && crl->crlList->extAuthKeyId[0] != 0) { + if (ret == 0 && crl->crlList->extAuthKeyIdSet && + crl->crlList->extAuthKeyId[0] != 0) { word32 i; char val[5]; int valSz = 5; if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%s", indent + 4, "", "X509v3 Authority Key Identifier:") >= MAX_WIDTH) { - return WOLFSSL_FAILURE; + ret = WOLFSSL_FAILURE; } - XSTRNCAT(tmp, "\n", MAX_WIDTH - XSTRLEN(tmp) - 1); + if (ret == 0) { + XSTRNCAT(tmp, "\n", MAX_WIDTH - XSTRLEN(tmp) - 1); + } - if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { - return WOLFSSL_FAILURE; + if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + ret = WOLFSSL_FAILURE; } XMEMSET(tmp, 0, MAX_WIDTH); - if (XSNPRINTF(tmp, MAX_WIDTH - 1, "%*s%s", + if (ret == 0 && XSNPRINTF(tmp, MAX_WIDTH - 1, "%*s%s", indent + 8, "", "keyid") >= MAX_WIDTH) { - return WOLFSSL_FAILURE; + ret = WOLFSSL_FAILURE; } for (i = 0; i < XSTRLEN((char*)crl->crlList->extAuthKeyId); i++) { /* check if buffer is almost full */ - if (XSTRLEN(tmp) >= sizeof(tmp) - valSz) { + if (ret == 0 && XSTRLEN(tmp) >= sizeof(tmp) - valSz) { if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { - return WOLFSSL_FAILURE; + ret = WOLFSSL_FAILURE; } tmp[0] = '\0'; } - if (XSNPRINTF(val, (size_t)valSz, ":%02X", - crl->crlList->extAuthKeyId[i]) >= valSz) - { + if (ret == 0 && XSNPRINTF(val, (size_t)valSz, ":%02X", + crl->crlList->extAuthKeyId[i]) >= valSz) { WOLFSSL_MSG("buffer overrun"); - return WOLFSSL_FAILURE; + ret = WOLFSSL_FAILURE; + } + if (ret == 0) { + XSTRNCAT(tmp, val, valSz); } - XSTRNCAT(tmp, val, valSz); } - XSTRNCAT(tmp, "\n", XSTRLEN("\n") + 1); - if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { - return WOLFSSL_FAILURE; + if (ret == 0) { + XSTRNCAT(tmp, "\n", XSTRLEN("\n") + 1); + } + if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + ret = WOLFSSL_FAILURE; } } #endif - return WOLFSSL_SUCCESS; + if (ret == 0) { + ret = WOLFSSL_SUCCESS; + } + + return ret; } /* iterate through a CRL's Revoked Certs and print out in human @@ -9180,7 +9227,7 @@ void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl) } #endif /* HAVE_CRL && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */ -#ifdef OPENSSL_EXTRA +#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA) WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl) { if ((crl != NULL) && (crl->crlList != NULL) && @@ -9210,7 +9257,7 @@ int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key) return 0; } #endif -#endif /* OPENSSL_EXTRA */ +#endif /* HAVE_CRL && OPENSSL_EXTRA */ #ifdef OPENSSL_EXTRA diff --git a/tests/api.c b/tests/api.c index d4be8331f..180a939cd 100644 --- a/tests/api.c +++ b/tests/api.c @@ -42980,7 +42980,8 @@ static int test_wolfSSL_X509V3_set_ctx(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && \ - defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \ + defined(HAVE_CRL) WOLFSSL_X509V3_CTX ctx; WOLFSSL_X509* issuer = NULL; WOLFSSL_X509* subject = NULL; @@ -56410,7 +56411,7 @@ static void updateCrlCb(CrlInfo* old, CrlInfo* cnew) AssertTrue((f = XFOPEN(crl1, "rb")) != XBADFILE); AssertTrue(XFSEEK(f, 0, XSEEK_END) == 0); - AssertIntGE(sz = (size_t) XFTELL(f), 1); + AssertIntGE(sz = (word32) XFTELL(f), 1); AssertTrue(XFSEEK(f, 0, XSEEK_SET) == 0); AssertTrue( \ (crl1Buff = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)) != NULL); @@ -56420,7 +56421,7 @@ static void updateCrlCb(CrlInfo* old, CrlInfo* cnew) AssertTrue((f = XFOPEN(crlRevoked, "rb")) != XBADFILE); AssertTrue(XFSEEK(f, 0, XSEEK_END) == 0); - AssertIntGE(sz = (size_t) XFTELL(f), 1); + AssertIntGE(sz = (word32) XFTELL(f), 1); AssertTrue(XFSEEK(f, 0, XSEEK_SET) == 0); AssertTrue( \ (crlRevBuff = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)) != NULL); @@ -56441,7 +56442,8 @@ static void updateCrlCb(CrlInfo* old, CrlInfo* cnew) AssertIntEQ(crl1Info.lastDateFormat, old->lastDateFormat); AssertIntEQ(crl1Info.nextDateMaxLen, old->nextDateMaxLen); AssertIntEQ(crl1Info.nextDateFormat, old->nextDateFormat); - AssertIntEQ(crl1Info.crlNumber, old->crlNumber); + AssertIntEQ(XMEMCMP( + crl1Info.crlNumber, old->crlNumber, CRL_MAX_NUM_SZ), 0); AssertIntEQ(XMEMCMP( crl1Info.issuerHash, old->issuerHash, old->issuerHashLen), 0); AssertIntEQ(XMEMCMP( @@ -56455,7 +56457,8 @@ static void updateCrlCb(CrlInfo* old, CrlInfo* cnew) AssertIntEQ(crlRevInfo.lastDateFormat, cnew->lastDateFormat); AssertIntEQ(crlRevInfo.nextDateMaxLen, cnew->nextDateMaxLen); AssertIntEQ(crlRevInfo.nextDateFormat, cnew->nextDateFormat); - AssertIntEQ(crlRevInfo.crlNumber, cnew->crlNumber); + AssertIntEQ(XMEMCMP( + crlRevInfo.crlNumber, cnew->crlNumber, CRL_MAX_NUM_SZ), 0); AssertIntEQ(XMEMCMP( crlRevInfo.issuerHash, cnew->issuerHash, cnew->issuerHashLen), 0); AssertIntEQ(XMEMCMP( diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 690bca980..49f970525 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -40263,50 +40263,39 @@ static int ParseCRL_Extensions(DecodedCRL* dcrl, const byte* buf, return ret; } else { - if (length > 1) { - int i; - #ifdef WOLFSSL_SMALL_STACK - mp_int* m = (mp_int*)XMALLOC(sizeof(*m), NULL, - DYNAMIC_TYPE_BIGINT); - if (m == NULL) { - return MEMORY_E; - } - #else - mp_int m[1]; - #endif - - if (mp_init(m) != MP_OKAY) { - ret = MP_INIT_E; - } - - if (ret == 0) - ret = mp_read_unsigned_bin(m, buf + idx, length); - if (ret != MP_OKAY) - ret = BUFFER_E; - - if (ret == 0) { - dcrl->crlNumber = 0; - for (i = 0; i < (int)(*m).used; ++i) { - if (i > (CHAR_BIT * - (int)sizeof(word32) / DIGIT_BIT)) { - break; - } - dcrl->crlNumber |= ((word32)(*m).dp[i]) << - (DIGIT_BIT * i); - } - } - - mp_free(m); - #ifdef WOLFSSL_SMALL_STACK - XFREE(m, NULL, DYNAMIC_TYPE_BIGINT); - #endif - - if (ret != 0) - return ret; + DECL_MP_INT_SIZE_DYN(m, CRL_MAX_NUM_SZ * CHAR_BIT, + CRL_MAX_NUM_SZ * CHAR_BIT); + NEW_MP_INT_SIZE(m, CRL_MAX_NUM_SZ * CHAR_BIT, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + #ifdef MP_INT_SIZE_CHECK_NULL + if (m == NULL) { + ret = MEMORY_E; } - else if (length == 1) { - dcrl->crlNumber = buf[idx]; + #endif + + if (ret == 0 && ((ret = INIT_MP_INT_SIZE(m, CRL_MAX_NUM_SZ + * CHAR_BIT)) != MP_OKAY)) { + ret = MP_INIT_E; } + + if (ret == MP_OKAY) + ret = mp_read_unsigned_bin(m, buf + idx, length); + + if (ret != MP_OKAY) + ret = BUFFER_E; + + if (ret == MP_OKAY && mp_toradix(m, (char*)dcrl->crlNumber, + MP_RADIX_HEX) != MP_OKAY) + ret = BUFFER_E; + + if (ret == MP_OKAY) { + dcrl->crlNumberSet = 1; + } + + FREE_MP_INT_SIZE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret != MP_OKAY) + return ret; } } } @@ -40349,6 +40338,7 @@ static int ParseCRL_Extensions(DecodedCRL* dcrl, const byte* buf, word32 idx, ret = GetASN_Items(certExtASN, dataASN, certExtASN_Length, 0, buf, &idx, maxIdx); if (ret == 0) { + word32 localIdx = idx; /* OID in extension. */ word32 oid = dataASN[CERTEXTASN_IDX_OID].data.oid.sum; /* Length of extension data. */ @@ -40358,39 +40348,42 @@ static int ParseCRL_Extensions(DecodedCRL* dcrl, const byte* buf, word32 idx, #ifndef NO_SKID /* Parse Authority Key Id extension. * idx is at start of OCTET_STRING data. */ - ret = ParseCRL_AuthKeyIdExt(buf + idx, length, dcrl); + ret = ParseCRL_AuthKeyIdExt(buf + localIdx, length, dcrl); if (ret != 0) { WOLFSSL_MSG("\tcouldn't parse AuthKeyId extension"); } #endif } else if (oid == CRL_NUMBER_OID) { - #ifdef WOLFSSL_SMALL_STACK - mp_int* m = (mp_int*)XMALLOC(sizeof(*m), NULL, - DYNAMIC_TYPE_BIGINT); + DECL_MP_INT_SIZE_DYN(m, CRL_MAX_NUM_SZ * CHAR_BIT, + CRL_MAX_NUM_SZ * CHAR_BIT); + NEW_MP_INT_SIZE(m, CRL_MAX_NUM_SZ * CHAR_BIT, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + #ifdef MP_INT_SIZE_CHECK_NULL if (m == NULL) { ret = MEMORY_E; } - #else - mp_int m[1]; #endif - if (ret == 0) { - if (mp_init(m) != MP_OKAY) { + if (ret == 0 && (INIT_MP_INT_SIZE(m, CRL_MAX_NUM_SZ * CHAR_BIT) + != MP_OKAY)) { ret = MP_INIT_E; - } - } - if (ret == 0) { - ret = GetInt(m, buf, &idx, maxIdx); - } - if (ret == 0) { - dcrl->crlNumber = (int)m->dp[0]; } - mp_free(m); - #ifdef WOLFSSL_SMALL_STACK - XFREE(m, NULL, DYNAMIC_TYPE_BIGINT); - #endif + if (ret == 0) { + ret = GetInt(m, buf, &localIdx, maxIdx); + } + + if (ret == 0 && mp_toradix(m, (char*)dcrl->crlNumber, + MP_RADIX_HEX) != MP_OKAY) + ret = BUFFER_E; + + if (ret == 0) { + dcrl->crlNumberSet = 1; + } + + FREE_MP_INT_SIZE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); } /* TODO: check criticality */ /* Move index on to next extension. */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 52a075efd..b834f12df 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2548,6 +2548,8 @@ typedef struct CRL_Entry CRL_Entry; #error CRL_MAX_REVOKED_CERTS too big, max is 22000 #endif #endif + +#ifdef HAVE_CRL /* Complete CRL */ struct CRL_Entry { byte* toBeSigned; @@ -2560,6 +2562,7 @@ struct CRL_Entry { /* DupCRL_Entry copies data after the `verifyMutex` member. Using the mutex * as the marker because clang-tidy doesn't like taking the sizeof a * pointer. */ + byte crlNumber[CRL_MAX_NUM_SZ]; /* CRL number extension */ byte issuerHash[CRL_DIGEST_SIZE]; /* issuer hash */ /* byte crlHash[CRL_DIGEST_SIZE]; raw crl data hash */ /* restore the hash here if needed for optimized comparisons */ @@ -2587,10 +2590,10 @@ struct CRL_Entry { byte* sigParams; /* buffer with signature parameters */ #endif #if !defined(NO_SKID) && !defined(NO_ASN) - byte extAuthKeyIdSet; byte extAuthKeyId[KEYID_SIZE]; + byte extAuthKeyIdSet:1; /* Auth key identifier set indicator */ #endif - int crlNumber; /* CRL number extension */ + byte crlNumberSet:1; /* CRL number set indicator */ }; @@ -2643,6 +2646,7 @@ struct WOLFSSL_CRL { #endif void* heap; /* heap hint for dynamic memory */ }; +#endif #ifdef NO_ASN diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 908d5c6e8..45f94e69d 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -3749,6 +3749,7 @@ typedef int (*CbCrlIO)(WOLFSSL_CRL* crl, const char* url, int urlSz); #ifdef HAVE_CRL_UPDATE_CB typedef struct CrlInfo { + byte crlNumber[CRL_MAX_NUM_SZ]; byte *issuerHash; word32 issuerHashLen; byte *lastDate; @@ -3757,7 +3758,7 @@ typedef struct CrlInfo { byte *nextDate; word32 nextDateMaxLen; byte nextDateFormat; - sword32 crlNumber; + byte crlNumberSet:1; } CrlInfo; typedef void (*CbUpdateCRL)(CrlInfo* old, CrlInfo* cnew); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index f3913f367..a4f897c3b 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2610,6 +2610,11 @@ struct RevokedCert { byte revDateFormat; }; +#ifndef CRL_MAX_NUM_SZ +#define CRL_MAX_NUM_SZ 20 /* RFC5280 states that CRL number can be up to 20 */ +#endif /* octets long */ + + typedef struct DecodedCRL DecodedCRL; struct DecodedCRL { @@ -2622,6 +2627,7 @@ struct DecodedCRL { word32 sigParamsLength; /* length of signature parameters */ #endif byte* signature; /* pointer into raw source, not owned */ + byte crlNumber[CRL_MAX_NUM_SZ]; /* CRL number extension */ byte issuerHash[SIGNER_DIGEST_SIZE]; /* issuer name hash */ byte crlHash[SIGNER_DIGEST_SIZE]; /* raw crl data hash */ byte lastDate[MAX_DATE_SIZE]; /* last date updated */ @@ -2637,10 +2643,10 @@ struct DecodedCRL { int version; /* version of cert */ void* heap; #ifndef NO_SKID - byte extAuthKeyIdSet; - byte extAuthKeyId[SIGNER_DIGEST_SIZE]; /* Authority Key ID */ + byte extAuthKeyId[SIGNER_DIGEST_SIZE]; /* Authority Key ID */ + WC_BITFIELD extAuthKeyIdSet:1; /* Auth key identifier set indicator */ #endif - int crlNumber; /* CRL number extension */ + WC_BITFIELD crlNumberSet:1; /* CRL number set indicator */ }; WOLFSSL_LOCAL void InitDecodedCRL(DecodedCRL* dcrl, void* heap); From 29cf3eb84e338c5d6d948e3e3e0aa7a878034372 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 5 Jun 2025 09:18:18 +0400 Subject: [PATCH 02/16] linuxkm/lkcapi_sha_glue.c: refactor DRBG wrapper to instantiate one DRBG per core, to relieve contention. --- linuxkm/lkcapi_sha_glue.c | 101 +++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 29 deletions(-) diff --git a/linuxkm/lkcapi_sha_glue.c b/linuxkm/lkcapi_sha_glue.c index 647fb627c..0108bd66f 100644 --- a/linuxkm/lkcapi_sha_glue.c +++ b/linuxkm/lkcapi_sha_glue.c @@ -902,38 +902,65 @@ struct wc_swallow_the_semicolon #include struct wc_linuxkm_drbg_ctx { - wolfSSL_Mutex lock; - WC_RNG rng; + struct wc_rng_inst { + wolfSSL_Mutex lock; + WC_RNG rng; + } *rngs; /* one per CPU ID */ }; static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm) { struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_tfm_ctx(tfm); + unsigned int i; int ret; - ret = wc_InitMutex(&ctx->lock); - if (ret != 0) - return -EINVAL; + ctx->rngs = (struct wc_rng_inst *)malloc(sizeof(*ctx->rngs) * nr_cpu_ids); + if (! ctx->rngs) + return -ENOMEM; + XMEMSET(ctx->rngs, 0, sizeof(*ctx->rngs) * nr_cpu_ids); - /* Note the new DRBG instance is seeded, and later reseeded, from system - * get_random_bytes() via wc_GenerateSeed(). - */ - ret = wc_InitRng(&ctx->rng); - if (ret != 0) { - (void)wc_FreeMutex(&ctx->lock); - return -EINVAL; + for (i = 0; i < nr_cpu_ids; ++i) { + ret = wc_InitMutex(&ctx->rngs[i].lock); + if (ret != 0) { + ret = -EINVAL; + break; + } + + /* Note the new DRBG instance is seeded, and later reseeded, from system + * get_random_bytes() via wc_GenerateSeed(). + */ + ret = wc_InitRng(&ctx->rngs[i].rng); + if (ret != 0) { + ret = -EINVAL; + break; + } } - return 0; + if (ret != 0) { + for (i = 0; i < nr_cpu_ids; ++i) { + (void)wc_FreeMutex(&ctx->rngs[i].lock); + wc_FreeRng(&ctx->rngs[i].rng); + } + free(ctx->rngs); + ctx->rngs = NULL; + } + + return ret; } static void wc_linuxkm_drbg_exit_tfm(struct crypto_tfm *tfm) { struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_tfm_ctx(tfm); + unsigned int i; - wc_FreeRng(&ctx->rng); - - (void)wc_FreeMutex(&ctx->lock); + if (ctx->rngs) { + for (i = 0; i < nr_cpu_ids; ++i) { + (void)wc_FreeMutex(&ctx->rngs[i].lock); + wc_FreeRng(&ctx->rngs[i].rng); + } + free(ctx->rngs); + ctx->rngs = NULL; + } return; } @@ -944,24 +971,34 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm, { struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(tfm); int ret; + int my_cpu = + raw_smp_processor_id(); /* Note, core is not locked, so the actual core + * ID may change while executing, hence the + * mutex. + * The mutex is also needed to coordinate with + * wc_linuxkm_drbg_seed(), which seeds all + * instances. + */ + wolfSSL_Mutex *lock = &ctx->rngs[my_cpu].lock; + WC_RNG *rng = &ctx->rngs[my_cpu].rng; - wc_LockMutex(&ctx->lock); + wc_LockMutex(lock); if (slen > 0) { - ret = wc_RNG_DRBG_Reseed(&ctx->rng, src, slen); + ret = wc_RNG_DRBG_Reseed(rng, src, slen); if (ret != 0) { ret = -EINVAL; goto out; } } - ret = wc_RNG_GenerateBlock(&ctx->rng, dst, dlen); + ret = wc_RNG_GenerateBlock(rng, dst, dlen); if (ret != 0) ret = -EINVAL; out: - wc_UnLockMutex(&ctx->lock); + wc_UnLockMutex(lock); return ret; } @@ -971,22 +1008,28 @@ static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm, { struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(tfm); int ret; + unsigned int i; if (slen == 0) return 0; - wc_LockMutex(&ctx->lock); + for (i = 0; i < nr_cpu_ids; ++i) { + wolfSSL_Mutex *lock = &ctx->rngs[i].lock; + WC_RNG *rng = &ctx->rngs[i].rng; - ret = wc_RNG_DRBG_Reseed(&ctx->rng, seed, slen); - if (ret != 0) { - ret = -EINVAL; - goto out; + wc_LockMutex(lock); + + ret = wc_RNG_DRBG_Reseed(rng, seed, slen); + if (ret != 0) { + ret = -EINVAL; + } + + wc_UnLockMutex(lock); + + if (ret != 0) + break; } -out: - - wc_UnLockMutex(&ctx->lock); - return ret; } From dbc34352c70debf39a0138996122e3f05fd68a06 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 5 Jun 2025 16:31:46 +0400 Subject: [PATCH 03/16] linuxkm/lkcapi_sha_glue.c: in wc_linuxkm_drbg_seed(), prefix the supplied seed with the CPU ID of each DRBG, to avoid duplicate states; wolfcrypt/src/random.c: in Hash_DRBG_Generate(), always put digest[] on the stack even in WOLFSSL_SMALL_STACK configuration (it's only 32 bytes); configure.ac: default smallstackcache on when linuxkm-defaults. --- configure.ac | 8 +++++++- linuxkm/lkcapi_sha_glue.c | 16 +++++++++++++++- wolfcrypt/src/random.c | 10 ---------- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index e0b6d769c..e5cf76e83 100644 --- a/configure.ac +++ b/configure.ac @@ -7181,10 +7181,16 @@ then fi # Small Stack - Cache on object +if test "$ENABLED_LINUXKM_DEFAULTS" = "yes" +then + ENABLED_SMALL_STACK_CACHE_DEFAULT=yes +else + ENABLED_SMALL_STACK_CACHE_DEFAULT=no +fi AC_ARG_ENABLE([smallstackcache], [AS_HELP_STRING([--enable-smallstackcache],[Enable Small Stack Usage Caching (default: disabled)])], [ ENABLED_SMALL_STACK_CACHE=$enableval ], - [ ENABLED_SMALL_STACK_CACHE=no ] + [ ENABLED_SMALL_STACK_CACHE=$ENABLED_SMALL_STACK_CACHE_DEFAULT ] ) if test "x$ENABLED_SMALL_STACK_CACHE" = "xyes" diff --git a/linuxkm/lkcapi_sha_glue.c b/linuxkm/lkcapi_sha_glue.c index 0108bd66f..dadc7846a 100644 --- a/linuxkm/lkcapi_sha_glue.c +++ b/linuxkm/lkcapi_sha_glue.c @@ -1007,19 +1007,31 @@ static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen) { struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(tfm); + u8 *seed_copy = NULL; int ret; unsigned int i; if (slen == 0) return 0; + seed_copy = (u8 *)malloc(slen + 2); + if (! seed_copy) + return -ENOMEM; + XMEMCPY(seed_copy + 2, seed, slen); + for (i = 0; i < nr_cpu_ids; ++i) { wolfSSL_Mutex *lock = &ctx->rngs[i].lock; WC_RNG *rng = &ctx->rngs[i].rng; + /* perturb the seed with the CPU ID, so that no DRBG has the exact same + * seed. + */ + seed_copy[0] = (u8)(i >> 8); + seed_copy[1] = (u8)i; + wc_LockMutex(lock); - ret = wc_RNG_DRBG_Reseed(rng, seed, slen); + ret = wc_RNG_DRBG_Reseed(rng, seed_copy, slen + 2); if (ret != 0) { ret = -EINVAL; } @@ -1030,6 +1042,8 @@ static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm, break; } + free(seed_copy); + return ret; } diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 311d5a71c..f22a8ed6e 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -647,14 +647,7 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) return DRBG_NEED_RESEED; } else { - #ifndef WOLFSSL_SMALL_STACK byte digest[WC_SHA256_DIGEST_SIZE]; - #else - byte* digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap, - DYNAMIC_TYPE_DIGEST); - if (digest == NULL) - return DRBG_FAILURE; - #endif type = drbgGenerateH; reseedCtr = drbg->reseedCtr; @@ -692,9 +685,6 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) drbg->reseedCtr++; } ForceZero(digest, WC_SHA256_DIGEST_SIZE); - #ifdef WOLFSSL_SMALL_STACK - XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); - #endif } return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; From ae15693fa878d610a393942016f118ad8dfc7516 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Sat, 7 Jun 2025 07:07:20 +0400 Subject: [PATCH 04/16] linuxkm/lkcapi_sha_glue.c: in wc_linuxkm_drbg_generate() and wc_linuxkm_drbg_seed(), check retval from wc_LockMutex(). wolfcrypt/src/random.c: in Hash_DRBG_Generate(), restore smallstack path for digest[], but use non-smallstack path for WOLFSSL_LINUXKM. --- linuxkm/lkcapi_sha_glue.c | 20 ++++++++++---------- wolfcrypt/src/random.c | 10 ++++++++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/linuxkm/lkcapi_sha_glue.c b/linuxkm/lkcapi_sha_glue.c index dadc7846a..ca6b722e6 100644 --- a/linuxkm/lkcapi_sha_glue.c +++ b/linuxkm/lkcapi_sha_glue.c @@ -971,18 +971,17 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm, { struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(tfm); int ret; - int my_cpu = - raw_smp_processor_id(); /* Note, core is not locked, so the actual core - * ID may change while executing, hence the - * mutex. - * The mutex is also needed to coordinate with - * wc_linuxkm_drbg_seed(), which seeds all - * instances. - */ + /* Note, core is not locked, so the actual core ID may change while + * executing, hence the mutex. + * The mutex is also needed to coordinate with wc_linuxkm_drbg_seed(), which + * seeds all instances. + */ + int my_cpu = raw_smp_processor_id(); wolfSSL_Mutex *lock = &ctx->rngs[my_cpu].lock; WC_RNG *rng = &ctx->rngs[my_cpu].rng; - wc_LockMutex(lock); + if (wc_LockMutex(lock) != 0) + return -EINVAL; if (slen > 0) { ret = wc_RNG_DRBG_Reseed(rng, src, slen); @@ -1029,7 +1028,8 @@ static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm, seed_copy[0] = (u8)(i >> 8); seed_copy[1] = (u8)i; - wc_LockMutex(lock); + if (wc_LockMutex(lock) != 0) + return -EINVAL; ret = wc_RNG_DRBG_Reseed(rng, seed_copy, slen + 2); if (ret != 0) { diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index f22a8ed6e..cb62a3dcc 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -647,7 +647,14 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) return DRBG_NEED_RESEED; } else { + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_LINUXKM) + byte* digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap, + DYNAMIC_TYPE_DIGEST); + if (digest == NULL) + return DRBG_FAILURE; + #else byte digest[WC_SHA256_DIGEST_SIZE]; + #endif type = drbgGenerateH; reseedCtr = drbg->reseedCtr; @@ -685,6 +692,9 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) drbg->reseedCtr++; } ForceZero(digest, WC_SHA256_DIGEST_SIZE); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_LINUXKM) + XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); + #endif } return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; From 31490ab813a5aac096f50800c26c690d8ae586d2 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 10 Jun 2025 12:49:08 -0600 Subject: [PATCH 05/16] add sanity checks on pid with RNG --- CMakeLists.txt | 1 + configure.ac | 4 +- src/ssl.c | 40 +++++++++++- wolfcrypt/src/random.c | 126 ++++++++++++++++++++++--------------- wolfssl/wolfcrypt/random.h | 3 + 5 files changed, 118 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 688d9dc4e..a33712f03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,7 @@ check_function_exists("memset" HAVE_MEMSET) check_function_exists("socket" HAVE_SOCKET) check_function_exists("strftime" HAVE_STRFTIME) check_function_exists("__atomic_fetch_add" HAVE_C___ATOMIC) +check_function_exists("getpid" HAVE_GETPID) include(CheckSymbolExists) check_symbol_exists(isascii "ctype.h" HAVE_ISASCII) diff --git a/configure.ac b/configure.ac index e0b6d769c..7da6c7647 100644 --- a/configure.ac +++ b/configure.ac @@ -129,8 +129,8 @@ AC_CHECK_HEADER(assert.h, [AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSL_HAVE_ASSERT_H"],[ # check if functions of interest are linkable, but also check if # they're declared by the expected headers, and if not, supersede the # unusable positive from AC_CHECK_FUNCS(). -AC_CHECK_FUNCS([gethostbyname getaddrinfo gettimeofday gmtime_r gmtime_s inet_ntoa memset socket strftime atexit isascii]) -AC_CHECK_DECLS([gethostbyname, getaddrinfo, gettimeofday, gmtime_r, gmtime_s, inet_ntoa, memset, socket, strftime, atexit, isascii], [], [ +AC_CHECK_FUNCS([gethostbyname getaddrinfo gettimeofday gmtime_r gmtime_s inet_ntoa memset socket strftime atexit isascii getpid]) +AC_CHECK_DECLS([gethostbyname, getaddrinfo, gettimeofday, gmtime_r, gmtime_s, inet_ntoa, memset, socket, strftime, atexit, isascii, getpid], [], [ if test "$(eval echo \$"$(eval 'echo ac_cv_func_${as_decl_name}')")" = "yes" then AC_MSG_NOTICE([ note: earlier check for $(eval 'echo ${as_decl_name}') superseded.]) diff --git a/src/ssl.c b/src/ssl.c index bb1d1176c..e8f298d6f 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -25512,6 +25512,10 @@ int wolfSSL_RAND_Init(void) if (initGlobalRNG == 0) { ret = wc_InitRng(&globalRNG); if (ret == 0) { + #if defined(HAVE_GETPID) && defined(HAVE_FIPS) && \ + FIPS_VERSION3_LT(6,0,0))) + currentPid = getpid(); + #endif initGlobalRNG = 1; ret = WOLFSSL_SUCCESS; } @@ -25946,8 +25950,30 @@ int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num) return ret; } -/* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise - * WOLFSSL_FAILURE */ +#if defined(HAVE_GETPID) && defined(HAVE_FIPS) && FIPS_VERSION3_LT(6,0,0))) +/* In older FIPS bundles add check for reseed here since it does not exist in + * the older random.c certified files. */ +static pid_t currentPid = 0; + +/* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ +static int RandCheckReSeed() +{ + int ret = WOLFSSL_SUCCESS; + pid_t p; + + p = getpid(); + if (p != currentPid) { + currentPid = p; + if (wolfSSL_RAND_poll() != WOLFSSL_SUCCESS) { + ret = WOLFSSL_FAILURE; + } + } + return ret; +} +#endif + +/* returns WOLFSSL_SUCCESS (1) if the bytes generated are valid otherwise 0 + * on failure */ int wolfSSL_RAND_bytes(unsigned char* buf, int num) { int ret = 0; @@ -25990,6 +26016,16 @@ int wolfSSL_RAND_bytes(unsigned char* buf, int num) */ if (initGlobalRNG) { rng = &globalRNG; + + #if defined(HAVE_GETPID) && defined(HAVE_FIPS) && \ + FIPS_VERSION3_LT(6,0,0))) + if (RandCheckReSeed() != WOLFSSL_SUCCESS) { + wc_UnLockMutex(&globalRNGMutex); + WOLFSSL_MSG("Issue with check pid and reseed"); + return ret; + } + #endif + used_global = 1; } else { diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 311d5a71c..7370300ed 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1640,6 +1640,9 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, #else rng->heap = heap; #endif +#ifdef HAVE_GETPID + rng->pid = getpid(); +#endif #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) rng->devId = devId; #if defined(WOLF_CRYPTO_CB) @@ -1895,6 +1898,63 @@ int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz, return _InitRng(rng, nonce, nonceSz, heap, devId); } +#ifdef HAVE_HASHDRBG +static int PollAndReSeed(WC_RNG* rng) +{ + int ret = DRBG_NEED_RESEED; + int devId = INVALID_DEVID; +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + devId = rng->devId; +#endif + if (wc_RNG_HealthTestLocal(1, rng->heap, devId) == 0) { + #ifndef WOLFSSL_SMALL_STACK + byte newSeed[SEED_SZ + SEED_BLOCK_SZ]; + ret = DRBG_SUCCESS; + #else + byte* newSeed = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap, + DYNAMIC_TYPE_SEED); + ret = (newSeed == NULL) ? MEMORY_E : DRBG_SUCCESS; + #endif + if (ret == DRBG_SUCCESS) { + #ifdef WC_RNG_SEED_CB + if (seedCb == NULL) { + ret = DRBG_NO_SEED_CB; + } + else { + ret = seedCb(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ); + if (ret != 0) { + ret = DRBG_FAILURE; + } + } + #else + ret = wc_GenerateSeed(&rng->seed, newSeed, + SEED_SZ + SEED_BLOCK_SZ); + #endif + if (ret != 0) + ret = DRBG_FAILURE; + } + if (ret == DRBG_SUCCESS) + 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); + #ifdef WOLFSSL_SMALL_STACK + if (newSeed != NULL) { + ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ); + } + XFREE(newSeed, rng->heap, DYNAMIC_TYPE_SEED); + #else + ForceZero(newSeed, sizeof(newSeed)); + #endif + } + else { + ret = DRBG_CONT_FAILURE; + } + + return ret; +} +#endif /* place a generated block in output */ WOLFSSL_ABI @@ -1954,60 +2014,22 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) if (rng->status != DRBG_OK) return RNG_FAILURE_E; +#ifdef HAVE_GETPID + if (rng->pid != getpid()) { + rng->pid = getpid(); + ret = PollAndReSeed(rng); + if (ret != DRBG_SUCCESS) { + rng->status = DRBG_FAILED; + return RNG_FAILURE_E; + } + } +#endif + ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); if (ret == DRBG_NEED_RESEED) { - int devId = INVALID_DEVID; - #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) - devId = rng->devId; - #endif - if (wc_RNG_HealthTestLocal(1, rng->heap, devId) == 0) { - #ifndef WOLFSSL_SMALL_STACK - byte newSeed[SEED_SZ + SEED_BLOCK_SZ]; - ret = DRBG_SUCCESS; - #else - byte* newSeed = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap, - DYNAMIC_TYPE_SEED); - ret = (newSeed == NULL) ? MEMORY_E : DRBG_SUCCESS; - #endif - if (ret == DRBG_SUCCESS) { - #ifdef WC_RNG_SEED_CB - if (seedCb == NULL) { - ret = DRBG_NO_SEED_CB; - } - else { - ret = seedCb(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ); - if (ret != 0) { - ret = DRBG_FAILURE; - } - } - #else - ret = wc_GenerateSeed(&rng->seed, newSeed, - SEED_SZ + SEED_BLOCK_SZ); - #endif - if (ret != 0) - ret = DRBG_FAILURE; - } - if (ret == DRBG_SUCCESS) - 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); - if (ret == DRBG_SUCCESS) - ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); - - #ifdef WOLFSSL_SMALL_STACK - if (newSeed != NULL) { - ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ); - } - XFREE(newSeed, rng->heap, DYNAMIC_TYPE_SEED); - #else - ForceZero(newSeed, sizeof(newSeed)); - #endif - } - else { - ret = DRBG_CONT_FAILURE; - } + ret = PollAndReSeed(rng); + if (ret == DRBG_SUCCESS) + ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); } if (ret == DRBG_SUCCESS) { diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 5abd6c011..2b559bf55 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -189,6 +189,9 @@ struct WC_RNG { #endif byte status; #endif +#ifdef HAVE_GETPID + pid_t pid; +#endif #ifdef WOLFSSL_ASYNC_CRYPT WC_ASYNC_DEV asyncDev; #endif From fbbb6b7707f7f8ae1c38ab68daec0af02ee0208a Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 10 Jun 2025 14:15:38 -0600 Subject: [PATCH 06/16] add mutex locking and compat layer FIPS case --- src/ssl.c | 62 +++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index e8f298d6f..cd81c05dd 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -25500,6 +25500,12 @@ static int wolfSSL_RAND_InitMutex(void) #ifdef OPENSSL_EXTRA +#if defined(HAVE_GETPID) && defined(HAVE_FIPS) && FIPS_VERSION3_LT(6,0,0) +/* In older FIPS bundles add check for reseed here since it does not exist in + * the older random.c certified files. */ +static pid_t currentRandPid = 0; +#endif + /* Checks if the global RNG has been created. If not then one is created. * * Returns WOLFSSL_SUCCESS when no error is encountered. @@ -25513,8 +25519,8 @@ int wolfSSL_RAND_Init(void) ret = wc_InitRng(&globalRNG); if (ret == 0) { #if defined(HAVE_GETPID) && defined(HAVE_FIPS) && \ - FIPS_VERSION3_LT(6,0,0))) - currentPid = getpid(); + FIPS_VERSION3_LT(6,0,0) + currentRandPid = getpid(); #endif initGlobalRNG = 1; ret = WOLFSSL_SUCCESS; @@ -25950,28 +25956,6 @@ int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num) return ret; } -#if defined(HAVE_GETPID) && defined(HAVE_FIPS) && FIPS_VERSION3_LT(6,0,0))) -/* In older FIPS bundles add check for reseed here since it does not exist in - * the older random.c certified files. */ -static pid_t currentPid = 0; - -/* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ -static int RandCheckReSeed() -{ - int ret = WOLFSSL_SUCCESS; - pid_t p; - - p = getpid(); - if (p != currentPid) { - currentPid = p; - if (wolfSSL_RAND_poll() != WOLFSSL_SUCCESS) { - ret = WOLFSSL_FAILURE; - } - } - return ret; -} -#endif - /* returns WOLFSSL_SUCCESS (1) if the bytes generated are valid otherwise 0 * on failure */ int wolfSSL_RAND_bytes(unsigned char* buf, int num) @@ -26015,17 +25999,27 @@ int wolfSSL_RAND_bytes(unsigned char* buf, int num) * have the lock. */ if (initGlobalRNG) { - rng = &globalRNG; - #if defined(HAVE_GETPID) && defined(HAVE_FIPS) && \ - FIPS_VERSION3_LT(6,0,0))) - if (RandCheckReSeed() != WOLFSSL_SUCCESS) { + FIPS_VERSION3_LT(6,0,0) + pid_t p; + + p = getpid(); + if (p != currentRandPid) { wc_UnLockMutex(&globalRNGMutex); - WOLFSSL_MSG("Issue with check pid and reseed"); - return ret; + if (wolfSSL_RAND_poll() != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Issue with check pid and reseed"); + ret = WOLFSSL_FAILURE; + } + + /* reclaim lock after wolfSSL_RAND_poll */ + if (wc_LockMutex(&globalRNGMutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex rng"); + return ret; + } + currentRandPid = p; } #endif - + rng = &globalRNG; used_global = 1; } else { @@ -26101,6 +26095,11 @@ int wolfSSL_RAND_poll(void) } else { #ifdef HAVE_HASHDRBG + if (wc_LockMutex(&globalRNGMutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex rng"); + return ret; + } + ret = wc_RNG_DRBG_Reseed(&globalRNG, entropy, entropy_sz); if (ret != 0) { WOLFSSL_MSG("Error reseeding DRBG"); @@ -26109,6 +26108,7 @@ int wolfSSL_RAND_poll(void) else { ret = WOLFSSL_SUCCESS; } + wc_UnLockMutex(&globalRNGMutex); #else WOLFSSL_MSG("RAND_poll called with HAVE_HASHDRBG not set"); ret = WOLFSSL_FAILURE; From d0134f22121019a2f208f00c30097e6a79a8bf62 Mon Sep 17 00:00:00 2001 From: Ruby Martin Date: Tue, 27 May 2025 16:25:41 -0600 Subject: [PATCH 07/16] coverity: address reuse after free, add NULL checks --- tests/api.c | 80 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/tests/api.c b/tests/api.c index a049f9ad3..f736556da 100644 --- a/tests/api.c +++ b/tests/api.c @@ -20906,21 +20906,33 @@ static int test_wolfSSL_ASN1_TIME_adj(void) /* offset_sec = -45 * min;*/ ExpectNotNull(asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec)); - ExpectTrue(asn_time->type == asn_utc_time); - ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, - CTC_DATE_SIZE)); - date_str[CTC_DATE_SIZE] = '\0'; - ExpectIntEQ(0, XMEMCMP(date_str, "000222211500Z", 13)); + if (asn_time != NULL) { + ExpectTrue(asn_time->type == asn_utc_time); + ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, + CTC_DATE_SIZE)); + date_str[CTC_DATE_SIZE] = '\0'; + ExpectIntEQ(0, XMEMCMP(date_str, "000222211500Z", 13)); + if (asn_time != s) { + XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); + } + asn_time = NULL; + } /* negative offset */ offset_sec = -45 * mini; asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); ExpectNotNull(asn_time); - ExpectTrue(asn_time->type == asn_utc_time); - ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, - CTC_DATE_SIZE)); - date_str[CTC_DATE_SIZE] = '\0'; - ExpectIntEQ(0, XMEMCMP(date_str, "000222194500Z", 13)); + if (asn_time != NULL) { + ExpectTrue(asn_time->type == asn_utc_time); + ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, + CTC_DATE_SIZE)); + date_str[CTC_DATE_SIZE] = '\0'; + ExpectIntEQ(0, XMEMCMP(date_str, "000222194500Z", 13)); + if (asn_time != s) { + XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); + } + asn_time = NULL; + } XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); s = NULL; @@ -20937,11 +20949,17 @@ static int test_wolfSSL_ASN1_TIME_adj(void) offset_sec = 10 * mini; ExpectNotNull(asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec)); - ExpectTrue(asn_time->type == asn_gen_time); - ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, - CTC_DATE_SIZE)); - date_str[CTC_DATE_SIZE] = '\0'; - ExpectIntEQ(0, XMEMCMP(date_str, "20550313091000Z", 15)); + if (asn_time != NULL) { + ExpectTrue(asn_time->type == asn_gen_time); + ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, + CTC_DATE_SIZE)); + date_str[CTC_DATE_SIZE] = '\0'; + ExpectIntEQ(0, XMEMCMP(date_str, "20550313091000Z", 15)); + if (asn_time != s) { + XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); + } + asn_time = NULL; + } XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); s = NULL; @@ -20956,22 +20974,26 @@ static int test_wolfSSL_ASN1_TIME_adj(void) offset_sec = 45 * mini; ExpectNotNull(asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec)); - ExpectTrue(asn_time->type == asn_utc_time); - ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, - CTC_DATE_SIZE)); - date_str[CTC_DATE_SIZE] = '\0'; - ExpectIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); - XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); - asn_time = NULL; - + if (asn_time != NULL) { + ExpectTrue(asn_time->type == asn_utc_time); + ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, + CTC_DATE_SIZE)); + date_str[CTC_DATE_SIZE] = '\0'; + ExpectIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); + XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); + asn_time = NULL; + } ExpectNotNull(asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, offset_day, offset_sec)); - ExpectTrue(asn_time->type == asn_utc_time); - ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, - CTC_DATE_SIZE)); - date_str[CTC_DATE_SIZE] = '\0'; - ExpectIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); - XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); + if (asn_time != NULL) { + ExpectTrue(asn_time->type == asn_utc_time); + ExpectNotNull(XSTRNCPY(date_str, (const char*)&asn_time->data, + CTC_DATE_SIZE)); + date_str[CTC_DATE_SIZE] = '\0'; + ExpectIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); + XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); + asn_time = NULL; + } #endif return EXPECT_RESULT(); } From 4207affc72378bfbf3b3961b0b227d3d82d4adf4 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 10 Jun 2025 15:56:39 -0600 Subject: [PATCH 08/16] adding additional RAND test cases --- .github/workflows/os-check.yml | 1 + tests/api.c | 120 +++++++++++++++++++++++---------- 2 files changed, 87 insertions(+), 34 deletions(-) diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index e63918860..155172da9 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -48,6 +48,7 @@ jobs: '--enable-sniffer --enable-curve25519 --enable-curve448 --enable-enckeys CFLAGS=-DWOLFSSL_DH_EXTRA', '--enable-dtls --enable-dtls13 --enable-dtls-frag-ch --enable-dtls-mtu CPPFLAGS=-DWOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS', + '--enable-opensslall --enable-opensslextra CPPFLAGS=-DWC_RNG_SEED_CB', ] name: make check if: github.repository_owner == 'wolfssl' diff --git a/tests/api.c b/tests/api.c index a049f9ad3..6a6ded3ce 100644 --- a/tests/api.c +++ b/tests/api.c @@ -33105,6 +33105,12 @@ static int test_wolfSSL_RAND_bytes(void) const int size4 = RNG_MAX_BLOCK_LEN * 4; /* in bytes */ int max_bufsize; byte *my_buf = NULL; +#if defined(HAVE_GETPID) + byte seed[16] = {0}; + byte randbuf[8] = {0}; + int pipefds[2] = {0}; + pid_t pid = 0; +#endif /* sanity check */ ExpectIntEQ(RAND_bytes(NULL, 16), 0); @@ -33124,6 +33130,42 @@ static int test_wolfSSL_RAND_bytes(void) ExpectIntEQ(RAND_bytes(my_buf, size3), 1); ExpectIntEQ(RAND_bytes(my_buf, size4), 1); +#if defined(OPENSSL_EXTRA) && defined(HAVE_GETPID) + XMEMSET(seed, 0, sizeof(seed)); + RAND_cleanup(); + + /* No global methods set. */ + ExpectIntEQ(RAND_seed(seed, sizeof(seed)), 1); + + ExpectIntEQ(pipe(pipefds), 0); + pid = fork(); + ExpectIntGE(pid, 0); + if (pid == 0) { + ssize_t n_written = 0; + + /* Child process. */ + close(pipefds[0]); + RAND_bytes(randbuf, sizeof(randbuf)); + n_written = write(pipefds[1], randbuf, sizeof(randbuf)); + close(pipefds[1]); + exit(n_written == sizeof(randbuf) ? 0 : 1); + } + else { + /* Parent process. */ + word64 childrand64 = 0; + int waitstatus = 0; + + close(pipefds[1]); + ExpectIntEQ(RAND_bytes(randbuf, sizeof(randbuf)), 1); + ExpectIntEQ(read(pipefds[0], &childrand64, sizeof(childrand64)), + sizeof(childrand64)); + ExpectBufNE(randbuf, &childrand64, sizeof(randbuf)); + close(pipefds[0]); + waitpid(pid, &waitstatus, 0); + } + RAND_cleanup(); +#endif + XFREE(my_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); @@ -33156,50 +33198,60 @@ static int test_wolfSSL_RAND(void) } +#ifdef WC_RNG_SEED_CB +static int wc_DummyGenerateSeed(OS_Seed* os, byte* output, word32 sz) +{ + word32 i; + for (i = 0; i < sz; i++ ) + output[i] = (byte)i; + + (void)os; + + return 0; +} +#endif /* WC_RNG_SEED_CB */ + + static int test_wolfSSL_RAND_poll(void) { EXPECT_DECLS; -#if defined(OPENSSL_EXTRA) && defined(__linux__) - byte seed[16] = {0}; - byte randbuf[8] = {0}; - int pipefds[2] = {0}; - pid_t pid = 0; +#if defined(OPENSSL_EXTRA) + byte seed[16]; + byte rand1[16]; +#ifdef WC_RNG_SEED_CB + byte rand2[16]; +#endif XMEMSET(seed, 0, sizeof(seed)); - - /* No global methods set. */ ExpectIntEQ(RAND_seed(seed, sizeof(seed)), 1); + ExpectIntEQ(RAND_poll(), 1); + ExpectIntEQ(RAND_bytes(rand1, 16), 1); + RAND_cleanup(); - ExpectIntEQ(pipe(pipefds), 0); - pid = fork(); - ExpectIntGE(pid, 0); - if (pid == 0) - { - ssize_t n_written = 0; +#ifdef WC_RNG_SEED_CB + /* Test with custom seed and poll */ + wc_SetSeed_Cb(wc_DummyGenerateSeed); - /* Child process. */ - close(pipefds[0]); - RAND_poll(); - RAND_bytes(randbuf, sizeof(randbuf)); - n_written = write(pipefds[1], randbuf, sizeof(randbuf)); - close(pipefds[1]); - exit(n_written == sizeof(randbuf) ? 0 : 1); - } - else - { - /* Parent process. */ - word64 childrand64 = 0; - int waitstatus = 0; + ExpectIntEQ(RAND_seed(seed, sizeof(seed)), 1); + ExpectIntEQ(RAND_bytes(rand1, 16), 1); + RAND_cleanup(); - close(pipefds[1]); - ExpectIntEQ(RAND_poll(), 1); - ExpectIntEQ(RAND_bytes(randbuf, sizeof(randbuf)), 1); - ExpectIntEQ(read(pipefds[0], &childrand64, sizeof(childrand64)), sizeof(childrand64)); - ExpectBufNE(randbuf, &childrand64, sizeof(randbuf)); - close(pipefds[0]); - waitpid(pid, &waitstatus, 0); - } + /* test that the same value is generated twice with dummy seed function */ + ExpectIntEQ(RAND_seed(seed, sizeof(seed)), 1); + ExpectIntEQ(RAND_bytes(rand2, 16), 1); + ExpectIntEQ(XMEMCMP(rand1, rand2, 16), 0); + RAND_cleanup(); + + /* test that doing a poll is reseeding RNG */ + ExpectIntEQ(RAND_seed(seed, sizeof(seed)), 1); + ExpectIntEQ(RAND_poll(), 1); + ExpectIntEQ(RAND_bytes(rand2, 16), 1); + ExpectIntNE(XMEMCMP(rand1, rand2, 16), 0); + + /* reset the seed function used */ + wc_SetSeed_Cb(wc_GenerateSeed); +#endif RAND_cleanup(); ExpectIntEQ(RAND_egd(NULL), -1); From 47cf634965a3aabe82fd97a8feed9efd6688e34a Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 10 Jun 2025 16:12:09 -0600 Subject: [PATCH 09/16] add a way to restore previous pid behavior --- .github/workflows/os-check.yml | 2 ++ src/ssl.c | 11 ++++++----- tests/api.c | 4 ++++ wolfcrypt/src/random.c | 4 ++-- wolfssl/wolfcrypt/random.h | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index 155172da9..fd2cbb3d4 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -49,6 +49,8 @@ jobs: '--enable-dtls --enable-dtls13 --enable-dtls-frag-ch --enable-dtls-mtu CPPFLAGS=-DWOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS', '--enable-opensslall --enable-opensslextra CPPFLAGS=-DWC_RNG_SEED_CB', + '--enable-opensslall --enable-opensslextra + CPPFLAGS='-DWC_RNG_SEED_CB -DWOLFSSL_NO_GETPID'', ] name: make check if: github.repository_owner == 'wolfssl' diff --git a/src/ssl.c b/src/ssl.c index cd81c05dd..80589ad5c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -25500,7 +25500,8 @@ static int wolfSSL_RAND_InitMutex(void) #ifdef OPENSSL_EXTRA -#if defined(HAVE_GETPID) && defined(HAVE_FIPS) && FIPS_VERSION3_LT(6,0,0) +#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID) && \ + defined(HAVE_FIPS) && FIPS_VERSION3_LT(6,0,0) /* In older FIPS bundles add check for reseed here since it does not exist in * the older random.c certified files. */ static pid_t currentRandPid = 0; @@ -25518,8 +25519,8 @@ int wolfSSL_RAND_Init(void) if (initGlobalRNG == 0) { ret = wc_InitRng(&globalRNG); if (ret == 0) { - #if defined(HAVE_GETPID) && defined(HAVE_FIPS) && \ - FIPS_VERSION3_LT(6,0,0) + #if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID) && \ + defined(HAVE_FIPS) && FIPS_VERSION3_LT(6,0,0) currentRandPid = getpid(); #endif initGlobalRNG = 1; @@ -25999,8 +26000,8 @@ int wolfSSL_RAND_bytes(unsigned char* buf, int num) * have the lock. */ if (initGlobalRNG) { - #if defined(HAVE_GETPID) && defined(HAVE_FIPS) && \ - FIPS_VERSION3_LT(6,0,0) + #if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID) && \ + defined(HAVE_FIPS) && FIPS_VERSION3_LT(6,0,0) pid_t p; p = getpid(); diff --git a/tests/api.c b/tests/api.c index 6a6ded3ce..68f51aad2 100644 --- a/tests/api.c +++ b/tests/api.c @@ -33159,7 +33159,11 @@ static int test_wolfSSL_RAND_bytes(void) ExpectIntEQ(RAND_bytes(randbuf, sizeof(randbuf)), 1); ExpectIntEQ(read(pipefds[0], &childrand64, sizeof(childrand64)), sizeof(childrand64)); + #ifdef WOLFSSL_NO_GETPID + ExpectBufEQ(randbuf, &childrand64, sizeof(randbuf)); + #else ExpectBufNE(randbuf, &childrand64, sizeof(randbuf)); + #endif close(pipefds[0]); waitpid(pid, &waitstatus, 0); } diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 7370300ed..3bc5f2d76 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1640,7 +1640,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, #else rng->heap = heap; #endif -#ifdef HAVE_GETPID +#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID) rng->pid = getpid(); #endif #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) @@ -2014,7 +2014,7 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) if (rng->status != DRBG_OK) return RNG_FAILURE_E; -#ifdef HAVE_GETPID +#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID) if (rng->pid != getpid()) { rng->pid = getpid(); ret = PollAndReSeed(rng); diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 2b559bf55..a566956f1 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -189,7 +189,7 @@ struct WC_RNG { #endif byte status; #endif -#ifdef HAVE_GETPID +#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID) pid_t pid; #endif #ifdef WOLFSSL_ASYNC_CRYPT From d66863d0ac760ae7adc1910d53787d4202a2de38 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 3 Jun 2025 09:00:51 +1000 Subject: [PATCH 10/16] Aarch64 XFENCE Use sb instruction instead of isb if available. --- configure.ac | 26 ++++++++++++++++++++++++++ wolfcrypt/src/wc_port.c | 9 +++++++++ wolfssl/wolfcrypt/cpuid.h | 18 ++++++++++-------- wolfssl/wolfcrypt/wc_port.h | 18 +++++++++++++++++- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index e0b6d769c..5ec88e8b7 100644 --- a/configure.ac +++ b/configure.ac @@ -3228,6 +3228,26 @@ then ENABLED_ARMASM_CRYPTO_SM4=yes ENABLED_ARMASM_PLUS=yes ;; + barrier-sb) + case $host_cpu in + *aarch64*) + ;; + *) + AC_MSG_ERROR([SB instructions only available on Aarch64 v8.5+ CPU.]) + break;; + esac + ENABLED_ARMASM_BARRIER_SB=yes + ;; + barrier-detect) + case $host_cpu in + *aarch64*) + ;; + *) + AC_MSG_ERROR([SB instructions only available on Aarch64 v8.5+ CPU.]) + break;; + esac + ENABLED_ARMASM_BARRIER_DETECT=yes + ;; *) AC_MSG_ERROR([Invalid choice of ARM asm inclusions (yes, sha512-crypto, sha3-crypto): $ENABLED_ARMASM.]) break;; @@ -3370,6 +3390,12 @@ fi if test "$ENABLED_ARMASM_SM4" = "yes"; then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ARMASM_CRYPTO_SM4" fi +if test "$ENABLED_ARMASM_BARRIER_SB" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ARMASM_BARRIER_SB" +fi +if test "$ENABLED_ARMASM_BARRIER_DETECT" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ARMASM_BARRIER_DETECT" +fi if test "$ENABLED_ARMASM_CRYPTO" = "unknown"; then ENABLED_ARMASM_CRYPTO=no fi diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index ee876752e..6abc118b5 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -25,6 +25,7 @@ #include #endif +#include #ifdef HAVE_ECC #include #endif @@ -145,6 +146,10 @@ /* prevent multiple mutex initializations */ static volatile int initRefCount = 0; +#if defined(__aarch64__) && defined(WOLFSSL_ARMASM_BARRIER_DETECT) +int aarch64_use_sb = 0; +#endif + /* Used to initialize state for wolfcrypt return 0 on success */ @@ -155,6 +160,10 @@ int wolfCrypt_Init(void) if (initRefCount == 0) { WOLFSSL_ENTER("wolfCrypt_Init"); + #if defined(__aarch64__) && defined(WOLFSSL_ARMASM_BARRIER_DETECT) + aarch64_use_sb = IS_AARCH64_SB(cpuid_get_flags()); + #endif + #ifdef WOLFSSL_CHECK_MEM_ZERO /* Initialize the mutex for access to the list of memory locations that * must be freed. */ diff --git a/wolfssl/wolfcrypt/cpuid.h b/wolfssl/wolfcrypt/cpuid.h index bb883cb45..e4a0499d2 100644 --- a/wolfssl/wolfcrypt/cpuid.h +++ b/wolfssl/wolfcrypt/cpuid.h @@ -70,14 +70,15 @@ #elif defined(HAVE_CPUID_AARCH64) - #define CPUID_AES 0x0001 - #define CPUID_PMULL 0x0002 - #define CPUID_SHA256 0x0004 - #define CPUID_SHA512 0x0008 - #define CPUID_RDM 0x0010 - #define CPUID_SHA3 0x0020 - #define CPUID_SM3 0x0040 - #define CPUID_SM4 0x0080 + #define CPUID_AES 0x0001 /* AES enc/dec */ + #define CPUID_PMULL 0x0002 /* Carryless multiplication */ + #define CPUID_SHA256 0x0004 /* SHA-256 digest */ + #define CPUID_SHA512 0x0008 /* SHA-512 digest */ + #define CPUID_RDM 0x0010 /* SQRDMLAH and SQRDMLSH */ + #define CPUID_SHA3 0x0020 /* SHA-3 digest */ + #define CPUID_SM3 0x0040 /* SM3 digest */ + #define CPUID_SM4 0x0080 /* SM4 enc/dec */ + #define CPUID_SB 0x0100 /* Speculation barrier */ #define IS_AARCH64_AES(f) ((f) & CPUID_AES) #define IS_AARCH64_PMULL(f) ((f) & CPUID_PMULL) @@ -87,6 +88,7 @@ #define IS_AARCH64_SHA3(f) ((f) & CPUID_SHA3) #define IS_AARCH64_SM3(f) ((f) & CPUID_SM3) #define IS_AARCH64_SM4(f) ((f) & CPUID_SM4) + #define IS_AARCH64_SB(f) ((f) & CPUID_SB) #endif diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index db17cb506..5385edee7 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -1536,8 +1536,24 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void); #define XFENCE() WC_DO_NOTHING #elif defined (__i386__) || defined(__x86_64__) #define XFENCE() XASM_VOLATILE("lfence") - #elif (defined (__arm__) && (__ARM_ARCH > 6)) || defined(__aarch64__) + #elif defined (__arm__) && (__ARM_ARCH > 6) #define XFENCE() XASM_VOLATILE("isb") + #elif defined(__aarch64__) + /* Change ".inst 0xd50330ff" to "sb" when compilers support it. */ + #ifdef WOLFSSL_ARMASM_BARRIER_SB + #define XFENCE() XASM_VOLATILE(".inst 0xd50330ff") + #elif defined(WOLFSSL_ARMASM_BARRIER_DETECT) + extern int aarch64_use_sb; + #define XFENCE() \ + do { \ + if (aarch64_use_sb) \ + XASM_VOLATILE(".inst 0xd50330ff"); \ + else \ + XASM_VOLATILE("isb"); \ + } while (0) + #else + #define XFENCE() XASM_VOLATILE("isb") + #endif #elif defined(__riscv) #define XFENCE() XASM_VOLATILE("fence") #elif defined(__PPC__) || defined(__POWERPC__) From 8ee1f8f287710fe15150a06dc9b39296b9da8c9e Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Wed, 11 Jun 2025 10:43:47 -0600 Subject: [PATCH 11/16] add macro guard on test case --- tests/api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/api.c b/tests/api.c index 68f51aad2..099c6e0a5 100644 --- a/tests/api.c +++ b/tests/api.c @@ -33202,7 +33202,7 @@ static int test_wolfSSL_RAND(void) } -#ifdef WC_RNG_SEED_CB +#if defined(WC_RNG_SEED_CB) && defined(OPENSSL_EXTRA) static int wc_DummyGenerateSeed(OS_Seed* os, byte* output, word32 sz) { word32 i; From b78f8a4ed6f54a6d6030a357eecb2cf89f0b218e Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Thu, 12 Jun 2025 15:55:56 -0600 Subject: [PATCH 12/16] fix for perl module version used with nginx test --- .github/workflows/nginx.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nginx.yml b/.github/workflows/nginx.yml index 868a02aba..c85161a0e 100644 --- a/.github/workflows/nginx.yml +++ b/.github/workflows/nginx.yml @@ -122,7 +122,28 @@ jobs: - name: Install dependencies run: | - sudo cpan -iT Proc::Find Net::SSLeay IO::Socket::SSL + sudo cpan -iT Proc::Find + + # Locking in the version of SSLeay used with testing + - name: Download and install Net::SSLeay 1.94 manually + run: | + curl -LO https://www.cpan.org/modules/by-module/Net/CHRISN/Net-SSLeay-1.94.tar.gz + tar -xzf Net-SSLeay-1.94.tar.gz + cd Net-SSLeay-1.94 + perl Makefile.PL + make + sudo make install + + # SSL version 2.091 changes '' return to undef causing test case to fail. + # Locking in the test version to use as 2.090 + - name: Download and install IO::Socket::SSL 2.090 manually + run: | + curl -LO https://www.cpan.org/modules/by-module/IO/IO-Socket-SSL-2.090.tar.gz + tar -xzf IO-Socket-SSL-2.090.tar.gz + cd IO-Socket-SSL-2.090 + perl Makefile.PL + make + sudo make install - name: Checkout wolfssl-nginx uses: actions/checkout@v4 From bb5291aa5e36909c27ac3a364e87694d7e56acc0 Mon Sep 17 00:00:00 2001 From: jordan Date: Fri, 13 Jun 2025 00:45:12 -0500 Subject: [PATCH 13/16] linuxkm: don't toggle fips_enabled. --- .wolfssl_known_macro_extras | 1 + linuxkm/lkcapi_ecdh_glue.c | 21 +++-- linuxkm/lkcapi_ecdsa_glue.c | 25 ++++-- linuxkm/lkcapi_glue.c | 165 +++++++++++++++++++++++++----------- 4 files changed, 151 insertions(+), 61 deletions(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 93007391a..e1f7b789e 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -294,6 +294,7 @@ LIBWOLFSSL_VERSION_GIT_HASH_DATE LIBWOLFSSL_VERSION_GIT_ORIGIN LIBWOLFSSL_VERSION_GIT_SHORT_HASH LIBWOLFSSL_VERSION_GIT_TAG +LINUXKM_DONT_FORCE_FIPS_ENABLED LINUXKM_FPU_STATES_FOLLOW_THREADS LINUXKM_LKCAPI_PRIORITY_ALLOW_MASKING LINUX_CYCLE_COUNT diff --git a/linuxkm/lkcapi_ecdh_glue.c b/linuxkm/lkcapi_ecdh_glue.c index fe4edfb01..c21afdaaf 100644 --- a/linuxkm/lkcapi_ecdh_glue.c +++ b/linuxkm/lkcapi_ecdh_glue.c @@ -885,12 +885,23 @@ static int linuxkm_test_ecdh_nist_driver(const char * driver, */ tfm = crypto_alloc_kpp(driver, 0, 0); if (IS_ERR(tfm)) { - pr_err("error: allocating kpp algorithm %s failed: %ld\n", - driver, PTR_ERR(tfm)); - if (PTR_ERR(tfm) == -ENOMEM) - test_rc = MEMORY_E; + #if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ + !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) + if ((PTR_ERR(tfm) == -ENOENT) && fips_enabled) { + pr_info("info: skipping unsupported kpp algorithm %s: %ld\n", + driver, PTR_ERR(tfm)); + test_rc = NOT_COMPILED_IN; + } else - test_rc = BAD_FUNC_ARG; + #endif + { + pr_err("error: allocating kpp algorithm %s failed: %ld\n", + driver, PTR_ERR(tfm)); + if (PTR_ERR(tfm) == -ENOMEM) + test_rc = MEMORY_E; + else + test_rc = BAD_FUNC_ARG; + } tfm = NULL; goto test_ecdh_nist_end; } diff --git a/linuxkm/lkcapi_ecdsa_glue.c b/linuxkm/lkcapi_ecdsa_glue.c index 487935e9b..5f42dfb86 100644 --- a/linuxkm/lkcapi_ecdsa_glue.c +++ b/linuxkm/lkcapi_ecdsa_glue.c @@ -727,12 +727,27 @@ static int linuxkm_test_ecdsa_nist_driver(const char * driver, */ tfm = crypto_alloc_akcipher(driver, 0, 0); if (IS_ERR(tfm)) { - pr_err("error: allocating akcipher algorithm %s failed: %ld\n", - driver, PTR_ERR(tfm)); - if (PTR_ERR(tfm) == -ENOMEM) - test_rc = MEMORY_E; + #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \ + defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ + !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) + /* ecdsa was not recognized as fips_allowed before linux v6.3 + * in kernel crypto/testmgr.c, and the kernel will block + * its allocation if fips_enabled is set. */ + if ((PTR_ERR(tfm) == -ENOENT) && fips_enabled) { + pr_info("info: skipping unsupported akcipher algorithm %s: %ld\n", + driver, PTR_ERR(tfm)); + test_rc = NOT_COMPILED_IN; + } else - test_rc = BAD_FUNC_ARG; + #endif + { + pr_err("error: allocating akcipher algorithm %s failed: %ld\n", + driver, PTR_ERR(tfm)); + if (PTR_ERR(tfm) == -ENOMEM) + test_rc = MEMORY_E; + else + test_rc = BAD_FUNC_ARG; + } tfm = NULL; goto test_ecdsa_nist_end; } diff --git a/linuxkm/lkcapi_glue.c b/linuxkm/lkcapi_glue.c index e13105338..005e9f946 100644 --- a/linuxkm/lkcapi_glue.c +++ b/linuxkm/lkcapi_glue.c @@ -222,6 +222,11 @@ WC_MAYBE_UNUSED static int check_shash_driver_masking(struct crypto_shash *tfm, static int linuxkm_lkcapi_register(void); static int linuxkm_lkcapi_unregister(void); +#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ + !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) +static int enabled_fips = 0; +#endif + static ssize_t install_algs_handler(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { @@ -261,6 +266,14 @@ static ssize_t deinstall_algs_handler(struct kobject *kobj, struct kobj_attribut if (ret != 0) return ret; +#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ + !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) + if (enabled_fips) { + pr_info("wolfCrypt: restoring fips_enabled to off."); + enabled_fips = fips_enabled = 0; + } +#endif + return count; } @@ -305,10 +318,6 @@ static int linuxkm_lkcapi_register(void) { int ret = -1; int seen_err = 0; -#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ - !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) - int enabled_fips = 0; -#endif ret = linuxkm_lkcapi_sysfs_install(); if (ret) @@ -321,12 +330,14 @@ static int linuxkm_lkcapi_register(void) */ disable_setkey_warnings = 1; #endif -#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ - !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) +#if !defined(LINUXKM_DONT_FORCE_FIPS_ENABLED) && \ + defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ + !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) if (! fips_enabled) { - /* temporarily assert system-wide FIPS status, to disable FIPS-forbidden + /* assert system-wide FIPS status, to disable FIPS-forbidden * test vectors and fuzzing from the CRYPTO_MANAGER. */ + pr_info("wolfCrypt: changing fips_enabled from 0 to 1 for FIPS module."); enabled_fips = fips_enabled = 1; } #endif @@ -365,6 +376,59 @@ static int linuxkm_lkcapi_register(void) } \ } while (0) +#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ + !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) +/* Same as above, but allow for option to skip problematic algs that are + * not consistently labeled fips_allowed in crypto/testmgr.c, and hence + * may be rejected by the kernel at runtime if is_fips is true. */ +#define REGISTER_ALG_OPTIONAL(alg, alg_class, tester) do {\ + if (! alg ## _loaded) { \ + ret = (crypto_register_ ## alg_class)(&(alg)); \ + if (ret) { \ + if (fips_enabled && (ret == NOT_COMPILED_IN)) { \ + pr_info("wolfCrypt: skipping FIPS-incompatible alg %s.\n", \ + (alg).base.cra_driver_name); \ + } \ + else { \ + seen_err = ret; \ + pr_err("ERROR: crypto_register_" #alg_class \ + " for %s failed " \ + "with return code %d.\n", \ + (alg).base.cra_driver_name, ret); \ + } \ + } else { \ + ret = (tester()); \ + if (ret) { \ + if (fips_enabled && (ret == NOT_COMPILED_IN)) { \ + pr_info("wolfCrypt: skipping FIPS-incompatible alg %s.\n", \ + (alg).base.cra_driver_name); \ + } \ + else { \ + seen_err = -EINVAL; \ + pr_err("ERROR: wolfCrypt self-test for %s failed " \ + "with return code %d.\n", \ + (alg).base.cra_driver_name, ret); \ + } \ + (crypto_unregister_ ## alg_class)(&(alg)); \ + if (! (alg.base.cra_flags & CRYPTO_ALG_DEAD)) { \ + pr_err("ERROR: alg %s not _DEAD " \ + "after crypto_unregister_%s -- " \ + "marking as loaded despite test failure.", \ + (alg).base.cra_driver_name, \ + #alg_class); \ + alg ## _loaded = 1; \ + ++linuxkm_lkcapi_n_registered; \ + } \ + } else { \ + alg ## _loaded = 1; \ + ++linuxkm_lkcapi_n_registered; \ + WOLFKM_INSTALL_NOTICE(alg) \ + } \ + } \ + } \ + } while (0) +#endif /* HAVE_FIPS && CONFIG_CRYPTO_MANAGER && etc.. */ + /* We always register the derivative/composite algs first, to assure that * the kernel doesn't synthesize them dynamically from our primitives. */ @@ -464,7 +528,6 @@ static int linuxkm_lkcapi_register(void) #endif #ifdef LINUXKM_LKCAPI_REGISTER_ECDSA - #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \ defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_FIPS) && \ defined(CONFIG_CRYPTO_MANAGER) && \ @@ -473,30 +536,43 @@ static int linuxkm_lkcapi_register(void) * ecdsa was not recognized as fips_allowed before linux v6.3 * in kernel crypto/testmgr.c. */ - fips_enabled = 0; - #endif + #if defined(LINUXKM_ECC192) + REGISTER_ALG_OPTIONAL(ecdsa_nist_p192, akcipher, + linuxkm_test_ecdsa_nist_p192); + #endif /* LINUXKM_ECC192 */ - #if defined(LINUXKM_ECC192) - REGISTER_ALG(ecdsa_nist_p192, akcipher, - linuxkm_test_ecdsa_nist_p192); - #endif /* LINUXKM_ECC192 */ + REGISTER_ALG_OPTIONAL(ecdsa_nist_p256, akcipher, + linuxkm_test_ecdsa_nist_p256); - REGISTER_ALG(ecdsa_nist_p256, akcipher, - linuxkm_test_ecdsa_nist_p256); + REGISTER_ALG_OPTIONAL(ecdsa_nist_p384, akcipher, + linuxkm_test_ecdsa_nist_p384); - REGISTER_ALG(ecdsa_nist_p384, akcipher, - linuxkm_test_ecdsa_nist_p384); + #if defined(HAVE_ECC521) + REGISTER_ALG_OPTIONAL(ecdsa_nist_p521, akcipher, + linuxkm_test_ecdsa_nist_p521); + #endif /* HAVE_ECC521 */ + #else + #if defined(LINUXKM_ECC192) + REGISTER_ALG(ecdsa_nist_p192, akcipher, + linuxkm_test_ecdsa_nist_p192); + #endif /* LINUXKM_ECC192 */ - #if defined(HAVE_ECC521) - REGISTER_ALG(ecdsa_nist_p521, akcipher, - linuxkm_test_ecdsa_nist_p521); - #endif /* HAVE_ECC521 */ + REGISTER_ALG(ecdsa_nist_p256, akcipher, + linuxkm_test_ecdsa_nist_p256); + + REGISTER_ALG(ecdsa_nist_p384, akcipher, + linuxkm_test_ecdsa_nist_p384); + + #if defined(HAVE_ECC521) + REGISTER_ALG(ecdsa_nist_p521, akcipher, + linuxkm_test_ecdsa_nist_p521); + #endif /* HAVE_ECC521 */ + #endif /* if linux < 6.3 && HAVE_FIPS && etc.. */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \ defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_FIPS) && \ defined(CONFIG_CRYPTO_MANAGER) && \ !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) - fips_enabled = 1; #endif #endif /* LINUXKM_LKCAPI_REGISTER_ECDSA */ @@ -514,33 +590,24 @@ static int linuxkm_lkcapi_register(void) * Given the above, and given we're not actually relying on the crypto * manager for FIPS self tests, and given the FIPS ECDH implementation passes * the non-FIPS ECDH crypto manager tests, the pragmatic solution we settle - * on here for ECDH is to always clear fips_enabled in target kernels that - * have it. + * on here is for ECDH loading to be optional when fips and fips tests are + * enabled. Failures because of !fips_allowed are skipped over. */ - #if defined(CONFIG_CRYPTO_FIPS) && \ defined(CONFIG_CRYPTO_MANAGER) && \ !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) - fips_enabled = 0; - #endif - - #if defined(LINUXKM_ECC192) - REGISTER_ALG(ecdh_nist_p192, kpp, - linuxkm_test_ecdh_nist_p192); - #endif /* LINUXKM_ECC192 */ - - REGISTER_ALG(ecdh_nist_p256, kpp, - linuxkm_test_ecdh_nist_p256); - - REGISTER_ALG(ecdh_nist_p384, kpp, - linuxkm_test_ecdh_nist_p384); - - #if defined(CONFIG_CRYPTO_FIPS) && \ - defined(CONFIG_CRYPTO_MANAGER) && \ - !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) - fips_enabled = 1; - #endif - + #if defined(LINUXKM_ECC192) + REGISTER_ALG_OPTIONAL(ecdh_nist_p192, kpp, linuxkm_test_ecdh_nist_p192); + #endif /* LINUXKM_ECC192 */ + REGISTER_ALG_OPTIONAL(ecdh_nist_p256, kpp, linuxkm_test_ecdh_nist_p256); + REGISTER_ALG_OPTIONAL(ecdh_nist_p384, kpp, linuxkm_test_ecdh_nist_p384); + #else + #if defined(LINUXKM_ECC192) + REGISTER_ALG(ecdh_nist_p192, kpp, linuxkm_test_ecdh_nist_p192); + #endif /* LINUXKM_ECC192 */ + REGISTER_ALG(ecdh_nist_p256, kpp, linuxkm_test_ecdh_nist_p256); + REGISTER_ALG(ecdh_nist_p384, kpp, linuxkm_test_ecdh_nist_p384); + #endif /* CONFIG_CRYPTO_FIPS && etc.. */ #endif /* LINUXKM_LKCAPI_REGISTER_ECDH */ #ifdef LINUXKM_LKCAPI_REGISTER_RSA @@ -625,12 +692,8 @@ static int linuxkm_lkcapi_register(void) #endif /* LINUXKM_LKCAPI_REGISTER_DH */ #undef REGISTER_ALG +#undef REGISTER_ALG_OPTIONAL -#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ - !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) - if (enabled_fips) - fips_enabled = 0; -#endif #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS disable_setkey_warnings = 0; #endif From b6b58a957b2798d98cab428572b6026044592469 Mon Sep 17 00:00:00 2001 From: jordan Date: Fri, 13 Jun 2025 01:45:47 -0500 Subject: [PATCH 14/16] linuxkm: add missing WC_NO_ERR_TRACE. --- linuxkm/lkcapi_glue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linuxkm/lkcapi_glue.c b/linuxkm/lkcapi_glue.c index 005e9f946..84dc0f85b 100644 --- a/linuxkm/lkcapi_glue.c +++ b/linuxkm/lkcapi_glue.c @@ -385,7 +385,7 @@ static int linuxkm_lkcapi_register(void) if (! alg ## _loaded) { \ ret = (crypto_register_ ## alg_class)(&(alg)); \ if (ret) { \ - if (fips_enabled && (ret == NOT_COMPILED_IN)) { \ + if (fips_enabled && (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN))) { \ pr_info("wolfCrypt: skipping FIPS-incompatible alg %s.\n", \ (alg).base.cra_driver_name); \ } \ @@ -399,7 +399,7 @@ static int linuxkm_lkcapi_register(void) } else { \ ret = (tester()); \ if (ret) { \ - if (fips_enabled && (ret == NOT_COMPILED_IN)) { \ + if (fips_enabled && (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN))) { \ pr_info("wolfCrypt: skipping FIPS-incompatible alg %s.\n", \ (alg).base.cra_driver_name); \ } \ From 8181561f0f15d2f52d994c79e2cd156e09167005 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 13 Jun 2025 07:17:37 -0700 Subject: [PATCH 15/16] Fix for syntax error in os-check.yml added in PR #8867. --- .github/workflows/os-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index fd2cbb3d4..9cb948101 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -50,7 +50,7 @@ jobs: --enable-dtls-mtu CPPFLAGS=-DWOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS', '--enable-opensslall --enable-opensslextra CPPFLAGS=-DWC_RNG_SEED_CB', '--enable-opensslall --enable-opensslextra - CPPFLAGS='-DWC_RNG_SEED_CB -DWOLFSSL_NO_GETPID'', + CPPFLAGS=''-DWC_RNG_SEED_CB -DWOLFSSL_NO_GETPID'' ', ] name: make check if: github.repository_owner == 'wolfssl' From ff1baf0ae7a0fdd0da66ad7fcf5812ede2fb3109 Mon Sep 17 00:00:00 2001 From: Koji Takeda Date: Mon, 9 Jun 2025 16:08:22 +0900 Subject: [PATCH 16/16] Apply stronger salt length for PBES2 --- wolfcrypt/src/pkcs12.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index 3116fe5bf..f6bb6b573 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -1830,6 +1830,8 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, word32 totalSz = 0; int ret; byte* pkcs8Key = NULL; + byte salt[PKCS5V2_SALT_SZ]; /* PKCS5V2_SALT_SZ > PKCS5_SALT_SZ */ + word32 saltSz = 0; int vPKCS = -1; int outAlgo = -1; @@ -1875,9 +1877,13 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, &hmacOid)) < 0) { return ret; } + saltSz = (outAlgo != PBES2) ? PKCS5_SALT_SZ : PKCS5V2_SALT_SZ; + if ((ret = wc_RNG_GenerateBlock(rng, salt, saltSz)) < 0) { + return ret; + } ret = TraditionalEnc_ex(key, keySz, pkcs8Key, &sz, pass, passSz, - vPKCS, outAlgo, blkOid, NULL, 0, itt, hmacOid, rng, heap); + vPKCS, outAlgo, blkOid, salt, saltSz, itt, hmacOid, rng, heap); } if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { *outSz = sz + MAX_LENGTH_SZ + 1;