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