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