Browse Source

Add support for nginx-1.25.0

- nginx: add necessary defines and function
- Implement Certificate Authorities for TLS 1.3
- Implement secret logging for TLS 1.3. Can be used for example with:
  ./configure CPPFLAGS="-DWOLFSSL_SSLKEYLOGFILE -DSHOW_SECRETS -DHAVE_SECRET_CALLBACK -DWOLFSSL_SSLKEYLOGFILE_OUTPUT='\"/tmp/secrets\"'"
- Implement session context checking for tickets
- Check for authorized responder in OCSP basic response
- Fix handling call to ocsp->statusCb
- compat: Translate SOCKET_PEER_CLOSED_E to WOLFSSL_ERROR_SYSCALL
- Fix wolfSSL_CTX_set_session_cache_mode
  - WOLFSSL_SESS_CACHE_OFF means nothing should be on
  - WOLFSSL_SESS_CACHE_NO_INTERNAL turns off only the internal cache
- Respect ssl->options.internalCacheOff
- Implement SSL_SESSION_set_time
- wolfSSL_SSL_in_init: fix detection for TLS 1.3
- Fix handling call to ssl->alpnSelect
- SendTls13NewSessionTicket: always generate new ID
  - When we send a new ticket for the same session (for example we resumed a connection and are sending a new ticket so that the client can resume in the future), we need to generate a new ID so that we don't overwrite the old session in the cache. Overwriting the session results in the `diff` calculation in `DoClientTicketCheck()` producing the wrong value and failing to resume.
Add nginx github action test
- Fix memory leaks
- wolfSSL_OCSP_basic_verify: implement OCSP_TRUSTOTHER flag
- AKID: implement matching on issuer name and serial number
- ocsp: check for a chain match for OCSP responder
- Split CreateTicket into CreateTicket and SetupTicket
- SendCertificateStatus: free response.buffer
- Use heap hint when allocating responseBuffer
- Remove responseBuffer from internal API's that don't use it anywhere
Juliusz Sosinowicz 9 months ago
parent
commit
0abaa89787
15 changed files with 1177 additions and 225 deletions
  1. 2 0
      .github/workflows/main.yml
  2. 176 0
      .github/workflows/nginx.yml
  3. 12 2
      configure.ac
  4. 105 48
      src/internal.c
  5. 191 40
      src/ocsp.c
  6. 141 52
      src/ssl.c
  7. 274 29
      src/tls.c
  8. 88 2
      src/tls13.c
  9. 2 1
      tests/api.c
  10. 86 21
      wolfcrypt/src/asn.c
  11. 49 13
      wolfssl/internal.h
  12. 9 5
      wolfssl/ocsp.h
  13. 7 0
      wolfssl/openssl/ssl.h
  14. 14 11
      wolfssl/ssl.h
  15. 21 1
      wolfssl/wolfcrypt/asn.h

+ 2 - 0
.github/workflows/main.yml

@@ -26,6 +26,8 @@ jobs:
         uses: ./.github/workflows/openvpn.yml
     hostap:
         uses: ./.github/workflows/hostap.yml
+    nginx:
+        uses: ./.github/workflows/nginx.yml
 # TODO: Currently this test fails. Enable it once it becomes passing.        
 #    haproxy:
 #        uses: ./.github/workflows/haproxy.yml

+ 176 - 0
.github/workflows/nginx.yml

@@ -0,0 +1,176 @@
+name: nginx Tests
+
+on:
+  push:
+  workflow_call:
+
+jobs:
+  build_wolfssl:
+    name: Build wolfSSL
+    # Just to keep it the same as the testing target
+    runs-on: ubuntu-latest
+    steps:
+      - if: ${{ runner.debug }}
+        name: Enable wolfSSL debug logging
+        run: |
+          # We don't use --enable-debug since it makes the logs too loud
+          echo "wolf_debug_flags= CFLAGS='-g3 -O0'" >> $GITHUB_ENV
+
+      - name: Build wolfSSL
+        uses: wolfSSL/actions-build-autotools-project@v1
+        with:
+          path: wolfssl
+          configure: --enable-nginx ${{ env.wolf_debug_flags }}
+          install: true
+
+      - name: Upload built lib
+        uses: actions/upload-artifact@v3
+        with:
+          name: wolf-install-nginx
+          path: build-dir
+          retention-days: 1
+
+  nginx_check:
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          # in general we want to pass all tests that match *ssl*
+          - ref: 1.25.0
+            test-ref: 5b2894ea1afd01a26c589ce11f310df118e42592
+            # Following tests pass with sanitizer on
+            sanitize-ok: >-
+              h2_ssl_proxy_cache.t h2_ssl.t h2_ssl_variables.t h2_ssl_verify_client.t
+              mail_imap_ssl.t mail_ssl_conf_command.t mail_ssl_session_reuse.t
+              mail_ssl.t proxy_ssl_certificate_empty.t proxy_ssl_certificate.t
+              proxy_ssl_certificate_vars.t proxy_ssl_conf_command.t proxy_ssl_name.t
+              ssl_certificate_chain.t ssl_certificate_perl.t ssl_certificates.t
+              ssl_certificate.t ssl_client_escaped_cert.t ssl_conf_command.t
+              ssl_crl.t ssl_curve.t ssl_engine_keys.t ssl_ocsp.t ssl_password_file.t
+              ssl_proxy_protocol.t ssl_proxy_upgrade.t ssl_reject_handshake.t
+              ssl_session_reuse.t ssl_session_ticket_key.t ssl_sni_reneg.t
+              ssl_sni_sessions.t ssl_sni.t ssl_stapling.t ssl.t ssl_verify_client.t
+              ssl_verify_depth.t stream_proxy_ssl_certificate.t stream_proxy_ssl_certificate_vars.t
+              stream_proxy_ssl_conf_command.t stream_proxy_ssl_name_complex.t
+              stream_proxy_ssl_name.t stream_ssl_certificate.t stream_ssl_conf_command.t
+              stream_ssl_preread_alpn.t stream_ssl_preread_protocol.t stream_ssl_preread.t
+              stream_ssl_realip.t stream_ssl_session_reuse.t stream_ssl.t stream_ssl_variables.t
+              stream_ssl_verify_client.t stream_upstream_zone_ssl.t upstream_zone_ssl.t
+              uwsgi_ssl_certificate.t uwsgi_ssl_certificate_vars.t uwsgi_ssl.t
+              uwsgi_ssl_verify.t
+            # Following tests do not pass with sanitizer on (with OpenSSL too)
+            sanitize-not-ok: >-
+              grpc_ssl.t h2_proxy_request_buffering_ssl.t h2_proxy_ssl.t
+              proxy_request_buffering_ssl.t proxy_ssl_keepalive.t proxy_ssl.t
+              proxy_ssl_verify.t stream_proxy_protocol_ssl.t stream_proxy_ssl.t
+              stream_proxy_ssl_verify.t stream_ssl_alpn.t
+    name: ${{ matrix.ref }}
+    runs-on: ubuntu-latest
+    needs: build_wolfssl
+    steps:
+      - name: Download lib
+        uses: actions/download-artifact@v3
+        with:
+          name: wolf-install-nginx
+          path: build-dir
+
+      - name: Install dependencies
+        run: |
+          sudo cpan -iT Proc::Find Net::SSLeay IO::Socket::SSL
+
+      - name: Checkout wolfssl-nginx
+        uses: actions/checkout@v3
+        with:
+          repository: wolfssl/wolfssl-nginx
+          path: wolfssl-nginx
+
+      - name: Checkout nginx
+        uses: actions/checkout@v3
+        with:
+          repository: nginx/nginx
+          path: nginx
+          ref: release-${{ matrix.ref }}
+
+      - name: Apply nginx patch
+        working-directory: nginx
+        run: patch -p1 < ../wolfssl-nginx/nginx-${{ matrix.ref }}-wolfssl.patch
+
+      - if: ${{ runner.debug }}
+        name: Apply nginx debug patch
+        working-directory: nginx
+        run: patch -p1 < ../wolfssl-nginx/nginx-${{ matrix.ref }}-wolfssl-debug.patch
+
+      - name: Checkout nginx-tests
+        uses: actions/checkout@v3
+        with:
+          repository: nginx/nginx-tests
+          path: nginx-tests
+          ref: ${{ matrix.test-ref }}
+
+      - name: Apply nginx-tests patch
+        working-directory: nginx-tests
+        run: patch -p1 < ../wolfssl-nginx/nginx-tests-patches/*${{ matrix.test-ref }}.patch
+
+      - name: Build nginx without sanitizer
+        working-directory: nginx
+        run: |
+          ./auto/configure --with-wolfssl=$GITHUB_WORKSPACE/build-dir --with-http_ssl_module \
+            --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \
+            --with-http_v2_module --with-mail --with-mail_ssl_module
+          make -j
+
+      - name: Confirm nginx built with wolfSSL
+        working-directory: nginx
+        run: ldd objs/nginx | grep wolfssl
+
+      - if: ${{ runner.debug }}
+        name: Run nginx-tests without sanitizer (debug)
+        working-directory: nginx-tests
+        run: |
+          LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GITHUB_WORKSPACE/build-dir/lib \
+            TMPDIR=$GITHUB_WORKSPACE TEST_NGINX_VERBOSE=y TEST_NGINX_CATLOG=y \
+            TEST_NGINX_BINARY=../nginx/objs/nginx prove -v ${{ matrix.sanitize-not-ok }}
+
+      - if: ${{ !runner.debug }}
+        name: Run nginx-tests without sanitizer
+        working-directory: nginx-tests
+        run: |
+          LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GITHUB_WORKSPACE/build-dir/lib \
+            TMPDIR=$GITHUB_WORKSPACE TEST_NGINX_BINARY=../nginx/objs/nginx \
+            prove ${{ matrix.sanitize-not-ok }}
+
+      - if: ${{ runner.debug }}
+        name: Enable wolfSSL debug logging
+        run: |
+          echo "nginx_c_flags=-O0" >> $GITHUB_ENV
+
+      - name: Build nginx with sanitizer
+        working-directory: nginx
+        run: |
+          ./auto/configure --with-wolfssl=$GITHUB_WORKSPACE/build-dir --with-http_ssl_module \
+            --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \
+            --with-http_v2_module --with-mail --with-mail_ssl_module \
+            --with-cc-opt='-fsanitize=address -DNGX_DEBUG_PALLOC=1 -g3 ${{ env.nginx_c_flags }}' \
+            --with-ld-opt='-fsanitize=address ${{ env.nginx_c_flags }}'
+          make -j
+
+      - name: Confirm nginx built with wolfSSL
+        working-directory: nginx
+        run: ldd objs/nginx | grep wolfssl
+
+      - if: ${{ runner.debug }}
+        name: Run nginx-tests with sanitizer (debug)
+        working-directory: nginx-tests
+        run: |
+          LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GITHUB_WORKSPACE/build-dir/lib \
+          TMPDIR=$GITHUB_WORKSPACE TEST_NGINX_VERBOSE=y TEST_NGINX_CATLOG=y \
+          TEST_NGINX_BINARY=../nginx/objs/nginx prove -v ${{ matrix.sanitize-ok }}
+
+      - if: ${{ !runner.debug }}
+        name: Run nginx-tests with sanitizer
+        working-directory: nginx-tests
+        run: |
+          LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GITHUB_WORKSPACE/build-dir/lib \
+            TMPDIR=$GITHUB_WORKSPACE TEST_NGINX_BINARY=../nginx/objs/nginx \
+            prove ${{ matrix.sanitize-ok }}
+ 

+ 12 - 2
configure.ac

@@ -5844,6 +5844,8 @@ fi
 if test "$ENABLED_NGINX" = "yes"
 then
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NGINX -DWOLFSSL_SIGNER_DER_CERT"
+    AM_CFLAGS="$AM_CFLAGS -DOPENSSL_COMPATIBLE_DEFAULTS"
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ERROR_CODE_OPENSSL"
 fi
 
 if test "$ENABLED_HAPROXY" = "yes"
@@ -7836,6 +7838,8 @@ then
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALT_CERT_CHAINS"
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PRIORITIZE_PSK"
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CHECK_ALERT_ON_ERR"
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TICKET_HAVE_ID"
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_OCSP_ISSUER_CHECK"
     ENABLED_TRUSTED_PEER_CERT=yes
 fi
 
@@ -8855,8 +8859,14 @@ fi
 
 if test "$ENABLED_REPRODUCIBLE_BUILD" != "yes"
 then
-    echo "#define LIBWOLFSSL_CONFIGURE_ARGS \"$ac_configure_args\"" | sed 's/\\/\\\\/g' > "${output_objdir}/.build_params" &&
-        echo "#define LIBWOLFSSL_GLOBAL_CFLAGS \"$CPPFLAGS $AM_CPPFLAGS $CFLAGS $AM_CFLAGS\" LIBWOLFSSL_GLOBAL_EXTRA_CFLAGS" | sed 's/\\/\\\\/g' >> "${output_objdir}/.build_params" ||
+    ESCAPED_ARGS="$ac_configure_args"
+    ESCAPED_ARGS=$(echo "$ESCAPED_ARGS" | sed 's/\\/\\\\/g')
+    ESCAPED_ARGS=$(echo "$ESCAPED_ARGS" | sed 's/\"/\\\"/g')
+    ESCAPED_GLOBAL_ARGS="$CPPFLAGS $AM_CPPFLAGS $CFLAGS $AM_CFLAGS"
+    ESCAPED_GLOBAL_ARGS=$(echo "$ESCAPED_GLOBAL_ARGS" | sed 's/\\/\\\\/g')
+    ESCAPED_GLOBAL_ARGS=$(echo "$ESCAPED_GLOBAL_ARGS" | sed 's/\"/\\\"/g')
+    echo "#define LIBWOLFSSL_CONFIGURE_ARGS \"$ESCAPED_ARGS\"" > "${output_objdir}/.build_params" &&
+        echo "#define LIBWOLFSSL_GLOBAL_CFLAGS \"$ESCAPED_GLOBAL_ARGS\" LIBWOLFSSL_GLOBAL_EXTRA_CFLAGS" >> "${output_objdir}/.build_params" ||
         AC_MSG_ERROR([Couldn't create ${output_objdir}/.build_params.])
 else
     rm -f "${output_objdir}/.build_params"

+ 105 - 48
src/internal.c

@@ -2541,8 +2541,8 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
         wolfSSL_X509_STORE_free(ctx->x509_store_pt);
     #endif
     #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY)
-        wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL);
-        ctx->ca_names = NULL;
+        wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL);
+        ctx->client_ca_names = NULL;
     #endif
     #ifdef OPENSSL_EXTRA
         if (ctx->x509Chain) {
@@ -7416,6 +7416,11 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
         return ret;
 #endif
 
+#if defined(HAVE_SECRET_CALLBACK) && defined(SHOW_SECRETS) && \
+    defined(WOLFSSL_SSLKEYLOGFILE)
+    (void)wolfSSL_set_tls13_secret_cb(ssl, tls13ShowSecrets, NULL);
+#endif
+
     return 0;
 }
 
@@ -8143,8 +8148,8 @@ void SSL_ResourceFree(WOLFSSL* ssl)
     #endif
 #endif
 #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY)
-    wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL);
-    ssl->ca_names = NULL;
+    wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
+    ssl->client_ca_names = NULL;
 #endif
 #ifdef WOLFSSL_DTLS13
     Dtls13FreeFsmResources(ssl);
@@ -11927,7 +11932,7 @@ static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
 
 #if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
     defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-static void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType)
+void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType)
 {
     if (nameType == SUBJECT) {
         XSTRNCPY(name->name, dCert->subject, ASN_NAME_MAX);
@@ -13942,7 +13947,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
                                             SSL_CM(ssl)->ocspCheckAll) {
                             WOLFSSL_MSG("Doing Non Leaf OCSP check");
                             ret = CheckCertOCSP_ex(SSL_CM(ssl)->ocsp,
-                                                    args->dCert, NULL, ssl);
+                                                    args->dCert, ssl);
                         #ifdef WOLFSSL_NONBLOCK_OCSP
                             if (ret == OCSP_WANT_READ) {
                                 args->lastErr = ret;
@@ -14331,7 +14336,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
                     if (doLookup && SSL_CM(ssl)->ocspEnabled) {
                         WOLFSSL_MSG("Doing Leaf OCSP check");
                         ret = CheckCertOCSP_ex(SSL_CM(ssl)->ocsp,
-                                                    args->dCert, NULL, ssl);
+                                                    args->dCert, ssl);
                     #ifdef WOLFSSL_NONBLOCK_OCSP
                         if (ret == OCSP_WANT_READ) {
                             goto exit_ppc;
@@ -22078,7 +22083,8 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
 
     if (ret == 0) {
         request->ssl = ssl;
-        ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling, request, response);
+        ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling, request, response,
+                               ssl->heap);
 
         /* Suppressing, not critical */
         if (ret == OCSP_CERT_REVOKED ||
@@ -22418,7 +22424,7 @@ int SendCertificateRequest(WOLFSSL* ssl)
     int    sendSz;
     word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
     word32 dnLen = 0;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)
