Browse Source

stunnel 5.61 support

- New/Implemented API
  - `SSL_has_pending`
  - `wolfSSL_CertManagerLoadCRLFile`
  - `wolfSSL_LoadCRLFile`
  - `wolfSSL_CTX_LoadCRLFile`
  - `wolfSSL_CTX_add_session`
- Calling chain certificate API (for example `wolfSSL_CTX_use_certificate_chain_file`) no longer requires an actual chain certificate PEM file to be passed in as input. `ProcessUserChain` error in `ProcessBuffer` is ignored if it returns that it didn't find a chain.
- Add `WOLFSSL_TICKET_HAVE_ID` macro. When defined tickets will include the original session ID that can be used to lookup the session in internal cache. This is useful for fetching information about the peer that doesn't get sent in a resumption (such as the peer's certificate chain).
  - Add `ssl->ticketSessionID` field because `ssl->session.sessionID` is used to return the "bogus" session ID sent by the client in TLS 1.3
- `OPENSSL_COMPATIBLE_DEFAULTS` changes
  - Define `WOLFSSL_TRUST_PEER_CERT` and certificates added as CA's will also be loaded as trusted peer certificates
  - Define `WOLFSSL_TLS13_MIDDLEBOX_COMPAT`
- Seperate `internalCacheOff` and `internalCacheLookupOff` options to govern session addition and lookup
- `VerifyServerSuite` now determines if RSA is available by checking for it directly and not assuming it as the default if static ECC is not available
- `WOLFSSL_SESSION` changes
  - `ssl->extSession` added to return a dynamic session when internalCacheOff is set
  - `ssl->session.refPtr` made dynamic and gets free'd in `SSL_ResourceFree`
- If `SSL_MODE_AUTO_RETRY` is set then retry should only occur during a handshake
- `WOLFSSL_TRUST_PEER_CERT` code now always uses `cert->subjectHash` for the `cm->tpTable` table row selection
- Change some error message names to line up with OpenSSL equivalents
- Run `MatchSuite` again if certificate setup callback installed and successful
- Refactor clearing `ASN_NO_PEM_HEADER` off the error queue into a macro
- `wolfSSL_get_peer_certificate` now returns a duplicated object meaning that the caller needs to free the returned object
- Allign `wolfSSL_CRYPTO_set_mem_functions` callbacks with OpenSSL API
- `wolfSSL_d2i_PKCS12_bio` now consumes the input BIO. It now supports all supported BIO's instead of only memory BIO.
- stunnel specific
  - Always return a session object even if we don't have a session in cache. This allows stunnel to save information in the session external data that will be transfered to new connections if the session is reused
  - When allocating a dynamic session, always do `wolfSSL_SESSION_set_ex_data(session, 0, (void *)(-1)`. This is to mimic the new index callback set in `SSL_SESSION_get_ex_new_index`.
- Fix comment in `wolfSSL_AES_cbc_encrypt`
- Trusted peer certificate suite tests need to have CRL disabled since we don't have the issuer certificate in the CA store if the certificates are only added as trusted peer certificates.
tested
Juliusz Sosinowicz 2 years ago
parent
commit
afca455cda
14 changed files with 762 additions and 258 deletions
  1. 10 1
      configure.ac
  2. 79 17
      src/internal.c
  3. 353 188
      src/ssl.c
  4. 5 1
      src/tls13.c
  5. 227 19
      tests/api.c
  6. 14 0
      tests/test-trustpeer.conf
  7. 4 0
      wolfcrypt/src/error.c
  8. 43 19
      wolfssl/internal.h
  9. 3 3
      wolfssl/openssl/opensslv.h
  10. 1 0
      wolfssl/openssl/ssl.h
  11. 15 9
      wolfssl/ssl.h
  12. 1 0
      wolfssl/test.h
  13. 1 1
      wolfssl/wolfcrypt/asn.h
  14. 6 0
      wolfssl/wolfcrypt/memory.h

+ 10 - 1
configure.ac

@@ -5224,6 +5224,7 @@ then
     AM_CFLAGS="$AM_CFLAGS -DHAVE_STUNNEL -DWOLFSSL_ALWAYS_VERIFY_CB"
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI -DHAVE_EX_DATA"
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB -DWOLFSSL_SIGNER_DER_CERT"
+    AM_CFLAGS="$AM_CFLAGS -DOPENSSL_COMPATIBLE_DEFAULTS -DWOLFSSL_TICKET_HAVE_ID"
 fi
 
 # curl Support
