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