Annotation of src/usr.bin/ssh/sshkey.c, Revision 1.121
1.121 ! djm 1: /* $OpenBSD: sshkey.c,v 1.120 2022/01/06 22:05:42 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:
1.121 ! djm 2082: /* Check deterministic padding after private key */
! 2083: static int
! 2084: private2_check_padding(struct sshbuf *decrypted)
! 2085: {
! 2086: u_char pad;
! 2087: size_t i;
! 2088: int r;
! 2089:
! 2090: i = 0;
! 2091: while (sshbuf_len(decrypted)) {
! 2092: if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
! 2093: goto out;
! 2094: if (pad != (++i & 0xff)) {
! 2095: r = SSH_ERR_INVALID_FORMAT;
! 2096: goto out;
! 2097: }
! 2098: }
! 2099: /* success */
! 2100: r = 0;
! 2101: out:
! 2102: explicit_bzero(&pad, sizeof(pad));
! 2103: explicit_bzero(&i, sizeof(i));
! 2104: return r;
! 2105: }
! 2106:
1.76 djm 2107: int
2108: sshkey_unshield_private(struct sshkey *k)
2109: {
2110: struct sshbuf *prvbuf = NULL;
1.121 ! djm 2111: u_char *cp, keyiv[SSH_DIGEST_MAX_LENGTH];
1.76 djm 2112: struct sshcipher_ctx *cctx = NULL;
2113: const struct sshcipher *cipher;
2114: struct sshkey *kswap = NULL, tmp;
2115: int r = SSH_ERR_INTERNAL_ERROR;
2116:
2117: #ifdef DEBUG_PK
2118: fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
2119: #endif
2120: if (!sshkey_is_shielded(k))
2121: return 0; /* nothing to do */
2122:
2123: if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
2124: r = SSH_ERR_INVALID_ARGUMENT;
2125: goto out;
2126: }
2127: if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
2128: ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
2129: r = SSH_ERR_INTERNAL_ERROR;
2130: goto out;
2131: }
2132: /* check size of shielded key blob */
2133: if (k->shielded_len < cipher_blocksize(cipher) ||
2134: (k->shielded_len % cipher_blocksize(cipher)) != 0) {
2135: r = SSH_ERR_INVALID_FORMAT;
2136: goto out;
2137: }
2138:
2139: /* Calculate the ephemeral key from the prekey */
2140: if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
2141: k->shield_prekey, k->shield_prekey_len,
2142: keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
2143: goto out;
2144: if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
2145: keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 0)) != 0)
2146: goto out;
2147: #ifdef DEBUG_PK
2148: fprintf(stderr, "%s: key+iv\n", __func__);
2149: sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
2150: stderr);
2151: #endif
2152:
2153: /* Decrypt and parse the shielded private key using the ephemeral key */
2154: if ((prvbuf = sshbuf_new()) == NULL) {
2155: r = SSH_ERR_ALLOC_FAIL;
2156: goto out;
2157: }
2158: if ((r = sshbuf_reserve(prvbuf, k->shielded_len, &cp)) != 0)
2159: goto out;
2160: /* decrypt */
2161: #ifdef DEBUG_PK
2162: fprintf(stderr, "%s: encrypted\n", __func__);
2163: sshbuf_dump_data(k->shielded_private, k->shielded_len, stderr);
2164: #endif
2165: if ((r = cipher_crypt(cctx, 0, cp,
2166: k->shielded_private, k->shielded_len, 0, 0)) != 0)
2167: goto out;
2168: #ifdef DEBUG_PK
2169: fprintf(stderr, "%s: serialised\n", __func__);
2170: sshbuf_dump(prvbuf, stderr);
2171: #endif
2172: /* Parse private key */
2173: if ((r = sshkey_private_deserialize(prvbuf, &kswap)) != 0)
2174: goto out;
1.121 ! djm 2175:
! 2176: if ((r = private2_check_padding(prvbuf)) != 0)
! 2177: goto out;
1.76 djm 2178:
2179: /* Swap the parsed key back into place */
2180: tmp = *kswap;
2181: *kswap = *k;
2182: *k = tmp;
2183:
2184: /* success */
2185: r = 0;
2186:
2187: out:
2188: cipher_free(cctx);
2189: explicit_bzero(keyiv, sizeof(keyiv));
2190: explicit_bzero(&tmp, sizeof(tmp));
2191: sshkey_free(kswap);
2192: sshbuf_free(prvbuf);
2193: return r;
2194: }
2195:
1.1 djm 2196: static int
1.14 djm 2197: cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1.1 djm 2198: {
1.14 djm 2199: struct sshbuf *principals = NULL, *crit = NULL;
2200: struct sshbuf *exts = NULL, *ca = NULL;
2201: u_char *sig = NULL;
2202: size_t signed_len = 0, slen = 0, kidlen = 0;
1.1 djm 2203: int ret = SSH_ERR_INTERNAL_ERROR;
2204:
2205: /* Copy the entire key blob for verification and later serialisation */
1.14 djm 2206: if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0)
1.1 djm 2207: return ret;
2208:
1.20 djm 2209: /* Parse body of certificate up to signature */
2210: if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 ||
1.1 djm 2211: (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
2212: (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
1.4 djm 2213: (ret = sshbuf_froms(b, &principals)) != 0 ||
1.1 djm 2214: (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
2215: (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
1.4 djm 2216: (ret = sshbuf_froms(b, &crit)) != 0 ||
1.20 djm 2217: (ret = sshbuf_froms(b, &exts)) != 0 ||
1.1 djm 2218: (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
1.14 djm 2219: (ret = sshbuf_froms(b, &ca)) != 0) {
1.1 djm 2220: /* XXX debug print error for ret */
2221: ret = SSH_ERR_INVALID_FORMAT;
2222: goto out;
2223: }
2224:
2225: /* Signature is left in the buffer so we can calculate this length */
2226: signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b);
2227:
2228: if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) {
2229: ret = SSH_ERR_INVALID_FORMAT;
2230: goto out;
2231: }
2232:
2233: if (key->cert->type != SSH2_CERT_TYPE_USER &&
2234: key->cert->type != SSH2_CERT_TYPE_HOST) {
2235: ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE;
2236: goto out;
2237: }
2238:
1.4 djm 2239: /* Parse principals section */
2240: while (sshbuf_len(principals) > 0) {
2241: char *principal = NULL;
2242: char **oprincipals = NULL;
2243:
1.1 djm 2244: if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
2245: ret = SSH_ERR_INVALID_FORMAT;
2246: goto out;
2247: }
1.4 djm 2248: if ((ret = sshbuf_get_cstring(principals, &principal,
2249: NULL)) != 0) {
1.1 djm 2250: ret = SSH_ERR_INVALID_FORMAT;
2251: goto out;
2252: }
2253: oprincipals = key->cert->principals;
1.51 deraadt 2254: key->cert->principals = recallocarray(key->cert->principals,
2255: key->cert->nprincipals, key->cert->nprincipals + 1,
2256: sizeof(*key->cert->principals));
1.1 djm 2257: if (key->cert->principals == NULL) {
2258: free(principal);
2259: key->cert->principals = oprincipals;
2260: ret = SSH_ERR_ALLOC_FAIL;
2261: goto out;
2262: }
2263: key->cert->principals[key->cert->nprincipals++] = principal;
2264: }
2265:
1.4 djm 2266: /*
2267: * Stash a copies of the critical options and extensions sections
2268: * for later use.
2269: */
2270: if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 ||
2271: (exts != NULL &&
2272: (ret = sshbuf_putb(key->cert->extensions, exts)) != 0))
1.1 djm 2273: goto out;
2274:
1.4 djm 2275: /*
2276: * Validate critical options and extensions sections format.
2277: */
2278: while (sshbuf_len(crit) != 0) {
2279: if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
2280: (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) {
2281: sshbuf_reset(key->cert->critical);
1.1 djm 2282: ret = SSH_ERR_INVALID_FORMAT;
2283: goto out;
2284: }
2285: }
1.4 djm 2286: while (exts != NULL && sshbuf_len(exts) != 0) {
2287: if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 ||
2288: (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) {
2289: sshbuf_reset(key->cert->extensions);
1.1 djm 2290: ret = SSH_ERR_INVALID_FORMAT;
2291: goto out;
2292: }
2293: }
2294:
1.4 djm 2295: /* Parse CA key and check signature */
1.14 djm 2296: if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) {
1.1 djm 2297: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2298: goto out;
2299: }
2300: if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) {
2301: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2302: goto out;
2303: }
2304: if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1.96 djm 2305: sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0, NULL)) != 0)
1.1 djm 2306: goto out;
1.82 djm 2307: if ((ret = sshkey_get_sigtype(sig, slen,
2308: &key->cert->signature_type)) != 0)
1.67 djm 2309: goto out;
1.4 djm 2310:
2311: /* Success */
1.1 djm 2312: ret = 0;
2313: out:
1.14 djm 2314: sshbuf_free(ca);
1.4 djm 2315: sshbuf_free(crit);
2316: sshbuf_free(exts);
2317: sshbuf_free(principals);
1.1 djm 2318: free(sig);
2319: return ret;
2320: }
2321:
1.83 djm 2322: #ifdef WITH_OPENSSL
1.1 djm 2323: static int
1.69 djm 2324: check_rsa_length(const RSA *rsa)
2325: {
2326: const BIGNUM *rsa_n;
2327:
2328: RSA_get0_key(rsa, &rsa_n, NULL, NULL);
2329: if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
2330: return SSH_ERR_KEY_LENGTH;
2331: return 0;
2332: }
1.83 djm 2333: #endif /* WITH_OPENSSL */
1.69 djm 2334:
2335: static int
1.14 djm 2336: sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
2337: int allow_cert)
1.1 djm 2338: {
1.12 djm 2339: int type, ret = SSH_ERR_INTERNAL_ERROR;
1.62 markus 2340: char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
1.1 djm 2341: struct sshkey *key = NULL;
2342: size_t len;
2343: u_char *pk = NULL;
1.14 djm 2344: struct sshbuf *copy;
1.1 djm 2345: #ifdef WITH_OPENSSL
2346: EC_POINT *q = NULL;
1.69 djm 2347: BIGNUM *rsa_n = NULL, *rsa_e = NULL;
2348: BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
1.1 djm 2349: #endif /* WITH_OPENSSL */
2350:
2351: #ifdef DEBUG_PK /* XXX */
1.14 djm 2352: sshbuf_dump(b, stderr);
1.1 djm 2353: #endif
1.32 djm 2354: if (keyp != NULL)
2355: *keyp = NULL;
1.14 djm 2356: if ((copy = sshbuf_fromb(b)) == NULL) {
2357: ret = SSH_ERR_ALLOC_FAIL;
2358: goto out;
2359: }
1.1 djm 2360: if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
2361: ret = SSH_ERR_INVALID_FORMAT;
2362: goto out;
2363: }
2364:
2365: type = sshkey_type_from_name(ktype);
2366: if (!allow_cert && sshkey_type_is_cert(type)) {
2367: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2368: goto out;
2369: }
2370: switch (type) {
2371: #ifdef WITH_OPENSSL
2372: case KEY_RSA_CERT:
1.14 djm 2373: /* Skip nonce */
1.1 djm 2374: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2375: ret = SSH_ERR_INVALID_FORMAT;
2376: goto out;
2377: }
2378: /* FALLTHROUGH */
2379: case KEY_RSA:
2380: if ((key = sshkey_new(type)) == NULL) {
2381: ret = SSH_ERR_ALLOC_FAIL;
2382: goto out;
2383: }
1.73 djm 2384: if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
2385: sshbuf_get_bignum2(b, &rsa_n) != 0) {
1.1 djm 2386: ret = SSH_ERR_INVALID_FORMAT;
2387: goto out;
2388: }
1.69 djm 2389: if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
2390: ret = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 2391: goto out;
2392: }
1.69 djm 2393: rsa_n = rsa_e = NULL; /* transferred */
2394: if ((ret = check_rsa_length(key->rsa)) != 0)
2395: goto out;
1.1 djm 2396: #ifdef DEBUG_PK
2397: RSA_print_fp(stderr, key->rsa, 8);
2398: #endif
2399: break;
2400: case KEY_DSA_CERT:
1.14 djm 2401: /* Skip nonce */
1.1 djm 2402: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2403: ret = SSH_ERR_INVALID_FORMAT;
2404: goto out;
2405: }
2406: /* FALLTHROUGH */
2407: case KEY_DSA:
2408: if ((key = sshkey_new(type)) == NULL) {
2409: ret = SSH_ERR_ALLOC_FAIL;
2410: goto out;
2411: }
1.73 djm 2412: if (sshbuf_get_bignum2(b, &dsa_p) != 0 ||
2413: sshbuf_get_bignum2(b, &dsa_q) != 0 ||
2414: sshbuf_get_bignum2(b, &dsa_g) != 0 ||
2415: sshbuf_get_bignum2(b, &dsa_pub_key) != 0) {
1.1 djm 2416: ret = SSH_ERR_INVALID_FORMAT;
2417: goto out;
2418: }
1.69 djm 2419: if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) {
2420: ret = SSH_ERR_LIBCRYPTO_ERROR;
2421: goto out;
2422: }
2423: dsa_p = dsa_q = dsa_g = NULL; /* transferred */
2424: if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) {
2425: ret = SSH_ERR_LIBCRYPTO_ERROR;
2426: goto out;
2427: }
2428: dsa_pub_key = NULL; /* transferred */
1.1 djm 2429: #ifdef DEBUG_PK
2430: DSA_print_fp(stderr, key->dsa, 8);
2431: #endif
2432: break;
2433: case KEY_ECDSA_CERT:
1.85 djm 2434: case KEY_ECDSA_SK_CERT:
1.14 djm 2435: /* Skip nonce */
1.1 djm 2436: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2437: ret = SSH_ERR_INVALID_FORMAT;
2438: goto out;
2439: }
2440: /* FALLTHROUGH */
2441: case KEY_ECDSA:
1.85 djm 2442: case KEY_ECDSA_SK:
1.1 djm 2443: if ((key = sshkey_new(type)) == NULL) {
2444: ret = SSH_ERR_ALLOC_FAIL;
2445: goto out;
2446: }
1.12 djm 2447: key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
1.1 djm 2448: if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
2449: ret = SSH_ERR_INVALID_FORMAT;
2450: goto out;
2451: }
2452: if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
2453: ret = SSH_ERR_EC_CURVE_MISMATCH;
2454: goto out;
2455: }
1.60 jsing 2456: EC_KEY_free(key->ecdsa);
1.1 djm 2457: if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
2458: == NULL) {
2459: ret = SSH_ERR_EC_CURVE_INVALID;
2460: goto out;
2461: }
2462: if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
2463: ret = SSH_ERR_ALLOC_FAIL;
2464: goto out;
2465: }
2466: if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
2467: ret = SSH_ERR_INVALID_FORMAT;
2468: goto out;
2469: }
2470: if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
2471: q) != 0) {
2472: ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2473: goto out;
2474: }
2475: if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
2476: /* XXX assume it is a allocation error */
2477: ret = SSH_ERR_ALLOC_FAIL;
2478: goto out;
2479: }
2480: #ifdef DEBUG_PK
2481: sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
2482: #endif
1.85 djm 2483: if (type == KEY_ECDSA_SK || type == KEY_ECDSA_SK_CERT) {
2484: /* Parse additional security-key application string */
2485: if (sshbuf_get_cstring(b, &key->sk_application,
2486: NULL) != 0) {
2487: ret = SSH_ERR_INVALID_FORMAT;
2488: goto out;
2489: }
2490: #ifdef DEBUG_PK
2491: fprintf(stderr, "App: %s\n", key->sk_application);
2492: #endif
2493: }
1.1 djm 2494: break;
2495: #endif /* WITH_OPENSSL */
2496: case KEY_ED25519_CERT:
1.90 markus 2497: case KEY_ED25519_SK_CERT:
1.14 djm 2498: /* Skip nonce */
1.1 djm 2499: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2500: ret = SSH_ERR_INVALID_FORMAT;
2501: goto out;
2502: }
2503: /* FALLTHROUGH */
2504: case KEY_ED25519:
1.90 markus 2505: case KEY_ED25519_SK:
1.1 djm 2506: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2507: goto out;
2508: if (len != ED25519_PK_SZ) {
2509: ret = SSH_ERR_INVALID_FORMAT;
2510: goto out;
2511: }
2512: if ((key = sshkey_new(type)) == NULL) {
2513: ret = SSH_ERR_ALLOC_FAIL;
2514: goto out;
2515: }
1.90 markus 2516: if (type == KEY_ED25519_SK || type == KEY_ED25519_SK_CERT) {
2517: /* Parse additional security-key application string */
2518: if (sshbuf_get_cstring(b, &key->sk_application,
2519: NULL) != 0) {
2520: ret = SSH_ERR_INVALID_FORMAT;
2521: goto out;
2522: }
2523: #ifdef DEBUG_PK
2524: fprintf(stderr, "App: %s\n", key->sk_application);
2525: #endif
2526: }
1.1 djm 2527: key->ed25519_pk = pk;
2528: pk = NULL;
2529: break;
1.62 markus 2530: #ifdef WITH_XMSS
2531: case KEY_XMSS_CERT:
2532: /* Skip nonce */
2533: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2534: ret = SSH_ERR_INVALID_FORMAT;
2535: goto out;
2536: }
2537: /* FALLTHROUGH */
2538: case KEY_XMSS:
2539: if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
2540: goto out;
2541: if ((key = sshkey_new(type)) == NULL) {
2542: ret = SSH_ERR_ALLOC_FAIL;
2543: goto out;
2544: }
2545: if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
2546: goto out;
2547: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2548: goto out;
2549: if (len == 0 || len != sshkey_xmss_pklen(key)) {
2550: ret = SSH_ERR_INVALID_FORMAT;
2551: goto out;
2552: }
2553: key->xmss_pk = pk;
2554: pk = NULL;
2555: if (type != KEY_XMSS_CERT &&
2556: (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
2557: goto out;
2558: break;
2559: #endif /* WITH_XMSS */
1.1 djm 2560: case KEY_UNSPEC:
2561: default:
2562: ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2563: goto out;
2564: }
2565:
2566: /* Parse certificate potion */
1.14 djm 2567: if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
1.1 djm 2568: goto out;
2569:
2570: if (key != NULL && sshbuf_len(b) != 0) {
2571: ret = SSH_ERR_INVALID_FORMAT;
2572: goto out;
2573: }
2574: ret = 0;
1.32 djm 2575: if (keyp != NULL) {
2576: *keyp = key;
2577: key = NULL;
2578: }
1.1 djm 2579: out:
1.14 djm 2580: sshbuf_free(copy);
1.1 djm 2581: sshkey_free(key);
1.62 markus 2582: free(xmss_name);
1.1 djm 2583: free(ktype);
2584: free(curve);
2585: free(pk);
2586: #ifdef WITH_OPENSSL
1.60 jsing 2587: EC_POINT_free(q);
1.69 djm 2588: BN_clear_free(rsa_n);
2589: BN_clear_free(rsa_e);
2590: BN_clear_free(dsa_p);
2591: BN_clear_free(dsa_q);
2592: BN_clear_free(dsa_g);
2593: BN_clear_free(dsa_pub_key);
1.1 djm 2594: #endif /* WITH_OPENSSL */
2595: return ret;
2596: }
2597:
2598: int
2599: sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp)
2600: {
1.14 djm 2601: struct sshbuf *b;
2602: int r;
2603:
2604: if ((b = sshbuf_from(blob, blen)) == NULL)
2605: return SSH_ERR_ALLOC_FAIL;
2606: r = sshkey_from_blob_internal(b, keyp, 1);
2607: sshbuf_free(b);
2608: return r;
2609: }
2610:
2611: int
2612: sshkey_fromb(struct sshbuf *b, struct sshkey **keyp)
2613: {
2614: return sshkey_from_blob_internal(b, keyp, 1);
2615: }
2616:
2617: int
2618: sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2619: {
2620: struct sshbuf *b;
2621: int r;
2622:
2623: if ((r = sshbuf_froms(buf, &b)) != 0)
2624: return r;
2625: r = sshkey_from_blob_internal(b, keyp, 1);
1.58 djm 2626: sshbuf_free(b);
2627: return r;
2628: }
2629:
1.82 djm 2630: int
2631: sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
1.58 djm 2632: {
2633: int r;
2634: struct sshbuf *b = NULL;
2635: char *sigtype = NULL;
2636:
2637: if (sigtypep != NULL)
2638: *sigtypep = NULL;
2639: if ((b = sshbuf_from(sig, siglen)) == NULL)
2640: return SSH_ERR_ALLOC_FAIL;
2641: if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0)
2642: goto out;
2643: /* success */
2644: if (sigtypep != NULL) {
2645: *sigtypep = sigtype;
2646: sigtype = NULL;
2647: }
2648: r = 0;
2649: out:
2650: free(sigtype);
1.14 djm 2651: sshbuf_free(b);
2652: return r;
1.68 djm 2653: }
2654:
2655: /*
2656: *
2657: * Checks whether a certificate's signature type is allowed.
2658: * Returns 0 (success) if the certificate signature type appears in the
2659: * "allowed" pattern-list, or the key is not a certificate to begin with.
2660: * Otherwise returns a ssherr.h code.
2661: */
2662: int
2663: sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed)
2664: {
2665: if (key == NULL || allowed == NULL)
2666: return SSH_ERR_INVALID_ARGUMENT;
2667: if (!sshkey_type_is_cert(key->type))
2668: return 0;
2669: if (key->cert == NULL || key->cert->signature_type == NULL)
2670: return SSH_ERR_INVALID_ARGUMENT;
2671: if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1)
2672: return SSH_ERR_SIGN_ALG_UNSUPPORTED;
2673: return 0;
1.65 djm 2674: }
2675:
2676: /*
2677: * Returns the expected signature algorithm for a given public key algorithm.
2678: */
1.66 djm 2679: const char *
2680: sshkey_sigalg_by_name(const char *name)
1.65 djm 2681: {
2682: const struct keytype *kt;
2683:
2684: for (kt = keytypes; kt->type != -1; kt++) {
2685: if (strcmp(kt->name, name) != 0)
2686: continue;
2687: if (kt->sigalg != NULL)
2688: return kt->sigalg;
2689: if (!kt->cert)
2690: return kt->name;
2691: return sshkey_ssh_name_from_type_nid(
2692: sshkey_type_plain(kt->type), kt->nid);
2693: }
2694: return NULL;
2695: }
2696:
2697: /*
2698: * Verifies that the signature algorithm appearing inside the signature blob
2699: * matches that which was requested.
2700: */
2701: int
2702: sshkey_check_sigtype(const u_char *sig, size_t siglen,
2703: const char *requested_alg)
2704: {
2705: const char *expected_alg;
2706: char *sigtype = NULL;
2707: int r;
2708:
2709: if (requested_alg == NULL)
2710: return 0;
1.66 djm 2711: if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
1.65 djm 2712: return SSH_ERR_INVALID_ARGUMENT;
1.82 djm 2713: if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0)
1.65 djm 2714: return r;
2715: r = strcmp(expected_alg, sigtype) == 0;
2716: free(sigtype);
2717: return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
1.1 djm 2718: }
2719:
2720: int
1.76 djm 2721: sshkey_sign(struct sshkey *key,
1.1 djm 2722: u_char **sigp, size_t *lenp,
1.86 djm 2723: const u_char *data, size_t datalen,
1.111 djm 2724: const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
1.1 djm 2725: {
1.76 djm 2726: int was_shielded = sshkey_is_shielded(key);
2727: int r2, r = SSH_ERR_INTERNAL_ERROR;
2728:
1.1 djm 2729: if (sigp != NULL)
2730: *sigp = NULL;
2731: if (lenp != NULL)
2732: *lenp = 0;
2733: if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2734: return SSH_ERR_INVALID_ARGUMENT;
1.76 djm 2735: if ((r = sshkey_unshield_private(key)) != 0)
2736: return r;
1.1 djm 2737: switch (key->type) {
2738: #ifdef WITH_OPENSSL
2739: case KEY_DSA_CERT:
2740: case KEY_DSA:
1.76 djm 2741: r = ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
2742: break;
1.1 djm 2743: case KEY_ECDSA_CERT:
2744: case KEY_ECDSA:
1.76 djm 2745: r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
2746: break;
1.1 djm 2747: case KEY_RSA_CERT:
2748: case KEY_RSA:
1.76 djm 2749: r = ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
2750: break;
1.1 djm 2751: #endif /* WITH_OPENSSL */
2752: case KEY_ED25519:
2753: case KEY_ED25519_CERT:
1.76 djm 2754: r = ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
1.89 markus 2755: break;
2756: case KEY_ED25519_SK:
2757: case KEY_ED25519_SK_CERT:
1.97 djm 2758: case KEY_ECDSA_SK_CERT:
2759: case KEY_ECDSA_SK:
2760: r = sshsk_sign(sk_provider, key, sigp, lenp, data,
1.111 djm 2761: datalen, compat, sk_pin);
1.76 djm 2762: break;
1.62 markus 2763: #ifdef WITH_XMSS
2764: case KEY_XMSS:
2765: case KEY_XMSS_CERT:
1.76 djm 2766: r = ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
2767: break;
1.62 markus 2768: #endif /* WITH_XMSS */
1.1 djm 2769: default:
1.76 djm 2770: r = SSH_ERR_KEY_TYPE_UNKNOWN;
2771: break;
1.1 djm 2772: }
1.76 djm 2773: if (was_shielded && (r2 = sshkey_shield_private(key)) != 0)
2774: return r2;
2775: return r;
1.1 djm 2776: }
2777:
2778: /*
2779: * ssh_key_verify returns 0 for a correct signature and < 0 on error.
1.59 djm 2780: * If "alg" specified, then the signature must use that algorithm.
1.1 djm 2781: */
2782: int
2783: sshkey_verify(const struct sshkey *key,
2784: const u_char *sig, size_t siglen,
1.96 djm 2785: const u_char *data, size_t dlen, const char *alg, u_int compat,
2786: struct sshkey_sig_details **detailsp)
1.1 djm 2787: {
1.96 djm 2788: if (detailsp != NULL)
2789: *detailsp = NULL;
1.6 djm 2790: if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
1.1 djm 2791: return SSH_ERR_INVALID_ARGUMENT;
2792: switch (key->type) {
2793: #ifdef WITH_OPENSSL
2794: case KEY_DSA_CERT:
2795: case KEY_DSA:
2796: return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
2797: case KEY_ECDSA_CERT:
2798: case KEY_ECDSA:
2799: return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
1.85 djm 2800: case KEY_ECDSA_SK_CERT:
2801: case KEY_ECDSA_SK:
2802: return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen,
1.96 djm 2803: compat, detailsp);
1.1 djm 2804: case KEY_RSA_CERT:
2805: case KEY_RSA:
1.59 djm 2806: return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
1.1 djm 2807: #endif /* WITH_OPENSSL */
2808: case KEY_ED25519:
2809: case KEY_ED25519_CERT:
2810: return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
1.87 markus 2811: case KEY_ED25519_SK:
2812: case KEY_ED25519_SK_CERT:
2813: return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen,
1.96 djm 2814: compat, detailsp);
1.62 markus 2815: #ifdef WITH_XMSS
2816: case KEY_XMSS:
2817: case KEY_XMSS_CERT:
2818: return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
2819: #endif /* WITH_XMSS */
1.1 djm 2820: default:
2821: return SSH_ERR_KEY_TYPE_UNKNOWN;
2822: }
2823: }
2824:
2825: /* Convert a plain key to their _CERT equivalent */
2826: int
1.20 djm 2827: sshkey_to_certified(struct sshkey *k)
1.1 djm 2828: {
2829: int newtype;
2830:
2831: switch (k->type) {
2832: #ifdef WITH_OPENSSL
2833: case KEY_RSA:
1.20 djm 2834: newtype = KEY_RSA_CERT;
1.1 djm 2835: break;
2836: case KEY_DSA:
1.20 djm 2837: newtype = KEY_DSA_CERT;
1.1 djm 2838: break;
2839: case KEY_ECDSA:
2840: newtype = KEY_ECDSA_CERT;
2841: break;
1.85 djm 2842: case KEY_ECDSA_SK:
2843: newtype = KEY_ECDSA_SK_CERT;
2844: break;
1.1 djm 2845: #endif /* WITH_OPENSSL */
1.90 markus 2846: case KEY_ED25519_SK:
2847: newtype = KEY_ED25519_SK_CERT;
2848: break;
1.1 djm 2849: case KEY_ED25519:
2850: newtype = KEY_ED25519_CERT;
2851: break;
1.62 markus 2852: #ifdef WITH_XMSS
2853: case KEY_XMSS:
2854: newtype = KEY_XMSS_CERT;
2855: break;
2856: #endif /* WITH_XMSS */
1.1 djm 2857: default:
2858: return SSH_ERR_INVALID_ARGUMENT;
2859: }
2860: if ((k->cert = cert_new()) == NULL)
2861: return SSH_ERR_ALLOC_FAIL;
2862: k->type = newtype;
2863: return 0;
2864: }
2865:
2866: /* Convert a certificate to its raw key equivalent */
2867: int
2868: sshkey_drop_cert(struct sshkey *k)
2869: {
2870: if (!sshkey_type_is_cert(k->type))
2871: return SSH_ERR_KEY_TYPE_UNKNOWN;
2872: cert_free(k->cert);
2873: k->cert = NULL;
2874: k->type = sshkey_type_plain(k->type);
2875: return 0;
2876: }
2877:
2878: /* Sign a certified key, (re-)generating the signed certblob. */
2879: int
1.53 djm 2880: sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
1.111 djm 2881: const char *sk_provider, const char *sk_pin,
2882: sshkey_certify_signer *signer, void *signer_ctx)
1.1 djm 2883: {
2884: struct sshbuf *principals = NULL;
2885: u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
2886: size_t i, ca_len, sig_len;
2887: int ret = SSH_ERR_INTERNAL_ERROR;
1.67 djm 2888: struct sshbuf *cert = NULL;
2889: char *sigtype = NULL;
1.69 djm 2890: #ifdef WITH_OPENSSL
2891: const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
2892: #endif /* WITH_OPENSSL */
1.1 djm 2893:
2894: if (k == NULL || k->cert == NULL ||
2895: k->cert->certblob == NULL || ca == NULL)
2896: return SSH_ERR_INVALID_ARGUMENT;
2897: if (!sshkey_is_cert(k))
2898: return SSH_ERR_KEY_TYPE_UNKNOWN;
2899: if (!sshkey_type_is_valid_ca(ca->type))
2900: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2901:
1.67 djm 2902: /*
2903: * If no alg specified as argument but a signature_type was set,
2904: * then prefer that. If both were specified, then they must match.
2905: */
2906: if (alg == NULL)
2907: alg = k->cert->signature_type;
2908: else if (k->cert->signature_type != NULL &&
2909: strcmp(alg, k->cert->signature_type) != 0)
2910: return SSH_ERR_INVALID_ARGUMENT;
1.75 djm 2911:
2912: /*
2913: * If no signing algorithm or signature_type was specified and we're
2914: * using a RSA key, then default to a good signature algorithm.
2915: */
2916: if (alg == NULL && ca->type == KEY_RSA)
2917: alg = "rsa-sha2-512";
1.67 djm 2918:
1.1 djm 2919: if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2920: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2921:
2922: cert = k->cert->certblob; /* for readability */
2923: sshbuf_reset(cert);
2924: if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0)
2925: goto out;
2926:
2927: /* -v01 certs put nonce first */
2928: arc4random_buf(&nonce, sizeof(nonce));
1.20 djm 2929: if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
2930: goto out;
1.1 djm 2931:
2932: /* XXX this substantially duplicates to_blob(); refactor */
2933: switch (k->type) {
2934: #ifdef WITH_OPENSSL
2935: case KEY_DSA_CERT:
1.69 djm 2936: DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
2937: DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
2938: if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 ||
2939: (ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 ||
2940: (ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 ||
2941: (ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0)
1.1 djm 2942: goto out;
2943: break;
2944: case KEY_ECDSA_CERT:
1.85 djm 2945: case KEY_ECDSA_SK_CERT:
1.1 djm 2946: if ((ret = sshbuf_put_cstring(cert,
2947: sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 ||
2948: (ret = sshbuf_put_ec(cert,
2949: EC_KEY_get0_public_key(k->ecdsa),
2950: EC_KEY_get0_group(k->ecdsa))) != 0)
2951: goto out;
1.85 djm 2952: if (k->type == KEY_ECDSA_SK_CERT) {
2953: if ((ret = sshbuf_put_cstring(cert,
2954: k->sk_application)) != 0)
2955: goto out;
2956: }
1.1 djm 2957: break;
2958: case KEY_RSA_CERT:
1.69 djm 2959: RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
2960: if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 ||
2961: (ret = sshbuf_put_bignum2(cert, rsa_n)) != 0)
1.1 djm 2962: goto out;
2963: break;
2964: #endif /* WITH_OPENSSL */
2965: case KEY_ED25519_CERT:
1.94 djm 2966: case KEY_ED25519_SK_CERT:
1.1 djm 2967: if ((ret = sshbuf_put_string(cert,
2968: k->ed25519_pk, ED25519_PK_SZ)) != 0)
2969: goto out;
1.94 djm 2970: if (k->type == KEY_ED25519_SK_CERT) {
2971: if ((ret = sshbuf_put_cstring(cert,
2972: k->sk_application)) != 0)
2973: goto out;
2974: }
1.1 djm 2975: break;
1.62 markus 2976: #ifdef WITH_XMSS
2977: case KEY_XMSS_CERT:
2978: if (k->xmss_name == NULL) {
2979: ret = SSH_ERR_INVALID_ARGUMENT;
2980: goto out;
2981: }
2982: if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) ||
2983: (ret = sshbuf_put_string(cert,
2984: k->xmss_pk, sshkey_xmss_pklen(k))) != 0)
2985: goto out;
2986: break;
2987: #endif /* WITH_XMSS */
1.1 djm 2988: default:
2989: ret = SSH_ERR_INVALID_ARGUMENT;
1.15 djm 2990: goto out;
1.1 djm 2991: }
2992:
1.20 djm 2993: if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 ||
2994: (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
1.1 djm 2995: (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
2996: goto out;
2997:
2998: if ((principals = sshbuf_new()) == NULL) {
2999: ret = SSH_ERR_ALLOC_FAIL;
3000: goto out;
3001: }
3002: for (i = 0; i < k->cert->nprincipals; i++) {
3003: if ((ret = sshbuf_put_cstring(principals,
3004: k->cert->principals[i])) != 0)
3005: goto out;
3006: }
3007: if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
3008: (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
3009: (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
1.20 djm 3010: (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 ||
3011: (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 ||
3012: (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
1.1 djm 3013: (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
3014: goto out;
3015:
3016: /* Sign the whole mess */
1.53 djm 3017: if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
1.111 djm 3018: sshbuf_len(cert), alg, sk_provider, sk_pin, 0, signer_ctx)) != 0)
1.1 djm 3019: goto out;
1.67 djm 3020: /* Check and update signature_type against what was actually used */
1.82 djm 3021: if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
1.67 djm 3022: goto out;
3023: if (alg != NULL && strcmp(alg, sigtype) != 0) {
3024: ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
3025: goto out;
3026: }
3027: if (k->cert->signature_type == NULL) {
3028: k->cert->signature_type = sigtype;
3029: sigtype = NULL;
3030: }
1.1 djm 3031: /* Append signature and we are done */
3032: if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
3033: goto out;
3034: ret = 0;
3035: out:
3036: if (ret != 0)
3037: sshbuf_reset(cert);
1.29 mmcc 3038: free(sig_blob);
3039: free(ca_blob);
1.67 djm 3040: free(sigtype);
1.31 mmcc 3041: sshbuf_free(principals);
1.1 djm 3042: return ret;
1.53 djm 3043: }
3044:
3045: static int
1.76 djm 3046: default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
1.53 djm 3047: const u_char *data, size_t datalen,
1.111 djm 3048: const char *alg, const char *sk_provider, const char *sk_pin,
3049: u_int compat, void *ctx)
1.53 djm 3050: {
3051: if (ctx != NULL)
3052: return SSH_ERR_INVALID_ARGUMENT;
1.86 djm 3053: return sshkey_sign(key, sigp, lenp, data, datalen, alg,
1.111 djm 3054: sk_provider, sk_pin, compat);
1.53 djm 3055: }
3056:
3057: int
1.86 djm 3058: sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg,
1.111 djm 3059: const char *sk_provider, const char *sk_pin)
1.53 djm 3060: {
1.111 djm 3061: return sshkey_certify_custom(k, ca, alg, sk_provider, sk_pin,
1.86 djm 3062: default_key_sign, NULL);
1.1 djm 3063: }
3064:
3065: int
3066: sshkey_cert_check_authority(const struct sshkey *k,
1.114 djm 3067: int want_host, int require_principal, int wildcard_pattern,
1.119 djm 3068: uint64_t verify_time, const char *name, const char **reason)
1.1 djm 3069: {
3070: u_int i, principal_matches;
3071:
1.102 markus 3072: if (reason == NULL)
3073: return SSH_ERR_INVALID_ARGUMENT;
1.114 djm 3074: if (!sshkey_is_cert(k)) {
3075: *reason = "Key is not a certificate";
3076: return SSH_ERR_KEY_CERT_INVALID;
3077: }
1.1 djm 3078: if (want_host) {
3079: if (k->cert->type != SSH2_CERT_TYPE_HOST) {
3080: *reason = "Certificate invalid: not a host certificate";
3081: return SSH_ERR_KEY_CERT_INVALID;
3082: }
3083: } else {
3084: if (k->cert->type != SSH2_CERT_TYPE_USER) {
3085: *reason = "Certificate invalid: not a user certificate";
3086: return SSH_ERR_KEY_CERT_INVALID;
3087: }
3088: }
1.119 djm 3089: if (verify_time < k->cert->valid_after) {
1.1 djm 3090: *reason = "Certificate invalid: not yet valid";
3091: return SSH_ERR_KEY_CERT_INVALID;
3092: }
1.119 djm 3093: if (verify_time >= k->cert->valid_before) {
1.1 djm 3094: *reason = "Certificate invalid: expired";
3095: return SSH_ERR_KEY_CERT_INVALID;
3096: }
3097: if (k->cert->nprincipals == 0) {
3098: if (require_principal) {
3099: *reason = "Certificate lacks principal list";
3100: return SSH_ERR_KEY_CERT_INVALID;
3101: }
3102: } else if (name != NULL) {
3103: principal_matches = 0;
3104: for (i = 0; i < k->cert->nprincipals; i++) {
1.114 djm 3105: if (wildcard_pattern) {
3106: if (match_pattern(k->cert->principals[i],
3107: name)) {
3108: principal_matches = 1;
3109: break;
3110: }
3111: } else if (strcmp(name, k->cert->principals[i]) == 0) {
1.1 djm 3112: principal_matches = 1;
3113: break;
3114: }
3115: }
3116: if (!principal_matches) {
3117: *reason = "Certificate invalid: name is not a listed "
3118: "principal";
3119: return SSH_ERR_KEY_CERT_INVALID;
3120: }
1.114 djm 3121: }
3122: return 0;
3123: }
3124:
3125: int
1.119 djm 3126: sshkey_cert_check_authority_now(const struct sshkey *k,
3127: int want_host, int require_principal, int wildcard_pattern,
3128: const char *name, const char **reason)
3129: {
3130: time_t now;
3131:
3132: if ((now = time(NULL)) < 0) {
3133: /* yikes - system clock before epoch! */
3134: *reason = "Certificate invalid: not yet valid";
3135: return SSH_ERR_KEY_CERT_INVALID;
3136: }
3137: return sshkey_cert_check_authority(k, want_host, require_principal,
3138: wildcard_pattern, (uint64_t)now, name, reason);
3139: }
3140:
3141: int
1.114 djm 3142: sshkey_cert_check_host(const struct sshkey *key, const char *host,
3143: int wildcard_principals, const char *ca_sign_algorithms,
3144: const char **reason)
3145: {
3146: int r;
3147:
1.119 djm 3148: if ((r = sshkey_cert_check_authority_now(key, 1, 0, wildcard_principals,
1.114 djm 3149: host, reason)) != 0)
3150: return r;
3151: if (sshbuf_len(key->cert->critical) != 0) {
3152: *reason = "Certificate contains unsupported critical options";
3153: return SSH_ERR_KEY_CERT_INVALID;
3154: }
3155: if (ca_sign_algorithms != NULL &&
3156: (r = sshkey_check_cert_sigtype(key, ca_sign_algorithms)) != 0) {
3157: *reason = "Certificate signed with disallowed algorithm";
3158: return SSH_ERR_KEY_CERT_INVALID;
1.1 djm 3159: }
3160: return 0;
1.27 djm 3161: }
3162:
3163: size_t
3164: sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
3165: {
1.113 dtucker 3166: char from[32], to[32], ret[128];
1.27 djm 3167:
3168: *from = *to = '\0';
3169: if (cert->valid_after == 0 &&
3170: cert->valid_before == 0xffffffffffffffffULL)
3171: return strlcpy(s, "forever", l);
3172:
1.118 dtucker 3173: if (cert->valid_after != 0)
3174: format_absolute_time(cert->valid_after, from, sizeof(from));
3175: if (cert->valid_before != 0xffffffffffffffffULL)
3176: format_absolute_time(cert->valid_before, to, sizeof(to));
1.27 djm 3177:
3178: if (cert->valid_after == 0)
3179: snprintf(ret, sizeof(ret), "before %s", to);
3180: else if (cert->valid_before == 0xffffffffffffffffULL)
3181: snprintf(ret, sizeof(ret), "after %s", from);
3182: else
3183: snprintf(ret, sizeof(ret), "from %s to %s", from, to);
3184:
3185: return strlcpy(s, ret, l);
1.1 djm 3186: }
3187:
3188: int
1.76 djm 3189: sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
1.62 markus 3190: enum sshkey_serialize_rep opts)
1.1 djm 3191: {
3192: int r = SSH_ERR_INTERNAL_ERROR;
1.76 djm 3193: int was_shielded = sshkey_is_shielded(key);
3194: struct sshbuf *b = NULL;
1.69 djm 3195: #ifdef WITH_OPENSSL
3196: const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
3197: const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key;
3198: #endif /* WITH_OPENSSL */
1.1 djm 3199:
1.76 djm 3200: if ((r = sshkey_unshield_private(key)) != 0)
3201: return r;
3202: if ((b = sshbuf_new()) == NULL)
3203: return SSH_ERR_ALLOC_FAIL;
1.1 djm 3204: if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
3205: goto out;
3206: switch (key->type) {
3207: #ifdef WITH_OPENSSL
3208: case KEY_RSA:
1.69 djm 3209: RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
3210: RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
3211: RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
3212: if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
3213: (r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
3214: (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
3215: (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
3216: (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
3217: (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
1.1 djm 3218: goto out;
3219: break;
3220: case KEY_RSA_CERT:
3221: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3222: r = SSH_ERR_INVALID_ARGUMENT;
3223: goto out;
3224: }
1.69 djm 3225: RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
3226: RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
3227: RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
1.1 djm 3228: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
1.69 djm 3229: (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
3230: (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
3231: (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
3232: (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
1.1 djm 3233: goto out;
3234: break;
3235: case KEY_DSA:
1.69 djm 3236: DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
3237: DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key);
3238: if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
3239: (r = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
3240: (r = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
3241: (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 ||
3242: (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
1.1 djm 3243: goto out;
3244: break;
3245: case KEY_DSA_CERT:
3246: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3247: r = SSH_ERR_INVALID_ARGUMENT;
3248: goto out;
3249: }
1.69 djm 3250: DSA_get0_key(key->dsa, NULL, &dsa_priv_key);
1.1 djm 3251: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
1.69 djm 3252: (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
1.1 djm 3253: goto out;
3254: break;
3255: case KEY_ECDSA:
3256: if ((r = sshbuf_put_cstring(b,
3257: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
3258: (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
3259: (r = sshbuf_put_bignum2(b,
3260: EC_KEY_get0_private_key(key->ecdsa))) != 0)
3261: goto out;
3262: break;
3263: case KEY_ECDSA_CERT:
3264: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3265: r = SSH_ERR_INVALID_ARGUMENT;
3266: goto out;
3267: }
3268: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3269: (r = sshbuf_put_bignum2(b,
3270: EC_KEY_get0_private_key(key->ecdsa))) != 0)
3271: goto out;
3272: break;
1.85 djm 3273: case KEY_ECDSA_SK:
3274: if ((r = sshbuf_put_cstring(b,
3275: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
3276: (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
3277: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
3278: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
3279: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
3280: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
3281: goto out;
3282: break;
3283: case KEY_ECDSA_SK_CERT:
3284: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3285: r = SSH_ERR_INVALID_ARGUMENT;
3286: goto out;
3287: }
3288: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3289: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
3290: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
3291: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
3292: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
3293: goto out;
3294: break;
1.1 djm 3295: #endif /* WITH_OPENSSL */
3296: case KEY_ED25519:
3297: if ((r = sshbuf_put_string(b, key->ed25519_pk,
3298: ED25519_PK_SZ)) != 0 ||
3299: (r = sshbuf_put_string(b, key->ed25519_sk,
3300: ED25519_SK_SZ)) != 0)
3301: goto out;
3302: break;
3303: case KEY_ED25519_CERT:
3304: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3305: r = SSH_ERR_INVALID_ARGUMENT;
3306: goto out;
3307: }
3308: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3309: (r = sshbuf_put_string(b, key->ed25519_pk,
3310: ED25519_PK_SZ)) != 0 ||
3311: (r = sshbuf_put_string(b, key->ed25519_sk,
3312: ED25519_SK_SZ)) != 0)
3313: goto out;
3314: break;
1.90 markus 3315: case KEY_ED25519_SK:
3316: if ((r = sshbuf_put_string(b, key->ed25519_pk,
3317: ED25519_PK_SZ)) != 0 ||
3318: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
3319: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
3320: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
3321: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
3322: goto out;
3323: break;
3324: case KEY_ED25519_SK_CERT:
3325: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3326: r = SSH_ERR_INVALID_ARGUMENT;
3327: goto out;
3328: }
3329: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3330: (r = sshbuf_put_string(b, key->ed25519_pk,
3331: ED25519_PK_SZ)) != 0 ||
3332: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
3333: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
3334: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
3335: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
3336: goto out;
3337: break;
1.62 markus 3338: #ifdef WITH_XMSS
3339: case KEY_XMSS:
3340: if (key->xmss_name == NULL) {
3341: r = SSH_ERR_INVALID_ARGUMENT;
3342: goto out;
3343: }
3344: if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
3345: (r = sshbuf_put_string(b, key->xmss_pk,
3346: sshkey_xmss_pklen(key))) != 0 ||
3347: (r = sshbuf_put_string(b, key->xmss_sk,
3348: sshkey_xmss_sklen(key))) != 0 ||
3349: (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
3350: goto out;
3351: break;
3352: case KEY_XMSS_CERT:
3353: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
3354: key->xmss_name == NULL) {
3355: r = SSH_ERR_INVALID_ARGUMENT;
3356: goto out;
3357: }
3358: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3359: (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
3360: (r = sshbuf_put_string(b, key->xmss_pk,
3361: sshkey_xmss_pklen(key))) != 0 ||
3362: (r = sshbuf_put_string(b, key->xmss_sk,
3363: sshkey_xmss_sklen(key))) != 0 ||
3364: (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
3365: goto out;
3366: break;
3367: #endif /* WITH_XMSS */
1.1 djm 3368: default:
3369: r = SSH_ERR_INVALID_ARGUMENT;
3370: goto out;
3371: }
1.76 djm 3372: /*
3373: * success (but we still need to append the output to buf after
3374: * possibly re-shielding the private key)
3375: */
1.1 djm 3376: r = 0;
3377: out:
1.76 djm 3378: if (was_shielded)
3379: r = sshkey_shield_private(key);
3380: if (r == 0)
3381: r = sshbuf_putb(buf, b);
3382: sshbuf_free(b);
3383:
1.1 djm 3384: return r;
3385: }
3386:
3387: int
1.76 djm 3388: sshkey_private_serialize(struct sshkey *key, struct sshbuf *b)
1.62 markus 3389: {
3390: return sshkey_private_serialize_opt(key, b,
3391: SSHKEY_SERIALIZE_DEFAULT);
3392: }
3393:
3394: int
1.1 djm 3395: sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3396: {
1.62 markus 3397: char *tname = NULL, *curve = NULL, *xmss_name = NULL;
1.115 djm 3398: char *expect_sk_application = NULL;
1.1 djm 3399: struct sshkey *k = NULL;
1.14 djm 3400: size_t pklen = 0, sklen = 0;
1.1 djm 3401: int type, r = SSH_ERR_INTERNAL_ERROR;
3402: u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
1.115 djm 3403: u_char *expect_ed25519_pk = NULL;
1.62 markus 3404: u_char *xmss_pk = NULL, *xmss_sk = NULL;
1.1 djm 3405: #ifdef WITH_OPENSSL
3406: BIGNUM *exponent = NULL;
1.69 djm 3407: BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
3408: BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
3409: BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
3410: BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
1.1 djm 3411: #endif /* WITH_OPENSSL */
3412:
3413: if (kp != NULL)
3414: *kp = NULL;
3415: if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
3416: goto out;
3417: type = sshkey_type_from_name(tname);
1.108 djm 3418: if (sshkey_type_is_cert(type)) {
3419: /*
3420: * Certificate key private keys begin with the certificate
3421: * itself. Make sure this matches the type of the enclosing
3422: * private key.
3423: */
3424: if ((r = sshkey_froms(buf, &k)) != 0)
3425: goto out;
3426: if (k->type != type) {
3427: r = SSH_ERR_KEY_CERT_MISMATCH;
3428: goto out;
3429: }
3430: /* For ECDSA keys, the group must match too */
3431: if (k->type == KEY_ECDSA &&
3432: k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) {
3433: r = SSH_ERR_KEY_CERT_MISMATCH;
3434: goto out;
3435: }
1.115 djm 3436: /*
3437: * Several fields are redundant between certificate and
3438: * private key body, we require these to match.
3439: */
3440: expect_sk_application = k->sk_application;
3441: expect_ed25519_pk = k->ed25519_pk;
3442: k->sk_application = NULL;
3443: k->ed25519_pk = NULL;
1.108 djm 3444: } else {
1.70 djm 3445: if ((k = sshkey_new(type)) == NULL) {
1.1 djm 3446: r = SSH_ERR_ALLOC_FAIL;
3447: goto out;
3448: }
1.108 djm 3449: }
3450: switch (type) {
3451: #ifdef WITH_OPENSSL
3452: case KEY_DSA:
1.73 djm 3453: if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 ||
3454: (r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 ||
3455: (r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 ||
1.108 djm 3456: (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0)
1.69 djm 3457: goto out;
3458: if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) {
3459: r = SSH_ERR_LIBCRYPTO_ERROR;
3460: goto out;
3461: }
3462: dsa_p = dsa_q = dsa_g = NULL; /* transferred */
1.108 djm 3463: if (!DSA_set0_key(k->dsa, dsa_pub_key, NULL)) {
1.69 djm 3464: r = SSH_ERR_LIBCRYPTO_ERROR;
1.1 djm 3465: goto out;
1.69 djm 3466: }
1.108 djm 3467: dsa_pub_key = NULL; /* transferred */
3468: /* FALLTHROUGH */
1.1 djm 3469: case KEY_DSA_CERT:
1.108 djm 3470: if ((r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
1.84 djm 3471: goto out;
1.69 djm 3472: if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) {
3473: r = SSH_ERR_LIBCRYPTO_ERROR;
3474: goto out;
3475: }
3476: dsa_priv_key = NULL; /* transferred */
1.1 djm 3477: break;
3478: case KEY_ECDSA:
3479: if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
3480: r = SSH_ERR_INVALID_ARGUMENT;
3481: goto out;
3482: }
3483: if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
3484: goto out;
3485: if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
3486: r = SSH_ERR_EC_CURVE_MISMATCH;
3487: goto out;
3488: }
3489: k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
1.73 djm 3490: if (k->ecdsa == NULL) {
1.1 djm 3491: r = SSH_ERR_LIBCRYPTO_ERROR;
3492: goto out;
3493: }
1.108 djm 3494: if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0)
1.1 djm 3495: goto out;
1.108 djm 3496: /* FALLTHROUGH */
1.1 djm 3497: case KEY_ECDSA_CERT:
1.108 djm 3498: if ((r = sshbuf_get_bignum2(buf, &exponent)) != 0)
1.1 djm 3499: goto out;
3500: if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
3501: r = SSH_ERR_LIBCRYPTO_ERROR;
3502: goto out;
3503: }
3504: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
1.22 jsg 3505: EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
1.1 djm 3506: (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
3507: goto out;
3508: break;
1.85 djm 3509: case KEY_ECDSA_SK:
3510: if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
3511: r = SSH_ERR_INVALID_ARGUMENT;
3512: goto out;
3513: }
3514: if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
3515: goto out;
3516: if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
3517: r = SSH_ERR_EC_CURVE_MISMATCH;
3518: goto out;
3519: }
3520: if ((k->sk_key_handle = sshbuf_new()) == NULL ||
3521: (k->sk_reserved = sshbuf_new()) == NULL) {
3522: r = SSH_ERR_ALLOC_FAIL;
3523: goto out;
3524: }
3525: k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
3526: if (k->ecdsa == NULL) {
3527: r = SSH_ERR_LIBCRYPTO_ERROR;
3528: goto out;
3529: }
3530: if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
3531: (r = sshbuf_get_cstring(buf, &k->sk_application,
3532: NULL)) != 0 ||
3533: (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
3534: (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
3535: (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
3536: goto out;
3537: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
3538: EC_KEY_get0_public_key(k->ecdsa))) != 0)
3539: goto out;
3540: break;
3541: case KEY_ECDSA_SK_CERT:
3542: if ((k->sk_key_handle = sshbuf_new()) == NULL ||
3543: (k->sk_reserved = sshbuf_new()) == NULL) {
3544: r = SSH_ERR_ALLOC_FAIL;
3545: goto out;
3546: }
3547: if ((r = sshbuf_get_cstring(buf, &k->sk_application,
3548: NULL)) != 0 ||
3549: (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
3550: (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
3551: (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
3552: goto out;
3553: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
3554: EC_KEY_get0_public_key(k->ecdsa))) != 0)
3555: goto out;
3556: break;
1.1 djm 3557: case KEY_RSA:
1.73 djm 3558: if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 ||
1.108 djm 3559: (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0)
1.1 djm 3560: goto out;
1.108 djm 3561: if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, NULL)) {
1.69 djm 3562: r = SSH_ERR_LIBCRYPTO_ERROR;
3563: goto out;
3564: }
1.108 djm 3565: rsa_n = rsa_e = NULL; /* transferred */
3566: /* FALLTHROUGH */
1.1 djm 3567: case KEY_RSA_CERT:
1.108 djm 3568: if ((r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
1.73 djm 3569: (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
3570: (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
3571: (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
1.1 djm 3572: goto out;
1.69 djm 3573: if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) {
3574: r = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 3575: goto out;
3576: }
1.69 djm 3577: rsa_d = NULL; /* transferred */
3578: if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) {
3579: r = SSH_ERR_LIBCRYPTO_ERROR;
3580: goto out;
3581: }
3582: rsa_p = rsa_q = NULL; /* transferred */
3583: if ((r = check_rsa_length(k->rsa)) != 0)
3584: goto out;
3585: if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
3586: goto out;
1.1 djm 3587: break;
3588: #endif /* WITH_OPENSSL */
3589: case KEY_ED25519:
1.108 djm 3590: case KEY_ED25519_CERT:
1.1 djm 3591: if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3592: (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3593: goto out;
3594: if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3595: r = SSH_ERR_INVALID_FORMAT;
3596: goto out;
3597: }
3598: k->ed25519_pk = ed25519_pk;
3599: k->ed25519_sk = ed25519_sk;
1.84 djm 3600: ed25519_pk = ed25519_sk = NULL; /* transferred */
1.1 djm 3601: break;
1.90 markus 3602: case KEY_ED25519_SK:
1.108 djm 3603: case KEY_ED25519_SK_CERT:
1.90 markus 3604: if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0)
3605: goto out;
3606: if (pklen != ED25519_PK_SZ) {
3607: r = SSH_ERR_INVALID_FORMAT;
3608: goto out;
3609: }
3610: if ((k->sk_key_handle = sshbuf_new()) == NULL ||
3611: (k->sk_reserved = sshbuf_new()) == NULL) {
3612: r = SSH_ERR_ALLOC_FAIL;
3613: goto out;
3614: }
3615: if ((r = sshbuf_get_cstring(buf, &k->sk_application,
3616: NULL)) != 0 ||
3617: (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
3618: (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
3619: (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
3620: goto out;
3621: k->ed25519_pk = ed25519_pk;
3622: ed25519_pk = NULL; /* transferred */
3623: break;
1.62 markus 3624: #ifdef WITH_XMSS
3625: case KEY_XMSS:
1.108 djm 3626: case KEY_XMSS_CERT:
1.62 markus 3627: if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
3628: (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3629: (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
1.110 markus 3630: goto out;
3631: if (type == KEY_XMSS &&
3632: (r = sshkey_xmss_init(k, xmss_name)) != 0)
1.62 markus 3633: goto out;
3634: if (pklen != sshkey_xmss_pklen(k) ||
3635: sklen != sshkey_xmss_sklen(k)) {
3636: r = SSH_ERR_INVALID_FORMAT;
3637: goto out;
3638: }
3639: k->xmss_pk = xmss_pk;
3640: k->xmss_sk = xmss_sk;
3641: xmss_pk = xmss_sk = NULL;
3642: /* optional internal state */
3643: if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3644: goto out;
3645: break;
3646: #endif /* WITH_XMSS */
1.1 djm 3647: default:
3648: r = SSH_ERR_KEY_TYPE_UNKNOWN;
3649: goto out;
3650: }
3651: #ifdef WITH_OPENSSL
3652: /* enable blinding */
3653: switch (k->type) {
3654: case KEY_RSA:
3655: case KEY_RSA_CERT:
3656: if (RSA_blinding_on(k->rsa, NULL) != 1) {
3657: r = SSH_ERR_LIBCRYPTO_ERROR;
3658: goto out;
3659: }
3660: break;
3661: }
3662: #endif /* WITH_OPENSSL */
1.115 djm 3663: if ((expect_sk_application != NULL && (k->sk_application == NULL ||
3664: strcmp(expect_sk_application, k->sk_application) != 0)) ||
3665: (expect_ed25519_pk != NULL && (k->ed25519_pk == NULL ||
1.116 djm 3666: memcmp(expect_ed25519_pk, k->ed25519_pk, ED25519_PK_SZ) != 0))) {
1.115 djm 3667: r = SSH_ERR_KEY_CERT_MISMATCH;
3668: goto out;
3669: }
1.1 djm 3670: /* success */
3671: r = 0;
3672: if (kp != NULL) {
3673: *kp = k;
3674: k = NULL;
3675: }
3676: out:
3677: free(tname);
3678: free(curve);
3679: #ifdef WITH_OPENSSL
1.60 jsing 3680: BN_clear_free(exponent);
1.69 djm 3681: BN_clear_free(dsa_p);
3682: BN_clear_free(dsa_q);
3683: BN_clear_free(dsa_g);
3684: BN_clear_free(dsa_pub_key);
3685: BN_clear_free(dsa_priv_key);
3686: BN_clear_free(rsa_n);
3687: BN_clear_free(rsa_e);
3688: BN_clear_free(rsa_d);
3689: BN_clear_free(rsa_p);
3690: BN_clear_free(rsa_q);
3691: BN_clear_free(rsa_iqmp);
1.1 djm 3692: #endif /* WITH_OPENSSL */
3693: sshkey_free(k);
1.61 jsing 3694: freezero(ed25519_pk, pklen);
3695: freezero(ed25519_sk, sklen);
1.62 markus 3696: free(xmss_name);
3697: freezero(xmss_pk, pklen);
3698: freezero(xmss_sk, sklen);
1.115 djm 3699: free(expect_sk_application);
3700: free(expect_ed25519_pk);
1.1 djm 3701: return r;
3702: }
3703:
3704: #ifdef WITH_OPENSSL
3705: int
3706: sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
3707: {
3708: EC_POINT *nq = NULL;
1.93 djm 3709: BIGNUM *order = NULL, *x = NULL, *y = NULL, *tmp = NULL;
1.1 djm 3710: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
1.40 djm 3711:
3712: /*
3713: * NB. This assumes OpenSSL has already verified that the public
3714: * point lies on the curve. This is done by EC_POINT_oct2point()
3715: * implicitly calling EC_POINT_is_on_curve(). If this code is ever
3716: * reachable with public points not unmarshalled using
3717: * EC_POINT_oct2point then the caller will need to explicitly check.
3718: */
1.1 djm 3719:
3720: /*
3721: * We shouldn't ever hit this case because bignum_get_ecpoint()
3722: * refuses to load GF2m points.
3723: */
3724: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3725: NID_X9_62_prime_field)
3726: goto out;
3727:
3728: /* Q != infinity */
3729: if (EC_POINT_is_at_infinity(group, public))
3730: goto out;
3731:
1.93 djm 3732: if ((x = BN_new()) == NULL ||
3733: (y = BN_new()) == NULL ||
3734: (order = BN_new()) == NULL ||
3735: (tmp = BN_new()) == NULL) {
1.1 djm 3736: ret = SSH_ERR_ALLOC_FAIL;
3737: goto out;
3738: }
3739:
3740: /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
1.93 djm 3741: if (EC_GROUP_get_order(group, order, NULL) != 1 ||
1.1 djm 3742: EC_POINT_get_affine_coordinates_GFp(group, public,
1.93 djm 3743: x, y, NULL) != 1) {
1.1 djm 3744: ret = SSH_ERR_LIBCRYPTO_ERROR;
3745: goto out;
3746: }
3747: if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
3748: BN_num_bits(y) <= BN_num_bits(order) / 2)
3749: goto out;
3750:
3751: /* nQ == infinity (n == order of subgroup) */
3752: if ((nq = EC_POINT_new(group)) == NULL) {
3753: ret = SSH_ERR_ALLOC_FAIL;
3754: goto out;
3755: }
1.93 djm 3756: if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) {
1.1 djm 3757: ret = SSH_ERR_LIBCRYPTO_ERROR;
3758: goto out;
3759: }
3760: if (EC_POINT_is_at_infinity(group, nq) != 1)
3761: goto out;
3762:
3763: /* x < order - 1, y < order - 1 */
3764: if (!BN_sub(tmp, order, BN_value_one())) {
3765: ret = SSH_ERR_LIBCRYPTO_ERROR;
3766: goto out;
3767: }
3768: if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0)
3769: goto out;
3770: ret = 0;
3771: out:
1.93 djm 3772: BN_clear_free(x);
3773: BN_clear_free(y);
3774: BN_clear_free(order);
3775: BN_clear_free(tmp);
1.60 jsing 3776: EC_POINT_free(nq);
1.1 djm 3777: return ret;
3778: }
3779:
3780: int
3781: sshkey_ec_validate_private(const EC_KEY *key)
3782: {
1.93 djm 3783: BIGNUM *order = NULL, *tmp = NULL;
1.1 djm 3784: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
3785:
1.93 djm 3786: if ((order = BN_new()) == NULL || (tmp = BN_new()) == NULL) {
1.1 djm 3787: ret = SSH_ERR_ALLOC_FAIL;
3788: goto out;
3789: }
3790:
3791: /* log2(private) > log2(order)/2 */
1.93 djm 3792: if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, NULL) != 1) {
1.1 djm 3793: ret = SSH_ERR_LIBCRYPTO_ERROR;
3794: goto out;
3795: }
3796: if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
3797: BN_num_bits(order) / 2)
3798: goto out;
3799:
3800: /* private < order - 1 */
3801: if (!BN_sub(tmp, order, BN_value_one())) {
3802: ret = SSH_ERR_LIBCRYPTO_ERROR;
3803: goto out;
3804: }
3805: if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0)
3806: goto out;
3807: ret = 0;
3808: out:
1.93 djm 3809: BN_clear_free(order);
3810: BN_clear_free(tmp);
1.1 djm 3811: return ret;
3812: }
3813:
3814: void
3815: sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
3816: {
1.93 djm 3817: BIGNUM *x = NULL, *y = NULL;
1.1 djm 3818:
3819: if (point == NULL) {
3820: fputs("point=(NULL)\n", stderr);
3821: return;
3822: }
1.93 djm 3823: if ((x = BN_new()) == NULL || (y = BN_new()) == NULL) {
3824: fprintf(stderr, "%s: BN_new failed\n", __func__);
3825: goto out;
1.1 djm 3826: }
3827: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3828: NID_X9_62_prime_field) {
3829: fprintf(stderr, "%s: group is not a prime field\n", __func__);
1.93 djm 3830: goto out;
1.1 djm 3831: }
1.93 djm 3832: if (EC_POINT_get_affine_coordinates_GFp(group, point,
3833: x, y, NULL) != 1) {
1.1 djm 3834: fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
3835: __func__);
1.93 djm 3836: goto out;
1.1 djm 3837: }
3838: fputs("x=", stderr);
3839: BN_print_fp(stderr, x);
3840: fputs("\ny=", stderr);
3841: BN_print_fp(stderr, y);
3842: fputs("\n", stderr);
1.93 djm 3843: out:
3844: BN_clear_free(x);
3845: BN_clear_free(y);
1.1 djm 3846: }
3847:
3848: void
3849: sshkey_dump_ec_key(const EC_KEY *key)
3850: {
3851: const BIGNUM *exponent;
3852:
3853: sshkey_dump_ec_point(EC_KEY_get0_group(key),
3854: EC_KEY_get0_public_key(key));
3855: fputs("exponent=", stderr);
3856: if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
3857: fputs("(NULL)", stderr);
3858: else
3859: BN_print_fp(stderr, EC_KEY_get0_private_key(key));
3860: fputs("\n", stderr);
3861: }
3862: #endif /* WITH_OPENSSL */
3863:
3864: static int
1.76 djm 3865: sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob,
1.1 djm 3866: const char *passphrase, const char *comment, const char *ciphername,
3867: int rounds)
3868: {
1.4 djm 3869: u_char *cp, *key = NULL, *pubkeyblob = NULL;
1.1 djm 3870: u_char salt[SALT_LEN];
1.4 djm 3871: char *b64 = NULL;
1.1 djm 3872: size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
3873: u_int check;
3874: int r = SSH_ERR_INTERNAL_ERROR;
1.36 djm 3875: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 3876: const struct sshcipher *cipher;
3877: const char *kdfname = KDFNAME;
3878: struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
3879:
3880: if (rounds <= 0)
3881: rounds = DEFAULT_ROUNDS;
3882: if (passphrase == NULL || !strlen(passphrase)) {
3883: ciphername = "none";
3884: kdfname = "none";
3885: } else if (ciphername == NULL)
3886: ciphername = DEFAULT_CIPHERNAME;
1.47 djm 3887: if ((cipher = cipher_by_name(ciphername)) == NULL) {
1.1 djm 3888: r = SSH_ERR_INVALID_ARGUMENT;
3889: goto out;
3890: }
3891:
3892: if ((kdf = sshbuf_new()) == NULL ||
3893: (encoded = sshbuf_new()) == NULL ||
3894: (encrypted = sshbuf_new()) == NULL) {
3895: r = SSH_ERR_ALLOC_FAIL;
3896: goto out;
3897: }
3898: blocksize = cipher_blocksize(cipher);
3899: keylen = cipher_keylen(cipher);
3900: ivlen = cipher_ivlen(cipher);
3901: authlen = cipher_authlen(cipher);
3902: if ((key = calloc(1, keylen + ivlen)) == NULL) {
3903: r = SSH_ERR_ALLOC_FAIL;
3904: goto out;
3905: }
3906: if (strcmp(kdfname, "bcrypt") == 0) {
3907: arc4random_buf(salt, SALT_LEN);
3908: if (bcrypt_pbkdf(passphrase, strlen(passphrase),
3909: salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) {
3910: r = SSH_ERR_INVALID_ARGUMENT;
3911: goto out;
3912: }
3913: if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 ||
3914: (r = sshbuf_put_u32(kdf, rounds)) != 0)
3915: goto out;
3916: } else if (strcmp(kdfname, "none") != 0) {
3917: /* Unsupported KDF type */
3918: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3919: goto out;
3920: }
3921: if ((r = cipher_init(&ciphercontext, cipher, key, keylen,
3922: key + keylen, ivlen, 1)) != 0)
3923: goto out;
3924:
3925: if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 ||
3926: (r = sshbuf_put_cstring(encoded, ciphername)) != 0 ||
3927: (r = sshbuf_put_cstring(encoded, kdfname)) != 0 ||
3928: (r = sshbuf_put_stringb(encoded, kdf)) != 0 ||
3929: (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */
3930: (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 ||
3931: (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0)
3932: goto out;
3933:
3934: /* set up the buffer that will be encrypted */
3935:
3936: /* Random check bytes */
3937: check = arc4random();
3938: if ((r = sshbuf_put_u32(encrypted, check)) != 0 ||
3939: (r = sshbuf_put_u32(encrypted, check)) != 0)
3940: goto out;
3941:
3942: /* append private key and comment*/
1.62 markus 3943: if ((r = sshkey_private_serialize_opt(prv, encrypted,
1.116 djm 3944: SSHKEY_SERIALIZE_FULL)) != 0 ||
1.1 djm 3945: (r = sshbuf_put_cstring(encrypted, comment)) != 0)
3946: goto out;
3947:
3948: /* padding */
3949: i = 0;
3950: while (sshbuf_len(encrypted) % blocksize) {
3951: if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0)
3952: goto out;
3953: }
3954:
3955: /* length in destination buffer */
3956: if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0)
3957: goto out;
3958:
3959: /* encrypt */
3960: if ((r = sshbuf_reserve(encoded,
3961: sshbuf_len(encrypted) + authlen, &cp)) != 0)
3962: goto out;
1.36 djm 3963: if ((r = cipher_crypt(ciphercontext, 0, cp,
1.1 djm 3964: sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
3965: goto out;
3966:
1.81 djm 3967: sshbuf_reset(blob);
1.1 djm 3968:
1.81 djm 3969: /* assemble uuencoded key */
3970: if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0 ||
3971: (r = sshbuf_dtob64(encoded, blob, 1)) != 0 ||
3972: (r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
1.1 djm 3973: goto out;
3974:
3975: /* success */
3976: r = 0;
3977:
3978: out:
3979: sshbuf_free(kdf);
3980: sshbuf_free(encoded);
3981: sshbuf_free(encrypted);
1.36 djm 3982: cipher_free(ciphercontext);
1.1 djm 3983: explicit_bzero(salt, sizeof(salt));
1.100 jsg 3984: if (key != NULL)
3985: freezero(key, keylen + ivlen);
1.121 ! djm 3986: if (pubkeyblob != NULL)
1.100 jsg 3987: freezero(pubkeyblob, pubkeylen);
1.121 ! djm 3988: if (b64 != NULL)
1.100 jsg 3989: freezero(b64, strlen(b64));
1.1 djm 3990: return r;
3991: }
3992:
3993: static int
1.103 djm 3994: private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp)
1.1 djm 3995: {
3996: const u_char *cp;
3997: size_t encoded_len;
1.103 djm 3998: int r;
3999: u_char last;
1.1 djm 4000: struct sshbuf *encoded = NULL, *decoded = NULL;
4001:
1.103 djm 4002: if (blob == NULL || decodedp == NULL)
4003: return SSH_ERR_INVALID_ARGUMENT;
4004:
4005: *decodedp = NULL;
1.1 djm 4006:
4007: if ((encoded = sshbuf_new()) == NULL ||
1.103 djm 4008: (decoded = sshbuf_new()) == NULL) {
1.1 djm 4009: r = SSH_ERR_ALLOC_FAIL;
4010: goto out;
4011: }
4012:
4013: /* check preamble */
4014: cp = sshbuf_ptr(blob);
4015: encoded_len = sshbuf_len(blob);
4016: if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) ||
4017: memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) {
4018: r = SSH_ERR_INVALID_FORMAT;
4019: goto out;
4020: }
4021: cp += MARK_BEGIN_LEN;
4022: encoded_len -= MARK_BEGIN_LEN;
4023:
4024: /* Look for end marker, removing whitespace as we go */
4025: while (encoded_len > 0) {
4026: if (*cp != '\n' && *cp != '\r') {
4027: if ((r = sshbuf_put_u8(encoded, *cp)) != 0)
4028: goto out;
4029: }
4030: last = *cp;
4031: encoded_len--;
4032: cp++;
4033: if (last == '\n') {
4034: if (encoded_len >= MARK_END_LEN &&
4035: memcmp(cp, MARK_END, MARK_END_LEN) == 0) {
4036: /* \0 terminate */
4037: if ((r = sshbuf_put_u8(encoded, 0)) != 0)
4038: goto out;
4039: break;
4040: }
4041: }
4042: }
4043: if (encoded_len == 0) {
4044: r = SSH_ERR_INVALID_FORMAT;
4045: goto out;
4046: }
4047:
4048: /* decode base64 */
1.4 djm 4049: if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0)
1.1 djm 4050: goto out;
4051:
4052: /* check magic */
4053: if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) ||
4054: memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
4055: r = SSH_ERR_INVALID_FORMAT;
4056: goto out;
4057: }
1.103 djm 4058: /* success */
4059: *decodedp = decoded;
4060: decoded = NULL;
4061: r = 0;
4062: out:
4063: sshbuf_free(encoded);
4064: sshbuf_free(decoded);
4065: return r;
4066: }
4067:
4068: static int
1.104 djm 4069: private2_decrypt(struct sshbuf *decoded, const char *passphrase,
4070: struct sshbuf **decryptedp, struct sshkey **pubkeyp)
1.103 djm 4071: {
4072: char *ciphername = NULL, *kdfname = NULL;
4073: const struct sshcipher *cipher = NULL;
4074: int r = SSH_ERR_INTERNAL_ERROR;
4075: size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0;
4076: struct sshbuf *kdf = NULL, *decrypted = NULL;
4077: struct sshcipher_ctx *ciphercontext = NULL;
1.104 djm 4078: struct sshkey *pubkey = NULL;
1.103 djm 4079: u_char *key = NULL, *salt = NULL, *dp;
4080: u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
4081:
1.104 djm 4082: if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL)
1.103 djm 4083: return SSH_ERR_INVALID_ARGUMENT;
4084:
4085: *decryptedp = NULL;
1.104 djm 4086: *pubkeyp = NULL;
1.103 djm 4087:
4088: if ((decrypted = sshbuf_new()) == NULL) {
4089: r = SSH_ERR_ALLOC_FAIL;
4090: goto out;
4091: }
4092:
1.1 djm 4093: /* parse public portion of key */
4094: if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
4095: (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
4096: (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
4097: (r = sshbuf_froms(decoded, &kdf)) != 0 ||
1.103 djm 4098: (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
4099: goto out;
4100:
4101: if (nkeys != 1) {
4102: /* XXX only one key supported at present */
4103: r = SSH_ERR_INVALID_FORMAT;
4104: goto out;
4105: }
4106:
1.104 djm 4107: if ((r = sshkey_froms(decoded, &pubkey)) != 0 ||
1.1 djm 4108: (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
4109: goto out;
4110:
4111: if ((cipher = cipher_by_name(ciphername)) == NULL) {
4112: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
4113: goto out;
4114: }
4115: if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
4116: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
4117: goto out;
4118: }
1.101 markus 4119: if (strcmp(kdfname, "none") == 0 && strcmp(ciphername, "none") != 0) {
1.1 djm 4120: r = SSH_ERR_INVALID_FORMAT;
1.101 markus 4121: goto out;
4122: }
4123: if ((passphrase == NULL || strlen(passphrase) == 0) &&
4124: strcmp(kdfname, "none") != 0) {
4125: /* passphrase required */
4126: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
1.1 djm 4127: goto out;
4128: }
4129:
4130: /* check size of encrypted key blob */
4131: blocksize = cipher_blocksize(cipher);
4132: if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
4133: r = SSH_ERR_INVALID_FORMAT;
4134: goto out;
4135: }
4136:
4137: /* setup key */
4138: keylen = cipher_keylen(cipher);
4139: ivlen = cipher_ivlen(cipher);
1.18 djm 4140: authlen = cipher_authlen(cipher);
1.1 djm 4141: if ((key = calloc(1, keylen + ivlen)) == NULL) {
4142: r = SSH_ERR_ALLOC_FAIL;
4143: goto out;
4144: }
4145: if (strcmp(kdfname, "bcrypt") == 0) {
4146: if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 ||
4147: (r = sshbuf_get_u32(kdf, &rounds)) != 0)
4148: goto out;
4149: if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
4150: key, keylen + ivlen, rounds) < 0) {
4151: r = SSH_ERR_INVALID_FORMAT;
4152: goto out;
4153: }
4154: }
4155:
1.18 djm 4156: /* check that an appropriate amount of auth data is present */
1.84 djm 4157: if (sshbuf_len(decoded) < authlen ||
4158: sshbuf_len(decoded) - authlen < encrypted_len) {
1.18 djm 4159: r = SSH_ERR_INVALID_FORMAT;
4160: goto out;
4161: }
4162:
1.1 djm 4163: /* decrypt private portion of key */
4164: if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
4165: (r = cipher_init(&ciphercontext, cipher, key, keylen,
4166: key + keylen, ivlen, 0)) != 0)
4167: goto out;
1.36 djm 4168: if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
1.18 djm 4169: encrypted_len, 0, authlen)) != 0) {
1.1 djm 4170: /* an integrity error here indicates an incorrect passphrase */
4171: if (r == SSH_ERR_MAC_INVALID)
4172: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4173: goto out;
4174: }
1.18 djm 4175: if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
1.1 djm 4176: goto out;
4177: /* there should be no trailing data */
4178: if (sshbuf_len(decoded) != 0) {
4179: r = SSH_ERR_INVALID_FORMAT;
4180: goto out;
4181: }
4182:
4183: /* check check bytes */
4184: if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 ||
4185: (r = sshbuf_get_u32(decrypted, &check2)) != 0)
4186: goto out;
4187: if (check1 != check2) {
4188: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4189: goto out;
4190: }
1.103 djm 4191: /* success */
4192: *decryptedp = decrypted;
4193: decrypted = NULL;
1.104 djm 4194: *pubkeyp = pubkey;
4195: pubkey = NULL;
1.103 djm 4196: r = 0;
4197: out:
4198: cipher_free(ciphercontext);
4199: free(ciphername);
4200: free(kdfname);
1.104 djm 4201: sshkey_free(pubkey);
1.103 djm 4202: if (salt != NULL) {
4203: explicit_bzero(salt, slen);
4204: free(salt);
4205: }
4206: if (key != NULL) {
4207: explicit_bzero(key, keylen + ivlen);
4208: free(key);
4209: }
4210: sshbuf_free(kdf);
4211: sshbuf_free(decrypted);
4212: return r;
4213: }
4214:
4215: static int
4216: sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4217: struct sshkey **keyp, char **commentp)
4218: {
4219: char *comment = NULL;
4220: int r = SSH_ERR_INTERNAL_ERROR;
4221: struct sshbuf *decoded = NULL, *decrypted = NULL;
1.104 djm 4222: struct sshkey *k = NULL, *pubkey = NULL;
1.103 djm 4223:
4224: if (keyp != NULL)
4225: *keyp = NULL;
4226: if (commentp != NULL)
4227: *commentp = NULL;
4228:
4229: /* Undo base64 encoding and decrypt the private section */
4230: if ((r = private2_uudecode(blob, &decoded)) != 0 ||
1.104 djm 4231: (r = private2_decrypt(decoded, passphrase,
4232: &decrypted, &pubkey)) != 0)
1.103 djm 4233: goto out;
1.105 djm 4234:
4235: if (type != KEY_UNSPEC &&
4236: sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
4237: r = SSH_ERR_KEY_TYPE_MISMATCH;
4238: goto out;
4239: }
1.103 djm 4240:
4241: /* Load the private key and comment */
4242: if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
4243: (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
4244: goto out;
4245:
4246: /* Check deterministic padding after private section */
4247: if ((r = private2_check_padding(decrypted)) != 0)
4248: goto out;
1.1 djm 4249:
1.104 djm 4250: /* Check that the public key in the envelope matches the private key */
4251: if (!sshkey_equal(pubkey, k)) {
4252: r = SSH_ERR_INVALID_FORMAT;
4253: goto out;
4254: }
1.1 djm 4255:
4256: /* success */
4257: r = 0;
4258: if (keyp != NULL) {
4259: *keyp = k;
4260: k = NULL;
4261: }
4262: if (commentp != NULL) {
4263: *commentp = comment;
4264: comment = NULL;
4265: }
4266: out:
4267: free(comment);
4268: sshbuf_free(decoded);
4269: sshbuf_free(decrypted);
4270: sshkey_free(k);
1.104 djm 4271: sshkey_free(pubkey);
1.1 djm 4272: return r;
4273: }
4274:
1.107 djm 4275: static int
4276: sshkey_parse_private2_pubkey(struct sshbuf *blob, int type,
4277: struct sshkey **keyp)
4278: {
4279: int r = SSH_ERR_INTERNAL_ERROR;
4280: struct sshbuf *decoded = NULL;
4281: struct sshkey *pubkey = NULL;
4282: u_int nkeys = 0;
4283:
4284: if (keyp != NULL)
4285: *keyp = NULL;
4286:
4287: if ((r = private2_uudecode(blob, &decoded)) != 0)
4288: goto out;
4289: /* parse public key from unencrypted envelope */
4290: if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
4291: (r = sshbuf_skip_string(decoded)) != 0 || /* cipher */
4292: (r = sshbuf_skip_string(decoded)) != 0 || /* KDF alg */
4293: (r = sshbuf_skip_string(decoded)) != 0 || /* KDF hint */
4294: (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
4295: goto out;
4296:
4297: if (nkeys != 1) {
4298: /* XXX only one key supported at present */
4299: r = SSH_ERR_INVALID_FORMAT;
4300: goto out;
4301: }
4302:
4303: /* Parse the public key */
4304: if ((r = sshkey_froms(decoded, &pubkey)) != 0)
4305: goto out;
4306:
4307: if (type != KEY_UNSPEC &&
4308: sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
4309: r = SSH_ERR_KEY_TYPE_MISMATCH;
4310: goto out;
4311: }
4312:
4313: /* success */
4314: r = 0;
4315: if (keyp != NULL) {
4316: *keyp = pubkey;
4317: pubkey = NULL;
4318: }
4319: out:
4320: sshbuf_free(decoded);
4321: sshkey_free(pubkey);
4322: return r;
4323: }
4324:
1.1 djm 4325: #ifdef WITH_OPENSSL
1.80 djm 4326: /* convert SSH v2 key to PEM or PKCS#8 format */
1.1 djm 4327: static int
1.80 djm 4328: sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
4329: int format, const char *_passphrase, const char *comment)
1.1 djm 4330: {
1.76 djm 4331: int was_shielded = sshkey_is_shielded(key);
1.1 djm 4332: int success, r;
4333: int blen, len = strlen(_passphrase);
4334: u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
4335: const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
1.57 djm 4336: char *bptr;
1.1 djm 4337: BIO *bio = NULL;
1.76 djm 4338: struct sshbuf *blob;
1.80 djm 4339: EVP_PKEY *pkey = NULL;
1.1 djm 4340:
4341: if (len > 0 && len <= 4)
4342: return SSH_ERR_PASSPHRASE_TOO_SHORT;
1.76 djm 4343: if ((blob = sshbuf_new()) == NULL)
1.1 djm 4344: return SSH_ERR_ALLOC_FAIL;
1.76 djm 4345: if ((bio = BIO_new(BIO_s_mem())) == NULL) {
1.80 djm 4346: r = SSH_ERR_ALLOC_FAIL;
4347: goto out;
4348: }
4349: if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
4350: r = SSH_ERR_ALLOC_FAIL;
4351: goto out;
1.76 djm 4352: }
4353: if ((r = sshkey_unshield_private(key)) != 0)
4354: goto out;
1.1 djm 4355:
4356: switch (key->type) {
4357: case KEY_DSA:
1.80 djm 4358: if (format == SSHKEY_PRIVATE_PEM) {
4359: success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
4360: cipher, passphrase, len, NULL, NULL);
4361: } else {
4362: success = EVP_PKEY_set1_DSA(pkey, key->dsa);
4363: }
1.1 djm 4364: break;
4365: case KEY_ECDSA:
1.80 djm 4366: if (format == SSHKEY_PRIVATE_PEM) {
4367: success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
4368: cipher, passphrase, len, NULL, NULL);
4369: } else {
4370: success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
4371: }
1.1 djm 4372: break;
4373: case KEY_RSA:
1.80 djm 4374: if (format == SSHKEY_PRIVATE_PEM) {
4375: success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
4376: cipher, passphrase, len, NULL, NULL);
4377: } else {
4378: success = EVP_PKEY_set1_RSA(pkey, key->rsa);
4379: }
1.1 djm 4380: break;
4381: default:
4382: success = 0;
4383: break;
4384: }
4385: if (success == 0) {
4386: r = SSH_ERR_LIBCRYPTO_ERROR;
4387: goto out;
4388: }
1.80 djm 4389: if (format == SSHKEY_PRIVATE_PKCS8) {
4390: if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher,
4391: passphrase, len, NULL, NULL)) == 0) {
4392: r = SSH_ERR_LIBCRYPTO_ERROR;
4393: goto out;
4394: }
4395: }
1.1 djm 4396: if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
4397: r = SSH_ERR_INTERNAL_ERROR;
4398: goto out;
4399: }
4400: if ((r = sshbuf_put(blob, bptr, blen)) != 0)
4401: goto out;
4402: r = 0;
4403: out:
1.76 djm 4404: if (was_shielded)
4405: r = sshkey_shield_private(key);
4406: if (r == 0)
4407: r = sshbuf_putb(buf, blob);
1.80 djm 4408:
4409: EVP_PKEY_free(pkey);
1.76 djm 4410: sshbuf_free(blob);
1.1 djm 4411: BIO_free(bio);
4412: return r;
4413: }
4414: #endif /* WITH_OPENSSL */
4415:
4416: /* Serialise "key" to buffer "blob" */
4417: int
4418: sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
4419: const char *passphrase, const char *comment,
1.80 djm 4420: int format, const char *openssh_format_cipher, int openssh_format_rounds)
1.1 djm 4421: {
4422: switch (key->type) {
1.9 markus 4423: #ifdef WITH_OPENSSL
1.1 djm 4424: case KEY_DSA:
4425: case KEY_ECDSA:
4426: case KEY_RSA:
1.80 djm 4427: break; /* see below */
1.1 djm 4428: #endif /* WITH_OPENSSL */
4429: case KEY_ED25519:
1.90 markus 4430: case KEY_ED25519_SK:
1.62 markus 4431: #ifdef WITH_XMSS
4432: case KEY_XMSS:
4433: #endif /* WITH_XMSS */
1.85 djm 4434: #ifdef WITH_OPENSSL
4435: case KEY_ECDSA_SK:
4436: #endif /* WITH_OPENSSL */
1.1 djm 4437: return sshkey_private_to_blob2(key, blob, passphrase,
1.80 djm 4438: comment, openssh_format_cipher, openssh_format_rounds);
1.1 djm 4439: default:
4440: return SSH_ERR_KEY_TYPE_UNKNOWN;
4441: }
1.80 djm 4442:
4443: #ifdef WITH_OPENSSL
4444: switch (format) {
4445: case SSHKEY_PRIVATE_OPENSSH:
4446: return sshkey_private_to_blob2(key, blob, passphrase,
4447: comment, openssh_format_cipher, openssh_format_rounds);
4448: case SSHKEY_PRIVATE_PEM:
4449: case SSHKEY_PRIVATE_PKCS8:
4450: return sshkey_private_to_blob_pem_pkcs8(key, blob,
4451: format, passphrase, comment);
4452: default:
4453: return SSH_ERR_INVALID_ARGUMENT;
4454: }
4455: #endif /* WITH_OPENSSL */
1.1 djm 4456: }
4457:
4458: #ifdef WITH_OPENSSL
1.8 djm 4459: static int
1.52 djm 4460: translate_libcrypto_error(unsigned long pem_err)
4461: {
4462: int pem_reason = ERR_GET_REASON(pem_err);
4463:
4464: switch (ERR_GET_LIB(pem_err)) {
4465: case ERR_LIB_PEM:
4466: switch (pem_reason) {
4467: case PEM_R_BAD_PASSWORD_READ:
4468: case PEM_R_PROBLEMS_GETTING_PASSWORD:
4469: case PEM_R_BAD_DECRYPT:
4470: return SSH_ERR_KEY_WRONG_PASSPHRASE;
4471: default:
4472: return SSH_ERR_INVALID_FORMAT;
4473: }
4474: case ERR_LIB_EVP:
4475: switch (pem_reason) {
4476: case EVP_R_BAD_DECRYPT:
4477: return SSH_ERR_KEY_WRONG_PASSPHRASE;
1.69 djm 4478: #ifdef EVP_R_BN_DECODE_ERROR
1.52 djm 4479: case EVP_R_BN_DECODE_ERROR:
1.69 djm 4480: #endif
1.52 djm 4481: case EVP_R_DECODE_ERROR:
4482: #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
4483: case EVP_R_PRIVATE_KEY_DECODE_ERROR:
4484: #endif
4485: return SSH_ERR_INVALID_FORMAT;
4486: default:
4487: return SSH_ERR_LIBCRYPTO_ERROR;
4488: }
4489: case ERR_LIB_ASN1:
4490: return SSH_ERR_INVALID_FORMAT;
4491: }
4492: return SSH_ERR_LIBCRYPTO_ERROR;
4493: }
4494:
4495: static void
4496: clear_libcrypto_errors(void)
4497: {
4498: while (ERR_get_error() != 0)
4499: ;
4500: }
4501:
4502: /*
4503: * Translate OpenSSL error codes to determine whether
4504: * passphrase is required/incorrect.
4505: */
4506: static int
4507: convert_libcrypto_error(void)
4508: {
4509: /*
4510: * Some password errors are reported at the beginning
4511: * of the error queue.
4512: */
4513: if (translate_libcrypto_error(ERR_peek_error()) ==
4514: SSH_ERR_KEY_WRONG_PASSPHRASE)
4515: return SSH_ERR_KEY_WRONG_PASSPHRASE;
4516: return translate_libcrypto_error(ERR_peek_last_error());
4517: }
4518:
4519: static int
1.1 djm 4520: sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
1.8 djm 4521: const char *passphrase, struct sshkey **keyp)
1.1 djm 4522: {
4523: EVP_PKEY *pk = NULL;
4524: struct sshkey *prv = NULL;
4525: BIO *bio = NULL;
4526: int r;
4527:
1.32 djm 4528: if (keyp != NULL)
4529: *keyp = NULL;
1.1 djm 4530:
4531: if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
4532: return SSH_ERR_ALLOC_FAIL;
4533: if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
4534: (int)sshbuf_len(blob)) {
4535: r = SSH_ERR_ALLOC_FAIL;
4536: goto out;
4537: }
4538:
1.52 djm 4539: clear_libcrypto_errors();
1.1 djm 4540: if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
4541: (char *)passphrase)) == NULL) {
1.116 djm 4542: /*
4543: * libcrypto may return various ASN.1 errors when attempting
4544: * to parse a key with an incorrect passphrase.
4545: * Treat all format errors as "incorrect passphrase" if a
4546: * passphrase was supplied.
4547: */
1.71 djm 4548: if (passphrase != NULL && *passphrase != '\0')
4549: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4550: else
4551: r = convert_libcrypto_error();
1.1 djm 4552: goto out;
4553: }
1.69 djm 4554: if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA &&
1.1 djm 4555: (type == KEY_UNSPEC || type == KEY_RSA)) {
4556: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
4557: r = SSH_ERR_ALLOC_FAIL;
4558: goto out;
4559: }
4560: prv->rsa = EVP_PKEY_get1_RSA(pk);
4561: prv->type = KEY_RSA;
4562: #ifdef DEBUG_PK
4563: RSA_print_fp(stderr, prv->rsa, 8);
4564: #endif
4565: if (RSA_blinding_on(prv->rsa, NULL) != 1) {
4566: r = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 4567: goto out;
4568: }
1.69 djm 4569: if ((r = check_rsa_length(prv->rsa)) != 0)
1.1 djm 4570: goto out;
1.69 djm 4571: } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
1.1 djm 4572: (type == KEY_UNSPEC || type == KEY_DSA)) {
4573: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
4574: r = SSH_ERR_ALLOC_FAIL;
4575: goto out;
4576: }
4577: prv->dsa = EVP_PKEY_get1_DSA(pk);
4578: prv->type = KEY_DSA;
4579: #ifdef DEBUG_PK
4580: DSA_print_fp(stderr, prv->dsa, 8);
4581: #endif
1.69 djm 4582: } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC &&
1.1 djm 4583: (type == KEY_UNSPEC || type == KEY_ECDSA)) {
4584: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
4585: r = SSH_ERR_ALLOC_FAIL;
4586: goto out;
4587: }
4588: prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
4589: prv->type = KEY_ECDSA;
4590: prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
4591: if (prv->ecdsa_nid == -1 ||
4592: sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
4593: sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
4594: EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
4595: sshkey_ec_validate_private(prv->ecdsa) != 0) {
4596: r = SSH_ERR_INVALID_FORMAT;
4597: goto out;
4598: }
4599: #ifdef DEBUG_PK
4600: if (prv != NULL && prv->ecdsa != NULL)
4601: sshkey_dump_ec_key(prv->ecdsa);
4602: #endif
4603: } else {
4604: r = SSH_ERR_INVALID_FORMAT;
4605: goto out;
4606: }
4607: r = 0;
1.32 djm 4608: if (keyp != NULL) {
4609: *keyp = prv;
4610: prv = NULL;
4611: }
1.1 djm 4612: out:
4613: BIO_free(bio);
1.60 jsing 4614: EVP_PKEY_free(pk);
1.30 mmcc 4615: sshkey_free(prv);
1.1 djm 4616: return r;
4617: }
4618: #endif /* WITH_OPENSSL */
4619:
4620: int
4621: sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
4622: const char *passphrase, struct sshkey **keyp, char **commentp)
4623: {
1.42 djm 4624: int r = SSH_ERR_INTERNAL_ERROR;
4625:
1.32 djm 4626: if (keyp != NULL)
4627: *keyp = NULL;
1.1 djm 4628: if (commentp != NULL)
4629: *commentp = NULL;
4630:
4631: switch (type) {
4632: case KEY_ED25519:
1.62 markus 4633: case KEY_XMSS:
1.106 djm 4634: /* No fallback for new-format-only keys */
1.1 djm 4635: return sshkey_parse_private2(blob, type, passphrase,
4636: keyp, commentp);
1.106 djm 4637: default:
1.42 djm 4638: r = sshkey_parse_private2(blob, type, passphrase, keyp,
4639: commentp);
1.106 djm 4640: /* Only fallback to PEM parser if a format error occurred. */
4641: if (r != SSH_ERR_INVALID_FORMAT)
1.42 djm 4642: return r;
1.1 djm 4643: #ifdef WITH_OPENSSL
1.8 djm 4644: return sshkey_parse_private_pem_fileblob(blob, type,
4645: passphrase, keyp);
1.1 djm 4646: #else
4647: return SSH_ERR_INVALID_FORMAT;
4648: #endif /* WITH_OPENSSL */
4649: }
4650: }
4651:
4652: int
4653: sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
1.23 tim 4654: struct sshkey **keyp, char **commentp)
1.1 djm 4655: {
4656: if (keyp != NULL)
4657: *keyp = NULL;
4658: if (commentp != NULL)
4659: *commentp = NULL;
4660:
1.23 tim 4661: return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
4662: passphrase, keyp, commentp);
1.96 djm 4663: }
4664:
4665: void
4666: sshkey_sig_details_free(struct sshkey_sig_details *details)
4667: {
4668: freezero(details, sizeof(*details));
1.107 djm 4669: }
4670:
4671: int
4672: sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type,
4673: struct sshkey **pubkeyp)
4674: {
4675: int r = SSH_ERR_INTERNAL_ERROR;
4676:
4677: if (pubkeyp != NULL)
4678: *pubkeyp = NULL;
4679: /* only new-format private keys bundle a public key inside */
4680: if ((r = sshkey_parse_private2_pubkey(blob, type, pubkeyp)) != 0)
4681: return r;
4682: return 0;
1.1 djm 4683: }
1.62 markus 4684:
4685: #ifdef WITH_XMSS
4686: /*
4687: * serialize the key with the current state and forward the state
4688: * maxsign times.
4689: */
4690: int
1.77 djm 4691: sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
1.112 dtucker 4692: u_int32_t maxsign, int printerror)
1.62 markus 4693: {
4694: int r, rupdate;
4695:
4696: if (maxsign == 0 ||
4697: sshkey_type_plain(k->type) != KEY_XMSS)
4698: return sshkey_private_serialize_opt(k, b,
4699: SSHKEY_SERIALIZE_DEFAULT);
1.112 dtucker 4700: if ((r = sshkey_xmss_get_state(k, printerror)) != 0 ||
1.62 markus 4701: (r = sshkey_private_serialize_opt(k, b,
4702: SSHKEY_SERIALIZE_STATE)) != 0 ||
4703: (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
4704: goto out;
4705: r = 0;
4706: out:
1.112 dtucker 4707: if ((rupdate = sshkey_xmss_update_state(k, printerror)) != 0) {
1.62 markus 4708: if (r == 0)
4709: r = rupdate;
4710: }
4711: return r;
4712: }
4713:
4714: u_int32_t
4715: sshkey_signatures_left(const struct sshkey *k)
4716: {
4717: if (sshkey_type_plain(k->type) == KEY_XMSS)
4718: return sshkey_xmss_signatures_left(k);
4719: return 0;
4720: }
4721:
4722: int
4723: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4724: {
4725: if (sshkey_type_plain(k->type) != KEY_XMSS)
4726: return SSH_ERR_INVALID_ARGUMENT;
4727: return sshkey_xmss_enable_maxsign(k, maxsign);
4728: }
4729:
4730: int
4731: sshkey_set_filename(struct sshkey *k, const char *filename)
4732: {
4733: if (k == NULL)
4734: return SSH_ERR_INVALID_ARGUMENT;
4735: if (sshkey_type_plain(k->type) != KEY_XMSS)
4736: return 0;
4737: if (filename == NULL)
4738: return SSH_ERR_INVALID_ARGUMENT;
4739: if ((k->xmss_filename = strdup(filename)) == NULL)
4740: return SSH_ERR_ALLOC_FAIL;
4741: return 0;
4742: }
4743: #else
4744: int
1.76 djm 4745: sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
1.112 dtucker 4746: u_int32_t maxsign, int printerror)
1.62 markus 4747: {
4748: return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
4749: }
4750:
4751: u_int32_t
4752: sshkey_signatures_left(const struct sshkey *k)
4753: {
4754: return 0;
4755: }
4756:
4757: int
4758: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4759: {
4760: return SSH_ERR_INVALID_ARGUMENT;
4761: }
4762:
4763: int
4764: sshkey_set_filename(struct sshkey *k, const char *filename)
4765: {
4766: if (k == NULL)
4767: return SSH_ERR_INVALID_ARGUMENT;
4768: return 0;
4769: }
4770: #endif /* WITH_XMSS */