1*ba1276acSMatthew Dillon /* $OpenBSD: ssh-xmss.c,v 1.14 2022/10/28 00:44:44 djm Exp $*/
2*ba1276acSMatthew Dillon /*
3*ba1276acSMatthew Dillon * Copyright (c) 2017 Stefan-Lukas Gazdag.
4*ba1276acSMatthew Dillon * Copyright (c) 2017 Markus Friedl.
5*ba1276acSMatthew Dillon *
6*ba1276acSMatthew Dillon * Permission to use, copy, modify, and distribute this software for any
7*ba1276acSMatthew Dillon * purpose with or without fee is hereby granted, provided that the above
8*ba1276acSMatthew Dillon * copyright notice and this permission notice appear in all copies.
9*ba1276acSMatthew Dillon *
10*ba1276acSMatthew Dillon * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*ba1276acSMatthew Dillon * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*ba1276acSMatthew Dillon * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*ba1276acSMatthew Dillon * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*ba1276acSMatthew Dillon * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*ba1276acSMatthew Dillon * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*ba1276acSMatthew Dillon * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*ba1276acSMatthew Dillon */
18*ba1276acSMatthew Dillon #include "includes.h"
19*ba1276acSMatthew Dillon #ifdef WITH_XMSS
20*ba1276acSMatthew Dillon
21*ba1276acSMatthew Dillon #define SSHKEY_INTERNAL
22*ba1276acSMatthew Dillon #include <sys/types.h>
23*ba1276acSMatthew Dillon #include <limits.h>
24*ba1276acSMatthew Dillon
25*ba1276acSMatthew Dillon #include <stdlib.h>
26*ba1276acSMatthew Dillon #include <string.h>
27*ba1276acSMatthew Dillon #include <stdarg.h>
28*ba1276acSMatthew Dillon #ifdef HAVE_STDINT_H
29*ba1276acSMatthew Dillon # include <stdint.h>
30*ba1276acSMatthew Dillon #endif
31*ba1276acSMatthew Dillon #include <unistd.h>
32*ba1276acSMatthew Dillon
33*ba1276acSMatthew Dillon #include "log.h"
34*ba1276acSMatthew Dillon #include "sshbuf.h"
35*ba1276acSMatthew Dillon #include "sshkey.h"
36*ba1276acSMatthew Dillon #include "sshkey-xmss.h"
37*ba1276acSMatthew Dillon #include "ssherr.h"
38*ba1276acSMatthew Dillon #include "ssh.h"
39*ba1276acSMatthew Dillon
40*ba1276acSMatthew Dillon #include "xmss_fast.h"
41*ba1276acSMatthew Dillon
42*ba1276acSMatthew Dillon static void
ssh_xmss_cleanup(struct sshkey * k)43*ba1276acSMatthew Dillon ssh_xmss_cleanup(struct sshkey *k)
44*ba1276acSMatthew Dillon {
45*ba1276acSMatthew Dillon freezero(k->xmss_pk, sshkey_xmss_pklen(k));
46*ba1276acSMatthew Dillon freezero(k->xmss_sk, sshkey_xmss_sklen(k));
47*ba1276acSMatthew Dillon sshkey_xmss_free_state(k);
48*ba1276acSMatthew Dillon free(k->xmss_name);
49*ba1276acSMatthew Dillon free(k->xmss_filename);
50*ba1276acSMatthew Dillon k->xmss_pk = NULL;
51*ba1276acSMatthew Dillon k->xmss_sk = NULL;
52*ba1276acSMatthew Dillon k->xmss_name = NULL;
53*ba1276acSMatthew Dillon k->xmss_filename = NULL;
54*ba1276acSMatthew Dillon }
55*ba1276acSMatthew Dillon
56*ba1276acSMatthew Dillon static int
ssh_xmss_equal(const struct sshkey * a,const struct sshkey * b)57*ba1276acSMatthew Dillon ssh_xmss_equal(const struct sshkey *a, const struct sshkey *b)
58*ba1276acSMatthew Dillon {
59*ba1276acSMatthew Dillon if (a->xmss_pk == NULL || b->xmss_pk == NULL)
60*ba1276acSMatthew Dillon return 0;
61*ba1276acSMatthew Dillon if (sshkey_xmss_pklen(a) != sshkey_xmss_pklen(b))
62*ba1276acSMatthew Dillon return 0;
63*ba1276acSMatthew Dillon if (memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) != 0)
64*ba1276acSMatthew Dillon return 0;
65*ba1276acSMatthew Dillon return 1;
66*ba1276acSMatthew Dillon }
67*ba1276acSMatthew Dillon
68*ba1276acSMatthew Dillon static int
ssh_xmss_serialize_public(const struct sshkey * key,struct sshbuf * b,enum sshkey_serialize_rep opts)69*ba1276acSMatthew Dillon ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b,
70*ba1276acSMatthew Dillon enum sshkey_serialize_rep opts)
71*ba1276acSMatthew Dillon {
72*ba1276acSMatthew Dillon int r;
73*ba1276acSMatthew Dillon
74*ba1276acSMatthew Dillon if (key->xmss_name == NULL || key->xmss_pk == NULL ||
75*ba1276acSMatthew Dillon sshkey_xmss_pklen(key) == 0)
76*ba1276acSMatthew Dillon return SSH_ERR_INVALID_ARGUMENT;
77*ba1276acSMatthew Dillon if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
78*ba1276acSMatthew Dillon (r = sshbuf_put_string(b, key->xmss_pk,
79*ba1276acSMatthew Dillon sshkey_xmss_pklen(key))) != 0 ||
80*ba1276acSMatthew Dillon (r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
81*ba1276acSMatthew Dillon return r;
82*ba1276acSMatthew Dillon
83*ba1276acSMatthew Dillon return 0;
84*ba1276acSMatthew Dillon }
85*ba1276acSMatthew Dillon
86*ba1276acSMatthew Dillon static int
ssh_xmss_serialize_private(const struct sshkey * key,struct sshbuf * b,enum sshkey_serialize_rep opts)87*ba1276acSMatthew Dillon ssh_xmss_serialize_private(const struct sshkey *key, struct sshbuf *b,
88*ba1276acSMatthew Dillon enum sshkey_serialize_rep opts)
89*ba1276acSMatthew Dillon {
90*ba1276acSMatthew Dillon int r;
91*ba1276acSMatthew Dillon
92*ba1276acSMatthew Dillon if (key->xmss_name == NULL)
93*ba1276acSMatthew Dillon return SSH_ERR_INVALID_ARGUMENT;
94*ba1276acSMatthew Dillon /* Note: can't reuse ssh_xmss_serialize_public because of sk order */
95*ba1276acSMatthew Dillon if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
96*ba1276acSMatthew Dillon (r = sshbuf_put_string(b, key->xmss_pk,
97*ba1276acSMatthew Dillon sshkey_xmss_pklen(key))) != 0 ||
98*ba1276acSMatthew Dillon (r = sshbuf_put_string(b, key->xmss_sk,
99*ba1276acSMatthew Dillon sshkey_xmss_sklen(key))) != 0 ||
100*ba1276acSMatthew Dillon (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
101*ba1276acSMatthew Dillon return r;
102*ba1276acSMatthew Dillon
103*ba1276acSMatthew Dillon return 0;
104*ba1276acSMatthew Dillon }
105*ba1276acSMatthew Dillon
106*ba1276acSMatthew Dillon static int
ssh_xmss_copy_public(const struct sshkey * from,struct sshkey * to)107*ba1276acSMatthew Dillon ssh_xmss_copy_public(const struct sshkey *from, struct sshkey *to)
108*ba1276acSMatthew Dillon {
109*ba1276acSMatthew Dillon int r = SSH_ERR_INTERNAL_ERROR;
110*ba1276acSMatthew Dillon u_int32_t left;
111*ba1276acSMatthew Dillon size_t pklen;
112*ba1276acSMatthew Dillon
113*ba1276acSMatthew Dillon if ((r = sshkey_xmss_init(to, from->xmss_name)) != 0)
114*ba1276acSMatthew Dillon return r;
115*ba1276acSMatthew Dillon if (from->xmss_pk == NULL)
116*ba1276acSMatthew Dillon return 0; /* XXX SSH_ERR_INTERNAL_ERROR ? */
117*ba1276acSMatthew Dillon
118*ba1276acSMatthew Dillon if ((pklen = sshkey_xmss_pklen(from)) == 0 ||
119*ba1276acSMatthew Dillon sshkey_xmss_pklen(to) != pklen)
120*ba1276acSMatthew Dillon return SSH_ERR_INTERNAL_ERROR;
121*ba1276acSMatthew Dillon if ((to->xmss_pk = malloc(pklen)) == NULL)
122*ba1276acSMatthew Dillon return SSH_ERR_ALLOC_FAIL;
123*ba1276acSMatthew Dillon memcpy(to->xmss_pk, from->xmss_pk, pklen);
124*ba1276acSMatthew Dillon /* simulate number of signatures left on pubkey */
125*ba1276acSMatthew Dillon left = sshkey_xmss_signatures_left(from);
126*ba1276acSMatthew Dillon if (left)
127*ba1276acSMatthew Dillon sshkey_xmss_enable_maxsign(to, left);
128*ba1276acSMatthew Dillon return 0;
129*ba1276acSMatthew Dillon }
130*ba1276acSMatthew Dillon
131*ba1276acSMatthew Dillon static int
ssh_xmss_deserialize_public(const char * ktype,struct sshbuf * b,struct sshkey * key)132*ba1276acSMatthew Dillon ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b,
133*ba1276acSMatthew Dillon struct sshkey *key)
134*ba1276acSMatthew Dillon {
135*ba1276acSMatthew Dillon size_t len = 0;
136*ba1276acSMatthew Dillon char *xmss_name = NULL;
137*ba1276acSMatthew Dillon u_char *pk = NULL;
138*ba1276acSMatthew Dillon int ret = SSH_ERR_INTERNAL_ERROR;
139*ba1276acSMatthew Dillon
140*ba1276acSMatthew Dillon if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
141*ba1276acSMatthew Dillon goto out;
142*ba1276acSMatthew Dillon if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
143*ba1276acSMatthew Dillon goto out;
144*ba1276acSMatthew Dillon if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
145*ba1276acSMatthew Dillon goto out;
146*ba1276acSMatthew Dillon if (len == 0 || len != sshkey_xmss_pklen(key)) {
147*ba1276acSMatthew Dillon ret = SSH_ERR_INVALID_FORMAT;
148*ba1276acSMatthew Dillon goto out;
149*ba1276acSMatthew Dillon }
150*ba1276acSMatthew Dillon key->xmss_pk = pk;
151*ba1276acSMatthew Dillon pk = NULL;
152*ba1276acSMatthew Dillon if (!sshkey_is_cert(key) &&
153*ba1276acSMatthew Dillon (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
154*ba1276acSMatthew Dillon goto out;
155*ba1276acSMatthew Dillon /* success */
156*ba1276acSMatthew Dillon ret = 0;
157*ba1276acSMatthew Dillon out:
158*ba1276acSMatthew Dillon free(xmss_name);
159*ba1276acSMatthew Dillon freezero(pk, len);
160*ba1276acSMatthew Dillon return ret;
161*ba1276acSMatthew Dillon }
162*ba1276acSMatthew Dillon
163*ba1276acSMatthew Dillon static int
ssh_xmss_deserialize_private(const char * ktype,struct sshbuf * b,struct sshkey * key)164*ba1276acSMatthew Dillon ssh_xmss_deserialize_private(const char *ktype, struct sshbuf *b,
165*ba1276acSMatthew Dillon struct sshkey *key)
166*ba1276acSMatthew Dillon {
167*ba1276acSMatthew Dillon int r;
168*ba1276acSMatthew Dillon char *xmss_name = NULL;
169*ba1276acSMatthew Dillon size_t pklen = 0, sklen = 0;
170*ba1276acSMatthew Dillon u_char *xmss_pk = NULL, *xmss_sk = NULL;
171*ba1276acSMatthew Dillon
172*ba1276acSMatthew Dillon /* Note: can't reuse ssh_xmss_deserialize_public because of sk order */
173*ba1276acSMatthew Dillon if ((r = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0 ||
174*ba1276acSMatthew Dillon (r = sshbuf_get_string(b, &xmss_pk, &pklen)) != 0 ||
175*ba1276acSMatthew Dillon (r = sshbuf_get_string(b, &xmss_sk, &sklen)) != 0)
176*ba1276acSMatthew Dillon goto out;
177*ba1276acSMatthew Dillon if (!sshkey_is_cert(key) &&
178*ba1276acSMatthew Dillon (r = sshkey_xmss_init(key, xmss_name)) != 0)
179*ba1276acSMatthew Dillon goto out;
180*ba1276acSMatthew Dillon if (pklen != sshkey_xmss_pklen(key) ||
181*ba1276acSMatthew Dillon sklen != sshkey_xmss_sklen(key)) {
182*ba1276acSMatthew Dillon r = SSH_ERR_INVALID_FORMAT;
183*ba1276acSMatthew Dillon goto out;
184*ba1276acSMatthew Dillon }
185*ba1276acSMatthew Dillon key->xmss_pk = xmss_pk;
186*ba1276acSMatthew Dillon key->xmss_sk = xmss_sk;
187*ba1276acSMatthew Dillon xmss_pk = xmss_sk = NULL;
188*ba1276acSMatthew Dillon /* optional internal state */
189*ba1276acSMatthew Dillon if ((r = sshkey_xmss_deserialize_state_opt(key, b)) != 0)
190*ba1276acSMatthew Dillon goto out;
191*ba1276acSMatthew Dillon /* success */
192*ba1276acSMatthew Dillon r = 0;
193*ba1276acSMatthew Dillon out:
194*ba1276acSMatthew Dillon free(xmss_name);
195*ba1276acSMatthew Dillon freezero(xmss_pk, pklen);
196*ba1276acSMatthew Dillon freezero(xmss_sk, sklen);
197*ba1276acSMatthew Dillon return r;
198*ba1276acSMatthew Dillon }
199*ba1276acSMatthew Dillon
200*ba1276acSMatthew Dillon 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)201*ba1276acSMatthew Dillon ssh_xmss_sign(struct sshkey *key,
202*ba1276acSMatthew Dillon u_char **sigp, size_t *lenp,
203*ba1276acSMatthew Dillon const u_char *data, size_t datalen,
204*ba1276acSMatthew Dillon const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
205*ba1276acSMatthew Dillon {
206*ba1276acSMatthew Dillon u_char *sig = NULL;
207*ba1276acSMatthew Dillon size_t slen = 0, len = 0, required_siglen;
208*ba1276acSMatthew Dillon unsigned long long smlen;
209*ba1276acSMatthew Dillon int r, ret;
210*ba1276acSMatthew Dillon struct sshbuf *b = NULL;
211*ba1276acSMatthew Dillon
212*ba1276acSMatthew Dillon if (lenp != NULL)
213*ba1276acSMatthew Dillon *lenp = 0;
214*ba1276acSMatthew Dillon if (sigp != NULL)
215*ba1276acSMatthew Dillon *sigp = NULL;
216*ba1276acSMatthew Dillon
217*ba1276acSMatthew Dillon if (key == NULL ||
218*ba1276acSMatthew Dillon sshkey_type_plain(key->type) != KEY_XMSS ||
219*ba1276acSMatthew Dillon key->xmss_sk == NULL ||
220*ba1276acSMatthew Dillon sshkey_xmss_params(key) == NULL)
221*ba1276acSMatthew Dillon return SSH_ERR_INVALID_ARGUMENT;
222*ba1276acSMatthew Dillon if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0)
223*ba1276acSMatthew Dillon return r;
224*ba1276acSMatthew Dillon if (datalen >= INT_MAX - required_siglen)
225*ba1276acSMatthew Dillon return SSH_ERR_INVALID_ARGUMENT;
226*ba1276acSMatthew Dillon smlen = slen = datalen + required_siglen;
227*ba1276acSMatthew Dillon if ((sig = malloc(slen)) == NULL)
228*ba1276acSMatthew Dillon return SSH_ERR_ALLOC_FAIL;
229*ba1276acSMatthew Dillon if ((r = sshkey_xmss_get_state(key, 1)) != 0)
230*ba1276acSMatthew Dillon goto out;
231*ba1276acSMatthew Dillon if ((ret = xmss_sign(key->xmss_sk, sshkey_xmss_bds_state(key), sig, &smlen,
232*ba1276acSMatthew Dillon data, datalen, sshkey_xmss_params(key))) != 0 || smlen <= datalen) {
233*ba1276acSMatthew Dillon r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */
234*ba1276acSMatthew Dillon goto out;
235*ba1276acSMatthew Dillon }
236*ba1276acSMatthew Dillon /* encode signature */
237*ba1276acSMatthew Dillon if ((b = sshbuf_new()) == NULL) {
238*ba1276acSMatthew Dillon r = SSH_ERR_ALLOC_FAIL;
239*ba1276acSMatthew Dillon goto out;
240*ba1276acSMatthew Dillon }
241*ba1276acSMatthew Dillon if ((r = sshbuf_put_cstring(b, "ssh-xmss@openssh.com")) != 0 ||
242*ba1276acSMatthew Dillon (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0)
243*ba1276acSMatthew Dillon goto out;
244*ba1276acSMatthew Dillon len = sshbuf_len(b);
245*ba1276acSMatthew Dillon if (sigp != NULL) {
246*ba1276acSMatthew Dillon if ((*sigp = malloc(len)) == NULL) {
247*ba1276acSMatthew Dillon r = SSH_ERR_ALLOC_FAIL;
248*ba1276acSMatthew Dillon goto out;
249*ba1276acSMatthew Dillon }
250*ba1276acSMatthew Dillon memcpy(*sigp, sshbuf_ptr(b), len);
251*ba1276acSMatthew Dillon }
252*ba1276acSMatthew Dillon if (lenp != NULL)
253*ba1276acSMatthew Dillon *lenp = len;
254*ba1276acSMatthew Dillon /* success */
255*ba1276acSMatthew Dillon r = 0;
256*ba1276acSMatthew Dillon out:
257*ba1276acSMatthew Dillon if ((ret = sshkey_xmss_update_state(key, 1)) != 0) {
258*ba1276acSMatthew Dillon /* discard signature since we cannot update the state */
259*ba1276acSMatthew Dillon if (r == 0 && sigp != NULL && *sigp != NULL) {
260*ba1276acSMatthew Dillon explicit_bzero(*sigp, len);
261*ba1276acSMatthew Dillon free(*sigp);
262*ba1276acSMatthew Dillon }
263*ba1276acSMatthew Dillon if (sigp != NULL)
264*ba1276acSMatthew Dillon *sigp = NULL;
265*ba1276acSMatthew Dillon if (lenp != NULL)
266*ba1276acSMatthew Dillon *lenp = 0;
267*ba1276acSMatthew Dillon r = ret;
268*ba1276acSMatthew Dillon }
269*ba1276acSMatthew Dillon sshbuf_free(b);
270*ba1276acSMatthew Dillon if (sig != NULL)
271*ba1276acSMatthew Dillon freezero(sig, slen);
272*ba1276acSMatthew Dillon
273*ba1276acSMatthew Dillon return r;
274*ba1276acSMatthew Dillon }
275*ba1276acSMatthew Dillon
276*ba1276acSMatthew Dillon 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)277*ba1276acSMatthew Dillon ssh_xmss_verify(const struct sshkey *key,
278*ba1276acSMatthew Dillon const u_char *sig, size_t siglen,
279*ba1276acSMatthew Dillon const u_char *data, size_t dlen, const char *alg, u_int compat,
280*ba1276acSMatthew Dillon struct sshkey_sig_details **detailsp)
281*ba1276acSMatthew Dillon {
282*ba1276acSMatthew Dillon struct sshbuf *b = NULL;
283*ba1276acSMatthew Dillon char *ktype = NULL;
284*ba1276acSMatthew Dillon const u_char *sigblob;
285*ba1276acSMatthew Dillon u_char *sm = NULL, *m = NULL;
286*ba1276acSMatthew Dillon size_t len, required_siglen;
287*ba1276acSMatthew Dillon unsigned long long smlen = 0, mlen = 0;
288*ba1276acSMatthew Dillon int r, ret;
289*ba1276acSMatthew Dillon
290*ba1276acSMatthew Dillon if (key == NULL ||
291*ba1276acSMatthew Dillon sshkey_type_plain(key->type) != KEY_XMSS ||
292*ba1276acSMatthew Dillon key->xmss_pk == NULL ||
293*ba1276acSMatthew Dillon sshkey_xmss_params(key) == NULL ||
294*ba1276acSMatthew Dillon sig == NULL || siglen == 0)
295*ba1276acSMatthew Dillon return SSH_ERR_INVALID_ARGUMENT;
296*ba1276acSMatthew Dillon if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0)
297*ba1276acSMatthew Dillon return r;
298*ba1276acSMatthew Dillon if (dlen >= INT_MAX - required_siglen)
299*ba1276acSMatthew Dillon return SSH_ERR_INVALID_ARGUMENT;
300*ba1276acSMatthew Dillon
301*ba1276acSMatthew Dillon if ((b = sshbuf_from(sig, siglen)) == NULL)
302*ba1276acSMatthew Dillon return SSH_ERR_ALLOC_FAIL;
303*ba1276acSMatthew Dillon if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 ||
304*ba1276acSMatthew Dillon (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0)
305*ba1276acSMatthew Dillon goto out;
306*ba1276acSMatthew Dillon if (strcmp("ssh-xmss@openssh.com", ktype) != 0) {
307*ba1276acSMatthew Dillon r = SSH_ERR_KEY_TYPE_MISMATCH;
308*ba1276acSMatthew Dillon goto out;
309*ba1276acSMatthew Dillon }
310*ba1276acSMatthew Dillon if (sshbuf_len(b) != 0) {
311*ba1276acSMatthew Dillon r = SSH_ERR_UNEXPECTED_TRAILING_DATA;
312*ba1276acSMatthew Dillon goto out;
313*ba1276acSMatthew Dillon }
314*ba1276acSMatthew Dillon if (len != required_siglen) {
315*ba1276acSMatthew Dillon r = SSH_ERR_INVALID_FORMAT;
316*ba1276acSMatthew Dillon goto out;
317*ba1276acSMatthew Dillon }
318*ba1276acSMatthew Dillon if (dlen >= SIZE_MAX - len) {
319*ba1276acSMatthew Dillon r = SSH_ERR_INVALID_ARGUMENT;
320*ba1276acSMatthew Dillon goto out;
321*ba1276acSMatthew Dillon }
322*ba1276acSMatthew Dillon smlen = len + dlen;
323*ba1276acSMatthew Dillon mlen = smlen;
324*ba1276acSMatthew Dillon if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) {
325*ba1276acSMatthew Dillon r = SSH_ERR_ALLOC_FAIL;
326*ba1276acSMatthew Dillon goto out;
327*ba1276acSMatthew Dillon }
328*ba1276acSMatthew Dillon memcpy(sm, sigblob, len);
329*ba1276acSMatthew Dillon memcpy(sm+len, data, dlen);
330*ba1276acSMatthew Dillon if ((ret = xmss_sign_open(m, &mlen, sm, smlen,
331*ba1276acSMatthew Dillon key->xmss_pk, sshkey_xmss_params(key))) != 0) {
332*ba1276acSMatthew Dillon debug2_f("xmss_sign_open failed: %d", ret);
333*ba1276acSMatthew Dillon }
334*ba1276acSMatthew Dillon if (ret != 0 || mlen != dlen) {
335*ba1276acSMatthew Dillon r = SSH_ERR_SIGNATURE_INVALID;
336*ba1276acSMatthew Dillon goto out;
337*ba1276acSMatthew Dillon }
338*ba1276acSMatthew Dillon /* XXX compare 'm' and 'data' ? */
339*ba1276acSMatthew Dillon /* success */
340*ba1276acSMatthew Dillon r = 0;
341*ba1276acSMatthew Dillon out:
342*ba1276acSMatthew Dillon if (sm != NULL)
343*ba1276acSMatthew Dillon freezero(sm, smlen);
344*ba1276acSMatthew Dillon if (m != NULL)
345*ba1276acSMatthew Dillon freezero(m, smlen);
346*ba1276acSMatthew Dillon sshbuf_free(b);
347*ba1276acSMatthew Dillon free(ktype);
348*ba1276acSMatthew Dillon return r;
349*ba1276acSMatthew Dillon }
350*ba1276acSMatthew Dillon
351*ba1276acSMatthew Dillon static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
352*ba1276acSMatthew Dillon /* .size = */ NULL,
353*ba1276acSMatthew Dillon /* .alloc = */ NULL,
354*ba1276acSMatthew Dillon /* .cleanup = */ ssh_xmss_cleanup,
355*ba1276acSMatthew Dillon /* .equal = */ ssh_xmss_equal,
356*ba1276acSMatthew Dillon /* .ssh_serialize_public = */ ssh_xmss_serialize_public,
357*ba1276acSMatthew Dillon /* .ssh_deserialize_public = */ ssh_xmss_deserialize_public,
358*ba1276acSMatthew Dillon /* .ssh_serialize_private = */ ssh_xmss_serialize_private,
359*ba1276acSMatthew Dillon /* .ssh_deserialize_private = */ ssh_xmss_deserialize_private,
360*ba1276acSMatthew Dillon /* .generate = */ sshkey_xmss_generate_private_key,
361*ba1276acSMatthew Dillon /* .copy_public = */ ssh_xmss_copy_public,
362*ba1276acSMatthew Dillon /* .sign = */ ssh_xmss_sign,
363*ba1276acSMatthew Dillon /* .verify = */ ssh_xmss_verify,
364*ba1276acSMatthew Dillon };
365*ba1276acSMatthew Dillon
366*ba1276acSMatthew Dillon const struct sshkey_impl sshkey_xmss_impl = {
367*ba1276acSMatthew Dillon /* .name = */ "ssh-xmss@openssh.com",
368*ba1276acSMatthew Dillon /* .shortname = */ "XMSS",
369*ba1276acSMatthew Dillon /* .sigalg = */ NULL,
370*ba1276acSMatthew Dillon /* .type = */ KEY_XMSS,
371*ba1276acSMatthew Dillon /* .nid = */ 0,
372*ba1276acSMatthew Dillon /* .cert = */ 0,
373*ba1276acSMatthew Dillon /* .sigonly = */ 0,
374*ba1276acSMatthew Dillon /* .keybits = */ 256,
375*ba1276acSMatthew Dillon /* .funcs = */ &sshkey_xmss_funcs,
376*ba1276acSMatthew Dillon };
377*ba1276acSMatthew Dillon
378*ba1276acSMatthew Dillon const struct sshkey_impl sshkey_xmss_cert_impl = {
379*ba1276acSMatthew Dillon /* .name = */ "ssh-xmss-cert-v01@openssh.com",
380*ba1276acSMatthew Dillon /* .shortname = */ "XMSS-CERT",
381*ba1276acSMatthew Dillon /* .sigalg = */ NULL,
382*ba1276acSMatthew Dillon /* .type = */ KEY_XMSS_CERT,
383*ba1276acSMatthew Dillon /* .nid = */ 0,
384*ba1276acSMatthew Dillon /* .cert = */ 1,
385*ba1276acSMatthew Dillon /* .sigonly = */ 0,
386*ba1276acSMatthew Dillon /* .keybits = */ 256,
387*ba1276acSMatthew Dillon /* .funcs = */ &sshkey_xmss_funcs,
388*ba1276acSMatthew Dillon };
389*ba1276acSMatthew Dillon #endif /* WITH_XMSS */
390