diff --git a/src/dtls13.c b/src/dtls13.c index 070fc2e9f2..5a367be879 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -1823,6 +1823,13 @@ int Dtls13CheckEpoch(WOLFSSL* ssl, enum HandShakeType type) } break; case end_of_early_data: + /* RFC 9147 5.6.1: EndOfEarlyData is not used in DTLS 1.3. Its + * receipt must terminate the connection with an + * unexpected_message alert. */ + WOLFSSL_MSG("EndOfEarlyData not valid in DTLS 1.3"); + SendAlert(ssl, alert_fatal, unexpected_message); + WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E); + return SANITY_MSG_E; case message_hash: case no_shake: default: diff --git a/src/internal.c b/src/internal.c index 5914aa4203..790bbf5acd 100644 --- a/src/internal.c +++ b/src/internal.c @@ -3519,6 +3519,16 @@ void InitSuitesHashSigAlgo(byte* hashSigAlgo, int haveSig, int tls1_2, int tls1_3, int keySz, word16* len) { word16 idx = 0; +#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || defined(WOLFSSL_ALLOW_TLS_SHA1)) + /* RFC 9155 deprecates SHA-1 signatures for TLS 1.2. Offer them only for a + * TLS 1.0/1.1 handshake unless the operator opts in with + * WOLFSSL_ALLOW_TLS_SHA1. */ + #ifdef WOLFSSL_ALLOW_TLS_SHA1 + int offerSha1Sig = 1; + #else + int offerSha1Sig = !tls1_2; + #endif +#endif (void)tls1_2; (void)tls1_3; @@ -3559,7 +3569,10 @@ void InitSuitesHashSigAlgo(byte* hashSigAlgo, int haveSig, int tls1_2, #endif #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ defined(WOLFSSL_ALLOW_TLS_SHA1)) - AddSuiteHashSigAlgo(hashSigAlgo, sha_mac, ecc_dsa_sa_algo, keySz, &idx); + if (offerSha1Sig) { + AddSuiteHashSigAlgo(hashSigAlgo, sha_mac, ecc_dsa_sa_algo, keySz, + &idx); + } #endif #endif #ifdef HAVE_ED25519 @@ -3625,7 +3638,9 @@ void InitSuitesHashSigAlgo(byte* hashSigAlgo, int haveSig, int tls1_2, #endif #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ defined(WOLFSSL_ALLOW_TLS_SHA1)) - AddSuiteHashSigAlgo(hashSigAlgo, sha_mac, rsa_sa_algo, keySz, &idx); + if (offerSha1Sig) { + AddSuiteHashSigAlgo(hashSigAlgo, sha_mac, rsa_sa_algo, keySz, &idx); + } #endif } @@ -18037,6 +18052,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #endif /* KEEP_PEER_CERT */ + /* Enforced by default (RFC 5280 4.2.1.3 / RFC 8446 4.4.2.4: + * keyEncipherment/digitalSignature and serverAuth/clientAuth EKU + * on TLS certs). IGNORE_KEY_EXTENSIONS is a deliberate, + * RFC-non-conformant opt-out; see the macro list at the top of + * wolfcrypt/src/asn.c. */ #ifndef IGNORE_KEY_EXTENSIONS #if defined(OPENSSL_EXTRA) /* when compatibility layer is turned on and no verify is @@ -24712,6 +24732,12 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) * DTLS handshake message */ ssl->dtls_timeout = ssl->dtls_timeout_init; } + else { + if (SendFatalAlertOnly(ssl, ret) + == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) { + ret = SOCKET_ERROR_E; + } + } } #endif /* WOLFSSL_DTLS13 */ } diff --git a/src/pk_ec.c b/src/pk_ec.c index d71f0d22d6..778478344f 100644 --- a/src/pk_ec.c +++ b/src/pk_ec.c @@ -5349,6 +5349,10 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen, ret = 0; } } + else { + WOLFSSL_MSG("i2d_ECDSA_SIG failed"); + ret = WOLFSSL_FATAL_ERROR; + } #endif /* WOLF_CRYPTO_CB_ONLY_ECC */ } diff --git a/src/sniffer.c b/src/sniffer.c index a5bdf54d38..f952241a52 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -564,15 +564,27 @@ typedef struct SnifferSession { } SnifferSession; +/* The session, server, and keylog secret tables below are qualified + * THREAD_LS_T. When thread-local storage is genuinely available each thread + * owns a private copy of these tables, so their lookups and list mutations + * need no mutex. THREAD_LS_T is only a real thread-local qualifier when + * HAVE_THREAD_LS is defined and NO_THREAD_LS is not; otherwise the tables are + * process-shared globals that must be locked. HAVE_C___ATOMIC by itself does + * not make the tables thread-local, so the lock elision is gated on both. */ +#if defined(HAVE_C___ATOMIC) && defined(HAVE_THREAD_LS) && \ + !defined(NO_THREAD_LS) + #define SNIFFER_LOCKLESS_TABLES +#endif + /* Sniffer Server List and mutex */ static THREAD_LS_T SnifferServer* ServerList = NULL; -#ifndef HAVE_C___ATOMIC +#ifndef SNIFFER_LOCKLESS_TABLES static WC_THREADSHARED wolfSSL_Mutex ServerListMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(ServerListMutex); #endif /* Session Hash Table, mutex, and count */ static THREAD_LS_T SnifferSession* SessionTable[HASH_SIZE]; -#ifndef HAVE_C___ATOMIC +#ifndef SNIFFER_LOCKLESS_TABLES static WC_THREADSHARED wolfSSL_Mutex SessionMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(SessionMutex); #endif static THREAD_LS_T int SessionCount = 0; @@ -641,7 +653,7 @@ static void UpdateMissedDataSessions(void) NOLOCK_INC_STAT(x); UNLOCK_STAT(); } while (0) #endif /* WOLFSSL_SNIFFER_STATS */ -#ifdef HAVE_C___ATOMIC +#ifdef SNIFFER_LOCKLESS_TABLES #define LOCK_SESSION() WC_DO_NOTHING #define UNLOCK_SESSION() WC_DO_NOTHING #define LOCK_SERVER_LIST() WC_DO_NOTHING @@ -682,7 +694,7 @@ void ssl_InitSniffer_ex(int devId) { wolfSSL_Init(); #ifndef WOLFSSL_MUTEX_INITIALIZER -#ifndef HAVE_C___ATOMIC +#ifndef SNIFFER_LOCKLESS_TABLES wc_InitMutex(&ServerListMutex); wc_InitMutex(&SessionMutex); #endif @@ -908,7 +920,7 @@ void ssl_FreeSniffer(void) #ifndef WOLFSSL_SNIFFER_NO_RECOVERY wc_FreeMutex(&RecoveryMutex); #endif -#ifndef HAVE_C___ATOMIC +#ifndef SNIFFER_LOCKLESS_TABLES wc_FreeMutex(&SessionMutex); wc_FreeMutex(&ServerListMutex); #endif @@ -5222,14 +5234,14 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, SnifferSession* previous = 0; SnifferSession* current; word32 row = rowHint; -#ifndef HAVE_C___ATOMIC +#ifndef SNIFFER_LOCKLESS_TABLES int haveLock = 0; #endif Trace(REMOVE_SESSION_STR); if (ipInfo && tcpInfo) row = SessionHash(ipInfo, tcpInfo); -#ifndef HAVE_C___ATOMIC +#ifndef SNIFFER_LOCKLESS_TABLES else haveLock = 1; #endif @@ -5237,7 +5249,7 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, if (row >= HASH_SIZE) return; -#ifndef HAVE_C___ATOMIC +#ifndef SNIFFER_LOCKLESS_TABLES if (!haveLock) { LOCK_SESSION(); } @@ -5259,7 +5271,7 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, current = current->next; } -#ifndef HAVE_C___ATOMIC +#ifndef SNIFFER_LOCKLESS_TABLES if (!haveLock) { UNLOCK_SESSION(); } @@ -7439,13 +7451,13 @@ typedef struct SecretNode { static THREAD_LS_T SecretNode* secretHashTable[WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE] = {NULL}; -#ifndef HAVE_C___ATOMIC +#ifndef SNIFFER_LOCKLESS_TABLES static WC_THREADSHARED wolfSSL_Mutex secretListMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(secretListMutex); #endif static unsigned int secretHashFunction(unsigned char* clientRandom); -#ifdef HAVE_C___ATOMIC +#ifdef SNIFFER_LOCKLESS_TABLES #define LOCK_SECRET_LIST() WC_DO_NOTHING #define UNLOCK_SECRET_LIST() WC_DO_NOTHING #else diff --git a/src/ssl_api_ext.c b/src/ssl_api_ext.c index 2e4a8952f1..a1d9843508 100644 --- a/src/ssl_api_ext.c +++ b/src/ssl_api_ext.c @@ -554,7 +554,15 @@ int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count) * @param [in] ssl SSL/TLS object. * @param [in] protocol_name_list Comma-separated list of protocol names. * @param [in] protocol_name_listSz Length of the list in bytes. - * @param [in] options Bitmask of ALPN options. + * @param [in] options Bitmask of ALPN options. A mismatch + * behavior must be set or BAD_FUNC_ARG is returned. + * WOLFSSL_ALPN_FAILED_ON_MISMATCH sends the fatal + * no_application_protocol alert and fails the handshake when no + * protocol matches, per RFC 7301 section 3.2. + * WOLFSSL_ALPN_CONTINUE_ON_MISMATCH instead continues without an + * agreed protocol like OpenSSL. That does not send the alert and is + * therefore not RFC 7301 compliant, so use it only for OpenSSL + * interop. * @return WOLFSSL_SUCCESS on success. * @return BAD_FUNC_ARG when an argument is NULL, the list is too long or * options are unsupported. diff --git a/src/ssl_certman.c b/src/ssl_certman.c index d712e3b459..28dd7b1c85 100644 --- a/src/ssl_certman.c +++ b/src/ssl_certman.c @@ -3213,6 +3213,10 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) WOLFSSL_MSG("\tCan't add as CA if not actually one"); ret = NOT_CA_ERROR; } + /* Enforced by default. ALLOW_INVALID_CERTSIGN is a deliberate, + * RFC-non-conformant opt-out for interop with deployed certs that carry + * malformed keyUsage; see the macro list at the top of + * wolfcrypt/src/asn.c. */ #ifndef ALLOW_INVALID_CERTSIGN else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA && !cert->selfSigned && cert->extKeyUsageSet && diff --git a/src/tls.c b/src/tls.c index 661410b8e4..1f19c46035 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1957,8 +1957,10 @@ static int ALPN_find_match(WOLFSSL *ssl, TLSX **pextension, if (sel == NULL) { WOLFSSL_MSG("No ALPN protocol match"); - /* do nothing if no protocol match between client and server and option - is set to continue (like OpenSSL) */ + /* The caller explicitly opted out of failing on mismatch by passing + * WOLFSSL_ALPN_CONTINUE_ON_MISMATCH, so continue without an agreed + * protocol like OpenSSL. This deliberately skips the RFC 7301 section + * 3.2 fatal no_application_protocol alert. */ if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) { WOLFSSL_MSG("Continue on mismatch"); } @@ -6401,6 +6403,18 @@ static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, const byte* input, return ret; } +/* tmp_keys holds a copy of the session cipher and MAC keys, so wipe the + * struct before freeing it, matching the ForceZero of ssl->keys on connection + * teardown. */ +static void TLSX_SecureRenegotiation_Free(SecureRenegotiation* data, void* heap) +{ + if (data != NULL) { + ForceZero(data, sizeof(SecureRenegotiation)); + } + XFREE(data, heap, DYNAMIC_TYPE_TLSX); + (void)heap; +} + int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap) { int ret = 0; @@ -6446,7 +6460,7 @@ int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap) #endif /* HAVE_SERVER_RENEGOTIATION_INFO */ -#define SCR_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX) +#define SCR_FREE_ALL TLSX_SecureRenegotiation_Free #define SCR_GET_SIZE TLSX_SecureRenegotiation_GetSize #define SCR_WRITE TLSX_SecureRenegotiation_Write #define SCR_PARSE TLSX_SecureRenegotiation_Parse @@ -15192,7 +15206,7 @@ void TLSX_FreeAll(TLSX* list, void* heap) case TLSX_RENEGOTIATION_INFO: WOLFSSL_MSG("Secure Renegotiation extension free"); - SCR_FREE_ALL(extension->data, heap); + SCR_FREE_ALL((SecureRenegotiation*)extension->data, heap); break; case TLSX_SESSION_TICKET: diff --git a/tests/api.c b/tests/api.c index 7cf9225e49..0eb785a475 100644 --- a/tests/api.c +++ b/tests/api.c @@ -19470,6 +19470,12 @@ static int test_wolfSSL_sigalg_info(void) word16 len = 0; word16 idx = 0; int allSigAlgs = SIG_ECDSA | SIG_RSA | SIG_SM2 | SIG_FALCON | SIG_MLDSA; +#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || defined(WOLFSSL_ALLOW_TLS_SHA1)) + int sawSha1 = 0; +#endif +#ifndef WOLFSSL_ALLOW_TLS_SHA1 + int tls13 = 0; +#endif InitSuitesHashSigAlgo(hashSigAlgo, allSigAlgs, 1, 1, 0xFFFFFFFF, &len); for (idx = 0; idx < len; idx += 2) { @@ -19495,6 +19501,37 @@ static int test_wolfSSL_sigalg_info(void) ExpectIntNE(hashAlgo, 0); } + /* RFC 9155 deprecates SHA-1 signatures for TLS 1.2, and RFC 8446 forbids + * them for TLS 1.3. When the negotiated version is TLS 1.2 or higher + * (tls1_2 argument set, whether or not tls1_3 is also set) the SHA-1 + * schemes must not be offered unless the operator opts in with + * WOLFSSL_ALLOW_TLS_SHA1. */ +#ifndef WOLFSSL_ALLOW_TLS_SHA1 + for (tls13 = 0; tls13 <= 1; tls13++) { + InitSuitesHashSigAlgo(hashSigAlgo, allSigAlgs, 1, tls13, 0xFFFFFFFF, + &len); + for (idx = 0; idx < len; idx += 2) { + ExpectFalse((hashSigAlgo[idx] == sha_mac) && + ((hashSigAlgo[idx + 1] == rsa_sa_algo) || + (hashSigAlgo[idx + 1] == ecc_dsa_sa_algo))); + } + } +#endif + + /* For a TLS 1.0/1.1 handshake the SHA-1 schemes remain available when + * they are compiled in. */ +#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || defined(WOLFSSL_ALLOW_TLS_SHA1)) + InitSuitesHashSigAlgo(hashSigAlgo, allSigAlgs, 0, 0, 0xFFFFFFFF, &len); + for (idx = 0; idx < len; idx += 2) { + if ((hashSigAlgo[idx] == sha_mac) && + ((hashSigAlgo[idx + 1] == rsa_sa_algo) || + (hashSigAlgo[idx + 1] == ecc_dsa_sa_algo))) { + sawSha1 = 1; + } + } + ExpectIntEQ(sawSha1, 1); +#endif + #endif return EXPECT_RESULT(); } diff --git a/tests/api/test_dtls13.c b/tests/api/test_dtls13.c index 7752fe739c..a46a6a0c91 100644 --- a/tests/api/test_dtls13.c +++ b/tests/api/test_dtls13.c @@ -1073,6 +1073,7 @@ int test_dtls13_epochs(void) { WOLFSSL* ssl = NULL; byte input[20]; word32 inOutIdx = 0; + WOLFSSL_ALERT_HISTORY alertHistory; XMEMSET(input, 0, sizeof(input)); @@ -1107,6 +1108,11 @@ int test_dtls13_epochs(void) { ExpectIntEQ(Dtls13CheckEpoch(ssl, key_update), SANITY_MSG_E); ExpectIntEQ(Dtls13CheckEpoch(ssl, session_ticket), SANITY_MSG_E); ExpectIntEQ(Dtls13CheckEpoch(ssl, end_of_early_data), SANITY_MSG_E); + /* RFC 9147 5.6.1: EndOfEarlyData is not used in DTLS 1.3 and its receipt + * must terminate the connection with an unexpected_message alert. */ + ExpectIntEQ(wolfSSL_get_alert_history(ssl, &alertHistory), WOLFSSL_SUCCESS); + ExpectIntEQ(alertHistory.last_tx.level, alert_fatal); + ExpectIntEQ(alertHistory.last_tx.code, unexpected_message); ExpectIntEQ(Dtls13CheckEpoch(ssl, message_hash), SANITY_MSG_E); ExpectIntEQ(Dtls13CheckEpoch(ssl, no_shake), SANITY_MSG_E); diff --git a/tests/api/test_ossl_x509_acert.c b/tests/api/test_ossl_x509_acert.c index e468aa0a6f..d1c133055c 100644 --- a/tests/api/test_ossl_x509_acert.c +++ b/tests/api/test_ossl_x509_acert.c @@ -104,6 +104,22 @@ static int do_acert_verify_test(const char * acert_file, return 0; } + +#if !defined(NO_ASN_TIME) && !defined(NO_ASN_TIME_CHECK) +/* Return a fixed time after the notAfter date of certs/acert/acert.pem + * (2028-01-01), used to exercise attribute certificate validity period + * enforcement without depending on the real system clock. */ +static time_t acert_expired_time_cb(time_t* t) +{ + time_t expired = (time_t)1893456000; /* 2030-01-01 00:00:00 UTC */ + + if (t != NULL) { + *t = expired; + } + + return expired; +} +#endif /* !NO_ASN_TIME && !NO_ASN_TIME_CHECK */ #endif int test_wolfSSL_X509_ACERT_verify(void) @@ -140,6 +156,17 @@ int test_wolfSSL_X509_ACERT_verify(void) } ExpectIntEQ(rc, 0); + +#if !defined(NO_ASN_TIME) && !defined(NO_ASN_TIME_CHECK) + /* Override the current time to be past the acert's notAfter date. A + * cert with a valid signature must now fail verification because its + * validity period no longer includes the current time (RFC 5755). */ + ExpectIntEQ(wc_SetTimeCb(acert_expired_time_cb), 0); + ExpectIntEQ(do_acert_verify_test(acerts[0], pkeys[0], 0), 0); + /* Always restore the real time source, even if the check above failed, + * so subsequent tests are unaffected. */ + wc_SetTimeCb(NULL); +#endif /* !NO_ASN_TIME && !NO_ASN_TIME_CHECK */ #endif return EXPECT_RESULT(); } diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 525f5f562c..6646bf5fc0 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -133,8 +133,17 @@ ASN Options: * NO_STRICT_ECDSA_LEN: Allow non-strict ECDSA signature length * NO_WOLFSSL_CM_VERIFY: Disable cert manager verify callback * NO_WOLFSSL_SKIP_TRAILING_PAD: Don't skip trailing padding + * ALLOW_INVALID_CERTSIGN: Opt-in, RFC 5280 non-conformant. Accept a + * certificate that asserts keyCertSign without the + * cA basic-constraint (RFC 5280 4.2.1.9), and a CA + * whose present keyUsage extension omits keyCertSign + * (RFC 5280 6.1.4). Off by default; enforcement is + * active in a stock build. Intended for interop with + * deployed certs that carry malformed keyUsage + * (e.g. the Mosquitto integration). * ALLOW_SELFSIGNED_INVALID_CERTSIGN: Allow self-signed certs - * without keyCertSign in keyUsage + * without keyCertSign in keyUsage. Narrower opt-in + * than ALLOW_INVALID_CERTSIGN (self-signed only). * ALLOW_V1_EXTENSIONS: Allow extensions in v1 certificates * USE_WOLF_VALIDDATE: Use wolfSSL date validation * WC_ASN_RUNTIME_DATE_CHECK_CONTROL: Runtime control of date checking @@ -150,7 +159,13 @@ ASN Options: * WOLFSSL_SEP: Enable SubjectEntryPoint extension * WOLFSSL_EKU_OID: Enable Extended Key Usage OID support * WOLFSSL_ACERT: Enable attribute certificate support - * IGNORE_KEY_EXTENSIONS: Ignore key usage extensions + * IGNORE_KEY_EXTENSIONS: Opt-in, RFC non-conformant. Suppress all key-usage + * and extended-key-usage enforcement: the TLS + * keyEncipherment/digitalSignature checks and the + * serverAuth/clientAuth EKU checks (ProcessPeerCerts, + * src/internal.c), and the cRLSign requirement on a + * CRL-signing CA (VerifyCRL_Signature, below). Off by + * default; enforcement is active in a stock build. * IGNORE_NETSCAPE_CERT_TYPE: Ignore Netscape cert type extension * WOLFSSL_ALLOW_CRIT_AIA: Allow critical Authority Info Access * WOLFSSL_ALLOW_CRIT_AKID: Allow critical Auth Key Identifier @@ -24326,7 +24341,10 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm, #endif #ifndef ALLOW_INVALID_CERTSIGN - /* https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9 + /* Enforced by default. ALLOW_INVALID_CERTSIGN is a deliberate, + * RFC-non-conformant opt-out for interop with deployed certs that + * carry malformed keyUsage; see the macro list at the top of file. + * https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9 * If the cA boolean is not asserted, then the keyCertSign bit in the * key usage extension MUST NOT be asserted. */ if (!cert->isCA && cert->extKeyUsageSet && @@ -37032,6 +37050,9 @@ int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned, int sigParamsSz, Signer *ca, void* heap) { /* try to confirm/verify signature */ + /* Enforced by default (RFC 5280 4.2.1.3 / 5.2: a CRL issuer MUST assert + * cRLSign). IGNORE_KEY_EXTENSIONS is a deliberate, RFC-non-conformant + * opt-out; see the macro list at the top of file. */ #ifndef IGNORE_KEY_EXTENSIONS if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { WOLFSSL_MSG("CA cannot sign CRLs"); @@ -40288,7 +40309,7 @@ int ParseX509Acert(DecodedAcert* acert, int verify) if ((verify != NO_VERIFY) && (verify != VERIFY_SKIP_DATE) && (! AsnSkipDateCheck)) { - badDate = ASN_BEFORE_DATE_E; + badDate = ASN_AFTER_DATE_E; } } @@ -40589,6 +40610,16 @@ int VerifyX509Acert(const byte* der, word32 derSz, } #endif + /* Enforce the attribute certificate validity period (RFC 5755 section + * 5.4). CheckDate returns the appropriate date error, or 0, and honors + * the runtime skip-date control internally. */ + if (ret == 0) { + ret = CheckDate(&dataASN[ACERT_IDX_ACINFO_VALIDITY_NOTB_GT], ASN_BEFORE); + } + if (ret == 0) { + ret = CheckDate(&dataASN[ACERT_IDX_ACINFO_VALIDITY_NOTA_GT], ASN_AFTER); + } + if (ret == 0) { /* Finally, do the verification. */ ret = acert_sig_verify(acinfo, acinfoSz, diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index b71810d318..a80839b012 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -4708,7 +4708,14 @@ WOLFSSL_API int wolfSSL_UseTrustedCA(WOLFSSL* ssl, unsigned char type, enum { WOLFSSL_ALPN_NO_MATCH = 0, WOLFSSL_ALPN_MATCH = 1, + /* On mismatch, continue the handshake without an agreed protocol, like + * OpenSSL. This intentionally does NOT send the RFC 7301 section 3.2 fatal + * no_application_protocol alert, so it is not compliant with that SHALL + * requirement. Select this only when OpenSSL-compatible behavior is + * needed. */ WOLFSSL_ALPN_CONTINUE_ON_MISMATCH = 2, + /* On mismatch, send the fatal no_application_protocol alert and fail the + * handshake, as required by RFC 7301 section 3.2. */ WOLFSSL_ALPN_FAILED_ON_MISMATCH = 4 };