+#ifndef WOLFSSL_NO_CA_NAMES
     WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
 #endif
     const Suites* suites = WOLFSSL_SUITES(ssl);
@@ -22432,7 +22438,7 @@ int SendCertificateRequest(WOLFSSL* ssl)
     if (IsAtLeastTLSv1_2(ssl))
         reqSz += LENGTH_SZ + suites->hashSigAlgoSz;
 
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)
+#ifndef WOLFSSL_NO_CA_NAMES
     /* Certificate Authorities */
     names = SSL_CA_NAMES(ssl);
     while (names != NULL) {
@@ -22525,7 +22531,7 @@ int SendCertificateRequest(WOLFSSL* ssl)
     /* Certificate Authorities */
     c16toa((word16)dnLen, &output[i]);  /* auth's */
     i += REQ_HEADER_SZ;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)
+#ifndef WOLFSSL_NO_CA_NAMES
     names = SSL_CA_NAMES(ssl);
     while (names != NULL) {
         byte seq[MAX_SEQ_SZ];
@@ -22775,6 +22781,8 @@ int SendCertificateStatus(WOLFSSL* ssl)
             if (ret == 0 && response.buffer) {
                 ret = BuildCertificateStatus(ssl, status_type, &response, 1);
 
+            }
+            if (response.buffer) {
                 XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
                 response.buffer = NULL;
             }
@@ -22851,7 +22859,7 @@ int SendCertificateStatus(WOLFSSL* ssl)
                         if (ret == 0) {
                             request->ssl = ssl;
                         ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling,
-                                                    request, &responses[i + 1]);
+                                        request, &responses[i + 1], ssl->heap);
 
                             /* Suppressing, not critical */
                             if (ret == OCSP_CERT_REVOKED ||
@@ -22877,7 +22885,7 @@ int SendCertificateStatus(WOLFSSL* ssl)
                             NULL != (request = ssl->ctx->chainOcspRequest[i])) {
                     request->ssl = ssl;
                     ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling,
-                                                request, &responses[++i]);
+                                           request, &responses[++i], ssl->heap);
 
                     /* Suppressing, not critical */
                     if (ret == OCSP_CERT_REVOKED ||
@@ -28086,10 +28094,10 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
             return BUFFER_ERROR;
 
     #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)
-        if (ssl->ca_names != ssl->ctx->ca_names)
-            wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL);
-        ssl->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
-        if (ssl->ca_names == NULL) {
+        if (ssl->client_ca_names != ssl->ctx->client_ca_names)
+            wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
+        ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+        if (ssl->client_ca_names == NULL) {
             return MEMORY_ERROR;
         }
     #endif
@@ -28134,7 +28142,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
                 }
 
                 if (ret == 0) {
-                    if (wolfSSL_sk_X509_NAME_push(ssl->ca_names, name)
+                    if (wolfSSL_sk_X509_NAME_push(ssl->client_ca_names, name)
                         == WOLFSSL_FAILURE)
                     {
                         ret = MEMORY_ERROR;
@@ -35441,7 +35449,61 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
 
 #ifdef HAVE_SESSION_TICKET
 
-    /* create a new session ticket, 0 on success */
+#ifdef WOLFSSL_TICKET_HAVE_ID
+    static void GetRealSessionID(WOLFSSL* ssl, const byte** id, byte* idSz)
+    {
+        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;
+        }
+    }
+#endif
+
+    int SetupTicket(WOLFSSL* ssl)
+    {
+        int ret = 0;
+
+        (void)ssl;
+
+#ifdef WOLFSSL_TLS13
+        {
+            /* Client adds to ticket age to obfuscate. */
+            byte ageAdd[AGEADD_LEN]; /* Obfuscation of age */
+            ret = wc_RNG_GenerateBlock(ssl->rng, ageAdd, AGEADD_LEN);
+            if (ret != 0)
+                return ret;
+            ato32(ageAdd, &ssl->session->ticketAdd);
+        }
+#endif
+
+#ifdef WOLFSSL_TICKET_HAVE_ID
+        {
+            const byte* id = NULL;
+            byte idSz = 0;
+
+            GetRealSessionID(ssl, &id, &idSz);
+            if (idSz == 0) {
+                ret = wc_RNG_GenerateBlock(ssl->rng, ssl->session->altSessionID,
+                                           ID_LEN);
+                if (ret != 0)
+                    return ret;
+                ssl->session->haveAltSessionID = 1;
+            }
+        }
+#endif
+        return ret;
+    }
+
+    /* create a new session ticket, 0 on success
+     * Do any kind of setup in SetupTicket */
     int CreateTicket(WOLFSSL* ssl)
     {
         InternalTicket* it;
@@ -35502,14 +35564,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
                 goto error;
             }
 
-            /* Client adds to ticket age to obfuscate. */
-            ret = wc_RNG_GenerateBlock(ssl->rng, it->ageAdd,
-                                       sizeof(it->ageAdd));
-            if (ret != 0) {
-                ret = BAD_TICKET_ENCRYPT;
-                goto error;
-            }
-            ato32(it->ageAdd, &ssl->session->ticketAdd);
+            c32toa(ssl->session->ticketAdd, it->ageAdd);
             c16toa(ssl->session->namedGroup, it->namedGroup);
         #ifdef WOLFSSL_32BIT_MILLI_TIME
             c32toa(now, it->timestamp);
@@ -35530,31 +35585,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
 #endif
         }
 
+#ifdef OPENSSL_EXTRA
+        it->sessionCtxSz = ssl->sessionCtxSz;
+        XMEMCPY(it->sessionCtx, ssl->sessionCtx, ID_LEN);
+#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)
-                    goto error;
-                ssl->session->haveAltSessionID = 1;
-                id = ssl->session->altSessionID;
-                idSz = ID_LEN;
-            }
+            GetRealSessionID(ssl, &id, &idSz);
             /* make sure idSz is not larger than ID_LEN */
             if (idSz > ID_LEN)
                 idSz = ID_LEN;
@@ -35829,6 +35869,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
         (void)suite;
         if (!FindSuiteSSL(ssl, psk->it->suite))
             return -1;
+#endif
+#ifdef OPENSSL_EXTRA
+        if (ssl->sessionCtxSz > 0 &&
+               (psk->it->sessionCtxSz != ssl->sessionCtxSz ||
+                XMEMCMP(psk->it->sessionCtx, ssl->sessionCtx,
+                        ssl->sessionCtxSz) != 0))
+            return -1;
 #endif
         return 0;
     }
@@ -35961,6 +36008,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
             XMEMCPY(it->id, sess->altSessionID, ID_LEN);
         else
             XMEMCPY(it->id, sess->sessionID, ID_LEN);
+#endif
+#ifdef OPENSSL_EXTRA
+        it->sessionCtxSz = sess->sessionCtxSz;
+        XMEMCPY(it->sessionCtx, sess->sessionCtx, sess->sessionCtxSz);
 #endif
     }
 
@@ -36067,6 +36118,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
             break;
         default:
             psk->decryptRet = PSK_DECRYPT_FAIL;
+            WOLFSSL_LEAVE("DoClientTicket_ex", decryptRet);
             return decryptRet;
         }
 #ifdef WOLFSSL_CHECK_MEM_ZERO
@@ -36082,8 +36134,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
 #ifdef WOLFSSL_CHECK_MEM_ZERO
             wc_MemZero_Check(psk->it, sizeof(InternalTicket));
 #endif