@@ -6824,6 +6825,14 @@ AC_ARG_ENABLE([optflags],
 AS_CASE(["$CFLAGS $CPPFLAGS"],[*'WOLFSSL_TRUST_PEER_CERT'*],[ENABLED_TRUSTED_PEER_CERT=yes])
 
 
+AS_CASE(["$CFLAGS $CPPFLAGS $AM_CFLAGS"],[*'OPENSSL_COMPATIBLE_DEFAULTS'*],
+	[ENABLED_OPENSSL_COMPATIBLE_DEFAULTS=yes])
+if test "x$ENABLED_OPENSSL_COMPATIBLE_DEFAULTS" = "xyes"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRUST_PEER_CERT -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT"
+    ENABLED_TRUSTED_PEER_CERT=yes
+fi
+
 # dertermine if we have key validation mechanism
 if test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_RSA" = "xyes"
 then
@@ -7105,7 +7114,7 @@ then
 fi
 
 AS_IF([test "x$ENABLED_OPENSSLALL" = "xyes"],
-      [AM_CFLAGS="$AM_CFLAGS -DOPENSSL_ALL -DWOLFSSL_EITHER_SIDE -DWC_RSA_NO_PADDING -DWC_RSA_PSS -DWOLFSSL_PSS_LONG_SALT"])
+      [AM_CFLAGS="$AM_CFLAGS -DOPENSSL_ALL -DWOLFSSL_EITHER_SIDE -DWC_RSA_NO_PADDING -DWC_RSA_PSS -DWOLFSSL_PSS_LONG_SALT -DWOLFSSL_TICKET_HAVE_ID"])
 
 AS_IF([test "x$ENABLED_AESSIV" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_SIV"])
 

+ 79 - 17
src/internal.c

@@ -5952,6 +5952,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
     ssl->options.downgrade    = ctx->method->downgrade;
     ssl->options.minDowngrade = ctx->minDowngrade;
 
+    ssl->options.haveRSA       = ctx->haveRSA;
     ssl->options.haveDH        = ctx->haveDH;
     ssl->options.haveECDSAsig  = ctx->haveECDSAsig;
     ssl->options.haveECC       = ctx->haveECC;
@@ -5998,6 +5999,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
     ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
 #ifdef HAVE_EXT_CACHE
     ssl->options.internalCacheOff     = ctx->internalCacheOff;
+    ssl->options.internalCacheLookupOff = ctx->internalCacheLookupOff;
 #endif
 
     ssl->options.verifyPeer     = ctx->verifyPeer;
@@ -7014,6 +7016,13 @@ void SSL_ResourceFree(WOLFSSL* ssl)
      * example with the RNG, it isn't used beyond the handshake except when
      * using stream ciphers where it is retained. */
 
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        WOLFSSL_MSG("Free'ing server ssl");
+    }
+    else {
+        WOLFSSL_MSG("Free'ing client ssl");
+    }
+
 #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
     wolfSSL_CRYPTO_cleanup_ex_data(&ssl->ex_data);
 #endif
@@ -7221,6 +7230,9 @@ void SSL_ResourceFree(WOLFSSL* ssl)
         ssl->session.ticketLen = 0;
     }
 #endif
+#ifdef ENABLE_CLIENT_SESSION_REF
+    wolfSSL_SESSION_free(ssl->session.refPtr);
+#endif
 #ifdef HAVE_EXT_CACHE
     wolfSSL_SESSION_free(ssl->extSession);
 #endif
@@ -8985,7 +8997,7 @@ retry:
                 return -1;
 
             case WOLFSSL_CBIO_ERR_WANT_READ:      /* want read, would block */
-                if (ssl->ctx->autoRetry)
+                if (ssl->ctx->autoRetry && !ssl->options.handShakeDone)
                     goto retry;
                 return WANT_READ;
 
