works OCSP Stapling with TLS1.3 like OCSPv2Multi

This commit is contained in:
Hideki Miyazaki 2024-07-11 19:02:32 +09:00
parent 4962180a93
commit 69e390f8b9
13 changed files with 1102 additions and 165 deletions

View File

@ -35,6 +35,7 @@ scripts/
google.test - example client test against google, part of tests
resume.test - example sessoin resume test, part of tests
ocsp-stapling.test - example client test against globalsign, part of tests
ocsp-stapling1_tls13.text - example client test against example server, part of tests
ocsp-stapling2.test - example client test against example server, part of tests
sniffer-testsuite.test - runs snifftest on a pcap of testsuite, part of tests
in sniffer mode

View File

@ -5995,10 +5995,27 @@ fi
# Certificate Status Request : a.k.a. OCSP Stapling
AC_ARG_ENABLE([ocspstapling],
[AS_HELP_STRING([--enable-ocspstapling],[Enable OCSP Stapling (default: disabled)])],
[AS_HELP_STRING([--enable-ocspstapling],[Enable OCSP Stapling ((options: yes, no-multi, no, disabled default: disabled)])],
[ ENABLED_CERTIFICATE_STATUS_REQUEST=$enableval ],
[ ENABLED_CERTIFICATE_STATUS_REQUEST=no ]
)
AS_CASE([$ENABLED_CERTIFICATE_STATUS_REQUEST],
[no],[
ENABLED_CERTIFICATE_STATUS_REQUEST="no"
ENABLED_TLS_OCSP_MULTI="no"
],
[disabled],[
ENABLED_CERTIFICATE_STATUS_REQUEST="no"
ENABLED_TLS_OCSP_MULTI="no"
],
[yes],[
ENABLED_CERTIFICATE_STATUS_REQUEST="yes"
ENABLED_TLS_OCSP_MULTI="yes"
],
[no-multi],[
ENABLED_CERTIFICATE_STATUS_REQUEST="yes"
ENABLED_TLS_OCSP_MULTI="no"
])
if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_WPAS" = "xyes" || \
test "x$ENABLED_HAPROXY" = "xyes" || test "x$ENABLED_LIGHTY" = "xyes" || \
@ -9580,7 +9597,17 @@ if test "$ENABLED_DH" != "no" && test "$ENABLED_DH" != "const"; then
LT_LIB_M
fi
# mulitple OCSP stapling for TLS 1.3 Certificate extension
if test "$ENABLED_CERTIFICATE_STATUS_REQUEST" = "yes"
then
if test "$ENABLED_TLS13" = "yes"
then
if test "$ENABLED_TLS_OCSP_MULTI" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TLS_OCSP_MULTI"
fi
fi
fi
################################################################################
# USER SETTINGS
@ -9835,6 +9862,7 @@ AM_CONDITIONAL([BUILD_SM4],[test "x$ENABLED_SM4" != "xno" || test "x$ENABLED_USE
AM_CONDITIONAL([BUILD_INLINE],[test "x$ENABLED_INLINE" = "xyes"])
AM_CONDITIONAL([BUILD_OCSP],[test "x$ENABLED_OCSP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
AM_CONDITIONAL([BUILD_OCSP_STAPLING],[test "x$ENABLED_CERTIFICATE_STATUS_REQUEST" = "xyes"])
AM_CONDITIONAL([BUILD_OCSP_STAPLING_MULTI],[test "x$ENABLED_CERTIFICATE_STATUS_REQUEST" = "xyes" && test "x$ENABLED_TLS13" = "xyes" && test "x$ENABLED_TLS_OCSP_MULTI" = "xyes"])
AM_CONDITIONAL([BUILD_OCSP_STAPLING_V2],[test "x$ENABLED_CERTIFICATE_STATUS_REQUEST_V2" = "xyes"])
AM_CONDITIONAL([BUILD_CRL],[test "x$ENABLED_CRL" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"])
AM_CONDITIONAL([BUILD_CRL_MONITOR],[test "x$ENABLED_CRL_MONITOR" = "xyes"])

View File

@ -1242,66 +1242,70 @@ static const char* client_usage_msg[][78] = {
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
"-W <num> Use OCSP Stapling (1 v1, 2 v2, 3 v2 multi)\n", /* 41 */
" With 'm' at end indicates MUST staple\n", /* 42 */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS_OCSP_MULTI)
" -W 1 -v 4, Perform multi OCSP stapling for TLS13\n",
/* 43 */
#endif
#endif
#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
"-U Atomic User Record Layer Callbacks\n", /* 43 */
"-U Atomic User Record Layer Callbacks\n", /* 45 */
#endif
#ifdef HAVE_PK_CALLBACKS
"-P Public Key Callbacks\n", /* 44 */
"-P Public Key Callbacks\n", /* 45 */
#endif
#ifdef HAVE_ANON
"-a Anonymous client\n", /* 45 */
"-a Anonymous client\n", /* 46 */
#endif
#ifdef HAVE_CRL
"-C Disable CRL\n", /* 46 */
"-C Disable CRL\n", /* 47 */
#endif
#ifdef WOLFSSL_TRUST_PEER_CERT
"-E <file> Path to load trusted peer cert\n", /* 47 */
"-E <file> Path to load trusted peer cert\n", /* 48 */
#endif
#ifdef HAVE_WNR
"-q <file> Whitewood config file, defaults\n", /* 48 */
"-q <file> Whitewood config file, defaults\n", /* 49 */
#endif
"-H <arg> Internal tests"
" [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 49 */
" loadSSL, disallowETM]\n", /* 50 */
" [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 50 */
" loadSSL, disallowETM]\n", /* 51 */
#ifdef WOLFSSL_TLS13
"-J Use HelloRetryRequest to choose group for KE\n", /* 51 */
"-K Key Exchange for PSK not using (EC)DHE\n", /* 52 */
"-I Update keys and IVs before sending data\n", /* 53 */
"-J Use HelloRetryRequest to choose group for KE\n", /* 52 */
"-K Key Exchange for PSK not using (EC)DHE\n", /* 53 */
"-I Update keys and IVs before sending data\n", /* 54 */
#ifndef NO_DH
"-y Key Share with FFDHE named groups only\n", /* 54 */
"-y Key Share with FFDHE named groups only\n", /* 55 */
#endif
#ifdef HAVE_ECC
"-Y Key Share with ECC named groups only\n", /* 55 */
"-Y Key Share with ECC named groups only\n", /* 56 */
#endif
#endif /* WOLFSSL_TLS13 */
#ifdef HAVE_CURVE25519
"-t Use X25519 for key exchange\n", /* 56 */
"-t Use X25519 for key exchange\n", /* 57 */
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
"-Q Support requesting certificate post-handshake\n", /* 57 */
"-Q Support requesting certificate post-handshake\n", /* 58 */
#endif
#ifdef WOLFSSL_EARLY_DATA
"-0 Early data sent to server (0-RTT handshake)\n", /* 58 */
"-0 Early data sent to server (0-RTT handshake)\n", /* 59 */
#endif
#ifdef WOLFSSL_MULTICAST
"-3 <grpid> Multicast, grpid < 256\n", /* 59 */
"-3 <grpid> Multicast, grpid < 256\n", /* 60 */
#endif
"-1 <num> Display a result by specified language.\n"
" 0: English, 1: Japanese\n", /* 60 */
" 0: English, 1: Japanese\n", /* 61 */
#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
"-2 Disable DH Prime check\n", /* 61 */
"-2 Disable DH Prime check\n", /* 62 */
#endif
#ifdef HAVE_SECURE_RENEGOTIATION
"-4 Use resumption for renegotiation\n", /* 62 */
"-4 Use resumption for renegotiation\n", /* 63 */
#endif
#ifdef HAVE_TRUSTED_CA
"-5 Use Trusted CA Key Indication\n", /* 63 */
"-5 Use Trusted CA Key Indication\n", /* 64 */
#endif
"-6 Simulate WANT_WRITE errors on every other IO send\n",
#ifdef HAVE_CURVE448
"-8 Use X448 for key exchange\n", /* 66 */
"-8 Use X448 for key exchange\n", /* 65 */
#endif
#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
(defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
@ -1469,69 +1473,73 @@ static const char* client_usage_msg[][78] = {
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
"-W <num> OCSP Staplingを使用する"
" (1 v1, 2 v2, 3 v2 multi)\n", /* 41 */
" 'm' を最後に指定すると必ず staple を使用する\n" /* 42 */
" 'm' を最後に指定すると必ず staple を使用する\n" /* 42 */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS_OCSP_MULTI)
" -W 1 -v 4, "
"TLS13 使用時に複数(Multi)の OCSP を実施します\n" /* 43 */
#endif
#endif
#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
"-U アトミック・ユーザー記録の"
"コールバックを利用する\n", /* 43 */
"コールバックを利用する\n", /* 44 */
#endif
#ifdef HAVE_PK_CALLBACKS
"-P 公開鍵コールバック\n", /* 44 */
"-P 公開鍵コールバック\n", /* 45 */
#endif
#ifdef HAVE_ANON
"-a 匿名クライアント\n", /* 45 */
"-a 匿名クライアント\n", /* 46 */
#endif
#ifdef HAVE_CRL
"-C CRLを無効\n", /* 46 */
"-C CRLを無効\n", /* 47 */
#endif
#ifdef WOLFSSL_TRUST_PEER_CERT
"-E <file> 信頼出来るピアの証明書ロードの為のパス\n", /* 47 */
"-E <file> 信頼出来るピアの証明書ロードの為のパス\n", /* 48 */
#endif
#ifdef HAVE_WNR
"-q <file> Whitewood コンフィグファイル, 既定値\n", /* 48 */
"-q <file> Whitewood コンフィグファイル, 既定値\n", /* 49 */
#endif
"-H <arg> 内部テスト"
" [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 49 */
" loadSSL, disallowETM]\n", /* 50 */
" [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 50 */
" loadSSL, disallowETM]\n", /* 51 */
#ifdef WOLFSSL_TLS13
"-J HelloRetryRequestをKEのグループ選択に使用する\n", /* 51 */
"-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 52 */
"-I データ送信前に、鍵とIVを更新する\n", /* 53 */
"-J HelloRetryRequestをKEのグループ選択に使用する\n", /* 52 */
"-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 53 */
"-I データ送信前に、鍵とIVを更新する\n", /* 54 */
#ifndef NO_DH
"-y FFDHE名前付きグループとの鍵共有のみ\n", /* 54 */
"-y FFDHE名前付きグループとの鍵共有のみ\n", /* 55 */
#endif
#ifdef HAVE_ECC
"-Y ECC名前付きグループとの鍵共有のみ\n", /* 55 */
"-Y ECC名前付きグループとの鍵共有のみ\n", /* 56 */
#endif
#endif /* WOLFSSL_TLS13 */
#ifdef HAVE_CURVE25519
"-t X25519を鍵交換に使用する\n", /* 56 */
"-t X25519を鍵交換に使用する\n", /* 57 */
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
"-Q ポストハンドシェークの証明要求をサポートする\n", /* 57 */
"-Q ポストハンドシェークの証明要求をサポートする\n", /* 58 */
#endif
#ifdef WOLFSSL_EARLY_DATA
"-0 Early data をサーバーへ送信する"
"0-RTTハンドシェイク\n", /* 58 */
"0-RTTハンドシェイク\n", /* 59 */
#endif
#ifdef WOLFSSL_MULTICAST
"-3 <grpid> マルチキャスト, grpid < 256\n", /* 59 */
"-3 <grpid> マルチキャスト, grpid < 256\n", /* 60 */
#endif
"-1 <num> 指定された言語で結果を表示します。\n"
" 0: 英語、 1: 日本語\n", /* 60 */
" 0: 英語、 1: 日本語\n", /* 61 */
#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
"-2 DHプライム番号チェックを無効にする\n", /* 61 */
"-2 DHプライム番号チェックを無効にする\n", /* 62 */
#endif
#ifdef HAVE_SECURE_RENEGOTIATION
"-4 再交渉に再開を使用\n", /* 62 */
"-4 再交渉に再開を使用\n", /* 63 */
#endif
#ifdef HAVE_TRUSTED_CA
"-5 信頼できる認証局の鍵表示を使用する\n", /* 63 */
"-5 信頼できる認証局の鍵表示を使用する\n", /* 64 */
#endif
"-6 WANT_WRITE エラーを全てのIO 送信でシミュレートします\n",
#ifdef HAVE_CURVE448
"-8 鍵交換に X448 を使用する\n", /* 66 */
"-8 鍵交換に X448 を使用する\n", /* 65 */
#endif
#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
(defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \

View File

@ -27,6 +27,9 @@ endif
if BUILD_OCSP_STAPLING
dist_noinst_SCRIPTS+= scripts/ocsp-stapling.test
if BUILD_OCSP_STAPLING_MULTI
dist_noinst_SCRIPTS+= scripts/ocsp-stapling_tls13multi.test
endif
if !BUILD_OCSP_STAPLING_V2
testsuite/testsuite.log: scripts/ocsp-stapling.log scripts/ocsp-stapling-with-ca-as-responder.log
endif
@ -34,6 +37,9 @@ scripts/ocsp-stapling.log: scripts/ocsp.log
dist_noinst_SCRIPTS+= scripts/ocsp-stapling-with-ca-as-responder.test
scripts/ocsp-stapling-with-ca-as-responder.log: scripts/ocsp.log
scripts/ocsp-stapling-with-ca-as-responder.log: scripts/ocsp-stapling.log
if BUILD_OCSP_STAPLING_MULTI
scripts/ocsp-stapling_tls13multi.log: scripts/ocsp-stapling-with-ca-as-responder.log
endif
endif
if BUILD_OCSP_STAPLING_V2

View File

@ -27,6 +27,20 @@ if ./examples/client/client '-#' | fgrep -q -e ' -DWOLFSSL_SNIFFER '; then
exit 77
fi
if ./examples/client/client -V | grep -q 4; then
tls13=yes
fi
if ./examples/client/client -? 2>&1 | grep -q 'DTLSv1.3'; then
dtls13=yes
fi
./examples/client/client '-?' 2>&1 | grep -- 'Perform multi OCSP stapling for TLS13'
if [ $? -eq 0 ]; then
tls13multi=yes
else
tls13multi=no
fi
if openssl s_server -help 2>&1 | fgrep -q -i ipv6 && nc -h 2>&1 | fgrep -q -i ipv6; then
IPV6_SUPPORTED=yes
else
@ -346,7 +360,7 @@ RESULT=$?
printf '%s\n\n' "Test successfully REVOKED!"
if ./examples/client/client -V | grep -q 4; then
if [[ ("$tls13" == "yes") && ("$tls13multi" == "no") ]]; then
printf '%s\n\n' "------------- TEST CASE 3 SHOULD PASS --------------------"
# client test against our own server - GOOD CERT
remove_single_rF "$ready_file2"
@ -412,7 +426,7 @@ if ./examples/client/client -? 2>&1 | grep -q 'DTLSv1.2'; then
printf '%s\n\n' "Test PASSED!"
fi
if ./examples/client/client -? 2>&1 | grep -q 'DTLSv1.3'; then
if [[ ("$dtls13" == "yes") && ("$tls13multi" == "no") ]]; then
printf '%s\n\n' "------------- TEST CASE DTLS-2 SHOULD PASS -------------------"
# client test against our own server, must staple - GOOD CERT
./examples/server/server -c certs/ocsp/server1-cert.pem -R "$ready_file2" \

View File

@ -43,7 +43,7 @@ fi
if ./examples/client/client '-#' | fgrep -q -e ' -DTEST_IPV6 '; then
if [[ "$IPV6_SUPPORTED" == "no" ]]; then
echo 'Skipping IPV6 test in environment lacking IPV6 support.'
exit 0
exit 77
fi
LOCALHOST='[::1]'
LOCALHOST_FOR_NC='-6 ::1'

View File

@ -0,0 +1,522 @@
#!/bin/bash
# ocsp-stapling_tls13multi.test
# Test requires HAVE_OCSP and HAVE_CERTIFICATE_STATUS_REQUEST_V2
SCRIPT_DIR="$(dirname "$0")"
# if we can, isolate the network namespace to eliminate port collisions.
if [[ -n "$NETWORK_UNSHARE_HELPER" ]]; then
if [[ -z "$NETWORK_UNSHARE_HELPER_CALLED" ]]; then
export NETWORK_UNSHARE_HELPER_CALLED=yes
exec "$NETWORK_UNSHARE_HELPER" "$0" "$@" || exit $?
fi
elif [ "${AM_BWRAPPED-}" != "yes" ]; then
bwrap_path="$(command -v bwrap)"
if [ -n "$bwrap_path" ]; then
export AM_BWRAPPED=yes
exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@"
fi
unset AM_BWRAPPED
fi
if [[ -z "${RETRIES_REMAINING-}" ]]; then
export RETRIES_REMAINING=2
fi
if ! ./examples/client/client -V | grep -q 4; then
tls13=no
else
tls13=yes
fi
if ! ./examples/client/client -? 2>&1 | grep -q 'DTLSv1.3'; then
dtls13=no
else
dtls13=yes
fi
if [[ ("$tls13" == "no") && ("$dtls13" == "no") ]]; then
echo 'skipping ocsp-stapling_tls13multi.test because TLS1.3 is not available.' 1>&2
exit 77
fi
if ! ./examples/client/client -V | grep -q 4; then
tls13=no
echo 'skipping ocsp-stapling_tls13multi.test because TLS1.3 is not available.' 1>&2
exit 77
else
tls13=yes
fi
if openssl s_server -help 2>&1 | fgrep -q -i ipv6 && nc -h 2>&1 | fgrep -q -i ipv6; then
IPV6_SUPPORTED=yes
else
IPV6_SUPPORTED=no
fi
if ./examples/client/client '-#' | fgrep -q -e ' -DTEST_IPV6 '; then
if [[ "$IPV6_SUPPORTED" == "no" ]]; then
echo 'Skipping IPV6 test in environment lacking IPV6 support.'
exit 77
fi
LOCALHOST='[::1]'
LOCALHOST_FOR_NC='-6 ::1'
else
LOCALHOST='127.0.0.1'
LOCALHOST_FOR_NC='127.0.0.1'
fi
PARENTDIR="$PWD"
# create a unique workspace directory ending in PID for the script instance ($$)
# to make this instance orthogonal to any others running, even on same repo.
# TCP ports are also carefully formed below from the PID, to minimize conflicts.
#WORKSPACE="${PARENTDIR}/workspace.pid$$"
#mkdir "${WORKSPACE}" || exit $?
WORKSPACE="$(mktemp -d -p ${PARENTDIR})"
cp -pR ${SCRIPT_DIR}/../certs "${WORKSPACE}"/ || exit $?
cd "$WORKSPACE" || exit $?
ln -s ../examples
CERT_DIR="certs/ocsp"
ready_file1="$WORKSPACE"/wolf_ocsp_s2_readyF1$$
ready_file2="$WORKSPACE"/wolf_ocsp_s2_readyF2$$
ready_file3="$WORKSPACE"/wolf_ocsp_s2_readyF3$$
ready_file4="$WORKSPACE"/wolf_ocsp_s2_readyF4$$
ready_file5="$WORKSPACE"/wolf_ocsp_s2_readyF5$$
printf '%s\n' "ready file 1: $ready_file1"
printf '%s\n' "ready file 2: $ready_file2"
printf '%s\n' "ready file 3: $ready_file3"
printf '%s\n' "ready file 4: $ready_file4"
printf '%s\n' "ready file 5: $ready_file5"
test_cnf="ocsp_s2.cnf"
wait_for_readyFile(){
counter=0
while [ ! -s $1 -a "$counter" -lt 20 ]; do
if [[ -n "${2-}" ]]; then
if ! kill -0 $2 2>&-; then
echo "pid $2 for port ${3-} exited before creating ready file. bailing..."
exit 1
fi
fi
echo -e "waiting for ready file..."
sleep 0.1
counter=$((counter+ 1))
done
if test -e $1; then
echo -e "found ready file, starting client..."
else
echo -e "NO ready file at $1 -- ending test..."
exit 1
fi
}
remove_single_rF(){
if test -e $1; then
printf '%s\n' "removing ready file: $1"
rm $1
fi
}
#create a configure file for cert generation with the port 0 solution
create_new_cnf() {
echo "Random Ports Selected: $1 $2 $3 $4"
cat <<- EOF > $test_cnf
#
# openssl configuration file for OCSP certificates
#
# Extensions to add to a certificate request (intermediate1-ca)
[ v3_req1 ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
authorityInfoAccess = OCSP;URI:http://127.0.0.1:$1
# Extensions to add to a certificate request (intermediate2-ca)
[ v3_req2 ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
authorityInfoAccess = OCSP;URI:http://127.0.0.1:$2
# Extensions to add to a certificate request (intermediate3-ca)
[ v3_req3 ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
authorityInfoAccess = OCSP;URI:http://127.0.0.1:$3
# Extensions for a typical CA
[ v3_ca ]
basicConstraints = CA:true
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = keyCertSign, cRLSign
authorityInfoAccess = OCSP;URI:http://127.0.0.1:$4
# OCSP extensions.
[ v3_ocsp ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
extendedKeyUsage = OCSPSigning
EOF
mv $test_cnf $CERT_DIR/$test_cnf
cd $CERT_DIR
CURR_LOC="$PWD"
printf '%s\n' "echo now in $CURR_LOC"
./renewcerts-for-test.sh $test_cnf
cd $WORKSPACE
}
remove_ready_file(){
if test -e $ready_file1; then
printf '%s\n' "removing ready file: $ready_file1"
rm $ready_file1
fi
if test -e $ready_file2; then
printf '%s\n' "removing ready file: $ready_file2"
rm $ready_file2
fi
if test -e $ready_file3; then
printf '%s\n' "removing ready file: $ready_file3"
rm $ready_file3
fi
if test -e $ready_file4; then
printf '%s\n' "removing ready file: $ready_file4"
rm $ready_file4
fi
if test -e $ready_file5; then
printf '%s\n' "removing ready file: $ready_file5"
rm $ready_file5
fi
}
cleanup()
{
exit_status=$?
for i in $(jobs -pr)
do
kill -s KILL "$i"
done
remove_ready_file
rm $CERT_DIR/$test_cnf
cd "$PARENTDIR" || return 1
rm -r "$WORKSPACE" || return 1
if [[ ("$exit_status" == 1) && ($RETRIES_REMAINING -gt 0) ]]; then
echo "retrying..."
RETRIES_REMAINING=$((RETRIES_REMAINING - 1))
exec $0 "$@"
fi
}
trap cleanup EXIT INT TERM HUP
[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1
# check if supported key size is large enough to handle 4096 bit RSA
size="$(./examples/client/client '-?' | grep "Max RSA key")"
size="${size//[^0-9]/}"
if [ ! -z "$size" ]; then
printf 'check on max key size of %d ...' $size
if [ $size -lt 4096 ]; then
printf '%s\n' "4096 bit RSA keys not supported"
exit 0
fi
printf 'OK\n'
fi
#get four unique ports
# choose consecutive ports based on the PID, skipping any that are
# already bound, to avoid the birthday problem in case other
# instances are sharing this host.
get_first_free_port() {
local ret="$1"
while :; do
if [[ "$ret" -ge 65536 ]]; then
ret=1024
fi
if ! nc -z ${LOCALHOST_FOR_NC} "$ret"; then
break
fi
ret=$((ret+1))
done
echo "$ret"
return 0
}
base_port=$((((($$ + $RETRIES_REMAINING) * 5) % (65536 - 2048)) + 1024))
port1=$(get_first_free_port $base_port)
port2=$(get_first_free_port $((port1 + 1)))
port3=$(get_first_free_port $((port2 + 1)))
port4=$(get_first_free_port $((port3 + 1)))
port5=$(get_first_free_port $((port4 + 1)))
# 1:
./examples/server/server -R $ready_file1 -p $port1 &
server_pid1=$!
wait_for_readyFile $ready_file1 $server_pid1 $port1
if [ ! -f $ready_file1 ]; then
printf '%s\n' "Failed to create ready file1: \"$ready_file1\""
exit 1
fi
# 2:
./examples/server/server -R $ready_file2 -p $port2 &
server_pid2=$!
wait_for_readyFile $ready_file2 $server_pid2 $port2
if [ ! -f $ready_file2 ]; then
printf '%s\n' "Failed to create ready file2: \"$ready_file2\""
exit 1
fi
# 3:
./examples/server/server -R $ready_file3 -p $port3 &
server_pid3=$!
wait_for_readyFile $ready_file3 $server_pid3 $port3
if [ ! -f $ready_file3 ]; then
printf '%s\n' "Failed to create ready file3: \"$ready_file3\""
exit 1
fi
# 4:
./examples/server/server -R $ready_file4 -p $port4 &
server_pid4=$!
wait_for_readyFile $ready_file4 $server_pid4 $port4
if [ ! -f $ready_file4 ]; then
printf '%s\n' "Failed to create ready file4: \"$ready_file4\""
exit 1
fi
printf '%s\n' "------------- PORTS ---------------"
printf '%s' "Random ports selected: $port1 $port2"
printf '%s\n' " $port3 $port4"
printf '%s\n' "-----------------------------------"
# Use client connections to cleanly shutdown the servers
./examples/client/client -p $port1
./examples/client/client -p $port2
./examples/client/client -p $port3
./examples/client/client -p $port4
create_new_cnf $port1 $port2 $port3 \
$port4
sleep 0.1
# setup ocsp responders
# OLD: ./certs/ocsp/ocspd-root-ca-and-intermediate-cas.sh &
# NEW: openssl isn't being cleaned up, invoke directly in script for cleanup
# purposes!
openssl ocsp -port $port1 -nmin 1 \
-index certs/ocsp/index-ca-and-intermediate-cas.txt \
-rsigner certs/ocsp/ocsp-responder-cert.pem \
-rkey certs/ocsp/ocsp-responder-key.pem \
-CA certs/ocsp/root-ca-cert.pem \
"$@" \
&
# OLD: ./certs/ocsp/ocspd-intermediate2-ca-issued-certs.sh &
# NEW: openssl isn't being cleaned up, invoke directly in script for cleanup
# purposes!
openssl ocsp -port $port2 -nmin 1 \
-index certs/ocsp/index-intermediate2-ca-issued-certs.txt \
-rsigner certs/ocsp/ocsp-responder-cert.pem \
-rkey certs/ocsp/ocsp-responder-key.pem \
-CA certs/ocsp/intermediate2-ca-cert.pem \
"$@" \
&
# OLD: ./certs/ocsp/ocspd-intermediate3-ca-issued-certs.sh &
# NEW: openssl isn't being cleaned up, invoke directly in script for cleanup
# purposes!
openssl ocsp -port $port3 -nmin 1 \
-index certs/ocsp/index-intermediate3-ca-issued-certs.txt \
-rsigner certs/ocsp/ocsp-responder-cert.pem \
-rkey certs/ocsp/ocsp-responder-key.pem \
-CA certs/ocsp/intermediate3-ca-cert.pem \
"$@" \
&
# NEW: openssl isn't being cleaned up, invoke directly in script for cleanup
# purposes!
openssl ocsp -port $port4 -nmin 1 \
-index certs/ocsp/index-ca-and-intermediate-cas.txt \
-rsigner certs/ocsp/ocsp-responder-cert.pem \
-rkey certs/ocsp/ocsp-responder-key.pem \
-CA certs/ocsp/root-ca-cert.pem \
"$@" \
&
sleep 0.1
# "jobs" is not portable for posix. Must use bash interpreter!
[ $(jobs -r | wc -l) -ne 4 ] && printf '\n\n%s\n' "Setup ocsp responder failed, skipping" && exit 0
printf '\n\n%s\n\n' "All OCSP responders started successfully!"
if [ "$tls13" == "yes" ]; then
printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------"
# client test against our own server - GOOD CERTS
./examples/server/server -c certs/ocsp/server3-cert.pem \
-k certs/ocsp/server3-key.pem -R $ready_file5 \
-p $port5 -v 4 &
server_pid5=$!
wait_for_readyFile $ready_file5 $server_pid5 $port5
./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 \
-p $port5
RESULT=$?
[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 1 failed" && exit 1
printf '%s\n\n' "Test PASSED!"
printf '%s\n\n' "------------- TEST CASE 2 SHOULD REVOKE ----------------------"
# client test against our own server - REVOKED SERVER CERT
remove_single_rF $ready_file5
./examples/server/server -c certs/ocsp/server4-cert.pem \
-k certs/ocsp/server4-key.pem -R $ready_file5 \
-p $port5 -v 4 &
server_pid5=$!
wait_for_readyFile $ready_file5 $server_pid5 $port5
./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 \
-p $port5
RESULT=$?
[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1
printf '%s\n\n' "Test successfully REVOKED!"
printf '%s\n\n' "------------- TEST CASE 3 SHOULD REVOKE ----------------------"
remove_single_rF $ready_file5
./examples/server/server -c certs/ocsp/server4-cert.pem \
-k certs/ocsp/server4-key.pem -R $ready_file5 \
-p $port5 &
sleep 0.1
./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 \
-p $port5
RESULT=$?
[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1
printf '%s\n\n' "Test successfully REVOKED!"
printf '%s\n\n' "------------- TEST CASE 4 SHOULD REVOKE ------------------------"
# client test against our own server - REVOKED INTERMEDIATE CERT
remove_single_rF $ready_file5
./examples/server/server -c certs/ocsp/server5-cert.pem \
-k certs/ocsp/server5-key.pem -R $ready_file5 \
-p $port5 -v 4 &
server_pid5=$!
wait_for_readyFile $ready_file5 $server_pid5 $port5
./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 \
-p $port5
RESULT=$?
[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1
printf '%s\n\n' "Test successfully REVOKED!"
printf '%s\n\n' "------------- TEST CASE 5 SHOULD REVOKE ----------------------"
remove_single_rF $ready_file5
./examples/server/server -c certs/ocsp/server5-cert.pem \
-k certs/ocsp/server5-key.pem -R $ready_file5 \
-p $port5 -v 4 &
server_pid5=$!
wait_for_readyFile $ready_file5 $server_pid5 $port5
./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 \
-p $port5
RESULT=$?
[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1
printf '%s\n\n' "Test successfully REVOKED!"
printf '%s\n\n' "------------- TEST CASE 6 LOAD CERT IN SSL -------------------"
remove_single_rF $ready_file5
./examples/server/server -c certs/ocsp/server1-cert.pem \
-k certs/ocsp/server1-key.pem -R $ready_file5 -v 4 \
-p $port5 -H loadSSL &
server_pid5=$!
wait_for_readyFile $ready_file5 $server_pid5 $port5
echo "test connection" | openssl s_client -status -legacy_renegotiation -connect ${LOCALHOST}:$port5 -cert ./certs/client-cert.pem -key ./certs/client-key.pem -CAfile ./certs/ocsp/root-ca-cert.pem
RESULT=$?
[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection failed $RESULT" && exit 1
wait $server_pid5
if [ $? -ne 0 ]; then
printf '%s\n' "Unexpected server result"
exit 1
fi
printf '%s\n\n' "Test successful"
printf '%s\n\n' "------------- TEST CASE 7 SHOULD REVOKE ----------------------"
remove_single_rF $ready_file5
./examples/server/server -c certs/ocsp/server4-cert.pem \
-k certs/ocsp/server4-key.pem -R $ready_file5 \
-p $port5 -H loadSSL -v 4 &
server_pid5=$!
sleep 0.1
./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 \
-p $port5
RESULT=$?
[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1
wait $server_pid5
if [ $? -ne 1 ]; then
printf '%s\n' "Unexpected server result"
exit 1
fi
printf '%s\n\n' "Test successfully REVOKED!"
fi
if [ "$dtls13" == "yes" ]; then
printf '%s\n\n' "------------- TEST CASE DTLS-1 SHOULD PASS ---------------"
# client test against our own server - GOOD CERTS
./examples/server/server -c certs/ocsp/server3-cert.pem \
-k certs/ocsp/server3-key.pem -R $ \
-p $port5 -u -v 4 &
server_pid5=$!
sleep 0.2
./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -u -v 4 \
-p $port5
RESULT=$?
[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 1 failed" && exit 1
printf '%s\n\n' "Test PASSED!"
printf '%s\n\n' "------------- TEST CASE DTLS-2 SHOULD REVOKE --------------"
# client test against our own server - REVOKED SERVER CERT
remove_single_rF $ready_file5
./examples/server/server -c certs/ocsp/server4-cert.pem \
-k certs/ocsp/server4-key.pem -R $ready_file5 \
-p $port5 -v 4 &
server_pid5=$!
sleep 0.2
./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 \
-p $port5
RESULT=$?
[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1
printf '%s\n\n' "Test successfully REVOKED!"
fi
# need a unique port since may run the same time as testsuite
generate_port() {
#-------------------------------------------------------------------------#
# Generate a random port number
#-------------------------------------------------------------------------#
if [[ "$OSTYPE" == "linux"* ]]; then
port=$(($(od -An -N2 /dev/urandom) % (65535-49512) + 49512))
elif [[ "$OSTYPE" == "darwin"* ]]; then
port=$(($(od -An -N2 /dev/random) % (65535-49512) + 49512))
else
echo "Unknown OS TYPE"
exit 1
fi
}
printf '%s\n\n' "------------------- TESTS COMPLETE ---------------------------"
exit 0

View File

@ -7745,6 +7745,11 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->sigSpec = ctx->sigSpec;
ssl->sigSpecSz = ctx->sigSpecSz;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifdef HAVE_OCSP
#if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
ssl->response_idx = 0;
#endif
#endif
/* Returns 0 on success, not WOLFSSL_SUCCESS (1) */
WOLFSSL_MSG_EX("InitSSL done. return 0 (success)");
return 0;
@ -13416,12 +13421,17 @@ int CopyDecodedAcertToX509(WOLFSSL_X509_ACERT* x509, DecodedAcert* dAcert)
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
(defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(WOLFSSL_NO_TLS12))
static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 status_length)
static int ProcessCSR_ex(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 status_length, int idx)
{
int ret = 0;
OcspRequest* request;
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
TLSX* ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
CertificateStatusRequest* csr;
#else
(void)idx;
#endif
#ifdef WOLFSSL_SMALL_STACK
CertStatus* status;
OcspEntry* single;
@ -13433,11 +13443,19 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif
WOLFSSL_ENTER("ProcessCSR");
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
if (ext) {
/* status request */
csr = (CertificateStatusRequest*)ext->data;
if (csr && !csr->ssl)
csr->ssl = ssl;
}
#endif
do {
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (ssl->status_request) {
request = (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
request = (OcspRequest*)TLSX_CSR_GetRequest_ex(ssl->extensions,
idx);
ssl->status_request = 0;
break;
}
@ -13506,6 +13524,12 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
WOLFSSL_LEAVE("ProcessCSR", ret);
return ret;
}
static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 status_length)
{
return ProcessCSR_ex(ssl, input, inOutIdx, status_length, 0);
}
#endif
@ -14562,6 +14586,52 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args)
return ret;
}
#if defined(HAVE_OCSP) && defined(WOLFSSL_TLS13) \
&& defined(HAVE_CERTIFICATE_STATUS_REQUEST)
static int ProcessPeerCertsChainOCSPStatusCheck(WOLFSSL* ssl)
{
int ret = 0;
word32 i;
word32 idx = 0;
TLSX* ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
CertificateStatusRequest* csr;
if (ext) {
csr = (CertificateStatusRequest*)ext->data;
if (csr == NULL) {
return 0;
}
} else
return 0;
/* error when leaf cert doesn't have certificate status */
if (csr->requests < 1 || csr->responses[0].length == 0) {
WOLFSSL_MSG("Leaf cert doesn't have certificate status.");
return BAD_CERTIFICATE_STATUS_ERROR;
}
for (i = 0; i < csr->requests; i++) {
if (csr->responses[i].length != 0) {
ssl->status_request = 1;
idx = 0;
ret = ProcessCSR_ex(ssl,
csr->responses[i].buffer,
&idx, csr->responses[i].length, i);
if (ret < 0) {
WOLFSSL_ERROR_VERBOSE(ret);
break;
}
}
else {
WOLFSSL_MSG("Intermediate cert doesn't have certificate status.");
}
}
return ret;
}
#endif
#ifdef HAVE_CRL
static int ProcessPeerCertsChainCRLCheck(WOLFSSL* ssl, ProcPeerCertArgs* args)
{
@ -14844,8 +14914,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
args->idx += extSz;
listSz -= extSz + OPAQUE16_LEN;
WOLFSSL_MSG_EX("\tParsing %d bytes of cert extensions",
args->exts[args->totalCerts].length);
args->exts[args->totalCerts].length);
#if !defined(NO_TLS)
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
ssl->response_idx = args->totalCerts;
#endif
ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer,
(word16)args->exts[args->totalCerts].length,
certificate, NULL);
@ -15040,6 +15113,13 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
else /* skips OCSP and force CRL check */
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
if (IsAtLeastTLSv1_3(ssl->version)) {
ret = TLSX_CSR_InitRequest_ex(ssl->extensions,
args->dCert, ssl->heap, args->certIdx);
}
else
#endif
if (SSL_CM(ssl)->ocspEnabled &&
SSL_CM(ssl)->ocspCheckAll) {
WOLFSSL_MSG("Doing Non Leaf OCSP check");
@ -15520,24 +15600,17 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->options.side == WOLFSSL_CLIENT_END) {
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (ssl->status_request) {
args->fatal = (TLSX_CSR_InitRequest(ssl->extensions,
args->dCert, ssl->heap) != 0);
args->fatal = (TLSX_CSR_InitRequest_ex(
ssl->extensions, args->dCert,
ssl->heap, args->certIdx) != 0);
doLookup = 0;
WOLFSSL_MSG("\tHave status request");
#if defined(WOLFSSL_TLS13)
if (ssl->options.tls1_3) {
TLSX* ext = TLSX_Find(ssl->extensions,
TLSX_STATUS_REQUEST);
if (ext != NULL) {
word32 idx = 0;
CertificateStatusRequest* csr =
(CertificateStatusRequest*)ext->data;
ret = ProcessCSR(ssl, csr->response.buffer,
&idx, csr->response.length);
if (ret < 0) {
WOLFSSL_ERROR_VERBOSE(ret);
goto exit_ppc;
}
ret = ProcessPeerCertsChainOCSPStatusCheck(ssl);
if (ret < 0) {
WOLFSSL_ERROR_VERBOSE(ret);
goto exit_ppc;
}
}
#endif
@ -23398,7 +23471,7 @@ int SendFinished(WOLFSSL* ssl)
*
* Returns 0 on success
*/
static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
DecodedCert* cert, byte* certData, word32 length,
byte *ctxOwnsRequest)
{
@ -24284,7 +24357,6 @@ int SendCertificateStatus(WOLFSSL* ssl)
if (idx > chain->length)
break;
ret = CreateOcspRequest(ssl, request, cert, der.buffer,
der.length, &ctxOwnsRequest);
if (ret == 0) {
@ -25485,6 +25557,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case MAX_CHAIN_ERROR:
return "Maximum Chain Depth Exceeded";
case MAX_CERT_EXTENSIONS_ERR:
return "Maximum Cert Extension Exceeded";
case COOKIE_ERROR:
return "DTLS Cookie Error";

View File

@ -13210,7 +13210,11 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
#ifdef WOLFSSL_QUIC
wolfSSL_quic_clear(ssl);
#endif
#ifdef HAVE_OCSP
#if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
ssl->response_idx = 0;
#endif
#endif
return WOLFSSL_SUCCESS;
}

254
src/tls.c
View File

@ -3184,51 +3184,64 @@ int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap)
static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap)
{
int i;
switch (csr->status_type) {
case WOLFSSL_CSR_OCSP:
FreeOcspRequest(&csr->request.ocsp);
for (i = 0; i <= csr->requests; i++) {
FreeOcspRequest(&csr->request.ocsp[i]);
}
break;
}
#ifdef WOLFSSL_TLS13
if (csr->response.buffer != NULL) {
XFREE(csr->response.buffer, csr->ssl->heap,
for (i = 0; i < MAX_CERT_EXTENSIONS; i++) {
if (csr->responses[i].buffer != NULL) {
XFREE(csr->responses[i].buffer, heap,
DYNAMIC_TYPE_TMP_BUFFER);
}
}
#endif
XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
(void)heap;
}
static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
word16 TLSX_CSR_GetSize_ex(CertificateStatusRequest* csr, byte isRequest,
int idx)
{
word16 size = 0;
/* shut up compiler warnings */
(void) csr; (void) isRequest;
#ifndef NO_WOLFSSL_CLIENT
if (isRequest) {
switch (csr->status_type) {
case WOLFSSL_CSR_OCSP:
size += ENUM_LEN + 2 * OPAQUE16_LEN;
if (csr->request.ocsp.nonceSz)
if (csr->request.ocsp[0].nonceSz)
size += OCSP_NONCE_EXT_SZ;
break;
}
}
#endif
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
if (!isRequest && csr->ssl->options.tls1_3)
return OPAQUE8_LEN + OPAQUE24_LEN + csr->response.length;
if (!isRequest && IsAtLeastTLSv1_3(csr->ssl->version)) {
return (word16)(OPAQUE8_LEN + OPAQUE24_LEN +
csr->responses[idx].length);
}
#else
(void)idx;
#endif
return size;
}
static int TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
byte isRequest)
static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
{
return TLSX_CSR_GetSize_ex(csr, isRequest, 0);
}
int TLSX_CSR_Write_ex(CertificateStatusRequest* csr, byte* output,
byte isRequest, int idx)
{
/* shut up compiler warnings */
(void) csr; (void) output; (void) isRequest;
@ -3249,8 +3262,8 @@ static int TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
offset += OPAQUE16_LEN;
/* request extensions */
if (csr->request.ocsp.nonceSz) {
ret = (int)EncodeOcspRequestExtensions(&csr->request.ocsp,
if (csr->request.ocsp[0].nonceSz) {
ret = (int)EncodeOcspRequestExtensions(&csr->request.ocsp[0],
output + offset + OPAQUE16_LEN,
OCSP_NONCE_EXT_SZ);
@ -3272,20 +3285,112 @@ static int TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
}
#endif
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
if (!isRequest && csr->ssl->options.tls1_3) {
if (!isRequest && IsAtLeastTLSv1_3(csr->ssl->version)) {
word16 offset = 0;
output[offset++] = csr->status_type;
c32to24(csr->response.length, output + offset);
c32to24(csr->responses[idx].length, output + offset);
offset += OPAQUE24_LEN;
XMEMCPY(output + offset, csr->response.buffer, csr->response.length);
offset += csr->response.length;
XMEMCPY(output + offset, csr->responses[idx].buffer,
csr->responses[idx].length);
offset += (word16)csr->responses[idx].length;
return offset;
}
#else
(void)idx;
#endif
return 0;
}
static int TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
byte isRequest)
{
return TLSX_CSR_Write_ex(csr, output, isRequest, 0);
}
#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \
defined(WOLFSSL_TLS_OCSP_MULTI)
/* Process OCSP request certificate chain
*
* ssl SSL/TLS object.
* returns 0 on success, otherwise failure.
*/
static int ProcessChainOCSPRequest(WOLFSSL* ssl)
{
DecodedCert* cert;
OcspRequest* request;
TLSX* extension;
CertificateStatusRequest* csr;
DerBuffer* chain;
word32 pos = 0;
buffer der;
int i = 1;
int ret = 0;
byte ctxOwnsRequest = 0;
/* use certChain if available, otherwise use peer certificate */
chain = ssl->buffers.certChain;
if (chain == NULL) {
chain = ssl->buffers.certificate;
}
extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
csr = extension ?
(CertificateStatusRequest*)extension->data : NULL;
if (csr == NULL)
return MEMORY_ERROR;
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
DYNAMIC_TYPE_DCERT);
if (cert == NULL) {
return MEMORY_E;
}
if (chain && chain->buffer) {
while (ret == 0 && pos + OPAQUE24_LEN < chain->length) {
c24to32(chain->buffer + pos, &der.length);
pos += OPAQUE24_LEN;
der.buffer = chain->buffer + pos;
pos += der.length;
if (pos > chain->length)
break;
request = &csr->request.ocsp[i];
if (ret == 0) {
ret = CreateOcspRequest(ssl, request, cert,
der.buffer, der.length, &ctxOwnsRequest);
if (ctxOwnsRequest) {
wolfSSL_Mutex* ocspLock =
&SSL_CM(ssl)->ocsp_stapling->ocspLock;
if (wc_LockMutex(ocspLock) == 0) {
/* the request is ours */
ssl->ctx->certOcspRequest = NULL;
}
wc_UnLockMutex(ocspLock);
}
}
if (ret == 0) {
request->ssl = ssl;
ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling,
request, &csr->responses[i], ssl->heap);
/* Suppressing, not critical */
if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED) ||
ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN) ||
ret == WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL)) {
ret = 0;
}
i++;
csr->requests++;
}
}
}
XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
return ret;
}
#endif
static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
byte isRequest)
{
@ -3340,14 +3445,14 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
switch (csr->status_type) {
case WOLFSSL_CSR_OCSP:
/* propagate nonce */
if (csr->request.ocsp.nonceSz) {
if (csr->request.ocsp[0].nonceSz) {
request =
(OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
if (request) {
XMEMCPY(request->nonce, csr->request.ocsp.nonce,
csr->request.ocsp.nonceSz);
request->nonceSz = csr->request.ocsp.nonceSz;
XMEMCPY(request->nonce, csr->request.ocsp[0].nonce,
csr->request.ocsp[0].nonceSz);
request->nonceSz = csr->request.ocsp[0].nonceSz;
}
}
break;
@ -3378,14 +3483,21 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
ret = BUFFER_ERROR;
}
if (ret == 0) {
csr->response.buffer = (byte*)XMALLOC(resp_length, ssl->heap,
if (ssl->response_idx < (1 + MAX_CHAIN_DEPTH))
csr->responses[ssl->response_idx].buffer =
(byte*)XMALLOC(resp_length, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (csr->response.buffer == NULL)
else
ret = BAD_FUNC_ARG;
if (ret == 0 &&
csr->responses[ssl->response_idx].buffer == NULL)
ret = MEMORY_ERROR;
}
if (ret == 0) {
XMEMCPY(csr->response.buffer, input + offset, resp_length);
csr->response.length = resp_length;
XMEMCPY(csr->responses[ssl->response_idx].buffer,
input + offset, resp_length);
csr->responses[ssl->response_idx].length = resp_length;
}
return ret;
@ -3450,6 +3562,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
#if defined(WOLFSSL_TLS13)
if (ssl->options.tls1_3) {
if (ssl->buffers.certificate == NULL) {
WOLFSSL_MSG("Certificate buffer not set!");
return BUFFER_ERROR;
@ -3480,19 +3593,33 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
}
FreeDecodedCert(cert);
XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
csr = extension ?
(CertificateStatusRequest*)extension->data : NULL;
if (csr == NULL)
return MEMORY_ERROR;
request = &csr->request.ocsp;
ret = CreateOcspResponse(ssl, &request, &csr->response);
request = &csr->request.ocsp[0];
ret = CreateOcspResponse(ssl, &request, &csr->responses[0]);
if (request != &csr->request.ocsp[0] &&
ssl->buffers.weOwnCert) {
/* request will be allocated in CreateOcspResponse() */
FreeOcspRequest(request);
XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
}
if (ret != 0)
return ret;
if (csr->response.buffer)
if (csr->responses[0].buffer)
TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST);
#if defined(WOLFSSL_TLS_OCSP_MULTI)
/* process OCSP request in certificate chain */
if ((ret = ProcessChainOCSPRequest(ssl)) != 0) {
WOLFSSL_MSG("Process Cert Chain OCSP request failed");
WOLFSSL_ERROR_VERBOSE(ret);
return ret;
}
#endif
}
else
#endif
@ -3504,9 +3631,10 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
return 0;
}
int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap)
int TLSX_CSR_InitRequest_ex(TLSX* extensions, DecodedCert* cert,
void* heap, int idx)
{
TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
CertificateStatusRequest* csr = extension ?
(CertificateStatusRequest*)extension->data : NULL;
int ret = 0;
@ -3515,18 +3643,31 @@ int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap)
switch (csr->status_type) {
case WOLFSSL_CSR_OCSP: {
byte nonce[MAX_OCSP_NONCE_SZ];
int nonceSz = csr->request.ocsp.nonceSz;
int req_cnt = idx == -1 ? csr->requests : idx;
int nonceSz = csr->request.ocsp[0].nonceSz;
OcspRequest* request;
request = &csr->request.ocsp[req_cnt];
if (request->serial != NULL) {
/* clear request contents before re-use */
FreeOcspRequest(request);
}
/* preserve nonce */
XMEMCPY(nonce, csr->request.ocsp.nonce, nonceSz);
XMEMCPY(nonce, request->nonce, nonceSz);
if ((ret = InitOcspRequest(&csr->request.ocsp, cert, 0, heap))
!= 0)
return ret;
if (req_cnt < MAX_CERT_EXTENSIONS) {
if ((ret = InitOcspRequest(request, cert, 0, heap)) != 0)
return ret;
/* restore nonce */
XMEMCPY(csr->request.ocsp.nonce, nonce, nonceSz);
csr->request.ocsp.nonceSz = nonceSz;
/* restore nonce */
XMEMCPY(request->nonce, nonce, nonceSz);
request->nonceSz = nonceSz;
csr->requests++;
}
else {
WOLFSSL_ERROR_VERBOSE(MAX_CERT_EXTENSIONS_ERR);
return MAX_CERT_EXTENSIONS_ERR;
}
}
break;
}
@ -3535,22 +3676,37 @@ int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap)
return ret;
}
void* TLSX_CSR_GetRequest(TLSX* extensions)
int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap)
{
return TLSX_CSR_InitRequest_ex(extensions, cert, heap, -1);
}
void* TLSX_CSR_GetRequest_ex(TLSX* extensions, int idx)
{
TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
CertificateStatusRequest* csr = extension ?
(CertificateStatusRequest*)extension->data : NULL;
if (csr) {
if (csr && csr->ssl) {
switch (csr->status_type) {
case WOLFSSL_CSR_OCSP:
return &csr->request.ocsp;
if (IsAtLeastTLSv1_3(csr->ssl->version)) {
return idx < csr->requests ? &csr->request.ocsp[idx] : NULL;
}
else {
return idx == 0 ? &csr->request.ocsp[0] : NULL;
}
}
}
return NULL;
}
void* TLSX_CSR_GetRequest(TLSX* extensions)
{
return TLSX_CSR_GetRequest_ex(extensions, 0);
}
int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
{
TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
@ -3561,9 +3717,9 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
switch (csr->status_type) {
case WOLFSSL_CSR_OCSP:
if (SSL_CM(ssl)->ocspEnabled) {
csr->request.ocsp.ssl = ssl;
csr->request.ocsp[0].ssl = ssl;
return CheckOcspRequest(SSL_CM(ssl)->ocsp,
&csr->request.ocsp, NULL, NULL);
&csr->request.ocsp[0], NULL, NULL);
}
else {
WOLFSSL_ERROR_VERBOSE(OCSP_LOOKUP_FAIL);
@ -3591,7 +3747,9 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type,
return MEMORY_E;
ForceZero(csr, sizeof(CertificateStatusRequest));
#if defined(WOLFSSL_TLS13)
XMEMSET(csr->responses, 0, sizeof(csr->responses));
#endif
csr->status_type = status_type;
csr->options = options;
csr->ssl = ssl;
@ -3608,9 +3766,9 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type,
(void)devId;
#endif
if (ret == 0) {
if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce,
if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp[0].nonce,
MAX_OCSP_NONCE_SZ) == 0)
csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ;
csr->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ;
wc_FreeRng(&rng);
}

View File

@ -8421,6 +8421,75 @@ static word32 NextCert(byte* data, word32 length, word32* idx)
return len;
}
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
/* Write certificate status request into certificate to buffer.
*
* ssl SSL/TLS object.
* certExts DerBuffer array. buffers written
* extSz word32 array.
* Length of the certificate status request data for the certificate.
* extSz_num number of the CSR written
* extIdx The index number of certificate status request data
* for the certificate.
* offset index offset
* returns Total number of bytes written.
*/
static word32 WriteCSRToBuffer(WOLFSSL* ssl, DerBuffer** certExts,
word16* extSz, word16 extSz_num)
{
int ret = 0;
TLSX* ext;
CertificateStatusRequest* csr;
word32 ex_offset = HELLO_EXT_TYPE_SZ + OPAQUE16_LEN /* extension type */
+ OPAQUE16_LEN /* extension length */;
word32 totalSz = 0;
word32 tmpSz;
word32 extIdx;
DerBuffer* der;
ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
csr = ext ? (CertificateStatusRequest*)ext->data : NULL;
if (csr) {
for (extIdx = 0; extIdx < (word16)(extSz_num); extIdx++) {
tmpSz = TLSX_CSR_GetSize_ex(csr, 0, extIdx);
if (tmpSz > (OPAQUE8_LEN + OPAQUE24_LEN) &&
certExts[extIdx] == NULL) {
/* csr extension is not zero */
extSz[extIdx] = tmpSz;
ret = AllocDer(&certExts[extIdx], extSz[extIdx] + ex_offset,
CERT_TYPE, ssl->heap);
if (ret < 0)
return ret;
der = certExts[extIdx];
/* write extension type */
c16toa(ext->type, der->buffer
+ OPAQUE16_LEN);
/* writes extension data length. */
c16toa(extSz[extIdx], der->buffer
+ HELLO_EXT_TYPE_SZ + OPAQUE16_LEN);
/* write extension data */
extSz[extIdx] = (word16)TLSX_CSR_Write_ex(csr,
der->buffer + ex_offset, 0, extIdx);
/* add extension offset */
extSz[extIdx] += (word16)ex_offset;
/* extension length */
c16toa(extSz[extIdx] - OPAQUE16_LEN,
der->buffer);
}
totalSz += extSz[extIdx];
}
}
else {
/* chain cert empty extension size */
totalSz += OPAQUE16_LEN * extSz_num;
}
return totalSz;
}
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
/* Add certificate data and empty extension to output up to the fragment size.
*
* ssl SSL/TLS object.
@ -8430,10 +8499,11 @@ static word32 NextCert(byte* data, word32 length, word32* idx)
* idx The start of the certificate data to write out.
* fragSz The maximum size of this fragment.
* output The buffer to write to.
* extIdx The index number of the extension data with the certificate
* returns the number of bytes written.
*/
static word32 AddCertExt(WOLFSSL* ssl, byte* cert, word32 len, word16 extSz,
word32 idx, word32 fragSz, byte* output)
word32 idx, word32 fragSz, byte* output, word16 extIdx)
{
word32 i = 0;
word32 copySz = min(len - idx, fragSz);
@ -8454,7 +8524,7 @@ static word32 AddCertExt(WOLFSSL* ssl, byte* cert, word32 len, word16 extSz,
}
}
else {
byte* certExts = ssl->buffers.certExts->buffer + idx + i - len;
byte* certExts = ssl->buffers.certExts[extIdx]->buffer + idx + i - len;
/* Put out as much of the extensions' data as will fit in fragment. */
if (copySz > fragSz - i)
copySz = fragSz - i;
@ -8476,8 +8546,10 @@ static int SendTls13Certificate(WOLFSSL* ssl)
{
int ret = 0;
word32 certSz, certChainSz, headerSz, listSz, payloadSz;
word16 extSz = 0;
word16 extSz[1 + MAX_CERT_EXTENSIONS];
word16 extIdx = 0;
word32 maxFragment;
word32 totalextSz = 0;
word32 len = 0;
word32 idx = 0;
word32 offset = OPAQUE16_LEN;
@ -8538,35 +8610,45 @@ static int SendTls13Certificate(WOLFSSL* ssl)
/* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */
headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ +
CERT_HEADER_SZ;
/* set empty extension as default */
for (extIdx = 0; extIdx < XELEM_CNT(extSz); extIdx++)
extSz[extIdx] = OPAQUE16_LEN;
ret = TLSX_GetResponseSize(ssl, certificate, &extSz);
if (ret < 0)
return ret;
length = 0;
listSz = 0;
/* Create extensions' data if none already present. */
if (extSz > OPAQUE16_LEN && ssl->buffers.certExts == NULL) {
ret = AllocDer(&ssl->buffers.certExts, extSz, CERT_TYPE, ssl->heap);
if (ret < 0)
return ret;
extSz = 0;
ret = TLSX_WriteResponse(ssl, ssl->buffers.certExts->buffer,
certificate, &extSz);
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
/* We only send CSR on the server side. On client side, the CSR data
* is populated with the server response. We would be sending the server
* its own stapling data. */
if (ssl->options.side == WOLFSSL_SERVER_END) {
ret = WriteCSRToBuffer(ssl, &ssl->buffers.certExts[0], &extSz[0],
1 /* +1 for leaf */ + ssl->buffers.certChainCnt);
if (ret < 0)
return ret;
totalextSz += ret;
ret = 0; /* Clear to signal no error */
}
else
#endif
{
/* Leaf cert empty extension size */
totalextSz += OPAQUE16_LEN;
/* chain cert empty extension size */
totalextSz += OPAQUE16_LEN * ssl->buffers.certChainCnt;
}
/* Length of message data with one certificate and extensions. */
length = (sword32)(headerSz + certSz + extSz);
length += (sword32)(headerSz + certSz + totalextSz);
/* Length of list data with one certificate and extensions. */
listSz = CERT_HEADER_SZ + certSz + extSz;
listSz += CERT_HEADER_SZ + certSz + totalextSz;
/* Send rest of chain if sending cert (chain has leading size/s). */
if (certSz > 0 && ssl->buffers.certChainCnt > 0) {
p = ssl->buffers.certChain->buffer;
/* Chain length including extensions. */
certChainSz = ssl->buffers.certChain->length +
OPAQUE16_LEN * (word32)ssl->buffers.certChainCnt;
certChainSz = ssl->buffers.certChain->length;
length += certChainSz;
listSz += certChainSz;
}
@ -8581,6 +8663,8 @@ static int SendTls13Certificate(WOLFSSL* ssl)
maxFragment = (word32)wolfSSL_GetMaxFragSize(ssl, MAX_RECORD_SIZE);
extIdx = 0;
while (length > 0 && ret == 0) {
byte* output = NULL;
word32 fragSz = 0;
@ -8595,15 +8679,15 @@ static int SendTls13Certificate(WOLFSSL* ssl)
#endif /* WOLFSSL_DTLS13 */
if (ssl->fragOffset == 0) {
if (headerSz + certSz + extSz + certChainSz <=
if (headerSz + certSz + totalextSz + certChainSz <=
maxFragment - HANDSHAKE_HEADER_SZ) {
fragSz = headerSz + certSz + extSz + certChainSz;
fragSz = headerSz + certSz + totalextSz + certChainSz;
}
#ifdef WOLFSSL_DTLS13
else if (ssl->options.dtls){
/* short-circuit the fragmentation logic here. DTLS
fragmentation will be done in dtls13HandshakeSend() */
fragSz = headerSz + certSz + extSz + certChainSz;
fragSz = headerSz + certSz + totalextSz + certChainSz;
}
#endif /* WOLFSSL_DTLS13 */
else {
@ -8662,20 +8746,23 @@ static int SendTls13Certificate(WOLFSSL* ssl)
else
AddTls13RecordHeader(output, fragSz, handshake, ssl);
if (certSz > 0 && ssl->fragOffset < certSz + extSz) {
/* Put in the leaf certificate with extensions. */
word32 copySz = AddCertExt(ssl, ssl->buffers.certificate->buffer,
certSz, extSz, ssl->fragOffset, fragSz, output + i);
i += copySz;
ssl->fragOffset += copySz;
length -= copySz;
fragSz -= copySz;
if (ssl->fragOffset == certSz + extSz)
FreeDer(&ssl->buffers.certExts);
if (extIdx == 0) {
if (certSz > 0 && ssl->fragOffset < certSz + extSz[0]) {
/* Put in the leaf certificate with extensions. */
word32 copySz = AddCertExt(ssl, ssl->buffers.certificate->buffer,
certSz, extSz[extIdx], ssl->fragOffset, fragSz,
output + i, extIdx);
i += copySz;
ssl->fragOffset += copySz;
length -= copySz;
fragSz -= copySz;
if (ssl->fragOffset == certSz + extSz[extIdx])
FreeDer(&ssl->buffers.certExts[extIdx]);
}
}
if (certChainSz > 0 && fragSz > 0) {
/* Put in the CA certificates with empty extensions. */
while (fragSz > 0) {
/* Put in the CA certificates with extensions. */
while (fragSz > 0) {
word32 l;
if (offset == len + OPAQUE16_LEN) {
@ -8684,19 +8771,27 @@ static int SendTls13Certificate(WOLFSSL* ssl)
/* Point to the start of current cert in chain buffer. */
p = ssl->buffers.certChain->buffer + idx;
len = NextCert(ssl->buffers.certChain->buffer,
ssl->buffers.certChain->length, &idx);
ssl->buffers.certChain->length, &idx);
if (len == 0)
break;
if (MAX_CERT_EXTENSIONS > extIdx)
extIdx++;
}
/* Write out certificate and empty extension. */
l = AddCertExt(ssl, p, len, OPAQUE16_LEN, offset, fragSz,
output + i);
/* Write out certificate and extension. */
l = AddCertExt(ssl, p, len, extSz[extIdx], offset, fragSz,
output + i, extIdx);
i += l;
ssl->fragOffset += l;
length -= l;
fragSz -= l;
offset += l;
if (extIdx != 0 && extIdx < MAX_CERT_EXTENSIONS &&
ssl->buffers.certExts[extIdx] != NULL &&
offset == len + extSz[extIdx])
FreeDer(&ssl->buffers.certExts[extIdx]);
/* for next chain cert */
len += extSz[extIdx] - OPAQUE16_LEN;
}
}

View File

@ -115,7 +115,7 @@ enum wolfSSL_ErrorCodes {
COOKIE_ERROR = -369, /* dtls cookie error */
SEQUENCE_ERROR = -370, /* dtls sequence error */
SUITES_ERROR = -371, /* suites pointer error */
MAX_CERT_EXTENSIONS_ERR = -372, /* max cert extension exceeded */
OUT_OF_ORDER_E = -373, /* out of order message */
BAD_KEA_TYPE_E = -374, /* bad KEA type found */
SANITY_CIPHER_E = -375, /* sanity check on cipher error */

View File

@ -2024,6 +2024,15 @@ enum Misc {
#define MAX_CHAIN_DEPTH 9
#endif
/* Max certificate extensions in TLS1.3 */
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
/* Number of extensions to set each OCSP response */
#define MAX_CERT_EXTENSIONS (1 + MAX_CHAIN_DEPTH)
#else
/* Only empty extensions */
#define MAX_CERT_EXTENSIONS 1
#endif
/* max size of a certificate message payload */
/* assumes MAX_CHAIN_DEPTH number of certificates at 2kb per certificate */
#ifndef MAX_CERTIFICATE_SZ
@ -3274,10 +3283,11 @@ typedef struct {
byte options;
WOLFSSL* ssl;
union {
OcspRequest ocsp;
OcspRequest ocsp[MAX_CERT_EXTENSIONS];
} request;
word16 requests;
#ifdef WOLFSSL_TLS13
buffer response;
buffer responses[MAX_CERT_EXTENSIONS];
#endif
} CertificateStatusRequest;
@ -3286,12 +3296,25 @@ WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions,
#ifndef NO_CERTS
WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert,
void* heap);
WOLFSSL_LOCAL int TLSX_CSR_InitRequest_ex(TLSX* extensions, DecodedCert* cert,
void* heap, int idx);
#endif
WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions);
WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl);
WOLFSSL_LOCAL word16 TLSX_CSR_GetSize_ex(CertificateStatusRequest* csr,
byte isRequest,
int idx);
WOLFSSL_LOCAL int TLSX_CSR_Write_ex(CertificateStatusRequest* csr, byte* output,
byte isRequest, int idx);
WOLFSSL_LOCAL void* TLSX_CSR_GetRequest_ex(TLSX* extensions, int idx);
#endif
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
WOLFSSL_LOCAL int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
DecodedCert* cert, byte* certData, word32 length,
byte *ctxOwnsRequest);
#endif
/** Certificate Status Request v2 - RFC 6961 */
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
@ -4771,7 +4794,7 @@ typedef struct Buffers {
/* chain after self, in DER, with leading size for each cert */
#ifdef WOLFSSL_TLS13
int certChainCnt;
DerBuffer* certExts;
DerBuffer* certExts[MAX_CERT_EXTENSIONS];
#endif
#endif
#ifdef WOLFSSL_SEND_HRR_COOKIE
@ -6040,6 +6063,9 @@ struct WOLFSSL {
char* url;
#endif
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
word32 response_idx;
#endif
#endif
#ifdef HAVE_NETX
NetX_Ctx nxCtx; /* NetX IO Context */