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