Annotation of src/usr.bin/ssh/sshkey.c, Revision 1.44
1.44 ! dtucker 1: /* $OpenBSD: sshkey.c,v 1.43 2017/02/17 02:31:14 dtucker Exp $ */
1.1 djm 2: /*
3: * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4: * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
5: * Copyright (c) 2010,2011 Damien Miller. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: #include <sys/types.h>
1.7 djm 29: #include <netinet/in.h>
1.1 djm 30:
1.12 djm 31: #ifdef WITH_OPENSSL
1.1 djm 32: #include <openssl/evp.h>
33: #include <openssl/err.h>
34: #include <openssl/pem.h>
1.12 djm 35: #endif
1.1 djm 36:
37: #include "crypto_api.h"
38:
39: #include <errno.h>
40: #include <stdio.h>
41: #include <string.h>
42: #include <util.h>
1.13 deraadt 43: #include <limits.h>
1.7 djm 44: #include <resolv.h>
1.1 djm 45:
46: #include "ssh2.h"
47: #include "ssherr.h"
48: #include "misc.h"
49: #include "sshbuf.h"
50: #include "rsa.h"
51: #include "cipher.h"
52: #include "digest.h"
53: #define SSHKEY_INTERNAL
54: #include "sshkey.h"
1.11 djm 55: #include "match.h"
1.1 djm 56:
57: /* openssh private key file format */
58: #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
59: #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
60: #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
61: #define MARK_END_LEN (sizeof(MARK_END) - 1)
62: #define KDFNAME "bcrypt"
63: #define AUTH_MAGIC "openssh-key-v1"
64: #define SALT_LEN 16
65: #define DEFAULT_CIPHERNAME "aes256-cbc"
66: #define DEFAULT_ROUNDS 16
67:
68: /* Version identification string for SSH v1 identity files. */
69: #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
70:
1.14 djm 71: static int sshkey_from_blob_internal(struct sshbuf *buf,
1.1 djm 72: struct sshkey **keyp, int allow_cert);
73:
74: /* Supported key types */
75: struct keytype {
76: const char *name;
77: const char *shortname;
78: int type;
79: int nid;
80: int cert;
1.28 markus 81: int sigonly;
1.1 djm 82: };
83: static const struct keytype keytypes[] = {
1.28 markus 84: { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 },
1.1 djm 85: { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
1.28 markus 86: KEY_ED25519_CERT, 0, 1, 0 },
1.1 djm 87: #ifdef WITH_OPENSSL
1.43 dtucker 88: # ifdef WITH_SSH1
1.28 markus 89: { NULL, "RSA1", KEY_RSA1, 0, 0, 0 },
1.43 dtucker 90: # endif
1.28 markus 91: { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 },
92: { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 },
93: { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 },
94: { "ssh-dss", "DSA", KEY_DSA, 0, 0, 0 },
95: { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
96: { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0, 0 },
97: { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0, 0 },
98: { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1, 0 },
99: { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1, 0 },
1.1 djm 100: { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
1.28 markus 101: KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
1.1 djm 102: { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
1.28 markus 103: KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
1.1 djm 104: { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
1.28 markus 105: KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
1.1 djm 106: #endif /* WITH_OPENSSL */
1.28 markus 107: { NULL, NULL, -1, -1, 0, 0 }
1.1 djm 108: };
109:
110: const char *
111: sshkey_type(const struct sshkey *k)
112: {
113: const struct keytype *kt;
114:
115: for (kt = keytypes; kt->type != -1; kt++) {
116: if (kt->type == k->type)
117: return kt->shortname;
118: }
119: return "unknown";
120: }
121:
122: static const char *
123: sshkey_ssh_name_from_type_nid(int type, int nid)
124: {
125: const struct keytype *kt;
126:
127: for (kt = keytypes; kt->type != -1; kt++) {
128: if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
129: return kt->name;
130: }
131: return "ssh-unknown";
132: }
133:
134: int
135: sshkey_type_is_cert(int type)
136: {
137: const struct keytype *kt;
138:
139: for (kt = keytypes; kt->type != -1; kt++) {
140: if (kt->type == type)
141: return kt->cert;
142: }
143: return 0;
144: }
145:
146: const char *
147: sshkey_ssh_name(const struct sshkey *k)
148: {
149: return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
150: }
151:
152: const char *
153: sshkey_ssh_name_plain(const struct sshkey *k)
154: {
155: return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type),
156: k->ecdsa_nid);
157: }
158:
159: int
160: sshkey_type_from_name(const char *name)
161: {
162: const struct keytype *kt;
163:
164: for (kt = keytypes; kt->type != -1; kt++) {
165: /* Only allow shortname matches for plain key types */
166: if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
167: (!kt->cert && strcasecmp(kt->shortname, name) == 0))
168: return kt->type;
169: }
170: return KEY_UNSPEC;
171: }
172:
173: int
174: sshkey_ecdsa_nid_from_name(const char *name)
175: {
176: const struct keytype *kt;
177:
1.4 djm 178: for (kt = keytypes; kt->type != -1; kt++) {
179: if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
180: continue;
181: if (kt->name != NULL && strcmp(name, kt->name) == 0)
182: return kt->nid;
183: }
1.1 djm 184: return -1;
185: }
186:
187: char *
1.38 djm 188: sshkey_alg_list(int certs_only, int plain_only, char sep)
1.1 djm 189: {
190: char *tmp, *ret = NULL;
191: size_t nlen, rlen = 0;
192: const struct keytype *kt;
193:
194: for (kt = keytypes; kt->type != -1; kt++) {
1.28 markus 195: if (kt->name == NULL || kt->sigonly)
1.1 djm 196: continue;
197: if ((certs_only && !kt->cert) || (plain_only && kt->cert))
198: continue;
199: if (ret != NULL)
1.38 djm 200: ret[rlen++] = sep;
1.1 djm 201: nlen = strlen(kt->name);
202: if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
203: free(ret);
204: return NULL;
205: }
206: ret = tmp;
207: memcpy(ret + rlen, kt->name, nlen + 1);
208: rlen += nlen;
209: }
210: return ret;
211: }
212:
213: int
1.11 djm 214: sshkey_names_valid2(const char *names, int allow_wildcard)
1.1 djm 215: {
216: char *s, *cp, *p;
1.11 djm 217: const struct keytype *kt;
218: int type;
1.1 djm 219:
220: if (names == NULL || strcmp(names, "") == 0)
221: return 0;
222: if ((s = cp = strdup(names)) == NULL)
223: return 0;
224: for ((p = strsep(&cp, ",")); p && *p != '\0';
225: (p = strsep(&cp, ","))) {
1.11 djm 226: type = sshkey_type_from_name(p);
227: if (type == KEY_RSA1) {
228: free(s);
229: return 0;
230: }
231: if (type == KEY_UNSPEC) {
232: if (allow_wildcard) {
233: /*
234: * Try matching key types against the string.
235: * If any has a positive or negative match then
236: * the component is accepted.
237: */
238: for (kt = keytypes; kt->type != -1; kt++) {
239: if (kt->type == KEY_RSA1)
240: continue;
241: if (match_pattern_list(kt->name,
1.17 djm 242: p, 0) != 0)
1.11 djm 243: break;
244: }
245: if (kt->type != -1)
246: continue;
247: }
1.1 djm 248: free(s);
249: return 0;
250: }
251: }
252: free(s);
253: return 1;
254: }
255:
256: u_int
257: sshkey_size(const struct sshkey *k)
258: {
259: switch (k->type) {
260: #ifdef WITH_OPENSSL
261: case KEY_RSA1:
262: case KEY_RSA:
263: case KEY_RSA_CERT:
264: return BN_num_bits(k->rsa->n);
265: case KEY_DSA:
266: case KEY_DSA_CERT:
267: return BN_num_bits(k->dsa->p);
268: case KEY_ECDSA:
269: case KEY_ECDSA_CERT:
270: return sshkey_curve_nid_to_bits(k->ecdsa_nid);
271: #endif /* WITH_OPENSSL */
272: case KEY_ED25519:
273: case KEY_ED25519_CERT:
274: return 256; /* XXX */
275: }
276: return 0;
277: }
278:
279: static int
280: sshkey_type_is_valid_ca(int type)
281: {
282: switch (type) {
283: case KEY_RSA:
284: case KEY_DSA:
285: case KEY_ECDSA:
286: case KEY_ED25519:
287: return 1;
288: default:
289: return 0;
290: }
291: }
292:
293: int
294: sshkey_is_cert(const struct sshkey *k)
295: {
296: if (k == NULL)
297: return 0;
298: return sshkey_type_is_cert(k->type);
299: }
300:
301: /* Return the cert-less equivalent to a certified key type */
302: int
303: sshkey_type_plain(int type)
304: {
305: switch (type) {
306: case KEY_RSA_CERT:
307: return KEY_RSA;
308: case KEY_DSA_CERT:
309: return KEY_DSA;
310: case KEY_ECDSA_CERT:
311: return KEY_ECDSA;
312: case KEY_ED25519_CERT:
313: return KEY_ED25519;
314: default:
315: return type;
316: }
317: }
318:
319: #ifdef WITH_OPENSSL
320: /* XXX: these are really begging for a table-driven approach */
321: int
322: sshkey_curve_name_to_nid(const char *name)
323: {
324: if (strcmp(name, "nistp256") == 0)
325: return NID_X9_62_prime256v1;
326: else if (strcmp(name, "nistp384") == 0)
327: return NID_secp384r1;
328: else if (strcmp(name, "nistp521") == 0)
329: return NID_secp521r1;
330: else
331: return -1;
332: }
333:
334: u_int
335: sshkey_curve_nid_to_bits(int nid)
336: {
337: switch (nid) {
338: case NID_X9_62_prime256v1:
339: return 256;
340: case NID_secp384r1:
341: return 384;
342: case NID_secp521r1:
343: return 521;
344: default:
345: return 0;
346: }
347: }
348:
349: int
350: sshkey_ecdsa_bits_to_nid(int bits)
351: {
352: switch (bits) {
353: case 256:
354: return NID_X9_62_prime256v1;
355: case 384:
356: return NID_secp384r1;
357: case 521:
358: return NID_secp521r1;
359: default:
360: return -1;
361: }
362: }
363:
364: const char *
365: sshkey_curve_nid_to_name(int nid)
366: {
367: switch (nid) {
368: case NID_X9_62_prime256v1:
369: return "nistp256";
370: case NID_secp384r1:
371: return "nistp384";
372: case NID_secp521r1:
373: return "nistp521";
374: default:
375: return NULL;
376: }
377: }
378:
379: int
380: sshkey_ec_nid_to_hash_alg(int nid)
381: {
382: int kbits = sshkey_curve_nid_to_bits(nid);
383:
384: if (kbits <= 0)
385: return -1;
386:
387: /* RFC5656 section 6.2.1 */
388: if (kbits <= 256)
389: return SSH_DIGEST_SHA256;
390: else if (kbits <= 384)
391: return SSH_DIGEST_SHA384;
392: else
393: return SSH_DIGEST_SHA512;
394: }
395: #endif /* WITH_OPENSSL */
396:
397: static void
398: cert_free(struct sshkey_cert *cert)
399: {
400: u_int i;
401:
402: if (cert == NULL)
403: return;
1.31 mmcc 404: sshbuf_free(cert->certblob);
405: sshbuf_free(cert->critical);
406: sshbuf_free(cert->extensions);
1.29 mmcc 407: free(cert->key_id);
1.1 djm 408: for (i = 0; i < cert->nprincipals; i++)
409: free(cert->principals[i]);
1.29 mmcc 410: free(cert->principals);
1.30 mmcc 411: sshkey_free(cert->signature_key);
1.1 djm 412: explicit_bzero(cert, sizeof(*cert));
413: free(cert);
414: }
415:
416: static struct sshkey_cert *
417: cert_new(void)
418: {
419: struct sshkey_cert *cert;
420:
421: if ((cert = calloc(1, sizeof(*cert))) == NULL)
422: return NULL;
423: if ((cert->certblob = sshbuf_new()) == NULL ||
424: (cert->critical = sshbuf_new()) == NULL ||
425: (cert->extensions = sshbuf_new()) == NULL) {
426: cert_free(cert);
427: return NULL;
428: }
429: cert->key_id = NULL;
430: cert->principals = NULL;
431: cert->signature_key = NULL;
432: return cert;
433: }
434:
435: struct sshkey *
436: sshkey_new(int type)
437: {
438: struct sshkey *k;
439: #ifdef WITH_OPENSSL
440: RSA *rsa;
441: DSA *dsa;
442: #endif /* WITH_OPENSSL */
443:
444: if ((k = calloc(1, sizeof(*k))) == NULL)
445: return NULL;
446: k->type = type;
447: k->ecdsa = NULL;
448: k->ecdsa_nid = -1;
449: k->dsa = NULL;
450: k->rsa = NULL;
451: k->cert = NULL;
452: k->ed25519_sk = NULL;
453: k->ed25519_pk = NULL;
454: switch (k->type) {
455: #ifdef WITH_OPENSSL
456: case KEY_RSA1:
457: case KEY_RSA:
458: case KEY_RSA_CERT:
459: if ((rsa = RSA_new()) == NULL ||
460: (rsa->n = BN_new()) == NULL ||
461: (rsa->e = BN_new()) == NULL) {
462: if (rsa != NULL)
463: RSA_free(rsa);
464: free(k);
465: return NULL;
466: }
467: k->rsa = rsa;
468: break;
469: case KEY_DSA:
470: case KEY_DSA_CERT:
471: if ((dsa = DSA_new()) == NULL ||
472: (dsa->p = BN_new()) == NULL ||
473: (dsa->q = BN_new()) == NULL ||
474: (dsa->g = BN_new()) == NULL ||
475: (dsa->pub_key = BN_new()) == NULL) {
476: if (dsa != NULL)
477: DSA_free(dsa);
478: free(k);
479: return NULL;
480: }
481: k->dsa = dsa;
482: break;
483: case KEY_ECDSA:
484: case KEY_ECDSA_CERT:
485: /* Cannot do anything until we know the group */
486: break;
487: #endif /* WITH_OPENSSL */
488: case KEY_ED25519:
489: case KEY_ED25519_CERT:
490: /* no need to prealloc */
491: break;
492: case KEY_UNSPEC:
493: break;
494: default:
495: free(k);
496: return NULL;
497: }
498:
499: if (sshkey_is_cert(k)) {
500: if ((k->cert = cert_new()) == NULL) {
501: sshkey_free(k);
502: return NULL;
503: }
504: }
505:
506: return k;
507: }
508:
509: int
510: sshkey_add_private(struct sshkey *k)
511: {
512: switch (k->type) {
513: #ifdef WITH_OPENSSL
514: case KEY_RSA1:
515: case KEY_RSA:
516: case KEY_RSA_CERT:
517: #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)
518: if (bn_maybe_alloc_failed(k->rsa->d) ||
519: bn_maybe_alloc_failed(k->rsa->iqmp) ||
520: bn_maybe_alloc_failed(k->rsa->q) ||
521: bn_maybe_alloc_failed(k->rsa->p) ||
522: bn_maybe_alloc_failed(k->rsa->dmq1) ||
523: bn_maybe_alloc_failed(k->rsa->dmp1))
524: return SSH_ERR_ALLOC_FAIL;
525: break;
526: case KEY_DSA:
527: case KEY_DSA_CERT:
528: if (bn_maybe_alloc_failed(k->dsa->priv_key))
529: return SSH_ERR_ALLOC_FAIL;
530: break;
531: #undef bn_maybe_alloc_failed
532: case KEY_ECDSA:
533: case KEY_ECDSA_CERT:
534: /* Cannot do anything until we know the group */
535: break;
536: #endif /* WITH_OPENSSL */
537: case KEY_ED25519:
538: case KEY_ED25519_CERT:
539: /* no need to prealloc */
540: break;
541: case KEY_UNSPEC:
542: break;
543: default:
544: return SSH_ERR_INVALID_ARGUMENT;
545: }
546: return 0;
547: }
548:
549: struct sshkey *
550: sshkey_new_private(int type)
551: {
552: struct sshkey *k = sshkey_new(type);
553:
554: if (k == NULL)
555: return NULL;
556: if (sshkey_add_private(k) != 0) {
557: sshkey_free(k);
558: return NULL;
559: }
560: return k;
561: }
562:
563: void
564: sshkey_free(struct sshkey *k)
565: {
566: if (k == NULL)
567: return;
568: switch (k->type) {
569: #ifdef WITH_OPENSSL
570: case KEY_RSA1:
571: case KEY_RSA:
572: case KEY_RSA_CERT:
573: if (k->rsa != NULL)
574: RSA_free(k->rsa);
575: k->rsa = NULL;
576: break;
577: case KEY_DSA:
578: case KEY_DSA_CERT:
579: if (k->dsa != NULL)
580: DSA_free(k->dsa);
581: k->dsa = NULL;
582: break;
583: case KEY_ECDSA:
584: case KEY_ECDSA_CERT:
585: if (k->ecdsa != NULL)
586: EC_KEY_free(k->ecdsa);
587: k->ecdsa = NULL;
588: break;
589: #endif /* WITH_OPENSSL */
590: case KEY_ED25519:
591: case KEY_ED25519_CERT:
592: if (k->ed25519_pk) {
593: explicit_bzero(k->ed25519_pk, ED25519_PK_SZ);
594: free(k->ed25519_pk);
595: k->ed25519_pk = NULL;
596: }
597: if (k->ed25519_sk) {
598: explicit_bzero(k->ed25519_sk, ED25519_SK_SZ);
599: free(k->ed25519_sk);
600: k->ed25519_sk = NULL;
601: }
602: break;
603: case KEY_UNSPEC:
604: break;
605: default:
606: break;
607: }
608: if (sshkey_is_cert(k))
609: cert_free(k->cert);
610: explicit_bzero(k, sizeof(*k));
611: free(k);
612: }
613:
614: static int
615: cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
616: {
617: if (a == NULL && b == NULL)
618: return 1;
619: if (a == NULL || b == NULL)
620: return 0;
621: if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob))
622: return 0;
623: if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob),
624: sshbuf_len(a->certblob)) != 0)
625: return 0;
626: return 1;
627: }
628:
629: /*
630: * Compare public portions of key only, allowing comparisons between
631: * certificates and plain keys too.
632: */
633: int
634: sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
635: {
636: #ifdef WITH_OPENSSL
637: BN_CTX *bnctx;
638: #endif /* WITH_OPENSSL */
639:
640: if (a == NULL || b == NULL ||
641: sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
642: return 0;
643:
644: switch (a->type) {
645: #ifdef WITH_OPENSSL
646: case KEY_RSA1:
647: case KEY_RSA_CERT:
648: case KEY_RSA:
649: return a->rsa != NULL && b->rsa != NULL &&
650: BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
651: BN_cmp(a->rsa->n, b->rsa->n) == 0;
652: case KEY_DSA_CERT:
653: case KEY_DSA:
654: return a->dsa != NULL && b->dsa != NULL &&
655: BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
656: BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
657: BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
658: BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
659: case KEY_ECDSA_CERT:
660: case KEY_ECDSA:
661: if (a->ecdsa == NULL || b->ecdsa == NULL ||
662: EC_KEY_get0_public_key(a->ecdsa) == NULL ||
663: EC_KEY_get0_public_key(b->ecdsa) == NULL)
664: return 0;
665: if ((bnctx = BN_CTX_new()) == NULL)
666: return 0;
667: if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
668: EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
669: EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
670: EC_KEY_get0_public_key(a->ecdsa),
671: EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
672: BN_CTX_free(bnctx);
673: return 0;
674: }
675: BN_CTX_free(bnctx);
676: return 1;
677: #endif /* WITH_OPENSSL */
678: case KEY_ED25519:
679: case KEY_ED25519_CERT:
680: return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
681: memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
682: default:
683: return 0;
684: }
685: /* NOTREACHED */
686: }
687:
688: int
689: sshkey_equal(const struct sshkey *a, const struct sshkey *b)
690: {
691: if (a == NULL || b == NULL || a->type != b->type)
692: return 0;
693: if (sshkey_is_cert(a)) {
694: if (!cert_compare(a->cert, b->cert))
695: return 0;
696: }
697: return sshkey_equal_public(a, b);
698: }
699:
700: static int
701: to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
702: {
703: int type, ret = SSH_ERR_INTERNAL_ERROR;
704: const char *typename;
705:
706: if (key == NULL)
707: return SSH_ERR_INVALID_ARGUMENT;
708:
1.19 djm 709: if (sshkey_is_cert(key)) {
710: if (key->cert == NULL)
711: return SSH_ERR_EXPECTED_CERT;
712: if (sshbuf_len(key->cert->certblob) == 0)
713: return SSH_ERR_KEY_LACKS_CERTBLOB;
714: }
1.1 djm 715: type = force_plain ? sshkey_type_plain(key->type) : key->type;
716: typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
717:
718: switch (type) {
719: #ifdef WITH_OPENSSL
720: case KEY_DSA_CERT:
721: case KEY_ECDSA_CERT:
722: case KEY_RSA_CERT:
723: #endif /* WITH_OPENSSL */
724: case KEY_ED25519_CERT:
725: /* Use the existing blob */
726: /* XXX modified flag? */
727: if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
728: return ret;
729: break;
730: #ifdef WITH_OPENSSL
731: case KEY_DSA:
732: if (key->dsa == NULL)
733: return SSH_ERR_INVALID_ARGUMENT;
734: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
735: (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
736: (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
737: (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
738: (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0)
739: return ret;
740: break;
741: case KEY_ECDSA:
742: if (key->ecdsa == NULL)
743: return SSH_ERR_INVALID_ARGUMENT;
744: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
745: (ret = sshbuf_put_cstring(b,
746: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
747: (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
748: return ret;
749: break;
750: case KEY_RSA:
751: if (key->rsa == NULL)
752: return SSH_ERR_INVALID_ARGUMENT;
753: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
754: (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
755: (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0)
756: return ret;
757: break;
758: #endif /* WITH_OPENSSL */
759: case KEY_ED25519:
760: if (key->ed25519_pk == NULL)
761: return SSH_ERR_INVALID_ARGUMENT;
762: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
763: (ret = sshbuf_put_string(b,
764: key->ed25519_pk, ED25519_PK_SZ)) != 0)
765: return ret;
766: break;
767: default:
768: return SSH_ERR_KEY_TYPE_UNKNOWN;
769: }
770: return 0;
771: }
772:
773: int
1.14 djm 774: sshkey_putb(const struct sshkey *key, struct sshbuf *b)
1.1 djm 775: {
776: return to_blob_buf(key, b, 0);
777: }
778:
779: int
1.14 djm 780: sshkey_puts(const struct sshkey *key, struct sshbuf *b)
781: {
782: struct sshbuf *tmp;
783: int r;
784:
785: if ((tmp = sshbuf_new()) == NULL)
786: return SSH_ERR_ALLOC_FAIL;
787: r = to_blob_buf(key, tmp, 0);
788: if (r == 0)
789: r = sshbuf_put_stringb(b, tmp);
790: sshbuf_free(tmp);
791: return r;
792: }
793:
794: int
795: sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)
1.1 djm 796: {
797: return to_blob_buf(key, b, 1);
798: }
799:
800: static int
801: to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain)
802: {
803: int ret = SSH_ERR_INTERNAL_ERROR;
804: size_t len;
805: struct sshbuf *b = NULL;
806:
807: if (lenp != NULL)
808: *lenp = 0;
809: if (blobp != NULL)
810: *blobp = NULL;
811: if ((b = sshbuf_new()) == NULL)
812: return SSH_ERR_ALLOC_FAIL;
813: if ((ret = to_blob_buf(key, b, force_plain)) != 0)
814: goto out;
815: len = sshbuf_len(b);
816: if (lenp != NULL)
817: *lenp = len;
818: if (blobp != NULL) {
819: if ((*blobp = malloc(len)) == NULL) {
820: ret = SSH_ERR_ALLOC_FAIL;
821: goto out;
822: }
823: memcpy(*blobp, sshbuf_ptr(b), len);
824: }
825: ret = 0;
826: out:
827: sshbuf_free(b);
828: return ret;
829: }
830:
831: int
832: sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
833: {
834: return to_blob(key, blobp, lenp, 0);
835: }
836:
837: int
838: sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
839: {
840: return to_blob(key, blobp, lenp, 1);
841: }
842:
843: int
1.7 djm 844: sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
1.1 djm 845: u_char **retp, size_t *lenp)
846: {
847: u_char *blob = NULL, *ret = NULL;
848: size_t blob_len = 0;
1.7 djm 849: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 850:
851: if (retp != NULL)
852: *retp = NULL;
853: if (lenp != NULL)
854: *lenp = 0;
1.7 djm 855: if (ssh_digest_bytes(dgst_alg) == 0) {
1.1 djm 856: r = SSH_ERR_INVALID_ARGUMENT;
857: goto out;
858: }
859:
860: if (k->type == KEY_RSA1) {
861: #ifdef WITH_OPENSSL
862: int nlen = BN_num_bytes(k->rsa->n);
863: int elen = BN_num_bytes(k->rsa->e);
864:
1.39 djm 865: if (nlen < 0 || elen < 0 || nlen >= INT_MAX - elen) {
866: r = SSH_ERR_INVALID_FORMAT;
867: goto out;
868: }
1.1 djm 869: blob_len = nlen + elen;
1.39 djm 870: if ((blob = malloc(blob_len)) == NULL) {
1.1 djm 871: r = SSH_ERR_ALLOC_FAIL;
872: goto out;
873: }
874: BN_bn2bin(k->rsa->n, blob);
875: BN_bn2bin(k->rsa->e, blob + nlen);
876: #endif /* WITH_OPENSSL */
877: } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0)
878: goto out;
879: if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
880: r = SSH_ERR_ALLOC_FAIL;
881: goto out;
882: }
1.7 djm 883: if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
1.1 djm 884: ret, SSH_DIGEST_MAX_LENGTH)) != 0)
885: goto out;
886: /* success */
887: if (retp != NULL) {
888: *retp = ret;
889: ret = NULL;
890: }
891: if (lenp != NULL)
1.7 djm 892: *lenp = ssh_digest_bytes(dgst_alg);
1.1 djm 893: r = 0;
894: out:
895: free(ret);
896: if (blob != NULL) {
897: explicit_bzero(blob, blob_len);
898: free(blob);
899: }
900: return r;
901: }
902:
903: static char *
1.7 djm 904: fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
905: {
906: char *ret;
907: size_t plen = strlen(alg) + 1;
908: size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
909: int r;
910:
911: if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
912: return NULL;
913: strlcpy(ret, alg, rlen);
914: strlcat(ret, ":", rlen);
915: if (dgst_raw_len == 0)
916: return ret;
917: if ((r = b64_ntop(dgst_raw, dgst_raw_len,
918: ret + plen, rlen - plen)) == -1) {
919: explicit_bzero(ret, rlen);
920: free(ret);
921: return NULL;
922: }
923: /* Trim padding characters from end */
924: ret[strcspn(ret, "=")] = '\0';
925: return ret;
926: }
927:
928: static char *
929: fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
1.1 djm 930: {
1.7 djm 931: char *retval, hex[5];
932: size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
1.1 djm 933:
1.7 djm 934: if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
1.1 djm 935: return NULL;
1.7 djm 936: strlcpy(retval, alg, rlen);
937: strlcat(retval, ":", rlen);
1.1 djm 938: for (i = 0; i < dgst_raw_len; i++) {
1.7 djm 939: snprintf(hex, sizeof(hex), "%s%02x",
940: i > 0 ? ":" : "", dgst_raw[i]);
941: strlcat(retval, hex, rlen);
1.1 djm 942: }
943: return retval;
944: }
945:
946: static char *
947: fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
948: {
949: char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
950: char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
951: 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
952: u_int i, j = 0, rounds, seed = 1;
953: char *retval;
954:
955: rounds = (dgst_raw_len / 2) + 1;
956: if ((retval = calloc(rounds, 6)) == NULL)
957: return NULL;
958: retval[j++] = 'x';
959: for (i = 0; i < rounds; i++) {
960: u_int idx0, idx1, idx2, idx3, idx4;
961: if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
962: idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
963: seed) % 6;
964: idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
965: idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
966: (seed / 6)) % 6;
967: retval[j++] = vowels[idx0];
968: retval[j++] = consonants[idx1];
969: retval[j++] = vowels[idx2];
970: if ((i + 1) < rounds) {
971: idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
972: idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
973: retval[j++] = consonants[idx3];
974: retval[j++] = '-';
975: retval[j++] = consonants[idx4];
976: seed = ((seed * 5) +
977: ((((u_int)(dgst_raw[2 * i])) * 7) +
978: ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
979: }
980: } else {
981: idx0 = seed % 6;
982: idx1 = 16;
983: idx2 = seed / 6;
984: retval[j++] = vowels[idx0];
985: retval[j++] = consonants[idx1];
986: retval[j++] = vowels[idx2];
987: }
988: }
989: retval[j++] = 'x';
990: retval[j++] = '\0';
991: return retval;
992: }
993:
994: /*
995: * Draw an ASCII-Art representing the fingerprint so human brain can
996: * profit from its built-in pattern recognition ability.
997: * This technique is called "random art" and can be found in some
998: * scientific publications like this original paper:
999: *
1000: * "Hash Visualization: a New Technique to improve Real-World Security",
1001: * Perrig A. and Song D., 1999, International Workshop on Cryptographic
1002: * Techniques and E-Commerce (CrypTEC '99)
1003: * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
1004: *
1005: * The subject came up in a talk by Dan Kaminsky, too.
1006: *
1007: * If you see the picture is different, the key is different.
1008: * If the picture looks the same, you still know nothing.
1009: *
1010: * The algorithm used here is a worm crawling over a discrete plane,
1011: * leaving a trace (augmenting the field) everywhere it goes.
1012: * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
1013: * makes the respective movement vector be ignored for this turn.
1014: * Graphs are not unambiguous, because circles in graphs can be
1015: * walked in either direction.
1016: */
1017:
1018: /*
1019: * Field sizes for the random art. Have to be odd, so the starting point
1020: * can be in the exact middle of the picture, and FLDBASE should be >=8 .
1021: * Else pictures would be too dense, and drawing the frame would
1022: * fail, too, because the key type would not fit in anymore.
1023: */
1024: #define FLDBASE 8
1025: #define FLDSIZE_Y (FLDBASE + 1)
1026: #define FLDSIZE_X (FLDBASE * 2 + 1)
1027: static char *
1.7 djm 1028: fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
1.1 djm 1029: const struct sshkey *k)
1030: {
1031: /*
1032: * Chars to be used after each other every time the worm
1033: * intersects with itself. Matter of taste.
1034: */
1035: char *augmentation_string = " .o+=*BOX@%&#/^SE";
1.7 djm 1036: char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
1.1 djm 1037: u_char field[FLDSIZE_X][FLDSIZE_Y];
1.7 djm 1038: size_t i, tlen, hlen;
1.1 djm 1039: u_int b;
1.3 djm 1040: int x, y, r;
1.1 djm 1041: size_t len = strlen(augmentation_string) - 1;
1042:
1043: if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
1044: return NULL;
1045:
1046: /* initialize field */
1047: memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
1048: x = FLDSIZE_X / 2;
1049: y = FLDSIZE_Y / 2;
1050:
1051: /* process raw key */
1052: for (i = 0; i < dgst_raw_len; i++) {
1053: int input;
1054: /* each byte conveys four 2-bit move commands */
1055: input = dgst_raw[i];
1056: for (b = 0; b < 4; b++) {
1057: /* evaluate 2 bit, rest is shifted later */
1058: x += (input & 0x1) ? 1 : -1;
1059: y += (input & 0x2) ? 1 : -1;
1060:
1061: /* assure we are still in bounds */
1.37 deraadt 1062: x = MAXIMUM(x, 0);
1063: y = MAXIMUM(y, 0);
1064: x = MINIMUM(x, FLDSIZE_X - 1);
1065: y = MINIMUM(y, FLDSIZE_Y - 1);
1.1 djm 1066:
1067: /* augment the field */
1068: if (field[x][y] < len - 2)
1069: field[x][y]++;
1070: input = input >> 2;
1071: }
1072: }
1073:
1074: /* mark starting point and end point*/
1075: field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
1076: field[x][y] = len;
1077:
1.3 djm 1078: /* assemble title */
1079: r = snprintf(title, sizeof(title), "[%s %u]",
1080: sshkey_type(k), sshkey_size(k));
1081: /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
1082: if (r < 0 || r > (int)sizeof(title))
1.7 djm 1083: r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
1084: tlen = (r <= 0) ? 0 : strlen(title);
1085:
1086: /* assemble hash ID. */
1087: r = snprintf(hash, sizeof(hash), "[%s]", alg);
1088: hlen = (r <= 0) ? 0 : strlen(hash);
1.1 djm 1089:
1090: /* output upper border */
1.3 djm 1091: p = retval;
1092: *p++ = '+';
1093: for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
1094: *p++ = '-';
1095: memcpy(p, title, tlen);
1096: p += tlen;
1.7 djm 1097: for (i += tlen; i < FLDSIZE_X; i++)
1.1 djm 1098: *p++ = '-';
1099: *p++ = '+';
1100: *p++ = '\n';
1101:
1102: /* output content */
1103: for (y = 0; y < FLDSIZE_Y; y++) {
1104: *p++ = '|';
1105: for (x = 0; x < FLDSIZE_X; x++)
1.37 deraadt 1106: *p++ = augmentation_string[MINIMUM(field[x][y], len)];
1.1 djm 1107: *p++ = '|';
1108: *p++ = '\n';
1109: }
1110:
1111: /* output lower border */
1112: *p++ = '+';
1.7 djm 1113: for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
1114: *p++ = '-';
1115: memcpy(p, hash, hlen);
1116: p += hlen;
1117: for (i += hlen; i < FLDSIZE_X; i++)
1.1 djm 1118: *p++ = '-';
1119: *p++ = '+';
1120:
1121: return retval;
1122: }
1123:
1124: char *
1.7 djm 1125: sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1.1 djm 1126: enum sshkey_fp_rep dgst_rep)
1127: {
1128: char *retval = NULL;
1129: u_char *dgst_raw;
1130: size_t dgst_raw_len;
1131:
1.7 djm 1132: if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
1.1 djm 1133: return NULL;
1134: switch (dgst_rep) {
1.7 djm 1135: case SSH_FP_DEFAULT:
1136: if (dgst_alg == SSH_DIGEST_MD5) {
1137: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1138: dgst_raw, dgst_raw_len);
1139: } else {
1140: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1141: dgst_raw, dgst_raw_len);
1142: }
1143: break;
1.1 djm 1144: case SSH_FP_HEX:
1.7 djm 1145: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1146: dgst_raw, dgst_raw_len);
1147: break;
1148: case SSH_FP_BASE64:
1149: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1150: dgst_raw, dgst_raw_len);
1.1 djm 1151: break;
1152: case SSH_FP_BUBBLEBABBLE:
1153: retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
1154: break;
1155: case SSH_FP_RANDOMART:
1.7 djm 1156: retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
1157: dgst_raw, dgst_raw_len, k);
1.1 djm 1158: break;
1159: default:
1160: explicit_bzero(dgst_raw, dgst_raw_len);
1161: free(dgst_raw);
1162: return NULL;
1163: }
1164: explicit_bzero(dgst_raw, dgst_raw_len);
1165: free(dgst_raw);
1166: return retval;
1167: }
1168:
1169: #ifdef WITH_SSH1
1170: /*
1171: * Reads a multiple-precision integer in decimal from the buffer, and advances
1172: * the pointer. The integer must already be initialized. This function is
1173: * permitted to modify the buffer. This leaves *cpp to point just beyond the
1174: * last processed character.
1175: */
1176: static int
1177: read_decimal_bignum(char **cpp, BIGNUM *v)
1178: {
1179: char *cp;
1180: size_t e;
1181: int skip = 1; /* skip white space */
1182:
1183: cp = *cpp;
1184: while (*cp == ' ' || *cp == '\t')
1185: cp++;
1186: e = strspn(cp, "0123456789");
1187: if (e == 0)
1188: return SSH_ERR_INVALID_FORMAT;
1189: if (e > SSHBUF_MAX_BIGNUM * 3)
1190: return SSH_ERR_BIGNUM_TOO_LARGE;
1191: if (cp[e] == '\0')
1192: skip = 0;
1.26 millert 1193: else if (strchr(" \t\r\n", cp[e]) == NULL)
1.1 djm 1194: return SSH_ERR_INVALID_FORMAT;
1195: cp[e] = '\0';
1196: if (BN_dec2bn(&v, cp) <= 0)
1197: return SSH_ERR_INVALID_FORMAT;
1198: *cpp = cp + e + skip;
1199: return 0;
1200: }
1201: #endif /* WITH_SSH1 */
1202:
1203: /* returns 0 ok, and < 0 error */
1204: int
1205: sshkey_read(struct sshkey *ret, char **cpp)
1206: {
1207: struct sshkey *k;
1208: int retval = SSH_ERR_INVALID_FORMAT;
1.25 djm 1209: char *ep, *cp, *space;
1.1 djm 1210: int r, type, curve_nid = -1;
1211: struct sshbuf *blob;
1212: #ifdef WITH_SSH1
1213: u_long bits;
1214: #endif /* WITH_SSH1 */
1.44 ! dtucker 1215:
! 1216: if (ret == NULL)
! 1217: return SSH_ERR_INVALID_ARGUMENT;
1.1 djm 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
1.32 djm 1939: if (keyp != NULL)
1940: *keyp = NULL;
1.14 djm 1941: if ((copy = sshbuf_fromb(b)) == NULL) {
1942: ret = SSH_ERR_ALLOC_FAIL;
1943: goto out;
1944: }
1.1 djm 1945: if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
1946: ret = SSH_ERR_INVALID_FORMAT;
1947: goto out;
1948: }
1949:
1950: type = sshkey_type_from_name(ktype);
1951: if (!allow_cert && sshkey_type_is_cert(type)) {
1952: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1953: goto out;
1954: }
1955: switch (type) {
1956: #ifdef WITH_OPENSSL
1957: case KEY_RSA_CERT:
1.14 djm 1958: /* Skip nonce */
1.1 djm 1959: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
1960: ret = SSH_ERR_INVALID_FORMAT;
1961: goto out;
1962: }
1963: /* FALLTHROUGH */
1964: case KEY_RSA:
1965: if ((key = sshkey_new(type)) == NULL) {
1966: ret = SSH_ERR_ALLOC_FAIL;
1967: goto out;
1968: }
1.16 djm 1969: if (sshbuf_get_bignum2(b, key->rsa->e) != 0 ||
1970: sshbuf_get_bignum2(b, key->rsa->n) != 0) {
1.1 djm 1971: ret = SSH_ERR_INVALID_FORMAT;
1972: goto out;
1973: }
1974: #ifdef DEBUG_PK
1975: RSA_print_fp(stderr, key->rsa, 8);
1976: #endif
1977: break;
1978: case KEY_DSA_CERT:
1.14 djm 1979: /* Skip nonce */
1.1 djm 1980: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
1981: ret = SSH_ERR_INVALID_FORMAT;
1982: goto out;
1983: }
1984: /* FALLTHROUGH */
1985: case KEY_DSA:
1986: if ((key = sshkey_new(type)) == NULL) {
1987: ret = SSH_ERR_ALLOC_FAIL;
1988: goto out;
1989: }
1.16 djm 1990: if (sshbuf_get_bignum2(b, key->dsa->p) != 0 ||
1991: sshbuf_get_bignum2(b, key->dsa->q) != 0 ||
1992: sshbuf_get_bignum2(b, key->dsa->g) != 0 ||
1993: sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) {
1.1 djm 1994: ret = SSH_ERR_INVALID_FORMAT;
1995: goto out;
1996: }
1997: #ifdef DEBUG_PK
1998: DSA_print_fp(stderr, key->dsa, 8);
1999: #endif
2000: break;
2001: case KEY_ECDSA_CERT:
1.14 djm 2002: /* Skip nonce */
1.1 djm 2003: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2004: ret = SSH_ERR_INVALID_FORMAT;
2005: goto out;
2006: }
2007: /* FALLTHROUGH */
2008: case KEY_ECDSA:
2009: if ((key = sshkey_new(type)) == NULL) {
2010: ret = SSH_ERR_ALLOC_FAIL;
2011: goto out;
2012: }
1.12 djm 2013: key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
1.1 djm 2014: if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
2015: ret = SSH_ERR_INVALID_FORMAT;
2016: goto out;
2017: }
2018: if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
2019: ret = SSH_ERR_EC_CURVE_MISMATCH;
2020: goto out;
2021: }
2022: if (key->ecdsa != NULL)
2023: EC_KEY_free(key->ecdsa);
2024: if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
2025: == NULL) {
2026: ret = SSH_ERR_EC_CURVE_INVALID;
2027: goto out;
2028: }
2029: if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
2030: ret = SSH_ERR_ALLOC_FAIL;
2031: goto out;
2032: }
2033: if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
2034: ret = SSH_ERR_INVALID_FORMAT;
2035: goto out;
2036: }
2037: if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
2038: q) != 0) {
2039: ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2040: goto out;
2041: }
2042: if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
2043: /* XXX assume it is a allocation error */
2044: ret = SSH_ERR_ALLOC_FAIL;
2045: goto out;
2046: }
2047: #ifdef DEBUG_PK
2048: sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
2049: #endif
2050: break;
2051: #endif /* WITH_OPENSSL */
2052: case KEY_ED25519_CERT:
1.14 djm 2053: /* Skip nonce */
1.1 djm 2054: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2055: ret = SSH_ERR_INVALID_FORMAT;
2056: goto out;
2057: }
2058: /* FALLTHROUGH */
2059: case KEY_ED25519:
2060: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2061: goto out;
2062: if (len != ED25519_PK_SZ) {
2063: ret = SSH_ERR_INVALID_FORMAT;
2064: goto out;
2065: }
2066: if ((key = sshkey_new(type)) == NULL) {
2067: ret = SSH_ERR_ALLOC_FAIL;
2068: goto out;
2069: }
2070: key->ed25519_pk = pk;
2071: pk = NULL;
2072: break;
2073: case KEY_UNSPEC:
2074: if ((key = sshkey_new(type)) == NULL) {
2075: ret = SSH_ERR_ALLOC_FAIL;
2076: goto out;
2077: }
2078: break;
2079: default:
2080: ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2081: goto out;
2082: }
2083:
2084: /* Parse certificate potion */
1.14 djm 2085: if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
1.1 djm 2086: goto out;
2087:
2088: if (key != NULL && sshbuf_len(b) != 0) {
2089: ret = SSH_ERR_INVALID_FORMAT;
2090: goto out;
2091: }
2092: ret = 0;
1.32 djm 2093: if (keyp != NULL) {
2094: *keyp = key;
2095: key = NULL;
2096: }
1.1 djm 2097: out:
1.14 djm 2098: sshbuf_free(copy);
1.1 djm 2099: sshkey_free(key);
2100: free(ktype);
2101: free(curve);
2102: free(pk);
2103: #ifdef WITH_OPENSSL
2104: if (q != NULL)
2105: EC_POINT_free(q);
2106: #endif /* WITH_OPENSSL */
2107: return ret;
2108: }
2109:
2110: int
2111: sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp)
2112: {
1.14 djm 2113: struct sshbuf *b;
2114: int r;
2115:
2116: if ((b = sshbuf_from(blob, blen)) == NULL)
2117: return SSH_ERR_ALLOC_FAIL;
2118: r = sshkey_from_blob_internal(b, keyp, 1);
2119: sshbuf_free(b);
2120: return r;
2121: }
2122:
2123: int
2124: sshkey_fromb(struct sshbuf *b, struct sshkey **keyp)
2125: {
2126: return sshkey_from_blob_internal(b, keyp, 1);
2127: }
2128:
2129: int
2130: sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2131: {
2132: struct sshbuf *b;
2133: int r;
2134:
2135: if ((r = sshbuf_froms(buf, &b)) != 0)
2136: return r;
2137: r = sshkey_from_blob_internal(b, keyp, 1);
2138: sshbuf_free(b);
2139: return r;
1.1 djm 2140: }
2141:
2142: int
2143: sshkey_sign(const struct sshkey *key,
2144: u_char **sigp, size_t *lenp,
1.28 markus 2145: const u_char *data, size_t datalen, const char *alg, u_int compat)
1.1 djm 2146: {
2147: if (sigp != NULL)
2148: *sigp = NULL;
2149: if (lenp != NULL)
2150: *lenp = 0;
2151: if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2152: return SSH_ERR_INVALID_ARGUMENT;
2153: switch (key->type) {
2154: #ifdef WITH_OPENSSL
2155: case KEY_DSA_CERT:
2156: case KEY_DSA:
2157: return ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
2158: case KEY_ECDSA_CERT:
2159: case KEY_ECDSA:
2160: return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
2161: case KEY_RSA_CERT:
2162: case KEY_RSA:
1.28 markus 2163: return ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
1.1 djm 2164: #endif /* WITH_OPENSSL */
2165: case KEY_ED25519:
2166: case KEY_ED25519_CERT:
2167: return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
2168: default:
2169: return SSH_ERR_KEY_TYPE_UNKNOWN;
2170: }
2171: }
2172:
2173: /*
2174: * ssh_key_verify returns 0 for a correct signature and < 0 on error.
2175: */
2176: int
2177: sshkey_verify(const struct sshkey *key,
2178: const u_char *sig, size_t siglen,
2179: const u_char *data, size_t dlen, u_int compat)
2180: {
1.6 djm 2181: if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
1.1 djm 2182: return SSH_ERR_INVALID_ARGUMENT;
2183: switch (key->type) {
2184: #ifdef WITH_OPENSSL
2185: case KEY_DSA_CERT:
2186: case KEY_DSA:
2187: return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
2188: case KEY_ECDSA_CERT:
2189: case KEY_ECDSA:
2190: return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
2191: case KEY_RSA_CERT:
2192: case KEY_RSA:
1.28 markus 2193: return ssh_rsa_verify(key, sig, siglen, data, dlen);
1.1 djm 2194: #endif /* WITH_OPENSSL */
2195: case KEY_ED25519:
2196: case KEY_ED25519_CERT:
2197: return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
2198: default:
2199: return SSH_ERR_KEY_TYPE_UNKNOWN;
2200: }
2201: }
2202:
2203: /* Converts a private to a public key */
2204: int
2205: sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
2206: {
2207: struct sshkey *pk;
2208: int ret = SSH_ERR_INTERNAL_ERROR;
2209:
1.24 djm 2210: *dkp = NULL;
1.1 djm 2211: if ((pk = calloc(1, sizeof(*pk))) == NULL)
2212: return SSH_ERR_ALLOC_FAIL;
2213: pk->type = k->type;
2214: pk->flags = k->flags;
2215: pk->ecdsa_nid = k->ecdsa_nid;
2216: pk->dsa = NULL;
2217: pk->ecdsa = NULL;
2218: pk->rsa = NULL;
2219: pk->ed25519_pk = NULL;
2220: pk->ed25519_sk = NULL;
2221:
2222: switch (k->type) {
2223: #ifdef WITH_OPENSSL
2224: case KEY_RSA_CERT:
2225: if ((ret = sshkey_cert_copy(k, pk)) != 0)
2226: goto fail;
2227: /* FALLTHROUGH */
2228: case KEY_RSA1:
2229: case KEY_RSA:
2230: if ((pk->rsa = RSA_new()) == NULL ||
2231: (pk->rsa->e = BN_dup(k->rsa->e)) == NULL ||
2232: (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) {
2233: ret = SSH_ERR_ALLOC_FAIL;
2234: goto fail;
2235: }
2236: break;
2237: case KEY_DSA_CERT:
2238: if ((ret = sshkey_cert_copy(k, pk)) != 0)
2239: goto fail;
2240: /* FALLTHROUGH */
2241: case KEY_DSA:
2242: if ((pk->dsa = DSA_new()) == NULL ||
2243: (pk->dsa->p = BN_dup(k->dsa->p)) == NULL ||
2244: (pk->dsa->q = BN_dup(k->dsa->q)) == NULL ||
2245: (pk->dsa->g = BN_dup(k->dsa->g)) == NULL ||
2246: (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) {
2247: ret = SSH_ERR_ALLOC_FAIL;
2248: goto fail;
2249: }
2250: break;
2251: case KEY_ECDSA_CERT:
2252: if ((ret = sshkey_cert_copy(k, pk)) != 0)
2253: goto fail;
2254: /* FALLTHROUGH */
2255: case KEY_ECDSA:
2256: pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid);
2257: if (pk->ecdsa == NULL) {
2258: ret = SSH_ERR_ALLOC_FAIL;
2259: goto fail;
2260: }
2261: if (EC_KEY_set_public_key(pk->ecdsa,
2262: EC_KEY_get0_public_key(k->ecdsa)) != 1) {
2263: ret = SSH_ERR_LIBCRYPTO_ERROR;
2264: goto fail;
2265: }
2266: break;
2267: #endif /* WITH_OPENSSL */
2268: case KEY_ED25519_CERT:
2269: if ((ret = sshkey_cert_copy(k, pk)) != 0)
2270: goto fail;
2271: /* FALLTHROUGH */
2272: case KEY_ED25519:
2273: if (k->ed25519_pk != NULL) {
2274: if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
2275: ret = SSH_ERR_ALLOC_FAIL;
2276: goto fail;
2277: }
2278: memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
2279: }
2280: break;
2281: default:
2282: ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2283: fail:
2284: sshkey_free(pk);
2285: return ret;
2286: }
2287: *dkp = pk;
2288: return 0;
2289: }
2290:
2291: /* Convert a plain key to their _CERT equivalent */
2292: int
1.20 djm 2293: sshkey_to_certified(struct sshkey *k)
1.1 djm 2294: {
2295: int newtype;
2296:
2297: switch (k->type) {
2298: #ifdef WITH_OPENSSL
2299: case KEY_RSA:
1.20 djm 2300: newtype = KEY_RSA_CERT;
1.1 djm 2301: break;
2302: case KEY_DSA:
1.20 djm 2303: newtype = KEY_DSA_CERT;
1.1 djm 2304: break;
2305: case KEY_ECDSA:
2306: newtype = KEY_ECDSA_CERT;
2307: break;
2308: #endif /* WITH_OPENSSL */
2309: case KEY_ED25519:
2310: newtype = KEY_ED25519_CERT;
2311: break;
2312: default:
2313: return SSH_ERR_INVALID_ARGUMENT;
2314: }
2315: if ((k->cert = cert_new()) == NULL)
2316: return SSH_ERR_ALLOC_FAIL;
2317: k->type = newtype;
2318: return 0;
2319: }
2320:
2321: /* Convert a certificate to its raw key equivalent */
2322: int
2323: sshkey_drop_cert(struct sshkey *k)
2324: {
2325: if (!sshkey_type_is_cert(k->type))
2326: return SSH_ERR_KEY_TYPE_UNKNOWN;
2327: cert_free(k->cert);
2328: k->cert = NULL;
2329: k->type = sshkey_type_plain(k->type);
2330: return 0;
2331: }
2332:
2333: /* Sign a certified key, (re-)generating the signed certblob. */
2334: int
1.33 djm 2335: sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
1.1 djm 2336: {
2337: struct sshbuf *principals = NULL;
2338: u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
2339: size_t i, ca_len, sig_len;
2340: int ret = SSH_ERR_INTERNAL_ERROR;
2341: struct sshbuf *cert;
2342:
2343: if (k == NULL || k->cert == NULL ||
2344: k->cert->certblob == NULL || ca == NULL)
2345: return SSH_ERR_INVALID_ARGUMENT;
2346: if (!sshkey_is_cert(k))
2347: return SSH_ERR_KEY_TYPE_UNKNOWN;
2348: if (!sshkey_type_is_valid_ca(ca->type))
2349: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2350:
2351: if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2352: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2353:
2354: cert = k->cert->certblob; /* for readability */
2355: sshbuf_reset(cert);
2356: if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0)
2357: goto out;
2358:
2359: /* -v01 certs put nonce first */
2360: arc4random_buf(&nonce, sizeof(nonce));
1.20 djm 2361: if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
2362: goto out;
1.1 djm 2363:
2364: /* XXX this substantially duplicates to_blob(); refactor */
2365: switch (k->type) {
2366: #ifdef WITH_OPENSSL
2367: case KEY_DSA_CERT:
2368: if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 ||
2369: (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 ||
2370: (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 ||
2371: (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0)
2372: goto out;
2373: break;
2374: case KEY_ECDSA_CERT:
2375: if ((ret = sshbuf_put_cstring(cert,
2376: sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 ||
2377: (ret = sshbuf_put_ec(cert,
2378: EC_KEY_get0_public_key(k->ecdsa),
2379: EC_KEY_get0_group(k->ecdsa))) != 0)
2380: goto out;
2381: break;
2382: case KEY_RSA_CERT:
2383: if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 ||
2384: (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0)
2385: goto out;
2386: break;
2387: #endif /* WITH_OPENSSL */
2388: case KEY_ED25519_CERT:
2389: if ((ret = sshbuf_put_string(cert,
2390: k->ed25519_pk, ED25519_PK_SZ)) != 0)
2391: goto out;
2392: break;
2393: default:
2394: ret = SSH_ERR_INVALID_ARGUMENT;
1.15 djm 2395: goto out;
1.1 djm 2396: }
2397:
1.20 djm 2398: if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 ||
2399: (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
1.1 djm 2400: (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
2401: goto out;
2402:
2403: if ((principals = sshbuf_new()) == NULL) {
2404: ret = SSH_ERR_ALLOC_FAIL;
2405: goto out;
2406: }
2407: for (i = 0; i < k->cert->nprincipals; i++) {
2408: if ((ret = sshbuf_put_cstring(principals,
2409: k->cert->principals[i])) != 0)
2410: goto out;
2411: }
2412: if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
2413: (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
2414: (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
1.20 djm 2415: (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 ||
2416: (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 ||
2417: (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
1.1 djm 2418: (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
2419: goto out;
2420:
2421: /* Sign the whole mess */
2422: if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
1.33 djm 2423: sshbuf_len(cert), alg, 0)) != 0)
1.1 djm 2424: goto out;
2425:
2426: /* Append signature and we are done */
2427: if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
2428: goto out;
2429: ret = 0;
2430: out:
2431: if (ret != 0)
2432: sshbuf_reset(cert);
1.29 mmcc 2433: free(sig_blob);
2434: free(ca_blob);
1.31 mmcc 2435: sshbuf_free(principals);
1.1 djm 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;
1.40 djm 2820:
2821: /*
2822: * NB. This assumes OpenSSL has already verified that the public
2823: * point lies on the curve. This is done by EC_POINT_oct2point()
2824: * implicitly calling EC_POINT_is_on_curve(). If this code is ever
2825: * reachable with public points not unmarshalled using
2826: * EC_POINT_oct2point then the caller will need to explicitly check.
2827: */
1.1 djm 2828:
2829: if ((bnctx = BN_CTX_new()) == NULL)
2830: return SSH_ERR_ALLOC_FAIL;
2831: BN_CTX_start(bnctx);
2832:
2833: /*
2834: * We shouldn't ever hit this case because bignum_get_ecpoint()
2835: * refuses to load GF2m points.
2836: */
2837: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2838: NID_X9_62_prime_field)
2839: goto out;
2840:
2841: /* Q != infinity */
2842: if (EC_POINT_is_at_infinity(group, public))
2843: goto out;
2844:
2845: if ((x = BN_CTX_get(bnctx)) == NULL ||
2846: (y = BN_CTX_get(bnctx)) == NULL ||
2847: (order = BN_CTX_get(bnctx)) == NULL ||
2848: (tmp = BN_CTX_get(bnctx)) == NULL) {
2849: ret = SSH_ERR_ALLOC_FAIL;
2850: goto out;
2851: }
2852:
2853: /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
2854: if (EC_GROUP_get_order(group, order, bnctx) != 1 ||
2855: EC_POINT_get_affine_coordinates_GFp(group, public,
2856: x, y, bnctx) != 1) {
2857: ret = SSH_ERR_LIBCRYPTO_ERROR;
2858: goto out;
2859: }
2860: if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
2861: BN_num_bits(y) <= BN_num_bits(order) / 2)
2862: goto out;
2863:
2864: /* nQ == infinity (n == order of subgroup) */
2865: if ((nq = EC_POINT_new(group)) == NULL) {
2866: ret = SSH_ERR_ALLOC_FAIL;
2867: goto out;
2868: }
2869: if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) {
2870: ret = SSH_ERR_LIBCRYPTO_ERROR;
2871: goto out;
2872: }
2873: if (EC_POINT_is_at_infinity(group, nq) != 1)
2874: goto out;
2875:
2876: /* x < order - 1, y < order - 1 */
2877: if (!BN_sub(tmp, order, BN_value_one())) {
2878: ret = SSH_ERR_LIBCRYPTO_ERROR;
2879: goto out;
2880: }
2881: if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0)
2882: goto out;
2883: ret = 0;
2884: out:
2885: BN_CTX_free(bnctx);
2886: if (nq != NULL)
2887: EC_POINT_free(nq);
2888: return ret;
2889: }
2890:
2891: int
2892: sshkey_ec_validate_private(const EC_KEY *key)
2893: {
2894: BN_CTX *bnctx;
2895: BIGNUM *order, *tmp;
2896: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2897:
2898: if ((bnctx = BN_CTX_new()) == NULL)
2899: return SSH_ERR_ALLOC_FAIL;
2900: BN_CTX_start(bnctx);
2901:
2902: if ((order = BN_CTX_get(bnctx)) == NULL ||
2903: (tmp = BN_CTX_get(bnctx)) == NULL) {
2904: ret = SSH_ERR_ALLOC_FAIL;
2905: goto out;
2906: }
2907:
2908: /* log2(private) > log2(order)/2 */
2909: if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) {
2910: ret = SSH_ERR_LIBCRYPTO_ERROR;
2911: goto out;
2912: }
2913: if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
2914: BN_num_bits(order) / 2)
2915: goto out;
2916:
2917: /* private < order - 1 */
2918: if (!BN_sub(tmp, order, BN_value_one())) {
2919: ret = SSH_ERR_LIBCRYPTO_ERROR;
2920: goto out;
2921: }
2922: if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0)
2923: goto out;
2924: ret = 0;
2925: out:
2926: BN_CTX_free(bnctx);
2927: return ret;
2928: }
2929:
2930: void
2931: sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
2932: {
2933: BIGNUM *x, *y;
2934: BN_CTX *bnctx;
2935:
2936: if (point == NULL) {
2937: fputs("point=(NULL)\n", stderr);
2938: return;
2939: }
2940: if ((bnctx = BN_CTX_new()) == NULL) {
2941: fprintf(stderr, "%s: BN_CTX_new failed\n", __func__);
2942: return;
2943: }
2944: BN_CTX_start(bnctx);
2945: if ((x = BN_CTX_get(bnctx)) == NULL ||
2946: (y = BN_CTX_get(bnctx)) == NULL) {
2947: fprintf(stderr, "%s: BN_CTX_get failed\n", __func__);
2948: return;
2949: }
2950: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2951: NID_X9_62_prime_field) {
2952: fprintf(stderr, "%s: group is not a prime field\n", __func__);
2953: return;
2954: }
2955: if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y,
2956: bnctx) != 1) {
2957: fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
2958: __func__);
2959: return;
2960: }
2961: fputs("x=", stderr);
2962: BN_print_fp(stderr, x);
2963: fputs("\ny=", stderr);
2964: BN_print_fp(stderr, y);
2965: fputs("\n", stderr);
2966: BN_CTX_free(bnctx);
2967: }
2968:
2969: void
2970: sshkey_dump_ec_key(const EC_KEY *key)
2971: {
2972: const BIGNUM *exponent;
2973:
2974: sshkey_dump_ec_point(EC_KEY_get0_group(key),
2975: EC_KEY_get0_public_key(key));
2976: fputs("exponent=", stderr);
2977: if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
2978: fputs("(NULL)", stderr);
2979: else
2980: BN_print_fp(stderr, EC_KEY_get0_private_key(key));
2981: fputs("\n", stderr);
2982: }
2983: #endif /* WITH_OPENSSL */
2984:
2985: static int
2986: sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
2987: const char *passphrase, const char *comment, const char *ciphername,
2988: int rounds)
2989: {
1.4 djm 2990: u_char *cp, *key = NULL, *pubkeyblob = NULL;
1.1 djm 2991: u_char salt[SALT_LEN];
1.4 djm 2992: char *b64 = NULL;
1.1 djm 2993: size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
2994: u_int check;
2995: int r = SSH_ERR_INTERNAL_ERROR;
1.36 djm 2996: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 2997: const struct sshcipher *cipher;
2998: const char *kdfname = KDFNAME;
2999: struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
3000:
3001: if (rounds <= 0)
3002: rounds = DEFAULT_ROUNDS;
3003: if (passphrase == NULL || !strlen(passphrase)) {
3004: ciphername = "none";
3005: kdfname = "none";
3006: } else if (ciphername == NULL)
3007: ciphername = DEFAULT_CIPHERNAME;
3008: else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) {
3009: r = SSH_ERR_INVALID_ARGUMENT;
3010: goto out;
3011: }
3012: if ((cipher = cipher_by_name(ciphername)) == NULL) {
3013: r = SSH_ERR_INTERNAL_ERROR;
3014: goto out;
3015: }
3016:
3017: if ((kdf = sshbuf_new()) == NULL ||
3018: (encoded = sshbuf_new()) == NULL ||
3019: (encrypted = sshbuf_new()) == NULL) {
3020: r = SSH_ERR_ALLOC_FAIL;
3021: goto out;
3022: }
3023: blocksize = cipher_blocksize(cipher);
3024: keylen = cipher_keylen(cipher);
3025: ivlen = cipher_ivlen(cipher);
3026: authlen = cipher_authlen(cipher);
3027: if ((key = calloc(1, keylen + ivlen)) == NULL) {
3028: r = SSH_ERR_ALLOC_FAIL;
3029: goto out;
3030: }
3031: if (strcmp(kdfname, "bcrypt") == 0) {
3032: arc4random_buf(salt, SALT_LEN);
3033: if (bcrypt_pbkdf(passphrase, strlen(passphrase),
3034: salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) {
3035: r = SSH_ERR_INVALID_ARGUMENT;
3036: goto out;
3037: }
3038: if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 ||
3039: (r = sshbuf_put_u32(kdf, rounds)) != 0)
3040: goto out;
3041: } else if (strcmp(kdfname, "none") != 0) {
3042: /* Unsupported KDF type */
3043: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3044: goto out;
3045: }
3046: if ((r = cipher_init(&ciphercontext, cipher, key, keylen,
3047: key + keylen, ivlen, 1)) != 0)
3048: goto out;
3049:
3050: if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 ||
3051: (r = sshbuf_put_cstring(encoded, ciphername)) != 0 ||
3052: (r = sshbuf_put_cstring(encoded, kdfname)) != 0 ||
3053: (r = sshbuf_put_stringb(encoded, kdf)) != 0 ||
3054: (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */
3055: (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 ||
3056: (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0)
3057: goto out;
3058:
3059: /* set up the buffer that will be encrypted */
3060:
3061: /* Random check bytes */
3062: check = arc4random();
3063: if ((r = sshbuf_put_u32(encrypted, check)) != 0 ||
3064: (r = sshbuf_put_u32(encrypted, check)) != 0)
3065: goto out;
3066:
3067: /* append private key and comment*/
3068: if ((r = sshkey_private_serialize(prv, encrypted)) != 0 ||
3069: (r = sshbuf_put_cstring(encrypted, comment)) != 0)
3070: goto out;
3071:
3072: /* padding */
3073: i = 0;
3074: while (sshbuf_len(encrypted) % blocksize) {
3075: if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0)
3076: goto out;
3077: }
3078:
3079: /* length in destination buffer */
3080: if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0)
3081: goto out;
3082:
3083: /* encrypt */
3084: if ((r = sshbuf_reserve(encoded,
3085: sshbuf_len(encrypted) + authlen, &cp)) != 0)
3086: goto out;
1.36 djm 3087: if ((r = cipher_crypt(ciphercontext, 0, cp,
1.1 djm 3088: sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
3089: goto out;
3090:
3091: /* uuencode */
3092: if ((b64 = sshbuf_dtob64(encoded)) == NULL) {
3093: r = SSH_ERR_ALLOC_FAIL;
3094: goto out;
3095: }
3096:
3097: sshbuf_reset(blob);
3098: if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0)
3099: goto out;
3100: for (i = 0; i < strlen(b64); i++) {
3101: if ((r = sshbuf_put_u8(blob, b64[i])) != 0)
3102: goto out;
3103: /* insert line breaks */
3104: if (i % 70 == 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3105: goto out;
3106: }
3107: if (i % 70 != 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3108: goto out;
3109: if ((r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
3110: goto out;
3111:
3112: /* success */
3113: r = 0;
3114:
3115: out:
3116: sshbuf_free(kdf);
3117: sshbuf_free(encoded);
3118: sshbuf_free(encrypted);
1.36 djm 3119: cipher_free(ciphercontext);
1.1 djm 3120: explicit_bzero(salt, sizeof(salt));
3121: if (key != NULL) {
3122: explicit_bzero(key, keylen + ivlen);
3123: free(key);
3124: }
3125: if (pubkeyblob != NULL) {
3126: explicit_bzero(pubkeyblob, pubkeylen);
3127: free(pubkeyblob);
3128: }
3129: if (b64 != NULL) {
3130: explicit_bzero(b64, strlen(b64));
3131: free(b64);
3132: }
3133: return r;
3134: }
3135:
3136: static int
3137: sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3138: struct sshkey **keyp, char **commentp)
3139: {
3140: char *comment = NULL, *ciphername = NULL, *kdfname = NULL;
3141: const struct sshcipher *cipher = NULL;
3142: const u_char *cp;
3143: int r = SSH_ERR_INTERNAL_ERROR;
3144: size_t encoded_len;
1.18 djm 3145: size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;
1.1 djm 3146: struct sshbuf *encoded = NULL, *decoded = NULL;
3147: struct sshbuf *kdf = NULL, *decrypted = NULL;
1.36 djm 3148: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 3149: struct sshkey *k = NULL;
3150: u_char *key = NULL, *salt = NULL, *dp, pad, last;
3151: u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
3152:
3153: if (keyp != NULL)
3154: *keyp = NULL;
3155: if (commentp != NULL)
3156: *commentp = NULL;
3157:
3158: if ((encoded = sshbuf_new()) == NULL ||
3159: (decoded = sshbuf_new()) == NULL ||
3160: (decrypted = sshbuf_new()) == NULL) {
3161: r = SSH_ERR_ALLOC_FAIL;
3162: goto out;
3163: }
3164:
3165: /* check preamble */
3166: cp = sshbuf_ptr(blob);
3167: encoded_len = sshbuf_len(blob);
3168: if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) ||
3169: memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) {
3170: r = SSH_ERR_INVALID_FORMAT;
3171: goto out;
3172: }
3173: cp += MARK_BEGIN_LEN;
3174: encoded_len -= MARK_BEGIN_LEN;
3175:
3176: /* Look for end marker, removing whitespace as we go */
3177: while (encoded_len > 0) {
3178: if (*cp != '\n' && *cp != '\r') {
3179: if ((r = sshbuf_put_u8(encoded, *cp)) != 0)
3180: goto out;
3181: }
3182: last = *cp;
3183: encoded_len--;
3184: cp++;
3185: if (last == '\n') {
3186: if (encoded_len >= MARK_END_LEN &&
3187: memcmp(cp, MARK_END, MARK_END_LEN) == 0) {
3188: /* \0 terminate */
3189: if ((r = sshbuf_put_u8(encoded, 0)) != 0)
3190: goto out;
3191: break;
3192: }
3193: }
3194: }
3195: if (encoded_len == 0) {
3196: r = SSH_ERR_INVALID_FORMAT;
3197: goto out;
3198: }
3199:
3200: /* decode base64 */
1.4 djm 3201: if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0)
1.1 djm 3202: goto out;
3203:
3204: /* check magic */
3205: if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) ||
3206: memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
3207: r = SSH_ERR_INVALID_FORMAT;
3208: goto out;
3209: }
3210: /* parse public portion of key */
3211: if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
3212: (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
3213: (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
3214: (r = sshbuf_froms(decoded, &kdf)) != 0 ||
3215: (r = sshbuf_get_u32(decoded, &nkeys)) != 0 ||
3216: (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */
3217: (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
3218: goto out;
3219:
3220: if ((cipher = cipher_by_name(ciphername)) == NULL) {
3221: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3222: goto out;
3223: }
3224: if ((passphrase == NULL || strlen(passphrase) == 0) &&
3225: strcmp(ciphername, "none") != 0) {
3226: /* passphrase required */
3227: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3228: goto out;
3229: }
3230: if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
3231: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3232: goto out;
3233: }
3234: if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
3235: r = SSH_ERR_INVALID_FORMAT;
3236: goto out;
3237: }
3238: if (nkeys != 1) {
3239: /* XXX only one key supported */
3240: r = SSH_ERR_INVALID_FORMAT;
3241: goto out;
3242: }
3243:
3244: /* check size of encrypted key blob */
3245: blocksize = cipher_blocksize(cipher);
3246: if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
3247: r = SSH_ERR_INVALID_FORMAT;
3248: goto out;
3249: }
3250:
3251: /* setup key */
3252: keylen = cipher_keylen(cipher);
3253: ivlen = cipher_ivlen(cipher);
1.18 djm 3254: authlen = cipher_authlen(cipher);
1.1 djm 3255: if ((key = calloc(1, keylen + ivlen)) == NULL) {
3256: r = SSH_ERR_ALLOC_FAIL;
3257: goto out;
3258: }
3259: if (strcmp(kdfname, "bcrypt") == 0) {
3260: if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 ||
3261: (r = sshbuf_get_u32(kdf, &rounds)) != 0)
3262: goto out;
3263: if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
3264: key, keylen + ivlen, rounds) < 0) {
3265: r = SSH_ERR_INVALID_FORMAT;
3266: goto out;
3267: }
3268: }
3269:
1.18 djm 3270: /* check that an appropriate amount of auth data is present */
3271: if (sshbuf_len(decoded) < encrypted_len + authlen) {
3272: r = SSH_ERR_INVALID_FORMAT;
3273: goto out;
3274: }
3275:
1.1 djm 3276: /* decrypt private portion of key */
3277: if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
3278: (r = cipher_init(&ciphercontext, cipher, key, keylen,
3279: key + keylen, ivlen, 0)) != 0)
3280: goto out;
1.36 djm 3281: if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
1.18 djm 3282: encrypted_len, 0, authlen)) != 0) {
1.1 djm 3283: /* an integrity error here indicates an incorrect passphrase */
3284: if (r == SSH_ERR_MAC_INVALID)
3285: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3286: goto out;
3287: }
1.18 djm 3288: if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
1.1 djm 3289: goto out;
3290: /* there should be no trailing data */
3291: if (sshbuf_len(decoded) != 0) {
3292: r = SSH_ERR_INVALID_FORMAT;
3293: goto out;
3294: }
3295:
3296: /* check check bytes */
3297: if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 ||
3298: (r = sshbuf_get_u32(decrypted, &check2)) != 0)
3299: goto out;
3300: if (check1 != check2) {
3301: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3302: goto out;
3303: }
3304:
3305: /* Load the private key and comment */
3306: if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
3307: (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
3308: goto out;
3309:
3310: /* Check deterministic padding */
3311: i = 0;
3312: while (sshbuf_len(decrypted)) {
3313: if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
3314: goto out;
3315: if (pad != (++i & 0xff)) {
3316: r = SSH_ERR_INVALID_FORMAT;
3317: goto out;
3318: }
3319: }
3320:
3321: /* XXX decode pubkey and check against private */
3322:
3323: /* success */
3324: r = 0;
3325: if (keyp != NULL) {
3326: *keyp = k;
3327: k = NULL;
3328: }
3329: if (commentp != NULL) {
3330: *commentp = comment;
3331: comment = NULL;
3332: }
3333: out:
3334: pad = 0;
1.36 djm 3335: cipher_free(ciphercontext);
1.1 djm 3336: free(ciphername);
3337: free(kdfname);
3338: free(comment);
3339: if (salt != NULL) {
3340: explicit_bzero(salt, slen);
3341: free(salt);
3342: }
3343: if (key != NULL) {
3344: explicit_bzero(key, keylen + ivlen);
3345: free(key);
3346: }
3347: sshbuf_free(encoded);
3348: sshbuf_free(decoded);
3349: sshbuf_free(kdf);
3350: sshbuf_free(decrypted);
3351: sshkey_free(k);
3352: return r;
3353: }
3354:
3355: #if WITH_SSH1
3356: /*
3357: * Serialises the authentication (private) key to a blob, encrypting it with
3358: * passphrase. The identification of the blob (lowest 64 bits of n) will
3359: * precede the key to provide identification of the key without needing a
3360: * passphrase.
3361: */
3362: static int
3363: sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
3364: const char *passphrase, const char *comment)
3365: {
3366: struct sshbuf *buffer = NULL, *encrypted = NULL;
3367: u_char buf[8];
3368: int r, cipher_num;
1.36 djm 3369: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 3370: const struct sshcipher *cipher;
3371: u_char *cp;
3372:
3373: /*
3374: * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
3375: * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
3376: */
3377: cipher_num = (strcmp(passphrase, "") == 0) ?
3378: SSH_CIPHER_NONE : SSH_CIPHER_3DES;
3379: if ((cipher = cipher_by_number(cipher_num)) == NULL)
3380: return SSH_ERR_INTERNAL_ERROR;
3381:
3382: /* This buffer is used to build the secret part of the private key. */
3383: if ((buffer = sshbuf_new()) == NULL)
3384: return SSH_ERR_ALLOC_FAIL;
3385:
3386: /* Put checkbytes for checking passphrase validity. */
3387: if ((r = sshbuf_reserve(buffer, 4, &cp)) != 0)
3388: goto out;
3389: arc4random_buf(cp, 2);
3390: memcpy(cp + 2, cp, 2);
3391:
3392: /*
3393: * Store the private key (n and e will not be stored because they
3394: * will be stored in plain text, and storing them also in encrypted
3395: * format would just give known plaintext).
3396: * Note: q and p are stored in reverse order to SSL.
3397: */
3398: if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 ||
3399: (r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 ||
3400: (r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 ||
3401: (r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0)
3402: goto out;
3403:
3404: /* Pad the part to be encrypted to a size that is a multiple of 8. */
3405: explicit_bzero(buf, 8);
3406: if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0)
3407: goto out;
3408:
3409: /* This buffer will be used to contain the data in the file. */
3410: if ((encrypted = sshbuf_new()) == NULL) {
3411: r = SSH_ERR_ALLOC_FAIL;
3412: goto out;
3413: }
3414:
3415: /* First store keyfile id string. */
3416: if ((r = sshbuf_put(encrypted, LEGACY_BEGIN,
3417: sizeof(LEGACY_BEGIN))) != 0)
3418: goto out;
3419:
3420: /* Store cipher type and "reserved" field. */
3421: if ((r = sshbuf_put_u8(encrypted, cipher_num)) != 0 ||
3422: (r = sshbuf_put_u32(encrypted, 0)) != 0)
3423: goto out;
3424:
3425: /* Store public key. This will be in plain text. */
3426: if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 ||
1.22 jsg 3427: (r = sshbuf_put_bignum1(encrypted, key->rsa->n)) != 0 ||
3428: (r = sshbuf_put_bignum1(encrypted, key->rsa->e)) != 0 ||
3429: (r = sshbuf_put_cstring(encrypted, comment)) != 0)
1.1 djm 3430: goto out;
3431:
3432: /* Allocate space for the private part of the key in the buffer. */
3433: if ((r = sshbuf_reserve(encrypted, sshbuf_len(buffer), &cp)) != 0)
3434: goto out;
3435:
3436: if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
3437: CIPHER_ENCRYPT)) != 0)
3438: goto out;
1.36 djm 3439: if ((r = cipher_crypt(ciphercontext, 0, cp,
1.1 djm 3440: sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0)
3441: goto out;
3442:
3443: r = sshbuf_putb(blob, encrypted);
3444:
3445: out:
1.36 djm 3446: cipher_free(ciphercontext);
1.1 djm 3447: explicit_bzero(buf, sizeof(buf));
1.31 mmcc 3448: sshbuf_free(buffer);
3449: sshbuf_free(encrypted);
1.1 djm 3450:
3451: return r;
3452: }
3453: #endif /* WITH_SSH1 */
3454:
3455: #ifdef WITH_OPENSSL
3456: /* convert SSH v2 key in OpenSSL PEM format */
3457: static int
3458: sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
3459: const char *_passphrase, const char *comment)
3460: {
3461: int success, r;
3462: int blen, len = strlen(_passphrase);
3463: u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
3464: const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
3465: const u_char *bptr;
3466: BIO *bio = NULL;
3467:
3468: if (len > 0 && len <= 4)
3469: return SSH_ERR_PASSPHRASE_TOO_SHORT;
3470: if ((bio = BIO_new(BIO_s_mem())) == NULL)
3471: return SSH_ERR_ALLOC_FAIL;
3472:
3473: switch (key->type) {
3474: case KEY_DSA:
3475: success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
3476: cipher, passphrase, len, NULL, NULL);
3477: break;
3478: case KEY_ECDSA:
3479: success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
3480: cipher, passphrase, len, NULL, NULL);
3481: break;
3482: case KEY_RSA:
3483: success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
3484: cipher, passphrase, len, NULL, NULL);
3485: break;
3486: default:
3487: success = 0;
3488: break;
3489: }
3490: if (success == 0) {
3491: r = SSH_ERR_LIBCRYPTO_ERROR;
3492: goto out;
3493: }
3494: if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
3495: r = SSH_ERR_INTERNAL_ERROR;
3496: goto out;
3497: }
3498: if ((r = sshbuf_put(blob, bptr, blen)) != 0)
3499: goto out;
3500: r = 0;
3501: out:
3502: BIO_free(bio);
3503: return r;
3504: }
3505: #endif /* WITH_OPENSSL */
3506:
3507: /* Serialise "key" to buffer "blob" */
3508: int
3509: sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3510: const char *passphrase, const char *comment,
3511: int force_new_format, const char *new_format_cipher, int new_format_rounds)
3512: {
3513: switch (key->type) {
1.9 markus 3514: #ifdef WITH_SSH1
1.1 djm 3515: case KEY_RSA1:
3516: return sshkey_private_rsa1_to_blob(key, blob,
3517: passphrase, comment);
1.9 markus 3518: #endif /* WITH_SSH1 */
3519: #ifdef WITH_OPENSSL
1.1 djm 3520: case KEY_DSA:
3521: case KEY_ECDSA:
3522: case KEY_RSA:
3523: if (force_new_format) {
3524: return sshkey_private_to_blob2(key, blob, passphrase,
3525: comment, new_format_cipher, new_format_rounds);
3526: }
3527: return sshkey_private_pem_to_blob(key, blob,
3528: passphrase, comment);
3529: #endif /* WITH_OPENSSL */
3530: case KEY_ED25519:
3531: return sshkey_private_to_blob2(key, blob, passphrase,
3532: comment, new_format_cipher, new_format_rounds);
3533: default:
3534: return SSH_ERR_KEY_TYPE_UNKNOWN;
3535: }
3536: }
3537:
3538: #ifdef WITH_SSH1
3539: /*
3540: * Parse the public, unencrypted portion of a RSA1 key.
3541: */
3542: int
3543: sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
3544: struct sshkey **keyp, char **commentp)
3545: {
3546: int r;
3547: struct sshkey *pub = NULL;
3548: struct sshbuf *copy = NULL;
3549:
3550: if (keyp != NULL)
3551: *keyp = NULL;
3552: if (commentp != NULL)
3553: *commentp = NULL;
3554:
3555: /* Check that it is at least big enough to contain the ID string. */
3556: if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
3557: return SSH_ERR_INVALID_FORMAT;
3558:
3559: /*
3560: * Make sure it begins with the id string. Consume the id string
3561: * from the buffer.
3562: */
3563: if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
3564: return SSH_ERR_INVALID_FORMAT;
3565: /* Make a working copy of the keyblob and skip past the magic */
3566: if ((copy = sshbuf_fromb(blob)) == NULL)
3567: return SSH_ERR_ALLOC_FAIL;
3568: if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
3569: goto out;
3570:
3571: /* Skip cipher type, reserved data and key bits. */
3572: if ((r = sshbuf_get_u8(copy, NULL)) != 0 || /* cipher type */
3573: (r = sshbuf_get_u32(copy, NULL)) != 0 || /* reserved */
3574: (r = sshbuf_get_u32(copy, NULL)) != 0) /* key bits */
3575: goto out;
3576:
3577: /* Read the public key from the buffer. */
3578: if ((pub = sshkey_new(KEY_RSA1)) == NULL ||
3579: (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 ||
3580: (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0)
3581: goto out;
3582:
3583: /* Finally, the comment */
3584: if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0)
3585: goto out;
3586:
3587: /* The encrypted private part is not parsed by this function. */
3588:
3589: r = 0;
1.32 djm 3590: if (keyp != NULL) {
1.1 djm 3591: *keyp = pub;
1.32 djm 3592: pub = NULL;
3593: }
1.1 djm 3594: out:
1.31 mmcc 3595: sshbuf_free(copy);
1.30 mmcc 3596: sshkey_free(pub);
1.1 djm 3597: return r;
3598: }
3599:
3600: static int
3601: sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
3602: struct sshkey **keyp, char **commentp)
3603: {
3604: int r;
3605: u_int16_t check1, check2;
3606: u_int8_t cipher_type;
3607: struct sshbuf *decrypted = NULL, *copy = NULL;
3608: u_char *cp;
3609: char *comment = NULL;
1.36 djm 3610: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 3611: const struct sshcipher *cipher;
3612: struct sshkey *prv = NULL;
3613:
1.32 djm 3614: if (keyp != NULL)
3615: *keyp = NULL;
1.1 djm 3616: if (commentp != NULL)
3617: *commentp = NULL;
3618:
3619: /* Check that it is at least big enough to contain the ID string. */
3620: if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
3621: return SSH_ERR_INVALID_FORMAT;
3622:
3623: /*
3624: * Make sure it begins with the id string. Consume the id string
3625: * from the buffer.
3626: */
3627: if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
3628: return SSH_ERR_INVALID_FORMAT;
3629:
3630: if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) {
3631: r = SSH_ERR_ALLOC_FAIL;
3632: goto out;
3633: }
3634: if ((copy = sshbuf_fromb(blob)) == NULL ||
3635: (decrypted = sshbuf_new()) == NULL) {
3636: r = SSH_ERR_ALLOC_FAIL;
3637: goto out;
3638: }
3639: if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
3640: goto out;
3641:
3642: /* Read cipher type. */
3643: if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 ||
3644: (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */
3645: goto out;
3646:
3647: /* Read the public key and comment from the buffer. */
3648: if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */
3649: (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 ||
3650: (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 ||
3651: (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0)
3652: goto out;
3653:
3654: /* Check that it is a supported cipher. */
3655: cipher = cipher_by_number(cipher_type);
3656: if (cipher == NULL) {
3657: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3658: goto out;
3659: }
3660: /* Initialize space for decrypted data. */
3661: if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0)
3662: goto out;
3663:
3664: /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
3665: if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
3666: CIPHER_DECRYPT)) != 0)
3667: goto out;
1.36 djm 3668: if ((r = cipher_crypt(ciphercontext, 0, cp,
3669: sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0)
1.1 djm 3670: goto out;
3671:
3672: if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 ||
3673: (r = sshbuf_get_u16(decrypted, &check2)) != 0)
3674: goto out;
3675: if (check1 != check2) {
3676: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3677: goto out;
3678: }
3679:
3680: /* Read the rest of the private key. */
3681: if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 ||
3682: (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 ||
3683: (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 ||
3684: (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0)
3685: goto out;
3686:
3687: /* calculate p-1 and q-1 */
3688: if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0)
3689: goto out;
3690:
3691: /* enable blinding */
3692: if (RSA_blinding_on(prv->rsa, NULL) != 1) {
3693: r = SSH_ERR_LIBCRYPTO_ERROR;
3694: goto out;
3695: }
3696: r = 0;
1.32 djm 3697: if (keyp != NULL) {
3698: *keyp = prv;
3699: prv = NULL;
3700: }
1.1 djm 3701: if (commentp != NULL) {
3702: *commentp = comment;
3703: comment = NULL;
3704: }
3705: out:
1.36 djm 3706: cipher_free(ciphercontext);
1.29 mmcc 3707: free(comment);
1.30 mmcc 3708: sshkey_free(prv);
1.31 mmcc 3709: sshbuf_free(copy);
3710: sshbuf_free(decrypted);
1.1 djm 3711: return r;
3712: }
3713: #endif /* WITH_SSH1 */
3714:
3715: #ifdef WITH_OPENSSL
1.8 djm 3716: static int
1.1 djm 3717: sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
1.8 djm 3718: const char *passphrase, struct sshkey **keyp)
1.1 djm 3719: {
3720: EVP_PKEY *pk = NULL;
3721: struct sshkey *prv = NULL;
3722: BIO *bio = NULL;
3723: int r;
3724:
1.32 djm 3725: if (keyp != NULL)
3726: *keyp = NULL;
1.1 djm 3727:
3728: if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
3729: return SSH_ERR_ALLOC_FAIL;
3730: if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
3731: (int)sshbuf_len(blob)) {
3732: r = SSH_ERR_ALLOC_FAIL;
3733: goto out;
3734: }
3735:
3736: if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
3737: (char *)passphrase)) == NULL) {
1.42 djm 3738: unsigned long pem_err = ERR_peek_last_error();
3739: int pem_reason = ERR_GET_REASON(pem_err);
3740:
3741: /*
3742: * Translate OpenSSL error codes to determine whether
3743: * passphrase is required/incorrect.
3744: */
3745: switch (ERR_GET_LIB(pem_err)) {
3746: case ERR_LIB_PEM:
3747: switch (pem_reason) {
3748: case PEM_R_BAD_PASSWORD_READ:
3749: case PEM_R_PROBLEMS_GETTING_PASSWORD:
3750: case PEM_R_BAD_DECRYPT:
3751: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3752: goto out;
3753: default:
3754: r = SSH_ERR_INVALID_FORMAT;
3755: goto out;
3756: }
3757: case ERR_LIB_EVP:
3758: switch (pem_reason) {
3759: case EVP_R_BAD_DECRYPT:
3760: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3761: goto out;
3762: case EVP_R_BN_DECODE_ERROR:
3763: case EVP_R_DECODE_ERROR:
3764: case EVP_R_PRIVATE_KEY_DECODE_ERROR:
3765: r = SSH_ERR_INVALID_FORMAT;
3766: goto out;
3767: default:
3768: r = SSH_ERR_LIBCRYPTO_ERROR;
3769: goto out;
3770: }
3771: case ERR_LIB_ASN1:
3772: r = SSH_ERR_INVALID_FORMAT;
3773: goto out;
3774: }
3775: r = SSH_ERR_LIBCRYPTO_ERROR;
1.1 djm 3776: goto out;
3777: }
3778: if (pk->type == EVP_PKEY_RSA &&
3779: (type == KEY_UNSPEC || type == KEY_RSA)) {
3780: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3781: r = SSH_ERR_ALLOC_FAIL;
3782: goto out;
3783: }
3784: prv->rsa = EVP_PKEY_get1_RSA(pk);
3785: prv->type = KEY_RSA;
3786: #ifdef DEBUG_PK
3787: RSA_print_fp(stderr, prv->rsa, 8);
3788: #endif
3789: if (RSA_blinding_on(prv->rsa, NULL) != 1) {
3790: r = SSH_ERR_LIBCRYPTO_ERROR;
3791: goto out;
3792: }
3793: } else if (pk->type == EVP_PKEY_DSA &&
3794: (type == KEY_UNSPEC || type == KEY_DSA)) {
3795: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3796: r = SSH_ERR_ALLOC_FAIL;
3797: goto out;
3798: }
3799: prv->dsa = EVP_PKEY_get1_DSA(pk);
3800: prv->type = KEY_DSA;
3801: #ifdef DEBUG_PK
3802: DSA_print_fp(stderr, prv->dsa, 8);
3803: #endif
3804: } else if (pk->type == EVP_PKEY_EC &&
3805: (type == KEY_UNSPEC || type == KEY_ECDSA)) {
3806: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3807: r = SSH_ERR_ALLOC_FAIL;
3808: goto out;
3809: }
3810: prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
3811: prv->type = KEY_ECDSA;
3812: prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
3813: if (prv->ecdsa_nid == -1 ||
3814: sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
3815: sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
3816: EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
3817: sshkey_ec_validate_private(prv->ecdsa) != 0) {
3818: r = SSH_ERR_INVALID_FORMAT;
3819: goto out;
3820: }
3821: #ifdef DEBUG_PK
3822: if (prv != NULL && prv->ecdsa != NULL)
3823: sshkey_dump_ec_key(prv->ecdsa);
3824: #endif
3825: } else {
3826: r = SSH_ERR_INVALID_FORMAT;
3827: goto out;
3828: }
3829: r = 0;
1.32 djm 3830: if (keyp != NULL) {
3831: *keyp = prv;
3832: prv = NULL;
3833: }
1.1 djm 3834: out:
3835: BIO_free(bio);
3836: if (pk != NULL)
3837: EVP_PKEY_free(pk);
1.30 mmcc 3838: sshkey_free(prv);
1.1 djm 3839: return r;
3840: }
3841: #endif /* WITH_OPENSSL */
3842:
3843: int
3844: sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
3845: const char *passphrase, struct sshkey **keyp, char **commentp)
3846: {
1.42 djm 3847: int r = SSH_ERR_INTERNAL_ERROR;
3848:
1.32 djm 3849: if (keyp != NULL)
3850: *keyp = NULL;
1.1 djm 3851: if (commentp != NULL)
3852: *commentp = NULL;
3853:
3854: switch (type) {
1.9 markus 3855: #ifdef WITH_SSH1
1.1 djm 3856: case KEY_RSA1:
3857: return sshkey_parse_private_rsa1(blob, passphrase,
3858: keyp, commentp);
1.9 markus 3859: #endif /* WITH_SSH1 */
3860: #ifdef WITH_OPENSSL
1.1 djm 3861: case KEY_DSA:
3862: case KEY_ECDSA:
3863: case KEY_RSA:
1.8 djm 3864: return sshkey_parse_private_pem_fileblob(blob, type,
3865: passphrase, keyp);
1.1 djm 3866: #endif /* WITH_OPENSSL */
3867: case KEY_ED25519:
3868: return sshkey_parse_private2(blob, type, passphrase,
3869: keyp, commentp);
3870: case KEY_UNSPEC:
1.42 djm 3871: r = sshkey_parse_private2(blob, type, passphrase, keyp,
3872: commentp);
3873: /* Do not fallback to PEM parser if only passphrase is wrong. */
3874: if (r == 0 || r == SSH_ERR_KEY_WRONG_PASSPHRASE)
3875: return r;
1.1 djm 3876: #ifdef WITH_OPENSSL
1.8 djm 3877: return sshkey_parse_private_pem_fileblob(blob, type,
3878: passphrase, keyp);
1.1 djm 3879: #else
3880: return SSH_ERR_INVALID_FORMAT;
3881: #endif /* WITH_OPENSSL */
3882: default:
3883: return SSH_ERR_KEY_TYPE_UNKNOWN;
3884: }
3885: }
3886:
3887: int
3888: sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
1.23 tim 3889: struct sshkey **keyp, char **commentp)
1.1 djm 3890: {
3891: if (keyp != NULL)
3892: *keyp = NULL;
3893: if (commentp != NULL)
3894: *commentp = NULL;
3895:
3896: #ifdef WITH_SSH1
3897: /* it's a SSH v1 key if the public key part is readable */
1.23 tim 3898: if (sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL) == 0) {
1.1 djm 3899: return sshkey_parse_private_fileblob_type(buffer, KEY_RSA1,
3900: passphrase, keyp, commentp);
3901: }
3902: #endif /* WITH_SSH1 */
1.23 tim 3903: return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
3904: passphrase, keyp, commentp);
1.1 djm 3905: }