+            WOLFSSL_LEAVE("DoClientTicket_ex", ret);
             return ret;
         }
+        WOLFSSL_LEAVE("DoClientTicket_ex", decryptRet);
         return decryptRet;
     }
 #endif /* WOLFSL_TLS13 */
@@ -36186,6 +36240,9 @@ cleanup:
         WOLFSSL_ENTER("SendTicket");
 
         if (ssl->options.createTicket) {
+            ret = SetupTicket(ssl);
+            if (ret != 0)
+                return ret;
             ret = CreateTicket(ssl);
             if (ret != 0)
                 return ret;

+ 191 - 40
src/ocsp.c

@@ -28,6 +28,13 @@
 
 #include <wolfssl/wolfcrypt/settings.h>
 
+/*
+ * WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK:
+ *     Disable looking for an authorized responder in the verification path of
+ *     the issuer. This will make the authorized responder only look at the
+ *     OCSP response signer and direct issuer.
+ */
+
 #ifndef WOLFCRYPT_ONLY
 #ifdef HAVE_OCSP
 
@@ -135,7 +142,7 @@ static int xstat2err(int st)
     }
 }
 
-int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl)
+int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, WOLFSSL* ssl)
 {
     int ret = OCSP_LOOKUP_FAIL;
 
@@ -160,7 +167,7 @@ int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuff
     if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
                                                          ocsp->cm->heap) == 0) {
         ocspRequest->ssl = ssl;
-        ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer);
+        ret = CheckOcspRequest(ocsp, ocspRequest, NULL, NULL);
 
         FreeOcspRequest(ocspRequest);
     }
@@ -172,9 +179,9 @@ int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuff
     WOLFSSL_LEAVE("CheckCertOCSP", ret);
     return ret;
 }
-int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer)
+int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
 {
-    return CheckCertOCSP_ex(ocsp, cert, responseBuffer, NULL);
+    return CheckCertOCSP_ex(ocsp, cert, NULL);
 }
 
 static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
@@ -217,12 +224,14 @@ static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
  * Returns OCSP status
  */
 static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
-                  OcspEntry* entry, CertStatus** status, buffer* responseBuffer)
+                  OcspEntry* entry, CertStatus** status, buffer* responseBuffer,
+                  void* heap)
 {
     int ret = OCSP_INVALID_STATUS;
 
     WOLFSSL_ENTER("GetOcspStatus");
 
+    (void)heap;
     *status = NULL;
 
     if (wc_LockMutex(&ocsp->ocspLock) != 0) {
@@ -252,7 +261,8 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
 
             if (responseBuffer) {
                 responseBuffer->buffer = (byte*)XMALLOC(
-                   (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                   (*status)->rawOcspResponseSz, heap,
+                   DYNAMIC_TYPE_TMP_BUFFER);
 
                 if (responseBuffer->buffer) {
                     responseBuffer->length = (*status)->rawOcspResponseSz;
@@ -277,11 +287,13 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
  * reponseBuffer  Buffer object to return the response with.
  * status         The certificate status object.
  * entry          The OCSP entry for this certificate.
+ * ocspRequest    Request corresponding to response.
+ * heap           Heap hint used for responseBuffer
  * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise.
  */
 int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
                       WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status,
-                      OcspEntry *entry, OcspRequest *ocspRequest)
+                      OcspEntry *entry, OcspRequest *ocspRequest, void* heap)
 {
 #ifdef WOLFSSL_SMALL_STACK
     CertStatus*   newStatus;
@@ -295,6 +307,8 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
     int           ret;
     int           validated      = 0;    /* ocsp validation flag */
 
+    (void)heap;
+
 #ifdef WOLFSSL_SMALL_STACK
     newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
                                                        DYNAMIC_TYPE_OCSP_STATUS);
@@ -336,7 +350,7 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
     }
 
     if (responseBuffer) {
-        responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap,
+        responseBuffer->buffer = (byte*)XMALLOC(responseSz, heap,
                                                 DYNAMIC_TYPE_TMP_BUFFER);
 
         if (responseBuffer->buffer) {
@@ -418,7 +432,7 @@ end:
 #define OCSP_MAX_REQUEST_SZ 2048
 #endif
 int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
-                                                      buffer* responseBuffer)
+                     buffer* responseBuffer, void* heap)
 {
     OcspEntry*  entry          = NULL;
     CertStatus* status         = NULL;
@@ -446,10 +460,16 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
     if (ret != 0)
         return ret;
 
-    ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer);
+    ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer,
+                        heap);
     if (ret != OCSP_INVALID_STATUS)
         return ret;
 
+    if (responseBuffer) {
+        XFREE(responseBuffer->buffer, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        responseBuffer->buffer = NULL;
+    }
+
     /* get SSL and IOCtx */
     ssl = (WOLFSSL*)ocspRequest->ssl;
     ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
@@ -457,16 +477,26 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
 
 #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
     if (ocsp->statusCb != NULL && ssl != NULL) {
+        WOLFSSL_MSG("Calling ocsp->statusCb");
         ret = ocsp->statusCb(ssl, ioCtx);
-        if (ret == 0) {
-            ret = wolfSSL_get_ocsp_response(ssl, &response);
-            ret = CheckOcspResponse(ocsp, response, ret, responseBuffer, status,
-                                entry, NULL);
-            if (response != NULL)
-                XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
-            return ret;
+        switch (ret) {
+            case SSL_TLSEXT_ERR_OK:
+                ret = wolfSSL_get_ocsp_response(ssl, &response);
+                ret = CheckOcspResponse(ocsp, response, ret, responseBuffer,
+                                        status, entry, NULL, heap);
+                if (response != NULL)
+                    XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
+                break;
+            case SSL_TLSEXT_ERR_NOACK:
+                ret = OCSP_LOOKUP_FAIL;
+                break;
+            case SSL_TLSEXT_ERR_ALERT_FATAL:
+            default:
+                WOLFSSL_LEAVE("CheckOcspRequest", ocsp->error);
+                ret = WOLFSSL_FATAL_ERROR;
+                break;
         }
-        WOLFSSL_LEAVE("CheckOcspRequest", ocsp->error);
+        WOLFSSL_LEAVE("CheckOcspRequest", ret);
         return ret;
     }
 #endif
@@ -491,10 +521,6 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
     request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
     if (request == NULL) {
         WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
-        if (responseBuffer) {
-            XFREE(responseBuffer->buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            responseBuffer->buffer = NULL;
-        }
         return MEMORY_ERROR;
     }
 
@@ -511,7 +537,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
 
     if (responseSz >= 0 && response) {
         ret = CheckOcspResponse(ocsp, response, responseSz, responseBuffer, status,
-                            entry, ocspRequest);
+                            entry, ocspRequest, heap);
     }
 
     if (response != NULL && ocsp->cm->ocspRespFreeCb)
@@ -523,9 +549,107 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
     return ret;
 }
 
+#ifdef HAVE_OCSP
+
+#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
+static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert,
+        void* vp) {
+    /* Attempt to build a chain up to cert's issuer */
+    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+    Signer* ca = NULL;
+    Signer* prev = NULL;
+    int passed = 0;
+
+    /*
+     *       Relation between certs:
+     *                 CA
+     *        /                 \
+     *  intermediate(s)   cert in OCSP response
+     *        |           with OCSP key usage ext
+     *  issuer of cert
+     *  in OCSP request
+     */
+
+    /* End loop if no more issuers found or if we have found a self
+     * signed cert (ca == prev) */
+    for (ca = GetCAByName(cm, single->issuerHash); ca != NULL && ca != prev;
+            prev = ca, ca = GetCAByName(cm, ca->issuerNameHash)) {
+        if (XMEMCMP(cert->issuerHash, ca->issuerNameHash,
+                OCSP_DIGEST_SIZE) == 0) {
+            WOLFSSL_MSG("\tOCSP Response signed by authorized "
+                    "responder delegated by issuer "
+                    "(found in chain)");
+            passed = 1;
+            break;
+        }
+    }
+    return passed;
+}
+#endif
+
+/**
+ * Enforce https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2
+ * @param bs   The basic response to verify
+ * @param cert The decoded bs->cert
+ * @return
+ */
+int CheckOcspResponder(OcspResponse *bs, DecodedCert *cert, void* vp)
+{
+    int ret = 0;
+    OcspEntry* single;
+
+    /* Both evaluate to enum values so can't use a pre-processor check */
+    WOLFSSL_ASSERT_EQ(OCSP_DIGEST_SIZE, SIGNER_DIGEST_SIZE);
+
+    (void)vp;
+
+    WOLFSSL_ENTER("CheckOcspResponder");
+
+    /* In the future if this API is used more then it could be beneficial to
+     * implement calling InitDecodedCert and ParseCertRelative here
+     * automatically when cert == NULL. */
+    if (bs == NULL || cert == NULL)
+        return BAD_FUNC_ARG;
+
+    /* Traverse the list and check that the cert has the authority to provide
+     * an OCSP response for each entry. */
+    for (single = bs->single; single != NULL; single = single->next) {
+        int passed = 0;
+
+        if (XMEMCMP(cert->subjectHash, single->issuerHash, OCSP_DIGEST_SIZE)
+                == 0) {
+            WOLFSSL_MSG("\tOCSP Response signed by issuer");
+            passed = 1;
+        }
+        else if ((cert->extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) != 0) {
+            if (XMEMCMP(cert->issuerHash, single->issuerHash,
+                        OCSP_DIGEST_SIZE) == 0) {
+                WOLFSSL_MSG("\tOCSP Response signed by authorized responder "
+                            "delegated by issuer");
+                passed = 1;
+            }
+#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
+            else if (vp != NULL) {
+                passed = CheckOcspResponderChain(single, cert, vp);
+            }
+#endif
+        }
+
+        if (!passed) {
+            WOLFSSL_MSG("\tOCSP Responder not authorized");
+#ifdef OPENSSL_EXTRA
+            bs->verifyError = OCSP_BAD_ISSUER;
+#endif
+            ret = BAD_OCSP_RESPONDER;
+            break;
+        }
+    }
+    return ret;
+}
+#endif /* HAVE_OCSP */
+
 #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
     defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIGHTY)
-
 int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
     WOLFSSL_OCSP_CERTID* id, int* status, int* reason,
     WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd,
