Address review findings on the sniffer Encrypt-Then-MAC fix

Hand the corrected plaintext length to the WOLFSSL_SNIFFER_STORE_DATA_CB
callback. The previous commit fixed the length only for the branch that
copies into the caller's buffer; the callback branch still passed the raw
record size, which spans the explicit IV, the tag or MAC and any padding.
The callback pointer already points at the start of the plaintext, so the
extra bytes run off the end of the decrypt output buffer, which leaves only
a record header of slack. AddressSanitizer reports a heap-buffer-overflow
read of 68 bytes on a TLS 1.2 CBC capture before this change and is clean
after it.

Reject a non-empty encrypt_then_mac extension in the ServerHello. RFC 7366
section 3.1 specifies empty extension_data and TLSX_EncryptThenMac_Parse
enforces it, as do the neighbouring length-constrained cases in the same
switch.

Clear the Encrypt-Then-MAC decision at the start of every ServerHello.
Nothing reset it, so a renegotiation that dropped the extension kept
stripping a MAC that was no longer there, and one that added it started
stripping while the previous cipher was still active.

Reset the decrypted flag at doMessage and gate the padSz subtraction on it.
The flag is set inside the decrypt block and was never cleared, so it
described whichever earlier record in the packet had last been decrypted.
The handshake case already guards the same value with it.

Set the decoded-data flag on the WOLFSSL_ASYNC_CRYPT drain path too. A
record that goes pending is completed inside SnifferAsyncPollQueue rather
than DecodePacket, so an async build could decrypt a capture correctly and
still report that nothing was decrypted. Send that diagnostic to stderr
rather than into the decoded output, and note the exit status in the usage
text so a wrapper is not surprised by it.

Add a TLS 1.2 CBC Encrypt-Then-MAC capture and the sniffer-gen.sh recipe
that produces it, so the fix has a regression test that can be regenerated.
The existing static RSA and IPv6 captures exercise the same path but no
script in the tree can rebuild them. The new capture covers both failure
modes: with an HMAC-SHA1 suite the old code fails the decrypt outright,
and with HMAC-SHA256, whose MAC is a multiple of the block size, it
silently decrypts the wrong byte range and emits 48 bytes where 14 are
correct.

Warn when the Encrypt-Then-MAC gate drops the TLS 1.2 CBC captures, so a
build configuration that loses coverage says so, and regenerate the keylog
reference output with a binary that carries the new feature token.
pull/11319/head
Tobias Frauenschlaeger 2026-08-24 21:53:41 +00:00 committed by Tobias Frauenschläger
parent 6a35183ab6
commit 960551cee0
18 changed files with 415 additions and 68 deletions

View File

@ -123,6 +123,14 @@
{"name": "sniffer-curves-enckeys", "minutes": 2.2,
"configure": ["--enable-sniffer", "--enable-curve25519", "--enable-curve448",
"--enable-enckeys", "CPPFLAGS=-DWOLFSSL_DH_EXTRA"]},
{"name": "sniffer-keylog-storedata", "minutes": 2.5,
"comment": "The sniffer keylog legs of scripts/sniffer-testsuite.test only run with WOLFSSL_SNIFFER_KEYLOGFILE, and the store data callback path is only compiled with WOLFSSL_SNIFFER_STORE_DATA_CB. Neither is set by any other entry.",
"configure": ["--enable-sniffer", "--enable-session-ticket",
"--enable-curve25519", "--enable-ed25519",
"CPPFLAGS=-DWOLFSSL_SNIFFER_KEYLOGFILE -DWOLFSSL_SNIFFER_STORE_DATA_CB"]},
{"name": "sniffer-no-enc-then-mac", "minutes": 2.2,
"comment": "The sniffer cannot read a capture that negotiated RFC 7366 without Encrypt-Then-MAC support, and says so through a dedicated error. That arm, and the assertion for it in scripts/sniffer-testsuite.test, are only compiled here.",
"configure": ["--enable-sniffer", "--enable-enc-then-mac=no"]},
{"name": "cryptocb-keygen-utils-aes-setkey", "minutes": 2.2,
"configure": ["--enable-cryptocb", "--enable-keygen", "--enable-cryptocbutils",
"CPPFLAGS=-DWOLF_CRYPTO_CB_AES_SETKEY"]},

View File

@ -177,7 +177,13 @@
so for a CBC suite it passed the trailing MAC to the block decrypt along with
the ciphertext, the length was not a multiple of the block size, and every
record failed. Since wolfSSL peers negotiate it by default, this covered
most TLS 1.2 CBC captures.
most TLS 1.2 CBC captures. A build without Encrypt-Then-MAC support now
reports that, once the negotiated suite is known to be a block cipher, rather
than failing every record with a generic decrypt error. Both the
`client_key_exchange` handler and the TLS 1.3 ServerHello path also overwrote
a specific error with "Server Client Key Mismatch", which hid the reason a
session could not be decrypted; they now keep an error that has already been
described.
* **Fix (sniffer reported plaintext lengths that included the MAC or AEAD
tag)**: the length returned to the caller was taken from the record size
@ -185,7 +191,22 @@
`ssl->keys.padSz`, so a 14 byte payload was reported as 30 under TLS 1.2
AES-GCM. The plaintext itself was correct, only the length was wrong, so a
caller trusting it read past the end of the message. The sniffer now
subtracts `padSz`, matching the non-sniffer read path.
subtracts `padSz`, matching the non-sniffer read path. The same corrected
length is handed to the `WOLFSSL_SNIFFER_STORE_DATA_CB` callback, which
previously received the raw record size and so read past the end of the
decrypt output buffer; that overread is confirmed by AddressSanitizer and is
fixed here.
* **Fix (`snifftest` could not report a failed capture)**: the read loop
assigned `hadBadPacket` on every packet instead of accumulating it, so an
early error was erased by any later packet that decoded cleanly and the
process still exited 0. A new `-expectdata` option additionally exits
non-zero when no application data could be decrypted at all; it is off by
default so that a handshake-only capture still exits 0. The example
`WOLFSSL_SNIFFER_STORE_DATA_CB` callback also sized its buffer from the first
record of a packet and reused it for every later one, even though the offset
it is handed restarts at zero for each record, so a larger second record
wrote past the end; it now grows the buffer per record and appends.
* **Fix (certificate manager left pointing at a released store)**:
`wolfSSL_CTX_set_cert_store()` pairs the store handed to it with the

