1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00
Files
wolfssl/scripts/pkcallbacks.test
Tobias Frauenschläger f0b78fb9ba Complete a TLS 1.3 handshake with the ECC PK callbacks
myEccKeyGen() generated the key share straight into the library's key object,
and myEccSharedSecret() is handed only the peer's key, so a TLS 1.3 client had
no private key left to reach and every handshake ended with:

  wolfSSL_connect error -170, ECC input argument wrong type, invalid input

TEST_PK_PRIVKEY already kept the key on the application's side, which is what
a real PK-callback application does anyway; it just was not the default. Keep
it whenever the connection is TLS or DTLS v1.3 as well, and have the shared
secret callback pick the key by the same question its key gen asked, not by a
flag key gen has not set yet. The union holding it stops being
TEST_PK_PRIVKEY-only, and its comment stops naming TLS v1.2 as the version
that needs it.

Neither example zeroed its PkCbInfo, so hasKeyGen started as stack garbage.
Only the TEST_PK_PRIVKEY paths read it before, which hid that; zero it in
both.

scripts/pkcallbacks.test only ever ran the build's default version, and that
is TLS v1.2 wherever it is compiled in, so none of the above was covered. Run
the default and then each version the build has.
2026-09-08 18:56:18 +02:00

193 lines
5.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# timeout(1) is GNU coreutils and absent on macOS; where it's missing, run the
# command unbounded (the flaky hang this guards against is Linux-only CI).
# A prefix variable rather than a shell function: backgrounding a function
# makes $! the forked subshell, so a later "kill $server_pid" would stop the
# wrapper and orphan the server it was meant to kill.
if command -v timeout >/dev/null 2>&1; then
TIMEOUT_KILL_2M="timeout -s KILL 2m"
else
TIMEOUT_KILL_2M=""
fi
#pkcallbacks.test
[ ! -x ./examples/client/client ] && printf '\n\n%s\n' "Client doesn't exist" \
&& exit 1
if ./examples/client/client -? 2>&1 | grep "Client not compiled in!" ; then
echo 'skipping pkcallbacks.test because client not compiled in.' 1>&2
exit 77
fi
if ./examples/server/server -? 2>&1 | grep "Server not compiled in!" ; then
echo 'skipping pkcallbacks.test because server not compiled in.' 1>&2
exit 77
fi
# 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
exit_code=1
counter=0
# need a unique resume port since may run the same time as testsuite
# use server port zero hack to get one
pk_port=0
#no_pid tells us process was never started if -1
no_pid=-1
#server_pid captured on startup, stores the id of the server process
server_pid=$no_pid
# let's use absolute path to a local dir (make distcheck may be in sub dir)
# also let's add some randomness by adding pid in case multiple 'make check's
# per source tree
ready_file=`pwd`/wolfssl_pk_ready$$
remove_ready_file() {
if test -e "$ready_file"; then
echo -e "removing existing ready file"
rm "$ready_file"
fi
}
do_cleanup() {
echo "in cleanup"
if [ $server_pid != $no_pid ] && kill -0 $server_pid 2>&-
then
# sleep to give sanitizers time to dump backtraces.
sleep 1
echo "killing server"
kill -9 $server_pid
fi
remove_ready_file
}
# trap this function so if user aborts with ^C or other kill signal we still
# get an exit that will in turn clean up the file system
abort_trap() {
echo "script aborted"
if [ $server_pid != $no_pid ] && kill -0 $server_pid 2>&-
then
# sleep to give sanitizers time to dump backtraces.
sleep 1
echo "killing server"
kill -9 $server_pid
fi
exit_code=2 #different exit code in case of user interrupt
echo "got abort signal, exiting with $exit_code"
exit $exit_code
}
trap abort_trap INT TERM
# trap this function so that if we exit on an error the file system will still
# be restored and the other tests may still pass. Never call this function
# instead use "exit <some value>" and this function will run automatically
restore_file_system() {
remove_ready_file
}
trap restore_file_system EXIT
# $1 is the version flag pair to run with, empty for the build's default.
run_test() {
version_args="$1"
echo -e "\nStarting example server for pkcallbacks test ${version_args:-default}...\n"
# Back to the port zero hack for every run: the previous run left its
# allocated port here, and reusing a now-known port is exactly what the
# hack exists to avoid when another make check is running alongside.
pk_port=0
remove_ready_file
# starts the server on pk_port, -R generates ready file to be used as a
# mutex lock, -P does pkcallbacks. We capture the processid
# into the variable server_pid
$TIMEOUT_KILL_2M ./examples/server/server -P -R "$ready_file" -p $pk_port \
$version_args &
server_pid=$!
counter=0
while [ ! -s "$ready_file" -a "$counter" -lt 20 ]; do
echo -e "waiting for ready file..."
sleep 0.1
counter=$((counter+ 1))
done
if test -e "$ready_file"; then
echo -e "found ready file, starting client..."
else
echo -e "NO ready file ending test..."
exit 1
fi
# sleep for an additional 0.1 to mitigate race on write/read of $ready_file:
sleep 0.1
# get created port 0 ephemeral port
pk_port=`cat "$ready_file"`
# starts client on pk_port with pkcallbacks, captures the output from client
capture_out=$(./examples/client/client -P -p $pk_port $version_args 2>&1)
client_result=$?
if [ $client_result != 0 ]
then
echo -e "client failed!"
echo "$capture_out"
do_cleanup
exit 1
fi
wait $server_pid
server_result=$?
if [ $server_result != 0 ]
then
echo -e "server failed!"
exit 1
fi
}
######### begin program #########
# The build's default version, then each version explicitly. Running only the
# default used to hide that the ECC PK callbacks could not complete a TLS v1.3
# handshake: the default is TLS v1.2 wherever it is compiled in, so the 1.3
# path was never taken here.
run_test ""
if ./examples/client/client -V | grep -q 3; then
run_test "-v 3"
fi
if ./examples/client/client -V | grep -q 4; then
run_test "-v 4"
fi
# If we get to this, success
echo "Success!"
exit 0
########## end program ##########