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