diff options
Diffstat (limited to '')
-rw-r--r-- | regress/cfginclude.sh | 26 | ||||
-rw-r--r-- | regress/misc/fuzz-harness/Makefile | 44 | ||||
-rw-r--r-- | regress/misc/fuzz-harness/mkcorpus_sntrup761.c | 82 | ||||
-rw-r--r-- | regress/misc/fuzz-harness/sntrup761_dec_fuzz.cc | 74 | ||||
-rw-r--r-- | regress/misc/fuzz-harness/sntrup761_enc_fuzz.cc | 57 | ||||
-rwxr-xr-x | regress/misc/fuzz-harness/watch-sntrup761.sh | 20 | ||||
-rw-r--r-- | regress/multiplex.sh | 29 | ||||
-rw-r--r-- | regress/rekey.sh | 118 | ||||
-rw-r--r-- | regress/unittests/kex/Makefile | 3 | ||||
-rw-r--r-- | regress/unittests/kex/test_kex.c | 6 | ||||
-rw-r--r-- | regress/unittests/sshkey/common.c | 18 | ||||
-rw-r--r-- | regress/unittests/sshkey/test_file.c | 11 | ||||
-rw-r--r-- | regress/unittests/sshkey/test_sshkey.c | 26 | ||||
-rw-r--r-- | regress/unittests/test_helper/fuzz.c | 2 |
14 files changed, 418 insertions, 98 deletions
diff --git a/regress/cfginclude.sh b/regress/cfginclude.sh index f5b492f..d442cdd 100644 --- a/regress/cfginclude.sh +++ b/regress/cfginclude.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cfginclude.sh,v 1.3 2021/06/08 06:52:43 djm Exp $ +# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $ # Placed in the Public Domain. tid="config include" @@ -142,7 +142,7 @@ trial a aa # cleanup rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out -# $OpenBSD: cfginclude.sh,v 1.3 2021/06/08 06:52:43 djm Exp $ +# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $ # Placed in the Public Domain. tid="config include" @@ -289,5 +289,27 @@ _EOF ${REAL_SSH} -F $OBJ/ssh_config.i -G a 2>/dev/null && \ fail "ssh include allowed infinite recursion?" # or hang... +# Environment variable expansion +cat > $OBJ/ssh_config.i << _EOF +Include $OBJ/ssh_config.\${REAL_FILE} +_EOF +cat > $OBJ/ssh_config.i.x << _EOF +Hostname xyzzy +_EOF +REAL_FILE=i.x +export REAL_FILE +trial a xyzzy + +# Environment variable expansion +cat > $OBJ/ssh_config.i << _EOF +Include $OBJ/ssh_config.i.%h%h +_EOF +cat > $OBJ/ssh_config.i.blahblah << _EOF +Hostname mekmitastdigoat +_EOF +REAL_FILE=i.x +export REAL_FILE +trial blah mekmitastdigoat + # cleanup rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out diff --git a/regress/misc/fuzz-harness/Makefile b/regress/misc/fuzz-harness/Makefile index 1072130..55dcc17 100644 --- a/regress/misc/fuzz-harness/Makefile +++ b/regress/misc/fuzz-harness/Makefile @@ -4,52 +4,68 @@ CXX=clang++-16 FUZZ_FLAGS=-fsanitize=address,fuzzer -fno-omit-frame-pointer FUZZ_LIBS=-L/usr/lib/llvm-16/lib -lFuzzer -CXXFLAGS=-O2 -g -Wall -Wextra -Wno-unused-parameter -Wno-exceptions -I ../../.. $(FUZZ_FLAGS) -CFLAGS=$(CXXFLAGS) -LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g $(FUZZ_FLAGS) +CFLAGS=-D_GNU_SOURCE=1 -O2 -g -Wall -Wextra -Wno-unused-parameter -Wno-exceptions -Wno-deprecated -I ../../.. +CXXFLAGS=$(CFLAGS) $(FUZZ_FLAGS) +LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g LIBS=-lssh -lopenbsd-compat -lmd -lcrypto -lfido2 -lcbor $(FUZZ_LIBS) SK_NULL_OBJS=ssh-sk-null.o COMMON_DEPS=../../../libssh.a TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz authkeys_fuzz sshsig_fuzz \ - sshsigopt_fuzz privkey_fuzz kex_fuzz agent_fuzz + sshsigopt_fuzz privkey_fuzz kex_fuzz agent_fuzz \ + mkcorpus_sntrup761 sntrup761_enc_fuzz sntrup761_dec_fuzz all: $(TARGETS) .cc.o: $(CXX) $(CXXFLAGS) -c $< -o $@ +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + pubkey_fuzz: pubkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ pubkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) + $(CXX) -o $@ pubkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) sig_fuzz: sig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ sig_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) + $(CXX) -o $@ sig_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) authopt_fuzz: authopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ authopt_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o $(LDFLAGS) $(LIBS) + $(CXX) -o $@ authopt_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) authkeys_fuzz: authkeys_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ authkeys_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o ../../../auth2-pubkeyfile.o $(LDFLAGS) $(LIBS) + $(CXX) -o $@ authkeys_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o ../../../auth2-pubkeyfile.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) sshsig_fuzz: sshsig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ sshsig_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS) + $(CXX) -o $@ sshsig_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) sshsigopt_fuzz: sshsigopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ sshsigopt_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS) + $(CXX) -o $@ sshsigopt_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) privkey_fuzz: privkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ privkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) + $(CXX) -o $@ privkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) kex_fuzz: kex_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ kex_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) -lz + $(CXX) -o $@ kex_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) -lz agent_fuzz: agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(COMMON_DEPS) - $(CXX) -o $@ agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(LDFLAGS) $(LIBS) -lz + $(CXX) -o $@ agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS) -lz agent_fuzz_helper.o: agent_fuzz_helper.c ../../../ssh-agent.c sk-dummy.o: ../sk-dummy/sk-dummy.c - $(CC) $(CFLAGS) -c -o $@ ../sk-dummy/sk-dummy.c -DSK_DUMMY_INTEGRATE=1 $(LDFLAGS) + $(CC) $(CFLAGS) -c -o $@ ../sk-dummy/sk-dummy.c -DSK_DUMMY_INTEGRATE=1 $(LDFLAGS) $(FUZZ_FLAGS) + +mkcorpus_sntrup761: mkcorpus_sntrup761.o + $(CC) -o $@ mkcorpus_sntrup761.o $(LDFLAGS) -lcrypto + +sntrup761_dec_fuzz: sntrup761_dec_fuzz.o + $(CXX) -o $@ sntrup761_dec_fuzz.o $(LDFLAGS) $(FUZZ_FLAGS) $(FUZZ_LIBS) -lcrypto + +sntrup761_enc_fuzz: sntrup761_enc_fuzz.o + $(CXX) -o $@ sntrup761_enc_fuzz.o $(LDFLAGS) $(FUZZ_FLAGS) $(FUZZ_LIBS) -lcrypto clean: -rm -f *.o $(TARGETS) + +cleandir: clean + diff --git a/regress/misc/fuzz-harness/mkcorpus_sntrup761.c b/regress/misc/fuzz-harness/mkcorpus_sntrup761.c new file mode 100644 index 0000000..86a8e02 --- /dev/null +++ b/regress/misc/fuzz-harness/mkcorpus_sntrup761.c @@ -0,0 +1,82 @@ +// Makes basic seed corpora for other fuzzers +// +// Will write to ./sntrup761_pubkey_corpus (for sntrup761_enc_fuzz) and +// to ./sntrup761_ciphertext_corpus (for sntrup761_dec_fuzz) + +#include <sys/stat.h> +#include <stddef.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <err.h> +#include <errno.h> + +#include "crypto_api.h" +#include "hash.c" + +#undef randombytes +#define USE_SNTRUP761X25519 1 +void randombytes(unsigned char *ptr, size_t l); +volatile crypto_int16 crypto_int16_optblocker = 0; +volatile crypto_int32 crypto_int32_optblocker = 0; +volatile crypto_int64 crypto_int64_optblocker = 0; +#include "sntrup761.c" + +#define NSEEDS 1000 + +static int real_random; + +void +randombytes(unsigned char *ptr, size_t l) +{ + if (real_random) + arc4random_buf(ptr, l); + else + memset(ptr, 0, l); +} + +void write_blob(const char *path, int n, const char *suffix, + const void *ptr, size_t l) +{ + char name[256]; + FILE *f; + + snprintf(name, sizeof(name), "%s/%06d.%s", path, n, suffix); + if ((f = fopen(name, "wb+")) == NULL) + err(1, "fopen %s", name); + if (fwrite(ptr, l, 1, f) != 1) + err(1, "write %s", name); + fclose(f); +} + +int main(void) +{ + int i; + unsigned char pk[crypto_kem_sntrup761_PUBLICKEYBYTES]; + unsigned char sk[crypto_kem_sntrup761_SECRETKEYBYTES]; + unsigned char ciphertext[crypto_kem_sntrup761_CIPHERTEXTBYTES]; + unsigned char secret[crypto_kem_sntrup761_BYTES]; + + if (mkdir("sntrup761_pubkey_corpus", 0777) != 0 && errno != EEXIST) + err(1, "mkdir sntrup761_pubkey_corpus"); + if (mkdir("sntrup761_ciphertext_corpus", 0777) != 0 && errno != EEXIST) + err(1, "mkdir sntrup761_ciphertext_corpus"); + + fprintf(stderr, "making: "); + for (i = 0; i < NSEEDS; i++) { + real_random = i != 0; + if (crypto_kem_sntrup761_keypair(pk, sk) != 0) + errx(1, "crypto_kem_sntrup761_keypair failed"); + write_blob("sntrup761_pubkey_corpus", i, "pk", pk, sizeof(pk)); + if (crypto_kem_sntrup761_enc(ciphertext, secret, pk) != 0) + errx(1, "crypto_kem_sntrup761_enc failed"); + write_blob("sntrup761_ciphertext_corpus", i, "ct", + ciphertext, sizeof(ciphertext)); + if (i % 20 == 0) + fprintf(stderr, "."); + } + fprintf(stderr, "\n"); + return 0; +} diff --git a/regress/misc/fuzz-harness/sntrup761_dec_fuzz.cc b/regress/misc/fuzz-harness/sntrup761_dec_fuzz.cc new file mode 100644 index 0000000..9aecae0 --- /dev/null +++ b/regress/misc/fuzz-harness/sntrup761_dec_fuzz.cc @@ -0,0 +1,74 @@ +// Basic fuzz test for depcapsulate operation, + +#include <stddef.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <err.h> + +extern "C" { + +#include "crypto_api.h" +#include "hash.c" + +#undef randombytes +#define USE_SNTRUP761X25519 1 +#ifdef SNTRUP761_NO_ASM +# undef __GNUC__ +#endif +void randombytes(unsigned char *ptr, size_t l); +volatile crypto_int16 crypto_int16_optblocker = 0; +volatile crypto_int32 crypto_int32_optblocker = 0; +volatile crypto_int64 crypto_int64_optblocker = 0; +#include "sntrup761.c" + +static int real_random; + +void +randombytes(unsigned char *ptr, size_t l) +{ + if (real_random) + arc4random_buf(ptr, l); + else + memset(ptr, 0, l); +} + +void privkeys(unsigned char *zero_sk, unsigned char *rnd_sk) +{ + unsigned char pk[crypto_kem_sntrup761_PUBLICKEYBYTES]; + + real_random = 0; + if (crypto_kem_sntrup761_keypair(pk, zero_sk) != 0) + errx(1, "crypto_kem_sntrup761_keypair failed"); + real_random = 1; + if (crypto_kem_sntrup761_keypair(pk, rnd_sk) != 0) + errx(1, "crypto_kem_sntrup761_keypair failed"); +} + +int LLVMFuzzerTestOneInput(const uint8_t* input, size_t len) +{ + static bool once; + static unsigned char zero_sk[crypto_kem_sntrup761_SECRETKEYBYTES]; + static unsigned char rnd_sk[crypto_kem_sntrup761_SECRETKEYBYTES]; + unsigned char ciphertext[crypto_kem_sntrup761_CIPHERTEXTBYTES]; + unsigned char secret[crypto_kem_sntrup761_BYTES]; + + if (!once) { + privkeys(zero_sk, rnd_sk); + once = true; + } + + memset(&ciphertext, 0, sizeof(ciphertext)); + if (len > sizeof(ciphertext)) { + len = sizeof(ciphertext); + } + memcpy(ciphertext, input, len); + + (void)crypto_kem_sntrup761_dec(secret, ciphertext, zero_sk); + (void)crypto_kem_sntrup761_dec(secret, ciphertext, rnd_sk); + return 0; +} + +} // extern diff --git a/regress/misc/fuzz-harness/sntrup761_enc_fuzz.cc b/regress/misc/fuzz-harness/sntrup761_enc_fuzz.cc new file mode 100644 index 0000000..c4ebac4 --- /dev/null +++ b/regress/misc/fuzz-harness/sntrup761_enc_fuzz.cc @@ -0,0 +1,57 @@ +// Basic fuzz test for encapsulate operation. + +#include <stddef.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <err.h> + +extern "C" { + +#include "crypto_api.h" +#include "hash.c" + +#undef randombytes +#define USE_SNTRUP761X25519 1 +#ifdef SNTRUP761_NO_ASM +# undef __GNUC__ +#endif +void randombytes(unsigned char *ptr, size_t l); +volatile crypto_int16 crypto_int16_optblocker = 0; +volatile crypto_int32 crypto_int32_optblocker = 0; +volatile crypto_int64 crypto_int64_optblocker = 0; +#include "sntrup761.c" + +static int real_random; + +void +randombytes(unsigned char *ptr, size_t l) +{ + if (real_random) + arc4random_buf(ptr, l); + else + memset(ptr, 0, l); +} + +int LLVMFuzzerTestOneInput(const uint8_t* input, size_t len) +{ + unsigned char pk[crypto_kem_sntrup761_PUBLICKEYBYTES]; + unsigned char ciphertext[crypto_kem_sntrup761_CIPHERTEXTBYTES]; + unsigned char secret[crypto_kem_sntrup761_BYTES]; + + memset(&pk, 0, sizeof(pk)); + if (len > sizeof(pk)) { + len = sizeof(pk); + } + memcpy(pk, input, len); + + real_random = 0; + (void)crypto_kem_sntrup761_enc(ciphertext, secret, pk); + real_random = 1; + (void)crypto_kem_sntrup761_enc(ciphertext, secret, pk); + return 0; +} + +} // extern diff --git a/regress/misc/fuzz-harness/watch-sntrup761.sh b/regress/misc/fuzz-harness/watch-sntrup761.sh new file mode 100755 index 0000000..482f831 --- /dev/null +++ b/regress/misc/fuzz-harness/watch-sntrup761.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +set -e +mkdir -p sntrup761_dec_fuzzing sntrup761_enc_fuzzing +(cd sntrup761_enc_fuzzing ; + ../sntrup761_enc_fuzz -jobs=48 ../sntrup761_pubkey_corpus &) +(cd sntrup761_dec_fuzzing ; + ../sntrup761_dec_fuzz -jobs=48 ../sntrup761_ciphertext_corpus &) + +while true ; do + clear + uptime + echo + echo "Findings" + ls -1 sntrup761_dec_fuzzing sntrup761_enc_fuzzing | grep -v '^fuzz-.*log$' + printf "\n\n" + printf "ciphertext_corpus: " ; ls -1 sntrup761_ciphertext_corpus | wc -l + printf " pubkey_corpus: "; ls -1 sntrup761_pubkey_corpus | wc -l + sleep 10; +done diff --git a/regress/multiplex.sh b/regress/multiplex.sh index b992cd4..8274b9d 100644 --- a/regress/multiplex.sh +++ b/regress/multiplex.sh @@ -1,4 +1,4 @@ -# $OpenBSD: multiplex.sh,v 1.36 2023/03/01 09:29:32 dtucker Exp $ +# $OpenBSD: multiplex.sh,v 1.37 2024/07/19 04:33:36 djm Exp $ # Placed in the Public Domain. make_tmpdir @@ -56,19 +56,20 @@ if [ $? -ne 0 ]; then fail "environment not found" fi - -verbose "test $tid: transfer" -rm -f ${COPY} -trace "ssh transfer over multiplexed connection and check result" -${SSH} -F $OBJ/ssh_config -S$CTL otherhost cat ${DATA} > ${COPY} -test -f ${COPY} || fail "ssh -Sctl: failed copy ${DATA}" -cmp ${DATA} ${COPY} || fail "ssh -Sctl: corrupted copy of ${DATA}" - -rm -f ${COPY} -trace "ssh transfer over multiplexed connection and check result" -${SSH} -F $OBJ/ssh_config -S $CTL otherhost cat ${DATA} > ${COPY} -test -f ${COPY} || fail "ssh -S ctl: failed copy ${DATA}" -cmp ${DATA} ${COPY} || fail "ssh -S ctl: corrupted copy of ${DATA}" +for mode in "" "-Oproxy"; do + verbose "test $tid: transfer $mode" + rm -f ${COPY} + trace "ssh transfer over $mode multiplexed connection and check result" + ${SSH} $mode -F $OBJ/ssh_config -S$CTL otherhost cat ${DATA} > ${COPY} + test -f ${COPY} || fail "ssh -Sctl: failed copy ${DATA}" + cmp ${DATA} ${COPY} || fail "ssh -Sctl: corrupted copy of ${DATA}" + + rm -f ${COPY} + trace "ssh transfer over $mode multiplexed connection and check result" + ${SSH} $mode -F $OBJ/ssh_config -S $CTL otherhost cat ${DATA} > ${COPY} + test -f ${COPY} || fail "ssh -S ctl: failed copy ${DATA}" + cmp ${DATA} ${COPY} || fail "ssh -S ctl: corrupted copy of ${DATA}" +done rm -f ${COPY} trace "sftp transfer over multiplexed connection and check result" diff --git a/regress/rekey.sh b/regress/rekey.sh index 8005a86..3f5e1d5 100644 --- a/regress/rekey.sh +++ b/regress/rekey.sh @@ -1,76 +1,114 @@ -# $OpenBSD: rekey.sh,v 1.20 2024/05/22 04:20:00 djm Exp $ +# $OpenBSD: rekey.sh,v 1.30 2024/08/28 12:08:26 djm Exp $ # Placed in the Public Domain. tid="rekey" LOG=${TEST_SSH_LOGFILE} +COPY2=$OBJ/copy2 rm -f ${LOG} cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak +echo "Compression no" >> $OBJ/ssh_proxy +echo "RekeyLimit 256k" >> $OBJ/ssh_proxy +echo "KexAlgorithms curve25519-sha256" >> ssh_proxy + # Test rekeying based on data volume only. -# Arguments will be passed to ssh. +# Arguments: rekeylimit, kex method, optional remaining opts are passed to ssh. ssh_data_rekeying() { + _bytes=$1 ; shift _kexopt=$1 ; shift _opts="$@" + if test -z "$_bytes"; then + _bytes=32k + fi if ! test -z "$_kexopt" ; then cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "$_kexopt" >> $OBJ/sshd_proxy _opts="$_opts -o$_kexopt" fi - rm -f ${COPY} ${LOG} - _opts="$_opts -oCompression=no" - ${SSH} <${DATA} $_opts -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}" + case "$_kexopt" in + MACs=*) + # default chacha20-poly1305 cipher has implicit MAC + _opts="$_opts -oCiphers=aes128-ctr" ;; + esac + trace bytes $_bytes kex $_kexopt opts $_opts + rm -f ${COPY} ${COPY2} ${LOG} + # Create data file just big enough to reach rekey threshold. + dd if=${DATA} of=${COPY} bs=$_bytes count=1 2>/dev/null + ${SSH} <${COPY} $_opts -vv \ + -oRekeyLimit=$_bytes -F $OBJ/ssh_proxy somehost "cat >${COPY2}" if [ $? -ne 0 ]; then fail "ssh failed ($@)" fi - cmp ${DATA} ${COPY} || fail "corrupted copy ($@)" + cmp ${COPY} ${COPY2} || fail "corrupted copy ($@)" n=`grep 'NEWKEYS sent' ${LOG} | wc -l` n=`expr $n - 1` + _want=`echo $_kexopt | cut -f2 -d=` + _got="" + case "$_kexopt" in + KexAlgorithms=*) + _got=`awk '/kex: algorithm: /{print $4}' ${LOG} | \ + tr -d '\r' | sort -u` ;; + Ciphers=*) + _got=`awk '/kex: client->server cipher:/{print $5}' ${LOG} | \ + tr -d '\r' | sort -u` ;; + MACs=*) + _got=`awk '/kex: client->server cipher:/{print $7}' ${LOG} | \ + tr -d '\r' | sort -u` ;; + esac + if [ "$_want" != "$_got" ]; then + fail "unexpected algorithm, want $_want, got $_got" + fi trace "$n rekeying(s)" if [ $n -lt 1 ]; then fail "no rekeying occurred ($@)" fi + cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy } increase_datafile_size 300 opts="" -for i in `${SSH} -Q kex`; do + +# Filter out duplicate curve algo +kexs=`${SSH} -Q kex | grep -v curve25519-sha256@libssh.org` +ciphers=`${SSH} -Q cipher` +macs=`${SSH} -Q mac` + +for i in $kexs; do opts="$opts KexAlgorithms=$i" done -for i in `${SSH} -Q cipher`; do +for i in $ciphers; do opts="$opts Ciphers=$i" done -for i in `${SSH} -Q mac`; do +for i in $macs; do opts="$opts MACs=$i" done for opt in $opts; do verbose "client rekey $opt" - ssh_data_rekeying "$opt" -oRekeyLimit=256k + if ${SSH} -Q cipher-auth | sed 's/^/Ciphers=/' | \ + grep $opt >/dev/null; then + trace AEAD cipher, testing all KexAlgorithms + for kex in $kexs; do + ssh_data_rekeying "" "KexAlgorithms=$kex" "-o$opt" + done + else + ssh_data_rekeying "" "$opt" + fi done -# AEAD ciphers are magical so test with all KexAlgorithms -if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then - for c in `${SSH} -Q cipher-auth`; do - for kex in `${SSH} -Q kex`; do - verbose "client rekey $c $kex" - ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c - done - done -fi - for s in 16 1k 128k 256k; do verbose "client rekeylimit ${s}" - ssh_data_rekeying "" -oCompression=no -oRekeyLimit=$s + ssh_data_rekeying "$s" "" done for s in 5 10; do verbose "client rekeylimit default ${s}" rm -f ${COPY} ${LOG} - ${SSH} < ${DATA} -oCompression=no -oRekeyLimit="default $s" -F \ + ${SSH} < ${DATA} -oRekeyLimit="default $s" -F \ $OBJ/ssh_proxy somehost "cat >${COPY};sleep $s;sleep 10" if [ $? -ne 0 ]; then fail "ssh failed" @@ -87,7 +125,7 @@ done for s in 5 10; do verbose "client rekeylimit default ${s} no data" rm -f ${COPY} ${LOG} - ${SSH} -oCompression=no -oRekeyLimit="default $s" -F \ + ${SSH} -oRekeyLimit="default $s" -F \ $OBJ/ssh_proxy somehost "sleep $s;sleep 10" if [ $? -ne 0 ]; then fail "ssh failed" @@ -104,13 +142,13 @@ for s in 16 1k 128k 256k; do verbose "server rekeylimit ${s}" cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "rekeylimit ${s}" >>$OBJ/sshd_proxy - rm -f ${COPY} ${LOG} - ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "cat ${DATA}" \ - > ${COPY} + rm -f ${COPY} ${COPY2} ${LOG} + dd if=${DATA} of=${COPY} bs=$s count=1 2>/dev/null + ${SSH} -F $OBJ/ssh_proxy somehost "cat ${COPY}" >${COPY2} if [ $? -ne 0 ]; then fail "ssh failed" fi - cmp ${DATA} ${COPY} || fail "corrupted copy" + cmp ${COPY} ${COPY2} || fail "corrupted copy" n=`grep 'NEWKEYS sent' ${LOG} | wc -l` n=`expr $n - 1` trace "$n rekeying(s)" @@ -124,7 +162,7 @@ for s in 5 10; do cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "rekeylimit default ${s}" >>$OBJ/sshd_proxy rm -f ${COPY} ${LOG} - ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "sleep $s;sleep 10" + ${SSH} -F $OBJ/ssh_proxy somehost "sleep $s;sleep 10" if [ $? -ne 0 ]; then fail "ssh failed" fi @@ -136,9 +174,8 @@ for s in 5 10; do fi done -verbose "rekeylimit parsing" +verbose "rekeylimit parsing: bytes" for size in 16 1k 1K 1m 1M 1g 1G 4G 8G; do - for time in 1 1m 1M 1h 1H 1d 1D 1w 1W; do case $size in 16) bytes=16 ;; 1k|1K) bytes=1024 ;; @@ -147,6 +184,15 @@ for size in 16 1k 1K 1m 1M 1g 1G 4G 8G; do 4g|4G) bytes=4294967296 ;; 8g|8G) bytes=8589934592 ;; esac + b=`${SSH} -G -o "rekeylimit $size" -F $OBJ/ssh_proxy host | \ + awk '/rekeylimit/{print $2}'` + if [ "$bytes" != "$b" ]; then + fatal "rekeylimit size: expected $bytes bytes got $b" + fi +done + +verbose "rekeylimit parsing: time" +for time in 1 1m 1M 1h 1H 1d 1D 1w 1W; do case $time in 1) seconds=1 ;; 1m|1M) seconds=60 ;; @@ -154,19 +200,11 @@ for size in 16 1k 1K 1m 1M 1g 1G 4G 8G; do 1d|1D) seconds=86400 ;; 1w|1W) seconds=604800 ;; esac - - b=`$SUDO ${SSHD} -T -o "rekeylimit $size $time" -f $OBJ/sshd_proxy | \ - awk '/rekeylimit/{print $2}'` - s=`$SUDO ${SSHD} -T -o "rekeylimit $size $time" -f $OBJ/sshd_proxy | \ + s=`${SSH} -G -o "rekeylimit default $time" -F $OBJ/ssh_proxy host | \ awk '/rekeylimit/{print $3}'` - - if [ "$bytes" != "$b" ]; then - fatal "rekeylimit size: expected $bytes bytes got $b" - fi if [ "$seconds" != "$s" ]; then fatal "rekeylimit time: expected $time seconds got $s" fi - done done -rm -f ${COPY} ${DATA} +rm -f ${COPY} ${COPY2} ${DATA} diff --git a/regress/unittests/kex/Makefile b/regress/unittests/kex/Makefile index 3c89840..ca4f0ee 100644 --- a/regress/unittests/kex/Makefile +++ b/regress/unittests/kex/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.15 2024/05/19 19:10:01 anton Exp $ +# $OpenBSD: Makefile,v 1.16 2024/09/09 03:13:39 djm Exp $ PROG=test_kex SRCS=tests.c test_kex.c test_proposal.c @@ -25,6 +25,7 @@ SRCS+= kexc25519.c SRCS+= smult_curve25519_ref.c SRCS+= kexgen.c SRCS+= kexsntrup761x25519.c +SRCS+= kexmlkem768x25519.c SRCS+= sntrup761.c SRCS+= utf8.c diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c index b1161ea..caf8f57 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_kex.c,v 1.8 2024/03/25 19:28:09 djm Exp $ */ +/* $OpenBSD: test_kex.c,v 1.9 2024/09/09 03:13:39 djm Exp $ */ /* * Regress test KEX * @@ -153,6 +153,7 @@ do_kex_with_key(char *kex, int keytype, int bits) #endif /* WITH_OPENSSL */ server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server; server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; + server2->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; server2->kex->load_host_public_key = server->kex->load_host_public_key; server2->kex->load_host_private_key = server->kex->load_host_private_key; server2->kex->sign = server->kex->sign; @@ -207,6 +208,9 @@ kex_tests(void) do_kex("diffie-hellman-group-exchange-sha1"); do_kex("diffie-hellman-group14-sha1"); do_kex("diffie-hellman-group1-sha1"); +# ifdef USE_MLKEM768X25519 + do_kex("mlkem768x25519-sha256"); +# endif /* USE_MLKEM768X25519 */ # ifdef USE_SNTRUP761X25519 do_kex("sntrup761x25519-sha512@openssh.com"); # endif /* USE_SNTRUP761X25519 */ diff --git a/regress/unittests/sshkey/common.c b/regress/unittests/sshkey/common.c index 51b0d92..f325c2a 100644 --- a/regress/unittests/sshkey/common.c +++ b/regress/unittests/sshkey/common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: common.c,v 1.5 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: common.c,v 1.6 2024/08/15 00:52:23 djm Exp $ */ /* * Helpers for key API tests * @@ -89,8 +89,8 @@ rsa_n(struct sshkey *k) const BIGNUM *n = NULL; ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->rsa, NULL); - RSA_get0_key(k->rsa, &n, NULL, NULL); + ASSERT_PTR_NE(k->pkey, NULL); + RSA_get0_key(EVP_PKEY_get0_RSA(k->pkey), &n, NULL, NULL); return n; } @@ -100,8 +100,8 @@ rsa_e(struct sshkey *k) const BIGNUM *e = NULL; ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->rsa, NULL); - RSA_get0_key(k->rsa, NULL, &e, NULL); + ASSERT_PTR_NE(k->pkey, NULL); + RSA_get0_key(EVP_PKEY_get0_RSA(k->pkey), NULL, &e, NULL); return e; } @@ -111,8 +111,8 @@ rsa_p(struct sshkey *k) const BIGNUM *p = NULL; ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->rsa, NULL); - RSA_get0_factors(k->rsa, &p, NULL); + ASSERT_PTR_NE(EVP_PKEY_get0_RSA(k->pkey), NULL); + RSA_get0_factors(EVP_PKEY_get0_RSA(k->pkey), &p, NULL); return p; } @@ -122,8 +122,8 @@ rsa_q(struct sshkey *k) const BIGNUM *q = NULL; ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->rsa, NULL); - RSA_get0_factors(k->rsa, NULL, &q); + ASSERT_PTR_NE(EVP_PKEY_get0_RSA(k->pkey), NULL); + RSA_get0_factors(EVP_PKEY_get0_RSA(k->pkey), NULL, &q); return q; } diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c index 4528405..3babe60 100644 --- a/regress/unittests/sshkey/test_file.c +++ b/regress/unittests/sshkey/test_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_file.c,v 1.11 2024/01/11 01:45:58 djm Exp $ */ +/* $OpenBSD: test_file.c,v 1.12 2024/08/15 00:52:23 djm Exp $ */ /* * Regress test for sshkey.h key management API * @@ -271,11 +271,12 @@ sshkey_file_tests(void) #ifndef OPENSSL_IS_BORINGSSL /* lacks EC_POINT_point2bn() */ a = load_bignum("ecdsa_1.param.priv"); b = load_bignum("ecdsa_1.param.pub"); - c = EC_POINT_point2bn(EC_KEY_get0_group(k1->ecdsa), - EC_KEY_get0_public_key(k1->ecdsa), POINT_CONVERSION_UNCOMPRESSED, - NULL, NULL); + c = EC_POINT_point2bn(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(k1->pkey)), + EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(k1->pkey)), + POINT_CONVERSION_UNCOMPRESSED, NULL, NULL); ASSERT_PTR_NE(c, NULL); - ASSERT_BIGNUM_EQ(EC_KEY_get0_private_key(k1->ecdsa), a); + ASSERT_BIGNUM_EQ( + EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(k1->pkey)), a); ASSERT_BIGNUM_EQ(b, c); BN_free(a); BN_free(b); diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c index c1cbb11..5bf4b65 100644 --- a/regress/unittests/sshkey/test_sshkey.c +++ b/regress/unittests/sshkey/test_sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_sshkey.c,v 1.24 2024/01/11 01:45:58 djm Exp $ */ +/* $OpenBSD: test_sshkey.c,v 1.25 2024/08/15 00:52:23 djm Exp $ */ /* * Regress test for sshkey.h key management API * @@ -204,7 +204,7 @@ sshkey_tests(void) TEST_START("new/free KEY_RSA"); k1 = sshkey_new(KEY_RSA); ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(k1->rsa, NULL); + ASSERT_PTR_NE(k1->pkey, NULL); sshkey_free(k1); TEST_DONE(); @@ -221,7 +221,7 @@ sshkey_tests(void) TEST_START("new/free KEY_ECDSA"); k1 = sshkey_new(KEY_ECDSA); ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_EQ(k1->ecdsa, NULL); /* Can't allocate without NID */ + ASSERT_PTR_EQ(k1->pkey, NULL); /* Can't allocate without NID */ sshkey_free(k1); TEST_DONE(); #endif @@ -270,7 +270,7 @@ sshkey_tests(void) SSH_ERR_KEY_LENGTH); ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0); ASSERT_PTR_NE(kr, NULL); - ASSERT_PTR_NE(kr->rsa, NULL); + ASSERT_PTR_NE(EVP_PKEY_get0_RSA(kr->pkey), NULL); ASSERT_PTR_NE(rsa_n(kr), NULL); ASSERT_PTR_NE(rsa_e(kr), NULL); ASSERT_PTR_NE(rsa_p(kr), NULL); @@ -291,9 +291,11 @@ sshkey_tests(void) TEST_START("generate KEY_ECDSA"); ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &ke), 0); ASSERT_PTR_NE(ke, NULL); - ASSERT_PTR_NE(ke->ecdsa, NULL); - ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL); - ASSERT_PTR_NE(EC_KEY_get0_private_key(ke->ecdsa), NULL); + ASSERT_PTR_NE(EVP_PKEY_get0_EC_KEY(ke->pkey), NULL); + ASSERT_PTR_NE(EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(ke->pkey)), + NULL); + ASSERT_PTR_NE(EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(ke->pkey)), + NULL); TEST_DONE(); #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ @@ -312,7 +314,7 @@ sshkey_tests(void) ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(kr, k1); ASSERT_INT_EQ(k1->type, KEY_RSA); - ASSERT_PTR_NE(k1->rsa, NULL); + ASSERT_PTR_NE(EVP_PKEY_get0_RSA(k1->pkey), NULL); ASSERT_PTR_NE(rsa_n(k1), NULL); ASSERT_PTR_NE(rsa_e(k1), NULL); ASSERT_PTR_EQ(rsa_p(k1), NULL); @@ -346,10 +348,12 @@ sshkey_tests(void) ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(ke, k1); ASSERT_INT_EQ(k1->type, KEY_ECDSA); - ASSERT_PTR_NE(k1->ecdsa, NULL); + ASSERT_PTR_NE(EVP_PKEY_get0_EC_KEY(k1->pkey), NULL); ASSERT_INT_EQ(k1->ecdsa_nid, ke->ecdsa_nid); - ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL); - ASSERT_PTR_EQ(EC_KEY_get0_private_key(k1->ecdsa), NULL); + ASSERT_PTR_NE(EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(ke->pkey)), + NULL); + ASSERT_PTR_EQ(EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(k1->pkey)), + NULL); TEST_DONE(); TEST_START("equal KEY_ECDSA/demoted KEY_ECDSA"); diff --git a/regress/unittests/test_helper/fuzz.c b/regress/unittests/test_helper/fuzz.c index 78b3665..9995b26 100644 --- a/regress/unittests/test_helper/fuzz.c +++ b/regress/unittests/test_helper/fuzz.c @@ -214,7 +214,7 @@ siginfo(int unused __attribute__((__unused__))) struct fuzz * fuzz_begin(u_int strategies, const void *p, size_t l) { - struct fuzz *ret = calloc(sizeof(*ret), 1); + struct fuzz *ret = calloc(1, sizeof(*ret)); assert(p != NULL); assert(ret != NULL); |