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