From 30eb558d583395427236a9b9bbda066597013cb2 Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Fri, 21 Jun 2024 08:29:42 +0900 Subject: [PATCH 1/2] fix ocsp response when using DTLS --- examples/client/client.c | 4 ++ scripts/ocsp-stapling.test | 43 +++++++++++++++++ scripts/ocsp-stapling2.test | 16 +++++++ src/internal.c | 95 ++++++++++--------------------------- 4 files changed, 88 insertions(+), 70 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index efad24a207..cd0394f13d 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1162,6 +1162,7 @@ static const char* client_usage_msg[][78] = { "-D Override Date Errors example\n", /* 18 */ "-e List Every cipher suite available, \n", /* 19 */ "-g Send server HTTP GET\n", /* 20 */ +#ifdef WOLFSSL_DTLS #ifndef WOLFSSL_DTLS13 "-u Use UDP DTLS, add -v 2 for DTLSv1, -v 3 for DTLSv1.2" " (default)\n", /* 21 */ @@ -1169,6 +1170,7 @@ static const char* client_usage_msg[][78] = { "-u Use UDP DTLS, add -v 2 for DTLSv1, -v 3 for DTLSv1.2" " (default), -v 4 for DTLSv1.3\n", /* 21 */ #endif /* !WOLFSSL_DTLS13 */ +#endif #ifdef WOLFSSL_SCTP "-G Use SCTP DTLS," " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n", /* 22 */ @@ -1387,6 +1389,7 @@ static const char* client_usage_msg[][78] = { "-D 日付エラー用コールバック例の上書きを行う\n", /* 18 */ "-e 利用可能な全ての暗号スイートをリスト, \n", /* 19 */ "-g サーバーへ HTTP GET を送信\n", /* 20 */ +#ifdef WOLFSSL_DTLS "-u UDP DTLSを使用する。\n" #ifndef WOLFSSL_DTLS13 " -v 2 を追加指定するとDTLSv1, " @@ -1396,6 +1399,7 @@ static const char* client_usage_msg[][78] = { "-v 3 を追加指定すると DTLSv1.2 (既定値),\n" " -v 4 を追加指定すると DTLSv1.3\n", /* 21 */ #endif /* !WOLFSSL_DTLS13 */ +#endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_SCTP "-G SCTP DTLSを使用する。-v 2 を追加指定すると" " DTLSv1, -v 3 を追加指定すると DTLSv1.2 (既定値)\n", /* 22 */ diff --git a/scripts/ocsp-stapling.test b/scripts/ocsp-stapling.test index c14fbf0e76..9ad1834376 100755 --- a/scripts/ocsp-stapling.test +++ b/scripts/ocsp-stapling.test @@ -388,6 +388,49 @@ else echo 'skipping TLS1.3 stapling tests.' 1>&2 fi +printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" +# client test against our own server - GOOD CERT +./examples/server/server -c certs/ocsp/server1-cert.pem -R "$ready_file2" \ + -k certs/ocsp/server1-key.pem -p $port3 & +wolf_pid3=$! +wait_for_readyFile "$ready_file2" $wolf_pid3 $port3 +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -p $port3 +RESULT=$? +[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 1 failed" && exit 1 +printf '%s\n\n' "Test PASSED!" + +# DTLS 1.2 and 1.3 cases +if ./examples/client/client -? 2>&1 | grep -q 'DTLS'; then + printf '%s\n\n' "------------- TEST CASE DTLS-1 SHOULD PASS -------------------" + # client test against our own server, must staple - GOOD CERT + echo $ready_file2 + ./examples/server/server -c certs/ocsp/server1-cert.pem -R "$ready_file2" \ + -k certs/ocsp/server1-key.pem -u -v 3 \ + -p $port3 & + wolf_pid3=$! + + sleep 0.2 + ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -u -v 3 \ + -W 1 -p $port3 + RESULT=$? + [ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 5 failed" && exit 1 + printf '%s\n\n' "Test PASSED!" + + 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" \ + -k certs/ocsp/server1-key.pem -u -v 4 \ + -p $port3 & + wolf_pid3=$! + sleep 0.2 + ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -u -v 4 \ + -W 1 -p $port3 + RESULT=$? + [ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 5 failed" && exit 1 + printf '%s\n\n' "Test PASSED!" + +fi + # need a unique port since may run the same time as testsuite generate_port() { #-------------------------------------------------------------------------# diff --git a/scripts/ocsp-stapling2.test b/scripts/ocsp-stapling2.test index 18df014634..7b51653fbf 100755 --- a/scripts/ocsp-stapling2.test +++ b/scripts/ocsp-stapling2.test @@ -499,6 +499,22 @@ RESULT=$? && exit 1 printf '%s\n\n' "Test PASSED!" + +if ./examples/client/client -? 2>&1 | grep -q 'DTLS'; 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 $ready_file5 \ + -p $port5 -u -v 3 & +server_pid5=$! +sleep 0.2 +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 2 -u -v 3 \ + -p $port5 +RESULT=$? +[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 1 failed" && exit 1 +printf '%s\n\n' "Test PASSED!" +fi + printf '%s\n\n' "------------------- TESTS COMPLETE ---------------------------" exit 0 diff --git a/src/internal.c b/src/internal.c index f5e1d89ef4..51752d51ba 100644 --- a/src/internal.c +++ b/src/internal.c @@ -23860,6 +23860,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, byte* output = NULL; word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; word32 length = ENUM_LEN; + word32 headerSz= idx; int sendSz = 0; int ret = 0; int i = 0; @@ -23879,88 +23880,42 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, default: return 0; } +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + headerSz = idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ; + sendSz = idx + length; + } else +#endif sendSz = (int)(idx + length); if (ssl->keys.encryptionOn) sendSz += MAX_MSG_EXTRA; - /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state - * is not advanced yet */ - ssl->options.buildingMsg = 1; - - if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) { - output = GetOutputBuffer(ssl); - - AddHeaders(output, length, certificate_status, ssl); - - output[idx++] = type; - - if (type == WOLFSSL_CSR2_OCSP_MULTI) { - c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx); - idx += OPAQUE24_LEN; - } - - for (i = 0; i < count; i++) { - c32to24(status[i].length, output + idx); - idx += OPAQUE24_LEN; - - XMEMCPY(output + idx, status[i].buffer, status[i].length); - idx += status[i].length; - } - - if (IsEncryptionOn(ssl, 1)) { - byte* input; - int inputSz = (int)idx; /* build msg adds rec hdr */ - int recordHeaderSz = RECORD_HEADER_SZ; + output =(byte*)XMALLOC(sendSz, ssl->heap, DYNAMIC_TYPE_OCSP); + if (output == NULL) + return MEMORY_E; - if (ssl->options.dtls) - recordHeaderSz += DTLS_RECORD_EXTRA; - inputSz -= recordHeaderSz; - input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); - if (input == NULL) - return MEMORY_E; + AddHeaders(output, length, certificate_status, ssl); - XMEMCPY(input, output + recordHeaderSz, inputSz); - #ifdef WOLFSSL_DTLS - ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz, certificate_status); - #endif - if (ret == 0) - sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0, 0, CUR_ORDER); - XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + output[idx++] = type; - if (sendSz < 0) - ret = sendSz; - } - else { - #ifdef WOLFSSL_DTLS - if (ret == 0 && IsDtlsNotSctpMode(ssl)) - ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, certificate_status); - if (ret == 0 && ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - ret = HashOutput(ssl, output, sendSz, 0); - } + if (type == WOLFSSL_CSR2_OCSP_MULTI) { + c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx); + idx += OPAQUE24_LEN; + } - #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) - if (ret == 0 && ssl->hsInfoOn) - AddPacketName(ssl, "CertificateStatus"); - if (ret == 0 && ssl->toInfoOn) { - ret = AddPacketInfo(ssl, "CertificateStatus", handshake, output, - sendSz, WRITE_PROTO, 0, ssl->heap); - if (ret != 0) - return ret; - } - #endif + for (i = 0; i < count; i++) { + c32to24(status[i].length, output + idx); + idx += OPAQUE24_LEN; - if (ret == 0) { - ssl->options.buildingMsg = 0; - ssl->buffers.outputBuffer.length += sendSz; - if (!ssl->options.groupMessages) - ret = SendBuffered(ssl); - } + XMEMCPY(output + idx, status[i].buffer, status[i].length); + idx += status[i].length; } + /* Send Message. Handled message fragmentation in the function if needed */ + ret = SendHandshakeMsg(ssl, output, (sendSz - headerSz), certificate_status, + "Certificate Status"); + XFREE(output, ssl->heap, DYNAMIC_TYPE_OCSP); WOLFSSL_LEAVE("BuildCertificateStatus", ret); return ret; From ac5b81edd1d4bbc4ef51d7b2eb190fd44b8a3cca Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Fri, 21 Jun 2024 13:22:00 +0900 Subject: [PATCH 2/2] fix unit test --- scripts/ocsp-stapling.test | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/scripts/ocsp-stapling.test b/scripts/ocsp-stapling.test index 9ad1834376..04d8ce9ace 100755 --- a/scripts/ocsp-stapling.test +++ b/scripts/ocsp-stapling.test @@ -388,19 +388,8 @@ else echo 'skipping TLS1.3 stapling tests.' 1>&2 fi -printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" -# client test against our own server - GOOD CERT -./examples/server/server -c certs/ocsp/server1-cert.pem -R "$ready_file2" \ - -k certs/ocsp/server1-key.pem -p $port3 & -wolf_pid3=$! -wait_for_readyFile "$ready_file2" $wolf_pid3 $port3 -./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -p $port3 -RESULT=$? -[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 1 failed" && exit 1 -printf '%s\n\n' "Test PASSED!" - # DTLS 1.2 and 1.3 cases -if ./examples/client/client -? 2>&1 | grep -q 'DTLS'; then +if ./examples/client/client -? 2>&1 | grep -q 'DTLSv1.2'; then printf '%s\n\n' "------------- TEST CASE DTLS-1 SHOULD PASS -------------------" # client test against our own server, must staple - GOOD CERT echo $ready_file2 @@ -415,7 +404,9 @@ if ./examples/client/client -? 2>&1 | grep -q 'DTLS'; then RESULT=$? [ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 5 failed" && exit 1 printf '%s\n\n' "Test PASSED!" +fi +if ./examples/client/client -? 2>&1 | grep -q 'DTLSv1.3'; 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" \