Annotation of src/usr.bin/ssh/sshkey.c, Revision 1.68
1.68 ! djm 1: /* $OpenBSD: sshkey.c,v 1.67 2018/09/12 01:31:30 djm Exp $ */
1.1 djm 2: /*
3: * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4: * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
5: * Copyright (c) 2010,2011 Damien Miller. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: #include <sys/types.h>
1.7 djm 29: #include <netinet/in.h>
1.1 djm 30:
1.12 djm 31: #ifdef WITH_OPENSSL
1.1 djm 32: #include <openssl/evp.h>
33: #include <openssl/err.h>
34: #include <openssl/pem.h>
1.12 djm 35: #endif
1.1 djm 36:
37: #include "crypto_api.h"
38:
39: #include <errno.h>
40: #include <stdio.h>
41: #include <string.h>
42: #include <util.h>
1.13 deraadt 43: #include <limits.h>
1.7 djm 44: #include <resolv.h>
1.1 djm 45:
46: #include "ssh2.h"
47: #include "ssherr.h"
48: #include "misc.h"
49: #include "sshbuf.h"
50: #include "cipher.h"
51: #include "digest.h"
52: #define SSHKEY_INTERNAL
53: #include "sshkey.h"
1.62 markus 54: #include "sshkey-xmss.h"
1.11 djm 55: #include "match.h"
1.1 djm 56:
1.62 markus 57: #include "xmss_fast.h"
58:
1.1 djm 59: /* openssh private key file format */
60: #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
61: #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
62: #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
63: #define MARK_END_LEN (sizeof(MARK_END) - 1)
64: #define KDFNAME "bcrypt"
65: #define AUTH_MAGIC "openssh-key-v1"
66: #define SALT_LEN 16
1.56 djm 67: #define DEFAULT_CIPHERNAME "aes256-ctr"
1.1 djm 68: #define DEFAULT_ROUNDS 16
69:
70: /* Version identification string for SSH v1 identity files. */
71: #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
72:
1.62 markus 73: int sshkey_private_serialize_opt(const struct sshkey *key,
74: struct sshbuf *buf, enum sshkey_serialize_rep);
1.14 djm 75: static int sshkey_from_blob_internal(struct sshbuf *buf,
1.1 djm 76: struct sshkey **keyp, int allow_cert);
1.67 djm 77: static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep);
1.1 djm 78:
79: /* Supported key types */
80: struct keytype {
81: const char *name;
82: const char *shortname;
1.65 djm 83: const char *sigalg;
1.1 djm 84: int type;
85: int nid;
86: int cert;
1.28 markus 87: int sigonly;
1.1 djm 88: };
89: static const struct keytype keytypes[] = {
1.65 djm 90: { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
91: { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
1.28 markus 92: KEY_ED25519_CERT, 0, 1, 0 },
1.62 markus 93: #ifdef WITH_XMSS
1.65 djm 94: { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
95: { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
1.62 markus 96: KEY_XMSS_CERT, 0, 1, 0 },
97: #endif /* WITH_XMSS */
1.1 djm 98: #ifdef WITH_OPENSSL
1.65 djm 99: { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
100: { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
101: { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
102: { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
103: { "ecdsa-sha2-nistp256", "ECDSA", NULL,
104: KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
105: { "ecdsa-sha2-nistp384", "ECDSA", NULL,
106: KEY_ECDSA, NID_secp384r1, 0, 0 },
107: { "ecdsa-sha2-nistp521", "ECDSA", NULL,
108: KEY_ECDSA, NID_secp521r1, 0, 0 },
109: { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
110: KEY_RSA_CERT, 0, 1, 0 },
111: { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
112: "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
113: { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
114: "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
115: { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
116: KEY_DSA_CERT, 0, 1, 0 },
117: { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
1.28 markus 118: KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
1.65 djm 119: { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
1.28 markus 120: KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
1.65 djm 121: { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
122: KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
1.1 djm 123: #endif /* WITH_OPENSSL */
1.65 djm 124: { NULL, NULL, NULL, -1, -1, 0, 0 }
1.1 djm 125: };
126:
127: const char *
128: sshkey_type(const struct sshkey *k)
129: {
130: const struct keytype *kt;
131:
132: for (kt = keytypes; kt->type != -1; kt++) {
133: if (kt->type == k->type)
134: return kt->shortname;
135: }
136: return "unknown";
137: }
138:
139: static const char *
140: sshkey_ssh_name_from_type_nid(int type, int nid)
141: {
142: const struct keytype *kt;
143:
144: for (kt = keytypes; kt->type != -1; kt++) {
145: if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
146: return kt->name;
147: }
148: return "ssh-unknown";
149: }
150:
151: int
152: sshkey_type_is_cert(int type)
153: {
154: const struct keytype *kt;
155:
156: for (kt = keytypes; kt->type != -1; kt++) {
157: if (kt->type == type)
158: return kt->cert;
159: }
160: return 0;
161: }
162:
163: const char *
164: sshkey_ssh_name(const struct sshkey *k)
165: {
166: return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
167: }
168:
169: const char *
170: sshkey_ssh_name_plain(const struct sshkey *k)
171: {
172: return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type),
173: k->ecdsa_nid);
174: }
175:
176: int
177: sshkey_type_from_name(const char *name)
178: {
179: const struct keytype *kt;
180:
181: for (kt = keytypes; kt->type != -1; kt++) {
182: /* Only allow shortname matches for plain key types */
183: if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
184: (!kt->cert && strcasecmp(kt->shortname, name) == 0))
185: return kt->type;
186: }
187: return KEY_UNSPEC;
188: }
189:
190: int
191: sshkey_ecdsa_nid_from_name(const char *name)
192: {
193: const struct keytype *kt;
194:
1.4 djm 195: for (kt = keytypes; kt->type != -1; kt++) {
196: if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
197: continue;
198: if (kt->name != NULL && strcmp(name, kt->name) == 0)
199: return kt->nid;
200: }
1.1 djm 201: return -1;
202: }
203:
204: char *
1.45 djm 205: sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
1.1 djm 206: {
207: char *tmp, *ret = NULL;
208: size_t nlen, rlen = 0;
209: const struct keytype *kt;
210:
211: for (kt = keytypes; kt->type != -1; kt++) {
1.45 djm 212: if (kt->name == NULL)
213: continue;
214: if (!include_sigonly && kt->sigonly)
1.1 djm 215: continue;
216: if ((certs_only && !kt->cert) || (plain_only && kt->cert))
217: continue;
218: if (ret != NULL)
1.38 djm 219: ret[rlen++] = sep;
1.1 djm 220: nlen = strlen(kt->name);
221: if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
222: free(ret);
223: return NULL;
224: }
225: ret = tmp;
226: memcpy(ret + rlen, kt->name, nlen + 1);
227: rlen += nlen;
228: }
229: return ret;
230: }
231:
232: int
1.11 djm 233: sshkey_names_valid2(const char *names, int allow_wildcard)
1.1 djm 234: {
235: char *s, *cp, *p;
1.11 djm 236: const struct keytype *kt;
237: int type;
1.1 djm 238:
239: if (names == NULL || strcmp(names, "") == 0)
240: return 0;
241: if ((s = cp = strdup(names)) == NULL)
242: return 0;
243: for ((p = strsep(&cp, ",")); p && *p != '\0';
244: (p = strsep(&cp, ","))) {
1.11 djm 245: type = sshkey_type_from_name(p);
246: if (type == KEY_UNSPEC) {
247: if (allow_wildcard) {
248: /*
249: * Try matching key types against the string.
250: * If any has a positive or negative match then
251: * the component is accepted.
252: */
253: for (kt = keytypes; kt->type != -1; kt++) {
254: if (match_pattern_list(kt->name,
1.17 djm 255: p, 0) != 0)
1.11 djm 256: break;
257: }
258: if (kt->type != -1)
259: continue;
260: }
1.1 djm 261: free(s);
262: return 0;
263: }
264: }
265: free(s);
266: return 1;
267: }
268:
269: u_int
270: sshkey_size(const struct sshkey *k)
271: {
272: switch (k->type) {
273: #ifdef WITH_OPENSSL
274: case KEY_RSA:
275: case KEY_RSA_CERT:
276: return BN_num_bits(k->rsa->n);
277: case KEY_DSA:
278: case KEY_DSA_CERT:
279: return BN_num_bits(k->dsa->p);
280: case KEY_ECDSA:
281: case KEY_ECDSA_CERT:
282: return sshkey_curve_nid_to_bits(k->ecdsa_nid);
283: #endif /* WITH_OPENSSL */
284: case KEY_ED25519:
285: case KEY_ED25519_CERT:
1.62 markus 286: case KEY_XMSS:
287: case KEY_XMSS_CERT:
1.1 djm 288: return 256; /* XXX */
289: }
290: return 0;
291: }
292:
293: static int
294: sshkey_type_is_valid_ca(int type)
295: {
296: switch (type) {
297: case KEY_RSA:
298: case KEY_DSA:
299: case KEY_ECDSA:
300: case KEY_ED25519:
1.62 markus 301: case KEY_XMSS:
1.1 djm 302: return 1;
303: default:
304: return 0;
305: }
306: }
307:
308: int
309: sshkey_is_cert(const struct sshkey *k)
310: {
311: if (k == NULL)
312: return 0;
313: return sshkey_type_is_cert(k->type);
314: }
315:
316: /* Return the cert-less equivalent to a certified key type */
317: int
318: sshkey_type_plain(int type)
319: {
320: switch (type) {
321: case KEY_RSA_CERT:
322: return KEY_RSA;
323: case KEY_DSA_CERT:
324: return KEY_DSA;
325: case KEY_ECDSA_CERT:
326: return KEY_ECDSA;
327: case KEY_ED25519_CERT:
328: return KEY_ED25519;
1.62 markus 329: case KEY_XMSS_CERT:
330: return KEY_XMSS;
1.1 djm 331: default:
332: return type;
333: }
334: }
335:
336: #ifdef WITH_OPENSSL
337: /* XXX: these are really begging for a table-driven approach */
338: int
339: sshkey_curve_name_to_nid(const char *name)
340: {
341: if (strcmp(name, "nistp256") == 0)
342: return NID_X9_62_prime256v1;
343: else if (strcmp(name, "nistp384") == 0)
344: return NID_secp384r1;
345: else if (strcmp(name, "nistp521") == 0)
346: return NID_secp521r1;
347: else
348: return -1;
349: }
350:
351: u_int
352: sshkey_curve_nid_to_bits(int nid)
353: {
354: switch (nid) {
355: case NID_X9_62_prime256v1:
356: return 256;
357: case NID_secp384r1:
358: return 384;
359: case NID_secp521r1:
360: return 521;
361: default:
362: return 0;
363: }
364: }
365:
366: int
367: sshkey_ecdsa_bits_to_nid(int bits)
368: {
369: switch (bits) {
370: case 256:
371: return NID_X9_62_prime256v1;
372: case 384:
373: return NID_secp384r1;
374: case 521:
375: return NID_secp521r1;
376: default:
377: return -1;
378: }
379: }
380:
381: const char *
382: sshkey_curve_nid_to_name(int nid)
383: {
384: switch (nid) {
385: case NID_X9_62_prime256v1:
386: return "nistp256";
387: case NID_secp384r1:
388: return "nistp384";
389: case NID_secp521r1:
390: return "nistp521";
391: default:
392: return NULL;
393: }
394: }
395:
396: int
397: sshkey_ec_nid_to_hash_alg(int nid)
398: {
399: int kbits = sshkey_curve_nid_to_bits(nid);
400:
401: if (kbits <= 0)
402: return -1;
403:
404: /* RFC5656 section 6.2.1 */
405: if (kbits <= 256)
406: return SSH_DIGEST_SHA256;
407: else if (kbits <= 384)
408: return SSH_DIGEST_SHA384;
409: else
410: return SSH_DIGEST_SHA512;
411: }
412: #endif /* WITH_OPENSSL */
413:
414: static void
415: cert_free(struct sshkey_cert *cert)
416: {
417: u_int i;
418:
419: if (cert == NULL)
420: return;
1.31 mmcc 421: sshbuf_free(cert->certblob);
422: sshbuf_free(cert->critical);
423: sshbuf_free(cert->extensions);
1.29 mmcc 424: free(cert->key_id);
1.1 djm 425: for (i = 0; i < cert->nprincipals; i++)
426: free(cert->principals[i]);
1.29 mmcc 427: free(cert->principals);
1.30 mmcc 428: sshkey_free(cert->signature_key);
1.67 djm 429: free(cert->signature_type);
1.61 jsing 430: freezero(cert, sizeof(*cert));
1.1 djm 431: }
432:
433: static struct sshkey_cert *
434: cert_new(void)
435: {
436: struct sshkey_cert *cert;
437:
438: if ((cert = calloc(1, sizeof(*cert))) == NULL)
439: return NULL;
440: if ((cert->certblob = sshbuf_new()) == NULL ||
441: (cert->critical = sshbuf_new()) == NULL ||
442: (cert->extensions = sshbuf_new()) == NULL) {
443: cert_free(cert);
444: return NULL;
445: }
446: cert->key_id = NULL;
447: cert->principals = NULL;
448: cert->signature_key = NULL;
1.67 djm 449: cert->signature_type = NULL;
1.1 djm 450: return cert;
451: }
452:
453: struct sshkey *
454: sshkey_new(int type)
455: {
456: struct sshkey *k;
457: #ifdef WITH_OPENSSL
458: RSA *rsa;
459: DSA *dsa;
460: #endif /* WITH_OPENSSL */
461:
462: if ((k = calloc(1, sizeof(*k))) == NULL)
463: return NULL;
464: k->type = type;
465: k->ecdsa = NULL;
466: k->ecdsa_nid = -1;
467: k->dsa = NULL;
468: k->rsa = NULL;
469: k->cert = NULL;
470: k->ed25519_sk = NULL;
471: k->ed25519_pk = NULL;
1.62 markus 472: k->xmss_sk = NULL;
473: k->xmss_pk = NULL;
1.1 djm 474: switch (k->type) {
475: #ifdef WITH_OPENSSL
476: case KEY_RSA:
477: case KEY_RSA_CERT:
478: if ((rsa = RSA_new()) == NULL ||
479: (rsa->n = BN_new()) == NULL ||
480: (rsa->e = BN_new()) == NULL) {
1.60 jsing 481: RSA_free(rsa);
1.1 djm 482: free(k);
483: return NULL;
484: }
485: k->rsa = rsa;
486: break;
487: case KEY_DSA:
488: case KEY_DSA_CERT:
489: if ((dsa = DSA_new()) == NULL ||
490: (dsa->p = BN_new()) == NULL ||
491: (dsa->q = BN_new()) == NULL ||
492: (dsa->g = BN_new()) == NULL ||
493: (dsa->pub_key = BN_new()) == NULL) {
1.60 jsing 494: DSA_free(dsa);
1.1 djm 495: free(k);
496: return NULL;
497: }
498: k->dsa = dsa;
499: break;
500: case KEY_ECDSA:
501: case KEY_ECDSA_CERT:
502: /* Cannot do anything until we know the group */
503: break;
504: #endif /* WITH_OPENSSL */
505: case KEY_ED25519:
506: case KEY_ED25519_CERT:
1.62 markus 507: case KEY_XMSS:
508: case KEY_XMSS_CERT:
1.1 djm 509: /* no need to prealloc */
510: break;
511: case KEY_UNSPEC:
512: break;
513: default:
514: free(k);
515: return NULL;
516: }
517:
518: if (sshkey_is_cert(k)) {
519: if ((k->cert = cert_new()) == NULL) {
520: sshkey_free(k);
521: return NULL;
522: }
523: }
524:
525: return k;
526: }
527:
528: int
529: sshkey_add_private(struct sshkey *k)
530: {
531: switch (k->type) {
532: #ifdef WITH_OPENSSL
533: case KEY_RSA:
534: case KEY_RSA_CERT:
535: #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)
536: if (bn_maybe_alloc_failed(k->rsa->d) ||
537: bn_maybe_alloc_failed(k->rsa->iqmp) ||
538: bn_maybe_alloc_failed(k->rsa->q) ||
539: bn_maybe_alloc_failed(k->rsa->p) ||
540: bn_maybe_alloc_failed(k->rsa->dmq1) ||
541: bn_maybe_alloc_failed(k->rsa->dmp1))
542: return SSH_ERR_ALLOC_FAIL;
543: break;
544: case KEY_DSA:
545: case KEY_DSA_CERT:
546: if (bn_maybe_alloc_failed(k->dsa->priv_key))
547: return SSH_ERR_ALLOC_FAIL;
548: break;
549: #undef bn_maybe_alloc_failed
550: case KEY_ECDSA:
551: case KEY_ECDSA_CERT:
552: /* Cannot do anything until we know the group */
553: break;
554: #endif /* WITH_OPENSSL */
555: case KEY_ED25519:
556: case KEY_ED25519_CERT:
1.62 markus 557: case KEY_XMSS:
558: case KEY_XMSS_CERT:
1.1 djm 559: /* no need to prealloc */
560: break;
561: case KEY_UNSPEC:
562: break;
563: default:
564: return SSH_ERR_INVALID_ARGUMENT;
565: }
566: return 0;
567: }
568:
569: struct sshkey *
570: sshkey_new_private(int type)
571: {
572: struct sshkey *k = sshkey_new(type);
573:
574: if (k == NULL)
575: return NULL;
576: if (sshkey_add_private(k) != 0) {
577: sshkey_free(k);
578: return NULL;
579: }
580: return k;
581: }
582:
583: void
584: sshkey_free(struct sshkey *k)
585: {
586: if (k == NULL)
587: return;
588: switch (k->type) {
589: #ifdef WITH_OPENSSL
590: case KEY_RSA:
591: case KEY_RSA_CERT:
1.60 jsing 592: RSA_free(k->rsa);
1.1 djm 593: k->rsa = NULL;
594: break;
595: case KEY_DSA:
596: case KEY_DSA_CERT:
1.60 jsing 597: DSA_free(k->dsa);
1.1 djm 598: k->dsa = NULL;
599: break;
600: case KEY_ECDSA:
601: case KEY_ECDSA_CERT:
1.60 jsing 602: EC_KEY_free(k->ecdsa);
1.1 djm 603: k->ecdsa = NULL;
604: break;
605: #endif /* WITH_OPENSSL */
606: case KEY_ED25519:
607: case KEY_ED25519_CERT:
1.61 jsing 608: freezero(k->ed25519_pk, ED25519_PK_SZ);
609: k->ed25519_pk = NULL;
610: freezero(k->ed25519_sk, ED25519_SK_SZ);
611: k->ed25519_sk = NULL;
1.1 djm 612: break;
1.62 markus 613: #ifdef WITH_XMSS
614: case KEY_XMSS:
615: case KEY_XMSS_CERT:
616: freezero(k->xmss_pk, sshkey_xmss_pklen(k));
617: k->xmss_pk = NULL;
618: freezero(k->xmss_sk, sshkey_xmss_sklen(k));
619: k->xmss_sk = NULL;
620: sshkey_xmss_free_state(k);
621: free(k->xmss_name);
622: k->xmss_name = NULL;
623: free(k->xmss_filename);
624: k->xmss_filename = NULL;
625: break;
626: #endif /* WITH_XMSS */
1.1 djm 627: case KEY_UNSPEC:
628: break;
629: default:
630: break;
631: }
632: if (sshkey_is_cert(k))
633: cert_free(k->cert);
1.61 jsing 634: freezero(k, sizeof(*k));
1.1 djm 635: }
636:
637: static int
638: cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
639: {
640: if (a == NULL && b == NULL)
641: return 1;
642: if (a == NULL || b == NULL)
643: return 0;
644: if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob))
645: return 0;
646: if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob),
647: sshbuf_len(a->certblob)) != 0)
648: return 0;
649: return 1;
650: }
651:
652: /*
653: * Compare public portions of key only, allowing comparisons between
654: * certificates and plain keys too.
655: */
656: int
657: sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
658: {
659: #ifdef WITH_OPENSSL
660: BN_CTX *bnctx;
661: #endif /* WITH_OPENSSL */
662:
663: if (a == NULL || b == NULL ||
664: sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
665: return 0;
666:
667: switch (a->type) {
668: #ifdef WITH_OPENSSL
669: case KEY_RSA_CERT:
670: case KEY_RSA:
671: return a->rsa != NULL && b->rsa != NULL &&
672: BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
673: BN_cmp(a->rsa->n, b->rsa->n) == 0;
674: case KEY_DSA_CERT:
675: case KEY_DSA:
676: return a->dsa != NULL && b->dsa != NULL &&
677: BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
678: BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
679: BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
680: BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
681: case KEY_ECDSA_CERT:
682: case KEY_ECDSA:
683: if (a->ecdsa == NULL || b->ecdsa == NULL ||
684: EC_KEY_get0_public_key(a->ecdsa) == NULL ||
685: EC_KEY_get0_public_key(b->ecdsa) == NULL)
686: return 0;
687: if ((bnctx = BN_CTX_new()) == NULL)
688: return 0;
689: if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
690: EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
691: EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
692: EC_KEY_get0_public_key(a->ecdsa),
693: EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
694: BN_CTX_free(bnctx);
695: return 0;
696: }
697: BN_CTX_free(bnctx);
698: return 1;
699: #endif /* WITH_OPENSSL */
700: case KEY_ED25519:
701: case KEY_ED25519_CERT:
702: return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
703: memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
1.62 markus 704: #ifdef WITH_XMSS
705: case KEY_XMSS:
706: case KEY_XMSS_CERT:
707: return a->xmss_pk != NULL && b->xmss_pk != NULL &&
708: sshkey_xmss_pklen(a) == sshkey_xmss_pklen(b) &&
709: memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) == 0;
710: #endif /* WITH_XMSS */
1.1 djm 711: default:
712: return 0;
713: }
714: /* NOTREACHED */
715: }
716:
717: int
718: sshkey_equal(const struct sshkey *a, const struct sshkey *b)
719: {
720: if (a == NULL || b == NULL || a->type != b->type)
721: return 0;
722: if (sshkey_is_cert(a)) {
723: if (!cert_compare(a->cert, b->cert))
724: return 0;
725: }
726: return sshkey_equal_public(a, b);
727: }
728:
729: static int
1.62 markus 730: to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
731: enum sshkey_serialize_rep opts)
1.1 djm 732: {
733: int type, ret = SSH_ERR_INTERNAL_ERROR;
734: const char *typename;
735:
736: if (key == NULL)
737: return SSH_ERR_INVALID_ARGUMENT;
738:
1.19 djm 739: if (sshkey_is_cert(key)) {
740: if (key->cert == NULL)
741: return SSH_ERR_EXPECTED_CERT;
742: if (sshbuf_len(key->cert->certblob) == 0)
743: return SSH_ERR_KEY_LACKS_CERTBLOB;
744: }
1.1 djm 745: type = force_plain ? sshkey_type_plain(key->type) : key->type;
746: typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
747:
748: switch (type) {
749: #ifdef WITH_OPENSSL
750: case KEY_DSA_CERT:
751: case KEY_ECDSA_CERT:
752: case KEY_RSA_CERT:
753: #endif /* WITH_OPENSSL */
754: case KEY_ED25519_CERT:
1.62 markus 755: #ifdef WITH_XMSS
756: case KEY_XMSS_CERT:
757: #endif /* WITH_XMSS */
1.1 djm 758: /* Use the existing blob */
759: /* XXX modified flag? */
760: if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
761: return ret;
762: break;
763: #ifdef WITH_OPENSSL
764: case KEY_DSA:
765: if (key->dsa == NULL)
766: return SSH_ERR_INVALID_ARGUMENT;
767: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
768: (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
769: (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
770: (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
771: (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0)
772: return ret;
773: break;
774: case KEY_ECDSA:
775: if (key->ecdsa == NULL)
776: return SSH_ERR_INVALID_ARGUMENT;
777: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
778: (ret = sshbuf_put_cstring(b,
779: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
780: (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
781: return ret;
782: break;
783: case KEY_RSA:
784: if (key->rsa == NULL)
785: return SSH_ERR_INVALID_ARGUMENT;
786: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
787: (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
788: (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0)
789: return ret;
790: break;
791: #endif /* WITH_OPENSSL */
792: case KEY_ED25519:
793: if (key->ed25519_pk == NULL)
794: return SSH_ERR_INVALID_ARGUMENT;
795: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
796: (ret = sshbuf_put_string(b,
797: key->ed25519_pk, ED25519_PK_SZ)) != 0)
798: return ret;
799: break;
1.62 markus 800: #ifdef WITH_XMSS
801: case KEY_XMSS:
802: if (key->xmss_name == NULL || key->xmss_pk == NULL ||
803: sshkey_xmss_pklen(key) == 0)
804: return SSH_ERR_INVALID_ARGUMENT;
805: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
806: (ret = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
807: (ret = sshbuf_put_string(b,
808: key->xmss_pk, sshkey_xmss_pklen(key))) != 0 ||
809: (ret = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
810: return ret;
811: break;
812: #endif /* WITH_XMSS */
1.1 djm 813: default:
814: return SSH_ERR_KEY_TYPE_UNKNOWN;
815: }
816: return 0;
817: }
818:
819: int
1.14 djm 820: sshkey_putb(const struct sshkey *key, struct sshbuf *b)
1.1 djm 821: {
1.62 markus 822: return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 823: }
824:
825: int
1.62 markus 826: sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b,
827: enum sshkey_serialize_rep opts)
1.14 djm 828: {
829: struct sshbuf *tmp;
830: int r;
831:
832: if ((tmp = sshbuf_new()) == NULL)
833: return SSH_ERR_ALLOC_FAIL;
1.62 markus 834: r = to_blob_buf(key, tmp, 0, opts);
1.14 djm 835: if (r == 0)
836: r = sshbuf_put_stringb(b, tmp);
837: sshbuf_free(tmp);
838: return r;
839: }
840:
841: int
1.62 markus 842: sshkey_puts(const struct sshkey *key, struct sshbuf *b)
843: {
844: return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT);
845: }
846:
847: int
1.14 djm 848: sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)
1.1 djm 849: {
1.62 markus 850: return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 851: }
852:
853: static int
1.62 markus 854: to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain,
855: enum sshkey_serialize_rep opts)
1.1 djm 856: {
857: int ret = SSH_ERR_INTERNAL_ERROR;
858: size_t len;
859: struct sshbuf *b = NULL;
860:
861: if (lenp != NULL)
862: *lenp = 0;
863: if (blobp != NULL)
864: *blobp = NULL;
865: if ((b = sshbuf_new()) == NULL)
866: return SSH_ERR_ALLOC_FAIL;
1.62 markus 867: if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0)
1.1 djm 868: goto out;
869: len = sshbuf_len(b);
870: if (lenp != NULL)
871: *lenp = len;
872: if (blobp != NULL) {
873: if ((*blobp = malloc(len)) == NULL) {
874: ret = SSH_ERR_ALLOC_FAIL;
875: goto out;
876: }
877: memcpy(*blobp, sshbuf_ptr(b), len);
878: }
879: ret = 0;
880: out:
881: sshbuf_free(b);
882: return ret;
883: }
884:
885: int
886: sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
887: {
1.62 markus 888: return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 889: }
890:
891: int
892: sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
893: {
1.62 markus 894: return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 895: }
896:
897: int
1.7 djm 898: sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
1.1 djm 899: u_char **retp, size_t *lenp)
900: {
901: u_char *blob = NULL, *ret = NULL;
902: size_t blob_len = 0;
1.7 djm 903: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 904:
905: if (retp != NULL)
906: *retp = NULL;
907: if (lenp != NULL)
908: *lenp = 0;
1.7 djm 909: if (ssh_digest_bytes(dgst_alg) == 0) {
1.1 djm 910: r = SSH_ERR_INVALID_ARGUMENT;
911: goto out;
912: }
1.62 markus 913: if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT))
914: != 0)
1.1 djm 915: goto out;
916: if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
917: r = SSH_ERR_ALLOC_FAIL;
918: goto out;
919: }
1.7 djm 920: if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
1.1 djm 921: ret, SSH_DIGEST_MAX_LENGTH)) != 0)
922: goto out;
923: /* success */
924: if (retp != NULL) {
925: *retp = ret;
926: ret = NULL;
927: }
928: if (lenp != NULL)
1.7 djm 929: *lenp = ssh_digest_bytes(dgst_alg);
1.1 djm 930: r = 0;
931: out:
932: free(ret);
933: if (blob != NULL) {
934: explicit_bzero(blob, blob_len);
935: free(blob);
936: }
937: return r;
938: }
939:
940: static char *
1.7 djm 941: fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
942: {
943: char *ret;
944: size_t plen = strlen(alg) + 1;
945: size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
946: int r;
947:
948: if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
949: return NULL;
950: strlcpy(ret, alg, rlen);
951: strlcat(ret, ":", rlen);
952: if (dgst_raw_len == 0)
953: return ret;
954: if ((r = b64_ntop(dgst_raw, dgst_raw_len,
955: ret + plen, rlen - plen)) == -1) {
1.61 jsing 956: freezero(ret, rlen);
1.7 djm 957: return NULL;
958: }
959: /* Trim padding characters from end */
960: ret[strcspn(ret, "=")] = '\0';
961: return ret;
962: }
963:
964: static char *
965: fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
1.1 djm 966: {
1.7 djm 967: char *retval, hex[5];
968: size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
1.1 djm 969:
1.7 djm 970: if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
1.1 djm 971: return NULL;
1.7 djm 972: strlcpy(retval, alg, rlen);
973: strlcat(retval, ":", rlen);
1.1 djm 974: for (i = 0; i < dgst_raw_len; i++) {
1.7 djm 975: snprintf(hex, sizeof(hex), "%s%02x",
976: i > 0 ? ":" : "", dgst_raw[i]);
977: strlcat(retval, hex, rlen);
1.1 djm 978: }
979: return retval;
980: }
981:
982: static char *
983: fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
984: {
985: char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
986: char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
987: 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
988: u_int i, j = 0, rounds, seed = 1;
989: char *retval;
990:
991: rounds = (dgst_raw_len / 2) + 1;
992: if ((retval = calloc(rounds, 6)) == NULL)
993: return NULL;
994: retval[j++] = 'x';
995: for (i = 0; i < rounds; i++) {
996: u_int idx0, idx1, idx2, idx3, idx4;
997: if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
998: idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
999: seed) % 6;
1000: idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
1001: idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
1002: (seed / 6)) % 6;
1003: retval[j++] = vowels[idx0];
1004: retval[j++] = consonants[idx1];
1005: retval[j++] = vowels[idx2];
1006: if ((i + 1) < rounds) {
1007: idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
1008: idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
1009: retval[j++] = consonants[idx3];
1010: retval[j++] = '-';
1011: retval[j++] = consonants[idx4];
1012: seed = ((seed * 5) +
1013: ((((u_int)(dgst_raw[2 * i])) * 7) +
1014: ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
1015: }
1016: } else {
1017: idx0 = seed % 6;
1018: idx1 = 16;
1019: idx2 = seed / 6;
1020: retval[j++] = vowels[idx0];
1021: retval[j++] = consonants[idx1];
1022: retval[j++] = vowels[idx2];
1023: }
1024: }
1025: retval[j++] = 'x';
1026: retval[j++] = '\0';
1027: return retval;
1028: }
1029:
1030: /*
1031: * Draw an ASCII-Art representing the fingerprint so human brain can
1032: * profit from its built-in pattern recognition ability.
1033: * This technique is called "random art" and can be found in some
1034: * scientific publications like this original paper:
1035: *
1036: * "Hash Visualization: a New Technique to improve Real-World Security",
1037: * Perrig A. and Song D., 1999, International Workshop on Cryptographic
1038: * Techniques and E-Commerce (CrypTEC '99)
1039: * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
1040: *
1041: * The subject came up in a talk by Dan Kaminsky, too.
1042: *
1043: * If you see the picture is different, the key is different.
1044: * If the picture looks the same, you still know nothing.
1045: *
1046: * The algorithm used here is a worm crawling over a discrete plane,
1047: * leaving a trace (augmenting the field) everywhere it goes.
1048: * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
1049: * makes the respective movement vector be ignored for this turn.
1050: * Graphs are not unambiguous, because circles in graphs can be
1051: * walked in either direction.
1052: */
1053:
1054: /*
1055: * Field sizes for the random art. Have to be odd, so the starting point
1056: * can be in the exact middle of the picture, and FLDBASE should be >=8 .
1057: * Else pictures would be too dense, and drawing the frame would
1058: * fail, too, because the key type would not fit in anymore.
1059: */
1060: #define FLDBASE 8
1061: #define FLDSIZE_Y (FLDBASE + 1)
1062: #define FLDSIZE_X (FLDBASE * 2 + 1)
1063: static char *
1.7 djm 1064: fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
1.1 djm 1065: const struct sshkey *k)
1066: {
1067: /*
1068: * Chars to be used after each other every time the worm
1069: * intersects with itself. Matter of taste.
1070: */
1071: char *augmentation_string = " .o+=*BOX@%&#/^SE";
1.7 djm 1072: char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
1.1 djm 1073: u_char field[FLDSIZE_X][FLDSIZE_Y];
1.7 djm 1074: size_t i, tlen, hlen;
1.1 djm 1075: u_int b;
1.3 djm 1076: int x, y, r;
1.1 djm 1077: size_t len = strlen(augmentation_string) - 1;
1078:
1079: if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
1080: return NULL;
1081:
1082: /* initialize field */
1083: memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
1084: x = FLDSIZE_X / 2;
1085: y = FLDSIZE_Y / 2;
1086:
1087: /* process raw key */
1088: for (i = 0; i < dgst_raw_len; i++) {
1089: int input;
1090: /* each byte conveys four 2-bit move commands */
1091: input = dgst_raw[i];
1092: for (b = 0; b < 4; b++) {
1093: /* evaluate 2 bit, rest is shifted later */
1094: x += (input & 0x1) ? 1 : -1;
1095: y += (input & 0x2) ? 1 : -1;
1096:
1097: /* assure we are still in bounds */
1.37 deraadt 1098: x = MAXIMUM(x, 0);
1099: y = MAXIMUM(y, 0);
1100: x = MINIMUM(x, FLDSIZE_X - 1);
1101: y = MINIMUM(y, FLDSIZE_Y - 1);
1.1 djm 1102:
1103: /* augment the field */
1104: if (field[x][y] < len - 2)
1105: field[x][y]++;
1106: input = input >> 2;
1107: }
1108: }
1109:
1110: /* mark starting point and end point*/
1111: field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
1112: field[x][y] = len;
1113:
1.3 djm 1114: /* assemble title */
1115: r = snprintf(title, sizeof(title), "[%s %u]",
1116: sshkey_type(k), sshkey_size(k));
1117: /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
1118: if (r < 0 || r > (int)sizeof(title))
1.7 djm 1119: r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
1120: tlen = (r <= 0) ? 0 : strlen(title);
1121:
1122: /* assemble hash ID. */
1123: r = snprintf(hash, sizeof(hash), "[%s]", alg);
1124: hlen = (r <= 0) ? 0 : strlen(hash);
1.1 djm 1125:
1126: /* output upper border */
1.3 djm 1127: p = retval;
1128: *p++ = '+';
1129: for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
1130: *p++ = '-';
1131: memcpy(p, title, tlen);
1132: p += tlen;
1.7 djm 1133: for (i += tlen; i < FLDSIZE_X; i++)
1.1 djm 1134: *p++ = '-';
1135: *p++ = '+';
1136: *p++ = '\n';
1137:
1138: /* output content */
1139: for (y = 0; y < FLDSIZE_Y; y++) {
1140: *p++ = '|';
1141: for (x = 0; x < FLDSIZE_X; x++)
1.37 deraadt 1142: *p++ = augmentation_string[MINIMUM(field[x][y], len)];
1.1 djm 1143: *p++ = '|';
1144: *p++ = '\n';
1145: }
1146:
1147: /* output lower border */
1148: *p++ = '+';
1.7 djm 1149: for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
1150: *p++ = '-';
1151: memcpy(p, hash, hlen);
1152: p += hlen;
1153: for (i += hlen; i < FLDSIZE_X; i++)
1.1 djm 1154: *p++ = '-';
1155: *p++ = '+';
1156:
1157: return retval;
1158: }
1159:
1160: char *
1.7 djm 1161: sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1.1 djm 1162: enum sshkey_fp_rep dgst_rep)
1163: {
1164: char *retval = NULL;
1165: u_char *dgst_raw;
1166: size_t dgst_raw_len;
1167:
1.7 djm 1168: if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
1.1 djm 1169: return NULL;
1170: switch (dgst_rep) {
1.7 djm 1171: case SSH_FP_DEFAULT:
1172: if (dgst_alg == SSH_DIGEST_MD5) {
1173: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1174: dgst_raw, dgst_raw_len);
1175: } else {
1176: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1177: dgst_raw, dgst_raw_len);
1178: }
1179: break;
1.1 djm 1180: case SSH_FP_HEX:
1.7 djm 1181: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1182: dgst_raw, dgst_raw_len);
1183: break;
1184: case SSH_FP_BASE64:
1185: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1186: dgst_raw, dgst_raw_len);
1.1 djm 1187: break;
1188: case SSH_FP_BUBBLEBABBLE:
1189: retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
1190: break;
1191: case SSH_FP_RANDOMART:
1.7 djm 1192: retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
1193: dgst_raw, dgst_raw_len, k);
1.1 djm 1194: break;
1195: default:
1196: explicit_bzero(dgst_raw, dgst_raw_len);
1197: free(dgst_raw);
1198: return NULL;
1199: }
1200: explicit_bzero(dgst_raw, dgst_raw_len);
1201: free(dgst_raw);
1202: return retval;
1203: }
1204:
1.63 djm 1205: static int
1206: peek_type_nid(const char *s, size_t l, int *nid)
1207: {
1208: const struct keytype *kt;
1209:
1210: for (kt = keytypes; kt->type != -1; kt++) {
1211: if (kt->name == NULL || strlen(kt->name) != l)
1212: continue;
1213: if (memcmp(s, kt->name, l) == 0) {
1214: *nid = -1;
1215: if (kt->type == KEY_ECDSA || kt->type == KEY_ECDSA_CERT)
1216: *nid = kt->nid;
1217: return kt->type;
1218: }
1219: }
1220: return KEY_UNSPEC;
1221: }
1222:
1.1 djm 1223:
1.63 djm 1224: /* XXX this can now be made const char * */
1.1 djm 1225: int
1226: sshkey_read(struct sshkey *ret, char **cpp)
1227: {
1228: struct sshkey *k;
1.63 djm 1229: char *cp, *blobcopy;
1230: size_t space;
1.1 djm 1231: int r, type, curve_nid = -1;
1232: struct sshbuf *blob;
1.44 dtucker 1233:
1234: if (ret == NULL)
1235: return SSH_ERR_INVALID_ARGUMENT;
1.1 djm 1236:
1237: switch (ret->type) {
1238: case KEY_UNSPEC:
1239: case KEY_RSA:
1240: case KEY_DSA:
1241: case KEY_ECDSA:
1242: case KEY_ED25519:
1243: case KEY_DSA_CERT:
1244: case KEY_ECDSA_CERT:
1245: case KEY_RSA_CERT:
1246: case KEY_ED25519_CERT:
1.62 markus 1247: #ifdef WITH_XMSS
1248: case KEY_XMSS:
1249: case KEY_XMSS_CERT:
1250: #endif /* WITH_XMSS */
1.63 djm 1251: break; /* ok */
1252: default:
1253: return SSH_ERR_INVALID_ARGUMENT;
1254: }
1255:
1256: /* Decode type */
1257: cp = *cpp;
1258: space = strcspn(cp, " \t");
1259: if (space == strlen(cp))
1260: return SSH_ERR_INVALID_FORMAT;
1261: if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC)
1262: return SSH_ERR_INVALID_FORMAT;
1263:
1264: /* skip whitespace */
1265: for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1266: ;
1267: if (*cp == '\0')
1268: return SSH_ERR_INVALID_FORMAT;
1269: if (ret->type != KEY_UNSPEC && ret->type != type)
1270: return SSH_ERR_KEY_TYPE_MISMATCH;
1271: if ((blob = sshbuf_new()) == NULL)
1272: return SSH_ERR_ALLOC_FAIL;
1273:
1274: /* find end of keyblob and decode */
1275: space = strcspn(cp, " \t");
1276: if ((blobcopy = strndup(cp, space)) == NULL) {
1277: sshbuf_free(blob);
1278: return SSH_ERR_ALLOC_FAIL;
1279: }
1280: if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) {
1281: free(blobcopy);
1282: sshbuf_free(blob);
1283: return r;
1284: }
1285: free(blobcopy);
1286: if ((r = sshkey_fromb(blob, &k)) != 0) {
1.1 djm 1287: sshbuf_free(blob);
1.63 djm 1288: return r;
1289: }
1290: sshbuf_free(blob);
1291:
1292: /* skip whitespace and leave cp at start of comment */
1293: for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1294: ;
1295:
1296: /* ensure type of blob matches type at start of line */
1297: if (k->type != type) {
1298: sshkey_free(k);
1299: return SSH_ERR_KEY_TYPE_MISMATCH;
1300: }
1301: if (sshkey_type_plain(type) == KEY_ECDSA && curve_nid != k->ecdsa_nid) {
1302: sshkey_free(k);
1303: return SSH_ERR_EC_CURVE_MISMATCH;
1304: }
1305:
1306: /* Fill in ret from parsed key */
1307: ret->type = type;
1308: if (sshkey_is_cert(ret)) {
1309: if (!sshkey_is_cert(k)) {
1.1 djm 1310: sshkey_free(k);
1.63 djm 1311: return SSH_ERR_EXPECTED_CERT;
1.1 djm 1312: }
1.63 djm 1313: if (ret->cert != NULL)
1314: cert_free(ret->cert);
1315: ret->cert = k->cert;
1316: k->cert = NULL;
1317: }
1318: switch (sshkey_type_plain(ret->type)) {
1.1 djm 1319: #ifdef WITH_OPENSSL
1.63 djm 1320: case KEY_RSA:
1321: RSA_free(ret->rsa);
1322: ret->rsa = k->rsa;
1323: k->rsa = NULL;
1.1 djm 1324: #ifdef DEBUG_PK
1.63 djm 1325: RSA_print_fp(stderr, ret->rsa, 8);
1.1 djm 1326: #endif
1.63 djm 1327: break;
1328: case KEY_DSA:
1329: DSA_free(ret->dsa);
1330: ret->dsa = k->dsa;
1331: k->dsa = NULL;
1.1 djm 1332: #ifdef DEBUG_PK
1.63 djm 1333: DSA_print_fp(stderr, ret->dsa, 8);
1.1 djm 1334: #endif
1.63 djm 1335: break;
1336: case KEY_ECDSA:
1337: EC_KEY_free(ret->ecdsa);
1338: ret->ecdsa = k->ecdsa;
1339: ret->ecdsa_nid = k->ecdsa_nid;
1340: k->ecdsa = NULL;
1341: k->ecdsa_nid = -1;
1.1 djm 1342: #ifdef DEBUG_PK
1.63 djm 1343: sshkey_dump_ec_key(ret->ecdsa);
1.1 djm 1344: #endif
1.63 djm 1345: break;
1.1 djm 1346: #endif /* WITH_OPENSSL */
1.63 djm 1347: case KEY_ED25519:
1348: freezero(ret->ed25519_pk, ED25519_PK_SZ);
1349: ret->ed25519_pk = k->ed25519_pk;
1350: k->ed25519_pk = NULL;
1.1 djm 1351: #ifdef DEBUG_PK
1.63 djm 1352: /* XXX */
1.1 djm 1353: #endif
1.63 djm 1354: break;
1.62 markus 1355: #ifdef WITH_XMSS
1.63 djm 1356: case KEY_XMSS:
1357: free(ret->xmss_pk);
1358: ret->xmss_pk = k->xmss_pk;
1359: k->xmss_pk = NULL;
1360: free(ret->xmss_state);
1361: ret->xmss_state = k->xmss_state;
1362: k->xmss_state = NULL;
1363: free(ret->xmss_name);
1364: ret->xmss_name = k->xmss_name;
1365: k->xmss_name = NULL;
1366: free(ret->xmss_filename);
1367: ret->xmss_filename = k->xmss_filename;
1368: k->xmss_filename = NULL;
1.62 markus 1369: #ifdef DEBUG_PK
1.63 djm 1370: /* XXX */
1.62 markus 1371: #endif
1.63 djm 1372: break;
1.62 markus 1373: #endif /* WITH_XMSS */
1.63 djm 1374: default:
1.1 djm 1375: sshkey_free(k);
1.63 djm 1376: return SSH_ERR_INTERNAL_ERROR;
1.1 djm 1377: }
1.63 djm 1378: sshkey_free(k);
1379:
1380: /* success */
1381: *cpp = cp;
1382: return 0;
1.1 djm 1383: }
1384:
1385: int
1.19 djm 1386: sshkey_to_base64(const struct sshkey *key, char **b64p)
1.1 djm 1387: {
1.19 djm 1388: int r = SSH_ERR_INTERNAL_ERROR;
1389: struct sshbuf *b = NULL;
1.1 djm 1390: char *uu = NULL;
1.19 djm 1391:
1392: if (b64p != NULL)
1393: *b64p = NULL;
1394: if ((b = sshbuf_new()) == NULL)
1395: return SSH_ERR_ALLOC_FAIL;
1396: if ((r = sshkey_putb(key, b)) != 0)
1397: goto out;
1398: if ((uu = sshbuf_dtob64(b)) == NULL) {
1399: r = SSH_ERR_ALLOC_FAIL;
1400: goto out;
1401: }
1402: /* Success */
1403: if (b64p != NULL) {
1404: *b64p = uu;
1405: uu = NULL;
1406: }
1407: r = 0;
1408: out:
1409: sshbuf_free(b);
1410: free(uu);
1411: return r;
1412: }
1413:
1.52 djm 1414: int
1.19 djm 1415: sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
1416: {
1417: int r = SSH_ERR_INTERNAL_ERROR;
1418: char *uu = NULL;
1419:
1.48 djm 1420: if ((r = sshkey_to_base64(key, &uu)) != 0)
1421: goto out;
1422: if ((r = sshbuf_putf(b, "%s %s",
1423: sshkey_ssh_name(key), uu)) != 0)
1424: goto out;
1.19 djm 1425: r = 0;
1426: out:
1427: free(uu);
1428: return r;
1429: }
1430:
1431: int
1432: sshkey_write(const struct sshkey *key, FILE *f)
1433: {
1434: struct sshbuf *b = NULL;
1435: int r = SSH_ERR_INTERNAL_ERROR;
1436:
1437: if ((b = sshbuf_new()) == NULL)
1438: return SSH_ERR_ALLOC_FAIL;
1439: if ((r = sshkey_format_text(key, b)) != 0)
1.1 djm 1440: goto out;
1441: if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) {
1442: if (feof(f))
1443: errno = EPIPE;
1.19 djm 1444: r = SSH_ERR_SYSTEM_ERROR;
1.1 djm 1445: goto out;
1446: }
1.19 djm 1447: /* Success */
1448: r = 0;
1.1 djm 1449: out:
1.19 djm 1450: sshbuf_free(b);
1451: return r;
1.1 djm 1452: }
1453:
1454: const char *
1455: sshkey_cert_type(const struct sshkey *k)
1456: {
1457: switch (k->cert->type) {
1458: case SSH2_CERT_TYPE_USER:
1459: return "user";
1460: case SSH2_CERT_TYPE_HOST:
1461: return "host";
1462: default:
1463: return "unknown";
1464: }
1465: }
1466:
1467: #ifdef WITH_OPENSSL
1468: static int
1469: rsa_generate_private_key(u_int bits, RSA **rsap)
1470: {
1471: RSA *private = NULL;
1472: BIGNUM *f4 = NULL;
1473: int ret = SSH_ERR_INTERNAL_ERROR;
1474:
1.49 djm 1475: if (rsap == NULL)
1476: return SSH_ERR_INVALID_ARGUMENT;
1477: if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
1.1 djm 1478: bits > SSHBUF_MAX_BIGNUM * 8)
1.49 djm 1479: return SSH_ERR_KEY_LENGTH;
1.1 djm 1480: *rsap = NULL;
1481: if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
1482: ret = SSH_ERR_ALLOC_FAIL;
1483: goto out;
1484: }
1485: if (!BN_set_word(f4, RSA_F4) ||
1486: !RSA_generate_key_ex(private, bits, f4, NULL)) {
1487: ret = SSH_ERR_LIBCRYPTO_ERROR;
1488: goto out;
1489: }
1490: *rsap = private;
1491: private = NULL;
1492: ret = 0;
1493: out:
1.60 jsing 1494: RSA_free(private);
1495: BN_free(f4);
1.1 djm 1496: return ret;
1497: }
1498:
1499: static int
1500: dsa_generate_private_key(u_int bits, DSA **dsap)
1501: {
1502: DSA *private;
1503: int ret = SSH_ERR_INTERNAL_ERROR;
1504:
1.49 djm 1505: if (dsap == NULL)
1.1 djm 1506: return SSH_ERR_INVALID_ARGUMENT;
1.49 djm 1507: if (bits != 1024)
1508: return SSH_ERR_KEY_LENGTH;
1.1 djm 1509: if ((private = DSA_new()) == NULL) {
1510: ret = SSH_ERR_ALLOC_FAIL;
1511: goto out;
1512: }
1513: *dsap = NULL;
1514: if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1515: NULL, NULL) || !DSA_generate_key(private)) {
1516: ret = SSH_ERR_LIBCRYPTO_ERROR;
1517: goto out;
1518: }
1519: *dsap = private;
1520: private = NULL;
1521: ret = 0;
1522: out:
1.60 jsing 1523: DSA_free(private);
1.1 djm 1524: return ret;
1525: }
1526:
1527: int
1528: sshkey_ecdsa_key_to_nid(EC_KEY *k)
1529: {
1530: EC_GROUP *eg;
1531: int nids[] = {
1532: NID_X9_62_prime256v1,
1533: NID_secp384r1,
1534: NID_secp521r1,
1535: -1
1536: };
1537: int nid;
1538: u_int i;
1539: BN_CTX *bnctx;
1540: const EC_GROUP *g = EC_KEY_get0_group(k);
1541:
1542: /*
1543: * The group may be stored in a ASN.1 encoded private key in one of two
1544: * ways: as a "named group", which is reconstituted by ASN.1 object ID
1545: * or explicit group parameters encoded into the key blob. Only the
1546: * "named group" case sets the group NID for us, but we can figure
1547: * it out for the other case by comparing against all the groups that
1548: * are supported.
1549: */
1550: if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1551: return nid;
1552: if ((bnctx = BN_CTX_new()) == NULL)
1553: return -1;
1554: for (i = 0; nids[i] != -1; i++) {
1555: if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) {
1556: BN_CTX_free(bnctx);
1557: return -1;
1558: }
1559: if (EC_GROUP_cmp(g, eg, bnctx) == 0)
1560: break;
1561: EC_GROUP_free(eg);
1562: }
1563: BN_CTX_free(bnctx);
1564: if (nids[i] != -1) {
1565: /* Use the group with the NID attached */
1566: EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1567: if (EC_KEY_set_group(k, eg) != 1) {
1568: EC_GROUP_free(eg);
1569: return -1;
1570: }
1571: }
1572: return nids[i];
1573: }
1574:
1575: static int
1576: ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
1577: {
1578: EC_KEY *private;
1579: int ret = SSH_ERR_INTERNAL_ERROR;
1580:
1.50 djm 1581: if (nid == NULL || ecdsap == NULL)
1.1 djm 1582: return SSH_ERR_INVALID_ARGUMENT;
1.50 djm 1583: if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
1584: return SSH_ERR_KEY_LENGTH;
1.1 djm 1585: *ecdsap = NULL;
1586: if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
1587: ret = SSH_ERR_ALLOC_FAIL;
1588: goto out;
1589: }
1590: if (EC_KEY_generate_key(private) != 1) {
1591: ret = SSH_ERR_LIBCRYPTO_ERROR;
1592: goto out;
1593: }
1594: EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
1595: *ecdsap = private;
1596: private = NULL;
1597: ret = 0;
1598: out:
1.60 jsing 1599: EC_KEY_free(private);
1.1 djm 1600: return ret;
1601: }
1602: #endif /* WITH_OPENSSL */
1603:
1604: int
1605: sshkey_generate(int type, u_int bits, struct sshkey **keyp)
1606: {
1607: struct sshkey *k;
1608: int ret = SSH_ERR_INTERNAL_ERROR;
1609:
1610: if (keyp == NULL)
1611: return SSH_ERR_INVALID_ARGUMENT;
1612: *keyp = NULL;
1613: if ((k = sshkey_new(KEY_UNSPEC)) == NULL)
1614: return SSH_ERR_ALLOC_FAIL;
1615: switch (type) {
1616: case KEY_ED25519:
1617: if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL ||
1618: (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) {
1619: ret = SSH_ERR_ALLOC_FAIL;
1620: break;
1621: }
1622: crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
1623: ret = 0;
1624: break;
1.62 markus 1625: #ifdef WITH_XMSS
1626: case KEY_XMSS:
1627: ret = sshkey_xmss_generate_private_key(k, bits);
1628: break;
1629: #endif /* WITH_XMSS */
1.1 djm 1630: #ifdef WITH_OPENSSL
1631: case KEY_DSA:
1632: ret = dsa_generate_private_key(bits, &k->dsa);
1633: break;
1634: case KEY_ECDSA:
1635: ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid,
1636: &k->ecdsa);
1637: break;
1638: case KEY_RSA:
1639: ret = rsa_generate_private_key(bits, &k->rsa);
1640: break;
1641: #endif /* WITH_OPENSSL */
1642: default:
1643: ret = SSH_ERR_INVALID_ARGUMENT;
1644: }
1645: if (ret == 0) {
1646: k->type = type;
1647: *keyp = k;
1648: } else
1649: sshkey_free(k);
1650: return ret;
1651: }
1652:
1653: int
1654: sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
1655: {
1656: u_int i;
1657: const struct sshkey_cert *from;
1658: struct sshkey_cert *to;
1.67 djm 1659: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 1660:
1.67 djm 1661: if (to_key == NULL || (from = from_key->cert) == NULL)
1.1 djm 1662: return SSH_ERR_INVALID_ARGUMENT;
1663:
1.67 djm 1664: if ((to = cert_new()) == NULL)
1.1 djm 1665: return SSH_ERR_ALLOC_FAIL;
1666:
1.67 djm 1667: if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
1668: (r = sshbuf_putb(to->critical, from->critical)) != 0 ||
1669: (r = sshbuf_putb(to->extensions, from->extensions)) != 0)
1670: goto out;
1.1 djm 1671:
1672: to->serial = from->serial;
1673: to->type = from->type;
1674: if (from->key_id == NULL)
1675: to->key_id = NULL;
1.67 djm 1676: else if ((to->key_id = strdup(from->key_id)) == NULL) {
1677: r = SSH_ERR_ALLOC_FAIL;
1678: goto out;
1679: }
1.1 djm 1680: to->valid_after = from->valid_after;
1681: to->valid_before = from->valid_before;
1682: if (from->signature_key == NULL)
1683: to->signature_key = NULL;
1.67 djm 1684: else if ((r = sshkey_from_private(from->signature_key,
1.1 djm 1685: &to->signature_key)) != 0)
1.67 djm 1686: goto out;
1687: if (from->signature_type != NULL &&
1688: (to->signature_type = strdup(from->signature_type)) == NULL) {
1689: r = SSH_ERR_ALLOC_FAIL;
1690: goto out;
1691: }
1692: if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) {
1693: r = SSH_ERR_INVALID_ARGUMENT;
1694: goto out;
1695: }
1.1 djm 1696: if (from->nprincipals > 0) {
1697: if ((to->principals = calloc(from->nprincipals,
1.67 djm 1698: sizeof(*to->principals))) == NULL) {
1699: r = SSH_ERR_ALLOC_FAIL;
1700: goto out;
1701: }
1.1 djm 1702: for (i = 0; i < from->nprincipals; i++) {
1703: to->principals[i] = strdup(from->principals[i]);
1704: if (to->principals[i] == NULL) {
1705: to->nprincipals = i;
1.67 djm 1706: r = SSH_ERR_ALLOC_FAIL;
1707: goto out;
1.1 djm 1708: }
1709: }
1710: }
1711: to->nprincipals = from->nprincipals;
1.67 djm 1712:
1713: /* success */
1714: cert_free(to_key->cert);
1715: to_key->cert = to;
1716: to = NULL;
1717: r = 0;
1718: out:
1719: cert_free(to);
1720: return r;
1.1 djm 1721: }
1722:
1723: int
1724: sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1725: {
1726: struct sshkey *n = NULL;
1727: int ret = SSH_ERR_INTERNAL_ERROR;
1728:
1.24 djm 1729: *pkp = NULL;
1.1 djm 1730: switch (k->type) {
1731: #ifdef WITH_OPENSSL
1732: case KEY_DSA:
1733: case KEY_DSA_CERT:
1734: if ((n = sshkey_new(k->type)) == NULL)
1735: return SSH_ERR_ALLOC_FAIL;
1736: if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
1737: (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
1738: (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
1739: (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) {
1740: sshkey_free(n);
1741: return SSH_ERR_ALLOC_FAIL;
1742: }
1743: break;
1744: case KEY_ECDSA:
1745: case KEY_ECDSA_CERT:
1746: if ((n = sshkey_new(k->type)) == NULL)
1747: return SSH_ERR_ALLOC_FAIL;
1748: n->ecdsa_nid = k->ecdsa_nid;
1749: n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
1750: if (n->ecdsa == NULL) {
1751: sshkey_free(n);
1752: return SSH_ERR_ALLOC_FAIL;
1753: }
1754: if (EC_KEY_set_public_key(n->ecdsa,
1755: EC_KEY_get0_public_key(k->ecdsa)) != 1) {
1756: sshkey_free(n);
1757: return SSH_ERR_LIBCRYPTO_ERROR;
1758: }
1759: break;
1760: case KEY_RSA:
1761: case KEY_RSA_CERT:
1762: if ((n = sshkey_new(k->type)) == NULL)
1763: return SSH_ERR_ALLOC_FAIL;
1764: if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
1765: (BN_copy(n->rsa->e, k->rsa->e) == NULL)) {
1766: sshkey_free(n);
1767: return SSH_ERR_ALLOC_FAIL;
1768: }
1769: break;
1770: #endif /* WITH_OPENSSL */
1771: case KEY_ED25519:
1772: case KEY_ED25519_CERT:
1773: if ((n = sshkey_new(k->type)) == NULL)
1774: return SSH_ERR_ALLOC_FAIL;
1775: if (k->ed25519_pk != NULL) {
1776: if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
1777: sshkey_free(n);
1778: return SSH_ERR_ALLOC_FAIL;
1779: }
1780: memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1781: }
1782: break;
1.62 markus 1783: #ifdef WITH_XMSS
1784: case KEY_XMSS:
1785: case KEY_XMSS_CERT:
1786: if ((n = sshkey_new(k->type)) == NULL)
1787: return SSH_ERR_ALLOC_FAIL;
1788: if ((ret = sshkey_xmss_init(n, k->xmss_name)) != 0) {
1789: sshkey_free(n);
1790: return ret;
1791: }
1792: if (k->xmss_pk != NULL) {
1793: size_t pklen = sshkey_xmss_pklen(k);
1794: if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
1795: sshkey_free(n);
1796: return SSH_ERR_INTERNAL_ERROR;
1797: }
1798: if ((n->xmss_pk = malloc(pklen)) == NULL) {
1799: sshkey_free(n);
1800: return SSH_ERR_ALLOC_FAIL;
1801: }
1802: memcpy(n->xmss_pk, k->xmss_pk, pklen);
1803: }
1804: break;
1805: #endif /* WITH_XMSS */
1.1 djm 1806: default:
1807: return SSH_ERR_KEY_TYPE_UNKNOWN;
1808: }
1809: if (sshkey_is_cert(k)) {
1810: if ((ret = sshkey_cert_copy(k, n)) != 0) {
1811: sshkey_free(n);
1812: return ret;
1813: }
1814: }
1815: *pkp = n;
1816: return 0;
1817: }
1818:
1819: static int
1.14 djm 1820: cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1.1 djm 1821: {
1.14 djm 1822: struct sshbuf *principals = NULL, *crit = NULL;
1823: struct sshbuf *exts = NULL, *ca = NULL;
1824: u_char *sig = NULL;
1825: size_t signed_len = 0, slen = 0, kidlen = 0;
1.1 djm 1826: int ret = SSH_ERR_INTERNAL_ERROR;
1827:
1828: /* Copy the entire key blob for verification and later serialisation */
1.14 djm 1829: if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0)
1.1 djm 1830: return ret;
1831:
1.20 djm 1832: /* Parse body of certificate up to signature */
1833: if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 ||
1.1 djm 1834: (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
1835: (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
1.4 djm 1836: (ret = sshbuf_froms(b, &principals)) != 0 ||
1.1 djm 1837: (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
1838: (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
1.4 djm 1839: (ret = sshbuf_froms(b, &crit)) != 0 ||
1.20 djm 1840: (ret = sshbuf_froms(b, &exts)) != 0 ||
1.1 djm 1841: (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
1.14 djm 1842: (ret = sshbuf_froms(b, &ca)) != 0) {
1.1 djm 1843: /* XXX debug print error for ret */
1844: ret = SSH_ERR_INVALID_FORMAT;
1845: goto out;
1846: }
1847:
1848: /* Signature is left in the buffer so we can calculate this length */
1849: signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b);
1850:
1851: if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) {
1852: ret = SSH_ERR_INVALID_FORMAT;
1853: goto out;
1854: }
1855:
1856: if (key->cert->type != SSH2_CERT_TYPE_USER &&
1857: key->cert->type != SSH2_CERT_TYPE_HOST) {
1858: ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE;
1859: goto out;
1860: }
1861:
1.4 djm 1862: /* Parse principals section */
1863: while (sshbuf_len(principals) > 0) {
1864: char *principal = NULL;
1865: char **oprincipals = NULL;
1866:
1.1 djm 1867: if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
1868: ret = SSH_ERR_INVALID_FORMAT;
1869: goto out;
1870: }
1.4 djm 1871: if ((ret = sshbuf_get_cstring(principals, &principal,
1872: NULL)) != 0) {
1.1 djm 1873: ret = SSH_ERR_INVALID_FORMAT;
1874: goto out;
1875: }
1876: oprincipals = key->cert->principals;
1.51 deraadt 1877: key->cert->principals = recallocarray(key->cert->principals,
1878: key->cert->nprincipals, key->cert->nprincipals + 1,
1879: sizeof(*key->cert->principals));
1.1 djm 1880: if (key->cert->principals == NULL) {
1881: free(principal);
1882: key->cert->principals = oprincipals;
1883: ret = SSH_ERR_ALLOC_FAIL;
1884: goto out;
1885: }
1886: key->cert->principals[key->cert->nprincipals++] = principal;
1887: }
1888:
1.4 djm 1889: /*
1890: * Stash a copies of the critical options and extensions sections
1891: * for later use.
1892: */
1893: if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 ||
1894: (exts != NULL &&
1895: (ret = sshbuf_putb(key->cert->extensions, exts)) != 0))
1.1 djm 1896: goto out;
1897:
1.4 djm 1898: /*
1899: * Validate critical options and extensions sections format.
1900: */
1901: while (sshbuf_len(crit) != 0) {
1902: if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
1903: (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) {
1904: sshbuf_reset(key->cert->critical);
1.1 djm 1905: ret = SSH_ERR_INVALID_FORMAT;
1906: goto out;
1907: }
1908: }
1.4 djm 1909: while (exts != NULL && sshbuf_len(exts) != 0) {
1910: if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 ||
1911: (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) {
1912: sshbuf_reset(key->cert->extensions);
1.1 djm 1913: ret = SSH_ERR_INVALID_FORMAT;
1914: goto out;
1915: }
1916: }
1917:
1.4 djm 1918: /* Parse CA key and check signature */
1.14 djm 1919: if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) {
1.1 djm 1920: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1921: goto out;
1922: }
1923: if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) {
1924: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1925: goto out;
1926: }
1927: if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1.59 djm 1928: sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
1.1 djm 1929: goto out;
1.67 djm 1930: if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0)
1931: goto out;
1.4 djm 1932:
1933: /* Success */
1.1 djm 1934: ret = 0;
1935: out:
1.14 djm 1936: sshbuf_free(ca);
1.4 djm 1937: sshbuf_free(crit);
1938: sshbuf_free(exts);
1939: sshbuf_free(principals);
1.1 djm 1940: free(sig);
1941: return ret;
1942: }
1943:
1944: static int
1.14 djm 1945: sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
1946: int allow_cert)
1.1 djm 1947: {
1.12 djm 1948: int type, ret = SSH_ERR_INTERNAL_ERROR;
1.62 markus 1949: char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
1.1 djm 1950: struct sshkey *key = NULL;
1951: size_t len;
1952: u_char *pk = NULL;
1.14 djm 1953: struct sshbuf *copy;
1.1 djm 1954: #ifdef WITH_OPENSSL
1955: EC_POINT *q = NULL;
1956: #endif /* WITH_OPENSSL */
1957:
1958: #ifdef DEBUG_PK /* XXX */
1.14 djm 1959: sshbuf_dump(b, stderr);
1.1 djm 1960: #endif
1.32 djm 1961: if (keyp != NULL)
1962: *keyp = NULL;
1.14 djm 1963: if ((copy = sshbuf_fromb(b)) == NULL) {
1964: ret = SSH_ERR_ALLOC_FAIL;
1965: goto out;
1966: }
1.1 djm 1967: if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
1968: ret = SSH_ERR_INVALID_FORMAT;
1969: goto out;
1970: }
1971:
1972: type = sshkey_type_from_name(ktype);
1973: if (!allow_cert && sshkey_type_is_cert(type)) {
1974: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1975: goto out;
1976: }
1977: switch (type) {
1978: #ifdef WITH_OPENSSL
1979: case KEY_RSA_CERT:
1.14 djm 1980: /* Skip nonce */
1.1 djm 1981: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
1982: ret = SSH_ERR_INVALID_FORMAT;
1983: goto out;
1984: }
1985: /* FALLTHROUGH */
1986: case KEY_RSA:
1987: if ((key = sshkey_new(type)) == NULL) {
1988: ret = SSH_ERR_ALLOC_FAIL;
1989: goto out;
1990: }
1.16 djm 1991: if (sshbuf_get_bignum2(b, key->rsa->e) != 0 ||
1992: sshbuf_get_bignum2(b, key->rsa->n) != 0) {
1.1 djm 1993: ret = SSH_ERR_INVALID_FORMAT;
1994: goto out;
1995: }
1.49 djm 1996: if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
1997: ret = SSH_ERR_KEY_LENGTH;
1998: goto out;
1999: }
1.1 djm 2000: #ifdef DEBUG_PK
2001: RSA_print_fp(stderr, key->rsa, 8);
2002: #endif
2003: break;
2004: case KEY_DSA_CERT:
1.14 djm 2005: /* Skip nonce */
1.1 djm 2006: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2007: ret = SSH_ERR_INVALID_FORMAT;
2008: goto out;
2009: }
2010: /* FALLTHROUGH */
2011: case KEY_DSA:
2012: if ((key = sshkey_new(type)) == NULL) {
2013: ret = SSH_ERR_ALLOC_FAIL;
2014: goto out;
2015: }
1.16 djm 2016: if (sshbuf_get_bignum2(b, key->dsa->p) != 0 ||
2017: sshbuf_get_bignum2(b, key->dsa->q) != 0 ||
2018: sshbuf_get_bignum2(b, key->dsa->g) != 0 ||
2019: sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) {
1.1 djm 2020: ret = SSH_ERR_INVALID_FORMAT;
2021: goto out;
2022: }
2023: #ifdef DEBUG_PK
2024: DSA_print_fp(stderr, key->dsa, 8);
2025: #endif
2026: break;
2027: case KEY_ECDSA_CERT:
1.14 djm 2028: /* Skip nonce */
1.1 djm 2029: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2030: ret = SSH_ERR_INVALID_FORMAT;
2031: goto out;
2032: }
2033: /* FALLTHROUGH */
2034: case KEY_ECDSA:
2035: if ((key = sshkey_new(type)) == NULL) {
2036: ret = SSH_ERR_ALLOC_FAIL;
2037: goto out;
2038: }
1.12 djm 2039: key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
1.1 djm 2040: if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
2041: ret = SSH_ERR_INVALID_FORMAT;
2042: goto out;
2043: }
2044: if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
2045: ret = SSH_ERR_EC_CURVE_MISMATCH;
2046: goto out;
2047: }
1.60 jsing 2048: EC_KEY_free(key->ecdsa);
1.1 djm 2049: if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
2050: == NULL) {
2051: ret = SSH_ERR_EC_CURVE_INVALID;
2052: goto out;
2053: }
2054: if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
2055: ret = SSH_ERR_ALLOC_FAIL;
2056: goto out;
2057: }
2058: if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
2059: ret = SSH_ERR_INVALID_FORMAT;
2060: goto out;
2061: }
2062: if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
2063: q) != 0) {
2064: ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2065: goto out;
2066: }
2067: if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
2068: /* XXX assume it is a allocation error */
2069: ret = SSH_ERR_ALLOC_FAIL;
2070: goto out;
2071: }
2072: #ifdef DEBUG_PK
2073: sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
2074: #endif
2075: break;
2076: #endif /* WITH_OPENSSL */
2077: case KEY_ED25519_CERT:
1.14 djm 2078: /* Skip nonce */
1.1 djm 2079: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2080: ret = SSH_ERR_INVALID_FORMAT;
2081: goto out;
2082: }
2083: /* FALLTHROUGH */
2084: case KEY_ED25519:
2085: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2086: goto out;
2087: if (len != ED25519_PK_SZ) {
2088: ret = SSH_ERR_INVALID_FORMAT;
2089: goto out;
2090: }
2091: if ((key = sshkey_new(type)) == NULL) {
2092: ret = SSH_ERR_ALLOC_FAIL;
2093: goto out;
2094: }
2095: key->ed25519_pk = pk;
2096: pk = NULL;
2097: break;
1.62 markus 2098: #ifdef WITH_XMSS
2099: case KEY_XMSS_CERT:
2100: /* Skip nonce */
2101: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2102: ret = SSH_ERR_INVALID_FORMAT;
2103: goto out;
2104: }
2105: /* FALLTHROUGH */
2106: case KEY_XMSS:
2107: if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
2108: goto out;
2109: if ((key = sshkey_new(type)) == NULL) {
2110: ret = SSH_ERR_ALLOC_FAIL;
2111: goto out;
2112: }
2113: if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
2114: goto out;
2115: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2116: goto out;
2117: if (len == 0 || len != sshkey_xmss_pklen(key)) {
2118: ret = SSH_ERR_INVALID_FORMAT;
2119: goto out;
2120: }
2121: key->xmss_pk = pk;
2122: pk = NULL;
2123: if (type != KEY_XMSS_CERT &&
2124: (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
2125: goto out;
2126: break;
2127: #endif /* WITH_XMSS */
1.1 djm 2128: case KEY_UNSPEC:
2129: default:
2130: ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2131: goto out;
2132: }
2133:
2134: /* Parse certificate potion */
1.14 djm 2135: if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
1.1 djm 2136: goto out;
2137:
2138: if (key != NULL && sshbuf_len(b) != 0) {
2139: ret = SSH_ERR_INVALID_FORMAT;
2140: goto out;
2141: }
2142: ret = 0;
1.32 djm 2143: if (keyp != NULL) {
2144: *keyp = key;
2145: key = NULL;
2146: }
1.1 djm 2147: out:
1.14 djm 2148: sshbuf_free(copy);
1.1 djm 2149: sshkey_free(key);
1.62 markus 2150: free(xmss_name);
1.1 djm 2151: free(ktype);
2152: free(curve);
2153: free(pk);
2154: #ifdef WITH_OPENSSL
1.60 jsing 2155: EC_POINT_free(q);
1.1 djm 2156: #endif /* WITH_OPENSSL */
2157: return ret;
2158: }
2159:
2160: int
2161: sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp)
2162: {
1.14 djm 2163: struct sshbuf *b;
2164: int r;
2165:
2166: if ((b = sshbuf_from(blob, blen)) == NULL)
2167: return SSH_ERR_ALLOC_FAIL;
2168: r = sshkey_from_blob_internal(b, keyp, 1);
2169: sshbuf_free(b);
2170: return r;
2171: }
2172:
2173: int
2174: sshkey_fromb(struct sshbuf *b, struct sshkey **keyp)
2175: {
2176: return sshkey_from_blob_internal(b, keyp, 1);
2177: }
2178:
2179: int
2180: sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2181: {
2182: struct sshbuf *b;
2183: int r;
2184:
2185: if ((r = sshbuf_froms(buf, &b)) != 0)
2186: return r;
2187: r = sshkey_from_blob_internal(b, keyp, 1);
1.58 djm 2188: sshbuf_free(b);
2189: return r;
2190: }
2191:
1.65 djm 2192: static int
2193: get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
1.58 djm 2194: {
2195: int r;
2196: struct sshbuf *b = NULL;
2197: char *sigtype = NULL;
2198:
2199: if (sigtypep != NULL)
2200: *sigtypep = NULL;
2201: if ((b = sshbuf_from(sig, siglen)) == NULL)
2202: return SSH_ERR_ALLOC_FAIL;
2203: if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0)
2204: goto out;
2205: /* success */
2206: if (sigtypep != NULL) {
2207: *sigtypep = sigtype;
2208: sigtype = NULL;
2209: }
2210: r = 0;
2211: out:
2212: free(sigtype);
1.14 djm 2213: sshbuf_free(b);
2214: return r;
1.68 ! djm 2215: }
! 2216:
! 2217: /*
! 2218: *
! 2219: * Checks whether a certificate's signature type is allowed.
! 2220: * Returns 0 (success) if the certificate signature type appears in the
! 2221: * "allowed" pattern-list, or the key is not a certificate to begin with.
! 2222: * Otherwise returns a ssherr.h code.
! 2223: */
! 2224: int
! 2225: sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed)
! 2226: {
! 2227: if (key == NULL || allowed == NULL)
! 2228: return SSH_ERR_INVALID_ARGUMENT;
! 2229: if (!sshkey_type_is_cert(key->type))
! 2230: return 0;
! 2231: if (key->cert == NULL || key->cert->signature_type == NULL)
! 2232: return SSH_ERR_INVALID_ARGUMENT;
! 2233: if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1)
! 2234: return SSH_ERR_SIGN_ALG_UNSUPPORTED;
! 2235: return 0;
1.65 djm 2236: }
2237:
2238: /*
2239: * Returns the expected signature algorithm for a given public key algorithm.
2240: */
1.66 djm 2241: const char *
2242: sshkey_sigalg_by_name(const char *name)
1.65 djm 2243: {
2244: const struct keytype *kt;
2245:
2246: for (kt = keytypes; kt->type != -1; kt++) {
2247: if (strcmp(kt->name, name) != 0)
2248: continue;
2249: if (kt->sigalg != NULL)
2250: return kt->sigalg;
2251: if (!kt->cert)
2252: return kt->name;
2253: return sshkey_ssh_name_from_type_nid(
2254: sshkey_type_plain(kt->type), kt->nid);
2255: }
2256: return NULL;
2257: }
2258:
2259: /*
2260: * Verifies that the signature algorithm appearing inside the signature blob
2261: * matches that which was requested.
2262: */
2263: int
2264: sshkey_check_sigtype(const u_char *sig, size_t siglen,
2265: const char *requested_alg)
2266: {
2267: const char *expected_alg;
2268: char *sigtype = NULL;
2269: int r;
2270:
2271: if (requested_alg == NULL)
2272: return 0;
1.66 djm 2273: if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
1.65 djm 2274: return SSH_ERR_INVALID_ARGUMENT;
2275: if ((r = get_sigtype(sig, siglen, &sigtype)) != 0)
2276: return r;
2277: r = strcmp(expected_alg, sigtype) == 0;
2278: free(sigtype);
2279: return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
1.1 djm 2280: }
2281:
2282: int
2283: sshkey_sign(const struct sshkey *key,
2284: u_char **sigp, size_t *lenp,
1.28 markus 2285: const u_char *data, size_t datalen, const char *alg, u_int compat)
1.1 djm 2286: {
2287: if (sigp != NULL)
2288: *sigp = NULL;
2289: if (lenp != NULL)
2290: *lenp = 0;
2291: if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2292: return SSH_ERR_INVALID_ARGUMENT;
2293: switch (key->type) {
2294: #ifdef WITH_OPENSSL
2295: case KEY_DSA_CERT:
2296: case KEY_DSA:
2297: return ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
2298: case KEY_ECDSA_CERT:
2299: case KEY_ECDSA:
2300: return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
2301: case KEY_RSA_CERT:
2302: case KEY_RSA:
1.28 markus 2303: return ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
1.1 djm 2304: #endif /* WITH_OPENSSL */
2305: case KEY_ED25519:
2306: case KEY_ED25519_CERT:
2307: return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
1.62 markus 2308: #ifdef WITH_XMSS
2309: case KEY_XMSS:
2310: case KEY_XMSS_CERT:
2311: return ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
2312: #endif /* WITH_XMSS */
1.1 djm 2313: default:
2314: return SSH_ERR_KEY_TYPE_UNKNOWN;
2315: }
2316: }
2317:
2318: /*
2319: * ssh_key_verify returns 0 for a correct signature and < 0 on error.
1.59 djm 2320: * If "alg" specified, then the signature must use that algorithm.
1.1 djm 2321: */
2322: int
2323: sshkey_verify(const struct sshkey *key,
2324: const u_char *sig, size_t siglen,
1.59 djm 2325: const u_char *data, size_t dlen, const char *alg, u_int compat)
1.1 djm 2326: {
1.6 djm 2327: if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
1.1 djm 2328: return SSH_ERR_INVALID_ARGUMENT;
2329: switch (key->type) {
2330: #ifdef WITH_OPENSSL
2331: case KEY_DSA_CERT:
2332: case KEY_DSA:
2333: return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
2334: case KEY_ECDSA_CERT:
2335: case KEY_ECDSA:
2336: return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
2337: case KEY_RSA_CERT:
2338: case KEY_RSA:
1.59 djm 2339: return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
1.1 djm 2340: #endif /* WITH_OPENSSL */
2341: case KEY_ED25519:
2342: case KEY_ED25519_CERT:
2343: return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
1.62 markus 2344: #ifdef WITH_XMSS
2345: case KEY_XMSS:
2346: case KEY_XMSS_CERT:
2347: return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
2348: #endif /* WITH_XMSS */
1.1 djm 2349: default:
2350: return SSH_ERR_KEY_TYPE_UNKNOWN;
2351: }
2352: }
2353:
2354: /* Converts a private to a public key */
2355: int
2356: sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
2357: {
2358: struct sshkey *pk;
2359: int ret = SSH_ERR_INTERNAL_ERROR;
2360:
1.24 djm 2361: *dkp = NULL;
1.1 djm 2362: if ((pk = calloc(1, sizeof(*pk))) == NULL)
2363: return SSH_ERR_ALLOC_FAIL;
2364: pk->type = k->type;
2365: pk->flags = k->flags;
2366: pk->ecdsa_nid = k->ecdsa_nid;
2367: pk->dsa = NULL;
2368: pk->ecdsa = NULL;
2369: pk->rsa = NULL;
2370: pk->ed25519_pk = NULL;
2371: pk->ed25519_sk = NULL;
1.62 markus 2372: pk->xmss_pk = NULL;
2373: pk->xmss_sk = NULL;
1.1 djm 2374:
2375: switch (k->type) {
2376: #ifdef WITH_OPENSSL
2377: case KEY_RSA_CERT:
2378: if ((ret = sshkey_cert_copy(k, pk)) != 0)
2379: goto fail;
2380: /* FALLTHROUGH */
2381: case KEY_RSA:
2382: if ((pk->rsa = RSA_new()) == NULL ||
2383: (pk->rsa->e = BN_dup(k->rsa->e)) == NULL ||
2384: (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) {
2385: ret = SSH_ERR_ALLOC_FAIL;
2386: goto fail;
2387: }
2388: break;
2389: case KEY_DSA_CERT:
2390: if ((ret = sshkey_cert_copy(k, pk)) != 0)
2391: goto fail;
2392: /* FALLTHROUGH */
2393: case KEY_DSA:
2394: if ((pk->dsa = DSA_new()) == NULL ||
2395: (pk->dsa->p = BN_dup(k->dsa->p)) == NULL ||
2396: (pk->dsa->q = BN_dup(k->dsa->q)) == NULL ||
2397: (pk->dsa->g = BN_dup(k->dsa->g)) == NULL ||
2398: (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) {
2399: ret = SSH_ERR_ALLOC_FAIL;
2400: goto fail;
2401: }
2402: break;
2403: case KEY_ECDSA_CERT:
2404: if ((ret = sshkey_cert_copy(k, pk)) != 0)
2405: goto fail;
2406: /* FALLTHROUGH */
2407: case KEY_ECDSA:
2408: pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid);
2409: if (pk->ecdsa == NULL) {
2410: ret = SSH_ERR_ALLOC_FAIL;
2411: goto fail;
2412: }
2413: if (EC_KEY_set_public_key(pk->ecdsa,
2414: EC_KEY_get0_public_key(k->ecdsa)) != 1) {
2415: ret = SSH_ERR_LIBCRYPTO_ERROR;
2416: goto fail;
2417: }
2418: break;
2419: #endif /* WITH_OPENSSL */
2420: case KEY_ED25519_CERT:
2421: if ((ret = sshkey_cert_copy(k, pk)) != 0)
2422: goto fail;
2423: /* FALLTHROUGH */
2424: case KEY_ED25519:
2425: if (k->ed25519_pk != NULL) {
2426: if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
2427: ret = SSH_ERR_ALLOC_FAIL;
2428: goto fail;
2429: }
2430: memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
2431: }
2432: break;
1.62 markus 2433: #ifdef WITH_XMSS
2434: case KEY_XMSS_CERT:
2435: if ((ret = sshkey_cert_copy(k, pk)) != 0)
2436: goto fail;
2437: /* FALLTHROUGH */
2438: case KEY_XMSS:
2439: if ((ret = sshkey_xmss_init(pk, k->xmss_name)) != 0)
2440: goto fail;
2441: if (k->xmss_pk != NULL) {
2442: size_t pklen = sshkey_xmss_pklen(k);
2443:
2444: if (pklen == 0 || sshkey_xmss_pklen(pk) != pklen) {
2445: ret = SSH_ERR_INTERNAL_ERROR;
2446: goto fail;
2447: }
2448: if ((pk->xmss_pk = malloc(pklen)) == NULL) {
2449: ret = SSH_ERR_ALLOC_FAIL;
2450: goto fail;
2451: }
2452: memcpy(pk->xmss_pk, k->xmss_pk, pklen);
2453: }
2454: break;
2455: #endif /* WITH_XMSS */
1.1 djm 2456: default:
2457: ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2458: fail:
2459: sshkey_free(pk);
2460: return ret;
2461: }
2462: *dkp = pk;
2463: return 0;
2464: }
2465:
2466: /* Convert a plain key to their _CERT equivalent */
2467: int
1.20 djm 2468: sshkey_to_certified(struct sshkey *k)
1.1 djm 2469: {
2470: int newtype;
2471:
2472: switch (k->type) {
2473: #ifdef WITH_OPENSSL
2474: case KEY_RSA:
1.20 djm 2475: newtype = KEY_RSA_CERT;
1.1 djm 2476: break;
2477: case KEY_DSA:
1.20 djm 2478: newtype = KEY_DSA_CERT;
1.1 djm 2479: break;
2480: case KEY_ECDSA:
2481: newtype = KEY_ECDSA_CERT;
2482: break;
2483: #endif /* WITH_OPENSSL */
2484: case KEY_ED25519:
2485: newtype = KEY_ED25519_CERT;
2486: break;
1.62 markus 2487: #ifdef WITH_XMSS
2488: case KEY_XMSS:
2489: newtype = KEY_XMSS_CERT;
2490: break;
2491: #endif /* WITH_XMSS */
1.1 djm 2492: default:
2493: return SSH_ERR_INVALID_ARGUMENT;
2494: }
2495: if ((k->cert = cert_new()) == NULL)
2496: return SSH_ERR_ALLOC_FAIL;
2497: k->type = newtype;
2498: return 0;
2499: }
2500:
2501: /* Convert a certificate to its raw key equivalent */
2502: int
2503: sshkey_drop_cert(struct sshkey *k)
2504: {
2505: if (!sshkey_type_is_cert(k->type))
2506: return SSH_ERR_KEY_TYPE_UNKNOWN;
2507: cert_free(k->cert);
2508: k->cert = NULL;
2509: k->type = sshkey_type_plain(k->type);
2510: return 0;
2511: }
2512:
2513: /* Sign a certified key, (re-)generating the signed certblob. */
2514: int
1.53 djm 2515: sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2516: sshkey_certify_signer *signer, void *signer_ctx)
1.1 djm 2517: {
2518: struct sshbuf *principals = NULL;
2519: u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
2520: size_t i, ca_len, sig_len;
2521: int ret = SSH_ERR_INTERNAL_ERROR;
1.67 djm 2522: struct sshbuf *cert = NULL;
2523: char *sigtype = NULL;
1.1 djm 2524:
2525: if (k == NULL || k->cert == NULL ||
2526: k->cert->certblob == NULL || ca == NULL)
2527: return SSH_ERR_INVALID_ARGUMENT;
2528: if (!sshkey_is_cert(k))
2529: return SSH_ERR_KEY_TYPE_UNKNOWN;
2530: if (!sshkey_type_is_valid_ca(ca->type))
2531: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2532:
1.67 djm 2533: /*
2534: * If no alg specified as argument but a signature_type was set,
2535: * then prefer that. If both were specified, then they must match.
2536: */
2537: if (alg == NULL)
2538: alg = k->cert->signature_type;
2539: else if (k->cert->signature_type != NULL &&
2540: strcmp(alg, k->cert->signature_type) != 0)
2541: return SSH_ERR_INVALID_ARGUMENT;
2542:
1.1 djm 2543: if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2544: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2545:
2546: cert = k->cert->certblob; /* for readability */
2547: sshbuf_reset(cert);
2548: if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0)
2549: goto out;
2550:
2551: /* -v01 certs put nonce first */
2552: arc4random_buf(&nonce, sizeof(nonce));
1.20 djm 2553: if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
2554: goto out;
1.1 djm 2555:
2556: /* XXX this substantially duplicates to_blob(); refactor */
2557: switch (k->type) {
2558: #ifdef WITH_OPENSSL
2559: case KEY_DSA_CERT:
2560: if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 ||
2561: (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 ||
2562: (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 ||
2563: (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0)
2564: goto out;
2565: break;
2566: case KEY_ECDSA_CERT:
2567: if ((ret = sshbuf_put_cstring(cert,
2568: sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 ||
2569: (ret = sshbuf_put_ec(cert,
2570: EC_KEY_get0_public_key(k->ecdsa),
2571: EC_KEY_get0_group(k->ecdsa))) != 0)
2572: goto out;
2573: break;
2574: case KEY_RSA_CERT:
2575: if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 ||
2576: (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0)
2577: goto out;
2578: break;
2579: #endif /* WITH_OPENSSL */
2580: case KEY_ED25519_CERT:
2581: if ((ret = sshbuf_put_string(cert,
2582: k->ed25519_pk, ED25519_PK_SZ)) != 0)
2583: goto out;
2584: break;
1.62 markus 2585: #ifdef WITH_XMSS
2586: case KEY_XMSS_CERT:
2587: if (k->xmss_name == NULL) {
2588: ret = SSH_ERR_INVALID_ARGUMENT;
2589: goto out;
2590: }
2591: if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) ||
2592: (ret = sshbuf_put_string(cert,
2593: k->xmss_pk, sshkey_xmss_pklen(k))) != 0)
2594: goto out;
2595: break;
2596: #endif /* WITH_XMSS */
1.1 djm 2597: default:
2598: ret = SSH_ERR_INVALID_ARGUMENT;
1.15 djm 2599: goto out;
1.1 djm 2600: }
2601:
1.20 djm 2602: if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 ||
2603: (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
1.1 djm 2604: (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
2605: goto out;
2606:
2607: if ((principals = sshbuf_new()) == NULL) {
2608: ret = SSH_ERR_ALLOC_FAIL;
2609: goto out;
2610: }
2611: for (i = 0; i < k->cert->nprincipals; i++) {
2612: if ((ret = sshbuf_put_cstring(principals,
2613: k->cert->principals[i])) != 0)
2614: goto out;
2615: }
2616: if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
2617: (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
2618: (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
1.20 djm 2619: (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 ||
2620: (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 ||
2621: (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
1.1 djm 2622: (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
2623: goto out;
2624:
2625: /* Sign the whole mess */
1.53 djm 2626: if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
2627: sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
1.1 djm 2628: goto out;
1.67 djm 2629: /* Check and update signature_type against what was actually used */
2630: if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
2631: goto out;
2632: if (alg != NULL && strcmp(alg, sigtype) != 0) {
2633: ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
2634: goto out;
2635: }
2636: if (k->cert->signature_type == NULL) {
2637: k->cert->signature_type = sigtype;
2638: sigtype = NULL;
2639: }
1.1 djm 2640: /* Append signature and we are done */
2641: if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
2642: goto out;
2643: ret = 0;
2644: out:
2645: if (ret != 0)
2646: sshbuf_reset(cert);
1.29 mmcc 2647: free(sig_blob);
2648: free(ca_blob);
1.67 djm 2649: free(sigtype);
1.31 mmcc 2650: sshbuf_free(principals);
1.1 djm 2651: return ret;
1.53 djm 2652: }
2653:
2654: static int
2655: default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
2656: const u_char *data, size_t datalen,
2657: const char *alg, u_int compat, void *ctx)
2658: {
2659: if (ctx != NULL)
2660: return SSH_ERR_INVALID_ARGUMENT;
2661: return sshkey_sign(key, sigp, lenp, data, datalen, alg, compat);
2662: }
2663:
2664: int
2665: sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
2666: {
2667: return sshkey_certify_custom(k, ca, alg, default_key_sign, NULL);
1.1 djm 2668: }
2669:
2670: int
2671: sshkey_cert_check_authority(const struct sshkey *k,
2672: int want_host, int require_principal,
2673: const char *name, const char **reason)
2674: {
2675: u_int i, principal_matches;
2676: time_t now = time(NULL);
2677:
2678: if (reason != NULL)
2679: *reason = NULL;
2680:
2681: if (want_host) {
2682: if (k->cert->type != SSH2_CERT_TYPE_HOST) {
2683: *reason = "Certificate invalid: not a host certificate";
2684: return SSH_ERR_KEY_CERT_INVALID;
2685: }
2686: } else {
2687: if (k->cert->type != SSH2_CERT_TYPE_USER) {
2688: *reason = "Certificate invalid: not a user certificate";
2689: return SSH_ERR_KEY_CERT_INVALID;
2690: }
2691: }
2692: if (now < 0) {
2693: /* yikes - system clock before epoch! */
2694: *reason = "Certificate invalid: not yet valid";
2695: return SSH_ERR_KEY_CERT_INVALID;
2696: }
2697: if ((u_int64_t)now < k->cert->valid_after) {
2698: *reason = "Certificate invalid: not yet valid";
2699: return SSH_ERR_KEY_CERT_INVALID;
2700: }
2701: if ((u_int64_t)now >= k->cert->valid_before) {
2702: *reason = "Certificate invalid: expired";
2703: return SSH_ERR_KEY_CERT_INVALID;
2704: }
2705: if (k->cert->nprincipals == 0) {
2706: if (require_principal) {
2707: *reason = "Certificate lacks principal list";
2708: return SSH_ERR_KEY_CERT_INVALID;
2709: }
2710: } else if (name != NULL) {
2711: principal_matches = 0;
2712: for (i = 0; i < k->cert->nprincipals; i++) {
2713: if (strcmp(name, k->cert->principals[i]) == 0) {
2714: principal_matches = 1;
2715: break;
2716: }
2717: }
2718: if (!principal_matches) {
2719: *reason = "Certificate invalid: name is not a listed "
2720: "principal";
2721: return SSH_ERR_KEY_CERT_INVALID;
2722: }
2723: }
2724: return 0;
1.27 djm 2725: }
2726:
2727: size_t
2728: sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
2729: {
2730: char from[32], to[32], ret[64];
2731: time_t tt;
2732: struct tm *tm;
2733:
2734: *from = *to = '\0';
2735: if (cert->valid_after == 0 &&
2736: cert->valid_before == 0xffffffffffffffffULL)
2737: return strlcpy(s, "forever", l);
2738:
2739: if (cert->valid_after != 0) {
2740: /* XXX revisit INT_MAX in 2038 :) */
2741: tt = cert->valid_after > INT_MAX ?
2742: INT_MAX : cert->valid_after;
2743: tm = localtime(&tt);
2744: strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
2745: }
2746: if (cert->valid_before != 0xffffffffffffffffULL) {
2747: /* XXX revisit INT_MAX in 2038 :) */
2748: tt = cert->valid_before > INT_MAX ?
2749: INT_MAX : cert->valid_before;
2750: tm = localtime(&tt);
2751: strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
2752: }
2753:
2754: if (cert->valid_after == 0)
2755: snprintf(ret, sizeof(ret), "before %s", to);
2756: else if (cert->valid_before == 0xffffffffffffffffULL)
2757: snprintf(ret, sizeof(ret), "after %s", from);
2758: else
2759: snprintf(ret, sizeof(ret), "from %s to %s", from, to);
2760:
2761: return strlcpy(s, ret, l);
1.1 djm 2762: }
2763:
2764: int
1.62 markus 2765: sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b,
2766: enum sshkey_serialize_rep opts)
1.1 djm 2767: {
2768: int r = SSH_ERR_INTERNAL_ERROR;
2769:
2770: if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
2771: goto out;
2772: switch (key->type) {
2773: #ifdef WITH_OPENSSL
2774: case KEY_RSA:
2775: if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 ||
2776: (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
2777: (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
2778: (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
2779: (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
2780: (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
2781: goto out;
2782: break;
2783: case KEY_RSA_CERT:
2784: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2785: r = SSH_ERR_INVALID_ARGUMENT;
2786: goto out;
2787: }
2788: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2789: (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
2790: (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
2791: (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
2792: (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
2793: goto out;
2794: break;
2795: case KEY_DSA:
2796: if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
2797: (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
2798: (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
2799: (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 ||
2800: (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
2801: goto out;
2802: break;
2803: case KEY_DSA_CERT:
2804: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2805: r = SSH_ERR_INVALID_ARGUMENT;
2806: goto out;
2807: }
2808: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2809: (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
2810: goto out;
2811: break;
2812: case KEY_ECDSA:
2813: if ((r = sshbuf_put_cstring(b,
2814: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
2815: (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
2816: (r = sshbuf_put_bignum2(b,
2817: EC_KEY_get0_private_key(key->ecdsa))) != 0)
2818: goto out;
2819: break;
2820: case KEY_ECDSA_CERT:
2821: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2822: r = SSH_ERR_INVALID_ARGUMENT;
2823: goto out;
2824: }
2825: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2826: (r = sshbuf_put_bignum2(b,
2827: EC_KEY_get0_private_key(key->ecdsa))) != 0)
2828: goto out;
2829: break;
2830: #endif /* WITH_OPENSSL */
2831: case KEY_ED25519:
2832: if ((r = sshbuf_put_string(b, key->ed25519_pk,
2833: ED25519_PK_SZ)) != 0 ||
2834: (r = sshbuf_put_string(b, key->ed25519_sk,
2835: ED25519_SK_SZ)) != 0)
2836: goto out;
2837: break;
2838: case KEY_ED25519_CERT:
2839: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2840: r = SSH_ERR_INVALID_ARGUMENT;
2841: goto out;
2842: }
2843: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2844: (r = sshbuf_put_string(b, key->ed25519_pk,
2845: ED25519_PK_SZ)) != 0 ||
2846: (r = sshbuf_put_string(b, key->ed25519_sk,
2847: ED25519_SK_SZ)) != 0)
2848: goto out;
2849: break;
1.62 markus 2850: #ifdef WITH_XMSS
2851: case KEY_XMSS:
2852: if (key->xmss_name == NULL) {
2853: r = SSH_ERR_INVALID_ARGUMENT;
2854: goto out;
2855: }
2856: if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
2857: (r = sshbuf_put_string(b, key->xmss_pk,
2858: sshkey_xmss_pklen(key))) != 0 ||
2859: (r = sshbuf_put_string(b, key->xmss_sk,
2860: sshkey_xmss_sklen(key))) != 0 ||
2861: (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
2862: goto out;
2863: break;
2864: case KEY_XMSS_CERT:
2865: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
2866: key->xmss_name == NULL) {
2867: r = SSH_ERR_INVALID_ARGUMENT;
2868: goto out;
2869: }
2870: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2871: (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
2872: (r = sshbuf_put_string(b, key->xmss_pk,
2873: sshkey_xmss_pklen(key))) != 0 ||
2874: (r = sshbuf_put_string(b, key->xmss_sk,
2875: sshkey_xmss_sklen(key))) != 0 ||
2876: (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
2877: goto out;
2878: break;
2879: #endif /* WITH_XMSS */
1.1 djm 2880: default:
2881: r = SSH_ERR_INVALID_ARGUMENT;
2882: goto out;
2883: }
2884: /* success */
2885: r = 0;
2886: out:
2887: return r;
2888: }
2889:
2890: int
1.62 markus 2891: sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
2892: {
2893: return sshkey_private_serialize_opt(key, b,
2894: SSHKEY_SERIALIZE_DEFAULT);
2895: }
2896:
2897: int
1.1 djm 2898: sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
2899: {
1.62 markus 2900: char *tname = NULL, *curve = NULL, *xmss_name = NULL;
1.1 djm 2901: struct sshkey *k = NULL;
1.14 djm 2902: size_t pklen = 0, sklen = 0;
1.1 djm 2903: int type, r = SSH_ERR_INTERNAL_ERROR;
2904: u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
1.62 markus 2905: u_char *xmss_pk = NULL, *xmss_sk = NULL;
1.1 djm 2906: #ifdef WITH_OPENSSL
2907: BIGNUM *exponent = NULL;
2908: #endif /* WITH_OPENSSL */
2909:
2910: if (kp != NULL)
2911: *kp = NULL;
2912: if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
2913: goto out;
2914: type = sshkey_type_from_name(tname);
2915: switch (type) {
2916: #ifdef WITH_OPENSSL
2917: case KEY_DSA:
2918: if ((k = sshkey_new_private(type)) == NULL) {
2919: r = SSH_ERR_ALLOC_FAIL;
2920: goto out;
2921: }
2922: if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 ||
2923: (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 ||
2924: (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 ||
2925: (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 ||
2926: (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
2927: goto out;
2928: break;
2929: case KEY_DSA_CERT:
1.14 djm 2930: if ((r = sshkey_froms(buf, &k)) != 0 ||
1.1 djm 2931: (r = sshkey_add_private(k)) != 0 ||
2932: (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
2933: goto out;
2934: break;
2935: case KEY_ECDSA:
2936: if ((k = sshkey_new_private(type)) == NULL) {
2937: r = SSH_ERR_ALLOC_FAIL;
2938: goto out;
2939: }
2940: if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
2941: r = SSH_ERR_INVALID_ARGUMENT;
2942: goto out;
2943: }
2944: if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
2945: goto out;
2946: if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
2947: r = SSH_ERR_EC_CURVE_MISMATCH;
2948: goto out;
2949: }
2950: k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
2951: if (k->ecdsa == NULL || (exponent = BN_new()) == NULL) {
2952: r = SSH_ERR_LIBCRYPTO_ERROR;
2953: goto out;
2954: }
2955: if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
2956: (r = sshbuf_get_bignum2(buf, exponent)))
2957: goto out;
2958: if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
2959: r = SSH_ERR_LIBCRYPTO_ERROR;
2960: goto out;
2961: }
2962: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
1.22 jsg 2963: EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
1.1 djm 2964: (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
2965: goto out;
2966: break;
2967: case KEY_ECDSA_CERT:
2968: if ((exponent = BN_new()) == NULL) {
2969: r = SSH_ERR_LIBCRYPTO_ERROR;
2970: goto out;
2971: }
1.14 djm 2972: if ((r = sshkey_froms(buf, &k)) != 0 ||
1.1 djm 2973: (r = sshkey_add_private(k)) != 0 ||
2974: (r = sshbuf_get_bignum2(buf, exponent)) != 0)
2975: goto out;
2976: if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
2977: r = SSH_ERR_LIBCRYPTO_ERROR;
2978: goto out;
2979: }
2980: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
1.22 jsg 2981: EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
1.1 djm 2982: (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
2983: goto out;
2984: break;
2985: case KEY_RSA:
2986: if ((k = sshkey_new_private(type)) == NULL) {
2987: r = SSH_ERR_ALLOC_FAIL;
2988: goto out;
2989: }
2990: if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 ||
2991: (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 ||
2992: (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
2993: (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
2994: (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
2995: (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
1.54 djm 2996: (r = ssh_rsa_generate_additional_parameters(k)) != 0)
1.1 djm 2997: goto out;
1.49 djm 2998: if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
2999: r = SSH_ERR_KEY_LENGTH;
3000: goto out;
3001: }
1.1 djm 3002: break;
3003: case KEY_RSA_CERT:
1.14 djm 3004: if ((r = sshkey_froms(buf, &k)) != 0 ||
1.1 djm 3005: (r = sshkey_add_private(k)) != 0 ||
1.22 jsg 3006: (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
3007: (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
3008: (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
3009: (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
1.54 djm 3010: (r = ssh_rsa_generate_additional_parameters(k)) != 0)
1.1 djm 3011: goto out;
1.49 djm 3012: if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
3013: r = SSH_ERR_KEY_LENGTH;
3014: goto out;
3015: }
1.1 djm 3016: break;
3017: #endif /* WITH_OPENSSL */
3018: case KEY_ED25519:
3019: if ((k = sshkey_new_private(type)) == NULL) {
3020: r = SSH_ERR_ALLOC_FAIL;
3021: goto out;
3022: }
3023: if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3024: (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3025: goto out;
3026: if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3027: r = SSH_ERR_INVALID_FORMAT;
3028: goto out;
3029: }
3030: k->ed25519_pk = ed25519_pk;
3031: k->ed25519_sk = ed25519_sk;
3032: ed25519_pk = ed25519_sk = NULL;
3033: break;
3034: case KEY_ED25519_CERT:
1.14 djm 3035: if ((r = sshkey_froms(buf, &k)) != 0 ||
1.1 djm 3036: (r = sshkey_add_private(k)) != 0 ||
3037: (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3038: (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3039: goto out;
3040: if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3041: r = SSH_ERR_INVALID_FORMAT;
3042: goto out;
3043: }
3044: k->ed25519_pk = ed25519_pk;
3045: k->ed25519_sk = ed25519_sk;
3046: ed25519_pk = ed25519_sk = NULL;
3047: break;
1.62 markus 3048: #ifdef WITH_XMSS
3049: case KEY_XMSS:
3050: if ((k = sshkey_new_private(type)) == NULL) {
3051: r = SSH_ERR_ALLOC_FAIL;
3052: goto out;
3053: }
3054: if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
3055: (r = sshkey_xmss_init(k, xmss_name)) != 0 ||
3056: (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3057: (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
3058: goto out;
3059: if (pklen != sshkey_xmss_pklen(k) ||
3060: sklen != sshkey_xmss_sklen(k)) {
3061: r = SSH_ERR_INVALID_FORMAT;
3062: goto out;
3063: }
3064: k->xmss_pk = xmss_pk;
3065: k->xmss_sk = xmss_sk;
3066: xmss_pk = xmss_sk = NULL;
3067: /* optional internal state */
3068: if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3069: goto out;
3070: break;
3071: case KEY_XMSS_CERT:
3072: if ((r = sshkey_froms(buf, &k)) != 0 ||
3073: (r = sshkey_add_private(k)) != 0 ||
1.64 markus 3074: (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
1.62 markus 3075: (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3076: (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
3077: goto out;
1.64 markus 3078: if (strcmp(xmss_name, k->xmss_name)) {
3079: r = SSH_ERR_INVALID_FORMAT;
3080: goto out;
3081: }
1.62 markus 3082: if (pklen != sshkey_xmss_pklen(k) ||
3083: sklen != sshkey_xmss_sklen(k)) {
3084: r = SSH_ERR_INVALID_FORMAT;
3085: goto out;
3086: }
3087: k->xmss_pk = xmss_pk;
3088: k->xmss_sk = xmss_sk;
3089: xmss_pk = xmss_sk = NULL;
3090: /* optional internal state */
3091: if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3092: goto out;
3093: break;
3094: #endif /* WITH_XMSS */
1.1 djm 3095: default:
3096: r = SSH_ERR_KEY_TYPE_UNKNOWN;
3097: goto out;
3098: }
3099: #ifdef WITH_OPENSSL
3100: /* enable blinding */
3101: switch (k->type) {
3102: case KEY_RSA:
3103: case KEY_RSA_CERT:
3104: if (RSA_blinding_on(k->rsa, NULL) != 1) {
3105: r = SSH_ERR_LIBCRYPTO_ERROR;
3106: goto out;
3107: }
3108: break;
3109: }
3110: #endif /* WITH_OPENSSL */
3111: /* success */
3112: r = 0;
3113: if (kp != NULL) {
3114: *kp = k;
3115: k = NULL;
3116: }
3117: out:
3118: free(tname);
3119: free(curve);
3120: #ifdef WITH_OPENSSL
1.60 jsing 3121: BN_clear_free(exponent);
1.1 djm 3122: #endif /* WITH_OPENSSL */
3123: sshkey_free(k);
1.61 jsing 3124: freezero(ed25519_pk, pklen);
3125: freezero(ed25519_sk, sklen);
1.62 markus 3126: free(xmss_name);
3127: freezero(xmss_pk, pklen);
3128: freezero(xmss_sk, sklen);
1.1 djm 3129: return r;
3130: }
3131:
3132: #ifdef WITH_OPENSSL
3133: int
3134: sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
3135: {
3136: BN_CTX *bnctx;
3137: EC_POINT *nq = NULL;
3138: BIGNUM *order, *x, *y, *tmp;
3139: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
1.40 djm 3140:
3141: /*
3142: * NB. This assumes OpenSSL has already verified that the public
3143: * point lies on the curve. This is done by EC_POINT_oct2point()
3144: * implicitly calling EC_POINT_is_on_curve(). If this code is ever
3145: * reachable with public points not unmarshalled using
3146: * EC_POINT_oct2point then the caller will need to explicitly check.
3147: */
1.1 djm 3148:
3149: if ((bnctx = BN_CTX_new()) == NULL)
3150: return SSH_ERR_ALLOC_FAIL;
3151: BN_CTX_start(bnctx);
3152:
3153: /*
3154: * We shouldn't ever hit this case because bignum_get_ecpoint()
3155: * refuses to load GF2m points.
3156: */
3157: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3158: NID_X9_62_prime_field)
3159: goto out;
3160:
3161: /* Q != infinity */
3162: if (EC_POINT_is_at_infinity(group, public))
3163: goto out;
3164:
3165: if ((x = BN_CTX_get(bnctx)) == NULL ||
3166: (y = BN_CTX_get(bnctx)) == NULL ||
3167: (order = BN_CTX_get(bnctx)) == NULL ||
3168: (tmp = BN_CTX_get(bnctx)) == NULL) {
3169: ret = SSH_ERR_ALLOC_FAIL;
3170: goto out;
3171: }
3172:
3173: /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
3174: if (EC_GROUP_get_order(group, order, bnctx) != 1 ||
3175: EC_POINT_get_affine_coordinates_GFp(group, public,
3176: x, y, bnctx) != 1) {
3177: ret = SSH_ERR_LIBCRYPTO_ERROR;
3178: goto out;
3179: }
3180: if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
3181: BN_num_bits(y) <= BN_num_bits(order) / 2)
3182: goto out;
3183:
3184: /* nQ == infinity (n == order of subgroup) */
3185: if ((nq = EC_POINT_new(group)) == NULL) {
3186: ret = SSH_ERR_ALLOC_FAIL;
3187: goto out;
3188: }
3189: if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) {
3190: ret = SSH_ERR_LIBCRYPTO_ERROR;
3191: goto out;
3192: }
3193: if (EC_POINT_is_at_infinity(group, nq) != 1)
3194: goto out;
3195:
3196: /* x < order - 1, y < order - 1 */
3197: if (!BN_sub(tmp, order, BN_value_one())) {
3198: ret = SSH_ERR_LIBCRYPTO_ERROR;
3199: goto out;
3200: }
3201: if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0)
3202: goto out;
3203: ret = 0;
3204: out:
3205: BN_CTX_free(bnctx);
1.60 jsing 3206: EC_POINT_free(nq);
1.1 djm 3207: return ret;
3208: }
3209:
3210: int
3211: sshkey_ec_validate_private(const EC_KEY *key)
3212: {
3213: BN_CTX *bnctx;
3214: BIGNUM *order, *tmp;
3215: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
3216:
3217: if ((bnctx = BN_CTX_new()) == NULL)
3218: return SSH_ERR_ALLOC_FAIL;
3219: BN_CTX_start(bnctx);
3220:
3221: if ((order = BN_CTX_get(bnctx)) == NULL ||
3222: (tmp = BN_CTX_get(bnctx)) == NULL) {
3223: ret = SSH_ERR_ALLOC_FAIL;
3224: goto out;
3225: }
3226:
3227: /* log2(private) > log2(order)/2 */
3228: if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) {
3229: ret = SSH_ERR_LIBCRYPTO_ERROR;
3230: goto out;
3231: }
3232: if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
3233: BN_num_bits(order) / 2)
3234: goto out;
3235:
3236: /* private < order - 1 */
3237: if (!BN_sub(tmp, order, BN_value_one())) {
3238: ret = SSH_ERR_LIBCRYPTO_ERROR;
3239: goto out;
3240: }
3241: if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0)
3242: goto out;
3243: ret = 0;
3244: out:
3245: BN_CTX_free(bnctx);
3246: return ret;
3247: }
3248:
3249: void
3250: sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
3251: {
3252: BIGNUM *x, *y;
3253: BN_CTX *bnctx;
3254:
3255: if (point == NULL) {
3256: fputs("point=(NULL)\n", stderr);
3257: return;
3258: }
3259: if ((bnctx = BN_CTX_new()) == NULL) {
3260: fprintf(stderr, "%s: BN_CTX_new failed\n", __func__);
3261: return;
3262: }
3263: BN_CTX_start(bnctx);
3264: if ((x = BN_CTX_get(bnctx)) == NULL ||
3265: (y = BN_CTX_get(bnctx)) == NULL) {
3266: fprintf(stderr, "%s: BN_CTX_get failed\n", __func__);
3267: return;
3268: }
3269: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3270: NID_X9_62_prime_field) {
3271: fprintf(stderr, "%s: group is not a prime field\n", __func__);
3272: return;
3273: }
3274: if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y,
3275: bnctx) != 1) {
3276: fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
3277: __func__);
3278: return;
3279: }
3280: fputs("x=", stderr);
3281: BN_print_fp(stderr, x);
3282: fputs("\ny=", stderr);
3283: BN_print_fp(stderr, y);
3284: fputs("\n", stderr);
3285: BN_CTX_free(bnctx);
3286: }
3287:
3288: void
3289: sshkey_dump_ec_key(const EC_KEY *key)
3290: {
3291: const BIGNUM *exponent;
3292:
3293: sshkey_dump_ec_point(EC_KEY_get0_group(key),
3294: EC_KEY_get0_public_key(key));
3295: fputs("exponent=", stderr);
3296: if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
3297: fputs("(NULL)", stderr);
3298: else
3299: BN_print_fp(stderr, EC_KEY_get0_private_key(key));
3300: fputs("\n", stderr);
3301: }
3302: #endif /* WITH_OPENSSL */
3303:
3304: static int
3305: sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
3306: const char *passphrase, const char *comment, const char *ciphername,
3307: int rounds)
3308: {
1.4 djm 3309: u_char *cp, *key = NULL, *pubkeyblob = NULL;
1.1 djm 3310: u_char salt[SALT_LEN];
1.4 djm 3311: char *b64 = NULL;
1.1 djm 3312: size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
3313: u_int check;
3314: int r = SSH_ERR_INTERNAL_ERROR;
1.36 djm 3315: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 3316: const struct sshcipher *cipher;
3317: const char *kdfname = KDFNAME;
3318: struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
3319:
3320: if (rounds <= 0)
3321: rounds = DEFAULT_ROUNDS;
3322: if (passphrase == NULL || !strlen(passphrase)) {
3323: ciphername = "none";
3324: kdfname = "none";
3325: } else if (ciphername == NULL)
3326: ciphername = DEFAULT_CIPHERNAME;
1.47 djm 3327: if ((cipher = cipher_by_name(ciphername)) == NULL) {
1.1 djm 3328: r = SSH_ERR_INVALID_ARGUMENT;
3329: goto out;
3330: }
3331:
3332: if ((kdf = sshbuf_new()) == NULL ||
3333: (encoded = sshbuf_new()) == NULL ||
3334: (encrypted = sshbuf_new()) == NULL) {
3335: r = SSH_ERR_ALLOC_FAIL;
3336: goto out;
3337: }
3338: blocksize = cipher_blocksize(cipher);
3339: keylen = cipher_keylen(cipher);
3340: ivlen = cipher_ivlen(cipher);
3341: authlen = cipher_authlen(cipher);
3342: if ((key = calloc(1, keylen + ivlen)) == NULL) {
3343: r = SSH_ERR_ALLOC_FAIL;
3344: goto out;
3345: }
3346: if (strcmp(kdfname, "bcrypt") == 0) {
3347: arc4random_buf(salt, SALT_LEN);
3348: if (bcrypt_pbkdf(passphrase, strlen(passphrase),
3349: salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) {
3350: r = SSH_ERR_INVALID_ARGUMENT;
3351: goto out;
3352: }
3353: if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 ||
3354: (r = sshbuf_put_u32(kdf, rounds)) != 0)
3355: goto out;
3356: } else if (strcmp(kdfname, "none") != 0) {
3357: /* Unsupported KDF type */
3358: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3359: goto out;
3360: }
3361: if ((r = cipher_init(&ciphercontext, cipher, key, keylen,
3362: key + keylen, ivlen, 1)) != 0)
3363: goto out;
3364:
3365: if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 ||
3366: (r = sshbuf_put_cstring(encoded, ciphername)) != 0 ||
3367: (r = sshbuf_put_cstring(encoded, kdfname)) != 0 ||
3368: (r = sshbuf_put_stringb(encoded, kdf)) != 0 ||
3369: (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */
3370: (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 ||
3371: (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0)
3372: goto out;
3373:
3374: /* set up the buffer that will be encrypted */
3375:
3376: /* Random check bytes */
3377: check = arc4random();
3378: if ((r = sshbuf_put_u32(encrypted, check)) != 0 ||
3379: (r = sshbuf_put_u32(encrypted, check)) != 0)
3380: goto out;
3381:
3382: /* append private key and comment*/
1.62 markus 3383: if ((r = sshkey_private_serialize_opt(prv, encrypted,
3384: SSHKEY_SERIALIZE_FULL)) != 0 ||
1.1 djm 3385: (r = sshbuf_put_cstring(encrypted, comment)) != 0)
3386: goto out;
3387:
3388: /* padding */
3389: i = 0;
3390: while (sshbuf_len(encrypted) % blocksize) {
3391: if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0)
3392: goto out;
3393: }
3394:
3395: /* length in destination buffer */
3396: if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0)
3397: goto out;
3398:
3399: /* encrypt */
3400: if ((r = sshbuf_reserve(encoded,
3401: sshbuf_len(encrypted) + authlen, &cp)) != 0)
3402: goto out;
1.36 djm 3403: if ((r = cipher_crypt(ciphercontext, 0, cp,
1.1 djm 3404: sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
3405: goto out;
3406:
3407: /* uuencode */
3408: if ((b64 = sshbuf_dtob64(encoded)) == NULL) {
3409: r = SSH_ERR_ALLOC_FAIL;
3410: goto out;
3411: }
3412:
3413: sshbuf_reset(blob);
3414: if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0)
3415: goto out;
3416: for (i = 0; i < strlen(b64); i++) {
3417: if ((r = sshbuf_put_u8(blob, b64[i])) != 0)
3418: goto out;
3419: /* insert line breaks */
3420: if (i % 70 == 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3421: goto out;
3422: }
3423: if (i % 70 != 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3424: goto out;
3425: if ((r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
3426: goto out;
3427:
3428: /* success */
3429: r = 0;
3430:
3431: out:
3432: sshbuf_free(kdf);
3433: sshbuf_free(encoded);
3434: sshbuf_free(encrypted);
1.36 djm 3435: cipher_free(ciphercontext);
1.1 djm 3436: explicit_bzero(salt, sizeof(salt));
3437: if (key != NULL) {
3438: explicit_bzero(key, keylen + ivlen);
3439: free(key);
3440: }
3441: if (pubkeyblob != NULL) {
3442: explicit_bzero(pubkeyblob, pubkeylen);
3443: free(pubkeyblob);
3444: }
3445: if (b64 != NULL) {
3446: explicit_bzero(b64, strlen(b64));
3447: free(b64);
3448: }
3449: return r;
3450: }
3451:
3452: static int
3453: sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3454: struct sshkey **keyp, char **commentp)
3455: {
3456: char *comment = NULL, *ciphername = NULL, *kdfname = NULL;
3457: const struct sshcipher *cipher = NULL;
3458: const u_char *cp;
3459: int r = SSH_ERR_INTERNAL_ERROR;
3460: size_t encoded_len;
1.18 djm 3461: size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;
1.1 djm 3462: struct sshbuf *encoded = NULL, *decoded = NULL;
3463: struct sshbuf *kdf = NULL, *decrypted = NULL;
1.36 djm 3464: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 3465: struct sshkey *k = NULL;
3466: u_char *key = NULL, *salt = NULL, *dp, pad, last;
3467: u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
3468:
3469: if (keyp != NULL)
3470: *keyp = NULL;
3471: if (commentp != NULL)
3472: *commentp = NULL;
3473:
3474: if ((encoded = sshbuf_new()) == NULL ||
3475: (decoded = sshbuf_new()) == NULL ||
3476: (decrypted = sshbuf_new()) == NULL) {
3477: r = SSH_ERR_ALLOC_FAIL;
3478: goto out;
3479: }
3480:
3481: /* check preamble */
3482: cp = sshbuf_ptr(blob);
3483: encoded_len = sshbuf_len(blob);
3484: if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) ||
3485: memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) {
3486: r = SSH_ERR_INVALID_FORMAT;
3487: goto out;
3488: }
3489: cp += MARK_BEGIN_LEN;
3490: encoded_len -= MARK_BEGIN_LEN;
3491:
3492: /* Look for end marker, removing whitespace as we go */
3493: while (encoded_len > 0) {
3494: if (*cp != '\n' && *cp != '\r') {
3495: if ((r = sshbuf_put_u8(encoded, *cp)) != 0)
3496: goto out;
3497: }
3498: last = *cp;
3499: encoded_len--;
3500: cp++;
3501: if (last == '\n') {
3502: if (encoded_len >= MARK_END_LEN &&
3503: memcmp(cp, MARK_END, MARK_END_LEN) == 0) {
3504: /* \0 terminate */
3505: if ((r = sshbuf_put_u8(encoded, 0)) != 0)
3506: goto out;
3507: break;
3508: }
3509: }
3510: }
3511: if (encoded_len == 0) {
3512: r = SSH_ERR_INVALID_FORMAT;
3513: goto out;
3514: }
3515:
3516: /* decode base64 */
1.4 djm 3517: if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0)
1.1 djm 3518: goto out;
3519:
3520: /* check magic */
3521: if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) ||
3522: memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
3523: r = SSH_ERR_INVALID_FORMAT;
3524: goto out;
3525: }
3526: /* parse public portion of key */
3527: if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
3528: (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
3529: (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
3530: (r = sshbuf_froms(decoded, &kdf)) != 0 ||
3531: (r = sshbuf_get_u32(decoded, &nkeys)) != 0 ||
3532: (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */
3533: (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
3534: goto out;
3535:
3536: if ((cipher = cipher_by_name(ciphername)) == NULL) {
3537: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3538: goto out;
3539: }
3540: if ((passphrase == NULL || strlen(passphrase) == 0) &&
3541: strcmp(ciphername, "none") != 0) {
3542: /* passphrase required */
3543: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3544: goto out;
3545: }
3546: if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
3547: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3548: goto out;
3549: }
3550: if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
3551: r = SSH_ERR_INVALID_FORMAT;
3552: goto out;
3553: }
3554: if (nkeys != 1) {
3555: /* XXX only one key supported */
3556: r = SSH_ERR_INVALID_FORMAT;
3557: goto out;
3558: }
3559:
3560: /* check size of encrypted key blob */
3561: blocksize = cipher_blocksize(cipher);
3562: if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
3563: r = SSH_ERR_INVALID_FORMAT;
3564: goto out;
3565: }
3566:
3567: /* setup key */
3568: keylen = cipher_keylen(cipher);
3569: ivlen = cipher_ivlen(cipher);
1.18 djm 3570: authlen = cipher_authlen(cipher);
1.1 djm 3571: if ((key = calloc(1, keylen + ivlen)) == NULL) {
3572: r = SSH_ERR_ALLOC_FAIL;
3573: goto out;
3574: }
3575: if (strcmp(kdfname, "bcrypt") == 0) {
3576: if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 ||
3577: (r = sshbuf_get_u32(kdf, &rounds)) != 0)
3578: goto out;
3579: if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
3580: key, keylen + ivlen, rounds) < 0) {
3581: r = SSH_ERR_INVALID_FORMAT;
3582: goto out;
3583: }
3584: }
3585:
1.18 djm 3586: /* check that an appropriate amount of auth data is present */
3587: if (sshbuf_len(decoded) < encrypted_len + authlen) {
3588: r = SSH_ERR_INVALID_FORMAT;
3589: goto out;
3590: }
3591:
1.1 djm 3592: /* decrypt private portion of key */
3593: if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
3594: (r = cipher_init(&ciphercontext, cipher, key, keylen,
3595: key + keylen, ivlen, 0)) != 0)
3596: goto out;
1.36 djm 3597: if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
1.18 djm 3598: encrypted_len, 0, authlen)) != 0) {
1.1 djm 3599: /* an integrity error here indicates an incorrect passphrase */
3600: if (r == SSH_ERR_MAC_INVALID)
3601: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3602: goto out;
3603: }
1.18 djm 3604: if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
1.1 djm 3605: goto out;
3606: /* there should be no trailing data */
3607: if (sshbuf_len(decoded) != 0) {
3608: r = SSH_ERR_INVALID_FORMAT;
3609: goto out;
3610: }
3611:
3612: /* check check bytes */
3613: if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 ||
3614: (r = sshbuf_get_u32(decrypted, &check2)) != 0)
3615: goto out;
3616: if (check1 != check2) {
3617: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3618: goto out;
3619: }
3620:
3621: /* Load the private key and comment */
3622: if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
3623: (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
3624: goto out;
3625:
3626: /* Check deterministic padding */
3627: i = 0;
3628: while (sshbuf_len(decrypted)) {
3629: if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
3630: goto out;
3631: if (pad != (++i & 0xff)) {
3632: r = SSH_ERR_INVALID_FORMAT;
3633: goto out;
3634: }
3635: }
3636:
3637: /* XXX decode pubkey and check against private */
3638:
3639: /* success */
3640: r = 0;
3641: if (keyp != NULL) {
3642: *keyp = k;
3643: k = NULL;
3644: }
3645: if (commentp != NULL) {
3646: *commentp = comment;
3647: comment = NULL;
3648: }
3649: out:
3650: pad = 0;
1.36 djm 3651: cipher_free(ciphercontext);
1.1 djm 3652: free(ciphername);
3653: free(kdfname);
3654: free(comment);
3655: if (salt != NULL) {
3656: explicit_bzero(salt, slen);
3657: free(salt);
3658: }
3659: if (key != NULL) {
3660: explicit_bzero(key, keylen + ivlen);
3661: free(key);
3662: }
3663: sshbuf_free(encoded);
3664: sshbuf_free(decoded);
3665: sshbuf_free(kdf);
3666: sshbuf_free(decrypted);
3667: sshkey_free(k);
3668: return r;
3669: }
3670:
3671:
3672: #ifdef WITH_OPENSSL
3673: /* convert SSH v2 key in OpenSSL PEM format */
3674: static int
3675: sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
3676: const char *_passphrase, const char *comment)
3677: {
3678: int success, r;
3679: int blen, len = strlen(_passphrase);
3680: u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
3681: const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
1.57 djm 3682: char *bptr;
1.1 djm 3683: BIO *bio = NULL;
3684:
3685: if (len > 0 && len <= 4)
3686: return SSH_ERR_PASSPHRASE_TOO_SHORT;
3687: if ((bio = BIO_new(BIO_s_mem())) == NULL)
3688: return SSH_ERR_ALLOC_FAIL;
3689:
3690: switch (key->type) {
3691: case KEY_DSA:
3692: success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
3693: cipher, passphrase, len, NULL, NULL);
3694: break;
3695: case KEY_ECDSA:
3696: success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
3697: cipher, passphrase, len, NULL, NULL);
3698: break;
3699: case KEY_RSA:
3700: success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
3701: cipher, passphrase, len, NULL, NULL);
3702: break;
3703: default:
3704: success = 0;
3705: break;
3706: }
3707: if (success == 0) {
3708: r = SSH_ERR_LIBCRYPTO_ERROR;
3709: goto out;
3710: }
3711: if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
3712: r = SSH_ERR_INTERNAL_ERROR;
3713: goto out;
3714: }
3715: if ((r = sshbuf_put(blob, bptr, blen)) != 0)
3716: goto out;
3717: r = 0;
3718: out:
3719: BIO_free(bio);
3720: return r;
3721: }
3722: #endif /* WITH_OPENSSL */
3723:
3724: /* Serialise "key" to buffer "blob" */
3725: int
3726: sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3727: const char *passphrase, const char *comment,
3728: int force_new_format, const char *new_format_cipher, int new_format_rounds)
3729: {
3730: switch (key->type) {
1.9 markus 3731: #ifdef WITH_OPENSSL
1.1 djm 3732: case KEY_DSA:
3733: case KEY_ECDSA:
3734: case KEY_RSA:
3735: if (force_new_format) {
3736: return sshkey_private_to_blob2(key, blob, passphrase,
3737: comment, new_format_cipher, new_format_rounds);
3738: }
3739: return sshkey_private_pem_to_blob(key, blob,
3740: passphrase, comment);
3741: #endif /* WITH_OPENSSL */
3742: case KEY_ED25519:
1.62 markus 3743: #ifdef WITH_XMSS
3744: case KEY_XMSS:
3745: #endif /* WITH_XMSS */
1.1 djm 3746: return sshkey_private_to_blob2(key, blob, passphrase,
3747: comment, new_format_cipher, new_format_rounds);
3748: default:
3749: return SSH_ERR_KEY_TYPE_UNKNOWN;
3750: }
3751: }
3752:
3753:
3754: #ifdef WITH_OPENSSL
1.8 djm 3755: static int
1.52 djm 3756: translate_libcrypto_error(unsigned long pem_err)
3757: {
3758: int pem_reason = ERR_GET_REASON(pem_err);
3759:
3760: switch (ERR_GET_LIB(pem_err)) {
3761: case ERR_LIB_PEM:
3762: switch (pem_reason) {
3763: case PEM_R_BAD_PASSWORD_READ:
3764: case PEM_R_PROBLEMS_GETTING_PASSWORD:
3765: case PEM_R_BAD_DECRYPT:
3766: return SSH_ERR_KEY_WRONG_PASSPHRASE;
3767: default:
3768: return SSH_ERR_INVALID_FORMAT;
3769: }
3770: case ERR_LIB_EVP:
3771: switch (pem_reason) {
3772: case EVP_R_BAD_DECRYPT:
3773: return SSH_ERR_KEY_WRONG_PASSPHRASE;
3774: case EVP_R_BN_DECODE_ERROR:
3775: case EVP_R_DECODE_ERROR:
3776: #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
3777: case EVP_R_PRIVATE_KEY_DECODE_ERROR:
3778: #endif
3779: return SSH_ERR_INVALID_FORMAT;
3780: default:
3781: return SSH_ERR_LIBCRYPTO_ERROR;
3782: }
3783: case ERR_LIB_ASN1:
3784: return SSH_ERR_INVALID_FORMAT;
3785: }
3786: return SSH_ERR_LIBCRYPTO_ERROR;
3787: }
3788:
3789: static void
3790: clear_libcrypto_errors(void)
3791: {
3792: while (ERR_get_error() != 0)
3793: ;
3794: }
3795:
3796: /*
3797: * Translate OpenSSL error codes to determine whether
3798: * passphrase is required/incorrect.
3799: */
3800: static int
3801: convert_libcrypto_error(void)
3802: {
3803: /*
3804: * Some password errors are reported at the beginning
3805: * of the error queue.
3806: */
3807: if (translate_libcrypto_error(ERR_peek_error()) ==
3808: SSH_ERR_KEY_WRONG_PASSPHRASE)
3809: return SSH_ERR_KEY_WRONG_PASSPHRASE;
3810: return translate_libcrypto_error(ERR_peek_last_error());
3811: }
3812:
3813: static int
1.1 djm 3814: sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
1.8 djm 3815: const char *passphrase, struct sshkey **keyp)
1.1 djm 3816: {
3817: EVP_PKEY *pk = NULL;
3818: struct sshkey *prv = NULL;
3819: BIO *bio = NULL;
3820: int r;
3821:
1.32 djm 3822: if (keyp != NULL)
3823: *keyp = NULL;
1.1 djm 3824:
3825: if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
3826: return SSH_ERR_ALLOC_FAIL;
3827: if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
3828: (int)sshbuf_len(blob)) {
3829: r = SSH_ERR_ALLOC_FAIL;
3830: goto out;
3831: }
3832:
1.52 djm 3833: clear_libcrypto_errors();
1.1 djm 3834: if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
3835: (char *)passphrase)) == NULL) {
1.52 djm 3836: r = convert_libcrypto_error();
1.1 djm 3837: goto out;
3838: }
3839: if (pk->type == EVP_PKEY_RSA &&
3840: (type == KEY_UNSPEC || type == KEY_RSA)) {
3841: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3842: r = SSH_ERR_ALLOC_FAIL;
3843: goto out;
3844: }
3845: prv->rsa = EVP_PKEY_get1_RSA(pk);
3846: prv->type = KEY_RSA;
3847: #ifdef DEBUG_PK
3848: RSA_print_fp(stderr, prv->rsa, 8);
3849: #endif
3850: if (RSA_blinding_on(prv->rsa, NULL) != 1) {
3851: r = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 3852: goto out;
3853: }
3854: if (BN_num_bits(prv->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
3855: r = SSH_ERR_KEY_LENGTH;
1.1 djm 3856: goto out;
3857: }
3858: } else if (pk->type == EVP_PKEY_DSA &&
3859: (type == KEY_UNSPEC || type == KEY_DSA)) {
3860: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3861: r = SSH_ERR_ALLOC_FAIL;
3862: goto out;
3863: }
3864: prv->dsa = EVP_PKEY_get1_DSA(pk);
3865: prv->type = KEY_DSA;
3866: #ifdef DEBUG_PK
3867: DSA_print_fp(stderr, prv->dsa, 8);
3868: #endif
3869: } else if (pk->type == EVP_PKEY_EC &&
3870: (type == KEY_UNSPEC || type == KEY_ECDSA)) {
3871: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3872: r = SSH_ERR_ALLOC_FAIL;
3873: goto out;
3874: }
3875: prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
3876: prv->type = KEY_ECDSA;
3877: prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
3878: if (prv->ecdsa_nid == -1 ||
3879: sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
3880: sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
3881: EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
3882: sshkey_ec_validate_private(prv->ecdsa) != 0) {
3883: r = SSH_ERR_INVALID_FORMAT;
3884: goto out;
3885: }
3886: #ifdef DEBUG_PK
3887: if (prv != NULL && prv->ecdsa != NULL)
3888: sshkey_dump_ec_key(prv->ecdsa);
3889: #endif
3890: } else {
3891: r = SSH_ERR_INVALID_FORMAT;
3892: goto out;
3893: }
3894: r = 0;
1.32 djm 3895: if (keyp != NULL) {
3896: *keyp = prv;
3897: prv = NULL;
3898: }
1.1 djm 3899: out:
3900: BIO_free(bio);
1.60 jsing 3901: EVP_PKEY_free(pk);
1.30 mmcc 3902: sshkey_free(prv);
1.1 djm 3903: return r;
3904: }
3905: #endif /* WITH_OPENSSL */
3906:
3907: int
3908: sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
3909: const char *passphrase, struct sshkey **keyp, char **commentp)
3910: {
1.42 djm 3911: int r = SSH_ERR_INTERNAL_ERROR;
3912:
1.32 djm 3913: if (keyp != NULL)
3914: *keyp = NULL;
1.1 djm 3915: if (commentp != NULL)
3916: *commentp = NULL;
3917:
3918: switch (type) {
1.9 markus 3919: #ifdef WITH_OPENSSL
1.1 djm 3920: case KEY_DSA:
3921: case KEY_ECDSA:
3922: case KEY_RSA:
1.8 djm 3923: return sshkey_parse_private_pem_fileblob(blob, type,
3924: passphrase, keyp);
1.1 djm 3925: #endif /* WITH_OPENSSL */
3926: case KEY_ED25519:
1.62 markus 3927: #ifdef WITH_XMSS
3928: case KEY_XMSS:
3929: #endif /* WITH_XMSS */
1.1 djm 3930: return sshkey_parse_private2(blob, type, passphrase,
3931: keyp, commentp);
3932: case KEY_UNSPEC:
1.42 djm 3933: r = sshkey_parse_private2(blob, type, passphrase, keyp,
3934: commentp);
3935: /* Do not fallback to PEM parser if only passphrase is wrong. */
3936: if (r == 0 || r == SSH_ERR_KEY_WRONG_PASSPHRASE)
3937: return r;
1.1 djm 3938: #ifdef WITH_OPENSSL
1.8 djm 3939: return sshkey_parse_private_pem_fileblob(blob, type,
3940: passphrase, keyp);
1.1 djm 3941: #else
3942: return SSH_ERR_INVALID_FORMAT;
3943: #endif /* WITH_OPENSSL */
3944: default:
3945: return SSH_ERR_KEY_TYPE_UNKNOWN;
3946: }
3947: }
3948:
3949: int
3950: sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
1.23 tim 3951: struct sshkey **keyp, char **commentp)
1.1 djm 3952: {
3953: if (keyp != NULL)
3954: *keyp = NULL;
3955: if (commentp != NULL)
3956: *commentp = NULL;
3957:
1.23 tim 3958: return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
3959: passphrase, keyp, commentp);
1.1 djm 3960: }
1.62 markus 3961:
3962: #ifdef WITH_XMSS
3963: /*
3964: * serialize the key with the current state and forward the state
3965: * maxsign times.
3966: */
3967: int
3968: sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
3969: u_int32_t maxsign, sshkey_printfn *pr)
3970: {
3971: int r, rupdate;
3972:
3973: if (maxsign == 0 ||
3974: sshkey_type_plain(k->type) != KEY_XMSS)
3975: return sshkey_private_serialize_opt(k, b,
3976: SSHKEY_SERIALIZE_DEFAULT);
3977: if ((r = sshkey_xmss_get_state(k, pr)) != 0 ||
3978: (r = sshkey_private_serialize_opt(k, b,
3979: SSHKEY_SERIALIZE_STATE)) != 0 ||
3980: (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
3981: goto out;
3982: r = 0;
3983: out:
3984: if ((rupdate = sshkey_xmss_update_state(k, pr)) != 0) {
3985: if (r == 0)
3986: r = rupdate;
3987: }
3988: return r;
3989: }
3990:
3991: u_int32_t
3992: sshkey_signatures_left(const struct sshkey *k)
3993: {
3994: if (sshkey_type_plain(k->type) == KEY_XMSS)
3995: return sshkey_xmss_signatures_left(k);
3996: return 0;
3997: }
3998:
3999: int
4000: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4001: {
4002: if (sshkey_type_plain(k->type) != KEY_XMSS)
4003: return SSH_ERR_INVALID_ARGUMENT;
4004: return sshkey_xmss_enable_maxsign(k, maxsign);
4005: }
4006:
4007: int
4008: sshkey_set_filename(struct sshkey *k, const char *filename)
4009: {
4010: if (k == NULL)
4011: return SSH_ERR_INVALID_ARGUMENT;
4012: if (sshkey_type_plain(k->type) != KEY_XMSS)
4013: return 0;
4014: if (filename == NULL)
4015: return SSH_ERR_INVALID_ARGUMENT;
4016: if ((k->xmss_filename = strdup(filename)) == NULL)
4017: return SSH_ERR_ALLOC_FAIL;
4018: return 0;
4019: }
4020: #else
4021: int
4022: sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
4023: u_int32_t maxsign, sshkey_printfn *pr)
4024: {
4025: return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
4026: }
4027:
4028: u_int32_t
4029: sshkey_signatures_left(const struct sshkey *k)
4030: {
4031: return 0;
4032: }
4033:
4034: int
4035: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4036: {
4037: return SSH_ERR_INVALID_ARGUMENT;
4038: }
4039:
4040: int
4041: sshkey_set_filename(struct sshkey *k, const char *filename)
4042: {
4043: if (k == NULL)
4044: return SSH_ERR_INVALID_ARGUMENT;
4045: return 0;
4046: }
4047: #endif /* WITH_XMSS */