diff options
Diffstat (limited to 'regress/unittests')
219 files changed, 10632 insertions, 0 deletions
diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile new file mode 100644 index 0000000..e370900 --- /dev/null +++ b/regress/unittests/Makefile @@ -0,0 +1,6 @@ +# $OpenBSD: Makefile,v 1.13 2023/09/24 08:14:13 claudio Exp $ + +SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion +SUBDIR+=authopt misc sshsig + +.include <bsd.subdir.mk> diff --git a/regress/unittests/Makefile.inc b/regress/unittests/Makefile.inc new file mode 100644 index 0000000..623896f --- /dev/null +++ b/regress/unittests/Makefile.inc @@ -0,0 +1,87 @@ +# $OpenBSD: Makefile.inc,v 1.15 2023/09/24 08:14:13 claudio Exp $ + +.include <bsd.own.mk> +.include <bsd.obj.mk> + +# User-settable options +UNITTEST_FAST?= no # Skip slow tests (e.g. less intensive fuzzing). +UNITTEST_SLOW?= no # Include slower tests (e.g. more intensive fuzzing). +UNITTEST_VERBOSE?= no # Verbose test output (inc. per-test names). + +MALLOC_OPTIONS?= CFGJRSUX +TEST_ENV?= MALLOC_OPTIONS=${MALLOC_OPTIONS} + +# XXX detect from ssh binary? +OPENSSL?= yes + +.if (${OPENSSL:L} == "yes") +CFLAGS+= -DWITH_OPENSSL +.endif + +# enable warnings +WARNINGS=Yes + +DEBUG=-g +CFLAGS+= -fstack-protector-all +CDIAGFLAGS= -Wall +CDIAGFLAGS+= -Wextra +CDIAGFLAGS+= -Werror +CDIAGFLAGS+= -Wchar-subscripts +CDIAGFLAGS+= -Wcomment +CDIAGFLAGS+= -Wformat +CDIAGFLAGS+= -Wformat-security +CDIAGFLAGS+= -Wimplicit +CDIAGFLAGS+= -Winline +CDIAGFLAGS+= -Wmissing-declarations +CDIAGFLAGS+= -Wmissing-prototypes +CDIAGFLAGS+= -Wparentheses +CDIAGFLAGS+= -Wpointer-arith +CDIAGFLAGS+= -Wreturn-type +CDIAGFLAGS+= -Wshadow +CDIAGFLAGS+= -Wsign-compare +CDIAGFLAGS+= -Wstrict-aliasing +CDIAGFLAGS+= -Wstrict-prototypes +CDIAGFLAGS+= -Wswitch +CDIAGFLAGS+= -Wtrigraphs +CDIAGFLAGS+= -Wuninitialized +CDIAGFLAGS+= -Wunused +CDIAGFLAGS+= -Wno-unused-parameter +.if ${COMPILER_VERSION:L} != "gcc3" +CDIAGFLAGS+= -Wold-style-definition +.endif + +SSHREL=../../../../../usr.bin/ssh + +CFLAGS+=-I${.CURDIR}/../test_helper -I${.CURDIR}/${SSHREL} + +.if exists(${.CURDIR}/../test_helper/${__objdir}) +LDADD+=-L${.CURDIR}/../test_helper/${__objdir} -ltest_helper +DPADD+=${.CURDIR}/../test_helper/${__objdir}/libtest_helper.a +.else +LDADD+=-L${.CURDIR}/../test_helper -ltest_helper +DPADD+=${.CURDIR}/../test_helper/libtest_helper.a +.endif + +.PATH: ${.CURDIR}/${SSHREL} + +LDADD+= -lutil +DPADD+= ${LIBUTIL} + +.if (${OPENSSL:L} == "yes") +LDADD+= -lcrypto +DPADD+= ${LIBCRYPTO} +.endif + +LDADD+= -lfido2 -lcbor -lusbhid +DPADD+= ${LIBFIDO2} ${LIBCBOR} ${LIBUSBHID} + +UNITTEST_ARGS?= + +.if (${UNITTEST_VERBOSE:L} != "no") +UNITTEST_ARGS+= -v +.endif +.if (${UNITTEST_FAST:L} != "no") +UNITTEST_ARGS+= -f +.elif (${UNITTEST_SLOW:L} != "no") +UNITTEST_ARGS+= -F +.endif diff --git a/regress/unittests/authopt/Makefile b/regress/unittests/authopt/Makefile new file mode 100644 index 0000000..3045ec7 --- /dev/null +++ b/regress/unittests/authopt/Makefile @@ -0,0 +1,27 @@ +# $OpenBSD: Makefile,v 1.7 2023/01/15 23:35:10 djm Exp $ + +PROG=test_authopt +SRCS=tests.c + +SRCS+=auth-options.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c +SRCS+=addr.c addrmatch.c bitmap.c +SRCS+=ed25519.c hash.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c + +SRCS+=digest-openssl.c +#SRCS+=digest-libc.c +SRCS+=utf8.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata + +.include <bsd.regress.mk> diff --git a/regress/unittests/authopt/testdata/all_permit.cert b/regress/unittests/authopt/testdata/all_permit.cert new file mode 100644 index 0000000..38ac573 --- /dev/null +++ b/regress/unittests/authopt/testdata/all_permit.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIOv/h7mJS1WkRHukSvqPwKDiNVrcib/VqBLpbHW6xjWCAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQNe1XDN+J4Eb82TH5J5sYypcabocufjTFRfpU57K+csRP41Yo1FCSEWx95ilUuNvK9Iv3yFDOeVPzdqRqzWoHwE= user key diff --git a/regress/unittests/authopt/testdata/bad_sourceaddr.cert b/regress/unittests/authopt/testdata/bad_sourceaddr.cert new file mode 100644 index 0000000..9732745 --- /dev/null +++ b/regress/unittests/authopt/testdata/bad_sourceaddr.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAILFEJyunlz9scYU3mwbOEJoSSkeO1z20uNBw13tEn+lJAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAHwAAAA5zb3VyY2UtYWRkcmVzcwAAAAkAAAAFeHh4eHgAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEA5xY/OEAJ3tgg8/KJqaBR5KMdYYRDiMJ6u4VKS9lQOV1HJQvDDvjj3F5k53BIqTJRVQx242YWs+B3C4db/uLgB user key diff --git a/regress/unittests/authopt/testdata/force_command.cert b/regress/unittests/authopt/testdata/force_command.cert new file mode 100644 index 0000000..f7af27e --- /dev/null +++ b/regress/unittests/authopt/testdata/force_command.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJkpCeqaVl6qnp7qa90KehAmHFecx3HW8HZQ22KEqeKBAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAHAAAAA1mb3JjZS1jb21tYW5kAAAABwAAAANmb28AAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEAxbhjgbXvfEumRP1E7VH8nUfuJyVlDChhCxiPg9Nvb9PFK8cHdDUEybDCzKCsIDieRc3mtLTyEu7Kb52va/B4C user key diff --git a/regress/unittests/authopt/testdata/host.cert b/regress/unittests/authopt/testdata/host.cert new file mode 100644 index 0000000..6326d04 --- /dev/null +++ b/regress/unittests/authopt/testdata/host.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIFWMw3ftP29RSefnxQwdvK1KiE2G9Y7rPRrJ7ZsrDiOeAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAACAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAKTMqwPkaBg23RS7/aj347dc2kY4bWt/sHwzREYSrKRqZ5RNBnSvZOQ8m5euMCEuf92bZ8VJEdF653jRiW6VoBA== user key diff --git a/regress/unittests/authopt/testdata/mktestdata.sh b/regress/unittests/authopt/testdata/mktestdata.sh new file mode 100644 index 0000000..06a24e3 --- /dev/null +++ b/regress/unittests/authopt/testdata/mktestdata.sh @@ -0,0 +1,48 @@ +#/bin/sh + +set -xe + +rm -f ca_key ca_key.pub +rm -f user_key user_key.pub +rm -f *.cert + +ssh-keygen -q -f ca_key -t ed25519 -C CA -N '' +ssh-keygen -q -f user_key -t ed25519 -C "user key" -N '' + +sign() { + output=$1 + shift + set -xe + ssh-keygen -q -s ca_key -I user -n user \ + -V 19990101:19991231 -z 1 "$@" user_key.pub + mv user_key-cert.pub "$output" +} + +sign all_permit.cert -Opermit-agent-forwarding -Opermit-port-forwarding \ + -Opermit-pty -Opermit-user-rc -Opermit-X11-forwarding +sign no_permit.cert -Oclear + +sign no_agentfwd.cert -Ono-agent-forwarding +sign no_portfwd.cert -Ono-port-forwarding +sign no_pty.cert -Ono-pty +sign no_user_rc.cert -Ono-user-rc +sign no_x11fwd.cert -Ono-X11-forwarding + +sign only_agentfwd.cert -Oclear -Opermit-agent-forwarding +sign only_portfwd.cert -Oclear -Opermit-port-forwarding +sign only_pty.cert -Oclear -Opermit-pty +sign only_user_rc.cert -Oclear -Opermit-user-rc +sign only_x11fwd.cert -Oclear -Opermit-X11-forwarding + +sign force_command.cert -Oforce-command="foo" +sign sourceaddr.cert -Osource-address="127.0.0.1/32,::1/128" + +# ssh-keygen won't permit generation of certs with invalid source-address +# values, so we do it as a custom extension. +sign bad_sourceaddr.cert -Ocritical:source-address=xxxxx + +sign unknown_critical.cert -Ocritical:blah=foo + +sign host.cert -h + +rm -f user_key ca_key user_key.pub ca_key.pub diff --git a/regress/unittests/authopt/testdata/no_agentfwd.cert b/regress/unittests/authopt/testdata/no_agentfwd.cert new file mode 100644 index 0000000..bfa5c2e --- /dev/null +++ b/regress/unittests/authopt/testdata/no_agentfwd.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIL2qEsLCVtKaBkbCrZicxbPUorcHHrQ8yw5h/26krTOlAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGMAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAdRhISpol01OwV30g39PM/JD1t35muskX4lyCcGpFQ08GQtBuHE/hABOp6apbGBJIC7CZYYF+uHkD7PfGU3NPAQ== user key diff --git a/regress/unittests/authopt/testdata/no_permit.cert b/regress/unittests/authopt/testdata/no_permit.cert new file mode 100644 index 0000000..351e138 --- /dev/null +++ b/regress/unittests/authopt/testdata/no_permit.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIGVQtVgp9sD4sc8esIhVWbZaM8d0NxpX3UbEVzTHm9feAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAIKlI0TqqraKjYTjIuKhwoxAV/XnzWRJHq8lNs4aj5yDb84un2xXDF/0vXoLjPgVcLgEbksBKKn0i4whp+xn9Ag== user key diff --git a/regress/unittests/authopt/testdata/no_portfwd.cert b/regress/unittests/authopt/testdata/no_portfwd.cert new file mode 100644 index 0000000..9457dc3 --- /dev/null +++ b/regress/unittests/authopt/testdata/no_portfwd.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIE6gC/QjjuzGWVDkr8ZyaHhja80V+lKLC/MvmEFa+CEBAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGQAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQEzpgckYlfc1BK1ir0reDSXo9OIDx4UoDMrNXrFO6I44NXoJJ4TlUUJH07WcKp/Xp5ESCdyVZtqwgHQxZr0+PwI= user key diff --git a/regress/unittests/authopt/testdata/no_pty.cert b/regress/unittests/authopt/testdata/no_pty.cert new file mode 100644 index 0000000..e8154ec --- /dev/null +++ b/regress/unittests/authopt/testdata/no_pty.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIFFjhISpSDR3blDejuCf2T9Fe4aHW53jG7KOH2PV/E7jAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAHAAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQF5c4BdxVYgqbMGAep414IGFK4deCFBCeNUTOLpKodrfb1M0gS4d2qoeMxZvMv5yMf/viKl/gallHzEmcrEcIQY= user key diff --git a/regress/unittests/authopt/testdata/no_user_rc.cert b/regress/unittests/authopt/testdata/no_user_rc.cert new file mode 100644 index 0000000..6676a0c --- /dev/null +++ b/regress/unittests/authopt/testdata/no_user_rc.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIFUM0VLATkYh05QeS5uuhB1X50NMom3jTWeQUmrPQ1FwAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGwAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAcmJ3c2FCKJL9BCLv1Ij+uN1N+NWZmMXYionsSkv42Go4pMZiH3g8UfTd+OKq9Q7GAcCzGXa///6Dr/wqFssoDA== user key diff --git a/regress/unittests/authopt/testdata/no_x11fwd.cert b/regress/unittests/authopt/testdata/no_x11fwd.cert new file mode 100644 index 0000000..0aff9e6 --- /dev/null +++ b/regress/unittests/authopt/testdata/no_x11fwd.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIPRKPAP+b5S+4zihdgoJrYNcMovFBgKZaJupIhN1kUvkAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAGUAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAECMzj6VDfT+BJmIEo1qUKdr8VDLExF92K7KkbNxTH77n7uip7TL24HDfXjYBCvqxSSn9KAGBhnWsIC/GPx6A+cP user key diff --git a/regress/unittests/authopt/testdata/only_agentfwd.cert b/regress/unittests/authopt/testdata/only_agentfwd.cert new file mode 100644 index 0000000..3cf64b0 --- /dev/null +++ b/regress/unittests/authopt/testdata/only_agentfwd.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIOvJ28yW5uvA7yxE3ySuyFvPjcRYKAr03CYr4okGTNIFAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAB8AAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQEG2uTgmOSk9dJ0s/Ol1EIERXFP9PF6AauF9t5jBMSthNyvSANSrC/1EIaf4TV5kMYfhZxJXoS0XHQjGndcq2AE= user key diff --git a/regress/unittests/authopt/testdata/only_portfwd.cert b/regress/unittests/authopt/testdata/only_portfwd.cert new file mode 100644 index 0000000..bb09c3a --- /dev/null +++ b/regress/unittests/authopt/testdata/only_portfwd.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIGPoYoExiSyHMyDEvOFgoNZXk5z91u7xq/7357X23TotAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAB4AAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABAHN3YnwipcbDKVn+PObGSoaT9rwlau+yrPYZ50oetvCKng3RMjGaV+roqlv0vjjLcxE9J4Y0ti+9MXtQ0D7beBA== user key diff --git a/regress/unittests/authopt/testdata/only_pty.cert b/regress/unittests/authopt/testdata/only_pty.cert new file mode 100644 index 0000000..520c89f --- /dev/null +++ b/regress/unittests/authopt/testdata/only_pty.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAILvocWYto5Lg7P46YLbe7U4/b2h9Lr5rWqMZ4Cj4ra7RAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAABIAAAAKcGVybWl0LXB0eQAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAoVYLMLNBOH1SSgemFuDBprzpDXop6ufRSOo6vtD4mTwAAAFMAAAALc3NoLWVkMjU1MTkAAABASv2xQvp+Y6E8dCf5pzg3MZaan5bl1ToYXNcmQ3ysGrk9Djkcu8m3TytDpF471KmUejxy/iF4xjs9CDpk7h+SBQ== user key diff --git a/regress/unittests/authopt/testdata/only_user_rc.cert b/regress/unittests/authopt/testdata/only_user_rc.cert new file mode 100644 index 0000000..fb49c35 --- /dev/null +++ b/regress/unittests/authopt/testdata/only_user_rc.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJwsRZQ7kx4A8AQ0q/G/3i6sHM48kr4TxJtTcyy3lZAPAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAABYAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgKFWCzCzQTh9UkoHphbgwaa86Q16Kern0UjqOr7Q+Jk8AAABTAAAAC3NzaC1lZDI1NTE5AAAAQDhgEXsvoHr21XrxmiZq/sIjWeYapp11XvEVkkTBPVhBnPwtrrUeJbPmGs3gmJkQdv8BYajYpT7TXEX8GvEeLwU= user key diff --git a/regress/unittests/authopt/testdata/only_x11fwd.cert b/regress/unittests/authopt/testdata/only_x11fwd.cert new file mode 100644 index 0000000..6715585 --- /dev/null +++ b/regress/unittests/authopt/testdata/only_x11fwd.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIDAhZFZBl3eu8Qa8I5BaHCz/mpH8xCjaPusBwo1eJ9OGAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAAAAAAB0AAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDysfgbhniX/zdA8576rrDJpaO2D7QtQse2KWIM9XmREPkLKeP6FKiXKKFcPQiMyV28rptfvK8bBXAiOvITSUgL user key diff --git a/regress/unittests/authopt/testdata/sourceaddr.cert b/regress/unittests/authopt/testdata/sourceaddr.cert new file mode 100644 index 0000000..0fcf7b1 --- /dev/null +++ b/regress/unittests/authopt/testdata/sourceaddr.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJ54qqoPs87gtjN1aJoLUn7ZTYUtcaGxkzLyJvRkYG7nAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAALgAAAA5zb3VyY2UtYWRkcmVzcwAAABgAAAAUMTI3LjAuMC4xLzMyLDo6MS8xMjgAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEAppSUKQ/a9tw/HgIazWceCO3d48GU7mkV4iQMpWWs2nB1dFryY1GDtZrBggAjMviwmBXyM3jIk5vxJDINZXGQJ user key diff --git a/regress/unittests/authopt/testdata/unknown_critical.cert b/regress/unittests/authopt/testdata/unknown_critical.cert new file mode 100644 index 0000000..216960a --- /dev/null +++ b/regress/unittests/authopt/testdata/unknown_critical.cert @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIIjs/wRAB/p5QShSfqoU9cWnCLT3lSveUirk61A27KxVAAAAICeF4LbtRqwIRhewXifa5PKpbSU9P/K8CzeVYj8J/iBoAAAAAAAAAAEAAAABAAAABHVzZXIAAAAIAAAABHVzZXIAAAAANouDYAAAAAA4a2VgAAAAEwAAAARibGFoAAAABwAAAANmb28AAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIChVgsws0E4fVJKB6YW4MGmvOkNeinq59FI6jq+0PiZPAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDix3FV7JIBuHNAwtZOVIqGBq8lqhnEwP51DqPA43qt+Tzynm56EWxuFzgGehBPF3L8gl+fVqxIJmiQ9iHB0LUD user key diff --git a/regress/unittests/authopt/tests.c b/regress/unittests/authopt/tests.c new file mode 100644 index 0000000..d9e1903 --- /dev/null +++ b/regress/unittests/authopt/tests.c @@ -0,0 +1,578 @@ +/* $OpenBSD: tests.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ + +/* + * Regress test for keys options functions. + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "sshkey.h" +#include "authfile.h" +#include "auth-options.h" +#include "misc.h" +#include "log.h" + +static struct sshkey * +load_key(const char *name) +{ + struct sshkey *ret; + int r; + + r = sshkey_load_public(test_data_file(name), &ret, NULL); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(ret, NULL); + return ret; +} + +static struct sshauthopt * +default_authkey_opts(void) +{ + struct sshauthopt *ret = sshauthopt_new(); + + ASSERT_PTR_NE(ret, NULL); + ret->permit_port_forwarding_flag = 1; + ret->permit_agent_forwarding_flag = 1; + ret->permit_x11_forwarding_flag = 1; + ret->permit_pty_flag = 1; + ret->permit_user_rc = 1; + return ret; +} + +static struct sshauthopt * +default_authkey_restrict_opts(void) +{ + struct sshauthopt *ret = sshauthopt_new(); + + ASSERT_PTR_NE(ret, NULL); + ret->permit_port_forwarding_flag = 0; + ret->permit_agent_forwarding_flag = 0; + ret->permit_x11_forwarding_flag = 0; + ret->permit_pty_flag = 0; + ret->permit_user_rc = 0; + ret->restricted = 1; + return ret; +} + +static char ** +commasplit(const char *s, size_t *np) +{ + char *ocp, *cp, *cp2, **ret = NULL; + size_t n; + + ocp = cp = strdup(s); + ASSERT_PTR_NE(cp, NULL); + for (n = 0; (cp2 = strsep(&cp, ",")) != NULL;) { + ret = recallocarray(ret, n, n + 1, sizeof(*ret)); + ASSERT_PTR_NE(ret, NULL); + cp2 = strdup(cp2); + ASSERT_PTR_NE(cp2, NULL); + ret[n++] = cp2; + } + free(ocp); + *np = n; + return ret; +} + +static void +compare_opts(const struct sshauthopt *opts, + const struct sshauthopt *expected) +{ + size_t i; + + ASSERT_PTR_NE(opts, NULL); + ASSERT_PTR_NE(expected, NULL); + ASSERT_PTR_NE(expected, opts); /* bozo :) */ + +#define FLAG_EQ(x) ASSERT_INT_EQ(opts->x, expected->x) + FLAG_EQ(permit_port_forwarding_flag); + FLAG_EQ(permit_agent_forwarding_flag); + FLAG_EQ(permit_x11_forwarding_flag); + FLAG_EQ(permit_pty_flag); + FLAG_EQ(permit_user_rc); + FLAG_EQ(restricted); + FLAG_EQ(cert_authority); +#undef FLAG_EQ + +#define STR_EQ(x) \ + do { \ + if (expected->x == NULL) \ + ASSERT_PTR_EQ(opts->x, expected->x); \ + else \ + ASSERT_STRING_EQ(opts->x, expected->x); \ + } while (0) + STR_EQ(cert_principals); + STR_EQ(force_command); + STR_EQ(required_from_host_cert); + STR_EQ(required_from_host_keys); +#undef STR_EQ + +#define ARRAY_EQ(nx, x) \ + do { \ + ASSERT_SIZE_T_EQ(opts->nx, expected->nx); \ + if (expected->nx == 0) \ + break; \ + for (i = 0; i < expected->nx; i++) \ + ASSERT_STRING_EQ(opts->x[i], expected->x[i]); \ + } while (0) + ARRAY_EQ(nenv, env); + ARRAY_EQ(npermitopen, permitopen); +#undef ARRAY_EQ +} + +static void +test_authkeys_parse(void) +{ + struct sshauthopt *opts, *expected; + const char *errstr; + +#define FAIL_TEST(label, keywords) \ + do { \ + TEST_START("sshauthopt_parse invalid " label); \ + opts = sshauthopt_parse(keywords, &errstr); \ + ASSERT_PTR_EQ(opts, NULL); \ + ASSERT_PTR_NE(errstr, NULL); \ + TEST_DONE(); \ + } while (0) +#define CHECK_SUCCESS_AND_CLEANUP() \ + do { \ + if (errstr != NULL) \ + ASSERT_STRING_EQ(errstr, ""); \ + compare_opts(opts, expected); \ + sshauthopt_free(expected); \ + sshauthopt_free(opts); \ + } while (0) + + /* Basic tests */ + TEST_START("sshauthopt_parse empty"); + expected = default_authkey_opts(); + opts = sshauthopt_parse("", &errstr); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + TEST_START("sshauthopt_parse trailing whitespace"); + expected = default_authkey_opts(); + opts = sshauthopt_parse(" ", &errstr); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + TEST_START("sshauthopt_parse restrict"); + expected = default_authkey_restrict_opts(); + opts = sshauthopt_parse("restrict", &errstr); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + /* Invalid syntax */ + FAIL_TEST("trailing comma", "restrict,"); + FAIL_TEST("bare comma", ","); + FAIL_TEST("unknown option", "BLAH"); + FAIL_TEST("unknown option with trailing comma", "BLAH,"); + FAIL_TEST("unknown option with trailing whitespace", "BLAH "); + + /* force_tun_device */ + TEST_START("sshauthopt_parse tunnel explicit"); + expected = default_authkey_opts(); + expected->force_tun_device = 1; + opts = sshauthopt_parse("tunnel=\"1\"", &errstr); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + TEST_START("sshauthopt_parse tunnel any"); + expected = default_authkey_opts(); + expected->force_tun_device = SSH_TUNID_ANY; + opts = sshauthopt_parse("tunnel=\"any\"", &errstr); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + FAIL_TEST("tunnel", "tunnel=\"blah\""); + + /* Flag options */ +#define FLAG_TEST(keyword, var, val) \ + do { \ + TEST_START("sshauthopt_parse " keyword); \ + expected = default_authkey_opts(); \ + expected->var = val; \ + opts = sshauthopt_parse(keyword, &errstr); \ + CHECK_SUCCESS_AND_CLEANUP(); \ + expected = default_authkey_restrict_opts(); \ + expected->var = val; \ + opts = sshauthopt_parse("restrict,"keyword, &errstr); \ + CHECK_SUCCESS_AND_CLEANUP(); \ + TEST_DONE(); \ + } while (0) + /* Positive flags */ + FLAG_TEST("cert-authority", cert_authority, 1); + FLAG_TEST("port-forwarding", permit_port_forwarding_flag, 1); + FLAG_TEST("agent-forwarding", permit_agent_forwarding_flag, 1); + FLAG_TEST("x11-forwarding", permit_x11_forwarding_flag, 1); + FLAG_TEST("pty", permit_pty_flag, 1); + FLAG_TEST("user-rc", permit_user_rc, 1); + /* Negative flags */ + FLAG_TEST("no-port-forwarding", permit_port_forwarding_flag, 0); + FLAG_TEST("no-agent-forwarding", permit_agent_forwarding_flag, 0); + FLAG_TEST("no-x11-forwarding", permit_x11_forwarding_flag, 0); + FLAG_TEST("no-pty", permit_pty_flag, 0); + FLAG_TEST("no-user-rc", permit_user_rc, 0); +#undef FLAG_TEST + FAIL_TEST("no-cert-authority", "no-cert-authority"); + + /* String options */ +#define STRING_TEST(keyword, var, val) \ + do { \ + TEST_START("sshauthopt_parse " keyword); \ + expected = default_authkey_opts(); \ + expected->var = strdup(val); \ + ASSERT_PTR_NE(expected->var, NULL); \ + opts = sshauthopt_parse(keyword "=" #val, &errstr); \ + CHECK_SUCCESS_AND_CLEANUP(); \ + expected = default_authkey_restrict_opts(); \ + expected->var = strdup(val); \ + ASSERT_PTR_NE(expected->var, NULL); \ + opts = sshauthopt_parse( \ + "restrict," keyword "=" #val ",restrict", &errstr); \ + CHECK_SUCCESS_AND_CLEANUP(); \ + TEST_DONE(); \ + } while (0) + STRING_TEST("command", force_command, "/bin/true"); + STRING_TEST("principals", cert_principals, "gregor,josef,K"); + STRING_TEST("from", required_from_host_keys, "127.0.0.0/8"); +#undef STRING_TEST + FAIL_TEST("unquoted command", "command=oops"); + FAIL_TEST("unquoted principals", "principals=estragon"); + FAIL_TEST("unquoted from", "from=127.0.0.1"); + + /* String array option tests */ +#define ARRAY_TEST(label, keywords, var, nvar, val) \ + do { \ + TEST_START("sshauthopt_parse " label); \ + expected = default_authkey_opts(); \ + expected->var = commasplit(val, &expected->nvar); \ + ASSERT_PTR_NE(expected->var, NULL); \ + opts = sshauthopt_parse(keywords, &errstr); \ + CHECK_SUCCESS_AND_CLEANUP(); \ + expected = default_authkey_restrict_opts(); \ + expected->var = commasplit(val, &expected->nvar); \ + ASSERT_PTR_NE(expected->var, NULL); \ + opts = sshauthopt_parse( \ + "restrict," keywords ",restrict", &errstr); \ + CHECK_SUCCESS_AND_CLEANUP(); \ + TEST_DONE(); \ + } while (0) + ARRAY_TEST("environment", "environment=\"foo=1\",environment=\"bar=2\"", + env, nenv, "foo=1,bar=2"); + ARRAY_TEST("environment", "environment=\"foo=1\",environment=\"foo=2\"", + env, nenv, "foo=1"); + ARRAY_TEST("permitopen", "permitopen=\"foo:123\",permitopen=\"bar:*\"", + permitopen, npermitopen, "foo:123,bar:*"); +#undef ARRAY_TEST + FAIL_TEST("environment", "environment=\",=bah\""); + FAIL_TEST("permitopen port", "foo:bar"); + FAIL_TEST("permitopen missing port", "foo:"); + FAIL_TEST("permitopen missing port specification", "foo"); + FAIL_TEST("permitopen invalid host", "[:"); + +#undef CHECK_SUCCESS_AND_CLEANUP +#undef FAIL_TEST +} + +static void +test_cert_parse(void) +{ + struct sshkey *cert; + struct sshauthopt *opts, *expected; + +#define CHECK_SUCCESS_AND_CLEANUP() \ + do { \ + compare_opts(opts, expected); \ + sshauthopt_free(expected); \ + sshauthopt_free(opts); \ + sshkey_free(cert); \ + } while (0) +#define FLAG_TEST(keybase, var) \ + do { \ + TEST_START("sshauthopt_from_cert no_" keybase); \ + cert = load_key("no_" keybase ".cert"); \ + expected = default_authkey_opts(); \ + expected->var = 0; \ + opts = sshauthopt_from_cert(cert); \ + CHECK_SUCCESS_AND_CLEANUP(); \ + TEST_DONE(); \ + TEST_START("sshauthopt_from_cert only_" keybase); \ + cert = load_key("only_" keybase ".cert"); \ + expected = sshauthopt_new(); \ + ASSERT_PTR_NE(expected, NULL); \ + expected->var = 1; \ + opts = sshauthopt_from_cert(cert); \ + CHECK_SUCCESS_AND_CLEANUP(); \ + TEST_DONE(); \ + } while (0) + FLAG_TEST("agentfwd", permit_agent_forwarding_flag); + FLAG_TEST("portfwd", permit_port_forwarding_flag); + FLAG_TEST("pty", permit_pty_flag); + FLAG_TEST("user_rc", permit_user_rc); + FLAG_TEST("x11fwd", permit_x11_forwarding_flag); +#undef FLAG_TEST + + TEST_START("sshauthopt_from_cert all permitted"); + cert = load_key("all_permit.cert"); + expected = default_authkey_opts(); + opts = sshauthopt_from_cert(cert); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + TEST_START("sshauthopt_from_cert nothing permitted"); + cert = load_key("no_permit.cert"); + expected = sshauthopt_new(); + ASSERT_PTR_NE(expected, NULL); + opts = sshauthopt_from_cert(cert); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + TEST_START("sshauthopt_from_cert force-command"); + cert = load_key("force_command.cert"); + expected = default_authkey_opts(); + expected->force_command = strdup("foo"); + ASSERT_PTR_NE(expected->force_command, NULL); + opts = sshauthopt_from_cert(cert); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + TEST_START("sshauthopt_from_cert source-address"); + cert = load_key("sourceaddr.cert"); + expected = default_authkey_opts(); + expected->required_from_host_cert = strdup("127.0.0.1/32,::1/128"); + ASSERT_PTR_NE(expected->required_from_host_cert, NULL); + opts = sshauthopt_from_cert(cert); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); +#undef CHECK_SUCCESS_AND_CLEANUP + +#define FAIL_TEST(keybase) \ + do { \ + TEST_START("sshauthopt_from_cert " keybase); \ + cert = load_key(keybase ".cert"); \ + opts = sshauthopt_from_cert(cert); \ + ASSERT_PTR_EQ(opts, NULL); \ + sshkey_free(cert); \ + TEST_DONE(); \ + } while (0) + FAIL_TEST("host"); + FAIL_TEST("bad_sourceaddr"); + FAIL_TEST("unknown_critical"); +#undef FAIL_TEST +} + +static void +test_merge(void) +{ + struct sshkey *cert; + struct sshauthopt *key_opts, *cert_opts, *merge_opts, *expected; + const char *errstr; + + /* + * Prepare for a test by making some key and cert options and + * attempting to merge them. + */ +#define PREPARE(label, keyname, keywords) \ + do { \ + expected = NULL; \ + TEST_START("sshauthopt_merge " label); \ + cert = load_key(keyname ".cert"); \ + cert_opts = sshauthopt_from_cert(cert); \ + ASSERT_PTR_NE(cert_opts, NULL); \ + key_opts = sshauthopt_parse(keywords, &errstr); \ + if (errstr != NULL) \ + ASSERT_STRING_EQ(errstr, ""); \ + ASSERT_PTR_NE(key_opts, NULL); \ + merge_opts = sshauthopt_merge(key_opts, \ + cert_opts, &errstr); \ + } while (0) + + /* Cleanup stuff allocated by PREPARE() */ +#define CLEANUP() \ + do { \ + sshauthopt_free(expected); \ + sshauthopt_free(merge_opts); \ + sshauthopt_free(key_opts); \ + sshauthopt_free(cert_opts); \ + sshkey_free(cert); \ + } while (0) + + /* Check the results of PREPARE() against expectation; calls CLEANUP */ +#define CHECK_SUCCESS_AND_CLEANUP() \ + do { \ + if (errstr != NULL) \ + ASSERT_STRING_EQ(errstr, ""); \ + compare_opts(merge_opts, expected); \ + CLEANUP(); \ + } while (0) + + /* Check a single case of merging of flag options */ +#define FLAG_CASE(keybase, label, keyname, keywords, mostly_off, var, val) \ + do { \ + PREPARE(keybase " " label, keyname, keywords); \ + expected = mostly_off ? \ + sshauthopt_new() : default_authkey_opts(); \ + expected->var = val; \ + ASSERT_PTR_NE(expected, NULL); \ + CHECK_SUCCESS_AND_CLEANUP(); \ + TEST_DONE(); \ + } while (0) + + /* + * Fairly exhaustive exercise of a flag option. Tests + * option both set and clear in certificate, set and clear in + * authorized_keys and set and cleared via restrict keyword. + */ +#define FLAG_TEST(keybase, keyword, var) \ + do { \ + FLAG_CASE(keybase, "keys:default,yes cert:default,no", \ + "no_" keybase, keyword, 0, var, 0); \ + FLAG_CASE(keybase,"keys:-*,yes cert:default,no", \ + "no_" keybase, "restrict," keyword, 1, var, 0); \ + FLAG_CASE(keybase, "keys:default,no cert:default,no", \ + "no_" keybase, "no-" keyword, 0, var, 0); \ + FLAG_CASE(keybase, "keys:-*,no cert:default,no", \ + "no_" keybase, "restrict,no-" keyword, 1, var, 0); \ + \ + FLAG_CASE(keybase, "keys:default,yes cert:-*,yes", \ + "only_" keybase, keyword, 1, var, 1); \ + FLAG_CASE(keybase,"keys:-*,yes cert:-*,yes", \ + "only_" keybase, "restrict," keyword, 1, var, 1); \ + FLAG_CASE(keybase, "keys:default,no cert:-*,yes", \ + "only_" keybase, "no-" keyword, 1, var, 0); \ + FLAG_CASE(keybase, "keys:-*,no cert:-*,yes", \ + "only_" keybase, "restrict,no-" keyword, 1, var, 0); \ + \ + FLAG_CASE(keybase, "keys:default,yes cert:-*", \ + "no_permit", keyword, 1, var, 0); \ + FLAG_CASE(keybase,"keys:-*,yes cert:-*", \ + "no_permit", "restrict," keyword, 1, var, 0); \ + FLAG_CASE(keybase, "keys:default,no cert:-*", \ + "no_permit", "no-" keyword, 1, var, 0); \ + FLAG_CASE(keybase, "keys:-*,no cert:-*", \ + "no_permit", "restrict,no-" keyword, 1, var, 0); \ + \ + FLAG_CASE(keybase, "keys:default,yes cert:*", \ + "all_permit", keyword, 0, var, 1); \ + FLAG_CASE(keybase,"keys:-*,yes cert:*", \ + "all_permit", "restrict," keyword, 1, var, 1); \ + FLAG_CASE(keybase, "keys:default,no cert:*", \ + "all_permit", "no-" keyword, 0, var, 0); \ + FLAG_CASE(keybase, "keys:-*,no cert:*", \ + "all_permit", "restrict,no-" keyword, 1, var, 0); \ + \ + } while (0) + FLAG_TEST("portfwd", "port-forwarding", permit_port_forwarding_flag); + FLAG_TEST("agentfwd", "agent-forwarding", permit_agent_forwarding_flag); + FLAG_TEST("pty", "pty", permit_pty_flag); + FLAG_TEST("user_rc", "user-rc", permit_user_rc); + FLAG_TEST("x11fwd", "x11-forwarding", permit_x11_forwarding_flag); +#undef FLAG_TEST + + PREPARE("source-address both", "sourceaddr", "from=\"127.0.0.1\""); + expected = default_authkey_opts(); + expected->required_from_host_cert = strdup("127.0.0.1/32,::1/128"); + ASSERT_PTR_NE(expected->required_from_host_cert, NULL); + expected->required_from_host_keys = strdup("127.0.0.1"); + ASSERT_PTR_NE(expected->required_from_host_keys, NULL); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("source-address none", "all_permit", ""); + expected = default_authkey_opts(); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("source-address keys", "all_permit", "from=\"127.0.0.1\""); + expected = default_authkey_opts(); + expected->required_from_host_keys = strdup("127.0.0.1"); + ASSERT_PTR_NE(expected->required_from_host_keys, NULL); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("source-address cert", "sourceaddr", ""); + expected = default_authkey_opts(); + expected->required_from_host_cert = strdup("127.0.0.1/32,::1/128"); + ASSERT_PTR_NE(expected->required_from_host_cert, NULL); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("force-command both", "force_command", "command=\"foo\""); + expected = default_authkey_opts(); + expected->force_command = strdup("foo"); + ASSERT_PTR_NE(expected->force_command, NULL); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("force-command none", "all_permit", ""); + expected = default_authkey_opts(); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("force-command keys", "all_permit", "command=\"bar\""); + expected = default_authkey_opts(); + expected->force_command = strdup("bar"); + ASSERT_PTR_NE(expected->force_command, NULL); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("force-command cert", "force_command", ""); + expected = default_authkey_opts(); + expected->force_command = strdup("foo"); + ASSERT_PTR_NE(expected->force_command, NULL); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("force-command mismatch", "force_command", "command=\"bar\""); + ASSERT_PTR_EQ(merge_opts, NULL); + CLEANUP(); + TEST_DONE(); + + PREPARE("tunnel", "all_permit", "tunnel=\"6\""); + expected = default_authkey_opts(); + expected->force_tun_device = 6; + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("permitopen", "all_permit", + "permitopen=\"127.0.0.1:*\",permitopen=\"127.0.0.1:123\""); + expected = default_authkey_opts(); + expected->permitopen = commasplit("127.0.0.1:*,127.0.0.1:123", + &expected->npermitopen); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); + + PREPARE("environment", "all_permit", + "environment=\"foo=a\",environment=\"bar=b\""); + expected = default_authkey_opts(); + expected->env = commasplit("foo=a,bar=b", &expected->nenv); + CHECK_SUCCESS_AND_CLEANUP(); + TEST_DONE(); +} + +void +tests(void) +{ + extern char *__progname; + LogLevel ll = test_is_verbose() ? + SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_QUIET; + + /* test_cert_parse() are a bit spammy to error() by default... */ + log_init(__progname, ll, SYSLOG_FACILITY_USER, 1); + + test_authkeys_parse(); + test_cert_parse(); + test_merge(); +} diff --git a/regress/unittests/bitmap/Makefile b/regress/unittests/bitmap/Makefile new file mode 100644 index 0000000..fe30acc --- /dev/null +++ b/regress/unittests/bitmap/Makefile @@ -0,0 +1,14 @@ +# $OpenBSD: Makefile,v 1.4 2017/12/21 00:41:22 djm Exp $ + +PROG=test_bitmap +SRCS=tests.c + +# From usr.sbin/ssh +SRCS+=bitmap.c atomicio.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} + +.include <bsd.regress.mk> diff --git a/regress/unittests/bitmap/tests.c b/regress/unittests/bitmap/tests.c new file mode 100644 index 0000000..576b863 --- /dev/null +++ b/regress/unittests/bitmap/tests.c @@ -0,0 +1,138 @@ +/* $OpenBSD: tests.c,v 1.2 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for bitmap.h bitmap API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#endif + +#include "../test_helper/test_helper.h" + +#include "bitmap.h" + +#define NTESTS 131 + +void +tests(void) +{ +#ifdef WITH_OPENSSL + struct bitmap *b; + BIGNUM *bn; + size_t len; + int i, j, k, n; + u_char bbuf[1024], bnbuf[1024]; + int r; + + TEST_START("bitmap_new"); + b = bitmap_new(); + ASSERT_PTR_NE(b, NULL); + bn = BN_new(); + ASSERT_PTR_NE(bn, NULL); + TEST_DONE(); + + TEST_START("bitmap_set_bit / bitmap_test_bit"); + for (i = -1; i < NTESTS; i++) { + for (j = -1; j < NTESTS; j++) { + for (k = -1; k < NTESTS; k++) { + bitmap_zero(b); + BN_clear(bn); + + test_subtest_info("set %d/%d/%d", i, j, k); + /* Set bits */ + if (i >= 0) { + ASSERT_INT_EQ(bitmap_set_bit(b, i), 0); + ASSERT_INT_EQ(BN_set_bit(bn, i), 1); + } + if (j >= 0) { + ASSERT_INT_EQ(bitmap_set_bit(b, j), 0); + ASSERT_INT_EQ(BN_set_bit(bn, j), 1); + } + if (k >= 0) { + ASSERT_INT_EQ(bitmap_set_bit(b, k), 0); + ASSERT_INT_EQ(BN_set_bit(bn, k), 1); + } + + /* Check perfect match between bitmap and bn */ + test_subtest_info("match %d/%d/%d", i, j, k); + for (n = 0; n < NTESTS; n++) { + ASSERT_INT_EQ(BN_is_bit_set(bn, n), + bitmap_test_bit(b, n)); + } + + /* Test length calculations */ + test_subtest_info("length %d/%d/%d", i, j, k); + ASSERT_INT_EQ(BN_num_bits(bn), + (int)bitmap_nbits(b)); + ASSERT_INT_EQ(BN_num_bytes(bn), + (int)bitmap_nbytes(b)); + + /* Test serialisation */ + test_subtest_info("serialise %d/%d/%d", + i, j, k); + len = bitmap_nbytes(b); + memset(bbuf, 0xfc, sizeof(bbuf)); + ASSERT_INT_EQ(bitmap_to_string(b, bbuf, + sizeof(bbuf)), 0); + for (n = len; n < (int)sizeof(bbuf); n++) + ASSERT_U8_EQ(bbuf[n], 0xfc); + r = BN_bn2bin(bn, bnbuf); + ASSERT_INT_GE(r, 0); + ASSERT_INT_EQ(r, (int)len); + ASSERT_MEM_EQ(bbuf, bnbuf, len); + + /* Test deserialisation */ + test_subtest_info("deserialise %d/%d/%d", + i, j, k); + bitmap_zero(b); + ASSERT_INT_EQ(bitmap_from_string(b, bnbuf, + len), 0); + for (n = 0; n < NTESTS; n++) { + ASSERT_INT_EQ(BN_is_bit_set(bn, n), + bitmap_test_bit(b, n)); + } + + /* Test clearing bits */ + test_subtest_info("clear %d/%d/%d", + i, j, k); + for (n = 0; n < NTESTS; n++) { + ASSERT_INT_EQ(bitmap_set_bit(b, n), 0); + ASSERT_INT_EQ(BN_set_bit(bn, n), 1); + } + if (i >= 0) { + bitmap_clear_bit(b, i); + BN_clear_bit(bn, i); + } + if (j >= 0) { + bitmap_clear_bit(b, j); + BN_clear_bit(bn, j); + } + if (k >= 0) { + bitmap_clear_bit(b, k); + BN_clear_bit(bn, k); + } + for (n = 0; n < NTESTS; n++) { + ASSERT_INT_EQ(BN_is_bit_set(bn, n), + bitmap_test_bit(b, n)); + } + } + } + } + bitmap_free(b); + BN_free(bn); + TEST_DONE(); +#endif +} + diff --git a/regress/unittests/conversion/Makefile b/regress/unittests/conversion/Makefile new file mode 100644 index 0000000..5793c49 --- /dev/null +++ b/regress/unittests/conversion/Makefile @@ -0,0 +1,16 @@ +# $OpenBSD: Makefile,v 1.4 2021/01/09 12:24:30 dtucker Exp $ + +PROG=test_conversion +SRCS=tests.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=atomicio.c misc.c xmalloc.c log.c uidswap.c cleanup.c fatal.c ssherr.c +SRCS+=match.c addr.c addrmatch.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} + +.include <bsd.regress.mk> diff --git a/regress/unittests/conversion/tests.c b/regress/unittests/conversion/tests.c new file mode 100644 index 0000000..5b526f7 --- /dev/null +++ b/regress/unittests/conversion/tests.c @@ -0,0 +1,52 @@ +/* $OpenBSD: tests.c,v 1.4 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for conversions + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "misc.h" + +void +tests(void) +{ + char buf[1024]; + + TEST_START("conversion_convtime"); + ASSERT_INT_EQ(convtime("0"), 0); + ASSERT_INT_EQ(convtime("1"), 1); + ASSERT_INT_EQ(convtime("1S"), 1); + /* from the examples in the comment above the function */ + ASSERT_INT_EQ(convtime("90m"), 5400); + ASSERT_INT_EQ(convtime("1h30m"), 5400); + ASSERT_INT_EQ(convtime("2d"), 172800); + ASSERT_INT_EQ(convtime("1w"), 604800); + + /* negative time is not allowed */ + ASSERT_INT_EQ(convtime("-7"), -1); + ASSERT_INT_EQ(convtime("-9d"), -1); + + /* overflow */ + snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX); + ASSERT_INT_EQ(convtime(buf), INT_MAX); + snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX + 1); + ASSERT_INT_EQ(convtime(buf), -1); + + /* overflow with multiplier */ + snprintf(buf, sizeof buf, "%lluM", (unsigned long long)INT_MAX/60 + 1); + ASSERT_INT_EQ(convtime(buf), -1); + ASSERT_INT_EQ(convtime("1000000000000000000000w"), -1); + TEST_DONE(); +} diff --git a/regress/unittests/hostkeys/Makefile b/regress/unittests/hostkeys/Makefile new file mode 100644 index 0000000..04d9335 --- /dev/null +++ b/regress/unittests/hostkeys/Makefile @@ -0,0 +1,25 @@ +# $OpenBSD: Makefile,v 1.10 2023/01/15 23:35:10 djm Exp $ + +PROG=test_hostkeys +SRCS=tests.c test_iterate.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c +SRCS+=addr.c addrmatch.c bitmap.c hostfile.c +SRCS+=ed25519.c hash.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c + +SRCS+=digest-openssl.c +#SRCS+=digest-libc.c +SRCS+=utf8.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata + +.include <bsd.regress.mk> diff --git a/regress/unittests/hostkeys/mktestdata.sh b/regress/unittests/hostkeys/mktestdata.sh new file mode 100644 index 0000000..5a46de9 --- /dev/null +++ b/regress/unittests/hostkeys/mktestdata.sh @@ -0,0 +1,86 @@ +#!/bin/sh +# $OpenBSD: mktestdata.sh,v 1.2 2017/04/30 23:33:48 djm Exp $ + +set -ex + +cd testdata + +rm -f rsa* dsa* ecdsa* ed25519* +rm -f known_hosts* + +gen_all() { + _n=$1 + _ecdsa_bits=256 + test "x$_n" = "x1" && _ecdsa_bits=384 + test "x$_n" = "x2" && _ecdsa_bits=521 + ssh-keygen -qt rsa -b 1024 -C "RSA #$_n" -N "" -f rsa_$_n + ssh-keygen -qt dsa -b 1024 -C "DSA #$_n" -N "" -f dsa_$_n + ssh-keygen -qt ecdsa -b $_ecdsa_bits -C "ECDSA #$_n" -N "" -f ecdsa_$_n + ssh-keygen -qt ed25519 -C "ED25519 #$_n" -N "" -f ed25519_$_n + # Don't need private keys + rm -f rsa_$_n dsa_$_n ecdsa_$_n ed25519_$_n +} + +hentries() { + _preamble=$1 + _kspec=$2 + for k in `ls -1 $_kspec | sort` ; do + printf "$_preamble " + cat $k + done + echo +} + +gen_all 1 +gen_all 2 +gen_all 3 +gen_all 4 +gen_all 5 +gen_all 6 + +# A section of known_hosts with hashed hostnames. +( + hentries "sisyphus.example.com" "*_5.pub" + hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_6.pub" +) > known_hosts_hash_frag +ssh-keygen -Hf known_hosts_hash_frag +rm -f known_hosts_hash_frag.old + +# Populated known_hosts, including comments, hashed names and invalid lines +( + echo "# Plain host keys, plain host names" + hentries "sisyphus.example.com" "*_1.pub" + + echo "# Plain host keys, hostnames + addresses" + hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_2.pub" + + echo "# Some hosts with wildcard names / IPs" + hentries "*.example.com,192.0.2.*,2001:*" "*_3.pub" + + echo "# Hashed hostname and address entries" + cat known_hosts_hash_frag + rm -f known_hosts_hash_frag + echo + + echo "# Revoked and CA keys" + printf "@revoked sisyphus.example.com " ; cat ed25519_4.pub + printf "@cert-authority prometheus.example.com " ; cat ecdsa_4.pub + printf "@cert-authority *.example.com " ; cat dsa_4.pub + + printf "\n" + echo "# Some invalid lines" + # Invalid marker + printf "@what sisyphus.example.com " ; cat dsa_1.pub + # Key missing + echo "sisyphus.example.com " + # Key blob missing + echo "prometheus.example.com ssh-ed25519 " + # Key blob truncated + echo "sisyphus.example.com ssh-dsa AAAATgAAAAdz" + # Invalid type + echo "sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==" + # Type mismatch with blob + echo "prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==" +) > known_hosts + +echo OK diff --git a/regress/unittests/hostkeys/test_iterate.c b/regress/unittests/hostkeys/test_iterate.c new file mode 100644 index 0000000..84f26b5 --- /dev/null +++ b/regress/unittests/hostkeys/test_iterate.c @@ -0,0 +1,1117 @@ +/* $OpenBSD: test_iterate.c,v 1.8 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for hostfile.h hostkeys_foreach() + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "sshkey.h" +#include "authfile.h" +#include "hostfile.h" + +struct expected { + const char *key_file; /* Path for key, NULL for none */ + int no_parse_status; /* Expected status w/o key parsing */ + int no_parse_keytype; /* Expected keytype w/o key parsing */ + int match_host_p; /* Match 'prometheus.example.com' */ + int match_host_s; /* Match 'sisyphus.example.com' */ + int match_ipv4; /* Match '192.0.2.1' */ + int match_ipv6; /* Match '2001:db8::1' */ + int match_flags; /* Expected flags from match */ + struct hostkey_foreach_line l; /* Expected line contents */ +}; + +struct cbctx { + const struct expected *expected; + size_t nexpected; + size_t i; + int flags; + int match_host_p; + int match_host_s; + int match_ipv4; + int match_ipv6; +}; + +/* + * hostkeys_foreach() iterator callback that verifies the line passed + * against an array of expected entries. + */ +static int +check(struct hostkey_foreach_line *l, void *_ctx) +{ + struct cbctx *ctx = (struct cbctx *)_ctx; + const struct expected *expected; + int parse_key = (ctx->flags & HKF_WANT_PARSE_KEY) != 0; + const int matching = (ctx->flags & HKF_WANT_MATCH) != 0; + u_int expected_status, expected_match; + int expected_keytype, skip = 0; + + test_subtest_info("entry %zu/%zu, file line %ld", + ctx->i + 1, ctx->nexpected, l->linenum); + + for (;;) { + ASSERT_SIZE_T_LT(ctx->i, ctx->nexpected); + expected = ctx->expected + ctx->i++; + /* If we are matching host/IP then skip entries that don't */ + if (!matching) + break; + if (ctx->match_host_p && expected->match_host_p) + break; + if (ctx->match_host_s && expected->match_host_s) + break; + if (ctx->match_ipv4 && expected->match_ipv4) + break; + if (ctx->match_ipv6 && expected->match_ipv6) + break; + } + expected_status = (parse_key || expected->no_parse_status < 0) ? + expected->l.status : (u_int)expected->no_parse_status; + expected_match = expected->l.match; +#define UPDATE_MATCH_STATUS(x) do { \ + if (ctx->x && expected->x) { \ + expected_match |= expected->x; \ + if (expected_status == HKF_STATUS_OK) \ + expected_status = HKF_STATUS_MATCHED; \ + } \ + } while (0) + expected_keytype = (parse_key || expected->no_parse_keytype < 0) ? + expected->l.keytype : expected->no_parse_keytype; + +#ifndef OPENSSL_HAS_ECC + if (expected->l.keytype == KEY_ECDSA || + expected->no_parse_keytype == KEY_ECDSA) + skip = 1; +#endif /* OPENSSL_HAS_ECC */ +#ifndef WITH_OPENSSL + if (expected->l.keytype == KEY_DSA || + expected->no_parse_keytype == KEY_DSA || + expected->l.keytype == KEY_RSA || + expected->no_parse_keytype == KEY_RSA || + expected->l.keytype == KEY_ECDSA || + expected->no_parse_keytype == KEY_ECDSA) + skip = 1; +#endif /* WITH_OPENSSL */ + if (skip) { + expected_status = HKF_STATUS_INVALID; + expected_keytype = KEY_UNSPEC; + parse_key = 0; + } + UPDATE_MATCH_STATUS(match_host_p); + UPDATE_MATCH_STATUS(match_host_s); + UPDATE_MATCH_STATUS(match_ipv4); + UPDATE_MATCH_STATUS(match_ipv6); + + ASSERT_PTR_NE(l->path, NULL); /* Don't care about path */ + ASSERT_LONG_LONG_EQ(l->linenum, expected->l.linenum); + ASSERT_U_INT_EQ(l->status, expected_status); + ASSERT_U_INT_EQ(l->match, expected_match); + /* Not all test entries contain fulltext */ + if (expected->l.line != NULL) + ASSERT_STRING_EQ(l->line, expected->l.line); + ASSERT_INT_EQ(l->marker, expected->l.marker); + /* XXX we skip hashed hostnames for now; implement checking */ + if (expected->l.hosts != NULL) + ASSERT_STRING_EQ(l->hosts, expected->l.hosts); + /* Not all test entries contain raw keys */ + if (expected->l.rawkey != NULL) + ASSERT_STRING_EQ(l->rawkey, expected->l.rawkey); + /* XXX synthesise raw key for cases lacking and compare */ + ASSERT_INT_EQ(l->keytype, expected_keytype); + if (parse_key) { + if (expected->l.key == NULL) + ASSERT_PTR_EQ(l->key, NULL); + if (expected->l.key != NULL) { + ASSERT_PTR_NE(l->key, NULL); + ASSERT_INT_EQ(sshkey_equal(l->key, expected->l.key), 1); + } + } + if (parse_key && !(l->comment == NULL && expected->l.comment == NULL)) + ASSERT_STRING_EQ(l->comment, expected->l.comment); + return 0; +} + +/* Loads public keys for a set of expected results */ +static void +prepare_expected(struct expected *expected, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) { + if (expected[i].key_file == NULL) + continue; +#ifndef OPENSSL_HAS_ECC + if (expected[i].l.keytype == KEY_ECDSA) + continue; +#endif /* OPENSSL_HAS_ECC */ +#ifndef WITH_OPENSSL + switch (expected[i].l.keytype) { + case KEY_RSA: + case KEY_DSA: + case KEY_ECDSA: + continue; + } +#endif /* WITH_OPENSSL */ + ASSERT_INT_EQ(sshkey_load_public( + test_data_file(expected[i].key_file), &expected[i].l.key, + NULL), 0); + } +} + +static void +cleanup_expected(struct expected *expected, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) { + sshkey_free(expected[i].l.key); + expected[i].l.key = NULL; + } +} + +struct expected expected_full[] = { + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, /* path, don't care */ + 1, /* line number */ + HKF_STATUS_COMMENT, /* status */ + 0, /* match flags */ + "# Plain host keys, plain host names", /* full line, optional */ + MRK_NONE, /* marker (CA / revoked) */ + NULL, /* hosts text */ + NULL, /* raw key, optional */ + KEY_UNSPEC, /* key type */ + NULL, /* deserialised key */ + NULL, /* comment */ + 0, /* note */ + } }, + { "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 2, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #1", + 0, + } }, + { "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 3, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #1", + 0, + } }, + { "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 4, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #1", + 0, + } }, + { "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 5, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #1", + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 6, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 7, + HKF_STATUS_COMMENT, + 0, + "# Plain host keys, hostnames + addresses", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 8, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "prometheus.example.com,192.0.2.1,2001:db8::1", + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #2", + 0, + } }, + { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 9, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "prometheus.example.com,192.0.2.1,2001:db8::1", + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #2", + 0, + } }, + { "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 10, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "prometheus.example.com,192.0.2.1,2001:db8::1", + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #2", + 0, + } }, + { "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 11, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "prometheus.example.com,192.0.2.1,2001:db8::1", + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #2", + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 12, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 13, + HKF_STATUS_COMMENT, + 0, + "# Some hosts with wildcard names / IPs", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 14, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "*.example.com,192.0.2.*,2001:*", + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #3", + 0, + } }, + { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 15, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "*.example.com,192.0.2.*,2001:*", + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #3", + 0, + } }, + { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 16, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "*.example.com,192.0.2.*,2001:*", + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #3", + 0, + } }, + { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 17, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "*.example.com,192.0.2.*,2001:*", + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #3", + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 18, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 19, + HKF_STATUS_COMMENT, + 0, + "# Hashed hostname and address entries", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { + NULL, + 20, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #5", + 0, + } }, + { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { + NULL, + 21, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #5", + 0, + } }, + { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { + NULL, + 22, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #5", + 0, + } }, + { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { + NULL, + 23, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #5", + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 24, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + /* + * The next series have each key listed multiple times, as the + * hostname and addresses in the pre-hashed known_hosts are split + * to separate lines. + */ + { "dsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { + NULL, + 25, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #6", + 0, + } }, + { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { + NULL, + 26, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #6", + 0, + } }, + { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { + NULL, + 27, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #6", + 0, + } }, + { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { + NULL, + 28, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #6", + 0, + } }, + { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { + NULL, + 29, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #6", + 0, + } }, + { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { + NULL, + 30, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #6", + 0, + } }, + { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { + NULL, + 31, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #6", + 0, + } }, + { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { + NULL, + 32, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #6", + 0, + } }, + { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { + NULL, + 33, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #6", + 0, + } }, + { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { + NULL, + 34, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #6", + 0, + } }, + { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { + NULL, + 35, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #6", + 0, + } }, + { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { + NULL, + 36, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #6", + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 37, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 38, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 39, + HKF_STATUS_COMMENT, + 0, + "# Revoked and CA keys", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 40, + HKF_STATUS_OK, + 0, + NULL, + MRK_REVOKE, + "sisyphus.example.com", + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #4", + 0, + } }, + { "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { + NULL, + 41, + HKF_STATUS_OK, + 0, + NULL, + MRK_CA, + "prometheus.example.com", + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #4", + 0, + } }, + { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 42, + HKF_STATUS_OK, + 0, + NULL, + MRK_CA, + "*.example.com", + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #4", + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 43, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 44, + HKF_STATUS_COMMENT, + 0, + "# Some invalid lines", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 45, + HKF_STATUS_INVALID, + 0, + NULL, + MRK_ERROR, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 46, + HKF_STATUS_INVALID, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { + NULL, + 47, + HKF_STATUS_INVALID, + 0, + NULL, + MRK_NONE, + "prometheus.example.com", + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 48, + HKF_STATUS_INVALID, /* Would be ok if key not parsed */ + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_UNSPEC, + NULL, + NULL, + 0, + } }, + { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 49, + HKF_STATUS_INVALID, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_UNSPEC, + NULL, /* filled at runtime */ + NULL, + 0, + } }, + { NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, { + NULL, + 50, + HKF_STATUS_INVALID, /* Would be ok if key not parsed */ + 0, + NULL, + MRK_NONE, + "prometheus.example.com", + NULL, + KEY_UNSPEC, + NULL, /* filled at runtime */ + NULL, + 0, + } }, +}; + +void test_iterate(void); + +void +test_iterate(void) +{ + struct cbctx ctx; + + TEST_START("hostkeys_iterate all with key parse"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_PARSE_KEY; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, NULL, NULL, ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate all without key parse"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, NULL, NULL, ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host 1"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_host_p = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "prometheus.example.com", NULL, ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host 2"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_host_s = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "sisyphus.example.com", NULL, ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host 1"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_host_p = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "prometheus.example.com", NULL, ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host 2"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_host_s = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "sisyphus.example.com", NULL, ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host missing"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "actaeon.example.org", NULL, ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host missing"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "actaeon.example.org", NULL, ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify IPv4"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_ipv4 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify IPv6"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_ipv6 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "2001:db8::1", + ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate match IPv4"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_ipv4 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate match IPv6"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_ipv6 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "2001:db8::1", + ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify addr missing"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "192.168.0.1", + ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate match addr missing"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "::1", ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host 2 and IPv4"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_host_s = 1; + ctx.match_ipv4 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host 1 and IPv6"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_host_p = 1; + ctx.match_ipv6 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "prometheus.example.com", + "2001:db8::1", ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host 2 and IPv4 w/ key parse"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_PARSE_KEY; + ctx.match_host_s = 1; + ctx.match_ipv4 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host 1 and IPv6 w/ key parse"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH|HKF_WANT_PARSE_KEY; + ctx.match_host_p = 1; + ctx.match_ipv6 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "prometheus.example.com", + "2001:db8::1", ctx.flags, 0), 0); + cleanup_expected(expected_full, ctx.nexpected); + TEST_DONE(); +} + diff --git a/regress/unittests/hostkeys/testdata/dsa_1.pub b/regress/unittests/hostkeys/testdata/dsa_1.pub new file mode 100644 index 0000000..56e1e37 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/dsa_1.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 diff --git a/regress/unittests/hostkeys/testdata/dsa_2.pub b/regress/unittests/hostkeys/testdata/dsa_2.pub new file mode 100644 index 0000000..394e0bf --- /dev/null +++ b/regress/unittests/hostkeys/testdata/dsa_2.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2 diff --git a/regress/unittests/hostkeys/testdata/dsa_3.pub b/regress/unittests/hostkeys/testdata/dsa_3.pub new file mode 100644 index 0000000..e506ea4 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/dsa_3.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3 diff --git a/regress/unittests/hostkeys/testdata/dsa_4.pub b/regress/unittests/hostkeys/testdata/dsa_4.pub new file mode 100644 index 0000000..8552c38 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/dsa_4.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4 diff --git a/regress/unittests/hostkeys/testdata/dsa_5.pub b/regress/unittests/hostkeys/testdata/dsa_5.pub new file mode 100644 index 0000000..149e1ef --- /dev/null +++ b/regress/unittests/hostkeys/testdata/dsa_5.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5 diff --git a/regress/unittests/hostkeys/testdata/dsa_6.pub b/regress/unittests/hostkeys/testdata/dsa_6.pub new file mode 100644 index 0000000..edbb976 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/dsa_6.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 diff --git a/regress/unittests/hostkeys/testdata/ecdsa_1.pub b/regress/unittests/hostkeys/testdata/ecdsa_1.pub new file mode 100644 index 0000000..16a535b --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ecdsa_1.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1 diff --git a/regress/unittests/hostkeys/testdata/ecdsa_2.pub b/regress/unittests/hostkeys/testdata/ecdsa_2.pub new file mode 100644 index 0000000..d2bad11 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ecdsa_2.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2 diff --git a/regress/unittests/hostkeys/testdata/ecdsa_3.pub b/regress/unittests/hostkeys/testdata/ecdsa_3.pub new file mode 100644 index 0000000..e3ea925 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ecdsa_3.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3 diff --git a/regress/unittests/hostkeys/testdata/ecdsa_4.pub b/regress/unittests/hostkeys/testdata/ecdsa_4.pub new file mode 100644 index 0000000..2d616f5 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ecdsa_4.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4 diff --git a/regress/unittests/hostkeys/testdata/ecdsa_5.pub b/regress/unittests/hostkeys/testdata/ecdsa_5.pub new file mode 100644 index 0000000..a3df9b3 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ecdsa_5.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5 diff --git a/regress/unittests/hostkeys/testdata/ecdsa_6.pub b/regress/unittests/hostkeys/testdata/ecdsa_6.pub new file mode 100644 index 0000000..139f5a7 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ecdsa_6.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 diff --git a/regress/unittests/hostkeys/testdata/ed25519_1.pub b/regress/unittests/hostkeys/testdata/ed25519_1.pub new file mode 100644 index 0000000..0b12efe --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ed25519_1.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1 diff --git a/regress/unittests/hostkeys/testdata/ed25519_2.pub b/regress/unittests/hostkeys/testdata/ed25519_2.pub new file mode 100644 index 0000000..78e262b --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ed25519_2.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2 diff --git a/regress/unittests/hostkeys/testdata/ed25519_3.pub b/regress/unittests/hostkeys/testdata/ed25519_3.pub new file mode 100644 index 0000000..64e5f12 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ed25519_3.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3 diff --git a/regress/unittests/hostkeys/testdata/ed25519_4.pub b/regress/unittests/hostkeys/testdata/ed25519_4.pub new file mode 100644 index 0000000..47b6724 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ed25519_4.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4 diff --git a/regress/unittests/hostkeys/testdata/ed25519_5.pub b/regress/unittests/hostkeys/testdata/ed25519_5.pub new file mode 100644 index 0000000..72ccae6 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ed25519_5.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5 diff --git a/regress/unittests/hostkeys/testdata/ed25519_6.pub b/regress/unittests/hostkeys/testdata/ed25519_6.pub new file mode 100644 index 0000000..0f71973 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/ed25519_6.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 diff --git a/regress/unittests/hostkeys/testdata/known_hosts b/regress/unittests/hostkeys/testdata/known_hosts new file mode 100644 index 0000000..4446f45 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/known_hosts @@ -0,0 +1,50 @@ +# Plain host keys, plain host names +sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 +sisyphus.example.com ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1 +sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1 +sisyphus.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1 + +# Plain host keys, hostnames + addresses +prometheus.example.com,192.0.2.1,2001:db8::1 ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2 +prometheus.example.com,192.0.2.1,2001:db8::1 ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2 +prometheus.example.com,192.0.2.1,2001:db8::1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2 +prometheus.example.com,192.0.2.1,2001:db8::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2 + +# Some hosts with wildcard names / IPs +*.example.com,192.0.2.*,2001:* ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3 +*.example.com,192.0.2.*,2001:* ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3 +*.example.com,192.0.2.*,2001:* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3 +*.example.com,192.0.2.*,2001:* ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3 + +# Hashed hostname and address entries +|1|z3xOIdT5ue3Vuf3MzT67kaioqjw=|GZhhe5uwDOBQrC9N4cCjpbLpSn4= ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5 +|1|B7t/AYabn8zgwU47Cb4A/Nqt3eI=|arQPZyRphkzisr7w6wwikvhaOyE= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5 +|1|JR81WxEocTP5d7goIRkl8fHBbno=|l6sj6FOsoXxgEZMzn/BnOfPKN68= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5 +|1|W7x4zY6KtTZJgsopyOusJqvVPag=|QauLt7hKezBZFZi2i4Xopho7Nsk= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5 + +|1|mxnU8luzqWLvfVi5qBm5xVIyCRM=|9Epopft7LBd80Bf6RmWPIpwa8yU= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 +|1|klvLmvh2vCpkNMDEjVvrE8SJWTg=|e/dqEEBLnbgqmwEesl4cDRu/7TM= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 +|1|wsk3ddB3UjuxEsoeNCeZjZ6NvZs=|O3O/q2Z/u7DrxoTiIq6kzCevQT0= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 +|1|B8epmkLSni+vGZDijr/EwxeR2k4=|7ct8yzNOVJhKm3ZD2w0XIT7df8E= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 +|1|JojD885UhYhbCu571rgyM/5PpYU=|BJaU2aE1FebQZy3B5tzTDRWFRG0= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 +|1|5t7UDHDybVrDZVQPCpwdnr6nk4k=|EqJ73W/veIL3H2x+YWHcJxI5ETA= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 +|1|OCcBfGc/b9+ip+W6Gp+3ftdluO4=|VbrKUdzOOtIBOOmEE+jlK4SD3Xc= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 +|1|9fLN0YdP+BJ25lKuKvYuOdUo93w=|vZyr0rOiX01hv5XbghhHMW+Zb3U= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 +|1|nc9RoaaQ0s5jdPxwlUmluGHU3uk=|un6OsJajokKQ3MgyS9mfDNeyP6U= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 +|1|rsHB6juT9q6GOY91qOeOwL6TSJE=|ps/vXF9Izuues5PbOn887Gw/2Dg= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 +|1|BsckdLH2aRyWQooRmv+Yo3t4dKg=|Lf3tJc5Iyx0KxNwAG89FsImsfEE= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 +|1|plqkBA4hq7UATyd5+/Xl+zL7ghw=|stacofaUed46666mfqxp9gJFjt4= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 + + +# Revoked and CA keys +@revoked sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4 +@cert-authority prometheus.example.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4 +@cert-authority *.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4 + +# Some invalid lines +@what sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 +sisyphus.example.com +prometheus.example.com ssh-ed25519 +sisyphus.example.com ssh-dsa AAAATgAAAAdz +sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg== +prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg== diff --git a/regress/unittests/hostkeys/testdata/rsa1_1.pub b/regress/unittests/hostkeys/testdata/rsa1_1.pub new file mode 100644 index 0000000..772ce9c --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa1_1.pub @@ -0,0 +1 @@ +1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 diff --git a/regress/unittests/hostkeys/testdata/rsa1_2.pub b/regress/unittests/hostkeys/testdata/rsa1_2.pub new file mode 100644 index 0000000..78794b9 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa1_2.pub @@ -0,0 +1 @@ +1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2 diff --git a/regress/unittests/hostkeys/testdata/rsa1_3.pub b/regress/unittests/hostkeys/testdata/rsa1_3.pub new file mode 100644 index 0000000..0c035fe --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa1_3.pub @@ -0,0 +1 @@ +1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3 diff --git a/regress/unittests/hostkeys/testdata/rsa1_4.pub b/regress/unittests/hostkeys/testdata/rsa1_4.pub new file mode 100644 index 0000000..0006442 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa1_4.pub @@ -0,0 +1 @@ +1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4 diff --git a/regress/unittests/hostkeys/testdata/rsa1_5.pub b/regress/unittests/hostkeys/testdata/rsa1_5.pub new file mode 100644 index 0000000..bb53c26 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa1_5.pub @@ -0,0 +1 @@ +1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5 diff --git a/regress/unittests/hostkeys/testdata/rsa1_6.pub b/regress/unittests/hostkeys/testdata/rsa1_6.pub new file mode 100644 index 0000000..85d6576 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa1_6.pub @@ -0,0 +1 @@ +1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 diff --git a/regress/unittests/hostkeys/testdata/rsa_1.pub b/regress/unittests/hostkeys/testdata/rsa_1.pub new file mode 100644 index 0000000..2b87885 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa_1.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1 diff --git a/regress/unittests/hostkeys/testdata/rsa_2.pub b/regress/unittests/hostkeys/testdata/rsa_2.pub new file mode 100644 index 0000000..33f1fd9 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa_2.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2 diff --git a/regress/unittests/hostkeys/testdata/rsa_3.pub b/regress/unittests/hostkeys/testdata/rsa_3.pub new file mode 100644 index 0000000..c2f6b20 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa_3.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3 diff --git a/regress/unittests/hostkeys/testdata/rsa_4.pub b/regress/unittests/hostkeys/testdata/rsa_4.pub new file mode 100644 index 0000000..35545a7 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa_4.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDI8AdjBAozcdRnIikVlt69iyDHKyrtxmpdkbRy9bWaL86OH+PTmLUk5e+T/ufiakpeE2pm0hkE3e4Sh/FsY+rsQdRoraWVNFfchcMeVlKvuy5RZN0ElvmaQebOJUeNeBn2LLw8aL8bJ4CP/bQRKrmrSSqjz3+4H9YNVyyk1OGBPQ== RSA #4 diff --git a/regress/unittests/hostkeys/testdata/rsa_5.pub b/regress/unittests/hostkeys/testdata/rsa_5.pub new file mode 100644 index 0000000..befbaa7 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa_5.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5 diff --git a/regress/unittests/hostkeys/testdata/rsa_6.pub b/regress/unittests/hostkeys/testdata/rsa_6.pub new file mode 100644 index 0000000..393e116 --- /dev/null +++ b/regress/unittests/hostkeys/testdata/rsa_6.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 diff --git a/regress/unittests/hostkeys/tests.c b/regress/unittests/hostkeys/tests.c new file mode 100644 index 0000000..92c7646 --- /dev/null +++ b/regress/unittests/hostkeys/tests.c @@ -0,0 +1,16 @@ +/* $OpenBSD: tests.c,v 1.1 2015/02/16 22:18:34 djm Exp $ */ +/* + * Regress test for known_hosts-related API. + * + * Placed in the public domain + */ + +void tests(void); +void test_iterate(void); /* test_iterate.c */ + +void +tests(void) +{ + test_iterate(); +} + diff --git a/regress/unittests/kex/Makefile b/regress/unittests/kex/Makefile new file mode 100644 index 0000000..981affe --- /dev/null +++ b/regress/unittests/kex/Makefile @@ -0,0 +1,40 @@ +# $OpenBSD: Makefile,v 1.14 2023/02/02 12:12:52 djm Exp $ + +PROG=test_kex +SRCS=tests.c test_kex.c test_proposal.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c +SRCS+=addr.c addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.c +SRCS+=compat.c ed25519.c hash.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c + +SRCS+= kex.c +SRCS+= dh.c +SRCS+= kexdh.c +SRCS+= kexecdh.c +SRCS+= kexgex.c +SRCS+= kexgexc.c +SRCS+= kexgexs.c +SRCS+= kexc25519.c +SRCS+= smult_curve25519_ref.c +SRCS+= kexgen.c +SRCS+= kexsntrup761x25519.c +SRCS+= sntrup761.c +SRCS+= utf8.c + +SRCS+=digest-openssl.c +#SRCS+=digest-libc.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} + +.include <bsd.regress.mk> + +LDADD+=-lz diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c new file mode 100644 index 0000000..c26761e --- /dev/null +++ b/regress/unittests/kex/test_kex.c @@ -0,0 +1,208 @@ +/* $OpenBSD: test_kex.c,v 1.6 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test KEX + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "ssh_api.h" +#include "sshbuf.h" +#include "packet.h" +#include "myproposal.h" + +void kex_tests(void); +static int do_debug = 0; + +static int +do_send_and_receive(struct ssh *from, struct ssh *to) +{ + u_char type; + size_t len; + const u_char *buf; + int r; + + for (;;) { + if ((r = ssh_packet_next(from, &type)) != 0) { + fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r)); + return r; + } + if (type != 0) + return 0; + buf = ssh_output_ptr(from, &len); + if (do_debug) + printf("%zu", len); + if (len == 0) + return 0; + if ((r = ssh_output_consume(from, len)) != 0 || + (r = ssh_input_append(to, buf, len)) != 0) + return r; + } +} + +static void +run_kex(struct ssh *client, struct ssh *server) +{ + int r = 0; + + while (!server->kex->done || !client->kex->done) { + if (do_debug) + printf(" S:"); + if ((r = do_send_and_receive(server, client))) + break; + if (do_debug) + printf(" C:"); + if ((r = do_send_and_receive(client, server))) + break; + } + if (do_debug) + printf("done: %s\n", ssh_err(r)); + ASSERT_INT_EQ(r, 0); + ASSERT_INT_EQ(server->kex->done, 1); + ASSERT_INT_EQ(client->kex->done, 1); +} + +static void +do_kex_with_key(char *kex, int keytype, int bits) +{ + struct ssh *client = NULL, *server = NULL, *server2 = NULL; + struct sshkey *private, *public; + struct sshbuf *state; + struct kex_params kex_params; + char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + char *keyname = NULL; + + TEST_START("sshkey_generate"); + ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0); + TEST_DONE(); + + TEST_START("sshkey_from_private"); + ASSERT_INT_EQ(sshkey_from_private(private, &public), 0); + TEST_DONE(); + + TEST_START("ssh_init"); + memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); + if (kex != NULL) + kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; + keyname = strdup(sshkey_ssh_name(private)); + ASSERT_PTR_NE(keyname, NULL); + kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; + ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); + ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0); + ASSERT_PTR_NE(client, NULL); + ASSERT_PTR_NE(server, NULL); + TEST_DONE(); + + TEST_START("ssh_add_hostkey"); + ASSERT_INT_EQ(ssh_add_hostkey(server, private), 0); + ASSERT_INT_EQ(ssh_add_hostkey(client, public), 0); + TEST_DONE(); + + TEST_START("kex"); + run_kex(client, server); + TEST_DONE(); + + TEST_START("rekeying client"); + ASSERT_INT_EQ(kex_send_kexinit(client), 0); + run_kex(client, server); + TEST_DONE(); + + TEST_START("rekeying server"); + ASSERT_INT_EQ(kex_send_kexinit(server), 0); + run_kex(client, server); + TEST_DONE(); + + TEST_START("ssh_packet_get_state"); + state = sshbuf_new(); + ASSERT_PTR_NE(state, NULL); + ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0); + ASSERT_INT_GE(sshbuf_len(state), 1); + TEST_DONE(); + + TEST_START("ssh_packet_set_state"); + server2 = NULL; + ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0); + ASSERT_PTR_NE(server2, NULL); + ASSERT_INT_EQ(ssh_add_hostkey(server2, private), 0); + ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0); + ASSERT_INT_EQ(sshbuf_len(state), 0); + sshbuf_free(state); + ASSERT_PTR_NE(server2->kex, NULL); + /* XXX we need to set the callbacks */ +#ifdef WITH_OPENSSL + server2->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; + server2->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; + server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; +#ifdef OPENSSL_HAS_ECC + server2->kex->kex[KEX_ECDH_SHA2] = kex_gen_server; +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server; + server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = 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; + TEST_DONE(); + + TEST_START("rekeying server2"); + ASSERT_INT_EQ(kex_send_kexinit(server2), 0); + run_kex(client, server2); + ASSERT_INT_EQ(kex_send_kexinit(client), 0); + run_kex(client, server2); + TEST_DONE(); + + TEST_START("cleanup"); + sshkey_free(private); + sshkey_free(public); + ssh_free(client); + ssh_free(server); + ssh_free(server2); + free(keyname); + TEST_DONE(); +} + +static void +do_kex(char *kex) +{ +#ifdef WITH_OPENSSL + do_kex_with_key(kex, KEY_RSA, 2048); + do_kex_with_key(kex, KEY_DSA, 1024); +#ifdef OPENSSL_HAS_ECC + do_kex_with_key(kex, KEY_ECDSA, 256); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + do_kex_with_key(kex, KEY_ED25519, 256); +} + +void +kex_tests(void) +{ + do_kex("curve25519-sha256@libssh.org"); +#ifdef WITH_OPENSSL +#ifdef OPENSSL_HAS_ECC + do_kex("ecdh-sha2-nistp256"); + do_kex("ecdh-sha2-nistp384"); + do_kex("ecdh-sha2-nistp521"); +#endif /* OPENSSL_HAS_ECC */ + do_kex("diffie-hellman-group-exchange-sha256"); + do_kex("diffie-hellman-group-exchange-sha1"); + do_kex("diffie-hellman-group14-sha1"); + do_kex("diffie-hellman-group1-sha1"); +# ifdef USE_SNTRUP761X25519 + do_kex("sntrup761x25519-sha512@openssh.com"); +# endif /* USE_SNTRUP761X25519 */ +#endif /* WITH_OPENSSL */ +} diff --git a/regress/unittests/kex/test_proposal.c b/regress/unittests/kex/test_proposal.c new file mode 100644 index 0000000..fa4192b --- /dev/null +++ b/regress/unittests/kex/test_proposal.c @@ -0,0 +1,124 @@ +/* $OpenBSD: test_proposal.c,v 1.2 2023/03/06 12:15:47 dtucker Exp $ */ +/* + * Regress test KEX + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <signal.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "cipher.h" +#include "compat.h" +#include "ssherr.h" +#include "sshbuf.h" +#include "kex.h" +#include "myproposal.h" +#include "packet.h" +#include "xmalloc.h" + +void kex_proposal_tests(void); +void kex_proposal_populate_tests(void); + +#define CURVE25519 "curve25519-sha256@libssh.org" +#define DHGEX1 "diffie-hellman-group-exchange-sha1" +#define DHGEX256 "diffie-hellman-group-exchange-sha256" +#define KEXALGOS CURVE25519","DHGEX256","DHGEX1 +void +kex_proposal_tests(void) +{ + size_t i; + struct ssh ssh; + char *result, *out, *in; + struct { + char *in; /* TODO: make this const */ + char *out; + int compat; + } tests[] = { + { KEXALGOS, KEXALGOS, 0}, + { KEXALGOS, DHGEX256","DHGEX1, SSH_BUG_CURVE25519PAD }, + { KEXALGOS, CURVE25519, SSH_OLD_DHGEX }, + { "a,"KEXALGOS, "a", SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX }, + /* TODO: enable once compat_kex_proposal doesn't fatal() */ + /* { KEXALGOS, "", SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX }, */ + }; + + TEST_START("compat_kex_proposal"); + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + ssh.compat = tests[i].compat; + /* match entire string */ + result = compat_kex_proposal(&ssh, tests[i].in); + ASSERT_STRING_EQ(result, tests[i].out); + free(result); + /* match at end */ + in = kex_names_cat("a", tests[i].in); + out = kex_names_cat("a", tests[i].out); + result = compat_kex_proposal(&ssh, in); + ASSERT_STRING_EQ(result, out); + free(result); free(in); free(out); + /* match at start */ + in = kex_names_cat(tests[i].in, "a"); + out = kex_names_cat(tests[i].out, "a"); + result = compat_kex_proposal(&ssh, in); + ASSERT_STRING_EQ(result, out); + free(result); free(in); free(out); + /* match in middle */ + xasprintf(&in, "a,%s,b", tests[i].in); + if (*(tests[i].out) == '\0') + out = xstrdup("a,b"); + else + xasprintf(&out, "a,%s,b", tests[i].out); + result = compat_kex_proposal(&ssh, in); + ASSERT_STRING_EQ(result, out); + free(result); free(in); free(out); + } + TEST_DONE(); +} + +void +kex_proposal_populate_tests(void) +{ + char *prop[PROPOSAL_MAX], *kexalgs, *ciphers, *macs, *hkalgs; + const char *comp = compression_alg_list(0); + int i; + struct ssh ssh; + struct kex kex; + + kexalgs = kex_alg_list(','); + ciphers = cipher_alg_list(',', 0); + macs = mac_alg_list(','); + hkalgs = kex_alg_list(','); + + ssh.kex = &kex; + TEST_START("compat_kex_proposal_populate"); + for (i = 0; i <= 1; i++) { + kex.server = i; + for (ssh.compat = 0; ssh.compat < 0x40000000; ) { + kex_proposal_populate_entries(&ssh, prop, NULL, NULL, + NULL, NULL, NULL); + kex_proposal_free_entries(prop); + kex_proposal_populate_entries(&ssh, prop, kexalgs, + ciphers, macs, hkalgs, comp); + kex_proposal_free_entries(prop); + if (ssh.compat == 0) + ssh.compat = 1; + else + ssh.compat <<= 1; + } + } + + free(kexalgs); + free(ciphers); + free(macs); + free(hkalgs); +} diff --git a/regress/unittests/kex/tests.c b/regress/unittests/kex/tests.c new file mode 100644 index 0000000..d3044f0 --- /dev/null +++ b/regress/unittests/kex/tests.c @@ -0,0 +1,18 @@ +/* $OpenBSD: tests.c,v 1.3 2023/03/06 12:15:47 dtucker Exp $ */ +/* + * Placed in the public domain + */ + +#include "../test_helper/test_helper.h" + +void kex_tests(void); +void kex_proposal_tests(void); +void kex_proposal_populate_tests(void); + +void +tests(void) +{ + kex_tests(); + kex_proposal_tests(); + kex_proposal_populate_tests(); +} diff --git a/regress/unittests/match/Makefile b/regress/unittests/match/Makefile new file mode 100644 index 0000000..939163d --- /dev/null +++ b/regress/unittests/match/Makefile @@ -0,0 +1,16 @@ +# $OpenBSD: Makefile,v 1.5 2021/01/09 12:24:31 dtucker Exp $ + +PROG=test_match +SRCS=tests.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=match.c misc.c log.c uidswap.c fatal.c ssherr.c addrmatch.c xmalloc.c +SRCS+=cleanup.c atomicio.c addr.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} + +.include <bsd.regress.mk> diff --git a/regress/unittests/match/tests.c b/regress/unittests/match/tests.c new file mode 100644 index 0000000..f00d1f9 --- /dev/null +++ b/regress/unittests/match/tests.c @@ -0,0 +1,131 @@ +/* $OpenBSD: tests.c,v 1.8 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for matching functions + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "match.h" + +void +tests(void) +{ + TEST_START("match_pattern"); + ASSERT_INT_EQ(match_pattern("", ""), 1); + ASSERT_INT_EQ(match_pattern("", "aaa"), 0); + ASSERT_INT_EQ(match_pattern("aaa", ""), 0); + ASSERT_INT_EQ(match_pattern("aaa", "aaaa"), 0); + ASSERT_INT_EQ(match_pattern("aaaa", "aaa"), 0); + TEST_DONE(); + + TEST_START("match_pattern wildcard"); + ASSERT_INT_EQ(match_pattern("", "*"), 1); + ASSERT_INT_EQ(match_pattern("a", "?"), 1); + ASSERT_INT_EQ(match_pattern("aa", "a?"), 1); + ASSERT_INT_EQ(match_pattern("a", "*"), 1); + ASSERT_INT_EQ(match_pattern("aa", "a*"), 1); + ASSERT_INT_EQ(match_pattern("aa", "?*"), 1); + ASSERT_INT_EQ(match_pattern("aa", "**"), 1); + ASSERT_INT_EQ(match_pattern("aa", "?a"), 1); + ASSERT_INT_EQ(match_pattern("aa", "*a"), 1); + ASSERT_INT_EQ(match_pattern("ba", "a?"), 0); + ASSERT_INT_EQ(match_pattern("ba", "a*"), 0); + ASSERT_INT_EQ(match_pattern("ab", "?a"), 0); + ASSERT_INT_EQ(match_pattern("ab", "*a"), 0); + TEST_DONE(); + + TEST_START("match_pattern_list"); + ASSERT_INT_EQ(match_pattern_list("", "", 0), 0); /* no patterns */ + ASSERT_INT_EQ(match_pattern_list("", "*", 0), 1); + ASSERT_INT_EQ(match_pattern_list("", "!*", 0), -1); + ASSERT_INT_EQ(match_pattern_list("", "!a,*", 0), 1); + ASSERT_INT_EQ(match_pattern_list("", "*,!a", 0), 1); + ASSERT_INT_EQ(match_pattern_list("", "a,!*", 0), -1); + ASSERT_INT_EQ(match_pattern_list("", "!*,a", 0), -1); + ASSERT_INT_EQ(match_pattern_list("a", "", 0), 0); + ASSERT_INT_EQ(match_pattern_list("a", "*", 0), 1); + ASSERT_INT_EQ(match_pattern_list("a", "!*", 0), -1); + ASSERT_INT_EQ(match_pattern_list("a", "!a", 0), -1); + /* XXX negated ASSERT_INT_EQ(match_pattern_list("a", "!b", 0), 1); */ + ASSERT_INT_EQ(match_pattern_list("a", "!a,*", 0), -1); + ASSERT_INT_EQ(match_pattern_list("b", "!a,*", 0), 1); + ASSERT_INT_EQ(match_pattern_list("a", "*,!a", 0), -1); + ASSERT_INT_EQ(match_pattern_list("b", "*,!a", 0), 1); + ASSERT_INT_EQ(match_pattern_list("a", "a,!*", 0), -1); + ASSERT_INT_EQ(match_pattern_list("b", "a,!*", 0), -1); + ASSERT_INT_EQ(match_pattern_list("a", "a,!a", 0), -1); + /* XXX negated ASSERT_INT_EQ(match_pattern_list("b", "a,!a", 0), 1); */ + ASSERT_INT_EQ(match_pattern_list("a", "!*,a", 0), -1); + ASSERT_INT_EQ(match_pattern_list("b", "!*,a", 0), -1); + TEST_DONE(); + + TEST_START("match_pattern_list lowercase"); + ASSERT_INT_EQ(match_pattern_list("abc", "ABC", 0), 0); + ASSERT_INT_EQ(match_pattern_list("ABC", "abc", 0), 0); + ASSERT_INT_EQ(match_pattern_list("abc", "ABC", 1), 1); + ASSERT_INT_EQ(match_pattern_list("ABC", "abc", 1), 0); + TEST_DONE(); + + TEST_START("addr_match_list"); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.1/44"), -2); + ASSERT_INT_EQ(addr_match_list(NULL, "127.0.0.1/44"), -2); + ASSERT_INT_EQ(addr_match_list("a", "*"), 0); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "*"), 1); + ASSERT_INT_EQ(addr_match_list(NULL, "*"), 0); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.1"), 1); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.2"), 0); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.1"), -1); + /* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.2"), 1); */ + ASSERT_INT_EQ(addr_match_list("127.0.0.255", "127.0.0.0/24"), 1); + ASSERT_INT_EQ(addr_match_list("127.0.1.1", "127.0.0.0/24"), 0); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.0/24"), 1); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.1.0/24"), 0); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.0/24"), -1); + /* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.1.0/24"), 1); */ + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "10.0.0.1,!127.0.0.1"), -1); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.1,10.0.0.1"), -1); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "10.0.0.1,127.0.0.2"), 0); + ASSERT_INT_EQ(addr_match_list("127.0.0.1", "127.0.0.2,10.0.0.1"), 0); + /* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "10.0.0.1,!127.0.0.2"), 1); */ + /* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.2,10.0.0.1"), 1); */ + TEST_DONE(); + +#define CHECK_FILTER(string,filter,expected) \ + do { \ + char *result = match_filter_denylist((string), (filter)); \ + ASSERT_STRING_EQ(result, expected); \ + free(result); \ + } while (0) + + TEST_START("match_filter_list"); + CHECK_FILTER("a,b,c", "", "a,b,c"); + CHECK_FILTER("a,b,c", "a", "b,c"); + CHECK_FILTER("a,b,c", "b", "a,c"); + CHECK_FILTER("a,b,c", "c", "a,b"); + CHECK_FILTER("a,b,c", "a,b", "c"); + CHECK_FILTER("a,b,c", "a,c", "b"); + CHECK_FILTER("a,b,c", "b,c", "a"); + CHECK_FILTER("a,b,c", "a,b,c", ""); + CHECK_FILTER("a,b,c", "b,c", "a"); + CHECK_FILTER("", "a,b,c", ""); + TEST_DONE(); +/* + * XXX TODO + * int match_host_and_ip(const char *, const char *, const char *); + * int match_user(const char *, const char *, const char *, const char *); + * char *match_list(const char *, const char *, u_int *); + * int addr_match_cidr_list(const char *, const char *); + */ +} diff --git a/regress/unittests/misc/Makefile b/regress/unittests/misc/Makefile new file mode 100644 index 0000000..d2be393 --- /dev/null +++ b/regress/unittests/misc/Makefile @@ -0,0 +1,33 @@ +# $OpenBSD: Makefile,v 1.9 2023/01/06 02:59:50 djm Exp $ + +PROG=test_misc +SRCS=tests.c +SRCS+= test_convtime.c +SRCS+= test_expand.c +SRCS+= test_parse.c +SRCS+= test_argv.c +SRCS+= test_strdelim.c +SRCS+= test_hpdelim.c +SRCS+= test_ptimeout.c + +# From usr.bin/ssh/Makefile.inc +SRCS+= sshbuf.c +SRCS+= sshbuf-getput-basic.c +SRCS+= sshbuf-misc.c +SRCS+= ssherr.c +SRCS+= log.c +SRCS+= xmalloc.c +SRCS+= misc.c +SRCS+= match.c +SRCS+= addr.c +SRCS+= addrmatch.c + +# From usr.bin/ssh/sshd/Makefile +SRCS+= atomicio.c cleanup.c fatal.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} + +.include <bsd.regress.mk> diff --git a/regress/unittests/misc/test_argv.c b/regress/unittests/misc/test_argv.c new file mode 100644 index 0000000..682863e --- /dev/null +++ b/regress/unittests/misc/test_argv.c @@ -0,0 +1,186 @@ +/* $OpenBSD: test_argv.c,v 1.4 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for misc argv handling functions. + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" + +void test_argv(void); + +void +test_argv(void) +{ + char **av = NULL; + int ac = 0; + +#define RESET_ARGV() \ + do { \ + argv_free(av, ac); \ + av = NULL; \ + ac = -1; \ + } while (0) + + TEST_START("empty args"); + ASSERT_INT_EQ(argv_split("", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 0); + ASSERT_PTR_NE(av, NULL); + ASSERT_PTR_EQ(av[0], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split(" ", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 0); + ASSERT_PTR_NE(av, NULL); + ASSERT_PTR_EQ(av[0], NULL); + RESET_ARGV(); + TEST_DONE(); + + TEST_START("trivial args"); + ASSERT_INT_EQ(argv_split("leamas", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "leamas"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("smiley leamas", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 2); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "smiley"); + ASSERT_STRING_EQ(av[1], "leamas"); + ASSERT_PTR_EQ(av[2], NULL); + RESET_ARGV(); + TEST_DONE(); + + TEST_START("quoted"); + ASSERT_INT_EQ(argv_split("\"smiley\"", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "smiley"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("leamas \" smiley \"", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 2); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "leamas"); + ASSERT_STRING_EQ(av[1], " smiley "); + ASSERT_PTR_EQ(av[2], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("\"smiley leamas\"", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "smiley leamas"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("smiley\" leamas\" liz", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 2); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "smiley leamas"); + ASSERT_STRING_EQ(av[1], "liz"); + ASSERT_PTR_EQ(av[2], NULL); + RESET_ARGV(); + TEST_DONE(); + + TEST_START("escaped"); + ASSERT_INT_EQ(argv_split("\\\"smiley\\'", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "\"smiley'"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("'\\'smiley\\\"'", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "'smiley\""); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("smiley\\'s leamas\\'", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 2); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "smiley's"); + ASSERT_STRING_EQ(av[1], "leamas'"); + ASSERT_PTR_EQ(av[2], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("leamas\\\\smiley", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "leamas\\smiley"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("leamas\\\\ \\\\smiley", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 2); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "leamas\\"); + ASSERT_STRING_EQ(av[1], "\\smiley"); + ASSERT_PTR_EQ(av[2], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("smiley\\ leamas", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "smiley leamas"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + TEST_DONE(); + + TEST_START("quoted escaped"); + ASSERT_INT_EQ(argv_split("'smiley\\ leamas'", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "smiley\\ leamas"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("\"smiley\\ leamas\"", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "smiley\\ leamas"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + TEST_DONE(); + + TEST_START("comments"); + ASSERT_INT_EQ(argv_split("# gold", &ac, &av, 0), 0); + ASSERT_INT_EQ(ac, 2); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "#"); + ASSERT_STRING_EQ(av[1], "gold"); + ASSERT_PTR_EQ(av[2], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("# gold", &ac, &av, 1), 0); + ASSERT_INT_EQ(ac, 0); + ASSERT_PTR_NE(av, NULL); + ASSERT_PTR_EQ(av[0], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("leamas#gold", &ac, &av, 1), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "leamas#gold"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("\"leamas # gold\"", &ac, &av, 1), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "leamas # gold"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + ASSERT_INT_EQ(argv_split("\"leamas\"#gold", &ac, &av, 1), 0); + ASSERT_INT_EQ(ac, 1); + ASSERT_PTR_NE(av, NULL); + ASSERT_STRING_EQ(av[0], "leamas#gold"); + ASSERT_PTR_EQ(av[1], NULL); + RESET_ARGV(); + TEST_DONE(); + + /* XXX test char *argv_assemble(int argc, char **argv) */ +} diff --git a/regress/unittests/misc/test_convtime.c b/regress/unittests/misc/test_convtime.c new file mode 100644 index 0000000..4794dbd --- /dev/null +++ b/regress/unittests/misc/test_convtime.c @@ -0,0 +1,121 @@ +/* $OpenBSD: test_convtime.c,v 1.3 2022/08/11 01:57:50 djm Exp $ */ +/* + * Regress test for misc time conversion functions. + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <limits.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" +#include "ssherr.h" + +void test_convtime(void); + +void +test_convtime(void) +{ + char buf[1024]; + uint64_t t; + + TEST_START("misc_convtime"); + ASSERT_INT_EQ(convtime("0"), 0); + ASSERT_INT_EQ(convtime("1"), 1); + ASSERT_INT_EQ(convtime("2s"), 2); + ASSERT_INT_EQ(convtime("3m"), 180); + ASSERT_INT_EQ(convtime("1m30"), 90); + ASSERT_INT_EQ(convtime("1m30s"), 90); + ASSERT_INT_EQ(convtime("1h1s"), 3601); + ASSERT_INT_EQ(convtime("1h30m"), 90 * 60); + ASSERT_INT_EQ(convtime("1d"), 24 * 60 * 60); + ASSERT_INT_EQ(convtime("1w"), 7 * 24 * 60 * 60); + ASSERT_INT_EQ(convtime("1w2d3h4m5"), 788645); + ASSERT_INT_EQ(convtime("1w2d3h4m5s"), 788645); + /* any negative number or error returns -1 */ + ASSERT_INT_EQ(convtime("-1"), -1); + ASSERT_INT_EQ(convtime(""), -1); + ASSERT_INT_EQ(convtime("trout"), -1); + ASSERT_INT_EQ(convtime("-77"), -1); + /* boundary conditions */ + snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX); + ASSERT_INT_EQ(convtime(buf), INT_MAX); + snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX + 1); + ASSERT_INT_EQ(convtime(buf), -1); + ASSERT_INT_EQ(convtime("3550w5d3h14m7s"), 2147483647); +#if INT_MAX == 2147483647 + ASSERT_INT_EQ(convtime("3550w5d3h14m8s"), -1); +#endif + TEST_DONE(); + + /* XXX timezones/DST make verification of this tricky */ + /* XXX maybe setenv TZ and tzset() to make it unambiguous? */ + TEST_START("misc_parse_absolute_time"); + ASSERT_INT_EQ(parse_absolute_time("20000101", &t), 0); + ASSERT_INT_EQ(parse_absolute_time("200001011223", &t), 0); + ASSERT_INT_EQ(parse_absolute_time("20000101122345", &t), 0); + + /* forced UTC TZ */ + ASSERT_INT_EQ(parse_absolute_time("20000101Z", &t), 0); + ASSERT_U64_EQ(t, 946684800); + ASSERT_INT_EQ(parse_absolute_time("200001011223Z", &t), 0); + ASSERT_U64_EQ(t, 946729380); + ASSERT_INT_EQ(parse_absolute_time("20000101122345Z", &t), 0); + ASSERT_U64_EQ(t, 946729425); + ASSERT_INT_EQ(parse_absolute_time("20000101UTC", &t), 0); + ASSERT_U64_EQ(t, 946684800); + ASSERT_INT_EQ(parse_absolute_time("200001011223UTC", &t), 0); + ASSERT_U64_EQ(t, 946729380); + ASSERT_INT_EQ(parse_absolute_time("20000101122345UTC", &t), 0); + ASSERT_U64_EQ(t, 946729425); + + /* Bad month */ + ASSERT_INT_EQ(parse_absolute_time("20001301", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000001", &t), + SSH_ERR_INVALID_FORMAT); + /* Incomplete */ + ASSERT_INT_EQ(parse_absolute_time("2", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("2000", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("200001", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("2000010", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("200001010", &t), + SSH_ERR_INVALID_FORMAT); + /* Bad day, hour, minute, second */ + ASSERT_INT_EQ(parse_absolute_time("20000199", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("200001019900", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("200001010099", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000101000099", &t), + SSH_ERR_INVALID_FORMAT); + /* Invalid TZ specifier */ + ASSERT_INT_EQ(parse_absolute_time("20000101ZZ", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000101PDT", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000101U", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000101UTCUTC", &t), + SSH_ERR_INVALID_FORMAT); + + TEST_DONE(); +} diff --git a/regress/unittests/misc/test_expand.c b/regress/unittests/misc/test_expand.c new file mode 100644 index 0000000..6f2cd8a --- /dev/null +++ b/regress/unittests/misc/test_expand.c @@ -0,0 +1,89 @@ +/* $OpenBSD: test_expand.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for misc string expansion functions. + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" + +void test_expand(void); + +void +test_expand(void) +{ + int parseerr; + char *ret; + + TEST_START("dollar_expand"); + ASSERT_INT_EQ(setenv("FOO", "bar", 1), 0); + ASSERT_INT_EQ(setenv("BAR", "baz", 1), 0); + (void)unsetenv("BAZ"); +#define ASSERT_DOLLAR_EQ(x, y) do { \ + char *str = dollar_expand(NULL, (x)); \ + ASSERT_STRING_EQ(str, (y)); \ + free(str); \ +} while(0) + ASSERT_DOLLAR_EQ("${FOO}", "bar"); + ASSERT_DOLLAR_EQ(" ${FOO}", " bar"); + ASSERT_DOLLAR_EQ("${FOO} ", "bar "); + ASSERT_DOLLAR_EQ(" ${FOO} ", " bar "); + ASSERT_DOLLAR_EQ("${FOO}${BAR}", "barbaz"); + ASSERT_DOLLAR_EQ(" ${FOO} ${BAR}", " bar baz"); + ASSERT_DOLLAR_EQ("${FOO}${BAR} ", "barbaz "); + ASSERT_DOLLAR_EQ(" ${FOO} ${BAR} ", " bar baz "); + ASSERT_DOLLAR_EQ("$", "$"); + ASSERT_DOLLAR_EQ(" $", " $"); + ASSERT_DOLLAR_EQ("$ ", "$ "); + + /* suppress error messages for error handing tests */ + log_init("test_misc", SYSLOG_LEVEL_QUIET, SYSLOG_FACILITY_AUTH, 1); + /* error checking, non existent variable */ + ret = dollar_expand(&parseerr, "a${BAZ}"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0); + ret = dollar_expand(&parseerr, "${BAZ}b"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0); + ret = dollar_expand(&parseerr, "a${BAZ}b"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0); + /* invalid format */ + ret = dollar_expand(&parseerr, "${"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); + ret = dollar_expand(&parseerr, "${F"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); + ret = dollar_expand(&parseerr, "${FO"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); + /* empty variable name */ + ret = dollar_expand(&parseerr, "${}"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); + /* restore loglevel to default */ + log_init("test_misc", SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 1); + TEST_DONE(); + + TEST_START("percent_expand"); + ASSERT_STRING_EQ(percent_expand("%%", "%h", "foo", NULL), "%"); + ASSERT_STRING_EQ(percent_expand("%h", "h", "foo", NULL), "foo"); + ASSERT_STRING_EQ(percent_expand("%h ", "h", "foo", NULL), "foo "); + ASSERT_STRING_EQ(percent_expand(" %h", "h", "foo", NULL), " foo"); + ASSERT_STRING_EQ(percent_expand(" %h ", "h", "foo", NULL), " foo "); + ASSERT_STRING_EQ(percent_expand(" %a%b ", "a", "foo", "b", "bar", NULL), + " foobar "); + TEST_DONE(); + + TEST_START("percent_dollar_expand"); + ASSERT_STRING_EQ(percent_dollar_expand("%h${FOO}", "h", "foo", NULL), + "foobar"); + TEST_DONE(); +} diff --git a/regress/unittests/misc/test_hpdelim.c b/regress/unittests/misc/test_hpdelim.c new file mode 100644 index 0000000..d423023 --- /dev/null +++ b/regress/unittests/misc/test_hpdelim.c @@ -0,0 +1,82 @@ +/* $OpenBSD: test_hpdelim.c,v 1.2 2022/02/06 22:58:33 dtucker Exp $ */ +/* + * Regress test for misc hpdelim() and co + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" +#include "xmalloc.h" + +void test_hpdelim(void); + +void +test_hpdelim(void) +{ + char *orig, *str, *cp, *port; + +#define START_STRING(x) orig = str = xstrdup(x) +#define DONE_STRING() free(orig) + + TEST_START("hpdelim host only"); + START_STRING("host"); + cp = hpdelim(&str); + ASSERT_STRING_EQ(cp, "host"); + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("hpdelim :port"); + START_STRING(":1234"); + cp = hpdelim(&str); + ASSERT_STRING_EQ(cp, ""); + ASSERT_PTR_NE(str, NULL); + port = hpdelim(&str); + ASSERT_STRING_EQ(port, "1234"); + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("hpdelim host:port"); + START_STRING("host:1234"); + cp = hpdelim(&str); + ASSERT_STRING_EQ(cp, "host"); + ASSERT_PTR_NE(str, NULL); + port = hpdelim(&str); + ASSERT_STRING_EQ(port, "1234"); + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("hpdelim [host]:port"); + START_STRING("[::1]:1234"); + cp = hpdelim(&str); + ASSERT_STRING_EQ(cp, "[::1]"); + ASSERT_PTR_NE(str, NULL); + port = hpdelim(&str); + ASSERT_STRING_EQ(port, "1234"); + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("hpdelim missing ] error"); + START_STRING("[::1:1234"); + cp = hpdelim(&str); + ASSERT_PTR_EQ(cp, NULL); + DONE_STRING(); + TEST_DONE(); + +} diff --git a/regress/unittests/misc/test_parse.c b/regress/unittests/misc/test_parse.c new file mode 100644 index 0000000..1f1ea31 --- /dev/null +++ b/regress/unittests/misc/test_parse.c @@ -0,0 +1,85 @@ +/* $OpenBSD: test_parse.c,v 1.2 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for misc user/host/URI parsing functions. + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" + +void test_parse(void); + +void +test_parse(void) +{ + int port; + char *user, *host, *path; + + TEST_START("misc_parse_user_host_path"); + ASSERT_INT_EQ(parse_user_host_path("someuser@some.host:some/path", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "some.host"); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_user_ipv4_path"); + ASSERT_INT_EQ(parse_user_host_path("someuser@1.22.33.144:some/path", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "1.22.33.144"); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_user_[ipv4]_path"); + ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:some/path", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "1.22.33.144"); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_user_[ipv4]_nopath"); + ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "1.22.33.144"); + ASSERT_STRING_EQ(path, "."); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_user_ipv6_path"); + ASSERT_INT_EQ(parse_user_host_path("someuser@[::1]:some/path", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "::1"); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_uri"); + ASSERT_INT_EQ(parse_uri("ssh", "ssh://someuser@some.host:22/some/path", + &user, &host, &port, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "some.host"); + ASSERT_INT_EQ(port, 22); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); +} diff --git a/regress/unittests/misc/test_ptimeout.c b/regress/unittests/misc/test_ptimeout.c new file mode 100644 index 0000000..cc58ee8 --- /dev/null +++ b/regress/unittests/misc/test_ptimeout.c @@ -0,0 +1,91 @@ +/* $OpenBSD: test_ptimeout.c,v 1.1 2023/01/06 02:59:50 djm Exp $ */ +/* + * Regress test for misc poll/ppoll timeout helpers. + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_POLL_H +# include <poll.h> +#endif +#include <time.h> + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" + +void test_ptimeout(void); + +void +test_ptimeout(void) +{ + struct timespec pt, *ts; + + TEST_START("ptimeout_init"); + ptimeout_init(&pt); + ASSERT_PTR_EQ(ptimeout_get_tsp(&pt), NULL); + ASSERT_INT_EQ(ptimeout_get_ms(&pt), -1); + TEST_DONE(); + + TEST_START("ptimeout_deadline_sec"); + ptimeout_deadline_sec(&pt, 100); + ptimeout_deadline_sec(&pt, 200); + ASSERT_INT_EQ(ptimeout_get_ms(&pt), 100 * 1000); + ts = ptimeout_get_tsp(&pt); + ASSERT_PTR_NE(ts, NULL); + ASSERT_LONG_EQ(ts->tv_nsec, 0); + ASSERT_LONG_EQ(ts->tv_sec, 100); + TEST_DONE(); + + TEST_START("ptimeout_deadline_ms"); + ptimeout_deadline_ms(&pt, 50123); + ptimeout_deadline_ms(&pt, 50500); + ASSERT_INT_EQ(ptimeout_get_ms(&pt), 50123); + ts = ptimeout_get_tsp(&pt); + ASSERT_PTR_NE(ts, NULL); + ASSERT_LONG_EQ(ts->tv_nsec, 123 * 1000000); + ASSERT_LONG_EQ(ts->tv_sec, 50); + TEST_DONE(); + + TEST_START("ptimeout zero"); + ptimeout_init(&pt); + ptimeout_deadline_ms(&pt, 0); + ASSERT_INT_EQ(ptimeout_get_ms(&pt), 0); + ts = ptimeout_get_tsp(&pt); + ASSERT_PTR_NE(ts, NULL); + ASSERT_LONG_EQ(ts->tv_nsec, 0); + ASSERT_LONG_EQ(ts->tv_sec, 0); + TEST_DONE(); + + TEST_START("ptimeout_deadline_monotime"); + ptimeout_init(&pt); + ptimeout_deadline_monotime(&pt, monotime() + 100); + ASSERT_INT_GT(ptimeout_get_ms(&pt), 50000); + ASSERT_INT_LT(ptimeout_get_ms(&pt), 200000); + ts = ptimeout_get_tsp(&pt); + ASSERT_PTR_NE(ts, NULL); + ASSERT_LONG_GT(ts->tv_sec, 50); + ASSERT_LONG_LT(ts->tv_sec, 200); + TEST_DONE(); + + TEST_START("ptimeout_deadline_monotime past"); + ptimeout_init(&pt); + ptimeout_deadline_monotime(&pt, monotime() + 100); + ptimeout_deadline_monotime(&pt, monotime() - 100); + ASSERT_INT_EQ(ptimeout_get_ms(&pt), 0); + ts = ptimeout_get_tsp(&pt); + ASSERT_PTR_NE(ts, NULL); + ASSERT_LONG_EQ(ts->tv_nsec, 0); + ASSERT_LONG_EQ(ts->tv_sec, 0); + TEST_DONE(); +} diff --git a/regress/unittests/misc/test_strdelim.c b/regress/unittests/misc/test_strdelim.c new file mode 100644 index 0000000..f7bea4b --- /dev/null +++ b/regress/unittests/misc/test_strdelim.c @@ -0,0 +1,201 @@ +/* $OpenBSD: test_strdelim.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for misc strdelim() and co + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" +#include "xmalloc.h" + +void test_strdelim(void); + +void +test_strdelim(void) +{ + char *orig, *str, *cp; + +#define START_STRING(x) orig = str = xstrdup(x) +#define DONE_STRING() free(orig) + + TEST_START("empty"); + START_STRING(""); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, ""); /* XXX arguable */ + cp = strdelim(&str); + ASSERT_PTR_EQ(cp, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("whitespace"); + START_STRING(" "); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ + ASSERT_STRING_EQ(str, ""); + DONE_STRING(); + TEST_DONE(); + + TEST_START("trivial"); + START_STRING("blob"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob"); + cp = strdelim(&str); + ASSERT_PTR_EQ(cp, NULL); + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("trivial whitespace"); + START_STRING("blob "); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob"); + ASSERT_STRING_EQ(str, ""); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("multi"); + START_STRING("blob1 blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob1"); + ASSERT_STRING_EQ(str, "blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob2"); + ASSERT_PTR_EQ(str, NULL); + cp = strdelim(&str); + ASSERT_PTR_EQ(cp, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("multi whitespace"); + START_STRING("blob1 blob2 "); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob1"); + ASSERT_STRING_EQ(str, "blob2 "); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("multi equals"); + START_STRING("blob1=blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob1"); + ASSERT_STRING_EQ(str, "blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob2"); + ASSERT_PTR_EQ(str, NULL); + cp = strdelim(&str); + ASSERT_PTR_EQ(cp, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("multi too many equals"); + START_STRING("blob1==blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob1"); /* XXX better returning NULL early */ + ASSERT_STRING_EQ(str, "=blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, ""); + ASSERT_STRING_EQ(str, "blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob2"); /* XXX should (but can't) reject */ + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("multi equals strdelimw"); + START_STRING("blob1=blob2"); + cp = strdelimw(&str); + ASSERT_STRING_EQ(cp, "blob1=blob2"); + ASSERT_PTR_EQ(str, NULL); + cp = strdelimw(&str); + ASSERT_PTR_EQ(cp, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("quoted"); + START_STRING("\"blob\""); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("quoted multi"); + START_STRING("\"blob1\" blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob1"); + ASSERT_STRING_EQ(str, "blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob2"); + ASSERT_PTR_EQ(str, NULL); + cp = strdelim(&str); + ASSERT_PTR_EQ(cp, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("quoted multi reverse"); + START_STRING("blob1 \"blob2\""); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob1"); + ASSERT_STRING_EQ(str, "\"blob2\""); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob2"); + ASSERT_STRING_EQ(str, ""); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */ + ASSERT_PTR_EQ(str, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("quoted multi middle"); + START_STRING("blob1 \"blob2\" blob3"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob1"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob2"); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob3"); + cp = strdelim(&str); + ASSERT_PTR_EQ(cp, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("badquote"); + START_STRING("\"blob"); + cp = strdelim(&str); + ASSERT_PTR_EQ(cp, NULL); + DONE_STRING(); + TEST_DONE(); + + TEST_START("oops quote"); + START_STRING("\"blob\\\""); + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, "blob\\"); /* XXX wrong */ + cp = strdelim(&str); + ASSERT_STRING_EQ(cp, ""); + DONE_STRING(); + TEST_DONE(); + +} diff --git a/regress/unittests/misc/tests.c b/regress/unittests/misc/tests.c new file mode 100644 index 0000000..3269954 --- /dev/null +++ b/regress/unittests/misc/tests.c @@ -0,0 +1,41 @@ +/* $OpenBSD: tests.c,v 1.10 2023/01/06 02:59:50 djm Exp $ */ +/* + * Regress test for misc helper functions. + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" + +void test_parse(void); +void test_convtime(void); +void test_expand(void); +void test_argv(void); +void test_strdelim(void); +void test_hpdelim(void); +void test_ptimeout(void); + +void +tests(void) +{ + test_parse(); + test_convtime(); + test_expand(); + test_argv(); + test_strdelim(); + test_hpdelim(); + test_ptimeout(); +} diff --git a/regress/unittests/sshbuf/Makefile b/regress/unittests/sshbuf/Makefile new file mode 100644 index 0000000..a8ddfaf --- /dev/null +++ b/regress/unittests/sshbuf/Makefile @@ -0,0 +1,22 @@ +# $OpenBSD: Makefile,v 1.10 2021/01/09 12:24:31 dtucker Exp $ + +# $OpenBSD: Makefile,v 1.8 2020/01/26 00:09:50 djm Exp $ + +PROG=test_sshbuf +SRCS=tests.c +SRCS+=test_sshbuf.c +SRCS+=test_sshbuf_getput_basic.c +SRCS+=test_sshbuf_getput_crypto.c +SRCS+=test_sshbuf_misc.c +SRCS+=test_sshbuf_fuzz.c +SRCS+=test_sshbuf_getput_fuzz.c +SRCS+=test_sshbuf_fixed.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=sshbuf-io.c atomicio.c misc.c xmalloc.c log.c fatal.c ssherr.c cleanup.c +SRCS+=match.c addr.c addrmatch.c + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} + diff --git a/regress/unittests/sshbuf/test_sshbuf.c b/regress/unittests/sshbuf/test_sshbuf.c new file mode 100644 index 0000000..e22b390 --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf.c @@ -0,0 +1,243 @@ +/* $OpenBSD: test_sshbuf.c,v 1.2 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#define SSHBUF_INTERNAL 1 /* access internals for testing */ +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "sshbuf.h" + +void sshbuf_tests(void); + +#ifndef roundup +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#endif + +void +sshbuf_tests(void) +{ + struct sshbuf *p1; + const u_char *cdp; + u_char *dp; + size_t sz; + int r; + + TEST_START("allocate sshbuf"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + TEST_DONE(); + + TEST_START("max size on fresh buffer"); + ASSERT_SIZE_T_GT(sshbuf_max_size(p1), 0); + TEST_DONE(); + + TEST_START("available on fresh buffer"); + ASSERT_SIZE_T_GT(sshbuf_avail(p1), 0); + TEST_DONE(); + + TEST_START("len = 0 on empty buffer"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + TEST_DONE(); + + TEST_START("set valid max size"); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 65536), 0); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 65536); + TEST_DONE(); + + TEST_START("available on limited buffer"); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 65536); + TEST_DONE(); + + TEST_START("free"); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("consume on empty buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0); + ASSERT_INT_EQ(sshbuf_consume(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("consume_end on empty buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 0), 0); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("reserve space"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + r = sshbuf_reserve(p1, 1, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + *dp = 0x11; + r = sshbuf_reserve(p1, 3, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + *dp++ = 0x22; + *dp++ = 0x33; + *dp++ = 0x44; + TEST_DONE(); + + TEST_START("sshbuf_len on filled buffer"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + TEST_DONE(); + + TEST_START("sshbuf_ptr on filled buffer"); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(cdp, NULL); + ASSERT_U8_EQ(cdp[0], 0x11); + ASSERT_U8_EQ(cdp[1], 0x22); + ASSERT_U8_EQ(cdp[2], 0x33); + ASSERT_U8_EQ(cdp[3], 0x44); + TEST_DONE(); + + TEST_START("consume on filled buffer"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + r = sshbuf_consume(p1, 64); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(p1, NULL); + ASSERT_U8_EQ(cdp[0], 0x22); + ASSERT_INT_EQ(sshbuf_consume(p1, 2), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(p1, NULL); + ASSERT_U8_EQ(cdp[0], 0x44); + r = sshbuf_consume(p1, 2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + r = sshbuf_consume(p1, 1); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("consume_end on filled buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + r = sshbuf_reserve(p1, 4, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + *dp++ = 0x11; + *dp++ = 0x22; + *dp++ = 0x33; + *dp++ = 0x44; + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + r = sshbuf_consume_end(p1, 5); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 3), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(cdp, NULL); + ASSERT_U8_EQ(*cdp, 0x11); + r = sshbuf_consume_end(p1, 2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("fill limited buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223); + r = sshbuf_reserve(p1, 1223, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + memset(dp, 0xd7, 1223); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0); + r = sshbuf_reserve(p1, 1, &dp); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_PTR_EQ(dp, NULL); + TEST_DONE(); + + TEST_START("consume and force compaction"); + ASSERT_INT_EQ(sshbuf_consume(p1, 223), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223); + r = sshbuf_reserve(p1, 224, &dp); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_PTR_EQ(dp, NULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223); + r = sshbuf_reserve(p1, 223, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + memset(dp, 0x7d, 223); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(cdp, NULL); + ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000); + ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223); + TEST_DONE(); + + TEST_START("resize full buffer"); + r = sshbuf_set_max_size(p1, 1000); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + sz = roundup(1223 + SSHBUF_SIZE_INC * 3, SSHBUF_SIZE_INC); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sz), 0); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - 1223); + ASSERT_INT_EQ(sshbuf_len(p1), 1223); + TEST_DONE(); + + /* NB. uses sshbuf internals */ + TEST_START("alloc chunking"); + r = sshbuf_reserve(p1, 1, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + *dp = 0xff; + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(cdp, NULL); + ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000); + ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223); + ASSERT_MEM_FILLED_EQ(cdp + 1223, 0xff, 1); + ASSERT_SIZE_T_EQ(sshbuf_alloc(p1) % SSHBUF_SIZE_INC, 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("reset buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223); + r = sshbuf_reserve(p1, 1223, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + memset(dp, 0xd7, 1223); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223); + sshbuf_reset(p1); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223); + sshbuf_free(p1); + TEST_DONE(); +} diff --git a/regress/unittests/sshbuf/test_sshbuf_fixed.c b/regress/unittests/sshbuf/test_sshbuf_fixed.c new file mode 100644 index 0000000..dff77f0 --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_fixed.c @@ -0,0 +1,125 @@ +/* $OpenBSD: test_sshbuf_fixed.c,v 1.2 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#define SSHBUF_INTERNAL 1 /* access internals for testing */ +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "sshbuf.h" +#include "ssherr.h" + +void sshbuf_fixed(void); + +const u_char test_buf[] = "\x01\x12\x34\x56\x78\x00\x00\x00\x05hello"; + +void +sshbuf_fixed(void) +{ + struct sshbuf *p1, *p2, *p3; + u_char c; + char *s; + u_int i; + size_t l; + + TEST_START("sshbuf_from"); + p1 = sshbuf_from(test_buf, sizeof(test_buf)); + ASSERT_PTR_NE(p1, NULL); + ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL); + ASSERT_INT_EQ(sshbuf_check_reserve(p1, 1), SSH_ERR_BUFFER_READ_ONLY); + ASSERT_INT_EQ(sshbuf_reserve(p1, 1, NULL), SSH_ERR_BUFFER_READ_ONLY); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 200), SSH_ERR_BUFFER_READ_ONLY); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), SSH_ERR_BUFFER_READ_ONLY); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_from data"); + p1 = sshbuf_from(test_buf, sizeof(test_buf) - 1); + ASSERT_PTR_NE(p1, NULL); + ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf); + ASSERT_INT_EQ(sshbuf_get_u8(p1, &c), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 1); + ASSERT_U8_EQ(c, 1); + ASSERT_INT_EQ(sshbuf_get_u32(p1, &i), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 5); + ASSERT_U32_EQ(i, 0x12345678); + ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s, &l), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + ASSERT_STRING_EQ(s, "hello"); + ASSERT_SIZE_T_EQ(l, 5); + sshbuf_free(p1); + free(s); + TEST_DONE(); + + TEST_START("sshbuf_fromb "); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1); + ASSERT_PTR_EQ(sshbuf_parent(p1), NULL); + ASSERT_INT_EQ(sshbuf_put(p1, test_buf, sizeof(test_buf) - 1), 0); + p2 = sshbuf_fromb(p1); + ASSERT_PTR_NE(p2, NULL); + ASSERT_U_INT_EQ(sshbuf_refcount(p1), 2); + ASSERT_PTR_EQ(sshbuf_parent(p1), NULL); + ASSERT_PTR_EQ(sshbuf_parent(p2), p1); + ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1)); + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_PTR_NE(sshbuf_ptr(p2), NULL); + ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL); + ASSERT_PTR_EQ(sshbuf_mutable_ptr(p2), NULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sshbuf_len(p2)); + ASSERT_INT_EQ(sshbuf_get_u8(p2, &c), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 1); + ASSERT_U8_EQ(c, 1); + ASSERT_INT_EQ(sshbuf_get_u32(p2, &i), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 5); + ASSERT_U32_EQ(i, 0x12345678); + ASSERT_INT_EQ(sshbuf_get_cstring(p2, &s, &l), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0); + ASSERT_STRING_EQ(s, "hello"); + ASSERT_SIZE_T_EQ(l, 5); + sshbuf_free(p1); + ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1); + sshbuf_free(p2); + free(s); + TEST_DONE(); + + TEST_START("sshbuf_froms"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x01), 0); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0); + ASSERT_INT_EQ(sshbuf_put_cstring(p1, "hello"), 0); + p2 = sshbuf_new(); + ASSERT_PTR_NE(p2, NULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(test_buf) - 1); + ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p2), sizeof(test_buf) + 4 - 1); + ASSERT_INT_EQ(sshbuf_froms(p2, &p3), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0); + ASSERT_PTR_NE(p3, NULL); + ASSERT_PTR_NE(sshbuf_ptr(p3), NULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p3), sizeof(test_buf) - 1); + ASSERT_MEM_EQ(sshbuf_ptr(p3), test_buf, sizeof(test_buf) - 1); + sshbuf_free(p3); + ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0); + ASSERT_INT_EQ(sshbuf_consume_end(p2, 1), 0); + ASSERT_INT_EQ(sshbuf_froms(p2, &p3), SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_PTR_EQ(p3, NULL); + sshbuf_free(p2); + sshbuf_free(p1); +} diff --git a/regress/unittests/sshbuf/test_sshbuf_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_fuzz.c new file mode 100644 index 0000000..c0b809d --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_fuzz.c @@ -0,0 +1,131 @@ +/* $OpenBSD: test_sshbuf_fuzz.c,v 1.4 2021/12/18 06:53:59 anton Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "sshbuf.h" + +#define NUM_FUZZ_TESTS (1 << 18) + +void sshbuf_fuzz_tests(void); + +void +sshbuf_fuzz_tests(void) +{ + struct sshbuf *p1; + u_char *dp; + size_t sz, sz2, i, ntests = NUM_FUZZ_TESTS; + u_int32_t r; + int ret; + + if (test_is_fast()) + ntests >>= 2; + if (test_is_slow()) + ntests <<= 2; + + /* NB. uses sshbuf internals */ + TEST_START("fuzz alloc/dealloc"); + p1 = sshbuf_new(); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0); + ASSERT_PTR_NE(p1, NULL); + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); + for (i = 0; i < ntests; i++) { + r = arc4random_uniform(10); + if (r == 0) { + /* 10% chance: small reserve */ + r = arc4random_uniform(10); + fuzz_reserve: + sz = sshbuf_avail(p1); + sz2 = sshbuf_len(p1); + ret = sshbuf_reserve(p1, r, &dp); + if (ret < 0) { + ASSERT_PTR_EQ(dp, NULL); + ASSERT_SIZE_T_LT(sz, r); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); + } else { + ASSERT_PTR_NE(dp, NULL); + ASSERT_SIZE_T_GE(sz, r); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r); + memset(dp, arc4random_uniform(255) + 1, r); + } + } else if (r < 3) { + /* 20% chance: big reserve */ + r = arc4random_uniform(8 * 1024); + goto fuzz_reserve; + } else if (r == 3) { + /* 10% chance: small consume */ + r = arc4random_uniform(10); + fuzz_consume: + sz = sshbuf_avail(p1); + sz2 = sshbuf_len(p1); + /* 50% change consume from end, otherwise start */ + ret = ((arc4random() & 1) ? + sshbuf_consume : sshbuf_consume_end)(p1, r); + if (ret < 0) { + ASSERT_SIZE_T_LT(sz2, r); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); + } else { + ASSERT_SIZE_T_GE(sz2, r); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r); + } + } else if (r < 8) { + /* 40% chance: big consume */ + r = arc4random_uniform(2 * 1024); + goto fuzz_consume; + } else if (r == 8) { + /* 10% chance: reset max size */ + r = arc4random_uniform(16 * 1024); + sz = sshbuf_max_size(p1); + if (sshbuf_set_max_size(p1, r) < 0) + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); + else + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r); + } else { + if (arc4random_uniform(8192) == 0) { + /* tiny chance: new buffer */ + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); + sshbuf_free(p1); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, + 16 * 1024), 0); + } else { + /* Almost 10%: giant reserve */ + /* use arc4random_buf for r > 2^32 on 64 bit */ + arc4random_buf(&r, sizeof(r)); + while (r < SSHBUF_SIZE_MAX / 2) { + r <<= 1; + r |= arc4random() & 1; + } + goto fuzz_reserve; + } + } + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024); + } + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); + sshbuf_free(p1); + TEST_DONE(); +} diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_basic.c b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c new file mode 100644 index 0000000..3da413e --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c @@ -0,0 +1,712 @@ +/* $OpenBSD: test_sshbuf_getput_basic.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" +#include "ssherr.h" +#include "sshbuf.h" + +void sshbuf_getput_basic_tests(void); + +void +sshbuf_getput_basic_tests(void) +{ + struct sshbuf *p1, *p2; + const u_char *cd; + u_char *d, d2[32], x[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x99 + }; + u_int64_t v64; + u_int32_t v32; + u_int16_t v16; + u_char v8; + size_t s; + char *s2; + int r; + u_char bn1[] = { 0x00, 0x00, 0x00 }; + u_char bn2[] = { 0x00, 0x00, 0x01, 0x02 }; + u_char bn3[] = { 0x00, 0x80, 0x09 }; + u_char bn_exp1[] = { 0x00, 0x00, 0x00, 0x00 }; + u_char bn_exp2[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 0x02 }; + u_char bn_exp3[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x80, 0x09 }; + + TEST_START("PEEK_U64"); + ASSERT_U64_EQ(PEEK_U64(x), 0x1122334455667788ULL); + TEST_DONE(); + + TEST_START("PEEK_U32"); + ASSERT_U32_EQ(PEEK_U32(x), 0x11223344); + TEST_DONE(); + + TEST_START("PEEK_U16"); + ASSERT_U16_EQ(PEEK_U16(x), 0x1122); + TEST_DONE(); + + TEST_START("POKE_U64"); + bzero(d2, sizeof(d2)); + POKE_U64(d2, 0x1122334455667788ULL); + ASSERT_MEM_EQ(d2, x, 8); + TEST_DONE(); + + TEST_START("POKE_U32"); + bzero(d2, sizeof(d2)); + POKE_U32(d2, 0x11223344); + ASSERT_MEM_EQ(d2, x, 4); + TEST_DONE(); + + TEST_START("POKE_U16"); + bzero(d2, sizeof(d2)); + POKE_U16(d2, 0x1122); + ASSERT_MEM_EQ(d2, x, 2); + TEST_DONE(); + + TEST_START("sshbuf_put"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 5), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5); + cd = sshbuf_ptr(p1); + ASSERT_PTR_NE(cd, NULL); + ASSERT_U8_EQ(cd[0], 0x11); + ASSERT_U8_EQ(cd[1], 0x22); + ASSERT_U8_EQ(cd[2], 0x33); + ASSERT_U8_EQ(cd[3], 0x44); + ASSERT_U8_EQ(cd[4], 0x55); + TEST_DONE(); + + TEST_START("sshbuf_get"); + ASSERT_INT_EQ(sshbuf_get(p1, d2, 4), 0); + ASSERT_MEM_EQ(d2, x, 4); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55); + TEST_DONE(); + + TEST_START("sshbuf_get truncated"); + r = sshbuf_get(p1, d2, 4); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55); + TEST_DONE(); + + TEST_START("sshbuf_put truncated"); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0); + r = sshbuf_put(p1, x, 5); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_u64"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10); + ASSERT_INT_EQ(sshbuf_get_u64(p1, &v64), 0); + ASSERT_U64_EQ(v64, 0x1122334455667788ULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + TEST_DONE(); + + TEST_START("sshbuf_get_u64 truncated"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + r = sshbuf_get_u64(p1, &v64); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_u32"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10); + ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0); + ASSERT_U32_EQ(v32, 0x11223344); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 6); + ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0); + ASSERT_U32_EQ(v32, 0x55667788); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + TEST_DONE(); + + TEST_START("sshbuf_get_u32 truncated"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + r = sshbuf_get_u32(p1, &v32); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_u16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 9), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 9); + ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); + ASSERT_U16_EQ(v16, 0x1122); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 7); + ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); + ASSERT_U16_EQ(v16, 0x3344); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5); + ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); + ASSERT_U16_EQ(v16, 0x5566); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3); + ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); + ASSERT_U16_EQ(v16, 0x7788); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + TEST_DONE(); + + TEST_START("sshbuf_get_u16 truncated"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + r = sshbuf_get_u16(p1, &v16); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_u8"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 2), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0); + ASSERT_U8_EQ(v8, 0x11); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0); + ASSERT_U8_EQ(v8, 0x22); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + TEST_DONE(); + + TEST_START("sshbuf_get_u8 truncated"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + r = sshbuf_get_u8(p1, &v8); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u64"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u64 exact"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 8), 0); + ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u64 limited"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 7), 0); + r = sshbuf_put_u64(p1, 0x1122334455667788ULL); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u32"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u32 exact"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u32 limited"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 3), 0); + r = sshbuf_put_u32(p1, 0x11223344); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 2), 0); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u16 limited"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1), 0); + r = sshbuf_put_u16(p1, 0x1122); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_string"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 + 4); + ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0); + ASSERT_SIZE_T_EQ(s, sizeof(x)); + ASSERT_MEM_EQ(d, x, sizeof(x)); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + free(d); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_string exact"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4), 0); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0); + ASSERT_SIZE_T_EQ(s, sizeof(x)); + ASSERT_MEM_EQ(d, x, sizeof(x)); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + free(d); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_string truncated"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3); + r = sshbuf_get_string(p1, &d, &s); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_string giant"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + r = sshbuf_get_string(p1, &d, &s); + ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_cstring giant"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + r = sshbuf_get_cstring(p1, &s2, &s); + ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_cstring embedded \\0"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + r = sshbuf_get_cstring(p1, &s2, NULL); + ASSERT_INT_EQ(r, SSH_ERR_INVALID_FORMAT); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_cstring trailing \\0"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x) - 1), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x) - 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 - 1); + ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s2, &s), 0); + ASSERT_SIZE_T_EQ(s, sizeof(x) - 1); + ASSERT_MEM_EQ(s2, x, s); + free(s2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_string"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_string(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), sizeof(x)); + ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, x, sizeof(x)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_string limited"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4 - 1), 0); + r = sshbuf_put_string(p1, x, sizeof(x)); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_string giant"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + r = sshbuf_put_string(p1, (void *)0x01, 0xfffffffc); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_putf"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + r = sshbuf_putf(p1, "%s %d %x", "hello", 23, 0x5f); + ASSERT_INT_EQ(r, 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 11); + ASSERT_MEM_EQ(sshbuf_ptr(p1), "hello 23 5f", 11); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_putb"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + p2 = sshbuf_new(); + ASSERT_PTR_NE(p2, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, "blahblahblah", 12), 0); + ASSERT_INT_EQ(sshbuf_putb(p2, p1), 0); + sshbuf_free(p1); + ASSERT_SIZE_T_EQ(sshbuf_len(p2), 12); + ASSERT_MEM_EQ(sshbuf_ptr(p2), "blahblahblah", 12); + sshbuf_free(p2); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes empty buf"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, NULL, 0), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes all zeroes"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn1, sizeof(bn1)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes simple"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2+2, sizeof(bn2)-2), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes leading zero"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2, sizeof(bn2)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes neg"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3+1, sizeof(bn3)-1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes neg and leading zero"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3, sizeof(bn3)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_peek_u64"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_peek_u64(p1, 0, &v64), 0); + ASSERT_U64_EQ(v64, 0x1122334455667788ULL); + ASSERT_INT_EQ(sshbuf_peek_u64(p1, 2, &v64), 0); + ASSERT_U64_EQ(v64, 0x3344556677880099ULL); + ASSERT_INT_EQ(sshbuf_peek_u64(p1, 3, &v64), SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_peek_u64(p1, sizeof(x), &v64), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_peek_u64(p1, 1000, &v64), + SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_peek_u32"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_peek_u32(p1, 0, &v32), 0); + ASSERT_U32_EQ(v32, 0x11223344); + ASSERT_INT_EQ(sshbuf_peek_u32(p1, 6, &v32), 0); + ASSERT_U32_EQ(v32, 0x77880099); + ASSERT_INT_EQ(sshbuf_peek_u32(p1, 7, &v32), SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_peek_u32(p1, sizeof(x), &v32), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_peek_u32(p1, 1000, &v32), + SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_peek_u16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_peek_u16(p1, 0, &v16), 0); + ASSERT_U16_EQ(v16, 0x1122); + ASSERT_INT_EQ(sshbuf_peek_u16(p1, 8, &v16), 0); + ASSERT_U16_EQ(v16, 0x99); + ASSERT_INT_EQ(sshbuf_peek_u16(p1, 9, &v16), SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_peek_u16(p1, sizeof(x), &v16), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_peek_u16(p1, 1000, &v16), + SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_peek_u8"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_peek_u8(p1, 0, &v8), 0); + ASSERT_U8_EQ(v8, 0x11); + ASSERT_INT_EQ(sshbuf_peek_u8(p1, 9, &v8), 0); + ASSERT_U8_EQ(v8, 0x99); + ASSERT_INT_EQ(sshbuf_peek_u8(p1, sizeof(x), &v8), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_peek_u8(p1, 1000, &v8), + SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_poke_u64"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke at start of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u64(p1, 0, 0xa1b2c3d4e5f60718ULL), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "a1b2c3d4e5f607180000"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke aligned with end of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u64(p1, 2, 0xa1b2c3d4e5f60718ULL), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "0000a1b2c3d4e5f60718"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke past end of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u64(p1, 3, 0xa1b2c3d4e5f60718ULL), + SSH_ERR_NO_BUFFER_SPACE); + ASSERT_INT_EQ(sshbuf_poke_u64(p1, 10, 0xa1b2c3d4e5f60718ULL), + SSH_ERR_NO_BUFFER_SPACE); + ASSERT_INT_EQ(sshbuf_poke_u64(p1, 1000, 0xa1b2c3d4e5f60718ULL), + SSH_ERR_NO_BUFFER_SPACE); + /* ensure failed pokes do not modify buffer */ + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "00000000000000000000"); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_poke_u32"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke at start of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u32(p1, 0, 0xa1b2c3d4), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "a1b2c3d4000000000000"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke aligned with end of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u32(p1, 6, 0xa1b2c3d4), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "000000000000a1b2c3d4"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke past end of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u32(p1, 7, 0xa1b2c3d4), + SSH_ERR_NO_BUFFER_SPACE); + ASSERT_INT_EQ(sshbuf_poke_u32(p1, 10, 0xa1b2c3d4), + SSH_ERR_NO_BUFFER_SPACE); + ASSERT_INT_EQ(sshbuf_poke_u32(p1, 1000, 0xa1b2c3d4), + SSH_ERR_NO_BUFFER_SPACE); + /* ensure failed pokes do not modify buffer */ + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "00000000000000000000"); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_poke_u16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke at start of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u16(p1, 0, 0xa1b2), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "a1b20000000000000000"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke aligned with end of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u16(p1, 8, 0xa1b2), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "0000000000000000a1b2"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke past end of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u16(p1, 9, 0xa1b2), + SSH_ERR_NO_BUFFER_SPACE); + ASSERT_INT_EQ(sshbuf_poke_u16(p1, 10, 0xa1b2), + SSH_ERR_NO_BUFFER_SPACE); + ASSERT_INT_EQ(sshbuf_poke_u16(p1, 1000, 0xa1b2), + SSH_ERR_NO_BUFFER_SPACE); + /* ensure failed pokes do not modify buffer */ + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "00000000000000000000"); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_poke_u8"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke at start of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u8(p1, 0, 0xa1), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "a1000000000000000000"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke aligned with end of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u8(p1, 9, 0xa1), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "000000000000000000a1"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke past end of buffer */ + ASSERT_INT_EQ(sshbuf_poke_u8(p1, 10, 0xa1), SSH_ERR_NO_BUFFER_SPACE); + ASSERT_INT_EQ(sshbuf_poke_u8(p1, 1000, 0xa1), SSH_ERR_NO_BUFFER_SPACE); + /* ensure failed pokes do not modify buffer */ + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "00000000000000000000"); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_poke"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke at start of buffer */ + ASSERT_INT_EQ(sshbuf_poke(p1, 0, "hello!", 6), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "68656c6c6f2100000000"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke aligned with end of buffer */ + ASSERT_INT_EQ(sshbuf_poke(p1, 4, "hello!", 6), 0); + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "0000000068656c6c6f21"); + free(s2); + sshbuf_reset(p1); + ASSERT_INT_EQ(sshbuf_reserve(p1, 10, NULL), 0); + /* poke past end of buffer */ + ASSERT_INT_EQ(sshbuf_poke(p1, 7, "hello!", 6), + SSH_ERR_NO_BUFFER_SPACE); + ASSERT_INT_EQ(sshbuf_poke(p1, 10, "hello!", 6), + SSH_ERR_NO_BUFFER_SPACE); + ASSERT_INT_EQ(sshbuf_poke(p1, 1000, "hello!", 6), + SSH_ERR_NO_BUFFER_SPACE); + /* ensure failed pokes do not modify buffer */ + s2 = sshbuf_dtob16(p1); + ASSERT_PTR_NE(s2, NULL); + ASSERT_STRING_EQ(s2, "00000000000000000000"); + sshbuf_free(p1); + TEST_DONE(); +} diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c new file mode 100644 index 0000000..e3620e9 --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c @@ -0,0 +1,280 @@ +/* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#ifdef WITH_OPENSSL + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include <openssl/bn.h> +#include <openssl/objects.h> +#ifdef OPENSSL_HAS_NISTP256 +# include <openssl/ec.h> +#endif + +#include "../test_helper/test_helper.h" +#include "ssherr.h" +#include "sshbuf.h" + +void sshbuf_getput_crypto_tests(void); + +void +sshbuf_getput_crypto_tests(void) +{ + struct sshbuf *p1; + BIGNUM *bn, *bn2; + const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10"; + /* This one has MSB set to test bignum2 encoding negative-avoidance */ + const char *hexbn2 = "f0e0d0c0b0a0908070605040302010007fff11"; + u_char expbn1[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + }; + u_char expbn2[] = { + 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, + 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, + 0x7f, 0xff, 0x11 + }; +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) + const u_char *d; + size_t s; + BIGNUM *bn_x, *bn_y; + int ec256_nid = NID_X9_62_prime256v1; + char *ec256_x = "0C828004839D0106AA59575216191357" + "34B451459DADB586677EF9DF55784999"; + char *ec256_y = "4D196B50F0B4E94B3C73E3A9D4CD9DF2" + "C8F9A35E42BDD047550F69D80EC23CD4"; + u_char expec256[] = { + 0x04, + 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06, + 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57, + 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86, + 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99, + 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b, + 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2, + 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47, + 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4 + }; + EC_KEY *eck; + EC_POINT *ecp; +#endif + int r; + +#define MKBN(b, bnn) \ + do { \ + bnn = NULL; \ + ASSERT_INT_GT(BN_hex2bn(&bnn, b), 0); \ + } while (0) + + TEST_START("sshbuf_put_bignum2"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 4); + ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn)); + ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, expbn1, sizeof(expbn1)); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2 limited"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 3), 0); + r = sshbuf_put_bignum2(p1, bn); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2 bn2"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4 + 1); /* MSB */ + ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn) + 1); + ASSERT_U8_EQ(*(sshbuf_ptr(p1) + 4), 0x00); + ASSERT_MEM_EQ(sshbuf_ptr(p1) + 5, expbn2, sizeof(expbn2)); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2 bn2 limited"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn2) + 3), 0); + r = sshbuf_put_bignum2(p1, bn); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + sizeof(expbn1)); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); + bn2 = NULL; + ASSERT_INT_EQ(sshbuf_get_bignum2(p1, &bn2), 0); + ASSERT_BIGNUM_EQ(bn, bn2); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 truncated"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0); + bn2 = NULL; + r = sshbuf_get_bignum2(p1, &bn2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 3); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 giant"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 65536), 0); + ASSERT_INT_EQ(sshbuf_reserve(p1, 65536, NULL), 0); + bn2 = NULL; + r = sshbuf_get_bignum2(p1, &bn2); + ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 65536 + 4); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 bn2"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); /* MSB */ + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + 1 + sizeof(expbn2)); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); + bn2 = NULL; + ASSERT_INT_EQ(sshbuf_get_bignum2(p1, &bn2), 0); + ASSERT_BIGNUM_EQ(bn, bn2); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 bn2 truncated"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0); + bn2 = NULL; + r = sshbuf_get_bignum2(p1, &bn2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 1 + 4 - 1); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 bn2 negative"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); + bn2 = NULL; + r = sshbuf_get_bignum2(p1, &bn2); + ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_IS_NEGATIVE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) + TEST_START("sshbuf_put_ec"); + eck = EC_KEY_new_by_curve_name(ec256_nid); + ASSERT_PTR_NE(eck, NULL); + ecp = EC_POINT_new(EC_KEY_get0_group(eck)); + ASSERT_PTR_NE(ecp, NULL); + MKBN(ec256_x, bn_x); + MKBN(ec256_y, bn_y); + ASSERT_INT_EQ(EC_POINT_set_affine_coordinates_GFp( + EC_KEY_get0_group(eck), ecp, bn_x, bn_y, NULL), 1); + ASSERT_INT_EQ(EC_KEY_set_public_key(eck, ecp), 1); + BN_free(bn_x); + BN_free(bn_y); + EC_POINT_free(ecp); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_eckey(p1, eck), 0); + ASSERT_INT_EQ(sshbuf_get_string_direct(p1, &d, &s), 0); + ASSERT_SIZE_T_EQ(s, sizeof(expec256)); + ASSERT_MEM_EQ(d, expec256, sizeof(expec256)); + sshbuf_free(p1); + EC_KEY_free(eck); + TEST_DONE(); + + TEST_START("sshbuf_get_ec"); + eck = EC_KEY_new_by_curve_name(ec256_nid); + ASSERT_PTR_NE(eck, NULL); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_string(p1, expec256, sizeof(expec256)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expec256) + 4); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); + ASSERT_INT_EQ(sshbuf_get_eckey(p1, eck), 0); + bn_x = BN_new(); + bn_y = BN_new(); + ASSERT_PTR_NE(bn_x, NULL); + ASSERT_PTR_NE(bn_y, NULL); + ASSERT_INT_EQ(EC_POINT_get_affine_coordinates_GFp( + EC_KEY_get0_group(eck), EC_KEY_get0_public_key(eck), + bn_x, bn_y, NULL), 1); + MKBN(ec256_x, bn); + MKBN(ec256_y, bn2); + ASSERT_INT_EQ(BN_cmp(bn_x, bn), 0); + ASSERT_INT_EQ(BN_cmp(bn_y, bn2), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + sshbuf_free(p1); + EC_KEY_free(eck); + BN_free(bn_x); + BN_free(bn_y); + BN_free(bn); + BN_free(bn2); + TEST_DONE(); +#endif +} + +#endif /* WITH_OPENSSL */ diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c new file mode 100644 index 0000000..3b48958 --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c @@ -0,0 +1,132 @@ +/* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.5 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#include <openssl/objects.h> +#ifdef OPENSSL_HAS_NISTP256 +# include <openssl/ec.h> +#endif +#endif + +#include "../test_helper/test_helper.h" +#include "ssherr.h" +#include "sshbuf.h" + +void sshbuf_getput_fuzz_tests(void); + +static void +attempt_parse_blob(u_char *blob, size_t len) +{ + struct sshbuf *p1; +#ifdef WITH_OPENSSL + BIGNUM *bn; +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) + EC_KEY *eck; +#endif /* defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) */ +#endif /* WITH_OPENSSL */ + u_char *s; + size_t l; + u_int8_t u8; + u_int16_t u16; + u_int32_t u32; + u_int64_t u64; + + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, blob, len), 0); + sshbuf_get_u8(p1, &u8); + sshbuf_get_u16(p1, &u16); + sshbuf_get_u32(p1, &u32); + sshbuf_get_u64(p1, &u64); + if (sshbuf_get_string(p1, &s, &l) == 0) { + bzero(s, l); + free(s); + } +#ifdef WITH_OPENSSL + bn = NULL; + sshbuf_get_bignum2(p1, &bn); + BN_clear_free(bn); +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) + eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + ASSERT_PTR_NE(eck, NULL); + sshbuf_get_eckey(p1, eck); + EC_KEY_free(eck); +#endif /* defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) */ +#endif /* WITH_OPENSSL */ + sshbuf_free(p1); +} + + +static void +onerror(void *fuzz) +{ + fprintf(stderr, "Failed during fuzz:\n"); + fuzz_dump((struct fuzz *)fuzz); +} + +void +sshbuf_getput_fuzz_tests(void) +{ + u_char blob[] = { + /* u8 */ + 0xd0, + /* u16 */ + 0xc0, 0xde, + /* u32 */ + 0xfa, 0xce, 0xde, 0xad, + /* u64 */ + 0xfe, 0xed, 0xac, 0x1d, 0x1f, 0x1c, 0xbe, 0xef, + /* string */ + 0x00, 0x00, 0x00, 0x09, + 'O', ' ', 'G', 'o', 'r', 'g', 'o', 'n', '!', + /* bignum2 */ + 0x00, 0x00, 0x00, 0x14, + 0x00, + 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, + 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, + 0x7f, 0xff, 0x11, + /* EC point (NIST-256 curve) */ + 0x00, 0x00, 0x00, 0x41, + 0x04, + 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06, + 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57, + 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86, + 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99, + 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b, + 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2, + 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47, + 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4, + }; + struct fuzz *fuzz; + u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END; + + if (test_is_fast()) + fuzzers &= ~(FUZZ_2_BYTE_FLIP|FUZZ_2_BIT_FLIP); + + TEST_START("fuzz blob parsing"); + fuzz = fuzz_begin(fuzzers, blob, sizeof(blob)); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) + attempt_parse_blob(blob, sizeof(blob)); + fuzz_cleanup(fuzz); + TEST_DONE(); + TEST_ONERROR(NULL, NULL); +} + diff --git a/regress/unittests/sshbuf/test_sshbuf_misc.c b/regress/unittests/sshbuf/test_sshbuf_misc.c new file mode 100644 index 0000000..249ecf2 --- /dev/null +++ b/regress/unittests/sshbuf/test_sshbuf_misc.c @@ -0,0 +1,217 @@ +/* $OpenBSD: test_sshbuf_misc.c,v 1.5 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "../test_helper/test_helper.h" + +#include "sshbuf.h" +#include "ssherr.h" + +void sshbuf_misc_tests(void); + +void +sshbuf_misc_tests(void) +{ + struct sshbuf *p1; + char tmp[512], msg[] = "imploring ping silence ping over", *p; + FILE *out; + size_t sz; + + TEST_START("sshbuf_dump"); + out = tmpfile(); + ASSERT_PTR_NE(out, NULL); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0); + sshbuf_dump(p1, out); + fflush(out); + rewind(out); + sz = fread(tmp, 1, sizeof(tmp), out); + ASSERT_INT_EQ(ferror(out), 0); + ASSERT_INT_NE(feof(out), 0); + ASSERT_SIZE_T_GT(sz, 0); + tmp[sz] = '\0'; + ASSERT_PTR_NE(strstr(tmp, "12 34 56 78"), NULL); + fclose(out); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0); + p = sshbuf_dtob16(p1); + ASSERT_PTR_NE(p, NULL); + ASSERT_STRING_EQ(p, "12345678"); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob64_string len 1"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0); + p = sshbuf_dtob64_string(p1, 0); + ASSERT_PTR_NE(p, NULL); + ASSERT_STRING_EQ(p, "EQ=="); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob64_string len 2"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0); + p = sshbuf_dtob64_string(p1, 0); + ASSERT_PTR_NE(p, NULL); + ASSERT_STRING_EQ(p, "ESI="); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob64_string len 3"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x33), 0); + p = sshbuf_dtob64_string(p1, 0); + ASSERT_PTR_NE(p, NULL); + ASSERT_STRING_EQ(p, "ESIz"); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob64_string len 8191"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_reserve(p1, 8192, NULL), 0); + bzero(sshbuf_mutable_ptr(p1), 8192); + p = sshbuf_dtob64_string(p1, 0); + ASSERT_PTR_NE(p, NULL); + ASSERT_SIZE_T_EQ(strlen(p), ((8191 + 2) / 3) * 4); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_b64tod len 1"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A=="), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_U8_EQ(*sshbuf_ptr(p1), 0xd0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_b64tod len 2"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A8="), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), 0xd00f); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_b64tod len 4"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A/QDw=="), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), 0xd00fd00f); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dup_string"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + /* Check empty buffer */ + p = sshbuf_dup_string(p1); + ASSERT_PTR_NE(p, NULL); + ASSERT_SIZE_T_EQ(strlen(p), 0); + free(p); + /* Check buffer with string */ + ASSERT_INT_EQ(sshbuf_put(p1, "quad1", strlen("quad1")), 0); + p = sshbuf_dup_string(p1); + ASSERT_PTR_NE(p, NULL); + ASSERT_SIZE_T_EQ(strlen(p), strlen("quad1")); + ASSERT_STRING_EQ(p, "quad1"); + free(p); + /* Check buffer with terminating nul */ + ASSERT_INT_EQ(sshbuf_put(p1, "\0", 1), 0); + p = sshbuf_dup_string(p1); + ASSERT_PTR_NE(p, NULL); + ASSERT_SIZE_T_EQ(strlen(p), strlen("quad1")); + ASSERT_STRING_EQ(p, "quad1"); + free(p); + /* Check buffer with data after nul (expect failure) */ + ASSERT_INT_EQ(sshbuf_put(p1, "quad2", strlen("quad2")), 0); + p = sshbuf_dup_string(p1); + ASSERT_PTR_EQ(p, NULL); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_cmp"); + p1 = sshbuf_from(msg, sizeof(msg) - 1); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_cmp(p1, 0, "i", 1), 0); + ASSERT_INT_EQ(sshbuf_cmp(p1, 0, "j", 1), SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(sshbuf_cmp(p1, 0, "imploring", 9), 0); + ASSERT_INT_EQ(sshbuf_cmp(p1, 0, "implored", 9), SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(sshbuf_cmp(p1, 10, "ping", 4), 0); + ASSERT_INT_EQ(sshbuf_cmp(p1, 10, "ring", 4), SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(sshbuf_cmp(p1, 28, "over", 4), 0); + ASSERT_INT_EQ(sshbuf_cmp(p1, 28, "rove", 4), SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(sshbuf_cmp(p1, 28, "overt", 5), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_cmp(p1, 32, "ping", 4), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_cmp(p1, 1000, "silence", 7), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_cmp(p1, 0, msg, sizeof(msg) - 1), 0); + TEST_DONE(); + + TEST_START("sshbuf_find"); + p1 = sshbuf_from(msg, sizeof(msg) - 1); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_find(p1, 0, "i", 1, &sz), 0); + ASSERT_SIZE_T_EQ(sz, 0); + ASSERT_INT_EQ(sshbuf_find(p1, 0, "j", 1, &sz), SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(sshbuf_find(p1, 0, "imploring", 9, &sz), 0); + ASSERT_SIZE_T_EQ(sz, 0); + ASSERT_INT_EQ(sshbuf_find(p1, 0, "implored", 9, &sz), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(sshbuf_find(p1, 3, "ping", 4, &sz), 0); + ASSERT_SIZE_T_EQ(sz, 10); + ASSERT_INT_EQ(sshbuf_find(p1, 11, "ping", 4, &sz), 0); + ASSERT_SIZE_T_EQ(sz, 23); + ASSERT_INT_EQ(sshbuf_find(p1, 20, "over", 4, &sz), 0); + ASSERT_SIZE_T_EQ(sz, 28); + ASSERT_INT_EQ(sshbuf_find(p1, 28, "over", 4, &sz), 0); + ASSERT_SIZE_T_EQ(sz, 28); + ASSERT_INT_EQ(sshbuf_find(p1, 28, "rove", 4, &sz), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(sshbuf_find(p1, 28, "overt", 5, &sz), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_find(p1, 32, "ping", 4, &sz), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_find(p1, 1000, "silence", 7, &sz), + SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_find(p1, 0, msg + 1, sizeof(msg) - 2, &sz), 0); + ASSERT_SIZE_T_EQ(sz, 1); + TEST_DONE(); +} + diff --git a/regress/unittests/sshbuf/tests.c b/regress/unittests/sshbuf/tests.c new file mode 100644 index 0000000..29916a1 --- /dev/null +++ b/regress/unittests/sshbuf/tests.c @@ -0,0 +1,30 @@ +/* $OpenBSD: tests.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "../test_helper/test_helper.h" + +void sshbuf_tests(void); +void sshbuf_getput_basic_tests(void); +void sshbuf_getput_crypto_tests(void); +void sshbuf_misc_tests(void); +void sshbuf_fuzz_tests(void); +void sshbuf_getput_fuzz_tests(void); +void sshbuf_fixed(void); + +void +tests(void) +{ + sshbuf_tests(); + sshbuf_getput_basic_tests(); +#ifdef WITH_OPENSSL + sshbuf_getput_crypto_tests(); +#endif + sshbuf_misc_tests(); + sshbuf_fuzz_tests(); + sshbuf_getput_fuzz_tests(); + sshbuf_fixed(); +} diff --git a/regress/unittests/sshkey/Makefile b/regress/unittests/sshkey/Makefile new file mode 100644 index 0000000..cd0f44d --- /dev/null +++ b/regress/unittests/sshkey/Makefile @@ -0,0 +1,26 @@ +# $OpenBSD: Makefile,v 1.12 2023/01/15 23:35:10 djm Exp $ + +PROG=test_sshkey +SRCS=tests.c test_sshkey.c test_file.c test_fuzz.c common.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c +SRCS+=addr.c addrmatch.c bitmap.c +SRCS+=ed25519.c hash.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c + +SRCS+=digest-openssl.c +#SRCS+=digest-libc.c +SRCS+=utf8.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} -d ${.CURDIR}/testdata + +.include <bsd.regress.mk> + diff --git a/regress/unittests/sshkey/common.c b/regress/unittests/sshkey/common.c new file mode 100644 index 0000000..51b0d92 --- /dev/null +++ b/regress/unittests/sshkey/common.c @@ -0,0 +1,163 @@ +/* $OpenBSD: common.c,v 1.5 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Helpers for key API tests + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/objects.h> +#ifdef OPENSSL_HAS_NISTP256 +# include <openssl/ec.h> +#endif /* OPENSSL_HAS_NISTP256 */ +#endif /* WITH_OPENSSL */ + +#include "openbsd-compat/openssl-compat.h" + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "authfile.h" +#include "sshkey.h" +#include "sshbuf.h" + +#include "common.h" + +struct sshbuf * +load_file(const char *name) +{ + struct sshbuf *ret = NULL; + + ASSERT_INT_EQ(sshbuf_load_file(test_data_file(name), &ret), 0); + ASSERT_PTR_NE(ret, NULL); + return ret; +} + +struct sshbuf * +load_text_file(const char *name) +{ + struct sshbuf *ret = load_file(name); + const u_char *p; + + /* Trim whitespace at EOL */ + for (p = sshbuf_ptr(ret); sshbuf_len(ret) > 0;) { + if (p[sshbuf_len(ret) - 1] == '\r' || + p[sshbuf_len(ret) - 1] == '\t' || + p[sshbuf_len(ret) - 1] == ' ' || + p[sshbuf_len(ret) - 1] == '\n') + ASSERT_INT_EQ(sshbuf_consume_end(ret, 1), 0); + else + break; + } + /* \0 terminate */ + ASSERT_INT_EQ(sshbuf_put_u8(ret, 0), 0); + return ret; +} + +#ifdef WITH_OPENSSL +BIGNUM * +load_bignum(const char *name) +{ + BIGNUM *ret = NULL; + struct sshbuf *buf; + + buf = load_text_file(name); + ASSERT_INT_NE(BN_hex2bn(&ret, (const char *)sshbuf_ptr(buf)), 0); + sshbuf_free(buf); + return ret; +} + +const BIGNUM * +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); + return n; +} + +const BIGNUM * +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); + return e; +} + +const BIGNUM * +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); + return p; +} + +const BIGNUM * +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); + return q; +} + +const BIGNUM * +dsa_g(struct sshkey *k) +{ + const BIGNUM *g = NULL; + + ASSERT_PTR_NE(k, NULL); + ASSERT_PTR_NE(k->dsa, NULL); + DSA_get0_pqg(k->dsa, NULL, NULL, &g); + return g; +} + +const BIGNUM * +dsa_pub_key(struct sshkey *k) +{ + const BIGNUM *pub_key = NULL; + + ASSERT_PTR_NE(k, NULL); + ASSERT_PTR_NE(k->dsa, NULL); + DSA_get0_key(k->dsa, &pub_key, NULL); + return pub_key; +} + +const BIGNUM * +dsa_priv_key(struct sshkey *k) +{ + const BIGNUM *priv_key = NULL; + + ASSERT_PTR_NE(k, NULL); + ASSERT_PTR_NE(k->dsa, NULL); + DSA_get0_key(k->dsa, NULL, &priv_key); + return priv_key; +} +#endif /* WITH_OPENSSL */ + diff --git a/regress/unittests/sshkey/common.h b/regress/unittests/sshkey/common.h new file mode 100644 index 0000000..7a514fd --- /dev/null +++ b/regress/unittests/sshkey/common.h @@ -0,0 +1,25 @@ +/* $OpenBSD: common.h,v 1.2 2018/09/13 09:03:20 djm Exp $ */ +/* + * Helpers for key API tests + * + * Placed in the public domain + */ + +/* Load a binary file into a buffer */ +struct sshbuf *load_file(const char *name); + +/* Load a text file into a buffer */ +struct sshbuf *load_text_file(const char *name); + +/* Load a bignum from a file */ +BIGNUM *load_bignum(const char *name); + +/* Accessors for key components */ +const BIGNUM *rsa_n(struct sshkey *k); +const BIGNUM *rsa_e(struct sshkey *k); +const BIGNUM *rsa_p(struct sshkey *k); +const BIGNUM *rsa_q(struct sshkey *k); +const BIGNUM *dsa_g(struct sshkey *k); +const BIGNUM *dsa_pub_key(struct sshkey *k); +const BIGNUM *dsa_priv_key(struct sshkey *k); + diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh new file mode 100755 index 0000000..fcd78e9 --- /dev/null +++ b/regress/unittests/sshkey/mktestdata.sh @@ -0,0 +1,222 @@ +#!/bin/sh +# $OpenBSD: mktestdata.sh,v 1.11 2020/06/19 03:48:49 djm Exp $ + +PW=mekmitasdigoat + +rsa_params() { + _in="$1" + _outbase="$2" + set -e + openssl rsa -noout -text -in $_in | \ + awk '/^modulus:$/,/^publicExponent:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.n + openssl rsa -noout -text -in $_in | \ + awk '/^prime1:$/,/^prime2:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.p + openssl rsa -noout -text -in $_in | \ + awk '/^prime2:$/,/^exponent1:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.q + for x in n p q ; do + echo "" >> ${_outbase}.$x + echo ============ ${_outbase}.$x + cat ${_outbase}.$x + echo ============ + done +} + +dsa_params() { + _in="$1" + _outbase="$2" + set -e + openssl dsa -noout -text -in $_in | \ + awk '/^priv:$/,/^pub:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv + openssl dsa -noout -text -in $_in | \ + awk '/^pub:/,/^P:/' | #\ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub + openssl dsa -noout -text -in $_in | \ + awk '/^G:/,0' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.g + for x in priv pub g ; do + echo "" >> ${_outbase}.$x + echo ============ ${_outbase}.$x + cat ${_outbase}.$x + echo ============ + done +} + +ecdsa_params() { + _in="$1" + _outbase="$2" + set -e + openssl ec -noout -text -in $_in | \ + awk '/^priv:$/,/^pub:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv + openssl ec -noout -text -in $_in | \ + awk '/^pub:/,/^ASN1 OID:/' | #\ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub + openssl ec -noout -text -in $_in | \ + grep "ASN1 OID:" | \ + sed 's/.*: //;s/ *$//' | tr -d '\n' > ${_outbase}.curve + for x in priv pub curve ; do + echo "" >> ${_outbase}.$x + echo ============ ${_outbase}.$x + cat ${_outbase}.$x + echo ============ + done +} + +set -ex + +cd testdata + +if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then + SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so +elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then + SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so +else + echo "Can't find sk-dummy.so" 1>&2 + exit 1 +fi + +rm -f rsa_1 dsa_1 ecdsa_1 ed25519_1 +rm -f rsa_2 dsa_2 ecdsa_2 ed25519_2 +rm -f rsa_n dsa_n ecdsa_n # new-format keys +rm -f rsa_1_pw dsa_1_pw ecdsa_1_pw ed25519_1_pw +rm -f rsa_n_pw dsa_n_pw ecdsa_n_pw +rm -f pw *.pub *.bn.* *.param.* *.fp *.fp.bb + +ssh-keygen -t rsa -b 1024 -C "RSA test key #1" -N "" -f rsa_1 -m PEM +ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 -m PEM +ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 -m PEM +ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1 +ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #1" \ + -N "" -f ecdsa_sk1 +ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #1" \ + -N "" -f ed25519_sk1 + + +ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 -m PEM +ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2 -m PEM +ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2 -m PEM +ssh-keygen -t ed25519 -C "ED25519 test key #2" -N "" -f ed25519_2 +ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #2" \ + -N "" -f ecdsa_sk2 +ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #2" \ + -N "" -f ed25519_sk2 + +cp rsa_1 rsa_n +cp dsa_1 dsa_n +cp ecdsa_1 ecdsa_n + +ssh-keygen -pf rsa_n -N "" +ssh-keygen -pf dsa_n -N "" +ssh-keygen -pf ecdsa_n -N "" + +cp rsa_1 rsa_1_pw +cp dsa_1 dsa_1_pw +cp ecdsa_1 ecdsa_1_pw +cp ed25519_1 ed25519_1_pw +cp ecdsa_sk1 ecdsa_sk1_pw +cp ed25519_sk1 ed25519_sk1_pw +cp rsa_1 rsa_n_pw +cp dsa_1 dsa_n_pw +cp ecdsa_1 ecdsa_n_pw + +ssh-keygen -pf rsa_1_pw -m PEM -N "$PW" +ssh-keygen -pf dsa_1_pw -m PEM -N "$PW" +ssh-keygen -pf ecdsa_1_pw -m PEM -N "$PW" +ssh-keygen -pf ed25519_1_pw -N "$PW" +ssh-keygen -pf ecdsa_sk1_pw -m PEM -N "$PW" +ssh-keygen -pf ed25519_sk1_pw -N "$PW" +ssh-keygen -pf rsa_n_pw -N "$PW" +ssh-keygen -pf dsa_n_pw -N "$PW" +ssh-keygen -pf ecdsa_n_pw -N "$PW" + +rsa_params rsa_1 rsa_1.param +rsa_params rsa_2 rsa_2.param +dsa_params dsa_1 dsa_1.param +dsa_params dsa_1 dsa_1.param +ecdsa_params ecdsa_1 ecdsa_1.param +ecdsa_params ecdsa_2 ecdsa_2.param +# XXX ed25519, *sk params + +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 1 rsa_1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 2 dsa_1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 3 ecdsa_1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 4 ed25519_1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 4 ecdsa_sk1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 4 ed25519_sk1.pub + + +# Make a few RSA variant signature too. +cp rsa_1 rsa_1_sha1 +cp rsa_1 rsa_1_sha512 +cp rsa_1.pub rsa_1_sha1.pub +cp rsa_1.pub rsa_1_sha512.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 -t ssh-rsa \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 1 rsa_1_sha1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 -t rsa-sha2-512 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 1 rsa_1_sha512.pub + +ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 5 rsa_1.pub +ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 6 dsa_1.pub +ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 7 ecdsa_1.pub +ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 8 ed25519_1.pub +ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 7 ecdsa_sk1.pub +ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 8 ed25519_sk1.pub + +ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp +ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp +ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp +ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp +ssh-keygen -lf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp +ssh-keygen -lf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp +ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp +ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp +ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp +ssh-keygen -lf ed25519_2 | awk '{print $2}' > ed25519_2.fp +ssh-keygen -lf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp +ssh-keygen -lf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp + +ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp +ssh-keygen -lf dsa_1-cert.pub | awk '{print $2}' > dsa_1-cert.fp +ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp +ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp +ssh-keygen -lf ecdsa_sk1-cert.pub | awk '{print $2}' > ecdsa_sk1-cert.fp +ssh-keygen -lf ed25519_sk1-cert.pub | awk '{print $2}' > ed25519_sk1-cert.fp + +ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb +ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb +ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb +ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb +ssh-keygen -Bf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp.bb +ssh-keygen -Bf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp.bb +ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb +ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb +ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb +ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb +ssh-keygen -Bf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp.bb +ssh-keygen -Bf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp.bb + +echo "$PW" > pw diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c new file mode 100644 index 0000000..488944c --- /dev/null +++ b/regress/unittests/sshkey/test_file.c @@ -0,0 +1,561 @@ +/* $OpenBSD: test_file.c,v 1.10 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for sshkey.h key management API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/objects.h> +#ifdef OPENSSL_HAS_NISTP256 +# include <openssl/ec.h> +#endif /* OPENSSL_HAS_NISTP256 */ +#endif /* WITH_OPENSSL */ + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "authfile.h" +#include "sshkey.h" +#include "sshbuf.h" +#include "digest.h" + +#include "common.h" + +void sshkey_file_tests(void); + +void +sshkey_file_tests(void) +{ + struct sshkey *k1, *k2; + struct sshbuf *buf, *pw; +#ifdef WITH_OPENSSL + BIGNUM *a, *b, *c; +#endif + char *cp; + + TEST_START("load passphrase"); + pw = load_text_file("pw"); + TEST_DONE(); + + +#ifdef WITH_OPENSSL + TEST_START("parse RSA from private"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + a = load_bignum("rsa_1.param.n"); + b = load_bignum("rsa_1.param.p"); + c = load_bignum("rsa_1.param.q"); + ASSERT_BIGNUM_EQ(rsa_n(k1), a); + ASSERT_BIGNUM_EQ(rsa_p(k1), b); + ASSERT_BIGNUM_EQ(rsa_q(k1), c); + BN_free(a); + BN_free(b); + BN_free(c); + TEST_DONE(); + + TEST_START("parse RSA from private w/ passphrase"); + buf = load_file("rsa_1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse RSA from new-format"); + buf = load_file("rsa_n"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse RSA from new-format w/ passphrase"); + buf = load_file("rsa_n_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load RSA from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load RSA cert with SHA1 signature"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_RSA_CERT); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa"); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load RSA cert with SHA512 signature"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_RSA_CERT); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + ASSERT_STRING_EQ(k2->cert->signature_type, "rsa-sha2-512"); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load RSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_RSA_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("RSA key hex fingerprint"); + buf = load_text_file("rsa_1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("RSA cert hex fingerprint"); + buf = load_text_file("rsa_1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("RSA key bubblebabble fingerprint"); + buf = load_text_file("rsa_1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); + + TEST_START("parse DSA from private"); + buf = load_file("dsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + a = load_bignum("dsa_1.param.g"); + b = load_bignum("dsa_1.param.priv"); + c = load_bignum("dsa_1.param.pub"); + ASSERT_BIGNUM_EQ(dsa_g(k1), a); + ASSERT_BIGNUM_EQ(dsa_priv_key(k1), b); + ASSERT_BIGNUM_EQ(dsa_pub_key(k1), c); + BN_free(a); + BN_free(b); + BN_free(c); + TEST_DONE(); + + TEST_START("parse DSA from private w/ passphrase"); + buf = load_file("dsa_1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse DSA from new-format"); + buf = load_file("dsa_n"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse DSA from new-format w/ passphrase"); + buf = load_file("dsa_n_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load DSA from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load DSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_DSA_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("DSA key hex fingerprint"); + buf = load_text_file("dsa_1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("DSA cert hex fingerprint"); + buf = load_text_file("dsa_1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("DSA key bubblebabble fingerprint"); + buf = load_text_file("dsa_1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); + +#ifdef OPENSSL_HAS_ECC + TEST_START("parse ECDSA from private"); + buf = load_file("ecdsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + buf = load_text_file("ecdsa_1.param.curve"); + ASSERT_STRING_EQ((const char *)sshbuf_ptr(buf), + OBJ_nid2sn(k1->ecdsa_nid)); + sshbuf_free(buf); +#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); + ASSERT_PTR_NE(c, NULL); + ASSERT_BIGNUM_EQ(EC_KEY_get0_private_key(k1->ecdsa), a); + ASSERT_BIGNUM_EQ(b, c); + BN_free(a); + BN_free(b); + BN_free(c); +#endif /* OPENSSL_IS_BORINGSSL */ + TEST_DONE(); + + TEST_START("parse ECDSA from private w/ passphrase"); + buf = load_file("ecdsa_1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse ECDSA from new-format"); + buf = load_file("ecdsa_n"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse ECDSA from new-format w/ passphrase"); + buf = load_file("ecdsa_n_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load ECDSA from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load ECDSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_ECDSA_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("ECDSA key hex fingerprint"); + buf = load_text_file("ecdsa_1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("ECDSA cert hex fingerprint"); + buf = load_text_file("ecdsa_1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("ECDSA key bubblebabble fingerprint"); + buf = load_text_file("ecdsa_1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + + TEST_START("parse Ed25519 from private"); + buf = load_file("ed25519_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + ASSERT_INT_EQ(k1->type, KEY_ED25519); + /* XXX check key contents */ + TEST_DONE(); + + TEST_START("parse Ed25519 from private w/ passphrase"); + buf = load_file("ed25519_1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load Ed25519 from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load Ed25519 cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_ED25519_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("Ed25519 key hex fingerprint"); + buf = load_text_file("ed25519_1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("Ed25519 cert hex fingerprint"); + buf = load_text_file("ed25519_1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("Ed25519 key bubblebabble fingerprint"); + buf = load_text_file("ed25519_1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); + +#ifdef ENABLE_SK +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + TEST_START("parse ECDSA-SK from private"); + buf = load_file("ecdsa_sk1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + ASSERT_INT_EQ(k1->type, KEY_ECDSA_SK); + TEST_DONE(); + + TEST_START("parse ECDSA-SK from private w/ passphrase"); + buf = load_file("ecdsa_sk1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load ECDSA-SK from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_sk1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load ECDSA-SK cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_sk1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_ECDSA_SK_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("ECDSA-SK key hex fingerprint"); + buf = load_text_file("ecdsa_sk1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("ECDSA-SK cert hex fingerprint"); + buf = load_text_file("ecdsa_sk1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("ECDSA-SK key bubblebabble fingerprint"); + buf = load_text_file("ecdsa_sk1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); +#endif + + TEST_START("parse Ed25519-SK from private"); + buf = load_file("ed25519_sk1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + ASSERT_INT_EQ(k1->type, KEY_ED25519_SK); + /* XXX check key contents */ + TEST_DONE(); + + TEST_START("parse Ed25519-SK from private w/ passphrase"); + buf = load_file("ed25519_sk1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load Ed25519-SK from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_sk1.pub"), + &k2, NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load Ed25519-SK cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_sk1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_ED25519_SK_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("Ed25519-SK key hex fingerprint"); + buf = load_text_file("ed25519_sk1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("Ed25519-SK cert hex fingerprint"); + buf = load_text_file("ed25519_sk1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("Ed25519-SK key bubblebabble fingerprint"); + buf = load_text_file("ed25519_sk1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); +#endif /* ENABLE_SK */ + + sshbuf_free(pw); + +} diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c new file mode 100644 index 0000000..2fae19d --- /dev/null +++ b/regress/unittests/sshkey/test_fuzz.c @@ -0,0 +1,391 @@ +/* $OpenBSD: test_fuzz.c,v 1.13 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Fuzz tests for key parsing + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/objects.h> +#ifdef OPENSSL_HAS_NISTP256 +# include <openssl/ec.h> +#endif +#endif + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "authfile.h" +#include "sshkey.h" +#include "sshbuf.h" + +#include "common.h" + +void sshkey_fuzz_tests(void); + +static void +onerror(void *fuzz) +{ + fprintf(stderr, "Failed during fuzz:\n"); + fuzz_dump((struct fuzz *)fuzz); +} + +static void +public_fuzz(struct sshkey *k) +{ + struct sshkey *k1; + struct sshbuf *buf; + struct fuzz *fuzz; + u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END; + + if (test_is_fast()) + fuzzers &= ~FUZZ_1_BIT_FLIP; + if (test_is_slow()) + fuzzers |= FUZZ_2_BIT_FLIP | FUZZ_2_BYTE_FLIP; + ASSERT_PTR_NE(buf = sshbuf_new(), NULL); + ASSERT_INT_EQ(sshkey_putb(k, buf), 0); + fuzz = fuzz_begin(fuzzers, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf), + &k1), 0); + sshkey_free(k1); + sshbuf_free(buf); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0) + sshkey_free(k1); + } + fuzz_cleanup(fuzz); +} + +static void +sig_fuzz(struct sshkey *k, const char *sig_alg) +{ + struct fuzz *fuzz; + u_char *sig, c[] = "some junk to be signed"; + size_t l; + u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END; + + if (test_is_fast()) + fuzzers &= ~FUZZ_2_BYTE_FLIP; + if (test_is_slow()) + fuzzers |= FUZZ_2_BIT_FLIP; + + ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c), + sig_alg, NULL, NULL, 0), 0); + ASSERT_SIZE_T_GT(l, 0); + fuzz = fuzz_begin(fuzzers, sig, l); + ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), NULL, 0, NULL), 0); + free(sig); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + /* Ensure 1-bit difference at least */ + if (fuzz_matches_original(fuzz)) + continue; + ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz), + c, sizeof(c), NULL, 0, NULL), 0); + } + fuzz_cleanup(fuzz); +} + +#define NUM_FAST_BASE64_TESTS 1024 + +void +sshkey_fuzz_tests(void) +{ + struct sshkey *k1; + struct sshbuf *buf, *fuzzed; + struct fuzz *fuzz; + int r, i; + +#ifdef WITH_OPENSSL + TEST_START("fuzz RSA private"); + buf = load_file("rsa_1"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) + break; + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz RSA new-format private"); + buf = load_file("rsa_n"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) + break; + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz DSA private"); + buf = load_file("dsa_1"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) + break; + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz DSA new-format private"); + buf = load_file("dsa_n"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) + break; + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("fuzz ECDSA private"); + buf = load_file("ecdsa_1"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) + break; + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz ECDSA new-format private"); + buf = load_file("ecdsa_n"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) + break; + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + + TEST_START("fuzz Ed25519 private"); + buf = load_file("ed25519_1"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) + break; + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + +#ifdef WITH_OPENSSL + TEST_START("fuzz RSA public"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz RSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz DSA public"); + buf = load_file("dsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz DSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("fuzz ECDSA public"); + buf = load_file("ecdsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz ECDSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + + TEST_START("fuzz Ed25519 public"); + buf = load_file("ed25519_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz Ed25519 cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + +#ifdef WITH_OPENSSL + TEST_START("fuzz RSA sig"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1, "ssh-rsa"); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz RSA SHA256 sig"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1, "rsa-sha2-256"); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz RSA SHA512 sig"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1, "rsa-sha2-512"); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz DSA sig"); + buf = load_file("dsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1, NULL); + sshkey_free(k1); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("fuzz ECDSA sig"); + buf = load_file("ecdsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1, NULL); + sshkey_free(k1); + TEST_DONE(); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + + TEST_START("fuzz Ed25519 sig"); + buf = load_file("ed25519_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1, NULL); + sshkey_free(k1); + TEST_DONE(); + +/* XXX fuzz decoded new-format blobs too */ +/* XXX fuzz XMSS too */ + +} diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c new file mode 100644 index 0000000..cc359ae --- /dev/null +++ b/regress/unittests/sshkey/test_sshkey.c @@ -0,0 +1,528 @@ +/* $OpenBSD: test_sshkey.c,v 1.23 2023/01/04 22:48:57 tb Exp $ */ +/* + * Regress test for sshkey.h key management API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) +# include <openssl/ec.h> +#endif +#endif + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "sshbuf.h" +#define SSHBUF_INTERNAL 1 /* access internals for testing */ +#include "sshkey.h" + +#include "authfile.h" +#include "common.h" +#include "ssh2.h" + +void sshkey_tests(void); + +static void +put_opt(struct sshbuf *b, const char *name, const char *value) +{ + struct sshbuf *sect; + + sect = sshbuf_new(); + ASSERT_PTR_NE(sect, NULL); + ASSERT_INT_EQ(sshbuf_put_cstring(b, name), 0); + if (value != NULL) + ASSERT_INT_EQ(sshbuf_put_cstring(sect, value), 0); + ASSERT_INT_EQ(sshbuf_put_stringb(b, sect), 0); + sshbuf_free(sect); +} + +#ifdef WITH_OPENSSL +static void +build_cert(struct sshbuf *b, struct sshkey *k, const char *type, + struct sshkey *sign_key, struct sshkey *ca_key, + const char *sig_alg) +{ + struct sshbuf *ca_buf, *pk, *principals, *critopts, *exts; + u_char *sigblob; + size_t siglen; + + ca_buf = sshbuf_new(); + ASSERT_PTR_NE(ca_buf, NULL); + ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0); + + /* + * Get the public key serialisation by rendering the key and skipping + * the type string. This is a bit of a hack :/ + */ + pk = sshbuf_new(); + ASSERT_PTR_NE(pk, NULL); + ASSERT_INT_EQ(sshkey_putb_plain(k, pk), 0); + ASSERT_INT_EQ(sshbuf_skip_string(pk), 0); + + principals = sshbuf_new(); + ASSERT_PTR_NE(principals, NULL); + ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0); + ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0); + + critopts = sshbuf_new(); + ASSERT_PTR_NE(critopts, NULL); + put_opt(critopts, "force-command", "/usr/local/bin/nethack"); + put_opt(critopts, "source-address", "192.168.0.0/24,127.0.0.1,::1"); + + exts = sshbuf_new(); + ASSERT_PTR_NE(exts, NULL); + put_opt(critopts, "permit-X11-forwarding", NULL); + + ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0); + ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */ + ASSERT_INT_EQ(sshbuf_putb(b, pk), 0); /* public key serialisation */ + ASSERT_INT_EQ(sshbuf_put_u64(b, 1234), 0); /* serial */ + ASSERT_INT_EQ(sshbuf_put_u32(b, SSH2_CERT_TYPE_USER), 0); /* type */ + ASSERT_INT_EQ(sshbuf_put_cstring(b, "gregor"), 0); /* key ID */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, principals), 0); /* principals */ + ASSERT_INT_EQ(sshbuf_put_u64(b, 0), 0); /* start */ + ASSERT_INT_EQ(sshbuf_put_u64(b, 0xffffffffffffffffULL), 0); /* end */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, critopts), 0); /* options */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */ + ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ + ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, + sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), 0); + ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ + + free(sigblob); + sshbuf_free(ca_buf); + sshbuf_free(exts); + sshbuf_free(critopts); + sshbuf_free(principals); + sshbuf_free(pk); +} +#endif /* WITH_OPENSSL */ + +static void +signature_test(struct sshkey *k, struct sshkey *bad, const char *sig_alg, + const u_char *d, size_t l) +{ + size_t len; + u_char *sig; + + ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, + NULL, NULL, 0), 0); + ASSERT_SIZE_T_GT(len, 8); + ASSERT_PTR_NE(sig, NULL); + ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); + ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0); + /* Fuzz test is more comprehensive, this is just a smoke test */ + sig[len - 5] ^= 0x10; + ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); + free(sig); +} + +static void +banana(u_char *s, size_t l) +{ + size_t o; + const u_char the_banana[] = { 'b', 'a', 'n', 'a', 'n', 'a' }; + + for (o = 0; o < l; o += sizeof(the_banana)) { + if (l - o < sizeof(the_banana)) { + memcpy(s + o, "nanananana", l - o); + break; + } + memcpy(s + o, the_banana, sizeof(the_banana)); + } +} + +static void +signature_tests(struct sshkey *k, struct sshkey *bad, const char *sig_alg) +{ + u_char i, buf[2049]; + size_t lens[] = { + 1, 2, 7, 8, 9, 15, 16, 17, 31, 32, 33, 127, 128, 129, + 255, 256, 257, 1023, 1024, 1025, 2047, 2048, 2049 + }; + + for (i = 0; i < (sizeof(lens)/sizeof(lens[0])); i++) { + test_subtest_info("%s key, banana length %zu", + sshkey_type(k), lens[i]); + banana(buf, lens[i]); + signature_test(k, bad, sig_alg, buf, lens[i]); + } +} + +static struct sshkey * +get_private(const char *n) +{ + struct sshbuf *b; + struct sshkey *ret; + + b = load_file(n); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", &ret, NULL), 0); + sshbuf_free(b); + return ret; +} + +void +sshkey_tests(void) +{ + struct sshkey *k1, *k2, *k3, *kf; +#ifdef WITH_OPENSSL + struct sshkey *k4, *kr, *kd; +#ifdef OPENSSL_HAS_ECC + struct sshkey *ke; +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + struct sshbuf *b; + + TEST_START("new invalid"); + k1 = sshkey_new(-42); + ASSERT_PTR_EQ(k1, NULL); + TEST_DONE(); + + TEST_START("new/free KEY_UNSPEC"); + k1 = sshkey_new(KEY_UNSPEC); + ASSERT_PTR_NE(k1, NULL); + sshkey_free(k1); + TEST_DONE(); + +#ifdef WITH_OPENSSL + TEST_START("new/free KEY_RSA"); + k1 = sshkey_new(KEY_RSA); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(k1->rsa, NULL); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("new/free KEY_DSA"); + k1 = sshkey_new(KEY_DSA); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(k1->dsa, NULL); + sshkey_free(k1); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + 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 */ + sshkey_free(k1); + TEST_DONE(); +#endif + + TEST_START("new/free KEY_ED25519"); + k1 = sshkey_new(KEY_ED25519); + ASSERT_PTR_NE(k1, NULL); + /* These should be blank until key loaded or generated */ + ASSERT_PTR_EQ(k1->ed25519_sk, NULL); + ASSERT_PTR_EQ(k1->ed25519_pk, NULL); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("generate KEY_RSA too small modulus"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 128, &k1), + SSH_ERR_KEY_LENGTH); + ASSERT_PTR_EQ(k1, NULL); + TEST_DONE(); + + TEST_START("generate KEY_RSA too large modulus"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1 << 20, &k1), + SSH_ERR_KEY_LENGTH); + ASSERT_PTR_EQ(k1, NULL); + TEST_DONE(); + + TEST_START("generate KEY_DSA wrong bits"); + ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 2048, &k1), + SSH_ERR_KEY_LENGTH); + ASSERT_PTR_EQ(k1, NULL); + sshkey_free(k1); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("generate KEY_ECDSA wrong bits"); + ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 42, &k1), + SSH_ERR_KEY_LENGTH); + ASSERT_PTR_EQ(k1, NULL); + sshkey_free(k1); + TEST_DONE(); +#endif + + TEST_START("generate KEY_RSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 767, &kr), + 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(rsa_n(kr), NULL); + ASSERT_PTR_NE(rsa_e(kr), NULL); + ASSERT_PTR_NE(rsa_p(kr), NULL); + ASSERT_INT_EQ(BN_num_bits(rsa_n(kr)), 1024); + TEST_DONE(); + + TEST_START("generate KEY_DSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0); + ASSERT_PTR_NE(kd, NULL); + ASSERT_PTR_NE(kd->dsa, NULL); + ASSERT_PTR_NE(dsa_g(kd), NULL); + ASSERT_PTR_NE(dsa_priv_key(kd), NULL); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + 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); + TEST_DONE(); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + + TEST_START("generate KEY_ED25519"); + ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &kf), 0); + ASSERT_PTR_NE(kf, NULL); + ASSERT_INT_EQ(kf->type, KEY_ED25519); + ASSERT_PTR_NE(kf->ed25519_pk, NULL); + ASSERT_PTR_NE(kf->ed25519_sk, NULL); + TEST_DONE(); + +#ifdef WITH_OPENSSL + TEST_START("demote KEY_RSA"); + ASSERT_INT_EQ(sshkey_from_private(kr, &k1), 0); + 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(rsa_n(k1), NULL); + ASSERT_PTR_NE(rsa_e(k1), NULL); + ASSERT_PTR_EQ(rsa_p(k1), NULL); + TEST_DONE(); + + TEST_START("equal KEY_RSA/demoted KEY_RSA"); + ASSERT_INT_EQ(sshkey_equal(kr, k1), 1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("demote KEY_DSA"); + ASSERT_INT_EQ(sshkey_from_private(kd, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(kd, k1); + ASSERT_INT_EQ(k1->type, KEY_DSA); + ASSERT_PTR_NE(k1->dsa, NULL); + ASSERT_PTR_NE(dsa_g(k1), NULL); + ASSERT_PTR_EQ(dsa_priv_key(k1), NULL); + TEST_DONE(); + + TEST_START("equal KEY_DSA/demoted KEY_DSA"); + ASSERT_INT_EQ(sshkey_equal(kd, k1), 1); + sshkey_free(k1); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("demote KEY_ECDSA"); + ASSERT_INT_EQ(sshkey_from_private(ke, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(ke, k1); + ASSERT_INT_EQ(k1->type, KEY_ECDSA); + ASSERT_PTR_NE(k1->ecdsa, 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); + TEST_DONE(); + + TEST_START("equal KEY_ECDSA/demoted KEY_ECDSA"); + ASSERT_INT_EQ(sshkey_equal(ke, k1), 1); + sshkey_free(k1); + TEST_DONE(); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + + TEST_START("demote KEY_ED25519"); + ASSERT_INT_EQ(sshkey_from_private(kf, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(kf, k1); + ASSERT_INT_EQ(k1->type, KEY_ED25519); + ASSERT_PTR_NE(k1->ed25519_pk, NULL); + ASSERT_PTR_EQ(k1->ed25519_sk, NULL); + TEST_DONE(); + + TEST_START("equal KEY_ED25519/demoted KEY_ED25519"); + ASSERT_INT_EQ(sshkey_equal(kf, k1), 1); + sshkey_free(k1); + TEST_DONE(); + +#ifdef WITH_OPENSSL + TEST_START("equal mismatched key types"); + ASSERT_INT_EQ(sshkey_equal(kd, kr), 0); +#ifdef OPENSSL_HAS_ECC + ASSERT_INT_EQ(sshkey_equal(kd, ke), 0); + ASSERT_INT_EQ(sshkey_equal(kr, ke), 0); + ASSERT_INT_EQ(sshkey_equal(ke, kf), 0); +#endif /* OPENSSL_HAS_ECC */ + ASSERT_INT_EQ(sshkey_equal(kd, kf), 0); + TEST_DONE(); +#endif /* WITH_OPENSSL */ + + TEST_START("equal different keys"); +#ifdef WITH_OPENSSL + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &k1), 0); + ASSERT_INT_EQ(sshkey_equal(kr, k1), 0); + sshkey_free(k1); + ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &k1), 0); + ASSERT_INT_EQ(sshkey_equal(kd, k1), 0); + sshkey_free(k1); +#ifdef OPENSSL_HAS_ECC + ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &k1), 0); + ASSERT_INT_EQ(sshkey_equal(ke, k1), 0); + sshkey_free(k1); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &k1), 0); + ASSERT_INT_EQ(sshkey_equal(kf, k1), 0); + sshkey_free(k1); + TEST_DONE(); + +#ifdef WITH_OPENSSL + sshkey_free(kr); + sshkey_free(kd); +#ifdef OPENSSL_HAS_ECC + sshkey_free(ke); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + sshkey_free(kf); + + TEST_START("certify key"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"), + &k1, NULL), 0); + k2 = get_private("ed25519_2"); + ASSERT_INT_EQ(sshkey_to_certified(k1), 0); + ASSERT_PTR_NE(k1->cert, NULL); + k1->cert->type = SSH2_CERT_TYPE_USER; + k1->cert->serial = 1234; + k1->cert->key_id = strdup("estragon"); + ASSERT_PTR_NE(k1->cert->key_id, NULL); + k1->cert->principals = calloc(4, sizeof(*k1->cert->principals)); + ASSERT_PTR_NE(k1->cert->principals, NULL); + k1->cert->principals[0] = strdup("estragon"); + k1->cert->principals[1] = strdup("vladimir"); + k1->cert->principals[2] = strdup("pozzo"); + k1->cert->principals[3] = strdup("lucky"); + ASSERT_PTR_NE(k1->cert->principals[0], NULL); + ASSERT_PTR_NE(k1->cert->principals[1], NULL); + ASSERT_PTR_NE(k1->cert->principals[2], NULL); + ASSERT_PTR_NE(k1->cert->principals[3], NULL); + k1->cert->nprincipals = 4; + k1->cert->valid_after = 0; + k1->cert->valid_before = (u_int64_t)-1; + sshbuf_free(k1->cert->critical); + k1->cert->critical = sshbuf_new(); + ASSERT_PTR_NE(k1->cert->critical, NULL); + sshbuf_free(k1->cert->extensions); + k1->cert->extensions = sshbuf_new(); + ASSERT_PTR_NE(k1->cert->extensions, NULL); + put_opt(k1->cert->critical, "force-command", "/usr/bin/true"); + put_opt(k1->cert->critical, "source-address", "127.0.0.1"); + put_opt(k1->cert->extensions, "permit-X11-forwarding", NULL); + put_opt(k1->cert->extensions, "permit-agent-forwarding", NULL); + ASSERT_INT_EQ(sshkey_from_private(k2, &k1->cert->signature_key), 0); + ASSERT_INT_EQ(sshkey_certify(k1, k2, NULL, NULL, NULL), 0); + b = sshbuf_new(); + ASSERT_PTR_NE(b, NULL); + ASSERT_INT_EQ(sshkey_putb(k1, b), 0); + ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k3), 0); + + sshkey_free(k1); + sshkey_free(k2); + sshkey_free(k3); + sshbuf_reset(b); + TEST_DONE(); + +#ifdef WITH_OPENSSL + TEST_START("sign and verify RSA"); + k1 = get_private("rsa_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2, "ssh-rsa"); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("sign and verify RSA-SHA256"); + k1 = get_private("rsa_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2, "rsa-sha2-256"); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("sign and verify RSA-SHA512"); + k1 = get_private("rsa_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2, "rsa-sha2-512"); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("sign and verify DSA"); + k1 = get_private("dsa_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2, NULL); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("sign and verify ECDSA"); + k1 = get_private("ecdsa_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2, NULL); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + + TEST_START("sign and verify ED25519"); + k1 = get_private("ed25519_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2, NULL); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); + +#ifdef WITH_OPENSSL + TEST_START("nested certificate"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, + NULL), 0); + k3 = get_private("rsa_1"); + build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, NULL); + ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4), + SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); + ASSERT_PTR_EQ(k4, NULL); + sshkey_free(k1); + sshkey_free(k2); + sshkey_free(k3); + sshbuf_free(b); + TEST_DONE(); +#endif /* WITH_OPENSSL */ +} diff --git a/regress/unittests/sshkey/testdata/dsa_1 b/regress/unittests/sshkey/testdata/dsa_1 new file mode 100644 index 0000000..d3f2482 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1 @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2m +Ka43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8Py +mcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwIVAKMD +/50qQy7j8JaMk+1+Xtg1pK01AoGBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwbl +o4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4P +h8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgz +LND26HrdAoGBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb +OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joo +t+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAhRYIbQ5 +KfXsZuBPuWe5FJz3ldaEgw== +-----END DSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.fp b/regress/unittests/sshkey/testdata/dsa_1-cert.fp new file mode 100644 index 0000000..75ff0e9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1-cert.fp @@ -0,0 +1 @@ +SHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.pub b/regress/unittests/sshkey/testdata/dsa_1-cert.pub new file mode 100644 index 0000000..e768db1 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1-cert.pub @@ -0,0 +1 @@ +ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgdTlbNU9Hn9Qng3FHxwH971bxCIoq1ern/QWFFDWXgmYAAACBAPqS600VGwdPAQC/p3f0uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw62+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxbOXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAAAAAAAAAAYAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANowB8AAAAABNHmBwAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAFMAAAALc3NoLWVkMjU1MTkAAABAh/z1LIdNL1b66tQ8t9DY9BTB3BQKpTKmc7ezyFKLwl96yaIniZwD9Ticdbe/8i/Li3uCFE3EAt8NAIv9zff8Bg== DSA test key #1 diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp b/regress/unittests/sshkey/testdata/dsa_1.fp new file mode 100644 index 0000000..75ff0e9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.fp @@ -0,0 +1 @@ +SHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp.bb b/regress/unittests/sshkey/testdata/dsa_1.fp.bb new file mode 100644 index 0000000..ba37776 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.fp.bb @@ -0,0 +1 @@ +xetag-todiz-mifah-torec-mynyv-cyvit-gopon-pygag-rupic-cenav-bexax diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.g b/regress/unittests/sshkey/testdata/dsa_1.param.g new file mode 100644 index 0000000..e51c3f9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.param.g @@ -0,0 +1 @@ +00eee5f505556d24a8cb996ae9c3adbe97fc525c0e6bafb30706e5a3882615dd51c17d725a403c910ed1ae109283c1dcea62069ca460291962ff72e06d27d9d286c525e86446d116b4de0f87c7d551e4bbe2241b23015078a9581c894d4d1a06b406dd8b79c7755f81064110735577ae3a98aa18cea33ff236c8332cd0f6e87add diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.priv b/regress/unittests/sshkey/testdata/dsa_1.param.priv new file mode 100644 index 0000000..4f74331 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.param.priv @@ -0,0 +1 @@ +5821b43929f5ec66e04fb967b9149cf795d68483 diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.pub b/regress/unittests/sshkey/testdata/dsa_1.param.pub new file mode 100644 index 0000000..ba0313b --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.param.pub @@ -0,0 +1 @@ +00e757a727e6a1b10168ea9902ebe08f53f4ba18c6d8fdf551fbabbf6d8558f054dc0f6aae4c5b397c04d0bc2f8c2bebb1057f96b621273fed8b2b38d1579a86e956644e520073171887fde4b88b4a0697323928ee3a28b7e2caf3896d2f29b067840c9d88e765249c95fd54bb240c714b5bdf8f88d2ef58727ca1a7699216c42d diff --git a/regress/unittests/sshkey/testdata/dsa_1.pub b/regress/unittests/sshkey/testdata/dsa_1.pub new file mode 100644 index 0000000..41cae2f --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAPqS600VGwdPAQC/p3f0uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw62+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxbOXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQt DSA test key #1 diff --git a/regress/unittests/sshkey/testdata/dsa_1_pw b/regress/unittests/sshkey/testdata/dsa_1_pw new file mode 100644 index 0000000..24c7303 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_1_pw @@ -0,0 +1,15 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,BC8386C373B22EB7F00ADC821D5D8BE9 + ++HDV2DQ09sxrIAeXTz9r3YFuPRa2hk1+NGcr3ETkXbC6KiZ14wpTnGTloKwaQjIW +eXTa9mpCOWAoohgvsVb+hOuOlP7AfeHu1IXV4EAS+GDpkiV5UxlCXXwqlD75Buu4 +wwDd/p4SWzILH3WGjDk5JIXoxWNY13LHwC7Q6gtGJx4AicUG7YBRTXMIBDa/Kh77 +6o2rFETKmp4VHBvHbakmiETfptdM8bbWxKWeY2vakThyESgeofsLoTOQCIwlEfJC +s2D/KYL65C8VbHYgIoSLTQnooO45DDyxIuhCqP+H23mhv9vB1Od3nc2atgHj/XFs +dcOPFkF/msDRYqxY3V0AS6+jpKwFodZ7g/hyGcyPxOkzlJVuKoKuH6P5PyQ69Gx0 +iqri0xEPyABr7kGlXNrjjctojX+B4WwSnjg/2euXXWFXCRalIdA7ErATTiQbGOx7 +Vd6Gn8PZbSy1MkqEDrZRip0pfAFJYI/8GXPC75BpnRsrVlfhtrngbW+kBP35LzaN +l2K+RQ3gSB3iFoqNb1Kuu6T5MZlyVl5H2dVlJSeb1euQ2OycXdDoFTyJ4AiyWS7w +Vlh8zeJnso5QRDjMwx99pZilbbuFGSLsahiGEveFc6o= +-----END DSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/dsa_2 b/regress/unittests/sshkey/testdata/dsa_2 new file mode 100644 index 0000000..3cc9631 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_2 @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvQIBAAKBgQCbyPXNdHeLsjpobPVCMkfagBkt15Zsltqf/PGNP1y1cuz7rsTX +ZekQwUkSTNm5coqXe+ZOw2O4tjobJDd60I1/VPgaB0NYlQR9Hn87M284WD4f6VY+ +aunHmP134a8ybG5G4NqVNF3ihvxAR2pVITqb7kE46r2uYZNcNlHI8voRCwIVAMcP +bwqFNsQbH5pJyZW30wj4KVZ3AoGBAIK98BVeKQVf8qDFqx9ovMuNgVSxpd+N0Yta +5ZEy1OI2ziu5RhjueIM2K7Gq2Mnp38ob1AM53BUxqlcBJaHEDa6rj6yvuMgW9oCJ +dImBM8sIFxfBbXNbpJiMaDwa6WyT84OkpDE6uuAepTMnWOUWkUVkAiyokHDUGXkG +GyoQblbXAoGBAIsf7TaZ804sUWwRV0wI8DYx+hxD5QdrfYPYMtL2fHn3lICimGt0 +FTtUZ25jKg0E0DMBPdET6ZEHB3ZZkR8hFoUzZhdnyJMu3UjVtgaV88Ue3PrXxchk +0W2jHPaAgQU3JIWzo8HFIFqvC/HEL+EyW3rBTY2uXM3XGI+YcWSA4ZrZAhUAsY2f +bDFNzgZ4DaZ9wLRzTgOswPU= +-----END DSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp b/regress/unittests/sshkey/testdata/dsa_2.fp new file mode 100644 index 0000000..51fbeb4 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_2.fp @@ -0,0 +1 @@ +SHA256:ecwhWcXgpdBxZ2e+OjpRRY7dqXHHCD62BGtoVQQBwCk diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp.bb b/regress/unittests/sshkey/testdata/dsa_2.fp.bb new file mode 100644 index 0000000..4d908ee --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_2.fp.bb @@ -0,0 +1 @@ +xeser-megad-pocan-rozit-belup-tapoh-fapif-kyvit-vonav-cehab-naxax diff --git a/regress/unittests/sshkey/testdata/dsa_2.pub b/regress/unittests/sshkey/testdata/dsa_2.pub new file mode 100644 index 0000000..77bb555 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_2.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAJvI9c10d4uyOmhs9UIyR9qAGS3XlmyW2p/88Y0/XLVy7PuuxNdl6RDBSRJM2blyipd75k7DY7i2OhskN3rQjX9U+BoHQ1iVBH0efzszbzhYPh/pVj5q6ceY/XfhrzJsbkbg2pU0XeKG/EBHalUhOpvuQTjqva5hk1w2Ucjy+hELAAAAFQDHD28KhTbEGx+aScmVt9MI+ClWdwAAAIEAgr3wFV4pBV/yoMWrH2i8y42BVLGl343Ri1rlkTLU4jbOK7lGGO54gzYrsarYyenfyhvUAzncFTGqVwElocQNrquPrK+4yBb2gIl0iYEzywgXF8Ftc1ukmIxoPBrpbJPzg6SkMTq64B6lMydY5RaRRWQCLKiQcNQZeQYbKhBuVtcAAACBAIsf7TaZ804sUWwRV0wI8DYx+hxD5QdrfYPYMtL2fHn3lICimGt0FTtUZ25jKg0E0DMBPdET6ZEHB3ZZkR8hFoUzZhdnyJMu3UjVtgaV88Ue3PrXxchk0W2jHPaAgQU3JIWzo8HFIFqvC/HEL+EyW3rBTY2uXM3XGI+YcWSA4ZrZ DSA test key #2 diff --git a/regress/unittests/sshkey/testdata/dsa_n b/regress/unittests/sshkey/testdata/dsa_n new file mode 100644 index 0000000..657624e --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_n @@ -0,0 +1,21 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABswAAAAdzc2gtZH +NzAAAAgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2mKa43vzXI8CNw +mRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8PymcHOxueHs95IcjrbIP +Nn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwAAABUAowP/nSpDLuPwloyT7X5e2DWk +rTUAAACBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwblo4gmFd1RwX1yWkA8kQ7RrhCSg8 +Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4Ph8fVUeS74iQbIwFQeKlYHIlNTRoGtAbd +i3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgzLND26HrdAAAAgQDnV6cn5qGxAWjqmQLr4I9T9L +oYxtj99VH7q79thVjwVNwPaq5MWzl8BNC8L4wr67EFf5a2ISc/7YsrONFXmobpVmROUgBz +FxiH/eS4i0oGlzI5KO46KLfiyvOJbS8psGeEDJ2I52UknJX9VLskDHFLW9+PiNLvWHJ8oa +dpkhbELQAAAdhWTOFbVkzhWwAAAAdzc2gtZHNzAAAAgQD6kutNFRsHTwEAv6d39Lhsqy1a +pdHBZ9c2HfyRr7WmypyGIy2mKa43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+Miwf +urwrR3CRe61QRYb8PymcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXplig +rGt2XwAAABUAowP/nSpDLuPwloyT7X5e2DWkrTUAAACBAO7l9QVVbSSoy5lq6cOtvpf8Ul +wOa6+zBwblo4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEW +tN4Ph8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgzLN +D26HrdAAAAgQDnV6cn5qGxAWjqmQLr4I9T9LoYxtj99VH7q79thVjwVNwPaq5MWzl8BNC8 +L4wr67EFf5a2ISc/7YsrONFXmobpVmROUgBzFxiH/eS4i0oGlzI5KO46KLfiyvOJbS8psG +eEDJ2I52UknJX9VLskDHFLW9+PiNLvWHJ8oadpkhbELQAAABRYIbQ5KfXsZuBPuWe5FJz3 +ldaEgwAAAAAB +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/dsa_n_pw b/regress/unittests/sshkey/testdata/dsa_n_pw new file mode 100644 index 0000000..24ac299 --- /dev/null +++ b/regress/unittests/sshkey/testdata/dsa_n_pw @@ -0,0 +1,21 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABCVs+LsMJ +wnB5zM9U9pTXrGAAAAEAAAAAEAAAGzAAAAB3NzaC1kc3MAAACBAPqS600VGwdPAQC/p3f0 +uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y +4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0 +k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw6 +2+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl +6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/ +I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb +OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84 +ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAAAB4HiOcRW4w+sIqBL0 +TPVbf0glN1hUi0rcE63Pqxmvxb8LkldC4IxAUagPrjhNAEW2AY42+CvPrtGB1z7gDADAIW +xZX6wKwIcXP0Qh+xHE12F4u6mwfasssnAp4t1Ki8uCjMjnimgb3KdWpp0kiUV0oR062TXV +PAdfrWjaq4fw0KOqbHIAG/v36AqzuqjSTfDbqvLZM3y0gp2Q1RxaQVJA5ZIKKyqRyFX7sr +BaEIyCgeE3hM0EB7BycY1oIcS/eNxrACBWVJCENl5N7LtEYXNX7TANFniztfXzwaqGTT6A +fCfbW4gz1UKldLUBzbIrPwMWlirAstbHvOf/2Iay2pNAs/SHhI0aF2jsGfvv5/D6N+r9dG +B2SgDKBg7pywMH1DTvg6YT3P4GjCx0GUHqRCFLvD1rDdk4KSjvaRMpVq1PJ0/Wv6UGtsMS +TR0PaEHDRNZqAX4YxqujnWrGKuRJhuz0eUvp7fZvbWHtiAMKV7368kkeUmkOHanb+TS+zs +KINX8ev8zJZ6WVr8Vl+IQavpv0i2bXwS6QqbEuifpv/+uBb7pqRiU4u8en0eMdX1bZoTPM +R6xHCnGD/Jpb3zS91Ya57T6CiXZ12KCaL6nWGnCkZVpzkfJ2HjFklWSWBQ6uyaosDQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_1 b/regress/unittests/sshkey/testdata/ecdsa_1 new file mode 100644 index 0000000..80382b6 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMoAoGCCqGSM49 +AwEHoUQDQgAEDFlblkOrW9ydKVhtM+9AY3c9saBE7SG3lFx38nBavkADDaI9jh3/ +kvG/Jt9vpm22qwoklTCGDfzCkXkIKaWlBw== +-----END EC PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp b/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp new file mode 100644 index 0000000..e48304f --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp @@ -0,0 +1 @@ +SHA256:8ty77fOpABat1y88aNdclQTfU+lVvWe7jYZGw8VYtfg diff --git a/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub b/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub new file mode 100644 index 0000000..55e2a25 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgOtFRnMigkGliaYfPmX5IidVWfV3tRH6lqRXv0l8bvKoAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQcAAAAAAAAABwAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2jAHwAAAAAE0eYHAAAAAAAAAAAAAAAAAAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQcAAABkAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABJAAAAIHbxGwTnue7KxhHXGFvRcxBnekhQ3Qx84vV/Vs4oVCrpAAAAIQC7vk2+d14aS7td7kVXLQn392oALjEBzMZoDvT1vT/zOA== ECDSA test key #1 diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.fp b/regress/unittests/sshkey/testdata/ecdsa_1.fp new file mode 100644 index 0000000..e48304f --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.fp @@ -0,0 +1 @@ +SHA256:8ty77fOpABat1y88aNdclQTfU+lVvWe7jYZGw8VYtfg diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb new file mode 100644 index 0000000..fa23c33 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb @@ -0,0 +1 @@ +xibah-vocun-sogyn-byhen-rivem-hegyh-luneh-dozyr-vatyf-dufid-myxyx diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.curve b/regress/unittests/sshkey/testdata/ecdsa_1.param.curve new file mode 100644 index 0000000..fa04004 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.curve @@ -0,0 +1 @@ +prime256v1 diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.priv b/regress/unittests/sshkey/testdata/ecdsa_1.param.priv new file mode 100644 index 0000000..dc908ad --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.priv @@ -0,0 +1 @@ +00f3cdc940278ef16bf9e4ffeedfc8ca3b9041dfda2c589363dd8b07d8088f2acc diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.pub b/regress/unittests/sshkey/testdata/ecdsa_1.param.pub new file mode 100644 index 0000000..71c9584 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.pub @@ -0,0 +1 @@ +040c595b9643ab5bdc9d29586d33ef4063773db1a044ed21b7945c77f2705abe40030da23d8e1dff92f1bf26df6fa66db6ab0a249530860dfcc291790829a5a507 diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.pub b/regress/unittests/sshkey/testdata/ecdsa_1.pub new file mode 100644 index 0000000..84a71f9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQc= ECDSA test key #1 diff --git a/regress/unittests/sshkey/testdata/ecdsa_1_pw b/regress/unittests/sshkey/testdata/ecdsa_1_pw new file mode 100644 index 0000000..5c83a65 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_1_pw @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,7BA38DE00F67851E4207216809C3BB15 + +8QkFoZHQkj9a2mt032sp+WKaJ1fwteqWDd4RpAW9OzDgqzMx1QO43qJgBDTfhzjt +M2Q8YfiGjfBEYpg4kCbacfcV68DEV4z6Ll7rIzzzO7OfWUNL++brD64vKx4z6f46 ++sn4nbZTXilpkzi/nmPDVzrNmTSywA8T7Yf0QcBUxks= +-----END EC PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_2 b/regress/unittests/sshkey/testdata/ecdsa_2 new file mode 100644 index 0000000..0f4e844 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2 @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIBqBtN7e6Essd3dlsgISViPCXXC0atlNkGtoMgSQdBTKVUfeJOi4lc +RZaXJdXnqWUqI/KEsH8h8QN4YcB8ugmAcc+gBwYFK4EEACOhgYkDgYYABAHZ2VNy +oDedBwqsdzY+kkNptc9DrtRCVmO6cULLj+691MhItqVqTMJbTFlI4MnAg9PoGTF/ +0KmLJfy8vSffXGKqqwGKcFNtd1XCo+7Qu9tXbxron9g6Dmu7y8jaLkixcwZwnwLs +6GmA9qZGuiAfOGV0Gf9/u98sr+vikOa4Ow5JFDTw5g== +-----END EC PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.fp b/regress/unittests/sshkey/testdata/ecdsa_2.fp new file mode 100644 index 0000000..581e48a --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.fp @@ -0,0 +1 @@ +SHA256:ed8YniRHA6qCrErCRnzrWxPHxYuA62a+CAFYUVxJgaI diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb new file mode 100644 index 0000000..e1cc664 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb @@ -0,0 +1 @@ +xufag-danul-putub-mokin-pugaz-covid-dofag-nihuz-sysab-genar-zaxyx diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.curve b/regress/unittests/sshkey/testdata/ecdsa_2.param.curve new file mode 100644 index 0000000..617ea2f --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.curve @@ -0,0 +1 @@ +secp521r1 diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.priv b/regress/unittests/sshkey/testdata/ecdsa_2.param.priv new file mode 100644 index 0000000..dd898d9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.priv @@ -0,0 +1 @@ +01a81b4dedee84b2c777765b202125623c25d70b46ad94d906b683204907414ca5547de24e8b895c45969725d5e7a9652a23f284b07f21f1037861c07cba098071cf diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.pub b/regress/unittests/sshkey/testdata/ecdsa_2.param.pub new file mode 100644 index 0000000..94301c9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.pub @@ -0,0 +1 @@ +0401d9d95372a0379d070aac77363e924369b5cf43aed4425663ba7142cb8feebdd4c848b6a56a4cc25b4c5948e0c9c083d3e819317fd0a98b25fcbcbd27df5c62aaab018a70536d7755c2a3eed0bbdb576f1ae89fd83a0e6bbbcbc8da2e48b17306709f02ece86980f6a646ba201f38657419ff7fbbdf2cafebe290e6b83b0e491434f0e6 diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.pub b/regress/unittests/sshkey/testdata/ecdsa_2.pub new file mode 100644 index 0000000..be9d84b --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_2.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHZ2VNyoDedBwqsdzY+kkNptc9DrtRCVmO6cULLj+691MhItqVqTMJbTFlI4MnAg9PoGTF/0KmLJfy8vSffXGKqqwGKcFNtd1XCo+7Qu9tXbxron9g6Dmu7y8jaLkixcwZwnwLs6GmA9qZGuiAfOGV0Gf9/u98sr+vikOa4Ow5JFDTw5g== ECDSA test key #2 diff --git a/regress/unittests/sshkey/testdata/ecdsa_n b/regress/unittests/sshkey/testdata/ecdsa_n new file mode 100644 index 0000000..9694f32 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_n @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQMWVuWQ6tb3J0pWG0z70Bjdz2xoETt +IbeUXHfycFq+QAMNoj2OHf+S8b8m32+mbbarCiSVMIYN/MKReQgppaUHAAAAoFrmmZBa5p +mQAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlY +bTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQ +cAAAAhAPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMAAAAAAECAwQFBgc= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_n_pw b/regress/unittests/sshkey/testdata/ecdsa_n_pw new file mode 100644 index 0000000..36b7fa7 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_n_pw @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABC4UwEov5 +z0RrCm7AMCxbuiAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlz +dHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvy +bfb6ZttqsKJJUwhg38wpF5CCmlpQcAAACgbCnAklQTHrf5qiHiMxKYwQJ7k/X9mp4fXD4v +xUbgNZiXSxN26mn8mC2rH+WA6Lk3CexR/hrtLI2ndpBsYu1h6HhVkOwwm3Kd/PMKArCupW +l6sYEabrT0EghXR/3aDEZvj79hgKSdu3RpayLvMdbCR8k1cg0/mDmR9hicWfeJ61n/IH05 +tUR268+0BVRW9kDhh/cuv8tVY4L09jCCQ6CpsA== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1 b/regress/unittests/sshkey/testdata/ecdsa_sk1 new file mode 100644 index 0000000..b51fb73 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1 @@ -0,0 +1,13 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 +RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQRnVT5Cji1D +Ge2+q2X0vATh6LYnODV+DJrshJorr5GnipW29RfuaDXs0WB6XBej9dOLazVRDjQrtV19Qg +O6cfkFAAAABHNzaDoAAAGQuPdnP7j3Zz8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv +cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEZ1U+Qo4tQxntvqtl9LwE4ei2Jzg1fgya7I +SaK6+Rp4qVtvUX7mg17NFgelwXo/XTi2s1UQ40K7VdfUIDunH5BQAAAARzc2g6AQAAAOMt +LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJRURmVFB4YzA0alN5Zk +Z5NlhoV1pTVlpzcnU5ZFlaSVpTOWhjeVFhcDlVT29Bb0dDQ3FHU000OQpBd0VIb1VRRFFn +QUVaMVUrUW80dFF4bnR2cXRsOUx3RTRlaTJKemcxZmd5YTdJU2FLNitScDRxVnR2VVg3bW +cxCjdORmdlbHdYby9YVGkyczFVUTQwSzdWZGZVSUR1bkg1QlE9PQotLS0tLUVORCBFQyBQ +UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzEBAgMEBQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp new file mode 100644 index 0000000..d192145 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp @@ -0,0 +1 @@ +SHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub new file mode 100644 index 0000000..9586c61 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgE012YoSBE9hEC2FRzblcSx784JNo2A4g611A7I75YMMAAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAAAAAAAHAAAAAgAAAAZqdWxpdXMAAAASAAAABWhvc3QxAAAABWhvc3QyAAAAADaLg2AAAAAATR3h4AAAAAAAAAAAAAAAAAAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAEEEAlTtPiWUHubBeCys4Xp0QF91dYARpkyqtCnzg10HRS+ZDgkMrSUvPPG+Ge8iqtnB951MBxDq9FqDFIkhQBYXDAAAAGQAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAEkAAAAhALY+eXRJjVGnMk38Sm5S+H5CloNq757ypsoxt+WYoadtAAAAIA42/mAhUfLij1GY7wl+OFrI+icB/t4tGiEUZmhx6Foo ECDSA-SK test key #1 diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1.fp b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp new file mode 100644 index 0000000..d192145 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp @@ -0,0 +1 @@ +SHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb new file mode 100644 index 0000000..cb9f4dd --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb @@ -0,0 +1 @@ +xovem-sacac-dageg-vovoc-symyz-bozal-cibiv-cyvat-vylyn-romib-hoxax diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1.pub b/regress/unittests/sshkey/testdata/ecdsa_sk1.pub new file mode 100644 index 0000000..c3b21e0 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOg== ECDSA-SK test key #1 diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1_pw b/regress/unittests/sshkey/testdata/ecdsa_sk1_pw new file mode 100644 index 0000000..4fa23a7 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1_pw @@ -0,0 +1,14 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB6vcJVx2 +cPc7yYRROup8VnAAAAEAAAAAEAAAB/AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3Bl +bnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmi +uvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAZBrvCxe +xFz0bvzXwaPhrUHBeNCoZy/wNKDx0kxlxUPuA+lgOvy5l3lT3yxxd0qj5PQB+NTcuz8AAE +1f7aSWQNZSifox3COsBGoHV9C8i+glcxiBKheAZD+EBnRGjG8kbcaLhuYDW/I39qNe8lHW +YSDjmvsT55Hy0IAtVRAXizDoXKNdFPTZisC67WyOSJ3ED7Fy4bfT4ApbvhoFTwjikZBEhy +LOad1sbJa4eT19TsskYfQdnJf8sjAmCMOZY4ZV0FiNW5XZOp8nIal1oyULPfzTAm6oaeFN +0ImCSU3U8h4wUQ8q/3XvBWtTKycZaoou0AwPoP0QN95Ywte7FHezNPb/n8KD7k0S6h9XAX +UcBeCe5NHyov/0ZzA2p737hzm3w+MXGOboTQMu8WFXeGh4m7QH2o8ZJdgBhM5JF17uii+Q +ppGoPWHf33MXwB3wxWmKZ0ua0f9AVLkQ2DfFszUoBJE/kcHRd4kj4Q4FWXeMBN0GoH8gdE +gRWIlxn2/FAOce/BFPzzdP87H0jwz7SdcuVO1L +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2 b/regress/unittests/sshkey/testdata/ecdsa_sk2 new file mode 100644 index 0000000..19db5a3 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk2 @@ -0,0 +1,13 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 +RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSTl+SR6rTg +lOZmcQkCtJ3Pd+lWinezo/gHk4oZdZcTQsmEYs766BlWGuB2Bz3qQRLa6cXsP+4K9kAjAJ +7zdoFUAAAABHNzaDoAAAGQ1qllJtapZSYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv +cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEk5fkkeq04JTmZnEJArSdz3fpVop3s6P4B5 +OKGXWXE0LJhGLO+ugZVhrgdgc96kES2unF7D/uCvZAIwCe83aBVAAAAARzc2g6AQAAAOMt +LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSkxwVkxnSTVvdkRlOW +VMWmZodCs5WWlMaitnam0rTXhHTXg5NndiRWw0Wm9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn +QUVrNWZra2VxMDRKVG1abkVKQXJTZHozZnBWb3AzczZQNEI1T0tHWFdYRTBMSmhHTE8rdW +daClZocmdkZ2M5NmtFUzJ1bkY3RC91Q3ZaQUl3Q2U4M2FCVkE9PQotLS0tLUVORCBFQyBQ +UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzIBAgMEBQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2.fp b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp new file mode 100644 index 0000000..1bc99ea --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp @@ -0,0 +1 @@ +SHA256:pz8VkgtRY3r50F4zSuzRlmq9c6vPTpJXLKKOgkyUcKE diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb new file mode 100644 index 0000000..bfee765 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb @@ -0,0 +1 @@ +xobel-gavur-gorym-pedop-rarob-bunek-gucer-lofeg-syhaf-fylur-zoxix diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2.pub b/regress/unittests/sshkey/testdata/ecdsa_sk2.pub new file mode 100644 index 0000000..2629d95 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk2.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBJOX5JHqtOCU5mZxCQK0nc936VaKd7Oj+AeTihl1lxNCyYRizvroGVYa4HYHPepBEtrpxew/7gr2QCMAnvN2gVQAAAAEc3NoOg== ECDSA-SK test key #2 diff --git a/regress/unittests/sshkey/testdata/ed25519_1 b/regress/unittests/sshkey/testdata/ed25519_1 new file mode 100644 index 0000000..6b0ae01 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAJjnj4Ao54+A +KAAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQ +AAAED3KgoDbjR54V7bdNpfKlQY5m20UK1QaHytkCR+6rZEDFOG6kY7Rf4UtCFvPwKgo/Bz +tXck2xC4a2WyA34XtIwZAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ed25519_1-cert.fp b/regress/unittests/sshkey/testdata/ed25519_1-cert.fp new file mode 100644 index 0000000..a9674e2 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1-cert.fp @@ -0,0 +1 @@ +SHA256:L3k/oJubblSY0lB9Ulsl7emDMnRPKm/8udf2ccwk560 diff --git a/regress/unittests/sshkey/testdata/ed25519_1-cert.pub b/regress/unittests/sshkey/testdata/ed25519_1-cert.pub new file mode 100644 index 0000000..649b4e8 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1-cert.pub @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIIxzuxl4z3uwAIslne8Huft+1n1IhHAlNbWZkQyyECCGAAAAIFOG6kY7Rf4UtCFvPwKgo/BztXck2xC4a2WyA34XtIwZAAAAAAAAAAgAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANowB8AAAAABNHmBwAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAFMAAAALc3NoLWVkMjU1MTkAAABABGTn+Bmz86Ajk+iqKCSdP5NClsYzn4alJd0V5bizhP0Kumc/HbqQfSt684J1WdSzih+EjvnTgBhK9jTBKb90AQ== ED25519 test key #1 diff --git a/regress/unittests/sshkey/testdata/ed25519_1.fp b/regress/unittests/sshkey/testdata/ed25519_1.fp new file mode 100644 index 0000000..a9674e2 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1.fp @@ -0,0 +1 @@ +SHA256:L3k/oJubblSY0lB9Ulsl7emDMnRPKm/8udf2ccwk560 diff --git a/regress/unittests/sshkey/testdata/ed25519_1.fp.bb b/regress/unittests/sshkey/testdata/ed25519_1.fp.bb new file mode 100644 index 0000000..309f2da --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1.fp.bb @@ -0,0 +1 @@ +xubop-rekyd-bakal-nubuf-pahaf-gicuh-logeb-gocif-petod-galip-fuxux diff --git a/regress/unittests/sshkey/testdata/ed25519_1.pub b/regress/unittests/sshkey/testdata/ed25519_1.pub new file mode 100644 index 0000000..e533059 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFOG6kY7Rf4UtCFvPwKgo/BztXck2xC4a2WyA34XtIwZ ED25519 test key #1 diff --git a/regress/unittests/sshkey/testdata/ed25519_1_pw b/regress/unittests/sshkey/testdata/ed25519_1_pw new file mode 100644 index 0000000..da94d2b --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_1_pw @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDKT56mBA +tXIMsWqmuuA2gdAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIFOG6kY7Rf4UtCFv +PwKgo/BztXck2xC4a2WyA34XtIwZAAAAoC13U47yfUOSZJePNUAwWXuFOk3aOKwPM5PMvK +0zwRnMZZjgn+tsMAYPwhsT3Mx3h5QzvVGFyFEqsiK7j4vAotD+LVQeBN5TwWbUBx4lnoGs +3iAfYVDakO/gNvVBDDGOqv5kdCc4cgn5HacjHQLKOAx6KzHe7JFn7uCywMdVVQjlpI6LHb +mHkaKiVX/C2oiRnsoe17HZ8Fxyt3vd1qNM8BE= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ed25519_2 b/regress/unittests/sshkey/testdata/ed25519_2 new file mode 100644 index 0000000..e4aed63 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_2 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACDPVKyLnm3eZE0lm0IfM3Uy9AsdGSBtozcoCt21blYBCwAAAJix1mBGsdZg +RgAAAAtzc2gtZWQyNTUxOQAAACDPVKyLnm3eZE0lm0IfM3Uy9AsdGSBtozcoCt21blYBCw +AAAECZEQHXs18o3DKjhUYaTyt+bUbhqfMeqmsKjYyFvzGVgs9UrIuebd5kTSWbQh8zdTL0 +Cx0ZIG2jNygK3bVuVgELAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ed25519_2.fp b/regress/unittests/sshkey/testdata/ed25519_2.fp new file mode 100644 index 0000000..0496626 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_2.fp @@ -0,0 +1 @@ +SHA256:vMbaARqVciRgXyZPNHDo+P5p5WK5yWG1Oo6VC35Bomw diff --git a/regress/unittests/sshkey/testdata/ed25519_2.fp.bb b/regress/unittests/sshkey/testdata/ed25519_2.fp.bb new file mode 100644 index 0000000..abba789 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_2.fp.bb @@ -0,0 +1 @@ +xuces-bapyb-vikob-zesyv-budod-nupip-kebon-tacyc-fofed-lezic-soxax diff --git a/regress/unittests/sshkey/testdata/ed25519_2.pub b/regress/unittests/sshkey/testdata/ed25519_2.pub new file mode 100644 index 0000000..af34236 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_2.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM9UrIuebd5kTSWbQh8zdTL0Cx0ZIG2jNygK3bVuVgEL ED25519 test key #1 diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1 b/regress/unittests/sshkey/testdata/ed25519_sk1 new file mode 100644 index 0000000..4196d9c --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1 @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 +gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAhaP5OS1PPOt7uumAvXlDtte9EHbqIT1EZEJ2y +2v3XMwAAAARzc2g6AAAAuBocY6UaHGOlAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 +9tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoBAAAAQJYq +lGHhFoA25/q8X/rdTqDAb7dhqs4ehhd/w8x99CwiIWj+TktTzzre7rpgL15Q7bXvRB26iE +9RGRCdstr91zMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzEBAgM= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp new file mode 100644 index 0000000..a6bb1a9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp @@ -0,0 +1 @@ +SHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub new file mode 100644 index 0000000..3c72c26 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub @@ -0,0 +1 @@ +sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJr7CuMntQKvHoUshx374fJLFEkyxKsEOBA1H6hk5scoAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAAAAAAAACAAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIOo/0xneV3iM2qWEo5RUwvUYa2bjff292T5vvuXRomGQAAAAUwAAAAtzc2gtZWQyNTUxOQAAAECgsRGLDh1SI3m66MRp9D2iLP4wabQ0OrDgGidk7LsVn2XZHV5jBZN1RtNfe6PBMeVzfRtGUzOg18sO7H7uU+EC ED25519-SK test key #1 diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1.fp b/regress/unittests/sshkey/testdata/ed25519_sk1.fp new file mode 100644 index 0000000..a6bb1a9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1.fp @@ -0,0 +1 @@ +SHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb b/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb new file mode 100644 index 0000000..1bfe20a --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb @@ -0,0 +1 @@ +xucac-vusip-tydoz-dudad-nerif-raran-tezun-cogyd-pamoh-bahef-ruxix diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1.pub b/regress/unittests/sshkey/testdata/ed25519_sk1.pub new file mode 100644 index 0000000..60fe00c --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1.pub @@ -0,0 +1 @@ +sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDo= ED25519-SK test key #1 diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1_pw b/regress/unittests/sshkey/testdata/ed25519_sk1_pw new file mode 100644 index 0000000..1c29ff0 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1_pw @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDr5R9Yf/ +ucEh0Ns6c34tcIAAAAEAAAAAEAAABKAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t +AAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAADA2T6owx +OSgKz4DvLnS3UJ/renbuew5mbkIWB1/y8xd3y5Usm08iUCAlKxep9dVRQvmyoTrc/7rHOM +DkokNw+WgKambnlYT/9QfqViZ9iCBtbdmhLM6ksUCgQefvquRyXoJxlWstjXUll6Ru+ZbT +H//Ss8C1bYtAiXR68OQ+rhDrvQxA9P8J1sGIlkuV3h8YXddSpyBW2Sn0LTHHBXYZo86cXZ +G4Lnc8aGYm65eqdHgkfRmht3eS8DTdzEBfBNH5Ml +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2 b/regress/unittests/sshkey/testdata/ed25519_sk2 new file mode 100644 index 0000000..b9b7489 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk2 @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 +gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAV8fu1Sc31QLK2R/zGPdN3ve5xuFvDc7mEAWxb +aI+YcwAAAARzc2g6AAAAuJCMX5uQjF+bAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 +9tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDoBAAAAQObE +PajcKI1W30EKOhBb6u+Fgx464kf7EjnqDSg4l7gAFfH7tUnN9UCytkf8xj3Td73ucbhbw3 +O5hAFsW2iPmHMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzIBAgM= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2.fp b/regress/unittests/sshkey/testdata/ed25519_sk2.fp new file mode 100644 index 0000000..1c4369a --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk2.fp @@ -0,0 +1 @@ +SHA256:b9BVPS5vuU4yu/FgweojLLg6zbfmBBoWLUgibdxxsoo diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb b/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb new file mode 100644 index 0000000..f5fd9ef --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb @@ -0,0 +1 @@ +xemac-tizim-dihep-supar-zupib-cukak-pasis-febeg-dyguv-hutec-dyxox diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2.pub b/regress/unittests/sshkey/testdata/ed25519_sk2.pub new file mode 100644 index 0000000..c7ed9f5 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk2.pub @@ -0,0 +1 @@ +sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDo= ED25519-SK test key #2 diff --git a/regress/unittests/sshkey/testdata/pw b/regress/unittests/sshkey/testdata/pw new file mode 100644 index 0000000..8a1dff9 --- /dev/null +++ b/regress/unittests/sshkey/testdata/pw @@ -0,0 +1 @@ +mekmitasdigoat diff --git a/regress/unittests/sshkey/testdata/rsa_1 b/regress/unittests/sshkey/testdata/rsa_1 new file mode 100644 index 0000000..5de3f84 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u +d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd +NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB +AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ +GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj +Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv +Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i +PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa +WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj +mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi +C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e +NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ +h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs= +-----END RSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/rsa_1-cert.fp b/regress/unittests/sshkey/testdata/rsa_1-cert.fp new file mode 100644 index 0000000..79f380a --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1-cert.fp @@ -0,0 +1 @@ +SHA256:l6itGumSMcRBBAFteCgmjQBIXqLK/jFGUH3viHX1RmE diff --git a/regress/unittests/sshkey/testdata/rsa_1-cert.pub b/regress/unittests/sshkey/testdata/rsa_1-cert.pub new file mode 100644 index 0000000..3bacf3c --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1-cert.pub @@ -0,0 +1 @@ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg98LhS2EHxLOWCLopZPwHdg/RJXusnkOqQXSc9R7aITkAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAAFAAAAAgAAAAZqdWxpdXMAAAASAAAABWhvc3QxAAAABWhvc3QyAAAAADaMAfAAAAAATR5gcAAAAAAAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgU4bqRjtF/hS0IW8/AqCj8HO1dyTbELhrZbIDfhe0jBkAAABTAAAAC3NzaC1lZDI1NTE5AAAAQI3QGlUCzC07KorupxpDkkGy6tniaZ8EvBflzvv+itXWNchGvfUeHmVT6aX0sRqehdz/lR+GmXRoZBhofwh0qAM= RSA test key #1 diff --git a/regress/unittests/sshkey/testdata/rsa_1.fp b/regress/unittests/sshkey/testdata/rsa_1.fp new file mode 100644 index 0000000..79f380a --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.fp @@ -0,0 +1 @@ +SHA256:l6itGumSMcRBBAFteCgmjQBIXqLK/jFGUH3viHX1RmE diff --git a/regress/unittests/sshkey/testdata/rsa_1.fp.bb b/regress/unittests/sshkey/testdata/rsa_1.fp.bb new file mode 100644 index 0000000..45bacd5 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.fp.bb @@ -0,0 +1 @@ +xosis-fodod-votot-dibum-ryvac-rediz-naruf-votun-kevis-halis-gexux diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.n b/regress/unittests/sshkey/testdata/rsa_1.param.n new file mode 100644 index 0000000..4933712 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.param.n @@ -0,0 +1 @@ +00cb5799544edec5ac00ec781fc21a1119ce9a288e3116e72f3e78fbcba6998adcc98c235f2e77abf1ce92b76f064b624552c9f2582341e622e1a176eef232b5bac1bf3881babc0b7d57a1ef4439170852e192bc329d3523354a39610eab916e50c507c913a2a5f2c7596aad779c5f297121438bd2313ebb4ad4d7debba43271fb diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.p b/regress/unittests/sshkey/testdata/rsa_1.param.p new file mode 100644 index 0000000..4783d21 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.param.p @@ -0,0 +1 @@ +00f56077ef05be4574906f52175ed8897e8da1626bc9b055534d6a20f6102c57c7a0b31b3e7864b101f4d3d57c35192bc949e14243a9e956361de23c5dd179f583 diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.q b/regress/unittests/sshkey/testdata/rsa_1.param.q new file mode 100644 index 0000000..00fc8a2 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.param.q @@ -0,0 +1 @@ +00d42541cc014be26370a657953f3adfcbaf713f781639adba33133f184eb3c7d8c2ec7810dca3da58a746fc5b87b34f396934436832e619c67c22f32ebbb36029 diff --git a/regress/unittests/sshkey/testdata/rsa_1.pub b/regress/unittests/sshkey/testdata/rsa_1.pub new file mode 100644 index 0000000..23ef872 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1 diff --git a/regress/unittests/sshkey/testdata/rsa_1_pw b/regress/unittests/sshkey/testdata/rsa_1_pw new file mode 100644 index 0000000..b4c0674 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1_pw @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,0C3F819F6EEA66A471BAEEDDA8171606 + +AhQNxgw7Z2un3dpm6KPHF1u5qVvOczm0yiTyPK4U11B3TTRhXOHdzPLAcKMX71Xq +fmLm2/JIZATUbLTaysLKIQlmAgtpmXoKLv9b90R3AXLophgToZzOLpvlQTCt+y9G +0E3QQZG/LFy9BLNyw6uD5cy0RHT3FQb5VQDwfBvR/I+K3qWBFLlb7Rw9bCujYczu +D3bimcDj/k6YkrWVsEa81Ch5RF2RClOYufti6bsvc4xIsB0Kd++vokER+kXFuQqf +Tl0Jz+SG0kr9QtjVvkhBtSxzJ6/olAosoUySQ5hqsB8iECufBgp1KelXqsHFJQXy +gCvVmGiivFUinX0rKOuWCHTplsSKQ9BnPSwDAAs8A7ZLcTXcLs/hMQ5r6fmOYfNN +YthhjZyE2ciJO0lydGJUJMb5aJUak0rl+uINRlYCHTRLVwmCOmpfqz9SfcJb1ieU +4Us8NR+pXJar4U0+C2wVlNJkAdpL6GvYxN6vp7vLa+BiFwIZOQozswacIZk/ScXm +QL9rmWug51RCmDeenX46WTEZeB0o0+xi60sDEDhhe4+iNYcJu5L0BJ5lqRFe3I5n +HRRv1mBEjbF2fDcg/ChYfOXsc4gDivH2nObabeASuMFZyadmXfA8tnXRZf+7Wuy/ +LZGYbM2xLeEyV3ss16WBHuIqexDt04OEZvs0jN90zj6Yv7qKCB975bdOcuKkN2Nn +n9lA11R2pgsCs6COp9rYiWXkXZeDf3sW6kdcEV+/SzkVsv4JlHcsIzgk4WGVF/E/ +ZkU4J9AvSdJPzEQDM+yszp0eeUow4+SAgpuNTqZiUO/2UUVbsr3qvlYMoCixhFAN +-----END RSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha1 b/regress/unittests/sshkey/testdata/rsa_1_sha1 new file mode 100644 index 0000000..5de3f84 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1_sha1 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u +d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd +NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB +AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ +GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj +Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv +Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i +PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa +WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj +mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi +C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e +NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ +h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs= +-----END RSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub b/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub new file mode 100644 index 0000000..ff49d75 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1_sha1-cert.pub @@ -0,0 +1 @@ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgy5PGFfSaEuSuXsjvKlMZGXYD0xlnqdZftuW9tMkUYz4AAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAABAAAAAQAAAARodWdvAAAAEgAAAAV1c2VyMQAAAAV1c2VyMgAAAAA2i4NgAAAAAE0d4eAAAABEAAAADWZvcmNlLWNvbW1hbmQAAAALAAAABy9iaW4vbHMAAAAOc291cmNlLWFkZHJlc3MAAAAOAAAACjEwLjAuMC4wLzgAAABkAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLrAAABDwAAAAdzc2gtcnNhAAABAF5BtPY8FbmIekK/zNq6/Lp5agKT5zEVxqAyZKhp75bLRP+kOMZBVB9ZWrekZk6IAVAOCZGQzTsD4mxIQsxBLl8k5hvEWb90/+w9/BzW9ScOGQe+y0COa0QWWR7L3k1S8WX2oAGvtDWOj7Md85nij4ZSU9/QQQFVDF8VilWPSMxUf/3I1fqyDq7AWcZkGk/bFUN6K6RsCSxIPlGmKt0IauyvSMI2IT0XeRT242RngeeUW8vFrn9TXy9YxJRW+cSeLKCuu8agBYyQMXWQ+q39eZZqVYSoo7nFEEhtaLs8d6jzgGkcE9wGJ9KLgfY/mG2vX3gI4IzncKkVJRoeiDzXFIk= RSA test key #1 diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha1.pub b/regress/unittests/sshkey/testdata/rsa_1_sha1.pub new file mode 100644 index 0000000..23ef872 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1_sha1.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1 diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha512 b/regress/unittests/sshkey/testdata/rsa_1_sha512 new file mode 100644 index 0000000..5de3f84 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1_sha512 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u +d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd +NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB +AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ +GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj +Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv +Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i +PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa +WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj +mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi +C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e +NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ +h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs= +-----END RSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub b/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub new file mode 100644 index 0000000..4745196 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1_sha512-cert.pub @@ -0,0 +1 @@ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg/bUEmnMYHxlv1N7iXvnYPYdzDjlTRKoaIGEPkaQQQDwAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAABAAAAAQAAAARodWdvAAAAEgAAAAV1c2VyMQAAAAV1c2VyMgAAAAA2i4NgAAAAAE0d4eAAAABEAAAADWZvcmNlLWNvbW1hbmQAAAALAAAABy9iaW4vbHMAAAAOc291cmNlLWFkZHJlc3MAAAAOAAAACjEwLjAuMC4wLzgAAABkAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLrAAABFAAAAAxyc2Etc2hhMi01MTIAAAEA7/GoZsJqrq4xYotsRbpM8arZDjCzT6kohXeD/GVy26s5E/YWXRYCrOMIzSZxjuN5rAaNRW8ffxq14JyI94566Kg2OeoxQ6rK/dTqkk7I1RyypSXunT3I4++RPs1Q+hu9eS/WBzur0/D3dMejhuc3IBg6iB0481I4pGBGcD8/KjQFfhlCuGVXwB1ALk2zfXFT1HYYrs6bYZuQqjgvArnjYJ0do3fTSDC20/ydV4BHnI3fVAY2THVjX45V2ppPadl/rpczaJqW1ZtpnpJkV8Un316stQSD0xLHUDjp89O6d9Yq5S0kDdfwTRJIPm9f2cGNakJwN5qzmmmdDroRKODYcg== RSA test key #1 diff --git a/regress/unittests/sshkey/testdata/rsa_1_sha512.pub b/regress/unittests/sshkey/testdata/rsa_1_sha512.pub new file mode 100644 index 0000000..23ef872 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_1_sha512.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1 diff --git a/regress/unittests/sshkey/testdata/rsa_2 b/regress/unittests/sshkey/testdata/rsa_2 new file mode 100644 index 0000000..2441d52 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2 @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA9NEUXp78SAkmL4+eAj4mBzPOjk+ccCPVzkTR+mZJdyTwkJAB +HUN4cn4a2kTmh7Er+N8CXCsiqxIOV1GfH2fwaCiBlOEXeQJi/cMjxr9kVWO4FhC6 +l1UqbvPUdrUCUZjFTA9/Ah9MKgk7qGYq5SjE3p+sn4GLhRKbqmq9LjiHgMmkBuv/ +a1Slit+rXHzO2F8fH5hkjeHivyYVgw45aNvGCe2RRfbpoeW2mRtgIv7y9wSewt6a +mhEDXSo/F6mkqA7xVinzro5NettEXLo91tA9Hb6f6x/Mc/GJDNXTKhpWCGeJ6xeW +nAefDZORWAY7Y9YbuAxhEJVi9QL5NWoFOA0C6wIDAQABAoIBAQDtRGVVfwhKWHOl +zK76xXjdqhwaWJXpKRHiI1jOMawpyKdNtAMgdW+apxUnTXePMurG/HuxEC09VvaH +MhfhvD6G9BsCS1UQdnuyLRnTWVLIXyjeWcA9QtEpTy8vDSb+Je2xVaNmTybl5qTn +BH22Mtj6Wg5XWJn7kplDhMdssGTDLsSCMw/rcxe9iT2qOKyltQal23RHzR7SijGp +QTtBp2SDGhvMZcyGuyMqJ084W8sdJpbyVzdDim2iaZdHlk7uvW2n0HcJ56I6yhIq +2U8wfgEEwydGVGHgmQNJ/n+SiT/hv6g5ebhDS46X9F9m5CHDwhdr0DrhPBVSsdhl +1HeJ0+FhAoGBAPuC3uNHToiJis688juKlwc3SQ6ger5ffAg3yaNhEcpHkvOtdZlF +/CfX94xazMov/YqFwkvpSSdKsX+PeXuaqnb1hPKNYX5t45U9RjB/ox7BIQj/2rPx +Bfs99UFW9HKP4HsVmLu1xeJg1Pc9iylTK/xrnwfYiZ+H7IGVccizjnqHAoGBAPkv +n1flAdxBzJH/O0rXoig2EtZsDRMPY51MGDdqVOW14ZOfTVlmu0OSnkSKQm2twfro +TPDVb2TY3wTRutz8H9yOFW1c1Nz4YOyTb8FmJhE2FWAQ9t8QpwUlhn15if72dS/Y +22+vP+AYu7wfqGL7QVVEXho5hGjXi053iEvfXBl9AoGAeZISpo1LGphRLgkKlVky +E1zXxWgwrGB/FYHRx1UeQkZCc+K+Wy4G6kNr9r3VC04TIafx+Lt0jrd+AIibUfG6 +v/GBJ7TLEU+QmAycJskrUaxMiYsSbbPtDjoumDytv8pn2VbhEqqUUg44IqHu6DS5 +qDNlFWfHbgNHgIN6EmcoUXUCgYEAi2G57X4pRjx/4wIy9jAbggaNDuctgQXQoIGZ +4hVWG49a+CnZKDKweKGgaZI0igjxQhmCQAwC3RP520Y9EbLtV38aOSv93QQJowrt +Le6nSGVKG4whqrAz3EsbKUA8kiLldbgFNjl+ryjmidnjZEpKRxmQ0XZuu/4k6+Us +ldQAPjkCgYBwjSm5eDUtK2eEPaBtbJykV05CTv5rn6CKC9L7ZBTkCcdU1hxeqe99 +wb22decnNawGRP1a5cGwqKJPOfkgybJVkdr6aqQW8ClzdFSaenjzs+nVW+T9JTXf +9lFpIZg5kN/geld3B9B4C99riTM0jg9hbe2RQvpLRTrZbnWMA1XoRw== +-----END RSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/rsa_2.fp b/regress/unittests/sshkey/testdata/rsa_2.fp new file mode 100644 index 0000000..4659639 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.fp @@ -0,0 +1 @@ +SHA256:NoQh0XBUuYUSWqnzOzOBnfpgJTRWLMj7BlWAb8IbjeE diff --git a/regress/unittests/sshkey/testdata/rsa_2.fp.bb b/regress/unittests/sshkey/testdata/rsa_2.fp.bb new file mode 100644 index 0000000..e9d1e4a --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.fp.bb @@ -0,0 +1 @@ +xogit-gupof-mydon-hocep-zuval-feson-rarif-cefar-tobar-ryvap-kuxex diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.n b/regress/unittests/sshkey/testdata/rsa_2.param.n new file mode 100644 index 0000000..a669dbf --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.param.n @@ -0,0 +1 @@ +00f4d1145e9efc4809262f8f9e023e260733ce8e4f9c7023d5ce44d1fa66497724f09090011d4378727e1ada44e687b12bf8df025c2b22ab120e57519f1f67f068288194e117790262fdc323c6bf645563b81610ba97552a6ef3d476b5025198c54c0f7f021f4c2a093ba8662ae528c4de9fac9f818b85129baa6abd2e388780c9a406ebff6b54a58adfab5c7cced85f1f1f98648de1e2bf2615830e3968dbc609ed9145f6e9a1e5b6991b6022fef2f7049ec2de9a9a11035d2a3f17a9a4a80ef15629f3ae8e4d7adb445cba3dd6d03d1dbe9feb1fcc73f1890cd5d32a1a56086789eb17969c079f0d939158063b63d61bb80c61109562f502f9356a05380d02eb diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.p b/regress/unittests/sshkey/testdata/rsa_2.param.p new file mode 100644 index 0000000..be7c1c3 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.param.p @@ -0,0 +1 @@ +00fb82dee3474e88898acebcf23b8a970737490ea07abe5f7c0837c9a36111ca4792f3ad759945fc27d7f78c5accca2ffd8a85c24be949274ab17f8f797b9aaa76f584f28d617e6de3953d46307fa31ec12108ffdab3f105fb3df54156f4728fe07b1598bbb5c5e260d4f73d8b29532bfc6b9f07d8899f87ec819571c8b38e7a87 diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.q b/regress/unittests/sshkey/testdata/rsa_2.param.q new file mode 100644 index 0000000..6f2c542 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.param.q @@ -0,0 +1 @@ +00f92f9f57e501dc41cc91ff3b4ad7a2283612d66c0d130f639d4c18376a54e5b5e1939f4d5966bb43929e448a426dadc1fae84cf0d56f64d8df04d1badcfc1fdc8e156d5cd4dcf860ec936fc166261136156010f6df10a70525867d7989fef6752fd8db6faf3fe018bbbc1fa862fb4155445e1a398468d78b4e77884bdf5c197d diff --git a/regress/unittests/sshkey/testdata/rsa_2.pub b/regress/unittests/sshkey/testdata/rsa_2.pub new file mode 100644 index 0000000..3322fbc --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_2.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLr RSA test key #2 diff --git a/regress/unittests/sshkey/testdata/rsa_n b/regress/unittests/sshkey/testdata/rsa_n new file mode 100644 index 0000000..b8e585e --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_n @@ -0,0 +1,16 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn +NhAAAAAwEAAQAAAIEAy1eZVE7exawA7HgfwhoRGc6aKI4xFucvPnj7y6aZitzJjCNfLner +8c6St28GS2JFUsnyWCNB5iLhoXbu8jK1usG/OIG6vAt9V6HvRDkXCFLhkrwynTUjNUo5YQ +6rkW5QxQfJE6Kl8sdZaq13nF8pcSFDi9IxPrtK1Nfeu6QycfsAAAH4to4I7raOCO4AAAAH +c3NoLXJzYQAAAIEAy1eZVE7exawA7HgfwhoRGc6aKI4xFucvPnj7y6aZitzJjCNfLner8c +6St28GS2JFUsnyWCNB5iLhoXbu8jK1usG/OIG6vAt9V6HvRDkXCFLhkrwynTUjNUo5YQ6r +kW5QxQfJE6Kl8sdZaq13nF8pcSFDi9IxPrtK1Nfeu6QycfsAAAADAQABAAAAgF8o+ZqY5m +w/mJcRiFs/86zOIRrFoHeFbXihCcU+jDCOLswkaZDHdHJPKB4sGRgCP0sFMyLILTjULh9w +F1bFIIIVuGJ5/vJLBL9CGfdfFgzA8Kr6pMq1c7DrGc6mIz3/A1AygqcBY55ZJydOMr1gWb +1YVrWODomfBldE7bLt5PhhAAAAQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ +h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZsAAABBAPVgd+8FvkV0kG9SF17YiX +6NoWJrybBVU01qIPYQLFfHoLMbPnhksQH009V8NRkryUnhQkOp6VY2HeI8XdF59YMAAABB +ANQlQcwBS+JjcKZXlT8638uvcT94FjmtujMTPxhOs8fYwux4ENyj2linRvxbh7NPOWk0Q2 +gy5hnGfCLzLruzYCkAAAAAAQID +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/rsa_n_pw b/regress/unittests/sshkey/testdata/rsa_n_pw new file mode 100644 index 0000000..dc18373 --- /dev/null +++ b/regress/unittests/sshkey/testdata/rsa_n_pw @@ -0,0 +1,17 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABAFw/Wg/V +I5SAXWj/HJr9qeAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7F +rADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu +7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylx +IUOL0jE+u0rU1967pDJx+wAAAgD1iSGiMlMJt2VH4kx5yr0wCJS+4UOmX0bxKO7UH5Jcul +K5eaSe5ZoKE7hTYBaz0K5dRF/0fqLsvVZlE4quDjFLN6Hyavgn2W/QM7SUqBHgRMal9pgH +LnxX6mFNWJ+4yb7f3bcbVIdgmMm3sT9Xjwaf5xgzNlR2mkUWtFwjyQh6FxUo5apNzqNBwO +l2Q4xfmyZTp1s++pStQ/su6obXpxnE2Nx5G/D84ZL5iWl+njUy/MvJTazHRbiTSyihU+UA +mUr5ZNuP3WUYY+h3KVlHpYHJYB7l3AMTKuPMFLhY9V7BJ+DuKPaqBgX4hvRzY0eVQiFr61 +ovjWjvfu1ulx550JqdYCgH2PpP0E89OQne35Cxs9QPThfe8DKojC9YquYh9zmVTvr7kNiE +Soluk/7oKpQIDaC+/SRk7AJ2e3Cbt1lXyGNn37PuqaaC/apaF/DOD6Yig9aClS7jOUrT96 +56trFAYfHEIKbRCUSMCiM1+x6HOLYf5ROrGE9KxT3kUD9XMsMpTva+cPpHUpbGpXcYE10N +MyYDz+V5M2/ZoIdEhscJNQ3UnhaZpeEaqcOyNyo90n3Dnaw/WpMDD/kNMGfm8daTaYInnQ +QnwA2gwlYfpTAqxE71oXgOuGmtA0yqJB4778Xq26Pb+B7/mZZZe6n0FVmiNC+ZG37ZGOw/ +iGL9e2Sxzw== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/tests.c b/regress/unittests/sshkey/tests.c new file mode 100644 index 0000000..78aa922 --- /dev/null +++ b/regress/unittests/sshkey/tests.c @@ -0,0 +1,22 @@ +/* $OpenBSD: tests.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include "../test_helper/test_helper.h" + +void sshkey_tests(void); +void sshkey_file_tests(void); +void sshkey_fuzz_tests(void); + +void +tests(void) +{ + sshkey_tests(); + sshkey_file_tests(); + sshkey_fuzz_tests(); +} diff --git a/regress/unittests/sshsig/Makefile b/regress/unittests/sshsig/Makefile new file mode 100644 index 0000000..bc3c6c7 --- /dev/null +++ b/regress/unittests/sshsig/Makefile @@ -0,0 +1,25 @@ +# $OpenBSD: Makefile,v 1.3 2023/01/15 23:35:10 djm Exp $ + +PROG=test_sshsig +SRCS=tests.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c +SRCS+=addr.c addrmatch.c bitmap.c sshsig.c +SRCS+=ed25519.c hash.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c + +SRCS+=digest-openssl.c +#SRCS+=digest-libc.c +SRCS+=utf8.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} -d ${.CURDIR}/testdata + +.include <bsd.regress.mk> diff --git a/regress/unittests/sshsig/mktestdata.sh b/regress/unittests/sshsig/mktestdata.sh new file mode 100755 index 0000000..d2300f9 --- /dev/null +++ b/regress/unittests/sshsig/mktestdata.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# $OpenBSD: mktestdata.sh,v 1.1 2020/06/19 04:32:09 djm Exp $ + +NAMESPACE=unittest + +set -ex + +cd testdata + +if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then + SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so +elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then + SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so +else + echo "Can't find sk-dummy.so" 1>&2 + exit 1 +fi + +rm -f signed-data namespace +rm -f rsa dsa ecdsa ed25519 ecdsa_sk ed25519_sk +rm -f rsa.sig dsa.sig ecdsa.sig ed25519.sig ecdsa_sk.sig ed25519_sk.sig + +printf "This is a test, this is only a test" > signed-data +printf "$NAMESPACE" > namespace + +ssh-keygen -t rsa -C "RSA test" -N "" -f rsa -m PEM +ssh-keygen -t dsa -C "DSA test" -N "" -f dsa -m PEM +ssh-keygen -t ecdsa -C "ECDSA test" -N "" -f ecdsa -m PEM +ssh-keygen -t ed25519 -C "ED25519 test key" -N "" -f ed25519 +ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key" \ + -N "" -f ecdsa_sk +ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key" \ + -N "" -f ed25519_sk + +ssh-keygen -Y sign -f rsa -n $NAMESPACE - < signed-data > rsa.sig +ssh-keygen -Y sign -f dsa -n $NAMESPACE - < signed-data > dsa.sig +ssh-keygen -Y sign -f ecdsa -n $NAMESPACE - < signed-data > ecdsa.sig +ssh-keygen -Y sign -f ed25519 -n $NAMESPACE - < signed-data > ed25519.sig +ssh-keygen -w "$SK_DUMMY" \ + -Y sign -f ecdsa_sk -n $NAMESPACE - < signed-data > ecdsa_sk.sig +ssh-keygen -w "$SK_DUMMY" \ + -Y sign -f ed25519_sk -n $NAMESPACE - < signed-data > ed25519_sk.sig diff --git a/regress/unittests/sshsig/testdata/dsa b/regress/unittests/sshsig/testdata/dsa new file mode 100644 index 0000000..7c0063e --- /dev/null +++ b/regress/unittests/sshsig/testdata/dsa @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCXpndQdz2mQVnk+lYOF3nxDT+h6SiJmUvBFhnFWBv8tG4pTOkb +EwGufLEzGpzjTj+3bjVau7LFt37AFrqs4Num272BWNsYNIjOlGPgq7Xjv32FN00x +JYh1DoRs1cGGnvohlsWEamGGhTHD1a9ipctPEBV+NrxtZMrl+pO/ZZg8vQIVAKJB +P3iNYSpSuW74+q4WxLCuK8O3AoGAQldE+BIuxlvoG1IFiWesx0CU+H2KO0SEZc9A +SX/qjOabh0Fb78ofTlEf9gWHFfat8SvSJQIOPMVlb76Lio8AAMT8Eaa/qQKKYmQL +dNq4MLhhjxx5KLGt6J2JyFPExCv+qnHYHD59ngtLwKyqGjpSC8LPLktdXn8W/Aad +Ly1K7+MCgYBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSN +u4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dB +yJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501BkwIVAILIa3Rg +0h7J9lQpHJphvF3K0M1T +-----END DSA PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/dsa.pub b/regress/unittests/sshsig/testdata/dsa.pub new file mode 100644 index 0000000..e77aa7e --- /dev/null +++ b/regress/unittests/sshsig/testdata/dsa.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAJemd1B3PaZBWeT6Vg4XefENP6HpKImZS8EWGcVYG/y0bilM6RsTAa58sTManONOP7duNVq7ssW3fsAWuqzg26bbvYFY2xg0iM6UY+CrteO/fYU3TTEliHUOhGzVwYae+iGWxYRqYYaFMcPVr2Kly08QFX42vG1kyuX6k79lmDy9AAAAFQCiQT94jWEqUrlu+PquFsSwrivDtwAAAIBCV0T4Ei7GW+gbUgWJZ6zHQJT4fYo7RIRlz0BJf+qM5puHQVvvyh9OUR/2BYcV9q3xK9IlAg48xWVvvouKjwAAxPwRpr+pAopiZAt02rgwuGGPHHkosa3onYnIU8TEK/6qcdgcPn2eC0vArKoaOlILws8uS11efxb8Bp0vLUrv4wAAAIBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSNu4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dByJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501Bkw== DSA test diff --git a/regress/unittests/sshsig/testdata/dsa.sig b/regress/unittests/sshsig/testdata/dsa.sig new file mode 100644 index 0000000..0b14ad6 --- /dev/null +++ b/regress/unittests/sshsig/testdata/dsa.sig @@ -0,0 +1,13 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAbEAAAAHc3NoLWRzcwAAAIEAl6Z3UHc9pkFZ5PpWDhd58Q0/oekoiZ +lLwRYZxVgb/LRuKUzpGxMBrnyxMxqc404/t241Wruyxbd+wBa6rODbptu9gVjbGDSIzpRj +4Ku14799hTdNMSWIdQ6EbNXBhp76IZbFhGphhoUxw9WvYqXLTxAVfja8bWTK5fqTv2WYPL +0AAAAVAKJBP3iNYSpSuW74+q4WxLCuK8O3AAAAgEJXRPgSLsZb6BtSBYlnrMdAlPh9ijtE +hGXPQEl/6ozmm4dBW+/KH05RH/YFhxX2rfEr0iUCDjzFZW++i4qPAADE/BGmv6kCimJkC3 +TauDC4YY8ceSixreidichTxMQr/qpx2Bw+fZ4LS8Csqho6UgvCzy5LXV5/FvwGnS8tSu/j +AAAAgGwwcFzOFJ5SHzDuLbQJWDg6U1OZ8lFVTa07o6kzFn+q6K1GbeEspI27jFGS8cnCLg +uFC2/VJe8sjmCzk/eAIby2wgCLIKouKceFrreIF0mmqGdX/H+Pt0HImvfElueYt1YuSQK0 +2TUivX8K4TP658DIsZ0paSwQC7VRSVvnTUGTAAAACHVuaXR0ZXN0AAAAAAAAAAZzaGE1MT +IAAAA3AAAAB3NzaC1kc3MAAAAodi5lr0pqBpO76OY4N1CtfR85BCgZ95qfVjP/e9lToj0q +lwjSJJXUjw== +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ecdsa b/regress/unittests/sshsig/testdata/ecdsa new file mode 100644 index 0000000..55fb440 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIFg0ZCSEB5LNeLsXYL25g3kqEWsqh52DR+yNOjyQJqyZoAoGCCqGSM49 +AwEHoUQDQgAE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWb +LzXBuUJucepaCNuW/QWgHBRbrjWj3ERm3A== +-----END EC PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/ecdsa.pub b/regress/unittests/sshsig/testdata/ecdsa.pub new file mode 100644 index 0000000..14ec6cf --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN7LnfPBVdDfBT7KWUley1qo+rjzy0WYkrHpzbhGALXlj8g4K2bFmy81wblCbnHqWgjblv0FoBwUW641o9xEZtw= ECDSA test diff --git a/regress/unittests/sshsig/testdata/ecdsa.sig b/regress/unittests/sshsig/testdata/ecdsa.sig new file mode 100644 index 0000000..7978157 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa.sig @@ -0,0 +1,7 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAE +EE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWbLzXBuUJucepaCNuW +/QWgHBRbrjWj3ERm3AAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAAAZQAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAASgAAACEAycVNsTlE+XEZYyYiDxWZlliruf/pPMhEEMR/XLdQ +a4MAAAAhALQt+5gES7L3uKGptHB6UZQMuZ2WyI0C6FJs4v6AtMIU +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk b/regress/unittests/sshsig/testdata/ecdsa_sk new file mode 100644 index 0000000..62ae44c --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk @@ -0,0 +1,13 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 +RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSg1WuY0XE+ +VexOsrJsFYuxyVoe6eQ/oXmyz2pEHKZw9moyWehv+Fs7oZWFp3JVmOtybKQ6dvfUZYauQE +/Ov4PAAAAABHNzaDoAAAGI6iV41+oleNcAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv +cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss +9qRBymcPZqMlnob/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AQAAAOMt +LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJQm9oeW54M2tpTFVEeS +t5UjU3WXBXSU5KektnU1p6WnV2VTljYXFla3JGcW9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn +QUVvTlZybU5GeFBsWHNUckt5YkJXTHNjbGFIdW5rUDZGNXNzOXFSQnltY1BacU1sbm9iL2 +hiCk82R1ZoYWR5VlpqcmNteWtPbmIzMUdXR3JrQlB6citEd0E9PQotLS0tLUVORCBFQyBQ +UklWQVRFIEtFWS0tLS0tCgAAAAAAAAARRUNEU0EtU0sgdGVzdCBrZXk= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk.pub b/regress/unittests/sshsig/testdata/ecdsa_sk.pub new file mode 100644 index 0000000..385ebf1 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBKDVa5jRcT5V7E6ysmwVi7HJWh7p5D+hebLPakQcpnD2ajJZ6G/4WzuhlYWnclWY63JspDp299Rlhq5AT86/g8AAAAAEc3NoOg== ECDSA-SK test key diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk.sig b/regress/unittests/sshsig/testdata/ecdsa_sk.sig new file mode 100644 index 0000000..86de360 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk.sig @@ -0,0 +1,8 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAH8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ +AAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss9qRBymcPZqMlno +b/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AAAACHVuaXR0ZXN0AAAAAA +AAAAZzaGE1MTIAAAB3AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20A +AABIAAAAIHohGwyy8iKT3zwd1TYA9V/Ioo7h/3zCJUtyq/Qigt/HAAAAIGzidTwq7D/kFa +7Xjcp/KkdbIs4MfQpfAW/0OciajlpzARI0Vng= +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub new file mode 100644 index 0000000..1597302 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBBRGwDjs4HhJFcn4tJ5Gr72KcmRmCS1OirETxaXvnsNApgoOLF1a/7rxldfSMHm73eT1nhHe97W8qicPPEAKDJQAAAALbWluZHJvdC5vcmc= diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig new file mode 100644 index 0000000..4bdd8ed --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig @@ -0,0 +1,13 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAIYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ +AAAAhuaXN0cDI1NgAAAEEEFEbAOOzgeEkVyfi0nkavvYpyZGYJLU6KsRPFpe+ew0CmCg4s +XVr/uvGV19Iwebvd5PWeEd73tbyqJw88QAoMlAAAAAttaW5kcm90Lm9yZwAAAAh1bml0dG +VzdAAAAAAAAAAGc2hhNTEyAAABhwAAACt3ZWJhdXRobi1zay1lY2RzYS1zaGEyLW5pc3Rw +MjU2QG9wZW5zc2guY29tAAAASQAAACBj2oMT9tb5wRXe6mdmf4/lgAO8wrgr95ouozwNg4 +itnQAAACEAtU9g5wz3HchUiLfLD6plr9T4TiJ32lVCrATSjpiy0SMBAAADHwAAABdodHRw +czovL3d3dy5taW5kcm90Lm9yZwAAAON7InR5cGUiOiJ3ZWJhdXRobi5nZXQiLCJjaGFsbG +VuZ2UiOiJVMU5JVTBsSEFBQUFDSFZ1YVhSMFpYTjBBQUFBQUFBQUFBWnphR0UxTVRJQUFB +QkFMTHU4WmdjU3h0Nk1zRlV6dWlaZ0c2R3dNZEo5ZDd4ZUU3WW9SSXcwZzlpSEpfd3NGRD +cxbzRXbHllenZGV0VqYnFRMHFDN0Z3R3Bqa2pVUVAtTmQ2dyIsIm9yaWdpbiI6Imh0dHBz +Oi8vd3d3Lm1pbmRyb3Qub3JnIiwiY3Jvc3NPcmlnaW4iOmZhbHNlfQAAAAA= +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ed25519 b/regress/unittests/sshsig/testdata/ed25519 new file mode 100644 index 0000000..b44a63d --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBAAAAJjpGas/6Rmr +PwAAAAtzc2gtZWQyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBA +AAAEDpSKRA1QKW6kYiQftGRWh+H0fNekzYLG6c3bzseoCpEolizSIN3DQV78VPNjVvvwjg +f+P5HqbPYCYu3BOMdjAEAAAAEEVEMjU1MTkgdGVzdCBrZXkBAgMEBQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/ed25519.pub b/regress/unittests/sshsig/testdata/ed25519.pub new file mode 100644 index 0000000..b078e45 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIlizSIN3DQV78VPNjVvvwjgf+P5HqbPYCYu3BOMdjAE ED25519 test key diff --git a/regress/unittests/sshsig/testdata/ed25519.sig b/regress/unittests/sshsig/testdata/ed25519.sig new file mode 100644 index 0000000..8e8ff2a --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519.sig @@ -0,0 +1,6 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgiWLNIg3cNBXvxU82NW+/COB/4/ +keps9gJi7cE4x2MAQAAAAIdW5pdHRlc3QAAAAAAAAABnNoYTUxMgAAAFMAAAALc3NoLWVk +MjU1MTkAAABAihQsbUzuNEFflk5Tw1+H9aLS7tZQk0RG8KW1DtOmDYYnWe3D3UKiG3fcJa +DNg4vBWp1j1gLRiBMOF+gwYNegDg== +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ed25519_sk b/regress/unittests/sshsig/testdata/ed25519_sk new file mode 100644 index 0000000..3a434ec --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519_sk @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 +gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCbGg2F0GK7nOm4pQmAyCuGEjnhvs5q0TtjPbdN +//+yxwAAAARzc2g6AAAAuBw56jAcOeowAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 +9tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDoBAAAAQFXc +6dCwWewIk1EBofAouGZApW8+s0XekXenxtb78+x0mxoNhdBiu5zpuKUJgMgrhhI54b7Oat +E7Yz23Tf//sscAAAAAAAAAE0VEMjU1MTktU0sgdGVzdCBrZXkBAgMEBQY= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/ed25519_sk.pub b/regress/unittests/sshsig/testdata/ed25519_sk.pub new file mode 100644 index 0000000..71051ec --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519_sk.pub @@ -0,0 +1 @@ +sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDo= ED25519-SK test key diff --git a/regress/unittests/sshsig/testdata/ed25519_sk.sig b/regress/unittests/sshsig/testdata/ed25519_sk.sig new file mode 100644 index 0000000..49b6818 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519_sk.sig @@ -0,0 +1,7 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAEoAAAAac2stc3NoLWVkMjU1MTlAb3BlbnNzaC5jb20AAAAgmxoNhd +Biu5zpuKUJgMgrhhI54b7OatE7Yz23Tf//sscAAAAEc3NoOgAAAAh1bml0dGVzdAAAAAAA +AAAGc2hhNTEyAAAAZwAAABpzay1zc2gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAAEAi+7eTjW +/+LQ2M+sCD+KFtH1n7VFFJon/SZFsxODyV8cWTlFKj617Ys1Ur5TV6uaEXQhck8rBA2oQI +HTPANLIPARI0Vng= +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/namespace b/regress/unittests/sshsig/testdata/namespace new file mode 100644 index 0000000..1570cd5 --- /dev/null +++ b/regress/unittests/sshsig/testdata/namespace @@ -0,0 +1 @@ +unittest
\ No newline at end of file diff --git a/regress/unittests/sshsig/testdata/rsa b/regress/unittests/sshsig/testdata/rsa new file mode 100644 index 0000000..228fad7 --- /dev/null +++ b/regress/unittests/sshsig/testdata/rsa @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEA386lmjRHtJpyj87BrS+ssMmtvc/1SPN0gXTPs9jZ1hYAq98P +ca3/RYVM4HaSu6COztQJ2ZnZD3Te/XeBnIU2mfuvQEl+DiwisGeNglVyRCi7787f +PFFfcxzZfDa7EB2qY8S3oaSGZK8QqzuGwmGAImjlQXz6J+HCd/eD/58GoCSSirIE +CFWCAt+uNrOC/EmgAzsbfcfaIbbVzA40tlgU3hO2J42kddz8CisDTtDKQABFcOaQ +ZycSfn7HDP+WgXLXXBUI9wVM1Tif1f+9MX08xIsvCvGzo7yLgbbTFLSGr5SkA+tO +rYuoA7V8fge0id/3pnVtG1Ui3I7vejeAwf0HZqtFeBEnOwkIJFmZeMtFeOVf+4ki +4h1rDqAvSscNvMtLp6OXpbAATATAuEWEkIQBl1rngnEe0iC9iU9itKMW6qJ4FtIb +4ACH1EoU1x8vqrFecg2hvqfk5CZBJIbV28JFuGjac3OxBZ17Fqb8ljomUir1GrET +2z66NMgb5TjDD7BVAgMBAAECggGACfjDGCPMLhfTkuS7bGP7ZcUWoKZrX1y5jCsQ +NgsraYaBcSb3ITGHdimCS139G68DreN0rOVV7oJejRyOAdNNo367SDn+C9ObmBCF +FZGJDdBiz0SAXceiYRaf+hDWNNmdheR16hXShxnlvDtivbZqZx4VWN2gp7Y/W+kD +UJhdSzVV8igMVfK5YDdnI7jL1UHSh1JS3z/QUEA9NmJLpvQ1uc9XBlwhP78g27Me +6pwS5tccQPOE65OqF0i+xa19nzbmnC940Y34yZeI/UE+PYaO2+asapvOfu/sboBH +Yb5BuWXVEkSeRWI23SpuZbmfNTtVgiRoRqOvqM4G88LkhYjZ6xpDggxQwJiShiiD +oWCucs0v3pX8H8/LbGs8l50SGI5nzUqAdZ7/QQucU/GuDiQtampntkLEDgf9KIw/ +SDrtCw1E9fnCWj4Z71IYfepY9bVY6QUEcfTdnDcYSY1Z5tVpzeMHVLeo0lbNVZv9 +2qmPnjjP/IvWbjjwu/PHpUWkUs0BAoHBAPx4YwPXWYgWnesMKXkjAHyO5KA4EyBr ++rcEmOZkZDibC8PKYzIK2ztptuthahVovW20R/QJhJkO5teGZMeGPFq+floCeC5P +la9CEYGYcTrzgSe1QM9IGMr1vGI1KIWck7VkJ0bkKoY40uIJSVZxnyG9pEpcwYSp +tnOqA/f5YZUFctWvXUz46OfiLKstXLrcrGIU7YRmLv2rW9twnpJYTzE98g3KpVJ2 +TI1pyvrDTdGeAQUTGCAjpviY6XR5d020vQKBwQDi76wsGLQ3XLI+OAE95Ljo0Mcl ++KdJPVVQPq/VcjKgZQndFloflMRrmgNHme9gmsHOrf8DLZvEDbtT+gbmWslMFZQ9 +om1kR404gfuGmfIYdBdOwWjuBLsZs3pfqDB4Xa3NkxljwOMYTp035n0r2UMFaSy3 +gvpW7fsdPOGAJsqNhSw/JNHcokHeBm7VbV0aD7tSyIghmARb5c98fmrSPbiEo8mP +ITIZlgbfZCq2KuXY4q16R3QvlpuSwitVobLR/3kCgcEAueH5JM7dQHFGe9RMhL/c +j9i1Q7GFg4183lsoKBkqIPMmylSsjB+qIihHYS4r6O9g6PCfOXH4iqiKFY0BjlWr +AjTW2naO/aniz1KZiQ0v8PNv2Eh/Gx4+AtDCjpwM5bLOnfLLaEp9dK1JttqXgGnP +fAwgdg+s+3votWgr29tkmU+VqPagfxeUg4Xm1XFkoL/wu5Yk+iIx3trXms1kMuOK +CvtMyBK3fetTmZqWs+Iv3XGz1oSkcqVNPiN3XyY/TJsRAoG/Q17jvjOXTNg4EkCO +HdHJE1Tnyl4HS7bpnOj/Sl6cqQFV7Ey2dKm1pjwSvS714bgP0UvWaRshIxLwif2w +DrLlD7FYUPPnhd24Dw6HnW4WcSwFv1uryv2cjgS6T6ueuB0Xe/AvmW2p/Y1ZHz9N +6baWLwUKQXCg4S3FXui0CVd6yoi+mgBUTSveYguG29WbziDde7YMs+xtXtravhrJ +m6C3Jql5LQSt2uqvH6KdC3ewxLKGzcZot7f+d5MtSj6216ECgcEA9PGmWeUkhVuW +Xz2c9iBeHwCtmDso7gVwxNnHqdqirB4f1nDCGbrJS7hz5Ss7/wfzekP2W5if2P6U +JPUdfykAQgALNn1twAtj1a+UAp31ZWu8JK/Qzt4hLJPBxzMo7MenJq189JmYmDnm +6D5d9vDLCW15gCZua89GZa8K8V50lYyeHBOHAyzNTfNlnMBkHyP645+nqpuEWzIT +3mCe2OAbl60o8VvvVUlAQyQ/ObLq37HHEoDu0U/YAnP157cxpa84 +-----END RSA PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/rsa.pub b/regress/unittests/sshsig/testdata/rsa.pub new file mode 100644 index 0000000..30142ac --- /dev/null +++ b/regress/unittests/sshsig/testdata/rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDfzqWaNEe0mnKPzsGtL6ywya29z/VI83SBdM+z2NnWFgCr3w9xrf9FhUzgdpK7oI7O1AnZmdkPdN79d4GchTaZ+69ASX4OLCKwZ42CVXJEKLvvzt88UV9zHNl8NrsQHapjxLehpIZkrxCrO4bCYYAiaOVBfPon4cJ394P/nwagJJKKsgQIVYIC3642s4L8SaADOxt9x9ohttXMDjS2WBTeE7YnjaR13PwKKwNO0MpAAEVw5pBnJxJ+fscM/5aBctdcFQj3BUzVOJ/V/70xfTzEiy8K8bOjvIuBttMUtIavlKQD606ti6gDtXx+B7SJ3/emdW0bVSLcju96N4DB/Qdmq0V4ESc7CQgkWZl4y0V45V/7iSLiHWsOoC9Kxw28y0uno5elsABMBMC4RYSQhAGXWueCcR7SIL2JT2K0oxbqongW0hvgAIfUShTXHy+qsV5yDaG+p+TkJkEkhtXbwkW4aNpzc7EFnXsWpvyWOiZSKvUasRPbPro0yBvlOMMPsFU= RSA test diff --git a/regress/unittests/sshsig/testdata/rsa.sig b/regress/unittests/sshsig/testdata/rsa.sig new file mode 100644 index 0000000..15a032e --- /dev/null +++ b/regress/unittests/sshsig/testdata/rsa.sig @@ -0,0 +1,19 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAN/OpZo0R7Saco/Owa0vrL +DJrb3P9UjzdIF0z7PY2dYWAKvfD3Gt/0WFTOB2krugjs7UCdmZ2Q903v13gZyFNpn7r0BJ +fg4sIrBnjYJVckQou+/O3zxRX3Mc2Xw2uxAdqmPEt6GkhmSvEKs7hsJhgCJo5UF8+ifhwn +f3g/+fBqAkkoqyBAhVggLfrjazgvxJoAM7G33H2iG21cwONLZYFN4TtieNpHXc/AorA07Q +ykAARXDmkGcnEn5+xwz/loFy11wVCPcFTNU4n9X/vTF9PMSLLwrxs6O8i4G20xS0hq+UpA +PrTq2LqAO1fH4HtInf96Z1bRtVItyO73o3gMH9B2arRXgRJzsJCCRZmXjLRXjlX/uJIuId +aw6gL0rHDbzLS6ejl6WwAEwEwLhFhJCEAZda54JxHtIgvYlPYrSjFuqieBbSG+AAh9RKFN +cfL6qxXnINob6n5OQmQSSG1dvCRbho2nNzsQWdexam/JY6JlIq9RqxE9s+ujTIG+U4ww+w +VQAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAABlAAAAAxyc2Etc2hhMi01MTIAAAGACi +nEpBrQxZi0yOrrT6h98JFfZh0XXioih4fzmvtoV0yOReWClS+otGgXoJyZHcbaKNOjDwSM +rIkUoX6OUJmtHYP0HRELnKw35m33LdBPXpFGS4tRS7NeSpvc04KtjT6jYXY9FjWy5hcn17 +Sxc/3DnJqLgJBur8acY7FeIzpWmKixPd/dGkEjdWoD9gO6szLczGuQgrOdYmSRL4yKadTJ +lVjz5OSeKSYYGQy33US2XQassRRNYf4e9byTA3DKvHa/OcTt7lFerea0kZdDpAboqffz7T +Yaw/hFskAYLIEdTW3aoXBGHSOvu8AkDOtb7qwuxGSQ27pjkDLDNsp1ceCFaCaQ6X83RZuK +ACv9JUBI5KaSf81e0bs0KezJKkhB9czeZ6dk96qISbgayEBnvhYgXvUDKtHn7HzNlCJKfK +5ABhNxfGG2CD+NKqcrndwFgS1sQO3hbA84zPQb26ShBovT8ytHBmW1F8ZK4O9Bz61Q6EZK +vs/u6xP6LUean/so5daa +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/signed-data b/regress/unittests/sshsig/testdata/signed-data new file mode 100644 index 0000000..7df4bed --- /dev/null +++ b/regress/unittests/sshsig/testdata/signed-data @@ -0,0 +1 @@ +This is a test, this is only a test
\ No newline at end of file diff --git a/regress/unittests/sshsig/tests.c b/regress/unittests/sshsig/tests.c new file mode 100644 index 0000000..13cfcfd --- /dev/null +++ b/regress/unittests/sshsig/tests.c @@ -0,0 +1,142 @@ +/* $OpenBSD: tests.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef WITH_OPENSSL +#include <openssl/evp.h> +#include <openssl/crypto.h> +#endif + +#include "ssherr.h" +#include "authfile.h" +#include "sshkey.h" +#include "sshbuf.h" +#include "sshsig.h" +#include "log.h" + +#include "../test_helper/test_helper.h" + +static struct sshbuf * +load_file(const char *name) +{ + struct sshbuf *ret = NULL; + + ASSERT_INT_EQ(sshbuf_load_file(test_data_file(name), &ret), 0); + ASSERT_PTR_NE(ret, NULL); + return ret; +} + +static struct sshkey * +load_key(const char *name) +{ + struct sshkey *ret = NULL; + ASSERT_INT_EQ(sshkey_load_public(test_data_file(name), &ret, NULL), 0); + ASSERT_PTR_NE(ret, NULL); + return ret; +} + +static void +check_sig(const char *keyname, const char *signame, const struct sshbuf *msg, + const char *namespace) +{ + struct sshkey *k, *sign_key; + struct sshbuf *sig, *rawsig; + struct sshkey_sig_details *sig_details; + + k = load_key(keyname); + sig = load_file(signame); + sign_key = NULL; + sig_details = NULL; + rawsig = NULL; + ASSERT_INT_EQ(sshsig_dearmor(sig, &rawsig), 0); + ASSERT_INT_EQ(sshsig_verifyb(rawsig, msg, namespace, + &sign_key, &sig_details), 0); + ASSERT_INT_EQ(sshkey_equal(k, sign_key), 1); + sshkey_free(k); + sshkey_free(sign_key); + sshkey_sig_details_free(sig_details); + sshbuf_free(sig); + sshbuf_free(rawsig); +} + +void +tests(void) +{ + struct sshbuf *msg; + char *namespace; + +#if 0 + log_init("test_sshsig", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); +#endif + +#ifdef WITH_OPENSSL + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); +#endif + + TEST_START("load data"); + msg = load_file("namespace"); + namespace = sshbuf_dup_string(msg); + ASSERT_PTR_NE(namespace, NULL); + sshbuf_free(msg); + msg = load_file("signed-data"); + TEST_DONE(); + +#ifdef WITH_OPENSSL + TEST_START("check RSA signature"); + check_sig("rsa.pub", "rsa.sig", msg, namespace); + TEST_DONE(); + + TEST_START("check DSA signature"); + check_sig("dsa.pub", "dsa.sig", msg, namespace); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("check ECDSA signature"); + check_sig("ecdsa.pub", "ecdsa.sig", msg, namespace); + TEST_DONE(); +#endif +#endif + + TEST_START("check ED25519 signature"); + check_sig("ed25519.pub", "ed25519.sig", msg, namespace); + TEST_DONE(); + +#ifdef ENABLE_SK +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + TEST_START("check ECDSA-SK signature"); + check_sig("ecdsa_sk.pub", "ecdsa_sk.sig", msg, namespace); + TEST_DONE(); +#endif + + TEST_START("check ED25519-SK signature"); + check_sig("ed25519_sk.pub", "ed25519_sk.sig", msg, namespace); + TEST_DONE(); + +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + TEST_START("check ECDSA-SK webauthn signature"); + check_sig("ecdsa_sk_webauthn.pub", "ecdsa_sk_webauthn.sig", + msg, namespace); + TEST_DONE(); +#endif +#endif /* ENABLE_SK */ + + sshbuf_free(msg); + free(namespace); +} diff --git a/regress/unittests/sshsig/webauthn.html b/regress/unittests/sshsig/webauthn.html new file mode 100644 index 0000000..5c9a32e --- /dev/null +++ b/regress/unittests/sshsig/webauthn.html @@ -0,0 +1,766 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> +<title>webauthn test</title> +</head> +<body onload="init()"> +<h1>webauthn test</h1> +<p> +This is a demo/test page for generating FIDO keys and signatures in SSH +formats. The page initially displays a form to generate a FIDO key and +convert it to a SSH public key. +</p> +<p> +Once a key has been generated, an additional form will be displayed to +allow signing of data using the just-generated key. The data may be signed +as either a raw SSH signature or wrapped in a sshsig message (the latter is +easier to test using command-line tools. +</p> +<p> +Lots of debugging is printed along the way. +</p> +<h2>Enroll</h2> +<span id="error" style="color: #800; font-weight: bold; font-size: 150%;"></span> +<form id="enrollform"> +<table> +<tr> +<td><b>Username:</b></td> +<td><input id="username" type="text" size="20" name="user" value="test" /></td> +</tr> +<tr><td></td><td><input id="assertsubmit" type="submit" value="submit" /></td></tr> +</table> +</form> +<span id="enrollresult" style="visibility: hidden;"> +<h2>clientData</h2> +<pre id="enrollresultjson" style="color: #008; font-family: monospace;"></pre> +<h2>attestationObject raw</h2> +<pre id="enrollresultraw" style="color: #008; font-family: monospace;"></pre> +<h2>attestationObject</h2> +<pre id="enrollresultattestobj" style="color: #008; font-family: monospace;"></pre> +<h2>key handle</h2> +<pre id="keyhandle" style="color: #008; font-family: monospace;"></pre> +<h2>authData raw</h2> +<pre id="enrollresultauthdataraw" style="color: #008; font-family: monospace;"></pre> +<h2>authData</h2> +<pre id="enrollresultauthdata" style="color: #008; font-family: monospace;"></pre> +<h2>SSH pubkey blob</h2> +<pre id="enrollresultpkblob" style="color: #008; font-family: monospace;"></pre> +<h2>SSH pubkey string</h2> +<pre id="enrollresultpk" style="color: #008; font-family: monospace;"></pre> +<h2>SSH private key string</h2> +<pre id="enrollresultprivkey" style="color: #008; font-family: monospace;"></pre> +</span> +<span id="assertsection" style="visibility: hidden;"> +<h2>Assert</h2> +<form id="assertform"> +<span id="asserterror" style="color: #800; font-weight: bold;"></span> +<table> +<tr> +<td><b>Data to sign:</b></td> +<td><input id="message" type="text" size="20" name="message" value="test" /></td> +</tr> +<tr> +<td><input id="message_sshsig" type="checkbox" checked /> use sshsig format</td> +</tr> +<tr> +<td><b>Signature namespace:</b></td> +<td><input id="message_namespace" type="text" size="20" name="namespace" value="test" /></td> +</tr> +<tr><td></td><td><input type="submit" value="submit" /></td></tr> +</table> +</form> +</span> +<span id="assertresult" style="visibility: hidden;"> +<h2>clientData</h2> +<pre id="assertresultjson" style="color: #008; font-family: monospace;"></pre> +<h2>signature raw</h2> +<pre id="assertresultsigraw" style="color: #008; font-family: monospace;"></pre> +<h2>authenticatorData raw</h2> +<pre id="assertresultauthdataraw" style="color: #008; font-family: monospace;"></pre> +<h2>authenticatorData</h2> +<pre id="assertresultauthdata" style="color: #008; font-family: monospace;"></pre> +<h2>signature in SSH format</h2> +<pre id="assertresultsshsigraw" style="color: #008; font-family: monospace;"></pre> +<h2>signature in SSH format (base64 encoded)</h2> +<pre id="assertresultsshsigb64" style="color: #008; font-family: monospace;"></pre> +</span> +</body> +<script> +// ------------------------------------------------------------------ +// a crappy CBOR decoder - 20200401 djm@openbsd.org + +var CBORDecode = function(buffer) { + this.buf = buffer + this.v = new DataView(buffer) + this.offset = 0 +} + +CBORDecode.prototype.empty = function() { + return this.offset >= this.buf.byteLength +} + +CBORDecode.prototype.getU8 = function() { + let r = this.v.getUint8(this.offset) + this.offset += 1 + return r +} + +CBORDecode.prototype.getU16 = function() { + let r = this.v.getUint16(this.offset) + this.offset += 2 + return r +} + +CBORDecode.prototype.getU32 = function() { + let r = this.v.getUint32(this.offset) + this.offset += 4 + return r +} + +CBORDecode.prototype.getU64 = function() { + let r = this.v.getUint64(this.offset) + this.offset += 8 + return r +} + +CBORDecode.prototype.getCBORTypeLen = function() { + let tl, t, l + tl = this.getU8() + t = (tl & 0xe0) >> 5 + l = tl & 0x1f + return [t, this.decodeInteger(l)] +} + +CBORDecode.prototype.decodeInteger = function(len) { + switch (len) { + case 0x18: return this.getU8() + case 0x19: return this.getU16() + case 0x20: return this.getU32() + case 0x21: return this.getU64() + default: + if (len <= 23) { + return len + } + throw new Error("Unsupported int type 0x" + len.toString(16)) + } +} + +CBORDecode.prototype.decodeNegint = function(len) { + let r = -(this.decodeInteger(len) + 1) + return r +} + +CBORDecode.prototype.decodeByteString = function(len) { + let r = this.buf.slice(this.offset, this.offset + len) + this.offset += len + return r +} + +CBORDecode.prototype.decodeTextString = function(len) { + let u8dec = new TextDecoder('utf-8') + r = u8dec.decode(this.decodeByteString(len)) + return r +} + +CBORDecode.prototype.decodeArray = function(len, level) { + let r = [] + for (let i = 0; i < len; i++) { + let v = this.decodeInternal(level) + r.push(v) + // console.log("decodeArray level " + level.toString() + " index " + i.toString() + " value " + JSON.stringify(v)) + } + return r +} + +CBORDecode.prototype.decodeMap = function(len, level) { + let r = {} + for (let i = 0; i < len; i++) { + let k = this.decodeInternal(level) + let v = this.decodeInternal(level) + r[k] = v + // console.log("decodeMap level " + level.toString() + " key " + k.toString() + " value " + JSON.stringify(v)) + // XXX check string keys, duplicates + } + return r +} + +CBORDecode.prototype.decodePrimitive = function(t) { + switch (t) { + case 20: return false + case 21: return true + case 22: return null + case 23: return undefined + default: + throw new Error("Unsupported primitive 0x" + t.toString(2)) + } +} + +CBORDecode.prototype.decodeInternal = function(level) { + if (level > 256) { + throw new Error("CBOR nesting too deep") + } + let t, l, r + [t, l] = this.getCBORTypeLen() + // console.log("decode level " + level.toString() + " type " + t.toString() + " len " + l.toString()) + switch (t) { + case 0: + r = this.decodeInteger(l) + break + case 1: + r = this.decodeNegint(l) + break + case 2: + r = this.decodeByteString(l) + break + case 3: + r = this.decodeTextString(l) + break + case 4: + r = this.decodeArray(l, level + 1) + break + case 5: + r = this.decodeMap(l, level + 1) + break + case 6: + console.log("XXX ignored semantic tag " + this.decodeInteger(l).toString()) + break; + case 7: + r = this.decodePrimitive(l) + break + default: + throw new Error("Unsupported type 0x" + t.toString(2) + " len " + l.toString()) + } + // console.log("decode level " + level.toString() + " value " + JSON.stringify(r)) + return r +} + +CBORDecode.prototype.decode = function() { + return this.decodeInternal(0) +} + +// ------------------------------------------------------------------ +// a crappy SSH message packer - 20200401 djm@openbsd.org + +var SSHMSG = function() { + this.r = [] +} + +SSHMSG.prototype.length = function() { + let len = 0 + for (buf of this.r) { + len += buf.length + } + return len +} + +SSHMSG.prototype.serialise = function() { + let r = new ArrayBuffer(this.length()) + let v = new Uint8Array(r) + let offset = 0 + for (buf of this.r) { + v.set(buf, offset) + offset += buf.length + } + if (offset != r.byteLength) { + throw new Error("djm can't count") + } + return r +} + +SSHMSG.prototype.serialiseBase64 = function(v) { + let b = this.serialise() + return btoa(String.fromCharCode(...new Uint8Array(b))); +} + +SSHMSG.prototype.putU8 = function(v) { + this.r.push(new Uint8Array([v])) +} + +SSHMSG.prototype.putU32 = function(v) { + this.r.push(new Uint8Array([ + (v >> 24) & 0xff, + (v >> 16) & 0xff, + (v >> 8) & 0xff, + (v & 0xff) + ])) +} + +SSHMSG.prototype.put = function(v) { + this.r.push(new Uint8Array(v)) +} + +SSHMSG.prototype.putStringRaw = function(v) { + let enc = new TextEncoder(); + let venc = enc.encode(v) + this.put(venc) +} + +SSHMSG.prototype.putString = function(v) { + let enc = new TextEncoder(); + let venc = enc.encode(v) + this.putU32(venc.length) + this.put(venc) +} + +SSHMSG.prototype.putSSHMSG = function(v) { + let msg = v.serialise() + this.putU32(msg.byteLength) + this.put(msg) +} + +SSHMSG.prototype.putBytes = function(v) { + this.putU32(v.byteLength) + this.put(v) +} + +SSHMSG.prototype.putECPoint = function(x, y) { + let x8 = new Uint8Array(x) + let y8 = new Uint8Array(y) + this.putU32(1 + x8.length + y8.length) + this.putU8(0x04) // Uncompressed point format. + this.put(x8) + this.put(y8) +} + +// ------------------------------------------------------------------ +// webauthn to SSH glue - djm@openbsd.org 20200408 + +function error(msg, ...args) { + document.getElementById("error").innerText = msg + console.log(msg) + for (const arg of args) { + console.dir(arg) + } +} +function hexdump(buf) { + const hex = Array.from(new Uint8Array(buf)).map( + b => b.toString(16).padStart(2, "0")) + const fmt = new Array() + for (let i = 0; i < hex.length; i++) { + if ((i % 16) == 0) { + // Prepend length every 16 bytes. + fmt.push(i.toString(16).padStart(4, "0")) + fmt.push(" ") + } + fmt.push(hex[i]) + fmt.push(" ") + if ((i % 16) == 15) { + fmt.push("\n") + } + } + return fmt.join("") +} +function enrollform_submit(event) { + event.preventDefault(); + console.log("submitted") + username = event.target.elements.username.value + if (username === "") { + error("no username specified") + return false + } + enrollStart(username) +} +function enrollStart(username) { + let challenge = new Uint8Array(32) + window.crypto.getRandomValues(challenge) + let userid = new Uint8Array(8) + window.crypto.getRandomValues(userid) + + console.log("challenge:" + btoa(challenge)) + console.log("userid:" + btoa(userid)) + + let pkopts = { + challenge: challenge, + rp: { + name: window.location.host, + id: window.location.host, + }, + user: { + id: userid, + name: username, + displayName: username, + }, + authenticatorSelection: { + authenticatorAttachment: "cross-platform", + userVerification: "discouraged", + }, + pubKeyCredParams: [{alg: -7, type: "public-key"}], // ES256 + timeout: 30 * 1000, + }; + console.dir(pkopts) + window.enrollOpts = pkopts + let credpromise = navigator.credentials.create({ publicKey: pkopts }); + credpromise.then(enrollSuccess, enrollFailure) +} +function enrollFailure(result) { + error("Enroll failed", result) +} +function enrollSuccess(result) { + console.log("Enroll succeeded") + console.dir(result) + window.enrollResult = result + document.getElementById("enrollresult").style.visibility = "visible" + + // Show the clientData + let u8dec = new TextDecoder('utf-8') + clientData = u8dec.decode(result.response.clientDataJSON) + document.getElementById("enrollresultjson").innerText = clientData + + // Show the raw key handle. + document.getElementById("keyhandle").innerText = hexdump(result.rawId) + + // Decode and show the attestationObject + document.getElementById("enrollresultraw").innerText = hexdump(result.response.attestationObject) + let aod = new CBORDecode(result.response.attestationObject) + let attestationObject = aod.decode() + console.log("attestationObject") + console.dir(attestationObject) + document.getElementById("enrollresultattestobj").innerText = JSON.stringify(attestationObject) + + // Decode and show the authData + document.getElementById("enrollresultauthdataraw").innerText = hexdump(attestationObject.authData) + let authData = decodeAuthenticatorData(attestationObject.authData, true) + console.log("authData") + console.dir(authData) + window.enrollAuthData = authData + document.getElementById("enrollresultauthdata").innerText = JSON.stringify(authData) + + // Reformat the pubkey as a SSH key for easy verification + window.rawKey = reformatPubkey(authData.attestedCredentialData.credentialPublicKey, window.enrollOpts.rp.id) + console.log("SSH pubkey blob") + console.dir(window.rawKey) + document.getElementById("enrollresultpkblob").innerText = hexdump(window.rawKey) + let pk64 = btoa(String.fromCharCode(...new Uint8Array(window.rawKey))); + let pk = "sk-ecdsa-sha2-nistp256@openssh.com " + pk64 + document.getElementById("enrollresultpk").innerText = pk + + // Format a private key too. + flags = 0x01 // SSH_SK_USER_PRESENCE_REQD + window.rawPrivkey = reformatPrivkey(authData.attestedCredentialData.credentialPublicKey, window.enrollOpts.rp.id, result.rawId, flags) + let privkeyFileBlob = privkeyFile(window.rawKey, window.rawPrivkey, window.enrollOpts.user.name, window.enrollOpts.rp.id) + let privk64 = btoa(String.fromCharCode(...new Uint8Array(privkeyFileBlob))); + let privkey = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + wrapString(privk64, 70) + "-----END OPENSSH PRIVATE KEY-----\n" + document.getElementById("enrollresultprivkey").innerText = privkey + + // Success: show the assertion form. + document.getElementById("assertsection").style.visibility = "visible" +} + +function decodeAuthenticatorData(authData, expectCred) { + let r = new Object() + let v = new DataView(authData) + + r.rpIdHash = authData.slice(0, 32) + r.flags = v.getUint8(32) + r.signCount = v.getUint32(33) + + // Decode attestedCredentialData if present. + let offset = 37 + let acd = new Object() + if (expectCred) { + acd.aaguid = authData.slice(offset, offset+16) + offset += 16 + let credentialIdLength = v.getUint16(offset) + offset += 2 + acd.credentialIdLength = credentialIdLength + acd.credentialId = authData.slice(offset, offset+credentialIdLength) + offset += credentialIdLength + r.attestedCredentialData = acd + } + console.log("XXXXX " + offset.toString()) + let pubkeyrest = authData.slice(offset, authData.byteLength) + let pkdecode = new CBORDecode(pubkeyrest) + if (expectCred) { + // XXX unsafe: doesn't mandate COSE canonical format. + acd.credentialPublicKey = pkdecode.decode() + } + if (!pkdecode.empty()) { + // Decode extensions if present. + r.extensions = pkdecode.decode() + } + return r +} + +function wrapString(s, l) { + ret = "" + for (i = 0; i < s.length; i += l) { + ret += s.slice(i, i + l) + "\n" + } + return ret +} + +function checkPubkey(pk) { + // pk is in COSE format. We only care about a tiny subset. + if (pk[1] != 2) { + console.dir(pk) + throw new Error("pubkey is not EC") + } + if (pk[-1] != 1) { + throw new Error("pubkey is not in P256") + } + if (pk[3] != -7) { + throw new Error("pubkey is not ES256") + } + if (pk[-2].byteLength != 32 || pk[-3].byteLength != 32) { + throw new Error("pubkey EC coords have bad length") + } +} + +function reformatPubkey(pk, rpid) { + checkPubkey(pk) + let msg = new SSHMSG() + msg.putString("sk-ecdsa-sha2-nistp256@openssh.com") // Key type + msg.putString("nistp256") // Key curve + msg.putECPoint(pk[-2], pk[-3]) // EC key + msg.putString(rpid) // RP ID + return msg.serialise() +} + +function reformatPrivkey(pk, rpid, kh, flags) { + checkPubkey(pk) + let msg = new SSHMSG() + msg.putString("sk-ecdsa-sha2-nistp256@openssh.com") // Key type + msg.putString("nistp256") // Key curve + msg.putECPoint(pk[-2], pk[-3]) // EC key + msg.putString(rpid) // RP ID + msg.putU8(flags) // flags + msg.putBytes(kh) // handle + msg.putString("") // reserved + return msg.serialise() +} + +function privkeyFile(pub, priv, user, rp) { + let innerMsg = new SSHMSG() + innerMsg.putU32(0xdeadbeef) // check byte + innerMsg.putU32(0xdeadbeef) // check byte + innerMsg.put(priv) // privkey + innerMsg.putString("webauthn.html " + user + "@" + rp) // comment + // Pad to cipher blocksize (8). + p = 1 + while (innerMsg.length() % 8 != 0) { + innerMsg.putU8(p++) + } + let msg = new SSHMSG() + msg.putStringRaw("openssh-key-v1") // Magic + msg.putU8(0) // \0 terminate + msg.putString("none") // cipher + msg.putString("none") // KDF + msg.putString("") // KDF options + msg.putU32(1) // nkeys + msg.putBytes(pub) // pubkey + msg.putSSHMSG(innerMsg) // inner + //msg.put(innerMsg.serialise()) // inner + return msg.serialise() +} + +async function assertform_submit(event) { + event.preventDefault(); + console.log("submitted") + message = event.target.elements.message.value + if (message === "") { + error("no message specified") + return false + } + let enc = new TextEncoder() + let encmsg = enc.encode(message) + window.assertSignRaw = !event.target.elements.message_sshsig.checked + console.log("using sshsig ", !window.assertSignRaw) + if (window.assertSignRaw) { + assertStart(encmsg) + return + } + // Format a sshsig-style message. + window.sigHashAlg = "sha512" + let msghash = await crypto.subtle.digest("SHA-512", encmsg); + console.log("raw message hash") + console.dir(msghash) + window.sigNamespace = event.target.elements.message_namespace.value + let sigbuf = new SSHMSG() + sigbuf.put(enc.encode("SSHSIG")) + sigbuf.putString(window.sigNamespace) + sigbuf.putU32(0) // Reserved string + sigbuf.putString(window.sigHashAlg) + sigbuf.putBytes(msghash) + let msg = sigbuf.serialise() + console.log("sigbuf") + console.dir(msg) + assertStart(msg) +} + +function assertStart(message) { + let assertReqOpts = { + challenge: message, + rpId: window.location.host, + allowCredentials: [{ + type: 'public-key', + id: window.enrollResult.rawId, + }], + userVerification: "discouraged", + timeout: (30 * 1000), + } + console.log("assertReqOpts") + console.dir(assertReqOpts) + window.assertReqOpts = assertReqOpts + let assertpromise = navigator.credentials.get({ + publicKey: assertReqOpts + }); + assertpromise.then(assertSuccess, assertFailure) +} +function assertFailure(result) { + error("Assertion failed", result) +} +function linewrap(s) { + const linelen = 70 + let ret = "" + for (let i = 0; i < s.length; i += linelen) { + end = i + linelen + if (end > s.length) { + end = s.length + } + if (i > 0) { + ret += "\n" + } + ret += s.slice(i, end) + } + return ret + "\n" +} +function assertSuccess(result) { + console.log("Assertion succeeded") + console.dir(result) + window.assertResult = result + document.getElementById("assertresult").style.visibility = "visible" + + // show the clientData. + let u8dec = new TextDecoder('utf-8') + clientData = u8dec.decode(result.response.clientDataJSON) + document.getElementById("assertresultjson").innerText = clientData + + // show the signature. + document.getElementById("assertresultsigraw").innerText = hexdump(result.response.signature) + + // decode and show the authData. + document.getElementById("assertresultauthdataraw").innerText = hexdump(result.response.authenticatorData) + authData = decodeAuthenticatorData(result.response.authenticatorData, false) + document.getElementById("assertresultauthdata").innerText = JSON.stringify(authData) + + // Parse and reformat the signature to an SSH style signature. + let sshsig = reformatSignature(result.response.signature, clientData, authData) + document.getElementById("assertresultsshsigraw").innerText = hexdump(sshsig) + let sig64 = btoa(String.fromCharCode(...new Uint8Array(sshsig))); + if (window.assertSignRaw) { + document.getElementById("assertresultsshsigb64").innerText = sig64 + } else { + document.getElementById("assertresultsshsigb64").innerText = + "-----BEGIN SSH SIGNATURE-----\n" + linewrap(sig64) + + "-----END SSH SIGNATURE-----\n"; + } +} + +function reformatSignature(sig, clientData, authData) { + if (sig.byteLength < 2) { + throw new Error("signature is too short") + } + let offset = 0 + let v = new DataView(sig) + // Expect an ASN.1 SEQUENCE that exactly spans the signature. + if (v.getUint8(offset) != 0x30) { + throw new Error("signature not an ASN.1 sequence") + } + offset++ + let seqlen = v.getUint8(offset) + offset++ + if ((seqlen & 0x80) != 0 || seqlen != sig.byteLength - offset) { + throw new Error("signature has unexpected length " + seqlen.toString() + " vs expected " + (sig.byteLength - offset).toString()) + } + + // Parse 'r' INTEGER value. + if (v.getUint8(offset) != 0x02) { + throw new Error("signature r not an ASN.1 integer") + } + offset++ + let rlen = v.getUint8(offset) + offset++ + if ((rlen & 0x80) != 0 || rlen > sig.byteLength - offset) { + throw new Error("signature r has unexpected length " + rlen.toString() + " vs buffer " + (sig.byteLength - offset).toString()) + } + let r = sig.slice(offset, offset + rlen) + offset += rlen + console.log("sig_r") + console.dir(r) + + // Parse 's' INTEGER value. + if (v.getUint8(offset) != 0x02) { + throw new Error("signature r not an ASN.1 integer") + } + offset++ + let slen = v.getUint8(offset) + offset++ + if ((slen & 0x80) != 0 || slen > sig.byteLength - offset) { + throw new Error("signature s has unexpected length " + slen.toString() + " vs buffer " + (sig.byteLength - offset).toString()) + } + let s = sig.slice(offset, offset + slen) + console.log("sig_s") + console.dir(s) + offset += slen + + if (offset != sig.byteLength) { + throw new Error("unexpected final offset during signature parsing " + offset.toString() + " expected " + sig.byteLength.toString()) + } + + // Reformat as an SSH signature. + let clientDataParsed = JSON.parse(clientData) + let innersig = new SSHMSG() + innersig.putBytes(r) + innersig.putBytes(s) + + let rawsshsig = new SSHMSG() + rawsshsig.putString("webauthn-sk-ecdsa-sha2-nistp256@openssh.com") + rawsshsig.putSSHMSG(innersig) + rawsshsig.putU8(authData.flags) + rawsshsig.putU32(authData.signCount) + rawsshsig.putString(clientDataParsed.origin) + rawsshsig.putString(clientData) + if (authData.extensions == undefined) { + rawsshsig.putU32(0) + } else { + rawsshsig.putBytes(authData.extensions) + } + + if (window.assertSignRaw) { + return rawsshsig.serialise() + } + // Format as SSHSIG. + let enc = new TextEncoder() + let sshsig = new SSHMSG() + sshsig.put(enc.encode("SSHSIG")) + sshsig.putU32(0x01) // Signature version. + sshsig.putBytes(window.rawKey) + sshsig.putString(window.sigNamespace) + sshsig.putU32(0) // Reserved string + sshsig.putString(window.sigHashAlg) + sshsig.putBytes(rawsshsig.serialise()) + return sshsig.serialise() +} + +function toggleNamespaceVisibility() { + const assertsigtype = document.getElementById('message_sshsig'); + const assertsignamespace = document.getElementById('message_namespace'); + assertsignamespace.disabled = !assertsigtype.checked; +} + +function init() { + if (document.location.protocol != "https:") { + error("This page must be loaded via https") + const assertsubmit = document.getElementById('assertsubmit') + assertsubmit.disabled = true + } + const enrollform = document.getElementById('enrollform'); + enrollform.addEventListener('submit', enrollform_submit); + const assertform = document.getElementById('assertform'); + assertform.addEventListener('submit', assertform_submit); + const assertsigtype = document.getElementById('message_sshsig'); + assertsigtype.onclick = toggleNamespaceVisibility; +} +</script> + +</html> diff --git a/regress/unittests/test_helper/Makefile b/regress/unittests/test_helper/Makefile new file mode 100644 index 0000000..78026e6 --- /dev/null +++ b/regress/unittests/test_helper/Makefile @@ -0,0 +1,15 @@ +# $OpenBSD: Makefile,v 1.3 2016/07/04 18:01:44 guenther Exp $ + +LIB= test_helper +SRCS= test_helper.c fuzz.c + +NOPROFILE= yes +NOPIC= yes + +# Hack to allow building with SUBDIR in ../../Makefile +regress: all + +install: + @echo -n + +.include <bsd.lib.mk> diff --git a/regress/unittests/test_helper/fuzz.c b/regress/unittests/test_helper/fuzz.c new file mode 100644 index 0000000..78b3665 --- /dev/null +++ b/regress/unittests/test_helper/fuzz.c @@ -0,0 +1,438 @@ +/* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller <djm@mindrot.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for fuzz tests */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/uio.h> + +#include <assert.h> +#include <ctype.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> + +#include "test_helper.h" +#include "atomicio.h" + +/* #define FUZZ_DEBUG */ + +#ifdef FUZZ_DEBUG +# define FUZZ_DBG(x) do { \ + printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ + printf x; \ + printf("\n"); \ + fflush(stdout); \ + } while (0) +#else +# define FUZZ_DBG(x) +#endif + +/* For brevity later */ +typedef unsigned long long fuzz_ullong; + +/* For base-64 fuzzing */ +static const char fuzz_b64chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +struct fuzz { + /* Fuzz method currently in use */ + int strategy; + + /* Fuzz methods remaining */ + int strategies; + + /* Original seed data blob */ + void *seed; + size_t slen; + + /* Current working copy of seed with fuzz mutations applied */ + u_char *fuzzed; + + /* Used by fuzz methods */ + size_t o1, o2; +}; + +static const char * +fuzz_ntop(u_int n) +{ + switch (n) { + case 0: + return "NONE"; + case FUZZ_1_BIT_FLIP: + return "FUZZ_1_BIT_FLIP"; + case FUZZ_2_BIT_FLIP: + return "FUZZ_2_BIT_FLIP"; + case FUZZ_1_BYTE_FLIP: + return "FUZZ_1_BYTE_FLIP"; + case FUZZ_2_BYTE_FLIP: + return "FUZZ_2_BYTE_FLIP"; + case FUZZ_TRUNCATE_START: + return "FUZZ_TRUNCATE_START"; + case FUZZ_TRUNCATE_END: + return "FUZZ_TRUNCATE_END"; + case FUZZ_BASE64: + return "FUZZ_BASE64"; + default: + abort(); + } +} + +static int +fuzz_fmt(struct fuzz *fuzz, char *s, size_t n) +{ + if (fuzz == NULL) + return -1; + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen * 8, fuzz->o1); + return 0; + case FUZZ_2_BIT_FLIP: + snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n", + fuzz_ntop(fuzz->strategy), + (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1, + ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8, + fuzz->o1, fuzz->o2); + return 0; + case FUZZ_1_BYTE_FLIP: + snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + return 0; + case FUZZ_2_BYTE_FLIP: + snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n", + fuzz_ntop(fuzz->strategy), + (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1, + ((fuzz_ullong)fuzz->slen) * fuzz->slen, + fuzz->o1, fuzz->o2); + return 0; + case FUZZ_TRUNCATE_START: + snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + return 0; + case FUZZ_TRUNCATE_END: + snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + return 0; + case FUZZ_BASE64: + assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); + snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n", + fuzz_ntop(fuzz->strategy), + (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2, + fuzz->slen * (fuzz_ullong)64, fuzz->o1, + fuzz_b64chars[fuzz->o2]); + return 0; + default: + return -1; + abort(); + } +} + +static void +dump(u_char *p, size_t len) +{ + size_t i, j; + + for (i = 0; i < len; i += 16) { + fprintf(stderr, "%.4zd: ", i); + for (j = i; j < i + 16; j++) { + if (j < len) + fprintf(stderr, "%02x ", p[j]); + else + fprintf(stderr, " "); + } + fprintf(stderr, " "); + for (j = i; j < i + 16; j++) { + if (j < len) { + if (isascii(p[j]) && isprint(p[j])) + fprintf(stderr, "%c", p[j]); + else + fprintf(stderr, "."); + } + } + fprintf(stderr, "\n"); + } +} + +void +fuzz_dump(struct fuzz *fuzz) +{ + char buf[256]; + + if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) { + fprintf(stderr, "%s: fuzz invalid\n", __func__); + abort(); + } + fputs(buf, stderr); + fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen); + dump(fuzz->seed, fuzz->slen); + fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz)); + dump(fuzz_ptr(fuzz), fuzz_len(fuzz)); +} + +static struct fuzz *last_fuzz; + +static void +siginfo(int unused __attribute__((__unused__))) +{ + char buf[256]; + + test_info(buf, sizeof(buf)); + atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); + if (last_fuzz != NULL) { + fuzz_fmt(last_fuzz, buf, sizeof(buf)); + atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); + } +} + +struct fuzz * +fuzz_begin(u_int strategies, const void *p, size_t l) +{ + struct fuzz *ret = calloc(sizeof(*ret), 1); + + assert(p != NULL); + assert(ret != NULL); + ret->seed = malloc(l); + assert(ret->seed != NULL); + memcpy(ret->seed, p, l); + ret->slen = l; + ret->strategies = strategies; + + assert(ret->slen < SIZE_MAX / 8); + assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1))); + + FUZZ_DBG(("begin, ret = %p", ret)); + + fuzz_next(ret); + + last_fuzz = ret; +#ifdef SIGINFO + signal(SIGINFO, siginfo); +#endif + signal(SIGUSR1, siginfo); + + return ret; +} + +void +fuzz_cleanup(struct fuzz *fuzz) +{ + FUZZ_DBG(("cleanup, fuzz = %p", fuzz)); + last_fuzz = NULL; +#ifdef SIGINFO + signal(SIGINFO, SIG_DFL); +#endif + signal(SIGUSR1, SIG_DFL); + assert(fuzz != NULL); + assert(fuzz->seed != NULL); + assert(fuzz->fuzzed != NULL); + free(fuzz->seed); + free(fuzz->fuzzed); + free(fuzz); +} + +static int +fuzz_strategy_done(struct fuzz *fuzz) +{ + FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu", + fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen)); + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + return fuzz->o1 >= fuzz->slen * 8; + case FUZZ_2_BIT_FLIP: + return fuzz->o2 >= fuzz->slen * 8; + case FUZZ_2_BYTE_FLIP: + return fuzz->o2 >= fuzz->slen; + case FUZZ_1_BYTE_FLIP: + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + case FUZZ_BASE64: + return fuzz->o1 >= fuzz->slen; + default: + abort(); + } +} + +void +fuzz_next(struct fuzz *fuzz) +{ + u_int i; + + FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, " + "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), + (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); + + if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) { + /* If we are just starting out, we need to allocate too */ + if (fuzz->fuzzed == NULL) { + FUZZ_DBG(("alloc")); + fuzz->fuzzed = calloc(fuzz->slen, 1); + } + /* Pick next strategy */ + FUZZ_DBG(("advance")); + for (i = 1; i <= FUZZ_MAX; i <<= 1) { + if ((fuzz->strategies & i) != 0) { + fuzz->strategy = i; + break; + } + } + FUZZ_DBG(("selected = %u", fuzz->strategy)); + if (fuzz->strategy == 0) { + FUZZ_DBG(("done, no more strategies")); + return; + } + fuzz->strategies &= ~(fuzz->strategy); + fuzz->o1 = fuzz->o2 = 0; + } + + assert(fuzz->fuzzed != NULL); + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + assert(fuzz->o1 / 8 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); + fuzz->o1++; + break; + case FUZZ_2_BIT_FLIP: + assert(fuzz->o1 / 8 < fuzz->slen); + assert(fuzz->o2 / 8 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); + fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8); + fuzz->o1++; + if (fuzz->o1 >= fuzz->slen * 8) { + fuzz->o1 = 0; + fuzz->o2++; + } + break; + case FUZZ_1_BYTE_FLIP: + assert(fuzz->o1 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] ^= 0xff; + fuzz->o1++; + break; + case FUZZ_2_BYTE_FLIP: + assert(fuzz->o1 < fuzz->slen); + assert(fuzz->o2 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] ^= 0xff; + fuzz->fuzzed[fuzz->o2] ^= 0xff; + fuzz->o1++; + if (fuzz->o1 >= fuzz->slen) { + fuzz->o1 = 0; + fuzz->o2++; + } + break; + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->o1++; + break; + case FUZZ_BASE64: + assert(fuzz->o1 < fuzz->slen); + assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2]; + fuzz->o2++; + if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) { + fuzz->o2 = 0; + fuzz->o1++; + } + break; + default: + abort(); + } + + FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, " + "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), + (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); +} + +int +fuzz_matches_original(struct fuzz *fuzz) +{ + if (fuzz_len(fuzz) != fuzz->slen) + return 0; + return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0; +} + +int +fuzz_done(struct fuzz *fuzz) +{ + FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz, + (u_long)fuzz->strategies)); + + return fuzz_strategy_done(fuzz) && fuzz->strategies == 0; +} + +size_t +fuzz_len(struct fuzz *fuzz) +{ + assert(fuzz->fuzzed != NULL); + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + case FUZZ_2_BIT_FLIP: + case FUZZ_1_BYTE_FLIP: + case FUZZ_2_BYTE_FLIP: + case FUZZ_BASE64: + return fuzz->slen; + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->slen - fuzz->o1; + default: + abort(); + } +} + +u_char * +fuzz_ptr(struct fuzz *fuzz) +{ + assert(fuzz->fuzzed != NULL); + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + case FUZZ_2_BIT_FLIP: + case FUZZ_1_BYTE_FLIP: + case FUZZ_2_BYTE_FLIP: + case FUZZ_BASE64: + return fuzz->fuzzed; + case FUZZ_TRUNCATE_START: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->fuzzed + fuzz->o1; + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->fuzzed; + default: + abort(); + } +} + diff --git a/regress/unittests/test_helper/test_helper.c b/regress/unittests/test_helper/test_helper.c new file mode 100644 index 0000000..e23128a --- /dev/null +++ b/regress/unittests/test_helper/test_helper.c @@ -0,0 +1,595 @@ +/* $OpenBSD: test_helper.c,v 1.13 2021/12/14 21:25:27 deraadt Exp $ */ +/* + * Copyright (c) 2011 Damien Miller <djm@mindrot.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for regress tests */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/uio.h> + +#include <stdarg.h> +#include <fcntl.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> +#include <signal.h> + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#include <openssl/err.h> +#endif + +#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) +# include <vis.h> +#endif + +#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) + +#include "entropy.h" +#include "test_helper.h" +#include "atomicio.h" + +#define TEST_CHECK_INT(r, pred) do { \ + switch (pred) { \ + case TEST_EQ: \ + if (r == 0) \ + return; \ + break; \ + case TEST_NE: \ + if (r != 0) \ + return; \ + break; \ + case TEST_LT: \ + if (r < 0) \ + return; \ + break; \ + case TEST_LE: \ + if (r <= 0) \ + return; \ + break; \ + case TEST_GT: \ + if (r > 0) \ + return; \ + break; \ + case TEST_GE: \ + if (r >= 0) \ + return; \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +#define TEST_CHECK(x1, x2, pred) do { \ + switch (pred) { \ + case TEST_EQ: \ + if (x1 == x2) \ + return; \ + break; \ + case TEST_NE: \ + if (x1 != x2) \ + return; \ + break; \ + case TEST_LT: \ + if (x1 < x2) \ + return; \ + break; \ + case TEST_LE: \ + if (x1 <= x2) \ + return; \ + break; \ + case TEST_GT: \ + if (x1 > x2) \ + return; \ + break; \ + case TEST_GE: \ + if (x1 >= x2) \ + return; \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +extern char *__progname; + +static int verbose_mode = 0; +static int quiet_mode = 0; +static char *active_test_name = NULL; +static u_int test_number = 0; +static test_onerror_func_t *test_onerror = NULL; +static void *onerror_ctx = NULL; +static const char *data_dir = NULL; +static char subtest_info[512]; +static int fast = 0; +static int slow = 0; + +int +main(int argc, char **argv) +{ + int ch; + + seed_rng(); +#ifdef WITH_OPENSSL + ERR_load_crypto_strings(); +#endif + + /* Handle systems without __progname */ + if (__progname == NULL) { + __progname = strrchr(argv[0], '/'); + if (__progname == NULL || __progname[1] == '\0') + __progname = argv[0]; + else + __progname++; + if ((__progname = strdup(__progname)) == NULL) { + fprintf(stderr, "strdup failed\n"); + exit(1); + } + } + + while ((ch = getopt(argc, argv, "Ffvqd:")) != -1) { + switch (ch) { + case 'F': + slow = 1; + break; + case 'f': + fast = 1; + break; + case 'd': + data_dir = optarg; + break; + case 'q': + verbose_mode = 0; + quiet_mode = 1; + break; + case 'v': + verbose_mode = 1; + quiet_mode = 0; + break; + default: + fprintf(stderr, "Unrecognised command line option\n"); + fprintf(stderr, "Usage: %s [-v]\n", __progname); + exit(1); + } + } + setvbuf(stdout, NULL, _IONBF, 0); + if (!quiet_mode) + printf("%s: ", __progname); + if (verbose_mode) + printf("\n"); + + tests(); + + if (!quiet_mode) + printf(" %u tests ok\n", test_number); + return 0; +} + +int +test_is_verbose(void) +{ + return verbose_mode; +} + +int +test_is_quiet(void) +{ + return quiet_mode; +} + +int +test_is_fast(void) +{ + return fast; +} + +int +test_is_slow(void) +{ + return slow; +} + +const char * +test_data_file(const char *name) +{ + static char ret[PATH_MAX]; + + if (data_dir != NULL) + snprintf(ret, sizeof(ret), "%s/%s", data_dir, name); + else + strlcpy(ret, name, sizeof(ret)); + if (access(ret, F_OK) != 0) { + fprintf(stderr, "Cannot access data file %s: %s\n", + ret, strerror(errno)); + exit(1); + } + return ret; +} + +void +test_info(char *s, size_t len) +{ + snprintf(s, len, "In test %u: \"%s\"%s%s\n", test_number, + active_test_name == NULL ? "<none>" : active_test_name, + *subtest_info != '\0' ? " - " : "", subtest_info); +} + +static void +siginfo(int unused __attribute__((__unused__))) +{ + char buf[256]; + + test_info(buf, sizeof(buf)); + atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); +} + +void +test_start(const char *n) +{ + assert(active_test_name == NULL); + assert((active_test_name = strdup(n)) != NULL); + *subtest_info = '\0'; + if (verbose_mode) + printf("test %u - \"%s\": ", test_number, active_test_name); + test_number++; +#ifdef SIGINFO + signal(SIGINFO, siginfo); +#endif + signal(SIGUSR1, siginfo); +} + +void +set_onerror_func(test_onerror_func_t *f, void *ctx) +{ + test_onerror = f; + onerror_ctx = ctx; +} + +void +test_done(void) +{ + *subtest_info = '\0'; + assert(active_test_name != NULL); + free(active_test_name); + active_test_name = NULL; + if (verbose_mode) + printf("OK\n"); + else if (!quiet_mode) { + printf("."); + fflush(stdout); + } +} + +void +test_subtest_info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsnprintf(subtest_info, sizeof(subtest_info), fmt, ap); + va_end(ap); +} + +void +ssl_err_check(const char *file, int line) +{ +#ifdef WITH_OPENSSL + long openssl_error = ERR_get_error(); + + if (openssl_error == 0) + return; + + fprintf(stderr, "\n%s:%d: uncaught OpenSSL error: %s", + file, line, ERR_error_string(openssl_error, NULL)); +#else /* WITH_OPENSSL */ + fprintf(stderr, "\n%s:%d: uncaught OpenSSL error ", + file, line); +#endif /* WITH_OPENSSL */ + abort(); +} + +static const char * +pred_name(enum test_predicate p) +{ + switch (p) { + case TEST_EQ: + return "EQ"; + case TEST_NE: + return "NE"; + case TEST_LT: + return "LT"; + case TEST_LE: + return "LE"; + case TEST_GT: + return "GT"; + case TEST_GE: + return "GE"; + default: + return "UNKNOWN"; + } +} + +static void +test_die(void) +{ + if (test_onerror != NULL) + test_onerror(onerror_ctx); + abort(); +} + +static void +test_header(const char *file, int line, const char *a1, const char *a2, + const char *name, enum test_predicate pred) +{ + fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n", + file, line, test_number, active_test_name, + *subtest_info != '\0' ? " - " : "", subtest_info); + fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n", + name, pred_name(pred), a1, + a2 != NULL ? ", " : "", a2 != NULL ? a2 : ""); +} + +#ifdef WITH_OPENSSL +void +assert_bignum(const char *file, int line, const char *a1, const char *a2, + const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred) +{ + int r = BN_cmp(aa1, aa2); + + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "BIGNUM", pred); + fprintf(stderr, "%12s = 0x%s\n", a1, BN_bn2hex(aa1)); + fprintf(stderr, "%12s = 0x%s\n", a2, BN_bn2hex(aa2)); + test_die(); +} +#endif + +void +assert_string(const char *file, int line, const char *a1, const char *a2, + const char *aa1, const char *aa2, enum test_predicate pred) +{ + int r; + + /* Verify pointers are not NULL */ + assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE); + assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE); + + r = strcmp(aa1, aa2); + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "STRING", pred); + fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1)); + fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2)); + test_die(); +} + +static char * +tohex(const void *_s, size_t l) +{ + u_int8_t *s = (u_int8_t *)_s; + size_t i, j; + const char *hex = "0123456789abcdef"; + char *r = malloc((l * 2) + 1); + + assert(r != NULL); + for (i = j = 0; i < l; i++) { + r[j++] = hex[(s[i] >> 4) & 0xf]; + r[j++] = hex[s[i] & 0xf]; + } + r[j] = '\0'; + return r; +} + +void +assert_mem(const char *file, int line, const char *a1, const char *a2, + const void *aa1, const void *aa2, size_t l, enum test_predicate pred) +{ + int r; + char *aa1_tohex = NULL; + char *aa2_tohex = NULL; + + if (l == 0) + return; + /* If length is >0, then verify pointers are not NULL */ + assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE); + assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE); + + r = memcmp(aa1, aa2, l); + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "STRING", pred); + aa1_tohex = tohex(aa1, MINIMUM(l, 256)); + aa2_tohex = tohex(aa2, MINIMUM(l, 256)); + fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1_tohex, l); + fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2_tohex, l); + free(aa1_tohex); + free(aa2_tohex); + test_die(); +} + +static int +memvalcmp(const u_int8_t *s, u_char v, size_t l, size_t *where) +{ + size_t i; + + for (i = 0; i < l; i++) { + if (s[i] != v) { + *where = i; + return 1; + } + } + return 0; +} + +void +assert_mem_filled(const char *file, int line, const char *a1, + const void *aa1, u_char v, size_t l, enum test_predicate pred) +{ + size_t where = -1; + int r; + char tmp[64]; + char *aa1_tohex = NULL; + + if (l == 0) + return; + /* If length is >0, then verify the pointer is not NULL */ + assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE); + + r = memvalcmp(aa1, v, l, &where); + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, NULL, "MEM_ZERO", pred); + aa1_tohex = tohex(aa1, MINIMUM(l, 20)); + fprintf(stderr, "%20s = %s%s (len %zu)\n", a1, + aa1_tohex, l > 20 ? "..." : "", l); + free(aa1_tohex); + snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where); + fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp, + ((u_char *)aa1)[where], v); + test_die(); +} + +void +assert_int(const char *file, int line, const char *a1, const char *a2, + int aa1, int aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "INT", pred); + fprintf(stderr, "%12s = %d\n", a1, aa1); + fprintf(stderr, "%12s = %d\n", a2, aa2); + test_die(); +} + +void +assert_size_t(const char *file, int line, const char *a1, const char *a2, + size_t aa1, size_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "SIZE_T", pred); + fprintf(stderr, "%12s = %zu\n", a1, aa1); + fprintf(stderr, "%12s = %zu\n", a2, aa2); + test_die(); +} + +void +assert_u_int(const char *file, int line, const char *a1, const char *a2, + u_int aa1, u_int aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U_INT", pred); + fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2); + test_die(); +} + +void +assert_long(const char *file, int line, const char *a1, const char *a2, + long aa1, long aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "LONG", pred); + fprintf(stderr, "%12s = %ld / 0x%lx\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %ld / 0x%lx\n", a2, aa2, aa2); + test_die(); +} + +void +assert_long_long(const char *file, int line, const char *a1, const char *a2, + long long aa1, long long aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "LONG LONG", pred); + fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2); + test_die(); +} + +void +assert_char(const char *file, int line, const char *a1, const char *a2, + char aa1, char aa2, enum test_predicate pred) +{ + char buf[8]; + + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "CHAR", pred); + fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, + vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1); + fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, + vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2); + test_die(); +} + +void +assert_u8(const char *file, int line, const char *a1, const char *a2, + u_int8_t aa1, u_int8_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U8", pred); + fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2); + test_die(); +} + +void +assert_u16(const char *file, int line, const char *a1, const char *a2, + u_int16_t aa1, u_int16_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U16", pred); + fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2); + test_die(); +} + +void +assert_u32(const char *file, int line, const char *a1, const char *a2, + u_int32_t aa1, u_int32_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U32", pred); + fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2); + test_die(); +} + +void +assert_u64(const char *file, int line, const char *a1, const char *a2, + u_int64_t aa1, u_int64_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U64", pred); + fprintf(stderr, "%12s = 0x%016llx %llu\n", a1, + (unsigned long long)aa1, (unsigned long long)aa1); + fprintf(stderr, "%12s = 0x%016llx %llu\n", a2, + (unsigned long long)aa2, (unsigned long long)aa2); + test_die(); +} + +void +assert_ptr(const char *file, int line, const char *a1, const char *a2, + const void *aa1, const void *aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "PTR", pred); + fprintf(stderr, "%12s = %p\n", a1, aa1); + fprintf(stderr, "%12s = %p\n", a2, aa2); + test_die(); +} + diff --git a/regress/unittests/test_helper/test_helper.h b/regress/unittests/test_helper/test_helper.h new file mode 100644 index 0000000..6630220 --- /dev/null +++ b/regress/unittests/test_helper/test_helper.h @@ -0,0 +1,326 @@ +/* $OpenBSD: test_helper.h,v 1.9 2018/10/17 23:28:05 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller <djm@mindrot.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for regress tests */ + +#ifndef _TEST_HELPER_H +#define _TEST_HELPER_H + +#include "includes.h" + +#include <sys/types.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#include <openssl/err.h> +#endif + +enum test_predicate { + TEST_EQ, TEST_NE, TEST_LT, TEST_LE, TEST_GT, TEST_GE +}; +typedef void (test_onerror_func_t)(void *); + +/* Supplied by test suite */ +void tests(void); + +const char *test_data_file(const char *name); +void test_start(const char *n); +void test_info(char *s, size_t len); +void set_onerror_func(test_onerror_func_t *f, void *ctx); +void test_done(void); +int test_is_verbose(void); +int test_is_quiet(void); +int test_is_fast(void); +int test_is_slow(void); +void test_subtest_info(const char *fmt, ...) + __attribute__((format(printf, 1, 2))); +void ssl_err_check(const char *file, int line); +#ifdef WITH_OPENSSL +void assert_bignum(const char *file, int line, + const char *a1, const char *a2, + const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred); +#endif +void assert_string(const char *file, int line, + const char *a1, const char *a2, + const char *aa1, const char *aa2, enum test_predicate pred); +void assert_mem(const char *file, int line, + const char *a1, const char *a2, + const void *aa1, const void *aa2, size_t l, enum test_predicate pred); +void assert_mem_filled(const char *file, int line, + const char *a1, + const void *aa1, u_char v, size_t l, enum test_predicate pred); +void assert_int(const char *file, int line, + const char *a1, const char *a2, + int aa1, int aa2, enum test_predicate pred); +void assert_size_t(const char *file, int line, + const char *a1, const char *a2, + size_t aa1, size_t aa2, enum test_predicate pred); +void assert_u_int(const char *file, int line, + const char *a1, const char *a2, + u_int aa1, u_int aa2, enum test_predicate pred); +void assert_long(const char *file, int line, + const char *a1, const char *a2, + long aa1, long aa2, enum test_predicate pred); +void assert_long_long(const char *file, int line, + const char *a1, const char *a2, + long long aa1, long long aa2, enum test_predicate pred); +void assert_char(const char *file, int line, + const char *a1, const char *a2, + char aa1, char aa2, enum test_predicate pred); +void assert_ptr(const char *file, int line, + const char *a1, const char *a2, + const void *aa1, const void *aa2, enum test_predicate pred); +void assert_u8(const char *file, int line, + const char *a1, const char *a2, + u_int8_t aa1, u_int8_t aa2, enum test_predicate pred); +void assert_u16(const char *file, int line, + const char *a1, const char *a2, + u_int16_t aa1, u_int16_t aa2, enum test_predicate pred); +void assert_u32(const char *file, int line, + const char *a1, const char *a2, + u_int32_t aa1, u_int32_t aa2, enum test_predicate pred); +void assert_u64(const char *file, int line, + const char *a1, const char *a2, + u_int64_t aa1, u_int64_t aa2, enum test_predicate pred); + +#define TEST_START(n) test_start(n) +#define TEST_DONE() test_done() +#define TEST_ONERROR(f, c) set_onerror_func(f, c) +#define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__) + +#define ASSERT_BIGNUM_EQ(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_STRING_EQ(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_MEM_EQ(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_EQ) +#define ASSERT_MEM_FILLED_EQ(a1, c, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, c, l, TEST_EQ) +#define ASSERT_MEM_ZERO_EQ(a1, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_EQ) +#define ASSERT_INT_EQ(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_SIZE_T_EQ(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U_INT_EQ(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_LONG_EQ(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_LONG_LONG_EQ(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_CHAR_EQ(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_PTR_EQ(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U8_EQ(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U16_EQ(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U32_EQ(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U64_EQ(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) + +#define ASSERT_BIGNUM_NE(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_STRING_NE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_MEM_NE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_NE) +#define ASSERT_MEM_ZERO_NE(a1, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_NE) +#define ASSERT_INT_NE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_SIZE_T_NE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U_INT_NE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_LONG_NE(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_LONG_LONG_NE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_CHAR_NE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_PTR_NE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U8_NE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U16_NE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U32_NE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U64_NE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) + +#define ASSERT_BIGNUM_LT(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_STRING_LT(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_MEM_LT(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LT) +#define ASSERT_INT_LT(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_SIZE_T_LT(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U_INT_LT(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_LONG_LT(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_LONG_LONG_LT(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_CHAR_LT(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_PTR_LT(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U8_LT(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U16_LT(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U32_LT(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U64_LT(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) + +#define ASSERT_BIGNUM_LE(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_STRING_LE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_MEM_LE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LE) +#define ASSERT_INT_LE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_SIZE_T_LE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U_INT_LE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_LONG_LE(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_LONG_LONG_LE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_CHAR_LE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_PTR_LE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U8_LE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U16_LE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U32_LE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U64_LE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) + +#define ASSERT_BIGNUM_GT(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_STRING_GT(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_MEM_GT(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GT) +#define ASSERT_INT_GT(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_SIZE_T_GT(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U_INT_GT(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_LONG_GT(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_LONG_LONG_GT(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_CHAR_GT(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_PTR_GT(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U8_GT(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U16_GT(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U32_GT(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U64_GT(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) + +#define ASSERT_BIGNUM_GE(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_STRING_GE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_MEM_GE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GE) +#define ASSERT_INT_GE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_SIZE_T_GE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U_INT_GE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_LONG_GE(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_LONG_LONG_GE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_CHAR_GE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_PTR_GE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U8_GE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U16_GE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U32_GE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U64_GE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) + +/* Fuzzing support */ + +struct fuzz; +#define FUZZ_1_BIT_FLIP 0x00000001 /* Flip one bit at a time */ +#define FUZZ_2_BIT_FLIP 0x00000002 /* Flip two bits at a time */ +#define FUZZ_1_BYTE_FLIP 0x00000004 /* Flip one byte at a time */ +#define FUZZ_2_BYTE_FLIP 0x00000008 /* Flip two bytes at a time */ +#define FUZZ_TRUNCATE_START 0x00000010 /* Truncate from beginning */ +#define FUZZ_TRUNCATE_END 0x00000020 /* Truncate from end */ +#define FUZZ_BASE64 0x00000040 /* Try all base64 chars */ +#define FUZZ_MAX FUZZ_BASE64 + +/* Start fuzzing a blob of data with selected strategies (bitmask) */ +struct fuzz *fuzz_begin(u_int strategies, const void *p, size_t l); + +/* Free a fuzz context */ +void fuzz_cleanup(struct fuzz *fuzz); + +/* Prepare the next fuzz case in the series */ +void fuzz_next(struct fuzz *fuzz); + +/* + * Check whether this fuzz case is identical to the original + * This is slow, but useful if the caller needs to ensure that all tests + * generated change the input (e.g. when fuzzing signatures). + */ +int fuzz_matches_original(struct fuzz *fuzz); + +/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */ +int fuzz_done(struct fuzz *fuzz); + +/* Return the length and a pointer to the current fuzzed case */ +size_t fuzz_len(struct fuzz *fuzz); +u_char *fuzz_ptr(struct fuzz *fuzz); + +/* Dump the current fuzz case to stderr */ +void fuzz_dump(struct fuzz *fuzz); + +#endif /* _TEST_HELPER_H */ diff --git a/regress/unittests/utf8/Makefile b/regress/unittests/utf8/Makefile new file mode 100644 index 0000000..f8eec04 --- /dev/null +++ b/regress/unittests/utf8/Makefile @@ -0,0 +1,14 @@ +# $OpenBSD: Makefile,v 1.5 2017/12/21 00:41:22 djm Exp $ + +PROG=test_utf8 +SRCS=tests.c + +# From usr.bin/ssh +SRCS+=utf8.c atomicio.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} + +.include <bsd.regress.mk> diff --git a/regress/unittests/utf8/tests.c b/regress/unittests/utf8/tests.c new file mode 100644 index 0000000..8cf524d --- /dev/null +++ b/regress/unittests/utf8/tests.c @@ -0,0 +1,104 @@ +/* $OpenBSD: tests.c,v 1.4 2017/02/19 00:11:29 djm Exp $ */ +/* + * Regress test for the utf8.h *mprintf() API + * + * Written by Ingo Schwarze <schwarze@openbsd.org> in 2016 + * and placed in the public domain. + */ + +#include "includes.h" + +#include <locale.h> +#include <stdarg.h> +#include <string.h> +#include <stdio.h> + +#include "../test_helper/test_helper.h" + +#include "utf8.h" + +static void +badarg(void) +{ + char buf[16]; + int len, width; + + width = 1; + TEST_START("utf8_badarg"); + len = snmprintf(buf, sizeof(buf), &width, "\377"); + ASSERT_INT_EQ(len, -1); + ASSERT_STRING_EQ(buf, ""); + ASSERT_INT_EQ(width, 0); + TEST_DONE(); +} + +static void +one(int utf8, const char *name, const char *mbs, int width, + int wantwidth, int wantlen, const char *wants) +{ + char buf[16]; + int *wp; + int len; + + if (wantlen == -2) + wantlen = strlen(wants); + (void)strlcpy(buf, utf8 ? "utf8_" : "c_", sizeof(buf)); + (void)strlcat(buf, name, sizeof(buf)); + TEST_START(buf); + wp = wantwidth == -2 ? NULL : &width; + len = snmprintf(buf, sizeof(buf), wp, "%s", mbs); + ASSERT_INT_EQ(len, wantlen); + ASSERT_STRING_EQ(buf, wants); + ASSERT_INT_EQ(width, wantwidth); + TEST_DONE(); +} + +void +tests(void) +{ + char *loc; + + TEST_START("utf8_setlocale"); + loc = setlocale(LC_CTYPE, "en_US.UTF-8"); + ASSERT_PTR_NE(loc, NULL); + TEST_DONE(); + + badarg(); + one(1, "empty", "", 2, 0, 0, ""); + one(1, "ascii", "x", -2, -2, -2, "x"); + one(1, "newline", "a\nb", -2, -2, -2, "a\nb"); + one(1, "cr", "a\rb", -2, -2, -2, "a\rb"); + one(1, "tab", "a\tb", -2, -2, -2, "a\tb"); + one(1, "esc", "\033x", -2, -2, -2, "\\033x"); + one(1, "inv_badbyte", "\377x", -2, -2, -2, "\\377x"); + one(1, "inv_nocont", "\341x", -2, -2, -2, "\\341x"); + one(1, "inv_nolead", "a\200b", -2, -2, -2, "a\\200b"); + one(1, "sz_ascii", "1234567890123456", -2, -2, 16, "123456789012345"); + one(1, "sz_esc", "123456789012\033", -2, -2, 16, "123456789012"); + one(1, "width_ascii", "123", 2, 2, -1, "12"); + one(1, "width_double", "a\343\201\201", 2, 1, -1, "a"); + one(1, "double_fit", "a\343\201\201", 3, 3, 4, "a\343\201\201"); + one(1, "double_spc", "a\343\201\201", 4, 3, 4, "a\343\201\201"); + + TEST_START("C_setlocale"); + loc = setlocale(LC_CTYPE, "C"); + ASSERT_PTR_NE(loc, NULL); + TEST_DONE(); + + badarg(); + one(0, "empty", "", 2, 0, 0, ""); + one(0, "ascii", "x", -2, -2, -2, "x"); + one(0, "newline", "a\nb", -2, -2, -2, "a\nb"); + one(0, "cr", "a\rb", -2, -2, -2, "a\rb"); + one(0, "tab", "a\tb", -2, -2, -2, "a\tb"); + one(0, "esc", "\033x", -2, -2, -2, "\\033x"); + one(0, "inv_badbyte", "\377x", -2, -2, -2, "\\377x"); + one(0, "inv_nocont", "\341x", -2, -2, -2, "\\341x"); + one(0, "inv_nolead", "a\200b", -2, -2, -2, "a\\200b"); + one(0, "sz_ascii", "1234567890123456", -2, -2, 16, "123456789012345"); + one(0, "sz_esc", "123456789012\033", -2, -2, 16, "123456789012"); + one(0, "width_ascii", "123", 2, 2, -1, "12"); + one(0, "width_double", "a\343\201\201", 2, 1, -1, "a"); + one(0, "double_fit", "a\343\201\201", 7, 5, -1, "a\\343"); + one(0, "double_spc", "a\343\201\201", 13, 13, 13, "a\\343\\201\\201"); +} |