diff --git a/configure.ac b/configure.ac index 92d9f4c324..a69d5a6ce6 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,16 @@ 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" + AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE_REF" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" + 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 +7116,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/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index 59bc6ae7b6..6f0ec59940 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -11166,7 +11166,7 @@ WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx); if(wolfSSL_get_SessionTicket(ssl, buf, bufSz) <= 0){ // Nothing was written to the buffer } else { - // the buffer holds the content from ssl->session.ticket + // the buffer holds the content from ssl->session->ticket } \endcode diff --git a/examples/server/server.c b/examples/server/server.c index 535fbf7f8a..64e30f4e8e 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -802,7 +802,7 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, /* 4. add the same message into Japanese section */ /* (will be translated later) */ /* 5. add printf() into suitable position of Usage() */ -static const char* server_usage_msg[][60] = { +static const char* server_usage_msg[][63] = { /* English */ { " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ diff --git a/src/internal.c b/src/internal.c index 0fba90d6ce..31a051ce76 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; @@ -6627,16 +6629,14 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) } #endif /*OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ - ssl->session.masterSecret = ssl->session._masterSecret; -#ifndef NO_CLIENT_CACHE - ssl->session.serverID = ssl->session._serverID; -#endif -#ifdef OPENSSL_EXTRA - ssl->session.sessionCtx = ssl->session._sessionCtx; -#endif + ssl->session = wolfSSL_NewSession(ssl->heap); + if (ssl->session == NULL) { + WOLFSSL_MSG("SSL Session Memory error"); + return MEMORY_E; + } + #ifdef HAVE_SESSION_TICKET ssl->options.noTicketTls12 = ctx->noTicketTls12; - ssl->session.ticket = ssl->session._staticTicket; #endif #ifdef WOLFSSL_MULTICAST @@ -6683,10 +6683,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) void FreeArrays(WOLFSSL* ssl, int keep) { if (ssl->arrays) { - if (keep) { + if (keep && !IsAtLeastTLSv1_3(ssl->version)) { /* keeps session id for user retrieval */ - XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); - ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; + XMEMCPY(ssl->session->sessionID, ssl->arrays->sessionID, ID_LEN); + ssl->session->sessionIDSz = ssl->arrays->sessionIDSz; } if (ssl->arrays->preMasterSecret) { XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET); @@ -7014,6 +7014,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 @@ -7213,17 +7220,8 @@ void SSL_ResourceFree(WOLFSSL* ssl) FreeX509(&ssl->peerCert); #endif -#ifdef HAVE_SESSION_TICKET - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; - ssl->session.ticketLen = 0; - } -#endif -#ifdef HAVE_EXT_CACHE - wolfSSL_SESSION_free(ssl->extSession); -#endif + if (ssl->session != NULL) + wolfSSL_FreeSession(ssl->session); #ifdef HAVE_WRITE_DUP if (ssl->dupWrite) { FreeWriteDup(ssl); @@ -7490,15 +7488,6 @@ void FreeHandshakeResources(WOLFSSL* ssl) } #endif /* HAVE_PK_CALLBACKS */ -#ifdef HAVE_SESSION_TICKET - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; - ssl->session.ticketLen = 0; - } -#endif - #if defined(HAVE_TLS_EXTENSIONS) && !defined(HAVE_SNI) && \ !defined(HAVE_ALPN) && !defined(WOLFSSL_POST_HANDSHAKE_AUTH) /* Some extensions need to be kept for post-handshake querying. */ @@ -8960,6 +8949,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz, static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) { int recvd; + int retryLimit = WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS; if (ssl->CBIORecv == NULL) { WOLFSSL_MSG("Your IO Recv callback is null, please set"); @@ -8985,8 +8975,11 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) return -1; case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */ - if (ssl->ctx->autoRetry) + if (retryLimit > 0 && ssl->ctx->autoRetry && + !ssl->options.handShakeDone && !ssl->options.dtls) { + retryLimit--; goto retry; + } return WANT_READ; case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */ @@ -11358,7 +11351,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, } #endif #ifdef SESSION_CERTS - store->sesChain = &ssl->session.chain; + store->sesChain = &ssl->session->chain; #endif } #ifndef NO_WOLFSSL_CM_VERIFY @@ -11428,9 +11421,9 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, #ifdef SESSION_CERTS if ((ssl != NULL) && (store->discardSessionCerts)) { WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session.chain.count = 0; + ssl->session->chain.count = 0; #ifdef WOLFSSL_ALT_CERT_CHAINS - ssl->session.altChain.count = 0; + ssl->session->altChain.count = 0; #endif } #endif /* SESSION_CERTS */ @@ -12072,7 +12065,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, args->certs[args->totalCerts].buffer = input + args->idx; #ifdef SESSION_CERTS - AddSessionCertToChain(&ssl->session.chain, + AddSessionCertToChain(&ssl->session->chain, input + args->idx, certSz); #endif /* SESSION_CERTS */ @@ -12157,7 +12150,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 +12166,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)) { @@ -12372,7 +12360,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS) /* if using alternate chain, store the cert used */ if (ssl->options.usingAltCertChain) { - AddSessionCertToChain(&ssl->session.altChain, + AddSessionCertToChain(&ssl->session->altChain, cert->buffer, cert->length); } #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ @@ -12468,7 +12456,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* if using alternate chain, store the cert used */ if (ssl->options.usingAltCertChain) { buffer* cert = &args->certs[args->certIdx]; - AddSessionCertToChain(&ssl->session.altChain, + AddSessionCertToChain(&ssl->session->altChain, cert->buffer, cert->length); } #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ @@ -12514,13 +12502,18 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_MSG("Failed to verify Peer's cert"); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) if (ssl->peerVerifyRet == 0) { /* Return first cert error here */ - if (ret == ASN_BEFORE_DATE_E) - ssl->peerVerifyRet = X509_V_ERR_CERT_NOT_YET_VALID; - else if (ret == ASN_AFTER_DATE_E) - ssl->peerVerifyRet = X509_V_ERR_CERT_HAS_EXPIRED; + if (ret == ASN_BEFORE_DATE_E) { + ssl->peerVerifyRet = + (unsigned long)X509_V_ERR_CERT_NOT_YET_VALID; + } + else if (ret == ASN_AFTER_DATE_E) { + ssl->peerVerifyRet = + (unsigned long)X509_V_ERR_CERT_HAS_EXPIRED; + } else { ssl->peerVerifyRet = - X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + (unsigned long) + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; } } #endif @@ -13265,9 +13258,9 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef SESSION_CERTS /* Reset the session cert chain count in case the session resume failed. */ - ssl->session.chain.count = 0; + ssl->session->chain.count = 0; #ifdef WOLFSSL_ALT_CERT_CHAINS - ssl->session.altChain.count = 0; + ssl->session->altChain.count = 0; #endif #endif /* SESSION_CERTS */ @@ -18874,8 +18867,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 @@ -20214,8 +20209,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case SIDE_ERROR : return "wrong client/server type"; - case NO_PEER_CERT : - return "peer didn't send cert"; + case NO_PEER_CERT : /* OpenSSL compatibility expects this exact text */ + return "peer did not return a certificate"; case UNKNOWN_HANDSHAKE_TYPE : return "weird handshake type"; @@ -20529,8 +20524,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case MISSING_HANDSHAKE_DATA: return "The handshake message is missing required data"; - case BAD_BINDER: - return "Binder value does not match value server calculated"; + case BAD_BINDER: /* OpenSSL compatibility expects this exact text */ + return "binder does not verify"; case EXT_NOT_ALLOWED: return "Extension type not allowed in handshake message type"; @@ -22745,7 +22740,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) return BAD_FUNC_ARG; } - idSz = ssl->options.resuming ? ssl->session.sessionIDSz : 0; + idSz = ssl->options.resuming ? ssl->session->sessionIDSz : 0; #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version)) @@ -22761,11 +22756,11 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } #ifdef HAVE_SESSION_TICKET - if (ssl->options.resuming && ssl->session.ticketLen > 0) { + if (ssl->options.resuming && ssl->session->ticketLen > 0) { SessionTicket* ticket; - ticket = TLSX_SessionTicket_Create(0, ssl->session.ticket, - ssl->session.ticketLen, ssl->heap); + ticket = TLSX_SessionTicket_Create(0, ssl->session->ticket, + ssl->session->ticketLen, ssl->heap); if (ticket == NULL) return MEMORY_E; ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap); @@ -22854,9 +22849,9 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) /* then session id */ output[idx++] = (byte)idSz; if (idSz) { - XMEMCPY(output + idx, ssl->session.sessionID, - ssl->session.sessionIDSz); - idx += ssl->session.sessionIDSz; + XMEMCPY(output + idx, ssl->session->sessionID, + ssl->session->sessionIDSz); + idx += ssl->session->sessionIDSz; } /* then DTLS cookie */ @@ -23053,12 +23048,12 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) #ifdef HAVE_SESSION_TICKET /* server may send blank ticket which may not be expected to indicate * existing one ok but will also be sending a new one */ - ret = ret || (ssl->session.ticketLen > 0); + ret = ret || (ssl->session->ticketLen > 0); #endif ret = ret || (ssl->options.haveSessionId && XMEMCMP(ssl->arrays->sessionID, - ssl->session.sessionID, ID_LEN) == 0); + ssl->session->sessionID, ID_LEN) == 0); return ret; } @@ -23396,7 +23391,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) #ifdef HAVE_SECRET_CALLBACK if (ssl->sessionSecretCb != NULL) { int secretSz = SECRET_LEN; - ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, + ret = ssl->sessionSecretCb(ssl, ssl->session->masterSecret, &secretSz, ssl->sessionSecretCtx); if (ret != 0 || secretSz != SECRET_LEN) return SESSION_SECRET_CB_E; @@ -23454,7 +23449,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) if (SetCipherSpecs(ssl) == 0) { XMEMCPY(ssl->arrays->masterSecret, - ssl->session.masterSecret, SECRET_LEN); + ssl->session->masterSecret, SECRET_LEN); #ifdef NO_OLD_TLS ret = DeriveTlsKeys(ssl); #else @@ -26726,27 +26721,27 @@ int SendCertificateVerify(WOLFSSL* ssl) int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length) { /* Free old dynamic ticket if we already had one */ - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; + if (ssl->session->ticketLenAlloc > 0) { + XFREE(ssl->session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session->ticket = ssl->session->_staticTicket; + ssl->session->ticketLenAlloc = 0; } - if (length > sizeof(ssl->session._staticTicket)) { + if (length > sizeof(ssl->session->_staticTicket)) { byte* sessionTicket = (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); if (sessionTicket == NULL) return MEMORY_E; - ssl->session.ticket = sessionTicket; - ssl->session.ticketLenAlloc = (word16)length; + ssl->session->ticket = sessionTicket; + ssl->session->ticketLenAlloc = (word16)length; } - ssl->session.ticketLen = (word16)length; + ssl->session->ticketLen = (word16)length; if (length > 0) { - XMEMCPY(ssl->session.ticket, ticket, length); + XMEMCPY(ssl->session->ticket, ticket, length); if (ssl->session_ticket_cb != NULL) { ssl->session_ticket_cb(ssl, - ssl->session.ticket, ssl->session.ticketLen, + ssl->session->ticket, ssl->session->ticketLen, ssl->session_ticket_ctx); } /* Create a fake sessionID based on the ticket, this will @@ -26754,13 +26749,13 @@ int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length) ssl->options.haveSessionId = 1; #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) { - XMEMCPY(ssl->session.sessionID, - ssl->session.ticket + length - ID_LEN, ID_LEN); + XMEMCPY(ssl->session->sessionID, + ssl->session->ticket + length - ID_LEN, ID_LEN); } else #endif XMEMCPY(ssl->arrays->sessionID, - ssl->session.ticket + length - ID_LEN, ID_LEN); + ssl->session->ticket + length - ID_LEN, ID_LEN); } return 0; @@ -28843,7 +28838,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 +28856,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; } @@ -29195,7 +29189,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->arrays->masterSecret, 1); #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket == 1) { - session = &ssl->session; + session = ssl->session; } #endif @@ -29253,13 +29247,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { int ret = 0; WOLFSSL_SESSION* session; - #ifdef HAVE_EXT_CACHE - byte gotSess = 0; - #endif (void)bogusID; #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket == 1) { - session = &ssl->session; + session = ssl->session; } else if (bogusID == 1 && ssl->options.rejectTicket == 0) { WOLFSSL_MSG("Bogus session ID without session ticket"); return BUFFER_ERROR; @@ -29267,9 +29258,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif { session = wolfSSL_GetSession(ssl, ssl->arrays->masterSecret, 1); - #ifdef HAVE_EXT_CACHE - gotSess = 1; - #endif } if (!session) { WOLFSSL_MSG("Session lookup for resume failed"); @@ -29359,12 +29347,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } - #ifdef HAVE_EXT_CACHE - if (gotSess) { - wolfSSL_SESSION_free(session); - } - #endif - return ret; } @@ -29968,7 +29950,14 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif #endif - ret = MatchSuite(ssl, &clSuites); +#ifdef OPENSSL_EXTRA + /* Give user last chance to provide a cert for cipher selection */ + if (ret == 0 && ssl->ctx->certSetupCb != NULL) + ret = CertSetupCbWrapper(ssl); +#endif + if (ret == 0) + ret = MatchSuite(ssl, &clSuites); + #ifdef WOLFSSL_EXTRA_ALERTS if (ret == BUFFER_ERROR) SendAlert(ssl, alert_fatal, decode_error); @@ -29996,11 +29985,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); @@ -30513,20 +30497,25 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_TICKET_IV_SZ + WOLFSSL_TICKET_MAC_SZ + LENGTH_SZ) #define WOLFSSL_TICKET_ENC_SZ (SESSION_TICKET_LEN - WOLFSSL_TICKET_FIXED_SZ) - /* our ticket format */ + /* Our ticket format. All members need to be a byte or array of byte to + * avoid alignment issues */ typedef struct InternalTicket { ProtocolVersion pv; /* version when ticket created */ byte suite[SUITE_LEN]; /* cipher suite when created */ byte msecret[SECRET_LEN]; /* master secret */ - word32 timestamp; /* born on */ - word16 haveEMS; /* have extended master secret */ + byte timestamp[TIMESTAMP_LEN]; /* born on */ + byte haveEMS; /* have extended master secret */ #ifdef WOLFSSL_TLS13 - word32 ageAdd; /* Obfuscation of age */ - word16 namedGroup; /* Named group used */ + byte ageAdd[AGEADD_LEN]; /* Obfuscation of age */ + byte namedGroup[NAMEDGREOUP_LEN]; /* Named group used */ TicketNonce ticketNonce; /* Ticket nonce */ #ifdef WOLFSSL_EARLY_DATA - word32 maxEarlyDataSz; /* Max size of early data */ + byte maxEarlyDataSz[MAXEARLYDATASZ_LEN]; /* Max size of + * early data */ #endif +#endif +#ifdef WOLFSSL_TICKET_HAVE_ID + byte id[ID_LEN]; #endif } InternalTicket; @@ -30572,7 +30561,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int CreateTicket(WOLFSSL* ssl) { InternalTicket it; - ExternalTicket* et = (ExternalTicket*)ssl->session.ticket; + ExternalTicket* et = (ExternalTicket*)ssl->session->ticket; int encLen; int ret; byte zeros[WOLFSSL_TICKET_MAC_SZ]; /* biggest cmp size */ @@ -30587,7 +30576,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, it.suite[1] = ssl->options.cipherSuite; #ifdef WOLFSSL_EARLY_DATA - it.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + c32toa(ssl->options.maxEarlyDataSz, it.maxEarlyDataSz); #endif if (!ssl->options.tls1_3) { @@ -30604,19 +30593,57 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, sizeof(it.ageAdd)); if (ret != 0) return BAD_TICKET_ENCRYPT; - ssl->session.ticketAdd = it.ageAdd; - it.namedGroup = ssl->session.namedGroup; - it.timestamp = TimeNowInMilliseconds(); + ato32(it.ageAdd, &ssl->session->ticketAdd); + c16toa(ssl->session->namedGroup, it.namedGroup); + c32toa(TimeNowInMilliseconds(), it.timestamp); /* Resumption master secret. */ - XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN); - XMEMCPY(&it.ticketNonce, &ssl->session.ticketNonce, + XMEMCPY(it.msecret, ssl->session->masterSecret, SECRET_LEN); + XMEMCPY(&it.ticketNonce, &ssl->session->ticketNonce, sizeof(TicketNonce)); #endif } +#ifdef WOLFSSL_TICKET_HAVE_ID + { + const byte* id = NULL; + byte idSz = 0; + if (ssl->session->haveAltSessionID) { + id = ssl->session->altSessionID; + idSz = ID_LEN; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) { + id = ssl->arrays->sessionID; + idSz = ssl->arrays->sessionIDSz; + } + else { + id = ssl->session->sessionID; + idSz = ssl->session->sessionIDSz; + } + if (idSz == 0) { + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->session->altSessionID, + ID_LEN); + if (ret != 0) + return ret; + ssl->session->haveAltSessionID = 1; + id = ssl->session->altSessionID; + idSz = ID_LEN; + } + XMEMCPY(it.id, id, ID_LEN); + } +#endif + /* encrypt */ encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */ - if (ssl->ctx->ticketEncCb == NULL) { + if (ssl->ctx->ticketEncCb == NULL +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) + || + /* SSL_OP_NO_TICKET turns off tickets in < 1.2. Forces + * "stateful" tickets for 1.3 so just use the regular + * stateless ones. */ + (!IsAtLeastTLSv1_3(ssl->version) && + (ssl->options.mask & SSL_OP_NO_TICKET) != 0) +#endif + ) { ret = WOLFSSL_TICKET_RET_FATAL; } else { @@ -30674,7 +30701,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* set size */ c16toa((word16)encLen, et->enc_len); - ssl->session.ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ); + ssl->session->ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ); if (encLen < WOLFSSL_TICKET_ENC_SZ) { /* move mac up since whole enc buffer not used */ XMEMMOVE(et->enc_ticket +encLen, et->mac,WOLFSSL_TICKET_MAC_SZ); @@ -30689,7 +30716,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len) { ExternalTicket* et; - InternalTicket it; + InternalTicket* it; int ret; int outLen; word16 inLen; @@ -30711,7 +30738,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } outLen = inLen; /* may be reduced by user padding */ - if (ssl->ctx->ticketEncCb == NULL) { + if (ssl->ctx->ticketEncCb == NULL +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) + || + /* SSL_OP_NO_TICKET turns off tickets in < 1.2. Forces + * "stateful" tickets for 1.3 so just use the regular + * stateless ones. */ + (!IsAtLeastTLSv1_3(ssl->version) && + (ssl->options.mask & SSL_OP_NO_TICKET) != 0) +#endif + ) { ret = WOLFSSL_TICKET_RET_FATAL; } else { @@ -30726,19 +30762,17 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return BAD_TICKET_KEY_CB_SZ; } - /* copy the decrypted ticket to avoid alignment issues */ - XMEMCPY(&it, et->enc_ticket, sizeof(InternalTicket)); - ForceZero(et->enc_ticket, sizeof(it)); + it = (InternalTicket*)et->enc_ticket; /* get master secret */ if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { - if (ssl->version.minor < it.pv.minor) { + if (ssl->version.minor < it->pv.minor) { ForceZero(&it, sizeof(it)); WOLFSSL_MSG("Ticket has greater version"); return VERSION_ERROR; } - else if (ssl->version.minor > it.pv.minor) { - if (IsAtLeastTLSv1_3(it.pv) != IsAtLeastTLSv1_3(ssl->version)) { + else if (ssl->version.minor > it->pv.minor) { + if (IsAtLeastTLSv1_3(it->pv) != IsAtLeastTLSv1_3(ssl->version)) { ForceZero(&it, sizeof(it)); WOLFSSL_MSG("Tickets cannot be shared between " "TLS 1.3 and TLS 1.2 and lower"); @@ -30753,40 +30787,54 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Downgrading protocol due to ticket"); - if (it.pv.minor < ssl->options.minDowngrade) { + if (it->pv.minor < ssl->options.minDowngrade) { ForceZero(&it, sizeof(it)); return VERSION_ERROR; } - ssl->version.minor = it.pv.minor; + ssl->version.minor = it->pv.minor; } +#ifdef WOLFSSL_TICKET_HAVE_ID + { + ssl->session->haveAltSessionID = 1; + XMEMCPY(ssl->session->altSessionID, it->id, ID_LEN); + 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); + XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); /* Copy the haveExtendedMasterSecret property from the ticket to * the saved session, so the property may be checked later. */ - ssl->session.haveEMS = it.haveEMS; - ato32((const byte*)&it.timestamp, &ssl->session.bornOn); + ssl->session->haveEMS = it->haveEMS; + ato32((const byte*)&it->timestamp, &ssl->session->bornOn); #ifndef NO_RESUME_SUITE_CHECK - ssl->session.cipherSuite0 = it.suite[0]; - ssl->session.cipherSuite = it.suite[1]; + ssl->session->cipherSuite0 = it->suite[0]; + ssl->session->cipherSuite = it->suite[1]; #endif } else { #ifdef WOLFSSL_TLS13 /* Restore information to renegotiate. */ - ssl->session.ticketSeen = it.timestamp; - ssl->session.ticketAdd = it.ageAdd; - ssl->session.cipherSuite0 = it.suite[0]; - ssl->session.cipherSuite = it.suite[1]; + ato32(it->timestamp, &ssl->session->ticketSeen); + ato32(it->ageAdd, &ssl->session->ticketAdd); + ssl->session->cipherSuite0 = it->suite[0]; + ssl->session->cipherSuite = it->suite[1]; #ifdef WOLFSSL_EARLY_DATA - ssl->session.maxEarlyDataSz = it.maxEarlyDataSz; + ato32(it->maxEarlyDataSz, &ssl->session->maxEarlyDataSz); #endif /* Resumption master secret. */ - XMEMCPY(ssl->session.masterSecret, it.msecret, SECRET_LEN); - XMEMCPY(&ssl->session.ticketNonce, &it.ticketNonce, + XMEMCPY(ssl->session->masterSecret, it->msecret, SECRET_LEN); + XMEMCPY(&ssl->session->ticketNonce, &it->ticketNonce, sizeof(TicketNonce)); - ssl->session.namedGroup = it.namedGroup; + ato16(it->namedGroup, &ssl->session->namedGroup); #endif } } @@ -30817,7 +30865,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; } - length += ssl->session.ticketLen; + length += ssl->session->ticketLen; sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; if (!ssl->options.dtls) { @@ -30849,12 +30897,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, idx += SESSION_HINT_SZ; /* length */ - c16toa(ssl->session.ticketLen, output + idx); + c16toa(ssl->session->ticketLen, output + idx); idx += LENGTH_SZ; /* ticket */ - XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); - idx += ssl->session.ticketLen; + XMEMCPY(output + idx, ssl->session->ticket, ssl->session->ticketLen); + idx += ssl->session->ticketLen; if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { byte* input; @@ -31209,6 +31257,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/sniffer.c b/src/sniffer.c index 2e35e1487e..8eae315c85 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -3044,9 +3044,9 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes, *sslBytes -= OPAQUE8_LEN; #ifdef HAVE_SESSION_TICKET /* store nonce in server for DeriveResumptionPSK */ - session->sslServer->session.ticketNonce.len = len; + session->sslServer->session->ticketNonce.len = len; if (len > 0) - XMEMCPY(&session->sslServer->session.ticketNonce.data, input, len); + XMEMCPY(&session->sslServer->session->ticketNonce.data, input, len); #endif input += len; *sslBytes -= len; @@ -3123,7 +3123,7 @@ static int DoResume(SnifferSession* session, char* error) #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(session->sslServer->version)) { resume = wolfSSL_GetSession(session->sslServer, - session->sslServer->session.masterSecret, 0); + session->sslServer->session->masterSecret, 0); if (resume == NULL) { /* TLS v1.3 with hello_retry uses session_id even for new session, so ignore error here */ @@ -3147,8 +3147,8 @@ static int DoResume(SnifferSession* session, char* error) /* make sure client has master secret too */ #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(session->sslServer->version)) { - XMEMCPY(session->sslClient->session.masterSecret, - session->sslServer->session.masterSecret, SECRET_LEN); + XMEMCPY(session->sslClient->session->masterSecret, + session->sslServer->session->masterSecret, SECRET_LEN); } else #endif @@ -3179,8 +3179,8 @@ static int DoResume(SnifferSession* session, char* error) session->sslServer->arrays->psk_keySz = session->sslServer->specs.hash_size; session->sslClient->arrays->psk_keySz = session->sslClient->specs.hash_size; ret = DeriveResumptionPSK(session->sslServer, - session->sslServer->session.ticketNonce.data, - session->sslServer->session.ticketNonce.len, + session->sslServer->session->ticketNonce.data, + session->sslServer->session->ticketNonce.len, session->sslServer->arrays->psk_key); /* Copy resumption PSK to client */ XMEMCPY(session->sslClient->arrays->psk_key, @@ -3266,7 +3266,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, } if (b) { #ifdef WOLFSSL_TLS13 - XMEMCPY(session->sslServer->session.sessionID, input, ID_LEN); + XMEMCPY(session->sslServer->session->sessionID, input, ID_LEN); #endif XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN); session->sslServer->options.haveSessionId = 1; @@ -3370,10 +3370,10 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, session->sslClient->options.resuming = 1; #ifdef WOLFSSL_TLS13 /* default nonce to len = 1, data = 0 */ - session->sslServer->session.ticketNonce.len = 1; - session->sslServer->session.ticketNonce.data[0] = 0; - session->sslClient->session.ticketNonce.len = 1; - session->sslClient->session.ticketNonce.data[0] = 0; + session->sslServer->session->ticketNonce.len = 1; + session->sslServer->session->ticketNonce.data[0] = 0; + session->sslClient->session->ticketNonce.len = 1; + session->sslClient->session->ticketNonce.data[0] = 0; #endif break; #endif @@ -3595,7 +3595,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes, } Trace(CLIENT_RESUME_TRY_STR); #ifdef WOLFSSL_TLS13 - XMEMCPY(session->sslClient->session.sessionID, input, ID_LEN); + XMEMCPY(session->sslClient->session->sessionID, input, ID_LEN); #endif if (session->sslClient->arrays) XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN); @@ -4014,14 +4014,14 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, #ifdef HAVE_SESSION_TICKET /* derive resumption secret for next session - on finished (from client) */ ret += DeriveResumptionSecret(session->sslClient, - session->sslClient->session.masterSecret); + session->sslClient->session->masterSecret); /* copy resumption secret to server */ - XMEMCPY(session->sslServer->session.masterSecret, - session->sslClient->session.masterSecret, SECRET_LEN); + XMEMCPY(session->sslServer->session->masterSecret, + session->sslClient->session->masterSecret, SECRET_LEN); #ifdef SHOW_SECRETS PrintSecret("resumption secret", - session->sslClient->session.masterSecret, SECRET_LEN); + session->sslClient->session->masterSecret, SECRET_LEN); #endif #endif } diff --git a/src/ssl.c b/src/ssl.c index e22f1130fa..1df33d6476 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -164,6 +164,11 @@ * should make porting to new projects easier. * WOLFSSL_CHECK_ALERT_ON_ERR: * Check for alerts during the handshake in the event of an error. + * NO_SESSION_CACHE_REF: + * wolfSSL_get_session on a client will return a reference to the internal + * ClientCache by default for backwards compatibility. This define will + * make wolfSSL_get_session return a reference to ssl->session. The returned + * pointer will be freed with the related WOLFSSL object. */ #define WOLFSSL_EVP_INCLUDED @@ -542,14 +547,12 @@ WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method) #endif } -#ifdef OPENSSL_EXTRA /* increases CTX reference count to track proper time to "free" */ int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx) { int refCount = SSL_CTX_RefCount(ctx, 1); return ((refCount > 1) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE); } -#endif WOLFSSL_ABI void wolfSSL_CTX_free(WOLFSSL_CTX* ctx) @@ -3321,9 +3324,9 @@ WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0) return BAD_FUNC_ARG; - if (ssl->session.ticketLen <= *bufSz) { - XMEMCPY(buf, ssl->session.ticket, ssl->session.ticketLen); - *bufSz = ssl->session.ticketLen; + if (ssl->session->ticketLen <= *bufSz) { + XMEMCPY(buf, ssl->session->ticket, ssl->session->ticketLen); + *bufSz = ssl->session->ticketLen; } else *bufSz = 0; @@ -3340,32 +3343,32 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, if (bufSz > 0) { /* Ticket will fit into static ticket */ if (bufSz <= SESSION_TICKET_LEN) { - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, + if (ssl->session->ticketLenAlloc > 0) { + XFREE(ssl->session->ticket, ssl->session->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticketLenAlloc = 0; - ssl->session.ticket = ssl->session._staticTicket; + ssl->session->ticketLenAlloc = 0; + ssl->session->ticket = ssl->session->_staticTicket; } } else { /* Ticket requires dynamic ticket storage */ - if (ssl->session.ticketLen < bufSz) { /* is dyn buffer big enough */ - if (ssl->session.ticketLenAlloc > 0) { - XFREE(ssl->session.ticket, ssl->heap, + if (ssl->session->ticketLen < bufSz) { /* is dyn buffer big enough */ + if (ssl->session->ticketLenAlloc > 0) { + XFREE(ssl->session->ticket, ssl->session->heap, DYNAMIC_TYPE_SESSION_TICK); } - ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap, + ssl->session->ticket = (byte*)XMALLOC(bufSz, ssl->session->heap, DYNAMIC_TYPE_SESSION_TICK); - if(ssl->session.ticket == NULL) { - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; + if(ssl->session->ticket == NULL) { + ssl->session->ticket = ssl->session->_staticTicket; + ssl->session->ticketLenAlloc = 0; return MEMORY_ERROR; } - ssl->session.ticketLenAlloc = (word16)bufSz; + ssl->session->ticketLenAlloc = (word16)bufSz; } } - XMEMCPY(ssl->session.ticket, buf, bufSz); + XMEMCPY(ssl->session->ticket, buf, bufSz); } - ssl->session.ticketLen = (word16)bufSz; + ssl->session->ticketLen = (word16)bufSz; return WOLFSSL_SUCCESS; } @@ -4202,6 +4205,7 @@ int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm) #ifndef SINGLE_THREADED if (wc_LockMutex(&cm->refMutex) != 0) { WOLFSSL_MSG("Failed to lock cm mutex"); + return WOLFSSL_FAILURE; } #endif cm->refCount++; @@ -4397,6 +4401,10 @@ void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len, #endif #endif +/* + * TODO This ssl parameter needs to be changed to const once our ABI checker + * stops flagging qualifier additions as ABI breaking. + */ WOLFSSL_ABI int wolfSSL_pending(WOLFSSL* ssl) { @@ -4407,6 +4415,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 +4709,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 +4743,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 +4880,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 +4909,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 +4916,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 +4957,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 +5266,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 @@ -5308,20 +5301,48 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) #define SESSION_ROW_UNLOCK(row) wc_UnLockMutex(&session_mutex); #endif + #if !defined(NO_SESSION_CACHE_REF) && defined(NO_CLIENT_CACHE) + #error ClientCache is required when not using NO_SESSION_CACHE_REF + #endif + #ifndef NO_CLIENT_CACHE + #ifndef CLIENT_SESSIONS_MULTIPLIER + #ifdef NO_SESSION_CACHE_REF + #define CLIENT_SESSIONS_MULTIPLIER 1 + #else + /* ClientSession objects are lightweight (compared to + * WOLFSSL_SESSION) so to decrease chance that user will reuse + * thse wrong session, increase the ClientCache size. This will + * make the entire ClientCache about the size of one + * WOLFSSL_SESSION object. */ + #define CLIENT_SESSIONS_MULTIPLIER 8 + #endif + #endif + #define CLIENT_SESSIONS_PER_ROW \ + (SESSIONS_PER_ROW * CLIENT_SESSIONS_MULTIPLIER) + #define CLIENT_SESSION_ROWS (SESSION_ROWS * CLIENT_SESSIONS_MULTIPLIER) + + #if CLIENT_SESSIONS_PER_ROW > 65535 + #error CLIENT_SESSIONS_PER_ROW too big + #endif + #if CLIENT_SESSION_ROWS > 65535 + #error CLIENT_SESSION_ROWS too big + #endif + typedef struct ClientSession { word16 serverRow; /* SessionCache Row id */ word16 serverIdx; /* SessionCache Idx (column) */ + word32 sessionIDHash; } ClientSession; typedef struct ClientRow { int nextIdx; /* where to place next one */ int totalCount; /* sessions ever on this row */ - ClientSession Clients[SESSIONS_PER_ROW]; + ClientSession Clients[CLIENT_SESSIONS_PER_ROW]; } ClientRow; - static WOLFSSL_GLOBAL ClientRow ClientCache[SESSION_ROWS]; + static WOLFSSL_GLOBAL ClientRow ClientCache[CLIENT_SESSION_ROWS]; /* Client Cache */ /* uses session mutex */ @@ -6107,6 +6128,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; + } } } @@ -6139,13 +6165,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #ifdef WOLFSSL_TRUST_PEER_CERT else if (type == TRUSTED_PEER_TYPE) { - if (ctx == NULL) { - WOLFSSL_MSG("Need context for trusted peer cert load"); - FreeDer(&der); - return BAD_FUNC_ARG; - } /* add trusted peer cert. der is freed within */ - ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone); + if (ctx != NULL) + ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone); + else + ret = AddTrustedPeer(SSL_CM(ssl), &der, !ssl->options.verifyNone); if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error adding trusted peer"); } @@ -6331,13 +6355,21 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ - defined(HAVE_PQC) + defined(HAVE_PQC) || !defined(NO_RSA) if (ssl) { + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) ssl->pkCurveOID = cert->pkCurveOID; + #endif #ifndef WC_STRICT_SIG if (cert->keyOID == ECDSAk) { ssl->options.haveECC = 1; } + #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; @@ -6359,11 +6391,18 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif } else if (ctx) { + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) ctx->pkCurveOID = cert->pkCurveOID; + #endif #ifndef WC_STRICT_SIG if (cert->keyOID == ECDSAk) { ctx->haveECC = 1; } + #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 +7522,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 +7558,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 +7571,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); @@ -7603,6 +7658,18 @@ int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type) return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL, GET_VERIFY_SETTING_CTX(ctx)); } + +int wolfSSL_trust_peer_cert(WOLFSSL* ssl, const char* file, int type) +{ + WOLFSSL_ENTER("wolfSSL_trust_peer_cert"); + + if (ssl == NULL || file == NULL) { + return WOLFSSL_FAILURE; + } + + return ProcessFile(NULL, file, type, TRUSTED_PEER_TYPE, ssl, 0, NULL, + GET_VERIFY_SETTING_SSL(ssl)); +} #endif /* WOLFSSL_TRUST_PEER_CERT */ @@ -7781,6 +7848,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 +7896,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 +7958,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 @@ -12166,6 +12270,8 @@ int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, { int size; + ses = ClientSessionToSession(ses); + if (outSz == 0) { return SECRET_LEN; } @@ -12428,8 +12534,45 @@ WOLFSSL_ABI WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_session"); - if (ssl) - return wolfSSL_GetSession(ssl, NULL, 1); + if (ssl) { +#ifdef NO_SESSION_CACHE_REF + return ssl->session; +#else + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* On the client side we want to return a persistant reference for + * backwards compatibility. */ +#ifndef NO_CLIENT_CACHE + if (ssl->clientSession) + return (WOLFSSL_SESSION*)ssl->clientSession; + else { + /* Try to add a ClientCache entry to associate with the current + * session. Ignore any session cache options. */ + int error; + const byte* id = NULL; + byte idSz = 0; + id = ssl->session->sessionID; + idSz = ssl->session->sessionIDSz; + if (ssl->session->haveAltSessionID) { + id = ssl->session->altSessionID; + idSz = ID_LEN; + } + error = AddSessionToCache(ssl->session, id, idSz, + NULL, ssl->session->side, +#ifdef HAVE_SESSION_TICKET + ssl->session->ticketLen > 0, +#else + 0, +#endif + &ssl->clientSession); + if (error == 0) + return (WOLFSSL_SESSION*)ssl->clientSession; + } +#endif + } + else + return ssl->session; +#endif + } return NULL; } @@ -12438,17 +12581,15 @@ 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); + sess = ssl->session; 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) { + if (wolfSSL_SESSION_up_ref(sess) != WOLFSSL_SUCCESS) + sess = NULL; } - #endif } } return sess; @@ -12505,7 +12646,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; } } @@ -12514,8 +12655,8 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) if (session == NULL) { WOLFSSL_MSG("Valid ServerID not cached already"); - ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len); - XMEMCPY(ssl->session.serverID, id, ssl->session.idLen); + ssl->session->idLen = (word16)min(SERVER_ID_LEN, (word32)len); + XMEMCPY(ssl->session->serverID, id, ssl->session->idLen); } #ifdef HAVE_EXT_CACHE else { @@ -12570,9 +12711,6 @@ int wolfSSL_memsave_session_cache(void* mem, int sz) int i; cache_header_t cache_header; SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); -#ifndef NO_CLIENT_CACHE - ClientRow* clRow; -#endif WOLFSSL_ENTER("wolfSSL_memsave_session_cache"); @@ -12615,11 +12753,7 @@ int wolfSSL_memsave_session_cache(void* mem, int sz) WOLFSSL_MSG("Client cache mutex lock failed"); return BAD_MUTEX_E; } - - clRow = (ClientRow*)row; - for (i = 0; i < cache_header.rows; ++i) { - XMEMCPY(clRow++, ClientCache + i, sizeof(ClientRow)); - } + XMEMCPY(row, ClientCache, sizeof(ClientCache)); wc_UnLockMutex(&clisession_mutex); #endif @@ -12635,9 +12769,6 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz) int i; cache_header_t cache_header; SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); -#ifndef NO_CLIENT_CACHE - ClientRow* clRow; -#endif WOLFSSL_ENTER("wolfSSL_memrestore_session_cache"); @@ -12684,11 +12815,7 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz) WOLFSSL_MSG("Client cache mutex lock failed"); return BAD_MUTEX_E; } - - clRow = (ClientRow*)row; - for (i = 0; i < cache_header.rows; ++i) { - XMEMCPY(ClientCache + i, clRow++, sizeof(ClientRow)); - } + XMEMCPY(ClientCache, row, sizeof(ClientCache)); wc_UnLockMutex(&clisession_mutex); #endif @@ -12767,14 +12894,10 @@ int wolfSSL_save_session_cache(const char *fname) XFCLOSE(file); return BAD_MUTEX_E; } - - for (i = 0; i < cache_header.rows; ++i) { - ret = (int)XFWRITE(ClientCache + i, sizeof(ClientRow), 1, file); - if (ret != 1) { - WOLFSSL_MSG("Client cache member file write failed"); - rc = FWRITE_ERROR; - break; - } + ret = (int)XFWRITE(ClientCache, sizeof(ClientCache), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Client cache member file write failed"); + rc = FWRITE_ERROR; } wc_UnLockMutex(&clisession_mutex); #endif /* !NO_CLIENT_CACHE */ @@ -12859,14 +12982,11 @@ int wolfSSL_restore_session_cache(const char *fname) XFCLOSE(file); return BAD_MUTEX_E; } - for (i = 0; i < cache_header.rows; ++i) { - ret = (int)XFREAD(ClientCache + i, sizeof(ClientRow), 1, file); - if (ret != 1) { - WOLFSSL_MSG("Client cache member file read failed"); - XMEMSET(ClientCache, 0, sizeof ClientCache); - rc = FREAD_ERROR; - break; - } + ret = (int)XFREAD(ClientCache, sizeof(ClientCache), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Client cache member file read failed"); + XMEMSET(ClientCache, 0, sizeof ClientCache); + rc = FREAD_ERROR; } wc_UnLockMutex(&clisession_mutex); #endif /* !NO_CLIENT_CACHE */ @@ -12909,7 +13029,7 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx) ssl->sessionSecretCb = cb; ssl->sessionSecretCtx = ctx; /* If using a pre-set key, assume session resumption. */ - ssl->session.sessionIDSz = 0; + ssl->session->sessionIDSz = 0; ssl->options.resuming = 1; return WOLFSSL_SUCCESS; @@ -12938,6 +13058,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; @@ -15120,16 +15242,6 @@ int wolfSSL_Cleanup(void) } -static WC_INLINE WOLFSSL_SESSION* GetSessionPtr(const WOLFSSL_SESSION* s) -{ -#ifdef ENABLE_CLIENT_SESSION_REF - if (s && s->type == WOLFSSL_SESSION_TYPE_REF) { - s = (const WOLFSSL_SESSION*)s->refPtr; - } -#endif - return (WOLFSSL_SESSION*)s; -} - #ifndef NO_SESSION_CACHE /* some session IDs aren't random after all, let's make them random */ @@ -15251,8 +15363,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,16 +15376,22 @@ 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; + row = HashSession(id, len, &error) % CLIENT_SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); return NULL; @@ -15283,10 +15403,10 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) } /* start from most recently used */ - count = min((word32)ClientCache[row].totalCount, SESSIONS_PER_ROW); + count = min((word32)ClientCache[row].totalCount, CLIENT_SESSIONS_PER_ROW); idx = ClientCache[row].nextIdx - 1; - if (idx < 0 || idx >= SESSIONS_PER_ROW) { - idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ + if (idx < 0 || idx >= CLIENT_SESSIONS_PER_ROW) { + idx = CLIENT_SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ } clSess = ClientCache[row].Clients; @@ -15322,7 +15442,7 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) } SESSION_ROW_UNLOCK(sessRow); - idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1; + idx = idx > 0 ? idx - 1 : CLIENT_SESSIONS_PER_ROW - 1; } wc_UnLockMutex(&clisession_mutex); @@ -15332,43 +15452,6 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) #endif /* !NO_CLIENT_CACHE */ -/* Restore the master secret and session information for certificates. - * - * ssl The SSL/TLS object. - * session The cached session to restore. - * masterSecret The master secret from the cached session. - * restoreSessionCerts Restoring session certificates is required. - */ -static WC_INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session, - byte* masterSecret, byte restoreSessionCerts) -{ - (void)ssl; - (void)restoreSessionCerts; - - if (masterSecret) - XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN); -#ifdef SESSION_CERTS - /* If set, we should copy the session certs into the ssl object - * from the session we are returning so we can resume */ - if (restoreSessionCerts) { - ssl->session.chain = session->chain; - ssl->session.version = session->version; - #ifdef NO_RESUME_SUITE_CHECK - ssl->session.cipherSuite0 = session->cipherSuite0; - ssl->session.cipherSuite = session->cipherSuite; - #endif - } -#endif /* SESSION_CERTS */ -#if !defined(NO_RESUME_SUITE_CHECK) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - ssl->session.cipherSuite0 = session->cipherSuite0; - ssl->session.cipherSuite = session->cipherSuite; -#endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - ssl->peerVerifyRet = (unsigned long)session->peerVerifyRet; -#endif -} - static int SslSessionCacheOff(const WOLFSSL* ssl, const WOLFSSL_SESSION* session) { (void)session; @@ -15382,61 +15465,140 @@ static int SslSessionCacheOff(const WOLFSSL* ssl, const WOLFSSL_SESSION* session ; } -WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, - byte restoreSessionCerts) + +int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) { - WOLFSSL_SESSION* ret = NULL; + WOLFSSL_SESSION* sess = NULL; const byte* id = NULL; word32 row; int idx; int count; int error = 0; SessionRow* sessRow; +#ifdef HAVE_SESSION_TICKET +#ifndef WOLFSSL_SMALL_STACK + byte tmpTicket[PREALLOC_SESSION_TICKET_LEN]; +#else + byte* tmpTicket = NULL; +#endif + byte tmpBufSet = 0; +#endif +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* peer = NULL; +#endif + byte bogusID[ID_LEN]; + byte bogusIDSz = 0; - (void)restoreSessionCerts; + WOLFSSL_ENTER("wolfSSL_GetSessionFromCache"); - if (SslSessionCacheOff(ssl, &ssl->session)) - return NULL; + if (output == NULL) { + WOLFSSL_MSG("NULL output"); + return WOLFSSL_FAILURE; + } + + if (SslSessionCacheOff(ssl, ssl->session)) + return WOLFSSL_FAILURE; if (ssl->options.haveSessionId == 0) - return NULL; + return WOLFSSL_FAILURE; #ifdef HAVE_SESSION_TICKET if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) - return NULL; + return WOLFSSL_FAILURE; #endif - if (!ssl->options.tls1_3 && ssl->arrays != NULL) + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) id = ssl->arrays->sessionID; + else if (ssl->session->haveAltSessionID) { + id = ssl->session->altSessionID; + /* We want to restore the bogus ID for TLS compatibility */ + if (output == ssl->session) { + XMEMCPY(bogusID, ssl->session->sessionID, ID_LEN); + bogusIDSz = ssl->session->sessionIDSz; + } + } else - id = ssl->session.sessionID; + id = ssl->session->sessionID; + #ifdef HAVE_EXT_CACHE if (ssl->ctx->get_sess_cb != NULL) { int copy = 0; /* Attempt to retrieve the session from the external cache. */ - ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); - if (ret != NULL) { - RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); - return ret; + WOLFSSL_MSG("Calling external session cache"); + sess = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); + if (sess != NULL) { + WOLFSSL_MSG("Session found in external cache"); + error = wolfSSL_DupSession(sess, output, 0); + /* If copy not set then free immediately */ + if (!copy) + wolfSSL_SESSION_free(sess); + /* We want to restore the bogus ID for TLS compatibility */ + if (ssl->session->haveAltSessionID && + output == ssl->session) { + XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN); + ssl->session->sessionIDSz = bogusIDSz; + } + return error; } + WOLFSSL_MSG("Session not found in external cache"); } - if (ssl->ctx->internalCacheOff) - return NULL; + if (ssl->ctx->internalCacheLookupOff) { + WOLFSSL_MSG("Internal cache lookup turned off"); + return WOLFSSL_FAILURE; + } #endif row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); - return NULL; + return WOLFSSL_FAILURE; + } + + +#ifdef HAVE_SESSION_TICKET + if (output->ticket == NULL || + output->ticketLenAlloc < PREALLOC_SESSION_TICKET_LEN) { +#ifdef WOLFSSL_SMALL_STACK + tmpTicket = (byte*)XMALLOC(PREALLOC_SESSION_TICKET_LEN, output->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpTicket == NULL) { + WOLFSSL_MSG("tmpTicket malloc failed"); + return WOLFSSL_FAILURE; + } +#endif + if (output->ticketLenAlloc) + XFREE(output->ticket, output->heap, DYNAMIC_TYPE_SESSION_TICK); + output->ticket = tmpTicket; + output->ticketLenAlloc = PREALLOC_SESSION_TICKET_LEN; + output->ticketLen = 0; + tmpBufSet = 1; + } +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (output->peer != NULL) { + wolfSSL_X509_free(output->peer); + output->peer = NULL; } +#endif /* lock row */ sessRow = &SessionCache[row]; if (SESSION_ROW_LOCK(sessRow) != 0) { WOLFSSL_MSG("Session cache row lock failure"); - return NULL; +#ifdef HAVE_SESSION_TICKET + if (tmpBufSet) { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } +#ifdef WOLFSSL_SMALL_STACK + if (tmpTicket != NULL) + XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif +#endif + return WOLFSSL_FAILURE; } /* start from most recently used */ @@ -15455,9 +15617,7 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, WOLFSSL_MSG("Found a session match"); if (LowResTimer() < (current->bornOn + current->timeout)) { WOLFSSL_MSG("Session valid"); - ret = current; - - RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); + sess = current; } else { WOLFSSL_MSG("Session timed out"); } @@ -15469,154 +15629,150 @@ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1; } + if (sess != NULL) { +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + /* We don't want the peer member. We will free it at the end. */ + if (sess->peer != NULL) { + peer = sess->peer; + sess->peer = NULL; + } +#endif + error = wolfSSL_DupSession(sess, output, 1); + } + else { + error = WOLFSSL_FAILURE; + } + SESSION_ROW_UNLOCK(sessRow); - return ret; -} + /* We want to restore the bogus ID for TLS compatibility */ + if (ssl->session->haveAltSessionID && + output == ssl->session) { + XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN); + ssl->session->sessionIDSz = bogusIDSz; + } -int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) -{ - int ret = WOLFSSL_SUCCESS, row = -1; #ifdef HAVE_SESSION_TICKET - int ticLenAlloc; - byte *ticBuff = NULL; + if (tmpBufSet) { + if (error == WOLFSSL_SUCCESS) { + if (output->ticketLen > SESSION_TICKET_LEN) { + output->ticket = (byte*)XMALLOC(output->ticketLen, output->heap, + DYNAMIC_TYPE_SESSION_TICK); + if (output->ticket == NULL) { + error = WOLFSSL_FAILURE; + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + output->ticketLen = 0; + } + } + else { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } + } + else { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + output->ticketLen = 0; + } + if (error == WOLFSSL_SUCCESS) { + XMEMCPY(output->ticket, tmpTicket, output->ticketLen); + } + } +#ifdef WOLFSSL_SMALL_STACK + if (tmpTicket != NULL) + XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif -#ifdef ENABLE_CLIENT_SESSION_REF - WOLFSSL_SESSION* ref = NULL; #endif - if (ssl == NULL || session == NULL || SslSessionCacheOff(ssl, session)) { - return WOLFSSL_FAILURE; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (peer != NULL) { + wolfSSL_X509_free(peer); } +#endif - row = session->cacheRow; -#ifdef ENABLE_CLIENT_SESSION_REF - if (session->type == WOLFSSL_SESSION_TYPE_REF) { - if (session->refPtr == NULL) { - WOLFSSL_MSG("Invalid session reference"); - ret = WOLFSSL_FAILURE; - } - 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; - } - } + return error; +} + +WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, + byte restoreSessionCerts) +{ + WOLFSSL_SESSION* ret = NULL; + + (void)restoreSessionCerts; /* Kept for compatibility */ + + if (wolfSSL_GetSessionFromCache(ssl, ssl->session) == WOLFSSL_SUCCESS) { + ret = ssl->session; + } + else { + WOLFSSL_MSG("wolfSSL_GetSessionFromCache did not return a session"); } -#endif - if (row < 0 || row >= SESSION_ROWS) { - return BAD_FUNC_ARG; + if (ret != NULL && masterSecret != NULL) + XMEMCPY(masterSecret, ret->masterSecret, SECRET_LEN); + + return ret; +} + +int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + SessionRow* sessRow = NULL; + int ret = WOLFSSL_SUCCESS; + + session = ClientSessionToSession(session); + + if (ssl == NULL || session == NULL) { + return WOLFSSL_FAILURE; } - /* lock session cache row */ - if (SESSION_ROW_LOCK(&SessionCache[row]) != 0) { - return BAD_MUTEX_E; + if (session->type == WOLFSSL_SESSION_TYPE_CACHE) { + if (session->cacheRow < SESSION_ROWS) { + sessRow = &SessionCache[session->cacheRow]; + if (SESSION_ROW_LOCK(sessRow) != 0) { + WOLFSSL_MSG("Session row lock failed"); + return WOLFSSL_FAILURE; + } + } } -#ifdef ENABLE_CLIENT_SESSION_REF - /* verify if ID matches session cache entry */ - if (ref != NULL && - XMEMCMP(ref->sessionID, session->sessionID, ID_LEN) != 0) { - WOLFSSL_MSG("Session cache reference not longer valid"); + if (ret == WOLFSSL_SUCCESS && SslSessionCacheOff(ssl, session)) { + WOLFSSL_MSG("Session cache off"); ret = WOLFSSL_FAILURE; } -#endif -#ifdef HAVE_SESSION_TICKET - /* cache the old dynamic buffer and try to reuse or free later */ - ticLenAlloc = ssl->session.ticketLenAlloc; - if (ticLenAlloc > 0) { - ticBuff = ssl->session.ticket; + if (ret == WOLFSSL_SUCCESS && ssl->options.side != WOLFSSL_NEITHER_END && + (byte)ssl->options.side != session->side) { + WOLFSSL_MSG("Setting session for wrong role"); + ret = WOLFSSL_FAILURE; } -#endif - /* copy session structure */ - XMEMCPY(&ssl->session, session, sizeof(WOLFSSL_SESSION)); - ssl->session.type = WOLFSSL_SESSION_TYPE_SSL; - ssl->session.masterSecret = ssl->session._masterSecret; -#ifndef NO_CLIENT_CACHE - ssl->session.serverID = ssl->session._serverID; -#endif -#ifdef OPENSSL_EXTRA - ssl->session.sessionCtx = ssl->session._sessionCtx; -#endif -#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; + if (ret == WOLFSSL_SUCCESS && + wolfSSL_DupSession(session, ssl->session, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Session duplicate failed"); + ret = WOLFSSL_FAILURE; } -#endif - SESSION_ROW_UNLOCK(&SessionCache[row]); + /* Let's copy over the altSessionID for local cache purposes */ + if (ret == WOLFSSL_SUCCESS && session->haveAltSessionID) { + ssl->session->haveAltSessionID = 1; + XMEMCPY(ssl->session->altSessionID, session->altSessionID, ID_LEN); + } -#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; - } - 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]); - } + if (sessRow != NULL) { + SESSION_ROW_UNLOCK(sessRow); + sessRow = NULL; } -#endif + /* Make sure we don't access this anymore */ + session = NULL; - if (ret != WOLFSSL_SUCCESS) { - #ifdef HAVE_SESSION_TICKET - /* cleanup */ - if (ssl->session.ticket != ssl->session._staticTicket) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - } - ssl->session.ticket = ssl->session._staticTicket; - ssl->session.ticketLenAlloc = 0; - #endif + if (ret != WOLFSSL_SUCCESS) return ret; - } - /* don't use the provided session pointer from here to end of func, only use - * ssl->session. - */ #ifdef OPENSSL_EXTRA /* check for application context id */ if (ssl->sessionCtxSz > 0) { - if (XMEMCMP(ssl->sessionCtx, ssl->session.sessionCtx, ssl->sessionCtxSz)) { + if (XMEMCMP(ssl->sessionCtx, ssl->session->sessionCtx, ssl->sessionCtxSz)) { /* context id did not match! */ WOLFSSL_MSG("Session context did not match"); return WOLFSSL_FAILURE; @@ -15624,17 +15780,23 @@ int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) } #endif /* OPENSSL_EXTRA */ - if (LowResTimer() < (ssl->session.bornOn + ssl->session.timeout)) { + if (LowResTimer() < (ssl->session->bornOn + ssl->session->timeout)) { ssl->options.resuming = 1; + ssl->options.haveEMS = ssl->session->haveEMS; #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ defined(HAVE_SESSION_TICKET)) - ssl->version = ssl->session.version; + ssl->version = ssl->session->version; + if (IsAtLeastTLSv1_3(ssl->version)) + ssl->options.tls1_3 = 1; #endif #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - ssl->options.cipherSuite0 = ssl->session.cipherSuite0; - ssl->options.cipherSuite = ssl->session.cipherSuite; + ssl->options.cipherSuite0 = ssl->session->cipherSuite0; + ssl->options.cipherSuite = ssl->session->cipherSuite; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = (unsigned long)ssl->session->peerVerifyRet; #endif ret = WOLFSSL_SUCCESS; } @@ -15656,274 +15818,447 @@ static int get_locked_session_stats(word32* active, word32* total, word32* peak); #endif -int AddSession(WOLFSSL* ssl) +#ifndef NO_CLIENT_CACHE +ClientSession* AddSessionToClientCache(int side, int row, int idx, byte* serverID, + word16 idLen, const byte* sessionID, + word16 useTicket) +{ + int error = -1; + word32 clientRow = 0, clientIdx = 0, sessionIDHash = 0; + (void)useTicket; + if (side == WOLFSSL_CLIENT_END + && row != INVALID_SESSION_ROW + && (idLen +#ifdef HAVE_SESSION_TICKET + || useTicket == 1 +#endif + || serverID != NULL + )) { + + WOLFSSL_MSG("Trying to add client cache entry"); + + if (idLen) { + clientRow = HashSession(serverID, + idLen, &error) % CLIENT_SESSION_ROWS; + } + else if (serverID != NULL) { + clientRow = HashSession(sessionID, + ID_LEN, &error) % CLIENT_SESSION_ROWS; + } + else + error = -1; + if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) { + clientIdx = ClientCache[clientRow].nextIdx++; + ClientCache[clientRow].Clients[clientIdx].serverRow = + (word16)row; + ClientCache[clientRow].Clients[clientIdx].serverIdx = + (word16)idx; + if (sessionID != NULL) { + sessionIDHash = HashSession(sessionID, ID_LEN, &error); + if (error == 0) { + ClientCache[clientRow].Clients[clientIdx].sessionIDHash + = sessionIDHash; + } + } + if (error == 0) { + WOLFSSL_MSG("Adding client cache entry"); + if (ClientCache[clientRow].totalCount < CLIENT_SESSIONS_PER_ROW) + ClientCache[clientRow].totalCount++; + ClientCache[clientRow].nextIdx %= CLIENT_SESSIONS_PER_ROW; + } + + wc_UnLockMutex(&clisession_mutex); + } + else { + WOLFSSL_MSG("Hash session failed"); + } + } + else { + WOLFSSL_MSG("Skipping client cache"); + } + if (error == 0) + return &ClientCache[clientRow].Clients[clientIdx]; + else + return NULL; +} +#endif + +/** + * For backwards compatibility, this API needs to be used in *ALL* functions + * that access the WOLFSSL_SESSION members directly. + * + * This API checks if the passed in session is actually a ClientSession object + * and returns the matching session cache object. Otherwise just return the + * input. ClientSession objects only occur in the ClientCache. They are not + * allocated anywhere else. + */ +WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("ClientSessionToSession"); +#ifdef NO_SESSION_CACHE_REF + return (WOLFSSL_SESSION*)session; +#else +#ifndef NO_CLIENT_CACHE + if (session == NULL) + return NULL; + /* Check if session points into ClientCache */ + if ((byte*)session >= (byte*)ClientCache && + /* Cast to byte* to make pointer arithmetic work per byte */ + (byte*)session < ((byte*)ClientCache) + sizeof(ClientCache)) { + ClientSession* clientSession = (ClientSession*)session; + SessionRow* sessRow = NULL; + WOLFSSL_SESSION* cacheSession = NULL; + word32 sessionIDHash = 0; + int error = 0; + session = NULL; /* Default to NULL for failure case */ + if (wc_LockMutex(&clisession_mutex) != 0) { + WOLFSSL_MSG("Client cache mutex lock failed"); + return NULL; + } + if (clientSession->serverRow >= SESSION_ROWS || + clientSession->serverIdx >= SESSIONS_PER_ROW) { + WOLFSSL_MSG("Client cache serverRow or serverIdx invalid"); + error = -1; + } + if (error == 0) { + /* Lock row */ + sessRow = &SessionCache[clientSession->serverRow]; + error = SESSION_ROW_LOCK(sessRow); + if (error != 0) { + WOLFSSL_MSG("Session cache row lock failure"); + sessRow = NULL; + } + } + if (error == 0) { + cacheSession = &sessRow->Sessions[clientSession->serverIdx]; + if (cacheSession->sessionIDSz == 0) { + cacheSession = NULL; + WOLFSSL_MSG("Session cache entry not set"); + error = -1; + } + } + if (error == 0) { + /* Calculate the hash of the session ID */ + sessionIDHash = HashSession(cacheSession->sessionID, ID_LEN, + &error); + } + if (error == 0) { + /* Check the session ID hash matches */ + error = clientSession->sessionIDHash != sessionIDHash; + } + if (error == 0) { + /* Hashes match */ + session = cacheSession; + WOLFSSL_MSG("Found session cache matching client session object"); + } + if (sessRow != NULL) { + SESSION_ROW_UNLOCK(sessRow); + } + wc_UnLockMutex(&clisession_mutex); + return (WOLFSSL_SESSION*)session; + } + else { + /* Plain WOLFSSL_SESSION object */ + return (WOLFSSL_SESSION*)session; + } +#else + return (WOLFSSL_SESSION*)session; +#endif +#endif +} + +int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, byte idSz, + int* sessionIndex, int side, word16 useTicket, + ClientSession** clientCacheEntry) { - word32 row = 0; + WOLFSSL_SESSION* cacheSession = NULL; + SessionRow* sessRow = NULL; word32 idx = 0; - int error = 0; - const byte* id = NULL; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* peer = NULL; +#endif #ifdef HAVE_SESSION_TICKET + byte* cacheTicBuff = NULL; + byte ticBuffUsed = 0; byte* ticBuff = NULL; int ticLen = 0; #endif - WOLFSSL_SESSION* session; + int ret = 0; + int row; int i; int overwrite = 0; -#ifdef HAVE_EXT_CACHE - int cbRet = 0; -#endif - SessionRow* sessRow = NULL; - if (SslSessionCacheOff(ssl, &ssl->session)) - return 0; + (void)sessionIndex; + (void)useTicket; + (void)clientCacheEntry; - if (ssl->options.haveSessionId == 0) - return 0; + addSession = ClientSessionToSession(addSession); -#ifdef HAVE_SESSION_TICKET - if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) - return 0; -#endif - - if (!ssl->options.tls1_3 && ssl->arrays != NULL) - id = ssl->arrays->sessionID; - else - id = ssl->session.sessionID; - - if (id == NULL) { + if (addSession == NULL || idSz == 0) { + WOLFSSL_MSG("addSession NULL or idSz == 0"); return BAD_FUNC_ARG; } + /* Find a position for the new session in cache and use that */ #ifdef HAVE_SESSION_TICKET - ticLen = ssl->session.ticketLen; - /* Alloc Memory here so if Malloc fails can exit outside of lock */ + ticLen = addSession->ticketLen; + /* Alloc Memory here to avoid syscalls during lock */ if (ticLen > SESSION_TICKET_LEN) { - ticBuff = (byte*)XMALLOC(ticLen, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ticBuff = (byte*)XMALLOC(ticLen, NULL, + DYNAMIC_TYPE_SESSION_TICK); if (ticBuff == NULL) { return MEMORY_E; } } #endif + /* Use the session object in the cache for external cache if required */ + row = (int)(HashSession(id, ID_LEN, &ret) % SESSION_ROWS); + if (ret != 0) { + WOLFSSL_MSG("Hash session failed"); + #ifdef HAVE_SESSION_TICKET + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); + #endif + return ret; + } -#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; + sessRow = &SessionCache[row]; + if (SESSION_ROW_LOCK(sessRow) != 0) { + #ifdef HAVE_SESSION_TICKET + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); + #endif + WOLFSSL_MSG("Session row lock failed"); + return BAD_MUTEX_E; + } + + for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) { + if (XMEMCMP(id, + sessRow->Sessions[i].sessionID, ID_LEN) == 0 && + sessRow->Sessions[i].side == side) { + WOLFSSL_MSG("Session already exists. Overwriting."); + overwrite = 1; + idx = i; + break; } } - else + + if (!overwrite) + idx = sessRow->nextIdx; +#ifdef SESSION_INDEX + if (sessionIndex != NULL) + *sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; #endif - { - /* Use the session object in the cache for external cache if required */ - row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - #endif - return error; - } + cacheSession = &sessRow->Sessions[idx]; + cacheSession->type = WOLFSSL_SESSION_TYPE_CACHE; + cacheSession->cacheRow = row; - sessRow = &SessionCache[row]; - if (SESSION_ROW_LOCK(sessRow) != 0) { - #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - #endif - return BAD_MUTEX_E; - } +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + /* Save the peer field to free after unlocking the row */ + if (cacheSession->peer != NULL) + peer = cacheSession->peer; + cacheSession->peer = NULL; +#endif +#ifdef HAVE_SESSION_TICKET + /* If we can re-use the existing buffer in cacheSession then we won't touch + * ticBuff at all making it a very cheap malloc/free. The page on a modern + * OS will most likely not even be allocated to the process. */ + if (ticBuff != NULL && cacheSession->ticketLenAlloc < ticLen) { + cacheTicBuff = cacheSession->ticket; + ticBuffUsed = 1; + cacheSession->ticket = ticBuff; + cacheSession->ticketLenAlloc = ticLen; + } +#endif +#ifdef SESSION_CERTS + if (overwrite && + addSession->chain.count == 0 && + cacheSession->chain.count > 0) { + /* Copy in the certs from the session */ + addSession->chain.count = cacheSession->chain.count; + XMEMCPY(addSession->chain.certs, cacheSession->chain.certs, + sizeof(x509_buffer) * cacheSession->chain.count); + } +#endif /* SESSION_CERTS */ + cacheSession->heap = NULL; + /* Copy data into the cache object */ + ret = wolfSSL_DupSession(addSession, cacheSession, 1) == WOLFSSL_FAILURE; - for (i=0; iSessions[i].sessionID, ID_LEN) == 0 && - sessRow->Sessions[i].side == ssl->options.side) { - WOLFSSL_MSG("Session already exists. Overwriting."); - overwrite = 1; - idx = i; - break; - } + if (ret == 0) { + /* Increment the totalCount and the nextIdx */ + if (sessRow->totalCount < SESSIONS_PER_ROW) + sessRow->totalCount++; + sessRow->nextIdx = (sessRow->nextIdx + 1) % SESSIONS_PER_ROW; + if (id != addSession->sessionID) { + /* ssl->session->sessionID may contain the bogus ID or we want the + * ID from the arrays object */ + XMEMCPY(cacheSession->sessionID, id, ID_LEN); + cacheSession->sessionIDSz = ID_LEN; } + } +#ifdef HAVE_SESSION_TICKET + else if (ticBuffUsed) { + /* Error occured. Need to clean up the ticket buffer. */ + cacheSession->ticket = cacheSession->_staticTicket; + cacheSession->ticketLenAlloc = 0; + cacheSession->ticketLen = 0; + } +#endif - if (!overwrite) { - idx = sessRow->nextIdx++; - } -#ifdef SESSION_INDEX - ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; + SESSION_ROW_UNLOCK(sessRow); + cacheSession = NULL; /* Can't access after unlocked */ + +#ifndef NO_CLIENT_CACHE + if (ret == 0) { + ClientSession* clientCache = AddSessionToClientCache(side, row, idx, + addSession->serverID, addSession->idLen, id, useTicket); + if (clientCache != NULL && clientCacheEntry != NULL) + *clientCacheEntry = clientCache; + } #endif - session = &sessRow->Sessions[idx]; + +#ifdef HAVE_SESSION_TICKET + if (ticBuff != NULL && !ticBuffUsed) + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); + if (cacheTicBuff != NULL) + XFREE(cacheTicBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (peer != NULL) { + wolfSSL_X509_free(peer); + peer = NULL; /* Make sure not use after this point */ } +#endif + + return ret; +} - session->type = WOLFSSL_SESSION_TYPE_CACHE; - session->cacheRow = row; - session->side = (byte)ssl->options.side; - session->heap = ssl->heap; - session->masterSecret = session->_masterSecret; #ifndef NO_CLIENT_CACHE - session->serverID = session->_serverID; #endif -#ifdef OPENSSL_EXTRA - session->sessionCtx = session->_sessionCtx; + +void AddSession(WOLFSSL* ssl) +{ + int error = 0; + const byte* id = NULL; + byte idSz = 0; + WOLFSSL_SESSION* session = ssl->session; +#ifdef HAVE_EXT_CACHE + int cbRet = 0; #endif -#ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) { - XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN); - session->sessionIDSz = ID_LEN; + (void)error; + + WOLFSSL_ENTER("AddSession"); + + if (SslSessionCacheOff(ssl, session)) { + WOLFSSL_MSG("Cache off"); + return; + } + + if (ssl->options.haveSessionId == 0) { + WOLFSSL_MSG("Don't have session id"); + return; + } + +#if defined(HAVE_SESSION_TICKET) && !defined(OPENSSL_EXTRA) + /* For the compat layer generate a session object to use */ + if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) { + WOLFSSL_MSG("Using tickets instead of cache"); + return; } - else #endif - if (ssl->arrays != NULL) { - XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); - session->sessionIDSz = ssl->arrays->sessionIDSz; + + if (session->haveAltSessionID) { + id = session->altSessionID; + idSz = ID_LEN; + } + else { + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) { + /* Make sure the session ID is available when the user calls any + * get_session API */ + XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); + session->sessionIDSz = ssl->arrays->sessionIDSz; + } + id = session->sessionID; + idSz = session->sessionIDSz; } - XMEMCPY(session->sessionID, id, ID_LEN); - session->haveEMS = ssl->options.haveEMS; + session->timeout = ssl->timeout; + session->side = (byte)ssl->options.side; + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) + XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); + session->haveEMS = ssl->options.haveEMS; #ifdef OPENSSL_EXTRA /* If using compatibility layer then check for and copy over session context * id. */ if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) { - XMEMCPY(session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); + XMEMCPY(ssl->session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); session->sessionCtxSz = ssl->sessionCtxSz; } #endif - session->timeout = ssl->timeout; session->bornOn = LowResTimer(); - -#ifdef HAVE_SESSION_TICKET - /* Check if another thread modified ticket since alloc */ - if ((word16)ticLen != ssl->session.ticketLen) { - error = VAR_STATE_CHANGE_E; - } - if (error == 0) { - /* Cleanup cache row's old Dynamic buff if exists */ - if (session->ticketLenAlloc > 0) { - XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - session->ticket = NULL; - } - - /* If too large to store in static buffer, use dyn buffer */ - if (ticLen > SESSION_TICKET_LEN) { - session->ticket = ticBuff; - session->ticketLenAlloc = (word16)ticLen; - } - else { - session->ticket = session->_staticTicket; - session->ticketLenAlloc = 0; - } - - session->ticketLen = (word16)ticLen; - XMEMCPY(session->ticket, ssl->session.ticket, ticLen); - } - else { /* cleanup, reset state */ - session->ticket = session->_staticTicket; - session->ticketLenAlloc = 0; - session->ticketLen = 0; - if (ticBuff) { - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ticBuff = NULL; - } - } -#endif - -#ifdef SESSION_CERTS - if (error == 0) { - if (!overwrite || ssl->session.chain.count > 0) { - /* 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) * session->chain.count); - } - } -#endif /* SESSION_CERTS */ #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ defined(HAVE_SESSION_TICKET)) - if (error == 0) { - session->version = ssl->version; - } -#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */ + session->version = ssl->version; +#endif #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - if (error == 0) { - session->cipherSuite0 = ssl->options.cipherSuite0; - session->cipherSuite = ssl->options.cipherSuite; - } + session->cipherSuite0 = ssl->options.cipherSuite0; + session->cipherSuite = ssl->options.cipherSuite; #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - if (error == 0) { - session->peerVerifyRet = (byte)ssl->peerVerifyRet; - } -#endif -#if defined(WOLFSSL_TLS13) - if (error == 0) { - session->namedGroup = ssl->session.namedGroup; - } + session->peerVerifyRet = (byte)ssl->peerVerifyRet; +#endif + /* Do this last so that if it fails, the rest of the session is setup. Do + * this only for the client because if the server doesn't have an ID at + * this point, it won't on resumption. */ + if (idSz == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { + WC_RNG* rng = NULL; + if (ssl->rng != NULL) + rng = ssl->rng; +#if defined(HAVE_GLOBAL_RNG) && defined(OPENSSL_EXTRA) + else if (initGlobalRNG == 1 || wolfSSL_RAND_Init() == WOLFSSL_SUCCESS) { + rng = &globalRNG; + } #endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - if (error == 0) { - session->ticketSeen = ssl->session.ticketSeen; - session->ticketAdd = ssl->session.ticketAdd; - XMEMCPY(&session->ticketNonce, &ssl->session.ticketNonce, - sizeof(TicketNonce)); - #ifdef WOLFSSL_EARLY_DATA - session->maxEarlyDataSz = ssl->session.maxEarlyDataSz; - #endif + if (wc_RNG_GenerateBlock(rng, ssl->session->altSessionID, + ID_LEN) != 0) + return; + ssl->session->haveAltSessionID = 1; + id = ssl->session->altSessionID; + idSz = ID_LEN; } -#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */ + /* Setup done */ - if (error == 0 && sessRow != NULL) { - sessRow->totalCount++; - if (sessRow->nextIdx == SESSIONS_PER_ROW) { - sessRow->nextIdx = 0; - } +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + /* Try to add the session to cache. Its ok if we don't succeed. */ + (void)AddSessionToCache(session, id, idSz, +#ifdef SESSION_INDEX + &ssl->sessionIndex, +#else + NULL, +#endif + ssl->options.side, +#ifdef HAVE_SESSION_TICKET + ssl->options.useTicket, +#else + 0, +#endif + NULL + ); } -#ifndef NO_CLIENT_CACHE - if (error == 0) { - if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) { - word32 clientRow, clientIdx; - - WOLFSSL_MSG("Adding client cache entry"); - - session->idLen = ssl->session.idLen; - XMEMCPY(session->serverID, ssl->session.serverID, - ssl->session.idLen); - - if (sessRow != NULL) { - clientRow = HashSession(ssl->session.serverID, - ssl->session.idLen, &error) % SESSION_ROWS; - if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) { - clientIdx = ClientCache[clientRow].nextIdx++; - ClientCache[clientRow].Clients[clientIdx].serverRow = - (word16)row; - ClientCache[clientRow].Clients[clientIdx].serverIdx = - (word16)idx; - ClientCache[clientRow].totalCount++; - if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) { - ClientCache[clientRow].nextIdx = 0; - } - - wc_UnLockMutex(&clisession_mutex); - } - else { - WOLFSSL_MSG("Hash session failed"); - } - } - } - else { - session->idLen = 0; - } +#ifdef HAVE_EXT_CACHE + if (error == 0 && ssl->ctx->new_sess_cb != NULL) { + wolfSSL_SESSION_up_ref(session); + cbRet = ssl->ctx->new_sess_cb(ssl, session); + if (cbRet == 0) + wolfSSL_FreeSession(session); } -#endif /* !NO_CLIENT_CACHE */ - - if (sessRow != NULL) { - SESSION_ROW_UNLOCK(sessRow); +#endif #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) if (error == 0) { @@ -15939,18 +16274,6 @@ int AddSession(WOLFSSL* ssl) } } #endif /* WOLFSSL_SESSION_STATS && WOLFSSL_PEAK_SESSIONS */ - } - -#ifdef HAVE_EXT_CACHE - if (error == 0 && ssl->ctx->new_sess_cb != NULL) { - cbRet = ssl->ctx->new_sess_cb(ssl, session); - } - if (ssl->options.internalCacheOff && cbRet == 0) { - wolfSSL_FreeSession(session); - } -#endif - - return error; } @@ -15971,6 +16294,8 @@ int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex"); + session = ClientSessionToSession(session); + row = idx >> SESSIDX_ROW_SHIFT; col = idx & SESSIDX_IDX_MASK; @@ -16003,7 +16328,8 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); - session = GetSessionPtr(session); + session = ClientSessionToSession(session); + if (session) chain = &session->chain; @@ -16019,7 +16345,7 @@ WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session) { WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); - session = GetSessionPtr(session); + session = ClientSessionToSession(session); if (session) { int count; @@ -16203,6 +16529,11 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, #else /* NO_SESSION_CACHE */ +WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session) +{ + return (WOLFSSL_SESSION*)session; +} + /* No session cache version */ WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts) @@ -16712,6 +17043,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; } @@ -17118,6 +17454,18 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return wolfSSL_CertManagerUnload_trust_peers(ctx->cm); } + +#ifdef WOLFSSL_LOCAL_X509_STORE + int wolfSSL_Unload_trust_peers(WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl)); + } +#endif /* WOLFSSL_LOCAL_X509_STORE */ #endif /* WOLFSSL_TRUST_PEER_CERT */ /* old NO_FILESYSTEM end */ #endif /* !NO_CERTS */ @@ -17440,17 +17788,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 +18152,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ctx->mask = wolf_set_options(ctx->mask, opt); -#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) && \ - defined(OPENSSL_EXTRA) - if (ctx->mask & SSL_OP_NO_TICKET) { - ctx->ticketEncCb = NULL; - ctx->ticketEncCtx = NULL; - WOLFSSL_MSG("\tSSL_OP_NO_TICKET"); - } -#endif - return ctx->mask; } @@ -17893,6 +18222,12 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_MSG("wolfSSL_get_peer_certificate error"); return NULL; } + /* wolfSSL_get_peer_certificate returns a copy. We want the internal + * member so that we don't have to worry about free'ing it. We call + * wolfSSL_get_peer_certificate so that we don't have to worry about + * setting up the internal pointer. */ + wolfSSL_X509_free(peerCert); + peerCert = (WOLFSSL_X509*)&ssl->peerCert; chain = wolfSSL_get_peer_cert_chain(ssl); if (chain == NULL) { WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error"); @@ -20271,7 +20606,7 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, #endif } #ifdef SESSION_CERTS - ssl->session.chain.count = 0; + ssl->session->chain.count = 0; #endif #ifdef KEEP_PEER_CERT FreeX509(&ssl->peerCert); @@ -20647,21 +20982,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 */ @@ -20741,11 +21077,11 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) int ret; WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain"); - if ((ssl == NULL) || (ssl->session.chain.count == 0)) + if ((ssl == NULL) || (ssl->session->chain.count == 0)) return NULL; sk = wolfSSL_sk_X509_new(); - i = ssl->session.chain.count-1; + i = ssl->session->chain.count-1; for (; i >= 0; i--) { x509 = wolfSSL_X509_new(); if (x509 == NULL) { @@ -20753,10 +21089,10 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) wolfSSL_sk_X509_pop_free(sk, NULL); return NULL; } - ret = DecodeToX509(x509, ssl->session.chain.certs[i].buffer, - ssl->session.chain.certs[i].length); + ret = DecodeToX509(x509, ssl->session->chain.certs[i].buffer, + ssl->session->chain.certs[i].length); #if !defined(WOLFSSL_QT) - if (ret == 0 && i == ssl->session.chain.count-1) { + if (ret == 0 && i == ssl->session->chain.count-1) { /* On the last element in the chain try to add the CA chain * first if we have one for this cert */ if (PushCAx509Chain(SSL_CM(ssl), x509, sk) @@ -23573,57 +23909,13 @@ 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; } -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; -#endif - - session = wolfSSL_GetSession(ssl, NULL, 1); - if (session == NULL) { - return session; - } - -#ifdef ENABLE_CLIENT_SESSION_REF - /* if wolfSSL_GetSessionRef has already been called then use existing - * pointer */ - ref = (WOLFSSL_SESSION*)ssl->session.refPtr; - if (ref == NULL) { - ref = (WOLFSSL_SESSION*)XMALLOC(refSize, ssl->heap, - DYNAMIC_TYPE_SESSION); - } - else { - /* use existing ref count */ - refCount = ref->refCount; - } - if (ref == NULL) { - WOLFSSL_MSG("Error allocating client session reference"); - return NULL; - } - - XMEMCPY(ref, session, refSize); - ref->type = WOLFSSL_SESSION_TYPE_REF; - ref->refCount = refCount; - ref->refPtr = (void*)session; - ref->heap = ssl->heap; - ssl->session.refPtr = ref; - session = ref; -#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 +23925,17 @@ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) DYNAMIC_TYPE_SESSION); if (ret != NULL) { XMEMSET(ret, 0, sizeof(WOLFSSL_SESSION)); + #ifndef SINGLE_THREADED + if (wc_InitMutex(&ret->refMutex) != 0) { + WOLFSSL_MSG("Error setting up session reference mutex"); + XFREE(ret, ret->heap, DYNAMIC_TYPE_SESSION); + return NULL; + } + #endif + ret->refCount = 1; +#ifndef NO_SESSION_CACHE + ret->cacheRow = INVALID_SESSION_ROW; /* not in cache */ +#endif ret->type = WOLFSSL_SESSION_TYPE_HEAP; ret->heap = heap; ret->masterSecret = ret->_masterSecret; @@ -23645,30 +23948,27 @@ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) #ifdef HAVE_SESSION_TICKET ret->ticket = ret->_staticTicket; #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 } - (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"); - XFREE(ret, ret->heap, DYNAMIC_TYPE_SESSION); - return NULL; - } -#endif - ret->refCount = 1; - } -#endif - - return ret; + return wolfSSL_NewSession(heap); } + WOLFSSL_SESSION* wolfSSL_SESSION_new(void) { return wolfSSL_SESSION_new_ex(NULL); @@ -23678,24 +23978,181 @@ 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) + session = ClientSessionToSession(session); + + if (session == NULL || session->type != WOLFSSL_SESSION_TYPE_HEAP) return WOLFSSL_FAILURE; -#ifdef OPENSSL_EXTRA #ifndef SINGLE_THREADED if (wc_LockMutex(&session->refMutex) != 0) { WOLFSSL_MSG("Failed to lock session mutex"); + return WOLFSSL_FAILURE; } #endif session->refCount++; #ifndef SINGLE_THREADED wc_UnLockMutex(&session->refMutex); -#endif #endif return WOLFSSL_SUCCESS; } +/** + * Deep copy the contents from input to output. + * @param input The source of the copy. + * @param output The destination of the copy. + * @param avoidSysCalls If true, then system calls will be avoided or an error + * will be returned if it is not possible to proceed + * without a system call. This is useful for fetching + * sessions from cache. When a cache row is locked, we + * don't want to block other threads with long running + * system calls. + * @return WOLFSSL_SUCCESS on success + * WOLFSSL_FAILURE on failure + */ +int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output, + int avoidSysCalls) +{ +#ifdef HAVE_SESSION_TICKET + int ticLenAlloc = 0; + byte *ticBuff = NULL; +#endif + const size_t copyOffset = OFFSETOF(WOLFSSL_SESSION, heap) + sizeof(input->heap); + int ret = WOLFSSL_SUCCESS; + + (void)avoidSysCalls; + + input = ClientSessionToSession(input); + output = ClientSessionToSession(output); + + if (input == NULL || output == NULL || input == output) { + WOLFSSL_MSG("input or output are null or same"); + return WOLFSSL_FAILURE; + } + +#ifdef HAVE_SESSION_TICKET + if (output->ticket != output->_staticTicket) { + ticBuff = output->ticket; + ticLenAlloc = output->ticketLenAlloc; + } +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (output->peer != NULL) { + if (avoidSysCalls) { + WOLFSSL_MSG("Can't free cert when avoiding syscalls"); + return WOLFSSL_FAILURE; + } + wolfSSL_X509_free(output->peer); + output->peer = NULL; + } +#endif + + XMEMCPY((byte*)output + copyOffset, (byte*)input + copyOffset, + sizeof(WOLFSSL_SESSION) - copyOffset); + + /* Set sane values for copy */ + if (output->type != WOLFSSL_SESSION_TYPE_CACHE) +#ifndef NO_SESSION_CACHE + output->cacheRow = INVALID_SESSION_ROW; +#endif +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (input->peer != NULL && input->peer->dynamicMemory) { + if (wolfSSL_X509_up_ref(input->peer) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Can't increase peer cert ref count"); + output->peer = NULL; + } + } + else if (!avoidSysCalls) + output->peer = wolfSSL_X509_dup(input->peer); + else + /* output->peer is not that important to copy */ + output->peer = NULL; +#endif + output->masterSecret = output->_masterSecret; +#ifndef NO_CLIENT_CACHE + output->serverID = output->_serverID; +#endif +#ifdef OPENSSL_EXTRA + output->sessionCtx = output->_sessionCtx; +#endif +#ifdef HAVE_SESSION_TICKET + if (input->ticketLen > SESSION_TICKET_LEN) { + /* Need dynamic buffer */ + if (ticBuff == NULL || ticLenAlloc < input->ticketLen) { + /* allocate new one */ + byte* tmp; + if (!avoidSysCalls) { + WOLFSSL_MSG("Failed to allocate memory for ticket when avoiding" + " syscalls"); + output->ticket = ticBuff; + output->ticketLenAlloc = ticLenAlloc; + output->ticketLen = 0; + ret = WOLFSSL_FAILURE; + } + else { + tmp = (byte*)XREALLOC(ticBuff, input->ticketLen, + output->heap, DYNAMIC_TYPE_SESSION_TICK); + if (tmp == NULL) { + WOLFSSL_MSG("Failed to allocate memory for ticket"); + XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + output->ticket = NULL; + output->ticketLen = 0; + output->ticketLenAlloc = 0; + ret = WOLFSSL_FAILURE; + } + else { + ticBuff = tmp; + ticLenAlloc = input->ticketLen; + } + } + } + if (ticBuff != NULL && ret == WOLFSSL_SUCCESS) { + XMEMCPY(ticBuff, input->ticket, input->ticketLen); + output->ticket = ticBuff; + output->ticketLenAlloc = ticLenAlloc; + } + } + else { + /* Default ticket to non dynamic */ + if (avoidSysCalls) { + /* Try to use ticBuf if available. Caller can later move it to + * the static buffer. */ + if (ticBuff != NULL) { + if (ticLenAlloc >= input->ticketLen) { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } + else { + WOLFSSL_MSG("ticket dynamic buffer too small but we are " + "avoiding system calls"); + ret = WOLFSSL_FAILURE; + output->ticket = ticBuff; + output->ticketLenAlloc = ticLenAlloc; + output->ticketLen = 0; + } + } + else { + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } + } + else { + if (ticBuff != NULL) + XFREE(ticBuff, input->heap, DYNAMIC_TYPE_SESSION_TICK); + output->ticket = output->_staticTicket; + output->ticketLenAlloc = 0; + } + if (input->ticketLenAlloc > 0 && ret == WOLFSSL_SUCCESS) { + /* Shouldn't happen as session should have placed this in + * the static buffer */ + XMEMCPY(output->ticket, input->ticket, + input->ticketLen); + } + } + ticBuff = NULL; +#endif /* HAVE_SESSION_TICKET */ + return ret; +} WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) { @@ -23704,7 +24161,7 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_SESSION_dup"); - session = GetSessionPtr(session); + session = ClientSessionToSession(session); if (session == NULL) return NULL; @@ -23716,39 +24173,10 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) #endif copy = wolfSSL_NewSession(session->heap); - if (copy != NULL) { - 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; - } -#endif - copy->refCount = 1; -#endif -#ifdef HAVE_SESSION_TICKET - if (session->ticketLenAlloc > 0) { - copy->ticket = (byte*)XMALLOC(session->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); -#endif + if (copy != NULL && + wolfSSL_DupSession(session, copy, 0) != WOLFSSL_SUCCESS) { + wolfSSL_FreeSession(copy); + copy = NULL; } return copy; #else @@ -23758,44 +24186,19 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) #endif /* HAVE_EXT_CACHE */ } -#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */ - void wolfSSL_FreeSession(WOLFSSL_SESSION* session) { + session = ClientSessionToSession(session); if (session == NULL) return; -#ifdef ENABLE_CLIENT_SESSION_REF - if (session->type == WOLFSSL_SESSION_TYPE_REF) { - WOLFSSL_SESSION* ref; - session->refCount--; - if (session->refCount > 0) { - return; /* don't free yet */ - } - ref = session; - session = (WOLFSSL_SESSION*)session->refPtr; - XFREE(ref, ref->heap, DYNAMIC_TYPE_SESSION); - } -#endif - -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS - wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); -#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) { #ifndef SINGLE_THREADED if (wc_LockMutex(&session->refMutex) != 0) { WOLFSSL_MSG("Failed to lock session mutex"); + return; } #endif if (session->refCount > 1) { @@ -23807,7 +24210,18 @@ 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 @@ -23817,6 +24231,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); } @@ -23824,9 +24242,46 @@ void wolfSSL_FreeSession(WOLFSSL_SESSION* session) void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) { + session = ClientSessionToSession(session); wolfSSL_FreeSession(session); } +#ifndef NO_SESSION_CACHE +int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + int error = 0; + const byte* id = NULL; + byte idSz = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_add_session"); + + session = ClientSessionToSession(session); + if (session == NULL) + return WOLFSSL_FAILURE; + + /* Session cache is global */ + (void)ctx; + + id = session->sessionID; + idSz = session->sessionIDSz; + if (session->haveAltSessionID) { + id = session->altSessionID; + idSz = ID_LEN; + } + + error = AddSessionToCache(session, id, idSz, + NULL, session->side, +#ifdef HAVE_SESSION_TICKET + session->ticketLen > 0, +#else + 0, +#endif + NULL); + + return error == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} +#endif + #if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) /** @@ -23840,8 +24295,8 @@ int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, { WOLFSSL_ENTER("wolfSSL_SESSION_set_cipher"); + session = ClientSessionToSession(session); /* sanity check */ - session = GetSessionPtr(session); if (session == NULL || cipher == NULL) { WOLFSSL_MSG("bad argument"); return WOLFSSL_FAILURE; @@ -23988,9 +24443,9 @@ const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher) return wolfSSL_get_version(cipher->ssl); } -const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session) +const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session) { - session = GetSessionPtr(session); + session = ClientSessionToSession(session); if (session == NULL) { return NULL; } @@ -26466,6 +26921,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 +29725,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]; + } } /* @@ -29545,8 +30004,8 @@ long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) #if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) const unsigned char *SSL_SESSION_get0_id_context(const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length) { - const byte *c = wolfSSL_SESSION_get_id((WOLFSSL_SESSION *)sess, sid_ctx_length); - return c; + sess = ClientSessionToSession(sess); + return wolfSSL_SESSION_get_id((WOLFSSL_SESSION *)sess, sid_ctx_length); } #endif @@ -30706,6 +31165,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 +31674,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,7 +32594,9 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) #endif unsigned char *data; - sess = GetSessionPtr(sess); + WOLFSSL_ENTER("wolfSSL_i2d_SSL_SESSION"); + + sess = ClientSessionToSession(sess); if (sess == NULL) { return BAD_FUNC_ARG; } @@ -32141,6 +32605,8 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) * haveEMS */ size += OPAQUE8_LEN + OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz + SECRET_LEN + OPAQUE8_LEN; + /* altSessionID */ + size += OPAQUE8_LEN + (sess->haveAltSessionID ? ID_LEN : 0); #ifdef SESSION_CERTS /* Peer chain */ size += OPAQUE8_LEN; @@ -32204,6 +32670,11 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) idx += sess->sessionIDSz; XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN; data[idx++] = (byte)sess->haveEMS; + data[idx++] = sess->haveAltSessionID ? ID_LEN : 0; + if (sess->haveAltSessionID) { + XMEMCPY(data + idx, sess->altSessionID, ID_LEN); + idx += ID_LEN; + } #ifdef SESSION_CERTS data[idx++] = (byte)sess->chain.count; for (i = 0; i < sess->chain.count; i++) { @@ -32298,23 +32769,15 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, (void)p; (void)i; (void)ret; - - if (sess != NULL) { - s = GetSessionPtr(*sess); - } + (void)sess; #ifdef HAVE_EXT_CACHE if (p == NULL || *p == NULL) return NULL; - if (s == NULL) { - s = wolfSSL_SESSION_new(); - if (s == NULL) - return NULL; -#ifdef HAVE_SESSION_TICKET - s->ticketLenAlloc = 0; -#endif - } + s = wolfSSL_SESSION_new(); + if (s == NULL) + return NULL; idx = 0; data = (byte*)*p; @@ -32329,8 +32792,8 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN; s->sessionIDSz = data[idx++]; - /* sessionID | secret | haveEMS */ - if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) { + /* sessionID | secret | haveEMS | haveAltSessionID */ + if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN + OPAQUE8_LEN) { ret = BUFFER_ERROR; goto end; } @@ -32338,6 +32801,20 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, idx += s->sessionIDSz; XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN; s->haveEMS = data[idx++]; + if (data[idx] != ID_LEN && data[idx] != 0) { + ret = BUFFER_ERROR; + goto end; + } + s->haveAltSessionID = data[idx++] == ID_LEN; + + /* altSessionID */ + if (s->haveAltSessionID) { + if (i - idx < ID_LEN) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->altSessionID, data + idx, ID_LEN); idx += ID_LEN; + } #ifdef SESSION_CERTS /* Certificate chain */ @@ -32492,8 +32969,9 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, #endif (void)idx; - if (sess != NULL) + if (sess != NULL) { *sess = s; + } *p += idx; @@ -32515,7 +32993,7 @@ int wolfSSL_SESSION_has_ticket(const WOLFSSL_SESSION* sess) { WOLFSSL_ENTER("wolfSSL_SESSION_has_ticket"); #ifdef HAVE_SESSION_TICKET - sess = GetSessionPtr(sess); + sess = ClientSessionToSession(sess); if (sess) { if ((sess->ticketLen > 0) && (sess->ticket != NULL)) { return WOLFSSL_SUCCESS; @@ -32531,7 +33009,7 @@ unsigned long wolfSSL_SESSION_get_ticket_lifetime_hint( const WOLFSSL_SESSION* sess) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ticket_lifetime_hint"); - sess = GetSessionPtr(sess); + sess = ClientSessionToSession(sess); if (sess) { return sess->timeout; } @@ -32542,7 +33020,7 @@ long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) { long timeout = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); - sess = GetSessionPtr(sess); + sess = ClientSessionToSession(sess); if (sess) timeout = sess->timeout; return timeout; @@ -32553,7 +33031,7 @@ long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) { long bornOn = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); - sess = GetSessionPtr(sess); + sess = ClientSessionToSession(sess); if (sess) bornOn = sess->bornOn; return bornOn; @@ -32563,7 +33041,7 @@ long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) { word32 tmptime; - ses = GetSessionPtr(ses); + ses = ClientSessionToSession(ses); if (ses == NULL || t < 0) { return BAD_FUNC_ARG; } @@ -34279,11 +34757,16 @@ int wolfSSL_DH_set0_pqg(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *p, /* free existing internal DH structure and recreate with new p / g */ if (dh->inSet) { +#ifndef HAVE_SELFTEST ret = wc_FreeDhKey((DhKey*)dh->internal); if (ret != 0) { WOLFSSL_MSG("Unable to free internal DH key"); return WOLFSSL_FAILURE; } +#else + /* Selftest code has this API with a void return type */ + wc_FreeDhKey((DhKey*)dh->internal); +#endif } wolfSSL_BN_free(dh->p); @@ -40310,10 +40793,6 @@ int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) } /* End ECDSA_SIG */ - -/* Remove this prototype when code is reorganized. */ -static int wolfSSL_RAND_Init(void); - /* Start ECDH */ /* return code compliant with OpenSSL : * length of computed key if success, -1 if error @@ -42474,6 +42953,7 @@ int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa) #ifndef SINGLE_THREADED if (wc_LockMutex(&rsa->refMutex) != 0) { WOLFSSL_MSG("Failed to lock x509 mutex"); + return WOLFSSL_FAILURE; } #endif rsa->refCount++; @@ -42494,6 +42974,7 @@ int wolfSSL_X509_up_ref(WOLFSSL_X509* x509) #ifndef SINGLE_THREADED if (wc_LockMutex(&x509->refMutex) != 0) { WOLFSSL_MSG("Failed to lock x509 mutex"); + return WOLFSSL_FAILURE; } #endif x509->refCount++; @@ -42537,7 +43018,7 @@ WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain"); if (ssl) - return &ssl->session.altChain; + return &ssl->session->altChain; return 0; } @@ -42549,7 +43030,7 @@ WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_get_peer_chain"); if (ssl) - return &ssl->session.chain; + return &ssl->session->chain; return 0; } @@ -42718,6 +43199,7 @@ WOLFSSL_ABI const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session) { WOLFSSL_ENTER("wolfSSL_get_sessionID"); + session = ClientSessionToSession(session); if (session) return session->sessionID; @@ -45568,17 +46050,11 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) } else { #ifdef WOLFSSL_HAVE_ERROR_QUEUE - int err = (int)wolfSSL_ERR_peek_last_error(); - if (ERR_GET_LIB(err) == ERR_LIB_PEM && - ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { - /* - * wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio pushes an - * ASN_NO_PEM_HEADER error to the error queue on file end. - * This should not be left for the caller to find so we - * clear the last error. This also indicates that nothing - * more was found in the BIO. - */ - wc_RemoveErrorNode(-1); + unsigned long err; + CLEAR_ASN_NO_PEM_HEADER_ERROR(err); + if (ERR_GET_LIB(err) != ERR_LIB_PEM || + ERR_GET_REASON(err) != PEM_R_NO_START_LINE) { + ret = WOLFSSL_FAILURE; } #else if (wolfSSL_sk_X509_INFO_num(localSk) > 0) { @@ -45586,10 +46062,10 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) "Assuming error means EOF or no more PEM" "headers found."); } -#endif else { ret = WOLFSSL_FAILURE; } +#endif break; } } @@ -46988,6 +47464,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 +47479,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 +48794,18 @@ 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); - } + session = ClientSessionToSession(session); + if (session != NULL) + ret = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data); #else (void)session; (void)idx; (void)data; #endif - return WOLFSSL_FAILURE; + return ret; } #ifdef HAVE_EX_DATA_CLEANUP_HOOKS @@ -48337,6 +48816,7 @@ int wolfSSL_SESSION_set_ex_data_with_cleanup( wolfSSL_ex_data_cleanup_routine_t cleanup_routine) { WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data_with_cleanup"); + session = ClientSessionToSession(session); if(session != NULL) { return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&session->ex_data, idx, data, cleanup_routine); @@ -48349,6 +48829,7 @@ void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); #ifdef HAVE_EX_DATA + session = ClientSessionToSession(session); if (session != NULL) { return wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx); } @@ -48526,6 +49007,7 @@ void wolfSSL_sk_X509_NAME_ENTRY_free(WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk) (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) +#ifdef HAVE_EX_DATA int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, CRYPTO_free_func* cb3) { @@ -48534,23 +49016,62 @@ 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); +} +#endif + +#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 +49585,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 +49800,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"); @@ -49334,10 +49842,11 @@ WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) -const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) +const byte* wolfSSL_SESSION_get_id(const WOLFSSL_SESSION* sess, + unsigned int* idLen) { WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); - sess = GetSessionPtr(sess); + sess = ClientSessionToSession(sess); if (sess == NULL || idLen == NULL) { WOLFSSL_MSG("Bad func args. Please provide idLen"); return NULL; @@ -49356,6 +49865,7 @@ const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) /* returns a pointer to the protocol used by the session */ static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in) { + in = ClientSessionToSession(in); return wolfSSL_internal_get_version((ProtocolVersion*)&in->version); } #endif @@ -49363,6 +49873,7 @@ static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in) /* returns true (non 0) if the session has EMS (extended master secret) */ static int wolfSSL_SESSION_haveEMS(const WOLFSSL_SESSION* in) { + in = ClientSessionToSession(in); if (in == NULL) return 0; return in->haveEMS; @@ -49380,6 +49891,7 @@ static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio, byte* pt; + in = ClientSessionToSession(in); if (in == NULL || bio == NULL) { return BAD_FUNC_ARG; } @@ -49444,14 +49956,14 @@ static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio, /* prints out the session information in human readable form * return WOLFSSL_SUCCESS on success */ -int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *x) +int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *session) { const unsigned char* pt; unsigned char buf[SECRET_LEN]; unsigned int sz = 0, i; int ret; - WOLFSSL_SESSION* session = GetSessionPtr(x); + session = ClientSessionToSession(session); if (session == NULL) { return WOLFSSL_FAILURE; } @@ -50872,6 +51384,7 @@ int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s) { WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session"); + s = ClientSessionToSession(s); if (ctx == NULL || s == NULL) return BAD_FUNC_ARG; @@ -50978,21 +51491,9 @@ int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl) WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) { - WOLFSSL_SESSION *session; - WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); - if (ssl == NULL) { - return NULL; - } - - session = wolfSSL_get_session((WOLFSSL*)ssl); - -#ifdef HAVE_EXT_CACHE - ((WOLFSSL*)ssl)->extSession = session; -#endif - - return session; + return ssl->session; } #endif /* NO_SESSION_CACHE */ @@ -51234,8 +51735,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; } @@ -51717,13 +52221,19 @@ int wolfSSL_sk_WOLFSSL_STRING_num(WOLF_STACK_OF(WOLFSSL_STRING)* strings) #endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ + defined(KEEP_PEER_CERT) WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x) { WOLFSSL_ENTER("wolfSSL_X509_dup"); - 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; } @@ -57315,7 +57825,7 @@ int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx) */ int wolfSSL_SESSION_is_resumable(const WOLFSSL_SESSION *s) { - s = GetSessionPtr(s); + s = ClientSessionToSession(s); if (s == NULL) return 0; @@ -60490,7 +61000,7 @@ static int wolfSSL_RAND_InitMutex(void) * * Returns WOLFSSL_SUCCESS when no error is encountered. */ -static int wolfSSL_RAND_Init(void) +int wolfSSL_RAND_Init(void) { int ret = WOLFSSL_FAILURE; #ifdef HAVE_GLOBAL_RNG @@ -62130,6 +62640,7 @@ int wolfSSL_X509_STORE_up_ref(WOLFSSL_X509_STORE* store) #ifndef SINGLE_THREADED if (wc_LockMutex(&store->refMutex) != 0) { WOLFSSL_MSG("Failed to lock store mutex"); + return WOLFSSL_FAILURE; } #endif store->refCount++; @@ -63549,8 +64060,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 +64070,43 @@ WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) return NULL; } - localPkcs12 = wc_PKCS12_new(); - if (localPkcs12 == NULL) { - WOLFSSL_MSG("Memory error"); + memSz = wolfSSL_BIO_get_len(bio); + if (memSz <= 0) { + return NULL; + } + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { return NULL; } - if (pkcs12 != NULL) { - *pkcs12 = localPkcs12; + if (mem != NULL) { + localPkcs12 = wc_PKCS12_new(); + if (localPkcs12 == NULL) { + WOLFSSL_MSG("Memory error"); + } } - ret = wolfSSL_BIO_get_mem_data(bio, &mem); - if (mem == NULL || ret <= 0) { - WOLFSSL_MSG("Failed to get data from bio struct"); - wc_PKCS12_free(localPkcs12); - if (pkcs12 != NULL) { - *pkcs12 = NULL; + if (mem != NULL && localPkcs12 != NULL) { + if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { + ret = wc_d2i_PKCS12(mem, (word32)memSz, localPkcs12); + if (ret < 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + } + } + else { + WOLFSSL_MSG("Failed to get data from bio struct"); } - return NULL; } - size = ret; - ret = wc_d2i_PKCS12(mem, size, localPkcs12); - if (ret < 0) { - WOLFSSL_MSG("Failed to get PKCS12 sequence"); + /* cleanup */ + if (mem != NULL) + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0 && localPkcs12 != NULL) { wc_PKCS12_free(localPkcs12); - if (pkcs12 != NULL) { - *pkcs12 = NULL; - } - return NULL; + localPkcs12 = NULL; } + if (pkcs12 != NULL) + *pkcs12 = localPkcs12; return localPkcs12; } diff --git a/src/tls.c b/src/tls.c index d0802ff554..433605a44a 100644 --- a/src/tls.c +++ b/src/tls.c @@ -7698,7 +7698,7 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) int ret; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - ssl->session.namedGroup = (byte)keyShareEntry->group; + ssl->session->namedGroup = (byte)keyShareEntry->group; #endif /* reset the pre master secret size */ if (ssl->arrays->preMasterSz == 0) @@ -7943,7 +7943,7 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* Process the entry to calculate the secret. */ ret = TLSX_KeyShare_Process(ssl, keyShareEntry); if (ret == 0) - ssl->session.namedGroup = ssl->namedGroup = group; + ssl->session->namedGroup = ssl->namedGroup = group; } else if (msgType == hello_retry_request) { if (length != OPAQUE16_LEN) @@ -9122,10 +9122,10 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, const byte* input, #ifdef HAVE_SESSION_TICKET if (list->resumption) { /* Check that the session's details are the same as the server's. */ - if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 || - ssl->options.cipherSuite != ssl->session.cipherSuite || - ssl->session.version.major != ssl->ctx->method->version.major || - ssl->session.version.minor != ssl->ctx->method->version.minor) { + if (ssl->options.cipherSuite0 != ssl->session->cipherSuite0 || + ssl->options.cipherSuite != ssl->session->cipherSuite || + ssl->session->version.major != ssl->ctx->method->version.major || + ssl->session->version.minor != ssl->ctx->method->version.minor) { return PSK_KEY_ERROR; } } @@ -9636,7 +9636,7 @@ static int TLSX_EarlyData_Parse(WOLFSSL* ssl, const byte* input, word16 length, return BUFFER_E; ato32(input, &maxSz); - ssl->session.maxEarlyDataSz = maxSz; + ssl->session->maxEarlyDataSz = maxSz; return 0; } @@ -10195,8 +10195,8 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) int ret = WOLFSSL_SUCCESS; #ifdef WOLFSSL_TLS13 #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (ssl->options.resuming && ssl->session.namedGroup != 0) { - return TLSX_UseSupportedCurve(extensions, ssl->session.namedGroup, + if (ssl->options.resuming && ssl->session->namedGroup != 0) { + return TLSX_UseSupportedCurve(extensions, ssl->session->namedGroup, ssl->heap); } #endif @@ -10600,8 +10600,8 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); if (extension == NULL) { #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (ssl->options.resuming && ssl->session.namedGroup != 0) - namedGroup = ssl->session.namedGroup; + if (ssl->options.resuming && ssl->session->namedGroup != 0) + namedGroup = ssl->session->namedGroup; else #endif if (ssl->numGroups > 0) { @@ -10647,8 +10647,8 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); #endif #if defined(HAVE_SESSION_TICKET) - if (ssl->options.resuming && ssl->session.ticketLen > 0) { - WOLFSSL_SESSION* sess = &ssl->session; + if (ssl->options.resuming && ssl->session->ticketLen > 0) { + WOLFSSL_SESSION* sess = ssl->session; word32 now, milli; if (sess->ticketLen > MAX_PSK_ID_LEN) { diff --git a/src/tls13.c b/src/tls13.c index de194bcde5..a9571415b0 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -807,7 +807,7 @@ int DeriveResumptionSecret(WOLFSSL* ssl, byte* key) masterSecret = ssl->arrays->masterSecret; } else { - masterSecret = ssl->session.masterSecret; + masterSecret = ssl->session->masterSecret; } return DeriveKey(ssl, key, -1, masterSecret, resumeMasterLabel, RESUME_MASTER_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -1014,7 +1014,7 @@ int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret) PRIVATE_KEY_UNLOCK(); ret = wc_Tls13_HKDF_Expand_Label(secret, ssl->specs.hash_size, - ssl->session.masterSecret, ssl->specs.hash_size, + ssl->session->masterSecret, ssl->specs.hash_size, protocol, protocolLen, resumptionLabel, RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg); PRIVATE_KEY_LOCK(); @@ -2772,13 +2772,13 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello) } #ifdef WOLFSSL_EARLY_DATA - if (ssl->session.maxEarlyDataSz == 0) + if (ssl->session->maxEarlyDataSz == 0) ssl->earlyData = no_early_data; #endif /* Resumption PSK is master secret. */ ssl->arrays->psk_keySz = ssl->specs.hash_size; - if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data, - ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) { + if ((ret = DeriveResumptionPSK(ssl, ssl->session->ticketNonce.data, + ssl->session->ticketNonce.len, ssl->arrays->psk_key)) != 0) { return ret; } } @@ -3049,15 +3049,15 @@ int SendTls13ClientHello(WOLFSSL* ssl) #ifdef HAVE_SESSION_TICKET if (ssl->options.resuming && - (ssl->session.version.major != ssl->version.major || - ssl->session.version.minor != ssl->version.minor)) { + (ssl->session->version.major != ssl->version.major || + ssl->session->version.minor != ssl->version.minor)) { #ifndef WOLFSSL_NO_TLS12 - if (ssl->session.version.major == ssl->version.major && - ssl->session.version.minor < ssl->version.minor) { + if (ssl->session->version.major == ssl->version.major && + ssl->session->version.minor < ssl->version.minor) { /* Cannot resume with a different protocol version. */ ssl->options.resuming = 0; - ssl->version.major = ssl->session.version.major; - ssl->version.minor = ssl->session.version.minor; + ssl->version.major = ssl->session->version.major; + ssl->version.minor = ssl->session->version.minor; return SendClientHello(ssl); } else @@ -3097,8 +3097,8 @@ int SendTls13ClientHello(WOLFSSL* ssl) #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) args->length += ID_LEN; #else - if (ssl->session.sessionIDSz > 0) - args->length += ssl->session.sessionIDSz; + if (ssl->session->sessionIDSz > 0) + args->length += ssl->session->sessionIDSz; #endif /* Advance state and proceed */ @@ -3179,11 +3179,11 @@ int SendTls13ClientHello(WOLFSSL* ssl) XMEMCPY(args->output + args->idx, ssl->arrays->clientRandom, RAN_LEN); args->idx += RAN_LEN; - if (ssl->session.sessionIDSz > 0) { + if (ssl->session->sessionIDSz > 0) { /* Session resumption for old versions of protocol. */ args->output[args->idx++] = ID_LEN; - XMEMCPY(args->output + args->idx, ssl->session.sessionID, - ssl->session.sessionIDSz); + XMEMCPY(args->output + args->idx, ssl->session->sessionID, + ssl->session->sessionIDSz); args->idx += ID_LEN; } else { @@ -3255,7 +3255,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) #endif ret = SendBuffered(ssl); - break; + break; } default: ret = INPUT_CASE_ERROR; @@ -3514,7 +3514,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_SECRET_CALLBACK if (ssl->sessionSecretCb != NULL) { int secretSz = SECRET_LEN; - ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, + ret = ssl->sessionSecretCb(ssl, ssl->session->masterSecret, &secretSz, ssl->sessionSecretCtx); if (ret != 0 || secretSz != SECRET_LEN) { return SESSION_SECRET_CB_E; @@ -3562,22 +3562,26 @@ 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, + } + 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 - if (args->sessIdSz != ssl->session.sessionIDSz || (args->sessIdSz > 0 && - XMEMCMP(ssl->session.sessionID, args->sessId, args->sessIdSz) != 0)) + if (args->sessIdSz != ssl->session->sessionIDSz || (args->sessIdSz > 0 && + XMEMCMP(ssl->session->sessionID, args->sessId, args->sessIdSz) != 0)) { WOLFSSL_MSG("Server sent different session id"); return INVALID_PARAMETER; @@ -3940,7 +3944,7 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, byte* suite, int* err) ssl->options.verifyPeer = 0; /* PSK age is always zero. */ - if (psk->ticketAge != ssl->session.ticketAdd) { + if (psk->ticketAge != ssl->session->ticketAdd) { ret = PSK_KEY_ERROR; } } @@ -4012,7 +4016,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) /* Difference between now and time ticket constructed * (from decrypted ticket). */ diff = now; - diff -= ssl->session.ticketSeen; + diff -= ssl->session->ticketSeen; if (diff > (sword64)ssl->timeout * 1000 || diff > (sword64)TLS13_MAX_TICKET_AGE * 1000) { current = current->next; @@ -4020,7 +4024,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) } /* Subtract client's ticket age and unobfuscate. */ diff -= current->ticketAge; - diff += ssl->session.ticketAdd; + diff += ssl->session->ticketAdd; /* Check session and ticket age timeout. * Allow +/- 1000 milliseconds on ticket age. */ @@ -4033,14 +4037,14 @@ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) /* Check whether resumption is possible based on suites in SSL and * ciphersuite in ticket. */ - if ((suite[0] != ssl->session.cipherSuite0) || - (suite[1] != ssl->session.cipherSuite)) { + if ((suite[0] != ssl->session->cipherSuite0) || + (suite[1] != ssl->session->cipherSuite)) { current = current->next; continue; } #else - suite[0] = ssl->session.cipherSuite0; - suite[1] = ssl->session.cipherSuite; + suite[0] = ssl->session->cipherSuite0; + suite[1] = ssl->session->cipherSuite; if (!FindSuiteSSL(ssl, suite)) { current = current->next; continue; @@ -4048,19 +4052,19 @@ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) #endif #ifdef WOLFSSL_EARLY_DATA - ssl->options.maxEarlyDataSz = ssl->session.maxEarlyDataSz; + ssl->options.maxEarlyDataSz = ssl->session->maxEarlyDataSz; #endif /* Use the same cipher suite as before and set up for use. */ - ssl->options.cipherSuite0 = ssl->session.cipherSuite0; - ssl->options.cipherSuite = ssl->session.cipherSuite; + ssl->options.cipherSuite0 = ssl->session->cipherSuite0; + ssl->options.cipherSuite = ssl->session->cipherSuite; ret = SetCipherSpecs(ssl); if (ret != 0) return ret; /* Resumption PSK is resumption master secret. */ ssl->arrays->psk_keySz = ssl->specs.hash_size; - if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data, - ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) { + if ((ret = DeriveResumptionPSK(ssl, ssl->session->ticketNonce.data, + ssl->session->ticketNonce.len, ssl->arrays->psk_key)) != 0) { return ret; } @@ -4269,7 +4273,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe && ext != NULL) { /* Only use named group used in last session. */ - ssl->namedGroup = ssl->session.namedGroup; + ssl->namedGroup = ssl->session->namedGroup; *usingPSK = 2; /* generate new ephemeral key */ } @@ -4400,7 +4404,7 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) return ret; /* Reconstruct the HelloRetryMessage for handshake hash. */ - length = HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz + + length = HRR_BODY_SZ - ID_LEN + ssl->session->sessionIDSz + HRR_COOKIE_HDR_SZ + cookie->len; length += HRR_VERSIONS_SZ; if (cookieDataSz > hashSz + OPAQUE16_LEN) { @@ -4421,10 +4425,10 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) XMEMCPY(hrr + hrrIdx, helloRetryRequestRandom, RAN_LEN); hrrIdx += RAN_LEN; - hrr[hrrIdx++] = ssl->session.sessionIDSz; - if (ssl->session.sessionIDSz > 0) { - XMEMCPY(hrr + hrrIdx, ssl->session.sessionID, ssl->session.sessionIDSz); - hrrIdx += ssl->session.sessionIDSz; + hrr[hrrIdx++] = ssl->session->sessionIDSz; + if (ssl->session->sessionIDSz > 0) { + XMEMCPY(hrr + hrrIdx, ssl->session->sessionID, ssl->session->sessionIDSz); + hrrIdx += ssl->session->sessionIDSz; } /* Cipher Suite */ @@ -4435,7 +4439,7 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) hrr[hrrIdx++] = 0; /* Extensions' length */ - length -= HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz; + length -= HRR_BODY_SZ - ID_LEN + ssl->session->sessionIDSz; c16toa(length, hrr + hrrIdx); hrrIdx += 2; @@ -4713,9 +4717,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(BUFFER_ERROR, exit_dch); } - ssl->session.sessionIDSz = sessIdSz; + ssl->session->sessionIDSz = sessIdSz; if (sessIdSz == ID_LEN) { - XMEMCPY(ssl->session.sessionID, input + args->idx, sessIdSz); + XMEMCPY(ssl->session->sessionID, input + args->idx, sessIdSz); args->idx += ID_LEN; } @@ -4969,7 +4973,7 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) /* Protocol version, server random, session id, cipher suite, compression * and extensions. */ - length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session.sessionIDSz + + length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session->sessionIDSz + SUITE_LEN + COMP_LEN; ret = TLSX_GetResponseSize(ssl, extMsgType, &length); if (ret != 0) @@ -5010,10 +5014,10 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN); #endif - output[idx++] = ssl->session.sessionIDSz; - if (ssl->session.sessionIDSz > 0) { - XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz); - idx += ssl->session.sessionIDSz; + output[idx++] = ssl->session->sessionIDSz; + if (ssl->session->sessionIDSz > 0) { + XMEMCPY(output + idx, ssl->session->sessionID, ssl->session->sessionIDSz); + idx += ssl->session->sessionIDSz; } /* Chosen cipher suite */ @@ -7140,7 +7144,7 @@ static int SendTls13Finished(WOLFSSL* ssl) return ret; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); + ret = DeriveResumptionSecret(ssl, ssl->session->masterSecret); if (ret != 0) return ret; #endif @@ -7472,18 +7476,18 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, return now; /* Copy in ticket data (server identity). */ ssl->timeout = lifetime; - ssl->session.timeout = lifetime; - ssl->session.cipherSuite0 = ssl->options.cipherSuite0; - ssl->session.cipherSuite = ssl->options.cipherSuite; - ssl->session.ticketSeen = now; - ssl->session.ticketAdd = ageAdd; + ssl->session->timeout = lifetime; + ssl->session->cipherSuite0 = ssl->options.cipherSuite0; + ssl->session->cipherSuite = ssl->options.cipherSuite; + ssl->session->ticketSeen = now; + ssl->session->ticketAdd = ageAdd; #ifdef WOLFSSL_EARLY_DATA - ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + ssl->session->maxEarlyDataSz = ssl->options.maxEarlyDataSz; #endif - ssl->session.ticketNonce.len = nonceLength; + ssl->session->ticketNonce.len = nonceLength; if (nonceLength > 0) - XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength); - ssl->session.namedGroup = ssl->namedGroup; + XMEMCPY(&ssl->session->ticketNonce.data, nonce, nonceLength); + ssl->session->namedGroup = ssl->namedGroup; if ((*inOutIdx - begin) + EXTS_SZ > size) return BUFFER_ERROR; @@ -7588,7 +7592,7 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl) if ((ret = HashRaw(ssl, mac, finishedSz)) != 0) return ret; - if ((ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret)) != 0) + if ((ret = DeriveResumptionSecret(ssl, ssl->session->masterSecret)) != 0) return ret; /* Restore the hash inline with currently seen messages. */ @@ -7652,12 +7656,12 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) #endif /* Start ticket nonce at 0 and go up to 255. */ - if (ssl->session.ticketNonce.len == 0) { - ssl->session.ticketNonce.len = DEF_TICKET_NONCE_SZ; - ssl->session.ticketNonce.data[0] = 0; + if (ssl->session->ticketNonce.len == 0) { + ssl->session->ticketNonce.len = DEF_TICKET_NONCE_SZ; + ssl->session->ticketNonce.data[0] = 0; } else - ssl->session.ticketNonce.data[0]++; + ssl->session->ticketNonce.data[0]++; if (!ssl->options.noTicketTls13) { if ((ret = CreateTicket(ssl)) != 0) @@ -7665,9 +7669,9 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) } #ifdef WOLFSSL_EARLY_DATA - ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz; - if (ssl->session.maxEarlyDataSz > 0) - TLSX_EarlyData_Use(ssl, ssl->session.maxEarlyDataSz); + ssl->session->maxEarlyDataSz = ssl->options.maxEarlyDataSz; + if (ssl->session->maxEarlyDataSz > 0) + TLSX_EarlyData_Use(ssl, ssl->session->maxEarlyDataSz); extSz = 0; ret = TLSX_GetResponseSize(ssl, session_ticket, &extSz); if (ret != 0) @@ -7678,7 +7682,7 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) /* Lifetime | Age Add | Ticket | Extensions */ length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ + - ssl->session.ticketLen + extSz; + ssl->session->ticketLen + extSz; /* Nonce */ length += TICKET_NONCE_LEN_SZ + DEF_TICKET_NONCE_SZ; sendSz = idx + length + MAX_MSG_EXTRA; @@ -7698,18 +7702,18 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) c32toa(ssl->ctx->ticketHint, output + idx); idx += SESSION_HINT_SZ; /* Age add - obfuscator */ - c32toa(ssl->session.ticketAdd, output + idx); + c32toa(ssl->session->ticketAdd, output + idx); idx += SESSION_ADD_SZ; - output[idx++] = ssl->session.ticketNonce.len; - output[idx++] = ssl->session.ticketNonce.data[0]; + output[idx++] = ssl->session->ticketNonce.len; + output[idx++] = ssl->session->ticketNonce.data[0]; /* length */ - c16toa(ssl->session.ticketLen, output + idx); + c16toa(ssl->session->ticketLen, output + idx); idx += LENGTH_SZ; /* ticket */ - XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); - idx += ssl->session.ticketLen; + XMEMCPY(output + idx, ssl->session->ticket, ssl->session->ticketLen); + idx += ssl->session->ticketLen; #ifdef WOLFSSL_EARLY_DATA extSz = 0; @@ -8405,7 +8409,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifndef NO_WOLFSSL_SERVER #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (ssl->options.side == WOLFSSL_SERVER_END && type == finished) { - ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); + ret = DeriveResumptionSecret(ssl, ssl->session->masterSecret); if (ret != 0) return ret; } @@ -9929,8 +9933,8 @@ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) if (ssl->options.handShakeState == CLIENT_HELLO_COMPLETE) { #ifdef OPENSSL_EXTRA /* when processed early data exceeds max size */ - if (ssl->session.maxEarlyDataSz > 0 && - (ssl->earlyDataSz + sz > ssl->session.maxEarlyDataSz)) { + if (ssl->session->maxEarlyDataSz > 0 && + (ssl->earlyDataSz + sz > ssl->session->maxEarlyDataSz)) { ssl->error = TOO_MUCH_EARLY_DATA; return WOLFSSL_FATAL_ERROR; } diff --git a/tests/api.c b/tests/api.c index bfeb664413..e6db580d19 100644 --- a/tests/api.c +++ b/tests/api.c @@ -914,47 +914,66 @@ static void test_wolfSSL_CTX_trust_peer_cert(void) #if !defined(NO_CERTS) && defined(WOLFSSL_TRUST_PEER_CERT) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx; + WOLFSSL* ssl; AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + AssertNotNull(ssl = wolfSSL_new(ctx)); #if !defined(NO_FILESYSTEM) /* invalid file */ - assert(wolfSSL_CTX_trust_peer_cert(ctx, NULL, - WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS); - assert(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, - WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS); - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, - WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_trust_peer_cert(ctx, NULL, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* success */ - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM) - == WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* unload cert */ - assert(wolfSSL_CTX_Unload_trust_peers(NULL) != WOLFSSL_SUCCESS); - assert(wolfSSL_CTX_Unload_trust_peers(ctx) == WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_Unload_trust_peers(NULL), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_Unload_trust_peers(ctx), WOLFSSL_SUCCESS); + + /* invalid file */ + AssertIntNE(wolfSSL_trust_peer_cert(ssl, NULL, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_trust_peer_cert(ssl, bogusFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_trust_peer_cert(ssl, cliCertFile, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + /* success */ + AssertIntEQ(wolfSSL_trust_peer_cert(ssl, cliCertFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + /* unload cert */ + AssertIntNE(wolfSSL_Unload_trust_peers(NULL), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_Unload_trust_peers(ssl), WOLFSSL_SUCCESS); #endif /* Test of loading certs from buffers */ /* invalid buffer */ - assert(wolfSSL_CTX_trust_peer_buffer(ctx, NULL, -1, - WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_trust_peer_buffer(ctx, NULL, -1, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* success */ #ifdef USE_CERT_BUFFERS_1024 - assert(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_1024, - sizeof_client_cert_der_1024, WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_1024, + sizeof_client_cert_der_1024, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #endif #ifdef USE_CERT_BUFFERS_2048 - assert(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_2048, - sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_2048, + sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #endif /* unload cert */ - assert(wolfSSL_CTX_Unload_trust_peers(NULL) != WOLFSSL_SUCCESS); - assert(wolfSSL_CTX_Unload_trust_peers(ctx) == WOLFSSL_SUCCESS); + AssertIntNE(wolfSSL_CTX_Unload_trust_peers(NULL), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_Unload_trust_peers(ctx), WOLFSSL_SUCCESS); + wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif } @@ -2423,6 +2442,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 +2455,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 +4468,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 +4483,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 +4507,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 +4532,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 +4582,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 +4629,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 +4693,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 +4712,16 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) wc_ecc_fp_free(); /* free per thread cache */ #endif + if (cbf == NULL || !cbf->ticNoInit) { #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) - OpenSSLTicketCleanup(); + OpenSSLTicketCleanup(); #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) - TicketCleanup(); + TicketCleanup(); #endif #endif + } #ifndef WOLFSSL_TIRTOS return 0; @@ -5072,6 +5099,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 +6229,191 @@ 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) { +#ifdef NO_SESSION_CACHE_REF + AssertNotNull(*sess = wolfSSL_get1_session(ssl)); +#else + /* Test for backwards compatibility */ + if (wolfSSL_is_server(ssl)) { + AssertNotNull(*sess = wolfSSL_get1_session(ssl)); + } + else { + AssertNotNull(*sess = wolfSSL_get_session(ssl)); + } +#endif + /* Now save the session in the internal store to make it available + * for lookup. For TLS 1.3, we can't save the session without + * WOLFSSL_TICKET_HAVE_ID because there is no way to retrieve the + * session from cache. */ + if (wolfSSL_is_server(ssl) +#ifndef WOLFSSL_TICKET_HAVE_ID + && wolfSSL_version(ssl) != TLS1_3_VERSION +#endif + ) + AssertIntEQ(wolfSSL_CTX_add_session(wolfSSL_get_SSL_CTX(ssl), + *sess), WOLFSSL_SUCCESS); + } + else { + /* If we have a session retrieved then remaining connections should be + * 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 && + wolfSSL_session_reused(ssl)) +#endif + { + /* With WOLFSSL_TICKET_HAVE_ID the peer certs should be available + * for all connections. TLS 1.3 only has tickets so if we don't + * include the session id in the ticket then the certificates + * will not be available on resumption. */ + WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); + AssertNotNull(peer); + wolfSSL_X509_free(peer); + AssertNotNull(wolfSSL_SESSION_get_peer_chain(*sess)); + AssertNotNull(wolfSSL_SESSION_get0_peer(*sess)); + } +#endif +} + +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] = { +#if !defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \ + !defined(NO_DES3)) + /* Without AES there are almost no ciphersuites available. This leads + * to no ciphersuites being available and an error. */ + { wolfTLSv1_1_client_method, wolfTLSv1_1_server_method }, +#endif +#ifndef WOLFSSL_NO_TLS12 + { 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 +8176,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 +33869,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); } @@ -39076,7 +39294,10 @@ static void test_wolfSSL_SESSION(void) AssertPtrNE((sess = wolfSSL_get1_session(ssl)), NULL); /* ref count 1 */ AssertPtrNE((sess_copy = wolfSSL_get1_session(ssl)), NULL); /* ref count 2 */ - AssertPtrEq(sess, sess_copy); /* they should be the same pointer */ +#ifdef HAVE_EXT_CACHE + AssertPtrEq(sess, sess_copy); /* they should be the same pointer but without + * HAVE_EXT_CACHE we get new objects each time */ +#endif wolfSSL_SESSION_free(sess_copy); sess_copy = NULL; wolfSSL_SESSION_free(sess); sess = NULL; /* free session ref */ @@ -39097,6 +39318,9 @@ static void test_wolfSSL_SESSION(void) #endif #endif /* OPENSSL_EXTRA */ + /* Retain copy of the session for later testing */ + AssertNotNull(sess = wolfSSL_get1_session(ssl)); + wolfSSL_shutdown(ssl); wolfSSL_free(ssl); @@ -49800,11 +50024,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) @@ -49813,20 +50041,52 @@ static void test_wolfSSL_CTX_LoadCRL(void) FAIL_T1(wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor); - #ifndef NO_WOLFSSL_CLIENT +#ifndef NO_WOLFSSL_CLIENT AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); - #elif !defined(NO_WOLFSSL_SERVER) +#elif !defined(NO_WOLFSSL_SERVER) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); - #else +#else return; - #endif +#endif SUCC_T (wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor); SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, pemType, monitor); SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, derType, monitor); wolfSSL_CTX_free(ctx); - ctx = NULL; + +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#elif !defined(NO_WOLFSSL_SERVER) + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + return; +#endif + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, validFilePath, pemType), WOLFSSL_SUCCESS); + wolfSSL_CTX_free(ctx); + +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#elif !defined(NO_WOLFSSL_SERVER) + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + return; +#endif + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL), + WOLFSSL_SUCCESS); + AssertNotNull(ssl = wolfSSL_new(ctx)); + 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 +51180,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 +51232,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 */ } @@ -52112,6 +52379,7 @@ void ApiTest(void) #endif #ifdef HAVE_IO_TESTS_DEPENDENCIES test_wolfSSL_get_finished(); + test_wolfSSL_CTX_add_session(); #endif test_SSL_CIPHER_get_xxx(); test_wolfSSL_ERR_strings(); diff --git a/tests/test-trustpeer.conf b/tests/test-trustpeer.conf index c8df70416d..9cc242d655 100644 --- a/tests/test-trustpeer.conf +++ b/tests/test-trustpeer.conf @@ -1,5 +1,6 @@ # Both client and server use -E [path] for trusted peer # server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-V -v 3 -l DHE-RSA-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-cert.pem @@ -7,6 +8,7 @@ -c ./certs/intermediate/server-int-cert.pem # client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-C -v 3 -l DHE-RSA-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-cert.pem @@ -14,6 +16,7 @@ -c ./certs/intermediate/client-int-cert.pem # server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-V -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-cert.pem @@ -21,6 +24,7 @@ -c ./certs/intermediate/server-int-cert.pem # client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-C -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-cert.pem @@ -28,6 +32,7 @@ -c ./certs/intermediate/client-int-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer +-V -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-ecc-cert.pem @@ -35,6 +40,7 @@ -c ./certs/intermediate/server-int-ecc-cert.pem # client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer +-C -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-ecc-cert.pem @@ -42,6 +48,7 @@ -c ./certs/intermediate/client-int-ecc-cert.pem # server TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Trusted Peer +-V -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-cert.pem @@ -49,6 +56,7 @@ -c ./certs/intermediate/server-int-cert.pem # client TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Trusted Peer +-C -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-cert.pem @@ -56,6 +64,7 @@ -c ./certs/intermediate/client-int-cert.pem # server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer +-V -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/intermediate/client-int-ecc-cert.pem @@ -63,6 +72,7 @@ -c ./certs/intermediate/server-int-ecc-cert.pem # client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer +-C -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/intermediate/server-int-ecc-cert.pem @@ -71,6 +81,7 @@ # Test for ECC self signed certificate as trusted peer # server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-V -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -E ./certs/client-ecc-cert.pem @@ -78,6 +89,7 @@ -c ./certs/server-ecc-self.pem # client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-C -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -E ./certs/server-ecc-self.pem @@ -85,6 +97,7 @@ -c ./certs/client-ecc-cert.pem # server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-V -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/client-ecc-cert.pem @@ -92,6 +105,7 @@ -c ./certs/server-ecc-self.pem # client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-C -v 4 -l TLS13-AES128-GCM-SHA256 -E ./certs/server-ecc-self.pem diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index d690e3b86d..57de940ab3 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -252,7 +252,11 @@ const char* wc_GetErrorString(int error) return "Bad alignment error, no alloc help"; case ASN_NO_SIGNER_E : +#ifndef OPENSSL_EXTRA return "ASN no signer error to confirm failure"; +#else + return "certificate verify failed"; +#endif case ASN_CRL_CONFIRM_E : return "ASN CRL sig error, confirm failure"; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 05d8e262c7..fa0b911f63 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1185,6 +1185,14 @@ enum Misc { HELLO_EXT_EXTMS = 0x0017, /* ID for the extended master secret ext */ SECRET_LEN = WOLFSSL_MAX_MASTER_KEY_LENGTH, /* pre RSA and all master */ + TIMESTAMP_LEN = 4, /* timestamp size in ticket */ +#ifdef WOLFSSL_TLS13 + AGEADD_LEN = 4, /* ageAdd size in ticket */ + NAMEDGREOUP_LEN = 2, /* namedGroup size in ticket */ +#ifdef WOLFSSL_EARLY_DATA + MAXEARLYDATASZ_LEN = 4, /* maxEarlyDataSz size in ticket */ +#endif +#endif #ifdef HAVE_PQC ENCRYPT_LEN = 1500, /* allow 1500 bit static buffer for falcon */ #else @@ -1567,6 +1575,10 @@ enum Misc { #define SESSION_TICKET_LEN 256 #endif +#ifndef PREALLOC_SESSION_TICKET_LEN + #define PREALLOC_SESSION_TICKET_LEN 512 +#endif + #ifndef SESSION_TICKET_HINT_DEFAULT #define SESSION_TICKET_HINT_DEFAULT 300 #endif @@ -1678,6 +1690,8 @@ typedef WOLFSSL_BUFFER_INFO buffer; typedef struct Suites Suites; +/* Declare opaque struct for API to use */ +typedef struct ClientSession ClientSession; /* defaults to client */ WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv); @@ -2758,6 +2772,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 +3098,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 @@ -3291,33 +3306,40 @@ struct WOLFSSL_X509_CHAIN { x509_buffer certs[MAX_CHAIN_DEPTH]; /* only allow max depth 4 for now */ }; -#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_SESSION_CACHE_REF) - /* enable allocation of a smaller reference for the internal cache, - * to prevent client from using internal cache reference. */ - #define ENABLE_CLIENT_SESSION_REF -#endif - typedef enum WOLFSSL_SESSION_TYPE { WOLFSSL_SESSION_TYPE_UNKNOWN, WOLFSSL_SESSION_TYPE_SSL, /* in ssl->session */ WOLFSSL_SESSION_TYPE_CACHE, /* pointer to internal cache */ WOLFSSL_SESSION_TYPE_HEAP /* allocated from heap SESSION_new */ -#ifdef ENABLE_CLIENT_SESSION_REF - ,WOLFSSL_SESSION_TYPE_REF /* smaller allocation with reference to internal cache */ -#endif } WOLFSSL_SESSION_TYPE; /* wolfSSL session type */ struct WOLFSSL_SESSION { + /* WARNING Do not add fields here. They will be ignored in + * wolfSSL_DupSession. */ WOLFSSL_SESSION_TYPE type; +#ifndef NO_SESSION_CACHE + int cacheRow; /* row in session cache */ +#endif + int refCount; /* reference count */ +#ifndef SINGLE_THREADED + wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif + byte altSessionID[ID_LEN]; + byte haveAltSessionID:1; + void* heap; + /* WARNING The above fields (up to and including the heap) are not copied + * in wolfSSL_DupSession. Place new fields after the heap + * member */ + byte side; /* Either WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ - int cacheRow; /* row in session cache */ word32 bornOn; /* create time in seconds */ word32 timeout; /* timeout in seconds */ - byte sessionID[ID_LEN]; /* id for protocol */ + byte sessionID[ID_LEN]; /* id for protocol or bogus + * ID for TLS 1.3 */ byte sessionIDSz; byte* masterSecret; /* stored secret */ @@ -3363,18 +3385,22 @@ struct WOLFSSL_SESSION { word16 ticketLen; word16 ticketLenAlloc; /* is dynamic */ #endif - int refCount; /* reference count */ - void* heap; -#ifdef ENABLE_CLIENT_SESSION_REF - /* pointer to WOLFSSL_SESSION in internal cache (for WOLFSSL_SESSION_TYPE_REF) */ - void* refPtr; +#ifdef SESSION_CERTS + WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ + #ifdef WOLFSSL_ALT_CERT_CHAINS + WOLFSSL_X509_CHAIN altChain; /* peer alt cert chain, static */ + #endif +#endif +#ifdef HAVE_EX_DATA + WOLFSSL_CRYPTO_EX_DATA ex_data; #endif /* Below buffers are not allocated for the WOLFSSL_SESSION_TYPE_REF, instead * the above pointers reference the session cache for backwards * compatibility. For all other session types the above pointers reference - * these buffers directly */ + * these buffers directly. Keep these buffers at the end so that they don't + * get copied into the WOLFSSL_SESSION_TYPE_REF object. */ byte _masterSecret[SECRET_LEN]; #ifndef NO_CLIENT_CACHE byte _serverID[SERVER_ID_LEN]; @@ -3385,30 +3411,30 @@ struct WOLFSSL_SESSION { #ifdef OPENSSL_EXTRA byte _sessionCtx[ID_LEN]; #endif - -#ifdef SESSION_CERTS - WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ - #ifdef WOLFSSL_ALT_CERT_CHAINS - WOLFSSL_X509_CHAIN altChain; /* peer alt cert chain, static */ - #endif -#endif -#ifdef HAVE_EX_DATA - WOLFSSL_CRYPTO_EX_DATA ex_data; -#endif -#ifdef OPENSSL_EXTRA - #ifndef SINGLE_THREADED - wolfSSL_Mutex refMutex; /* ref count mutex */ - #endif -#endif }; +WOLFSSL_LOCAL int wolfSSL_RAND_Init(void); WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_NewSession(void* heap); WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_GetSession( WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts); -WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_GetSessionRef(WOLFSSL* ssl); +WOLFSSL_LOCAL void AddSession(WOLFSSL* ssl); +WOLFSSL_LOCAL int AddSessionToCache(WOLFSSL_SESSION* addSession, const byte* id, + byte idSz, int* sessionIndex, int side, word16 useTicket, + ClientSession** clientCacheEntry); +#ifndef NO_CLIENT_CACHE +WOLFSSL_LOCAL ClientSession* AddSessionToClientCache(int side, int row, int idx, + byte* serverID, word16 idLen, const byte* sessionID, + word16 useTicket); +#endif +WOLFSSL_LOCAL +WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session); +WOLFSSL_LOCAL int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output); WOLFSSL_LOCAL int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session); WOLFSSL_LOCAL void wolfSSL_FreeSession(WOLFSSL_SESSION* session); +WOLFSSL_LOCAL int wolfSSL_DupSession(const WOLFSSL_SESSION* input, + WOLFSSL_SESSION* output, int avoidSysCalls); + typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int, int); @@ -3598,6 +3624,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; @@ -4231,9 +4258,9 @@ struct WOLFSSL { Ciphers encrypt; Ciphers decrypt; Buffers buffers; - WOLFSSL_SESSION session; -#ifdef HAVE_EXT_CACHE - WOLFSSL_SESSION* extSession; + WOLFSSL_SESSION* session; +#ifndef NO_CLIENT_CACHE + ClientSession* clientSession; #endif WOLFSSL_ALERT_HISTORY alert_history; int error; @@ -4390,6 +4417,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 +4601,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. @@ -4740,7 +4785,6 @@ WOLFSSL_LOCAL const char* AlertTypeToString(int type); WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL* ssl); WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL* ssl); -WOLFSSL_LOCAL int AddSession(WOLFSSL* ssl); WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side); @@ -4827,8 +4871,7 @@ WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, #define WC_MATCH_SKID 0 #define WC_MATCH_NAME 1 - WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, - int type); + WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert); WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert); #endif diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index 8628685cf5..80289e0249 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -32,7 +32,7 @@ /* valid version */ #elif defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIBEST) || \ defined(WOLFSSL_BIND) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_RSYSLOG) || defined(WOLFSSL_KRB) + defined(WOLFSSL_RSYSLOG) || defined(WOLFSSL_KRB) || defined(HAVE_STUNNEL) /* For Apache httpd, Use 1.1.0 compatibility */ #define OPENSSL_VERSION_NUMBER 0x10100003L #elif defined(WOLFSSL_QT) || defined(WOLFSSL_PYTHON) @@ -40,7 +40,7 @@ #define OPENSSL_VERSION_NUMBER 0x10101000L #elif defined(WOLFSSL_HAPROXY) #define OPENSSL_VERSION_NUMBER 0x1010000fL -#elif defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || \ +#elif defined(OPENSSL_ALL) || defined(HAVE_LIGHTY) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_OPENVPN) /* version number can be increased for Lighty after compatibility for ECDH is added */ @@ -49,7 +49,7 @@ #define OPENSSL_VERSION_NUMBER 0x0090810fL #endif -#define OPENSSL_VERSION_TEXT LIBWOLFSSL_VERSION_STRING +#define OPENSSL_VERSION_TEXT "wolfSSL " LIBWOLFSSL_VERSION_STRING #define OPENSSL_VERSION 0 #endif /* header */ diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 164964bdf1..856c7f65a0 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 @@ -1268,15 +1269,6 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE; #define SSL3_RANDOM_SIZE 32 /* same as RAN_LEN in internal.h */ -#define SSL2_VERSION 0x0002 -#define SSL3_VERSION 0x0300 -#define TLS1_VERSION 0x0301 -#define TLS1_1_VERSION 0x0302 -#define TLS1_2_VERSION 0x0303 -#define TLS1_3_VERSION 0x0304 -#define DTLS1_VERSION 0xFEFF -#define DTLS1_2_VERSION 0xFEFD - /* Used as message callback types */ #define SSL3_RT_CHANGE_CIPHER_SPEC 20 #define SSL3_RT_ALERT 21 diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 37ec8a877f..5070b6b137 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 @@ -809,6 +810,9 @@ enum Tls13Secret { }; #endif +#ifndef WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS +#define WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS 10 +#endif typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap); @@ -969,6 +973,8 @@ WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_load_verify_locations( #ifdef WOLFSSL_TRUST_PEER_CERT WOLFSSL_API int wolfSSL_CTX_trust_peer_cert( WOLFSSL_CTX* ctx, const char* file, int type); +WOLFSSL_API int wolfSSL_trust_peer_cert( + WOLFSSL* ssl, const char* file, int type); #endif WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file( WOLFSSL_CTX* ctx, const char* file); @@ -996,8 +1002,8 @@ WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file( WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap); WOLFSSL_ABI WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method); -#ifdef OPENSSL_EXTRA WOLFSSL_API int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx); +#ifdef OPENSSL_EXTRA WOLFSSL_API int wolfSSL_CTX_set_ecdh_auto(WOLFSSL_CTX* ctx, int onoff); WOLFSSL_API int wolfSSL_get_signature_nid(WOLFSSL* ssl, int* nid); WOLFSSL_API int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, @@ -1193,6 +1199,7 @@ WOLFSSL_API int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val); WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx); WOLFSSL_ABI WOLFSSL_API int wolfSSL_pending(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); @@ -1482,6 +1489,8 @@ WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_new(void); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap); WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session); +WOLFSSL_API int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, + WOLFSSL_SESSION* session); WOLFSSL_API int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, const WOLFSSL_CIPHER* cipher); WOLFSSL_API int wolfSSL_is_init_finished(WOLFSSL* ssl); @@ -1499,12 +1508,13 @@ WOLFSSL_API int wolfSSL_CIPHER_get_digest_nid(const WOLFSSL_CIPHER* cipher); WOLFSSL_API int wolfSSL_CIPHER_get_kx_nid(const WOLFSSL_CIPHER* cipher); WOLFSSL_API int wolfSSL_CIPHER_is_aead(const WOLFSSL_CIPHER* cipher); WOLFSSL_API const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value); -WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session); +WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session); WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL* ssl); WOLFSSL_API void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void); +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509* x); #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) WOLFSSL_API int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa); WOLFSSL_API int wolfSSL_X509_up_ref(WOLFSSL_X509* x509); @@ -2189,7 +2199,10 @@ enum { SSL_MODE_ENABLE_PARTIAL_WRITE = 2, SSL_MODE_AUTO_RETRY = 3, /* wolfSSL default is to return WANT_{READ|WRITE} * to the user. This is set by default with - * OPENSSL_COMPATIBLE_DEFAULTS. */ + * OPENSSL_COMPATIBLE_DEFAULTS. The macro + * WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS is used to + * limit the possibility of an infinite retry loop + */ SSL_MODE_RELEASE_BUFFERS = -1, /* For libwebsockets build. No current use. */ BIO_CLOSE = 1, @@ -2199,12 +2212,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 +2227,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, @@ -2833,6 +2846,9 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* key, unsigned int len, WOLFSSL_API int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx); #ifdef WOLFSSL_TRUST_PEER_CERT WOLFSSL_API int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx); +#ifdef WOLFSSL_LOCAL_X509_STORE + WOLFSSL_API int wolfSSL_Unload_trust_peers(WOLFSSL* ssl); +#endif WOLFSSL_API int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx, const unsigned char*, long, int); #endif @@ -3348,6 +3364,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 +3407,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 +3424,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); @@ -4003,7 +4023,6 @@ WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_delete_entry( WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, const WOLFSSL_X509_NAME* y); WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void); -WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509* x); WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(WOLFSSL_X509_NAME* name); WOLFSSL_API int wolfSSL_X509_NAME_copy(WOLFSSL_X509_NAME* from, WOLFSSL_X509_NAME* to); WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); @@ -4313,9 +4332,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 *)); @@ -4430,13 +4449,11 @@ WOLFSSL_API int wolfSSL_ASN1_BIT_STRING_set_bit( WOLFSSL_ASN1_BIT_STRING* str, int pos, int val); #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +WOLFSSL_API int wolfSSL_version(WOLFSSL* ssl); + #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) \ || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) -WOLFSSL_API int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session); - -WOLFSSL_API int wolfSSL_version(WOLFSSL* ssl); - WOLFSSL_API int wolfSSL_get_state(const WOLFSSL* ssl); WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)*, int i); @@ -4465,8 +4482,8 @@ WOLFSSL_API int wolfSSL_SESSION_set_ex_data_with_cleanup( WOLFSSL_API int wolfSSL_SESSION_get_ex_new_index(long idx,void* data,void* cb1,void* cb2, CRYPTO_free_func* cb3); -WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, - unsigned int* idLen); +WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id( + const WOLFSSL_SESSION* sess, unsigned int* idLen); WOLFSSL_API int wolfSSL_SESSION_print(WOLFSSL_BIO* bp, const WOLFSSL_SESSION* session); @@ -4895,6 +4912,17 @@ WOLFSSL_API int wolfSSL_CRYPTO_get_ex_new_index(int class_index, long argl, void WOLFSSL_CRYPTO_EX_dup* dup_func, WOLFSSL_CRYPTO_EX_free* free_func); #endif /* HAVE_EX_DATA || WOLFSSL_WPAS_SMALL */ + +/* */ +#define SSL2_VERSION 0x0002 +#define SSL3_VERSION 0x0300 +#define TLS1_VERSION 0x0301 +#define TLS1_1_VERSION 0x0302 +#define TLS1_2_VERSION 0x0303 +#define TLS1_3_VERSION 0x0304 +#define DTLS1_VERSION 0xFEFF +#define DTLS1_2_VERSION 0xFEFD + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/test.h b/wolfssl/test.h index 7227e2261b..34ec8ff7aa 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -518,6 +518,7 @@ typedef struct callback_functions { int return_code; unsigned char isSharedCtx:1; unsigned char loadToSSL:1; + unsigned char ticNoInit:1; } callback_functions; #if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 25fd42233b..646e23175d 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1741,7 +1741,7 @@ struct TrustedPeerCert { /* sha hash of names in certificate */ #ifndef NO_SKID byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; - /* sha hash of names in certificate */ + /* sha hash of SKID in certificate */ #endif word32 sigLen; byte* sig; diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index 4014f25aed..b81009b67c 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -45,6 +45,12 @@ WOLFSSL_API void wolfSSL_SetMemFailCount(int memFailCount); #endif +#ifdef OPENSSL_EXTRA + typedef void *(*wolfSSL_OSSL_Malloc_cb)(size_t, const char *, int); + typedef void (*wolfSSL_OSSL_Free_cb)(void *, const char *, int); + typedef void *(*wolfSSL_OSSL_Realloc_cb)(void *, size_t, const char *, int); +#endif /* OPENSSL_EXTRA */ + #ifdef WOLFSSL_STATIC_MEMORY #ifdef WOLFSSL_DEBUG_MEMORY typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type, const char* func, unsigned int line);