@@ -12157,7 +12169,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
                 if (args->certIdx == 0) {
                 #ifdef WOLFSSL_TRUST_PEER_CERT
                     TrustedPeerCert* tp;
-                    int matchType = WC_MATCH_NAME;
                 #endif
 
                     ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, NO_VERIFY,
@@ -12174,11 +12185,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
                 #endif
 
                 #ifdef WOLFSSL_TRUST_PEER_CERT
-                    #ifndef NO_SKID
-                    if (args->dCert->extAuthKeyIdSet)
-                        matchType = WC_MATCH_SKID;
-                    #endif
-                    tp = GetTrustedPeer(SSL_CM(ssl), subjectHash, matchType);
+                    tp = GetTrustedPeer(SSL_CM(ssl), args->dCert);
                     WOLFSSL_MSG("Checking for trusted peer cert");
 
                     if (tp && MatchTrustedPeer(tp, args->dCert)) {
@@ -18874,8 +18881,10 @@ int SendCertificate(WOLFSSL* ssl)
     WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND);
     WOLFSSL_ENTER("SendCertificate");
 
-    if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
+    if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) {
+        WOLFSSL_MSG("Not sending certificate msg. Using PSK or ANON cipher.");
         return 0;  /* not needed */
+    }
 
     if (ssl->options.sendVerify == SEND_BLANK_CERT) {
     #ifdef OPENSSL_EXTRA
@@ -20215,7 +20224,11 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
         return "wrong client/server type";
 
     case NO_PEER_CERT :
+#ifndef OPENSSL_EXTRA
         return "peer didn't send cert";
+#else
+        return "peer did not return a certificate";
+#endif
 
     case UNKNOWN_HANDSHAKE_TYPE :
         return "weird handshake type";
@@ -20530,7 +20543,11 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
         return "The handshake message is missing required data";
 
     case BAD_BINDER:
+#ifndef OPENSSL_EXTRA
         return "Binder value does not match value server calculated";
+#else
+        return "binder does not verify";
+#endif
 
     case EXT_NOT_ALLOWED:
         return "Extension type not allowed in handshake message type";
@@ -28843,7 +28860,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
      */
     static int VerifyServerSuite(WOLFSSL* ssl, word16 idx)
     {
-        int  haveRSA = !ssl->options.haveStaticECC;
     #ifndef NO_PSK
         int  havePSK = ssl->options.havePSK;
     #endif
@@ -28862,7 +28878,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
 
         if (CipherRequires(first, second, REQUIRES_RSA)) {
             WOLFSSL_MSG("Requires RSA");
-            if (haveRSA == 0) {
+            if (ssl->options.haveRSA == 0) {
                 WOLFSSL_MSG("Don't have RSA");
                 return 0;
             }
@@ -29969,6 +29985,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
 #endif
 
         ret = MatchSuite(ssl, &clSuites);
+#ifdef OPENSSL_EXTRA
+        /* Give user last chance to provide a cert for cipher selection */
+        if (ret == 0)
+            ret = CertSetupCbWrapper(ssl);
+        /* Call again in case user changes affect cipher selection */
+        if (ret == 0 && ssl->ctx->certSetupCb != NULL)
+            ret = MatchSuite(ssl, &clSuites);
+#endif
+
 #ifdef WOLFSSL_EXTRA_ALERTS
         if (ret == BUFFER_ERROR)
             SendAlert(ssl, alert_fatal, decode_error);
@@ -29996,11 +30021,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
         wc_HmacFree(&cookieHmac);
 #endif
 
-#ifdef OPENSSL_EXTRA
-        if (ret == 0)
-            ret = CertSetupCbWrapper(ssl);
-#endif
-
         WOLFSSL_LEAVE("DoClientHello", ret);
         WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
 
@@ -30527,6 +30547,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
     #ifdef WOLFSSL_EARLY_DATA
         word32          maxEarlyDataSz;        /* Max size of early data */
     #endif
+#endif
+#ifdef WOLFSSL_TICKET_HAVE_ID
+        byte            id[ID_LEN];
 #endif
     } InternalTicket;
 
@@ -30614,9 +30637,27 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
 #endif
         }
 
+#ifdef WOLFSSL_TICKET_HAVE_ID
+        {
+            const byte* id = NULL;
+            if (ssl->options.haveTicketSessionID)
+                id = ssl->ticketSessionID;
+            else if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL)
+                id = ssl->arrays->sessionID;
+            else
+                id = ssl->session.sessionID;
+            XMEMCPY(it.id, id, ID_LEN);
+        }
+#endif
+
         /* encrypt */
         encLen = WOLFSSL_TICKET_ENC_SZ;  /* max size user can use */
-        if (ssl->ctx->ticketEncCb == NULL) {
+        if (ssl->ctx->ticketEncCb == NULL ||
+                /* SSL_OP_NO_TICKET turns off tickets in < 1.2. Forces
+                 * "stateful" tickets for 1.3 so just use the regular
+                 * stateless ones. */
+                (!IsAtLeastTLSv1_3(ssl->version) &&
+                        (ssl->options.mask & SSL_OP_NO_TICKET) != 0)) {
             ret = WOLFSSL_TICKET_RET_FATAL;
         }
         else {
@@ -30711,7 +30752,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
         }
         outLen = inLen;   /* may be reduced by user padding */
 
-        if (ssl->ctx->ticketEncCb == NULL) {
+        if (ssl->ctx->ticketEncCb == NULL ||
+                /* SSL_OP_NO_TICKET turns off tickets in < 1.2. Forces
+                 * "stateful" tickets for 1.3 so just use the regular
+                 * stateless ones. */
+                (!IsAtLeastTLSv1_3(ssl->version) &&
+                        (ssl->options.mask & SSL_OP_NO_TICKET) != 0)) {
             ret = WOLFSSL_TICKET_RET_FATAL;
         }
         else {
@@ -30760,6 +30806,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
                 ssl->version.minor = it.pv.minor;
             }
 
+#ifdef WOLFSSL_TICKET_HAVE_ID
+            {
+                ssl->options.haveTicketSessionID = 1;
+                XMEMCPY(ssl->ticketSessionID, it.id, ID_LEN);
+                if (wolfSSL_GetSession(ssl, NULL, 1) != NULL) {
+                    WOLFSSL_MSG("Found session matching the session id"
+                                " found in the ticket");
+                }
+                else {
+                    WOLFSSL_MSG("Can't find session matching the session id"
+                                " found in the ticket");
+                }
+            }
+#endif
 
             if (!IsAtLeastTLSv1_3(ssl->version)) {
                 XMEMCPY(ssl->arrays->masterSecret, it.msecret, SECRET_LEN);
@@ -31209,6 +31269,8 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
     byte* p = aad;
     int keyIdx = 0;
 
+    WOLFSSL_ENTER("DefTicketEncCb");
+
     /* Check we have setup the RNG, name and primary key. */
     if (keyCtx->expirary[0] == 0) {
 #ifndef SINGLE_THREADED

File diff suppressed because it is too large
+ 353 - 188
src/ssl.c


+ 5 - 1
src/tls13.c

@@ -3562,17 +3562,21 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
     case TLS_ASYNC_FINALIZE:
     {
 #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
-    if (args->sessIdSz == 0)
+    if (args->sessIdSz == 0) {
+        WOLFSSL_MSG("args->sessIdSz == 0");
         return INVALID_PARAMETER;
+    }
     if (ssl->session.sessionIDSz != 0) {
         if (ssl->session.sessionIDSz != args->sessIdSz ||
             XMEMCMP(ssl->session.sessionID, args->sessId,
                 args->sessIdSz) != 0) {
+            WOLFSSL_MSG("session id doesn't match");
             return INVALID_PARAMETER;
         }
     }
     else if (XMEMCMP(ssl->arrays->clientRandom, args->sessId,
             args->sessIdSz) != 0) {
+        WOLFSSL_MSG("session id doesn't match client random");
         return INVALID_PARAMETER;
     }
 #else

+ 227 - 19
tests/api.c

@@ -2423,6 +2423,7 @@ static int test_wolfSSL_CTX_use_certificate_chain_file_format(void)
     int ret = 0;
 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA)
     const char* server_chain_der = "./certs/server-cert-chain.der";
+    const char* client_single_pem = "./certs/client-cert.pem";
     WOLFSSL_CTX* ctx;
 
   #ifndef NO_WOLFSSL_CLIENT
@@ -2435,6 +2436,8 @@ static int test_wolfSSL_CTX_use_certificate_chain_file_format(void)
 
     AssertIntEQ(wolfSSL_CTX_use_certificate_chain_file_format(ctx,
         server_chain_der, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
+    AssertIntEQ(wolfSSL_CTX_use_certificate_chain_file_format(ctx,
+        client_single_pem, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
 
     wolfSSL_CTX_free(ctx);
 #endif
@@ -4446,6 +4449,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
     callback_functions* cbf;
     WOLFSSL_CTX* ctx = 0;
     WOLFSSL* ssl = 0;
+    func_args* opts = (func_args*)args;
 
     char msg[] = "I hear you fa shizzle!";
     char input[1024];
@@ -4460,8 +4464,8 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
     fdOpenSession(Task_self());
 #endif
 
-    ((func_args*)args)->return_code = TEST_FAIL;
-    cbf = ((func_args*)args)->callbacks;
+    opts->return_code = TEST_FAIL;
+    cbf = opts->callbacks;
 
 #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
     if (cbf != NULL && cbf->ctx) {
@@ -4484,19 +4488,21 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
         goto done;
     }
 
+    if (cbf != NULL && !cbf->ticNoInit) {
 #if defined(HAVE_SESSION_TICKET) && \
     ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))
 #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC)
-    OpenSSLTicketInit();
-    wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx, myTicketEncCbOpenSSL);
+        OpenSSLTicketInit();
+        wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx, myTicketEncCbOpenSSL);
 #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB)
-    TicketInit();
-    wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
+        TicketInit();
+        wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
 #endif
 #endif
+    }
 
 #if defined(USE_WINDOWS_API)
-    port = ((func_args*)args)->signal->port;
+    port = opts->signal->port;
 #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \
      !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS)
     /* Let tcp_listen assign port */
@@ -4507,7 +4513,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
 #endif
 
     /* do it here to detect failure */
-    tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0);
+    tcp_accept(&sockfd, &clientfd, opts, port, 0, 0, 0, 0, 1, 0, 0);
     CloseSocket(sockfd);
 
     wolfSSL_CTX_set_verify(ctx,
@@ -4557,7 +4563,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
 
 #ifdef WOLFSSL_SESSION_EXPORT
     /* only add in more complex nonblocking case with session export tests */
-    if (args && ((func_args*)args)->argc > 0) {
+    if (args && opts->argc > 0) {
         /* set as nonblock and time out for waiting on read/write */
         tcp_set_nonblocking(&clientfd);
         wolfSSL_dtls_set_using_nonblock(ssl, 1);
@@ -4604,10 +4610,10 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
 
 #ifdef WOLFSSL_SESSION_EXPORT
     /* only add in more complex nonblocking case with session export tests */
-    if (((func_args*)args)->argc > 0) {
+    if (opts->argc > 0) {
         ret = nonblocking_accept_read(args, ssl, &clientfd);
         if (ret >= 0) {
-            ((func_args*)args)->return_code = TEST_SUCCESS;
+            opts->return_code = TEST_SUCCESS;
         }
     #ifdef WOLFSSL_TIRTOS
         Task_yield();
@@ -4668,7 +4674,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
     Task_yield();
 #endif
 
-    ((func_args*)args)->return_code = TEST_SUCCESS;
+    opts->return_code = TEST_SUCCESS;
 
 done:
     wolfSSL_shutdown(ssl);
@@ -4687,14 +4693,16 @@ done:
     wc_ecc_fp_free();  /* free per thread cache */
 #endif
 
+    if (cbf != NULL && !cbf->ticNoInit) {
 #if defined(HAVE_SESSION_TICKET) && \
     ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))
 #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC)
-    OpenSSLTicketCleanup();
+        OpenSSLTicketCleanup();
 #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB)
-    TicketCleanup();
+        TicketCleanup();
 #endif
 #endif
+    }
 
 #ifndef WOLFSSL_TIRTOS
     return 0;
@@ -5072,6 +5080,9 @@ static void test_client_nofail(void* args, cbType cb)
         printf("Server response: %s\n", reply);
     }
 
+    if (cbf != NULL && cbf->on_result != NULL)
+        cbf->on_result(ssl);
+
     ((func_args*)args)->return_code = TEST_SUCCESS;
 
 done:
@@ -6199,6 +6210,168 @@ static void test_wolfSSL_get_finished(void)
 #endif
 }
 
+#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
+    !defined(SINGLE_THREADED) && defined(WOLFSSL_TLS13) && \
+    !defined(NO_SESSION_CACHE)
+
+/* Sessions to restore/store */
+static WOLFSSL_SESSION* test_wolfSSL_CTX_add_session_client_sess;
+static WOLFSSL_SESSION* test_wolfSSL_CTX_add_session_server_sess;
+static WOLFSSL_CTX*     test_wolfSSL_CTX_add_session_server_ctx;
+
+static void test_wolfSSL_CTX_add_session_ctx_ready(WOLFSSL_CTX* ctx)
+{
+    /* Don't store sessions. Lookup is still enabled. */
+    AssertIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx,
+            WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE), WOLFSSL_SUCCESS);
+    /* Require both peers to provide certs */
+    wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
+}
+
+static void test_wolfSSL_CTX_add_session_on_result(WOLFSSL* ssl)
+{
+    WOLFSSL_SESSION** sess;
+    if (wolfSSL_is_server(ssl))
+        sess = &test_wolfSSL_CTX_add_session_server_sess;
+    else
+        sess = &test_wolfSSL_CTX_add_session_client_sess;
+    if (*sess == NULL) {
+        AssertNotNull(*sess = wolfSSL_get1_session(ssl));
+        /* Now save the session in the internal store to make it available
+         * for lookup */
+        AssertIntEQ(wolfSSL_CTX_add_session(wolfSSL_get_SSL_CTX(ssl), *sess),
+                WOLFSSL_SUCCESS);
+    }
+    else {
+        /* If we have a session retrieved then remaining connections should be
+         * resuming on that session */
+        AssertIntEQ(wolfSSL_session_reused(ssl), 1);
+    }
+    /* Save CTX to be able to decrypt tickets */
+    if (wolfSSL_is_server(ssl) &&
+            test_wolfSSL_CTX_add_session_server_ctx == NULL) {
+        AssertNotNull(test_wolfSSL_CTX_add_session_server_ctx
+                = wolfSSL_get_SSL_CTX(ssl));
+        AssertIntEQ(wolfSSL_CTX_up_ref(wolfSSL_get_SSL_CTX(ssl)),
+                WOLFSSL_SUCCESS);
+    }
+#ifdef SESSION_CERTS
+#ifndef WOLFSSL_TICKET_HAVE_ID
+    if (wolfSSL_version(ssl) != TLS1_3_VERSION)
+#endif
+    {
+        /* With WOLFSSL_TICKET_HAVE_ID the peer certs should be available
+         * for all connections. TLS 1.3 only has tickets so if we don't
+         * include the session id in the ticket then the certificates
+         * will not be available. */
+        WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl);
+        AssertNotNull(peer);
+        wolfSSL_X509_free(peer);
+    }
+#endif
+}
+
+static void test_wolfSSL_CTX_add_session_ssl_ready(WOLFSSL* ssl)
+{
+    /* Set the session to reuse for the client */
+    AssertIntEQ(wolfSSL_set_session(ssl,
+            test_wolfSSL_CTX_add_session_client_sess), WOLFSSL_SUCCESS);
+}
+#endif
+
+static void test_wolfSSL_CTX_add_session(void)
+{
+#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
+    !defined(SINGLE_THREADED) && defined(WOLFSSL_TLS13) && \
+    !defined(NO_SESSION_CACHE)
+    tcp_ready ready;
+    func_args client_args;
+    func_args server_args;
+    THREAD_TYPE serverThread;
+    callback_functions client_cb;
+    callback_functions server_cb;
+    method_provider methods[][2] = {
+#ifndef NO_OLD_TLS
+        { wolfTLSv1_1_client_method, wolfTLSv1_1_server_method },
+#endif
+#ifndef WOLFSSL_NO_TLS12
+        { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method },
+#endif
+        /* Needs the default ticket callback since it is tied to the
+         * connection context and this makes it easy to carry over the ticket
+         * crypto context between connections */
+#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
+    defined(HAVE_SESSION_TICKET)
+        { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method },
+#endif
+    };
+    const size_t methodsLen = sizeof(methods)/sizeof(*methods);
+    size_t i, j;
+
+    printf(testingFmt, "wolfSSL_CTX_add_session()");
+
+    for (i = 0; i < methodsLen; i++) {
+        /* First run creates a connection while the second+ run will attempt
+         * to resume the connection. The trick is that the internal cache
+         * is turned off. wolfSSL_CTX_add_session should put the session in
+         * the cache anyway. */
+        test_wolfSSL_CTX_add_session_client_sess = NULL;
+        test_wolfSSL_CTX_add_session_server_sess = NULL;
+        test_wolfSSL_CTX_add_session_server_ctx = NULL;
+
+        for (j = 0; j < 5; j++) {
+#ifdef WOLFSSL_TIRTOS
+            fdOpenSession(Task_self());
+#endif
+
+            StartTCP();
+            InitTcpReady(&ready);
+
+            XMEMSET(&client_args, 0, sizeof(func_args));
+            XMEMSET(&server_args, 0, sizeof(func_args));
+
+            XMEMSET(&client_cb, 0, sizeof(callback_functions));
+            XMEMSET(&server_cb, 0, sizeof(callback_functions));
+            client_cb.method  = methods[i][0];
+            server_cb.method  = methods[i][1];
+
+            server_args.signal    = &ready;
+            server_args.callbacks = &server_cb;
+            client_args.signal    = &ready;
+            client_args.callbacks = &client_cb;
+
+            if (test_wolfSSL_CTX_add_session_server_ctx != NULL) {
+                server_cb.ctx = test_wolfSSL_CTX_add_session_server_ctx;
+                server_cb.isSharedCtx = 1;
+            }
+            server_cb.ctx_ready = test_wolfSSL_CTX_add_session_ctx_ready;
+            client_cb.ctx_ready = test_wolfSSL_CTX_add_session_ctx_ready;
+            if (j != 0)
+                client_cb.ssl_ready = test_wolfSSL_CTX_add_session_ssl_ready;
+            server_cb.on_result = test_wolfSSL_CTX_add_session_on_result;
+            client_cb.on_result = test_wolfSSL_CTX_add_session_on_result;
+            server_cb.ticNoInit = 1; /* Use default builtin */
+
+            start_thread(test_server_nofail, &server_args, &serverThread);
+            wait_tcp_ready(&server_args);
+            test_client_nofail(&client_args, NULL);
+            join_thread(serverThread);
+
+            AssertTrue(client_args.return_code);
+            AssertTrue(server_args.return_code);
+
+            FreeTcpReady(&ready);
+        }
+        wolfSSL_SESSION_free(test_wolfSSL_CTX_add_session_client_sess);
+        wolfSSL_SESSION_free(test_wolfSSL_CTX_add_session_server_sess);
+        wolfSSL_CTX_free(test_wolfSSL_CTX_add_session_server_ctx);
+    }
+
+    printf(resultFmt, passed);
+
+#endif
+}
+
 #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT)
 /* canned export of a session using older version 3 */
 static unsigned char version_3[] = {
@@ -7961,6 +8134,7 @@ static void test_wolfSSL_PKCS12(void)
     AssertNotNull(pkcs12);
     PKCS12_free(pkcs12);
 
+    AssertIntEQ(BIO_write(bio, buf, bytes), bytes); /* d2i consumes BIO */
     d2i_PKCS12_bio(bio, &pkcs12);
     AssertNotNull(pkcs12);
     BIO_free(bio);
@@ -33653,10 +33827,12 @@ static void post_auth_version_cb(WOLFSSL* ssl)
 
 static void post_auth_cb(WOLFSSL* ssl)
 {
+    WOLFSSL_X509* x509;
     /* do handshake and then test version error */
     AssertIntEQ(wolfSSL_accept(ssl), WOLFSSL_SUCCESS);
     AssertStrEQ("TLSv1.3", wolfSSL_get_version(ssl));
-    AssertNull(wolfSSL_get_peer_certificate(ssl));
+    AssertNull(x509 = wolfSSL_get_peer_certificate(ssl));
+    wolfSSL_X509_free(x509);
     AssertIntEQ(wolfSSL_verify_client_post_handshake(ssl), WOLFSSL_SUCCESS);
 }
 
@@ -49800,11 +49976,15 @@ static void test_wolfSSL_CTX_LoadCRL(void)
 {
 #ifdef HAVE_CRL
     WOLFSSL_CTX* ctx = NULL;
+    WOLFSSL* ssl = NULL;
     const char* badPath = "dummypath";
     const char* validPath = "./certs/crl";
+    const char* validFilePath = "./certs/crl/cliCrl.pem";
+    const char* issuerCert = "./certs/client-cert.pem";
     int derType = WOLFSSL_FILETYPE_ASN1;
     int pemType = WOLFSSL_FILETYPE_PEM;
     int monitor = WOLFSSL_CRL_MONITOR;
+    WOLFSSL_CERT_MANAGER* cm = NULL;
 
     #define FAIL_T1(x, y, z, p, d) AssertIntEQ((int) x(y, z, p, d), \
                                                 BAD_FUNC_ARG)
@@ -49826,7 +50006,27 @@ static void test_wolfSSL_CTX_LoadCRL(void)
     SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, derType, monitor);
 
     wolfSSL_CTX_free(ctx);
-    ctx = NULL;
+
+    AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method()));
+    AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL),
+            WOLFSSL_SUCCESS);
+    AssertIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, validFilePath, pemType), WOLFSSL_SUCCESS);
+    wolfSSL_CTX_free(ctx);
+
+    AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method()));
+    AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL),
+            WOLFSSL_SUCCESS);
+    AssertNotNull(ssl = wolfSSL_new(ctx));
+    AssertIntEQ(wolfSSL_LoadCRLFile(ssl, validFilePath, pemType), WOLFSSL_SUCCESS);
+    wolfSSL_free(ssl);
+    wolfSSL_CTX_free(ctx);
+
+    AssertNotNull(cm = wolfSSL_CertManagerNew());
+    AssertIntEQ(wolfSSL_CertManagerLoadCA(cm, issuerCert, NULL),
+            WOLFSSL_SUCCESS);
+    AssertIntEQ(wolfSSL_CertManagerLoadCRLFile(cm, validFilePath, pemType), WOLFSSL_SUCCESS);
+    wolfSSL_CertManagerFree(cm);
+
 #endif
 }
 
