From afca455cda81f1b03998b24a369373f2d6531c69 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 28 Jan 2022 14:40:45 +0100 Subject: [PATCH] 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 | 1031 ++++++++++++++++++++++++------------ src/tls13.c | 6 +- tests/api.c | 246 ++++++++- tests/test-trustpeer.conf | 14 + wolfcrypt/src/error.c | 4 + wolfssl/internal.h | 76 ++- 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, 1096 insertions(+), 428 deletions(-) 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);