@@ -706,38 +830,60 @@ void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
 int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs,
     WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags)
 {
-    int         ret;
+    int         ret = WOLFSSL_FAILURE;
 #ifdef WOLFSSL_SMALL_STACK
-    DecodedCert *cert = (DecodedCert *)
-        XMALLOC(sizeof(*cert), (st && st->cm) ? st->cm->heap : NULL,
-                DYNAMIC_TYPE_DCERT);
-    if (cert == NULL)
-        return WOLFSSL_FAILURE;
+    DecodedCert *cert;
 #else
     DecodedCert cert[1];
 #endif
+    byte        certInit = 0;
+    int         idx;
 
     (void)certs;
 
-    if (flags & OCSP_NOVERIFY) {
-        ret = WOLFSSL_SUCCESS;
-        goto out;
-    }
+    if (flags & OCSP_NOVERIFY)
+        return WOLFSSL_SUCCESS;
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert *)
+        XMALLOC(sizeof(*cert), (st && st->cm) ? st->cm->heap : NULL,
+                DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return WOLFSSL_FAILURE;
+#endif
 
 #ifdef OPENSSL_EXTRA
-    if (bs->verifyError != OCSP_VERIFY_ERROR_NONE) {
-        ret = WOLFSSL_FAILURE;
+    if (bs->verifyError != OCSP_VERIFY_ERROR_NONE)
         goto out;
-    }
 #endif
 
-    ret = WOLFSSL_SUCCESS;
+    if (flags & OCSP_TRUSTOTHER) {
+        for (idx = 0; idx < wolfSSL_sk_X509_num(certs); idx++) {
+            WOLFSSL_X509* x = wolfSSL_sk_X509_value(certs, idx);
+            int derSz = 0;
+            const byte* der = wolfSSL_X509_get_der(x, &derSz);
+
+            if (derSz == (int)bs->certSz && XMEMCMP(bs->cert, der, derSz) == 0) {
+                ret = WOLFSSL_SUCCESS;
+                goto out;
+            }
+        }
+    }
+
     InitDecodedCert(cert, bs->cert, bs->certSz, NULL);
+    certInit = 1;
     if (ParseCertRelative(cert, CERT_TYPE, VERIFY, st->cm) < 0)
-        ret = WOLFSSL_FAILURE;
-    FreeDecodedCert(cert);
+        goto out;
 
+    if (!(flags & OCSP_NOCHECKS)) {
+        if (CheckOcspResponder(bs, cert, st->cm) != 0)
+            goto out;
+    }
+
+    ret = WOLFSSL_SUCCESS;
 out:
+    if (certInit)
+        FreeDecodedCert(cert);
 
 #ifdef WOLFSSL_SMALL_STACK
     XFREE(cert, (st && st->cm) ? st->cm->heap : NULL, DYNAMIC_TYPE_DCERT);
@@ -990,6 +1136,11 @@ WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
     if (req == NULL || cid == NULL || cid->status == NULL)
         return NULL;
 
+    if (req->cid != NULL)
+        wolfSSL_OCSP_CERTID_free(req->cid);
+    /* Keep to free */
+    req->cid = (void*)cid;
+
     XMEMCPY(req->issuerHash, cid->issuerHash, KEYID_SIZE);
     XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, KEYID_SIZE);
     if (cid->status->serialSz > req->serialSz) {

+ 141 - 52
src/ssl.c

@@ -4519,6 +4519,10 @@ int wolfSSL_get_error(WOLFSSL* ssl, int ret)
         return WOLFSSL_ERROR_WANT_WRITE;        /* convert to OpenSSL type */
     else if (ssl->error == ZERO_RETURN || ssl->options.shutdownDone)
         return WOLFSSL_ERROR_ZERO_RETURN;       /* convert to OpenSSL type */
+#ifdef OPENSSL_EXTRA
+    else if (ssl->error == SOCKET_PEER_CLOSED_E)
+        return WOLFSSL_ERROR_SYSCALL;           /* convert to OpenSSL type */
+#endif
 #if defined(WOLFSSL_HAPROXY)
     return GetX509Error(ssl->error);
 #else
@@ -5803,6 +5807,46 @@ Signer* GetCA(void* vp, byte* hash)
     return ret;
 }
 
+#ifdef WOLFSSL_AKID_NAME
+Signer* GetCAByAKID(void* vp, const byte* issuer, word32 issuerSz,
+        const byte* serial, word32 serialSz)
+{
+    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+    Signer* ret = NULL;
+    Signer* signers;
+    byte nameHash[SIGNER_DIGEST_SIZE];
+    byte serialHash[SIGNER_DIGEST_SIZE];
+    word32 row;
+
+    if (cm == NULL || issuer == NULL || issuerSz == 0 ||
+            serial == NULL || serialSz == 0)
+        return NULL;
+
+    if (CalcHashId(issuer, issuerSz, nameHash) != 0 ||
+            CalcHashId(serial, serialSz, serialHash) != 0)
+        return NULL;
+
+    if (wc_LockMutex(&cm->caLock) != 0)
+        return ret;
+
+    /* Unfortunately we need to look through the entire table */
+    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
+        for (signers = cm->caTable[row]; signers != NULL;
+                signers = signers->next) {
+            if (XMEMCMP(signers->subjectNameHash, nameHash, SIGNER_DIGEST_SIZE)
+                    == 0 && XMEMCMP(signers->serialHash, serialHash,
+                                    SIGNER_DIGEST_SIZE) == 0) {
+                ret = signers;
+                break;
+            }
+        }
+    }
+
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+#endif
 
 #ifndef NO_SKID
 /* return CA if found, otherwise NULL. Walk through hash table. */
@@ -6110,6 +6154,9 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
     #ifdef WOLFSSL_SIGNER_DER_CERT
         ret = AllocDer(&signer->derCert, der->length, der->type, NULL);
     }
+    if (ret == 0 && signer != NULL) {
+        ret = CalcHashId(cert->serial, cert->serialSz, signer->serialHash);
+    }
     if (ret == 0 && signer != NULL) {
         XMEMCPY(signer->derCert->buffer, der->buffer, der->length);
     #endif
@@ -6137,7 +6184,10 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
         XMEMCPY(signer->subjectNameHash, cert->subjectHash,
                 SIGNER_DIGEST_SIZE);
     #ifdef HAVE_OCSP
-        XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash, KEYID_SIZE);
+        XMEMCPY(signer->issuerNameHash, cert->issuerHash,
+                SIGNER_DIGEST_SIZE);
+        XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash,
+                KEYID_SIZE);
     #endif
         signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
                                                 : 0xFFFF;
@@ -8641,7 +8691,7 @@ int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
     if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm)) != 0) {
         WOLFSSL_MSG("ParseCert failed");
     }
-    else if ((ret = CheckCertOCSP(cm->ocsp, cert, NULL)) != 0) {
+    else if ((ret = CheckCertOCSP(cm->ocsp, cert)) != 0) {
         WOLFSSL_MSG("CheckCertOCSP failed");
     }
 
@@ -8666,7 +8716,7 @@ int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm,
         return WOLFSSL_SUCCESS;
 
     ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer, status,
-                        entry, ocspRequest);
+                        entry, ocspRequest, NULL);
 
     return ret == 0 ? WOLFSSL_SUCCESS : ret;
 }
@@ -12156,13 +12206,19 @@ long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode)
     if (ctx == NULL)
         return WOLFSSL_FAILURE;
 
-    if (mode == WOLFSSL_SESS_CACHE_OFF)
+    if (mode == WOLFSSL_SESS_CACHE_OFF) {
         ctx->sessionCacheOff = 1;
+#ifdef HAVE_EXT_CACHE
+        ctx->internalCacheOff = 1;
+        ctx->internalCacheLookupOff = 1;
+#endif
+    }
 
     if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0)
         ctx->sessionCacheFlushOff = 1;
 
 #ifdef HAVE_EXT_CACHE
+    /* WOLFSSL_SESS_CACHE_NO_INTERNAL activates both if's */
     if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0)
         ctx->internalCacheOff = 1;
     if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP) != 0)
@@ -14965,6 +15021,22 @@ static int TlsSessionCacheGetAndLock(const byte *id,
     return 0;
 }
 
+static int CheckSessionMatch(const WOLFSSL* ssl, const WOLFSSL_SESSION* sess)
+{
+    if (ssl == NULL || sess == NULL)
+        return 0;
+#ifdef OPENSSL_EXTRA
+    if (ssl->sessionCtxSz > 0 && (ssl->sessionCtxSz != sess->sessionCtxSz ||
+           XMEMCMP(ssl->sessionCtx, sess->sessionCtx, sess->sessionCtxSz) != 0))
+        return 0;
+#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
+    if (IsAtLeastTLSv1_3(ssl->version) != IsAtLeastTLSv1_3(sess->version))
+        return 0;
+#endif
+    return 1;
+}
+
 int TlsSessionCacheGetAndRdLock(const byte *id, const WOLFSSL_SESSION **sess,
         word32 *lockedRow, byte side)
 {
@@ -15040,37 +15112,38 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
 #ifdef HAVE_EXT_CACHE
     if (ssl->ctx->get_sess_cb != NULL) {
         int copy = 0;
+        int found = 0;
         WOLFSSL_SESSION* extSess;
         /* Attempt to retrieve the session from the external cache. */
         WOLFSSL_MSG("Calling external session cache");
         extSess = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, &copy);
         if ((extSess != NULL)
-        #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
-            && (IsAtLeastTLSv1_3(ssl->version) ==
-                IsAtLeastTLSv1_3(extSess->version))
-        #endif
+                && CheckSessionMatch(ssl, extSess)
             ) {
             WOLFSSL_MSG("Session found in external cache");
+            found = 1;
+
             error = wolfSSL_DupSession(extSess, output, 0);
 #ifdef HAVE_EX_DATA
             extSess->ownExData = 1;
             output->ownExData = 0;
 #endif
-            /* If copy not set then free immediately */
-            if (!copy)
-                wolfSSL_FreeSession(ssl->ctx, extSess);
             /* 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;
         }
+        /* If copy not set then free immediately */
+        if (extSess != NULL && !copy)
+            wolfSSL_FreeSession(ssl->ctx, extSess);
+        if (found)
+            return error;
         WOLFSSL_MSG("Session not found in external cache");
     }
 
-    if (ssl->ctx->internalCacheLookupOff) {
+    if (ssl->options.internalCacheLookupOff) {
         WOLFSSL_MSG("Internal cache lookup turned off");
         return WOLFSSL_FAILURE;
     }
@@ -15154,12 +15227,12 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
 #endif
     }
     else {
-#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
-        if (IsAtLeastTLSv1_3(ssl->version) != IsAtLeastTLSv1_3(sess->version)) {
-            WOLFSSL_MSG("Invalid session: different protocol version");
+        if (!CheckSessionMatch(ssl, sess)) {
+            WOLFSSL_MSG("Invalid session: can't be used in this context");
             TlsSessionCacheUnlockRow(row);
             error = WOLFSSL_FAILURE;
         }
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
         else if (LowResTimer() >= (sess->bornOn + sess->timeout)) {
             WOLFSSL_SESSION* wrSess = NULL;
             WOLFSSL_MSG("Invalid session: timed out");
@@ -15932,27 +16005,32 @@ void AddSession(WOLFSSL* ssl)
         idSz = ID_LEN;
     }
 
-    /* Try to add the session to internal cache or external cache
-    if a new_sess_cb is set. Its ok if we don't succeed. */
-    (void)AddSessionToCache(ssl->ctx, session, id, idSz,
+#ifdef HAVE_EXT_CACHE
+    if (!ssl->options.internalCacheOff)
+#endif
+    {
+        /* Try to add the session to internal cache or external cache
+        if a new_sess_cb is set. Its ok if we don't succeed. */
+        (void)AddSessionToCache(ssl->ctx, session, id, idSz,
 #ifdef SESSION_INDEX
-            &ssl->sessionIndex,
+                &ssl->sessionIndex,
 #else
-            NULL,
+                NULL,
 #endif
-            ssl->options.side,
+                ssl->options.side,
 #ifdef HAVE_SESSION_TICKET
-            ssl->options.useTicket,
+                ssl->options.useTicket,
 #else
-            0,
+                0,
 #endif
 #ifdef NO_SESSION_CACHE_REF
-            NULL
+                NULL
 #else
-            (ssl->options.side == WOLFSSL_CLIENT_END) ?
-                    &ssl->clientSession : NULL
+                (ssl->options.side == WOLFSSL_CLIENT_END) ?
+                        &ssl->clientSession : NULL
 #endif
-                    );
+                        );
+    }
 
 #ifdef HAVE_EXT_CACHE
     if (error == 0 && ssl->ctx->new_sess_cb != NULL) {
@@ -17337,8 +17415,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
     {
         WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list");
         if (ctx != NULL) {
-            wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL);
-            ctx->ca_names = names;
+            wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL);
+            ctx->client_ca_names = names;
         }
     }
 
@@ -17347,9 +17425,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
     {
         WOLFSSL_ENTER("wolfSSL_set_client_CA_list");
         if (ssl != NULL) {
-            if (ssl->ca_names != ssl->ctx->ca_names)
-                wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL);
-            ssl->ca_names = names;
+            if (ssl->client_ca_names != ssl->ctx->client_ca_names)
+                wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
+            ssl->client_ca_names = names;
         }
     }
 
@@ -17409,7 +17487,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
 
 #endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */
 
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+#ifndef WOLFSSL_NO_CA_NAMES
     WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list(
             const WOLFSSL_CTX *ctx)
     {
@@ -17420,7 +17498,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
             return NULL;
         }
 
-        return ctx->ca_names;
+        return ctx->client_ca_names;
     }
 
     /* returns the CA's set on server side or the CA's sent from server when
@@ -17450,9 +17528,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
             return WOLFSSL_FAILURE;
         }
 
-        if (ctx->ca_names == NULL) {
-            ctx->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
-            if (ctx->ca_names == NULL) {
+        if (ctx->client_ca_names == NULL) {
+            ctx->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+            if (ctx->client_ca_names == NULL) {
                 WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
                 return WOLFSSL_FAILURE;
             }
@@ -17464,7 +17542,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
             return WOLFSSL_FAILURE;
         }
 
-        if (wolfSSL_sk_X509_NAME_push(ctx->ca_names, nameCopy) != WOLFSSL_SUCCESS) {
+        if (wolfSSL_sk_X509_NAME_push(ctx->client_ca_names, nameCopy) != WOLFSSL_SUCCESS) {
             WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
             wolfSSL_X509_NAME_free(nameCopy);
             return WOLFSSL_FAILURE;
@@ -22165,6 +22243,8 @@ const char* wolfSSL_get_curve_name(WOLFSSL* ssl)
 {
     const char* cName = NULL;
 
+    WOLFSSL_ENTER("wolfSSL_get_curve_name");
+
     if (ssl == NULL)
         return NULL;
 
@@ -23864,7 +23944,7 @@ long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
 }
 #endif /* HAVE_PK_CALLBACKS */
 
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)
 const unsigned char *wolfSSL_SESSION_get0_id_context(
                       const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length)
 {
@@ -26069,6 +26149,20 @@ long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess)
     return timeout;
 }
 
