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