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