+long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t)
+{
+    word32 tmptime;
+
+    ses = ClientSessionToSession(ses);
+    if (ses == NULL || t < 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    tmptime = t & 0xFFFFFFFF;
+    ses->timeout = tmptime;
+
+    return WOLFSSL_SUCCESS;
+}
 
 long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess)
 {
@@ -26080,19 +26174,15 @@ long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess)
     return bornOn;
 }
 
-long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t)
+long wolfSSL_SESSION_set_time(WOLFSSL_SESSION *ses, long t)
 {
-    word32 tmptime;
 
     ses = ClientSessionToSession(ses);
     if (ses == NULL || t < 0) {
-        return BAD_FUNC_ARG;
+        return 0;
     }
-
-    tmptime = t & 0xFFFFFFFF;
-    ses->timeout = tmptime;
-
-    return WOLFSSL_SUCCESS;
+    ses->bornOn = (word32)t;
+    return t;
 }
 
 #endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */
@@ -33006,10 +33096,9 @@ int wolfSSL_SSL_in_init(WOLFSSL *ssl)
     if (ssl == NULL)
         return WOLFSSL_FAILURE;
 
-    if (ssl->options.side == WOLFSSL_CLIENT_END) {
-        return ssl->options.connectState < SECOND_REPLY_DONE;
-    }
-    return ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
+    /* Can't use ssl->options.connectState and ssl->options.acceptState because
+     * they differ in meaning for TLS <=1.2 and 1.3 */
+    return ssl->options.handShakeState != HANDSHAKE_DONE;
 }
 
 int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl)

+ 274 - 29
src/tls.c

@@ -114,13 +114,6 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions);
     #endif
 #endif
 
-/* Optional Pre-Master-Secret logging for Wireshark */
-#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE)
-#ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT
-    #define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log"
-#endif
-#endif
-
 #ifndef WOLFSSL_NO_TLS12
 
 #ifdef WOLFSSL_SHA384
@@ -1683,19 +1676,29 @@ int ALPN_Select(WOLFSSL *ssl)
 
 #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
     if (ssl->alpnSelect != NULL && ssl->options.side == WOLFSSL_SERVER_END) {
-        if (ssl->alpnSelect(ssl, &sel, &sel_len, ssl->alpn_peer_requested,
-                            ssl->alpn_peer_requested_length,
-                            ssl->alpnSelectArg) == 0) {
-            WOLFSSL_MSG("ALPN protocol match");
-        }
-        else {
-            sel = NULL;
-            sel_len = 0;
+        r = ssl->alpnSelect(ssl, &sel, &sel_len, ssl->alpn_peer_requested,
+                ssl->alpn_peer_requested_length, ssl->alpnSelectArg);
+        switch (r) {
+            case SSL_TLSEXT_ERR_OK:
+                WOLFSSL_MSG("ALPN protocol match");
+                break;
+            case SSL_TLSEXT_ERR_NOACK:
+                WOLFSSL_MSG("ALPN cb no match but not fatal");
+                sel = NULL;
+                sel_len = 0;
+                break;
+            case SSL_TLSEXT_ERR_ALERT_FATAL:
+            default:
+                WOLFSSL_MSG("ALPN cb no match and fatal");
+                SendAlert(ssl, alert_fatal, no_application_protocol);
+                WOLFSSL_ERROR_VERBOSE(UNKNOWN_ALPN_PROTOCOL_NAME_E);
+                return UNKNOWN_ALPN_PROTOCOL_NAME_E;
+                break;
         }
     }
+    else
 #endif
-
-    if (sel == NULL) {
+    {
         r = ALPN_find_match(ssl, &extension, &sel, &sel_len,
                             ssl->alpn_peer_requested,
                             ssl->alpn_peer_requested_length);
@@ -3013,6 +3016,12 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap)
         break;
     }
 
+#ifdef WOLFSSL_TLS13
+    if (csr->response.buffer != NULL) {
+        XFREE(csr->response.buffer, csr->ssl->heap,
+                DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
     XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
     (void)heap;
 }
@@ -3144,7 +3153,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
                                      csr->status_type, csr->options, ssl,
                                      ssl->heap, ssl->devId);
             if (ret != WOLFSSL_SUCCESS)
-                return ret;
+                return ret == 0 ? -1 : ret;
 
             switch (csr->status_type) {
                 case WOLFSSL_CSR_OCSP:
@@ -3187,7 +3196,13 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
                     ret = BUFFER_ERROR;
             }
             if (ret == 0) {
-                csr->response.buffer = (byte*)(input + offset);
+                csr->response.buffer = (byte*)XMALLOC(resp_length, ssl->heap,
+                        DYNAMIC_TYPE_TMP_BUFFER);
+                if (csr->response.buffer == NULL)
+                    ret = MEMORY_ERROR;
+            }
+            if (ret == 0) {
+                XMEMCPY(csr->response.buffer, input + offset, resp_length);
                 csr->response.length = resp_length;
             }
 
@@ -3249,7 +3264,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
         ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
                                                  0, ssl, ssl->heap, ssl->devId);
         if (ret != WOLFSSL_SUCCESS)
-            return ret; /* throw error */
+            return ret == 0 ? -1 : ret; /* throw error */
 
     #if defined(WOLFSSL_TLS13)
         if (ssl->options.tls1_3) {
@@ -3266,14 +3281,17 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
                             ssl->buffers.certificate->length, ssl->heap);
             ret = ParseCert(cert, CERT_TYPE, 1, SSL_CM(ssl));
             if (ret != 0 ) {
+                FreeDecodedCert(cert);
                 XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
                 return ret;
             }
             ret = TLSX_CSR_InitRequest(ssl->extensions, cert, ssl->heap);
             if (ret != 0 ) {
+                FreeDecodedCert(cert);
                 XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
                 return ret;
             }
+            FreeDecodedCert(cert);
             XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
 
             extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
@@ -3358,7 +3376,7 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
                 if (SSL_CM(ssl)->ocspEnabled) {
                     csr->request.ocsp.ssl = ssl;
                     return CheckOcspRequest(SSL_CM(ssl)->ocsp,
-                                                      &csr->request.ocsp, NULL);
+                                              &csr->request.ocsp, NULL, NULL);
                 }
                 else {
                     WOLFSSL_ERROR_VERBOSE(OCSP_LOOKUP_FAIL);
@@ -3790,7 +3808,7 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl)
                 if (SSL_CM(ssl)->ocspEnabled) {
                     csr2->request.ocsp[0].ssl = ssl;
                     return CheckOcspRequest(SSL_CM(ssl)->ocsp,
-                                                  &csr2->request.ocsp[0], NULL);
+                                          &csr2->request.ocsp[0], NULL, NULL);
                 }
                 else {
                     WOLFSSL_ERROR_VERBOSE(OCSP_LOOKUP_FAIL);
@@ -6504,6 +6522,170 @@ int TLSX_Cookie_Use(const WOLFSSL* ssl, const byte* data, word16 len, byte* mac,
 #define CKE_PARSE(a, b, c, d) 0
 
 #endif
+
+#if defined(WOLFSSL_TLS13) && !defined(NO_CERTS) && \
+    !defined(WOLFSSL_NO_CA_NAMES) && defined(OPENSSL_EXTRA)
+/* Currently only settable through compatibility API */
+/******************************************************************************/
+/* Certificate Authorities                                                       */
+/******************************************************************************/
+
+static word16 TLSX_CA_Names_GetSize(void* data)
+{
+    WOLFSSL* ssl = (WOLFSSL*)data;
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
+    word16 size = 0;
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        /* To add support use a different member like ssl->ca_names and
+         * add accessor functions:
+         * - *_set0_CA_list
+         * - *_get0_CA_list */
+        WOLFSSL_MSG("We don't currently support sending the client's list.");
+        return 0;
+    }
+
+    /* Length of names */
+    size += OPAQUE16_LEN;
+    for (names = SSL_CA_NAMES(ssl); names != NULL; names = names->next) {
+        byte seq[MAX_SEQ_SZ];
+        WOLFSSL_X509_NAME* name = names->data.name;
+
+        if (name != NULL) {
+            /* 16-bit length | SEQ | Len | DER of name */
+            size += (word16)(OPAQUE16_LEN + SetSequence(name->rawLen, seq) +
+                             name->rawLen);
+        }
+    }
+    return size;
+}
+
+static word16 TLSX_CA_Names_Write(void* data, byte* output)
+{
+    WOLFSSL* ssl = (WOLFSSL*)data;
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
+    byte* len;
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        /* To add support use a different member like ssl->ca_names and
+         * add accessor functions:
+         * - *_set0_CA_list
+         * - *_get0_CA_list */
+        WOLFSSL_MSG("We don't currently support sending the client's list.");
+        return 0;
+    }
+
+    /* Reserve space for the length value */
+    len = output;
+    output += OPAQUE16_LEN;
+    for (names = SSL_CA_NAMES(ssl); names != NULL; names = names->next) {
+        byte seq[MAX_SEQ_SZ];
+        WOLFSSL_X509_NAME* name = names->data.name;
+
+        if (name != NULL) {
+            c16toa((word16)name->rawLen +
+                   (word16)SetSequence(name->rawLen, seq), output);
+            output += OPAQUE16_LEN;
+            output += SetSequence(name->rawLen, output);
+            XMEMCPY(output, name->raw, name->rawLen);
+            output += name->rawLen;
+        }
+    }
+    /* Write the total length */
+    c16toa((word16)(output - len - OPAQUE16_LEN), len);
+    return (word16)(output - len);
+}
+
+static int TLSX_CA_Names_Parse(WOLFSSL *ssl, const byte* input,
+                                  word16 length, byte isRequest)
+{
+    word16 extLen;
+
+    (void)isRequest;
+
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        /* To add support use a different member like ssl->ca_names and
+         * add accessor functions:
+         * - *_set0_CA_list
+         * - *_get0_CA_list */
+        WOLFSSL_MSG("We don't currently support parsing the client's list.");
+        return 0;
+    }
+
+    if (ssl->client_ca_names != ssl->ctx->client_ca_names)
+        wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
+    ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+    if (ssl->client_ca_names == NULL)
+        return MEMORY_ERROR;
+
+    ato16(input, &extLen);
+    input += OPAQUE16_LEN;
+    length -= OPAQUE16_LEN;
+    if (extLen != length)
+        return BUFFER_ERROR;
+
+    while (length) {
+        word32 idx = 0;
+        WOLFSSL_X509_NAME* name = NULL;
+        int ret = 0;
+        /* Use a DecodedCert struct to get access to GetName to
+         * parse DN name */
+#ifdef WOLFSSL_SMALL_STACK
+        DecodedCert *cert = (DecodedCert *)XMALLOC(
+            sizeof(*cert), ssl->heap, DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            return MEMORY_ERROR;
+#else
+        DecodedCert cert[1];
+#endif
+
+        ato16(input, &extLen);
+        idx += OPAQUE16_LEN;
+
+        if (extLen > length)
+            return BUFFER_ERROR;
+
+        InitDecodedCert(cert, input + idx, extLen, ssl->heap);
+        idx += extLen;
+
+        ret = GetName(cert, SUBJECT, extLen);
+
+        if (ret == 0 && (name = wolfSSL_X509_NAME_new()) == NULL)
+            ret = MEMORY_ERROR;
+
+        if (ret == 0)
+            CopyDecodedName(name, cert, SUBJECT);
+
+        if (ret == 0 && wolfSSL_sk_X509_NAME_push(ssl->client_ca_names, name)
+                == WOLFSSL_FAILURE)
+            ret = MEMORY_ERROR;
+
+        FreeDecodedCert(cert);
+
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+#endif
+        if (ret != 0)
+            return ret;
+
+        input += idx;
+        length -= (word16)idx;
+    }
+    return 0;
+}
+
+#define CAN_GET_SIZE  TLSX_CA_Names_GetSize
+#define CAN_WRITE     TLSX_CA_Names_Write
+#define CAN_PARSE     TLSX_CA_Names_Parse
+
+#else
+
+#define CAN_GET_SIZE(...)  0
+#define CAN_WRITE(...)     0
+#define CAN_PARSE(...)     0
+
+#endif
+
 #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
 /******************************************************************************/
 /* Signature Algorithms                                                       */
