1f374ba41SEd Maste /* $OpenBSD: ssh-xmss.c,v 1.14 2022/10/28 00:44:44 djm Exp $*/
247dd1d1bSDag-Erling Smørgrav /*
347dd1d1bSDag-Erling Smørgrav * Copyright (c) 2017 Stefan-Lukas Gazdag.
447dd1d1bSDag-Erling Smørgrav * Copyright (c) 2017 Markus Friedl.
547dd1d1bSDag-Erling Smørgrav *
647dd1d1bSDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any
747dd1d1bSDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above
847dd1d1bSDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies.
947dd1d1bSDag-Erling Smørgrav *
1047dd1d1bSDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1147dd1d1bSDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1247dd1d1bSDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1347dd1d1bSDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1447dd1d1bSDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1547dd1d1bSDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1647dd1d1bSDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1747dd1d1bSDag-Erling Smørgrav */
1847dd1d1bSDag-Erling Smørgrav #include "includes.h"
1947dd1d1bSDag-Erling Smørgrav #ifdef WITH_XMSS
2047dd1d1bSDag-Erling Smørgrav
2147dd1d1bSDag-Erling Smørgrav #define SSHKEY_INTERNAL
2247dd1d1bSDag-Erling Smørgrav #include <sys/types.h>
2347dd1d1bSDag-Erling Smørgrav #include <limits.h>
2447dd1d1bSDag-Erling Smørgrav
2538a52bd3SEd Maste #include <stdlib.h>
2647dd1d1bSDag-Erling Smørgrav #include <string.h>
2747dd1d1bSDag-Erling Smørgrav #include <stdarg.h>
28*535af610SEd Maste #ifdef HAVE_STDINT_H
2938a52bd3SEd Maste # include <stdint.h>
30*535af610SEd Maste #endif
3147dd1d1bSDag-Erling Smørgrav #include <unistd.h>
3247dd1d1bSDag-Erling Smørgrav
3347dd1d1bSDag-Erling Smørgrav #include "log.h"
3447dd1d1bSDag-Erling Smørgrav #include "sshbuf.h"
3547dd1d1bSDag-Erling Smørgrav #include "sshkey.h"
3647dd1d1bSDag-Erling Smørgrav #include "sshkey-xmss.h"
3747dd1d1bSDag-Erling Smørgrav #include "ssherr.h"
3847dd1d1bSDag-Erling Smørgrav #include "ssh.h"
3947dd1d1bSDag-Erling Smørgrav
4047dd1d1bSDag-Erling Smørgrav #include "xmss_fast.h"
4147dd1d1bSDag-Erling Smørgrav
42f374ba41SEd Maste static void
ssh_xmss_cleanup(struct sshkey * k)43f374ba41SEd Maste ssh_xmss_cleanup(struct sshkey *k)
44f374ba41SEd Maste {
45f374ba41SEd Maste freezero(k->xmss_pk, sshkey_xmss_pklen(k));
46f374ba41SEd Maste freezero(k->xmss_sk, sshkey_xmss_sklen(k));
47f374ba41SEd Maste sshkey_xmss_free_state(k);
48f374ba41SEd Maste free(k->xmss_name);
49f374ba41SEd Maste free(k->xmss_filename);
50f374ba41SEd Maste k->xmss_pk = NULL;
51f374ba41SEd Maste k->xmss_sk = NULL;
52f374ba41SEd Maste k->xmss_name = NULL;
53f374ba41SEd Maste k->xmss_filename = NULL;
54f374ba41SEd Maste }
55f374ba41SEd Maste
56f374ba41SEd Maste static int
ssh_xmss_equal(const struct sshkey * a,const struct sshkey * b)57f374ba41SEd Maste ssh_xmss_equal(const struct sshkey *a, const struct sshkey *b)
58f374ba41SEd Maste {
59f374ba41SEd Maste if (a->xmss_pk == NULL || b->xmss_pk == NULL)
60f374ba41SEd Maste return 0;
61f374ba41SEd Maste if (sshkey_xmss_pklen(a) != sshkey_xmss_pklen(b))
62f374ba41SEd Maste return 0;
63f374ba41SEd Maste if (memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) != 0)
64f374ba41SEd Maste return 0;
65f374ba41SEd Maste return 1;
66f374ba41SEd Maste }
67f374ba41SEd Maste
68f374ba41SEd Maste static int
ssh_xmss_serialize_public(const struct sshkey * key,struct sshbuf * b,enum sshkey_serialize_rep opts)69f374ba41SEd Maste ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b,
70f374ba41SEd Maste enum sshkey_serialize_rep opts)
71f374ba41SEd Maste {
72f374ba41SEd Maste int r;
73f374ba41SEd Maste
74f374ba41SEd Maste if (key->xmss_name == NULL || key->xmss_pk == NULL ||
75f374ba41SEd Maste sshkey_xmss_pklen(key) == 0)
76f374ba41SEd Maste return SSH_ERR_INVALID_ARGUMENT;
77f374ba41SEd Maste if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
78f374ba41SEd Maste (r = sshbuf_put_string(b, key->xmss_pk,
79f374ba41SEd Maste sshkey_xmss_pklen(key))) != 0 ||
80f374ba41SEd Maste (r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
81f374ba41SEd Maste return r;
82f374ba41SEd Maste
83f374ba41SEd Maste return 0;
84f374ba41SEd Maste }
85f374ba41SEd Maste
86f374ba41SEd Maste static int
ssh_xmss_serialize_private(const struct sshkey * key,struct sshbuf * b,enum sshkey_serialize_rep opts)87f374ba41SEd Maste ssh_xmss_serialize_private(const struct sshkey *key, struct sshbuf *b,
88f374ba41SEd Maste enum sshkey_serialize_rep opts)
89f374ba41SEd Maste {
90f374ba41SEd Maste int r;
91f374ba41SEd Maste
92f374ba41SEd Maste if (key->xmss_name == NULL)
93f374ba41SEd Maste return SSH_ERR_INVALID_ARGUMENT;
94f374ba41SEd Maste /* Note: can't reuse ssh_xmss_serialize_public because of sk order */
95f374ba41SEd Maste if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
96f374ba41SEd Maste (r = sshbuf_put_string(b, key->xmss_pk,
97f374ba41SEd Maste sshkey_xmss_pklen(key))) != 0 ||
98f374ba41SEd Maste (r = sshbuf_put_string(b, key->xmss_sk,
99f374ba41SEd Maste sshkey_xmss_sklen(key))) != 0 ||
100f374ba41SEd Maste (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
101f374ba41SEd Maste return r;
102f374ba41SEd Maste
103f374ba41SEd Maste return 0;
104f374ba41SEd Maste }
105f374ba41SEd Maste
106f374ba41SEd Maste static int
ssh_xmss_copy_public(const struct sshkey * from,struct sshkey * to)107f374ba41SEd Maste ssh_xmss_copy_public(const struct sshkey *from, struct sshkey *to)
108f374ba41SEd Maste {
109f374ba41SEd Maste int r = SSH_ERR_INTERNAL_ERROR;
110f374ba41SEd Maste u_int32_t left;
111f374ba41SEd Maste size_t pklen;
112f374ba41SEd Maste
113f374ba41SEd Maste if ((r = sshkey_xmss_init(to, from->xmss_name)) != 0)
114f374ba41SEd Maste return r;
115f374ba41SEd Maste if (from->xmss_pk == NULL)
116f374ba41SEd Maste return 0; /* XXX SSH_ERR_INTERNAL_ERROR ? */
117f374ba41SEd Maste
118f374ba41SEd Maste if ((pklen = sshkey_xmss_pklen(from)) == 0 ||
119f374ba41SEd Maste sshkey_xmss_pklen(to) != pklen)
120f374ba41SEd Maste return SSH_ERR_INTERNAL_ERROR;
121f374ba41SEd Maste if ((to->xmss_pk = malloc(pklen)) == NULL)
122f374ba41SEd Maste return SSH_ERR_ALLOC_FAIL;
123f374ba41SEd Maste memcpy(to->xmss_pk, from->xmss_pk, pklen);
124f374ba41SEd Maste /* simulate number of signatures left on pubkey */
125f374ba41SEd Maste left = sshkey_xmss_signatures_left(from);
126f374ba41SEd Maste if (left)
127f374ba41SEd Maste sshkey_xmss_enable_maxsign(to, left);
128f374ba41SEd Maste return 0;
129f374ba41SEd Maste }
130f374ba41SEd Maste
131f374ba41SEd Maste static int
ssh_xmss_deserialize_public(const char * ktype,struct sshbuf * b,struct sshkey * key)132f374ba41SEd Maste ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b,
133f374ba41SEd Maste struct sshkey *key)
134f374ba41SEd Maste {
135f374ba41SEd Maste size_t len = 0;
136f374ba41SEd Maste char *xmss_name = NULL;
137f374ba41SEd Maste u_char *pk = NULL;
138f374ba41SEd Maste int ret = SSH_ERR_INTERNAL_ERROR;
139f374ba41SEd Maste
140f374ba41SEd Maste if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
141f374ba41SEd Maste goto out;
142f374ba41SEd Maste if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
143f374ba41SEd Maste goto out;
144f374ba41SEd Maste if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
145f374ba41SEd Maste goto out;
146f374ba41SEd Maste if (len == 0 || len != sshkey_xmss_pklen(key)) {
147f374ba41SEd Maste ret = SSH_ERR_INVALID_FORMAT;
148f374ba41SEd Maste goto out;
149f374ba41SEd Maste }
150f374ba41SEd Maste key->xmss_pk = pk;
151f374ba41SEd Maste pk = NULL;
152f374ba41SEd Maste if (!sshkey_is_cert(key) &&
153f374ba41SEd Maste (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
154f374ba41SEd Maste goto out;
155f374ba41SEd Maste /* success */
156f374ba41SEd Maste ret = 0;
157f374ba41SEd Maste out:
158f374ba41SEd Maste free(xmss_name);
159f374ba41SEd Maste freezero(pk, len);
160f374ba41SEd Maste return ret;
161f374ba41SEd Maste }
162f374ba41SEd Maste
163f374ba41SEd Maste static int
ssh_xmss_deserialize_private(const char * ktype,struct sshbuf * b,struct sshkey * key)164f374ba41SEd Maste ssh_xmss_deserialize_private(const char *ktype, struct sshbuf *b,
165f374ba41SEd Maste struct sshkey *key)
166f374ba41SEd Maste {
167f374ba41SEd Maste int r;
168f374ba41SEd Maste char *xmss_name = NULL;
169f374ba41SEd Maste size_t pklen = 0, sklen = 0;
170f374ba41SEd Maste u_char *xmss_pk = NULL, *xmss_sk = NULL;
171f374ba41SEd Maste
172f374ba41SEd Maste /* Note: can't reuse ssh_xmss_deserialize_public because of sk order */
173f374ba41SEd Maste if ((r = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0 ||
174f374ba41SEd Maste (r = sshbuf_get_string(b, &xmss_pk, &pklen)) != 0 ||
175f374ba41SEd Maste (r = sshbuf_get_string(b, &xmss_sk, &sklen)) != 0)
176f374ba41SEd Maste goto out;
177f374ba41SEd Maste if (!sshkey_is_cert(key) &&
178f374ba41SEd Maste (r = sshkey_xmss_init(key, xmss_name)) != 0)
179f374ba41SEd Maste goto out;
180f374ba41SEd Maste if (pklen != sshkey_xmss_pklen(key) ||
181f374ba41SEd Maste sklen != sshkey_xmss_sklen(key)) {
182f374ba41SEd Maste r = SSH_ERR_INVALID_FORMAT;
183f374ba41SEd Maste goto out;
184f374ba41SEd Maste }
185f374ba41SEd Maste key->xmss_pk = xmss_pk;
186f374ba41SEd Maste key->xmss_sk = xmss_sk;
187f374ba41SEd Maste xmss_pk = xmss_sk = NULL;
188f374ba41SEd Maste /* optional internal state */
189f374ba41SEd Maste if ((r = sshkey_xmss_deserialize_state_opt(key, b)) != 0)
190f374ba41SEd Maste goto out;
191f374ba41SEd Maste /* success */
192f374ba41SEd Maste r = 0;
193f374ba41SEd Maste out:
194f374ba41SEd Maste free(xmss_name);
195f374ba41SEd Maste freezero(xmss_pk, pklen);
196f374ba41SEd Maste freezero(xmss_sk, sklen);
197f374ba41SEd Maste return r;
198f374ba41SEd Maste }
199f374ba41SEd Maste
200f374ba41SEd Maste 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)201f374ba41SEd Maste ssh_xmss_sign(struct sshkey *key,
202f374ba41SEd Maste u_char **sigp, size_t *lenp,
203f374ba41SEd Maste const u_char *data, size_t datalen,
204f374ba41SEd Maste const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
20547dd1d1bSDag-Erling Smørgrav {
20647dd1d1bSDag-Erling Smørgrav u_char *sig = NULL;
20747dd1d1bSDag-Erling Smørgrav size_t slen = 0, len = 0, required_siglen;
20847dd1d1bSDag-Erling Smørgrav unsigned long long smlen;
20947dd1d1bSDag-Erling Smørgrav int r, ret;
21047dd1d1bSDag-Erling Smørgrav struct sshbuf *b = NULL;
21147dd1d1bSDag-Erling Smørgrav
21247dd1d1bSDag-Erling Smørgrav if (lenp != NULL)
21347dd1d1bSDag-Erling Smørgrav *lenp = 0;
21447dd1d1bSDag-Erling Smørgrav if (sigp != NULL)
21547dd1d1bSDag-Erling Smørgrav *sigp = NULL;
21647dd1d1bSDag-Erling Smørgrav
21747dd1d1bSDag-Erling Smørgrav if (key == NULL ||
21847dd1d1bSDag-Erling Smørgrav sshkey_type_plain(key->type) != KEY_XMSS ||
21947dd1d1bSDag-Erling Smørgrav key->xmss_sk == NULL ||
22047dd1d1bSDag-Erling Smørgrav sshkey_xmss_params(key) == NULL)
22147dd1d1bSDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT;
22247dd1d1bSDag-Erling Smørgrav if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0)
22347dd1d1bSDag-Erling Smørgrav return r;
22447dd1d1bSDag-Erling Smørgrav if (datalen >= INT_MAX - required_siglen)
22547dd1d1bSDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT;
22647dd1d1bSDag-Erling Smørgrav smlen = slen = datalen + required_siglen;
22747dd1d1bSDag-Erling Smørgrav if ((sig = malloc(slen)) == NULL)
22847dd1d1bSDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL;
22919261079SEd Maste if ((r = sshkey_xmss_get_state(key, 1)) != 0)
23047dd1d1bSDag-Erling Smørgrav goto out;
23147dd1d1bSDag-Erling Smørgrav if ((ret = xmss_sign(key->xmss_sk, sshkey_xmss_bds_state(key), sig, &smlen,
23247dd1d1bSDag-Erling Smørgrav data, datalen, sshkey_xmss_params(key))) != 0 || smlen <= datalen) {
23347dd1d1bSDag-Erling Smørgrav r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */
23447dd1d1bSDag-Erling Smørgrav goto out;
23547dd1d1bSDag-Erling Smørgrav }
23647dd1d1bSDag-Erling Smørgrav /* encode signature */
23747dd1d1bSDag-Erling Smørgrav if ((b = sshbuf_new()) == NULL) {
23847dd1d1bSDag-Erling Smørgrav r = SSH_ERR_ALLOC_FAIL;
23947dd1d1bSDag-Erling Smørgrav goto out;
24047dd1d1bSDag-Erling Smørgrav }
24147dd1d1bSDag-Erling Smørgrav if ((r = sshbuf_put_cstring(b, "ssh-xmss@openssh.com")) != 0 ||
24247dd1d1bSDag-Erling Smørgrav (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0)
24347dd1d1bSDag-Erling Smørgrav goto out;
24447dd1d1bSDag-Erling Smørgrav len = sshbuf_len(b);
24547dd1d1bSDag-Erling Smørgrav if (sigp != NULL) {
24647dd1d1bSDag-Erling Smørgrav if ((*sigp = malloc(len)) == NULL) {
24747dd1d1bSDag-Erling Smørgrav r = SSH_ERR_ALLOC_FAIL;
24847dd1d1bSDag-Erling Smørgrav goto out;
24947dd1d1bSDag-Erling Smørgrav }
25047dd1d1bSDag-Erling Smørgrav memcpy(*sigp, sshbuf_ptr(b), len);
25147dd1d1bSDag-Erling Smørgrav }
25247dd1d1bSDag-Erling Smørgrav if (lenp != NULL)
25347dd1d1bSDag-Erling Smørgrav *lenp = len;
25447dd1d1bSDag-Erling Smørgrav /* success */
25547dd1d1bSDag-Erling Smørgrav r = 0;
25647dd1d1bSDag-Erling Smørgrav out:
25719261079SEd Maste if ((ret = sshkey_xmss_update_state(key, 1)) != 0) {
25847dd1d1bSDag-Erling Smørgrav /* discard signature since we cannot update the state */
25947dd1d1bSDag-Erling Smørgrav if (r == 0 && sigp != NULL && *sigp != NULL) {
26047dd1d1bSDag-Erling Smørgrav explicit_bzero(*sigp, len);
26147dd1d1bSDag-Erling Smørgrav free(*sigp);
26247dd1d1bSDag-Erling Smørgrav }
26347dd1d1bSDag-Erling Smørgrav if (sigp != NULL)
26447dd1d1bSDag-Erling Smørgrav *sigp = NULL;
26547dd1d1bSDag-Erling Smørgrav if (lenp != NULL)
26647dd1d1bSDag-Erling Smørgrav *lenp = 0;
26747dd1d1bSDag-Erling Smørgrav r = ret;
26847dd1d1bSDag-Erling Smørgrav }
26947dd1d1bSDag-Erling Smørgrav sshbuf_free(b);
27019261079SEd Maste if (sig != NULL)
27119261079SEd Maste freezero(sig, slen);
27247dd1d1bSDag-Erling Smørgrav
27347dd1d1bSDag-Erling Smørgrav return r;
27447dd1d1bSDag-Erling Smørgrav }
27547dd1d1bSDag-Erling Smørgrav
276f374ba41SEd Maste 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)27747dd1d1bSDag-Erling Smørgrav ssh_xmss_verify(const struct sshkey *key,
278f374ba41SEd Maste const u_char *sig, size_t siglen,
279f374ba41SEd Maste const u_char *data, size_t dlen, const char *alg, u_int compat,
280f374ba41SEd Maste struct sshkey_sig_details **detailsp)
28147dd1d1bSDag-Erling Smørgrav {
28247dd1d1bSDag-Erling Smørgrav struct sshbuf *b = NULL;
28347dd1d1bSDag-Erling Smørgrav char *ktype = NULL;
28447dd1d1bSDag-Erling Smørgrav const u_char *sigblob;
28547dd1d1bSDag-Erling Smørgrav u_char *sm = NULL, *m = NULL;
28647dd1d1bSDag-Erling Smørgrav size_t len, required_siglen;
28747dd1d1bSDag-Erling Smørgrav unsigned long long smlen = 0, mlen = 0;
28847dd1d1bSDag-Erling Smørgrav int r, ret;
28947dd1d1bSDag-Erling Smørgrav
29047dd1d1bSDag-Erling Smørgrav if (key == NULL ||
29147dd1d1bSDag-Erling Smørgrav sshkey_type_plain(key->type) != KEY_XMSS ||
29247dd1d1bSDag-Erling Smørgrav key->xmss_pk == NULL ||
29347dd1d1bSDag-Erling Smørgrav sshkey_xmss_params(key) == NULL ||
294f374ba41SEd Maste sig == NULL || siglen == 0)
29547dd1d1bSDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT;
29647dd1d1bSDag-Erling Smørgrav if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0)
29747dd1d1bSDag-Erling Smørgrav return r;
298f374ba41SEd Maste if (dlen >= INT_MAX - required_siglen)
29947dd1d1bSDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT;
30047dd1d1bSDag-Erling Smørgrav
301f374ba41SEd Maste if ((b = sshbuf_from(sig, siglen)) == NULL)
30247dd1d1bSDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL;
30347dd1d1bSDag-Erling Smørgrav if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 ||
30447dd1d1bSDag-Erling Smørgrav (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0)
30547dd1d1bSDag-Erling Smørgrav goto out;
30647dd1d1bSDag-Erling Smørgrav if (strcmp("ssh-xmss@openssh.com", ktype) != 0) {
30747dd1d1bSDag-Erling Smørgrav r = SSH_ERR_KEY_TYPE_MISMATCH;
30847dd1d1bSDag-Erling Smørgrav goto out;
30947dd1d1bSDag-Erling Smørgrav }
31047dd1d1bSDag-Erling Smørgrav if (sshbuf_len(b) != 0) {
31147dd1d1bSDag-Erling Smørgrav r = SSH_ERR_UNEXPECTED_TRAILING_DATA;
31247dd1d1bSDag-Erling Smørgrav goto out;
31347dd1d1bSDag-Erling Smørgrav }
31447dd1d1bSDag-Erling Smørgrav if (len != required_siglen) {
31547dd1d1bSDag-Erling Smørgrav r = SSH_ERR_INVALID_FORMAT;
31647dd1d1bSDag-Erling Smørgrav goto out;
31747dd1d1bSDag-Erling Smørgrav }
318f374ba41SEd Maste if (dlen >= SIZE_MAX - len) {
31947dd1d1bSDag-Erling Smørgrav r = SSH_ERR_INVALID_ARGUMENT;
32047dd1d1bSDag-Erling Smørgrav goto out;
32147dd1d1bSDag-Erling Smørgrav }
322f374ba41SEd Maste smlen = len + dlen;
32347dd1d1bSDag-Erling Smørgrav mlen = smlen;
32447dd1d1bSDag-Erling Smørgrav if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) {
32547dd1d1bSDag-Erling Smørgrav r = SSH_ERR_ALLOC_FAIL;
32647dd1d1bSDag-Erling Smørgrav goto out;
32747dd1d1bSDag-Erling Smørgrav }
32847dd1d1bSDag-Erling Smørgrav memcpy(sm, sigblob, len);
329f374ba41SEd Maste memcpy(sm+len, data, dlen);
33047dd1d1bSDag-Erling Smørgrav if ((ret = xmss_sign_open(m, &mlen, sm, smlen,
33147dd1d1bSDag-Erling Smørgrav key->xmss_pk, sshkey_xmss_params(key))) != 0) {
33219261079SEd Maste debug2_f("xmss_sign_open failed: %d", ret);
33347dd1d1bSDag-Erling Smørgrav }
334f374ba41SEd Maste if (ret != 0 || mlen != dlen) {
33547dd1d1bSDag-Erling Smørgrav r = SSH_ERR_SIGNATURE_INVALID;
33647dd1d1bSDag-Erling Smørgrav goto out;
33747dd1d1bSDag-Erling Smørgrav }
33847dd1d1bSDag-Erling Smørgrav /* XXX compare 'm' and 'data' ? */
33947dd1d1bSDag-Erling Smørgrav /* success */
34047dd1d1bSDag-Erling Smørgrav r = 0;
34147dd1d1bSDag-Erling Smørgrav out:
34219261079SEd Maste if (sm != NULL)
34319261079SEd Maste freezero(sm, smlen);
34419261079SEd Maste if (m != NULL)
34519261079SEd Maste freezero(m, smlen);
34647dd1d1bSDag-Erling Smørgrav sshbuf_free(b);
34747dd1d1bSDag-Erling Smørgrav free(ktype);
34847dd1d1bSDag-Erling Smørgrav return r;
34947dd1d1bSDag-Erling Smørgrav }
350f374ba41SEd Maste
351f374ba41SEd Maste static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
352f374ba41SEd Maste /* .size = */ NULL,
353f374ba41SEd Maste /* .alloc = */ NULL,
354f374ba41SEd Maste /* .cleanup = */ ssh_xmss_cleanup,
355f374ba41SEd Maste /* .equal = */ ssh_xmss_equal,
356f374ba41SEd Maste /* .ssh_serialize_public = */ ssh_xmss_serialize_public,
357f374ba41SEd Maste /* .ssh_deserialize_public = */ ssh_xmss_deserialize_public,
358f374ba41SEd Maste /* .ssh_serialize_private = */ ssh_xmss_serialize_private,
359f374ba41SEd Maste /* .ssh_deserialize_private = */ ssh_xmss_deserialize_private,
360f374ba41SEd Maste /* .generate = */ sshkey_xmss_generate_private_key,
361f374ba41SEd Maste /* .copy_public = */ ssh_xmss_copy_public,
362f374ba41SEd Maste /* .sign = */ ssh_xmss_sign,
363f374ba41SEd Maste /* .verify = */ ssh_xmss_verify,
364f374ba41SEd Maste };
365f374ba41SEd Maste
366f374ba41SEd Maste const struct sshkey_impl sshkey_xmss_impl = {
367f374ba41SEd Maste /* .name = */ "ssh-xmss@openssh.com",
368f374ba41SEd Maste /* .shortname = */ "XMSS",
369f374ba41SEd Maste /* .sigalg = */ NULL,
370f374ba41SEd Maste /* .type = */ KEY_XMSS,
371f374ba41SEd Maste /* .nid = */ 0,
372f374ba41SEd Maste /* .cert = */ 0,
373f374ba41SEd Maste /* .sigonly = */ 0,
374f374ba41SEd Maste /* .keybits = */ 256,
375f374ba41SEd Maste /* .funcs = */ &sshkey_xmss_funcs,
376f374ba41SEd Maste };
377f374ba41SEd Maste
378f374ba41SEd Maste const struct sshkey_impl sshkey_xmss_cert_impl = {
379f374ba41SEd Maste /* .name = */ "ssh-xmss-cert-v01@openssh.com",
380f374ba41SEd Maste /* .shortname = */ "XMSS-CERT",
381f374ba41SEd Maste /* .sigalg = */ NULL,
382f374ba41SEd Maste /* .type = */ KEY_XMSS_CERT,
383f374ba41SEd Maste /* .nid = */ 0,
384f374ba41SEd Maste /* .cert = */ 1,
385f374ba41SEd Maste /* .sigonly = */ 0,
386f374ba41SEd Maste /* .keybits = */ 256,
387f374ba41SEd Maste /* .funcs = */ &sshkey_xmss_funcs,
388f374ba41SEd Maste };
38947dd1d1bSDag-Erling Smørgrav #endif /* WITH_XMSS */
390