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