@@ -11351,6 +11533,10 @@ void TLSX_FreeAll(TLSX* list, void* heap)
             case TLSX_KEY_SHARE:
                 KS_FREE_ALL((KeyShareEntry*)extension->data, heap);
                 break;
+    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+            case TLSX_CERTIFICATE_AUTHORITIES:
+                break;
+    #endif
 #endif
 #ifdef WOLFSSL_SRTP
             case TLSX_USE_SRTP:
@@ -11376,8 +11562,8 @@ void TLSX_FreeAll(TLSX* list, void* heap)
             ECH_FREE((WOLFSSL_ECH*)extension->data, heap);
             break;
 #endif
-            default:
-                break;
+        default:
+            break;
         }
 
         XFREE(extension, heap, DYNAMIC_TYPE_TLSX);
@@ -11525,6 +11711,11 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
             case TLSX_KEY_SHARE:
                 length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType);
                 break;
+    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+            case TLSX_CERTIFICATE_AUTHORITIES:
+                length += CAN_GET_SIZE(extension->data);
+                break;
+    #endif
 #endif
 #ifdef WOLFSSL_SRTP
             case TLSX_USE_SRTP:
@@ -11731,6 +11922,12 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
                 offset += KS_WRITE((KeyShareEntry*)extension->data,
                                                       output + offset, msgType);
                 break;
+    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+            case TLSX_CERTIFICATE_AUTHORITIES:
+                WOLFSSL_MSG("Certificate Authorities extension to write");
+                offset += CAN_WRITE(extension->data, output + offset);
+                break;
+    #endif
 #endif
 #ifdef WOLFSSL_SRTP
             case TLSX_USE_SRTP:
@@ -12082,6 +12279,17 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
     ret = 0;
 #endif
 #ifdef WOLFSSL_TLS13
+    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+        if (isServer && IsAtLeastTLSv1_3(ssl->version)) {
+            if (SSL_CA_NAMES(ssl) != NULL) {
+                WOLFSSL_MSG("Adding certificate authorities extension");
+                if ((ret = TLSX_Push(&ssl->extensions,
+                        TLSX_CERTIFICATE_AUTHORITIES, ssl, ssl->heap)) != 0) {
+                        return ret;
+                }
+            }
+        }
+    #endif
         if (!isServer && IsAtLeastTLSv1_3(ssl->version)) {
             /* Add mandatory TLS v1.3 extension: supported version */
             WOLFSSL_MSG("Adding supported versions extension");
@@ -12558,8 +12766,9 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength)
             TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
 #endif
 #if defined(WOLFSSL_TLS13)
-        if (!IsAtLeastTLSv1_2(ssl))
+        if (!IsAtLeastTLSv1_2(ssl)) {
             TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
+        }
     #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
         if (!IsAtLeastTLSv1_3(ssl->version)) {
             TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
@@ -12576,6 +12785,10 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength)
         #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
             TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
         #endif
+        #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+            TURN_ON(semaphore,
+                    TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
+        #endif
         }
     #endif
 #endif /* WOLFSSL_TLS13 */
@@ -12597,8 +12810,11 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength)
 #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
         TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
 #endif
-        /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
-         *       TLSX_CERTIFICATE_AUTHORITIES, OID_FILTERS
+#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+        if (SSL_CA_NAMES(ssl) != NULL)
+            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
+#endif
+        /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, OID_FILTERS
          *       TLSX_STATUS_REQUEST
          */
     }
@@ -12801,6 +13017,10 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset)
         #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
             TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
         #endif
+        #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+            TURN_ON(semaphore,
+                    TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
+        #endif
         }
     #endif
     #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
@@ -12828,8 +13048,13 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset)
 #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
         TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
 #endif
-        /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
-         *       TLSX_CERTIFICATE_AUTHORITIES, TLSX_OID_FILTERS
+#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+        if (SSL_CA_NAMES(ssl) != NULL) {
+            TURN_OFF(semaphore,
+                    TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
+        }
+#endif
+        /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, TLSX_OID_FILTERS
          *       TLSX_STATUS_REQUEST
          */
     }
@@ -13739,6 +13964,26 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
                 break;
     #endif
 
+    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+            case TLSX_CERTIFICATE_AUTHORITIES:
+                WOLFSSL_MSG("Certificate Authorities extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                if (!IsAtLeastTLSv1_3(ssl->version))
+                    break;
+
+                if (msgType != client_hello &&
+                        msgType != certificate_request) {
+                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
+                    return EXT_NOT_ALLOWED;
+                }
+
+                ret = CAN_PARSE(ssl, input + offset, size, isRequest);
+                break;
+    #endif
+
             case TLSX_KEY_SHARE:
                 WOLFSSL_MSG("Key Share extension received");
             #ifdef WOLFSSL_DEBUG_TLS

+ 88 - 2
src/tls13.c

@@ -5763,6 +5763,8 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, const byte* suite, int* err)
     int         found = 0;
     byte        foundSuite[SUITE_LEN];
 
+    WOLFSSL_ENTER("FindPsk");
+
     ret = FindPskSuite(ssl, psk, ssl->arrays->psk_key, &ssl->arrays->psk_keySz,
                        suite, &found, foundSuite);
     if (ret == 0 && found) {
@@ -5797,6 +5799,8 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, const byte* suite, int* err)
     }
 
     *err = ret;
+    WOLFSSL_LEAVE("FindPsk", found);
+    WOLFSSL_LEAVE("FindPsk", ret);
     return found;
 }
 #endif /* !NO_PSK */
@@ -10601,9 +10605,24 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl)
             ssl->session->ticketNonce.data[0]++;
     }
 
+    if ((ssl->options.mask & WOLFSSL_OP_NO_TICKET) != 0) {
+        /* In this case we only send the ID as the ticket. Let's generate a new
+         * ID for the new ticket so that we don't overwrite any old ones */
+        ret = wc_RNG_GenerateBlock(ssl->rng, ssl->session->altSessionID,
+                                   ID_LEN);
+        if (ret != 0)
+            return ret;
+        ssl->session->haveAltSessionID = 1;
+    }
+
     if (!ssl->options.noTicketTls13) {
-        if ((ret = CreateTicket(ssl)) != 0)
+        if ((ret = SetupTicket(ssl)) != 0)
             return ret;
+        /* No need to create the ticket if we only send the ID */
+        if ((ssl->options.mask & WOLFSSL_OP_NO_TICKET) == 0) {
+            if ((ret = CreateTicket(ssl)) != 0)
+                return ret;
+        }
     }
 
 #ifdef WOLFSSL_EARLY_DATA
@@ -10662,7 +10681,7 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl)
         if (ssl->session->haveAltSessionID)
             XMEMCPY(output + idx, ssl->session->altSessionID, ID_LEN);
         else
-            XMEMCPY(output + idx, ssl->session->sessionID, ID_LEN);
+            return BAD_FUNC_ARG; /* Should not happen */
         idx += ID_LEN;
     }
     else {
@@ -13665,6 +13684,73 @@ int wolfSSL_set_tls13_secret_cb(WOLFSSL* ssl, Tls13SecretCb cb, void* ctx)
 
     return WOLFSSL_SUCCESS;
 }
+
+#if defined(SHOW_SECRETS) && defined(WOLFSSL_SSLKEYLOGFILE)
+int tls13ShowSecrets(WOLFSSL* ssl, int id, const unsigned char* secret,
+    int secretSz, void* ctx)
+{
+    int i;
+    const char* str = NULL;
+    byte clientRandom[RAN_LEN];
+    int clientRandomSz;
+    XFILE fp;
+
+    (void) ctx;
+#ifdef WOLFSSL_SSLKEYLOGFILE_OUTPUT
+    fp = XFOPEN(WOLFSSL_SSLKEYLOGFILE_OUTPUT, "ab");
+    if (fp == XBADFILE) {
+        return BAD_FUNC_ARG;
+    }
+#else
+    fp = stderr;
+#endif
+
+    clientRandomSz = (int)wolfSSL_get_client_random(ssl, clientRandom,
+        sizeof(clientRandom));
+
+    if (clientRandomSz <= 0) {
+        printf("Error getting server random %d\n", clientRandomSz);
+    }
+
+#if 0
+    printf("TLS Server Secret CB: Rand %d, Secret %d\n",
+        serverRandomSz, secretSz);
+#endif
+
+    switch (id) {
+        case CLIENT_EARLY_TRAFFIC_SECRET:
+            str = "CLIENT_EARLY_TRAFFIC_SECRET"; break;
+        case EARLY_EXPORTER_SECRET:
+            str = "EARLY_EXPORTER_SECRET"; break;
+        case CLIENT_HANDSHAKE_TRAFFIC_SECRET:
+            str = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"; break;
+        case SERVER_HANDSHAKE_TRAFFIC_SECRET:
+            str = "SERVER_HANDSHAKE_TRAFFIC_SECRET"; break;
+        case CLIENT_TRAFFIC_SECRET:
+            str = "CLIENT_TRAFFIC_SECRET_0"; break;
+        case SERVER_TRAFFIC_SECRET:
+            str = "SERVER_TRAFFIC_SECRET_0"; break;
+        case EXPORTER_SECRET:
+            str = "EXPORTER_SECRET"; break;
+    }
+
+    fprintf(fp, "%s ", str);
+    for (i = 0; i < (int)clientRandomSz; i++) {
+        fprintf(fp, "%02x", clientRandom[i]);
+    }
+    fprintf(fp, " ");
+    for (i = 0; i < secretSz; i++) {
+        fprintf(fp, "%02x", secret[i]);
+    }
+    fprintf(fp, "\n");
+
+#ifdef WOLFSSL_SSLKEYLOGFILE_OUTPUT
+    XFCLOSE(fp);
+#endif
+
+    return 0;
+}
+#endif
 #endif
 
 #undef ERROR_OUT

+ 2 - 1
tests/api.c

