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