diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a7944f9dc..685a629a3 100644 --- a/.github/workflows/main.yml +++ b/.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 diff --git a/.github/workflows/nginx.yml b/.github/workflows/nginx.yml new file mode 100644 index 000000000..7ac5e92f8 --- /dev/null +++ b/.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 }} + \ No newline at end of file diff --git a/configure.ac b/configure.ac index 46e9c1103..210f25f3e 100644 --- a/configure.ac +++ b/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" diff --git a/src/internal.c b/src/internal.c index cb439d870..7aba37a32 100644 --- a/src/internal.c +++ b/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); @@ -13944,7 +13949,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; @@ -14336,7 +14341,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; @@ -22083,7 +22088,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 || @@ -22423,7 +22429,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); @@ -22437,7 +22443,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) { @@ -22530,7 +22536,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]; @@ -22780,6 +22786,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; } @@ -22856,7 +22864,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 || @@ -22882,7 +22890,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 || @@ -28091,10 +28099,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 @@ -28139,7 +28147,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; @@ -35446,7 +35454,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; @@ -35507,14 +35569,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); @@ -35535,31 +35590,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; @@ -35834,6 +35874,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; } @@ -35966,6 +36013,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 } @@ -36072,6 +36123,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 @@ -36087,8 +36139,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 */ @@ -36191,6 +36245,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; diff --git a/src/ocsp.c b/src/ocsp.c index 69304b8f4..b1d89a165 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -28,6 +28,13 @@ #include +/* + * 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 *) + DecodedCert *cert; +#else + DecodedCert cert[1]; +#endif + byte certInit = 0; + int idx; + + (void)certs; + + 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; -#else - DecodedCert cert[1]; #endif - (void)certs; - - if (flags & OCSP_NOVERIFY) { - ret = WOLFSSL_SUCCESS; - goto out; - } - #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; - InitDecodedCert(cert, bs->cert, bs->certSz, NULL); - if (ParseCertRelative(cert, CERT_TYPE, VERIFY, st->cm) < 0) - ret = WOLFSSL_FAILURE; - FreeDecodedCert(cert); + 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) + 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) { diff --git a/src/ssl.c b/src/ssl.c index ceef3767f..c9720e96b 100644 --- a/src/ssl.c +++ b/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 @@ -6135,7 +6182,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; @@ -8644,7 +8694,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"); } @@ -8669,7 +8719,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; } @@ -12163,13 +12213,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) @@ -14972,6 +15028,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) { @@ -15047,37 +15119,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, ©); 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; } @@ -15161,12 +15234,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"); @@ -15939,27 +16012,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 SESSION_INDEX - &ssl->sessionIndex, -#else - NULL, +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) #endif - ssl->options.side, -#ifdef HAVE_SESSION_TICKET - ssl->options.useTicket, + { + /* 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, #else - 0, + NULL, +#endif + ssl->options.side, +#ifdef HAVE_SESSION_TICKET + ssl->options.useTicket, +#else + 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) { @@ -17344,8 +17422,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; } } @@ -17354,9 +17432,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; } } @@ -17416,7 +17494,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) { @@ -17427,7 +17505,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 @@ -17457,9 +17535,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; } @@ -17471,7 +17549,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; @@ -22172,6 +22250,8 @@ const char* wolfSSL_get_curve_name(WOLFSSL* ssl) { const char* cName = NULL; + WOLFSSL_ENTER("wolfSSL_get_curve_name"); + if (ssl == NULL) return NULL; @@ -23871,7 +23951,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) { @@ -26076,17 +26156,6 @@ long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) return timeout; } - -long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) -{ - long bornOn = 0; - WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); - sess = ClientSessionToSession(sess); - if (sess) - bornOn = sess->bornOn; - return bornOn; -} - long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) { word32 tmptime; @@ -26102,6 +26171,27 @@ long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) return WOLFSSL_SUCCESS; } +long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) +{ + long bornOn = 0; + WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); + sess = ClientSessionToSession(sess); + if (sess) + bornOn = sess->bornOn; + return bornOn; +} + +long wolfSSL_SESSION_set_time(WOLFSSL_SESSION *ses, long t) +{ + + ses = ClientSessionToSession(ses); + if (ses == NULL || t < 0) { + return 0; + } + ses->bornOn = (word32)t; + return t; +} + #endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */ #ifdef OPENSSL_EXTRA @@ -33013,10 +33103,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) diff --git a/src/tls.c b/src/tls.c index 9aee4ffd2..421924e7a 100644 --- a/src/tls.c +++ b/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 */ @@ -11352,6 +11534,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: @@ -11377,8 +11563,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); @@ -11526,6 +11712,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: @@ -11732,6 +11923,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: @@ -12083,6 +12280,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"); @@ -12559,8 +12767,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)); @@ -12577,6 +12786,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 */ @@ -12598,8 +12811,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 */ } @@ -12802,6 +13018,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) @@ -12829,8 +13049,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 */ } @@ -13740,6 +13965,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 diff --git a/src/tls13.c b/src/tls13.c index 23d9123c0..a51185ebe 100644 --- a/src/tls13.c +++ b/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.noTicketTls13) { - if ((ret = CreateTicket(ssl)) != 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 = 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 diff --git a/tests/api.c b/tests/api.c index 79b8d5860..9e9155186 100644 --- a/tests/api.c +++ b/tests/api.c @@ -8302,7 +8302,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 { diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 05ca5bd4d..469ac2c3b 100644 --- a/wolfcrypt/src/asn.c +++ b/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 #endif +#include #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - #include #include #endif @@ -18847,7 +18847,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"); @@ -18855,31 +18854,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; @@ -21458,6 +21485,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) @@ -22591,6 +22631,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) { @@ -34096,6 +34143,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) { @@ -34865,7 +34915,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 @@ -34876,6 +34926,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 */ @@ -35543,6 +35600,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 } } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 186c9e036..b4e630ad5 100644 --- a/wolfssl/internal.h +++ b/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, diff --git a/wolfssl/ocsp.h b/wolfssl/ocsp.h index 8afb196c2..4dff068b9 100644 --- a/wolfssl/ocsp.h +++ b/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) diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index d9ada762b..0bfe1e6ef 100644 --- a/wolfssl/openssl/ssl.h +++ b/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 diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 63bbfb107..b562d4b85 100644 --- a/wolfssl/ssl.h +++ b/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, diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index a69206415..29d5df388 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/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 @@ -1945,13 +1951,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 @@ -2448,6 +2463,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;