@@ -8275,7 +8275,8 @@ static int test_wolfSSL_CTX_add_session_ext(
                     /* (D)TLSv1.3 creates a new ticket,
                      * updates both internal and external cache */
                     ExpectIntEQ(twcase_new_session_called, 1);
-                    ExpectIntEQ(twcase_remove_session_called, 1);
+                    /* A new session ID is created for a new ticket */
+                    ExpectIntEQ(twcase_remove_session_called, 2);
 
                 }
                 else {

+ 86 - 21
wolfcrypt/src/asn.c

@@ -63,7 +63,7 @@ ASN Options:
     does not perform a PKI validation, so it is not a secure solution.
     Only enabled for OCSP.
  * WOLFSSL_NO_OCSP_ISSUER_CHECK: Can be defined for backwards compatibility to
-    disable checking of OCSP subject hash with issuer hash.
+    disable checking of https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2.
  * WOLFSSL_SMALL_CERT_VERIFY: Verify the certificate signature without using
     DecodedCert. Doubles up on some code but allows smaller dynamic memory
     usage.
@@ -190,8 +190,8 @@ ASN Options:
     #include <wolfssl/wolfcrypt/cryptocb.h>
 #endif
 
+#include <wolfssl/internal.h>
 #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    #include <wolfssl/internal.h>
     #include <wolfssl/openssl/objects.h>
 #endif
 
@@ -18843,7 +18843,6 @@ static int DecodeAuthKeyId(const byte* input, word32 sz, DecodedCert* cert)
 #else
     DECL_ASNGETDATA(dataASN, authKeyIdASN_Length);
     int ret = 0;
-    word32 idx = 0;
 
     WOLFSSL_ENTER("DecodeAuthKeyId");
 
@@ -18851,31 +18850,59 @@ static int DecodeAuthKeyId(const byte* input, word32 sz, DecodedCert* cert)
 
     if (ret == 0) {
         /* Parse an authority key identifier. */
+        word32 idx = 0;
         ret = GetASN_Items(authKeyIdASN, dataASN, authKeyIdASN_Length, 1, input,
                            &idx, sz);
     }
-    if (ret == 0) {
-        /* Key id is optional. */
-        if (dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.data == NULL) {
-            WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available");
-        }
-        else {
+    /* Each field is optional */
+    if (ret == 0 && dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.data != NULL) {
 #ifdef OPENSSL_EXTRA
-            /* Store the authority key id. */
-#ifdef WOLFSSL_AKID_NAME
-            cert->extRawAuthKeyIdSrc = input;
-            cert->extRawAuthKeyIdSz = sz;
-#endif
-            GetASN_GetConstRef(&dataASN[AUTHKEYIDASN_IDX_KEYID], &cert->extAuthKeyIdSrc,
-                               &cert->extAuthKeyIdSz);
+        GetASN_GetConstRef(&dataASN[AUTHKEYIDASN_IDX_KEYID],
+                &cert->extAuthKeyIdSrc, &cert->extAuthKeyIdSz);
 #endif /* OPENSSL_EXTRA */
+        /* Get the hash or hash of the hash if wrong size. */
+        ret = GetHashId(dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.data,
+                    (int)dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.length,
+                    cert->extAuthKeyId, HashIdAlg(cert->signatureOID));
+    }
+#ifdef WOLFSSL_AKID_NAME
+    if (ret == 0 && dataASN[AUTHKEYIDASN_IDX_ISSUER].data.ref.data != NULL) {
+        /* We only support using one (first) name. Parse the name to perform
+         * a sanity check. */
+        word32 idx = 0;
+        ASNGetData nameASN[altNameASN_Length];
+        XMEMSET(nameASN, 0, sizeof(nameASN));
+        /* Parse GeneralName with the choices supported. */
+        GetASN_Choice(&nameASN[ALTNAMEASN_IDX_GN], generalNameChoice);
+        /* Decode a GeneralName choice. */
+        ret = GetASN_Items(altNameASN, nameASN, altNameASN_Length, 0,
+                dataASN[AUTHKEYIDASN_IDX_ISSUER].data.ref.data, &idx,
+                dataASN[AUTHKEYIDASN_IDX_ISSUER].data.ref.length);
 
-            /* Get the hash or hash of the hash if wrong size. */
-            ret = GetHashId(dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.data,
-                        (int)dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.length,
-                        cert->extAuthKeyId, HashIdAlg((int)cert->signatureOID));
+        if (ret == 0) {
+            GetASN_GetConstRef(&nameASN[ALTNAMEASN_IDX_GN],
+                    &cert->extAuthKeyIdIssuer, &cert->extAuthKeyIdIssuerSz);
+        }
+    }
+    if (ret == 0 && dataASN[AUTHKEYIDASN_IDX_SERIAL].data.ref.data != NULL) {
+        GetASN_GetConstRef(&dataASN[AUTHKEYIDASN_IDX_SERIAL],
+                &cert->extAuthKeyIdIssuerSN, &cert->extAuthKeyIdIssuerSNSz);
+    }
+    if (ret == 0) {
+        if ((cert->extAuthKeyIdIssuerSz > 0) ^
+                (cert->extAuthKeyIdIssuerSNSz > 0)) {
+            WOLFSSL_MSG("authorityCertIssuer and authorityCertSerialNumber MUST"
+                       " both be present or both be absent");
         }
     }
+#endif /* WOLFSSL_AKID_NAME */
+    if (ret == 0) {
+#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_AKID_NAME)
+        /* Store the raw authority key id. */
+        cert->extRawAuthKeyIdSrc = input;
+        cert->extRawAuthKeyIdSz = sz;
+#endif /* OPENSSL_EXTRA */
+    }
 
     FREE_ASNGETDATA(dataASN, cert->heap);
     return ret;
@@ -21454,6 +21481,19 @@ Signer* GetCAByName(void* signers, byte* hash)
 }
 #endif /* NO_SKID */
 
+#ifdef WOLFSSL_AKID_NAME
+Signer* GetCAByAKID(void* vp, const byte* issuer, word32 issuerSz,
+        const byte* serial, word32 serialSz)
+{
+    (void)issuer;
+    (void)issuerSz;
+    (void)serial;
+    (void)serialSz;
+
+    return (Signer*)vp;
+}
+#endif
+
 #endif /* WOLFCRYPT_ONLY */
 
 #if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
@@ -22576,6 +22616,13 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
     #ifndef NO_SKID
             if (cert->extAuthKeyIdSet) {
                 cert->ca = GetCA(cm, cert->extAuthKeyId);
+        #ifdef WOLFSSL_AKID_NAME
+                if (cert->ca == NULL) {
+                    cert->ca = GetCAByAKID(cm, cert->extAuthKeyIdIssuer,
+                        cert->extAuthKeyIdIssuerSz, cert->extAuthKeyIdIssuerSN,
+                        cert->extAuthKeyIdIssuerSNSz);
+                }
+        #endif
             }
             if (cert->ca == NULL && cert->extSubjKeyIdSet
                                  && verify != VERIFY_OCSP) {
@@ -34140,6 +34187,9 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
     if (ret == 0) {
         /* Store serial size. */
         cs->serialSz = serialSz;
+        /* Set the hash algorithm OID */
+        single->hashAlgoOID =
+                dataASN[SINGLERESPONSEASN_IDX_CID_HASHALGO_OID].data.oid.sum;
 
         /* Determine status by which item was found. */
         if (dataASN[SINGLERESPONSEASN_IDX_CS_GOOD].tag != 0) {
@@ -34909,7 +34959,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
     if ((ret == 0) &&
             (dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL)) {
     #endif
-        /* Initialize the crtificate object. */
+        /* Initialize the certificate object. */
         InitDecodedCert(cert, resp->cert, resp->certSz, heap);
         certInit = 1;
         /* Parse the certificate and don't verify if we don't have access to
@@ -34920,6 +34970,13 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
             WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
         }
     }
+#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
+    if ((ret == 0) &&
+            (dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL) &&
+            !noVerify) {
+        ret = CheckOcspResponder(resp, cert, cm);
+    }
+#endif /* WOLFSSL_NO_OCSP_ISSUER_CHECK */
     if ((ret == 0) &&
             (dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL)) {
         /* TODO: ConfirmSignature is blocking here */
@@ -35587,6 +35644,14 @@ void FreeOcspRequest(OcspRequest* req)
         if (req->url)
             XFREE(req->url, req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
         req->url = NULL;
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_APACHE_HTTPD) || \
+    defined(HAVE_LIGHTY)
+        if (req->cid != NULL)
+            wolfSSL_OCSP_CERTID_free((WOLFSSL_OCSP_CERTID*)req->cid);
+        req->cid = NULL;
+#endif
     }
 }
 

+ 49 - 13
wolfssl/internal.h

@@ -1030,6 +1030,13 @@
 
 #undef WSSL_HARDEN_TLS
 
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY)
+#define SSL_CA_NAMES(ssl) ((ssl)->client_ca_names != NULL ? (ssl)->client_ca_names : \
+        (ssl)->ctx->client_ca_names)
+#else
+#define WOLFSSL_NO_CA_NAMES
+#endif
+
 /* actual cipher values, 2nd byte */
 enum {
     TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x16,
@@ -1991,11 +1998,19 @@ enum Misc {
 
 #define MAX_ENCRYPT_SZ ENCRYPT_LEN
 
-#define WOLFSSL_ASSERT_SIZEOF_GE(x, y) do {                           \
-    typedef char _args_test_[sizeof((x)) >= sizeof((y)) ? 1 : -1];    \
-    (void)sizeof(_args_test_);                                        \
+/* A static check to assert a relation between x and y */
+#define WOLFSSL_ASSERT_TEST(x, y, op) do {         \
+    typedef char _args_test_[(x) op (y) ? 1 : -1]; \
+    (void)sizeof(_args_test_);                     \
 } while(0)
 
+#define WOLFSSL_ASSERT_EQ(x, y) WOLFSSL_ASSERT_TEST(x, y, ==)
+
+#define WOLFSSL_ASSERT_SIZEOF_TEST(x, y, op) \
+    WOLFSSL_ASSERT_TEST(sizeof((x)), sizeof((y)), op)
+
+#define WOLFSSL_ASSERT_SIZEOF_GE(x, y) WOLFSSL_ASSERT_SIZEOF_TEST(x, y, >=)
+
 /* states. Adding state before HANDSHAKE_DONE will break session importing */
 enum states {
     NULL_STATE = 0,
@@ -2154,7 +2169,9 @@ WOLFSSL_LOCAL int  MatchDomainName(const char* pattern, int len, const char* str
 #ifndef NO_CERTS
 WOLFSSL_LOCAL int  CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN);
 WOLFSSL_LOCAL int  CheckIPAddr(DecodedCert* dCert, const char* ipasc);
+WOLFSSL_LOCAL void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType);
 #endif
+WOLFSSL_LOCAL int  SetupTicket(WOLFSSL* ssl);
 WOLFSSL_LOCAL int  CreateTicket(WOLFSSL* ssl);
 WOLFSSL_LOCAL int  HashRaw(WOLFSSL* ssl, const byte* output, int sz);
 WOLFSSL_LOCAL int  HashOutput(WOLFSSL* ssl, const byte* output, int sz,
@@ -2779,6 +2796,9 @@ typedef enum {
     #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
     TLSX_PSK_KEY_EXCHANGE_MODES     = 0x002d,
     #endif
+    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
+    TLSX_CERTIFICATE_AUTHORITIES    = 0x002f,
+    #endif
     #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
     TLSX_POST_HANDSHAKE_AUTH        = 0x0031,
     #endif
@@ -3008,7 +3028,7 @@ typedef struct {
     union {
         OcspRequest ocsp;
     } request;
-#if defined(WOLFSSL_TLS13)
+#ifdef WOLFSSL_TLS13
     buffer response;
 #endif
 } CertificateStatusRequest;
@@ -3163,6 +3183,10 @@ typedef struct InternalTicket {
 #ifdef WOLFSSL_TICKET_HAVE_ID
     byte            id[ID_LEN];
 #endif
+#ifdef OPENSSL_EXTRA
+    byte            sessionCtxSz;          /* sessionCtx length        */
+    byte            sessionCtx[ID_LEN];    /* app specific context id */
+#endif /* OPENSSL_EXTRA */
 } InternalTicket;
 
 #ifndef WOLFSSL_TICKET_EXTRA_PADDING_SZ
@@ -3449,8 +3473,8 @@ struct WOLFSSL_CTX {
     DerBuffer*  certificate;
     DerBuffer*  certChain;
                  /* chain after self, in DER, with leading size for each cert */
-    #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY)
-    WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names;
+    #ifndef WOLFSSL_NO_CA_NAMES
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* client_ca_names;
     #endif
     #ifdef OPENSSL_EXTRA
     WOLF_STACK_OF(WOLFSSL_X509)* x509Chain;
@@ -4822,7 +4846,7 @@ struct WOLFSSL_X509_NAME {
     WOLFSSL_X509_NAME_ENTRY entry[MAX_NAME_ENTRIES]; /* all entries i.e. CN */
     WOLFSSL_X509*           x509;   /* x509 that struct belongs to */
 #endif /* OPENSSL_EXTRA */
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)
+#ifndef WOLFSSL_NO_CA_NAMES
     byte  raw[ASN_NAME_MAX];
     int   rawLen;
 
@@ -5720,8 +5744,8 @@ struct WOLFSSL {
     byte clientFinished_len;
     byte serverFinished_len;
 #endif
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY)
-    WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names;
+#ifndef WOLFSSL_NO_CA_NAMES
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* client_ca_names;
 #endif
 #if defined(WOLFSSL_IOTSAFE) && defined(HAVE_PK_CALLBACKS)
     IOTSAFE iotsafe;
@@ -5792,9 +5816,6 @@ struct WOLFSSL {
         }                                                            \
     } while (0)
 
-#define SSL_CA_NAMES(ssl) ((ssl)->ca_names != NULL ? (ssl)->ca_names : \
-        (ssl)->ctx->ca_names)
-
 WOLFSSL_LOCAL int  SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup);
 WOLFSSL_LOCAL int  InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup);
 WOLFSSL_LOCAL int  ReinitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup);
@@ -6079,7 +6100,11 @@ WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG,
                                                              DecodedCert* cert);
     #endif
 
-    WOLFSSL_LOCAL Signer* GetCA(void* cm, byte* hash);
+    WOLFSSL_LOCAL Signer* GetCA(void* vp, byte* hash);
+    #ifdef WOLFSSL_AKID_NAME
+        WOLFSSL_LOCAL Signer* GetCAByAKID(void* vp, const byte* issuer,
+                word32 issuerSz, const byte* serial, word32 serialSz);
+    #endif
     #ifndef NO_SKID
         WOLFSSL_LOCAL Signer* GetCAByName(void* cm, byte* hash);
     #endif
@@ -6508,6 +6533,17 @@ WOLFSSL_LOCAL int wolfSSL_quic_keys_active(WOLFSSL* ssl, enum encrypt_side side)
 #define WOLFSSL_IS_QUIC(s) 0
 #endif /* WOLFSSL_QUIC (else) */
 
+#if defined(SHOW_SECRETS) && defined(WOLFSSL_SSLKEYLOGFILE)
+WOLFSSL_LOCAL int tls13ShowSecrets(WOLFSSL* ssl, int id, const unsigned char* secret,
+    int secretSz, void* ctx);
+#endif
+
+/* Optional Pre-Master-Secret logging for Wireshark */
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE)
+#ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT
+    #define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log"
+#endif
+#endif
 
 #if defined(WOLFSSL_TLS13) && !defined(NO_PSK)
 WOLFSSL_LOCAL int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk,

