1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

OpenResty 1.31.1.1 support and CI

Fixes needed by the OSP OpenResty 1.31.1.1 port, plus a workflow that
runs the bundled SSL tests against wolfSSL.

d2i_X509_bio(): read one DER object per call, as OpenSSL does. ngx_lua's
set_der_cert() decodes a chain from one BIO one certificate at a time.

MAX_EX_DATA: default to 10 slots for --enable-nginx unless
--enable-context-extra-user-data gives a number. nginx 1.31 allocates six
SSL_CTX ex_data indexes and the OpenResty Lua modules use five SSL ones.

wolfSSL_OCSP_resp_find_status() and wolfSSL_OCSP_single_get0_status():
return NULL for an absent thisUpdate or nextUpdate instead of a pointer
to a zeroed WOLFSSL_ASN1_TIME. ngx.ocsp.validate_ocsp_response() failed
with "invalid nextUpdate time" for responses without nextUpdate.

Session cache: with WOLFSSL_TICKET_HAVE_ID, DoClientTicketFinalize()
called the external cache callback on every ticket resumption because
useTicket is only set after DoClientTicket() returns. Add
wolfSSL_GetSessionFromInternalCache() and use it unless the server
accepts early data (maxEarlyDataSz > 0), where the external cache takes
part in the 0-RTT anti-replay eviction. OpenSSL does the same: stateful
tickets and a cache lookup only with max_early_data set. ngx_lua expects
ssl_session_fetch_by_lua* to be skipped for ticket resumptions.

.github/workflows/openresty.yml: build OpenResty 1.31.1.1 with the OSP
port and tests patches against --enable-openresty and run the SSL test
files of ngx_lua, ngx_stream_lua and lua-resty-core, plus the
encrypted-session and set-misc suites, with Test::Nginx. Files that need
APIs wolfSSL does not provide or the network are not run. The OSP
checkout points at julek-dev/osp openresty-1.31.1.1 until the patches are
merged into wolfSSL/osp. memcached is a new test dependency.

Tests: d2i_X509_bio chain decoding, absent OCSP times, session cache
callback counts with tickets and early data.
This commit is contained in:
Juliusz Sosinowicz
2026-09-18 12:58:30 +00:00
parent 31b9da2c8d
commit dacd8ee72b
14 changed files with 521 additions and 31 deletions

View File

@@ -81,6 +81,7 @@ libuv1-dev
linux-libc-dev
make
man2html
memcached
meson
mono-complete
nghttp2

230
.github/workflows/openresty.yml vendored Normal file
View File

