From afca455cda81f1b03998b24a369373f2d6531c69 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 28 Jan 2022 14:40:45 +0100 Subject: [PATCH 1/9] stunnel 5.61 support - New/Implemented API - `SSL_has_pending` - `wolfSSL_CertManagerLoadCRLFile` - `wolfSSL_LoadCRLFile` - `wolfSSL_CTX_LoadCRLFile` - `wolfSSL_CTX_add_session` - Calling chain certificate API (for example `wolfSSL_CTX_use_certificate_chain_file`) no longer requires an actual chain certificate PEM file to be passed in as input. `ProcessUserChain` error in `ProcessBuffer` is ignored if it returns that it didn't find a chain. - Add `WOLFSSL_TICKET_HAVE_ID` macro. When defined tickets will include the original session ID that can be used to lookup the session in internal cache. This is useful for fetching information about the peer that doesn't get sent in a resumption (such as the peer's certificate chain). - Add `ssl->ticketSessionID` field because `ssl->session.sessionID` is used to return the "bogus" session ID sent by the client in TLS 1.3 - `OPENSSL_COMPATIBLE_DEFAULTS` changes - Define `WOLFSSL_TRUST_PEER_CERT` and certificates added as CA's will also be loaded as trusted peer certificates - Define `WOLFSSL_TLS13_MIDDLEBOX_COMPAT` - Seperate `internalCacheOff` and `internalCacheLookupOff` options to govern session addition and lookup - `VerifyServerSuite` now determines if RSA is available by checking for it directly and not assuming it as the default if static ECC is not available - `WOLFSSL_SESSION` changes - `ssl->extSession` added to return a dynamic session when internalCacheOff is set - `ssl->session.refPtr` made dynamic and gets free'd in `SSL_ResourceFree` - If `SSL_MODE_AUTO_RETRY` is set then retry should only occur during a handshake - `WOLFSSL_TRUST_PEER_CERT` code now always uses `cert->subjectHash` for the `cm->tpTable` table row selection - Change some error message names to line up with OpenSSL equivalents - Run `MatchSuite` again if certificate setup callback installed and successful - Refactor clearing `ASN_NO_PEM_HEADER` off the error queue into a macro - `wolfSSL_get_peer_certificate` now returns a duplicated object meaning that the caller needs to free the returned object - Allign `wolfSSL_CRYPTO_set_mem_functions` callbacks with OpenSSL API - `wolfSSL_d2i_PKCS12_bio` now consumes the input BIO. It now supports all supported BIO's instead of only memory BIO. - stunnel specific - Always return a session object even if we don't have a session in cache. This allows stunnel to save information in the session external data that will be transfered to new connections if the session is reused - When allocating a dynamic session, always do `wolfSSL_SESSION_set_ex_data(session, 0, (void *)(-1)`. This is to mimic the new index callback set in `SSL_SESSION_get_ex_new_index`. - Fix comment in `wolfSSL_AES_cbc_encrypt` - Trusted peer certificate suite tests need to have CRL disabled since we don't have the issuer certificate in the CA store if the certificates are only added as trusted peer certificates. tested --- configure.ac | 11 +- src/internal.c | 96 +++- src/ssl.c | 1011 ++++++++++++++++++++++++------------ src/tls13.c | 6 +- tests/api.c | 246 ++++++++- tests/test-trustpeer.conf | 14 + wolfcrypt/src/error.c | 4 + wolfssl/internal.h | 62 ++- wolfssl/openssl/opensslv.h | 6 +- wolfssl/openssl/ssl.h | 1 + wolfssl/ssl.h | 24 +- wolfssl/test.h | 1 + wolfssl/wolfcrypt/asn.h | 2 +- wolfssl/wolfcrypt/memory.h | 6 + 14 files changed, 1079 insertions(+), 411 deletions(-) diff --git a/configure.ac b/configure.ac index 92d9f4c324..1504afda18 100644 --- a/configure.ac +++ b/configure.ac @@ -5224,6 +5224,7 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_STUNNEL -DWOLFSSL_ALWAYS_VERIFY_CB" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI -DHAVE_EX_DATA" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB -DWOLFSSL_SIGNER_DER_CERT" + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_COMPATIBLE_DEFAULTS -DWOLFSSL_TICKET_HAVE_ID" fi # curl Support @@ -6824,6 +6825,14 @@ AC_ARG_ENABLE([optflags], AS_CASE(["$CFLAGS $CPPFLAGS"],[*'WOLFSSL_TRUST_PEER_CERT'*],[ENABLED_TRUSTED_PEER_CERT=yes]) +AS_CASE(["$CFLAGS $CPPFLAGS $AM_CFLAGS"],[*'OPENSSL_COMPATIBLE_DEFAULTS'*], + [ENABLED_OPENSSL_COMPATIBLE_DEFAULTS=yes]) +if test "x$ENABLED_OPENSSL_COMPATIBLE_DEFAULTS" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRUST_PEER_CERT -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT" + ENABLED_TRUSTED_PEER_CERT=yes +fi + # dertermine if we have key validation mechanism if test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_RSA" = "xyes" then @@ -7105,7 +7114,7 @@ then fi AS_IF([test "x$ENABLED_OPENSSLALL" = "xyes"], - [AM_CFLAGS="$AM_CFLAGS -DOPENSSL_ALL -DWOLFSSL_EITHER_SIDE -DWC_RSA_NO_PADDING -DWC_RSA_PSS -DWOLFSSL_PSS_LONG_SALT"]) + [AM_CFLAGS="$AM_CFLAGS -DOPENSSL_ALL -DWOLFSSL_EITHER_SIDE -DWC_RSA_NO_PADDING -DWC_RSA_PSS -DWOLFSSL_PSS_LONG_SALT -DWOLFSSL_TICKET_HAVE_ID"]) AS_IF([test "x$ENABLED_AESSIV" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_SIV"]) diff --git a/src/internal.c b/src/internal.c index 0fba90d6ce..c45318410e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5952,6 +5952,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.downgrade = ctx->method->downgrade; ssl->options.minDowngrade = ctx->minDowngrade; + ssl->options.haveRSA = ctx->haveRSA; ssl->options.haveDH = ctx->haveDH; ssl->options.haveECDSAsig = ctx->haveECDSAsig; ssl->options.haveECC = ctx->haveECC; @@ -5998,6 +5999,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff; #ifdef HAVE_EXT_CACHE ssl->options.internalCacheOff = ctx->internalCacheOff; + ssl->options.internalCacheLookupOff = ctx->internalCacheLookupOff; #endif ssl->options.verifyPeer = ctx->verifyPeer; @@ -7014,6 +7016,13 @@ void SSL_ResourceFree(WOLFSSL* ssl) * example with the RNG, it isn't used beyond the handshake except when * using stream ciphers where it is retained. */ + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("Free'ing server ssl"); + } + else { + WOLFSSL_MSG("Free'ing client ssl"); + } + #ifdef HAVE_EX_DATA_CLEANUP_HOOKS wolfSSL_CRYPTO_cleanup_ex_data(&ssl->ex_data); #endif @@ -7221,6 +7230,9 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->session.ticketLen = 0; } #endif +#ifdef ENABLE_CLIENT_SESSION_REF + wolfSSL_SESSION_free(ssl->session.refPtr); +#endif #ifdef HAVE_EXT_CACHE wolfSSL_SESSION_free(ssl->extSession); #endif @@ -8985,7 +8997,7 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) return -1; case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */ - if (ssl->ctx->autoRetry) + if (ssl->ctx->autoRetry && !ssl->options.handShakeDone) goto retry; return WANT_READ; @@ -12157,7 +12169,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (args->certIdx == 0) { #ifdef WOLFSSL_TRUST_PEER_CERT TrustedPeerCert* tp; - int matchType = WC_MATCH_NAME; #endif ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, NO_VERIFY, @@ -12174,11 +12185,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif #ifdef WOLFSSL_TRUST_PEER_CERT - #ifndef NO_SKID - if (args->dCert->extAuthKeyIdSet) - matchType = WC_MATCH_SKID; - #endif - tp = GetTrustedPeer(SSL_CM(ssl), subjectHash, matchType); + tp = GetTrustedPeer(SSL_CM(ssl), args->dCert); WOLFSSL_MSG("Checking for trusted peer cert"); if (tp && MatchTrustedPeer(tp, args->dCert)) { @@ -18874,8 +18881,10 @@ int SendCertificate(WOLFSSL* ssl) WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND); WOLFSSL_ENTER("SendCertificate"); - if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) + if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) { + WOLFSSL_MSG("Not sending certificate msg. Using PSK or ANON cipher."); return 0; /* not needed */ + } if (ssl->options.sendVerify == SEND_BLANK_CERT) { #ifdef OPENSSL_EXTRA @@ -20215,7 +20224,11 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) return "wrong client/server type"; case NO_PEER_CERT : +#ifndef OPENSSL_EXTRA return "peer didn't send cert"; +#else + return "peer did not return a certificate"; +#endif case UNKNOWN_HANDSHAKE_TYPE : return "weird handshake type"; @@ -20530,7 +20543,11 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) return "The handshake message is missing required data"; case BAD_BINDER: +#ifndef OPENSSL_EXTRA return "Binder value does not match value server calculated"; +#else + return "binder does not verify"; +#endif case EXT_NOT_ALLOWED: return "Extension type not allowed in handshake message type"; @@ -28843,7 +28860,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, */ static int VerifyServerSuite(WOLFSSL* ssl, word16 idx) { - int haveRSA = !ssl->options.haveStaticECC; #ifndef NO_PSK int havePSK = ssl->options.havePSK; #endif @@ -28862,7 +28878,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (CipherRequires(first, second, REQUIRES_RSA)) { WOLFSSL_MSG("Requires RSA"); - if (haveRSA == 0) { + if (ssl->options.haveRSA == 0) { WOLFSSL_MSG("Don't have RSA"); return 0; } @@ -29969,6 +29985,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif ret = MatchSuite(ssl, &clSuites); +#ifdef OPENSSL_EXTRA + /* Give user last chance to provide a cert for cipher selection */ + if (ret == 0) + ret = CertSetupCbWrapper(ssl); + /* Call again in case user changes affect cipher selection */ + if (ret == 0 && ssl->ctx->certSetupCb != NULL) + ret = MatchSuite(ssl, &clSuites); +#endif + #ifdef WOLFSSL_EXTRA_ALERTS if (ret == BUFFER_ERROR) SendAlert(ssl, alert_fatal, decode_error); @@ -29996,11 +30021,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, wc_HmacFree(&cookieHmac); #endif -#ifdef OPENSSL_EXTRA - if (ret == 0) - ret = CertSetupCbWrapper(ssl); -#endif - WOLFSSL_LEAVE("DoClientHello", ret); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); @@ -30527,6 +30547,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_EARLY_DATA word32 maxEarlyDataSz; /* Max size of early data */ #endif +#endif +#ifdef WOLFSSL_TICKET_HAVE_ID + byte id[ID_LEN]; #endif } InternalTicket; @@ -30614,9 +30637,27 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif } +#ifdef WOLFSSL_TICKET_HAVE_ID + { + const byte* id = NULL; + if (ssl->options.haveTicketSessionID) + id = ssl->ticketSessionID; + else if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) + id = ssl->arrays->sessionID; + else + id = ssl->session.sessionID; + XMEMCPY(it.id, id, ID_LEN); + } +#endif + /* encrypt */ encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */ - if (ssl->ctx->ticketEncCb == NULL) { + if (ssl->ctx->ticketEncCb == NULL || + /* SSL_OP_NO_TICKET turns off tickets in < 1.2. Forces + * "stateful" tickets for 1.3 so just use the regular + * stateless ones. */ + (!IsAtLeastTLSv1_3(ssl->version) && + (ssl->options.mask & SSL_OP_NO_TICKET) != 0)) { ret = WOLFSSL_TICKET_RET_FATAL; } else { @@ -30711,7 +30752,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } outLen = inLen; /* may be reduced by user padding */ - if (ssl->ctx->ticketEncCb == NULL) { + if (ssl->ctx->ticketEncCb == NULL || + /* SSL_OP_NO_TICKET turns off tickets in < 1.2. Forces + * "stateful" tickets for 1.3 so just use the regular + * stateless ones. */ + (!IsAtLeastTLSv1_3(ssl->version) && + (ssl->options.mask & SSL_OP_NO_TICKET) != 0)) { ret = WOLFSSL_TICKET_RET_FATAL; } else { @@ -30760,6 +30806,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->version.minor = it.pv.minor; } +#ifdef WOLFSSL_TICKET_HAVE_ID + { + ssl->options.haveTicketSessionID = 1; + XMEMCPY(ssl->ticketSessionID, it.id, ID_LEN); + if (wolfSSL_GetSession(ssl, NULL, 1) != NULL) { + WOLFSSL_MSG("Found session matching the session id" + " found in the ticket"); + } + else { + WOLFSSL_MSG("Can't find session matching the session id" + " found in the ticket"); + } + } +#endif if (!IsAtLeastTLSv1_3(ssl->version)) { XMEMCPY(ssl->arrays->masterSecret, it.msecret, SECRET_LEN); @@ -31209,6 +31269,8 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], byte* p = aad; int keyIdx = 0; + WOLFSSL_ENTER("DefTicketEncCb"); + /* Check we have setup the RNG, name and primary key. */ if (keyCtx->expirary[0] == 0) { #ifndef SINGLE_THREADED diff --git a/src/ssl.c b/src/ssl.c index e22f1130fa..ffc0b03f86 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -4398,7 +4398,7 @@ void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len, #endif WOLFSSL_ABI -int wolfSSL_pending(WOLFSSL* ssl) +int wolfSSL_pending(const WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_pending"); if (ssl == NULL) @@ -4407,6 +4407,14 @@ int wolfSSL_pending(WOLFSSL* ssl) return ssl->buffers.clearOutputBuffer.length; } +int wolfSSL_has_pending(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_has_pending"); + if (ssl == NULL) + return WOLFSSL_FAILURE; + + return ssl->buffers.clearOutputBuffer.length > 0; +} #ifndef WOLFSSL_LEANPSK /* turn on handshake group messages for context */ @@ -4693,26 +4701,29 @@ static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash) } /* does trusted peer already exist on signer list */ -int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash) +int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DecodedCert* cert) { TrustedPeerCert* tp; int ret = 0; - word32 row = TrustedPeerHashSigner(hash); + word32 row = TrustedPeerHashSigner(cert->subjectHash); if (wc_LockMutex(&cm->tpLock) != 0) return ret; tp = cm->tpTable[row]; while (tp) { - byte* subjectHash; - #ifndef NO_SKID - subjectHash = tp->subjectKeyIdHash; - #else - subjectHash = tp->subjectNameHash; - #endif - if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + if (XMEMCMP(cert->subjectHash, tp->subjectNameHash, + SIGNER_DIGEST_SIZE) == 0) ret = 1; - break; + #ifndef NO_SKID + if (cert->extSubjKeyIdSet) { + /* Compare SKID as well if available */ + if (ret == 1 && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash, + SIGNER_DIGEST_SIZE) != 0) + ret = 0; } + #endif + if (ret == 1) + break; tp = tp->next; } wc_UnLockMutex(&cm->tpLock); @@ -4724,42 +4735,36 @@ int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash) /* return Trusted Peer if found, otherwise NULL type is what to match on */ -TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, int type) +TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert) { WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; TrustedPeerCert* ret = NULL; TrustedPeerCert* tp = NULL; word32 row; - if (cm == NULL || hash == NULL) + if (cm == NULL || cert == NULL) return NULL; - row = TrustedPeerHashSigner(hash); + row = TrustedPeerHashSigner(cert->subjectHash); if (wc_LockMutex(&cm->tpLock) != 0) return ret; tp = cm->tpTable[row]; while (tp) { - byte* subjectHash; - switch (type) { - #ifndef NO_SKID - case WC_MATCH_SKID: - subjectHash = tp->subjectKeyIdHash; - break; - #endif - case WC_MATCH_NAME: - subjectHash = tp->subjectNameHash; - break; - default: - WOLFSSL_MSG("Unknown search type"); - wc_UnLockMutex(&cm->tpLock); - return NULL; - } - if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + if (XMEMCMP(cert->subjectHash, tp->subjectNameHash, + SIGNER_DIGEST_SIZE) == 0) ret = tp; - break; + #ifndef NO_SKID + if (cert->extSubjKeyIdSet) { + /* Compare SKID as well if available */ + if (ret != NULL && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash, + SIGNER_DIGEST_SIZE) != 0) + ret = NULL; } + #endif + if (ret != NULL) + break; tp = tp->next; } wc_UnLockMutex(&cm->tpLock); @@ -4867,7 +4872,6 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) TrustedPeerCert* peerCert; DecodedCert* cert; DerBuffer* der = *pDer; - byte* subjectHash = NULL; WOLFSSL_MSG("Adding a Trusted Peer Cert"); @@ -4897,17 +4901,6 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) } XMEMSET(peerCert, 0, sizeof(TrustedPeerCert)); -#ifndef NO_SKID - if (cert->extAuthKeyIdSet) { - subjectHash = cert->extSubjKeyId; - } - else { - subjectHash = cert->subjectHash; - } -#else - subjectHash = cert->subjectHash; -#endif - #ifndef IGNORE_NAME_CONSTRAINTS if (peerCert->permittedNames) FreeNameSubtrees(peerCert->permittedNames, cm->heap); @@ -4915,7 +4908,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) FreeNameSubtrees(peerCert->excludedNames, cm->heap); #endif - if (AlreadyTrustedPeer(cm, subjectHash)) { + if (AlreadyTrustedPeer(cm, cert)) { WOLFSSL_MSG("\tAlready have this CA, not adding again"); FreeTrustedPeer(peerCert, cm->heap); (void)ret; @@ -4956,16 +4949,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) cert->excludedNames = NULL; #endif - #ifndef NO_SKID - if (cert->extAuthKeyIdSet) { - row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash); - } - else { - row = TrustedPeerHashSigner(peerCert->subjectNameHash); - } - #else row = TrustedPeerHashSigner(peerCert->subjectNameHash); - #endif if (wc_LockMutex(&cm->tpLock) == 0) { peerCert->next = cm->tpTable[row]; @@ -5274,6 +5258,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) #define SESSIONS_PER_ROW 3 #define SESSION_ROWS 11 #endif + #define INVALID_SESSION_ROW -1 #ifdef NO_SESSION_CACHE_ROW_LOCK #undef ENABLE_SESSION_CACHE_ROW_LOCK @@ -6107,6 +6092,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (userChain) { ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info, verify); + if (ret == ASN_NO_PEM_HEADER) { /* Additional chain is optional */ + unsigned long pemErr; + CLEAR_ASN_NO_PEM_HEADER_ERROR(pemErr); + ret = 0; + } } } @@ -6338,6 +6328,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (cert->keyOID == ECDSAk) { ssl->options.haveECC = 1; } + #ifndef NO_RSA + else if (cert->keyOID == RSAk) { + ssl->options.haveRSA = 1; + } + #endif #ifdef HAVE_ED25519 else if (cert->keyOID == ED25519k) { ssl->options.haveECC = 1; @@ -6364,6 +6359,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (cert->keyOID == ECDSAk) { ctx->haveECC = 1; } + #ifndef NO_RSA + else if (cert->keyOID == RSAk) { + ctx->haveRSA = 1; + } + #endif #ifdef HAVE_ED25519 else if (cert->keyOID == ED25519k) { ctx->haveECC = 1; @@ -7483,6 +7483,12 @@ int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file, #ifndef NO_WOLFSSL_DIR if (ret == WOLFSSL_SUCCESS) successCount++; +#endif +#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS) + ret = wolfSSL_CTX_trust_peer_cert(ctx, file, WOLFSSL_FILETYPE_PEM); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error"); + } #endif } @@ -7513,6 +7519,8 @@ int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file, (ret == ASN_NO_PEM_HEADER))) { /* Do not fail here if a certificate fails to load, continue to next file */ + unsigned long err; + CLEAR_ASN_NO_PEM_HEADER_ERROR(err); #if defined(WOLFSSL_QT) ret = WOLFSSL_SUCCESS; #endif @@ -7524,6 +7532,14 @@ int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file, } } else { + #if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS) + ret = wolfSSL_CTX_trust_peer_cert(ctx, file, WOLFSSL_FILETYPE_PEM); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error. Ignoring" + "this error."); + ret = WOLFSSL_SUCCESS; + } + #endif successCount++; } fileRet = wc_ReadDirNext(readCtx, path, &name); @@ -7781,6 +7797,24 @@ int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path, return LoadCRL(cm->crl, path, type, monitor); } + +int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm, const char* file, + int type) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLFile"); + if (cm == NULL || file == NULL) + return BAD_FUNC_ARG; + + if (cm->crl == NULL) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + return ProcessFile(NULL, file, type, CRL_TYPE, NULL, 0, cm->crl, + VERIFY); +} #endif int wolfSSL_EnableCRL(WOLFSSL* ssl, int options) @@ -7811,6 +7845,15 @@ int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor) else return BAD_FUNC_ARG; } + +int wolfSSL_LoadCRLFile(WOLFSSL* ssl, const char* file, int type) +{ + WOLFSSL_ENTER("wolfSSL_LoadCRL"); + if (ssl) + return wolfSSL_CertManagerLoadCRLFile(SSL_CM(ssl), file, type); + else + return BAD_FUNC_ARG; +} #endif @@ -7864,6 +7907,16 @@ int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, else return BAD_FUNC_ARG; } + +int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* file, + int type) +{ + WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL"); + if (ctx) + return wolfSSL_CertManagerLoadCRLFile(ctx->cm, file, type); + else + return BAD_FUNC_ARG; +} #endif @@ -12438,17 +12491,30 @@ WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) { WOLFSSL_SESSION* sess = NULL; + WOLFSSL_ENTER("SSL_get1_session"); if (ssl != NULL) { sess = wolfSSL_GetSessionRef(ssl); + if (sess == NULL) + sess = wolfSSL_GetSession(ssl, NULL, 1); + #ifdef HAVE_STUNNEL + /* stunnel wants to store meta data in the session so always give it + * something that it can write to. */ + if (sess == NULL) { + if (ssl->extSession == NULL) + ssl->extSession = sess = wolfSSL_SESSION_new(); + else + sess = ssl->extSession; + } + #endif if (sess != NULL) { /* wolfSSL_get_session returns either static cache or ref. If ref then * increase reference counter */ /* increase reference count if allocated session */ - #ifdef ENABLE_CLIENT_SESSION_REF - if (sess->type == WOLFSSL_SESSION_TYPE_REF) { - sess->refCount++; + if (sess->type == WOLFSSL_SESSION_TYPE_HEAP || + sess->type == WOLFSSL_SESSION_TYPE_REF) { + if (wolfSSL_SESSION_up_ref(sess) != WOLFSSL_SUCCESS) + sess = NULL; } - #endif } } return sess; @@ -12505,7 +12571,7 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) #ifdef HAVE_EXT_CACHE wolfSSL_FreeSession(session); #endif - WOLFSSL_MSG("SetSession failed"); + WOLFSSL_MSG("wolfSSL_SetSession failed"); session = NULL; } } @@ -12938,6 +13004,8 @@ long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode) #ifdef HAVE_EXT_CACHE if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0) ctx->internalCacheOff = 1; + if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP) != 0) + ctx->internalCacheLookupOff = 1; #endif return WOLFSSL_SUCCESS; @@ -15251,8 +15319,10 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) WOLFSSL_ENTER("GetSessionClient"); - if (ssl->ctx->sessionCacheOff) + if (ssl->ctx->sessionCacheOff) { + WOLFSSL_MSG("Session Cache off"); return NULL; + } if (ssl->options.side == WOLFSSL_SERVER_END) return NULL; @@ -15262,13 +15332,19 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) #ifdef HAVE_EXT_CACHE if (ssl->ctx->get_sess_cb != NULL) { int copy = 0; + WOLFSSL_MSG("Calling external session cache"); ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, ©); - if (ret != NULL) + if (ret != NULL) { + WOLFSSL_MSG("Session found in external cache"); return ret; + } + WOLFSSL_MSG("Session not found in external cache"); } - if (ssl->ctx->internalCacheOff) + if (ssl->ctx->internalCacheLookupOff) { + WOLFSSL_MSG("Internal cache turned off"); return NULL; + } #endif row = HashSession(id, len, &error) % SESSION_ROWS; @@ -15406,24 +15482,38 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, return NULL; #endif - if (!ssl->options.tls1_3 && ssl->arrays != NULL) + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) id = ssl->arrays->sessionID; else id = ssl->session.sessionID; +#ifdef WOLFSSL_TICKET_HAVE_ID + if (ssl->options.haveTicketSessionID) + id = ssl->ticketSessionID; +#endif + #ifdef HAVE_EXT_CACHE if (ssl->ctx->get_sess_cb != NULL) { int copy = 0; /* Attempt to retrieve the session from the external cache. */ + WOLFSSL_MSG("Calling external session cache"); ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); if (ret != NULL) { + WOLFSSL_MSG("Session found in external cache"); RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); return ret; } + WOLFSSL_MSG("Session not found in external cache"); } - if (ssl->ctx->internalCacheOff) + if (ssl->ctx->internalCacheLookupOff) { + if (ssl->extSession != NULL) { + WOLFSSL_MSG("Found dynamic session"); + return ssl->extSession; + } + WOLFSSL_MSG("Internal cache lookup turned off"); return NULL; + } #endif row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; @@ -15471,12 +15561,19 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, SESSION_ROW_UNLOCK(sessRow); +#ifdef HAVE_EXT_CACHE + if (ret == NULL && ssl->extSession != NULL) { + WOLFSSL_MSG("Found dynamic session"); + return ssl->extSession; + } +#endif + return ret; } int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) { - int ret = WOLFSSL_SUCCESS, row = -1; + int ret = WOLFSSL_SUCCESS, row; #ifdef HAVE_SESSION_TICKET int ticLenAlloc; byte *ticBuff = NULL; @@ -15497,24 +15594,22 @@ int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) ret = WOLFSSL_FAILURE; } if (ret == WOLFSSL_SUCCESS) { - int error = 0; ref = session; /* keep copy of ref for later */ session = (WOLFSSL_SESSION*)session->refPtr; - row = HashSession(ref->sessionID, ID_LEN, &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - ret = WOLFSSL_FAILURE; - } + row = session->cacheRow; } + if (ret == WOLFSSL_FAILURE) + return WOLFSSL_FAILURE; } #endif - if (row < 0 || row >= SESSION_ROWS) { + if (row != INVALID_SESSION_ROW && (row < 0 || row >= SESSION_ROWS)) { return BAD_FUNC_ARG; } /* lock session cache row */ - if (SESSION_ROW_LOCK(&SessionCache[row]) != 0) { + if (row != INVALID_SESSION_ROW && + SESSION_ROW_LOCK(&SessionCache[row]) != 0) { return BAD_MUTEX_E; } @@ -15535,72 +15630,93 @@ int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) } #endif - /* copy session structure */ - XMEMCPY(&ssl->session, session, sizeof(WOLFSSL_SESSION)); - ssl->session.type = WOLFSSL_SESSION_TYPE_SSL; - ssl->session.masterSecret = ssl->session._masterSecret; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (ssl->session.peer != NULL) { + wolfSSL_X509_free(ssl->session.peer); + ssl->session.peer = NULL; + } + if (session->peer != NULL && + wolfSSL_X509_up_ref(session->peer) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Can't increase peer cert ref count"); + ret = WOLFSSL_FAILURE; + } +#endif + + if (ret == WOLFSSL_SUCCESS) { + /* copy session structure */ + XMEMCPY(&ssl->session, session, sizeof(WOLFSSL_SESSION)); + /* Set sane defaults */ + ssl->session.type = WOLFSSL_SESSION_TYPE_SSL; + ssl->session.cacheRow = INVALID_SESSION_ROW; + ssl->session.masterSecret = ssl->session._masterSecret; #ifndef NO_CLIENT_CACHE - ssl->session.serverID = ssl->session._serverID; + ssl->session.serverID = ssl->session._serverID; #endif #ifdef OPENSSL_EXTRA - ssl->session.sessionCtx = ssl->session._sessionCtx; + ssl->session.sessionCtx = ssl->session._sessionCtx; #endif - #ifdef HAVE_SESSION_TICKET - /* try and use existing buffer */ - if (ssl->session.ticketLenAlloc > 0 && ticBuff != NULL && - ticLenAlloc >= ssl->session.ticketLen) { - XMEMCPY(ticBuff, session->ticket, ssl->session.ticketLen); - ssl->session.ticket = ticBuff; - ssl->session.ticketLenAlloc = (word16)ticLenAlloc; - ticBuff = NULL; /* don't free later after unlock */ - } - else { - /* Default ticket to non dynamic */ - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; - } + ssl->session.ticket = NULL; /* Set later */ #endif - - SESSION_ROW_UNLOCK(&SessionCache[row]); + ssl->session.refCount = 0; +#ifndef SINGLE_THREADED + XMEMSET(&ssl->session.refMutex, 0, sizeof(wolfSSL_Mutex)); +#endif + } #ifdef HAVE_SESSION_TICKET if (ret == WOLFSSL_SUCCESS) { - if (ticBuff != NULL) { - /* free old ticket buffer */ - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - } - /* allocate new one */ - ticBuff = (byte*)XMALLOC(ssl->session.ticketLen, ssl->heap, - DYNAMIC_TYPE_SESSION_TICK); - if (ticBuff != NULL) { - XMEMSET(ticBuff, 0, ssl->session.ticketLen); - ssl->session.ticketLenAlloc = (word16)ssl->session.ticketLen; - ssl->session.ticket = ticBuff; + if (ssl->session.ticketLen > SESSION_TICKET_LEN) { + if (ticBuff == NULL || ticLenAlloc < session->ticketLen) { + /* allocate new one */ + byte* tmp = (byte*)XREALLOC(ticBuff, session->ticketLen, + ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + if (tmp == NULL) { + WOLFSSL_MSG("Failed to allocate memory for ticket"); + ret = WOLFSSL_FAILURE; + XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ticBuff = NULL; + } + else { + ticBuff = tmp; + ticLenAlloc = session->ticketLen; + } + } + if (ticBuff != NULL) { + XMEMCPY(ticBuff, session->ticket, session->ticketLen); + ssl->session.ticket = ticBuff; + ssl->session.ticketLenAlloc = ticLenAlloc; + } } else { - ret = MEMORY_ERROR; - } - if (ret == WOLFSSL_SUCCESS && SESSION_ROW_LOCK(&SessionCache[row]) != 0) { - ret = BAD_MUTEX_E; - } - if (ret == WOLFSSL_SUCCESS && session->ticketLen != ssl->session.ticketLen) { - /* Another thread modified the ssl->session ticket during alloc. - * Treat as error, since ticket different than when copy requested */ - ret = VAR_STATE_CHANGE_E; - } - if (ret == WOLFSSL_SUCCESS) { - XMEMCPY(ssl->session.ticket, session->ticket, ssl->session.ticketLen); - } - if (ret != BAD_MUTEX_E) { - SESSION_ROW_UNLOCK(&SessionCache[row]); + /* Default ticket to non dynamic */ + /* free old ticket buffer */ + if (ticBuff != NULL) + XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticket = ssl->session._staticTicket; + ssl->session.ticketLenAlloc = 0; + if (session->ticketLenAlloc > 0) { + /* Shouldn't happen as session should have placed this in + * the static buffer */ + XMEMCPY(ssl->session.ticket, session->ticket, + session->ticketLen); + } } + ticBuff = NULL; } #endif + /* Unlock once we are done with session */ + if (row != INVALID_SESSION_ROW) + SESSION_ROW_UNLOCK(&SessionCache[row]); + if (ret != WOLFSSL_SUCCESS) { #ifdef HAVE_SESSION_TICKET /* cleanup */ + if (ticBuff != NULL) { + /* free old ticket buffer */ + XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + } if (ssl->session.ticket != ssl->session._staticTicket) { XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); } @@ -15671,26 +15787,42 @@ int AddSession(WOLFSSL* ssl) int overwrite = 0; #ifdef HAVE_EXT_CACHE int cbRet = 0; + byte sessionAlloc = 0; #endif SessionRow* sessRow = NULL; - if (SslSessionCacheOff(ssl, &ssl->session)) + WOLFSSL_ENTER("AddSession"); + + if (SslSessionCacheOff(ssl, &ssl->session)) { + WOLFSSL_MSG("Cache off"); return 0; + } - if (ssl->options.haveSessionId == 0) + if (ssl->options.haveSessionId == 0) { + WOLFSSL_MSG("Don't have session id"); return 0; + } -#ifdef HAVE_SESSION_TICKET - if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) +#if defined(HAVE_SESSION_TICKET) && !defined(OPENSSL_EXTRA) + /* For the compat layer generate a session object to use */ + if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) { + WOLFSSL_MSG("Using tickets instead of cache"); return 0; + } #endif - if (!ssl->options.tls1_3 && ssl->arrays != NULL) + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) id = ssl->arrays->sessionID; else id = ssl->session.sessionID; +#ifdef WOLFSSL_TICKET_HAVE_ID + if (ssl->options.haveTicketSessionID) + id = ssl->ticketSessionID; +#endif + if (id == NULL) { + WOLFSSL_MSG("No Session ID"); return BAD_FUNC_ARG; } @@ -15707,14 +15839,21 @@ int AddSession(WOLFSSL* ssl) #ifdef HAVE_EXT_CACHE if (ssl->options.internalCacheOff) { - /* Create a new session object to be stored. */ - session = wolfSSL_SESSION_new(); - if (session == NULL) { - #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - #endif - return MEMORY_E; + /* Create a new session object to be stored or use the existing + * one. */ + if (ssl->extSession != NULL) { + session = ssl->extSession; + } + else { + ssl->extSession = session = wolfSSL_SESSION_new(); + if (session == NULL) { + #ifdef HAVE_SESSION_TICKET + XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + #endif + return MEMORY_E; + } } + sessionAlloc = 1; } else #endif @@ -15737,7 +15876,7 @@ int AddSession(WOLFSSL* ssl) return BAD_MUTEX_E; } - for (i=0; itotalCount; i++) { if (XMEMCMP(id, sessRow->Sessions[i].sessionID, ID_LEN) == 0 && sessRow->Sessions[i].side == ssl->options.side) { @@ -15755,10 +15894,15 @@ int AddSession(WOLFSSL* ssl) ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; #endif session = &sessRow->Sessions[idx]; + session->type = WOLFSSL_SESSION_TYPE_CACHE; } - - session->type = WOLFSSL_SESSION_TYPE_CACHE; - session->cacheRow = row; + session->cacheRow = session->type == WOLFSSL_SESSION_TYPE_CACHE ? + (int)row : INVALID_SESSION_ROW; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (session->peer != NULL) + wolfSSL_X509_free(session->peer); + session->peer = NULL; +#endif session->side = (byte)ssl->options.side; session->heap = ssl->heap; session->masterSecret = session->_masterSecret; @@ -15770,7 +15914,7 @@ int AddSession(WOLFSSL* ssl) #endif #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) { + if (IsAtLeastTLSv1_3(ssl->version)) { XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN); session->sessionIDSz = ID_LEN; } @@ -15833,11 +15977,18 @@ int AddSession(WOLFSSL* ssl) #ifdef SESSION_CERTS if (error == 0) { - if (!overwrite || ssl->session.chain.count > 0) { + if (!overwrite) { /* If we are overwriting and no certs present in ssl->session.chain * then keep the old chain. */ session->chain.count = ssl->session.chain.count; XMEMCPY(session->chain.certs, ssl->session.chain.certs, + sizeof(x509_buffer) * ssl->session.chain.count); + } + else if (ssl->session.chain.count == 0 && + session->chain.count > 0) { + /* Copy in the certs from the session */ + ssl->session.chain.count = session->chain.count; + XMEMCPY(ssl->session.chain.certs, session->chain.certs, sizeof(x509_buffer) * session->chain.count); } } @@ -15878,15 +16029,19 @@ int AddSession(WOLFSSL* ssl) #endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */ if (error == 0 && sessRow != NULL) { - sessRow->totalCount++; - if (sessRow->nextIdx == SESSIONS_PER_ROW) { + if (sessRow->totalCount < SESSIONS_PER_ROW) + sessRow->totalCount++; + if (sessRow->nextIdx == SESSIONS_PER_ROW) sessRow->nextIdx = 0; - } } #ifndef NO_CLIENT_CACHE if (error == 0) { - if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) { + if (ssl->options.side == WOLFSSL_CLIENT_END && (ssl->session.idLen +#ifdef HAVE_SESSION_TICKET + || ssl->options.useTicket == 1 +#endif + )) { word32 clientRow, clientIdx; WOLFSSL_MSG("Adding client cache entry"); @@ -15904,10 +16059,10 @@ int AddSession(WOLFSSL* ssl) (word16)row; ClientCache[clientRow].Clients[clientIdx].serverIdx = (word16)idx; - ClientCache[clientRow].totalCount++; - if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) { + if (ClientCache[clientRow].totalCount < SESSIONS_PER_ROW) + ClientCache[clientRow].totalCount++; + if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) ClientCache[clientRow].nextIdx = 0; - } wc_UnLockMutex(&clisession_mutex); } @@ -15917,6 +16072,7 @@ int AddSession(WOLFSSL* ssl) } } else { + WOLFSSL_MSG("Skipping client cache"); session->idLen = 0; } } @@ -15943,10 +16099,11 @@ int AddSession(WOLFSSL* ssl) #ifdef HAVE_EXT_CACHE if (error == 0 && ssl->ctx->new_sess_cb != NULL) { + if (sessionAlloc) + wolfSSL_SESSION_up_ref(session); cbRet = ssl->ctx->new_sess_cb(ssl, session); - } - if (ssl->options.internalCacheOff && cbRet == 0) { - wolfSSL_FreeSession(session); + if (sessionAlloc && cbRet == 0) + wolfSSL_FreeSession(session); } #endif @@ -16712,6 +16869,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) else ret = ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL, NULL, userChain, verify); +#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS) + if (ret == WOLFSSL_SUCCESS) + ret = wolfSSL_CTX_trust_peer_buffer(ctx, in, sz, format); +#endif + WOLFSSL_LEAVE("wolfSSL_CTX_load_verify_buffer_ex", ret); return ret; } @@ -17440,17 +17602,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) cert = NULL; } - err = wolfSSL_ERR_peek_last_error(); - - if (ERR_GET_LIB(err) == ERR_LIB_PEM && - ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { - /* - * wolfSSL_PEM_read_bio_X509 pushes an ASN_NO_PEM_HEADER error - * to the error queue on file end. This should not be left - * for the caller to find so we clear the last error. - */ - wc_RemoveErrorNode(-1); - } + CLEAR_ASN_NO_PEM_HEADER_ERROR(err); err = WOLFSSL_SUCCESS; cleanup: @@ -17814,15 +17966,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ctx->mask = wolf_set_options(ctx->mask, opt); -#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) && \ - defined(OPENSSL_EXTRA) - if (ctx->mask & SSL_OP_NO_TICKET) { - ctx->ticketEncCb = NULL; - ctx->ticketEncCtx = NULL; - WOLFSSL_MSG("\tSSL_OP_NO_TICKET"); - } -#endif - return ctx->mask; } @@ -17893,6 +18036,12 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_MSG("wolfSSL_get_peer_certificate error"); return NULL; } + /* wolfSSL_get_peer_certificate returns a copy. We want the internal + * member so that we don't have to worry about free'ing it. We call + * wolfSSL_get_peer_certificate so that we don't have to worry about + * setting up the internal pointer. */ + wolfSSL_X509_free(peerCert); + peerCert = (WOLFSSL_X509*)&ssl->peerCert; chain = wolfSSL_get_peer_cert_chain(ssl); if (chain == NULL) { WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error"); @@ -20647,21 +20796,22 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, WOLFSSL_ABI WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) { + WOLFSSL_X509* ret = NULL; WOLFSSL_ENTER("SSL_get_peer_certificate"); - if (ssl == NULL) - return NULL; - - if (ssl->peerCert.issuer.sz) - return &ssl->peerCert; + if (ssl != NULL) { + if (ssl->peerCert.issuer.sz) + ret = wolfSSL_X509_dup(&ssl->peerCert); #ifdef SESSION_CERTS - else if (ssl->session.chain.count > 0) { - if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer, - ssl->session.chain.certs[0].length) == 0) { - return &ssl->peerCert; + else if (ssl->session.chain.count > 0) { + if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer, + ssl->session.chain.certs[0].length) == 0) { + ret = wolfSSL_X509_dup(&ssl->peerCert); + } } - } #endif - return NULL; + } + WOLFSSL_LEAVE("SSL_get_peer_certificate", ret != NULL); + return ret; } #endif /* KEEP_PEER_CERT */ @@ -23573,8 +23723,10 @@ int wolfSSL_get_shutdown(const WOLFSSL* ssl) int wolfSSL_session_reused(WOLFSSL* ssl) { int resuming = 0; + WOLFSSL_ENTER("wolfSSL_session_reused"); if (ssl) resuming = ssl->options.resuming; + WOLFSSL_LEAVE("wolfSSL_session_reused", resuming); return resuming; } @@ -23583,14 +23735,16 @@ WOLFSSL_SESSION* wolfSSL_GetSessionRef(WOLFSSL* ssl) WOLFSSL_SESSION* session; #ifdef ENABLE_CLIENT_SESSION_REF WOLFSSL_SESSION* ref = NULL; - const word32 refSize = (word32)OFFSETOF(WOLFSSL_SESSION, refPtr) + - (word32)sizeof(wc_ptr_t); - int refCount = 0; + const word32 refSize = (word32)OFFSETOF(WOLFSSL_SESSION, _masterSecret); + int refCount = 1; +#ifndef SINGLE_THREADED + byte mutexLocked = 0; +#endif #endif session = wolfSSL_GetSession(ssl, NULL, 1); - if (session == NULL) { - return session; + if (session == NULL || session->type != WOLFSSL_SESSION_TYPE_CACHE) { + return NULL; } #ifdef ENABLE_CLIENT_SESSION_REF @@ -23598,11 +23752,17 @@ WOLFSSL_SESSION* wolfSSL_GetSessionRef(WOLFSSL* ssl) * pointer */ ref = (WOLFSSL_SESSION*)ssl->session.refPtr; if (ref == NULL) { - ref = (WOLFSSL_SESSION*)XMALLOC(refSize, ssl->heap, - DYNAMIC_TYPE_SESSION); + ref = wolfSSL_NewSession(ssl->heap); } else { /* use existing ref count */ +#ifndef SINGLE_THREADED + if (wc_LockMutex(&ref->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock session mutex"); + } + else + mutexLocked = 1; +#endif refCount = ref->refCount; } if (ref == NULL) { @@ -23617,13 +23777,17 @@ WOLFSSL_SESSION* wolfSSL_GetSessionRef(WOLFSSL* ssl) ref->heap = ssl->heap; ssl->session.refPtr = ref; session = ref; + +#ifndef SINGLE_THREADED + if (mutexLocked) + wc_UnLockMutex(&ref->refMutex); +#endif + #endif /* ENABLE_CLIENT_SESSION_REF */ return session; } -#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) - /* return a new malloc'd session with default settings on success */ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) { @@ -23633,6 +23797,7 @@ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) DYNAMIC_TYPE_SESSION); if (ret != NULL) { XMEMSET(ret, 0, sizeof(WOLFSSL_SESSION)); + ret->cacheRow = INVALID_SESSION_ROW; /* not in cache */ ret->type = WOLFSSL_SESSION_TYPE_HEAP; ret->heap = heap; ret->masterSecret = ret->_masterSecret; @@ -23645,17 +23810,7 @@ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) #ifdef HAVE_SESSION_TICKET ret->ticket = ret->_staticTicket; #endif - } - (void)heap; - return ret; -} - -WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap) -{ - WOLFSSL_SESSION* ret = wolfSSL_NewSession(heap); - #ifdef OPENSSL_EXTRA - if (ret != NULL) { #ifndef SINGLE_THREADED if (wc_InitMutex(&ret->refMutex) != 0) { WOLFSSL_MSG("Error setting up session reference mutex"); @@ -23664,11 +23819,28 @@ WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap) } #endif ret->refCount = 1; - } #endif - +#ifdef HAVE_STUNNEL + /* stunnel has this funny mechanism of storing the "is_authenticated" + * session info in the session ex data. This is basically their + * default so let's just hard code it. */ + if (wolfSSL_SESSION_set_ex_data(ret, 0, (void *)(-1)) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error setting up ex data for stunnel"); + XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } +#endif + } return ret; } + + +WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap) +{ + return wolfSSL_NewSession(heap); +} + WOLFSSL_SESSION* wolfSSL_SESSION_new(void) { return wolfSSL_SESSION_new_ex(NULL); @@ -23678,11 +23850,9 @@ WOLFSSL_SESSION* wolfSSL_SESSION_new(void) * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */ int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) { - session = GetSessionPtr(session); if (session == NULL) return WOLFSSL_FAILURE; -#ifdef OPENSSL_EXTRA #ifndef SINGLE_THREADED if (wc_LockMutex(&session->refMutex) != 0) { WOLFSSL_MSG("Failed to lock session mutex"); @@ -23691,7 +23861,6 @@ int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) session->refCount++; #ifndef SINGLE_THREADED wc_UnLockMutex(&session->refMutex); -#endif #endif return WOLFSSL_SUCCESS; } @@ -23717,37 +23886,35 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) copy = wolfSSL_NewSession(session->heap); if (copy != NULL) { +#ifndef SINGLE_THREADED + /* Store value to restore after memcpy */ + wolfSSL_Mutex refMutex = copy->refMutex; +#endif XMEMCPY(copy, session, sizeof(WOLFSSL_SESSION)); copy->type = WOLFSSL_SESSION_TYPE_HEAP; - copy->cacheRow = -1; /* not in cache */ + copy->cacheRow = INVALID_SESSION_ROW; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + copy->peer = wolfSSL_X509_dup(session->peer); +#endif copy->masterSecret = copy->_masterSecret; - #ifndef NO_CLIENT_CACHE +#ifndef NO_CLIENT_CACHE copy->serverID = copy->_serverID; - #endif - #ifdef OPENSSL_EXTRA - copy->sessionCtx = copy->_sessionCtx; - #endif -#ifdef OPENSSL_EXTRA -#ifndef SINGLE_THREADED - if (wc_InitMutex(©->refMutex) != 0) { - WOLFSSL_MSG("Error setting up session reference mutex"); - XFREE(copy, copy->heap, DYNAMIC_TYPE_SESSION); - return NULL; - } #endif - copy->refCount = 1; +#ifdef OPENSSL_EXTRA + copy->sessionCtx = copy->_sessionCtx; #endif #ifdef HAVE_SESSION_TICKET - if (session->ticketLenAlloc > 0) { - copy->ticket = (byte*)XMALLOC(session->ticketLen, copy->heap, + if (copy->ticketLenAlloc > 0) { + copy->ticket = (byte*)XMALLOC(copy->ticketLen, copy->heap, DYNAMIC_TYPE_SESSION_TICK); XMEMCPY(copy->ticket, session->ticket, session->ticketLen); } else { copy->ticket = copy->_staticTicket; } #endif -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - copy->peer = wolfSSL_X509_dup(session->peer); + copy->refCount = 1; +#ifndef SINGLE_THREADED + copy->refMutex = refMutex; #endif } return copy; @@ -23758,8 +23925,6 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) #endif /* HAVE_EXT_CACHE */ } -#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */ - void wolfSSL_FreeSession(WOLFSSL_SESSION* session) { if (session == NULL) @@ -23767,29 +23932,28 @@ void wolfSSL_FreeSession(WOLFSSL_SESSION* session) #ifdef ENABLE_CLIENT_SESSION_REF if (session->type == WOLFSSL_SESSION_TYPE_REF) { - WOLFSSL_SESSION* ref; +#ifndef SINGLE_THREADED + if (wc_LockMutex(&session->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock session mutex"); + } +#endif session->refCount--; if (session->refCount > 0) { +#ifndef SINGLE_THREADED + wc_UnLockMutex(&session->refMutex); return; /* don't free yet */ - } - ref = session; - session = (WOLFSSL_SESSION*)session->refPtr; - XFREE(ref, ref->heap, DYNAMIC_TYPE_SESSION); - } #endif - -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS - wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); + } +#ifndef SINGLE_THREADED + wc_UnLockMutex(&session->refMutex); + wc_FreeMutex(&session->refMutex); #endif - -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (session->peer) { - wolfSSL_X509_free(session->peer); - session->peer = NULL; + XFREE(session, ref->heap, DYNAMIC_TYPE_SESSION); + /* Don't touch the internal session if this is a reference */ + return; } #endif -#ifdef OPENSSL_EXTRA /* refCount will always be 1 or more if created externally. * Internal cache sessions don't initialize a refMutex. */ if (session->refCount > 0) { @@ -23807,8 +23971,19 @@ void wolfSSL_FreeSession(WOLFSSL_SESSION* session) } #ifndef SINGLE_THREADED wc_UnLockMutex(&session->refMutex); + wc_FreeMutex(&session->refMutex); #endif } + +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (session->peer) { + wolfSSL_X509_free(session->peer); + session->peer = NULL; + } #endif #ifdef HAVE_SESSION_TICKET @@ -23817,6 +23992,10 @@ void wolfSSL_FreeSession(WOLFSSL_SESSION* session) } #endif +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); +#endif + if (session->type == WOLFSSL_SESSION_TYPE_HEAP) { XFREE(session, session->heap, DYNAMIC_TYPE_SESSION); } @@ -23827,6 +24006,109 @@ void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) wolfSSL_FreeSession(session); } +#ifdef HAVE_EXT_CACHE +/* HAVE_EXT_CACHE is needed for wolfSSL_SESSION_dup to work. Also without this + * define the input session will already always be in the session cache. */ +int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + word32 row; + int error = 0; + SessionRow* sessRow = NULL; + int i; + int overwrite = 0; + word32 idx = 0; + WOLFSSL_SESSION* copy; + WOLFSSL_SESSION* cacheSess; + + WOLFSSL_ENTER("wolfSSL_CTX_add_session"); + + if (session == NULL) + return WOLFSSL_FAILURE; + + /* Session cache is global */ + (void)ctx; + + /* Same session row selection logic as in AddSession */ + + row = HashSession(session->sessionID, ID_LEN, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + return WOLFSSL_FAILURE; + } + + sessRow = &SessionCache[row]; + if (SESSION_ROW_LOCK(sessRow) != 0) { + WOLFSSL_MSG("Row lock failed"); + return WOLFSSL_FAILURE; + } + + for (i=0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) { + if (XMEMCMP(session->sessionID, + sessRow->Sessions[i].sessionID, ID_LEN) == 0 && + sessRow->Sessions[i].side == session->side) { + WOLFSSL_MSG("Session already exists. Overwriting."); + overwrite = 1; + idx = i; + break; + } + } + + if (!overwrite) { + idx = sessRow->nextIdx++; + } + else if (session == &sessRow->Sessions[idx]) { + /* Sanity check to make sure we don't do unnecessary work */ + WOLFSSL_MSG("Session already present in cache"); + SESSION_ROW_UNLOCK(sessRow); + return WOLFSSL_SUCCESS; + } + + cacheSess = &sessRow->Sessions[idx]; + + copy = wolfSSL_SESSION_dup(session); + if (copy == NULL) { + WOLFSSL_MSG("wolfSSL_SESSION_dup failed"); + SESSION_ROW_UNLOCK(sessRow); + return WOLFSSL_FAILURE; + } + + wolfSSL_FreeSession(cacheSess); + + /* Just copy the fields and free the duplicated object */ + XMEMCPY(cacheSess, copy, sizeof(*copy)); + + cacheSess->type = WOLFSSL_SESSION_TYPE_CACHE; + cacheSess->cacheRow = row; + cacheSess->masterSecret = cacheSess->_masterSecret; +#ifndef NO_CLIENT_CACHE + cacheSess->serverID = cacheSess->_serverID; +#endif +#ifdef OPENSSL_EXTRA + cacheSess->sessionCtx = cacheSess->_sessionCtx; +#endif +#ifdef HAVE_SESSION_TICKET + if (cacheSess->ticketLenAlloc == 0) + cacheSess->ticket = cacheSess->_staticTicket; +#endif + cacheSess->refCount = 0; +#ifndef SINGLE_THREADED + /* We can free this since we are free'ing the `copy` object directly */ + wc_FreeMutex(&cacheSess->refMutex); +#endif + cacheSess->heap = NULL; + + if (sessRow->totalCount < SESSIONS_PER_ROW) + sessRow->totalCount++; + if (sessRow->nextIdx == SESSIONS_PER_ROW) + sessRow->nextIdx = 0; + + XFREE(copy, NULL, DYNAMIC_TYPE_SESSION); + + SESSION_ROW_UNLOCK(sessRow); + return WOLFSSL_SUCCESS; +} +#endif + #if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) /** @@ -26466,6 +26748,7 @@ char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, return ret; } + #ifndef NO_WOLFSSL_STUB int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, int* ssl) @@ -29269,10 +29552,13 @@ const char* wolfSSL_state_string_long(const WOLFSSL* ssl) } } - if (protocol == UNKNOWN) - return NULL; - else + if (protocol == UNKNOWN) { + WOLFSSL_MSG("Unknown protocol"); + return ""; + } + else { return OUTPUT_STR[state][protocol][cbmode]; + } } /* @@ -30706,6 +30992,9 @@ WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx) if (ctx->internalCacheOff == 1) { m |= SSL_SESS_CACHE_NO_INTERNAL_STORE; } + if (ctx->internalCacheLookupOff == 1) { + m |= SSL_SESS_CACHE_NO_INTERNAL_LOOKUP; + } #endif return m; @@ -31212,7 +31501,7 @@ void wolfSSL_AES_ecb_encrypt(const unsigned char *in, unsigned char* out, * len length of input buffer * key AES structure to use with encryption/decryption * iv iv to use with operation - * enc AES_ENCRYPT for encryption and AES_DECRYPT for decryption + * enc 1 for encryption and 0 for decryption */ void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out, size_t len, AES_KEY *key, unsigned char* iv, const int enc) @@ -32132,6 +32421,8 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) #endif unsigned char *data; + WOLFSSL_ENTER("wolfSSL_i2d_SSL_SESSION"); + sess = GetSessionPtr(sess); if (sess == NULL) { return BAD_FUNC_ARG; @@ -45568,18 +45859,8 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) } else { #ifdef WOLFSSL_HAVE_ERROR_QUEUE - int err = (int)wolfSSL_ERR_peek_last_error(); - if (ERR_GET_LIB(err) == ERR_LIB_PEM && - ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { - /* - * wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio pushes an - * ASN_NO_PEM_HEADER error to the error queue on file end. - * This should not be left for the caller to find so we - * clear the last error. This also indicates that nothing - * more was found in the BIO. - */ - wc_RemoveErrorNode(-1); - } + unsigned long err; + CLEAR_ASN_NO_PEM_HEADER_ERROR(err); #else if (wolfSSL_sk_X509_INFO_num(localSk) > 0) { WOLFSSL_MSG("At least one X509_INFO object on stack." @@ -46988,6 +47269,7 @@ static int get_ex_new_index(int class_index) /* index counter for each class index*/ static int ctx_idx = 0; static int ssl_idx = 0; + static int ssl_session_idx = 0; static int x509_idx = 0; int idx = -1; @@ -47002,9 +47284,11 @@ static int get_ex_new_index(int class_index) case CRYPTO_EX_INDEX_X509: idx = x509_idx++; break; + case CRYPTO_EX_INDEX_SSL_SESSION: + idx = ssl_session_idx++; + break; /* following class indexes are not supoprted */ - case CRYPTO_EX_INDEX_SSL_SESSION: case CRYPTO_EX_INDEX_X509_STORE: case CRYPTO_EX_INDEX_X509_STORE_CTX: case CRYPTO_EX_INDEX_DH: @@ -48315,18 +48599,22 @@ void wolfSSL_print_all_errors_fp(XFILE fp) defined(HAVE_EX_DATA) int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) { + int ret = WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); #ifdef HAVE_EX_DATA - session = GetSessionPtr(session); - if (session != NULL) { - return wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data); + if (session != NULL) + ret = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data); + if (ret == WOLFSSL_SUCCESS) { + WOLFSSL_SESSION* ref = GetSessionPtr(session); + if (ref != NULL) + ret = wolfSSL_CRYPTO_set_ex_data(&ref->ex_data, idx, data); } #else (void)session; (void)idx; (void)data; #endif - return WOLFSSL_FAILURE; + return ret; } #ifdef HAVE_EX_DATA_CLEANUP_HOOKS @@ -48349,6 +48637,7 @@ void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); #ifdef HAVE_EX_DATA + session = GetSessionPtr(session); if (session != NULL) { return wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx); } @@ -48534,23 +48823,61 @@ int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, (void)cb1; (void)cb2; (void)cb3; - if (XSTRNCMP((const char*)data, "redirect index", 14) == 0) { - return 0; - } - else if (XSTRNCMP((const char*)data, "addr index", 10) == 0) { - return 1; - } - return WOLFSSL_FAILURE; + (void)data; + return get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION); +} + +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY) +static wolfSSL_OSSL_Malloc_cb ossl_malloc = NULL; +static wolfSSL_OSSL_Free_cb ossl_free = NULL; +static wolfSSL_OSSL_Realloc_cb ossl_realloc = NULL; + +static void* OSSL_Malloc(size_t size) +{ + if (ossl_malloc != NULL) + return ossl_malloc(size, NULL, 0); + else + return NULL; +} + +static void OSSL_Free(void *ptr) +{ + if (ossl_free != NULL) + ossl_free(ptr, NULL, 0); +} + +static void* OSSL_Realloc(void *ptr, size_t size) +{ + if (ossl_realloc != NULL) + return ossl_realloc(ptr, size, NULL, 0); + else + return NULL; } +#endif /* USE_WOLFSSL_MEMORY && !WOLFSSL_DEBUG_MEMORY */ int wolfSSL_CRYPTO_set_mem_functions( - wolfSSL_Malloc_cb m, - wolfSSL_Realloc_cb r, - wolfSSL_Free_cb f) + wolfSSL_OSSL_Malloc_cb m, + wolfSSL_OSSL_Realloc_cb r, + wolfSSL_OSSL_Free_cb f) { #ifdef USE_WOLFSSL_MEMORY - if (wolfSSL_SetAllocators(m, f, r) == 0) +#ifdef WOLFSSL_DEBUG_MEMORY + WOLFSSL_MSG("mem functions will receive function name instead of " + "file name"); + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)m, (wolfSSL_Free_cb)f, + (wolfSSL_Realloc_cb)r) == 0) + return WOLFSSL_SUCCESS; +#else + WOLFSSL_MSG("wolfSSL was compiled without WOLFSSL_DEBUG_MEMORY. mem " + "functions will receive a NULL file name and 0 for the " + "line number."); + if (wolfSSL_SetAllocators(OSSL_Malloc, OSSL_Free, OSSL_Realloc) == 0) { + ossl_malloc = m; + ossl_free = f; + ossl_realloc = r; return WOLFSSL_SUCCESS; + } +#endif else return WOLFSSL_FAILURE; #else @@ -49064,51 +49391,6 @@ WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x) } #endif -#ifndef NO_WOLFSSL_STUB -int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) -{ - (void)ctx; - (void)session; - WOLFSSL_ENTER("wolfSSL_CTX_add_session"); - WOLFSSL_STUB("SSL_CTX_add_session"); - - return WOLFSSL_SUCCESS; -} -#endif - - -int wolfSSL_version(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_version"); - if (ssl->version.major == SSLv3_MAJOR) { - switch (ssl->version.minor) { - case SSLv3_MINOR : - return SSL3_VERSION; - case TLSv1_MINOR : - return TLS1_VERSION; - case TLSv1_1_MINOR : - return TLS1_1_VERSION; - case TLSv1_2_MINOR : - return TLS1_2_VERSION; - case TLSv1_3_MINOR : - return TLS1_3_VERSION; - default: - return WOLFSSL_FAILURE; - } - } - else if (ssl->version.major == DTLS_MAJOR) { - switch (ssl->version.minor) { - case DTLS_MINOR : - return DTLS1_VERSION; - case DTLSv1_2_MINOR : - return DTLS1_2_VERSION; - default: - return WOLFSSL_FAILURE; - } - } - return WOLFSSL_FAILURE; -} - #ifdef HAVE_SNI int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name) { @@ -49324,6 +49606,38 @@ unsigned long wolfSSL_ERR_peek_last_error(void) #endif /* OPENSSL_EXTRA */ +int wolfSSL_version(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_version"); + if (ssl->version.major == SSLv3_MAJOR) { + switch (ssl->version.minor) { + case SSLv3_MINOR : + return SSL3_VERSION; + case TLSv1_MINOR : + return TLS1_VERSION; + case TLSv1_1_MINOR : + return TLS1_1_VERSION; + case TLSv1_2_MINOR : + return TLS1_2_VERSION; + case TLSv1_3_MINOR : + return TLS1_3_VERSION; + default: + return WOLFSSL_FAILURE; + } + } + else if (ssl->version.major == DTLS_MAJOR) { + switch (ssl->version.minor) { + case DTLS_MINOR : + return DTLS1_VERSION; + case DTLSv1_2_MINOR : + return DTLS1_2_VERSION; + default: + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_FAILURE; +} + WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_get_SSL_CTX"); @@ -51234,8 +51548,11 @@ static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, *encLen = encTicketLen + len; } - ret = (res == TICKET_KEY_CB_RET_RENEW) ? WOLFSSL_TICKET_RET_CREATE : - WOLFSSL_TICKET_RET_OK; + if (res == TICKET_KEY_CB_RET_RENEW && !IsAtLeastTLSv1_3(ssl->version) + && !enc) + ret = WOLFSSL_TICKET_RET_CREATE; + else + ret = WOLFSSL_TICKET_RET_OK; end: return ret; } @@ -51722,8 +52039,13 @@ WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x) { WOLFSSL_ENTER("wolfSSL_X509_dup"); - if (x == NULL || x->derCert == NULL) { - WOLFSSL_MSG("Error: NULL certificate passed in"); + if (x == NULL) { + WOLFSSL_MSG("Error: NULL input"); + return NULL; + } + + if (x->derCert == NULL) { + WOLFSSL_MSG("Error: NULL derCert parameter"); return NULL; } @@ -63549,8 +63871,8 @@ WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) { WC_PKCS12* localPkcs12 = NULL; unsigned char* mem = NULL; - int ret; - word32 size; + long memSz; + int ret = -1; WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); @@ -63559,36 +63881,43 @@ WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) return NULL; } - localPkcs12 = wc_PKCS12_new(); - if (localPkcs12 == NULL) { - WOLFSSL_MSG("Memory error"); + memSz = wolfSSL_BIO_get_len(bio); + if (memSz <= 0) { + return NULL; + } + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { return NULL; } - if (pkcs12 != NULL) { - *pkcs12 = localPkcs12; + if (mem != NULL) { + localPkcs12 = wc_PKCS12_new(); + if (localPkcs12 == NULL) { + WOLFSSL_MSG("Memory error"); + } } - ret = wolfSSL_BIO_get_mem_data(bio, &mem); - if (mem == NULL || ret <= 0) { - WOLFSSL_MSG("Failed to get data from bio struct"); - wc_PKCS12_free(localPkcs12); - if (pkcs12 != NULL) { - *pkcs12 = NULL; + if (mem != NULL && localPkcs12 != NULL) { + if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { + ret = wc_d2i_PKCS12(mem, memSz, localPkcs12); + if (ret < 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + } + } + else { + WOLFSSL_MSG("Failed to get data from bio struct"); } - return NULL; } - size = ret; - ret = wc_d2i_PKCS12(mem, size, localPkcs12); - if (ret < 0) { - WOLFSSL_MSG("Failed to get PKCS12 sequence"); + /* cleanup */ + if (mem != NULL) + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0 && localPkcs12 != NULL) { wc_PKCS12_free(localPkcs12); - if (pkcs12 != NULL) { - *pkcs12 = NULL; - } - return NULL; + localPkcs12 = NULL; } + if (pkcs12 != NULL) + *pkcs12 = localPkcs12; return localPkcs12; } diff --git a/src/tls13.c b/src/tls13.c index de194bcde5..20b9dafc94 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3562,17 +3562,21 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case TLS_ASYNC_FINALIZE: { #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT - if (args->sessIdSz == 0) + if (args->sessIdSz == 0) { + WOLFSSL_MSG("args->sessIdSz == 0"); return INVALID_PARAMETER; + } if (ssl->session.sessionIDSz != 0) { if (ssl->session.sessionIDSz != args->sessIdSz || XMEMCMP(ssl->session.sessionID, args->sessId, args->sessIdSz) != 0) { + WOLFSSL_MSG("session id doesn't match"); return INVALID_PARAMETER; } } else if (XMEMCMP(ssl->arrays->clientRandom, args->sessId, args->sessIdSz) != 0) { + WOLFSSL_MSG("session id doesn't match client random"); return INVALID_PARAMETER; } #else diff --git a/tests/api.c b/tests/api.c index bfeb664413..17a561ad59 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2423,6 +2423,7 @@ static int test_wolfSSL_CTX_use_certificate_chain_file_format(void) int ret = 0; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) const char* server_chain_der = "./certs/server-cert-chain.der"; + const char* client_single_pem = "./certs/client-cert.pem"; WOLFSSL_CTX* ctx; #ifndef NO_WOLFSSL_CLIENT @@ -2435,6 +2436,8 @@ static int test_wolfSSL_CTX_use_certificate_chain_file_format(void) AssertIntEQ(wolfSSL_CTX_use_certificate_chain_file_format(ctx, server_chain_der, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_use_certificate_chain_file_format(ctx, + client_single_pem, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif @@ -4446,6 +4449,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) callback_functions* cbf; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; + func_args* opts = (func_args*)args; char msg[] = "I hear you fa shizzle!"; char input[1024]; @@ -4460,8 +4464,8 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) fdOpenSession(Task_self()); #endif - ((func_args*)args)->return_code = TEST_FAIL; - cbf = ((func_args*)args)->callbacks; + opts->return_code = TEST_FAIL; + cbf = opts->callbacks; #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (cbf != NULL && cbf->ctx) { @@ -4484,19 +4488,21 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) goto done; } + if (cbf != NULL && !cbf->ticNoInit) { #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) - OpenSSLTicketInit(); - wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx, myTicketEncCbOpenSSL); + OpenSSLTicketInit(); + wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx, myTicketEncCbOpenSSL); #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) - TicketInit(); - wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); + TicketInit(); + wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif #endif + } #if defined(USE_WINDOWS_API) - port = ((func_args*)args)->signal->port; + port = opts->signal->port; #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) /* Let tcp_listen assign port */ @@ -4507,7 +4513,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #endif /* do it here to detect failure */ - tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); + tcp_accept(&sockfd, &clientfd, opts, port, 0, 0, 0, 0, 1, 0, 0); CloseSocket(sockfd); wolfSSL_CTX_set_verify(ctx, @@ -4557,7 +4563,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #ifdef WOLFSSL_SESSION_EXPORT /* only add in more complex nonblocking case with session export tests */ - if (args && ((func_args*)args)->argc > 0) { + if (args && opts->argc > 0) { /* set as nonblock and time out for waiting on read/write */ tcp_set_nonblocking(&clientfd); wolfSSL_dtls_set_using_nonblock(ssl, 1); @@ -4604,10 +4610,10 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #ifdef WOLFSSL_SESSION_EXPORT /* only add in more complex nonblocking case with session export tests */ - if (((func_args*)args)->argc > 0) { + if (opts->argc > 0) { ret = nonblocking_accept_read(args, ssl, &clientfd); if (ret >= 0) { - ((func_args*)args)->return_code = TEST_SUCCESS; + opts->return_code = TEST_SUCCESS; } #ifdef WOLFSSL_TIRTOS Task_yield(); @@ -4668,7 +4674,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) Task_yield(); #endif - ((func_args*)args)->return_code = TEST_SUCCESS; + opts->return_code = TEST_SUCCESS; done: wolfSSL_shutdown(ssl); @@ -4687,14 +4693,16 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) wc_ecc_fp_free(); /* free per thread cache */ #endif + if (cbf != NULL && !cbf->ticNoInit) { #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) - OpenSSLTicketCleanup(); + OpenSSLTicketCleanup(); #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) - TicketCleanup(); + TicketCleanup(); #endif #endif + } #ifndef WOLFSSL_TIRTOS return 0; @@ -5072,6 +5080,9 @@ static void test_client_nofail(void* args, cbType cb) printf("Server response: %s\n", reply); } + if (cbf != NULL && cbf->on_result != NULL) + cbf->on_result(ssl); + ((func_args*)args)->return_code = TEST_SUCCESS; done: @@ -6199,6 +6210,168 @@ static void test_wolfSSL_get_finished(void) #endif } +#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ + !defined(SINGLE_THREADED) && defined(WOLFSSL_TLS13) && \ + !defined(NO_SESSION_CACHE) + +/* Sessions to restore/store */ +static WOLFSSL_SESSION* test_wolfSSL_CTX_add_session_client_sess; +static WOLFSSL_SESSION* test_wolfSSL_CTX_add_session_server_sess; +static WOLFSSL_CTX* test_wolfSSL_CTX_add_session_server_ctx; + +static void test_wolfSSL_CTX_add_session_ctx_ready(WOLFSSL_CTX* ctx) +{ + /* Don't store sessions. Lookup is still enabled. */ + AssertIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx, + WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE), WOLFSSL_SUCCESS); + /* Require both peers to provide certs */ + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); +} + +static void test_wolfSSL_CTX_add_session_on_result(WOLFSSL* ssl) +{ + WOLFSSL_SESSION** sess; + if (wolfSSL_is_server(ssl)) + sess = &test_wolfSSL_CTX_add_session_server_sess; + else + sess = &test_wolfSSL_CTX_add_session_client_sess; + if (*sess == NULL) { + AssertNotNull(*sess = wolfSSL_get1_session(ssl)); + /* Now save the session in the internal store to make it available + * for lookup */ + AssertIntEQ(wolfSSL_CTX_add_session(wolfSSL_get_SSL_CTX(ssl), *sess), + WOLFSSL_SUCCESS); + } + else { + /* If we have a session retrieved then remaining connections should be + * resuming on that session */ + AssertIntEQ(wolfSSL_session_reused(ssl), 1); + } + /* Save CTX to be able to decrypt tickets */ + if (wolfSSL_is_server(ssl) && + test_wolfSSL_CTX_add_session_server_ctx == NULL) { + AssertNotNull(test_wolfSSL_CTX_add_session_server_ctx + = wolfSSL_get_SSL_CTX(ssl)); + AssertIntEQ(wolfSSL_CTX_up_ref(wolfSSL_get_SSL_CTX(ssl)), + WOLFSSL_SUCCESS); + } +#ifdef SESSION_CERTS +#ifndef WOLFSSL_TICKET_HAVE_ID + if (wolfSSL_version(ssl) != TLS1_3_VERSION) +#endif + { + /* With WOLFSSL_TICKET_HAVE_ID the peer certs should be available + * for all connections. TLS 1.3 only has tickets so if we don't + * include the session id in the ticket then the certificates + * will not be available. */ + WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); + AssertNotNull(peer); + wolfSSL_X509_free(peer); + } +#endif +} + +static void test_wolfSSL_CTX_add_session_ssl_ready(WOLFSSL* ssl) +{ + /* Set the session to reuse for the client */ + AssertIntEQ(wolfSSL_set_session(ssl, + test_wolfSSL_CTX_add_session_client_sess), WOLFSSL_SUCCESS); +} +#endif + +static void test_wolfSSL_CTX_add_session(void) +{ +#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ + !defined(SINGLE_THREADED) && defined(WOLFSSL_TLS13) && \ + !defined(NO_SESSION_CACHE) + tcp_ready ready; + func_args client_args; + func_args server_args; + THREAD_TYPE serverThread; + callback_functions client_cb; + callback_functions server_cb; + method_provider methods[][2] = { +#ifndef NO_OLD_TLS + { wolfTLSv1_1_client_method, wolfTLSv1_1_server_method }, +#endif +#ifndef WOLFSSL_NO_TLS12 + { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method }, +#endif + /* Needs the default ticket callback since it is tied to the + * connection context and this makes it easy to carry over the ticket + * crypto context between connections */ +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ + defined(HAVE_SESSION_TICKET) + { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method }, +#endif + }; + const size_t methodsLen = sizeof(methods)/sizeof(*methods); + size_t i, j; + + printf(testingFmt, "wolfSSL_CTX_add_session()"); + + for (i = 0; i < methodsLen; i++) { + /* First run creates a connection while the second+ run will attempt + * to resume the connection. The trick is that the internal cache + * is turned off. wolfSSL_CTX_add_session should put the session in + * the cache anyway. */ + test_wolfSSL_CTX_add_session_client_sess = NULL; + test_wolfSSL_CTX_add_session_server_sess = NULL; + test_wolfSSL_CTX_add_session_server_ctx = NULL; + + for (j = 0; j < 5; j++) { +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + StartTCP(); + InitTcpReady(&ready); + + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + XMEMSET(&client_cb, 0, sizeof(callback_functions)); + XMEMSET(&server_cb, 0, sizeof(callback_functions)); + client_cb.method = methods[i][0]; + server_cb.method = methods[i][1]; + + server_args.signal = &ready; + server_args.callbacks = &server_cb; + client_args.signal = &ready; + client_args.callbacks = &client_cb; + + if (test_wolfSSL_CTX_add_session_server_ctx != NULL) { + server_cb.ctx = test_wolfSSL_CTX_add_session_server_ctx; + server_cb.isSharedCtx = 1; + } + server_cb.ctx_ready = test_wolfSSL_CTX_add_session_ctx_ready; + client_cb.ctx_ready = test_wolfSSL_CTX_add_session_ctx_ready; + if (j != 0) + client_cb.ssl_ready = test_wolfSSL_CTX_add_session_ssl_ready; + server_cb.on_result = test_wolfSSL_CTX_add_session_on_result; + client_cb.on_result = test_wolfSSL_CTX_add_session_on_result; + server_cb.ticNoInit = 1; /* Use default builtin */ + + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args, NULL); + join_thread(serverThread); + + AssertTrue(client_args.return_code); + AssertTrue(server_args.return_code); + + FreeTcpReady(&ready); + } + wolfSSL_SESSION_free(test_wolfSSL_CTX_add_session_client_sess); + wolfSSL_SESSION_free(test_wolfSSL_CTX_add_session_server_sess); + wolfSSL_CTX_free(test_wolfSSL_CTX_add_session_server_ctx); + } + + printf(resultFmt, passed); + +#endif +} + #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) /* canned export of a session using older version 3 */ static unsigned char version_3[] = { @@ -7961,6 +8134,7 @@ static void test_wolfSSL_PKCS12(void) AssertNotNull(pkcs12); PKCS12_free(pkcs12); + AssertIntEQ(BIO_write(bio, buf, bytes), bytes); /* d2i consumes BIO */ d2i_PKCS12_bio(bio, &pkcs12); AssertNotNull(pkcs12); BIO_free(bio); @@ -33653,10 +33827,12 @@ static void post_auth_version_cb(WOLFSSL* ssl) static void post_auth_cb(WOLFSSL* ssl) { + WOLFSSL_X509* x509; /* do handshake and then test version error */ AssertIntEQ(wolfSSL_accept(ssl), WOLFSSL_SUCCESS); AssertStrEQ("TLSv1.3", wolfSSL_get_version(ssl)); - AssertNull(wolfSSL_get_peer_certificate(ssl)); + AssertNull(x509 = wolfSSL_get_peer_certificate(ssl)); + wolfSSL_X509_free(x509); AssertIntEQ(wolfSSL_verify_client_post_handshake(ssl), WOLFSSL_SUCCESS); } @@ -49800,11 +49976,15 @@ static void test_wolfSSL_CTX_LoadCRL(void) { #ifdef HAVE_CRL WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; const char* badPath = "dummypath"; const char* validPath = "./certs/crl"; + const char* validFilePath = "./certs/crl/cliCrl.pem"; + const char* issuerCert = "./certs/client-cert.pem"; int derType = WOLFSSL_FILETYPE_ASN1; int pemType = WOLFSSL_FILETYPE_PEM; int monitor = WOLFSSL_CRL_MONITOR; + WOLFSSL_CERT_MANAGER* cm = NULL; #define FAIL_T1(x, y, z, p, d) AssertIntEQ((int) x(y, z, p, d), \ BAD_FUNC_ARG) @@ -49826,7 +50006,27 @@ static void test_wolfSSL_CTX_LoadCRL(void) SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, derType, monitor); wolfSSL_CTX_free(ctx); - ctx = NULL; + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, validFilePath, pemType), WOLFSSL_SUCCESS); + wolfSSL_CTX_free(ctx); + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL), + WOLFSSL_SUCCESS); + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntEQ(wolfSSL_LoadCRLFile(ssl, validFilePath, pemType), WOLFSSL_SUCCESS); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + AssertNotNull(cm = wolfSSL_CertManagerNew()); + AssertIntEQ(wolfSSL_CertManagerLoadCA(cm, issuerCert, NULL), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CertManagerLoadCRLFile(cm, validFilePath, pemType), WOLFSSL_SUCCESS); + wolfSSL_CertManagerFree(cm); + #endif } @@ -50920,9 +51120,7 @@ static void test_wolfSSL_CRYPTO_get_ex_new_index(void) printf(testingFmt, "test_wolfSSL_CRYPTO_get_ex_new_index()"); - /* test for unsupported flass index */ - AssertIntEQ(wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, - 0,NULL, NULL, NULL, NULL ), -1); + /* test for unsupported class index */ AssertIntEQ(wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, 0,NULL, NULL, NULL, NULL ), -1); AssertIntEQ(wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, @@ -50974,6 +51172,15 @@ static void test_wolfSSL_CRYPTO_get_ex_new_index(void) AssertIntNE(idx2, -1); AssertIntNE(idx1, idx2); + + idx1 = wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, + 0,NULL, NULL, NULL, NULL ); + idx2 = wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, + 0,NULL, NULL, NULL, NULL ); + AssertIntNE(idx1, -1); + AssertIntNE(idx2, -1); + AssertIntNE(idx1, idx2); + printf(resultFmt, "passed"); #endif /* HAVE_EX_DATA */ } @@ -52113,6 +52320,7 @@ void ApiTest(void) #ifdef HAVE_IO_TESTS_DEPENDENCIES test_wolfSSL_get_finished(); #endif + test_wolfSSL_CTX_add_session(); test_SSL_CIPHER_get_xxx(); test_wolfSSL_ERR_strings(); test_wolfSSL_EVP_shake128(); diff --git a/tests/test-trustpeer.conf b/tests/test-trustpeer.conf index c8df70416d..9cc242d655 100644 --- a/tests/test-trustpeer.conf +++ b/tests/test-trustpeer.conf @@ -1,5 +1,6 @@ # Both client and server use -E [path] for trusted peer # server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-V -v 3 -l DHE-RSA-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-cert.pem @@ -7,6 +8,7 @@ -c ./certs/intermediate/server-int-cert.pem # client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-C -v 3 -l DHE-RSA-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-cert.pem @@ -14,6 +16,7 @@ -c ./certs/intermediate/client-int-cert.pem # server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-V -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-cert.pem @@ -21,6 +24,7 @@ -c ./certs/intermediate/server-int-cert.pem # client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-C -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-cert.pem @@ -28,6 +32,7 @@ -c ./certs/intermediate/client-int-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer +-V -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-ecc-cert.pem @@ -35,6 +40,7 @@ -c ./certs/intermediate/server-int-ecc-cert.pem # client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer +-C -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-ecc-cert.pem @@ -42,6 +48,7 @@ -c ./certs/intermediate/client-int-ecc-cert.pem # server TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Trusted Peer +-V -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-cert.pem @@ -49,6 +56,7 @@ -c ./certs/intermediate/server-int-cert.pem # client TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Trusted Peer +-C -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-cert.pem @@ -56,6 +64,7 @@ -c ./certs/intermediate/client-int-cert.pem # server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer +-V -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-ecc-cert.pem @@ -63,6 +72,7 @@ -c ./certs/intermediate/server-int-ecc-cert.pem # client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer +-C -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-ecc-cert.pem @@ -71,6 +81,7 @@ # Test for ECC self signed certificate as trusted peer # server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-V -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -E ./certs/client-ecc-cert.pem @@ -78,6 +89,7 @@ -c ./certs/server-ecc-self.pem # client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-C -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -E ./certs/server-ecc-self.pem @@ -85,6 +97,7 @@ -c ./certs/client-ecc-cert.pem # server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-V -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/client-ecc-cert.pem @@ -92,6 +105,7 @@ -c ./certs/server-ecc-self.pem # client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-C -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/server-ecc-self.pem diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index d690e3b86d..57de940ab3 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -252,7 +252,11 @@ const char* wc_GetErrorString(int error) return "Bad alignment error, no alloc help"; case ASN_NO_SIGNER_E : +#ifndef OPENSSL_EXTRA return "ASN no signer error to confirm failure"; +#else + return "certificate verify failed"; +#endif case ASN_CRL_CONFIRM_E : return "ASN CRL sig error, confirm failure"; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 05d8e262c7..80e1d302d5 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2758,6 +2758,7 @@ struct WOLFSSL_CTX { byte sessionCacheFlushOff:1; #ifdef HAVE_EXT_CACHE byte internalCacheOff:1; + byte internalCacheLookupOff:1; #endif byte sendVerify:2; /* for client side (can not be single bit) */ byte haveRSA:1; /* RSA available */ @@ -3083,7 +3084,7 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_LOCAL int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify); WOLFSSL_LOCAL - int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash); + int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DecodedCert* cert); #endif #endif @@ -3364,8 +3365,21 @@ struct WOLFSSL_SESSION { word16 ticketLenAlloc; /* is dynamic */ #endif int refCount; /* reference count */ +#ifndef SINGLE_THREADED + wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif void* heap; +#ifdef SESSION_CERTS + WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ + #ifdef WOLFSSL_ALT_CERT_CHAINS + WOLFSSL_X509_CHAIN altChain; /* peer alt cert chain, static */ + #endif +#endif +#ifdef HAVE_EX_DATA + WOLFSSL_CRYPTO_EX_DATA ex_data; +#endif + #ifdef ENABLE_CLIENT_SESSION_REF /* pointer to WOLFSSL_SESSION in internal cache (for WOLFSSL_SESSION_TYPE_REF) */ void* refPtr; @@ -3374,7 +3388,8 @@ struct WOLFSSL_SESSION { /* Below buffers are not allocated for the WOLFSSL_SESSION_TYPE_REF, instead * the above pointers reference the session cache for backwards * compatibility. For all other session types the above pointers reference - * these buffers directly */ + * these buffers directly. Keep these buffers at the end so that they don't + * get copied into the WOLFSSL_SESSION_TYPE_REF object. */ byte _masterSecret[SECRET_LEN]; #ifndef NO_CLIENT_CACHE byte _serverID[SERVER_ID_LEN]; @@ -3385,21 +3400,6 @@ struct WOLFSSL_SESSION { #ifdef OPENSSL_EXTRA byte _sessionCtx[ID_LEN]; #endif - -#ifdef SESSION_CERTS - WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ - #ifdef WOLFSSL_ALT_CERT_CHAINS - WOLFSSL_X509_CHAIN altChain; /* peer alt cert chain, static */ - #endif -#endif -#ifdef HAVE_EX_DATA - WOLFSSL_CRYPTO_EX_DATA ex_data; -#endif -#ifdef OPENSSL_EXTRA - #ifndef SINGLE_THREADED - wolfSSL_Mutex refMutex; /* ref count mutex */ - #endif -#endif }; @@ -3598,6 +3598,7 @@ typedef struct Options { word16 sessionCacheFlushOff:1; #ifdef HAVE_EXT_CACHE word16 internalCacheOff:1; + word16 internalCacheLookupOff:1; #endif word16 side:2; /* client, server or neither end */ word16 verifyPeer:1; @@ -3703,6 +3704,9 @@ typedef struct Options { word16 startedETMRead:1; /* Doing Encrypt-Then-MAC read */ word16 startedETMWrite:1; /* Doing Encrypt-Then-MAC write */ #endif +#ifdef WOLFSSL_TICKET_HAVE_ID + word16 haveTicketSessionID:1; +#endif /* need full byte values for this section */ byte processReply; /* nonblocking resume */ @@ -4234,6 +4238,9 @@ struct WOLFSSL { WOLFSSL_SESSION session; #ifdef HAVE_EXT_CACHE WOLFSSL_SESSION* extSession; +#endif +#ifdef WOLFSSL_TICKET_HAVE_ID + byte ticketSessionID[ID_LEN]; #endif WOLFSSL_ALERT_HISTORY alert_history; int error; @@ -4390,6 +4397,8 @@ struct WOLFSSL { WOLFSSL_X509_STORE* x509_store_pt; /* take ownership of external store */ #endif #ifdef KEEP_PEER_CERT + /* TODO put this on the heap so we can properly use the + * reference counter and not have to duplicate it. */ WOLFSSL_X509 peerCert; /* X509 peer cert */ #endif #ifdef KEEP_OUR_CERT @@ -4572,6 +4581,22 @@ struct WOLFSSL { #endif }; +/* + * wolfSSL_PEM_read_bio_X509 pushes an ASN_NO_PEM_HEADER error + * to the error queue on file end. This should not be left + * for the caller to find so we clear the last error. + */ +#ifdef WOLFSSL_HAVE_ERROR_QUEUE +#define CLEAR_ASN_NO_PEM_HEADER_ERROR(err) \ + err = wolfSSL_ERR_peek_last_error(); \ + if (ERR_GET_LIB(err) == ERR_LIB_PEM && \ + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { \ + wc_RemoveErrorNode(-1); \ + } +#else +#define CLEAR_ASN_NO_PEM_HEADER_ERROR(err) (void)err; +#endif + /* * The SSL object may have its own certificate store. The below macros simplify * logic for choosing which WOLFSSL_CERT_MANAGER and WOLFSSL_X509_STORE to use. @@ -4827,8 +4852,7 @@ WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, #define WC_MATCH_SKID 0 #define WC_MATCH_NAME 1 - WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, - int type); + WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert); WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert); #endif diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index 8628685cf5..80289e0249 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -32,7 +32,7 @@ /* valid version */ #elif defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIBEST) || \ defined(WOLFSSL_BIND) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_RSYSLOG) || defined(WOLFSSL_KRB) + defined(WOLFSSL_RSYSLOG) || defined(WOLFSSL_KRB) || defined(HAVE_STUNNEL) /* For Apache httpd, Use 1.1.0 compatibility */ #define OPENSSL_VERSION_NUMBER 0x10100003L #elif defined(WOLFSSL_QT) || defined(WOLFSSL_PYTHON) @@ -40,7 +40,7 @@ #define OPENSSL_VERSION_NUMBER 0x10101000L #elif defined(WOLFSSL_HAPROXY) #define OPENSSL_VERSION_NUMBER 0x1010000fL -#elif defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || \ +#elif defined(OPENSSL_ALL) || defined(HAVE_LIGHTY) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_OPENVPN) /* version number can be increased for Lighty after compatibility for ECDH is added */ @@ -49,7 +49,7 @@ #define OPENSSL_VERSION_NUMBER 0x0090810fL #endif -#define OPENSSL_VERSION_TEXT LIBWOLFSSL_VERSION_STRING +#define OPENSSL_VERSION_TEXT "wolfSSL " LIBWOLFSSL_VERSION_STRING #define OPENSSL_VERSION 0 #endif /* header */ diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 164964bdf1..47329c03d6 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -319,6 +319,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_set_post_handshake_auth wolfSSL_set_post_handshake_auth #define SSL_CTX_set_post_handshake_auth wolfSSL_CTX_set_post_handshake_auth #define SSL_pending wolfSSL_pending +#define SSL_has_pending wolfSSL_has_pending #define SSL_load_error_strings wolfSSL_load_error_strings #define SSL_library_init wolfSSL_library_init #define OPENSSL_cleanup (void)wolfSSL_Cleanup diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 37ec8a877f..552f8c7acc 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -32,10 +32,11 @@ /* for users not using preprocessor flags*/ #include #include -#include #include -#include +#include +#include #include +#include /* For the types */ #include @@ -1192,7 +1193,8 @@ WOLFSSL_API int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val); WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx); -WOLFSSL_ABI WOLFSSL_API int wolfSSL_pending(WOLFSSL* ssl); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_pending(const WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_has_pending(const WOLFSSL* ssl); WOLFSSL_API void wolfSSL_load_error_strings(void); WOLFSSL_API int wolfSSL_library_init(void); @@ -2199,12 +2201,12 @@ enum { X509_V_OK = 0, X509_V_ERR_CRL_SIGNATURE_FAILURE = 8, - X509_V_ERR_CERT_HAS_EXPIRED = 10, + X509_V_ERR_CERT_HAS_EXPIRED = ASN_AFTER_DATE_E, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14, X509_V_ERR_CRL_HAS_EXPIRED = 15, X509_V_ERR_CERT_CHAIN_TOO_LONG = 17, X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18, - X509_V_ERR_CERT_NOT_YET_VALID = 19, + X509_V_ERR_CERT_NOT_YET_VALID = ASN_BEFORE_DATE_E, X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20, X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22, X509_V_ERR_CERT_REVOKED = 23, @@ -2214,7 +2216,7 @@ enum { X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 26, X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 27, X509_V_ERR_CERT_UNTRUSTED = 28, - X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 29, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = ASN_NO_SIGNER_E, X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 30, /* additional X509_V_ERR_* enums not used in wolfSSL */ X509_V_ERR_UNABLE_TO_GET_CRL, @@ -3348,6 +3350,8 @@ WOLFSSL_API void* wolfSSL_GetVerifyMacCtx(WOLFSSL* ssl); VerifyCallback vc); WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path, int type, int monitor); + WOLFSSL_API int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm, + const char* file, int type); WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm, const unsigned char* buff, long sz, int type); WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, @@ -3389,6 +3393,7 @@ WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options); WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor); + WOLFSSL_API int wolfSSL_LoadCRLFile(WOLFSSL* ssl, const char* file, int type); WOLFSSL_API int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff, long sz, int type); WOLFSSL_API int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb); @@ -3405,6 +3410,7 @@ WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( WOLFSSL_API int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options); WOLFSSL_API int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx); WOLFSSL_API int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, int type, int monitor); + WOLFSSL_API int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* path, int type); WOLFSSL_API int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, long sz, int type); WOLFSSL_API int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb); @@ -4313,9 +4319,9 @@ WOLFSSL_API WOLFSSL_ASN1_TYPE *wolfSSL_X509_ATTRIBUTE_get0_type( #include WOLFSSL_API int wolfSSL_CRYPTO_set_mem_functions( - wolfSSL_Malloc_cb m, - wolfSSL_Realloc_cb r, - wolfSSL_Free_cb f); + wolfSSL_OSSL_Malloc_cb m, + wolfSSL_OSSL_Realloc_cb r, + wolfSSL_OSSL_Free_cb f); WOLFSSL_API int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), void *(*r) (void *, size_t, const char *, int), void (*f) (void *)); diff --git a/wolfssl/test.h b/wolfssl/test.h index 7227e2261b..34ec8ff7aa 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -518,6 +518,7 @@ typedef struct callback_functions { int return_code; unsigned char isSharedCtx:1; unsigned char loadToSSL:1; + unsigned char ticNoInit:1; } callback_functions; #if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 25fd42233b..646e23175d 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1741,7 +1741,7 @@ struct TrustedPeerCert { /* sha hash of names in certificate */ #ifndef NO_SKID byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; - /* sha hash of names in certificate */ + /* sha hash of SKID in certificate */ #endif word32 sigLen; byte* sig; diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index 4014f25aed..b81009b67c 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -45,6 +45,12 @@ WOLFSSL_API void wolfSSL_SetMemFailCount(int memFailCount); #endif +#ifdef OPENSSL_EXTRA + typedef void *(*wolfSSL_OSSL_Malloc_cb)(size_t, const char *, int); + typedef void (*wolfSSL_OSSL_Free_cb)(void *, const char *, int); + typedef void *(*wolfSSL_OSSL_Realloc_cb)(void *, size_t, const char *, int); +#endif /* OPENSSL_EXTRA */ + #ifdef WOLFSSL_STATIC_MEMORY #ifdef WOLFSSL_DEBUG_MEMORY typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type, const char* func, unsigned int line); From 1d712d47ba9d1e85a9e866e296cb4d667e7145ac Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 1 Feb 2022 16:14:07 +0100 Subject: [PATCH 2/9] Access to session cache is now atomic - Adding and getting sessions to and from the local cache is now atomic. - The new internal `wolfSSL_GetSessionFromCache` requires a destination object to be supplied when retrieving from the cache so that items can be retrieved independently from the cache. For most existing calls, the destination is `ssl->session`. -`PREALLOC_SESSION_TICKET_LEN` defines how much memory is temporarily allocated for the ticket if it doesn't fit in the static session buffer. --- src/internal.c | 17 +- src/ssl.c | 1011 ++++++++++++++++++++--------------------- tests/api.c | 8 +- wolfssl/internal.h | 37 +- wolfssl/openssl/ssl.h | 9 - wolfssl/ssl.h | 20 +- 6 files changed, 532 insertions(+), 570 deletions(-) diff --git a/src/internal.c b/src/internal.c index c45318410e..04cdd3589e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -6629,6 +6629,8 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) } #endif /*OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ + ssl->session.heap = ssl->heap; + ssl->session.type = WOLFSSL_SESSION_TYPE_SSL; ssl->session.masterSecret = ssl->session._masterSecret; #ifndef NO_CLIENT_CACHE ssl->session.serverID = ssl->session._serverID; @@ -7230,9 +7232,6 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->session.ticketLen = 0; } #endif -#ifdef ENABLE_CLIENT_SESSION_REF - wolfSSL_SESSION_free(ssl->session.refPtr); -#endif #ifdef HAVE_EXT_CACHE wolfSSL_SESSION_free(ssl->extSession); #endif @@ -29269,9 +29268,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { int ret = 0; WOLFSSL_SESSION* session; - #ifdef HAVE_EXT_CACHE - byte gotSess = 0; - #endif (void)bogusID; #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket == 1) { @@ -29283,9 +29279,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif { session = wolfSSL_GetSession(ssl, ssl->arrays->masterSecret, 1); - #ifdef HAVE_EXT_CACHE - gotSess = 1; - #endif } if (!session) { WOLFSSL_MSG("Session lookup for resume failed"); @@ -29375,12 +29368,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } - #ifdef HAVE_EXT_CACHE - if (gotSess) { - wolfSSL_SESSION_free(session); - } - #endif - return ret; } diff --git a/src/ssl.c b/src/ssl.c index ffc0b03f86..21346570f1 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3353,7 +3353,7 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); } - ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap, + ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->session.heap, DYNAMIC_TYPE_SESSION_TICK); if(ssl->session.ticket == NULL) { ssl->session.ticket = ssl->session._staticTicket; @@ -4202,6 +4202,7 @@ int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm) #ifndef SINGLE_THREADED if (wc_LockMutex(&cm->refMutex) != 0) { WOLFSSL_MSG("Failed to lock cm mutex"); + return WOLFSSL_FAILURE; } #endif cm->refCount++; @@ -12482,7 +12483,7 @@ WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_session"); if (ssl) - return wolfSSL_GetSession(ssl, NULL, 1); + return &ssl->session; return NULL; } @@ -12493,25 +12494,39 @@ WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) WOLFSSL_SESSION* sess = NULL; WOLFSSL_ENTER("SSL_get1_session"); if (ssl != NULL) { - sess = wolfSSL_GetSessionRef(ssl); - if (sess == NULL) - sess = wolfSSL_GetSession(ssl, NULL, 1); - #ifdef HAVE_STUNNEL - /* stunnel wants to store meta data in the session so always give it - * something that it can write to. */ - if (sess == NULL) { - if (ssl->extSession == NULL) - ssl->extSession = sess = wolfSSL_SESSION_new(); - else - sess = ssl->extSession; +#ifdef HAVE_EXT_CACHE + sess = &ssl->session; + if (ssl->extSession == NULL) { + ssl->extSession = sess = wolfSSL_SESSION_new(); + if (wolfSSL_DupSession(&ssl->session, sess, 0) + != WOLFSSL_SUCCESS) { + sess = NULL; + } +#ifdef WOLFSSL_TICKET_HAVE_ID + /* Set the real session ID for the independent session object */ + if (sess != NULL && ssl->options.haveTicketSessionID) { + XMEMCPY(sess->sessionID, ssl->ticketSessionID, ID_LEN); + sess->sessionIDSz = ID_LEN; + } +#endif } - #endif + else + sess = ssl->extSession; +#else + sess = wolfSSL_SESSION_new(); + if (sess != NULL) { + if (wolfSSL_DupSession(&ssl->session, sess, 0) + != WOLFSSL_SUCCESS) { + wolfSSL_SESSION_free(sess); + sess = NULL; + } + } +#endif if (sess != NULL) { /* wolfSSL_get_session returns either static cache or ref. If ref then * increase reference counter */ /* increase reference count if allocated session */ - if (sess->type == WOLFSSL_SESSION_TYPE_HEAP || - sess->type == WOLFSSL_SESSION_TYPE_REF) { + if (sess->type == WOLFSSL_SESSION_TYPE_HEAP) { if (wolfSSL_SESSION_up_ref(sess) != WOLFSSL_SUCCESS) sess = NULL; } @@ -15188,16 +15203,6 @@ int wolfSSL_Cleanup(void) } -static WC_INLINE WOLFSSL_SESSION* GetSessionPtr(const WOLFSSL_SESSION* s) -{ -#ifdef ENABLE_CLIENT_SESSION_REF - if (s && s->type == WOLFSSL_SESSION_TYPE_REF) { - s = (const WOLFSSL_SESSION*)s->refPtr; - } -#endif - return (WOLFSSL_SESSION*)s; -} - #ifndef NO_SESSION_CACHE /* some session IDs aren't random after all, let's make them random */ @@ -15408,43 +15413,6 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) #endif /* !NO_CLIENT_CACHE */ -/* Restore the master secret and session information for certificates. - * - * ssl The SSL/TLS object. - * session The cached session to restore. - * masterSecret The master secret from the cached session. - * restoreSessionCerts Restoring session certificates is required. - */ -static WC_INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session, - byte* masterSecret, byte restoreSessionCerts) -{ - (void)ssl; - (void)restoreSessionCerts; - - if (masterSecret) - XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN); -#ifdef SESSION_CERTS - /* If set, we should copy the session certs into the ssl object - * from the session we are returning so we can resume */ - if (restoreSessionCerts) { - ssl->session.chain = session->chain; - ssl->session.version = session->version; - #ifdef NO_RESUME_SUITE_CHECK - ssl->session.cipherSuite0 = session->cipherSuite0; - ssl->session.cipherSuite = session->cipherSuite; - #endif - } -#endif /* SESSION_CERTS */ -#if !defined(NO_RESUME_SUITE_CHECK) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - ssl->session.cipherSuite0 = session->cipherSuite0; - ssl->session.cipherSuite = session->cipherSuite; -#endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - ssl->peerVerifyRet = (unsigned long)session->peerVerifyRet; -#endif -} - static int SslSessionCacheOff(const WOLFSSL* ssl, const WOLFSSL_SESSION* session) { (void)session; @@ -15458,28 +15426,47 @@ static int SslSessionCacheOff(const WOLFSSL* ssl, const WOLFSSL_SESSION* session ; } -WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, - byte restoreSessionCerts) + +int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) { - WOLFSSL_SESSION* ret = NULL; + WOLFSSL_SESSION* sess = NULL; const byte* id = NULL; word32 row; int idx; int count; int error = 0; SessionRow* sessRow; +#ifdef HAVE_SESSION_TICKET +#ifndef WOLFSSL_SMALL_STACK + byte tmpTicket[PREALLOC_SESSION_TICKET_LEN]; +#else + byte* tmpTicket = NULL; +#endif + byte tmpBufSet = 0; +#endif +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* peer = NULL; +#endif +#ifdef WOLFSSL_TICKET_HAVE_ID + byte bogusID[ID_LEN]; +#endif - (void)restoreSessionCerts; + WOLFSSL_ENTER("wolfSSL_GetSessionFromCache"); + + if (output == NULL) { + WOLFSSL_MSG("NULL output"); + return WOLFSSL_FAILURE; + } if (SslSessionCacheOff(ssl, &ssl->session)) - return NULL; + return WOLFSSL_FAILURE; if (ssl->options.haveSessionId == 0) - return NULL; + return WOLFSSL_FAILURE; #ifdef HAVE_SESSION_TICKET if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) - return NULL; + return WOLFSSL_FAILURE; #endif if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) @@ -15488,8 +15475,12 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, id = ssl->session.sessionID; #ifdef WOLFSSL_TICKET_HAVE_ID - if (ssl->options.haveTicketSessionID) + if (ssl->options.haveTicketSessionID) { id = ssl->ticketSessionID; + /* We want to restore the bogus ID for TLS compatibility */ + if (output->type == WOLFSSL_SESSION_TYPE_SSL) + XMEMCPY(bogusID, ssl->session.sessionID, ID_LEN); + } #endif #ifdef HAVE_EXT_CACHE @@ -15497,36 +15488,79 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, int copy = 0; /* Attempt to retrieve the session from the external cache. */ WOLFSSL_MSG("Calling external session cache"); - ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); - if (ret != NULL) { + sess = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); + if (sess != NULL) { WOLFSSL_MSG("Session found in external cache"); - RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); - return ret; + error = wolfSSL_DupSession(sess, output, 0); + /* If copy not set then free immediately */ + if (!copy) + wolfSSL_SESSION_free(sess); +#ifdef WOLFSSL_TICKET_HAVE_ID + /* We want to restore the bogus ID for TLS compatibility */ + if (ssl->options.haveTicketSessionID && + output->type == WOLFSSL_SESSION_TYPE_SSL) + XMEMCPY(ssl->session.sessionID, bogusID, ID_LEN); +#endif + return error; } WOLFSSL_MSG("Session not found in external cache"); } if (ssl->ctx->internalCacheLookupOff) { - if (ssl->extSession != NULL) { - WOLFSSL_MSG("Found dynamic session"); - return ssl->extSession; - } WOLFSSL_MSG("Internal cache lookup turned off"); - return NULL; + return WOLFSSL_FAILURE; } #endif row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); - return NULL; + return WOLFSSL_FAILURE; + } + + +#ifdef HAVE_SESSION_TICKET + if (output->ticket == NULL || + output->ticketLenAlloc < PREALLOC_SESSION_TICKET_LEN) { +#ifdef WOLFSSL_SMALL_STACK + tmpTicket = (byte*)XMALLOC(PREALLOC_SESSION_TICKET_LEN, output->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpTicket == NULL) { + WOLFSSL_MSG("tmpTicket malloc failed"); + return WOLFSSL_FAILURE; + } +#endif + if (output->ticketLenAlloc) + XFREE(output->ticket, output->heap, DYNAMIC_TYPE_SESSION_TICK); + output->ticket = tmpTicket; + output->ticketLenAlloc = PREALLOC_SESSION_TICKET_LEN; + output->ticketLen = 0; + tmpBufSet = 1; + } +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (output->peer != NULL) { + wolfSSL_X509_free(output->peer); + output->peer = NULL; } +#endif /* lock row */ sessRow = &SessionCache[row]; if (SESSION_ROW_LOCK(sessRow) != 0) { WOLFSSL_MSG("Session cache row lock failure"); - return NULL; +#ifdef HAVE_SESSION_TICKET + if (tmpBufSet) { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } +#ifdef WOLFSSL_SMALL_STACK + if (tmpTicket != NULL) + XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif +#endif + return WOLFSSL_FAILURE; } /* start from most recently used */ @@ -15545,9 +15579,7 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, WOLFSSL_MSG("Found a session match"); if (LowResTimer() < (current->bornOn + current->timeout)) { WOLFSSL_MSG("Session valid"); - ret = current; - - RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); + sess = current; } else { WOLFSSL_MSG("Session timed out"); } @@ -15559,175 +15591,117 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1; } - SESSION_ROW_UNLOCK(sessRow); - -#ifdef HAVE_EXT_CACHE - if (ret == NULL && ssl->extSession != NULL) { - WOLFSSL_MSG("Found dynamic session"); - return ssl->extSession; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + /* We don't want the peer member. We will free it at the end. */ + if (sess->peer != NULL) { + peer = sess->peer; + sess->peer = NULL; } #endif + error = wolfSSL_DupSession(sess, output, 1); - return ret; -} + SESSION_ROW_UNLOCK(sessRow); -int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) -{ - int ret = WOLFSSL_SUCCESS, row; -#ifdef HAVE_SESSION_TICKET - int ticLenAlloc; - byte *ticBuff = NULL; -#endif -#ifdef ENABLE_CLIENT_SESSION_REF - WOLFSSL_SESSION* ref = NULL; +#ifdef WOLFSSL_TICKET_HAVE_ID + /* We want to restore the bogus ID for TLS compatibility */ + if (ssl->options.haveTicketSessionID && + output->type == WOLFSSL_SESSION_TYPE_SSL) + XMEMCPY(ssl->session.sessionID, bogusID, ID_LEN); #endif - if (ssl == NULL || session == NULL || SslSessionCacheOff(ssl, session)) { - return WOLFSSL_FAILURE; - } - - row = session->cacheRow; -#ifdef ENABLE_CLIENT_SESSION_REF - if (session->type == WOLFSSL_SESSION_TYPE_REF) { - if (session->refPtr == NULL) { - WOLFSSL_MSG("Invalid session reference"); - ret = WOLFSSL_FAILURE; +#ifdef HAVE_SESSION_TICKET + if (tmpBufSet) { + if (error == WOLFSSL_SUCCESS) { + if (output->ticketLen > SESSION_TICKET_LEN) { + output->ticket = (byte*)XMALLOC(output->ticketLen, output->heap, + DYNAMIC_TYPE_SESSION_TICK); + if (output->ticket == NULL) { + error = WOLFSSL_FAILURE; + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + output->ticketLen = 0; + } + } + else { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } } - if (ret == WOLFSSL_SUCCESS) { - ref = session; /* keep copy of ref for later */ - session = (WOLFSSL_SESSION*)session->refPtr; - row = session->cacheRow; + else { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + output->ticketLen = 0; + } + if (error == WOLFSSL_SUCCESS) { + XMEMCPY(output->ticket, tmpTicket, output->ticketLen); } - if (ret == WOLFSSL_FAILURE) - return WOLFSSL_FAILURE; } +#ifdef WOLFSSL_SMALL_STACK + if (tmpTicket != NULL) + XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif #endif - if (row != INVALID_SESSION_ROW && (row < 0 || row >= SESSION_ROWS)) { - return BAD_FUNC_ARG; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (peer != NULL) { + wolfSSL_X509_free(peer); } +#endif - /* lock session cache row */ - if (row != INVALID_SESSION_ROW && - SESSION_ROW_LOCK(&SessionCache[row]) != 0) { - return BAD_MUTEX_E; - } + return error; +} -#ifdef ENABLE_CLIENT_SESSION_REF - /* verify if ID matches session cache entry */ - if (ref != NULL && - XMEMCMP(ref->sessionID, session->sessionID, ID_LEN) != 0) { - WOLFSSL_MSG("Session cache reference not longer valid"); - ret = WOLFSSL_FAILURE; - } -#endif +WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, + byte restoreSessionCerts) +{ + WOLFSSL_SESSION* ret = NULL; -#ifdef HAVE_SESSION_TICKET - /* cache the old dynamic buffer and try to reuse or free later */ - ticLenAlloc = ssl->session.ticketLenAlloc; - if (ticLenAlloc > 0) { - ticBuff = ssl->session.ticket; - } -#endif + (void)restoreSessionCerts; /* Kept for compatibility */ -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (ssl->session.peer != NULL) { - wolfSSL_X509_free(ssl->session.peer); - ssl->session.peer = NULL; + if (wolfSSL_GetSessionFromCache(ssl, &ssl->session) == WOLFSSL_SUCCESS) + ret = &ssl->session; + else { + WOLFSSL_MSG("wolfSSL_GetSessionFromCache did not return a session"); } - if (session->peer != NULL && - wolfSSL_X509_up_ref(session->peer) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Can't increase peer cert ref count"); - ret = WOLFSSL_FAILURE; + +#ifdef HAVE_EXT_CACHE + if (ret == NULL && ssl->extSession != NULL) { + WOLFSSL_MSG("Found dynamic session"); + ret = ssl->extSession; } #endif - if (ret == WOLFSSL_SUCCESS) { - /* copy session structure */ - XMEMCPY(&ssl->session, session, sizeof(WOLFSSL_SESSION)); - /* Set sane defaults */ - ssl->session.type = WOLFSSL_SESSION_TYPE_SSL; - ssl->session.cacheRow = INVALID_SESSION_ROW; - ssl->session.masterSecret = ssl->session._masterSecret; -#ifndef NO_CLIENT_CACHE - ssl->session.serverID = ssl->session._serverID; -#endif -#ifdef OPENSSL_EXTRA - ssl->session.sessionCtx = ssl->session._sessionCtx; -#endif -#ifdef HAVE_SESSION_TICKET - ssl->session.ticket = NULL; /* Set later */ -#endif - ssl->session.refCount = 0; -#ifndef SINGLE_THREADED - XMEMSET(&ssl->session.refMutex, 0, sizeof(wolfSSL_Mutex)); -#endif + if (ret != NULL && masterSecret != NULL) + XMEMCPY(masterSecret, ret->masterSecret, SECRET_LEN); + + return ret; +} + +int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + int ret = WOLFSSL_SUCCESS; + + if (ssl == NULL || session == NULL || SslSessionCacheOff(ssl, session)) { + return WOLFSSL_FAILURE; } -#ifdef HAVE_SESSION_TICKET - if (ret == WOLFSSL_SUCCESS) { - if (ssl->session.ticketLen > SESSION_TICKET_LEN) { - if (ticBuff == NULL || ticLenAlloc < session->ticketLen) { - /* allocate new one */ - byte* tmp = (byte*)XREALLOC(ticBuff, session->ticketLen, - ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - if (tmp == NULL) { - WOLFSSL_MSG("Failed to allocate memory for ticket"); - ret = WOLFSSL_FAILURE; - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ticBuff = NULL; - } - else { - ticBuff = tmp; - ticLenAlloc = session->ticketLen; - } - } - if (ticBuff != NULL) { - XMEMCPY(ticBuff, session->ticket, session->ticketLen); - ssl->session.ticket = ticBuff; - ssl->session.ticketLenAlloc = ticLenAlloc; - } - } - else { - /* Default ticket to non dynamic */ - /* free old ticket buffer */ - if (ticBuff != NULL) - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; - if (session->ticketLenAlloc > 0) { - /* Shouldn't happen as session should have placed this in - * the static buffer */ - XMEMCPY(ssl->session.ticket, session->ticket, - session->ticketLen); - } - } - ticBuff = NULL; + if (session->type == WOLFSSL_SESSION_TYPE_CACHE) { + WOLFSSL_MSG("Can't call wolfSSL_SetSession on a session in the cache. " + "This may cause issues when the cache entry is modified " + "before it gets used."); + return WOLFSSL_FAILURE; } -#endif - /* Unlock once we are done with session */ - if (row != INVALID_SESSION_ROW) - SESSION_ROW_UNLOCK(&SessionCache[row]); + if (ssl->options.side != WOLFSSL_NEITHER_END && + (byte)ssl->options.side != session->side) { + WOLFSSL_MSG("Setting session for wrong role"); + return WOLFSSL_FAILURE; + } - if (ret != WOLFSSL_SUCCESS) { - #ifdef HAVE_SESSION_TICKET - /* cleanup */ - if (ticBuff != NULL) { - /* free old ticket buffer */ - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - } - if (ssl->session.ticket != ssl->session._staticTicket) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - } - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; - #endif - return ret; + if (wolfSSL_DupSession(session, &ssl->session, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Session duplicate failed"); + return WOLFSSL_FAILURE; } - /* don't use the provided session pointer from here to end of func, only use - * ssl->session. - */ #ifdef OPENSSL_EXTRA /* check for application context id */ @@ -15742,15 +15716,21 @@ int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) if (LowResTimer() < (ssl->session.bornOn + ssl->session.timeout)) { ssl->options.resuming = 1; + ssl->options.haveEMS = ssl->session.haveEMS; #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ defined(HAVE_SESSION_TICKET)) ssl->version = ssl->session.version; + if (IsAtLeastTLSv1_3(ssl->version)) + ssl->options.tls1_3 = 1; #endif #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) ssl->options.cipherSuite0 = ssl->session.cipherSuite0; ssl->options.cipherSuite = ssl->session.cipherSuite; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = (unsigned long)ssl->session.peerVerifyRet; #endif ret = WOLFSSL_SUCCESS; } @@ -15774,7 +15754,7 @@ static int get_locked_session_stats(word32* active, word32* total, int AddSession(WOLFSSL* ssl) { - word32 row = 0; + int row = INVALID_SESSION_ROW; word32 idx = 0; int error = 0; const byte* id = NULL; @@ -15790,6 +15770,9 @@ int AddSession(WOLFSSL* ssl) byte sessionAlloc = 0; #endif SessionRow* sessRow = NULL; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* peer = NULL; +#endif WOLFSSL_ENTER("AddSession"); @@ -15826,6 +15809,42 @@ int AddSession(WOLFSSL* ssl) return BAD_FUNC_ARG; } + /* Setup the ssl->session object */ + ssl->session.timeout = ssl->timeout; + ssl->session.side = (byte)ssl->options.side; + if (ssl->arrays != NULL +#ifdef WOLFSSL_TLS13 + && !IsAtLeastTLSv1_3(ssl->version) +#endif + ) { + XMEMCPY(ssl->session.masterSecret, ssl->arrays->masterSecret, SECRET_LEN); + ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; + } + ssl->session.haveEMS = ssl->options.haveEMS; +#ifdef OPENSSL_EXTRA + /* If using compatibility layer then check for and copy over session context + * id. */ + if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) { + XMEMCPY(ssl->session.sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); + ssl->session.sessionCtxSz = ssl->sessionCtxSz; + } +#endif + ssl->session.timeout = ssl->timeout; + ssl->session.bornOn = LowResTimer(); +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + ssl->session.version = ssl->version; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + ssl->session.cipherSuite0 = ssl->options.cipherSuite0; + ssl->session.cipherSuite = ssl->options.cipherSuite; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->session.peerVerifyRet = (byte)ssl->peerVerifyRet; +#endif + /* Setup done */ + #ifdef HAVE_SESSION_TICKET ticLen = ssl->session.ticketLen; /* Alloc Memory here so if Malloc fails can exit outside of lock */ @@ -15859,7 +15878,7 @@ int AddSession(WOLFSSL* ssl) #endif { /* Use the session object in the cache for external cache if required */ - row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; + row = (int)(HashSession(id, ID_LEN, &error) % SESSION_ROWS); if (error != 0) { WOLFSSL_MSG("Hash session failed"); #ifdef HAVE_SESSION_TICKET @@ -15889,102 +15908,28 @@ int AddSession(WOLFSSL* ssl) if (!overwrite) { idx = sessRow->nextIdx++; + if (sessRow->totalCount < SESSIONS_PER_ROW) + sessRow->totalCount++; + if (sessRow->nextIdx >= SESSIONS_PER_ROW) + sessRow->nextIdx = 0; } #ifdef SESSION_INDEX ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; #endif session = &sessRow->Sessions[idx]; session->type = WOLFSSL_SESSION_TYPE_CACHE; + session->cacheRow = row; } - session->cacheRow = session->type == WOLFSSL_SESSION_TYPE_CACHE ? - (int)row : INVALID_SESSION_ROW; #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + /* We don't care about the peer field */ if (session->peer != NULL) - wolfSSL_X509_free(session->peer); + peer = session->peer; session->peer = NULL; #endif - session->side = (byte)ssl->options.side; - session->heap = ssl->heap; - session->masterSecret = session->_masterSecret; -#ifndef NO_CLIENT_CACHE - session->serverID = session->_serverID; -#endif -#ifdef OPENSSL_EXTRA - session->sessionCtx = session->_sessionCtx; -#endif - -#ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version)) { - XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN); - session->sessionIDSz = ID_LEN; - } - else -#endif - if (ssl->arrays != NULL) { - XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); - session->sessionIDSz = ssl->arrays->sessionIDSz; - } - XMEMCPY(session->sessionID, id, ID_LEN); - session->haveEMS = ssl->options.haveEMS; - -#ifdef OPENSSL_EXTRA - /* If using compatibility layer then check for and copy over session context - * id. */ - if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) { - XMEMCPY(session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); - session->sessionCtxSz = ssl->sessionCtxSz; - } -#endif - - session->timeout = ssl->timeout; - session->bornOn = LowResTimer(); - -#ifdef HAVE_SESSION_TICKET - /* Check if another thread modified ticket since alloc */ - if ((word16)ticLen != ssl->session.ticketLen) { - error = VAR_STATE_CHANGE_E; - } - if (error == 0) { - /* Cleanup cache row's old Dynamic buff if exists */ - if (session->ticketLenAlloc > 0) { - XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - session->ticket = NULL; - } - - /* If too large to store in static buffer, use dyn buffer */ - if (ticLen > SESSION_TICKET_LEN) { - session->ticket = ticBuff; - session->ticketLenAlloc = (word16)ticLen; - } - else { - session->ticket = session->_staticTicket; - session->ticketLenAlloc = 0; - } - - session->ticketLen = (word16)ticLen; - XMEMCPY(session->ticket, ssl->session.ticket, ticLen); - } - else { /* cleanup, reset state */ - session->ticket = session->_staticTicket; - session->ticketLenAlloc = 0; - session->ticketLen = 0; - if (ticBuff) { - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ticBuff = NULL; - } - } -#endif #ifdef SESSION_CERTS if (error == 0) { - if (!overwrite) { - /* If we are overwriting and no certs present in ssl->session.chain - * then keep the old chain. */ - session->chain.count = ssl->session.chain.count; - XMEMCPY(session->chain.certs, ssl->session.chain.certs, - sizeof(x509_buffer) * ssl->session.chain.count); - } - else if (ssl->session.chain.count == 0 && + if (ssl->session.chain.count == 0 && session->chain.count > 0) { /* Copy in the certs from the session */ ssl->session.chain.count = session->chain.count; @@ -15993,94 +15938,94 @@ int AddSession(WOLFSSL* ssl) } } #endif /* SESSION_CERTS */ -#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ - defined(HAVE_SESSION_TICKET)) - if (error == 0) { - session->version = ssl->version; - } -#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */ -#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + if (error == 0) { - session->cipherSuite0 = ssl->options.cipherSuite0; - session->cipherSuite = ssl->options.cipherSuite; - } +#ifdef HAVE_SESSION_TICKET + if (ticBuff != NULL) { + session->ticket = ticBuff; + session->ticketLenAlloc = ticLen; + } #endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - if (error == 0) { - session->peerVerifyRet = (byte)ssl->peerVerifyRet; + + /* Copy data into the session object */ + error = wolfSSL_DupSession(&ssl->session, session, + session->type == WOLFSSL_SESSION_TYPE_CACHE) == WOLFSSL_FAILURE; + + /* ssl->session.sessionID may contain the bogus ID or we want the ID from + * the arrays objects */ + XMEMCPY(session->sessionID, id, ID_LEN); + session->sessionIDSz = ID_LEN; + } + +#ifdef HAVE_SESSION_TICKET + if (error != 0 && ticBuff != NULL) { + session->ticket = session->_staticTicket; + session->ticketLenAlloc = 0; + session->ticketLen = 0; } #endif -#if defined(WOLFSSL_TLS13) - if (error == 0) { - session->namedGroup = ssl->session.namedGroup; + +#ifdef HAVE_EXT_CACHE + if (error == 0 && ssl->ctx->new_sess_cb != NULL) { + if (sessionAlloc) + wolfSSL_SESSION_up_ref(session); + cbRet = ssl->ctx->new_sess_cb(ssl, session); + if (sessionAlloc && cbRet == 0) + wolfSSL_FreeSession(session); } #endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - if (error == 0) { - session->ticketSeen = ssl->session.ticketSeen; - session->ticketAdd = ssl->session.ticketAdd; - XMEMCPY(&session->ticketNonce, &ssl->session.ticketNonce, - sizeof(TicketNonce)); - #ifdef WOLFSSL_EARLY_DATA - session->maxEarlyDataSz = ssl->session.maxEarlyDataSz; - #endif + + if (sessRow != NULL) { + SESSION_ROW_UNLOCK(sessRow); + session = NULL; /* Can't access after this point */ } -#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */ - if (error == 0 && sessRow != NULL) { - if (sessRow->totalCount < SESSIONS_PER_ROW) - sessRow->totalCount++; - if (sessRow->nextIdx == SESSIONS_PER_ROW) - sessRow->nextIdx = 0; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (peer != NULL) { + wolfSSL_X509_free(peer); + peer = NULL; /* Make sure not use after this point */ } +#endif #ifndef NO_CLIENT_CACHE + /* Make sure to do this outside of the lock. This way we don't */ if (error == 0) { - if (ssl->options.side == WOLFSSL_CLIENT_END && (ssl->session.idLen + if (ssl->options.side == WOLFSSL_CLIENT_END + && row != INVALID_SESSION_ROW + && (ssl->session.idLen #ifdef HAVE_SESSION_TICKET - || ssl->options.useTicket == 1 + || ssl->options.useTicket == 1 #endif - )) { + )) { word32 clientRow, clientIdx; WOLFSSL_MSG("Adding client cache entry"); - session->idLen = ssl->session.idLen; - XMEMCPY(session->serverID, ssl->session.serverID, - ssl->session.idLen); - - if (sessRow != NULL) { - clientRow = HashSession(ssl->session.serverID, - ssl->session.idLen, &error) % SESSION_ROWS; - if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) { - clientIdx = ClientCache[clientRow].nextIdx++; - ClientCache[clientRow].Clients[clientIdx].serverRow = - (word16)row; - ClientCache[clientRow].Clients[clientIdx].serverIdx = - (word16)idx; - if (ClientCache[clientRow].totalCount < SESSIONS_PER_ROW) - ClientCache[clientRow].totalCount++; - if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) - ClientCache[clientRow].nextIdx = 0; - - wc_UnLockMutex(&clisession_mutex); - } - else { - WOLFSSL_MSG("Hash session failed"); - } + clientRow = HashSession(ssl->session.serverID, + ssl->session.idLen, &error) % SESSION_ROWS; + if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) { + clientIdx = ClientCache[clientRow].nextIdx++; + ClientCache[clientRow].Clients[clientIdx].serverRow = + (word16)row; + ClientCache[clientRow].Clients[clientIdx].serverIdx = + (word16)idx; + if (ClientCache[clientRow].totalCount < SESSIONS_PER_ROW) + ClientCache[clientRow].totalCount++; + if (ClientCache[clientRow].nextIdx >= SESSIONS_PER_ROW) + ClientCache[clientRow].nextIdx = 0; + + wc_UnLockMutex(&clisession_mutex); + } + else { + WOLFSSL_MSG("Hash session failed"); } } else { WOLFSSL_MSG("Skipping client cache"); - session->idLen = 0; } } #endif /* !NO_CLIENT_CACHE */ - if (sessRow != NULL) { - SESSION_ROW_UNLOCK(sessRow); - #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) if (error == 0) { word32 active = 0; @@ -16095,16 +16040,10 @@ int AddSession(WOLFSSL* ssl) } } #endif /* WOLFSSL_SESSION_STATS && WOLFSSL_PEAK_SESSIONS */ - } -#ifdef HAVE_EXT_CACHE - if (error == 0 && ssl->ctx->new_sess_cb != NULL) { - if (sessionAlloc) - wolfSSL_SESSION_up_ref(session); - cbRet = ssl->ctx->new_sess_cb(ssl, session); - if (sessionAlloc && cbRet == 0) - wolfSSL_FreeSession(session); - } +#ifdef HAVE_SESSION_TICKET + if (ticBuff != NULL && error != 0) + XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); #endif return error; @@ -16160,7 +16099,6 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); - session = GetSessionPtr(session); if (session) chain = &session->chain; @@ -16176,7 +16114,6 @@ WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session) { WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); - session = GetSessionPtr(session); if (session) { int count; @@ -23730,64 +23667,6 @@ int wolfSSL_session_reused(WOLFSSL* ssl) return resuming; } -WOLFSSL_SESSION* wolfSSL_GetSessionRef(WOLFSSL* ssl) -{ - WOLFSSL_SESSION* session; -#ifdef ENABLE_CLIENT_SESSION_REF - WOLFSSL_SESSION* ref = NULL; - const word32 refSize = (word32)OFFSETOF(WOLFSSL_SESSION, _masterSecret); - int refCount = 1; -#ifndef SINGLE_THREADED - byte mutexLocked = 0; -#endif -#endif - - session = wolfSSL_GetSession(ssl, NULL, 1); - if (session == NULL || session->type != WOLFSSL_SESSION_TYPE_CACHE) { - return NULL; - } - -#ifdef ENABLE_CLIENT_SESSION_REF - /* if wolfSSL_GetSessionRef has already been called then use existing - * pointer */ - ref = (WOLFSSL_SESSION*)ssl->session.refPtr; - if (ref == NULL) { - ref = wolfSSL_NewSession(ssl->heap); - } - else { - /* use existing ref count */ -#ifndef SINGLE_THREADED - if (wc_LockMutex(&ref->refMutex) != 0) { - WOLFSSL_MSG("Failed to lock session mutex"); - } - else - mutexLocked = 1; -#endif - refCount = ref->refCount; - } - if (ref == NULL) { - WOLFSSL_MSG("Error allocating client session reference"); - return NULL; - } - - XMEMCPY(ref, session, refSize); - ref->type = WOLFSSL_SESSION_TYPE_REF; - ref->refCount = refCount; - ref->refPtr = (void*)session; - ref->heap = ssl->heap; - ssl->session.refPtr = ref; - session = ref; - -#ifndef SINGLE_THREADED - if (mutexLocked) - wc_UnLockMutex(&ref->refMutex); -#endif - -#endif /* ENABLE_CLIENT_SESSION_REF */ - - return session; -} - /* return a new malloc'd session with default settings on success */ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) { @@ -23856,6 +23735,7 @@ int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) #ifndef SINGLE_THREADED if (wc_LockMutex(&session->refMutex) != 0) { WOLFSSL_MSG("Failed to lock session mutex"); + return WOLFSSL_FAILURE; } #endif session->refCount++; @@ -23865,6 +23745,157 @@ int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) return WOLFSSL_SUCCESS; } +/** + * Deep copy the contents from input to output. + * @param input The source of the copy. + * @param output The destination of the copy. + * @param avoidSysCalls If true, then system calls will be avoided or an error + * will be returned if it is not possible to proceed + * without a system call. This is useful for fetching + * sessions from cache. When a cache row is locked, we + * don't want to block other threads with long running + * system calls. + * @return WOLFSSL_SUCCESS on success + * WOLFSSL_FAILURE on failure + */ +int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output, + int avoidSysCalls) +{ +#ifdef HAVE_SESSION_TICKET + int ticLenAlloc = 0; + byte *ticBuff = NULL; +#endif + const size_t copyOffset = OFFSETOF(WOLFSSL_SESSION, heap) + sizeof(input->heap); + int ret = WOLFSSL_SUCCESS; + + (void)avoidSysCalls; + + if (input == NULL || output == NULL || input == output) { + WOLFSSL_MSG("input or output are null or same"); + return WOLFSSL_FAILURE; + } + +#ifdef HAVE_SESSION_TICKET + if (output->ticket != output->_staticTicket) { + ticBuff = output->ticket; + ticLenAlloc = output->ticketLenAlloc; + } +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (output->peer != NULL) { + if (avoidSysCalls) { + WOLFSSL_MSG("Can't free cert when avoiding syscalls"); + return WOLFSSL_FAILURE; + } + wolfSSL_X509_free(output->peer); + output->peer = NULL; + } +#endif + + XMEMCPY((byte*)output + copyOffset, (byte*)input + copyOffset, + sizeof(WOLFSSL_SESSION) - copyOffset); + + /* Set sane values for copy */ + if (output->type != WOLFSSL_SESSION_TYPE_CACHE) + output->cacheRow = INVALID_SESSION_ROW; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (input->peer != NULL && input->peer->dynamicMemory) { + if (wolfSSL_X509_up_ref(input->peer) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Can't increase peer cert ref count"); + output->peer = NULL; + } + } + else if (!avoidSysCalls) + output->peer = wolfSSL_X509_dup(input->peer); + else + output->peer = NULL; +#endif + output->masterSecret = output->_masterSecret; +#ifndef NO_CLIENT_CACHE + output->serverID = output->_serverID; +#endif +#ifdef OPENSSL_EXTRA + output->sessionCtx = output->_sessionCtx; +#endif +#ifdef HAVE_SESSION_TICKET + if (input->ticketLen > SESSION_TICKET_LEN) { + /* Need dynamic buffer */ + if (ticBuff == NULL || ticLenAlloc < input->ticketLen) { + /* allocate new one */ + byte* tmp; + if (!avoidSysCalls) { + WOLFSSL_MSG("Failed to allocate memory for ticket when avoiding" + " syscalls"); + output->ticket = ticBuff; + output->ticketLenAlloc = ticLenAlloc; + output->ticketLen = 0; + ret = WOLFSSL_FAILURE; + } + else { + tmp = (byte*)XREALLOC(ticBuff, input->ticketLen, + output->heap, DYNAMIC_TYPE_SESSION_TICK); + if (tmp == NULL) { + WOLFSSL_MSG("Failed to allocate memory for ticket"); + XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + output->ticket = NULL; + output->ticketLen = 0; + output->ticketLenAlloc = 0; + ret = WOLFSSL_FAILURE; + } + else { + ticBuff = tmp; + ticLenAlloc = input->ticketLen; + } + } + } + if (ticBuff != NULL && ret == WOLFSSL_SUCCESS) { + XMEMCPY(ticBuff, input->ticket, input->ticketLen); + output->ticket = ticBuff; + output->ticketLenAlloc = ticLenAlloc; + } + } + else { + /* Default ticket to non dynamic */ + if (avoidSysCalls) { + /* Try to use ticBuf if available. Caller can later move it to + * the static buffer. */ + if (ticBuff != NULL) { + if (ticLenAlloc >= input->ticketLen) { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } + else { + WOLFSSL_MSG("ticket dynamic buffer too small but we are " + "avoiding system calls"); + ret = WOLFSSL_FAILURE; + output->ticket = ticBuff; + output->ticketLenAlloc = ticLenAlloc; + output->ticketLen = 0; + } + } + else { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } + } + else { + if (ticBuff != NULL) + XFREE(ticBuff, input->heap, DYNAMIC_TYPE_SESSION_TICK); + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } + if (input->ticketLenAlloc > 0 && ret == WOLFSSL_SUCCESS) { + /* Shouldn't happen as session should have placed this in + * the static buffer */ + XMEMCPY(output->ticket, input->ticket, + input->ticketLen); + } + } + ticBuff = NULL; +#endif /* HAVE_SESSION_TICKET */ + return ret; +} WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) { @@ -23873,7 +23904,6 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_SESSION_dup"); - session = GetSessionPtr(session); if (session == NULL) return NULL; @@ -23885,37 +23915,10 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) #endif copy = wolfSSL_NewSession(session->heap); - if (copy != NULL) { -#ifndef SINGLE_THREADED - /* Store value to restore after memcpy */ - wolfSSL_Mutex refMutex = copy->refMutex; -#endif - XMEMCPY(copy, session, sizeof(WOLFSSL_SESSION)); - copy->type = WOLFSSL_SESSION_TYPE_HEAP; - copy->cacheRow = INVALID_SESSION_ROW; -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - copy->peer = wolfSSL_X509_dup(session->peer); -#endif - copy->masterSecret = copy->_masterSecret; -#ifndef NO_CLIENT_CACHE - copy->serverID = copy->_serverID; -#endif -#ifdef OPENSSL_EXTRA - copy->sessionCtx = copy->_sessionCtx; -#endif -#ifdef HAVE_SESSION_TICKET - if (copy->ticketLenAlloc > 0) { - copy->ticket = (byte*)XMALLOC(copy->ticketLen, copy->heap, - DYNAMIC_TYPE_SESSION_TICK); - XMEMCPY(copy->ticket, session->ticket, session->ticketLen); - } else { - copy->ticket = copy->_staticTicket; - } -#endif - copy->refCount = 1; -#ifndef SINGLE_THREADED - copy->refMutex = refMutex; -#endif + if (copy != NULL && + wolfSSL_DupSession(session, copy, 0) != WOLFSSL_SUCCESS) { + wolfSSL_FreeSession(copy); + copy = NULL; } return copy; #else @@ -23930,30 +23933,6 @@ void wolfSSL_FreeSession(WOLFSSL_SESSION* session) if (session == NULL) return; -#ifdef ENABLE_CLIENT_SESSION_REF - if (session->type == WOLFSSL_SESSION_TYPE_REF) { -#ifndef SINGLE_THREADED - if (wc_LockMutex(&session->refMutex) != 0) { - WOLFSSL_MSG("Failed to lock session mutex"); - } -#endif - session->refCount--; - if (session->refCount > 0) { -#ifndef SINGLE_THREADED - wc_UnLockMutex(&session->refMutex); - return; /* don't free yet */ -#endif - } -#ifndef SINGLE_THREADED - wc_UnLockMutex(&session->refMutex); - wc_FreeMutex(&session->refMutex); -#endif - XFREE(session, ref->heap, DYNAMIC_TYPE_SESSION); - /* Don't touch the internal session if this is a reference */ - return; - } -#endif - /* refCount will always be 1 or more if created externally. * Internal cache sessions don't initialize a refMutex. */ if (session->refCount > 0) { @@ -24123,7 +24102,6 @@ int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, WOLFSSL_ENTER("wolfSSL_SESSION_set_cipher"); /* sanity check */ - session = GetSessionPtr(session); if (session == NULL || cipher == NULL) { WOLFSSL_MSG("bad argument"); return WOLFSSL_FAILURE; @@ -24270,9 +24248,8 @@ const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher) return wolfSSL_get_version(cipher->ssl); } -const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session) +const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session) { - session = GetSessionPtr(session); if (session == NULL) { return NULL; } @@ -32423,7 +32400,6 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) WOLFSSL_ENTER("wolfSSL_i2d_SSL_SESSION"); - sess = GetSessionPtr(sess); if (sess == NULL) { return BAD_FUNC_ARG; } @@ -32590,10 +32566,6 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, (void)i; (void)ret; - if (sess != NULL) { - s = GetSessionPtr(*sess); - } - #ifdef HAVE_EXT_CACHE if (p == NULL || *p == NULL) return NULL; @@ -32602,9 +32574,6 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, s = wolfSSL_SESSION_new(); if (s == NULL) return NULL; -#ifdef HAVE_SESSION_TICKET - s->ticketLenAlloc = 0; -#endif } idx = 0; @@ -32806,7 +32775,6 @@ int wolfSSL_SESSION_has_ticket(const WOLFSSL_SESSION* sess) { WOLFSSL_ENTER("wolfSSL_SESSION_has_ticket"); #ifdef HAVE_SESSION_TICKET - sess = GetSessionPtr(sess); if (sess) { if ((sess->ticketLen > 0) && (sess->ticket != NULL)) { return WOLFSSL_SUCCESS; @@ -32822,7 +32790,6 @@ unsigned long wolfSSL_SESSION_get_ticket_lifetime_hint( const WOLFSSL_SESSION* sess) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ticket_lifetime_hint"); - sess = GetSessionPtr(sess); if (sess) { return sess->timeout; } @@ -32833,7 +32800,6 @@ long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) { long timeout = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); - sess = GetSessionPtr(sess); if (sess) timeout = sess->timeout; return timeout; @@ -32844,7 +32810,6 @@ long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) { long bornOn = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); - sess = GetSessionPtr(sess); if (sess) bornOn = sess->bornOn; return bornOn; @@ -32854,7 +32819,6 @@ long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) { word32 tmptime; - ses = GetSessionPtr(ses); if (ses == NULL || t < 0) { return BAD_FUNC_ARG; } @@ -42765,6 +42729,7 @@ int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa) #ifndef SINGLE_THREADED if (wc_LockMutex(&rsa->refMutex) != 0) { WOLFSSL_MSG("Failed to lock x509 mutex"); + return WOLFSSL_FAILURE; } #endif rsa->refCount++; @@ -42785,6 +42750,7 @@ int wolfSSL_X509_up_ref(WOLFSSL_X509* x509) #ifndef SINGLE_THREADED if (wc_LockMutex(&x509->refMutex) != 0) { WOLFSSL_MSG("Failed to lock x509 mutex"); + return WOLFSSL_FAILURE; } #endif x509->refCount++; @@ -48604,11 +48570,6 @@ int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) #ifdef HAVE_EX_DATA if (session != NULL) ret = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data); - if (ret == WOLFSSL_SUCCESS) { - WOLFSSL_SESSION* ref = GetSessionPtr(session); - if (ref != NULL) - ret = wolfSSL_CRYPTO_set_ex_data(&ref->ex_data, idx, data); - } #else (void)session; (void)idx; @@ -48637,7 +48598,6 @@ void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); #ifdef HAVE_EX_DATA - session = GetSessionPtr(session); if (session != NULL) { return wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx); } @@ -49648,10 +49608,10 @@ WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) -const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) +const byte* wolfSSL_SESSION_get_id(const WOLFSSL_SESSION* sess, + unsigned int* idLen) { WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); - sess = GetSessionPtr(sess); if (sess == NULL || idLen == NULL) { WOLFSSL_MSG("Bad func args. Please provide idLen"); return NULL; @@ -49758,13 +49718,12 @@ static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio, /* prints out the session information in human readable form * return WOLFSSL_SUCCESS on success */ -int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *x) +int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *session) { const unsigned char* pt; unsigned char buf[SECRET_LEN]; unsigned int sz = 0, i; int ret; - WOLFSSL_SESSION* session = GetSessionPtr(x); if (session == NULL) { return WOLFSSL_FAILURE; @@ -57637,7 +57596,6 @@ int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx) */ int wolfSSL_SESSION_is_resumable(const WOLFSSL_SESSION *s) { - s = GetSessionPtr(s); if (s == NULL) return 0; @@ -62452,6 +62410,7 @@ int wolfSSL_X509_STORE_up_ref(WOLFSSL_X509_STORE* store) #ifndef SINGLE_THREADED if (wc_LockMutex(&store->refMutex) != 0) { WOLFSSL_MSG("Failed to lock store mutex"); + return WOLFSSL_FAILURE; } #endif store->refCount++; diff --git a/tests/api.c b/tests/api.c index 17a561ad59..535766b954 100644 --- a/tests/api.c +++ b/tests/api.c @@ -39252,7 +39252,10 @@ static void test_wolfSSL_SESSION(void) AssertPtrNE((sess = wolfSSL_get1_session(ssl)), NULL); /* ref count 1 */ AssertPtrNE((sess_copy = wolfSSL_get1_session(ssl)), NULL); /* ref count 2 */ - AssertPtrEq(sess, sess_copy); /* they should be the same pointer */ +#ifdef HAVE_EXT_CACHE + AssertPtrEq(sess, sess_copy); /* they should be the same pointer but without + * HAVE_EXT_CACHE we get new objects each time */ +#endif wolfSSL_SESSION_free(sess_copy); sess_copy = NULL; wolfSSL_SESSION_free(sess); sess = NULL; /* free session ref */ @@ -39273,6 +39276,9 @@ static void test_wolfSSL_SESSION(void) #endif #endif /* OPENSSL_EXTRA */ + /* Retain copy of the session for later testing */ + AssertNotNull(sess = wolfSSL_get1_session(ssl)); + wolfSSL_shutdown(ssl); wolfSSL_free(ssl); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 80e1d302d5..4cfcf96ef2 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1567,6 +1567,10 @@ enum Misc { #define SESSION_TICKET_LEN 256 #endif +#ifndef PREALLOC_SESSION_TICKET_LEN + #define PREALLOC_SESSION_TICKET_LEN 512 +#endif + #ifndef SESSION_TICKET_HINT_DEFAULT #define SESSION_TICKET_HINT_DEFAULT 300 #endif @@ -3303,22 +3307,31 @@ typedef enum WOLFSSL_SESSION_TYPE { WOLFSSL_SESSION_TYPE_SSL, /* in ssl->session */ WOLFSSL_SESSION_TYPE_CACHE, /* pointer to internal cache */ WOLFSSL_SESSION_TYPE_HEAP /* allocated from heap SESSION_new */ -#ifdef ENABLE_CLIENT_SESSION_REF - ,WOLFSSL_SESSION_TYPE_REF /* smaller allocation with reference to internal cache */ -#endif } WOLFSSL_SESSION_TYPE; /* wolfSSL session type */ struct WOLFSSL_SESSION { + /* WARNING Do not add fields here. They will be ignored in + * wolfSSL_DupSession. */ WOLFSSL_SESSION_TYPE type; + int cacheRow; /* row in session cache */ + int refCount; /* reference count */ +#ifndef SINGLE_THREADED + wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif + void* heap; + /* WARNING The above fields (up to and including the heap) are not copied + * in wolfSSL_DupSession. Place new fields after the heap + * member */ + byte side; /* Either WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ - int cacheRow; /* row in session cache */ word32 bornOn; /* create time in seconds */ word32 timeout; /* timeout in seconds */ - byte sessionID[ID_LEN]; /* id for protocol */ + byte sessionID[ID_LEN]; /* id for protocol or bogus + * ID for TLS 1.3 */ byte sessionIDSz; byte* masterSecret; /* stored secret */ @@ -3364,11 +3377,6 @@ struct WOLFSSL_SESSION { word16 ticketLen; word16 ticketLenAlloc; /* is dynamic */ #endif - int refCount; /* reference count */ -#ifndef SINGLE_THREADED - wolfSSL_Mutex refMutex; /* ref count mutex */ -#endif - void* heap; #ifdef SESSION_CERTS WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ @@ -3380,11 +3388,6 @@ struct WOLFSSL_SESSION { WOLFSSL_CRYPTO_EX_DATA ex_data; #endif -#ifdef ENABLE_CLIENT_SESSION_REF - /* pointer to WOLFSSL_SESSION in internal cache (for WOLFSSL_SESSION_TYPE_REF) */ - void* refPtr; -#endif - /* Below buffers are not allocated for the WOLFSSL_SESSION_TYPE_REF, instead * the above pointers reference the session cache for backwards * compatibility. For all other session types the above pointers reference @@ -3406,9 +3409,13 @@ struct WOLFSSL_SESSION { WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_NewSession(void* heap); WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_GetSession( WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts); +WOLFSSL_LOCAL int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output); WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_GetSessionRef(WOLFSSL* ssl); WOLFSSL_LOCAL int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session); WOLFSSL_LOCAL void wolfSSL_FreeSession(WOLFSSL_SESSION* session); +WOLFSSL_LOCAL int wolfSSL_DupSession(const WOLFSSL_SESSION* input, + WOLFSSL_SESSION* output, int avoidSysCalls); + typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int, int); diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 47329c03d6..856c7f65a0 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -1269,15 +1269,6 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE; #define SSL3_RANDOM_SIZE 32 /* same as RAN_LEN in internal.h */ -#define SSL2_VERSION 0x0002 -#define SSL3_VERSION 0x0300 -#define TLS1_VERSION 0x0301 -#define TLS1_1_VERSION 0x0302 -#define TLS1_2_VERSION 0x0303 -#define TLS1_3_VERSION 0x0304 -#define DTLS1_VERSION 0xFEFF -#define DTLS1_2_VERSION 0xFEFD - /* Used as message callback types */ #define SSL3_RT_CHANGE_CIPHER_SPEC 20 #define SSL3_RT_ALERT 21 diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 552f8c7acc..47a0297636 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1501,7 +1501,7 @@ WOLFSSL_API int wolfSSL_CIPHER_get_digest_nid(const WOLFSSL_CIPHER* cipher); WOLFSSL_API int wolfSSL_CIPHER_get_kx_nid(const WOLFSSL_CIPHER* cipher); WOLFSSL_API int wolfSSL_CIPHER_is_aead(const WOLFSSL_CIPHER* cipher); WOLFSSL_API const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value); -WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session); +WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session); WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL* ssl); WOLFSSL_API void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); @@ -4436,12 +4436,13 @@ WOLFSSL_API int wolfSSL_ASN1_BIT_STRING_set_bit( WOLFSSL_ASN1_BIT_STRING* str, int pos, int val); #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +WOLFSSL_API int wolfSSL_version(WOLFSSL* ssl); + #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) \ || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) WOLFSSL_API int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session); -WOLFSSL_API int wolfSSL_version(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_get_state(const WOLFSSL* ssl); @@ -4471,8 +4472,8 @@ WOLFSSL_API int wolfSSL_SESSION_set_ex_data_with_cleanup( WOLFSSL_API int wolfSSL_SESSION_get_ex_new_index(long idx,void* data,void* cb1,void* cb2, CRYPTO_free_func* cb3); -WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, - unsigned int* idLen); +WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id( + const WOLFSSL_SESSION* sess, unsigned int* idLen); WOLFSSL_API int wolfSSL_SESSION_print(WOLFSSL_BIO* bp, const WOLFSSL_SESSION* session); @@ -4901,6 +4902,17 @@ WOLFSSL_API int wolfSSL_CRYPTO_get_ex_new_index(int class_index, long argl, void WOLFSSL_CRYPTO_EX_dup* dup_func, WOLFSSL_CRYPTO_EX_free* free_func); #endif /* HAVE_EX_DATA || WOLFSSL_WPAS_SMALL */ + +/* */ +#define SSL2_VERSION 0x0002 +#define SSL3_VERSION 0x0300 +#define TLS1_VERSION 0x0301 +#define TLS1_1_VERSION 0x0302 +#define TLS1_2_VERSION 0x0303 +#define TLS1_3_VERSION 0x0304 +#define DTLS1_VERSION 0xFEFF +#define DTLS1_2_VERSION 0xFEFD + #ifdef __cplusplus } /* extern "C" */ #endif From 91b08fb691c138da89104d5f8dd3223da16d4584 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 7 Feb 2022 16:54:42 +0100 Subject: [PATCH 3/9] Allocate `ssl->session` separately on the heap - Refactor session cache access into `AddSessionToCache` and `wolfSSL_GetSessionFromCache` --- doc/dox_comments/header_files/ssl.h | 2 +- src/internal.c | 164 +++--- src/sniffer.c | 34 +- src/ssl.c | 771 +++++++++++++--------------- src/tls.c | 26 +- src/tls13.c | 152 +++--- tests/api.c | 5 +- wolfssl/internal.h | 17 +- wolfssl/ssl.h | 5 +- 9 files changed, 536 insertions(+), 640 deletions(-) diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index 59bc6ae7b6..6f0ec59940 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -11166,7 +11166,7 @@ WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx); if(wolfSSL_get_SessionTicket(ssl, buf, bufSz) <= 0){ // Nothing was written to the buffer } else { - // the buffer holds the content from ssl->session.ticket + // the buffer holds the content from ssl->session->ticket } \endcode diff --git a/src/internal.c b/src/internal.c index 04cdd3589e..8ba08423ee 100644 --- a/src/internal.c +++ b/src/internal.c @@ -6629,18 +6629,14 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) } #endif /*OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ - ssl->session.heap = ssl->heap; - ssl->session.type = WOLFSSL_SESSION_TYPE_SSL; - ssl->session.masterSecret = ssl->session._masterSecret; -#ifndef NO_CLIENT_CACHE - ssl->session.serverID = ssl->session._serverID; -#endif -#ifdef OPENSSL_EXTRA - ssl->session.sessionCtx = ssl->session._sessionCtx; -#endif + ssl->session = wolfSSL_NewSession(ssl->heap); + if (ssl->session == NULL) { + WOLFSSL_MSG("SSL Session Memory error"); + return MEMORY_E; + } + #ifdef HAVE_SESSION_TICKET ssl->options.noTicketTls12 = ctx->noTicketTls12; - ssl->session.ticket = ssl->session._staticTicket; #endif #ifdef WOLFSSL_MULTICAST @@ -6687,10 +6683,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) void FreeArrays(WOLFSSL* ssl, int keep) { if (ssl->arrays) { - if (keep) { + if (keep && !IsAtLeastTLSv1_3(ssl->version)) { /* keeps session id for user retrieval */ - XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); - ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; + XMEMCPY(ssl->session->sessionID, ssl->arrays->sessionID, ID_LEN); + ssl->session->sessionIDSz = ssl->arrays->sessionIDSz; } if (ssl->arrays->preMasterSecret) { XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET); @@ -7224,17 +7220,8 @@ void SSL_ResourceFree(WOLFSSL* ssl) FreeX509(&ssl->peerCert); #endif -#ifdef HAVE_SESSION_TICKET - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; - ssl->session.ticketLen = 0; - } -#endif -#ifdef HAVE_EXT_CACHE - wolfSSL_SESSION_free(ssl->extSession); -#endif + if (ssl->session != NULL) + wolfSSL_FreeSession(ssl->session); #ifdef HAVE_WRITE_DUP if (ssl->dupWrite) { FreeWriteDup(ssl); @@ -7501,15 +7488,6 @@ void FreeHandshakeResources(WOLFSSL* ssl) } #endif /* HAVE_PK_CALLBACKS */ -#ifdef HAVE_SESSION_TICKET - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; - ssl->session.ticketLen = 0; - } -#endif - #if defined(HAVE_TLS_EXTENSIONS) && !defined(HAVE_SNI) && \ !defined(HAVE_ALPN) && !defined(WOLFSSL_POST_HANDSHAKE_AUTH) /* Some extensions need to be kept for post-handshake querying. */ @@ -11369,7 +11347,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, } #endif #ifdef SESSION_CERTS - store->sesChain = &ssl->session.chain; + store->sesChain = &ssl->session->chain; #endif } #ifndef NO_WOLFSSL_CM_VERIFY @@ -11439,9 +11417,9 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, #ifdef SESSION_CERTS if ((ssl != NULL) && (store->discardSessionCerts)) { WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session.chain.count = 0; + ssl->session->chain.count = 0; #ifdef WOLFSSL_ALT_CERT_CHAINS - ssl->session.altChain.count = 0; + ssl->session->altChain.count = 0; #endif } #endif /* SESSION_CERTS */ @@ -12083,7 +12061,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, args->certs[args->totalCerts].buffer = input + args->idx; #ifdef SESSION_CERTS - AddSessionCertToChain(&ssl->session.chain, + AddSessionCertToChain(&ssl->session->chain, input + args->idx, certSz); #endif /* SESSION_CERTS */ @@ -12378,7 +12356,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS) /* if using alternate chain, store the cert used */ if (ssl->options.usingAltCertChain) { - AddSessionCertToChain(&ssl->session.altChain, + AddSessionCertToChain(&ssl->session->altChain, cert->buffer, cert->length); } #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ @@ -12474,7 +12452,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* if using alternate chain, store the cert used */ if (ssl->options.usingAltCertChain) { buffer* cert = &args->certs[args->certIdx]; - AddSessionCertToChain(&ssl->session.altChain, + AddSessionCertToChain(&ssl->session->altChain, cert->buffer, cert->length); } #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ @@ -13271,9 +13249,9 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef SESSION_CERTS /* Reset the session cert chain count in case the session resume failed. */ - ssl->session.chain.count = 0; + ssl->session->chain.count = 0; #ifdef WOLFSSL_ALT_CERT_CHAINS - ssl->session.altChain.count = 0; + ssl->session->altChain.count = 0; #endif #endif /* SESSION_CERTS */ @@ -22761,7 +22739,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) return BAD_FUNC_ARG; } - idSz = ssl->options.resuming ? ssl->session.sessionIDSz : 0; + idSz = ssl->options.resuming ? ssl->session->sessionIDSz : 0; #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version)) @@ -22777,11 +22755,11 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } #ifdef HAVE_SESSION_TICKET - if (ssl->options.resuming && ssl->session.ticketLen > 0) { + if (ssl->options.resuming && ssl->session->ticketLen > 0) { SessionTicket* ticket; - ticket = TLSX_SessionTicket_Create(0, ssl->session.ticket, - ssl->session.ticketLen, ssl->heap); + ticket = TLSX_SessionTicket_Create(0, ssl->session->ticket, + ssl->session->ticketLen, ssl->heap); if (ticket == NULL) return MEMORY_E; ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap); @@ -22870,9 +22848,9 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) /* then session id */ output[idx++] = (byte)idSz; if (idSz) { - XMEMCPY(output + idx, ssl->session.sessionID, - ssl->session.sessionIDSz); - idx += ssl->session.sessionIDSz; + XMEMCPY(output + idx, ssl->session->sessionID, + ssl->session->sessionIDSz); + idx += ssl->session->sessionIDSz; } /* then DTLS cookie */ @@ -23069,12 +23047,12 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) #ifdef HAVE_SESSION_TICKET /* server may send blank ticket which may not be expected to indicate * existing one ok but will also be sending a new one */ - ret = ret || (ssl->session.ticketLen > 0); + ret = ret || (ssl->session->ticketLen > 0); #endif ret = ret || (ssl->options.haveSessionId && XMEMCMP(ssl->arrays->sessionID, - ssl->session.sessionID, ID_LEN) == 0); + ssl->session->sessionID, ID_LEN) == 0); return ret; } @@ -23412,7 +23390,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) #ifdef HAVE_SECRET_CALLBACK if (ssl->sessionSecretCb != NULL) { int secretSz = SECRET_LEN; - ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, + ret = ssl->sessionSecretCb(ssl, ssl->session->masterSecret, &secretSz, ssl->sessionSecretCtx); if (ret != 0 || secretSz != SECRET_LEN) return SESSION_SECRET_CB_E; @@ -23470,7 +23448,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) if (SetCipherSpecs(ssl) == 0) { XMEMCPY(ssl->arrays->masterSecret, - ssl->session.masterSecret, SECRET_LEN); + ssl->session->masterSecret, SECRET_LEN); #ifdef NO_OLD_TLS ret = DeriveTlsKeys(ssl); #else @@ -26742,27 +26720,27 @@ int SendCertificateVerify(WOLFSSL* ssl) int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length) { /* Free old dynamic ticket if we already had one */ - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; + if (ssl->session->ticketLenAlloc > 0) { + XFREE(ssl->session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session->ticket = ssl->session->_staticTicket; + ssl->session->ticketLenAlloc = 0; } - if (length > sizeof(ssl->session._staticTicket)) { + if (length > sizeof(ssl->session->_staticTicket)) { byte* sessionTicket = (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); if (sessionTicket == NULL) return MEMORY_E; - ssl->session.ticket = sessionTicket; - ssl->session.ticketLenAlloc = (word16)length; + ssl->session->ticket = sessionTicket; + ssl->session->ticketLenAlloc = (word16)length; } - ssl->session.ticketLen = (word16)length; + ssl->session->ticketLen = (word16)length; if (length > 0) { - XMEMCPY(ssl->session.ticket, ticket, length); + XMEMCPY(ssl->session->ticket, ticket, length); if (ssl->session_ticket_cb != NULL) { ssl->session_ticket_cb(ssl, - ssl->session.ticket, ssl->session.ticketLen, + ssl->session->ticket, ssl->session->ticketLen, ssl->session_ticket_ctx); } /* Create a fake sessionID based on the ticket, this will @@ -26770,13 +26748,13 @@ int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length) ssl->options.haveSessionId = 1; #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) { - XMEMCPY(ssl->session.sessionID, - ssl->session.ticket + length - ID_LEN, ID_LEN); + XMEMCPY(ssl->session->sessionID, + ssl->session->ticket + length - ID_LEN, ID_LEN); } else #endif XMEMCPY(ssl->arrays->sessionID, - ssl->session.ticket + length - ID_LEN, ID_LEN); + ssl->session->ticket + length - ID_LEN, ID_LEN); } return 0; @@ -29271,7 +29249,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, (void)bogusID; #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket == 1) { - session = &ssl->session; + session = ssl->session; } else if (bogusID == 1 && ssl->options.rejectTicket == 0) { WOLFSSL_MSG("Bogus session ID without session ticket"); return BUFFER_ERROR; @@ -30582,7 +30560,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int CreateTicket(WOLFSSL* ssl) { InternalTicket it; - ExternalTicket* et = (ExternalTicket*)ssl->session.ticket; + ExternalTicket* et = (ExternalTicket*)ssl->session->ticket; int encLen; int ret; byte zeros[WOLFSSL_TICKET_MAC_SZ]; /* biggest cmp size */ @@ -30614,12 +30592,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, sizeof(it.ageAdd)); if (ret != 0) return BAD_TICKET_ENCRYPT; - ssl->session.ticketAdd = it.ageAdd; - it.namedGroup = ssl->session.namedGroup; + ssl->session->ticketAdd = it.ageAdd; + it.namedGroup = ssl->session->namedGroup; it.timestamp = TimeNowInMilliseconds(); /* Resumption master secret. */ - XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN); - XMEMCPY(&it.ticketNonce, &ssl->session.ticketNonce, + XMEMCPY(it.msecret, ssl->session->masterSecret, SECRET_LEN); + XMEMCPY(&it.ticketNonce, &ssl->session->ticketNonce, sizeof(TicketNonce)); #endif } @@ -30627,12 +30605,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_TICKET_HAVE_ID { const byte* id = NULL; - if (ssl->options.haveTicketSessionID) - id = ssl->ticketSessionID; + if (ssl->session->haveAltSessionID) + id = ssl->session->altSessionID; else if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) id = ssl->arrays->sessionID; else - id = ssl->session.sessionID; + id = ssl->session->sessionID; XMEMCPY(it.id, id, ID_LEN); } #endif @@ -30702,7 +30680,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* set size */ c16toa((word16)encLen, et->enc_len); - ssl->session.ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ); + ssl->session->ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ); if (encLen < WOLFSSL_TICKET_ENC_SZ) { /* move mac up since whole enc buffer not used */ XMEMMOVE(et->enc_ticket +encLen, et->mac,WOLFSSL_TICKET_MAC_SZ); @@ -30795,8 +30773,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_TICKET_HAVE_ID { - ssl->options.haveTicketSessionID = 1; - XMEMCPY(ssl->ticketSessionID, it.id, ID_LEN); + ssl->session->haveAltSessionID = 1; + XMEMCPY(ssl->session->altSessionID, it.id, ID_LEN); if (wolfSSL_GetSession(ssl, NULL, 1) != NULL) { WOLFSSL_MSG("Found session matching the session id" " found in the ticket"); @@ -30812,28 +30790,28 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(ssl->arrays->masterSecret, it.msecret, SECRET_LEN); /* Copy the haveExtendedMasterSecret property from the ticket to * the saved session, so the property may be checked later. */ - ssl->session.haveEMS = it.haveEMS; - ato32((const byte*)&it.timestamp, &ssl->session.bornOn); + ssl->session->haveEMS = it.haveEMS; + ato32((const byte*)&it.timestamp, &ssl->session->bornOn); #ifndef NO_RESUME_SUITE_CHECK - ssl->session.cipherSuite0 = it.suite[0]; - ssl->session.cipherSuite = it.suite[1]; + ssl->session->cipherSuite0 = it.suite[0]; + ssl->session->cipherSuite = it.suite[1]; #endif } else { #ifdef WOLFSSL_TLS13 /* Restore information to renegotiate. */ - ssl->session.ticketSeen = it.timestamp; - ssl->session.ticketAdd = it.ageAdd; - ssl->session.cipherSuite0 = it.suite[0]; - ssl->session.cipherSuite = it.suite[1]; + ssl->session->ticketSeen = it.timestamp; + ssl->session->ticketAdd = it.ageAdd; + ssl->session->cipherSuite0 = it.suite[0]; + ssl->session->cipherSuite = it.suite[1]; #ifdef WOLFSSL_EARLY_DATA - ssl->session.maxEarlyDataSz = it.maxEarlyDataSz; + ssl->session->maxEarlyDataSz = it.maxEarlyDataSz; #endif /* Resumption master secret. */ - XMEMCPY(ssl->session.masterSecret, it.msecret, SECRET_LEN); - XMEMCPY(&ssl->session.ticketNonce, &it.ticketNonce, + XMEMCPY(ssl->session->masterSecret, it.msecret, SECRET_LEN); + XMEMCPY(&ssl->session->ticketNonce, &it.ticketNonce, sizeof(TicketNonce)); - ssl->session.namedGroup = it.namedGroup; + ssl->session->namedGroup = it.namedGroup; #endif } } @@ -30864,7 +30842,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; } - length += ssl->session.ticketLen; + length += ssl->session->ticketLen; sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; if (!ssl->options.dtls) { @@ -30896,12 +30874,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, idx += SESSION_HINT_SZ; /* length */ - c16toa(ssl->session.ticketLen, output + idx); + c16toa(ssl->session->ticketLen, output + idx); idx += LENGTH_SZ; /* ticket */ - XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); - idx += ssl->session.ticketLen; + XMEMCPY(output + idx, ssl->session->ticket, ssl->session->ticketLen); + idx += ssl->session->ticketLen; if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { byte* input; diff --git a/src/sniffer.c b/src/sniffer.c index 2e35e1487e..8eae315c85 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -3044,9 +3044,9 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes, *sslBytes -= OPAQUE8_LEN; #ifdef HAVE_SESSION_TICKET /* store nonce in server for DeriveResumptionPSK */ - session->sslServer->session.ticketNonce.len = len; + session->sslServer->session->ticketNonce.len = len; if (len > 0) - XMEMCPY(&session->sslServer->session.ticketNonce.data, input, len); + XMEMCPY(&session->sslServer->session->ticketNonce.data, input, len); #endif input += len; *sslBytes -= len; @@ -3123,7 +3123,7 @@ static int DoResume(SnifferSession* session, char* error) #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(session->sslServer->version)) { resume = wolfSSL_GetSession(session->sslServer, - session->sslServer->session.masterSecret, 0); + session->sslServer->session->masterSecret, 0); if (resume == NULL) { /* TLS v1.3 with hello_retry uses session_id even for new session, so ignore error here */ @@ -3147,8 +3147,8 @@ static int DoResume(SnifferSession* session, char* error) /* make sure client has master secret too */ #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(session->sslServer->version)) { - XMEMCPY(session->sslClient->session.masterSecret, - session->sslServer->session.masterSecret, SECRET_LEN); + XMEMCPY(session->sslClient->session->masterSecret, + session->sslServer->session->masterSecret, SECRET_LEN); } else #endif @@ -3179,8 +3179,8 @@ static int DoResume(SnifferSession* session, char* error) session->sslServer->arrays->psk_keySz = session->sslServer->specs.hash_size; session->sslClient->arrays->psk_keySz = session->sslClient->specs.hash_size; ret = DeriveResumptionPSK(session->sslServer, - session->sslServer->session.ticketNonce.data, - session->sslServer->session.ticketNonce.len, + session->sslServer->session->ticketNonce.data, + session->sslServer->session->ticketNonce.len, session->sslServer->arrays->psk_key); /* Copy resumption PSK to client */ XMEMCPY(session->sslClient->arrays->psk_key, @@ -3266,7 +3266,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, } if (b) { #ifdef WOLFSSL_TLS13 - XMEMCPY(session->sslServer->session.sessionID, input, ID_LEN); + XMEMCPY(session->sslServer->session->sessionID, input, ID_LEN); #endif XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN); session->sslServer->options.haveSessionId = 1; @@ -3370,10 +3370,10 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, session->sslClient->options.resuming = 1; #ifdef WOLFSSL_TLS13 /* default nonce to len = 1, data = 0 */ - session->sslServer->session.ticketNonce.len = 1; - session->sslServer->session.ticketNonce.data[0] = 0; - session->sslClient->session.ticketNonce.len = 1; - session->sslClient->session.ticketNonce.data[0] = 0; + session->sslServer->session->ticketNonce.len = 1; + session->sslServer->session->ticketNonce.data[0] = 0; + session->sslClient->session->ticketNonce.len = 1; + session->sslClient->session->ticketNonce.data[0] = 0; #endif break; #endif @@ -3595,7 +3595,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes, } Trace(CLIENT_RESUME_TRY_STR); #ifdef WOLFSSL_TLS13 - XMEMCPY(session->sslClient->session.sessionID, input, ID_LEN); + XMEMCPY(session->sslClient->session->sessionID, input, ID_LEN); #endif if (session->sslClient->arrays) XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN); @@ -4014,14 +4014,14 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, #ifdef HAVE_SESSION_TICKET /* derive resumption secret for next session - on finished (from client) */ ret += DeriveResumptionSecret(session->sslClient, - session->sslClient->session.masterSecret); + session->sslClient->session->masterSecret); /* copy resumption secret to server */ - XMEMCPY(session->sslServer->session.masterSecret, - session->sslClient->session.masterSecret, SECRET_LEN); + XMEMCPY(session->sslServer->session->masterSecret, + session->sslClient->session->masterSecret, SECRET_LEN); #ifdef SHOW_SECRETS PrintSecret("resumption secret", - session->sslClient->session.masterSecret, SECRET_LEN); + session->sslClient->session->masterSecret, SECRET_LEN); #endif #endif } diff --git a/src/ssl.c b/src/ssl.c index 21346570f1..a14e27af0b 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3321,9 +3321,9 @@ WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0) return BAD_FUNC_ARG; - if (ssl->session.ticketLen <= *bufSz) { - XMEMCPY(buf, ssl->session.ticket, ssl->session.ticketLen); - *bufSz = ssl->session.ticketLen; + if (ssl->session->ticketLen <= *bufSz) { + XMEMCPY(buf, ssl->session->ticket, ssl->session->ticketLen); + *bufSz = ssl->session->ticketLen; } else *bufSz = 0; @@ -3340,32 +3340,32 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, if (bufSz > 0) { /* Ticket will fit into static ticket */ if (bufSz <= SESSION_TICKET_LEN) { - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, + if (ssl->session->ticketLenAlloc > 0) { + XFREE(ssl->session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticketLenAlloc = 0; - ssl->session.ticket = ssl->session._staticTicket; + ssl->session->ticketLenAlloc = 0; + ssl->session->ticket = ssl->session->_staticTicket; } } else { /* Ticket requires dynamic ticket storage */ - if (ssl->session.ticketLen < bufSz) { /* is dyn buffer big enough */ - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, + if (ssl->session->ticketLen < bufSz) { /* is dyn buffer big enough */ + if (ssl->session->ticketLenAlloc > 0) { + XFREE(ssl->session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); } - ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->session.heap, + ssl->session->ticket = (byte*)XMALLOC(bufSz, ssl->session->heap, DYNAMIC_TYPE_SESSION_TICK); - if(ssl->session.ticket == NULL) { - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; + if(ssl->session->ticket == NULL) { + ssl->session->ticket = ssl->session->_staticTicket; + ssl->session->ticketLenAlloc = 0; return MEMORY_ERROR; } - ssl->session.ticketLenAlloc = (word16)bufSz; + ssl->session->ticketLenAlloc = (word16)bufSz; } } - XMEMCPY(ssl->session.ticket, buf, bufSz); + XMEMCPY(ssl->session->ticket, buf, bufSz); } - ssl->session.ticketLen = (word16)bufSz; + ssl->session->ticketLen = (word16)bufSz; return WOLFSSL_SUCCESS; } @@ -12483,7 +12483,7 @@ WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_session"); if (ssl) - return &ssl->session; + return ssl->session; return NULL; } @@ -12494,37 +12494,8 @@ WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) WOLFSSL_SESSION* sess = NULL; WOLFSSL_ENTER("SSL_get1_session"); if (ssl != NULL) { -#ifdef HAVE_EXT_CACHE - sess = &ssl->session; - if (ssl->extSession == NULL) { - ssl->extSession = sess = wolfSSL_SESSION_new(); - if (wolfSSL_DupSession(&ssl->session, sess, 0) - != WOLFSSL_SUCCESS) { - sess = NULL; - } -#ifdef WOLFSSL_TICKET_HAVE_ID - /* Set the real session ID for the independent session object */ - if (sess != NULL && ssl->options.haveTicketSessionID) { - XMEMCPY(sess->sessionID, ssl->ticketSessionID, ID_LEN); - sess->sessionIDSz = ID_LEN; - } -#endif - } - else - sess = ssl->extSession; -#else - sess = wolfSSL_SESSION_new(); + sess = ssl->session; if (sess != NULL) { - if (wolfSSL_DupSession(&ssl->session, sess, 0) - != WOLFSSL_SUCCESS) { - wolfSSL_SESSION_free(sess); - sess = NULL; - } - } -#endif - if (sess != NULL) { - /* wolfSSL_get_session returns either static cache or ref. If ref then - * increase reference counter */ /* increase reference count if allocated session */ if (sess->type == WOLFSSL_SESSION_TYPE_HEAP) { if (wolfSSL_SESSION_up_ref(sess) != WOLFSSL_SUCCESS) @@ -12595,8 +12566,8 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) if (session == NULL) { WOLFSSL_MSG("Valid ServerID not cached already"); - ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len); - XMEMCPY(ssl->session.serverID, id, ssl->session.idLen); + ssl->session->idLen = (word16)min(SERVER_ID_LEN, (word32)len); + XMEMCPY(ssl->session->serverID, id, ssl->session->idLen); } #ifdef HAVE_EXT_CACHE else { @@ -12990,7 +12961,7 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx) ssl->sessionSecretCb = cb; ssl->sessionSecretCtx = ctx; /* If using a pre-set key, assume session resumption. */ - ssl->session.sessionIDSz = 0; + ssl->session->sessionIDSz = 0; ssl->options.resuming = 1; return WOLFSSL_SUCCESS; @@ -15447,9 +15418,8 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) WOLFSSL_X509* peer = NULL; #endif -#ifdef WOLFSSL_TICKET_HAVE_ID byte bogusID[ID_LEN]; -#endif + byte bogusIDSz = 0; WOLFSSL_ENTER("wolfSSL_GetSessionFromCache"); @@ -15458,7 +15428,7 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) return WOLFSSL_FAILURE; } - if (SslSessionCacheOff(ssl, &ssl->session)) + if (SslSessionCacheOff(ssl, ssl->session)) return WOLFSSL_FAILURE; if (ssl->options.haveSessionId == 0) @@ -15471,17 +15441,17 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) id = ssl->arrays->sessionID; - else - id = ssl->session.sessionID; - -#ifdef WOLFSSL_TICKET_HAVE_ID - if (ssl->options.haveTicketSessionID) { - id = ssl->ticketSessionID; + else if (ssl->session->haveAltSessionID) { + id = ssl->session->altSessionID; /* We want to restore the bogus ID for TLS compatibility */ - if (output->type == WOLFSSL_SESSION_TYPE_SSL) - XMEMCPY(bogusID, ssl->session.sessionID, ID_LEN); + if (output == ssl->session) { + XMEMCPY(bogusID, ssl->session->sessionID, ID_LEN); + bogusIDSz = ssl->session->sessionIDSz; + } } -#endif + else + id = ssl->session->sessionID; + #ifdef HAVE_EXT_CACHE if (ssl->ctx->get_sess_cb != NULL) { @@ -15495,12 +15465,12 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) /* If copy not set then free immediately */ if (!copy) wolfSSL_SESSION_free(sess); -#ifdef WOLFSSL_TICKET_HAVE_ID /* We want to restore the bogus ID for TLS compatibility */ - if (ssl->options.haveTicketSessionID && - output->type == WOLFSSL_SESSION_TYPE_SSL) - XMEMCPY(ssl->session.sessionID, bogusID, ID_LEN); -#endif + if (ssl->session->haveAltSessionID && + output == ssl->session) { + XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN); + ssl->session->sessionIDSz = bogusIDSz; + } return error; } WOLFSSL_MSG("Session not found in external cache"); @@ -15591,23 +15561,28 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1; } + if (sess != NULL) { #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - /* We don't want the peer member. We will free it at the end. */ - if (sess->peer != NULL) { - peer = sess->peer; - sess->peer = NULL; - } + /* We don't want the peer member. We will free it at the end. */ + if (sess->peer != NULL) { + peer = sess->peer; + sess->peer = NULL; + } #endif - error = wolfSSL_DupSession(sess, output, 1); + error = wolfSSL_DupSession(sess, output, 1); + } + else { + error = WOLFSSL_FAILURE; + } SESSION_ROW_UNLOCK(sessRow); -#ifdef WOLFSSL_TICKET_HAVE_ID /* We want to restore the bogus ID for TLS compatibility */ - if (ssl->options.haveTicketSessionID && - output->type == WOLFSSL_SESSION_TYPE_SSL) - XMEMCPY(ssl->session.sessionID, bogusID, ID_LEN); -#endif + if (ssl->session->haveAltSessionID && + output == ssl->session) { + XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN); + ssl->session->sessionIDSz = bogusIDSz; + } #ifdef HAVE_SESSION_TICKET if (tmpBufSet) { @@ -15658,19 +15633,13 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, (void)restoreSessionCerts; /* Kept for compatibility */ - if (wolfSSL_GetSessionFromCache(ssl, &ssl->session) == WOLFSSL_SUCCESS) - ret = &ssl->session; + if (wolfSSL_GetSessionFromCache(ssl, ssl->session) == WOLFSSL_SUCCESS) { + ret = ssl->session; + } else { WOLFSSL_MSG("wolfSSL_GetSessionFromCache did not return a session"); } -#ifdef HAVE_EXT_CACHE - if (ret == NULL && ssl->extSession != NULL) { - WOLFSSL_MSG("Found dynamic session"); - ret = ssl->extSession; - } -#endif - if (ret != NULL && masterSecret != NULL) XMEMCPY(masterSecret, ret->masterSecret, SECRET_LEN); @@ -15698,15 +15667,21 @@ int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) return WOLFSSL_FAILURE; } - if (wolfSSL_DupSession(session, &ssl->session, 0) != WOLFSSL_SUCCESS) { + if (wolfSSL_DupSession(session, ssl->session, 0) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Session duplicate failed"); return WOLFSSL_FAILURE; } + /* Let's copy over the altSessionID for local cache purposes */ + if (session->haveAltSessionID) { + ssl->session->haveAltSessionID = 1; + XMEMCPY(ssl->session->altSessionID, session->altSessionID, ID_LEN); + } + #ifdef OPENSSL_EXTRA /* check for application context id */ if (ssl->sessionCtxSz > 0) { - if (XMEMCMP(ssl->sessionCtx, ssl->session.sessionCtx, ssl->sessionCtxSz)) { + if (XMEMCMP(ssl->sessionCtx, ssl->session->sessionCtx, ssl->sessionCtxSz)) { /* context id did not match! */ WOLFSSL_MSG("Session context did not match"); return WOLFSSL_FAILURE; @@ -15714,23 +15689,23 @@ int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) } #endif /* OPENSSL_EXTRA */ - if (LowResTimer() < (ssl->session.bornOn + ssl->session.timeout)) { + if (LowResTimer() < (ssl->session->bornOn + ssl->session->timeout)) { ssl->options.resuming = 1; - ssl->options.haveEMS = ssl->session.haveEMS; + ssl->options.haveEMS = ssl->session->haveEMS; #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ defined(HAVE_SESSION_TICKET)) - ssl->version = ssl->session.version; + ssl->version = ssl->session->version; if (IsAtLeastTLSv1_3(ssl->version)) ssl->options.tls1_3 = 1; #endif #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - ssl->options.cipherSuite0 = ssl->session.cipherSuite0; - ssl->options.cipherSuite = ssl->session.cipherSuite; + ssl->options.cipherSuite0 = ssl->session->cipherSuite0; + ssl->options.cipherSuite = ssl->session->cipherSuite; #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - ssl->peerVerifyRet = (unsigned long)ssl->session.peerVerifyRet; + ssl->peerVerifyRet = (unsigned long)ssl->session->peerVerifyRet; #endif ret = WOLFSSL_SUCCESS; } @@ -15752,31 +15727,203 @@ static int get_locked_session_stats(word32* active, word32* total, word32* peak); #endif -int AddSession(WOLFSSL* ssl) +#ifndef NO_CLIENT_CACHE +int AddSessionToClientCache(int side, int row, int idx, byte* serverID, + word16 idLen, word16 useTicket) +{ + int error = 0; + (void)useTicket; + if (side == WOLFSSL_CLIENT_END + && row != INVALID_SESSION_ROW + && (idLen +#ifdef HAVE_SESSION_TICKET + || useTicket == 1 +#endif + )) { + word32 clientRow, clientIdx; + + WOLFSSL_MSG("Adding client cache entry"); + + clientRow = HashSession(serverID, + idLen, &error) % SESSION_ROWS; + if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) { + clientIdx = ClientCache[clientRow].nextIdx++; + ClientCache[clientRow].Clients[clientIdx].serverRow = + (word16)row; + ClientCache[clientRow].Clients[clientIdx].serverIdx = + (word16)idx; + if (ClientCache[clientRow].totalCount < SESSIONS_PER_ROW) + ClientCache[clientRow].totalCount++; + ClientCache[clientRow].nextIdx %= SESSIONS_PER_ROW; + + wc_UnLockMutex(&clisession_mutex); + } + else { + WOLFSSL_MSG("Hash session failed"); + } + } + else { + WOLFSSL_MSG("Skipping client cache"); + } + return error; +} +#endif + +int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, + int* sessionIndex, int side, word16 useTicket) { - int row = INVALID_SESSION_ROW; + WOLFSSL_SESSION* cacheSession = NULL; + SessionRow* sessRow = NULL; word32 idx = 0; - int error = 0; - const byte* id = NULL; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* peer = NULL; +#endif #ifdef HAVE_SESSION_TICKET byte* ticBuff = NULL; int ticLen = 0; #endif - WOLFSSL_SESSION* session; + int ret = 0; + int row; int i; int overwrite = 0; -#ifdef HAVE_EXT_CACHE - int cbRet = 0; - byte sessionAlloc = 0; + + (void)sessionIndex; + (void)useTicket; + + if (addSession == NULL) + return BAD_FUNC_ARG; + + /* Find a position for the new session in cache and use that */ +#ifdef HAVE_SESSION_TICKET + ticLen = addSession->ticketLen; + /* Alloc Memory here to avoid syscalls during lock */ + if (ticLen > SESSION_TICKET_LEN) { + ticBuff = (byte*)XMALLOC(ticLen, addSession->heap, + DYNAMIC_TYPE_SESSION_TICK); + if (ticBuff == NULL) { + return MEMORY_E; + } + } #endif - SessionRow* sessRow = NULL; + /* Use the session object in the cache for external cache if required */ + row = (int)(HashSession(id, ID_LEN, &ret) % SESSION_ROWS); + if (ret != 0) { + WOLFSSL_MSG("Hash session failed"); + #ifdef HAVE_SESSION_TICKET + XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + #endif + return ret; + } + + sessRow = &SessionCache[row]; + if (SESSION_ROW_LOCK(sessRow) != 0) { + #ifdef HAVE_SESSION_TICKET + XFREE(ticBuff, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); + #endif + return BAD_MUTEX_E; + } + + for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) { + if (XMEMCMP(id, + sessRow->Sessions[i].sessionID, ID_LEN) == 0 && + sessRow->Sessions[i].side == side) { + WOLFSSL_MSG("Session already exists. Overwriting."); + overwrite = 1; + idx = i; + break; + } + } + + if (!overwrite) + idx = sessRow->nextIdx; +#ifdef SESSION_INDEX + if (sessionIndex != NULL) + *sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; +#endif + cacheSession = &sessRow->Sessions[idx]; + cacheSession->type = WOLFSSL_SESSION_TYPE_CACHE; + cacheSession->cacheRow = row; + #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - WOLFSSL_X509* peer = NULL; + /* Save the peer field to free after unlocking the row */ + if (cacheSession->peer != NULL) + peer = cacheSession->peer; + cacheSession->peer = NULL; +#endif +#ifdef HAVE_SESSION_TICKET + if (ticBuff != NULL) { + cacheSession->ticket = ticBuff; + cacheSession->ticketLenAlloc = ticLen; + } +#endif +#ifdef SESSION_CERTS + if (overwrite && + addSession->chain.count == 0 && + cacheSession->chain.count > 0) { + /* Copy in the certs from the session */ + addSession->chain.count = cacheSession->chain.count; + XMEMCPY(addSession->chain.certs, cacheSession->chain.certs, + sizeof(x509_buffer) * cacheSession->chain.count); + } +#endif /* SESSION_CERTS */ + /* Copy data into the cache object */ + ret = wolfSSL_DupSession(addSession, cacheSession, 1) == WOLFSSL_FAILURE; + + if (ret == 0) { + /* Increment the totalCount and the nextIdx */ + if (sessRow->totalCount < SESSIONS_PER_ROW) + sessRow->totalCount++; + sessRow->nextIdx = (sessRow->nextIdx + 1) % SESSIONS_PER_ROW; + if (id != addSession->sessionID) { + /* ssl->session->sessionID may contain the bogus ID or we want the + * ID from the arrays object */ + XMEMCPY(cacheSession->sessionID, id, ID_LEN); + cacheSession->sessionIDSz = ID_LEN; + } + } +#ifdef HAVE_SESSION_TICKET + else if (ticBuff != NULL) { + /* Error occured. Need to clean up the ticket buffer. */ + cacheSession->ticket = cacheSession->_staticTicket; + cacheSession->ticketLenAlloc = 0; + cacheSession->ticketLen = 0; + } +#endif + + SESSION_ROW_UNLOCK(sessRow); + cacheSession = NULL; /* Can't access after unlocked */ + +#ifndef NO_CLIENT_CACHE + if (ret == 0) + ret = AddSessionToClientCache(side, row, idx, addSession->serverID, + addSession->idLen, useTicket); +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (peer != NULL) { + wolfSSL_X509_free(peer); + peer = NULL; /* Make sure not use after this point */ + } +#endif + + return ret; +} + +#ifndef NO_CLIENT_CACHE +#endif + +int AddSession(WOLFSSL* ssl) +{ + int error = 0; + const byte* id = NULL; + WOLFSSL_SESSION* session = ssl->session; +#ifdef HAVE_EXT_CACHE + int cbRet = 0; #endif WOLFSSL_ENTER("AddSession"); - if (SslSessionCacheOff(ssl, &ssl->session)) { + if (SslSessionCacheOff(ssl, session)) { WOLFSSL_MSG("Cache off"); return 0; } @@ -15794,15 +15941,18 @@ int AddSession(WOLFSSL* ssl) } #endif - if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) - id = ssl->arrays->sessionID; - else - id = ssl->session.sessionID; + if (session->haveAltSessionID) + id = session->altSessionID; + else { + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) { + /* Make sure the session ID is available when the user calls any + * get_session API */ + XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); + session->sessionIDSz = ssl->arrays->sessionIDSz; + } + id = session->sessionID; + } -#ifdef WOLFSSL_TICKET_HAVE_ID - if (ssl->options.haveTicketSessionID) - id = ssl->ticketSessionID; -#endif if (id == NULL) { WOLFSSL_MSG("No Session ID"); @@ -15810,222 +15960,63 @@ int AddSession(WOLFSSL* ssl) } /* Setup the ssl->session object */ - ssl->session.timeout = ssl->timeout; - ssl->session.side = (byte)ssl->options.side; - if (ssl->arrays != NULL -#ifdef WOLFSSL_TLS13 - && !IsAtLeastTLSv1_3(ssl->version) -#endif - ) { - XMEMCPY(ssl->session.masterSecret, ssl->arrays->masterSecret, SECRET_LEN); - ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; - } - ssl->session.haveEMS = ssl->options.haveEMS; + session->timeout = ssl->timeout; + session->side = (byte)ssl->options.side; + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) + XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); + session->haveEMS = ssl->options.haveEMS; #ifdef OPENSSL_EXTRA /* If using compatibility layer then check for and copy over session context * id. */ if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) { - XMEMCPY(ssl->session.sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); - ssl->session.sessionCtxSz = ssl->sessionCtxSz; + XMEMCPY(ssl->session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); + session->sessionCtxSz = ssl->sessionCtxSz; } #endif - ssl->session.timeout = ssl->timeout; - ssl->session.bornOn = LowResTimer(); + session->timeout = ssl->timeout; + session->bornOn = LowResTimer(); #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ defined(HAVE_SESSION_TICKET)) - ssl->session.version = ssl->version; + session->version = ssl->version; #endif #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - ssl->session.cipherSuite0 = ssl->options.cipherSuite0; - ssl->session.cipherSuite = ssl->options.cipherSuite; + session->cipherSuite0 = ssl->options.cipherSuite0; + session->cipherSuite = ssl->options.cipherSuite; #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - ssl->session.peerVerifyRet = (byte)ssl->peerVerifyRet; + session->peerVerifyRet = (byte)ssl->peerVerifyRet; #endif /* Setup done */ -#ifdef HAVE_SESSION_TICKET - ticLen = ssl->session.ticketLen; - /* Alloc Memory here so if Malloc fails can exit outside of lock */ - if (ticLen > SESSION_TICKET_LEN) { - ticBuff = (byte*)XMALLOC(ticLen, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - if (ticBuff == NULL) { - return MEMORY_E; - } - } -#endif - #ifdef HAVE_EXT_CACHE - if (ssl->options.internalCacheOff) { - /* Create a new session object to be stored or use the existing - * one. */ - if (ssl->extSession != NULL) { - session = ssl->extSession; - } - else { - ssl->extSession = session = wolfSSL_SESSION_new(); - if (session == NULL) { - #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - #endif - return MEMORY_E; - } - } - sessionAlloc = 1; - } - else + if (!ssl->options.internalCacheOff) #endif { - /* Use the session object in the cache for external cache if required */ - row = (int)(HashSession(id, ID_LEN, &error) % SESSION_ROWS); - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - #endif - return error; - } - - sessRow = &SessionCache[row]; - if (SESSION_ROW_LOCK(sessRow) != 0) { - #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - #endif - return BAD_MUTEX_E; - } - - for (i=0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) { - if (XMEMCMP(id, - sessRow->Sessions[i].sessionID, ID_LEN) == 0 && - sessRow->Sessions[i].side == ssl->options.side) { - WOLFSSL_MSG("Session already exists. Overwriting."); - overwrite = 1; - idx = i; - break; - } - } - - if (!overwrite) { - idx = sessRow->nextIdx++; - if (sessRow->totalCount < SESSIONS_PER_ROW) - sessRow->totalCount++; - if (sessRow->nextIdx >= SESSIONS_PER_ROW) - sessRow->nextIdx = 0; - } + error = AddSessionToCache(session, id, #ifdef SESSION_INDEX - ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; -#endif - session = &sessRow->Sessions[idx]; - session->type = WOLFSSL_SESSION_TYPE_CACHE; - session->cacheRow = row; - } -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - /* We don't care about the peer field */ - if (session->peer != NULL) - peer = session->peer; - session->peer = NULL; + &ssl->sessionIndex, +#else + NULL, #endif - -#ifdef SESSION_CERTS - if (error == 0) { - if (ssl->session.chain.count == 0 && - session->chain.count > 0) { - /* Copy in the certs from the session */ - ssl->session.chain.count = session->chain.count; - XMEMCPY(ssl->session.chain.certs, session->chain.certs, - sizeof(x509_buffer) * session->chain.count); - } - } -#endif /* SESSION_CERTS */ - - if (error == 0) { + ssl->options.side, #ifdef HAVE_SESSION_TICKET - if (ticBuff != NULL) { - session->ticket = ticBuff; - session->ticketLenAlloc = ticLen; - } + ssl->options.useTicket +#else + 0 #endif - - /* Copy data into the session object */ - error = wolfSSL_DupSession(&ssl->session, session, - session->type == WOLFSSL_SESSION_TYPE_CACHE) == WOLFSSL_FAILURE; - - /* ssl->session.sessionID may contain the bogus ID or we want the ID from - * the arrays objects */ - XMEMCPY(session->sessionID, id, ID_LEN); - session->sessionIDSz = ID_LEN; + ); } -#ifdef HAVE_SESSION_TICKET - if (error != 0 && ticBuff != NULL) { - session->ticket = session->_staticTicket; - session->ticketLenAlloc = 0; - session->ticketLen = 0; - } -#endif - #ifdef HAVE_EXT_CACHE if (error == 0 && ssl->ctx->new_sess_cb != NULL) { - if (sessionAlloc) - wolfSSL_SESSION_up_ref(session); + wolfSSL_SESSION_up_ref(session); cbRet = ssl->ctx->new_sess_cb(ssl, session); - if (sessionAlloc && cbRet == 0) + if (cbRet == 0) wolfSSL_FreeSession(session); } #endif - if (sessRow != NULL) { - SESSION_ROW_UNLOCK(sessRow); - session = NULL; /* Can't access after this point */ - } - -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (peer != NULL) { - wolfSSL_X509_free(peer); - peer = NULL; /* Make sure not use after this point */ - } -#endif - -#ifndef NO_CLIENT_CACHE - /* Make sure to do this outside of the lock. This way we don't */ - if (error == 0) { - if (ssl->options.side == WOLFSSL_CLIENT_END - && row != INVALID_SESSION_ROW - && (ssl->session.idLen -#ifdef HAVE_SESSION_TICKET - || ssl->options.useTicket == 1 -#endif - )) { - word32 clientRow, clientIdx; - - WOLFSSL_MSG("Adding client cache entry"); - - clientRow = HashSession(ssl->session.serverID, - ssl->session.idLen, &error) % SESSION_ROWS; - if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) { - clientIdx = ClientCache[clientRow].nextIdx++; - ClientCache[clientRow].Clients[clientIdx].serverRow = - (word16)row; - ClientCache[clientRow].Clients[clientIdx].serverIdx = - (word16)idx; - if (ClientCache[clientRow].totalCount < SESSIONS_PER_ROW) - ClientCache[clientRow].totalCount++; - if (ClientCache[clientRow].nextIdx >= SESSIONS_PER_ROW) - ClientCache[clientRow].nextIdx = 0; - - wc_UnLockMutex(&clisession_mutex); - } - else { - WOLFSSL_MSG("Hash session failed"); - } - } - else { - WOLFSSL_MSG("Skipping client cache"); - } - } -#endif /* !NO_CLIENT_CACHE */ - #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) if (error == 0) { word32 active = 0; @@ -16041,11 +16032,6 @@ int AddSession(WOLFSSL* ssl) } #endif /* WOLFSSL_SESSION_STATS && WOLFSSL_PEAK_SESSIONS */ -#ifdef HAVE_SESSION_TICKET - if (ticBuff != NULL && error != 0) - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); -#endif - return error; } @@ -20357,7 +20343,7 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, #endif } #ifdef SESSION_CERTS - ssl->session.chain.count = 0; + ssl->session->chain.count = 0; #endif #ifdef KEEP_PEER_CERT FreeX509(&ssl->peerCert); @@ -20739,9 +20725,9 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, if (ssl->peerCert.issuer.sz) ret = wolfSSL_X509_dup(&ssl->peerCert); #ifdef SESSION_CERTS - else if (ssl->session.chain.count > 0) { - if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer, - ssl->session.chain.certs[0].length) == 0) { + else if (ssl->session->chain.count > 0) { + if (DecodeToX509(&ssl->peerCert, ssl->session->chain.certs[0].buffer, + ssl->session->chain.certs[0].length) == 0) { ret = wolfSSL_X509_dup(&ssl->peerCert); } } @@ -20828,11 +20814,11 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) int ret; WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain"); - if ((ssl == NULL) || (ssl->session.chain.count == 0)) + if ((ssl == NULL) || (ssl->session->chain.count == 0)) return NULL; sk = wolfSSL_sk_X509_new(); - i = ssl->session.chain.count-1; + i = ssl->session->chain.count-1; for (; i >= 0; i--) { x509 = wolfSSL_X509_new(); if (x509 == NULL) { @@ -20840,10 +20826,10 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) wolfSSL_sk_X509_pop_free(sk, NULL); return NULL; } - ret = DecodeToX509(x509, ssl->session.chain.certs[i].buffer, - ssl->session.chain.certs[i].length); + ret = DecodeToX509(x509, ssl->session->chain.certs[i].buffer, + ssl->session->chain.certs[i].length); #if !defined(WOLFSSL_QT) - if (ret == 0 && i == ssl->session.chain.count-1) { + if (ret == 0 && i == ssl->session->chain.count-1) { /* On the last element in the chain try to add the CA chain * first if we have one for this cert */ if (PushCAx509Chain(SSL_CM(ssl), x509, sk) @@ -23676,6 +23662,14 @@ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) DYNAMIC_TYPE_SESSION); if (ret != NULL) { XMEMSET(ret, 0, sizeof(WOLFSSL_SESSION)); + #ifndef SINGLE_THREADED + if (wc_InitMutex(&ret->refMutex) != 0) { + WOLFSSL_MSG("Error setting up session reference mutex"); + XFREE(ret, ret->heap, DYNAMIC_TYPE_SESSION); + return NULL; + } + #endif + ret->refCount = 1; ret->cacheRow = INVALID_SESSION_ROW; /* not in cache */ ret->type = WOLFSSL_SESSION_TYPE_HEAP; ret->heap = heap; @@ -23689,16 +23683,6 @@ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) #ifdef HAVE_SESSION_TICKET ret->ticket = ret->_staticTicket; #endif -#ifdef OPENSSL_EXTRA -#ifndef SINGLE_THREADED - if (wc_InitMutex(&ret->refMutex) != 0) { - WOLFSSL_MSG("Error setting up session reference mutex"); - XFREE(ret, ret->heap, DYNAMIC_TYPE_SESSION); - return NULL; - } -#endif - ret->refCount = 1; -#endif #ifdef HAVE_STUNNEL /* stunnel has this funny mechanism of storing the "is_authenticated" * session info in the session ex data. This is basically their @@ -23809,6 +23793,7 @@ int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output, else if (!avoidSysCalls) output->peer = wolfSSL_X509_dup(input->peer); else + /* output->peer is not that important to copy */ output->peer = NULL; #endif output->masterSecret = output->_masterSecret; @@ -23939,6 +23924,7 @@ void wolfSSL_FreeSession(WOLFSSL_SESSION* session) #ifndef SINGLE_THREADED if (wc_LockMutex(&session->refMutex) != 0) { WOLFSSL_MSG("Failed to lock session mutex"); + return; } #endif if (session->refCount > 1) { @@ -23985,19 +23971,10 @@ void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) wolfSSL_FreeSession(session); } -#ifdef HAVE_EXT_CACHE -/* HAVE_EXT_CACHE is needed for wolfSSL_SESSION_dup to work. Also without this - * define the input session will already always be in the session cache. */ int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) { - word32 row; int error = 0; - SessionRow* sessRow = NULL; - int i; - int overwrite = 0; - word32 idx = 0; - WOLFSSL_SESSION* copy; - WOLFSSL_SESSION* cacheSess; + const byte* id = NULL; WOLFSSL_ENTER("wolfSSL_CTX_add_session"); @@ -24007,86 +23984,21 @@ int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) /* Session cache is global */ (void)ctx; - /* Same session row selection logic as in AddSession */ - - row = HashSession(session->sessionID, ID_LEN, &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - return WOLFSSL_FAILURE; - } - - sessRow = &SessionCache[row]; - if (SESSION_ROW_LOCK(sessRow) != 0) { - WOLFSSL_MSG("Row lock failed"); - return WOLFSSL_FAILURE; - } - - for (i=0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) { - if (XMEMCMP(session->sessionID, - sessRow->Sessions[i].sessionID, ID_LEN) == 0 && - sessRow->Sessions[i].side == session->side) { - WOLFSSL_MSG("Session already exists. Overwriting."); - overwrite = 1; - idx = i; - break; - } - } - - if (!overwrite) { - idx = sessRow->nextIdx++; - } - else if (session == &sessRow->Sessions[idx]) { - /* Sanity check to make sure we don't do unnecessary work */ - WOLFSSL_MSG("Session already present in cache"); - SESSION_ROW_UNLOCK(sessRow); - return WOLFSSL_SUCCESS; - } - - cacheSess = &sessRow->Sessions[idx]; - - copy = wolfSSL_SESSION_dup(session); - if (copy == NULL) { - WOLFSSL_MSG("wolfSSL_SESSION_dup failed"); - SESSION_ROW_UNLOCK(sessRow); - return WOLFSSL_FAILURE; - } - - wolfSSL_FreeSession(cacheSess); - - /* Just copy the fields and free the duplicated object */ - XMEMCPY(cacheSess, copy, sizeof(*copy)); + id = session->sessionID; + if (session->haveAltSessionID) + id = session->altSessionID; - cacheSess->type = WOLFSSL_SESSION_TYPE_CACHE; - cacheSess->cacheRow = row; - cacheSess->masterSecret = cacheSess->_masterSecret; -#ifndef NO_CLIENT_CACHE - cacheSess->serverID = cacheSess->_serverID; -#endif -#ifdef OPENSSL_EXTRA - cacheSess->sessionCtx = cacheSess->_sessionCtx; -#endif + error = AddSessionToCache(session, id, + NULL, session->side, #ifdef HAVE_SESSION_TICKET - if (cacheSess->ticketLenAlloc == 0) - cacheSess->ticket = cacheSess->_staticTicket; -#endif - cacheSess->refCount = 0; -#ifndef SINGLE_THREADED - /* We can free this since we are free'ing the `copy` object directly */ - wc_FreeMutex(&cacheSess->refMutex); + session->ticketLen > 0 +#else + 0 #endif - cacheSess->heap = NULL; - - if (sessRow->totalCount < SESSIONS_PER_ROW) - sessRow->totalCount++; - if (sessRow->nextIdx == SESSIONS_PER_ROW) - sessRow->nextIdx = 0; + ); - XFREE(copy, NULL, DYNAMIC_TYPE_SESSION); - - SESSION_ROW_UNLOCK(sessRow); - return WOLFSSL_SUCCESS; + return error == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } -#endif #if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) @@ -32408,6 +32320,8 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) * haveEMS */ size += OPAQUE8_LEN + OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz + SECRET_LEN + OPAQUE8_LEN; + /* altSessionID */ + size += OPAQUE8_LEN + (sess->haveAltSessionID ? ID_LEN : 0); #ifdef SESSION_CERTS /* Peer chain */ size += OPAQUE8_LEN; @@ -32471,6 +32385,11 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) idx += sess->sessionIDSz; XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN; data[idx++] = (byte)sess->haveEMS; + data[idx++] = sess->haveAltSessionID ? ID_LEN : 0; + if (sess->haveAltSessionID) { + XMEMCPY(data + idx, sess->altSessionID, ID_LEN); + idx += ID_LEN; + } #ifdef SESSION_CERTS data[idx++] = (byte)sess->chain.count; for (i = 0; i < sess->chain.count; i++) { @@ -32589,8 +32508,8 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN; s->sessionIDSz = data[idx++]; - /* sessionID | secret | haveEMS */ - if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) { + /* sessionID | secret | haveEMS | haveAltSessionID */ + if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN + OPAQUE8_LEN) { ret = BUFFER_ERROR; goto end; } @@ -32598,6 +32517,20 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, idx += s->sessionIDSz; XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN; s->haveEMS = data[idx++]; + if (data[idx] != ID_LEN && data[idx] != 0) { + ret = BUFFER_ERROR; + goto end; + } + s->haveAltSessionID = data[idx++] == ID_LEN; + + /* altSessionID */ + if (s->haveAltSessionID) { + if (i - idx < ID_LEN) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->altSessionID, data + idx, ID_LEN); idx += ID_LEN; + } #ifdef SESSION_CERTS /* Certificate chain */ @@ -42794,7 +42727,7 @@ WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain"); if (ssl) - return &ssl->session.altChain; + return &ssl->session->altChain; return 0; } @@ -42806,7 +42739,7 @@ WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_get_peer_chain"); if (ssl) - return &ssl->session.chain; + return &ssl->session->chain; return 0; } @@ -51251,21 +51184,9 @@ int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl) WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) { - WOLFSSL_SESSION *session; - WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); - if (ssl == NULL) { - return NULL; - } - - session = wolfSSL_get_session((WOLFSSL*)ssl); - -#ifdef HAVE_EXT_CACHE - ((WOLFSSL*)ssl)->extSession = session; -#endif - - return session; + return wolfSSL_get_session((WOLFSSL*)ssl); } #endif /* NO_SESSION_CACHE */ diff --git a/src/tls.c b/src/tls.c index d0802ff554..433605a44a 100644 --- a/src/tls.c +++ b/src/tls.c @@ -7698,7 +7698,7 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) int ret; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - ssl->session.namedGroup = (byte)keyShareEntry->group; + ssl->session->namedGroup = (byte)keyShareEntry->group; #endif /* reset the pre master secret size */ if (ssl->arrays->preMasterSz == 0) @@ -7943,7 +7943,7 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* Process the entry to calculate the secret. */ ret = TLSX_KeyShare_Process(ssl, keyShareEntry); if (ret == 0) - ssl->session.namedGroup = ssl->namedGroup = group; + ssl->session->namedGroup = ssl->namedGroup = group; } else if (msgType == hello_retry_request) { if (length != OPAQUE16_LEN) @@ -9122,10 +9122,10 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, const byte* input, #ifdef HAVE_SESSION_TICKET if (list->resumption) { /* Check that the session's details are the same as the server's. */ - if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 || - ssl->options.cipherSuite != ssl->session.cipherSuite || - ssl->session.version.major != ssl->ctx->method->version.major || - ssl->session.version.minor != ssl->ctx->method->version.minor) { + if (ssl->options.cipherSuite0 != ssl->session->cipherSuite0 || + ssl->options.cipherSuite != ssl->session->cipherSuite || + ssl->session->version.major != ssl->ctx->method->version.major || + ssl->session->version.minor != ssl->ctx->method->version.minor) { return PSK_KEY_ERROR; } } @@ -9636,7 +9636,7 @@ static int TLSX_EarlyData_Parse(WOLFSSL* ssl, const byte* input, word16 length, return BUFFER_E; ato32(input, &maxSz); - ssl->session.maxEarlyDataSz = maxSz; + ssl->session->maxEarlyDataSz = maxSz; return 0; } @@ -10195,8 +10195,8 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) int ret = WOLFSSL_SUCCESS; #ifdef WOLFSSL_TLS13 #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (ssl->options.resuming && ssl->session.namedGroup != 0) { - return TLSX_UseSupportedCurve(extensions, ssl->session.namedGroup, + if (ssl->options.resuming && ssl->session->namedGroup != 0) { + return TLSX_UseSupportedCurve(extensions, ssl->session->namedGroup, ssl->heap); } #endif @@ -10600,8 +10600,8 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); if (extension == NULL) { #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (ssl->options.resuming && ssl->session.namedGroup != 0) - namedGroup = ssl->session.namedGroup; + if (ssl->options.resuming && ssl->session->namedGroup != 0) + namedGroup = ssl->session->namedGroup; else #endif if (ssl->numGroups > 0) { @@ -10647,8 +10647,8 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); #endif #if defined(HAVE_SESSION_TICKET) - if (ssl->options.resuming && ssl->session.ticketLen > 0) { - WOLFSSL_SESSION* sess = &ssl->session; + if (ssl->options.resuming && ssl->session->ticketLen > 0) { + WOLFSSL_SESSION* sess = ssl->session; word32 now, milli; if (sess->ticketLen > MAX_PSK_ID_LEN) { diff --git a/src/tls13.c b/src/tls13.c index 20b9dafc94..94bf2debf6 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -807,7 +807,7 @@ int DeriveResumptionSecret(WOLFSSL* ssl, byte* key) masterSecret = ssl->arrays->masterSecret; } else { - masterSecret = ssl->session.masterSecret; + masterSecret = ssl->session->masterSecret; } return DeriveKey(ssl, key, -1, masterSecret, resumeMasterLabel, RESUME_MASTER_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -1014,7 +1014,7 @@ int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret) PRIVATE_KEY_UNLOCK(); ret = wc_Tls13_HKDF_Expand_Label(secret, ssl->specs.hash_size, - ssl->session.masterSecret, ssl->specs.hash_size, + ssl->session->masterSecret, ssl->specs.hash_size, protocol, protocolLen, resumptionLabel, RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg); PRIVATE_KEY_LOCK(); @@ -2772,13 +2772,13 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello) } #ifdef WOLFSSL_EARLY_DATA - if (ssl->session.maxEarlyDataSz == 0) + if (ssl->session->maxEarlyDataSz == 0) ssl->earlyData = no_early_data; #endif /* Resumption PSK is master secret. */ ssl->arrays->psk_keySz = ssl->specs.hash_size; - if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data, - ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) { + if ((ret = DeriveResumptionPSK(ssl, ssl->session->ticketNonce.data, + ssl->session->ticketNonce.len, ssl->arrays->psk_key)) != 0) { return ret; } } @@ -3049,15 +3049,15 @@ int SendTls13ClientHello(WOLFSSL* ssl) #ifdef HAVE_SESSION_TICKET if (ssl->options.resuming && - (ssl->session.version.major != ssl->version.major || - ssl->session.version.minor != ssl->version.minor)) { + (ssl->session->version.major != ssl->version.major || + ssl->session->version.minor != ssl->version.minor)) { #ifndef WOLFSSL_NO_TLS12 - if (ssl->session.version.major == ssl->version.major && - ssl->session.version.minor < ssl->version.minor) { + if (ssl->session->version.major == ssl->version.major && + ssl->session->version.minor < ssl->version.minor) { /* Cannot resume with a different protocol version. */ ssl->options.resuming = 0; - ssl->version.major = ssl->session.version.major; - ssl->version.minor = ssl->session.version.minor; + ssl->version.major = ssl->session->version.major; + ssl->version.minor = ssl->session->version.minor; return SendClientHello(ssl); } else @@ -3097,8 +3097,8 @@ int SendTls13ClientHello(WOLFSSL* ssl) #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) args->length += ID_LEN; #else - if (ssl->session.sessionIDSz > 0) - args->length += ssl->session.sessionIDSz; + if (ssl->session->sessionIDSz > 0) + args->length += ssl->session->sessionIDSz; #endif /* Advance state and proceed */ @@ -3179,11 +3179,11 @@ int SendTls13ClientHello(WOLFSSL* ssl) XMEMCPY(args->output + args->idx, ssl->arrays->clientRandom, RAN_LEN); args->idx += RAN_LEN; - if (ssl->session.sessionIDSz > 0) { + if (ssl->session->sessionIDSz > 0) { /* Session resumption for old versions of protocol. */ args->output[args->idx++] = ID_LEN; - XMEMCPY(args->output + args->idx, ssl->session.sessionID, - ssl->session.sessionIDSz); + XMEMCPY(args->output + args->idx, ssl->session->sessionID, + ssl->session->sessionIDSz); args->idx += ID_LEN; } else { @@ -3514,7 +3514,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_SECRET_CALLBACK if (ssl->sessionSecretCb != NULL) { int secretSz = SECRET_LEN; - ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, + ret = ssl->sessionSecretCb(ssl, ssl->session->masterSecret, &secretSz, ssl->sessionSecretCtx); if (ret != 0 || secretSz != SECRET_LEN) { return SESSION_SECRET_CB_E; @@ -3566,9 +3566,9 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("args->sessIdSz == 0"); return INVALID_PARAMETER; } - if (ssl->session.sessionIDSz != 0) { - if (ssl->session.sessionIDSz != args->sessIdSz || - XMEMCMP(ssl->session.sessionID, args->sessId, + if (ssl->session->sessionIDSz != 0) { + if (ssl->session->sessionIDSz != args->sessIdSz || + XMEMCMP(ssl->session->sessionID, args->sessId, args->sessIdSz) != 0) { WOLFSSL_MSG("session id doesn't match"); return INVALID_PARAMETER; @@ -3580,8 +3580,8 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return INVALID_PARAMETER; } #else - if (args->sessIdSz != ssl->session.sessionIDSz || (args->sessIdSz > 0 && - XMEMCMP(ssl->session.sessionID, args->sessId, args->sessIdSz) != 0)) + if (args->sessIdSz != ssl->session->sessionIDSz || (args->sessIdSz > 0 && + XMEMCMP(ssl->session->sessionID, args->sessId, args->sessIdSz) != 0)) { WOLFSSL_MSG("Server sent different session id"); return INVALID_PARAMETER; @@ -3944,7 +3944,7 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, byte* suite, int* err) ssl->options.verifyPeer = 0; /* PSK age is always zero. */ - if (psk->ticketAge != ssl->session.ticketAdd) { + if (psk->ticketAge != ssl->session->ticketAdd) { ret = PSK_KEY_ERROR; } } @@ -4016,7 +4016,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) /* Difference between now and time ticket constructed * (from decrypted ticket). */ diff = now; - diff -= ssl->session.ticketSeen; + diff -= ssl->session->ticketSeen; if (diff > (sword64)ssl->timeout * 1000 || diff > (sword64)TLS13_MAX_TICKET_AGE * 1000) { current = current->next; @@ -4024,7 +4024,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) } /* Subtract client's ticket age and unobfuscate. */ diff -= current->ticketAge; - diff += ssl->session.ticketAdd; + diff += ssl->session->ticketAdd; /* Check session and ticket age timeout. * Allow +/- 1000 milliseconds on ticket age. */ @@ -4037,14 +4037,14 @@ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) /* Check whether resumption is possible based on suites in SSL and * ciphersuite in ticket. */ - if ((suite[0] != ssl->session.cipherSuite0) || - (suite[1] != ssl->session.cipherSuite)) { + if ((suite[0] != ssl->session->cipherSuite0) || + (suite[1] != ssl->session->cipherSuite)) { current = current->next; continue; } #else - suite[0] = ssl->session.cipherSuite0; - suite[1] = ssl->session.cipherSuite; + suite[0] = ssl->session->cipherSuite0; + suite[1] = ssl->session->cipherSuite; if (!FindSuiteSSL(ssl, suite)) { current = current->next; continue; @@ -4052,19 +4052,19 @@ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) #endif #ifdef WOLFSSL_EARLY_DATA - ssl->options.maxEarlyDataSz = ssl->session.maxEarlyDataSz; + ssl->options.maxEarlyDataSz = ssl->session->maxEarlyDataSz; #endif /* Use the same cipher suite as before and set up for use. */ - ssl->options.cipherSuite0 = ssl->session.cipherSuite0; - ssl->options.cipherSuite = ssl->session.cipherSuite; + ssl->options.cipherSuite0 = ssl->session->cipherSuite0; + ssl->options.cipherSuite = ssl->session->cipherSuite; ret = SetCipherSpecs(ssl); if (ret != 0) return ret; /* Resumption PSK is resumption master secret. */ ssl->arrays->psk_keySz = ssl->specs.hash_size; - if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data, - ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) { + if ((ret = DeriveResumptionPSK(ssl, ssl->session->ticketNonce.data, + ssl->session->ticketNonce.len, ssl->arrays->psk_key)) != 0) { return ret; } @@ -4273,7 +4273,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe && ext != NULL) { /* Only use named group used in last session. */ - ssl->namedGroup = ssl->session.namedGroup; + ssl->namedGroup = ssl->session->namedGroup; *usingPSK = 2; /* generate new ephemeral key */ } @@ -4404,7 +4404,7 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) return ret; /* Reconstruct the HelloRetryMessage for handshake hash. */ - length = HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz + + length = HRR_BODY_SZ - ID_LEN + ssl->session->sessionIDSz + HRR_COOKIE_HDR_SZ + cookie->len; length += HRR_VERSIONS_SZ; if (cookieDataSz > hashSz + OPAQUE16_LEN) { @@ -4425,10 +4425,10 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) XMEMCPY(hrr + hrrIdx, helloRetryRequestRandom, RAN_LEN); hrrIdx += RAN_LEN; - hrr[hrrIdx++] = ssl->session.sessionIDSz; - if (ssl->session.sessionIDSz > 0) { - XMEMCPY(hrr + hrrIdx, ssl->session.sessionID, ssl->session.sessionIDSz); - hrrIdx += ssl->session.sessionIDSz; + hrr[hrrIdx++] = ssl->session->sessionIDSz; + if (ssl->session->sessionIDSz > 0) { + XMEMCPY(hrr + hrrIdx, ssl->session->sessionID, ssl->session->sessionIDSz); + hrrIdx += ssl->session->sessionIDSz; } /* Cipher Suite */ @@ -4439,7 +4439,7 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) hrr[hrrIdx++] = 0; /* Extensions' length */ - length -= HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz; + length -= HRR_BODY_SZ - ID_LEN + ssl->session->sessionIDSz; c16toa(length, hrr + hrrIdx); hrrIdx += 2; @@ -4717,9 +4717,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(BUFFER_ERROR, exit_dch); } - ssl->session.sessionIDSz = sessIdSz; + ssl->session->sessionIDSz = sessIdSz; if (sessIdSz == ID_LEN) { - XMEMCPY(ssl->session.sessionID, input + args->idx, sessIdSz); + XMEMCPY(ssl->session->sessionID, input + args->idx, sessIdSz); args->idx += ID_LEN; } @@ -4973,7 +4973,7 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) /* Protocol version, server random, session id, cipher suite, compression * and extensions. */ - length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session.sessionIDSz + + length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session->sessionIDSz + SUITE_LEN + COMP_LEN; ret = TLSX_GetResponseSize(ssl, extMsgType, &length); if (ret != 0) @@ -5014,10 +5014,10 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN); #endif - output[idx++] = ssl->session.sessionIDSz; - if (ssl->session.sessionIDSz > 0) { - XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz); - idx += ssl->session.sessionIDSz; + output[idx++] = ssl->session->sessionIDSz; + if (ssl->session->sessionIDSz > 0) { + XMEMCPY(output + idx, ssl->session->sessionID, ssl->session->sessionIDSz); + idx += ssl->session->sessionIDSz; } /* Chosen cipher suite */ @@ -7144,7 +7144,7 @@ static int SendTls13Finished(WOLFSSL* ssl) return ret; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); + ret = DeriveResumptionSecret(ssl, ssl->session->masterSecret); if (ret != 0) return ret; #endif @@ -7476,18 +7476,18 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, return now; /* Copy in ticket data (server identity). */ ssl->timeout = lifetime; - ssl->session.timeout = lifetime; - ssl->session.cipherSuite0 = ssl->options.cipherSuite0; - ssl->session.cipherSuite = ssl->options.cipherSuite; - ssl->session.ticketSeen = now; - ssl->session.ticketAdd = ageAdd; + ssl->session->timeout = lifetime; + ssl->session->cipherSuite0 = ssl->options.cipherSuite0; + ssl->session->cipherSuite = ssl->options.cipherSuite; + ssl->session->ticketSeen = now; + ssl->session->ticketAdd = ageAdd; #ifdef WOLFSSL_EARLY_DATA - ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + ssl->session->maxEarlyDataSz = ssl->options.maxEarlyDataSz; #endif - ssl->session.ticketNonce.len = nonceLength; + ssl->session->ticketNonce.len = nonceLength; if (nonceLength > 0) - XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength); - ssl->session.namedGroup = ssl->namedGroup; + XMEMCPY(&ssl->session->ticketNonce.data, nonce, nonceLength); + ssl->session->namedGroup = ssl->namedGroup; if ((*inOutIdx - begin) + EXTS_SZ > size) return BUFFER_ERROR; @@ -7592,7 +7592,7 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl) if ((ret = HashRaw(ssl, mac, finishedSz)) != 0) return ret; - if ((ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret)) != 0) + if ((ret = DeriveResumptionSecret(ssl, ssl->session->masterSecret)) != 0) return ret; /* Restore the hash inline with currently seen messages. */ @@ -7656,12 +7656,12 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) #endif /* Start ticket nonce at 0 and go up to 255. */ - if (ssl->session.ticketNonce.len == 0) { - ssl->session.ticketNonce.len = DEF_TICKET_NONCE_SZ; - ssl->session.ticketNonce.data[0] = 0; + if (ssl->session->ticketNonce.len == 0) { + ssl->session->ticketNonce.len = DEF_TICKET_NONCE_SZ; + ssl->session->ticketNonce.data[0] = 0; } else - ssl->session.ticketNonce.data[0]++; + ssl->session->ticketNonce.data[0]++; if (!ssl->options.noTicketTls13) { if ((ret = CreateTicket(ssl)) != 0) @@ -7669,9 +7669,9 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) } #ifdef WOLFSSL_EARLY_DATA - ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz; - if (ssl->session.maxEarlyDataSz > 0) - TLSX_EarlyData_Use(ssl, ssl->session.maxEarlyDataSz); + ssl->session->maxEarlyDataSz = ssl->options.maxEarlyDataSz; + if (ssl->session->maxEarlyDataSz > 0) + TLSX_EarlyData_Use(ssl, ssl->session->maxEarlyDataSz); extSz = 0; ret = TLSX_GetResponseSize(ssl, session_ticket, &extSz); if (ret != 0) @@ -7682,7 +7682,7 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) /* Lifetime | Age Add | Ticket | Extensions */ length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ + - ssl->session.ticketLen + extSz; + ssl->session->ticketLen + extSz; /* Nonce */ length += TICKET_NONCE_LEN_SZ + DEF_TICKET_NONCE_SZ; sendSz = idx + length + MAX_MSG_EXTRA; @@ -7702,18 +7702,18 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) c32toa(ssl->ctx->ticketHint, output + idx); idx += SESSION_HINT_SZ; /* Age add - obfuscator */ - c32toa(ssl->session.ticketAdd, output + idx); + c32toa(ssl->session->ticketAdd, output + idx); idx += SESSION_ADD_SZ; - output[idx++] = ssl->session.ticketNonce.len; - output[idx++] = ssl->session.ticketNonce.data[0]; + output[idx++] = ssl->session->ticketNonce.len; + output[idx++] = ssl->session->ticketNonce.data[0]; /* length */ - c16toa(ssl->session.ticketLen, output + idx); + c16toa(ssl->session->ticketLen, output + idx); idx += LENGTH_SZ; /* ticket */ - XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); - idx += ssl->session.ticketLen; + XMEMCPY(output + idx, ssl->session->ticket, ssl->session->ticketLen); + idx += ssl->session->ticketLen; #ifdef WOLFSSL_EARLY_DATA extSz = 0; @@ -8409,7 +8409,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifndef NO_WOLFSSL_SERVER #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (ssl->options.side == WOLFSSL_SERVER_END && type == finished) { - ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); + ret = DeriveResumptionSecret(ssl, ssl->session->masterSecret); if (ret != 0) return ret; } @@ -9933,8 +9933,8 @@ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) if (ssl->options.handShakeState == CLIENT_HELLO_COMPLETE) { #ifdef OPENSSL_EXTRA /* when processed early data exceeds max size */ - if (ssl->session.maxEarlyDataSz > 0 && - (ssl->earlyDataSz + sz > ssl->session.maxEarlyDataSz)) { + if (ssl->session->maxEarlyDataSz > 0 && + (ssl->earlyDataSz + sz > ssl->session->maxEarlyDataSz)) { ssl->error = TOO_MUCH_EARLY_DATA; return WOLFSSL_FATAL_ERROR; } diff --git a/tests/api.c b/tests/api.c index 535766b954..7053ba89f5 100644 --- a/tests/api.c +++ b/tests/api.c @@ -6257,13 +6257,14 @@ static void test_wolfSSL_CTX_add_session_on_result(WOLFSSL* ssl) } #ifdef SESSION_CERTS #ifndef WOLFSSL_TICKET_HAVE_ID - if (wolfSSL_version(ssl) != TLS1_3_VERSION) + if (wolfSSL_version(ssl) != TLS1_3_VERSION && + wolfSSL_session_reused(ssl)) #endif { /* With WOLFSSL_TICKET_HAVE_ID the peer certs should be available * for all connections. TLS 1.3 only has tickets so if we don't * include the session id in the ticket then the certificates - * will not be available. */ + * will not be available on resumption. */ WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); AssertNotNull(peer); wolfSSL_X509_free(peer); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 4cfcf96ef2..76f9162b3b 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3319,6 +3319,8 @@ struct WOLFSSL_SESSION { #ifndef SINGLE_THREADED wolfSSL_Mutex refMutex; /* ref count mutex */ #endif + byte altSessionID[ID_LEN]; + byte haveAltSessionID:1; void* heap; /* WARNING The above fields (up to and including the heap) are not copied * in wolfSSL_DupSession. Place new fields after the heap @@ -3711,9 +3713,6 @@ typedef struct Options { word16 startedETMRead:1; /* Doing Encrypt-Then-MAC read */ word16 startedETMWrite:1; /* Doing Encrypt-Then-MAC write */ #endif -#ifdef WOLFSSL_TICKET_HAVE_ID - word16 haveTicketSessionID:1; -#endif /* need full byte values for this section */ byte processReply; /* nonblocking resume */ @@ -4242,13 +4241,7 @@ struct WOLFSSL { Ciphers encrypt; Ciphers decrypt; Buffers buffers; - WOLFSSL_SESSION session; -#ifdef HAVE_EXT_CACHE - WOLFSSL_SESSION* extSession; -#endif -#ifdef WOLFSSL_TICKET_HAVE_ID - byte ticketSessionID[ID_LEN]; -#endif + WOLFSSL_SESSION* session; WOLFSSL_ALERT_HISTORY alert_history; int error; int rfd; /* read file descriptor */ @@ -4773,6 +4766,10 @@ WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL* ssl); WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL* ssl); WOLFSSL_LOCAL int AddSession(WOLFSSL* ssl); +WOLFSSL_LOCAL int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, + int* sessionIndex, int side, word16 useTicket); +WOLFSSL_LOCAL int AddSessionToClientCache(int side, int row, int idx, + byte* serverID, word16 idLen, word16 useTicket); WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 47a0297636..bad886e809 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1484,6 +1484,8 @@ WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_new(void); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap); WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session); +WOLFSSL_API int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, + WOLFSSL_SESSION* session); WOLFSSL_API int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, const WOLFSSL_CIPHER* cipher); WOLFSSL_API int wolfSSL_is_init_finished(WOLFSSL* ssl); @@ -4441,9 +4443,6 @@ WOLFSSL_API int wolfSSL_version(WOLFSSL* ssl); #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) \ || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) -WOLFSSL_API int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session); - - WOLFSSL_API int wolfSSL_get_state(const WOLFSSL* ssl); WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)*, int i); From ceff4012692fa4089e335053d6ed42df84d4af2b Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 8 Feb 2022 19:20:10 +0100 Subject: [PATCH 4/9] Fixes for Jenkins tests - Move test to `HAVE_IO_TESTS_DEPENDENCIES` - Implement `wolfSSL_trust_peer_cert` - have{cipher} options weren't being set with only RSA enabled --- examples/server/server.c | 2 +- src/internal.c | 58 ++++++++++++++++------ src/ssl.c | 102 ++++++++++++++++++++++++++++---------- tests/api.c | 103 +++++++++++++++++++++++++++------------ wolfssl/internal.h | 4 +- wolfssl/ssl.h | 9 +++- 6 files changed, 204 insertions(+), 74 deletions(-) diff --git a/examples/server/server.c b/examples/server/server.c index 535fbf7f8a..64e30f4e8e 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -802,7 +802,7 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, /* 4. add the same message into Japanese section */ /* (will be translated later) */ /* 5. add printf() into suitable position of Usage() */ -static const char* server_usage_msg[][60] = { +static const char* server_usage_msg[][63] = { /* English */ { " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ diff --git a/src/internal.c b/src/internal.c index 8ba08423ee..ba8291d769 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8974,7 +8974,8 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) return -1; case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */ - if (ssl->ctx->autoRetry && !ssl->options.handShakeDone) + if (ssl->ctx->autoRetry && !ssl->options.handShakeDone && + !ssl->options.dtls) goto retry; return WANT_READ; @@ -12498,13 +12499,18 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_MSG("Failed to verify Peer's cert"); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) if (ssl->peerVerifyRet == 0) { /* Return first cert error here */ - if (ret == ASN_BEFORE_DATE_E) - ssl->peerVerifyRet = X509_V_ERR_CERT_NOT_YET_VALID; - else if (ret == ASN_AFTER_DATE_E) - ssl->peerVerifyRet = X509_V_ERR_CERT_HAS_EXPIRED; + if (ret == ASN_BEFORE_DATE_E) { + ssl->peerVerifyRet = + (unsigned long)X509_V_ERR_CERT_NOT_YET_VALID; + } + else if (ret == ASN_AFTER_DATE_E) { + ssl->peerVerifyRet = + (unsigned long)X509_V_ERR_CERT_HAS_EXPIRED; + } else { ssl->peerVerifyRet = - X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + (unsigned long) + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; } } #endif @@ -29188,7 +29194,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->arrays->masterSecret, 1); #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket == 1) { - session = &ssl->session; + session = ssl->session; } #endif @@ -30605,24 +30611,44 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_TICKET_HAVE_ID { const byte* id = NULL; - if (ssl->session->haveAltSessionID) + byte idSz = 0; + if (ssl->session->haveAltSessionID) { id = ssl->session->altSessionID; - else if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) + idSz = ID_LEN; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) { id = ssl->arrays->sessionID; - else + idSz = ssl->arrays->sessionIDSz; + } + else { id = ssl->session->sessionID; + idSz = ssl->session->sessionIDSz; + } + if (idSz == 0) { + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->session->altSessionID, + ID_LEN); + if (ret != 0) + return ret; + ssl->session->haveAltSessionID = 1; + id = ssl->session->altSessionID; + idSz = ID_LEN; + } XMEMCPY(it.id, id, ID_LEN); } #endif /* encrypt */ encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */ - if (ssl->ctx->ticketEncCb == NULL || + if (ssl->ctx->ticketEncCb == NULL +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) + || /* SSL_OP_NO_TICKET turns off tickets in < 1.2. Forces * "stateful" tickets for 1.3 so just use the regular * stateless ones. */ (!IsAtLeastTLSv1_3(ssl->version) && - (ssl->options.mask & SSL_OP_NO_TICKET) != 0)) { + (ssl->options.mask & SSL_OP_NO_TICKET) != 0) +#endif + ) { ret = WOLFSSL_TICKET_RET_FATAL; } else { @@ -30717,12 +30743,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } outLen = inLen; /* may be reduced by user padding */ - if (ssl->ctx->ticketEncCb == NULL || + if (ssl->ctx->ticketEncCb == NULL +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) + || /* SSL_OP_NO_TICKET turns off tickets in < 1.2. Forces * "stateful" tickets for 1.3 so just use the regular * stateless ones. */ (!IsAtLeastTLSv1_3(ssl->version) && - (ssl->options.mask & SSL_OP_NO_TICKET) != 0)) { + (ssl->options.mask & SSL_OP_NO_TICKET) != 0) +#endif + ) { ret = WOLFSSL_TICKET_RET_FATAL; } else { diff --git a/src/ssl.c b/src/ssl.c index a14e27af0b..2088770078 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -4398,8 +4398,12 @@ void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len, #endif #endif +/* + * TODO This ssl parameter needs to be changed to const once our ABI checker + * stops flagging qualifier additions as ABI breaking. + */ WOLFSSL_ABI -int wolfSSL_pending(const WOLFSSL* ssl) +int wolfSSL_pending(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_pending"); if (ssl == NULL) @@ -6130,13 +6134,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #ifdef WOLFSSL_TRUST_PEER_CERT else if (type == TRUSTED_PEER_TYPE) { - if (ctx == NULL) { - WOLFSSL_MSG("Need context for trusted peer cert load"); - FreeDer(&der); - return BAD_FUNC_ARG; - } /* add trusted peer cert. der is freed within */ - ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone); + if (ctx != NULL) + ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone); + else + ret = AddTrustedPeer(SSL_CM(ssl), &der, !ssl->options.verifyNone); if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error adding trusted peer"); } @@ -6322,9 +6324,12 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ - defined(HAVE_PQC) + defined(HAVE_PQC) || !defined(NO_RSA) if (ssl) { + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) ssl->pkCurveOID = cert->pkCurveOID; + #endif #ifndef WC_STRICT_SIG if (cert->keyOID == ECDSAk) { ssl->options.haveECC = 1; @@ -6355,7 +6360,9 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif } else if (ctx) { + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) ctx->pkCurveOID = cert->pkCurveOID; + #endif #ifndef WC_STRICT_SIG if (cert->keyOID == ECDSAk) { ctx->haveECC = 1; @@ -7620,6 +7627,18 @@ int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type) return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL, GET_VERIFY_SETTING_CTX(ctx)); } + +int wolfSSL_trust_peer_cert(WOLFSSL* ssl, const char* file, int type) +{ + WOLFSSL_ENTER("wolfSSL_trust_peer_cert"); + + if (ssl == NULL || file == NULL) { + return WOLFSSL_FAILURE; + } + + return ProcessFile(NULL, file, type, TRUSTED_PEER_TYPE, ssl, 0, NULL, + GET_VERIFY_SETTING_SSL(ssl)); +} #endif /* WOLFSSL_TRUST_PEER_CERT */ @@ -15769,7 +15788,7 @@ int AddSessionToClientCache(int side, int row, int idx, byte* serverID, } #endif -int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, +int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, int* sessionIndex, int side, word16 useTicket) { WOLFSSL_SESSION* cacheSession = NULL; @@ -15790,8 +15809,10 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, (void)sessionIndex; (void)useTicket; - if (addSession == NULL) + if (addSession == NULL || idSz == 0) { + WOLFSSL_MSG("addSession NULL or idSz == 0"); return BAD_FUNC_ARG; + } /* Find a position for the new session in cache and use that */ #ifdef HAVE_SESSION_TICKET @@ -15916,6 +15937,7 @@ int AddSession(WOLFSSL* ssl) { int error = 0; const byte* id = NULL; + byte idSz = 0; WOLFSSL_SESSION* session = ssl->session; #ifdef HAVE_EXT_CACHE int cbRet = 0; @@ -15941,8 +15963,10 @@ int AddSession(WOLFSSL* ssl) } #endif - if (session->haveAltSessionID) + if (session->haveAltSessionID) { id = session->altSessionID; + idSz = ID_LEN; + } else { if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) { /* Make sure the session ID is available when the user calls any @@ -15951,15 +15975,9 @@ int AddSession(WOLFSSL* ssl) session->sessionIDSz = ssl->arrays->sessionIDSz; } id = session->sessionID; + idSz = session->sessionIDSz; } - - if (id == NULL) { - WOLFSSL_MSG("No Session ID"); - return BAD_FUNC_ARG; - } - - /* Setup the ssl->session object */ session->timeout = ssl->timeout; session->side = (byte)ssl->options.side; if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) @@ -15993,7 +16011,7 @@ int AddSession(WOLFSSL* ssl) if (!ssl->options.internalCacheOff) #endif { - error = AddSessionToCache(session, id, + error = AddSessionToCache(session, id, idSz, #ifdef SESSION_INDEX &ssl->sessionIndex, #else @@ -17203,6 +17221,18 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return wolfSSL_CertManagerUnload_trust_peers(ctx->cm); } + +#ifdef WOLFSSL_LOCAL_X509_STORE + int wolfSSL_Unload_trust_peers(WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl)); + } +#endif /* WOLFSSL_LOCAL_X509_STORE */ #endif /* WOLFSSL_TRUST_PEER_CERT */ /* old NO_FILESYSTEM end */ #endif /* !NO_CERTS */ @@ -23670,7 +23700,9 @@ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) } #endif ret->refCount = 1; +#ifndef NO_SESSION_CACHE ret->cacheRow = INVALID_SESSION_ROW; /* not in cache */ +#endif ret->type = WOLFSSL_SESSION_TYPE_HEAP; ret->heap = heap; ret->masterSecret = ret->_masterSecret; @@ -23782,7 +23814,9 @@ int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output, /* Set sane values for copy */ if (output->type != WOLFSSL_SESSION_TYPE_CACHE) +#ifndef NO_SESSION_CACHE output->cacheRow = INVALID_SESSION_ROW; +#endif #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) if (input->peer != NULL && input->peer->dynamicMemory) { if (wolfSSL_X509_up_ref(input->peer) != WOLFSSL_SUCCESS) { @@ -23971,10 +24005,12 @@ void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) wolfSSL_FreeSession(session); } +#ifndef NO_SESSION_CACHE int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) { int error = 0; const byte* id = NULL; + byte idSz = 0; WOLFSSL_ENTER("wolfSSL_CTX_add_session"); @@ -23985,10 +24021,13 @@ int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) (void)ctx; id = session->sessionID; - if (session->haveAltSessionID) + idSz = session->sessionIDSz; + if (session->haveAltSessionID) { id = session->altSessionID; + idSz = ID_LEN; + } - error = AddSessionToCache(session, id, + error = AddSessionToCache(session, id, idSz, NULL, session->side, #ifdef HAVE_SESSION_TICKET session->ticketLen > 0 @@ -23999,6 +24038,7 @@ int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) return error == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } +#endif #if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) @@ -32484,6 +32524,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, (void)p; (void)i; (void)ret; + (void)sess; #ifdef HAVE_EXT_CACHE if (p == NULL || *p == NULL) @@ -34467,11 +34508,16 @@ int wolfSSL_DH_set0_pqg(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *p, /* free existing internal DH structure and recreate with new p / g */ if (dh->inSet) { +#ifndef HAVE_SELFTEST ret = wc_FreeDhKey((DhKey*)dh->internal); if (ret != 0) { WOLFSSL_MSG("Unable to free internal DH key"); return WOLFSSL_FAILURE; } +#else + /* Selftest code has this API with a void return type */ + wc_FreeDhKey((DhKey*)dh->internal); +#endif } wolfSSL_BN_free(dh->p); @@ -40498,7 +40544,6 @@ int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) } /* End ECDSA_SIG */ - /* Remove this prototype when code is reorganized. */ static int wolfSSL_RAND_Init(void); @@ -45760,16 +45805,20 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) #ifdef WOLFSSL_HAVE_ERROR_QUEUE unsigned long err; CLEAR_ASN_NO_PEM_HEADER_ERROR(err); + if (ERR_GET_LIB(err) != ERR_LIB_PEM || + ERR_GET_REASON(err) != PEM_R_NO_START_LINE) { + ret = WOLFSSL_FAILURE; + } #else if (wolfSSL_sk_X509_INFO_num(localSk) > 0) { WOLFSSL_MSG("At least one X509_INFO object on stack." "Assuming error means EOF or no more PEM" "headers found."); } -#endif else { ret = WOLFSSL_FAILURE; } +#endif break; } } @@ -48708,6 +48757,7 @@ void wolfSSL_sk_X509_NAME_ENTRY_free(WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk) (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) +#ifdef HAVE_EX_DATA int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, CRYPTO_free_func* cb3) { @@ -48719,6 +48769,7 @@ int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, (void)data; return get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION); } +#endif #if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY) static wolfSSL_OSSL_Malloc_cb ossl_malloc = NULL; @@ -51914,7 +51965,8 @@ int wolfSSL_sk_WOLFSSL_STRING_num(WOLF_STACK_OF(WOLFSSL_STRING)* strings) #endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ + defined(KEEP_PEER_CERT) WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x) { WOLFSSL_ENTER("wolfSSL_X509_dup"); @@ -63779,7 +63831,7 @@ WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) if (mem != NULL && localPkcs12 != NULL) { if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { - ret = wc_d2i_PKCS12(mem, memSz, localPkcs12); + ret = wc_d2i_PKCS12(mem, (word32)memSz, localPkcs12); if (ret < 0) { WOLFSSL_MSG("Failed to get PKCS12 sequence"); } diff --git a/tests/api.c b/tests/api.c index 7053ba89f5..e47cf6352b 100644 --- a/tests/api.c +++ b/tests/api.c @@ -914,47 +914,66 @@ static void test_wolfSSL_CTX_trust_peer_cert(void) #if !defined(NO_CERTS) && defined(WOLFSSL_TRUST_PEER_CERT) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx; + WOLFSSL* ssl; AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + AssertNotNull(ssl = wolfSSL_new(ctx)); #if !defined(NO_FILESYSTEM) /* invalid file */ - assert(wolfSSL_CTX_trust_peer_cert(ctx, NULL, - WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS); - assert(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, - WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS); - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, - WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_trust_peer_cert(ctx, NULL, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + /* success */ + AssertIntEQ(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + /* unload cert */ + AssertIntNE(wolfSSL_CTX_Unload_trust_peers(NULL), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_Unload_trust_peers(ctx), WOLFSSL_SUCCESS); + + /* invalid file */ + AssertIntNE(wolfSSL_trust_peer_cert(ssl, NULL, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_trust_peer_cert(ssl, bogusFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_trust_peer_cert(ssl, cliCertFile, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* success */ - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM) - == WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_trust_peer_cert(ssl, cliCertFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* unload cert */ - assert(wolfSSL_CTX_Unload_trust_peers(NULL) != WOLFSSL_SUCCESS); - assert(wolfSSL_CTX_Unload_trust_peers(ctx) == WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_Unload_trust_peers(NULL), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_Unload_trust_peers(ssl), WOLFSSL_SUCCESS); #endif /* Test of loading certs from buffers */ /* invalid buffer */ - assert(wolfSSL_CTX_trust_peer_buffer(ctx, NULL, -1, - WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_trust_peer_buffer(ctx, NULL, -1, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* success */ #ifdef USE_CERT_BUFFERS_1024 - assert(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_1024, - sizeof_client_cert_der_1024, WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_1024, + sizeof_client_cert_der_1024, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #endif #ifdef USE_CERT_BUFFERS_2048 - assert(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_2048, - sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_2048, + sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #endif /* unload cert */ - assert(wolfSSL_CTX_Unload_trust_peers(NULL) != WOLFSSL_SUCCESS); - assert(wolfSSL_CTX_Unload_trust_peers(ctx) == WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_Unload_trust_peers(NULL), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_Unload_trust_peers(ctx), WOLFSSL_SUCCESS); + wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif } @@ -4488,7 +4507,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) goto done; } - if (cbf != NULL && !cbf->ticNoInit) { + if (cbf == NULL || !cbf->ticNoInit) { #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) @@ -4693,7 +4712,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) wc_ecc_fp_free(); /* free per thread cache */ #endif - if (cbf != NULL && !cbf->ticNoInit) { + if (cbf == NULL || !cbf->ticNoInit) { #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) @@ -6238,9 +6257,16 @@ static void test_wolfSSL_CTX_add_session_on_result(WOLFSSL* ssl) if (*sess == NULL) { AssertNotNull(*sess = wolfSSL_get1_session(ssl)); /* Now save the session in the internal store to make it available - * for lookup */ - AssertIntEQ(wolfSSL_CTX_add_session(wolfSSL_get_SSL_CTX(ssl), *sess), - WOLFSSL_SUCCESS); + * for lookup. For TLS 1.3, we can't save the session without + * WOLFSSL_TICKET_HAVE_ID because there is no way to retrieve the + * session from cache. */ + if (wolfSSL_is_server(ssl) +#ifndef WOLFSSL_TICKET_HAVE_ID + && wolfSSL_version(ssl) != TLS1_3_VERSION +#endif + ) + AssertIntEQ(wolfSSL_CTX_add_session(wolfSSL_get_SSL_CTX(ssl), + *sess), WOLFSSL_SUCCESS); } else { /* If we have a session retrieved then remaining connections should be @@ -6292,7 +6318,10 @@ static void test_wolfSSL_CTX_add_session(void) callback_functions client_cb; callback_functions server_cb; method_provider methods[][2] = { -#ifndef NO_OLD_TLS +#if !defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \ + !defined(NO_DES3)) + /* Without AES there are almost no ciphersuites available. This leads + * to no ciphersuites being available and an error. */ { wolfTLSv1_1_client_method, wolfTLSv1_1_server_method }, #endif #ifndef WOLFSSL_NO_TLS12 @@ -50000,13 +50029,13 @@ static void test_wolfSSL_CTX_LoadCRL(void) FAIL_T1(wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor); - #ifndef NO_WOLFSSL_CLIENT +#ifndef NO_WOLFSSL_CLIENT AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); - #elif !defined(NO_WOLFSSL_SERVER) +#elif !defined(NO_WOLFSSL_SERVER) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); - #else +#else return; - #endif +#endif SUCC_T (wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor); SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, pemType, monitor); @@ -50014,13 +50043,25 @@ static void test_wolfSSL_CTX_LoadCRL(void) wolfSSL_CTX_free(ctx); - AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#elif !defined(NO_WOLFSSL_SERVER) + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + return; +#endif AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL), WOLFSSL_SUCCESS); AssertIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, validFilePath, pemType), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); - AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#elif !defined(NO_WOLFSSL_SERVER) + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + return; +#endif AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL), WOLFSSL_SUCCESS); AssertNotNull(ssl = wolfSSL_new(ctx)); @@ -52326,8 +52367,8 @@ void ApiTest(void) #endif #ifdef HAVE_IO_TESTS_DEPENDENCIES test_wolfSSL_get_finished(); -#endif test_wolfSSL_CTX_add_session(); +#endif test_SSL_CIPHER_get_xxx(); test_wolfSSL_ERR_strings(); test_wolfSSL_EVP_shake128(); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 76f9162b3b..41df10959a 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3314,7 +3314,9 @@ struct WOLFSSL_SESSION { /* WARNING Do not add fields here. They will be ignored in * wolfSSL_DupSession. */ WOLFSSL_SESSION_TYPE type; +#ifndef NO_SESSION_CACHE int cacheRow; /* row in session cache */ +#endif int refCount; /* reference count */ #ifndef SINGLE_THREADED wolfSSL_Mutex refMutex; /* ref count mutex */ @@ -4767,7 +4769,7 @@ WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL* ssl); WOLFSSL_LOCAL int AddSession(WOLFSSL* ssl); WOLFSSL_LOCAL int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, - int* sessionIndex, int side, word16 useTicket); + byte idSz, int* sessionIndex, int side, word16 useTicket); WOLFSSL_LOCAL int AddSessionToClientCache(int side, int row, int idx, byte* serverID, word16 idLen, word16 useTicket); WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index bad886e809..e78a2134ba 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -970,6 +970,8 @@ WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_load_verify_locations( #ifdef WOLFSSL_TRUST_PEER_CERT WOLFSSL_API int wolfSSL_CTX_trust_peer_cert( WOLFSSL_CTX* ctx, const char* file, int type); +WOLFSSL_API int wolfSSL_trust_peer_cert( + WOLFSSL* ssl, const char* file, int type); #endif WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file( WOLFSSL_CTX* ctx, const char* file); @@ -1193,7 +1195,7 @@ WOLFSSL_API int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val); WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx); -WOLFSSL_ABI WOLFSSL_API int wolfSSL_pending(const WOLFSSL* ssl); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_pending(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_has_pending(const WOLFSSL* ssl); WOLFSSL_API void wolfSSL_load_error_strings(void); @@ -1509,6 +1511,7 @@ WOLFSSL_API void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void); +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509* x); #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) WOLFSSL_API int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa); WOLFSSL_API int wolfSSL_X509_up_ref(WOLFSSL_X509* x509); @@ -2837,6 +2840,9 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* key, unsigned int len, WOLFSSL_API int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx); #ifdef WOLFSSL_TRUST_PEER_CERT WOLFSSL_API int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx); +#ifdef WOLFSSL_LOCAL_X509_STORE + WOLFSSL_API int wolfSSL_Unload_trust_peers(WOLFSSL* ssl); +#endif WOLFSSL_API int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx, const unsigned char*, long, int); #endif @@ -4011,7 +4017,6 @@ WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_delete_entry( WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, const WOLFSSL_X509_NAME* y); WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void); -WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509* x); WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(WOLFSSL_X509_NAME* name); WOLFSSL_API int wolfSSL_X509_NAME_copy(WOLFSSL_X509_NAME* from, WOLFSSL_X509_NAME* to); WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); From b402102e58f4fbe04993f61562e801e00e1afbf6 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 11 Feb 2022 19:05:12 +0100 Subject: [PATCH 5/9] Add backwards compatibility for `wolfSSL_get_session` Before this pull request, `wolfSSL_get_session` always returned a pointer to the internal session cache. The user can't tell if the underlying session hasn't changed before it calls `wolfSSL_set_session` on it. This PR adds a define `NO_SESSION_CACHE_REF` (for now only defined with `OPENSSL_COMPATIBLE_DEFAULTS`) that makes wolfSSL only return a pointer to `ssl->session`. The issue is that this makes the pointer returned non-persistent ie: it gets free'd with the `WOLFSSL` object. This commit leverages the lightweight `ClientCache` to "increase" the size of the session cache. The hash of the session ID is checked to make sure that the underlying session hasn't changed. --- configure.ac | 1 + src/ssl.c | 430 +++++++++++++++++++++++++++++++++++---------- src/tls13.c | 2 +- tests/api.c | 12 ++ wolfssl/internal.h | 29 +-- 5 files changed, 368 insertions(+), 106 deletions(-) diff --git a/configure.ac b/configure.ac index 1504afda18..b7d5e9cb52 100644 --- a/configure.ac +++ b/configure.ac @@ -6830,6 +6830,7 @@ AS_CASE(["$CFLAGS $CPPFLAGS $AM_CFLAGS"],[*'OPENSSL_COMPATIBLE_DEFAULTS'*], if test "x$ENABLED_OPENSSL_COMPATIBLE_DEFAULTS" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRUST_PEER_CERT -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT" + AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE_REF" ENABLED_TRUSTED_PEER_CERT=yes fi diff --git a/src/ssl.c b/src/ssl.c index 2088770078..40eadf10d1 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -164,6 +164,11 @@ * should make porting to new projects easier. * WOLFSSL_CHECK_ALERT_ON_ERR: * Check for alerts during the handshake in the event of an error. + * NO_SESSION_CACHE_REF: + * wolfSSL_get_session on a client will return a reference to the internal + * ClientCache by default for backwards compatibility. This define will + * make wolfSSL_get_session return a reference to ssl->session. The returned + * pointer will be freed with the related WOLFSSL object. */ #define WOLFSSL_EVP_INCLUDED @@ -3341,7 +3346,7 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, /* Ticket will fit into static ticket */ if (bufSz <= SESSION_TICKET_LEN) { if (ssl->session->ticketLenAlloc > 0) { - XFREE(ssl->session->ticket, ssl->heap, + XFREE(ssl->session->ticket, ssl->session->heap, DYNAMIC_TYPE_SESSION_TICK); ssl->session->ticketLenAlloc = 0; ssl->session->ticket = ssl->session->_staticTicket; @@ -3350,7 +3355,7 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, else { /* Ticket requires dynamic ticket storage */ if (ssl->session->ticketLen < bufSz) { /* is dyn buffer big enough */ if (ssl->session->ticketLenAlloc > 0) { - XFREE(ssl->session->ticket, ssl->heap, + XFREE(ssl->session->ticket, ssl->session->heap, DYNAMIC_TYPE_SESSION_TICK); } ssl->session->ticket = (byte*)XMALLOC(bufSz, ssl->session->heap, @@ -5298,20 +5303,48 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) #define SESSION_ROW_UNLOCK(row) wc_UnLockMutex(&session_mutex); #endif + #if !defined(NO_SESSION_CACHE_REF) && defined(NO_CLIENT_CACHE) + #error ClientCache is required when not using NO_SESSION_CACHE_REF + #endif + #ifndef NO_CLIENT_CACHE + #ifndef CLIENT_SESSIONS_MULTIPLIER + #ifdef NO_SESSION_CACHE_REF + #define CLIENT_SESSIONS_MULTIPLIER 1 + #else + /* ClientSession objects are lightweight (compared to + * WOLFSSL_SESSION) so to decrease chance that user will reuse + * thse wrong session, increase the ClientCache size. This will + * make the entire ClientCache about the size of one + * WOLFSSL_SESSION object. */ + #define CLIENT_SESSIONS_MULTIPLIER 8 + #endif + #endif + #define CLIENT_SESSIONS_PER_ROW \ + (SESSIONS_PER_ROW * CLIENT_SESSIONS_MULTIPLIER) + #define CLIENT_SESSION_ROWS (SESSION_ROWS * CLIENT_SESSIONS_MULTIPLIER) + + #if CLIENT_SESSIONS_PER_ROW > 65535 + #error CLIENT_SESSIONS_PER_ROW too big + #endif + #if CLIENT_SESSION_ROWS > 65535 + #error CLIENT_SESSION_ROWS too big + #endif + typedef struct ClientSession { word16 serverRow; /* SessionCache Row id */ word16 serverIdx; /* SessionCache Idx (column) */ + word32 sessionIDHash; } ClientSession; typedef struct ClientRow { int nextIdx; /* where to place next one */ int totalCount; /* sessions ever on this row */ - ClientSession Clients[SESSIONS_PER_ROW]; + ClientSession Clients[CLIENT_SESSIONS_PER_ROW]; } ClientRow; - static WOLFSSL_GLOBAL ClientRow ClientCache[SESSION_ROWS]; + static WOLFSSL_GLOBAL ClientRow ClientCache[CLIENT_SESSION_ROWS]; /* Client Cache */ /* uses session mutex */ @@ -12239,6 +12272,8 @@ int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, { int size; + ses = ClientSessionToSession(ses); + if (outSz == 0) { return SECRET_LEN; } @@ -12501,8 +12536,45 @@ WOLFSSL_ABI WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_session"); - if (ssl) + if (ssl) { +#ifdef NO_SESSION_CACHE_REF return ssl->session; +#else + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* On the client side we want to return a persistant reference for + * backwards compatibility. */ +#ifndef NO_CLIENT_CACHE + if (ssl->clientSession) + return (WOLFSSL_SESSION*)ssl->clientSession; + else { + /* Try to add a ClientCache entry to associate with the current + * session. Ignore any session cache options. */ + int error; + const byte* id = NULL; + byte idSz = 0; + id = ssl->session->sessionID; + idSz = ssl->session->sessionIDSz; + if (ssl->session->haveAltSessionID) { + id = ssl->session->altSessionID; + idSz = ID_LEN; + } + error = AddSessionToCache(ssl->session, id, idSz, + NULL, ssl->session->side, +#ifdef HAVE_SESSION_TICKET + ssl->session->ticketLen > 0, +#else + 0, +#endif + &ssl->clientSession); + if (error == 0) + return (WOLFSSL_SESSION*)ssl->clientSession; + } +#endif + } + else + return ssl->session; +#endif + } return NULL; } @@ -12641,9 +12713,6 @@ int wolfSSL_memsave_session_cache(void* mem, int sz) int i; cache_header_t cache_header; SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); -#ifndef NO_CLIENT_CACHE - ClientRow* clRow; -#endif WOLFSSL_ENTER("wolfSSL_memsave_session_cache"); @@ -12686,11 +12755,7 @@ int wolfSSL_memsave_session_cache(void* mem, int sz) WOLFSSL_MSG("Client cache mutex lock failed"); return BAD_MUTEX_E; } - - clRow = (ClientRow*)row; - for (i = 0; i < cache_header.rows; ++i) { - XMEMCPY(clRow++, ClientCache + i, sizeof(ClientRow)); - } + XMEMCPY(row, ClientCache, sizeof(ClientCache)); wc_UnLockMutex(&clisession_mutex); #endif @@ -12706,9 +12771,6 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz) int i; cache_header_t cache_header; SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); -#ifndef NO_CLIENT_CACHE - ClientRow* clRow; -#endif WOLFSSL_ENTER("wolfSSL_memrestore_session_cache"); @@ -12755,11 +12817,7 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz) WOLFSSL_MSG("Client cache mutex lock failed"); return BAD_MUTEX_E; } - - clRow = (ClientRow*)row; - for (i = 0; i < cache_header.rows; ++i) { - XMEMCPY(ClientCache + i, clRow++, sizeof(ClientRow)); - } + XMEMCPY(ClientCache, row, sizeof(ClientCache)); wc_UnLockMutex(&clisession_mutex); #endif @@ -12838,14 +12896,10 @@ int wolfSSL_save_session_cache(const char *fname) XFCLOSE(file); return BAD_MUTEX_E; } - - for (i = 0; i < cache_header.rows; ++i) { - ret = (int)XFWRITE(ClientCache + i, sizeof(ClientRow), 1, file); - if (ret != 1) { - WOLFSSL_MSG("Client cache member file write failed"); - rc = FWRITE_ERROR; - break; - } + ret = (int)XFWRITE(ClientCache, sizeof(ClientCache), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Client cache member file write failed"); + rc = FWRITE_ERROR; } wc_UnLockMutex(&clisession_mutex); #endif /* !NO_CLIENT_CACHE */ @@ -12930,14 +12984,11 @@ int wolfSSL_restore_session_cache(const char *fname) XFCLOSE(file); return BAD_MUTEX_E; } - for (i = 0; i < cache_header.rows; ++i) { - ret = (int)XFREAD(ClientCache + i, sizeof(ClientRow), 1, file); - if (ret != 1) { - WOLFSSL_MSG("Client cache member file read failed"); - XMEMSET(ClientCache, 0, sizeof ClientCache); - rc = FREAD_ERROR; - break; - } + ret = (int)XFREAD(ClientCache, sizeof(ClientCache), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Client cache member file read failed"); + XMEMSET(ClientCache, 0, sizeof ClientCache); + rc = FREAD_ERROR; } wc_UnLockMutex(&clisession_mutex); #endif /* !NO_CLIENT_CACHE */ @@ -15342,7 +15393,7 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) } #endif - row = HashSession(id, len, &error) % SESSION_ROWS; + row = HashSession(id, len, &error) % CLIENT_SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); return NULL; @@ -15354,10 +15405,10 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) } /* start from most recently used */ - count = min((word32)ClientCache[row].totalCount, SESSIONS_PER_ROW); + count = min((word32)ClientCache[row].totalCount, CLIENT_SESSIONS_PER_ROW); idx = ClientCache[row].nextIdx - 1; - if (idx < 0 || idx >= SESSIONS_PER_ROW) { - idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ + if (idx < 0 || idx >= CLIENT_SESSIONS_PER_ROW) { + idx = CLIENT_SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ } clSess = ClientCache[row].Clients; @@ -15393,7 +15444,7 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) } SESSION_ROW_UNLOCK(sessRow); - idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1; + idx = idx > 0 ? idx - 1 : CLIENT_SESSIONS_PER_ROW - 1; } wc_UnLockMutex(&clisession_mutex); @@ -15667,36 +15718,59 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) { + SessionRow* sessRow = NULL; int ret = WOLFSSL_SUCCESS; - if (ssl == NULL || session == NULL || SslSessionCacheOff(ssl, session)) { + session = ClientSessionToSession(session); + + if (ssl == NULL || session == NULL) { return WOLFSSL_FAILURE; } if (session->type == WOLFSSL_SESSION_TYPE_CACHE) { - WOLFSSL_MSG("Can't call wolfSSL_SetSession on a session in the cache. " - "This may cause issues when the cache entry is modified " - "before it gets used."); - return WOLFSSL_FAILURE; + if (session->cacheRow < SESSION_ROWS) { + sessRow = &SessionCache[session->cacheRow]; + if (SESSION_ROW_LOCK(sessRow) != 0) { + WOLFSSL_MSG("Session row lock failed"); + return WOLFSSL_FAILURE; + } + } } - if (ssl->options.side != WOLFSSL_NEITHER_END && + if (ret == WOLFSSL_SUCCESS && SslSessionCacheOff(ssl, session)) { + WOLFSSL_MSG("Session cache off"); + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS && ssl->options.side != WOLFSSL_NEITHER_END && (byte)ssl->options.side != session->side) { WOLFSSL_MSG("Setting session for wrong role"); - return WOLFSSL_FAILURE; + ret = WOLFSSL_FAILURE; } - if (wolfSSL_DupSession(session, ssl->session, 0) != WOLFSSL_SUCCESS) { + + if (ret == WOLFSSL_SUCCESS && + wolfSSL_DupSession(session, ssl->session, 0) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Session duplicate failed"); - return WOLFSSL_FAILURE; + ret = WOLFSSL_FAILURE; } /* Let's copy over the altSessionID for local cache purposes */ - if (session->haveAltSessionID) { + if (ret == WOLFSSL_SUCCESS && session->haveAltSessionID) { ssl->session->haveAltSessionID = 1; XMEMCPY(ssl->session->altSessionID, session->altSessionID, ID_LEN); } + if (sessRow != NULL) { + SESSION_ROW_UNLOCK(sessRow); + sessRow = NULL; + } + /* Make sure we don't access this anymore */ + session = NULL; + + if (ret != WOLFSSL_SUCCESS) + return ret; + #ifdef OPENSSL_EXTRA /* check for application context id */ if (ssl->sessionCtxSz > 0) { @@ -15747,10 +15821,12 @@ static int get_locked_session_stats(word32* active, word32* total, #endif #ifndef NO_CLIENT_CACHE -int AddSessionToClientCache(int side, int row, int idx, byte* serverID, - word16 idLen, word16 useTicket) +ClientSession* AddSessionToClientCache(int side, int row, int idx, byte* serverID, + word16 idLen, const byte* sessionID, + word16 useTicket) { - int error = 0; + int error = -1; + word32 clientRow = 0, clientIdx = 0, sessionIDHash = 0; (void)useTicket; if (side == WOLFSSL_CLIENT_END && row != INVALID_SESSION_ROW @@ -15758,22 +15834,40 @@ int AddSessionToClientCache(int side, int row, int idx, byte* serverID, #ifdef HAVE_SESSION_TICKET || useTicket == 1 #endif + || serverID != NULL )) { - word32 clientRow, clientIdx; - WOLFSSL_MSG("Adding client cache entry"); + WOLFSSL_MSG("Trying to add client cache entry"); - clientRow = HashSession(serverID, - idLen, &error) % SESSION_ROWS; + if (idLen) { + clientRow = HashSession(serverID, + idLen, &error) % CLIENT_SESSION_ROWS; + } + else if (serverID != NULL) { + clientRow = HashSession(sessionID, + ID_LEN, &error) % CLIENT_SESSION_ROWS; + } + else + error = -1; if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) { clientIdx = ClientCache[clientRow].nextIdx++; ClientCache[clientRow].Clients[clientIdx].serverRow = (word16)row; ClientCache[clientRow].Clients[clientIdx].serverIdx = (word16)idx; - if (ClientCache[clientRow].totalCount < SESSIONS_PER_ROW) - ClientCache[clientRow].totalCount++; - ClientCache[clientRow].nextIdx %= SESSIONS_PER_ROW; + if (sessionID != NULL) { + sessionIDHash = HashSession(sessionID, ID_LEN, &error); + if (error == 0) { + ClientCache[clientRow].Clients[clientIdx].sessionIDHash + = sessionIDHash; + } + } + if (error == 0) { + WOLFSSL_MSG("Adding client cache entry"); + if (ClientCache[clientRow].totalCount < CLIENT_SESSIONS_PER_ROW) + ClientCache[clientRow].totalCount++; + ClientCache[clientRow].nextIdx %= CLIENT_SESSIONS_PER_ROW; + } wc_UnLockMutex(&clisession_mutex); } @@ -15784,12 +15878,100 @@ int AddSessionToClientCache(int side, int row, int idx, byte* serverID, else { WOLFSSL_MSG("Skipping client cache"); } - return error; + if (error == 0) + return &ClientCache[clientRow].Clients[clientIdx]; + else + return NULL; } #endif +/** + * For backwards compatibility, this API needs to be used in *ALL* functions + * that access the WOLFSSL_SESSION members directly. + * + * This API checks if the passed in session is actually a ClientSession object + * and returns the matching session cache object. Otherwise just return the + * input. ClientSession objects only occur in the ClientCache. They are not + * allocated anywhere else. + */ +WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("ClientSessionToSession"); +#ifdef NO_SESSION_CACHE_REF + return (WOLFSSL_SESSION*)session; +#else +#ifndef NO_CLIENT_CACHE + if (session == NULL) + return NULL; + /* Check if session points into ClientCache */ + if ((byte*)session >= (byte*)ClientCache && + /* Cast to byte* to make pointer arithmetic work per byte */ + (byte*)session < ((byte*)ClientCache) + sizeof(ClientCache)) { + ClientSession* clientSession = (ClientSession*)session; + SessionRow* sessRow = NULL; + WOLFSSL_SESSION* cacheSession = NULL; + word32 sessionIDHash = 0; + int error = 0; + session = NULL; /* Default to NULL for failure case */ + if (wc_LockMutex(&clisession_mutex) != 0) { + WOLFSSL_MSG("Client cache mutex lock failed"); + return NULL; + } + if (clientSession->serverRow >= SESSION_ROWS || + clientSession->serverIdx >= SESSIONS_PER_ROW) { + WOLFSSL_MSG("Client cache serverRow or serverIdx invalid"); + error = -1; + } + if (error == 0) { + /* Lock row */ + sessRow = &SessionCache[clientSession->serverRow]; + error = SESSION_ROW_LOCK(sessRow); + if (error != 0) { + WOLFSSL_MSG("Session cache row lock failure"); + sessRow = NULL; + } + } + if (error == 0) { + cacheSession = &sessRow->Sessions[clientSession->serverIdx]; + if (cacheSession->sessionIDSz == 0) { + cacheSession = NULL; + WOLFSSL_MSG("Session cache entry not set"); + error = -1; + } + } + if (error == 0) { + /* Calculate the hash of the session ID */ + sessionIDHash = HashSession(cacheSession->sessionID, ID_LEN, + &error); + } + if (error == 0) { + /* Check the session ID hash matches */ + error = clientSession->sessionIDHash != sessionIDHash; + } + if (error == 0) { + /* Hashes match */ + session = cacheSession; + WOLFSSL_MSG("Found session cache matching client session object"); + } + if (sessRow != NULL) { + SESSION_ROW_UNLOCK(sessRow); + } + wc_UnLockMutex(&clisession_mutex); + return (WOLFSSL_SESSION*)session; + } + else { + /* Plain WOLFSSL_SESSION object */ + return (WOLFSSL_SESSION*)session; + } +#else + return (WOLFSSL_SESSION*)session; +#endif +#endif +} + int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, - int* sessionIndex, int side, word16 useTicket) + int* sessionIndex, int side, word16 useTicket, + ClientSession** clientCacheEntry) { WOLFSSL_SESSION* cacheSession = NULL; SessionRow* sessRow = NULL; @@ -15808,6 +15990,9 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, (void)sessionIndex; (void)useTicket; + (void)clientCacheEntry; + + addSession = ClientSessionToSession(addSession); if (addSession == NULL || idSz == 0) { WOLFSSL_MSG("addSession NULL or idSz == 0"); @@ -15841,6 +16026,7 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, #ifdef HAVE_SESSION_TICKET XFREE(ticBuff, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); #endif + WOLFSSL_MSG("Session row lock failed"); return BAD_MUTEX_E; } @@ -15915,9 +16101,12 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, cacheSession = NULL; /* Can't access after unlocked */ #ifndef NO_CLIENT_CACHE - if (ret == 0) - ret = AddSessionToClientCache(side, row, idx, addSession->serverID, - addSession->idLen, useTicket); + if (ret == 0) { + ClientSession* clientCache = AddSessionToClientCache(side, row, idx, + addSession->serverID, addSession->idLen, id, useTicket); + if (clientCache != NULL && clientCacheEntry != NULL) + *clientCacheEntry = clientCache; + } #endif #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) @@ -15933,7 +16122,7 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, #ifndef NO_CLIENT_CACHE #endif -int AddSession(WOLFSSL* ssl) +void AddSession(WOLFSSL* ssl) { int error = 0; const byte* id = NULL; @@ -15943,23 +16132,25 @@ int AddSession(WOLFSSL* ssl) int cbRet = 0; #endif + (void)error; + WOLFSSL_ENTER("AddSession"); if (SslSessionCacheOff(ssl, session)) { WOLFSSL_MSG("Cache off"); - return 0; + return; } if (ssl->options.haveSessionId == 0) { WOLFSSL_MSG("Don't have session id"); - return 0; + return; } #if defined(HAVE_SESSION_TICKET) && !defined(OPENSSL_EXTRA) /* For the compat layer generate a session object to use */ if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) { WOLFSSL_MSG("Using tickets instead of cache"); - return 0; + return; } #endif @@ -16005,13 +16196,33 @@ int AddSession(WOLFSSL* ssl) #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) session->peerVerifyRet = (byte)ssl->peerVerifyRet; #endif + /* Do this last so that if it fails, the rest of the session is setup. Do + * this only for the client because if the server doesn't have an ID at + * this point, it won't on resumption. */ + if (idSz == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { + WC_RNG* rng = NULL; + if (ssl->rng != NULL) + rng = ssl->rng; +#ifdef HAVE_GLOBAL_RNG + else if (initGlobalRNG == 1 || wolfSSL_RAND_Init() == WOLFSSL_SUCCESS) { + rng = &globalRNG; + } +#endif + if (wc_RNG_GenerateBlock(rng, ssl->session->altSessionID, + ID_LEN) != 0) + return; + ssl->session->haveAltSessionID = 1; + id = ssl->session->altSessionID; + idSz = ID_LEN; + } /* Setup done */ #ifdef HAVE_EXT_CACHE if (!ssl->options.internalCacheOff) #endif { - error = AddSessionToCache(session, id, idSz, + /* Try to add the session to cache. Its ok if we don't succeed. */ + (void)AddSessionToCache(session, id, idSz, #ifdef SESSION_INDEX &ssl->sessionIndex, #else @@ -16019,10 +16230,11 @@ int AddSession(WOLFSSL* ssl) #endif ssl->options.side, #ifdef HAVE_SESSION_TICKET - ssl->options.useTicket + ssl->options.useTicket, #else - 0 + 0, #endif + NULL ); } @@ -16049,8 +16261,6 @@ int AddSession(WOLFSSL* ssl) } } #endif /* WOLFSSL_SESSION_STATS && WOLFSSL_PEAK_SESSIONS */ - - return error; } @@ -16071,6 +16281,8 @@ int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex"); + session = ClientSessionToSession(session); + row = idx >> SESSIDX_ROW_SHIFT; col = idx & SESSIDX_IDX_MASK; @@ -16103,6 +16315,8 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + session = ClientSessionToSession(session); + if (session) chain = &session->chain; @@ -16118,6 +16332,7 @@ WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session) { WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + session = ClientSessionToSession(session); if (session) { int count; @@ -16301,6 +16516,11 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, #else /* NO_SESSION_CACHE */ +WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session) +{ + return (WOLFSSL_SESSION*)session; +} + /* No session cache version */ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts) @@ -23745,7 +23965,9 @@ WOLFSSL_SESSION* wolfSSL_SESSION_new(void) * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */ int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) { - if (session == NULL) + session = ClientSessionToSession(session); + + if (session == NULL || session->type != WOLFSSL_SESSION_TYPE_HEAP) return WOLFSSL_FAILURE; #ifndef SINGLE_THREADED @@ -23786,6 +24008,9 @@ int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output, (void)avoidSysCalls; + input = ClientSessionToSession(input); + output = ClientSessionToSession(output); + if (input == NULL || output == NULL || input == output) { WOLFSSL_MSG("input or output are null or same"); return WOLFSSL_FAILURE; @@ -23923,6 +24148,7 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_SESSION_dup"); + session = ClientSessionToSession(session); if (session == NULL) return NULL; @@ -23949,6 +24175,7 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) void wolfSSL_FreeSession(WOLFSSL_SESSION* session) { + session = ClientSessionToSession(session); if (session == NULL) return; @@ -24002,6 +24229,7 @@ void wolfSSL_FreeSession(WOLFSSL_SESSION* session) void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) { + session = ClientSessionToSession(session); wolfSSL_FreeSession(session); } @@ -24014,6 +24242,7 @@ int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_CTX_add_session"); + session = ClientSessionToSession(session); if (session == NULL) return WOLFSSL_FAILURE; @@ -24030,11 +24259,11 @@ int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) error = AddSessionToCache(session, id, idSz, NULL, session->side, #ifdef HAVE_SESSION_TICKET - session->ticketLen > 0 + session->ticketLen > 0, #else - 0 + 0, #endif - ); + NULL); return error == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } @@ -24053,6 +24282,7 @@ int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, { WOLFSSL_ENTER("wolfSSL_SESSION_set_cipher"); + session = ClientSessionToSession(session); /* sanity check */ if (session == NULL || cipher == NULL) { WOLFSSL_MSG("bad argument"); @@ -24202,6 +24432,7 @@ const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher) const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session) { + session = ClientSessionToSession(session); if (session == NULL) { return NULL; } @@ -29760,8 +29991,8 @@ long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) #if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) const unsigned char *SSL_SESSION_get0_id_context(const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length) { - const byte *c = wolfSSL_SESSION_get_id((WOLFSSL_SESSION *)sess, sid_ctx_length); - return c; + sess = ClientSessionToSession(sess); + return wolfSSL_SESSION_get_id((WOLFSSL_SESSION *)sess, sid_ctx_length); } #endif @@ -32352,6 +32583,7 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) WOLFSSL_ENTER("wolfSSL_i2d_SSL_SESSION"); + sess = ClientSessionToSession(sess); if (sess == NULL) { return BAD_FUNC_ARG; } @@ -32530,11 +32762,9 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, if (p == NULL || *p == NULL) return NULL; - if (s == NULL) { - s = wolfSSL_SESSION_new(); - if (s == NULL) - return NULL; - } + s = wolfSSL_SESSION_new(); + if (s == NULL) + return NULL; idx = 0; data = (byte*)*p; @@ -32726,8 +32956,9 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, #endif (void)idx; - if (sess != NULL) + if (sess != NULL) { *sess = s; + } *p += idx; @@ -32749,6 +32980,7 @@ int wolfSSL_SESSION_has_ticket(const WOLFSSL_SESSION* sess) { WOLFSSL_ENTER("wolfSSL_SESSION_has_ticket"); #ifdef HAVE_SESSION_TICKET + sess = ClientSessionToSession(sess); if (sess) { if ((sess->ticketLen > 0) && (sess->ticket != NULL)) { return WOLFSSL_SUCCESS; @@ -32764,6 +32996,7 @@ unsigned long wolfSSL_SESSION_get_ticket_lifetime_hint( const WOLFSSL_SESSION* sess) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ticket_lifetime_hint"); + sess = ClientSessionToSession(sess); if (sess) { return sess->timeout; } @@ -32774,6 +33007,7 @@ long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) { long timeout = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); + sess = ClientSessionToSession(sess); if (sess) timeout = sess->timeout; return timeout; @@ -32784,6 +33018,7 @@ long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) { long bornOn = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); + sess = ClientSessionToSession(sess); if (sess) bornOn = sess->bornOn; return bornOn; @@ -32793,6 +33028,7 @@ long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) { word32 tmptime; + ses = ClientSessionToSession(ses); if (ses == NULL || t < 0) { return BAD_FUNC_ARG; } @@ -40544,9 +40780,6 @@ int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) } /* End ECDSA_SIG */ -/* Remove this prototype when code is reorganized. */ -static int wolfSSL_RAND_Init(void); - /* Start ECDH */ /* return code compliant with OpenSSL : * length of computed key if success, -1 if error @@ -42953,6 +43186,7 @@ WOLFSSL_ABI const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session) { WOLFSSL_ENTER("wolfSSL_get_sessionID"); + session = ClientSessionToSession(session); if (session) return session->sessionID; @@ -48550,6 +48784,7 @@ int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) int ret = WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); #ifdef HAVE_EX_DATA + session = ClientSessionToSession(session); if (session != NULL) ret = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data); #else @@ -48568,6 +48803,7 @@ int wolfSSL_SESSION_set_ex_data_with_cleanup( wolfSSL_ex_data_cleanup_routine_t cleanup_routine) { WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data_with_cleanup"); + session = ClientSessionToSession(session); if(session != NULL) { return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&session->ex_data, idx, data, cleanup_routine); @@ -48580,6 +48816,7 @@ void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); #ifdef HAVE_EX_DATA + session = ClientSessionToSession(session); if (session != NULL) { return wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx); } @@ -49596,6 +49833,7 @@ const byte* wolfSSL_SESSION_get_id(const WOLFSSL_SESSION* sess, unsigned int* idLen) { WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); + sess = ClientSessionToSession(sess); if (sess == NULL || idLen == NULL) { WOLFSSL_MSG("Bad func args. Please provide idLen"); return NULL; @@ -49614,6 +49852,7 @@ const byte* wolfSSL_SESSION_get_id(const WOLFSSL_SESSION* sess, /* returns a pointer to the protocol used by the session */ static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in) { + in = ClientSessionToSession(in); return wolfSSL_internal_get_version((ProtocolVersion*)&in->version); } #endif @@ -49621,6 +49860,7 @@ static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in) /* returns true (non 0) if the session has EMS (extended master secret) */ static int wolfSSL_SESSION_haveEMS(const WOLFSSL_SESSION* in) { + in = ClientSessionToSession(in); if (in == NULL) return 0; return in->haveEMS; @@ -49638,6 +49878,7 @@ static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio, byte* pt; + in = ClientSessionToSession(in); if (in == NULL || bio == NULL) { return BAD_FUNC_ARG; } @@ -49709,6 +49950,7 @@ int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *session) unsigned int sz = 0, i; int ret; + session = ClientSessionToSession(session); if (session == NULL) { return WOLFSSL_FAILURE; } @@ -51129,6 +51371,7 @@ int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s) { WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session"); + s = ClientSessionToSession(s); if (ctx == NULL || s == NULL) return BAD_FUNC_ARG; @@ -51237,7 +51480,7 @@ WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) { WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); - return wolfSSL_get_session((WOLFSSL*)ssl); + return ssl->session; } #endif /* NO_SESSION_CACHE */ @@ -57569,6 +57812,7 @@ int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx) */ int wolfSSL_SESSION_is_resumable(const WOLFSSL_SESSION *s) { + s = ClientSessionToSession(s); if (s == NULL) return 0; @@ -60743,7 +60987,7 @@ static int wolfSSL_RAND_InitMutex(void) * * Returns WOLFSSL_SUCCESS when no error is encountered. */ -static int wolfSSL_RAND_Init(void) +int wolfSSL_RAND_Init(void) { int ret = WOLFSSL_FAILURE; #ifdef HAVE_GLOBAL_RNG diff --git a/src/tls13.c b/src/tls13.c index 94bf2debf6..a9571415b0 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3255,7 +3255,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) #endif ret = SendBuffered(ssl); - break; + break; } default: ret = INPUT_CASE_ERROR; diff --git a/tests/api.c b/tests/api.c index e47cf6352b..e6db580d19 100644 --- a/tests/api.c +++ b/tests/api.c @@ -6255,7 +6255,17 @@ static void test_wolfSSL_CTX_add_session_on_result(WOLFSSL* ssl) else sess = &test_wolfSSL_CTX_add_session_client_sess; if (*sess == NULL) { +#ifdef NO_SESSION_CACHE_REF AssertNotNull(*sess = wolfSSL_get1_session(ssl)); +#else + /* Test for backwards compatibility */ + if (wolfSSL_is_server(ssl)) { + AssertNotNull(*sess = wolfSSL_get1_session(ssl)); + } + else { + AssertNotNull(*sess = wolfSSL_get_session(ssl)); + } +#endif /* Now save the session in the internal store to make it available * for lookup. For TLS 1.3, we can't save the session without * WOLFSSL_TICKET_HAVE_ID because there is no way to retrieve the @@ -6294,6 +6304,8 @@ static void test_wolfSSL_CTX_add_session_on_result(WOLFSSL* ssl) WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); AssertNotNull(peer); wolfSSL_X509_free(peer); + AssertNotNull(wolfSSL_SESSION_get_peer_chain(*sess)); + AssertNotNull(wolfSSL_SESSION_get0_peer(*sess)); } #endif } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 41df10959a..56a501126a 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1682,6 +1682,8 @@ typedef WOLFSSL_BUFFER_INFO buffer; typedef struct Suites Suites; +/* Declare opaque struct for API to use */ +typedef struct ClientSession ClientSession; /* defaults to client */ WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv); @@ -3296,12 +3298,6 @@ struct WOLFSSL_X509_CHAIN { x509_buffer certs[MAX_CHAIN_DEPTH]; /* only allow max depth 4 for now */ }; -#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_SESSION_CACHE_REF) - /* enable allocation of a smaller reference for the internal cache, - * to prevent client from using internal cache reference. */ - #define ENABLE_CLIENT_SESSION_REF -#endif - typedef enum WOLFSSL_SESSION_TYPE { WOLFSSL_SESSION_TYPE_UNKNOWN, WOLFSSL_SESSION_TYPE_SSL, /* in ssl->session */ @@ -3409,12 +3405,23 @@ struct WOLFSSL_SESSION { #endif }; +WOLFSSL_LOCAL int wolfSSL_RAND_Init(void); WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_NewSession(void* heap); WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_GetSession( WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts); +WOLFSSL_LOCAL void AddSession(WOLFSSL* ssl); +WOLFSSL_LOCAL int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, + byte idSz, int* sessionIndex, int side, word16 useTicket, + ClientSession** clientCacheEntry); +#ifndef NO_CLIENT_CACHE +WOLFSSL_LOCAL ClientSession* AddSessionToClientCache(int side, int row, int idx, + byte* serverID, word16 idLen, const byte* sessionID, + word16 useTicket); +#endif +WOLFSSL_LOCAL +WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session); WOLFSSL_LOCAL int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output); -WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_GetSessionRef(WOLFSSL* ssl); WOLFSSL_LOCAL int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session); WOLFSSL_LOCAL void wolfSSL_FreeSession(WOLFSSL_SESSION* session); WOLFSSL_LOCAL int wolfSSL_DupSession(const WOLFSSL_SESSION* input, @@ -4244,6 +4251,9 @@ struct WOLFSSL { Ciphers decrypt; Buffers buffers; WOLFSSL_SESSION* session; +#ifndef NO_CLIENT_CACHE + ClientSession* clientSession; +#endif WOLFSSL_ALERT_HISTORY alert_history; int error; int rfd; /* read file descriptor */ @@ -4767,11 +4777,6 @@ WOLFSSL_LOCAL const char* AlertTypeToString(int type); WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL* ssl); WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL* ssl); -WOLFSSL_LOCAL int AddSession(WOLFSSL* ssl); -WOLFSSL_LOCAL int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, - byte idSz, int* sessionIndex, int side, word16 useTicket); -WOLFSSL_LOCAL int AddSessionToClientCache(int side, int row, int idx, - byte* serverID, word16 idLen, word16 useTicket); WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side); From 617eda9d449a3755e9791ae8a8ce26ff43a7304b Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 14 Feb 2022 19:13:08 +0100 Subject: [PATCH 6/9] Fix misc memory issues - Make `InternalTicket` memory alignment independent --- configure.ac | 2 +- src/internal.c | 86 ++++++++++++++++++++-------------------------- src/ssl.c | 27 +++++++++++---- wolfssl/internal.h | 8 +++++ 4 files changed, 68 insertions(+), 55 deletions(-) diff --git a/configure.ac b/configure.ac index b7d5e9cb52..38d9539829 100644 --- a/configure.ac +++ b/configure.ac @@ -6829,7 +6829,7 @@ AS_CASE(["$CFLAGS $CPPFLAGS $AM_CFLAGS"],[*'OPENSSL_COMPATIBLE_DEFAULTS'*], [ENABLED_OPENSSL_COMPATIBLE_DEFAULTS=yes]) if test "x$ENABLED_OPENSSL_COMPATIBLE_DEFAULTS" = "xyes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRUST_PEER_CERT -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRUST_PEER_CERT" AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE_REF" ENABLED_TRUSTED_PEER_CERT=yes fi diff --git a/src/internal.c b/src/internal.c index ba8291d769..327ce501b5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -20206,12 +20206,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case SIDE_ERROR : return "wrong client/server type"; - case NO_PEER_CERT : -#ifndef OPENSSL_EXTRA - return "peer didn't send cert"; -#else + case NO_PEER_CERT : /* OpenSSL compatibility expects this exact text */ return "peer did not return a certificate"; -#endif case UNKNOWN_HANDSHAKE_TYPE : return "weird handshake type"; @@ -20525,12 +20521,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case MISSING_HANDSHAKE_DATA: return "The handshake message is missing required data"; - case BAD_BINDER: -#ifndef OPENSSL_EXTRA - return "Binder value does not match value server calculated"; -#else + case BAD_BINDER: /* OpenSSL compatibility expects this exact text */ return "binder does not verify"; -#endif case EXT_NOT_ALLOWED: return "Extension type not allowed in handshake message type"; @@ -29955,15 +29947,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif #endif - ret = MatchSuite(ssl, &clSuites); #ifdef OPENSSL_EXTRA /* Give user last chance to provide a cert for cipher selection */ - if (ret == 0) - ret = CertSetupCbWrapper(ssl); - /* Call again in case user changes affect cipher selection */ if (ret == 0 && ssl->ctx->certSetupCb != NULL) - ret = MatchSuite(ssl, &clSuites); + ret = CertSetupCbWrapper(ssl); #endif + if (ret == 0) + ret = MatchSuite(ssl, &clSuites); #ifdef WOLFSSL_EXTRA_ALERTS if (ret == BUFFER_ERROR) @@ -30504,19 +30494,21 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_TICKET_IV_SZ + WOLFSSL_TICKET_MAC_SZ + LENGTH_SZ) #define WOLFSSL_TICKET_ENC_SZ (SESSION_TICKET_LEN - WOLFSSL_TICKET_FIXED_SZ) - /* our ticket format */ + /* Our ticket format. All members need to be a byte or array of byte to + * avoid alignment issues */ typedef struct InternalTicket { ProtocolVersion pv; /* version when ticket created */ byte suite[SUITE_LEN]; /* cipher suite when created */ byte msecret[SECRET_LEN]; /* master secret */ - word32 timestamp; /* born on */ - word16 haveEMS; /* have extended master secret */ + byte timestamp[TIMESTAMP_LEN]; /* born on */ + byte haveEMS; /* have extended master secret */ #ifdef WOLFSSL_TLS13 - word32 ageAdd; /* Obfuscation of age */ - word16 namedGroup; /* Named group used */ + byte ageAdd[AGEADD_LEN]; /* Obfuscation of age */ + byte namedGroup[NAMEDGREOUP_LEN]; /* Named group used */ TicketNonce ticketNonce; /* Ticket nonce */ #ifdef WOLFSSL_EARLY_DATA - word32 maxEarlyDataSz; /* Max size of early data */ + byte maxEarlyDataSz[MAXEARLYDATASZ_LEN]; /* Max size of + * early data */ #endif #endif #ifdef WOLFSSL_TICKET_HAVE_ID @@ -30581,7 +30573,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, it.suite[1] = ssl->options.cipherSuite; #ifdef WOLFSSL_EARLY_DATA - it.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + c32toa(ssl->options.maxEarlyDataSz, it.maxEarlyDataSz); #endif if (!ssl->options.tls1_3) { @@ -30598,9 +30590,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, sizeof(it.ageAdd)); if (ret != 0) return BAD_TICKET_ENCRYPT; - ssl->session->ticketAdd = it.ageAdd; - it.namedGroup = ssl->session->namedGroup; - it.timestamp = TimeNowInMilliseconds(); + ato32(it.ageAdd, &ssl->session->ticketAdd); + c16toa(ssl->session->namedGroup, it.namedGroup); + c32toa(TimeNowInMilliseconds(), it.timestamp); /* Resumption master secret. */ XMEMCPY(it.msecret, ssl->session->masterSecret, SECRET_LEN); XMEMCPY(&it.ticketNonce, &ssl->session->ticketNonce, @@ -30721,7 +30713,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len) { ExternalTicket* et; - InternalTicket it; + InternalTicket* it; int ret; int outLen; word16 inLen; @@ -30767,19 +30759,17 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return BAD_TICKET_KEY_CB_SZ; } - /* copy the decrypted ticket to avoid alignment issues */ - XMEMCPY(&it, et->enc_ticket, sizeof(InternalTicket)); - ForceZero(et->enc_ticket, sizeof(it)); + it = (InternalTicket*)et->enc_ticket; /* get master secret */ if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { - if (ssl->version.minor < it.pv.minor) { + if (ssl->version.minor < it->pv.minor) { ForceZero(&it, sizeof(it)); WOLFSSL_MSG("Ticket has greater version"); return VERSION_ERROR; } - else if (ssl->version.minor > it.pv.minor) { - if (IsAtLeastTLSv1_3(it.pv) != IsAtLeastTLSv1_3(ssl->version)) { + else if (ssl->version.minor > it->pv.minor) { + if (IsAtLeastTLSv1_3(it->pv) != IsAtLeastTLSv1_3(ssl->version)) { ForceZero(&it, sizeof(it)); WOLFSSL_MSG("Tickets cannot be shared between " "TLS 1.3 and TLS 1.2 and lower"); @@ -30794,17 +30784,17 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Downgrading protocol due to ticket"); - if (it.pv.minor < ssl->options.minDowngrade) { + if (it->pv.minor < ssl->options.minDowngrade) { ForceZero(&it, sizeof(it)); return VERSION_ERROR; } - ssl->version.minor = it.pv.minor; + ssl->version.minor = it->pv.minor; } #ifdef WOLFSSL_TICKET_HAVE_ID { ssl->session->haveAltSessionID = 1; - XMEMCPY(ssl->session->altSessionID, it.id, ID_LEN); + XMEMCPY(ssl->session->altSessionID, it->id, ID_LEN); if (wolfSSL_GetSession(ssl, NULL, 1) != NULL) { WOLFSSL_MSG("Found session matching the session id" " found in the ticket"); @@ -30817,31 +30807,31 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif if (!IsAtLeastTLSv1_3(ssl->version)) { - XMEMCPY(ssl->arrays->masterSecret, it.msecret, SECRET_LEN); + XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); /* Copy the haveExtendedMasterSecret property from the ticket to * the saved session, so the property may be checked later. */ - ssl->session->haveEMS = it.haveEMS; - ato32((const byte*)&it.timestamp, &ssl->session->bornOn); + ssl->session->haveEMS = it->haveEMS; + ato32((const byte*)&it->timestamp, &ssl->session->bornOn); #ifndef NO_RESUME_SUITE_CHECK - ssl->session->cipherSuite0 = it.suite[0]; - ssl->session->cipherSuite = it.suite[1]; + ssl->session->cipherSuite0 = it->suite[0]; + ssl->session->cipherSuite = it->suite[1]; #endif } else { #ifdef WOLFSSL_TLS13 /* Restore information to renegotiate. */ - ssl->session->ticketSeen = it.timestamp; - ssl->session->ticketAdd = it.ageAdd; - ssl->session->cipherSuite0 = it.suite[0]; - ssl->session->cipherSuite = it.suite[1]; + ato32(it->timestamp, &ssl->session->ticketSeen); + ato32(it->ageAdd, &ssl->session->ticketAdd); + ssl->session->cipherSuite0 = it->suite[0]; + ssl->session->cipherSuite = it->suite[1]; #ifdef WOLFSSL_EARLY_DATA - ssl->session->maxEarlyDataSz = it.maxEarlyDataSz; + ato32(it->maxEarlyDataSz, &ssl->session->maxEarlyDataSz); #endif /* Resumption master secret. */ - XMEMCPY(ssl->session->masterSecret, it.msecret, SECRET_LEN); - XMEMCPY(&ssl->session->ticketNonce, &it.ticketNonce, + XMEMCPY(ssl->session->masterSecret, it->msecret, SECRET_LEN); + XMEMCPY(&ssl->session->ticketNonce, &it->ticketNonce, sizeof(TicketNonce)); - ssl->session->namedGroup = it.namedGroup; + ato16(it->namedGroup, &ssl->session->namedGroup); #endif } } diff --git a/src/ssl.c b/src/ssl.c index 40eadf10d1..ebe0b3ac82 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -15980,6 +15980,8 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, WOLFSSL_X509* peer = NULL; #endif #ifdef HAVE_SESSION_TICKET + byte* cacheTicBuff = NULL; + byte ticBuffUsed = 0; byte* ticBuff = NULL; int ticLen = 0; #endif @@ -16004,7 +16006,7 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, ticLen = addSession->ticketLen; /* Alloc Memory here to avoid syscalls during lock */ if (ticLen > SESSION_TICKET_LEN) { - ticBuff = (byte*)XMALLOC(ticLen, addSession->heap, + ticBuff = (byte*)XMALLOC(ticLen, NULL, DYNAMIC_TYPE_SESSION_TICK); if (ticBuff == NULL) { return MEMORY_E; @@ -16016,7 +16018,7 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, if (ret != 0) { WOLFSSL_MSG("Hash session failed"); #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); #endif return ret; } @@ -16024,7 +16026,7 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, sessRow = &SessionCache[row]; if (SESSION_ROW_LOCK(sessRow) != 0) { #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); #endif WOLFSSL_MSG("Session row lock failed"); return BAD_MUTEX_E; @@ -16058,7 +16060,12 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, cacheSession->peer = NULL; #endif #ifdef HAVE_SESSION_TICKET - if (ticBuff != NULL) { + /* If we can re-use the existing buffer in cacheSession then we won't touch + * ticBuff at all making it a very cheap malloc/free. The page on a modern + * OS will most likely not even be allocated to the process. */ + if (ticBuff != NULL && cacheSession->ticketLenAlloc < ticLen) { + cacheTicBuff = cacheSession->ticket; + ticBuffUsed = 1; cacheSession->ticket = ticBuff; cacheSession->ticketLenAlloc = ticLen; } @@ -16073,6 +16080,7 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, sizeof(x509_buffer) * cacheSession->chain.count); } #endif /* SESSION_CERTS */ + cacheSession->heap = NULL; /* Copy data into the cache object */ ret = wolfSSL_DupSession(addSession, cacheSession, 1) == WOLFSSL_FAILURE; @@ -16089,7 +16097,7 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, } } #ifdef HAVE_SESSION_TICKET - else if (ticBuff != NULL) { + else if (ticBuffUsed) { /* Error occured. Need to clean up the ticket buffer. */ cacheSession->ticket = cacheSession->_staticTicket; cacheSession->ticketLenAlloc = 0; @@ -16109,6 +16117,13 @@ int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, } #endif +#ifdef HAVE_SESSION_TICKET + if (ticBuff != NULL && !ticBuffUsed) + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); + if (cacheTicBuff != NULL) + XFREE(cacheTicBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); +#endif + #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) if (peer != NULL) { wolfSSL_X509_free(peer); @@ -16203,7 +16218,7 @@ void AddSession(WOLFSSL* ssl) WC_RNG* rng = NULL; if (ssl->rng != NULL) rng = ssl->rng; -#ifdef HAVE_GLOBAL_RNG +#if defined(HAVE_GLOBAL_RNG) && defined(OPENSSL_EXTRA) else if (initGlobalRNG == 1 || wolfSSL_RAND_Init() == WOLFSSL_SUCCESS) { rng = &globalRNG; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 56a501126a..fa0b911f63 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1185,6 +1185,14 @@ enum Misc { HELLO_EXT_EXTMS = 0x0017, /* ID for the extended master secret ext */ SECRET_LEN = WOLFSSL_MAX_MASTER_KEY_LENGTH, /* pre RSA and all master */ + TIMESTAMP_LEN = 4, /* timestamp size in ticket */ +#ifdef WOLFSSL_TLS13 + AGEADD_LEN = 4, /* ageAdd size in ticket */ + NAMEDGREOUP_LEN = 2, /* namedGroup size in ticket */ +#ifdef WOLFSSL_EARLY_DATA + MAXEARLYDATASZ_LEN = 4, /* maxEarlyDataSz size in ticket */ +#endif +#endif #ifdef HAVE_PQC ENCRYPT_LEN = 1500, /* allow 1500 bit static buffer for falcon */ #else From d1f53055e9c44c91075f2b8bf71001c12be00912 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 17 Feb 2022 15:08:08 +0100 Subject: [PATCH 7/9] Peeking can't return a `WOLFSSL_ERROR_WANT_READ` in compatibility mode --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 38d9539829..a69d5a6ce6 100644 --- a/configure.ac +++ b/configure.ac @@ -6831,6 +6831,7 @@ if test "x$ENABLED_OPENSSL_COMPATIBLE_DEFAULTS" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRUST_PEER_CERT" AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE_REF" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" ENABLED_TRUSTED_PEER_CERT=yes fi From fb943a2f238a1a7c660afadc8158fa771b5e49df Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 23 Feb 2022 09:55:52 +0100 Subject: [PATCH 8/9] Rebase and make `wolfSSL_CTX_up_ref` always available `wolfSSL_CTX_up_ref` is a small and potentially useful API for users so it doesn't need to be restricted only to the compatibility layer. The reference counting mechanisms are always available anyway. This just exposes the functionality to the user. --- src/ssl.c | 2 -- wolfssl/ssl.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index ebe0b3ac82..1df33d6476 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -547,14 +547,12 @@ WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method) #endif } -#ifdef OPENSSL_EXTRA /* increases CTX reference count to track proper time to "free" */ int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx) { int refCount = SSL_CTX_RefCount(ctx, 1); return ((refCount > 1) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE); } -#endif WOLFSSL_ABI void wolfSSL_CTX_free(WOLFSSL_CTX* ctx) diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index e78a2134ba..ae33938338 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -999,8 +999,8 @@ WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file( WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap); WOLFSSL_ABI WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method); -#ifdef OPENSSL_EXTRA WOLFSSL_API int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx); +#ifdef OPENSSL_EXTRA WOLFSSL_API int wolfSSL_CTX_set_ecdh_auto(WOLFSSL_CTX* ctx, int onoff); WOLFSSL_API int wolfSSL_get_signature_nid(WOLFSSL* ssl, int* nid); WOLFSSL_API int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, From 2c978a96b2b6fcd1e8df9f1006b68afdb75ee406 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 23 Feb 2022 10:07:21 +0100 Subject: [PATCH 9/9] Prevent possibility of an infinite retry loop and resource exhaution Reported in ZD13606 --- src/internal.c | 7 +++++-- wolfssl/ssl.h | 8 +++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/internal.c b/src/internal.c index 327ce501b5..31a051ce76 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8949,6 +8949,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz, static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) { int recvd; + int retryLimit = WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS; if (ssl->CBIORecv == NULL) { WOLFSSL_MSG("Your IO Recv callback is null, please set"); @@ -8974,9 +8975,11 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) return -1; case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */ - if (ssl->ctx->autoRetry && !ssl->options.handShakeDone && - !ssl->options.dtls) + if (retryLimit > 0 && ssl->ctx->autoRetry && + !ssl->options.handShakeDone && !ssl->options.dtls) { + retryLimit--; goto retry; + } return WANT_READ; case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index ae33938338..5070b6b137 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -810,6 +810,9 @@ enum Tls13Secret { }; #endif +#ifndef WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS +#define WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS 10 +#endif typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap); @@ -2196,7 +2199,10 @@ enum { SSL_MODE_ENABLE_PARTIAL_WRITE = 2, SSL_MODE_AUTO_RETRY = 3, /* wolfSSL default is to return WANT_{READ|WRITE} * to the user. This is set by default with - * OPENSSL_COMPATIBLE_DEFAULTS. */ + * OPENSSL_COMPATIBLE_DEFAULTS. The macro + * WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS is used to + * limit the possibility of an infinite retry loop + */ SSL_MODE_RELEASE_BUFFERS = -1, /* For libwebsockets build. No current use. */ BIO_CLOSE = 1,