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