+ 9 - 5
wolfssl/ocsp.h

@@ -53,15 +53,19 @@ typedef struct OcspRequest WOLFSSL_OCSP_REQUEST;
 WOLFSSL_LOCAL int  InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm);
 WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic);
 
-WOLFSSL_LOCAL int  CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert,
-                                 WOLFSSL_BUFFER_INFO* responseBuffer);
+WOLFSSL_LOCAL int  CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert);
 WOLFSSL_LOCAL int  CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert,
-                                    WOLFSSL_BUFFER_INFO* responseBuffer, WOLFSSL* ssl);
+                                    WOLFSSL* ssl);
 WOLFSSL_LOCAL int  CheckOcspRequest(WOLFSSL_OCSP* ocsp,
-                 OcspRequest* ocspRequest, WOLFSSL_BUFFER_INFO* responseBuffer);
+                 OcspRequest* ocspRequest, WOLFSSL_BUFFER_INFO* responseBuffer,
+                 void* heap);
 WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
                                     WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status,
-                                    OcspEntry *entry, OcspRequest *ocspRequest);
+                                    OcspEntry *entry, OcspRequest *ocspRequest,
+                                    void* heap);
+
+WOLFSSL_LOCAL int CheckOcspResponder(OcspResponse *bs, DecodedCert *cert,
+                                     void* vp);
 
 #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
     defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIGHTY)

+ 7 - 0
wolfssl/openssl/ssl.h

@@ -1083,6 +1083,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_
                                         wolfSSL_SESSION_get_ticket_lifetime_hint
 #define SSL_SESSION_set_timeout         wolfSSL_SSL_SESSION_set_timeout
 #define SSL_SESSION_get_timeout         wolfSSL_SESSION_get_timeout
+#define SSL_SESSION_set_time            wolfSSL_SESSION_set_time
 #define SSL_SESSION_get_time            wolfSSL_SESSION_get_time
 
 #define SSL_CTX_get_ex_new_index        wolfSSL_CTX_get_ex_new_index
@@ -1510,6 +1511,11 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE      SRTP_PROTECTION_PROFILE;
 #define SSL_R_UNEXPECTED_MESSAGE                   OUT_OF_ORDER_E
 #define SSL_R_UNEXPECTED_RECORD                    SANITY_MSG_E
 #define SSL_R_UNKNOWN_ALERT_TYPE                   BUFFER_ERROR
+#define SSL_R_BAD_DIGEST_LENGTH                    BUFFER_ERROR
+#define SSL_R_BAD_PACKET_LENGTH                    BUFFER_ERROR
+#define SSL_R_DATA_LENGTH_TOO_LONG                 BUFFER_ERROR
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG            BUFFER_ERROR
+#define SSL_R_BAD_LENGTH                           BUFFER_ERROR
 #define SSL_R_UNKNOWN_PROTOCOL                     VERSION_ERROR
 #define SSL_R_WRONG_VERSION_NUMBER                 VERSION_ERROR
 #define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC  ENCRYPT_ERROR
@@ -1519,6 +1525,7 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE      SRTP_PROTECTION_PROFILE;
 #define SSL_R_CERTIFICATE_VERIFY_FAILED            VERIFY_CERT_ERROR
 #define SSL_R_CERT_CB_ERROR                        CLIENT_CERT_CB_ERROR
 #define SSL_R_NULL_SSL_METHOD_PASSED               BAD_FUNC_ARG
+#define SSL_R_CCS_RECEIVED_EARLY                   OUT_OF_ORDER_E
 
 #ifdef HAVE_SESSION_TICKET
 #define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72

+ 14 - 11
wolfssl/ssl.h

@@ -1233,6 +1233,7 @@ WOLFSSL_API int  wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *
 
 WOLFSSL_ABI WOLFSSL_API int  wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session);
 WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t);
+WOLFSSL_API long wolfSSL_SESSION_set_time(WOLFSSL_SESSION *ses, long t);
 WOLFSSL_ABI WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl);
 WOLFSSL_ABI WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm);
 WOLFSSL_API void wolfSSL_CTX_flush_sessions(WOLFSSL_CTX* ctx, long tm);
@@ -2251,25 +2252,25 @@ enum {
     WOLFSSL_OP_TLS_BLOCK_PADDING_BUG                  = 0x00000100,
     WOLFSSL_OP_TLS_ROLLBACK_BUG                       = 0x00000200,
     WOLFSSL_OP_EPHEMERAL_RSA                          = 0x00000800,
-    WOLFSSL_OP_NO_SSLv3                           = 0x00001000,
-    WOLFSSL_OP_NO_TLSv1                           = 0x00002000,
+    WOLFSSL_OP_NO_SSLv3                               = 0x00001000,
+    WOLFSSL_OP_NO_TLSv1                               = 0x00002000,
     WOLFSSL_OP_PKCS1_CHECK_1                          = 0x00004000,
     WOLFSSL_OP_PKCS1_CHECK_2                          = 0x00008000,
     WOLFSSL_OP_NETSCAPE_CA_DN_BUG                     = 0x00010000,
     WOLFSSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG        = 0x00020000,
-    WOLFSSL_OP_SINGLE_DH_USE                      = 0x00040000,
+    WOLFSSL_OP_SINGLE_DH_USE                          = 0x00040000,
     WOLFSSL_OP_NO_TICKET                              = 0x00080000,
     WOLFSSL_OP_DONT_INSERT_EMPTY_FRAGMENTS            = 0x00100000,
     WOLFSSL_OP_NO_QUERY_MTU                           = 0x00200000,
     WOLFSSL_OP_COOKIE_EXCHANGE                        = 0x00400000,
     WOLFSSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00800000,
-    WOLFSSL_OP_SINGLE_ECDH_USE                    = 0x01000000,
-    WOLFSSL_OP_CIPHER_SERVER_PREFERENCE           = 0x02000000,
-    WOLFSSL_OP_NO_TLSv1_1                         = 0x04000000,
-    WOLFSSL_OP_NO_TLSv1_2                         = 0x08000000,
-    WOLFSSL_OP_NO_COMPRESSION                     = 0x10000000,
-    WOLFSSL_OP_NO_TLSv1_3                         = 0x20000000,
-    WOLFSSL_OP_NO_SSLv2                           = 0x40000000,
+    WOLFSSL_OP_SINGLE_ECDH_USE                        = 0x01000000,
+    WOLFSSL_OP_CIPHER_SERVER_PREFERENCE               = 0x02000000,
+    WOLFSSL_OP_NO_TLSv1_1                             = 0x04000000,
+    WOLFSSL_OP_NO_TLSv1_2                             = 0x08000000,
+    WOLFSSL_OP_NO_COMPRESSION                         = 0x10000000,
+    WOLFSSL_OP_NO_TLSv1_3                             = 0x20000000,
+    WOLFSSL_OP_NO_SSLv2                               = 0x40000000,
     WOLFSSL_OP_ALL   =
                    (WOLFSSL_OP_MICROSOFT_SESS_ID_BUG
                   | WOLFSSL_OP_NETSCAPE_CHALLENGE_BUG
@@ -2535,7 +2536,9 @@ enum { /* ssl Constants */
     WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR      = 0x0008,
     WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100,
     WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE  = 0x0200,
-    WOLFSSL_SESS_CACHE_NO_INTERNAL        = 0x0300,
+    WOLFSSL_SESS_CACHE_NO_INTERNAL        =
+            (WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE |
+                    WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP),
 
     WOLFSSL_ERROR_WANT_READ        =  2,
     WOLFSSL_ERROR_WANT_WRITE       =  3,

+ 21 - 1
wolfssl/wolfcrypt/asn.h

@@ -1660,6 +1660,12 @@ struct DecodedCert {
     int     extCrlInfoSz;            /* length of the URI                */
     byte    extSubjKeyId[KEYID_SIZE]; /* Subject Key ID                  */
     byte    extAuthKeyId[KEYID_SIZE]; /* Authority Key ID                */
+#ifdef WOLFSSL_AKID_NAME
+    const byte* extAuthKeyIdIssuer;  /* Authority Key ID authorityCertIssuer */
+    word32  extAuthKeyIdIssuerSz;    /* Authority Key ID authorityCertIssuer length */
+    const byte* extAuthKeyIdIssuerSN; /* Authority Key ID authorityCertSerialNumber */
+    word32  extAuthKeyIdIssuerSNSz;   /* Authority Key ID authorityCertSerialNumber length */
+#endif
     byte    pathLength;              /* CA basic constraint path length  */
     byte    maxPathLen;              /* max_path_len see RFC 5280 section
                                       * 6.1.2 "Initialization" - (k) for
@@ -1947,13 +1953,22 @@ struct Signer {
 #endif /* IGNORE_NAME_CONSTRAINTS */
     byte    subjectNameHash[SIGNER_DIGEST_SIZE];
                                      /* sha hash of names in certificate */
+    #ifdef HAVE_OCSP
+        byte    issuerNameHash[SIGNER_DIGEST_SIZE];
+                                     /* sha hash of issuer names in certificate.
+                                      * Used in OCSP to check for authorized
+                                      * responders. */
+    #endif
     #ifndef NO_SKID
         byte    subjectKeyIdHash[SIGNER_DIGEST_SIZE];
-                                     /* sha hash of names in certificate */
+                                     /* sha hash of key in certificate */
     #endif
     #ifdef HAVE_OCSP
         byte subjectKeyHash[KEYID_SIZE];
     #endif
+#ifdef WOLFSSL_AKID_NAME
+    byte serialHash[SIGNER_DIGEST_SIZE]; /* serial number hash */
+#endif
 #ifdef WOLFSSL_SIGNER_DER_CERT
     DerBuffer* derCert;
 #endif
@@ -2450,6 +2465,11 @@ struct OcspRequest {
     int    serialSz;
 #ifdef OPENSSL_EXTRA
     WOLFSSL_ASN1_INTEGER* serialInt;
+#endif
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_APACHE_HTTPD) || \
+    defined(HAVE_LIGHTY)
+    void* cid; /* WOLFSSL_OCSP_CERTID kept to free */
 #endif
     byte*  url;      /* copy of the extAuthInfo in source cert */
     int    urlSz;