Annotation of src/usr.bin/ssh/sshkey.c, Revision 1.11
1.11 ! djm 1: /* $OpenBSD: sshkey.c,v 1.10 2015/01/12 20:13:27 markus 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:
32: #include <openssl/evp.h>
33: #include <openssl/err.h>
34: #include <openssl/pem.h>
35:
36: #include "crypto_api.h"
37:
38: #include <errno.h>
39: #include <stdio.h>
40: #include <string.h>
41: #include <util.h>
1.7 djm 42: #include <resolv.h>
1.1 djm 43:
44: #include "ssh2.h"
45: #include "ssherr.h"
46: #include "misc.h"
47: #include "sshbuf.h"
48: #include "rsa.h"
49: #include "cipher.h"
50: #include "digest.h"
51: #define SSHKEY_INTERNAL
52: #include "sshkey.h"
1.11 ! djm 53: #include "match.h"
1.1 djm 54:
55: /* openssh private key file format */
56: #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
57: #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
58: #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
59: #define MARK_END_LEN (sizeof(MARK_END) - 1)
60: #define KDFNAME "bcrypt"
61: #define AUTH_MAGIC "openssh-key-v1"
62: #define SALT_LEN 16
63: #define DEFAULT_CIPHERNAME "aes256-cbc"
64: #define DEFAULT_ROUNDS 16
65:
66: /* Version identification string for SSH v1 identity files. */
67: #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
68:
69: static int sshkey_from_blob_internal(const u_char *blob, size_t blen,
70: struct sshkey **keyp, int allow_cert);
71:
72: /* Supported key types */
73: struct keytype {
74: const char *name;
75: const char *shortname;
76: int type;
77: int nid;
78: int cert;
79: };
80: static const struct keytype keytypes[] = {
81: { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 },
82: { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
83: KEY_ED25519_CERT, 0, 1 },
84: #ifdef WITH_OPENSSL
85: { NULL, "RSA1", KEY_RSA1, 0, 0 },
86: { "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
87: { "ssh-dss", "DSA", KEY_DSA, 0, 0 },
88: { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },
89: { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },
90: { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
91: { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },
92: { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },
93: { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
94: KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
95: { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
96: KEY_ECDSA_CERT, NID_secp384r1, 1 },
97: { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
98: KEY_ECDSA_CERT, NID_secp521r1, 1 },
99: { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",
100: KEY_RSA_CERT_V00, 0, 1 },
101: { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
102: KEY_DSA_CERT_V00, 0, 1 },
103: #endif /* WITH_OPENSSL */
104: { NULL, NULL, -1, -1, 0 }
105: };
106:
107: const char *
108: sshkey_type(const struct sshkey *k)
109: {
110: const struct keytype *kt;
111:
112: for (kt = keytypes; kt->type != -1; kt++) {
113: if (kt->type == k->type)
114: return kt->shortname;
115: }
116: return "unknown";
117: }
118:
119: static const char *
120: sshkey_ssh_name_from_type_nid(int type, int nid)
121: {
122: const struct keytype *kt;
123:
124: for (kt = keytypes; kt->type != -1; kt++) {
125: if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
126: return kt->name;
127: }
128: return "ssh-unknown";
129: }
130:
131: int
132: sshkey_type_is_cert(int type)
133: {
134: const struct keytype *kt;
135:
136: for (kt = keytypes; kt->type != -1; kt++) {
137: if (kt->type == type)
138: return kt->cert;
139: }
140: return 0;
141: }
142:
143: const char *
144: sshkey_ssh_name(const struct sshkey *k)
145: {
146: return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
147: }
148:
149: const char *
150: sshkey_ssh_name_plain(const struct sshkey *k)
151: {
152: return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type),
153: k->ecdsa_nid);
154: }
155:
156: int
157: sshkey_type_from_name(const char *name)
158: {
159: const struct keytype *kt;
160:
161: for (kt = keytypes; kt->type != -1; kt++) {
162: /* Only allow shortname matches for plain key types */
163: if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
164: (!kt->cert && strcasecmp(kt->shortname, name) == 0))
165: return kt->type;
166: }
167: return KEY_UNSPEC;
168: }
169:
170: int
171: sshkey_ecdsa_nid_from_name(const char *name)
172: {
173: const struct keytype *kt;
174:
1.4 djm 175: for (kt = keytypes; kt->type != -1; kt++) {
176: if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
177: continue;
178: if (kt->name != NULL && strcmp(name, kt->name) == 0)
179: return kt->nid;
180: }
1.1 djm 181: return -1;
182: }
183:
184: char *
185: key_alg_list(int certs_only, int plain_only)
186: {
187: char *tmp, *ret = NULL;
188: size_t nlen, rlen = 0;
189: const struct keytype *kt;
190:
191: for (kt = keytypes; kt->type != -1; kt++) {
192: if (kt->name == NULL)
193: continue;
194: if ((certs_only && !kt->cert) || (plain_only && kt->cert))
195: continue;
196: if (ret != NULL)
197: ret[rlen++] = '\n';
198: nlen = strlen(kt->name);
199: if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
200: free(ret);
201: return NULL;
202: }
203: ret = tmp;
204: memcpy(ret + rlen, kt->name, nlen + 1);
205: rlen += nlen;
206: }
207: return ret;
208: }
209:
210: int
1.11 ! djm 211: sshkey_names_valid2(const char *names, int allow_wildcard)
1.1 djm 212: {
213: char *s, *cp, *p;
1.11 ! djm 214: const struct keytype *kt;
! 215: int type;
1.1 djm 216:
217: if (names == NULL || strcmp(names, "") == 0)
218: return 0;
219: if ((s = cp = strdup(names)) == NULL)
220: return 0;
221: for ((p = strsep(&cp, ",")); p && *p != '\0';
222: (p = strsep(&cp, ","))) {
1.11 ! djm 223: type = sshkey_type_from_name(p);
! 224: if (type == KEY_RSA1) {
! 225: free(s);
! 226: return 0;
! 227: }
! 228: if (type == KEY_UNSPEC) {
! 229: if (allow_wildcard) {
! 230: /*
! 231: * Try matching key types against the string.
! 232: * If any has a positive or negative match then
! 233: * the component is accepted.
! 234: */
! 235: for (kt = keytypes; kt->type != -1; kt++) {
! 236: if (kt->type == KEY_RSA1)
! 237: continue;
! 238: if (match_pattern_list(kt->name,
! 239: p, strlen(p), 0) != 0)
! 240: break;
! 241: }
! 242: if (kt->type != -1)
! 243: continue;
! 244: }
1.1 djm 245: free(s);
246: return 0;
247: }
248: }
249: free(s);
250: return 1;
251: }
252:
253: u_int
254: sshkey_size(const struct sshkey *k)
255: {
256: switch (k->type) {
257: #ifdef WITH_OPENSSL
258: case KEY_RSA1:
259: case KEY_RSA:
260: case KEY_RSA_CERT_V00:
261: case KEY_RSA_CERT:
262: return BN_num_bits(k->rsa->n);
263: case KEY_DSA:
264: case KEY_DSA_CERT_V00:
265: case KEY_DSA_CERT:
266: return BN_num_bits(k->dsa->p);
267: case KEY_ECDSA:
268: case KEY_ECDSA_CERT:
269: return sshkey_curve_nid_to_bits(k->ecdsa_nid);
270: #endif /* WITH_OPENSSL */
271: case KEY_ED25519:
272: case KEY_ED25519_CERT:
273: return 256; /* XXX */
274: }
275: return 0;
276: }
277:
278: int
279: sshkey_cert_is_legacy(const struct sshkey *k)
280: {
281: switch (k->type) {
282: case KEY_DSA_CERT_V00:
283: case KEY_RSA_CERT_V00:
284: return 1;
285: default:
286: return 0;
287: }
288: }
289:
290: static int
291: sshkey_type_is_valid_ca(int type)
292: {
293: switch (type) {
294: case KEY_RSA:
295: case KEY_DSA:
296: case KEY_ECDSA:
297: case KEY_ED25519:
298: return 1;
299: default:
300: return 0;
301: }
302: }
303:
304: int
305: sshkey_is_cert(const struct sshkey *k)
306: {
307: if (k == NULL)
308: return 0;
309: return sshkey_type_is_cert(k->type);
310: }
311:
312: /* Return the cert-less equivalent to a certified key type */
313: int
314: sshkey_type_plain(int type)
315: {
316: switch (type) {
317: case KEY_RSA_CERT_V00:
318: case KEY_RSA_CERT:
319: return KEY_RSA;
320: case KEY_DSA_CERT_V00:
321: case KEY_DSA_CERT:
322: return KEY_DSA;
323: case KEY_ECDSA_CERT:
324: return KEY_ECDSA;
325: case KEY_ED25519_CERT:
326: return KEY_ED25519;
327: default:
328: return type;
329: }
330: }
331:
332: #ifdef WITH_OPENSSL
333: /* XXX: these are really begging for a table-driven approach */
334: int
335: sshkey_curve_name_to_nid(const char *name)
336: {
337: if (strcmp(name, "nistp256") == 0)
338: return NID_X9_62_prime256v1;
339: else if (strcmp(name, "nistp384") == 0)
340: return NID_secp384r1;
341: else if (strcmp(name, "nistp521") == 0)
342: return NID_secp521r1;
343: else
344: return -1;
345: }
346:
347: u_int
348: sshkey_curve_nid_to_bits(int nid)
349: {
350: switch (nid) {
351: case NID_X9_62_prime256v1:
352: return 256;
353: case NID_secp384r1:
354: return 384;
355: case NID_secp521r1:
356: return 521;
357: default:
358: return 0;
359: }
360: }
361:
362: int
363: sshkey_ecdsa_bits_to_nid(int bits)
364: {
365: switch (bits) {
366: case 256:
367: return NID_X9_62_prime256v1;
368: case 384:
369: return NID_secp384r1;
370: case 521:
371: return NID_secp521r1;
372: default:
373: return -1;
374: }
375: }
376:
377: const char *
378: sshkey_curve_nid_to_name(int nid)
379: {
380: switch (nid) {
381: case NID_X9_62_prime256v1:
382: return "nistp256";
383: case NID_secp384r1:
384: return "nistp384";
385: case NID_secp521r1:
386: return "nistp521";
387: default:
388: return NULL;
389: }
390: }
391:
392: int
393: sshkey_ec_nid_to_hash_alg(int nid)
394: {
395: int kbits = sshkey_curve_nid_to_bits(nid);
396:
397: if (kbits <= 0)
398: return -1;
399:
400: /* RFC5656 section 6.2.1 */
401: if (kbits <= 256)
402: return SSH_DIGEST_SHA256;
403: else if (kbits <= 384)
404: return SSH_DIGEST_SHA384;
405: else
406: return SSH_DIGEST_SHA512;
407: }
408: #endif /* WITH_OPENSSL */
409:
410: static void
411: cert_free(struct sshkey_cert *cert)
412: {
413: u_int i;
414:
415: if (cert == NULL)
416: return;
417: if (cert->certblob != NULL)
418: sshbuf_free(cert->certblob);
419: if (cert->critical != NULL)
420: sshbuf_free(cert->critical);
421: if (cert->extensions != NULL)
422: sshbuf_free(cert->extensions);
423: if (cert->key_id != NULL)
424: free(cert->key_id);
425: for (i = 0; i < cert->nprincipals; i++)
426: free(cert->principals[i]);
427: if (cert->principals != NULL)
428: free(cert->principals);
429: if (cert->signature_key != NULL)
430: sshkey_free(cert->signature_key);
431: explicit_bzero(cert, sizeof(*cert));
432: free(cert);
433: }
434:
435: static struct sshkey_cert *
436: cert_new(void)
437: {
438: struct sshkey_cert *cert;
439:
440: if ((cert = calloc(1, sizeof(*cert))) == NULL)
441: return NULL;
442: if ((cert->certblob = sshbuf_new()) == NULL ||
443: (cert->critical = sshbuf_new()) == NULL ||
444: (cert->extensions = sshbuf_new()) == NULL) {
445: cert_free(cert);
446: return NULL;
447: }
448: cert->key_id = NULL;
449: cert->principals = NULL;
450: cert->signature_key = NULL;
451: return cert;
452: }
453:
454: struct sshkey *
455: sshkey_new(int type)
456: {
457: struct sshkey *k;
458: #ifdef WITH_OPENSSL
459: RSA *rsa;
460: DSA *dsa;
461: #endif /* WITH_OPENSSL */
462:
463: if ((k = calloc(1, sizeof(*k))) == NULL)
464: return NULL;
465: k->type = type;
466: k->ecdsa = NULL;
467: k->ecdsa_nid = -1;
468: k->dsa = NULL;
469: k->rsa = NULL;
470: k->cert = NULL;
471: k->ed25519_sk = NULL;
472: k->ed25519_pk = NULL;
473: switch (k->type) {
474: #ifdef WITH_OPENSSL
475: case KEY_RSA1:
476: case KEY_RSA:
477: case KEY_RSA_CERT_V00:
478: case KEY_RSA_CERT:
479: if ((rsa = RSA_new()) == NULL ||
480: (rsa->n = BN_new()) == NULL ||
481: (rsa->e = BN_new()) == NULL) {
482: if (rsa != NULL)
483: RSA_free(rsa);
484: free(k);
485: return NULL;
486: }
487: k->rsa = rsa;
488: break;
489: case KEY_DSA:
490: case KEY_DSA_CERT_V00:
491: case KEY_DSA_CERT:
492: if ((dsa = DSA_new()) == NULL ||
493: (dsa->p = BN_new()) == NULL ||
494: (dsa->q = BN_new()) == NULL ||
495: (dsa->g = BN_new()) == NULL ||
496: (dsa->pub_key = BN_new()) == NULL) {
497: if (dsa != NULL)
498: DSA_free(dsa);
499: free(k);
500: return NULL;
501: }
502: k->dsa = dsa;
503: break;
504: case KEY_ECDSA:
505: case KEY_ECDSA_CERT:
506: /* Cannot do anything until we know the group */
507: break;
508: #endif /* WITH_OPENSSL */
509: case KEY_ED25519:
510: case KEY_ED25519_CERT:
511: /* no need to prealloc */
512: break;
513: case KEY_UNSPEC:
514: break;
515: default:
516: free(k);
517: return NULL;
518: break;
519: }
520:
521: if (sshkey_is_cert(k)) {
522: if ((k->cert = cert_new()) == NULL) {
523: sshkey_free(k);
524: return NULL;
525: }
526: }
527:
528: return k;
529: }
530:
531: int
532: sshkey_add_private(struct sshkey *k)
533: {
534: switch (k->type) {
535: #ifdef WITH_OPENSSL
536: case KEY_RSA1:
537: case KEY_RSA:
538: case KEY_RSA_CERT_V00:
539: case KEY_RSA_CERT:
540: #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)
541: if (bn_maybe_alloc_failed(k->rsa->d) ||
542: bn_maybe_alloc_failed(k->rsa->iqmp) ||
543: bn_maybe_alloc_failed(k->rsa->q) ||
544: bn_maybe_alloc_failed(k->rsa->p) ||
545: bn_maybe_alloc_failed(k->rsa->dmq1) ||
546: bn_maybe_alloc_failed(k->rsa->dmp1))
547: return SSH_ERR_ALLOC_FAIL;
548: break;
549: case KEY_DSA:
550: case KEY_DSA_CERT_V00:
551: case KEY_DSA_CERT:
552: if (bn_maybe_alloc_failed(k->dsa->priv_key))
553: return SSH_ERR_ALLOC_FAIL;
554: break;
555: #undef bn_maybe_alloc_failed
556: case KEY_ECDSA:
557: case KEY_ECDSA_CERT:
558: /* Cannot do anything until we know the group */
559: break;
560: #endif /* WITH_OPENSSL */
561: case KEY_ED25519:
562: case KEY_ED25519_CERT:
563: /* no need to prealloc */
564: break;
565: case KEY_UNSPEC:
566: break;
567: default:
568: return SSH_ERR_INVALID_ARGUMENT;
569: }
570: return 0;
571: }
572:
573: struct sshkey *
574: sshkey_new_private(int type)
575: {
576: struct sshkey *k = sshkey_new(type);
577:
578: if (k == NULL)
579: return NULL;
580: if (sshkey_add_private(k) != 0) {
581: sshkey_free(k);
582: return NULL;
583: }
584: return k;
585: }
586:
587: void
588: sshkey_free(struct sshkey *k)
589: {
590: if (k == NULL)
591: return;
592: switch (k->type) {
593: #ifdef WITH_OPENSSL
594: case KEY_RSA1:
595: case KEY_RSA:
596: case KEY_RSA_CERT_V00:
597: case KEY_RSA_CERT:
598: if (k->rsa != NULL)
599: RSA_free(k->rsa);
600: k->rsa = NULL;
601: break;
602: case KEY_DSA:
603: case KEY_DSA_CERT_V00:
604: case KEY_DSA_CERT:
605: if (k->dsa != NULL)
606: DSA_free(k->dsa);
607: k->dsa = NULL;
608: break;
609: case KEY_ECDSA:
610: case KEY_ECDSA_CERT:
611: if (k->ecdsa != NULL)
612: EC_KEY_free(k->ecdsa);
613: k->ecdsa = NULL;
614: break;
615: #endif /* WITH_OPENSSL */
616: case KEY_ED25519:
617: case KEY_ED25519_CERT:
618: if (k->ed25519_pk) {
619: explicit_bzero(k->ed25519_pk, ED25519_PK_SZ);
620: free(k->ed25519_pk);
621: k->ed25519_pk = NULL;
622: }
623: if (k->ed25519_sk) {
624: explicit_bzero(k->ed25519_sk, ED25519_SK_SZ);
625: free(k->ed25519_sk);
626: k->ed25519_sk = NULL;
627: }
628: break;
629: case KEY_UNSPEC:
630: break;
631: default:
632: break;
633: }
634: if (sshkey_is_cert(k))
635: cert_free(k->cert);
636: explicit_bzero(k, sizeof(*k));
637: free(k);
638: }
639:
640: static int
641: cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
642: {
643: if (a == NULL && b == NULL)
644: return 1;
645: if (a == NULL || b == NULL)
646: return 0;
647: if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob))
648: return 0;
649: if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob),
650: sshbuf_len(a->certblob)) != 0)
651: return 0;
652: return 1;
653: }
654:
655: /*
656: * Compare public portions of key only, allowing comparisons between
657: * certificates and plain keys too.
658: */
659: int
660: sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
661: {
662: #ifdef WITH_OPENSSL
663: BN_CTX *bnctx;
664: #endif /* WITH_OPENSSL */
665:
666: if (a == NULL || b == NULL ||
667: sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
668: return 0;
669:
670: switch (a->type) {
671: #ifdef WITH_OPENSSL
672: case KEY_RSA1:
673: case KEY_RSA_CERT_V00:
674: case KEY_RSA_CERT:
675: case KEY_RSA:
676: return a->rsa != NULL && b->rsa != NULL &&
677: BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
678: BN_cmp(a->rsa->n, b->rsa->n) == 0;
679: case KEY_DSA_CERT_V00:
680: case KEY_DSA_CERT:
681: case KEY_DSA:
682: return a->dsa != NULL && b->dsa != NULL &&
683: BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
684: BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
685: BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
686: BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
687: case KEY_ECDSA_CERT:
688: case KEY_ECDSA:
689: if (a->ecdsa == NULL || b->ecdsa == NULL ||
690: EC_KEY_get0_public_key(a->ecdsa) == NULL ||
691: EC_KEY_get0_public_key(b->ecdsa) == NULL)
692: return 0;
693: if ((bnctx = BN_CTX_new()) == NULL)
694: return 0;
695: if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
696: EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
697: EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
698: EC_KEY_get0_public_key(a->ecdsa),
699: EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
700: BN_CTX_free(bnctx);
701: return 0;
702: }
703: BN_CTX_free(bnctx);
704: return 1;
705: #endif /* WITH_OPENSSL */
706: case KEY_ED25519:
707: case KEY_ED25519_CERT:
708: return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
709: memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
710: default:
711: return 0;
712: }
713: /* NOTREACHED */
714: }
715:
716: int
717: sshkey_equal(const struct sshkey *a, const struct sshkey *b)
718: {
719: if (a == NULL || b == NULL || a->type != b->type)
720: return 0;
721: if (sshkey_is_cert(a)) {
722: if (!cert_compare(a->cert, b->cert))
723: return 0;
724: }
725: return sshkey_equal_public(a, b);
726: }
727:
728: static int
729: to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
730: {
731: int type, ret = SSH_ERR_INTERNAL_ERROR;
732: const char *typename;
733:
734: if (key == NULL)
735: return SSH_ERR_INVALID_ARGUMENT;
736:
737: type = force_plain ? sshkey_type_plain(key->type) : key->type;
738: typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
739:
740: switch (type) {
741: #ifdef WITH_OPENSSL
742: case KEY_DSA_CERT_V00:
743: case KEY_RSA_CERT_V00:
744: case KEY_DSA_CERT:
745: case KEY_ECDSA_CERT:
746: case KEY_RSA_CERT:
747: #endif /* WITH_OPENSSL */
748: case KEY_ED25519_CERT:
749: /* Use the existing blob */
750: /* XXX modified flag? */
751: if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
752: return ret;
753: break;
754: #ifdef WITH_OPENSSL
755: case KEY_DSA:
756: if (key->dsa == NULL)
757: return SSH_ERR_INVALID_ARGUMENT;
758: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
759: (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
760: (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
761: (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
762: (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0)
763: return ret;
764: break;
765: case KEY_ECDSA:
766: if (key->ecdsa == NULL)
767: return SSH_ERR_INVALID_ARGUMENT;
768: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
769: (ret = sshbuf_put_cstring(b,
770: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
771: (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
772: return ret;
773: break;
774: case KEY_RSA:
775: if (key->rsa == NULL)
776: return SSH_ERR_INVALID_ARGUMENT;
777: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
778: (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
779: (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0)
780: return ret;
781: break;
782: #endif /* WITH_OPENSSL */
783: case KEY_ED25519:
784: if (key->ed25519_pk == NULL)
785: return SSH_ERR_INVALID_ARGUMENT;
786: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
787: (ret = sshbuf_put_string(b,
788: key->ed25519_pk, ED25519_PK_SZ)) != 0)
789: return ret;
790: break;
791: default:
792: return SSH_ERR_KEY_TYPE_UNKNOWN;
793: }
794: return 0;
795: }
796:
797: int
798: sshkey_to_blob_buf(const struct sshkey *key, struct sshbuf *b)
799: {
800: return to_blob_buf(key, b, 0);
801: }
802:
803: int
804: sshkey_plain_to_blob_buf(const struct sshkey *key, struct sshbuf *b)
805: {
806: return to_blob_buf(key, b, 1);
807: }
808:
809: static int
810: to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain)
811: {
812: int ret = SSH_ERR_INTERNAL_ERROR;
813: size_t len;
814: struct sshbuf *b = NULL;
815:
816: if (lenp != NULL)
817: *lenp = 0;
818: if (blobp != NULL)
819: *blobp = NULL;
820: if ((b = sshbuf_new()) == NULL)
821: return SSH_ERR_ALLOC_FAIL;
822: if ((ret = to_blob_buf(key, b, force_plain)) != 0)
823: goto out;
824: len = sshbuf_len(b);
825: if (lenp != NULL)
826: *lenp = len;
827: if (blobp != NULL) {
828: if ((*blobp = malloc(len)) == NULL) {
829: ret = SSH_ERR_ALLOC_FAIL;
830: goto out;
831: }
832: memcpy(*blobp, sshbuf_ptr(b), len);
833: }
834: ret = 0;
835: out:
836: sshbuf_free(b);
837: return ret;
838: }
839:
840: int
841: sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
842: {
843: return to_blob(key, blobp, lenp, 0);
844: }
845:
846: int
847: sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
848: {
849: return to_blob(key, blobp, lenp, 1);
850: }
851:
852: int
1.7 djm 853: sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
1.1 djm 854: u_char **retp, size_t *lenp)
855: {
856: u_char *blob = NULL, *ret = NULL;
857: size_t blob_len = 0;
1.7 djm 858: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 859:
860: if (retp != NULL)
861: *retp = NULL;
862: if (lenp != NULL)
863: *lenp = 0;
1.7 djm 864: if (ssh_digest_bytes(dgst_alg) == 0) {
1.1 djm 865: r = SSH_ERR_INVALID_ARGUMENT;
866: goto out;
867: }
868:
869: if (k->type == KEY_RSA1) {
870: #ifdef WITH_OPENSSL
871: int nlen = BN_num_bytes(k->rsa->n);
872: int elen = BN_num_bytes(k->rsa->e);
873:
874: blob_len = nlen + elen;
875: if (nlen >= INT_MAX - elen ||
876: (blob = malloc(blob_len)) == NULL) {
877: r = SSH_ERR_ALLOC_FAIL;
878: goto out;
879: }
880: BN_bn2bin(k->rsa->n, blob);
881: BN_bn2bin(k->rsa->e, blob + nlen);
882: #endif /* WITH_OPENSSL */
883: } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0)
884: goto out;
885: if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
886: r = SSH_ERR_ALLOC_FAIL;
887: goto out;
888: }
1.7 djm 889: if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
1.1 djm 890: ret, SSH_DIGEST_MAX_LENGTH)) != 0)
891: goto out;
892: /* success */
893: if (retp != NULL) {
894: *retp = ret;
895: ret = NULL;
896: }
897: if (lenp != NULL)
1.7 djm 898: *lenp = ssh_digest_bytes(dgst_alg);
1.1 djm 899: r = 0;
900: out:
901: free(ret);
902: if (blob != NULL) {
903: explicit_bzero(blob, blob_len);
904: free(blob);
905: }
906: return r;
907: }
908:
909: static char *
1.7 djm 910: fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
911: {
912: char *ret;
913: size_t plen = strlen(alg) + 1;
914: size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
915: int r;
916:
917: if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
918: return NULL;
919: strlcpy(ret, alg, rlen);
920: strlcat(ret, ":", rlen);
921: if (dgst_raw_len == 0)
922: return ret;
923: if ((r = b64_ntop(dgst_raw, dgst_raw_len,
924: ret + plen, rlen - plen)) == -1) {
925: explicit_bzero(ret, rlen);
926: free(ret);
927: return NULL;
928: }
929: /* Trim padding characters from end */
930: ret[strcspn(ret, "=")] = '\0';
931: return ret;
932: }
933:
934: static char *
935: fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
1.1 djm 936: {
1.7 djm 937: char *retval, hex[5];
938: size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
1.1 djm 939:
1.7 djm 940: if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
1.1 djm 941: return NULL;
1.7 djm 942: strlcpy(retval, alg, rlen);
943: strlcat(retval, ":", rlen);
1.1 djm 944: for (i = 0; i < dgst_raw_len; i++) {
1.7 djm 945: snprintf(hex, sizeof(hex), "%s%02x",
946: i > 0 ? ":" : "", dgst_raw[i]);
947: strlcat(retval, hex, rlen);
1.1 djm 948: }
949: return retval;
950: }
951:
952: static char *
953: fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
954: {
955: char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
956: char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
957: 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
958: u_int i, j = 0, rounds, seed = 1;
959: char *retval;
960:
961: rounds = (dgst_raw_len / 2) + 1;
962: if ((retval = calloc(rounds, 6)) == NULL)
963: return NULL;
964: retval[j++] = 'x';
965: for (i = 0; i < rounds; i++) {
966: u_int idx0, idx1, idx2, idx3, idx4;
967: if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
968: idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
969: seed) % 6;
970: idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
971: idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
972: (seed / 6)) % 6;
973: retval[j++] = vowels[idx0];
974: retval[j++] = consonants[idx1];
975: retval[j++] = vowels[idx2];
976: if ((i + 1) < rounds) {
977: idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
978: idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
979: retval[j++] = consonants[idx3];
980: retval[j++] = '-';
981: retval[j++] = consonants[idx4];
982: seed = ((seed * 5) +
983: ((((u_int)(dgst_raw[2 * i])) * 7) +
984: ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
985: }
986: } else {
987: idx0 = seed % 6;
988: idx1 = 16;
989: idx2 = seed / 6;
990: retval[j++] = vowels[idx0];
991: retval[j++] = consonants[idx1];
992: retval[j++] = vowels[idx2];
993: }
994: }
995: retval[j++] = 'x';
996: retval[j++] = '\0';
997: return retval;
998: }
999:
1000: /*
1001: * Draw an ASCII-Art representing the fingerprint so human brain can
1002: * profit from its built-in pattern recognition ability.
1003: * This technique is called "random art" and can be found in some
1004: * scientific publications like this original paper:
1005: *
1006: * "Hash Visualization: a New Technique to improve Real-World Security",
1007: * Perrig A. and Song D., 1999, International Workshop on Cryptographic
1008: * Techniques and E-Commerce (CrypTEC '99)
1009: * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
1010: *
1011: * The subject came up in a talk by Dan Kaminsky, too.
1012: *
1013: * If you see the picture is different, the key is different.
1014: * If the picture looks the same, you still know nothing.
1015: *
1016: * The algorithm used here is a worm crawling over a discrete plane,
1017: * leaving a trace (augmenting the field) everywhere it goes.
1018: * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
1019: * makes the respective movement vector be ignored for this turn.
1020: * Graphs are not unambiguous, because circles in graphs can be
1021: * walked in either direction.
1022: */
1023:
1024: /*
1025: * Field sizes for the random art. Have to be odd, so the starting point
1026: * can be in the exact middle of the picture, and FLDBASE should be >=8 .
1027: * Else pictures would be too dense, and drawing the frame would
1028: * fail, too, because the key type would not fit in anymore.
1029: */
1030: #define FLDBASE 8
1031: #define FLDSIZE_Y (FLDBASE + 1)
1032: #define FLDSIZE_X (FLDBASE * 2 + 1)
1033: static char *
1.7 djm 1034: fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
1.1 djm 1035: const struct sshkey *k)
1036: {
1037: /*
1038: * Chars to be used after each other every time the worm
1039: * intersects with itself. Matter of taste.
1040: */
1041: char *augmentation_string = " .o+=*BOX@%&#/^SE";
1.7 djm 1042: char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
1.1 djm 1043: u_char field[FLDSIZE_X][FLDSIZE_Y];
1.7 djm 1044: size_t i, tlen, hlen;
1.1 djm 1045: u_int b;
1.3 djm 1046: int x, y, r;
1.1 djm 1047: size_t len = strlen(augmentation_string) - 1;
1048:
1049: if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
1050: return NULL;
1051:
1052: /* initialize field */
1053: memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
1054: x = FLDSIZE_X / 2;
1055: y = FLDSIZE_Y / 2;
1056:
1057: /* process raw key */
1058: for (i = 0; i < dgst_raw_len; i++) {
1059: int input;
1060: /* each byte conveys four 2-bit move commands */
1061: input = dgst_raw[i];
1062: for (b = 0; b < 4; b++) {
1063: /* evaluate 2 bit, rest is shifted later */
1064: x += (input & 0x1) ? 1 : -1;
1065: y += (input & 0x2) ? 1 : -1;
1066:
1067: /* assure we are still in bounds */
1068: x = MAX(x, 0);
1069: y = MAX(y, 0);
1070: x = MIN(x, FLDSIZE_X - 1);
1071: y = MIN(y, FLDSIZE_Y - 1);
1072:
1073: /* augment the field */
1074: if (field[x][y] < len - 2)
1075: field[x][y]++;
1076: input = input >> 2;
1077: }
1078: }
1079:
1080: /* mark starting point and end point*/
1081: field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
1082: field[x][y] = len;
1083:
1.3 djm 1084: /* assemble title */
1085: r = snprintf(title, sizeof(title), "[%s %u]",
1086: sshkey_type(k), sshkey_size(k));
1087: /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
1088: if (r < 0 || r > (int)sizeof(title))
1.7 djm 1089: r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
1090: tlen = (r <= 0) ? 0 : strlen(title);
1091:
1092: /* assemble hash ID. */
1093: r = snprintf(hash, sizeof(hash), "[%s]", alg);
1094: hlen = (r <= 0) ? 0 : strlen(hash);
1.1 djm 1095:
1096: /* output upper border */
1.3 djm 1097: p = retval;
1098: *p++ = '+';
1099: for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
1100: *p++ = '-';
1101: memcpy(p, title, tlen);
1102: p += tlen;
1.7 djm 1103: for (i += tlen; i < FLDSIZE_X; i++)
1.1 djm 1104: *p++ = '-';
1105: *p++ = '+';
1106: *p++ = '\n';
1107:
1108: /* output content */
1109: for (y = 0; y < FLDSIZE_Y; y++) {
1110: *p++ = '|';
1111: for (x = 0; x < FLDSIZE_X; x++)
1112: *p++ = augmentation_string[MIN(field[x][y], len)];
1113: *p++ = '|';
1114: *p++ = '\n';
1115: }
1116:
1117: /* output lower border */
1118: *p++ = '+';
1.7 djm 1119: for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
1120: *p++ = '-';
1121: memcpy(p, hash, hlen);
1122: p += hlen;
1123: for (i += hlen; i < FLDSIZE_X; i++)
1.1 djm 1124: *p++ = '-';
1125: *p++ = '+';
1126:
1127: return retval;
1128: }
1129:
1130: char *
1.7 djm 1131: sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1.1 djm 1132: enum sshkey_fp_rep dgst_rep)
1133: {
1134: char *retval = NULL;
1135: u_char *dgst_raw;
1136: size_t dgst_raw_len;
1137:
1.7 djm 1138: if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
1.1 djm 1139: return NULL;
1140: switch (dgst_rep) {
1.7 djm 1141: case SSH_FP_DEFAULT:
1142: if (dgst_alg == SSH_DIGEST_MD5) {
1143: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1144: dgst_raw, dgst_raw_len);
1145: } else {
1146: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1147: dgst_raw, dgst_raw_len);
1148: }
1149: break;
1.1 djm 1150: case SSH_FP_HEX:
1.7 djm 1151: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1152: dgst_raw, dgst_raw_len);
1153: break;
1154: case SSH_FP_BASE64:
1155: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1156: dgst_raw, dgst_raw_len);
1.1 djm 1157: break;
1158: case SSH_FP_BUBBLEBABBLE:
1159: retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
1160: break;
1161: case SSH_FP_RANDOMART:
1.7 djm 1162: retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
1163: dgst_raw, dgst_raw_len, k);
1.1 djm 1164: break;
1165: default:
1166: explicit_bzero(dgst_raw, dgst_raw_len);
1167: free(dgst_raw);
1168: return NULL;
1169: }
1170: explicit_bzero(dgst_raw, dgst_raw_len);
1171: free(dgst_raw);
1172: return retval;
1173: }
1174:
1175: #ifdef WITH_SSH1
1176: /*
1177: * Reads a multiple-precision integer in decimal from the buffer, and advances
1178: * the pointer. The integer must already be initialized. This function is
1179: * permitted to modify the buffer. This leaves *cpp to point just beyond the
1180: * last processed character.
1181: */
1182: static int
1183: read_decimal_bignum(char **cpp, BIGNUM *v)
1184: {
1185: char *cp;
1186: size_t e;
1187: int skip = 1; /* skip white space */
1188:
1189: cp = *cpp;
1190: while (*cp == ' ' || *cp == '\t')
1191: cp++;
1192: e = strspn(cp, "0123456789");
1193: if (e == 0)
1194: return SSH_ERR_INVALID_FORMAT;
1195: if (e > SSHBUF_MAX_BIGNUM * 3)
1196: return SSH_ERR_BIGNUM_TOO_LARGE;
1197: if (cp[e] == '\0')
1198: skip = 0;
1199: else if (index(" \t\r\n", cp[e]) == NULL)
1200: return SSH_ERR_INVALID_FORMAT;
1201: cp[e] = '\0';
1202: if (BN_dec2bn(&v, cp) <= 0)
1203: return SSH_ERR_INVALID_FORMAT;
1204: *cpp = cp + e + skip;
1205: return 0;
1206: }
1207: #endif /* WITH_SSH1 */
1208:
1209: /* returns 0 ok, and < 0 error */
1210: int
1211: sshkey_read(struct sshkey *ret, char **cpp)
1212: {
1213: struct sshkey *k;
1214: int retval = SSH_ERR_INVALID_FORMAT;
1215: char *cp, *space;
1216: int r, type, curve_nid = -1;
1217: struct sshbuf *blob;
1218: #ifdef WITH_SSH1
1219: char *ep;
1220: u_long bits;
1221: #endif /* WITH_SSH1 */
1222:
1223: cp = *cpp;
1224:
1225: switch (ret->type) {
1226: case KEY_RSA1:
1227: #ifdef WITH_SSH1
1228: /* Get number of bits. */
1229: bits = strtoul(cp, &ep, 10);
1230: if (*cp == '\0' || index(" \t\r\n", *ep) == NULL ||
1231: bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8)
1232: return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */
1233: /* Get public exponent, public modulus. */
1234: if ((r = read_decimal_bignum(&ep, ret->rsa->e)) < 0)
1235: return r;
1236: if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0)
1237: return r;
1238: *cpp = ep;
1239: /* validate the claimed number of bits */
1240: if (BN_num_bits(ret->rsa->n) != (int)bits)
1241: return SSH_ERR_KEY_BITS_MISMATCH;
1242: retval = 0;
1243: #endif /* WITH_SSH1 */
1244: break;
1245: case KEY_UNSPEC:
1246: case KEY_RSA:
1247: case KEY_DSA:
1248: case KEY_ECDSA:
1249: case KEY_ED25519:
1250: case KEY_DSA_CERT_V00:
1251: case KEY_RSA_CERT_V00:
1252: case KEY_DSA_CERT:
1253: case KEY_ECDSA_CERT:
1254: case KEY_RSA_CERT:
1255: case KEY_ED25519_CERT:
1256: space = strchr(cp, ' ');
1257: if (space == NULL)
1258: return SSH_ERR_INVALID_FORMAT;
1259: *space = '\0';
1260: type = sshkey_type_from_name(cp);
1261: if (sshkey_type_plain(type) == KEY_ECDSA &&
1262: (curve_nid = sshkey_ecdsa_nid_from_name(cp)) == -1)
1263: return SSH_ERR_EC_CURVE_INVALID;
1264: *space = ' ';
1265: if (type == KEY_UNSPEC)
1266: return SSH_ERR_INVALID_FORMAT;
1267: cp = space+1;
1268: if (*cp == '\0')
1269: return SSH_ERR_INVALID_FORMAT;
1.5 djm 1270: if (ret->type != KEY_UNSPEC && ret->type != type)
1.1 djm 1271: return SSH_ERR_KEY_TYPE_MISMATCH;
1272: if ((blob = sshbuf_new()) == NULL)
1273: return SSH_ERR_ALLOC_FAIL;
1274: /* trim comment */
1275: space = strchr(cp, ' ');
1.10 markus 1276: if (space) {
1277: /* advance 'space': skip whitespace */
1278: *space++ = '\0';
1279: while (*space == ' ' || *space == '\t')
1280: space++;
1281: *cpp = space;
1282: } else
1283: *cpp = cp + strlen(cp);
1.1 djm 1284: if ((r = sshbuf_b64tod(blob, cp)) != 0) {
1285: sshbuf_free(blob);
1286: return r;
1287: }
1288: if ((r = sshkey_from_blob(sshbuf_ptr(blob),
1289: sshbuf_len(blob), &k)) != 0) {
1290: sshbuf_free(blob);
1291: return r;
1292: }
1293: sshbuf_free(blob);
1294: if (k->type != type) {
1295: sshkey_free(k);
1296: return SSH_ERR_KEY_TYPE_MISMATCH;
1297: }
1298: if (sshkey_type_plain(type) == KEY_ECDSA &&
1299: curve_nid != k->ecdsa_nid) {
1300: sshkey_free(k);
1301: return SSH_ERR_EC_CURVE_MISMATCH;
1302: }
1.5 djm 1303: ret->type = type;
1.1 djm 1304: if (sshkey_is_cert(ret)) {
1305: if (!sshkey_is_cert(k)) {
1306: sshkey_free(k);
1307: return SSH_ERR_EXPECTED_CERT;
1308: }
1309: if (ret->cert != NULL)
1310: cert_free(ret->cert);
1311: ret->cert = k->cert;
1312: k->cert = NULL;
1313: }
1314: #ifdef WITH_OPENSSL
1315: if (sshkey_type_plain(ret->type) == KEY_RSA) {
1316: if (ret->rsa != NULL)
1317: RSA_free(ret->rsa);
1318: ret->rsa = k->rsa;
1319: k->rsa = NULL;
1320: #ifdef DEBUG_PK
1321: RSA_print_fp(stderr, ret->rsa, 8);
1322: #endif
1323: }
1324: if (sshkey_type_plain(ret->type) == KEY_DSA) {
1325: if (ret->dsa != NULL)
1326: DSA_free(ret->dsa);
1327: ret->dsa = k->dsa;
1328: k->dsa = NULL;
1329: #ifdef DEBUG_PK
1330: DSA_print_fp(stderr, ret->dsa, 8);
1331: #endif
1332: }
1333: if (sshkey_type_plain(ret->type) == KEY_ECDSA) {
1334: if (ret->ecdsa != NULL)
1335: EC_KEY_free(ret->ecdsa);
1336: ret->ecdsa = k->ecdsa;
1337: ret->ecdsa_nid = k->ecdsa_nid;
1338: k->ecdsa = NULL;
1339: k->ecdsa_nid = -1;
1340: #ifdef DEBUG_PK
1341: sshkey_dump_ec_key(ret->ecdsa);
1342: #endif
1343: }
1344: #endif /* WITH_OPENSSL */
1345: if (sshkey_type_plain(ret->type) == KEY_ED25519) {
1346: free(ret->ed25519_pk);
1347: ret->ed25519_pk = k->ed25519_pk;
1348: k->ed25519_pk = NULL;
1349: #ifdef DEBUG_PK
1350: /* XXX */
1351: #endif
1352: }
1353: retval = 0;
1354: /*XXXX*/
1355: sshkey_free(k);
1356: if (retval != 0)
1357: break;
1358: break;
1359: default:
1360: return SSH_ERR_INVALID_ARGUMENT;
1361: }
1362: return retval;
1363: }
1364:
1365: int
1366: sshkey_write(const struct sshkey *key, FILE *f)
1367: {
1368: int ret = SSH_ERR_INTERNAL_ERROR;
1369: struct sshbuf *b = NULL, *bb = NULL;
1370: char *uu = NULL;
1371: #ifdef WITH_SSH1
1372: u_int bits = 0;
1373: char *dec_e = NULL, *dec_n = NULL;
1374: #endif /* WITH_SSH1 */
1375:
1376: if (sshkey_is_cert(key)) {
1377: if (key->cert == NULL)
1378: return SSH_ERR_EXPECTED_CERT;
1379: if (sshbuf_len(key->cert->certblob) == 0)
1380: return SSH_ERR_KEY_LACKS_CERTBLOB;
1381: }
1382: if ((b = sshbuf_new()) == NULL)
1383: return SSH_ERR_ALLOC_FAIL;
1384: switch (key->type) {
1385: #ifdef WITH_SSH1
1386: case KEY_RSA1:
1387: if (key->rsa == NULL || key->rsa->e == NULL ||
1388: key->rsa->n == NULL) {
1389: ret = SSH_ERR_INVALID_ARGUMENT;
1390: goto out;
1391: }
1392: if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL ||
1393: (dec_n = BN_bn2dec(key->rsa->n)) == NULL) {
1394: ret = SSH_ERR_ALLOC_FAIL;
1395: goto out;
1396: }
1397: /* size of modulus 'n' */
1398: if ((bits = BN_num_bits(key->rsa->n)) <= 0) {
1399: ret = SSH_ERR_INVALID_ARGUMENT;
1400: goto out;
1401: }
1402: if ((ret = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0)
1403: goto out;
1404: #endif /* WITH_SSH1 */
1405: break;
1406: #ifdef WITH_OPENSSL
1407: case KEY_DSA:
1408: case KEY_DSA_CERT_V00:
1409: case KEY_DSA_CERT:
1410: case KEY_ECDSA:
1411: case KEY_ECDSA_CERT:
1412: case KEY_RSA:
1413: case KEY_RSA_CERT_V00:
1414: case KEY_RSA_CERT:
1415: #endif /* WITH_OPENSSL */
1416: case KEY_ED25519:
1417: case KEY_ED25519_CERT:
1418: if ((bb = sshbuf_new()) == NULL) {
1419: ret = SSH_ERR_ALLOC_FAIL;
1420: goto out;
1421: }
1422: if ((ret = sshkey_to_blob_buf(key, bb)) != 0)
1423: goto out;
1424: if ((uu = sshbuf_dtob64(bb)) == NULL) {
1425: ret = SSH_ERR_ALLOC_FAIL;
1426: goto out;
1427: }
1428: if ((ret = sshbuf_putf(b, "%s ", sshkey_ssh_name(key))) != 0)
1429: goto out;
1430: if ((ret = sshbuf_put(b, uu, strlen(uu))) != 0)
1431: goto out;
1432: break;
1433: default:
1434: ret = SSH_ERR_KEY_TYPE_UNKNOWN;
1435: goto out;
1436: }
1437: if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) {
1438: if (feof(f))
1439: errno = EPIPE;
1440: ret = SSH_ERR_SYSTEM_ERROR;
1441: goto out;
1442: }
1443: ret = 0;
1444: out:
1445: if (b != NULL)
1446: sshbuf_free(b);
1447: if (bb != NULL)
1448: sshbuf_free(bb);
1449: if (uu != NULL)
1450: free(uu);
1451: #ifdef WITH_SSH1
1452: if (dec_e != NULL)
1453: OPENSSL_free(dec_e);
1454: if (dec_n != NULL)
1455: OPENSSL_free(dec_n);
1456: #endif /* WITH_SSH1 */
1457: return ret;
1458: }
1459:
1460: const char *
1461: sshkey_cert_type(const struct sshkey *k)
1462: {
1463: switch (k->cert->type) {
1464: case SSH2_CERT_TYPE_USER:
1465: return "user";
1466: case SSH2_CERT_TYPE_HOST:
1467: return "host";
1468: default:
1469: return "unknown";
1470: }
1471: }
1472:
1473: #ifdef WITH_OPENSSL
1474: static int
1475: rsa_generate_private_key(u_int bits, RSA **rsap)
1476: {
1477: RSA *private = NULL;
1478: BIGNUM *f4 = NULL;
1479: int ret = SSH_ERR_INTERNAL_ERROR;
1480:
1481: if (rsap == NULL ||
1482: bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
1483: bits > SSHBUF_MAX_BIGNUM * 8)
1484: return SSH_ERR_INVALID_ARGUMENT;
1485: *rsap = NULL;
1486: if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
1487: ret = SSH_ERR_ALLOC_FAIL;
1488: goto out;
1489: }
1490: if (!BN_set_word(f4, RSA_F4) ||
1491: !RSA_generate_key_ex(private, bits, f4, NULL)) {
1492: ret = SSH_ERR_LIBCRYPTO_ERROR;
1493: goto out;
1494: }
1495: *rsap = private;
1496: private = NULL;
1497: ret = 0;
1498: out:
1499: if (private != NULL)
1500: RSA_free(private);
1501: if (f4 != NULL)
1502: BN_free(f4);
1503: return ret;
1504: }
1505:
1506: static int
1507: dsa_generate_private_key(u_int bits, DSA **dsap)
1508: {
1509: DSA *private;
1510: int ret = SSH_ERR_INTERNAL_ERROR;
1511:
1512: if (dsap == NULL || bits != 1024)
1513: return SSH_ERR_INVALID_ARGUMENT;
1514: if ((private = DSA_new()) == NULL) {
1515: ret = SSH_ERR_ALLOC_FAIL;
1516: goto out;
1517: }
1518: *dsap = NULL;
1519: if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1520: NULL, NULL) || !DSA_generate_key(private)) {
1521: DSA_free(private);
1522: ret = SSH_ERR_LIBCRYPTO_ERROR;
1523: goto out;
1524: }
1525: *dsap = private;
1526: private = NULL;
1527: ret = 0;
1528: out:
1529: if (private != NULL)
1530: DSA_free(private);
1531: return ret;
1532: }
1533:
1534: int
1535: sshkey_ecdsa_key_to_nid(EC_KEY *k)
1536: {
1537: EC_GROUP *eg;
1538: int nids[] = {
1539: NID_X9_62_prime256v1,
1540: NID_secp384r1,
1541: NID_secp521r1,
1542: -1
1543: };
1544: int nid;
1545: u_int i;
1546: BN_CTX *bnctx;
1547: const EC_GROUP *g = EC_KEY_get0_group(k);
1548:
1549: /*
1550: * The group may be stored in a ASN.1 encoded private key in one of two
1551: * ways: as a "named group", which is reconstituted by ASN.1 object ID
1552: * or explicit group parameters encoded into the key blob. Only the
1553: * "named group" case sets the group NID for us, but we can figure
1554: * it out for the other case by comparing against all the groups that
1555: * are supported.
1556: */
1557: if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1558: return nid;
1559: if ((bnctx = BN_CTX_new()) == NULL)
1560: return -1;
1561: for (i = 0; nids[i] != -1; i++) {
1562: if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) {
1563: BN_CTX_free(bnctx);
1564: return -1;
1565: }
1566: if (EC_GROUP_cmp(g, eg, bnctx) == 0)
1567: break;
1568: EC_GROUP_free(eg);
1569: }
1570: BN_CTX_free(bnctx);
1571: if (nids[i] != -1) {
1572: /* Use the group with the NID attached */
1573: EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1574: if (EC_KEY_set_group(k, eg) != 1) {
1575: EC_GROUP_free(eg);
1576: return -1;
1577: }
1578: }
1579: return nids[i];
1580: }
1581:
1582: static int
1583: ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
1584: {
1585: EC_KEY *private;
1586: int ret = SSH_ERR_INTERNAL_ERROR;
1587:
1588: if (nid == NULL || ecdsap == NULL ||
1589: (*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
1590: return SSH_ERR_INVALID_ARGUMENT;
1591: *ecdsap = NULL;
1592: if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
1593: ret = SSH_ERR_ALLOC_FAIL;
1594: goto out;
1595: }
1596: if (EC_KEY_generate_key(private) != 1) {
1597: ret = SSH_ERR_LIBCRYPTO_ERROR;
1598: goto out;
1599: }
1600: EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
1601: *ecdsap = private;
1602: private = NULL;
1603: ret = 0;
1604: out:
1605: if (private != NULL)
1606: EC_KEY_free(private);
1607: return ret;
1608: }
1609: #endif /* WITH_OPENSSL */
1610:
1611: int
1612: sshkey_generate(int type, u_int bits, struct sshkey **keyp)
1613: {
1614: struct sshkey *k;
1615: int ret = SSH_ERR_INTERNAL_ERROR;
1616:
1617: if (keyp == NULL)
1618: return SSH_ERR_INVALID_ARGUMENT;
1619: *keyp = NULL;
1620: if ((k = sshkey_new(KEY_UNSPEC)) == NULL)
1621: return SSH_ERR_ALLOC_FAIL;
1622: switch (type) {
1623: case KEY_ED25519:
1624: if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL ||
1625: (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) {
1626: ret = SSH_ERR_ALLOC_FAIL;
1627: break;
1628: }
1629: crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
1630: ret = 0;
1631: break;
1632: #ifdef WITH_OPENSSL
1633: case KEY_DSA:
1634: ret = dsa_generate_private_key(bits, &k->dsa);
1635: break;
1636: case KEY_ECDSA:
1637: ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid,
1638: &k->ecdsa);
1639: break;
1640: case KEY_RSA:
1641: case KEY_RSA1:
1642: ret = rsa_generate_private_key(bits, &k->rsa);
1643: break;
1644: #endif /* WITH_OPENSSL */
1645: default:
1646: ret = SSH_ERR_INVALID_ARGUMENT;
1647: }
1648: if (ret == 0) {
1649: k->type = type;
1650: *keyp = k;
1651: } else
1652: sshkey_free(k);
1653: return ret;
1654: }
1655:
1656: int
1657: sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
1658: {
1659: u_int i;
1660: const struct sshkey_cert *from;
1661: struct sshkey_cert *to;
1662: int ret = SSH_ERR_INTERNAL_ERROR;
1663:
1664: if (to_key->cert != NULL) {
1665: cert_free(to_key->cert);
1666: to_key->cert = NULL;
1667: }
1668:
1669: if ((from = from_key->cert) == NULL)
1670: return SSH_ERR_INVALID_ARGUMENT;
1671:
1672: if ((to = to_key->cert = cert_new()) == NULL)
1673: return SSH_ERR_ALLOC_FAIL;
1674:
1675: if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
1676: (ret = sshbuf_putb(to->critical, from->critical)) != 0 ||
1677: (ret = sshbuf_putb(to->extensions, from->extensions) != 0))
1678: return ret;
1679:
1680: to->serial = from->serial;
1681: to->type = from->type;
1682: if (from->key_id == NULL)
1683: to->key_id = NULL;
1684: else if ((to->key_id = strdup(from->key_id)) == NULL)
1685: return SSH_ERR_ALLOC_FAIL;
1686: to->valid_after = from->valid_after;
1687: to->valid_before = from->valid_before;
1688: if (from->signature_key == NULL)
1689: to->signature_key = NULL;
1690: else if ((ret = sshkey_from_private(from->signature_key,
1691: &to->signature_key)) != 0)
1692: return ret;
1693:
1694: if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS)
1695: return SSH_ERR_INVALID_ARGUMENT;
1696: if (from->nprincipals > 0) {
1697: if ((to->principals = calloc(from->nprincipals,
1698: sizeof(*to->principals))) == NULL)
1699: return SSH_ERR_ALLOC_FAIL;
1700: for (i = 0; i < from->nprincipals; i++) {
1701: to->principals[i] = strdup(from->principals[i]);
1702: if (to->principals[i] == NULL) {
1703: to->nprincipals = i;
1704: return SSH_ERR_ALLOC_FAIL;
1705: }
1706: }
1707: }
1708: to->nprincipals = from->nprincipals;
1709: return 0;
1710: }
1711:
1712: int
1713: sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1714: {
1715: struct sshkey *n = NULL;
1716: int ret = SSH_ERR_INTERNAL_ERROR;
1717:
1718: if (pkp != NULL)
1719: *pkp = NULL;
1720:
1721: switch (k->type) {
1722: #ifdef WITH_OPENSSL
1723: case KEY_DSA:
1724: case KEY_DSA_CERT_V00:
1725: case KEY_DSA_CERT:
1726: if ((n = sshkey_new(k->type)) == NULL)
1727: return SSH_ERR_ALLOC_FAIL;
1728: if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
1729: (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
1730: (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
1731: (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) {
1732: sshkey_free(n);
1733: return SSH_ERR_ALLOC_FAIL;
1734: }
1735: break;
1736: case KEY_ECDSA:
1737: case KEY_ECDSA_CERT:
1738: if ((n = sshkey_new(k->type)) == NULL)
1739: return SSH_ERR_ALLOC_FAIL;
1740: n->ecdsa_nid = k->ecdsa_nid;
1741: n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
1742: if (n->ecdsa == NULL) {
1743: sshkey_free(n);
1744: return SSH_ERR_ALLOC_FAIL;
1745: }
1746: if (EC_KEY_set_public_key(n->ecdsa,
1747: EC_KEY_get0_public_key(k->ecdsa)) != 1) {
1748: sshkey_free(n);
1749: return SSH_ERR_LIBCRYPTO_ERROR;
1750: }
1751: break;
1752: case KEY_RSA:
1753: case KEY_RSA1:
1754: case KEY_RSA_CERT_V00:
1755: case KEY_RSA_CERT:
1756: if ((n = sshkey_new(k->type)) == NULL)
1757: return SSH_ERR_ALLOC_FAIL;
1758: if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
1759: (BN_copy(n->rsa->e, k->rsa->e) == NULL)) {
1760: sshkey_free(n);
1761: return SSH_ERR_ALLOC_FAIL;
1762: }
1763: break;
1764: #endif /* WITH_OPENSSL */
1765: case KEY_ED25519:
1766: case KEY_ED25519_CERT:
1767: if ((n = sshkey_new(k->type)) == NULL)
1768: return SSH_ERR_ALLOC_FAIL;
1769: if (k->ed25519_pk != NULL) {
1770: if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
1771: sshkey_free(n);
1772: return SSH_ERR_ALLOC_FAIL;
1773: }
1774: memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1775: }
1776: break;
1777: default:
1778: return SSH_ERR_KEY_TYPE_UNKNOWN;
1779: }
1780: if (sshkey_is_cert(k)) {
1781: if ((ret = sshkey_cert_copy(k, n)) != 0) {
1782: sshkey_free(n);
1783: return ret;
1784: }
1785: }
1786: *pkp = n;
1787: return 0;
1788: }
1789:
1790: static int
1791: cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob,
1792: size_t blen)
1793: {
1.4 djm 1794: struct sshbuf *principals = NULL, *crit = NULL, *exts = NULL;
1.1 djm 1795: u_char *sig_key = NULL, *sig = NULL;
1.4 djm 1796: size_t signed_len = 0, sklen = 0, slen = 0, kidlen = 0;
1.1 djm 1797: int ret = SSH_ERR_INTERNAL_ERROR;
1798: int v00 = sshkey_cert_is_legacy(key);
1799:
1800: /* Copy the entire key blob for verification and later serialisation */
1801: if ((ret = sshbuf_put(key->cert->certblob, blob, blen)) != 0)
1802: return ret;
1803:
1804: if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) ||
1805: (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
1806: (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
1.4 djm 1807: (ret = sshbuf_froms(b, &principals)) != 0 ||
1.1 djm 1808: (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
1809: (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
1.4 djm 1810: (ret = sshbuf_froms(b, &crit)) != 0 ||
1811: (!v00 && (ret = sshbuf_froms(b, &exts)) != 0) ||
1.1 djm 1812: (v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) ||
1813: (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
1814: (ret = sshbuf_get_string(b, &sig_key, &sklen)) != 0) {
1815: /* XXX debug print error for ret */
1816: ret = SSH_ERR_INVALID_FORMAT;
1817: goto out;
1818: }
1819:
1820: /* Signature is left in the buffer so we can calculate this length */
1821: signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b);
1822:
1823: if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) {
1824: ret = SSH_ERR_INVALID_FORMAT;
1825: goto out;
1826: }
1827:
1828: if (key->cert->type != SSH2_CERT_TYPE_USER &&
1829: key->cert->type != SSH2_CERT_TYPE_HOST) {
1830: ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE;
1831: goto out;
1832: }
1833:
1.4 djm 1834: /* Parse principals section */
1835: while (sshbuf_len(principals) > 0) {
1836: char *principal = NULL;
1837: char **oprincipals = NULL;
1838:
1.1 djm 1839: if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
1840: ret = SSH_ERR_INVALID_FORMAT;
1841: goto out;
1842: }
1.4 djm 1843: if ((ret = sshbuf_get_cstring(principals, &principal,
1844: NULL)) != 0) {
1.1 djm 1845: ret = SSH_ERR_INVALID_FORMAT;
1846: goto out;
1847: }
1848: oprincipals = key->cert->principals;
1849: key->cert->principals = realloc(key->cert->principals,
1850: (key->cert->nprincipals + 1) *
1851: sizeof(*key->cert->principals));
1852: if (key->cert->principals == NULL) {
1853: free(principal);
1854: key->cert->principals = oprincipals;
1855: ret = SSH_ERR_ALLOC_FAIL;
1856: goto out;
1857: }
1858: key->cert->principals[key->cert->nprincipals++] = principal;
1859: }
1860:
1.4 djm 1861: /*
1862: * Stash a copies of the critical options and extensions sections
1863: * for later use.
1864: */
1865: if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 ||
1866: (exts != NULL &&
1867: (ret = sshbuf_putb(key->cert->extensions, exts)) != 0))
1.1 djm 1868: goto out;
1869:
1.4 djm 1870: /*
1871: * Validate critical options and extensions sections format.
1872: * NB. extensions are not present in v00 certs.
1873: */
1874: while (sshbuf_len(crit) != 0) {
1875: if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
1876: (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) {
1877: sshbuf_reset(key->cert->critical);
1.1 djm 1878: ret = SSH_ERR_INVALID_FORMAT;
1879: goto out;
1880: }
1881: }
1.4 djm 1882: while (exts != NULL && sshbuf_len(exts) != 0) {
1883: if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 ||
1884: (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) {
1885: sshbuf_reset(key->cert->extensions);
1.1 djm 1886: ret = SSH_ERR_INVALID_FORMAT;
1887: goto out;
1888: }
1889: }
1890:
1.4 djm 1891: /* Parse CA key and check signature */
1.1 djm 1892: if (sshkey_from_blob_internal(sig_key, sklen,
1893: &key->cert->signature_key, 0) != 0) {
1894: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1895: goto out;
1896: }
1897: if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) {
1898: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1899: goto out;
1900: }
1901: if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1902: sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0)
1903: goto out;
1.4 djm 1904:
1905: /* Success */
1.1 djm 1906: ret = 0;
1907: out:
1.4 djm 1908: sshbuf_free(crit);
1909: sshbuf_free(exts);
1910: sshbuf_free(principals);
1.1 djm 1911: free(sig_key);
1912: free(sig);
1913: return ret;
1914: }
1915:
1916: static int
1917: sshkey_from_blob_internal(const u_char *blob, size_t blen,
1918: struct sshkey **keyp, int allow_cert)
1919: {
1920: struct sshbuf *b = NULL;
1921: int type, nid = -1, ret = SSH_ERR_INTERNAL_ERROR;
1922: char *ktype = NULL, *curve = NULL;
1923: struct sshkey *key = NULL;
1924: size_t len;
1925: u_char *pk = NULL;
1926: #ifdef WITH_OPENSSL
1927: EC_POINT *q = NULL;
1928: #endif /* WITH_OPENSSL */
1929:
1930: #ifdef DEBUG_PK /* XXX */
1931: dump_base64(stderr, blob, blen);
1932: #endif
1933: *keyp = NULL;
1934: if ((b = sshbuf_from(blob, blen)) == NULL)
1935: return SSH_ERR_ALLOC_FAIL;
1936: if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
1937: ret = SSH_ERR_INVALID_FORMAT;
1938: goto out;
1939: }
1940:
1941: type = sshkey_type_from_name(ktype);
1942: if (sshkey_type_plain(type) == KEY_ECDSA)
1943: nid = sshkey_ecdsa_nid_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: }
2005: key->ecdsa_nid = nid;
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: }