View File

@ -128,6 +128,17 @@ dist_noinst_SCRIPTS+= scripts/tsp.test
EXTRA_DIST += scripts/sniffer-static-rsa.pcap \
scripts/sniffer-ipv6.pcap \
scripts/sniffer-tls12-etm.pcap \
scripts/sniffer-tls12-etm.out \
scripts/sniffer-tls12-etm-keylog.pcap \
scripts/sniffer-tls12-etm-keylog.sslkeylog \
scripts/sniffer-tls12-etm-keylog.out \
scripts/sniffer-tls12-keylog.pcap \
scripts/sniffer-tls12-keylog.sslkeylog \
scripts/sniffer-tls12-keylog.out \
scripts/sniffer-tls13-keylog.pcap \
scripts/sniffer-tls13-keylog.sslkeylog \
scripts/sniffer-tls13-keylog.out \
scripts/sniffer-tls13-dh.pcap \
scripts/sniffer-tls13-dh-resume.pcap \
scripts/sniffer-tls13-ecc.pcap \

View File

@ -25,6 +25,25 @@ fi
server_pid=0
tcpdump_pid=0
# tcpdump names the loopback interface differently across platforms.
if [ -z "$LOOPBACK_IF" ]; then
case "$(uname -s)" in
Darwin|*BSD) LOOPBACK_IF=lo0 ;;
*) LOOPBACK_IF=lo ;;
esac
fi
# stdbuf is GNU coreutils, absent on the BSDs.
STDBUF=()
if command -v stdbuf >/dev/null 2>&1; then
STDBUF=(stdbuf -oL -eL)
fi
# With no arguments every capture is regenerated, otherwise only the named
# ones, e.g. `scripts/sniffer-gen.sh tls12-etm ipv6`.
CAPTURES=("$@")
MATCHED=()
cleanup() {
if [ "$server_pid" -ne 0 ]; then kill $server_pid; server_pid=0; fi
if [ "$tcpdump_pid" -ne 0 ]; then sleep 1; kill -15 $tcpdump_pid; tcpdump_pid=0; fi
@ -42,11 +61,11 @@ run_test() { # Usage: run_test <cipher> [serverArgs [clientArgs]]
if [ "$CIPHER" != "" ]; then
CIPHER="-l $CIPHER"
fi
stdbuf -oL -eL ./examples/server/server -i -x $CIPHER $2 2>&1 | prepend "[server] " &
"${STDBUF[@]}" ./examples/server/server -i -x $CIPHER $2 2>&1 | prepend "[server] " &
server_pid=$!
((server_pid--)) # Get the first PID in the pipe
sleep 0.1
stdbuf -oL -eL ./examples/client/client $CIPHER $3 2>&1 | prepend "[client] "
"${STDBUF[@]}" ./examples/client/client $CIPHER $3 2>&1 | prepend "[client] "
RET=$?
if [ "$RET" != 0 ]; then
echo "Error in test: $RET"
@ -76,6 +95,14 @@ run_sequence() {
run_test "TLS13-AES128-GCM-SHA256" "-v 4 -r -c ./certs/ed25519/server-ed25519.pem -k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem" "-v 4 -r -c ./certs/ed25519/client-ed25519.pem -k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem"
run_test "TLS13-AES256-GCM-SHA384" "-v 4 -r -c ./certs/ed25519/server-ed25519.pem -k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem" "-v 4 -r -c ./certs/ed25519/client-ed25519.pem -k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem"
run_test "TLS13-CHACHA20-POLY1305-SHA256" "-v 4 -r -c ./certs/ed25519/server-ed25519.pem -k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem" "-v 4 -r -c ./certs/ed25519/client-ed25519.pem -k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem"
elif [ "$1" == "tls12-etm" ]; then # TLS v1.2 static RSA CBC, Encrypt-Then-MAC
run_test "AES128-SHA" "-v 3" "-v 3"
run_test "AES256-SHA256" "-v 3" "-v 3"
elif [ "$1" == "tls12-etm-keylog" ]; then # TLS v1.2 ECDHE CBC, Encrypt-Then-MAC
run_test "ECDHE-RSA-AES128-SHA256" "-v 3" "-v 3"
run_test "ECDHE-RSA-AES256-SHA384" "-v 3" "-v 3"
elif [ "$1" == "static-rsa" ] || [ "$1" == "ipv6" ]; then # TLS v1.2 static RSA
run_test "AES128-SHA" "-v 3" "-v 3"
elif [ "$1" == "tls13-hrr" ]; then # TLS v1.3 Hello Retry Request
run_test "" "-v 4 -g" "-v 4 -J"
else
@ -87,6 +114,12 @@ run_sequence() {
run_capture() {
local config_flags=()
if [ ${#CAPTURES[@]} -ne 0 ] &&
! printf '%s\n' "${CAPTURES[@]}" | grep -qx -- "$1"; then
return
fi
MATCHED+=("$1")
echo -e "\nconfiguring and building wolfssl ($1)..."
# Add default flags
@ -101,22 +134,64 @@ run_capture() {
./configure "${config_flags[@]}" 1>/dev/null || exit $?
make 1>/dev/null || exit $?
if [[ "$1" == "tls12-keylog" || "$1" == "tls13-keylog" ]]; then
if [[ "$1" == *keylog ]]; then
rm -f ./sslkeylog.log
fi
echo "starting capture"
tcpdump -i lo -n port 11111 -w ./scripts/sniffer-${1}.pcap -U &
tcpdump -i "$LOOPBACK_IF" -n port 11111 -w ./scripts/sniffer-${1}.pcap -U &
tcpdump_pid=$!
run_sequence $1
sleep 1
kill -15 $tcpdump_pid; tcpdump_pid=0
if [[ "$1" == "tls12-keylog" || "$1" == "tls13-keylog" ]]; then
if [[ "$1" == *keylog ]]; then
cp ./sslkeylog.log ./scripts/sniffer-${1}.sslkeylog
fi
run_snifftest $1
}
# Regenerate the known good output for the captures that sniffer-testsuite.test
# compares against one. The arguments have to match the ones the test uses.
run_snifftest() {
local args=()
case "$1" in
tls12-etm)
args=(-key ./certs/server-key.pem) ;;
tls12-keylog|tls13-keylog|tls12-etm-keylog)
args=(-keylogfile "./scripts/sniffer-${1}.sslkeylog") ;;
*)
return ;;
esac
echo "regenerating scripts/sniffer-${1}.out"
# Only the decrypted records are compared by sniffer-testsuite.test, and
# they are the only lines every build agrees on: the banner names whatever
# features the capture happened to be built with. Write to a temporary
# file so a failed run cannot leave the tracked one truncated.
local out
out=$(mktemp)
./sslSniffer/sslSnifferTest/snifftest -expectdata \
-pcap ./scripts/sniffer-${1}.pcap "${args[@]}" \
-server 127.0.0.1 -port 11111 \
| grep '^SSL App Data' > "$out"
local rc=$?
if [ $rc -ne 0 ]; then
rm -f "$out"
echo "snifftest could not read scripts/sniffer-${1}.pcap"
exit $rc
fi
mv "$out" ./scripts/sniffer-${1}.out
chmod 644 ./scripts/sniffer-${1}.out # mktemp hands back 0600
}
run_capture "static-rsa" "--enable-enc-then-mac=no"
run_capture "ipv6" "--enable-enc-then-mac=no --enable-ipv6"
run_capture "tls12" ""
run_capture "tls12-keylog" "--enable-enc-then-mac=no --enable-keylog-export CFLAGS='-Wno-cpp -DWOLFSSL_SNIFFER_KEYLOGFILE'"
run_capture "tls13-keylog" "--enable-keylog-export CFLAGS='-Wno-cpp -DWOLFSSL_SNIFFER_KEYLOGFILE'"
@ -126,6 +201,17 @@ run_capture "tls13-dh" "--disable-ecc"
run_capture "tls13-dh-resume" "--disable-ecc --enable-session-ticket"
run_capture "tls13-x25519" "--enable-curve25519 --enable-ed25519 --disable-dh --disable-ecc --disable-mlkem"
run_capture "tls13-x25519-resume" "--enable-curve25519 --enable-ed25519 --disable-dh --disable-ecc --disable-mlkem --enable-session-ticket"
run_capture "tls12-etm" ""
run_capture "tls12-etm-keylog" "--enable-keylog-export CFLAGS='-Wno-cpp -DWOLFSSL_SNIFFER_KEYLOGFILE'"
run_capture "tls13-hrr" "--disable-dh CFLAGS=-DWOLFSSL_SNIFFER_WATCH"
if [ ${#CAPTURES[@]} -ne 0 ]; then
for want in "${CAPTURES[@]}"; do
if ! printf '%s\n' "${MATCHED[@]}" | grep -qx -- "$want"; then
echo "No such capture: $want"
exit 1
fi
done
fi
echo "Tests passed in $SECONDS seconds"

Binary file not shown.

Binary file not shown.

View File

@ -59,12 +59,40 @@ has_static_rsa=no
if [ $? -eq 0 ]; then
has_static_rsa=yes
fi
# The TLS v1.2 CBC captures negotiated Encrypt-Then-MAC, so a sniffer built
# without it cannot decrypt them.
# sniffer-tls12-etm.pcap negotiated Encrypt-Then-MAC, so a sniffer built
# without it cannot decrypt that capture. Every other capture is readable by
# any build.
has_etm=no
./sslSniffer/sslSnifferTest/snifftest -? 2>&1 | grep -- 'encrypt_then_mac '
if [ $? -eq 0 ]; then
has_etm=yes
else
echo -e "\nWARNING: sniffer built without Encrypt-Then-MAC, skipping sniffer-tls12-etm.pcap\n"
fi
# A build that cannot read the capture has to say why, rather than failing
# every record with a generic decrypt error.
if test $has_etm == no && test $has_rsa == yes && test $has_tlsv12 == yes && test $has_static_rsa == yes
then
echo -e "\nChecking the Encrypt-Then-MAC diagnostic on sniffer-tls12-etm.pcap...\n"
TMPFILE=$(mktemp)
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest Encrypt-Then-MAC diagnostic failed: unable to create tmpfile\n" && exit 1
./sslSniffer/sslSnifferTest/snifftest \
-pcap ./scripts/sniffer-tls12-etm.pcap -key ./certs/server-key.pem \
-server 127.0.0.1 -port 11111 > $TMPFILE 2>&1
RESULT=$?
[ $RESULT -eq 0 ] && echo -e "\nsnifftest read an Encrypt-Then-MAC capture it cannot support\n" && rm $TMPFILE && exit 1
grep -q "Encrypt-Then-MAC not supported in this build" $TMPFILE
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest did not report the missing Encrypt-Then-MAC support\n" && rm $TMPFILE && exit 1
rm $TMPFILE
RESULT=0
fi
# ./configure --enable-sniffer CFLAGS="-DWOLFSSL_SNIFFER_KEYLOGFILE"
has_keylog=no
@ -93,25 +121,81 @@ has_packets() {
}
# TLS v1.2 Static RSA Test
if test $RESULT -eq 0 && test $has_rsa == yes && test $has_tlsv12 == yes && test $has_static_rsa == yes && test $has_etm == yes && has_packets ./scripts/sniffer-static-rsa.pcap
if test $RESULT -eq 0 && test $has_rsa == yes && test $has_tlsv12 == yes && test $has_static_rsa == yes && has_packets ./scripts/sniffer-static-rsa.pcap
then
echo -e "\nStarting snifftest on sniffer-static-rsa.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-static-rsa.pcap -key ./certs/server-key.pem -server 127.0.0.1 -port 11111
./sslSniffer/sslSnifferTest/snifftest -expectdata -pcap ./scripts/sniffer-static-rsa.pcap -key ./certs/server-key.pem -server 127.0.0.1 -port 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest static RSA failed\n" && exit 1
fi
# TLS v1.2 CBC Encrypt-Then-MAC Test (RFC 7366). The decrypted lengths are
# compared against known good output, since Encrypt-Then-MAC changes how much
# of a record is payload and a wrong length still decrypts.
if test $RESULT -eq 0 && test $has_rsa == yes && test $has_tlsv12 == yes && test $has_static_rsa == yes && test $has_etm == yes && has_packets ./scripts/sniffer-tls12-etm.pcap
then
echo -e "\nStarting snifftest on sniffer-tls12-etm.pcap...\n"
TMPFILE=$(mktemp)
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest Encrypt-Then-MAC failed: unable to create tmpfile\n" && exit 1
./sslSniffer/sslSnifferTest/snifftest -expectdata \
-pcap ./scripts/sniffer-tls12-etm.pcap \
-key ./certs/server-key.pem \
-server 127.0.0.1 -port 11111 | tee $TMPFILE
RESULT=${PIPESTATUS[0]}
[ $RESULT -ne 0 ] && echo -e "\nsnifftest Encrypt-Then-MAC failed: snifftest returned $RESULT\n" && rm $TMPFILE && exit 1
# use grep to only compare against decrypted output
SEARCH_STRING="SSL App Data"
grep "$SEARCH_STRING" $TMPFILE | diff - <(grep "$SEARCH_STRING" scripts/sniffer-tls12-etm.out)
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest Encrypt-Then-MAC failed: snifftest diff returned $RESULT\n" && rm $TMPFILE && exit 1
rm $TMPFILE
fi
# TLS v1.2 Static RSA Test (IPv6)
if test $RESULT -eq 0 && test $has_rsa == yes && test $has_tlsv12 == yes && test $has_static_rsa == yes && test $has_etm == yes && has_packets ./scripts/sniffer-ipv6.pcap
if test $RESULT -eq 0 && test $has_rsa == yes && test $has_tlsv12 == yes && test $has_static_rsa == yes && has_packets ./scripts/sniffer-ipv6.pcap
then
echo -e "\nStarting snifftest on sniffer-ipv6.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-ipv6.pcap -key ./certs/server-key.pem -server ::1 -port 11111
./sslSniffer/sslSnifferTest/snifftest -expectdata -pcap ./scripts/sniffer-ipv6.pcap -key ./certs/server-key.pem -server ::1 -port 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest (ipv6) failed\n" && exit 1
fi
# TLS v1.2 ECDHE CBC Encrypt-Then-MAC Test (RFC 7366)
if test $RESULT -eq 0 && test $has_rsa == yes && test $has_tlsv12 == yes && test $has_ecc == yes && test $has_etm == yes && test $has_keylog == yes
then
echo -e "\nStarting snifftest on sniffer-tls12-etm-keylog.pcap...\n"
TMPFILE=$(mktemp)
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest ECDHE Encrypt-Then-MAC failed: unable to create tmpfile\n" && exit 1
./sslSniffer/sslSnifferTest/snifftest -expectdata \
-pcap ./scripts/sniffer-tls12-etm-keylog.pcap \
-keylogfile ./scripts/sniffer-tls12-etm-keylog.sslkeylog \
-server 127.0.0.1 -port 11111 | tee $TMPFILE
RESULT=${PIPESTATUS[0]}
[ $RESULT -ne 0 ] && echo -e "\nsnifftest ECDHE Encrypt-Then-MAC failed: snifftest returned $RESULT\n" && rm $TMPFILE && exit 1
# use grep to only compare against decrypted output
SEARCH_STRING="SSL App Data"
grep "$SEARCH_STRING" $TMPFILE | diff - <(grep "$SEARCH_STRING" scripts/sniffer-tls12-etm-keylog.out)
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest ECDHE Encrypt-Then-MAC failed: snifftest diff returned $RESULT\n" && rm $TMPFILE && exit 1
rm $TMPFILE
fi
# TLS v1.2 and v1.3 sniffer keylog file test: runs sniffer on pcap and associated keylog file and compares decrypted traffic with known good output.
# To regenerate the known good output, run `scripts/sniffer-gen.sh` to regenerate the pcap and keylog file, then run the sniffer on it
# with the same arguments as in the test below, but redirect output to `./scripts/sniffer-tls12-keylog.out`.
@ -123,7 +207,7 @@ then
[[ $tlsver == "tls12" && $has_tlsv12 == "no" ]] && continue
[[ $tlsver == "tls13" && $has_tlsv13 == "no" ]] && continue
has_packets scripts/sniffer-$tlsver-keylog.pcap || continue
has_packets ./scripts/sniffer-$tlsver-keylog.pcap || continue
echo -e "\nStarting snifftest on sniffer-$tlsver-keylog.pcap...\n"
@ -131,7 +215,7 @@ then
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\n$tlsver snifftest keylog test failed: unable to create tmpfile\n" && rm $TMPFILE && exit 1
./sslSniffer/sslSnifferTest/snifftest \
./sslSniffer/sslSnifferTest/snifftest -expectdata \
-pcap scripts/sniffer-$tlsver-keylog.pcap \
-keylogfile scripts/sniffer-$tlsver-keylog.sslkeylog \
-server 127.0.0.1 -port 11111 | tee $TMPFILE
@ -154,7 +238,7 @@ fi
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_ecc == yes && has_packets ./scripts/sniffer-tls13-ecc.pcap
then
echo -e "\nStarting snifftest on sniffer-tls13-ecc.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-ecc.pcap -key ./certs/statickeys/ecc-secp256r1.pem -server 127.0.0.1 -port 11111
./sslSniffer/sslSnifferTest/snifftest -expectdata -pcap ./scripts/sniffer-tls13-ecc.pcap -key ./certs/statickeys/ecc-secp256r1.pem -server 127.0.0.1 -port 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 ECC failed\n" && exit 1
@ -164,7 +248,7 @@ fi
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_dh == yes && has_packets ./scripts/sniffer-tls13-dh.pcap
then
echo -e "\nStarting snifftest on sniffer-tls13-dh.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-dh.pcap -key ./certs/statickeys/dh-ffdhe2048.pem -server 127.0.0.1 -port 11111
./sslSniffer/sslSnifferTest/snifftest -expectdata -pcap ./scripts/sniffer-tls13-dh.pcap -key ./certs/statickeys/dh-ffdhe2048.pem -server 127.0.0.1 -port 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 DH failed\n" && exit 1
@ -174,7 +258,7 @@ fi
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_x25519 == yes && has_packets ./scripts/sniffer-tls13-x25519.pcap
then
echo -e "\nStarting snifftest on sniffer-tls13-x25519.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-x25519.pcap -key ./certs/statickeys/x25519.pem -server 127.0.0.1 -port 11111
./sslSniffer/sslSnifferTest/snifftest -expectdata -pcap ./scripts/sniffer-tls13-x25519.pcap -key ./certs/statickeys/x25519.pem -server 127.0.0.1 -port 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 X25519 failed\n" && exit 1
@ -184,7 +268,7 @@ fi
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_ecc == yes && test $session_ticket == yes && has_packets ./scripts/sniffer-tls13-ecc-resume.pcap
then
echo -e "\nStarting snifftest on sniffer-tls13-ecc-resume.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-ecc-resume.pcap -key ./certs/statickeys/ecc-secp256r1.pem -server 127.0.0.1 -port 11111
./sslSniffer/sslSnifferTest/snifftest -expectdata -pcap ./scripts/sniffer-tls13-ecc-resume.pcap -key ./certs/statickeys/ecc-secp256r1.pem -server 127.0.0.1 -port 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 ECC failed\n" && exit 1
@ -194,7 +278,7 @@ fi
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_dh == yes && test $session_ticket == yes && has_packets ./scripts/sniffer-tls13-dh-resume.pcap
then
echo -e "\nStarting snifftest on sniffer-tls13-dh-resume.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-dh-resume.pcap -key ./certs/statickeys/dh-ffdhe2048.pem -server 127.0.0.1 -port 11111
./sslSniffer/sslSnifferTest/snifftest -expectdata -pcap ./scripts/sniffer-tls13-dh-resume.pcap -key ./certs/statickeys/dh-ffdhe2048.pem -server 127.0.0.1 -port 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 DH failed\n" && exit 1
@ -204,7 +288,7 @@ fi
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_x25519 == yes && test $session_ticket == yes && has_packets ./scripts/sniffer-tls13-x25519-resume.pcap
then
echo -e "\nStarting snifftest on sniffer-tls13-x25519-resume.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-x25519-resume.pcap -key ./certs/statickeys/x25519.pem -server 127.0.0.1 -port 11111
./sslSniffer/sslSnifferTest/snifftest -expectdata -pcap ./scripts/sniffer-tls13-x25519-resume.pcap -key ./certs/statickeys/x25519.pem -server 127.0.0.1 -port 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 X25519 failed\n" && exit 1
@ -214,7 +298,7 @@ fi
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_ecc == yes && has_packets ./scripts/sniffer-tls13-hrr.pcap
then
echo -e "\nStarting snifftest on sniffer-tls13-hrr.pcap...\n"
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-hrr.pcap -key ./certs/statickeys/ecc-secp256r1.pem -server 127.0.0.1 -port 11111
./sslSniffer/sslSnifferTest/snifftest -expectdata -pcap ./scripts/sniffer-tls13-hrr.pcap -key ./certs/statickeys/ecc-secp256r1.pem -server 127.0.0.1 -port 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 HRR failed\n" && exit 1

View File

@ -0,0 +1,4 @@
SSL App Data(31:14):hello wolfssl!
SSL App Data(33:22):I hear you fa shizzle!
SSL App Data(72:14):hello wolfssl!
SSL App Data(74:22):I hear you fa shizzle!

Binary file not shown.

View File

@ -0,0 +1,4 @@
CLIENT_RANDOM 1810f69efd4315a092b03fc144a074df135ea6f2e0496206a0d374972abb39c9 7feab4a2632cd6b8ac603477c08d1b95e6d8bc7a5663d96ce6565b7cd95b2660ced0c8ce17159b79bfaad88ec585eebe
CLIENT_RANDOM 1810f69efd4315a092b03fc144a074df135ea6f2e0496206a0d374972abb39c9 7feab4a2632cd6b8ac603477c08d1b95e6d8bc7a5663d96ce6565b7cd95b2660ced0c8ce17159b79bfaad88ec585eebe
CLIENT_RANDOM f723e474965ef1d1c43e7040f293075d384c03d963b2904df65d54fb381ae5ea 4ee9a02ef5abecfdd9f5ff8d92276c91ba67e0d5bbacf849e2eb70058dd62c1749961cad9cb29ee45f63d922f0c095ea
CLIENT_RANDOM f723e474965ef1d1c43e7040f293075d384c03d963b2904df65d54fb381ae5ea 4ee9a02ef5abecfdd9f5ff8d92276c91ba67e0d5bbacf849e2eb70058dd62c1749961cad9cb29ee45f63d922f0c095ea

View File

@ -0,0 +1,4 @@
SSL App Data(29:14):hello wolfssl!
SSL App Data(31:22):I hear you fa shizzle!
SSL App Data(68:14):hello wolfssl!
SSL App Data(70:22):I hear you fa shizzle!

Binary file not shown.

View File

@ -1,7 +1,3 @@
snifftest 5.9.2
sniffer features: key_callback tls_v13 tls_v12 session_ticket static_ephemeral sni extended_master rsa dh ecc x22519 rsa_static dh_static ssl_keylog_file
Using packet filter: (ip6 or ip) and tcp and port 11111
SSL App Data(26:14):hello wolfssl!
SSL App Data(27:22):I hear you fa shizzle!
SSL App Data(58:14):hello wolfssl!

View File

@ -1,7 +1,3 @@
snifftest 5.9.2
sniffer features: key_callback tls_v13 tls_v12 session_ticket static_ephemeral sni extended_master rsa dh ecc x22519 rsa_static dh_static ssl_keylog_file
Using packet filter: (ip6 or ip) and tcp and port 11111
SSL App Data(22:14):hello wolfssl!
SSL App Data(24:22):I hear you fa shizzle!
SSL App Data(50:14):hello wolfssl!

View File

@ -378,6 +378,7 @@ static const char* const msgTable[] =
/* 99 */
"Invalid or missing keylog file",
"Encrypt-Then-MAC not supported in this build",
};
@ -467,6 +468,9 @@ typedef struct Flags {
#endif
byte gotFinished; /* processed finished */
byte secRenegEn; /* secure renegotiation enabled */
#if !defined(HAVE_ENCRYPT_THEN_MAC) || defined(WOLFSSL_AEAD_ONLY)
byte etmUnsupported; /* peer negotiated RFC 7366, we cannot */
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
byte wasPolled;
#endif
@ -2498,6 +2502,25 @@ static void FreeSetupKeysArgs(WOLFSSL* ssl, void* pArgs)
}
/* Process Keys */
#if !defined(HAVE_ENCRYPT_THEN_MAC) || defined(WOLFSSL_AEAD_ONLY)
/* RFC 7366 only covers block ciphers and a peer must not negotiate it for an
* AEAD or stream suite, so a session that asked for it is still readable here
* unless the negotiated suite turns out to be a block cipher.
returns 0 on success, WOLFSSL_FATAL_ERROR on a suite this build cannot read
*/
static int CheckEncryptThenMac(SnifferSession* session, char* error)
{
if (session->flags.etmUnsupported &&
session->sslServer->specs.cipher_type == block) {
SetError(ETM_NOT_SUPPORTED_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
return WOLFSSL_FATAL_ERROR;
}
return 0;
}
#endif
static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
char* error, KeyShareInfo* ksInfo)
{
@ -3230,6 +3253,12 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
ret = WOLFSSL_FATAL_ERROR; break;
}
#if !defined(HAVE_ENCRYPT_THEN_MAC) || defined(WOLFSSL_AEAD_ONLY)
if (CheckEncryptThenMac(session, error) != 0) {
ret = WOLFSSL_FATAL_ERROR; break;
}
#endif
#ifdef WOLFSSL_TLS13
/* TLS v1.3 derive handshake key */
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
@ -3678,6 +3707,11 @@ static int DoResume(SnifferSession* session, char* error)
return WOLFSSL_FATAL_ERROR;
}
#if !defined(HAVE_ENCRYPT_THEN_MAC) || defined(WOLFSSL_AEAD_ONLY)
if (CheckEncryptThenMac(session, error) != 0)
return WOLFSSL_FATAL_ERROR;
#endif
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
#ifdef HAVE_SESSION_TICKET
@ -3823,6 +3857,20 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
return WOLFSSL_FATAL_ERROR;
}
/* Encrypt-Then-MAC has to be re-negotiated in every ServerHello, so drop
* any earlier decision before parsing this one. Only the negotiated value
* is recorded here: it governs the records protected by the cipher spec
* this ServerHello is negotiating, and the ones still in flight under the
* previous one have to keep the decision they were made with. It is
* applied in ProcessMessage() when that cipher spec is switched to, the
* same point at which the library applies it. */
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
session->sslServer->options.encThenMac = 0;
session->sslClient->options.encThenMac = 0;
#else
session->flags.etmUnsupported = 0;
#endif
/* extensions */
if ((initialBytes - *sslBytes) < msgSz) {
word16 len;
@ -3936,10 +3984,24 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
break;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
case EXT_ENCRYPT_THEN_MAC:
/* RFC 7366 requires empty extension_data in the ServerHello. */
if (extLen != 0) {
SetError(SERVER_HELLO_INPUT_STR, error, session,
FATAL_ERROR_STATE);
return WOLFSSL_FATAL_ERROR;
}
/* MAC covers the ciphertext, so it has to be stripped before
* the record is decrypted. */
session->sslServer->options.startedETMRead = 1;
session->sslClient->options.startedETMRead = 1;
session->sslServer->options.encThenMac = 1;
session->sslClient->options.encThenMac = 1;
break;
#else
case EXT_ENCRYPT_THEN_MAC:
/* The session negotiated RFC 7366, but this build cannot
* strip the MAC ahead of decryption. Only a block cipher
* suite is actually unreadable, so the complaint waits until
* the suite is known. */
session->flags.etmUnsupported = 1;
break;
#endif
case EXT_MASTER_SECRET:
@ -4069,8 +4131,10 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
return ret;
}
#endif
SetError(KEY_MISMATCH_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
if (!session->verboseErr) {
SetError(KEY_MISMATCH_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
}
return ret;
}
@ -4890,7 +4954,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
#endif
if (ret != 0) {
if (ret != 0 && !session->verboseErr) {
SetError(KEY_MISMATCH_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
}
@ -6462,6 +6526,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
session->sslServer : session->sslClient;
doMessage:
decrypted = 0;
notEnough = 0;
rhSize = 0;
@ -6512,6 +6577,11 @@ doMessage:
session->flags.clientCipherOn = 1;
session->sslClient->options.handShakeState = HANDSHAKE_DONE;
session->sslClient->options.handShakeDone = 1;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
/* The ChangeCipherSpec that would have applied it was missed too. */
session->sslClient->options.startedETMRead =
session->sslClient->options.encThenMac;
#endif
}
/* decrypt if needed */
@ -6537,8 +6607,10 @@ doMessage:
sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
ssl->buffers.outputBuffer.buffer, &errCode,
&ivAdvance, &rh);
recordEnd = sslFrame - ivAdvance + rhSize; /* sslFrame moved so
should recordEnd */
if (sslFrame != NULL) {
/* sslFrame moved so should recordEnd */
recordEnd = sslFrame - ivAdvance + rhSize;
}
decrypted = 1;
#ifdef WOLFSSL_SNIFFER_STATS
@ -6605,6 +6677,12 @@ doPart:
else
session->flags.clientCipherOn = 1;
Trace(GOT_CHANGE_CIPHER_STR);
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
/* The records this side sends from here on are protected by the
cipher spec whose Encrypt-Then-MAC decision the last ServerHello
carried, so it only takes effect now. */
ssl->options.startedETMRead = ssl->options.encThenMac;
#endif
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
@ -6638,8 +6716,11 @@ doPart:
/* padSz covers the AEAD tag or record MAC, any block
* padding and the TLS 1.3 inner content type, matching what
* the non-sniffer read path removes from ssl->curSize. */
ret -= (int)ssl->keys.padSz;
* the non-sniffer read path removes from ssl->curSize.
* Only valid when this record went through
* DecryptMessage(), as in the handshake case above. */
if (decrypted)
ret -= (int)ssl->keys.padSz;
TraceGotData(ret);
if (ret > 0) { /* may be blank message */
@ -6670,7 +6751,9 @@ doPart:
int stored;
buf = ssl->buffers.clearOutputBuffer.buffer;
bufSz = ssl->buffers.clearOutputBuffer.length;
/* Same corrected extent the sibling branch
* copies, not the raw record size. */
bufSz = (word32)ret;
do {
stored = StoreDataCb(buf, bufSz, offset,
ctx);

View File

@ -170,7 +170,6 @@ static pcap_t* pcap = NULL;
static pcap_if_t* alldevs = NULL;
static struct bpf_program pcap_fp;
static const char *traceFile = "./tracefile.txt";
static int sawDecryptedData = 0;
static void FreeAll(void)
{
@ -315,13 +314,19 @@ static int myWatchCb(void* vSniffer,
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
typedef struct StoreDataCtx {
byte* data; /* plaintext of every record decoded from one packet */
word32 len; /* bytes stored so far */
} StoreDataCtx;
static int myStoreDataCb(const unsigned char* decryptBuf,
unsigned int decryptBufSz, unsigned int decryptBufOffset, void* ctx)
{
byte** data = (byte**)ctx;
unsigned int qty;
StoreDataCtx* store = (StoreDataCtx*)ctx;
unsigned int qty;
byte* tmpData;
if (data == NULL)
if (store == NULL)
return -1;
if (decryptBufSz < decryptBufOffset)
@ -329,21 +334,28 @@ static int myStoreDataCb(const unsigned char* decryptBuf,
qty = min(decryptBufSz - decryptBufOffset, STORE_DATA_BLOCK_SZ);
if (*data == NULL) {
byte* tmpData;
tmpData = (byte*)XREALLOC(*data, decryptBufSz + 1,
NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (tmpData == NULL) {
XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
*data = NULL;
return -1;
}
*data = tmpData;
/* One packet can carry several records, and the offset restarts at zero
* for each of them, so grow for this record and append after the ones
* already stored. The extra byte lets the caller null terminate. */
tmpData = (byte*)XREALLOC(store->data, store->len + decryptBufSz + 1,
NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (tmpData == NULL) {
XFREE(store->data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
store->data = NULL;
store->len = 0;
return -1;
}
store->data = tmpData;
XMEMCPY(store->data + store->len + decryptBufOffset,
decryptBuf + decryptBufOffset, qty);
if (decryptBufOffset + qty == decryptBufSz) {
/* record complete, the next one appends after it */
store->len += decryptBufSz;
}
XMEMCPY(*data + decryptBufOffset, decryptBuf + decryptBufOffset, qty);
return qty;
return (int)qty;
}
#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */
@ -646,6 +658,7 @@ typedef struct SnifferWorker {
char *passwd;
int port;
int hadBadPacket; /* track if sniffer worker saw bad packet */
int sawDecryptedData; /* track if sniffer worker decrypted app data */
int unused;
int id;
int shutdown;
@ -659,6 +672,8 @@ static int ssl_Init_SnifferWorker(SnifferWorker* worker, int port,
worker->keyFilesSrc = (char*)keyFilesSrc;
worker->passwd = (char*)passwd;
worker->port = port;
worker->hadBadPacket = 0;
worker->sawDecryptedData = 0;
worker->unused = 0;
worker->shutdown = 0;
worker ->id = id;
@ -747,7 +762,8 @@ static int SnifferWorkerPacketAdd(SnifferWorker* worker, int lastRet,
}
#endif /* THREADED_SNIFFTEST */
static int DecodePacket(byte* packet, int length, int packetNumber, char err[])
static int DecodePacket(byte* packet, int length, int packetNumber, char err[],
int* sawData)
{
int ret, j;
int hadBadPacket = 0;
@ -756,6 +772,9 @@ static int DecodePacket(byte* packet, int length, int packetNumber, char err[])
void* chain;
byte* data = NULL; /* pointer to decrypted data */
SSLInfo sslInfo;
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
StoreDataCtx store;
#endif
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
struct iovec chains[CHAIN_INPUT_COUNT];
unsigned int remainder;
@ -778,6 +797,10 @@ static int DecodePacket(byte* packet, int length, int packetNumber, char err[])
chainSz = length;
#endif
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
XMEMSET(&store, 0, sizeof(store));
#endif
#if defined(DEBUG_SNIFFER)
printf("Packet Number: %d\n", packetNumber);
#endif
@ -807,13 +830,15 @@ static int DecodePacket(byte* packet, int length, int packetNumber, char err[])
#elif defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \
defined(WOLFSSL_SNIFFER_STORE_DATA_CB)
ret = ssl_DecodePacketWithChainSessionInfoStoreData(chain, chainSz,
&data, &sslInfo, err);
&store, &sslInfo, err);
data = store.data;
#elif defined(WOLFSSL_SNIFFER_CHAIN_INPUT)
(void)sslInfo;
ret = ssl_DecodePacketWithChain(chain, chainSz, &data, err);
#elif defined(WOLFSSL_SNIFFER_STORE_DATA_CB)
ret = ssl_DecodePacketWithSessionInfoStoreData(packet,
length, &data, &sslInfo, err);
length, &store, &sslInfo, err);
data = store.data;
#else
ret = ssl_DecodePacketWithSessionInfo(packet, length, &data,
&sslInfo, err);
@ -834,8 +859,7 @@ static int DecodePacket(byte* packet, int length, int packetNumber, char err[])
data[ret] = 0;
printf("SSL App Data(%d:%d):%s\n", packetNumber, ret, data);
ssl_FreeZeroDecodeBuffer(&data, ret, err);
/* Plain store so worker threads do not race on a counter. */
sawDecryptedData = 1;
*sawData = 1;
}
(void)isChain;
@ -874,12 +898,17 @@ static void* snifferWorker(void* arg)
int packetNumber;
#ifdef WOLFSSL_ASYNC_CRYPT
SSLInfo sslInfo;
byte* data;
byte* data = NULL;
int queueSz = 0;
/* poll hardware and attempt to process items in queue. If
* returns > 0 then data pointer has decrypted something */
SnifferAsyncPollQueue(&data, err, &sslInfo, &queueSz);
if (data != NULL) {
/* Recovered here rather than in DecodePacket(), so
* record it. */
worker->sawDecryptedData = 1;
}
if (queueSz >= WOLF_ASYNC_MAX_PENDING) {
/* queue full, poll again */
continue;
@ -909,7 +938,8 @@ static void* snifferWorker(void* arg)
/* Decode Packet, ret value will indicate whether a
* bad packet was encountered */
ret = DecodePacket(packet, length, packetNumber, err);
ret = DecodePacket(packet, length, packetNumber, err,
&worker->sawDecryptedData);
if (ret) {
worker->hadBadPacket = 1;
}
@ -957,6 +987,8 @@ int main(int argc, char** argv)
int hadBadPacket = 0;
int inum = 0;
int saveFile = 0;
int expectData = 0;
int sawDecryptedData = 0;
int i = 0, defDev = 0;
int packetNumber = 0;
int frame = ETHER_IF_FRAME_LEN;
@ -1011,6 +1043,9 @@ int main(int argc, char** argv)
else if (strcmp(argv[i], "-tracefile") == 0 && i + 1 < argc) {
traceFile = argv[++i];
}
else if (strcmp(argv[i], "-expectdata") == 0) {
expectData = 1;
}
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
else if (strcmp(argv[i], "-keylogfile") == 0 && i + 1 < argc) {
sslKeyLogFile = argv[++i];
@ -1034,7 +1069,10 @@ int main(int argc, char** argv)
#if defined(THREADED_SNIFFTEST)
" [-threads threads_arg]"
#endif /* THREADED_SNIFFTEST */
" [-expectdata]"
"\n", argv[0]);
fprintf(stderr, "-expectdata exits non-zero if no application"
" data could be decrypted.\n");
exit(EXIT_FAILURE);
}
}
@ -1301,6 +1339,10 @@ int main(int argc, char** argv)
/* poll hardware and attempt to process items in queue. If returns > 0
* then data pointer has decrypted something */
SnifferAsyncPollQueue(&data, err, &sslInfo, &queueSz);
if (data != NULL) {
/* Recovered here rather than in DecodePacket(), so record it. */
sawDecryptedData = 1;
}
if (queueSz >= WOLF_ASYNC_MAX_PENDING) {
/* queue full, poll again */
continue;
@ -1364,7 +1406,8 @@ int main(int argc, char** argv)
#else
/* Decode Packet, ret value will indicate whether a
* bad packet was encountered */
if (DecodePacket((byte*)packet, header->caplen, packetNumber, err))
if (DecodePacket((byte*)packet, header->caplen, packetNumber, err,
&sawDecryptedData))
hadBadPacket = 1;
#endif
}
@ -1392,15 +1435,20 @@ int main(int argc, char** argv)
if (workers[i].hadBadPacket) {
hadBadPacket = 1;
}
if (workers[i].sawDecryptedData) {
sawDecryptedData = 1;
}
ssl_Free_SnifferWorker(&workers[i]);
}
#endif
FreeAll();
/* A capture file that yields no plaintext has tested nothing. */
if (saveFile && !sawDecryptedData) {
printf("No application data was decrypted from %s\n", pcapFile);
/* Asked for, because a capture that yields no plaintext has tested
* nothing. Off by default so a handshake-only capture still exits 0. */
if (expectData && !sawDecryptedData) {
fprintf(stderr, "No application data was decrypted from %s\n",
saveFile ? pcapFile : "the capture device");
hadBadPacket = 1;
}

View File

@ -144,6 +144,7 @@
#define KEY_MISMATCH_STR 98
#define KEYLOG_FILE_INVALID 99
#define ETM_NOT_SUPPORTED_STR 100
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */

View File

@ -120,4 +120,5 @@ STRINGTABLE
98, "Server Client Key Mismatch"
99, "Invalid or missing keylog file"
100, "Encrypt-Then-MAC not supported in this build"
}