diff --git a/configure.ac b/configure.ac index 92d9f4c32..1504afda1 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 0fba90d6c..c45318410 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 @@ retry: 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 e22f1130f..ffc0b03f8 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)) - return 0; + WOLFSSL_ENTER("AddSession"); - if (ssl->options.haveSessionId == 0) + if (SslSessionCacheOff(ssl, &ssl->session)) { + WOLFSSL_MSG("Cache off"); return 0; + } -#ifdef HAVE_SESSION_TICKET - if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) + if (ssl->options.haveSessionId == 0) { + WOLFSSL_MSG("Don't have session id"); return 0; + } + +#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 @@ cleanup: 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 @@ cleanup: 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->masterSecret = copy->_masterSecret; - #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; - } + copy->cacheRow = INVALID_SESSION_ROW; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + copy->peer = wolfSSL_X509_dup(session->peer); #endif - copy->refCount = 1; + 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 (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 */ +#endif } - ref = session; - session = (WOLFSSL_SESSION*)session->refPtr; - XFREE(ref, ref->heap, DYNAMIC_TYPE_SESSION); +#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 -#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 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 @@ err: } 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) { + if (mem != NULL) { + localPkcs12 = wc_PKCS12_new(); + if (localPkcs12 == NULL) { + WOLFSSL_MSG("Memory error"); + } + } + + 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"); + } + } + + /* cleanup */ + if (mem != NULL) + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0 && localPkcs12 != NULL) { + wc_PKCS12_free(localPkcs12); + localPkcs12 = NULL; + } + if (pkcs12 != NULL) *pkcs12 = localPkcs12; - } - - 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; - } - return NULL; - } - size = ret; - - ret = wc_d2i_PKCS12(mem, size, localPkcs12); - if (ret < 0) { - WOLFSSL_MSG("Failed to get PKCS12 sequence"); - wc_PKCS12_free(localPkcs12); - if (pkcs12 != NULL) { - *pkcs12 = NULL; - } - return NULL; - } return localPkcs12; } diff --git a/src/tls13.c b/src/tls13.c index de194bcde..20b9dafc9 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 bfeb66441..17a561ad5 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 @@ done: 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 c8df70416..9cc242d65 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 d690e3b86..57de940ab 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 05d8e262c..80e1d302d 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,28 +3365,11 @@ 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 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 - * these buffers directly */ - byte _masterSecret[SECRET_LEN]; -#ifndef NO_CLIENT_CACHE - byte _serverID[SERVER_ID_LEN]; -#endif -#ifdef HAVE_SESSION_TICKET - byte _staticTicket[SESSION_TICKET_LEN]; -#endif -#ifdef OPENSSL_EXTRA - byte _sessionCtx[ID_LEN]; -#endif - #ifdef SESSION_CERTS WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ #ifdef WOLFSSL_ALT_CERT_CHAINS @@ -3395,10 +3379,26 @@ struct WOLFSSL_SESSION { #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; +#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 + * 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]; +#endif +#ifdef HAVE_SESSION_TICKET + byte _staticTicket[SESSION_TICKET_LEN]; +#endif #ifdef OPENSSL_EXTRA - #ifndef SINGLE_THREADED - wolfSSL_Mutex refMutex; /* ref count mutex */ - #endif + byte _sessionCtx[ID_LEN]; #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 8628685cf..80289e024 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 164964bdf..47329c03d 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 37ec8a877..552f8c7ac 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 7227e2261..34ec8ff7a 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 25fd42233..646e23175 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 4014f25ae..b81009b67 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);