@@ -50920,9 +51120,7 @@ static void test_wolfSSL_CRYPTO_get_ex_new_index(void)
 
     printf(testingFmt, "test_wolfSSL_CRYPTO_get_ex_new_index()");
 
-    /* test for unsupported flass index */
-    AssertIntEQ(wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION,
-                                         0,NULL, NULL, NULL, NULL ), -1);
+    /* test for unsupported class index */
     AssertIntEQ(wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE,
                                          0,NULL, NULL, NULL, NULL ), -1);
     AssertIntEQ(wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX,
@@ -50974,6 +51172,15 @@ static void test_wolfSSL_CRYPTO_get_ex_new_index(void)
     AssertIntNE(idx2, -1);
     AssertIntNE(idx1, idx2);
 
+
+    idx1 = wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION,
+                                         0,NULL, NULL, NULL, NULL );
+    idx2 = wolfSSL_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION,
+                                         0,NULL, NULL, NULL, NULL );
+    AssertIntNE(idx1, -1);
+    AssertIntNE(idx2, -1);
+    AssertIntNE(idx1, idx2);
+
     printf(resultFmt, "passed");
 #endif /* HAVE_EX_DATA */
 }
@@ -52113,6 +52320,7 @@ void ApiTest(void)
 #ifdef HAVE_IO_TESTS_DEPENDENCIES
     test_wolfSSL_get_finished();
 #endif
