ssh-sk-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshbuf.h sshkey.h msg.h digest.h pathnames.h ssh-sk.h misc.h
ssh-sk-helper.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h sshkey.h authfd.h misc.h sshbuf.h msg.h uidswap.h ssh-sk.h ssh-pkcs11.h
ssh-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-ssh-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
ssh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h canohost.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h packet.h dispatch.h sshbuf.h channels.h
ssh.o: sshkey.h authfd.h authfile.h pathnames.h clientloop.h log.h ssherr.h misc.h readconf.h sshconnect.h kex.h mac.h crypto_api.h sshpty.h match.h msg.h version.h myproposal.h utf8.h
ssh_api.o: authfile.h dh.h misc.h version.h myproposal.h sshbuf.h openbsd-compat/openssl-compat.h
sshd.o: audit.h loginrec.h authfd.h msg.h version.h sk-api.h addr.h srclimit.h atomicio.h monitor_wrap.h
sshd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshpty.h log.h ssherr.h sshbuf.h misc.h servconf.h compat.h digest.h sshkey.h authfile.h pathnames.h canohost.h hostfile.h auth.h auth-pam.h
ssherr.o: ssherr.h
-sshkey-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
sshkey.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h ssh2.h ssherr.h misc.h sshbuf.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h match.h ssh-sk.h ssh-pkcs11.h openbsd-compat/openssl-compat.h
sshlogin.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshlogin.h ssherr.h loginrec.h log.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h
sshpty.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshpty.h log.h ssherr.h misc.h
umac128.o: umac.c includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h umac.h misc.h rijndael.h
utf8.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h utf8.h
xmalloc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h
-xmss_commons.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-xmss_fast.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-xmss_hash.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-xmss_hash_address.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-xmss_wots.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) sshd-auth$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) $(SK_STANDALONE)
-XMSS_OBJS=\
- ssh-xmss.o \
- sshkey-xmss.o \
- xmss_commons.o \
- xmss_fast.o \
- xmss_hash.o \
- xmss_hash_address.o \
- xmss_wots.o
-
LIBOPENSSH_OBJS=\
ssh_api.o \
ssherr.o \
sshbuf-misc.o \
sshbuf-getput-crypto.o \
krl.o \
- bitmap.o \
- ${XMSS_OBJS}
+ bitmap.o
LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
authfd.o authfile.o \
constraints against the session-bind@openssh.com bindings recorded for
the agent connection over which they were received.
-3. SSH_AGENT_CONSTRAIN_MAXSIGN key constraint
-
-This key constraint allows communication to an agent of the maximum
-number of signatures that may be made with an XMSS key. The format of
-the constraint is:
-
- byte SSH_AGENT_CONSTRAIN_MAXSIGN (0x03)
- uint32 max_signatures
-
-This option is only valid for XMSS keys.
-
3. associated-certs-v00@openssh.com key constraint extension
The key constraint extension allows certificates to be associated
if any key (plain private or certificate) was successfully loaded, or
SSH_AGENT_FAILURE if no key was loaded.
-$OpenBSD: PROTOCOL.agent,v 1.24 2024/11/27 13:27:34 djm Exp $
+$OpenBSD: PROTOCOL.agent,v 1.25 2025/08/29 03:50:38 djm Exp $
-/* $OpenBSD: authfd.c,v 1.135 2025/05/06 05:40:56 djm Exp $ */
+/* $OpenBSD: authfd.c,v 1.136 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
static int
encode_constraints(struct sshbuf *m, u_int life, u_int confirm,
- u_int maxsign, const char *provider,
+ const char *provider,
struct dest_constraint **dest_constraints, size_t ndest_constraints,
int cert_only, struct sshkey **certs, size_t ncerts)
{
if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_CONFIRM)) != 0)
goto out;
}
- if (maxsign != 0) {
- if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_MAXSIGN)) != 0 ||
- (r = sshbuf_put_u32(m, maxsign)) != 0)
- goto out;
- }
if (provider != NULL) {
if ((r = sshbuf_put_u8(m,
SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 ||
*/
int
ssh_add_identity_constrained(int sock, struct sshkey *key,
- const char *comment, u_int life, u_int confirm, u_int maxsign,
+ const char *comment, u_int life, u_int confirm,
const char *provider, struct dest_constraint **dest_constraints,
size_t ndest_constraints)
{
struct sshbuf *msg;
- int r, constrained = (life || confirm || maxsign ||
- provider || dest_constraints);
+ int r, constrained = (life || confirm || provider || dest_constraints);
u_char type;
if ((msg = sshbuf_new()) == NULL)
case KEY_ED25519_CERT:
case KEY_ED25519_SK:
case KEY_ED25519_SK_CERT:
- case KEY_XMSS:
- case KEY_XMSS_CERT:
type = constrained ?
SSH2_AGENTC_ADD_ID_CONSTRAINED :
SSH2_AGENTC_ADD_IDENTITY;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
- (r = sshkey_private_serialize_maxsign(key, msg, maxsign,
- 0)) != 0 ||
+ (r = sshkey_private_serialize(key, msg)) != 0 ||
(r = sshbuf_put_cstring(msg, comment)) != 0)
goto out;
break;
goto out;
}
if (constrained &&
- (r = encode_constraints(msg, life, confirm, maxsign,
- provider, dest_constraints, ndest_constraints, 0, NULL, 0)) != 0)
+ (r = encode_constraints(msg, life, confirm, provider,
+ dest_constraints, ndest_constraints, 0, NULL, 0)) != 0)
goto out;
if ((r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
(r = sshbuf_put_cstring(msg, pin)) != 0)
goto out;
if (constrained &&
- (r = encode_constraints(msg, life, confirm, 0, NULL,
+ (r = encode_constraints(msg, life, confirm, NULL,
dest_constraints, ndest_constraints,
cert_only, certs, ncerts)) != 0)
goto out;
-/* $OpenBSD: authfd.h,v 1.52 2023/12/18 14:46:56 djm Exp $ */
+/* $OpenBSD: authfd.h,v 1.53 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp);
void ssh_free_identitylist(struct ssh_identitylist *idl);
int ssh_add_identity_constrained(int sock, struct sshkey *key,
- const char *comment, u_int life, u_int confirm, u_int maxsign,
- const char *provider, struct dest_constraint **dest_constraints,
- size_t ndest_constraints);
+ const char *comment, u_int life, u_int confirm, const char *provider,
+ struct dest_constraint **dest_constraints, size_t ndest_constraints);
int ssh_agent_has_key(int sock, const struct sshkey *key);
int ssh_remove_identity(int sock, const struct sshkey *key);
int ssh_update_card(int sock, int add, const char *reader_id,
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
-#define SSH_AGENT_CONSTRAIN_MAXSIGN 3
#define SSH_AGENT_CONSTRAIN_EXTENSION 255
/* extended failure messages */
-/* $OpenBSD: authfile.c,v 1.146 2025/05/06 05:40:56 djm Exp $ */
+/* $OpenBSD: authfile.c,v 1.147 2025/08/29 03:50:38 djm Exp $ */
/*
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
*
goto out;
r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp);
- if (r == 0 && keyp && *keyp)
- r = sshkey_set_filename(*keyp, filename);
out:
close(fd);
return r;
(r = sshkey_parse_pubkey_from_private_fileblob_type(buffer,
KEY_UNSPEC, &pubkey)) != 0)
goto out;
- if ((r = sshkey_set_filename(pubkey, filename)) != 0)
- goto out;
/* success */
if (pubkeyp != NULL) {
*pubkeyp = pubkey;
case KEY_ECDSA:
#endif /* WITH_OPENSSL */
case KEY_ED25519:
- case KEY_XMSS:
case KEY_UNSPEC:
break;
default:
-/* $OpenBSD: dns.c,v 1.45 2025/05/06 05:40:56 djm Exp $ */
+/* $OpenBSD: dns.c,v 1.46 2025/08/29 03:50:38 djm Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
case KEY_ED25519:
*algorithm = SSHFP_KEY_ED25519;
break;
- case KEY_XMSS:
- *algorithm = SSHFP_KEY_XMSS;
- break;
default:
*algorithm = SSHFP_KEY_RESERVED; /* 0 */
}
-/* $OpenBSD: dns.h,v 1.20 2023/02/10 04:56:30 djm Exp $ */
+/* $OpenBSD: dns.h,v 1.21 2025/08/29 03:50:38 djm Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
SSHFP_KEY_RSA = 1,
SSHFP_KEY_DSA = 2,
SSHFP_KEY_ECDSA = 3,
- SSHFP_KEY_ED25519 = 4,
- SSHFP_KEY_XMSS = 5
+ SSHFP_KEY_ED25519 = 4
};
enum sshfp_hashes {
-/* $OpenBSD: pathnames.h,v 1.35 2025/05/06 05:40:56 djm Exp $ */
+/* $OpenBSD: pathnames.h,v 1.36 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
#define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config"
#define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key"
#define _PATH_HOST_ED25519_KEY_FILE SSHDIR "/ssh_host_ed25519_key"
-#define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key"
#define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key"
#define _PATH_DH_MODULI SSHDIR "/moduli"
#define _PATH_SSH_CLIENT_ID_ECDSA _PATH_SSH_USER_DIR "/id_ecdsa"
#define _PATH_SSH_CLIENT_ID_RSA _PATH_SSH_USER_DIR "/id_rsa"
#define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519"
-#define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss"
#define _PATH_SSH_CLIENT_ID_ECDSA_SK _PATH_SSH_USER_DIR "/id_ecdsa_sk"
#define _PATH_SSH_CLIENT_ID_ED25519_SK _PATH_SSH_USER_DIR "/id_ed25519_sk"
-/* $OpenBSD: readconf.c,v 1.405 2025/08/11 10:55:38 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.406 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
_PATH_SSH_CLIENT_ID_ED25519, 0);
add_identity_file(options, "~/",
_PATH_SSH_CLIENT_ID_ED25519_SK, 0);
- add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
}
if (options->escape_char == -1)
options->escape_char = '~';
-/* $OpenBSD: servconf.c,v 1.430 2025/08/05 09:08:16 job Exp $ */
+/* $OpenBSD: servconf.c,v 1.431 2025/08/29 03:50:38 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
#endif
servconf_add_hostkey("[default]", 0, options,
_PATH_HOST_ED25519_KEY_FILE, 0);
-#ifdef WITH_XMSS
- servconf_add_hostkey("[default]", 0, options,
- _PATH_HOST_XMSS_KEY_FILE, 0);
-#endif /* WITH_XMSS */
}
/* No certificates by default */
if (options->num_ports == 0)
-/* $OpenBSD: ssh-add.c,v 1.174 2025/05/06 05:40:56 djm Exp $ */
+/* $OpenBSD: ssh-add.c,v 1.175 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
#endif /* WITH_OPENSSL */
_PATH_SSH_CLIENT_ID_ED25519,
_PATH_SSH_CLIENT_ID_ED25519_SK,
- _PATH_SSH_CLIENT_ID_XMSS,
NULL
};
/* User has to confirm key use */
static int confirm = 0;
-/* Maximum number of signatures (XMSS) */
-static u_int maxsign = 0;
-static u_int minleft = 0;
-
/* we keep a cache of one passphrase */
static char *pass = NULL;
static void
char *comment = NULL;
char msg[1024], *certpath = NULL;
int r, fd, ret = -1;
- size_t i;
- u_int32_t left;
struct sshbuf *keyblob;
- struct ssh_identitylist *idlist;
if (strcmp(filename, "-") == 0) {
fd = STDIN_FILENO;
comment = xstrdup(filename);
sshbuf_free(keyblob);
- /* For XMSS */
- if ((r = sshkey_set_filename(private, filename)) != 0) {
- fprintf(stderr, "Could not add filename to private key: %s (%s)\n",
- filename, comment);
- goto out;
- }
- if (maxsign && minleft &&
- (r = ssh_fetch_identitylist(agent_fd, &idlist)) == 0) {
- for (i = 0; i < idlist->nkeys; i++) {
- if (!sshkey_equal_public(idlist->keys[i], private))
- continue;
- left = sshkey_signatures_left(idlist->keys[i]);
- if (left < minleft) {
- fprintf(stderr,
- "Only %d signatures left.\n", left);
- break;
- }
- fprintf(stderr, "Skipping update: ");
- if (left == minleft) {
- fprintf(stderr,
- "required signatures left (%d).\n", left);
- } else {
- fprintf(stderr,
- "more signatures left (%d) than"
- " required (%d).\n", left, minleft);
- }
- ssh_free_identitylist(idlist);
- goto out;
- }
- ssh_free_identitylist(idlist);
- }
-
if (sshkey_is_sk(private)) {
if (skprovider == NULL) {
fprintf(stderr, "Cannot load FIDO key %s "
if (!cert_only &&
(r = ssh_add_identity_constrained(agent_fd, private, comment,
- lifetime, confirm, maxsign, skprovider,
+ lifetime, confirm, skprovider,
dest_constraints, ndest_constraints)) == 0) {
ret = 0;
if (!qflag) {
sshkey_free(cert);
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
- lifetime, confirm, maxsign, skprovider,
+ lifetime, confirm, skprovider,
dest_constraints, ndest_constraints)) != 0) {
error_r(r, "Certificate %s (%s) add failed", certpath,
private->cert->key_id);
char *fp;
int r;
struct ssh_identitylist *idlist;
- u_int32_t left;
size_t i;
if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
ssh_err(r));
continue;
}
- fprintf(stdout, " %s", idlist->comments[i]);
- left = sshkey_signatures_left(idlist->keys[i]);
- if (left > 0)
- fprintf(stdout,
- " [signatures left %d]", left);
- fprintf(stdout, "\n");
+ fprintf(stdout, " %s\n", idlist->comments[i]);
}
}
ssh_free_identitylist(idlist);
fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal_f("sshkey_fingerprint failed");
if ((r = ssh_add_identity_constrained(agent_fd, key, "",
- lifetime, confirm, maxsign, skprovider,
+ lifetime, confirm, skprovider,
dest_constraints, ndest_constraints)) != 0) {
error("Unable to add key %s %s",
sshkey_type(key), fp);
fprintf(stderr,
"usage: ssh-add [-CcDdKkLlqvXx] [-E fingerprint_hash] [-H hostkey_file]\n"
" [-h destination_constraint] [-S provider] [-t life]\n"
-#ifdef WITH_XMSS
-" [-M maxsign] [-m minleft]\n"
-#endif
" [file ...]\n"
" ssh-add -s pkcs11 [-Cv] [certificate ...]\n"
" ssh-add -e pkcs11\n"
confirm = 1;
break;
case 'm':
- minleft = (u_int)strtonum(optarg, 1, UINT_MAX, NULL);
- if (minleft == 0) {
- usage();
- ret = 1;
- goto done;
- }
- break;
case 'M':
- maxsign = (u_int)strtonum(optarg, 1, UINT_MAX, NULL);
- if (maxsign == 0) {
- usage();
- ret = 1;
- goto done;
- }
+ /* deprecated */
break;
case 'd':
deleting = 1;
-/* $OpenBSD: ssh-agent.c,v 1.312 2025/05/05 02:48:06 djm Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.313 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
/* identity not visible, don't include in response */
if (identity_permitted(id, e, NULL, NULL, NULL) != 0)
continue;
- if ((r = sshkey_puts_opts(id->key, keys,
- SSHKEY_SERIALIZE_INFO)) != 0 ||
+ if ((r = sshkey_puts(id->key, keys)) != 0 ||
(r = sshbuf_put_cstring(keys, id->comment)) != 0) {
error_fr(r, "compose key/comment");
continue;
{
u_char ctype;
int r;
- u_int seconds, maxsign = 0;
+ u_int seconds;
while (sshbuf_len(m)) {
if ((r = sshbuf_get_u8(m, &ctype)) != 0) {
}
*confirmp = 1;
break;
- case SSH_AGENT_CONSTRAIN_MAXSIGN:
- if (k == NULL) {
- error_f("maxsign not valid here");
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if (maxsign != 0) {
- error_f("maxsign already set");
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if ((r = sshbuf_get_u32(m, &maxsign)) != 0) {
- error_fr(r, "parse maxsign constraint");
- goto out;
- }
- if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) {
- error_fr(r, "enable maxsign");
- goto out;
- }
- break;
case SSH_AGENT_CONSTRAIN_EXTENSION:
if ((r = parse_key_constraint_extension(m,
sk_providerp, dcsp, ndcsp,
-/* $OpenBSD: ssh-keygen.c,v 1.481 2025/05/24 03:37:40 dtucker Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.482 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
case KEY_ED25519_SK_CERT:
name = _PATH_SSH_CLIENT_ID_ED25519_SK;
break;
- case KEY_XMSS:
- case KEY_XMSS_CERT:
- name = _PATH_SSH_CLIENT_ID_XMSS;
- break;
default:
fatal("bad key type");
}
#endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
{ "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE },
-#ifdef WITH_XMSS
- { "xmss", "XMSS",_PATH_HOST_XMSS_KEY_FILE },
-#endif /* WITH_XMSS */
{ NULL, NULL, NULL }
};
}
}
- if (private->type != KEY_ED25519 && private->type != KEY_XMSS &&
+ if (private->type != KEY_ED25519 &&
private_key_format != SSHKEY_PRIVATE_OPENSSH) {
error("Comments are only supported for keys stored in "
"the new format (-o).");
n += do_print_resource_record(pw,
_PATH_HOST_ED25519_KEY_FILE, rr_hostname,
print_generic, opts, nopts);
- n += do_print_resource_record(pw,
- _PATH_HOST_XMSS_KEY_FILE, rr_hostname,
- print_generic, opts, nopts);
if (n == 0)
fatal("no keys found.");
exit(0);
-/* $OpenBSD: ssh-keyscan.c,v 1.166 2025/05/06 05:40:56 djm Exp $ */
+/* $OpenBSD: ssh-keyscan.c,v 1.167 2025/08/29 03:50:38 djm Exp $ */
/*
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
#define KT_RSA (1)
#define KT_ECDSA (1<<1)
#define KT_ED25519 (1<<2)
-#define KT_XMSS (1<<3)
#define KT_ECDSA_SK (1<<4)
#define KT_ED25519_SK (1<<5)
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
"ssh-ed25519-cert-v01@openssh.com" : "ssh-ed25519";
break;
- case KT_XMSS:
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
- "ssh-xmss-cert-v01@openssh.com" : "ssh-xmss@openssh.com";
- break;
case KT_ECDSA:
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
"ecdsa-sha2-nistp256-cert-v01@openssh.com,"
case KEY_ED25519:
get_keytypes |= KT_ED25519;
break;
- case KEY_XMSS:
- get_keytypes |= KT_XMSS;
- break;
case KEY_ED25519_SK:
get_keytypes |= KT_ED25519_SK;
break;
-/* $OpenBSD: ssh-keysign.c,v 1.76 2025/05/06 05:40:56 djm Exp $ */
+/* $OpenBSD: ssh-keysign.c,v 1.77 2025/08/29 03:50:38 djm Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
/* XXX This really needs to read sshd_config for the paths */
key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_ED25519_KEY_FILE, O_RDONLY);
- key_fd[i++] = open(_PATH_HOST_XMSS_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
if ((pw = getpwuid(getuid())) == NULL)
+++ /dev/null
-/* $OpenBSD: ssh-xmss.c,v 1.14 2022/10/28 00:44:44 djm Exp $*/
-/*
- * Copyright (c) 2017 Stefan-Lukas Gazdag.
- * Copyright (c) 2017 Markus Friedl.
- *
- * 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.
- */
-#include "includes.h"
-#ifdef WITH_XMSS
-
-#define SSHKEY_INTERNAL
-#include <sys/types.h>
-#include <limits.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#include <unistd.h>
-
-#include "log.h"
-#include "sshbuf.h"
-#include "sshkey.h"
-#include "sshkey-xmss.h"
-#include "ssherr.h"
-#include "ssh.h"
-
-#include "xmss_fast.h"
-
-static void
-ssh_xmss_cleanup(struct sshkey *k)
-{
- freezero(k->xmss_pk, sshkey_xmss_pklen(k));
- freezero(k->xmss_sk, sshkey_xmss_sklen(k));
- sshkey_xmss_free_state(k);
- free(k->xmss_name);
- free(k->xmss_filename);
- k->xmss_pk = NULL;
- k->xmss_sk = NULL;
- k->xmss_name = NULL;
- k->xmss_filename = NULL;
-}
-
-static int
-ssh_xmss_equal(const struct sshkey *a, const struct sshkey *b)
-{
- if (a->xmss_pk == NULL || b->xmss_pk == NULL)
- return 0;
- if (sshkey_xmss_pklen(a) != sshkey_xmss_pklen(b))
- return 0;
- if (memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) != 0)
- return 0;
- return 1;
-}
-
-static int
-ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b,
- enum sshkey_serialize_rep opts)
-{
- int r;
-
- if (key->xmss_name == NULL || key->xmss_pk == NULL ||
- sshkey_xmss_pklen(key) == 0)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
- (r = sshbuf_put_string(b, key->xmss_pk,
- sshkey_xmss_pklen(key))) != 0 ||
- (r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
- return r;
-
- return 0;
-}
-
-static int
-ssh_xmss_serialize_private(const struct sshkey *key, struct sshbuf *b,
- enum sshkey_serialize_rep opts)
-{
- int r;
-
- if (key->xmss_name == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- /* Note: can't reuse ssh_xmss_serialize_public because of sk order */
- if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
- (r = sshbuf_put_string(b, key->xmss_pk,
- sshkey_xmss_pklen(key))) != 0 ||
- (r = sshbuf_put_string(b, key->xmss_sk,
- sshkey_xmss_sklen(key))) != 0 ||
- (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
- return r;
-
- return 0;
-}
-
-static int
-ssh_xmss_copy_public(const struct sshkey *from, struct sshkey *to)
-{
- int r = SSH_ERR_INTERNAL_ERROR;
- u_int32_t left;
- size_t pklen;
-
- if ((r = sshkey_xmss_init(to, from->xmss_name)) != 0)
- return r;
- if (from->xmss_pk == NULL)
- return 0; /* XXX SSH_ERR_INTERNAL_ERROR ? */
-
- if ((pklen = sshkey_xmss_pklen(from)) == 0 ||
- sshkey_xmss_pklen(to) != pklen)
- return SSH_ERR_INTERNAL_ERROR;
- if ((to->xmss_pk = malloc(pklen)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- memcpy(to->xmss_pk, from->xmss_pk, pklen);
- /* simulate number of signatures left on pubkey */
- left = sshkey_xmss_signatures_left(from);
- if (left)
- sshkey_xmss_enable_maxsign(to, left);
- return 0;
-}
-
-static int
-ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b,
- struct sshkey *key)
-{
- size_t len = 0;
- char *xmss_name = NULL;
- u_char *pk = NULL;
- int ret = SSH_ERR_INTERNAL_ERROR;
-
- if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
- goto out;
- if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
- goto out;
- if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
- goto out;
- if (len == 0 || len != sshkey_xmss_pklen(key)) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- key->xmss_pk = pk;
- pk = NULL;
- if (!sshkey_is_cert(key) &&
- (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
- goto out;
- /* success */
- ret = 0;
- out:
- free(xmss_name);
- freezero(pk, len);
- return ret;
-}
-
-static int
-ssh_xmss_deserialize_private(const char *ktype, struct sshbuf *b,
- struct sshkey *key)
-{
- int r;
- char *xmss_name = NULL;
- size_t pklen = 0, sklen = 0;
- u_char *xmss_pk = NULL, *xmss_sk = NULL;
-
- /* Note: can't reuse ssh_xmss_deserialize_public because of sk order */
- if ((r = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0 ||
- (r = sshbuf_get_string(b, &xmss_pk, &pklen)) != 0 ||
- (r = sshbuf_get_string(b, &xmss_sk, &sklen)) != 0)
- goto out;
- if (!sshkey_is_cert(key) &&
- (r = sshkey_xmss_init(key, xmss_name)) != 0)
- goto out;
- if (pklen != sshkey_xmss_pklen(key) ||
- sklen != sshkey_xmss_sklen(key)) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- key->xmss_pk = xmss_pk;
- key->xmss_sk = xmss_sk;
- xmss_pk = xmss_sk = NULL;
- /* optional internal state */
- if ((r = sshkey_xmss_deserialize_state_opt(key, b)) != 0)
- goto out;
- /* success */
- r = 0;
- out:
- free(xmss_name);
- freezero(xmss_pk, pklen);
- freezero(xmss_sk, sklen);
- return r;
-}
-
-static int
-ssh_xmss_sign(struct sshkey *key,
- u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen,
- const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
-{
- u_char *sig = NULL;
- size_t slen = 0, len = 0, required_siglen;
- unsigned long long smlen;
- int r, ret;
- struct sshbuf *b = NULL;
-
- if (lenp != NULL)
- *lenp = 0;
- if (sigp != NULL)
- *sigp = NULL;
-
- if (key == NULL ||
- sshkey_type_plain(key->type) != KEY_XMSS ||
- key->xmss_sk == NULL ||
- sshkey_xmss_params(key) == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0)
- return r;
- if (datalen >= INT_MAX - required_siglen)
- return SSH_ERR_INVALID_ARGUMENT;
- smlen = slen = datalen + required_siglen;
- if ((sig = malloc(slen)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshkey_xmss_get_state(key, 1)) != 0)
- goto out;
- if ((ret = xmss_sign(key->xmss_sk, sshkey_xmss_bds_state(key), sig, &smlen,
- data, datalen, sshkey_xmss_params(key))) != 0 || smlen <= datalen) {
- r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */
- goto out;
- }
- /* encode signature */
- if ((b = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshbuf_put_cstring(b, "ssh-xmss@openssh.com")) != 0 ||
- (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0)
- goto out;
- len = sshbuf_len(b);
- if (sigp != NULL) {
- if ((*sigp = malloc(len)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(*sigp, sshbuf_ptr(b), len);
- }
- if (lenp != NULL)
- *lenp = len;
- /* success */
- r = 0;
- out:
- if ((ret = sshkey_xmss_update_state(key, 1)) != 0) {
- /* discard signature since we cannot update the state */
- if (r == 0 && sigp != NULL && *sigp != NULL) {
- explicit_bzero(*sigp, len);
- free(*sigp);
- }
- if (sigp != NULL)
- *sigp = NULL;
- if (lenp != NULL)
- *lenp = 0;
- r = ret;
- }
- sshbuf_free(b);
- if (sig != NULL)
- freezero(sig, slen);
-
- return r;
-}
-
-static int
-ssh_xmss_verify(const struct sshkey *key,
- const u_char *sig, size_t siglen,
- const u_char *data, size_t dlen, const char *alg, u_int compat,
- struct sshkey_sig_details **detailsp)
-{
- struct sshbuf *b = NULL;
- char *ktype = NULL;
- const u_char *sigblob;
- u_char *sm = NULL, *m = NULL;
- size_t len, required_siglen;
- unsigned long long smlen = 0, mlen = 0;
- int r, ret;
-
- if (key == NULL ||
- sshkey_type_plain(key->type) != KEY_XMSS ||
- key->xmss_pk == NULL ||
- sshkey_xmss_params(key) == NULL ||
- sig == NULL || siglen == 0)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0)
- return r;
- if (dlen >= INT_MAX - required_siglen)
- return SSH_ERR_INVALID_ARGUMENT;
-
- if ((b = sshbuf_from(sig, siglen)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 ||
- (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0)
- goto out;
- if (strcmp("ssh-xmss@openssh.com", ktype) != 0) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (sshbuf_len(b) != 0) {
- r = SSH_ERR_UNEXPECTED_TRAILING_DATA;
- goto out;
- }
- if (len != required_siglen) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if (dlen >= SIZE_MAX - len) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- smlen = len + dlen;
- mlen = smlen;
- if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(sm, sigblob, len);
- memcpy(sm+len, data, dlen);
- if ((ret = xmss_sign_open(m, &mlen, sm, smlen,
- key->xmss_pk, sshkey_xmss_params(key))) != 0) {
- debug2_f("xmss_sign_open failed: %d", ret);
- }
- if (ret != 0 || mlen != dlen) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
- /* XXX compare 'm' and 'data' ? */
- /* success */
- r = 0;
- out:
- if (sm != NULL)
- freezero(sm, smlen);
- if (m != NULL)
- freezero(m, smlen);
- sshbuf_free(b);
- free(ktype);
- return r;
-}
-
-static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
- /* .size = */ NULL,
- /* .alloc = */ NULL,
- /* .cleanup = */ ssh_xmss_cleanup,
- /* .equal = */ ssh_xmss_equal,
- /* .ssh_serialize_public = */ ssh_xmss_serialize_public,
- /* .ssh_deserialize_public = */ ssh_xmss_deserialize_public,
- /* .ssh_serialize_private = */ ssh_xmss_serialize_private,
- /* .ssh_deserialize_private = */ ssh_xmss_deserialize_private,
- /* .generate = */ sshkey_xmss_generate_private_key,
- /* .copy_public = */ ssh_xmss_copy_public,
- /* .sign = */ ssh_xmss_sign,
- /* .verify = */ ssh_xmss_verify,
-};
-
-const struct sshkey_impl sshkey_xmss_impl = {
- /* .name = */ "ssh-xmss@openssh.com",
- /* .shortname = */ "XMSS",
- /* .sigalg = */ NULL,
- /* .type = */ KEY_XMSS,
- /* .nid = */ 0,
- /* .cert = */ 0,
- /* .sigonly = */ 0,
- /* .keybits = */ 256,
- /* .funcs = */ &sshkey_xmss_funcs,
-};
-
-const struct sshkey_impl sshkey_xmss_cert_impl = {
- /* .name = */ "ssh-xmss-cert-v01@openssh.com",
- /* .shortname = */ "XMSS-CERT",
- /* .sigalg = */ NULL,
- /* .type = */ KEY_XMSS_CERT,
- /* .nid = */ 0,
- /* .cert = */ 1,
- /* .sigonly = */ 0,
- /* .keybits = */ 256,
- /* .funcs = */ &sshkey_xmss_funcs,
-};
-#endif /* WITH_XMSS */
-/* $OpenBSD: ssh.c,v 1.615 2025/08/18 03:43:01 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.616 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
L_PUBKEY(_PATH_HOST_ECDSA_KEY_FILE, 4);
L_PUBKEY(_PATH_HOST_ED25519_KEY_FILE, 5);
L_PUBKEY(_PATH_HOST_RSA_KEY_FILE, 6);
- L_CERT(_PATH_HOST_XMSS_KEY_FILE, 8);
- L_PUBKEY(_PATH_HOST_XMSS_KEY_FILE, 9);
if (loaded == 0)
debug("HostbasedAuthentication enabled but no "
"local public host keys could be loaded.");
-/* $OpenBSD: sshconnect.c,v 1.373 2025/08/12 11:09:48 sthen Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.374 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
KEY_RSA,
KEY_ECDSA,
KEY_ED25519,
- KEY_XMSS,
-1
};
int i, ret = 0;
if ((r = ssh_add_identity_constrained(auth_sock, private,
comment == NULL ? authfile : comment,
options.add_keys_to_agent_lifespan,
- (options.add_keys_to_agent == 3), 0, skprovider, NULL, 0)) == 0)
+ (options.add_keys_to_agent == 3), skprovider, NULL, 0)) == 0)
debug("identity added to agent: %s", authfile);
else
debug("could not add identity to agent: %s (%d)", authfile, r);
-/* $OpenBSD: sshd-auth.c,v 1.7 2025/08/18 04:38:21 djm Exp $ */
+/* $OpenBSD: sshd-auth.c,v 1.8 2025/08/29 03:50:38 djm Exp $ */
/*
* SSH2 implementation:
* Privilege Separation:
case KEY_ED25519:
case KEY_ECDSA_SK:
case KEY_ED25519_SK:
- case KEY_XMSS:
append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
case KEY_ED25519_CERT:
case KEY_ECDSA_SK_CERT:
case KEY_ED25519_SK_CERT:
- case KEY_XMSS_CERT:
append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
case KEY_ED25519_CERT:
case KEY_ECDSA_SK_CERT:
case KEY_ED25519_SK_CERT:
- case KEY_XMSS_CERT:
key = host_certificates[i];
break;
default:
-/* $OpenBSD: sshd-session.c,v 1.14 2025/08/18 03:43:01 djm Exp $ */
+/* $OpenBSD: sshd-session.c,v 1.15 2025/08/29 03:50:38 djm Exp $ */
/*
* SSH2 implementation:
* Privilege Separation:
case KEY_ED25519_CERT:
case KEY_ECDSA_SK_CERT:
case KEY_ED25519_SK_CERT:
- case KEY_XMSS_CERT:
key = sensitive_data.host_certificates[i];
break;
default:
-/* $OpenBSD: sshd.c,v 1.621 2025/07/04 09:51:01 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.622 2025/08/29 03:50:38 djm Exp $ */
/*
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
* Copyright (c) 2002 Niels Provos. All rights reserved.
case KEY_ED25519:
case KEY_ECDSA_SK:
case KEY_ED25519_SK:
- case KEY_XMSS:
if (have_agent || key != NULL)
sensitive_data.have_ssh2_key = 1;
break;
+++ /dev/null
-/* $OpenBSD: sshkey-xmss.c,v 1.12 2022/10/28 00:39:29 djm Exp $ */
-/*
- * Copyright (c) 2017 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-#ifdef WITH_XMSS
-
-#include <sys/types.h>
-#include <sys/uio.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#ifdef HAVE_SYS_FILE_H
-# include <sys/file.h>
-#endif
-
-#include "ssh2.h"
-#include "ssherr.h"
-#include "sshbuf.h"
-#include "cipher.h"
-#include "sshkey.h"
-#include "sshkey-xmss.h"
-#include "atomicio.h"
-#include "log.h"
-
-#include "xmss_fast.h"
-
-/* opaque internal XMSS state */
-#define XMSS_MAGIC "xmss-state-v1"
-#define XMSS_CIPHERNAME "aes256-gcm@openssh.com"
-struct ssh_xmss_state {
- xmss_params params;
- u_int32_t n, w, h, k;
-
- bds_state bds;
- u_char *stack;
- u_int32_t stackoffset;
- u_char *stacklevels;
- u_char *auth;
- u_char *keep;
- u_char *th_nodes;
- u_char *retain;
- treehash_inst *treehash;
-
- u_int32_t idx; /* state read from file */
- u_int32_t maxidx; /* restricted # of signatures */
- int have_state; /* .state file exists */
- int lockfd; /* locked in sshkey_xmss_get_state() */
- u_char allow_update; /* allow sshkey_xmss_update_state() */
- char *enc_ciphername;/* encrypt state with cipher */
- u_char *enc_keyiv; /* encrypt state with key */
- u_int32_t enc_keyiv_len; /* length of enc_keyiv */
-};
-
-int sshkey_xmss_init_bds_state(struct sshkey *);
-int sshkey_xmss_init_enc_key(struct sshkey *, const char *);
-void sshkey_xmss_free_bds(struct sshkey *);
-int sshkey_xmss_get_state_from_file(struct sshkey *, const char *,
- int *, int);
-int sshkey_xmss_encrypt_state(const struct sshkey *, struct sshbuf *,
- struct sshbuf **);
-int sshkey_xmss_decrypt_state(const struct sshkey *, struct sshbuf *,
- struct sshbuf **);
-int sshkey_xmss_serialize_enc_key(const struct sshkey *, struct sshbuf *);
-int sshkey_xmss_deserialize_enc_key(struct sshkey *, struct sshbuf *);
-
-#define PRINT(...) do { if (printerror) sshlog(__FILE__, __func__, __LINE__, \
- 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__); } while (0)
-
-int
-sshkey_xmss_init(struct sshkey *key, const char *name)
-{
- struct ssh_xmss_state *state;
-
- if (key->xmss_state != NULL)
- return SSH_ERR_INVALID_FORMAT;
- if (name == NULL)
- return SSH_ERR_INVALID_FORMAT;
- state = calloc(sizeof(struct ssh_xmss_state), 1);
- if (state == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if (strcmp(name, XMSS_SHA2_256_W16_H10_NAME) == 0) {
- state->n = 32;
- state->w = 16;
- state->h = 10;
- } else if (strcmp(name, XMSS_SHA2_256_W16_H16_NAME) == 0) {
- state->n = 32;
- state->w = 16;
- state->h = 16;
- } else if (strcmp(name, XMSS_SHA2_256_W16_H20_NAME) == 0) {
- state->n = 32;
- state->w = 16;
- state->h = 20;
- } else {
- free(state);
- return SSH_ERR_KEY_TYPE_UNKNOWN;
- }
- if ((key->xmss_name = strdup(name)) == NULL) {
- free(state);
- return SSH_ERR_ALLOC_FAIL;
- }
- state->k = 2; /* XXX hardcoded */
- state->lockfd = -1;
- if (xmss_set_params(&state->params, state->n, state->h, state->w,
- state->k) != 0) {
- free(state);
- return SSH_ERR_INVALID_FORMAT;
- }
- key->xmss_state = state;
- return 0;
-}
-
-void
-sshkey_xmss_free_state(struct sshkey *key)
-{
- struct ssh_xmss_state *state = key->xmss_state;
-
- sshkey_xmss_free_bds(key);
- if (state) {
- if (state->enc_keyiv) {
- explicit_bzero(state->enc_keyiv, state->enc_keyiv_len);
- free(state->enc_keyiv);
- }
- free(state->enc_ciphername);
- free(state);
- }
- key->xmss_state = NULL;
-}
-
-#define SSH_XMSS_K2_MAGIC "k=2"
-#define num_stack(x) ((x->h+1)*(x->n))
-#define num_stacklevels(x) (x->h+1)
-#define num_auth(x) ((x->h)*(x->n))
-#define num_keep(x) ((x->h >> 1)*(x->n))
-#define num_th_nodes(x) ((x->h - x->k)*(x->n))
-#define num_retain(x) (((1ULL << x->k) - x->k - 1) * (x->n))
-#define num_treehash(x) ((x->h) - (x->k))
-
-int
-sshkey_xmss_init_bds_state(struct sshkey *key)
-{
- struct ssh_xmss_state *state = key->xmss_state;
- u_int32_t i;
-
- state->stackoffset = 0;
- if ((state->stack = calloc(num_stack(state), 1)) == NULL ||
- (state->stacklevels = calloc(num_stacklevels(state), 1))== NULL ||
- (state->auth = calloc(num_auth(state), 1)) == NULL ||
- (state->keep = calloc(num_keep(state), 1)) == NULL ||
- (state->th_nodes = calloc(num_th_nodes(state), 1)) == NULL ||
- (state->retain = calloc(num_retain(state), 1)) == NULL ||
- (state->treehash = calloc(num_treehash(state),
- sizeof(treehash_inst))) == NULL) {
- sshkey_xmss_free_bds(key);
- return SSH_ERR_ALLOC_FAIL;
- }
- for (i = 0; i < state->h - state->k; i++)
- state->treehash[i].node = &state->th_nodes[state->n*i];
- xmss_set_bds_state(&state->bds, state->stack, state->stackoffset,
- state->stacklevels, state->auth, state->keep, state->treehash,
- state->retain, 0);
- return 0;
-}
-
-void
-sshkey_xmss_free_bds(struct sshkey *key)
-{
- struct ssh_xmss_state *state = key->xmss_state;
-
- if (state == NULL)
- return;
- free(state->stack);
- free(state->stacklevels);
- free(state->auth);
- free(state->keep);
- free(state->th_nodes);
- free(state->retain);
- free(state->treehash);
- state->stack = NULL;
- state->stacklevels = NULL;
- state->auth = NULL;
- state->keep = NULL;
- state->th_nodes = NULL;
- state->retain = NULL;
- state->treehash = NULL;
-}
-
-void *
-sshkey_xmss_params(const struct sshkey *key)
-{
- struct ssh_xmss_state *state = key->xmss_state;
-
- if (state == NULL)
- return NULL;
- return &state->params;
-}
-
-void *
-sshkey_xmss_bds_state(const struct sshkey *key)
-{
- struct ssh_xmss_state *state = key->xmss_state;
-
- if (state == NULL)
- return NULL;
- return &state->bds;
-}
-
-int
-sshkey_xmss_siglen(const struct sshkey *key, size_t *lenp)
-{
- struct ssh_xmss_state *state = key->xmss_state;
-
- if (lenp == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if (state == NULL)
- return SSH_ERR_INVALID_FORMAT;
- *lenp = 4 + state->n +
- state->params.wots_par.keysize +
- state->h * state->n;
- return 0;
-}
-
-size_t
-sshkey_xmss_pklen(const struct sshkey *key)
-{
- struct ssh_xmss_state *state = key->xmss_state;
-
- if (state == NULL)
- return 0;
- return state->n * 2;
-}
-
-size_t
-sshkey_xmss_sklen(const struct sshkey *key)
-{
- struct ssh_xmss_state *state = key->xmss_state;
-
- if (state == NULL)
- return 0;
- return state->n * 4 + 4;
-}
-
-int
-sshkey_xmss_init_enc_key(struct sshkey *k, const char *ciphername)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- const struct sshcipher *cipher;
- size_t keylen = 0, ivlen = 0;
-
- if (state == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((cipher = cipher_by_name(ciphername)) == NULL)
- return SSH_ERR_INTERNAL_ERROR;
- if ((state->enc_ciphername = strdup(ciphername)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- keylen = cipher_keylen(cipher);
- ivlen = cipher_ivlen(cipher);
- state->enc_keyiv_len = keylen + ivlen;
- if ((state->enc_keyiv = calloc(state->enc_keyiv_len, 1)) == NULL) {
- free(state->enc_ciphername);
- state->enc_ciphername = NULL;
- return SSH_ERR_ALLOC_FAIL;
- }
- arc4random_buf(state->enc_keyiv, state->enc_keyiv_len);
- return 0;
-}
-
-int
-sshkey_xmss_serialize_enc_key(const struct sshkey *k, struct sshbuf *b)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- int r;
-
- if (state == NULL || state->enc_keyiv == NULL ||
- state->enc_ciphername == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshbuf_put_cstring(b, state->enc_ciphername)) != 0 ||
- (r = sshbuf_put_string(b, state->enc_keyiv,
- state->enc_keyiv_len)) != 0)
- return r;
- return 0;
-}
-
-int
-sshkey_xmss_deserialize_enc_key(struct sshkey *k, struct sshbuf *b)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- size_t len;
- int r;
-
- if (state == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshbuf_get_cstring(b, &state->enc_ciphername, NULL)) != 0 ||
- (r = sshbuf_get_string(b, &state->enc_keyiv, &len)) != 0)
- return r;
- state->enc_keyiv_len = len;
- return 0;
-}
-
-int
-sshkey_xmss_serialize_pk_info(const struct sshkey *k, struct sshbuf *b,
- enum sshkey_serialize_rep opts)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- u_char have_info = 1;
- u_int32_t idx;
- int r;
-
- if (state == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if (opts != SSHKEY_SERIALIZE_INFO)
- return 0;
- idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx;
- if ((r = sshbuf_put_u8(b, have_info)) != 0 ||
- (r = sshbuf_put_u32(b, idx)) != 0 ||
- (r = sshbuf_put_u32(b, state->maxidx)) != 0)
- return r;
- return 0;
-}
-
-int
-sshkey_xmss_deserialize_pk_info(struct sshkey *k, struct sshbuf *b)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- u_char have_info;
- int r;
-
- if (state == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- /* optional */
- if (sshbuf_len(b) == 0)
- return 0;
- if ((r = sshbuf_get_u8(b, &have_info)) != 0)
- return r;
- if (have_info != 1)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshbuf_get_u32(b, &state->idx)) != 0 ||
- (r = sshbuf_get_u32(b, &state->maxidx)) != 0)
- return r;
- return 0;
-}
-
-int
-sshkey_xmss_generate_private_key(struct sshkey *k, int bits)
-{
- int r;
- const char *name;
-
- if (bits == 10) {
- name = XMSS_SHA2_256_W16_H10_NAME;
- } else if (bits == 16) {
- name = XMSS_SHA2_256_W16_H16_NAME;
- } else if (bits == 20) {
- name = XMSS_SHA2_256_W16_H20_NAME;
- } else {
- name = XMSS_DEFAULT_NAME;
- }
- if ((r = sshkey_xmss_init(k, name)) != 0 ||
- (r = sshkey_xmss_init_bds_state(k)) != 0 ||
- (r = sshkey_xmss_init_enc_key(k, XMSS_CIPHERNAME)) != 0)
- return r;
- if ((k->xmss_pk = malloc(sshkey_xmss_pklen(k))) == NULL ||
- (k->xmss_sk = malloc(sshkey_xmss_sklen(k))) == NULL) {
- return SSH_ERR_ALLOC_FAIL;
- }
- xmss_keypair(k->xmss_pk, k->xmss_sk, sshkey_xmss_bds_state(k),
- sshkey_xmss_params(k));
- return 0;
-}
-
-int
-sshkey_xmss_get_state_from_file(struct sshkey *k, const char *filename,
- int *have_file, int printerror)
-{
- struct sshbuf *b = NULL, *enc = NULL;
- int ret = SSH_ERR_SYSTEM_ERROR, r, fd = -1;
- u_int32_t len;
- unsigned char buf[4], *data = NULL;
-
- *have_file = 0;
- if ((fd = open(filename, O_RDONLY)) >= 0) {
- *have_file = 1;
- if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) {
- PRINT("corrupt state file: %s", filename);
- goto done;
- }
- len = PEEK_U32(buf);
- if ((data = calloc(len, 1)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto done;
- }
- if (atomicio(read, fd, data, len) != len) {
- PRINT("cannot read blob: %s", filename);
- goto done;
- }
- if ((enc = sshbuf_from(data, len)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto done;
- }
- sshkey_xmss_free_bds(k);
- if ((r = sshkey_xmss_decrypt_state(k, enc, &b)) != 0) {
- ret = r;
- goto done;
- }
- if ((r = sshkey_xmss_deserialize_state(k, b)) != 0) {
- ret = r;
- goto done;
- }
- ret = 0;
- }
-done:
- if (fd != -1)
- close(fd);
- free(data);
- sshbuf_free(enc);
- sshbuf_free(b);
- return ret;
-}
-
-int
-sshkey_xmss_get_state(const struct sshkey *k, int printerror)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- u_int32_t idx = 0;
- char *filename = NULL;
- char *statefile = NULL, *ostatefile = NULL, *lockfile = NULL;
- int lockfd = -1, have_state = 0, have_ostate, tries = 0;
- int ret = SSH_ERR_INVALID_ARGUMENT, r;
-
- if (state == NULL)
- goto done;
- /*
- * If maxidx is set, then we are allowed a limited number
- * of signatures, but don't need to access the disk.
- * Otherwise we need to deal with the on-disk state.
- */
- if (state->maxidx) {
- /* xmss_sk always contains the current state */
- idx = PEEK_U32(k->xmss_sk);
- if (idx < state->maxidx) {
- state->allow_update = 1;
- return 0;
- }
- return SSH_ERR_INVALID_ARGUMENT;
- }
- if ((filename = k->xmss_filename) == NULL)
- goto done;
- if (asprintf(&lockfile, "%s.lock", filename) == -1 ||
- asprintf(&statefile, "%s.state", filename) == -1 ||
- asprintf(&ostatefile, "%s.ostate", filename) == -1) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto done;
- }
- if ((lockfd = open(lockfile, O_CREAT|O_RDONLY, 0600)) == -1) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("cannot open/create: %s", lockfile);
- goto done;
- }
- while (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
- if (errno != EWOULDBLOCK) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("cannot lock: %s", lockfile);
- goto done;
- }
- if (++tries > 10) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("giving up on: %s", lockfile);
- goto done;
- }
- usleep(1000*100*tries);
- }
- /* XXX no longer const */
- if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k,
- statefile, &have_state, printerror)) != 0) {
- if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k,
- ostatefile, &have_ostate, printerror)) == 0) {
- state->allow_update = 1;
- r = sshkey_xmss_forward_state(k, 1);
- state->idx = PEEK_U32(k->xmss_sk);
- state->allow_update = 0;
- }
- }
- if (!have_state && !have_ostate) {
- /* check that bds state is initialized */
- if (state->bds.auth == NULL)
- goto done;
- PRINT("start from scratch idx 0: %u", state->idx);
- } else if (r != 0) {
- ret = r;
- goto done;
- }
- if (state->idx + 1 < state->idx) {
- PRINT("state wrap: %u", state->idx);
- goto done;
- }
- state->have_state = have_state;
- state->lockfd = lockfd;
- state->allow_update = 1;
- lockfd = -1;
- ret = 0;
-done:
- if (lockfd != -1)
- close(lockfd);
- free(lockfile);
- free(statefile);
- free(ostatefile);
- return ret;
-}
-
-int
-sshkey_xmss_forward_state(const struct sshkey *k, u_int32_t reserve)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- u_char *sig = NULL;
- size_t required_siglen;
- unsigned long long smlen;
- u_char data;
- int ret, r;
-
- if (state == NULL || !state->allow_update)
- return SSH_ERR_INVALID_ARGUMENT;
- if (reserve == 0)
- return SSH_ERR_INVALID_ARGUMENT;
- if (state->idx + reserve <= state->idx)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshkey_xmss_siglen(k, &required_siglen)) != 0)
- return r;
- if ((sig = malloc(required_siglen)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- while (reserve-- > 0) {
- state->idx = PEEK_U32(k->xmss_sk);
- smlen = required_siglen;
- if ((ret = xmss_sign(k->xmss_sk, sshkey_xmss_bds_state(k),
- sig, &smlen, &data, 0, sshkey_xmss_params(k))) != 0) {
- r = SSH_ERR_INVALID_ARGUMENT;
- break;
- }
- }
- free(sig);
- return r;
-}
-
-int
-sshkey_xmss_update_state(const struct sshkey *k, int printerror)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- struct sshbuf *b = NULL, *enc = NULL;
- u_int32_t idx = 0;
- unsigned char buf[4];
- char *filename = NULL;
- char *statefile = NULL, *ostatefile = NULL, *nstatefile = NULL;
- int fd = -1;
- int ret = SSH_ERR_INVALID_ARGUMENT;
-
- if (state == NULL || !state->allow_update)
- return ret;
- if (state->maxidx) {
- /* no update since the number of signatures is limited */
- ret = 0;
- goto done;
- }
- idx = PEEK_U32(k->xmss_sk);
- if (idx == state->idx) {
- /* no signature happened, no need to update */
- ret = 0;
- goto done;
- } else if (idx != state->idx + 1) {
- PRINT("more than one signature happened: idx %u state %u",
- idx, state->idx);
- goto done;
- }
- state->idx = idx;
- if ((filename = k->xmss_filename) == NULL)
- goto done;
- if (asprintf(&statefile, "%s.state", filename) == -1 ||
- asprintf(&ostatefile, "%s.ostate", filename) == -1 ||
- asprintf(&nstatefile, "%s.nstate", filename) == -1) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto done;
- }
- unlink(nstatefile);
- if ((b = sshbuf_new()) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto done;
- }
- if ((ret = sshkey_xmss_serialize_state(k, b)) != 0) {
- PRINT("SERLIALIZE FAILED: %d", ret);
- goto done;
- }
- if ((ret = sshkey_xmss_encrypt_state(k, b, &enc)) != 0) {
- PRINT("ENCRYPT FAILED: %d", ret);
- goto done;
- }
- if ((fd = open(nstatefile, O_CREAT|O_WRONLY|O_EXCL, 0600)) == -1) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("open new state file: %s", nstatefile);
- goto done;
- }
- POKE_U32(buf, sshbuf_len(enc));
- if (atomicio(vwrite, fd, buf, sizeof(buf)) != sizeof(buf)) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("write new state file hdr: %s", nstatefile);
- close(fd);
- goto done;
- }
- if (atomicio(vwrite, fd, sshbuf_mutable_ptr(enc), sshbuf_len(enc)) !=
- sshbuf_len(enc)) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("write new state file data: %s", nstatefile);
- close(fd);
- goto done;
- }
- if (fsync(fd) == -1) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("sync new state file: %s", nstatefile);
- close(fd);
- goto done;
- }
- if (close(fd) == -1) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("close new state file: %s", nstatefile);
- goto done;
- }
- if (state->have_state) {
- unlink(ostatefile);
- if (link(statefile, ostatefile)) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("backup state %s to %s", statefile, ostatefile);
- goto done;
- }
- }
- if (rename(nstatefile, statefile) == -1) {
- ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("rename %s to %s", nstatefile, statefile);
- goto done;
- }
- ret = 0;
-done:
- if (state->lockfd != -1) {
- close(state->lockfd);
- state->lockfd = -1;
- }
- if (nstatefile)
- unlink(nstatefile);
- free(statefile);
- free(ostatefile);
- free(nstatefile);
- sshbuf_free(b);
- sshbuf_free(enc);
- return ret;
-}
-
-int
-sshkey_xmss_serialize_state(const struct sshkey *k, struct sshbuf *b)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- treehash_inst *th;
- u_int32_t i, node;
- int r;
-
- if (state == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if (state->stack == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- state->stackoffset = state->bds.stackoffset; /* copy back */
- if ((r = sshbuf_put_cstring(b, SSH_XMSS_K2_MAGIC)) != 0 ||
- (r = sshbuf_put_u32(b, state->idx)) != 0 ||
- (r = sshbuf_put_string(b, state->stack, num_stack(state))) != 0 ||
- (r = sshbuf_put_u32(b, state->stackoffset)) != 0 ||
- (r = sshbuf_put_string(b, state->stacklevels, num_stacklevels(state))) != 0 ||
- (r = sshbuf_put_string(b, state->auth, num_auth(state))) != 0 ||
- (r = sshbuf_put_string(b, state->keep, num_keep(state))) != 0 ||
- (r = sshbuf_put_string(b, state->th_nodes, num_th_nodes(state))) != 0 ||
- (r = sshbuf_put_string(b, state->retain, num_retain(state))) != 0 ||
- (r = sshbuf_put_u32(b, num_treehash(state))) != 0)
- return r;
- for (i = 0; i < num_treehash(state); i++) {
- th = &state->treehash[i];
- node = th->node - state->th_nodes;
- if ((r = sshbuf_put_u32(b, th->h)) != 0 ||
- (r = sshbuf_put_u32(b, th->next_idx)) != 0 ||
- (r = sshbuf_put_u32(b, th->stackusage)) != 0 ||
- (r = sshbuf_put_u8(b, th->completed)) != 0 ||
- (r = sshbuf_put_u32(b, node)) != 0)
- return r;
- }
- return 0;
-}
-
-int
-sshkey_xmss_serialize_state_opt(const struct sshkey *k, struct sshbuf *b,
- enum sshkey_serialize_rep opts)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- int r = SSH_ERR_INVALID_ARGUMENT;
- u_char have_stack, have_filename, have_enc;
-
- if (state == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshbuf_put_u8(b, opts)) != 0)
- return r;
- switch (opts) {
- case SSHKEY_SERIALIZE_STATE:
- r = sshkey_xmss_serialize_state(k, b);
- break;
- case SSHKEY_SERIALIZE_FULL:
- if ((r = sshkey_xmss_serialize_enc_key(k, b)) != 0)
- return r;
- r = sshkey_xmss_serialize_state(k, b);
- break;
- case SSHKEY_SERIALIZE_SHIELD:
- /* all of stack/filename/enc are optional */
- have_stack = state->stack != NULL;
- if ((r = sshbuf_put_u8(b, have_stack)) != 0)
- return r;
- if (have_stack) {
- state->idx = PEEK_U32(k->xmss_sk); /* update */
- if ((r = sshkey_xmss_serialize_state(k, b)) != 0)
- return r;
- }
- have_filename = k->xmss_filename != NULL;
- if ((r = sshbuf_put_u8(b, have_filename)) != 0)
- return r;
- if (have_filename &&
- (r = sshbuf_put_cstring(b, k->xmss_filename)) != 0)
- return r;
- have_enc = state->enc_keyiv != NULL;
- if ((r = sshbuf_put_u8(b, have_enc)) != 0)
- return r;
- if (have_enc &&
- (r = sshkey_xmss_serialize_enc_key(k, b)) != 0)
- return r;
- if ((r = sshbuf_put_u32(b, state->maxidx)) != 0 ||
- (r = sshbuf_put_u8(b, state->allow_update)) != 0)
- return r;
- break;
- case SSHKEY_SERIALIZE_DEFAULT:
- r = 0;
- break;
- default:
- r = SSH_ERR_INVALID_ARGUMENT;
- break;
- }
- return r;
-}
-
-int
-sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- treehash_inst *th;
- u_int32_t i, lh, node;
- size_t ls, lsl, la, lk, ln, lr;
- char *magic;
- int r = SSH_ERR_INTERNAL_ERROR;
-
- if (state == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if (k->xmss_sk == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((state->treehash = calloc(num_treehash(state),
- sizeof(treehash_inst))) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_get_cstring(b, &magic, NULL)) != 0 ||
- (r = sshbuf_get_u32(b, &state->idx)) != 0 ||
- (r = sshbuf_get_string(b, &state->stack, &ls)) != 0 ||
- (r = sshbuf_get_u32(b, &state->stackoffset)) != 0 ||
- (r = sshbuf_get_string(b, &state->stacklevels, &lsl)) != 0 ||
- (r = sshbuf_get_string(b, &state->auth, &la)) != 0 ||
- (r = sshbuf_get_string(b, &state->keep, &lk)) != 0 ||
- (r = sshbuf_get_string(b, &state->th_nodes, &ln)) != 0 ||
- (r = sshbuf_get_string(b, &state->retain, &lr)) != 0 ||
- (r = sshbuf_get_u32(b, &lh)) != 0)
- goto out;
- if (strcmp(magic, SSH_XMSS_K2_MAGIC) != 0) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- /* XXX check stackoffset */
- if (ls != num_stack(state) ||
- lsl != num_stacklevels(state) ||
- la != num_auth(state) ||
- lk != num_keep(state) ||
- ln != num_th_nodes(state) ||
- lr != num_retain(state) ||
- lh != num_treehash(state)) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- for (i = 0; i < num_treehash(state); i++) {
- th = &state->treehash[i];
- if ((r = sshbuf_get_u32(b, &th->h)) != 0 ||
- (r = sshbuf_get_u32(b, &th->next_idx)) != 0 ||
- (r = sshbuf_get_u32(b, &th->stackusage)) != 0 ||
- (r = sshbuf_get_u8(b, &th->completed)) != 0 ||
- (r = sshbuf_get_u32(b, &node)) != 0)
- goto out;
- if (node < num_th_nodes(state))
- th->node = &state->th_nodes[node];
- }
- POKE_U32(k->xmss_sk, state->idx);
- xmss_set_bds_state(&state->bds, state->stack, state->stackoffset,
- state->stacklevels, state->auth, state->keep, state->treehash,
- state->retain, 0);
- /* success */
- r = 0;
- out:
- free(magic);
- return r;
-}
-
-int
-sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- enum sshkey_serialize_rep opts;
- u_char have_state, have_stack, have_filename, have_enc;
- int r;
-
- if ((r = sshbuf_get_u8(b, &have_state)) != 0)
- return r;
-
- opts = have_state;
- switch (opts) {
- case SSHKEY_SERIALIZE_DEFAULT:
- r = 0;
- break;
- case SSHKEY_SERIALIZE_SHIELD:
- if ((r = sshbuf_get_u8(b, &have_stack)) != 0)
- return r;
- if (have_stack &&
- (r = sshkey_xmss_deserialize_state(k, b)) != 0)
- return r;
- if ((r = sshbuf_get_u8(b, &have_filename)) != 0)
- return r;
- if (have_filename &&
- (r = sshbuf_get_cstring(b, &k->xmss_filename, NULL)) != 0)
- return r;
- if ((r = sshbuf_get_u8(b, &have_enc)) != 0)
- return r;
- if (have_enc &&
- (r = sshkey_xmss_deserialize_enc_key(k, b)) != 0)
- return r;
- if ((r = sshbuf_get_u32(b, &state->maxidx)) != 0 ||
- (r = sshbuf_get_u8(b, &state->allow_update)) != 0)
- return r;
- break;
- case SSHKEY_SERIALIZE_STATE:
- if ((r = sshkey_xmss_deserialize_state(k, b)) != 0)
- return r;
- break;
- case SSHKEY_SERIALIZE_FULL:
- if ((r = sshkey_xmss_deserialize_enc_key(k, b)) != 0 ||
- (r = sshkey_xmss_deserialize_state(k, b)) != 0)
- return r;
- break;
- default:
- r = SSH_ERR_INVALID_FORMAT;
- break;
- }
- return r;
-}
-
-int
-sshkey_xmss_encrypt_state(const struct sshkey *k, struct sshbuf *b,
- struct sshbuf **retp)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- struct sshbuf *encrypted = NULL, *encoded = NULL, *padded = NULL;
- struct sshcipher_ctx *ciphercontext = NULL;
- const struct sshcipher *cipher;
- u_char *cp, *key, *iv = NULL;
- size_t i, keylen, ivlen, blocksize, authlen, encrypted_len, aadlen;
- int r = SSH_ERR_INTERNAL_ERROR;
-
- if (retp != NULL)
- *retp = NULL;
- if (state == NULL ||
- state->enc_keyiv == NULL ||
- state->enc_ciphername == NULL)
- return SSH_ERR_INTERNAL_ERROR;
- if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) {
- r = SSH_ERR_INTERNAL_ERROR;
- goto out;
- }
- blocksize = cipher_blocksize(cipher);
- keylen = cipher_keylen(cipher);
- ivlen = cipher_ivlen(cipher);
- authlen = cipher_authlen(cipher);
- if (state->enc_keyiv_len != keylen + ivlen) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- key = state->enc_keyiv;
- if ((encrypted = sshbuf_new()) == NULL ||
- (encoded = sshbuf_new()) == NULL ||
- (padded = sshbuf_new()) == NULL ||
- (iv = malloc(ivlen)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
-
- /* replace first 4 bytes of IV with index to ensure uniqueness */
- memcpy(iv, key + keylen, ivlen);
- POKE_U32(iv, state->idx);
-
- if ((r = sshbuf_put(encoded, XMSS_MAGIC, sizeof(XMSS_MAGIC))) != 0 ||
- (r = sshbuf_put_u32(encoded, state->idx)) != 0)
- goto out;
-
- /* padded state will be encrypted */
- if ((r = sshbuf_putb(padded, b)) != 0)
- goto out;
- i = 0;
- while (sshbuf_len(padded) % blocksize) {
- if ((r = sshbuf_put_u8(padded, ++i & 0xff)) != 0)
- goto out;
- }
- encrypted_len = sshbuf_len(padded);
-
- /* header including the length of state is used as AAD */
- if ((r = sshbuf_put_u32(encoded, encrypted_len)) != 0)
- goto out;
- aadlen = sshbuf_len(encoded);
-
- /* concat header and state */
- if ((r = sshbuf_putb(encoded, padded)) != 0)
- goto out;
-
- /* reserve space for encryption of encoded data plus auth tag */
- /* encrypt at offset addlen */
- if ((r = sshbuf_reserve(encrypted,
- encrypted_len + aadlen + authlen, &cp)) != 0 ||
- (r = cipher_init(&ciphercontext, cipher, key, keylen,
- iv, ivlen, 1)) != 0 ||
- (r = cipher_crypt(ciphercontext, 0, cp, sshbuf_ptr(encoded),
- encrypted_len, aadlen, authlen)) != 0)
- goto out;
-
- /* success */
- r = 0;
- out:
- if (retp != NULL) {
- *retp = encrypted;
- encrypted = NULL;
- }
- sshbuf_free(padded);
- sshbuf_free(encoded);
- sshbuf_free(encrypted);
- cipher_free(ciphercontext);
- free(iv);
- return r;
-}
-
-int
-sshkey_xmss_decrypt_state(const struct sshkey *k, struct sshbuf *encoded,
- struct sshbuf **retp)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- struct sshbuf *copy = NULL, *decrypted = NULL;
- struct sshcipher_ctx *ciphercontext = NULL;
- const struct sshcipher *cipher = NULL;
- u_char *key, *iv = NULL, *dp;
- size_t keylen, ivlen, authlen, aadlen;
- u_int blocksize, encrypted_len, index;
- int r = SSH_ERR_INTERNAL_ERROR;
-
- if (retp != NULL)
- *retp = NULL;
- if (state == NULL ||
- state->enc_keyiv == NULL ||
- state->enc_ciphername == NULL)
- return SSH_ERR_INTERNAL_ERROR;
- if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- blocksize = cipher_blocksize(cipher);
- keylen = cipher_keylen(cipher);
- ivlen = cipher_ivlen(cipher);
- authlen = cipher_authlen(cipher);
- if (state->enc_keyiv_len != keylen + ivlen) {
- r = SSH_ERR_INTERNAL_ERROR;
- goto out;
- }
- key = state->enc_keyiv;
-
- if ((copy = sshbuf_fromb(encoded)) == NULL ||
- (decrypted = sshbuf_new()) == NULL ||
- (iv = malloc(ivlen)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
-
- /* check magic */
- if (sshbuf_len(encoded) < sizeof(XMSS_MAGIC) ||
- memcmp(sshbuf_ptr(encoded), XMSS_MAGIC, sizeof(XMSS_MAGIC))) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- /* parse public portion */
- if ((r = sshbuf_consume(encoded, sizeof(XMSS_MAGIC))) != 0 ||
- (r = sshbuf_get_u32(encoded, &index)) != 0 ||
- (r = sshbuf_get_u32(encoded, &encrypted_len)) != 0)
- goto out;
-
- /* check size of encrypted key blob */
- if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- /* check that an appropriate amount of auth data is present */
- if (sshbuf_len(encoded) < authlen ||
- sshbuf_len(encoded) - authlen < encrypted_len) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
-
- aadlen = sshbuf_len(copy) - sshbuf_len(encoded);
-
- /* replace first 4 bytes of IV with index to ensure uniqueness */
- memcpy(iv, key + keylen, ivlen);
- POKE_U32(iv, index);
-
- /* decrypt private state of key */
- if ((r = sshbuf_reserve(decrypted, aadlen + encrypted_len, &dp)) != 0 ||
- (r = cipher_init(&ciphercontext, cipher, key, keylen,
- iv, ivlen, 0)) != 0 ||
- (r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(copy),
- encrypted_len, aadlen, authlen)) != 0)
- goto out;
-
- /* there should be no trailing data */
- if ((r = sshbuf_consume(encoded, encrypted_len + authlen)) != 0)
- goto out;
- if (sshbuf_len(encoded) != 0) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
-
- /* remove AAD */
- if ((r = sshbuf_consume(decrypted, aadlen)) != 0)
- goto out;
- /* XXX encrypted includes unchecked padding */
-
- /* success */
- r = 0;
- if (retp != NULL) {
- *retp = decrypted;
- decrypted = NULL;
- }
- out:
- cipher_free(ciphercontext);
- sshbuf_free(copy);
- sshbuf_free(decrypted);
- free(iv);
- return r;
-}
-
-u_int32_t
-sshkey_xmss_signatures_left(const struct sshkey *k)
-{
- struct ssh_xmss_state *state = k->xmss_state;
- u_int32_t idx;
-
- if (sshkey_type_plain(k->type) == KEY_XMSS && state &&
- state->maxidx) {
- idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx;
- if (idx < state->maxidx)
- return state->maxidx - idx;
- }
- return 0;
-}
-
-int
-sshkey_xmss_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
-{
- struct ssh_xmss_state *state = k->xmss_state;
-
- if (sshkey_type_plain(k->type) != KEY_XMSS)
- return SSH_ERR_INVALID_ARGUMENT;
- if (maxsign == 0)
- return 0;
- if (state->idx + maxsign < state->idx)
- return SSH_ERR_INVALID_ARGUMENT;
- state->maxidx = state->idx + maxsign;
- return 0;
-}
-#endif /* WITH_XMSS */
+++ /dev/null
-/* $OpenBSD: sshkey-xmss.h,v 1.4 2022/10/28 00:39:29 djm Exp $ */
-/*
- * Copyright (c) 2017 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef SSHKEY_XMSS_H
-#define SSHKEY_XMSS_H
-
-#define XMSS_SHA2_256_W16_H10_NAME "XMSS_SHA2-256_W16_H10"
-#define XMSS_SHA2_256_W16_H16_NAME "XMSS_SHA2-256_W16_H16"
-#define XMSS_SHA2_256_W16_H20_NAME "XMSS_SHA2-256_W16_H20"
-#define XMSS_DEFAULT_NAME XMSS_SHA2_256_W16_H10_NAME
-
-size_t sshkey_xmss_pklen(const struct sshkey *);
-size_t sshkey_xmss_sklen(const struct sshkey *);
-int sshkey_xmss_init(struct sshkey *, const char *);
-void sshkey_xmss_free_state(struct sshkey *);
-int sshkey_xmss_generate_private_key(struct sshkey *, int);
-int sshkey_xmss_serialize_state(const struct sshkey *, struct sshbuf *);
-int sshkey_xmss_serialize_state_opt(const struct sshkey *, struct sshbuf *,
- enum sshkey_serialize_rep);
-int sshkey_xmss_serialize_pk_info(const struct sshkey *, struct sshbuf *,
- enum sshkey_serialize_rep);
-int sshkey_xmss_deserialize_state(struct sshkey *, struct sshbuf *);
-int sshkey_xmss_deserialize_state_opt(struct sshkey *, struct sshbuf *);
-int sshkey_xmss_deserialize_pk_info(struct sshkey *, struct sshbuf *);
-
-int sshkey_xmss_siglen(const struct sshkey *, size_t *);
-void *sshkey_xmss_params(const struct sshkey *);
-void *sshkey_xmss_bds_state(const struct sshkey *);
-int sshkey_xmss_get_state(const struct sshkey *, int);
-int sshkey_xmss_enable_maxsign(struct sshkey *, u_int32_t);
-int sshkey_xmss_forward_state(const struct sshkey *, u_int32_t);
-int sshkey_xmss_update_state(const struct sshkey *, int);
-u_int32_t sshkey_xmss_signatures_left(const struct sshkey *);
-
-#endif /* SSHKEY_XMSS_H */
-/* $OpenBSD: sshkey.c,v 1.151 2025/07/24 05:44:55 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.152 2025/08/29 03:50:38 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
#include "ssh-sk.h"
#include "ssh-pkcs11.h"
-#ifdef WITH_XMSS
-#include "sshkey-xmss.h"
-#include "xmss_fast.h"
-#endif
-
#include "openbsd-compat/openssl-compat.h"
/* openssh private key file format */
#define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */
#define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512
-int sshkey_private_serialize_opt(struct sshkey *key,
- struct sshbuf *buf, enum sshkey_serialize_rep);
static int sshkey_from_blob_internal(struct sshbuf *buf,
struct sshkey **keyp, int allow_cert);
extern const struct sshkey_impl sshkey_rsa_sha512_impl;
extern const struct sshkey_impl sshkey_rsa_sha512_cert_impl;
#endif /* WITH_OPENSSL */
-#ifdef WITH_XMSS
-extern const struct sshkey_impl sshkey_xmss_impl;
-extern const struct sshkey_impl sshkey_xmss_cert_impl;
-#endif
const struct sshkey_impl * const keyimpls[] = {
&sshkey_ed25519_impl,
&sshkey_rsa_sha512_impl,
&sshkey_rsa_sha512_cert_impl,
#endif /* WITH_OPENSSL */
-#ifdef WITH_XMSS
- &sshkey_xmss_impl,
- &sshkey_xmss_cert_impl,
-#endif
NULL
};
return KEY_ED25519;
case KEY_ED25519_SK_CERT:
return KEY_ED25519_SK;
- case KEY_XMSS_CERT:
- return KEY_XMSS;
default:
return type;
}
return KEY_ED25519_CERT;
case KEY_ED25519_SK:
return KEY_ED25519_SK_CERT;
- case KEY_XMSS:
- return KEY_XMSS_CERT;
default:
return -1;
}
return r;
}
-int
-sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b,
- enum sshkey_serialize_rep opts)
-{
- return sshkey_puts_opts_internal(key, b, opts, 0);
-}
-
int
sshkey_puts(const struct sshkey *key, struct sshbuf *b)
{
- return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT);
+ return sshkey_puts_opts_internal(key, b, SSHKEY_SERIALIZE_DEFAULT, 0);
}
int
}
if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0)
goto out;
- if ((r = sshkey_private_serialize_opt(k, prvbuf,
- SSHKEY_SERIALIZE_SHIELD)) != 0)
+ if ((r = sshkey_private_serialize(k, prvbuf)) != 0)
goto out;
/* pad to cipher blocksize */
i = 0;
return 0;
}
-int
+static int
sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
enum sshkey_serialize_rep opts)
{
SSHKEY_SERIALIZE_DEFAULT);
}
+
/* Shared deserialization of FIDO private key components */
int
sshkey_private_deserialize_sk(struct sshbuf *buf, struct sshkey *k)
expect_ed25519_pk = k->ed25519_pk;
k->sk_application = NULL;
k->ed25519_pk = NULL;
- /* XXX xmss too or refactor */
} else {
if ((k = sshkey_new(type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
if ((r = impl->funcs->deserialize_private(tname, buf, k)) != 0)
goto out;
- /* XXX xmss too or refactor */
if ((expect_sk_application != NULL && (k->sk_application == NULL ||
strcmp(expect_sk_application, k->sk_application) != 0)) ||
(expect_ed25519_pk != NULL && (k->ed25519_pk == NULL ||
goto out;
/* append private key and comment*/
- if ((r = sshkey_private_serialize_opt(prv, encrypted,
- SSHKEY_SERIALIZE_FULL)) != 0 ||
+ if ((r = sshkey_private_serialize(prv, encrypted)) != 0 ||
(r = sshbuf_put_cstring(encrypted, comment)) != 0)
goto out;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_SK:
-#ifdef WITH_XMSS
- case KEY_XMSS:
-#endif /* WITH_XMSS */
#ifdef WITH_OPENSSL
case KEY_ECDSA_SK:
#endif /* WITH_OPENSSL */
if (commentp != NULL)
*commentp = NULL;
- switch (type) {
- case KEY_XMSS:
- /* No fallback for new-format-only keys */
- return sshkey_parse_private2(blob, type, passphrase,
- keyp, commentp);
- default:
- r = sshkey_parse_private2(blob, type, passphrase, keyp,
- commentp);
- /* Only fallback to PEM parser if a format error occurred. */
- if (r != SSH_ERR_INVALID_FORMAT)
- return r;
+ r = sshkey_parse_private2(blob, type, passphrase, keyp, commentp);
+ /* Only fallback to PEM parser if a format error occurred. */
+ if (r != SSH_ERR_INVALID_FORMAT)
+ return r;
#ifdef WITH_OPENSSL
- return sshkey_parse_private_pem_fileblob(blob, type,
- passphrase, keyp);
+ return sshkey_parse_private_pem_fileblob(blob, type,
+ passphrase, keyp);
#else
- return SSH_ERR_INVALID_FORMAT;
+ return SSH_ERR_INVALID_FORMAT;
#endif /* WITH_OPENSSL */
- }
}
int
return r;
return 0;
}
-
-#ifdef WITH_XMSS
-/*
- * serialize the key with the current state and forward the state
- * maxsign times.
- */
-int
-sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
- u_int32_t maxsign, int printerror)
-{
- int r, rupdate;
-
- if (maxsign == 0 ||
- sshkey_type_plain(k->type) != KEY_XMSS)
- return sshkey_private_serialize_opt(k, b,
- SSHKEY_SERIALIZE_DEFAULT);
- if ((r = sshkey_xmss_get_state(k, printerror)) != 0 ||
- (r = sshkey_private_serialize_opt(k, b,
- SSHKEY_SERIALIZE_STATE)) != 0 ||
- (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
- goto out;
- r = 0;
-out:
- if ((rupdate = sshkey_xmss_update_state(k, printerror)) != 0) {
- if (r == 0)
- r = rupdate;
- }
- return r;
-}
-
-u_int32_t
-sshkey_signatures_left(const struct sshkey *k)
-{
- if (sshkey_type_plain(k->type) == KEY_XMSS)
- return sshkey_xmss_signatures_left(k);
- return 0;
-}
-
-int
-sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
-{
- if (sshkey_type_plain(k->type) != KEY_XMSS)
- return SSH_ERR_INVALID_ARGUMENT;
- return sshkey_xmss_enable_maxsign(k, maxsign);
-}
-
-int
-sshkey_set_filename(struct sshkey *k, const char *filename)
-{
- if (k == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if (sshkey_type_plain(k->type) != KEY_XMSS)
- return 0;
- if (filename == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- if ((k->xmss_filename = strdup(filename)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- return 0;
-}
-#else
-int
-sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
- u_int32_t maxsign, int printerror)
-{
- return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
-}
-
-u_int32_t
-sshkey_signatures_left(const struct sshkey *k)
-{
- return 0;
-}
-
-int
-sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
-{
- return SSH_ERR_INVALID_ARGUMENT;
-}
-
-int
-sshkey_set_filename(struct sshkey *k, const char *filename)
-{
- if (k == NULL)
- return SSH_ERR_INVALID_ARGUMENT;
- return 0;
-}
-#endif /* WITH_XMSS */
-/* $OpenBSD: sshkey.h,v 1.69 2025/07/24 06:12:08 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.70 2025/08/29 03:50:38 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
KEY_RSA_CERT,
KEY_ECDSA_CERT,
KEY_ED25519_CERT,
- KEY_XMSS,
- KEY_XMSS_CERT,
KEY_ECDSA_SK,
KEY_ECDSA_SK_CERT,
KEY_ED25519_SK,
/* Private key serialisation formats, used on the wire */
enum sshkey_serialize_rep {
SSHKEY_SERIALIZE_DEFAULT = 0,
- SSHKEY_SERIALIZE_STATE = 1, /* only state is serialized */
- SSHKEY_SERIALIZE_FULL = 2, /* include keys for saving to disk */
- SSHKEY_SERIALIZE_SHIELD = 3, /* everything, for encrypting in ram */
- SSHKEY_SERIALIZE_INFO = 254, /* minimal information */
};
/* Private key disk formats */
/* KEY_ED25519 and KEY_ED25519_SK */
u_char *ed25519_sk;
u_char *ed25519_pk;
- /* KEY_XMSS */
- char *xmss_name;
- char *xmss_filename; /* for state file updates */
- void *xmss_state; /* depends on xmss_name, opaque */
- u_char *xmss_sk;
- u_char *xmss_pk;
/* KEY_ECDSA_SK and KEY_ED25519_SK */
char *sk_application;
uint8_t sk_flags;
int sshkey_to_base64(const struct sshkey *, char **);
int sshkey_putb(const struct sshkey *, struct sshbuf *);
int sshkey_puts(const struct sshkey *, struct sshbuf *);
-int sshkey_puts_opts(const struct sshkey *, struct sshbuf *,
- enum sshkey_serialize_rep);
int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
int sshkey_putb_plain(const struct sshkey *, struct sshbuf *);
int sshkey_puts_plain(const struct sshkey *, struct sshbuf *);
/* private key parsing and serialisation */
int sshkey_private_serialize(struct sshkey *key, struct sshbuf *buf);
-int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
- enum sshkey_serialize_rep);
int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp);
/* private key file format parsing and serialisation */
int ssh_rsa_complete_crt_parameters(const BIGNUM *, const BIGNUM *,
const BIGNUM *, const BIGNUM *, BIGNUM **, BIGNUM **);
-/* stateful keys (e.g. XMSS) */
-int sshkey_set_filename(struct sshkey *, const char *);
-int sshkey_enable_maxsign(struct sshkey *, u_int32_t);
-u_int32_t sshkey_signatures_left(const struct sshkey *);
-int sshkey_private_serialize_maxsign(struct sshkey *key,
- struct sshbuf *buf, u_int32_t maxsign, int);
-
void sshkey_sig_details_free(struct sshkey_sig_details *);
#ifdef WITH_OPENSSL
+++ /dev/null
-/* $OpenBSD: xmss_commons.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
-/*
-xmss_commons.c 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-
-#include "includes.h"
-#ifdef WITH_XMSS
-
-#include "xmss_commons.h"
-#include <stdlib.h>
-#include <stdio.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-
-void to_byte(unsigned char *out, unsigned long long in, uint32_t bytes)
-{
- int32_t i;
- for (i = bytes-1; i >= 0; i--) {
- out[i] = in & 0xff;
- in = in >> 8;
- }
-}
-
-#if 0
-void hexdump(const unsigned char *a, size_t len)
-{
- size_t i;
- for (i = 0; i < len; i++)
- printf("%02x", a[i]);
-}
-#endif
-#endif /* WITH_XMSS */
+++ /dev/null
-#ifdef WITH_XMSS
-/* $OpenBSD: xmss_commons.h,v 1.3 2018/02/26 03:56:44 dtucker Exp $ */
-/*
-xmss_commons.h 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-#ifndef XMSS_COMMONS_H
-#define XMSS_COMMONS_H
-
-#include <stdlib.h>
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#endif
-void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes);
-#if 0
-void hexdump(const unsigned char *a, size_t len);
-#endif
-#endif /* WITH_XMSS */
+++ /dev/null
-/* $OpenBSD: xmss_fast.c,v 1.3 2018/03/22 07:06:11 markus Exp $ */
-/*
-xmss_fast.c version 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-
-#include "includes.h"
-#ifdef WITH_XMSS
-
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-
-#include "xmss_fast.h"
-#include "crypto_api.h"
-#include "xmss_wots.h"
-#include "xmss_hash.h"
-
-#include "xmss_commons.h"
-#include "xmss_hash_address.h"
-// For testing
-#include "stdio.h"
-
-
-
-/**
- * Used for pseudorandom keygeneration,
- * generates the seed for the WOTS keypair at address addr
- *
- * takes n byte sk_seed and returns n byte seed using 32 byte address addr.
- */
-static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8])
-{
- unsigned char bytes[32];
- // Make sure that chain addr, hash addr, and key bit are 0!
- setChainADRS(addr,0);
- setHashADRS(addr,0);
- setKeyAndMask(addr,0);
- // Generate pseudorandom value
- addr_to_byte(bytes, addr);
- prf(seed, bytes, sk_seed, n);
-}
-
-/**
- * Initialize xmss params struct
- * parameter names are the same as in the draft
- * parameter k is K as used in the BDS algorithm
- */
-int xmss_set_params(xmss_params *params, int n, int h, int w, int k)
-{
- if (k >= h || k < 2 || (h - k) % 2) {
- fprintf(stderr, "For BDS traversal, H - K must be even, with H > K >= 2!\n");
- return 1;
- }
- params->h = h;
- params->n = n;
- params->k = k;
- wots_params wots_par;
- wots_set_params(&wots_par, n, w);
- params->wots_par = wots_par;
- return 0;
-}
-
-/**
- * Initialize BDS state struct
- * parameter names are the same as used in the description of the BDS traversal
- */
-void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf)
-{
- state->stack = stack;
- state->stackoffset = stackoffset;
- state->stacklevels = stacklevels;
- state->auth = auth;
- state->keep = keep;
- state->treehash = treehash;
- state->retain = retain;
- state->next_leaf = next_leaf;
-}
-
-/**
- * Initialize xmssmt_params struct
- * parameter names are the same as in the draft
- *
- * Especially h is the total tree height, i.e. the XMSS trees have height h/d
- */
-int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k)
-{
- if (h % d) {
- fprintf(stderr, "d must divide h without remainder!\n");
- return 1;
- }
- params->h = h;
- params->d = d;
- params->n = n;
- params->index_len = (h + 7) / 8;
- xmss_params xmss_par;
- if (xmss_set_params(&xmss_par, n, (h/d), w, k)) {
- return 1;
- }
- params->xmss_par = xmss_par;
- return 0;
-}
-
-/**
- * Computes a leaf from a WOTS public key using an L-tree.
- */
-static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8])
-{
- unsigned int l = params->wots_par.len;
- unsigned int n = params->n;
- uint32_t i = 0;
- uint32_t height = 0;
- uint32_t bound;
-
- //ADRS.setTreeHeight(0);
- setTreeHeight(addr, height);
-
- while (l > 1) {
- bound = l >> 1; //floor(l / 2);
- for (i = 0; i < bound; i++) {
- //ADRS.setTreeIndex(i);
- setTreeIndex(addr, i);
- //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS);
- hash_h(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n);
- }
- //if ( l % 2 == 1 ) {
- if (l & 1) {
- //pk[floor(l / 2) + 1] = pk[l];
- memcpy(wots_pk+(l>>1)*n, wots_pk+(l-1)*n, n);
- //l = ceil(l / 2);
- l=(l>>1)+1;
- }
- else {
- //l = ceil(l / 2);
- l=(l>>1);
- }
- //ADRS.setTreeHeight(ADRS.getTreeHeight() + 1);
- height++;
- setTreeHeight(addr, height);
- }
- //return pk[0];
- memcpy(leaf, wots_pk, n);
-}
-
-/**
- * Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address.
- */
-static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8])
-{
- unsigned char seed[params->n];
- unsigned char pk[params->wots_par.keysize];
-
- get_seed(seed, sk_seed, params->n, ots_addr);
- wots_pkgen(pk, seed, &(params->wots_par), pub_seed, ots_addr);
-
- l_tree(leaf, pk, params, pub_seed, ltree_addr);
-}
-
-static int treehash_minheight_on_stack(bds_state* state, const xmss_params *params, const treehash_inst *treehash) {
- unsigned int r = params->h, i;
- for (i = 0; i < treehash->stackusage; i++) {
- if (state->stacklevels[state->stackoffset - i - 1] < r) {
- r = state->stacklevels[state->stackoffset - i - 1];
- }
- }
- return r;
-}
-
-/**
- * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash.
- * Currently only used for key generation.
- *
- */
-static void treehash_setup(unsigned char *node, int height, int index, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8])
-{
- unsigned int idx = index;
- unsigned int n = params->n;
- unsigned int h = params->h;
- unsigned int k = params->k;
- // use three different addresses because at this point we use all three formats in parallel
- uint32_t ots_addr[8];
- uint32_t ltree_addr[8];
- uint32_t node_addr[8];
- // only copy layer and tree address parts
- memcpy(ots_addr, addr, 12);
- // type = ots
- setType(ots_addr, 0);
- memcpy(ltree_addr, addr, 12);
- setType(ltree_addr, 1);
- memcpy(node_addr, addr, 12);
- setType(node_addr, 2);
-
- uint32_t lastnode, i;
- unsigned char stack[(height+1)*n];
- unsigned int stacklevels[height+1];
- unsigned int stackoffset=0;
- unsigned int nodeh;
-
- lastnode = idx+(1<<height);
-
- for (i = 0; i < h-k; i++) {
- state->treehash[i].h = i;
- state->treehash[i].completed = 1;
- state->treehash[i].stackusage = 0;
- }
-
- i = 0;
- for (; idx < lastnode; idx++) {
- setLtreeADRS(ltree_addr, idx);
- setOTSADRS(ots_addr, idx);
- gen_leaf_wots(stack+stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr);
- stacklevels[stackoffset] = 0;
- stackoffset++;
- if (h - k > 0 && i == 3) {
- memcpy(state->treehash[0].node, stack+stackoffset*n, n);
- }
- while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2])
- {
- nodeh = stacklevels[stackoffset-1];
- if (i >> nodeh == 1) {
- memcpy(state->auth + nodeh*n, stack+(stackoffset-1)*n, n);
- }
- else {
- if (nodeh < h - k && i >> nodeh == 3) {
- memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*n, n);
- }
- else if (nodeh >= h - k) {
- memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((i >> nodeh) - 3) >> 1)) * n, stack+(stackoffset-1)*n, n);
- }
- }
- setTreeHeight(node_addr, stacklevels[stackoffset-1]);
- setTreeIndex(node_addr, (idx >> (stacklevels[stackoffset-1]+1)));
- hash_h(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed,
- node_addr, n);
- stacklevels[stackoffset-2]++;
- stackoffset--;
- }
- i++;
- }
-
- for (i = 0; i < n; i++)
- node[i] = stack[i];
-}
-
-static void treehash_update(treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) {
- int n = params->n;
-
- uint32_t ots_addr[8];
- uint32_t ltree_addr[8];
- uint32_t node_addr[8];
- // only copy layer and tree address parts
- memcpy(ots_addr, addr, 12);
- // type = ots
- setType(ots_addr, 0);
- memcpy(ltree_addr, addr, 12);
- setType(ltree_addr, 1);
- memcpy(node_addr, addr, 12);
- setType(node_addr, 2);
-
- setLtreeADRS(ltree_addr, treehash->next_idx);
- setOTSADRS(ots_addr, treehash->next_idx);
-
- unsigned char nodebuffer[2 * n];
- unsigned int nodeheight = 0;
- gen_leaf_wots(nodebuffer, sk_seed, params, pub_seed, ltree_addr, ots_addr);
- while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) {
- memcpy(nodebuffer + n, nodebuffer, n);
- memcpy(nodebuffer, state->stack + (state->stackoffset-1)*n, n);
- setTreeHeight(node_addr, nodeheight);
- setTreeIndex(node_addr, (treehash->next_idx >> (nodeheight+1)));
- hash_h(nodebuffer, nodebuffer, pub_seed, node_addr, n);
- nodeheight++;
- treehash->stackusage--;
- state->stackoffset--;
- }
- if (nodeheight == treehash->h) { // this also implies stackusage == 0
- memcpy(treehash->node, nodebuffer, n);
- treehash->completed = 1;
- }
- else {
- memcpy(state->stack + state->stackoffset*n, nodebuffer, n);
- treehash->stackusage++;
- state->stacklevels[state->stackoffset] = nodeheight;
- state->stackoffset++;
- treehash->next_idx++;
- }
-}
-
-/**
- * Computes a root node given a leaf and an authapth
- */
-static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8])
-{
- unsigned int n = params->n;
-
- uint32_t i, j;
- unsigned char buffer[2*n];
-
- // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left.
- // Otherwise, it is the other way around
- if (leafidx & 1) {
- for (j = 0; j < n; j++)
- buffer[n+j] = leaf[j];
- for (j = 0; j < n; j++)
- buffer[j] = authpath[j];
- }
- else {
- for (j = 0; j < n; j++)
- buffer[j] = leaf[j];
- for (j = 0; j < n; j++)
- buffer[n+j] = authpath[j];
- }
- authpath += n;
-
- for (i=0; i < params->h-1; i++) {
- setTreeHeight(addr, i);
- leafidx >>= 1;
- setTreeIndex(addr, leafidx);
- if (leafidx&1) {
- hash_h(buffer+n, buffer, pub_seed, addr, n);
- for (j = 0; j < n; j++)
- buffer[j] = authpath[j];
- }
- else {
- hash_h(buffer, buffer, pub_seed, addr, n);
- for (j = 0; j < n; j++)
- buffer[j+n] = authpath[j];
- }
- authpath += n;
- }
- setTreeHeight(addr, (params->h-1));
- leafidx >>= 1;
- setTreeIndex(addr, leafidx);
- hash_h(root, buffer, pub_seed, addr, n);
-}
-
-/**
- * Performs one treehash update on the instance that needs it the most.
- * Returns 1 if such an instance was not found
- **/
-static char bds_treehash_update(bds_state *state, unsigned int updates, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) {
- uint32_t i, j;
- unsigned int level, l_min, low;
- unsigned int h = params->h;
- unsigned int k = params->k;
- unsigned int used = 0;
-
- for (j = 0; j < updates; j++) {
- l_min = h;
- level = h - k;
- for (i = 0; i < h - k; i++) {
- if (state->treehash[i].completed) {
- low = h;
- }
- else if (state->treehash[i].stackusage == 0) {
- low = i;
- }
- else {
- low = treehash_minheight_on_stack(state, params, &(state->treehash[i]));
- }
- if (low < l_min) {
- level = i;
- l_min = low;
- }
- }
- if (level == h - k) {
- break;
- }
- treehash_update(&(state->treehash[level]), state, sk_seed, params, pub_seed, addr);
- used++;
- }
- return updates - used;
-}
-
-/**
- * Updates the state (typically NEXT_i) by adding a leaf and updating the stack
- * Returns 1 if all leaf nodes have already been processed
- **/
-static char bds_state_update(bds_state *state, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) {
- uint32_t ltree_addr[8];
- uint32_t node_addr[8];
- uint32_t ots_addr[8];
-
- int n = params->n;
- int h = params->h;
- int k = params->k;
-
- int nodeh;
- int idx = state->next_leaf;
- if (idx == 1 << h) {
- return 1;
- }
-
- // only copy layer and tree address parts
- memcpy(ots_addr, addr, 12);
- // type = ots
- setType(ots_addr, 0);
- memcpy(ltree_addr, addr, 12);
- setType(ltree_addr, 1);
- memcpy(node_addr, addr, 12);
- setType(node_addr, 2);
-
- setOTSADRS(ots_addr, idx);
- setLtreeADRS(ltree_addr, idx);
-
- gen_leaf_wots(state->stack+state->stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr);
-
- state->stacklevels[state->stackoffset] = 0;
- state->stackoffset++;
- if (h - k > 0 && idx == 3) {
- memcpy(state->treehash[0].node, state->stack+state->stackoffset*n, n);
- }
- while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) {
- nodeh = state->stacklevels[state->stackoffset-1];
- if (idx >> nodeh == 1) {
- memcpy(state->auth + nodeh*n, state->stack+(state->stackoffset-1)*n, n);
- }
- else {
- if (nodeh < h - k && idx >> nodeh == 3) {
- memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*n, n);
- }
- else if (nodeh >= h - k) {
- memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((idx >> nodeh) - 3) >> 1)) * n, state->stack+(state->stackoffset-1)*n, n);
- }
- }
- setTreeHeight(node_addr, state->stacklevels[state->stackoffset-1]);
- setTreeIndex(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1)));
- hash_h(state->stack+(state->stackoffset-2)*n, state->stack+(state->stackoffset-2)*n, pub_seed, node_addr, n);
-
- state->stacklevels[state->stackoffset-2]++;
- state->stackoffset--;
- }
- state->next_leaf++;
- return 0;
-}
-
-/**
- * Returns the auth path for node leaf_idx and computes the auth path for the
- * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo
- * in "Post Quantum Cryptography", Springer 2009.
- */
-static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8])
-{
- unsigned int i;
- unsigned int n = params->n;
- unsigned int h = params->h;
- unsigned int k = params->k;
-
- unsigned int tau = h;
- unsigned int startidx;
- unsigned int offset, rowidx;
- unsigned char buf[2 * n];
-
- uint32_t ots_addr[8];
- uint32_t ltree_addr[8];
- uint32_t node_addr[8];
- // only copy layer and tree address parts
- memcpy(ots_addr, addr, 12);
- // type = ots
- setType(ots_addr, 0);
- memcpy(ltree_addr, addr, 12);
- setType(ltree_addr, 1);
- memcpy(node_addr, addr, 12);
- setType(node_addr, 2);
-
- for (i = 0; i < h; i++) {
- if (! ((leaf_idx >> i) & 1)) {
- tau = i;
- break;
- }
- }
-
- if (tau > 0) {
- memcpy(buf, state->auth + (tau-1) * n, n);
- // we need to do this before refreshing state->keep to prevent overwriting
- memcpy(buf + n, state->keep + ((tau-1) >> 1) * n, n);
- }
- if (!((leaf_idx >> (tau + 1)) & 1) && (tau < h - 1)) {
- memcpy(state->keep + (tau >> 1)*n, state->auth + tau*n, n);
- }
- if (tau == 0) {
- setLtreeADRS(ltree_addr, leaf_idx);
- setOTSADRS(ots_addr, leaf_idx);
- gen_leaf_wots(state->auth, sk_seed, params, pub_seed, ltree_addr, ots_addr);
- }
- else {
- setTreeHeight(node_addr, (tau-1));
- setTreeIndex(node_addr, leaf_idx >> tau);
- hash_h(state->auth + tau * n, buf, pub_seed, node_addr, n);
- for (i = 0; i < tau; i++) {
- if (i < h - k) {
- memcpy(state->auth + i * n, state->treehash[i].node, n);
- }
- else {
- offset = (1 << (h - 1 - i)) + i - h;
- rowidx = ((leaf_idx >> i) - 1) >> 1;
- memcpy(state->auth + i * n, state->retain + (offset + rowidx) * n, n);
- }
- }
-
- for (i = 0; i < ((tau < h - k) ? tau : (h - k)); i++) {
- startidx = leaf_idx + 1 + 3 * (1 << i);
- if (startidx < 1U << h) {
- state->treehash[i].h = i;
- state->treehash[i].next_idx = startidx;
- state->treehash[i].completed = 0;
- state->treehash[i].stackusage = 0;
- }
- }
- }
-}
-
-/*
- * Generates a XMSS key pair for a given parameter set.
- * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
- * Format pk: [root || PUB_SEED] omitting algo oid.
- */
-int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params)
-{
- unsigned int n = params->n;
- // Set idx = 0
- sk[0] = 0;
- sk[1] = 0;
- sk[2] = 0;
- sk[3] = 0;
- // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte)
- randombytes(sk+4, 3*n);
- // Copy PUB_SEED to public key
- memcpy(pk+n, sk+4+2*n, n);
-
- uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-
- // Compute root
- treehash_setup(pk, params->h, 0, state, sk+4, params, sk+4+2*n, addr);
- // copy root to sk
- memcpy(sk+4+3*n, pk, n);
- return 0;
-}
-
-/**
- * Signs a message.
- * Returns
- * 1. an array containing the signature followed by the message AND
- * 2. an updated secret key!
- *
- */
-int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmss_params *params)
-{
- unsigned int h = params->h;
- unsigned int n = params->n;
- unsigned int k = params->k;
- uint16_t i = 0;
-
- // Extract SK
- unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3];
- unsigned char sk_seed[n];
- memcpy(sk_seed, sk+4, n);
- unsigned char sk_prf[n];
- memcpy(sk_prf, sk+4+n, n);
- unsigned char pub_seed[n];
- memcpy(pub_seed, sk+4+2*n, n);
-
- // index as 32 bytes string
- unsigned char idx_bytes_32[32];
- to_byte(idx_bytes_32, idx, 32);
-
- unsigned char hash_key[3*n];
-
- // Update SK
- sk[0] = ((idx + 1) >> 24) & 255;
- sk[1] = ((idx + 1) >> 16) & 255;
- sk[2] = ((idx + 1) >> 8) & 255;
- sk[3] = (idx + 1) & 255;
- // -- Secret key for this non-forward-secure version is now updated.
- // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
-
- // Init working params
- unsigned char R[n];
- unsigned char msg_h[n];
- unsigned char ots_seed[n];
- uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-
- // ---------------------------------
- // Message Hashing
- // ---------------------------------
-
- // Message Hash:
- // First compute pseudorandom value
- prf(R, idx_bytes_32, sk_prf, n);
- // Generate hash key (R || root || idx)
- memcpy(hash_key, R, n);
- memcpy(hash_key+n, sk+4+3*n, n);
- to_byte(hash_key+2*n, idx, n);
- // Then use it for message digest
- h_msg(msg_h, msg, msglen, hash_key, 3*n, n);
-
- // Start collecting signature
- *sig_msg_len = 0;
-
- // Copy index to signature
- sig_msg[0] = (idx >> 24) & 255;
- sig_msg[1] = (idx >> 16) & 255;
- sig_msg[2] = (idx >> 8) & 255;
- sig_msg[3] = idx & 255;
-
- sig_msg += 4;
- *sig_msg_len += 4;
-
- // Copy R to signature
- for (i = 0; i < n; i++)
- sig_msg[i] = R[i];
-
- sig_msg += n;
- *sig_msg_len += n;
-
- // ----------------------------------
- // Now we start to "really sign"
- // ----------------------------------
-
- // Prepare Address
- setType(ots_addr, 0);
- setOTSADRS(ots_addr, idx);
-
- // Compute seed for OTS key pair
- get_seed(ots_seed, sk_seed, n, ots_addr);
-
- // Compute WOTS signature
- wots_sign(sig_msg, msg_h, ots_seed, &(params->wots_par), pub_seed, ots_addr);
-
- sig_msg += params->wots_par.keysize;
- *sig_msg_len += params->wots_par.keysize;
-
- // the auth path was already computed during the previous round
- memcpy(sig_msg, state->auth, h*n);
-
- if (idx < (1U << h) - 1) {
- bds_round(state, idx, sk_seed, params, pub_seed, ots_addr);
- bds_treehash_update(state, (h - k) >> 1, sk_seed, params, pub_seed, ots_addr);
- }
-
-/* TODO: save key/bds state here! */
-
- sig_msg += params->h*n;
- *sig_msg_len += params->h*n;
-
- //Whipe secret elements?
- //zerobytes(tsk, CRYPTO_SECRETKEYBYTES);
-
-
- memcpy(sig_msg, msg, msglen);
- *sig_msg_len += msglen;
-
- return 0;
-}
-
-/**
- * Verifies a given message signature pair under a given public key.
- */
-int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params)
-{
- unsigned int n = params->n;
-
- unsigned long long i, m_len;
- unsigned long idx=0;
- unsigned char wots_pk[params->wots_par.keysize];
- unsigned char pkhash[n];
- unsigned char root[n];
- unsigned char msg_h[n];
- unsigned char hash_key[3*n];
-
- unsigned char pub_seed[n];
- memcpy(pub_seed, pk+n, n);
-
- // Init addresses
- uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-
- setType(ots_addr, 0);
- setType(ltree_addr, 1);
- setType(node_addr, 2);
-
- // Extract index
- idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3];
- printf("verify:: idx = %lu\n", idx);
-
- // Generate hash key (R || root || idx)
- memcpy(hash_key, sig_msg+4,n);
- memcpy(hash_key+n, pk, n);
- to_byte(hash_key+2*n, idx, n);
-
- sig_msg += (n+4);
- sig_msg_len -= (n+4);
-
- // hash message
- unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n;
- m_len = sig_msg_len - tmp_sig_len;
- h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n);
-
- //-----------------------
- // Verify signature
- //-----------------------
-
- // Prepare Address
- setOTSADRS(ots_addr, idx);
- // Check WOTS signature
- wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->wots_par), pub_seed, ots_addr);
-
- sig_msg += params->wots_par.keysize;
- sig_msg_len -= params->wots_par.keysize;
-
- // Compute Ltree
- setLtreeADRS(ltree_addr, idx);
- l_tree(pkhash, wots_pk, params, pub_seed, ltree_addr);
-
- // Compute root
- validate_authpath(root, pkhash, idx, sig_msg, params, pub_seed, node_addr);
-
- sig_msg += params->h*n;
- sig_msg_len -= params->h*n;
-
- for (i = 0; i < n; i++)
- if (root[i] != pk[i])
- goto fail;
-
- *msglen = sig_msg_len;
- for (i = 0; i < *msglen; i++)
- msg[i] = sig_msg[i];
-
- return 0;
-
-
-fail:
- *msglen = sig_msg_len;
- for (i = 0; i < *msglen; i++)
- msg[i] = 0;
- *msglen = -1;
- return -1;
-}
-
-/*
- * Generates a XMSSMT key pair for a given parameter set.
- * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
- * Format pk: [root || PUB_SEED] omitting algo oid.
- */
-int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params)
-{
- unsigned int n = params->n;
- unsigned int i;
- unsigned char ots_seed[params->n];
- // Set idx = 0
- for (i = 0; i < params->index_len; i++) {
- sk[i] = 0;
- }
- // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte)
- randombytes(sk+params->index_len, 3*n);
- // Copy PUB_SEED to public key
- memcpy(pk+n, sk+params->index_len+2*n, n);
-
- // Set address to point on the single tree on layer d-1
- uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- setLayerADRS(addr, (params->d-1));
- // Set up state and compute wots signatures for all but topmost tree root
- for (i = 0; i < params->d - 1; i++) {
- // Compute seed for OTS key pair
- treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr);
- setLayerADRS(addr, (i+1));
- get_seed(ots_seed, sk+params->index_len, n, addr);
- wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, pk, ots_seed, &(params->xmss_par.wots_par), pk+n, addr);
- }
- treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr);
- memcpy(sk+params->index_len+3*n, pk, n);
- return 0;
-}
-
-/**
- * Signs a message.
- * Returns
- * 1. an array containing the signature followed by the message AND
- * 2. an updated secret key!
- *
- */
-int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params)
-{
- unsigned int n = params->n;
-
- unsigned int tree_h = params->xmss_par.h;
- unsigned int h = params->h;
- unsigned int k = params->xmss_par.k;
- unsigned int idx_len = params->index_len;
- uint64_t idx_tree;
- uint32_t idx_leaf;
- uint64_t i, j;
- int needswap_upto = -1;
- unsigned int updates;
-
- unsigned char sk_seed[n];
- unsigned char sk_prf[n];
- unsigned char pub_seed[n];
- // Init working params
- unsigned char R[n];
- unsigned char msg_h[n];
- unsigned char hash_key[3*n];
- unsigned char ots_seed[n];
- uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- unsigned char idx_bytes_32[32];
- bds_state tmp;
-
- // Extract SK
- unsigned long long idx = 0;
- for (i = 0; i < idx_len; i++) {
- idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - i);
- }
-
- memcpy(sk_seed, sk+idx_len, n);
- memcpy(sk_prf, sk+idx_len+n, n);
- memcpy(pub_seed, sk+idx_len+2*n, n);
-
- // Update SK
- for (i = 0; i < idx_len; i++) {
- sk[i] = ((idx + 1) >> 8*(idx_len - 1 - i)) & 255;
- }
- // -- Secret key for this non-forward-secure version is now updated.
- // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
-
-
- // ---------------------------------
- // Message Hashing
- // ---------------------------------
-
- // Message Hash:
- // First compute pseudorandom value
- to_byte(idx_bytes_32, idx, 32);
- prf(R, idx_bytes_32, sk_prf, n);
- // Generate hash key (R || root || idx)
- memcpy(hash_key, R, n);
- memcpy(hash_key+n, sk+idx_len+3*n, n);
- to_byte(hash_key+2*n, idx, n);
-
- // Then use it for message digest
- h_msg(msg_h, msg, msglen, hash_key, 3*n, n);
-
- // Start collecting signature
- *sig_msg_len = 0;
-
- // Copy index to signature
- for (i = 0; i < idx_len; i++) {
- sig_msg[i] = (idx >> 8*(idx_len - 1 - i)) & 255;
- }
-
- sig_msg += idx_len;
- *sig_msg_len += idx_len;
-
- // Copy R to signature
- for (i = 0; i < n; i++)
- sig_msg[i] = R[i];
-
- sig_msg += n;
- *sig_msg_len += n;
-
- // ----------------------------------
- // Now we start to "really sign"
- // ----------------------------------
-
- // Handle lowest layer separately as it is slightly different...
-
- // Prepare Address
- setType(ots_addr, 0);
- idx_tree = idx >> tree_h;
- idx_leaf = (idx & ((1 << tree_h)-1));
- setLayerADRS(ots_addr, 0);
- setTreeADRS(ots_addr, idx_tree);
- setOTSADRS(ots_addr, idx_leaf);
-
- // Compute seed for OTS key pair
- get_seed(ots_seed, sk_seed, n, ots_addr);
-
- // Compute WOTS signature
- wots_sign(sig_msg, msg_h, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr);
-
- sig_msg += params->xmss_par.wots_par.keysize;
- *sig_msg_len += params->xmss_par.wots_par.keysize;
-
- memcpy(sig_msg, states[0].auth, tree_h*n);
- sig_msg += tree_h*n;
- *sig_msg_len += tree_h*n;
-
- // prepare signature of remaining layers
- for (i = 1; i < params->d; i++) {
- // put WOTS signature in place
- memcpy(sig_msg, wots_sigs + (i-1)*params->xmss_par.wots_par.keysize, params->xmss_par.wots_par.keysize);
-
- sig_msg += params->xmss_par.wots_par.keysize;
- *sig_msg_len += params->xmss_par.wots_par.keysize;
-
- // put AUTH nodes in place
- memcpy(sig_msg, states[i].auth, tree_h*n);
- sig_msg += tree_h*n;
- *sig_msg_len += tree_h*n;
- }
-
- updates = (tree_h - k) >> 1;
-
- setTreeADRS(addr, (idx_tree + 1));
- // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists
- if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << h)) {
- bds_state_update(&states[params->d], sk_seed, &(params->xmss_par), pub_seed, addr);
- }
-
- for (i = 0; i < params->d; i++) {
- // check if we're not at the end of a tree
- if (! (((idx + 1) & ((1ULL << ((i+1)*tree_h)) - 1)) == 0)) {
- idx_leaf = (idx >> (tree_h * i)) & ((1 << tree_h)-1);
- idx_tree = (idx >> (tree_h * (i+1)));
- setLayerADRS(addr, i);
- setTreeADRS(addr, idx_tree);
- if (i == (unsigned int) (needswap_upto + 1)) {
- bds_round(&states[i], idx_leaf, sk_seed, &(params->xmss_par), pub_seed, addr);
- }
- updates = bds_treehash_update(&states[i], updates, sk_seed, &(params->xmss_par), pub_seed, addr);
- setTreeADRS(addr, (idx_tree + 1));
- // if a NEXT-tree exists for this level;
- if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << (h - tree_h * i))) {
- if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << h)) {
- bds_state_update(&states[params->d + i], sk_seed, &(params->xmss_par), pub_seed, addr);
- updates--;
- }
- }
- }
- else if (idx < (1ULL << h) - 1) {
- memcpy(&tmp, states+params->d + i, sizeof(bds_state));
- memcpy(states+params->d + i, states + i, sizeof(bds_state));
- memcpy(states + i, &tmp, sizeof(bds_state));
-
- setLayerADRS(ots_addr, (i+1));
- setTreeADRS(ots_addr, ((idx + 1) >> ((i+2) * tree_h)));
- setOTSADRS(ots_addr, (((idx >> ((i+1) * tree_h)) + 1) & ((1 << tree_h)-1)));
-
- get_seed(ots_seed, sk+params->index_len, n, ots_addr);
- wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, states[i].stack, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr);
-
- states[params->d + i].stackoffset = 0;
- states[params->d + i].next_leaf = 0;
-
- updates--; // WOTS-signing counts as one update
- needswap_upto = i;
- for (j = 0; j < tree_h-k; j++) {
- states[i].treehash[j].completed = 1;
- }
- }
- }
-
- //Whipe secret elements?
- //zerobytes(tsk, CRYPTO_SECRETKEYBYTES);
-
- memcpy(sig_msg, msg, msglen);
- *sig_msg_len += msglen;
-
- return 0;
-}
-
-/**
- * Verifies a given message signature pair under a given public key.
- */
-int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params)
-{
- unsigned int n = params->n;
-
- unsigned int tree_h = params->xmss_par.h;
- unsigned int idx_len = params->index_len;
- uint64_t idx_tree;
- uint32_t idx_leaf;
-
- unsigned long long i, m_len;
- unsigned long long idx=0;
- unsigned char wots_pk[params->xmss_par.wots_par.keysize];
- unsigned char pkhash[n];
- unsigned char root[n];
- unsigned char msg_h[n];
- unsigned char hash_key[3*n];
-
- unsigned char pub_seed[n];
- memcpy(pub_seed, pk+n, n);
-
- // Init addresses
- uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-
- // Extract index
- for (i = 0; i < idx_len; i++) {
- idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i));
- }
- printf("verify:: idx = %llu\n", idx);
- sig_msg += idx_len;
- sig_msg_len -= idx_len;
-
- // Generate hash key (R || root || idx)
- memcpy(hash_key, sig_msg,n);
- memcpy(hash_key+n, pk, n);
- to_byte(hash_key+2*n, idx, n);
-
- sig_msg += n;
- sig_msg_len -= n;
-
-
- // hash message (recall, R is now on pole position at sig_msg
- unsigned long long tmp_sig_len = (params->d * params->xmss_par.wots_par.keysize) + (params->h * n);
- m_len = sig_msg_len - tmp_sig_len;
- h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n);
-
-
- //-----------------------
- // Verify signature
- //-----------------------
-
- // Prepare Address
- idx_tree = idx >> tree_h;
- idx_leaf = (idx & ((1 << tree_h)-1));
- setLayerADRS(ots_addr, 0);
- setTreeADRS(ots_addr, idx_tree);
- setType(ots_addr, 0);
-
- memcpy(ltree_addr, ots_addr, 12);
- setType(ltree_addr, 1);
-
- memcpy(node_addr, ltree_addr, 12);
- setType(node_addr, 2);
-
- setOTSADRS(ots_addr, idx_leaf);
-
- // Check WOTS signature
- wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr);
-
- sig_msg += params->xmss_par.wots_par.keysize;
- sig_msg_len -= params->xmss_par.wots_par.keysize;
-
- // Compute Ltree
- setLtreeADRS(ltree_addr, idx_leaf);
- l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
-
- // Compute root
- validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
-
- sig_msg += tree_h*n;
- sig_msg_len -= tree_h*n;
-
- for (i = 1; i < params->d; i++) {
- // Prepare Address
- idx_leaf = (idx_tree & ((1 << tree_h)-1));
- idx_tree = idx_tree >> tree_h;
-
- setLayerADRS(ots_addr, i);
- setTreeADRS(ots_addr, idx_tree);
- setType(ots_addr, 0);
-
- memcpy(ltree_addr, ots_addr, 12);
- setType(ltree_addr, 1);
-
- memcpy(node_addr, ltree_addr, 12);
- setType(node_addr, 2);
-
- setOTSADRS(ots_addr, idx_leaf);
-
- // Check WOTS signature
- wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr);
-
- sig_msg += params->xmss_par.wots_par.keysize;
- sig_msg_len -= params->xmss_par.wots_par.keysize;
-
- // Compute Ltree
- setLtreeADRS(ltree_addr, idx_leaf);
- l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
-
- // Compute root
- validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
-
- sig_msg += tree_h*n;
- sig_msg_len -= tree_h*n;
-
- }
-
- for (i = 0; i < n; i++)
- if (root[i] != pk[i])
- goto fail;
-
- *msglen = sig_msg_len;
- for (i = 0; i < *msglen; i++)
- msg[i] = sig_msg[i];
-
- return 0;
-
-
-fail:
- *msglen = sig_msg_len;
- for (i = 0; i < *msglen; i++)
- msg[i] = 0;
- *msglen = -1;
- return -1;
-}
-#endif /* WITH_XMSS */
+++ /dev/null
-#ifdef WITH_XMSS
-/* $OpenBSD: xmss_fast.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
-/*
-xmss_fast.h version 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-
-#include "xmss_wots.h"
-
-#ifndef XMSS_H
-#define XMSS_H
-typedef struct{
- unsigned int level;
- unsigned long long subtree;
- unsigned int subleaf;
-} leafaddr;
-
-typedef struct{
- wots_params wots_par;
- unsigned int n;
- unsigned int h;
- unsigned int k;
-} xmss_params;
-
-typedef struct{
- xmss_params xmss_par;
- unsigned int n;
- unsigned int h;
- unsigned int d;
- unsigned int index_len;
-} xmssmt_params;
-
-typedef struct{
- unsigned int h;
- unsigned int next_idx;
- unsigned int stackusage;
- unsigned char completed;
- unsigned char *node;
-} treehash_inst;
-
-typedef struct {
- unsigned char *stack;
- unsigned int stackoffset;
- unsigned char *stacklevels;
- unsigned char *auth;
- unsigned char *keep;
- treehash_inst *treehash;
- unsigned char *retain;
- unsigned int next_leaf;
-} bds_state;
-
-/**
- * Initialize BDS state struct
- * parameter names are the same as used in the description of the BDS traversal
- */
-void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf);
-/**
- * Initializes parameter set.
- * Needed, for any of the other methods.
- */
-int xmss_set_params(xmss_params *params, int n, int h, int w, int k);
-/**
- * Initialize xmssmt_params struct
- * parameter names are the same as in the draft
- *
- * Especially h is the total tree height, i.e. the XMSS trees have height h/d
- */
-int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k);
-/**
- * Generates a XMSS key pair for a given parameter set.
- * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
- * Format pk: [root || PUB_SEED] omitting algo oid.
- */
-int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params);
-/**
- * Signs a message.
- * Returns
- * 1. an array containing the signature followed by the message AND
- * 2. an updated secret key!
- *
- */
-int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg,unsigned long long msglen, const xmss_params *params);
-/**
- * Verifies a given message signature pair under a given public key.
- *
- * Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg).
- */
-int xmss_sign_open(unsigned char *msg,unsigned long long *msglen, const unsigned char *sig_msg,unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params);
-
-/*
- * Generates a XMSSMT key pair for a given parameter set.
- * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
- * Format pk: [root || PUB_SEED] omitting algo oid.
- */
-int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params);
-/**
- * Signs a message.
- * Returns
- * 1. an array containing the signature followed by the message AND
- * 2. an updated secret key!
- *
- */
-int xmssmt_sign(unsigned char *sk, bds_state *state, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params);
-/**
- * Verifies a given message signature pair under a given public key.
- */
-int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params);
-#endif
-#endif /* WITH_XMSS */
+++ /dev/null
-/* $OpenBSD: xmss_hash.c,v 1.4 2023/12/20 00:06:25 jsg Exp $ */
-/*
-hash.c version 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-
-#include "includes.h"
-#ifdef WITH_XMSS
-
-#include "xmss_hash_address.h"
-#include "xmss_commons.h"
-#include "xmss_hash.h"
-
-#include <stddef.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#include <stdio.h>
-#include <string.h>
-
-int core_hash_SHA2(unsigned char *, const unsigned int, const unsigned char *,
- unsigned int, const unsigned char *, unsigned long long, unsigned int);
-
-unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]){
-#if IS_LITTLE_ENDIAN==1
- int i = 0;
- for(i=0;i<8;i++)
- to_byte(bytes+i*4, addr[i],4);
- return bytes;
-#else
- memcpy(bytes, addr, 32);
- return bytes;
-#endif
-}
-
-int core_hash_SHA2(unsigned char *out, const unsigned int type, const unsigned char *key, unsigned int keylen, const unsigned char *in, unsigned long long inlen, unsigned int n){
- unsigned long long i = 0;
- unsigned char buf[inlen + n + keylen];
-
- // Input is (toByte(X, 32) || KEY || M)
-
- // set toByte
- to_byte(buf, type, n);
-
- for (i=0; i < keylen; i++) {
- buf[i+n] = key[i];
- }
-
- for (i=0; i < inlen; i++) {
- buf[keylen + n + i] = in[i];
- }
-
- if (n == 32) {
- SHA256(buf, inlen + keylen + n, out);
- return 0;
- }
- else {
- if (n == 64) {
- SHA512(buf, inlen + keylen + n, out);
- return 0;
- }
- }
- return 1;
-}
-
-/**
- * Implements PRF
- */
-int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen)
-{
- return core_hash_SHA2(out, 3, key, keylen, in, 32, keylen);
-}
-
-/*
- * Implements H_msg
- */
-int h_msg(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n)
-{
- if (keylen != 3*n){
- // H_msg takes 3n-bit keys, but n does not match the keylength of keylen
- return -1;
- }
- return core_hash_SHA2(out, 2, key, keylen, in, inlen, n);
-}
-
-/**
- * We assume the left half is in in[0]...in[n-1]
- */
-int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n)
-{
-
- unsigned char buf[2*n];
- unsigned char key[n];
- unsigned char bitmask[2*n];
- unsigned char byte_addr[32];
- unsigned int i;
-
- setKeyAndMask(addr, 0);
- addr_to_byte(byte_addr, addr);
- prf(key, byte_addr, pub_seed, n);
- // Use MSB order
- setKeyAndMask(addr, 1);
- addr_to_byte(byte_addr, addr);
- prf(bitmask, byte_addr, pub_seed, n);
- setKeyAndMask(addr, 2);
- addr_to_byte(byte_addr, addr);
- prf(bitmask+n, byte_addr, pub_seed, n);
- for (i = 0; i < 2*n; i++) {
- buf[i] = in[i] ^ bitmask[i];
- }
- return core_hash_SHA2(out, 1, key, n, buf, 2*n, n);
-}
-
-int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n)
-{
- unsigned char buf[n];
- unsigned char key[n];
- unsigned char bitmask[n];
- unsigned char byte_addr[32];
- unsigned int i;
-
- setKeyAndMask(addr, 0);
- addr_to_byte(byte_addr, addr);
- prf(key, byte_addr, pub_seed, n);
-
- setKeyAndMask(addr, 1);
- addr_to_byte(byte_addr, addr);
- prf(bitmask, byte_addr, pub_seed, n);
-
- for (i = 0; i < n; i++) {
- buf[i] = in[i] ^ bitmask[i];
- }
- return core_hash_SHA2(out, 0, key, n, buf, n, n);
-}
-#endif /* WITH_XMSS */
+++ /dev/null
-#ifdef WITH_XMSS
-/* $OpenBSD: xmss_hash.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
-/*
-hash.h version 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-
-#ifndef HASH_H
-#define HASH_H
-
-#define IS_LITTLE_ENDIAN 1
-
-unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]);
-int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen);
-int h_msg(unsigned char *out,const unsigned char *in,unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n);
-int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n);
-int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n);
-
-#endif
-#endif /* WITH_XMSS */
+++ /dev/null
-/* $OpenBSD: xmss_hash_address.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
-/*
-hash_address.c version 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-#include "includes.h"
-#ifdef WITH_XMSS
-
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#include "xmss_hash_address.h" /* prototypes */
-
-void setLayerADRS(uint32_t adrs[8], uint32_t layer){
- adrs[0] = layer;
-}
-
-void setTreeADRS(uint32_t adrs[8], uint64_t tree){
- adrs[1] = (uint32_t) (tree >> 32);
- adrs[2] = (uint32_t) tree;
-}
-
-void setType(uint32_t adrs[8], uint32_t type){
- adrs[3] = type;
- int i;
- for(i = 4; i < 8; i++){
- adrs[i] = 0;
- }
-}
-
-void setKeyAndMask(uint32_t adrs[8], uint32_t keyAndMask){
- adrs[7] = keyAndMask;
-}
-
-// OTS
-
-void setOTSADRS(uint32_t adrs[8], uint32_t ots){
- adrs[4] = ots;
-}
-
-void setChainADRS(uint32_t adrs[8], uint32_t chain){
- adrs[5] = chain;
-}
-
-void setHashADRS(uint32_t adrs[8], uint32_t hash){
- adrs[6] = hash;
-}
-
-// L-tree
-
-void setLtreeADRS(uint32_t adrs[8], uint32_t ltree){
- adrs[4] = ltree;
-}
-
-// Hash Tree & L-tree
-
-void setTreeHeight(uint32_t adrs[8], uint32_t treeHeight){
- adrs[5] = treeHeight;
-}
-
-void setTreeIndex(uint32_t adrs[8], uint32_t treeIndex){
- adrs[6] = treeIndex;
-}
-#endif /* WITH_XMSS */
+++ /dev/null
-#ifdef WITH_XMSS
-/* $OpenBSD: xmss_hash_address.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */
-/*
-hash_address.h version 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
-void setLayerADRS(uint32_t adrs[8], uint32_t layer);
-
-void setTreeADRS(uint32_t adrs[8], uint64_t tree);
-
-void setType(uint32_t adrs[8], uint32_t type);
-
-void setKeyAndMask(uint32_t adrs[8], uint32_t keyAndMask);
-
-// OTS
-
-void setOTSADRS(uint32_t adrs[8], uint32_t ots);
-
-void setChainADRS(uint32_t adrs[8], uint32_t chain);
-
-void setHashADRS(uint32_t adrs[8], uint32_t hash);
-
-// L-tree
-
-void setLtreeADRS(uint32_t adrs[8], uint32_t ltree);
-
-// Hash Tree & L-tree
-
-void setTreeHeight(uint32_t adrs[8], uint32_t treeHeight);
-
-void setTreeIndex(uint32_t adrs[8], uint32_t treeIndex);
-
-#endif /* WITH_XMSS */
+++ /dev/null
-/* $OpenBSD: xmss_wots.c,v 1.3 2018/04/10 00:10:49 djm Exp $ */
-/*
-wots.c version 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-
-#include "includes.h"
-#ifdef WITH_XMSS
-
-#include <stdlib.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#include <limits.h>
-#include "xmss_commons.h"
-#include "xmss_hash.h"
-#include "xmss_wots.h"
-#include "xmss_hash_address.h"
-
-
-/* libm-free version of log2() for wots */
-static inline int
-wots_log2(uint32_t v)
-{
- int b;
-
- for (b = sizeof (v) * CHAR_BIT - 1; b >= 0; b--) {
- if ((1U << b) & v) {
- return b;
- }
- }
- return 0;
-}
-
-void
-wots_set_params(wots_params *params, int n, int w)
-{
- params->n = n;
- params->w = w;
- params->log_w = wots_log2(params->w);
- params->len_1 = (CHAR_BIT * n) / params->log_w;
- params->len_2 = (wots_log2(params->len_1 * (w - 1)) / params->log_w) + 1;
- params->len = params->len_1 + params->len_2;
- params->keysize = params->len * params->n;
-}
-
-/**
- * Helper method for pseudorandom key generation
- * Expands an n-byte array into a len*n byte array
- * this is done using PRF
- */
-static void expand_seed(unsigned char *outseeds, const unsigned char *inseed, const wots_params *params)
-{
- uint32_t i = 0;
- unsigned char ctr[32];
- for(i = 0; i < params->len; i++){
- to_byte(ctr, i, 32);
- prf((outseeds + (i*params->n)), ctr, inseed, params->n);
- }
-}
-
-/**
- * Computes the chaining function.
- * out and in have to be n-byte arrays
- *
- * interprets in as start-th value of the chain
- * addr has to contain the address of the chain
- */
-static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8])
-{
- uint32_t i, j;
- for (j = 0; j < params->n; j++)
- out[j] = in[j];
-
- for (i = start; i < (start+steps) && i < params->w; i++) {
- setHashADRS(addr, i);
- hash_f(out, out, pub_seed, addr, params->n);
- }
-}
-
-/**
- * base_w algorithm as described in draft.
- *
- *
- */
-static void base_w(int *output, const int out_len, const unsigned char *input, const wots_params *params)
-{
- int in = 0;
- int out = 0;
- uint32_t total = 0;
- int bits = 0;
- int consumed = 0;
-
- for (consumed = 0; consumed < out_len; consumed++) {
- if (bits == 0) {
- total = input[in];
- in++;
- bits += 8;
- }
- bits -= params->log_w;
- output[out] = (total >> bits) & (params->w - 1);
- out++;
- }
-}
-
-void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8])
-{
- uint32_t i;
- expand_seed(pk, sk, params);
- for (i=0; i < params->len; i++) {
- setChainADRS(addr, i);
- gen_chain(pk+i*params->n, pk+i*params->n, 0, params->w-1, params, pub_seed, addr);
- }
-}
-
-
-int wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8])
-{
- //int basew[params->len];
- int csum = 0;
- uint32_t i = 0;
- int *basew = calloc(params->len, sizeof(int));
- if (basew == NULL)
- return -1;
-
- base_w(basew, params->len_1, msg, params);
-
- for (i=0; i < params->len_1; i++) {
- csum += params->w - 1 - basew[i];
- }
-
- csum = csum << (8 - ((params->len_2 * params->log_w) % 8));
-
- int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8;
-
- unsigned char csum_bytes[len_2_bytes];
- to_byte(csum_bytes, csum, len_2_bytes);
-
- int csum_basew[params->len_2];
- base_w(csum_basew, params->len_2, csum_bytes, params);
-
- for (i = 0; i < params->len_2; i++) {
- basew[params->len_1 + i] = csum_basew[i];
- }
-
- expand_seed(sig, sk, params);
-
- for (i = 0; i < params->len; i++) {
- setChainADRS(addr, i);
- gen_chain(sig+i*params->n, sig+i*params->n, 0, basew[i], params, pub_seed, addr);
- }
- free(basew);
- return 0;
-}
-
-int wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8])
-{
- int csum = 0;
- uint32_t i = 0;
- int *basew = calloc(params->len, sizeof(int));
- if (basew == NULL)
- return -1;
-
- base_w(basew, params->len_1, msg, params);
-
- for (i=0; i < params->len_1; i++) {
- csum += params->w - 1 - basew[i];
- }
-
- csum = csum << (8 - ((params->len_2 * params->log_w) % 8));
-
- int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8;
-
- unsigned char csum_bytes[len_2_bytes];
- to_byte(csum_bytes, csum, len_2_bytes);
-
- int csum_basew[params->len_2];
- base_w(csum_basew, params->len_2, csum_bytes, params);
-
- for (i = 0; i < params->len_2; i++) {
- basew[params->len_1 + i] = csum_basew[i];
- }
- for (i=0; i < params->len; i++) {
- setChainADRS(addr, i);
- gen_chain(pk+i*params->n, sig+i*params->n, basew[i], params->w-1-basew[i], params, pub_seed, addr);
- }
- free(basew);
- return 0;
-}
-#endif /* WITH_XMSS */
+++ /dev/null
-#ifdef WITH_XMSS
-/* $OpenBSD: xmss_wots.h,v 1.3 2018/02/26 12:14:53 dtucker Exp $ */
-/*
-wots.h version 20160722
-Andreas Hülsing
-Joost Rijneveld
-Public domain.
-*/
-
-#ifndef WOTS_H
-#define WOTS_H
-
-#ifdef HAVE_STDINT_H
-#include "stdint.h"
-#endif
-
-/**
- * WOTS parameter set
- *
- * Meaning as defined in draft-irtf-cfrg-xmss-hash-based-signatures-02
- */
-typedef struct {
- uint32_t len_1;
- uint32_t len_2;
- uint32_t len;
- uint32_t n;
- uint32_t w;
- uint32_t log_w;
- uint32_t keysize;
-} wots_params;
-
-/**
- * Set the WOTS parameters,
- * only m, n, w are required as inputs,
- * len, len_1, and len_2 are computed from those.
- *
- * Assumes w is a power of 2
- */
-void wots_set_params(wots_params *params, int n, int w);
-
-/**
- * WOTS key generation. Takes a 32byte seed for the secret key, expands it to a full WOTS secret key and computes the corresponding public key.
- * For this it takes the seed pub_seed which is used to generate bitmasks and hash keys and the address of this WOTS key pair addr
- *
- * params, must have been initialized before using wots_set params for params ! This is not done in this function
- *
- * Places the computed public key at address pk.
- */
-void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]);
-
-/**
- * Takes a m-byte message and the 32-byte seed for the secret key to compute a signature that is placed at "sig".
- *
- */
-int wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]);
-
-/**
- * Takes a WOTS signature, a m-byte message and computes a WOTS public key that it places at pk.
- *
- */
-int wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]);
-
-#endif
-#endif /* WITH_XMSS */