@@ -0,0 +1,230 @@
name: OpenResty Tests
# START OF COMMON SECTION
on:
push:
branches: [ 'release/**' ]
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '*' ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
# END OF COMMON SECTION
jobs:
build_wolfssl:
name: Build wolfSSL
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
# Just to keep it the same as the testing target
runs-on: ubuntu-24.04
# This should be a safe limit for the tests to run.
timeout-minutes: 5
steps:
- name: Build wolfSSL
uses: wolfSSL/actions-build-autotools-project@v1
with:
path: wolfssl
configure: >-
--enable-openresty --enable-curve25519 --enable-ed25519
install: true
- name: tar build-dir
run: tar -zcf build-dir.tgz build-dir
- name: Upload built lib
uses: actions/upload-artifact@v6
with:
name: wolf-install-openresty
path: build-dir.tgz
retention-days: 5
openresty_check:
strategy:
fail-fast: false
matrix:
include:
# The SSL test files of the bundled Lua modules. The port patch and
# the tests patch come from the OSP repo.
#
# Not run (cannot work with wolfSSL, the tests patch makes them
# skip): ssl_client_hello_by_lua* files (ngx_lua 166, 187; stream
# 162, 163; lua-resty-core ssl-client-hello.t) need
# SSL_CTX_set_client_hello_cb; proxy_ssl_*_by_lua* files (ngx_lua
# 169, 170-proxy-ssl-cert; stream 164, 165-proxy-ssl-cert-by;
# lua-resty-core proxy-ssl*.t) need SSL_set_retry_verify; FFI into
# libcrypto (ngx_lua 193, stream 171, lua-resty-core
# socket-tcp-settrustedstore.t) needs OpenSSL symbol names.
# Not run (need the network): ngx_lua and stream 129-ssl-socket.t
# and 170-ssl-session-reuse.t.
- ref: 1.31.1.1
sha256: 65b78baadd3f0984055de89bf13f4a1932e5bfe9c31932037a134ea2b1a0ce42
osp-repo: julek-dev/osp
osp-ref: openresty-1.31.1.1
ngx-lua-tests: >-
139-ssl-cert-by.t 140-ssl-c-api.t 142-ssl-session-store.t
143-ssl-session-fetch.t 155-tls13.t 162-socket-tls-handshake.t
stream-lua-tests: >-
139-ssl-cert-by.t 140-ssl-c-api.t 165-serversslhandshake.t
166-serversslhandshake-starttls.t
167-serversslhandshake-errors.t
resty-core-tests: >-
ssl.t stream/ssl.t ocsp.t ssl-session-store.t
ssl-session-fetch.t
name: ${{ matrix.ref }}
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
runs-on: ubuntu-24.04
# Test::Nginx restarts nginx for every block, so the suites take a while.
timeout-minutes: 45
needs: build_wolfssl
env:
OR_PREFIX: ${{ github.workspace }}/or-install
TEST_NGINX_BINARY: ${{ github.workspace }}/or-install/nginx/sbin/nginx
TEST_NGINX_USE_WOLFSSL: 1
TEST_NGINX_NO_SHUFFLE: 1
TEST_NGINX_SLEEP: 0.05
TEST_NGINX_MEMCACHED_PORT: 11211
steps:
- name: Checkout wolfSSL CI actions
uses: actions/checkout@v5
with:
sparse-checkout: .github/actions
fetch-depth: 1
- name: Install test dependencies
uses: ./.github/actions/install-apt-deps
with:
packages: libpcre2-dev zlib1g-dev memcached
ghcr-debs-tag: ubuntu-24.04-full
- name: Download lib
uses: actions/download-artifact@v7
with:
name: wolf-install-openresty
- name: untar build-dir
run: tar -xf build-dir.tgz
- name: Setup Perl environment
uses: shogo82148/actions-setup-perl@v1
with:
perl-version: '5.38.2'
- name: Install Test::Nginx
run: cpanm --notest Test::Nginx@0.32
- name: Checkout OSP
uses: actions/checkout@v5
with:
repository: ${{ matrix.osp-repo }}
ref: ${{ matrix.osp-ref }}
path: osp
sparse-checkout: openresty
- name: Download OpenResty
run: |
curl -fsSL -o openresty.tar.gz \
https://openresty.org/download/openresty-${{ matrix.ref }}.tar.gz
echo "${{ matrix.sha256 }} openresty.tar.gz" | sha256sum -c
tar -xf openresty.tar.gz
- name: Apply OSP patches
working-directory: openresty-${{ matrix.ref }}
run: |
patch -p1 < ../osp/openresty/${{ matrix.ref }}.patch
patch -p1 < ../osp/openresty/${{ matrix.ref }}-tests.patch
# --with-debug: the tests check the debug log.
- name: Build OpenResty
working-directory: openresty-${{ matrix.ref }}
run: |
./configure --prefix=$OR_PREFIX \
--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-debug -j$(nproc)
make -j$(nproc)
make install
- name: Confirm OpenResty built with wolfSSL
run: |
ldd $TEST_NGINX_BINARY | grep wolfssl
$TEST_NGINX_BINARY -V 2>&1 | grep 'built with wolfSSL'
# Short paths: the tests listen on unix sockets under t/servroot.
# lua-resty-core expects its sibling lua-resty-lrucache by that name.
- name: Prepare test directories
working-directory: openresty-${{ matrix.ref }}/bundle
run: |
mkdir -p /tmp/ort
mv ngx_lua-* /tmp/ort/ngx_lua
mv ngx_stream_lua-* /tmp/ort/ngx_stream_lua
mv lua-resty-core-* /tmp/ort/lua-resty-core
mv lua-resty-lrucache-* /tmp/ort/lua-resty-lrucache
mv encrypted-session-nginx-module-* /tmp/ort/encrypted-session
mv set-misc-nginx-module-* /tmp/ort/set-misc
# Some blocks talk to memcached over UDP.
- name: Start memcached
run: |
pkill -x memcached || true
memcached -d -p 11211 -U 11211 -l 127.0.0.1
- if: ${{ runner.debug }}
name: Verbose prove
run: echo "prove_flags=-v" >> $GITHUB_ENV
- name: Run ngx_lua tests
working-directory: /tmp/ort/ngx_lua
env:
LD_LIBRARY_PATH: ${{ github.workspace }}/build-dir/lib:${{ github.workspace }}/or-install/luajit/lib
run: |
prove ${{ env.prove_flags }} -I. \
$(for t in ${{ matrix.ngx-lua-tests }}; do echo t/$t; done)
- if: ${{ !cancelled() }}
name: Run ngx_stream_lua tests
working-directory: /tmp/ort/ngx_stream_lua
env:
LD_LIBRARY_PATH: ${{ github.workspace }}/build-dir/lib:${{ github.workspace }}/or-install/luajit/lib
run: |
prove ${{ env.prove_flags }} -I. \
$(for t in ${{ matrix.stream-lua-tests }}; do echo t/$t; done)
- if: ${{ !cancelled() }}
name: Run lua-resty-core tests
working-directory: /tmp/ort/lua-resty-core
env:
LD_LIBRARY_PATH: ${{ github.workspace }}/build-dir/lib:${{ github.workspace }}/or-install/luajit/lib
run: |
prove ${{ env.prove_flags }} -I. \
$(for t in ${{ matrix.resty-core-tests }}; do echo t/$t; done)
# These two modules use the OpenSSL compatibility layer directly.
- if: ${{ !cancelled() }}
name: Run encrypted-session tests
working-directory: /tmp/ort/encrypted-session
env:
LD_LIBRARY_PATH: ${{ github.workspace }}/build-dir/lib:${{ github.workspace }}/or-install/luajit/lib
run: prove ${{ env.prove_flags }} -I. t/sanity.t
- if: ${{ !cancelled() }}
name: Run set-misc tests
working-directory: /tmp/ort/set-misc
env:
LD_LIBRARY_PATH: ${{ github.workspace }}/build-dir/lib:${{ github.workspace }}/or-install/luajit/lib
run: prove ${{ env.prove_flags }} -I. t/hmac.t
- if: ${{ failure() }}
name: Upload nginx logs
uses: actions/upload-artifact@v6
with:
name: openresty-${{ matrix.ref }}-logs
path: |
/tmp/ort/*/t/servroot*/logs/*.log
/tmp/ort/*/t/servroot*/conf/nginx.conf
retention-days: 5

