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