+    test_wolfSSL_CTX_add_session();
     test_SSL_CIPHER_get_xxx();
     test_wolfSSL_ERR_strings();
     test_wolfSSL_EVP_shake128();

+ 14 - 0
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

+ 4 - 0
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";

+ 43 - 19
wolfssl/internal.h

@@ -2758,6 +2758,7 @@ struct WOLFSSL_CTX {
     byte        sessionCacheFlushOff:1;
 #ifdef HAVE_EXT_CACHE
     byte        internalCacheOff:1;
+    byte        internalCacheLookupOff:1;
 #endif
     byte        sendVerify:2;     /* for client side (can not be single bit) */
     byte        haveRSA:1;        /* RSA available */
@@ -3083,7 +3084,7 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
     WOLFSSL_LOCAL
     int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify);
     WOLFSSL_LOCAL
-    int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash);
+    int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DecodedCert* cert);
 #endif
 #endif
 
@@ -3364,8 +3365,21 @@ struct WOLFSSL_SESSION {
     word16             ticketLenAlloc;    /* is dynamic */
 #endif
     int                refCount;          /* reference count */
+#ifndef SINGLE_THREADED
+    wolfSSL_Mutex      refMutex;          /* ref count mutex */
+#endif
     void*              heap;
 
+#ifdef SESSION_CERTS
+    WOLFSSL_X509_CHAIN chain;             /* peer cert chain, static  */
+    #ifdef WOLFSSL_ALT_CERT_CHAINS
+    WOLFSSL_X509_CHAIN altChain;          /* peer alt cert chain, static */
+    #endif
+#endif
+#ifdef HAVE_EX_DATA
+    WOLFSSL_CRYPTO_EX_DATA ex_data;
+#endif
+
 #ifdef ENABLE_CLIENT_SESSION_REF
     /* pointer to WOLFSSL_SESSION in internal cache (for WOLFSSL_SESSION_TYPE_REF) */
     void*              refPtr;
@@ -3374,7 +3388,8 @@ struct WOLFSSL_SESSION {
     /* Below buffers are not allocated for the WOLFSSL_SESSION_TYPE_REF, instead
      * the above pointers reference the session cache for backwards
      * compatibility. For all other session types the above pointers reference
-     * these buffers directly */
+     * these buffers directly. Keep these buffers at the end so that they don't
+     * get copied into the WOLFSSL_SESSION_TYPE_REF object. */
     byte               _masterSecret[SECRET_LEN];
 #ifndef NO_CLIENT_CACHE
     byte               _serverID[SERVER_ID_LEN];
@@ -3385,21 +3400,6 @@ struct WOLFSSL_SESSION {
 #ifdef OPENSSL_EXTRA
     byte               _sessionCtx[ID_LEN];
 #endif
-
-#ifdef SESSION_CERTS
-    WOLFSSL_X509_CHAIN chain;             /* peer cert chain, static  */
-    #ifdef WOLFSSL_ALT_CERT_CHAINS
-    WOLFSSL_X509_CHAIN altChain;          /* peer alt cert chain, static */
-    #endif
-#endif
-#ifdef HAVE_EX_DATA
-    WOLFSSL_CRYPTO_EX_DATA ex_data;
-#endif
-#ifdef OPENSSL_EXTRA
-    #ifndef SINGLE_THREADED
-    wolfSSL_Mutex      refMutex;          /* ref count mutex */
-    #endif
-#endif
 };
 
 
@@ -3598,6 +3598,7 @@ typedef struct Options {
     word16            sessionCacheFlushOff:1;
 #ifdef HAVE_EXT_CACHE
     word16            internalCacheOff:1;
+    word16            internalCacheLookupOff:1;
 #endif
     word16            side:2;             /* client, server or neither end */
     word16            verifyPeer:1;
@@ -3703,6 +3704,9 @@ typedef struct Options {
     word16            startedETMRead:1;       /* Doing Encrypt-Then-MAC read */
     word16            startedETMWrite:1;      /* Doing Encrypt-Then-MAC write */
 #endif
+#ifdef WOLFSSL_TICKET_HAVE_ID
+    word16          haveTicketSessionID:1;
+#endif
 
     /* need full byte values for this section */
     byte            processReply;           /* nonblocking resume */
@@ -4234,6 +4238,9 @@ struct WOLFSSL {
     WOLFSSL_SESSION session;
 #ifdef HAVE_EXT_CACHE
     WOLFSSL_SESSION* extSession;
+#endif
+#ifdef WOLFSSL_TICKET_HAVE_ID
+    byte            ticketSessionID[ID_LEN];
 #endif
     WOLFSSL_ALERT_HISTORY alert_history;
     int             error;
@@ -4390,6 +4397,8 @@ struct WOLFSSL {
     WOLFSSL_X509_STORE* x509_store_pt; /* take ownership of external store */
 #endif
 #ifdef KEEP_PEER_CERT
+    /* TODO put this on the heap so we can properly use the
+     * reference counter and not have to duplicate it. */
     WOLFSSL_X509     peerCert;           /* X509 peer cert */
 #endif
 #ifdef KEEP_OUR_CERT
@@ -4572,6 +4581,22 @@ struct WOLFSSL {
 #endif
 };
 
+/*
+ * wolfSSL_PEM_read_bio_X509 pushes an ASN_NO_PEM_HEADER error
+ * to the error queue on file end. This should not be left
+ * for the caller to find so we clear the last error.
+ */
+#ifdef WOLFSSL_HAVE_ERROR_QUEUE
+#define CLEAR_ASN_NO_PEM_HEADER_ERROR(err)                  \
+    err = wolfSSL_ERR_peek_last_error();                    \
+    if (ERR_GET_LIB(err) == ERR_LIB_PEM &&                  \
+            ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {   \
+        wc_RemoveErrorNode(-1);                             \
+    }
+#else
+#define CLEAR_ASN_NO_PEM_HEADER_ERROR(err) (void)err;
+#endif
+
 /*
  * The SSL object may have its own certificate store. The below macros simplify
  * logic for choosing which WOLFSSL_CERT_MANAGER and WOLFSSL_X509_STORE to use.
@@ -4827,8 +4852,7 @@ WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG,
         #define WC_MATCH_SKID 0
         #define WC_MATCH_NAME 1
 
-        WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash,
-                                                                      int type);
+        WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert);
         WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp,
                                                              DecodedCert* cert);
     #endif

+ 3 - 3
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 */

+ 1 - 0
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

+ 15 - 9
wolfssl/ssl.h

@@ -32,10 +32,11 @@
 /* for users not using preprocessor flags*/
 #include <wolfssl/wolfcrypt/settings.h>
 #include <wolfssl/version.h>
-#include <wolfssl/wolfcrypt/logging.h>
 #include <wolfssl/wolfcrypt/asn_public.h>
-#include <wolfssl/wolfcrypt/types.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
 #include <wolfssl/wolfcrypt/memory.h>
+#include <wolfssl/wolfcrypt/types.h>
 
 /* For the types */
 #include <wolfssl/openssl/compat_types.h>
@@ -1192,7 +1193,8 @@ WOLFSSL_API int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val);
 
 WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx);
 
-WOLFSSL_ABI WOLFSSL_API int  wolfSSL_pending(WOLFSSL* ssl);
+WOLFSSL_ABI WOLFSSL_API int  wolfSSL_pending(const WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_has_pending(const WOLFSSL* ssl);
 
 WOLFSSL_API void wolfSSL_load_error_strings(void);
 WOLFSSL_API int  wolfSSL_library_init(void);
@@ -2199,12 +2201,12 @@ enum {
 
     X509_V_OK                                    = 0,
     X509_V_ERR_CRL_SIGNATURE_FAILURE             = 8,
-    X509_V_ERR_CERT_HAS_EXPIRED                  = 10,
+    X509_V_ERR_CERT_HAS_EXPIRED                  = ASN_AFTER_DATE_E,
     X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD    = 14,
     X509_V_ERR_CRL_HAS_EXPIRED                   = 15,
     X509_V_ERR_CERT_CHAIN_TOO_LONG               = 17,
     X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT         = 18,
-    X509_V_ERR_CERT_NOT_YET_VALID                = 19,
+    X509_V_ERR_CERT_NOT_YET_VALID                = ASN_BEFORE_DATE_E,
     X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD    = 20,
     X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD     = 22,
     X509_V_ERR_CERT_REVOKED                      = 23,
@@ -2214,7 +2216,7 @@ enum {
     X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN         = 26,
     X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 27,
     X509_V_ERR_CERT_UNTRUSTED                    = 28,
-    X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE   = 29,
+    X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE   = ASN_NO_SIGNER_E,
     X509_V_ERR_SUBJECT_ISSUER_MISMATCH           = 30,
     /* additional X509_V_ERR_* enums not used in wolfSSL */
     X509_V_ERR_UNABLE_TO_GET_CRL,
@@ -3348,6 +3350,8 @@ WOLFSSL_API void* wolfSSL_GetVerifyMacCtx(WOLFSSL* ssl);
             VerifyCallback vc);
     WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm,
                                                          const char* path, int type, int monitor);
+    WOLFSSL_API int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm,
+                                                         const char* file, int type);
     WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
                                             const unsigned char* buff, long sz, int type);
     WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm,
@@ -3389,6 +3393,7 @@ WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(
     WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options);
     WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl);
     WOLFSSL_API int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor);
+    WOLFSSL_API int wolfSSL_LoadCRLFile(WOLFSSL* ssl, const char* file, int type);
     WOLFSSL_API int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl,
                                           const unsigned char* buff, long sz, int type);
     WOLFSSL_API int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb);
@@ -3405,6 +3410,7 @@ WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(
     WOLFSSL_API int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options);
     WOLFSSL_API int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx);
     WOLFSSL_API int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, int type, int monitor);
+    WOLFSSL_API int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* path, int type);
     WOLFSSL_API int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx,
                                             const unsigned char* buff, long sz, int type);
     WOLFSSL_API int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb);
@@ -4313,9 +4319,9 @@ WOLFSSL_API WOLFSSL_ASN1_TYPE *wolfSSL_X509_ATTRIBUTE_get0_type(
 #include <wolfssl/openssl/crypto.h>
 
 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 *));
 

+ 1 - 0
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)

+ 1 - 1
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;

+ 6 - 0
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);

Some files were not shown because too many files changed in this diff