View File

@@ -3891,6 +3891,13 @@ if(NOT WOLFSSL_CONTEXT_EXTRA_USER_DATA STREQUAL "no")
endif()
endif()
# nginx 1.31 and the OpenResty Lua modules need six ex_data slots per object.
if((WOLFSSL_NGINX OR WOLFSSL_OPENRESTY) AND
(WOLFSSL_CONTEXT_EXTRA_USER_DATA STREQUAL "no" OR
WOLFSSL_CONTEXT_EXTRA_USER_DATA STREQUAL "yes"))
list(APPEND WOLFSSL_DEFINITIONS "-DMAX_EX_DATA=10")
endif()
# ECC minimum key size (bits)
if(WOLFSSL_FIPS)
set(WOLFSSL_ECC_MIN_KEY_SZ_DEFAULT "192")

View File

@@ -12308,6 +12308,13 @@ yes) AM_CFLAGS="$AM_CFLAGS -DHAVE_EX_DATA"
;;
esac
# nginx 1.31 and the OpenResty Lua modules need six ex_data slots per object.
if test "$ENABLED_NGINX" = "yes" && \
(test "$ENABLED_EX_DATA" = "no" || test "$ENABLED_EX_DATA" = "yes")
then
AM_CFLAGS="$AM_CFLAGS -DMAX_EX_DATA=10"
fi
# IoT-Safe support
AC_ARG_ENABLE([iotsafe],
[AS_HELP_STRING([--enable-iotsafe],[Enables support for IoT-Safe secure applet (default: disabled)])],

View File

@@ -43738,9 +43738,18 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN);
ssl->session->sessionIDSz= bogusIDSz;
}
#ifdef WOLFSSL_TICKET_HAVE_ID
#if defined(WOLFSSL_TICKET_HAVE_ID) && !defined(NO_SESSION_CACHE)
else {
if (wolfSSL_GetSession(ssl, NULL, 1) != NULL) {
int found;
/* The external cache takes part in the 0-RTT anti-replay
* eviction, so it is only skipped when early data is off. */
#ifdef WOLFSSL_EARLY_DATA
if (ssl->options.maxEarlyDataSz > 0)
found = wolfSSL_GetSessionFromCache(ssl, ssl->session);
else
#endif
found = wolfSSL_GetSessionFromInternalCache(ssl, ssl->session);
if (found == WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Found session matching the session id"
" found in the ticket");
}

View File

@@ -730,10 +730,15 @@ int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
if (status != NULL)
*status = single->status->status;
#ifdef WOLFSSL_OCSP_PARSE_STATUS
if (thisupd != NULL)
*thisupd = &single->status->thisDateParsed;
if (nextupd != NULL)
*nextupd = &single->status->nextDateParsed;
/* NULL when the response has no such field, as with OpenSSL. */
if (thisupd != NULL) {
*thisupd = (single->status->thisDateParsed.length > 0) ?
&single->status->thisDateParsed : NULL;
}
if (nextupd != NULL) {
*nextupd = (single->status->nextDateParsed.length > 0) ?
&single->status->nextDateParsed : NULL;
}
#else
if (thisupd != NULL)
*thisupd = NULL;
@@ -1636,10 +1641,15 @@ int wolfSSL_OCSP_single_get0_status(WOLFSSL_OCSP_SINGLERESP *single,
return -1;
#ifdef WOLFSSL_OCSP_PARSE_STATUS
if (thisupd != NULL)
*thisupd = &single->status->thisDateParsed;
if (nextupd != NULL)
*nextupd = &single->status->nextDateParsed;
/* NULL when the response has no such field, as with OpenSSL. */
if (thisupd != NULL) {
*thisupd = (single->status->thisDateParsed.length > 0) ?
&single->status->thisDateParsed : NULL;
}
if (nextupd != NULL) {
*nextupd = (single->status->nextDateParsed.length > 0) ?
&single->status->nextDateParsed : NULL;
}
#else
if (thisupd != NULL)
*thisupd = NULL;

View File

@@ -1217,7 +1217,8 @@ int TlsSessionCacheGetAndWrLock(const byte *id, WOLFSSL_SESSION **sess,
lockedRow, 0, side);
}
int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
static int GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output,
byte internalOnly)
{
const WOLFSSL_SESSION* sess = NULL;
const byte* id = NULL;
@@ -1235,7 +1236,9 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
byte bogusID[ID_LEN];
byte bogusIDSz = 0;
WOLFSSL_ENTER("wolfSSL_GetSessionFromCache");
WOLFSSL_ENTER("GetSessionFromCache");
(void)internalOnly;
if (output == NULL) {
WOLFSSL_MSG("NULL output");
@@ -1270,7 +1273,7 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
#ifdef HAVE_EXT_CACHE
if (ssl->ctx->get_sess_cb != NULL) {
if (!internalOnly && ssl->ctx->get_sess_cb != NULL) {
int copy = 0;
int found = 0;
WOLFSSL_SESSION* extSess;
@@ -1499,6 +1502,18 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
return error;
}
int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
{
return GetSessionFromCache(ssl, output, 0);
}
/* Lookup by the ID carried in a decrypted ticket without calling the
* external cache callback. */
int wolfSSL_GetSessionFromInternalCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
{
return GetSessionFromCache(ssl, output, 1);
}
WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret,
byte restoreSessionCerts)
{

View File

@@ -8937,6 +8937,11 @@ static WOLFSSL_X509* d2i_X509orX509REQ_bio(WOLFSSL_BIO* bio,
WOLFSSL_X509* localX509 = NULL;
byte* mem = NULL;
int size;
int derSz;
int hdrSz = 2;
int len = 0;
word32 idx = 1;
byte hdr[6];
WOLFSSL_ENTER("wolfSSL_d2i_X509_bio");
@@ -8952,12 +8957,35 @@ static WOLFSSL_X509* d2i_X509orX509REQ_bio(WOLFSSL_BIO* bio,
return NULL;
}
if (!(mem = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL))) {
/* Consume only the first DER object. A BIO holding a chain is then
* decoded one certificate per call, as with OpenSSL. */
if (wolfSSL_BIO_read(bio, hdr, hdrSz) != hdrSz) {
WOLFSSL_MSG("wolfSSL_BIO_read error");
return NULL;
}
if (hdr[1] & ASN_LONG_LENGTH) {
int n = hdr[1] & 0x7F;
if (n < 1 || n > 4 || wolfSSL_BIO_read(bio, hdr + hdrSz, n) != n) {
WOLFSSL_MSG("Bad DER length");
return NULL;
}
hdrSz += n;
}
if (hdr[0] != (ASN_SEQUENCE | ASN_CONSTRUCTED) ||
GetLength_ex(hdr, &idx, &len, (word32)hdrSz, 0) < 0 ||
len < 0 || (int)idx + len > size) {
WOLFSSL_MSG("Bad DER header");
return NULL;
}
derSz = (int)idx + len;
if (!(mem = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL))) {
WOLFSSL_MSG("malloc error");
return NULL;
}
if ((size = wolfSSL_BIO_read(bio, mem, size)) == 0) {
XMEMCPY(mem, hdr, hdrSz);
if (derSz > hdrSz && wolfSSL_BIO_read(bio, mem + hdrSz, derSz - hdrSz) !=
derSz - hdrSz) {
WOLFSSL_MSG("wolfSSL_BIO_read error");
XFREE(mem, NULL, DYNAMIC_TYPE_OPENSSL);
return NULL;
@@ -8965,13 +8993,13 @@ static WOLFSSL_X509* d2i_X509orX509REQ_bio(WOLFSSL_BIO* bio,
if (req) {
#ifdef WOLFSSL_CERT_REQ
localX509 = wolfSSL_X509_REQ_d2i(NULL, mem, size);
localX509 = wolfSSL_X509_REQ_d2i(NULL, mem, derSz);
#else
WOLFSSL_MSG("CSR not compiled in");
#endif
}
else {
localX509 = wolfSSL_X509_d2i_ex(NULL, mem, size, bio->heap);
localX509 = wolfSSL_X509_d2i_ex(NULL, mem, derSz, bio->heap);
}
if (localX509 == NULL) {
WOLFSSL_MSG("wolfSSL_X509_d2i error");

View File

@@ -25111,6 +25111,8 @@ static int test_wolfSSL_OCSP_single_get0_status(void)
certStatus.thisDateParsed.data[i] = i;
certStatus.nextDateParsed.data[i] = i;
}
certStatus.thisDateParsed.length = CTC_DATE_SIZE;
certStatus.nextDateParsed.length = CTC_DATE_SIZE;
certStatus.status = CERT_GOOD;
single.status = &certStatus;
@@ -25120,6 +25122,16 @@ static int test_wolfSSL_OCSP_single_get0_status(void)
ExpectPtrEq(thisDate, &certStatus.thisDateParsed);
ExpectPtrEq(nextDate, &certStatus.nextDateParsed);
/* nextUpdate is optional. Absent gives NULL like OpenSSL. */
certStatus.nextDateParsed.length = 0;
thisDate = NULL;
nextDate = &certStatus.nextDateParsed;
ret = wolfSSL_OCSP_single_get0_status(&single, NULL, NULL, &thisDate,
&nextDate);
ExpectIntEQ(ret, CERT_GOOD);
ExpectPtrEq(thisDate, &certStatus.thisDateParsed);
ExpectNull(nextDate);
ExpectIntEQ(wolfSSL_OCSP_single_get0_status(NULL, NULL, NULL, NULL, NULL),
-1);
ExpectIntEQ(wolfSSL_OCSP_single_get0_status(&single, NULL, NULL, NULL,
@@ -42714,6 +42726,7 @@ TEST_CASE testCases[] = {
TEST_DECL_GROUP("ocsp", test_ocsp_certid_enc_dec),
TEST_DECL_GROUP("ocsp", test_ocsp_certid_dup),
TEST_DECL_GROUP("ocsp", test_ocsp_resp_find_status_serial_prefix),
TEST_DECL_GROUP("ocsp", test_ocsp_resp_times),
TEST_DECL(test_ocsp_tls_cert_cb),
TEST_DECL_GROUP("ocsp", test_ocsp_status_request_v2_multi_revoked_single),
TEST_DECL_GROUP("ocsp", test_ocsp_cert_unknown_crl_fallback),

View File

@@ -976,6 +976,8 @@ int test_ocsp_resp_find_status_serial_prefix(void)
OcspEntry requestedId;
CertStatus requestedStatus;
int status;
WOLFSSL_ASN1_TIME* thisupd = NULL;
WOLFSSL_ASN1_TIME* nextupd = NULL;
XMEMSET(&response, 0, sizeof(response));
XMEMSET(&single, 0, sizeof(single));
@@ -1008,6 +1010,21 @@ int test_ocsp_resp_find_status_serial_prefix(void)
NULL, NULL, NULL, NULL), WOLFSSL_SUCCESS);
ExpectIntEQ(status, CERT_GOOD);
/* No update times parsed: both must come back NULL. */
ExpectIntEQ(wolfSSL_OCSP_resp_find_status(&response, &requestedId, &status,
NULL, NULL, &thisupd, &nextupd), WOLFSSL_SUCCESS);
ExpectNull(thisupd);
ExpectNull(nextupd);
#ifdef WOLFSSL_OCSP_PARSE_STATUS
/* thisUpdate present, nextUpdate absent. */
responseStatus.thisDateParsed.length = 15;
nextupd = &responseStatus.nextDateParsed;
ExpectIntEQ(wolfSSL_OCSP_resp_find_status(&response, &requestedId, &status,
NULL, NULL, &thisupd, &nextupd), WOLFSSL_SUCCESS);
ExpectPtrEq(thisupd, &responseStatus.thisDateParsed);
ExpectNull(nextupd);
#endif
/* Request serial 01:02:03 (3 bytes) shares the 01:02 prefix of the
* response serial.
* The lookup must not bind the good response to this longer and
@@ -1023,6 +1040,43 @@ int test_ocsp_resp_find_status_serial_prefix(void)
return EXPECT_RESULT();
}
/* The test responses carry thisUpdate only. */
int test_ocsp_resp_times(void)
{
EXPECT_DECLS;
#if defined(HAVE_OCSP) && defined(OPENSSL_EXTRA) && !defined(NO_SHA) && \
!defined(NO_RSA)
const unsigned char* ptr = (const unsigned char*)resp;
OcspResponse* response = NULL;
WOLFSSL_OCSP_BASICRESP* bs = NULL;
WOLFSSL_OCSP_SINGLERESP* single = NULL;
WOLFSSL_ASN1_TIME* thisupd = NULL;
WOLFSSL_ASN1_TIME* nextupd = NULL;
int reason = -1;
ExpectNotNull(response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr,
sizeof(resp)));
ExpectNotNull(bs = wolfSSL_OCSP_response_get1_basic(response));
ExpectNotNull(single = wolfSSL_OCSP_resp_get0(bs, 0));
ExpectIntEQ(wolfSSL_OCSP_single_get0_status(single, &reason, NULL,
&thisupd, &nextupd), CERT_GOOD);
#ifdef WOLFSSL_OCSP_PARSE_STATUS
ExpectNotNull(thisupd);
if (thisupd != NULL) {
ExpectIntEQ(thisupd->type, ASN_GENERALIZED_TIME);
ExpectIntGT(thisupd->length, 0);
}
#else
ExpectNull(thisupd);
#endif
ExpectNull(nextupd);
wolfSSL_OCSP_BASICRESP_free(bs);
wolfSSL_OCSP_RESPONSE_free(response);
#endif
return EXPECT_RESULT();
}
#if defined(HAVE_OCSP) && defined(WOLFSSL_CERT_SETUP_CB) && \
defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_RSA) && \
(defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \

View File

@@ -25,6 +25,7 @@
int test_ocsp_certid_enc_dec(void);
int test_ocsp_certid_dup(void);
int test_ocsp_resp_find_status_serial_prefix(void);
int test_ocsp_resp_times(void);
int test_ocsp_status_callback(void);
int test_ocsp_basic_verify(void);
int test_ocsp_responder_keyhash_binding(void);

View File

@@ -640,6 +640,50 @@ int test_wolfSSL_X509(void)
X509_free(x509);
BIO_free(bio);
bio = NULL;
/* d2i_X509_bio reads one certificate per call and leaves the rest. */
{
byte chain[4096];
int svrSz = 0;
int caSz = 0;
X509* x509b = NULL;
ExpectTrue((fp = XFOPEN("certs/server-cert.der", "rb")) != XBADFILE);
if (fp != XBADFILE) {
svrSz = (int)XFREAD(chain, 1, sizeof(chain), fp);
XFCLOSE(fp);
fp = XBADFILE;
}
ExpectIntGT(svrSz, 0);
ExpectTrue((fp = XFOPEN(der, "rb")) != XBADFILE);
if (fp != XBADFILE && svrSz > 0) {
caSz = (int)XFREAD(chain + svrSz, 1, sizeof(chain) - svrSz, fp);
}
if (fp != XBADFILE) {
XFCLOSE(fp);
fp = XBADFILE;
}
ExpectIntGT(caSz, 0);
ExpectNotNull(bio = BIO_new_mem_buf(chain, svrSz + caSz));
ExpectNotNull(x509 = d2i_X509_bio(bio, NULL));
ExpectIntEQ(BIO_pending(bio), caSz);
ExpectNotNull(x509b = d2i_X509_bio(bio, NULL));
ExpectIntEQ(BIO_pending(bio), 0);
ExpectNull(d2i_X509_bio(bio, NULL));
ExpectIntNE(X509_cmp(x509, x509b), 0);
X509_free(x509);
x509 = NULL;
X509_free(x509b);
BIO_free(bio);
bio = NULL;
/* Truncated DER is rejected. */
ExpectNotNull(bio = BIO_new_mem_buf(chain, svrSz - 1));
ExpectNull(d2i_X509_bio(bio, NULL));
BIO_free(bio);
bio = NULL;
}
#endif
/* X509_up_ref test */

View File

@@ -490,6 +490,16 @@ static int twcase_cache_intOn_extOn_noTicket(WOLFSSL_CTX* ctx)
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
return TEST_SUCCESS;
}
#ifdef WOLFSSL_EARLY_DATA
/* Early data on: ticket resumption consults the external cache. */
static int twcase_cache_intOn_extOn_earlyData(WOLFSSL_CTX* ctx)
{
EXPECT_DECLS;
ExpectIntEQ(twcase_cache_intOn_extOn(ctx), TEST_SUCCESS);
ExpectIntGE(wolfSSL_CTX_set_max_early_data(ctx, MAX_EARLY_DATA_SZ), 0);
return EXPECT_RESULT();
}
#endif
static int twcase_server_sess_ctx_pre_shutdown(WOLFSSL* ssl)
{
EXPECT_DECLS;
@@ -575,6 +585,20 @@ static int twcase_client_sess_ctx_pre_shutdown(WOLFSSL* ssl)
#endif
return EXPECT_RESULT();
}
/* Client asks for a ticket so TLS 1.2 also resumes with one. */
static int twcase_client_use_ticket(WOLFSSL_CTX* ctx)
{
EXPECT_DECLS;
ExpectIntEQ(twcase_cache_intOff_extOff(ctx), TEST_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_UseSessionTicket(ctx), WOLFSSL_SUCCESS);
return EXPECT_RESULT();
}
static int twcase_resume_on_result(WOLFSSL* ssl)
{
EXPECT_DECLS;
ExpectIntEQ(wolfSSL_session_reused(ssl), 1);
return EXPECT_RESULT();
}
static int twcase_client_set_sess_ssl_ready(WOLFSSL* ssl)
{
EXPECT_DECLS;
@@ -602,6 +626,14 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
EXPECT_DECLS;
/* Test the default 33 sessions */
int j;
int tls13 = XSTRSTR(param->tls_version, "TLSv1_3") != NULL;
int dtls = XSTRSTR(param->tls_version, "DTLS") != NULL;
#ifdef WOLFSSL_EARLY_DATA
/* Case 6 enables early data, which is TLS 1.3 only. */
const int cases = tls13 ? 7 : 6;
#else
const int cases = 6;
#endif
/* Clear cache before starting */
wolfSSL_CTX_flush_sessions(NULL, -1);
@@ -612,15 +644,13 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
server_sessionCache.capacity = SESSION_CACHE_SIZE;
fprintf(stderr, "\tBegin %s\n", param->tls_version);
for (j = 0; j < 5; j++) {
int tls13 = XSTRSTR(param->tls_version, "TLSv1_3") != NULL;
int dtls = XSTRSTR(param->tls_version, "DTLS") != NULL;
for (j = 0; j < cases; j++) {
test_ssl_cbf client_cb;
test_ssl_cbf server_cb;
(void)dtls;
/* Test five cache configurations */
/* Test the cache configurations */
twcase_client_first_session_ptr = NULL;
twcase_server_first_session_ptr = NULL;
twcase_server_current_ctx_ptr = NULL;
@@ -657,8 +687,20 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
case 4:
server_cb.ctx_ready = twcase_cache_intOff_extOff;
break;
case 5:
/* ticket resumption for all versions */
server_cb.ctx_ready = twcase_cache_intOn_extOn;
break;
#ifdef WOLFSSL_EARLY_DATA
case 6:
server_cb.ctx_ready = twcase_cache_intOn_extOn_earlyData;
break;
#endif
}
client_cb.ctx_ready = twcase_cache_intOff_extOff;
if (j == 5)
client_cb.ctx_ready = twcase_client_use_ticket;
else
client_cb.ctx_ready = twcase_cache_intOff_extOff;
/* Add session to internal cache and save SSL session for testing */
server_cb.on_result = twcase_server_sess_ctx_pre_shutdown;
@@ -684,6 +726,8 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
case 0:
case 1:
case 2:
case 5:
case 6:
/* cache cannot be searched with out a connection */
/* Add a new session */
ExpectIntEQ(twcase_new_session_called, 1);
@@ -705,8 +749,8 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
twcase_new_session_called = 0;
twcase_remove_session_called = 0;
twcase_get_session_called = 0;
server_cb.on_result = 0;
client_cb.on_result = 0;
server_cb.on_result = twcase_resume_on_result;
client_cb.on_result = twcase_resume_on_result;
server_cb.ticNoInit = 1; /* Use default builtin */
server_cb.ctx = twcase_server_current_ctx_ptr;
@@ -754,8 +798,9 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
case 1:
if (tls13) {
/* (D)TLSv1.3 case */
/* cache hit */
ExpectIntEQ(twcase_get_session_called, 1);
/* Ticket resumption. The external cache is not
* consulted, as in OpenSSL. */
ExpectIntEQ(twcase_get_session_called, 0);
/* (D)TLSv1.3 creates a new ticket,
* updates both internal and external cache */
ExpectIntEQ(twcase_new_session_called, 1);
@@ -764,7 +809,7 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
ExpectIntEQ(twcase_remove_session_called, 1);
}
else {
/* non (D)TLSv1.3 case */
/* non (D)TLSv1.3 case, session ID resumption */
/* cache hit */
/* DTLS accesses cache once for stateless parsing and
* once for stateful parsing */
@@ -782,8 +827,9 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
case 2:
if (tls13) {
/* (D)TLSv1.3 case */
/* cache hit */
ExpectIntEQ(twcase_get_session_called, 1);
/* Ticket resumption. The external cache is not
* consulted, as in OpenSSL. */
ExpectIntEQ(twcase_get_session_called, 0);
/* (D)TLSv1.3 creates a new ticket,
* updates both internal and external cache */
ExpectIntEQ(twcase_new_session_called, 1);
@@ -792,7 +838,7 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
ExpectIntEQ(twcase_remove_session_called, 1);
}
else {
/* non (D)TLSv1.3 case */
/* non (D)TLSv1.3 case, session ID resumption */
/* cache hit */
/* DTLS accesses cache once for stateless parsing and
* once for stateful parsing */
@@ -814,6 +860,29 @@ static WC_MAYBE_UNUSED int test_wolfSSL_CTX_add_session_ext(
ExpectIntEQ(twcase_new_session_called, 0);
ExpectIntEQ(twcase_remove_session_called, 0);
break;
case 5:
/* Ticket resumption. The external cache is not consulted,
* as in OpenSSL. */
ExpectIntEQ(twcase_get_session_called, 0);
if (tls13) {
ExpectIntEQ(twcase_new_session_called, 1);
ExpectIntEQ(twcase_remove_session_called, 1);
}
else {
/* The ticket is reused, no new session */
ExpectIntEQ(twcase_new_session_called, 0);
ExpectIntEQ(twcase_remove_session_called, 1);
}
break;
#ifdef WOLFSSL_EARLY_DATA
case 6:
/* Ticket resumption with early data on. The external cache
* takes part in anti-replay, so it is consulted. */
ExpectIntEQ(twcase_get_session_called, 1);
ExpectIntEQ(twcase_new_session_called, 1);
ExpectIntEQ(twcase_remove_session_called, 1);
break;
#endif
}
wolfSSL_SESSION_free(twcase_client_first_session_ptr);
wolfSSL_SESSION_free(twcase_server_first_session_ptr);

View File

@@ -5193,6 +5193,8 @@ WOLFSSL_LOCAL int TlsSessionCacheGetAndWrLock(const byte *id,
WOLFSSL_SESSION **sess, word32 *lockedRow, byte side);
WOLFSSL_LOCAL void EvictSessionFromCache(WOLFSSL_SESSION* session);
WOLFSSL_TEST_VIS int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output);
WOLFSSL_LOCAL int wolfSSL_GetSessionFromInternalCache(WOLFSSL* ssl,
WOLFSSL_SESSION* output);
WOLFSSL_LOCAL int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session);
WOLFSSL_LOCAL void wolfSSL_FreeSession(WOLFSSL_CTX* ctx,
WOLFSSL_SESSION* session);