Annotation of src/usr.bin/ssh/sshkey.c, Revision 1.116
1.116 ! djm 1: /* $OpenBSD: sshkey.c,v 1.115 2021/02/02 22:36:46 djm Exp $ */
1.1 djm 2: /*
3: * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4: * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
5: * Copyright (c) 2010,2011 Damien Miller. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: #include <sys/types.h>
1.7 djm 29: #include <netinet/in.h>
1.1 djm 30:
1.12 djm 31: #ifdef WITH_OPENSSL
1.1 djm 32: #include <openssl/evp.h>
33: #include <openssl/err.h>
34: #include <openssl/pem.h>
1.12 djm 35: #endif
1.1 djm 36:
37: #include "crypto_api.h"
38:
39: #include <errno.h>
40: #include <stdio.h>
41: #include <string.h>
42: #include <util.h>
1.13 deraadt 43: #include <limits.h>
1.7 djm 44: #include <resolv.h>
1.1 djm 45:
46: #include "ssh2.h"
47: #include "ssherr.h"
48: #include "misc.h"
49: #include "sshbuf.h"
50: #include "cipher.h"
51: #include "digest.h"
52: #define SSHKEY_INTERNAL
53: #include "sshkey.h"
1.11 djm 54: #include "match.h"
1.86 djm 55: #include "ssh-sk.h"
1.1 djm 56:
1.74 dtucker 57: #ifdef WITH_XMSS
58: #include "sshkey-xmss.h"
1.62 markus 59: #include "xmss_fast.h"
1.74 dtucker 60: #endif
1.62 markus 61:
1.1 djm 62: /* openssh private key file format */
63: #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
64: #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
65: #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
66: #define MARK_END_LEN (sizeof(MARK_END) - 1)
67: #define KDFNAME "bcrypt"
68: #define AUTH_MAGIC "openssh-key-v1"
69: #define SALT_LEN 16
1.56 djm 70: #define DEFAULT_CIPHERNAME "aes256-ctr"
1.1 djm 71: #define DEFAULT_ROUNDS 16
72:
73: /* Version identification string for SSH v1 identity files. */
74: #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
75:
1.76 djm 76: /*
77: * Constants relating to "shielding" support; protection of keys expected
78: * to remain in memory for long durations
79: */
80: #define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024)
81: #define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */
82: #define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512
83:
84: int sshkey_private_serialize_opt(struct sshkey *key,
1.62 markus 85: struct sshbuf *buf, enum sshkey_serialize_rep);
1.14 djm 86: static int sshkey_from_blob_internal(struct sshbuf *buf,
1.1 djm 87: struct sshkey **keyp, int allow_cert);
88:
89: /* Supported key types */
90: struct keytype {
91: const char *name;
92: const char *shortname;
1.65 djm 93: const char *sigalg;
1.1 djm 94: int type;
95: int nid;
96: int cert;
1.28 markus 97: int sigonly;
1.1 djm 98: };
99: static const struct keytype keytypes[] = {
1.65 djm 100: { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
101: { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
1.28 markus 102: KEY_ED25519_CERT, 0, 1, 0 },
1.90 markus 103: { "sk-ssh-ed25519@openssh.com", "ED25519-SK", NULL,
104: KEY_ED25519_SK, 0, 0, 0 },
105: { "sk-ssh-ed25519-cert-v01@openssh.com", "ED25519-SK-CERT", NULL,
106: KEY_ED25519_SK_CERT, 0, 1, 0 },
1.62 markus 107: #ifdef WITH_XMSS
1.65 djm 108: { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
109: { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
1.62 markus 110: KEY_XMSS_CERT, 0, 1, 0 },
111: #endif /* WITH_XMSS */
1.1 djm 112: #ifdef WITH_OPENSSL
1.65 djm 113: { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
114: { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
115: { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
116: { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
117: { "ecdsa-sha2-nistp256", "ECDSA", NULL,
118: KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
119: { "ecdsa-sha2-nistp384", "ECDSA", NULL,
120: KEY_ECDSA, NID_secp384r1, 0, 0 },
121: { "ecdsa-sha2-nistp521", "ECDSA", NULL,
122: KEY_ECDSA, NID_secp521r1, 0, 0 },
1.85 djm 123: { "sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL,
124: KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 0 },
1.109 djm 125: { "webauthn-sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL,
126: KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 1 },
1.65 djm 127: { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
128: KEY_RSA_CERT, 0, 1, 0 },
129: { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
1.72 djm 130: "rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
1.65 djm 131: { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
1.72 djm 132: "rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
1.65 djm 133: { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
134: KEY_DSA_CERT, 0, 1, 0 },
135: { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
1.28 markus 136: KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
1.65 djm 137: { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
1.28 markus 138: KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
1.65 djm 139: { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
1.116 ! djm 140: KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
1.85 djm 141: { "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-SK-CERT", NULL,
142: KEY_ECDSA_SK_CERT, NID_X9_62_prime256v1, 1, 0 },
1.1 djm 143: #endif /* WITH_OPENSSL */
1.65 djm 144: { NULL, NULL, NULL, -1, -1, 0, 0 }
1.1 djm 145: };
146:
147: const char *
148: sshkey_type(const struct sshkey *k)
149: {
150: const struct keytype *kt;
151:
152: for (kt = keytypes; kt->type != -1; kt++) {
153: if (kt->type == k->type)
154: return kt->shortname;
155: }
156: return "unknown";
157: }
158:
159: static const char *
160: sshkey_ssh_name_from_type_nid(int type, int nid)
161: {
162: const struct keytype *kt;
163:
164: for (kt = keytypes; kt->type != -1; kt++) {
165: if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
166: return kt->name;
167: }
168: return "ssh-unknown";
169: }
170:
171: int
172: sshkey_type_is_cert(int type)
173: {
174: const struct keytype *kt;
175:
176: for (kt = keytypes; kt->type != -1; kt++) {
177: if (kt->type == type)
178: return kt->cert;
179: }
180: return 0;
181: }
182:
183: const char *
184: sshkey_ssh_name(const struct sshkey *k)
185: {
186: return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
187: }
188:
189: const char *
190: sshkey_ssh_name_plain(const struct sshkey *k)
191: {
192: return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type),
193: k->ecdsa_nid);
194: }
195:
196: int
197: sshkey_type_from_name(const char *name)
198: {
199: const struct keytype *kt;
200:
201: for (kt = keytypes; kt->type != -1; kt++) {
202: /* Only allow shortname matches for plain key types */
203: if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
204: (!kt->cert && strcasecmp(kt->shortname, name) == 0))
205: return kt->type;
206: }
207: return KEY_UNSPEC;
208: }
209:
1.85 djm 210: static int
211: key_type_is_ecdsa_variant(int type)
212: {
213: switch (type) {
214: case KEY_ECDSA:
215: case KEY_ECDSA_CERT:
216: case KEY_ECDSA_SK:
217: case KEY_ECDSA_SK_CERT:
218: return 1;
219: }
220: return 0;
221: }
222:
1.1 djm 223: int
224: sshkey_ecdsa_nid_from_name(const char *name)
225: {
226: const struct keytype *kt;
227:
1.4 djm 228: for (kt = keytypes; kt->type != -1; kt++) {
1.85 djm 229: if (!key_type_is_ecdsa_variant(kt->type))
1.4 djm 230: continue;
231: if (kt->name != NULL && strcmp(name, kt->name) == 0)
232: return kt->nid;
233: }
1.1 djm 234: return -1;
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: }
1278:
1.1 djm 1279:
1.63 djm 1280: /* XXX this can now be made const char * */
1.1 djm 1281: int
1282: sshkey_read(struct sshkey *ret, char **cpp)
1283: {
1284: struct sshkey *k;
1.63 djm 1285: char *cp, *blobcopy;
1286: size_t space;
1.1 djm 1287: int r, type, curve_nid = -1;
1288: struct sshbuf *blob;
1.44 dtucker 1289:
1290: if (ret == NULL)
1291: return SSH_ERR_INVALID_ARGUMENT;
1.1 djm 1292:
1293: switch (ret->type) {
1294: case KEY_UNSPEC:
1295: case KEY_RSA:
1296: case KEY_DSA:
1297: case KEY_ECDSA:
1.85 djm 1298: case KEY_ECDSA_SK:
1.1 djm 1299: case KEY_ED25519:
1.90 markus 1300: case KEY_ED25519_SK:
1.1 djm 1301: case KEY_DSA_CERT:
1302: case KEY_ECDSA_CERT:
1.85 djm 1303: case KEY_ECDSA_SK_CERT:
1.1 djm 1304: case KEY_RSA_CERT:
1305: case KEY_ED25519_CERT:
1.90 markus 1306: case KEY_ED25519_SK_CERT:
1.62 markus 1307: #ifdef WITH_XMSS
1308: case KEY_XMSS:
1309: case KEY_XMSS_CERT:
1310: #endif /* WITH_XMSS */
1.63 djm 1311: break; /* ok */
1312: default:
1313: return SSH_ERR_INVALID_ARGUMENT;
1314: }
1315:
1316: /* Decode type */
1317: cp = *cpp;
1318: space = strcspn(cp, " \t");
1319: if (space == strlen(cp))
1320: return SSH_ERR_INVALID_FORMAT;
1321: if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC)
1322: return SSH_ERR_INVALID_FORMAT;
1323:
1324: /* skip whitespace */
1325: for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1326: ;
1327: if (*cp == '\0')
1328: return SSH_ERR_INVALID_FORMAT;
1329: if (ret->type != KEY_UNSPEC && ret->type != type)
1330: return SSH_ERR_KEY_TYPE_MISMATCH;
1331: if ((blob = sshbuf_new()) == NULL)
1332: return SSH_ERR_ALLOC_FAIL;
1333:
1334: /* find end of keyblob and decode */
1335: space = strcspn(cp, " \t");
1336: if ((blobcopy = strndup(cp, space)) == NULL) {
1337: sshbuf_free(blob);
1338: return SSH_ERR_ALLOC_FAIL;
1339: }
1340: if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) {
1341: free(blobcopy);
1342: sshbuf_free(blob);
1343: return r;
1344: }
1345: free(blobcopy);
1346: if ((r = sshkey_fromb(blob, &k)) != 0) {
1.1 djm 1347: sshbuf_free(blob);
1.63 djm 1348: return r;
1349: }
1350: sshbuf_free(blob);
1351:
1352: /* skip whitespace and leave cp at start of comment */
1353: for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1354: ;
1355:
1356: /* ensure type of blob matches type at start of line */
1357: if (k->type != type) {
1358: sshkey_free(k);
1359: return SSH_ERR_KEY_TYPE_MISMATCH;
1360: }
1.85 djm 1361: if (key_type_is_ecdsa_variant(type) && curve_nid != k->ecdsa_nid) {
1.63 djm 1362: sshkey_free(k);
1363: return SSH_ERR_EC_CURVE_MISMATCH;
1364: }
1365:
1366: /* Fill in ret from parsed key */
1367: ret->type = type;
1368: if (sshkey_is_cert(ret)) {
1369: if (!sshkey_is_cert(k)) {
1.1 djm 1370: sshkey_free(k);
1.63 djm 1371: return SSH_ERR_EXPECTED_CERT;
1.1 djm 1372: }
1.63 djm 1373: if (ret->cert != NULL)
1374: cert_free(ret->cert);
1375: ret->cert = k->cert;
1376: k->cert = NULL;
1377: }
1378: switch (sshkey_type_plain(ret->type)) {
1.1 djm 1379: #ifdef WITH_OPENSSL
1.63 djm 1380: case KEY_RSA:
1381: RSA_free(ret->rsa);
1382: ret->rsa = k->rsa;
1383: k->rsa = NULL;
1.1 djm 1384: #ifdef DEBUG_PK
1.63 djm 1385: RSA_print_fp(stderr, ret->rsa, 8);
1.1 djm 1386: #endif
1.63 djm 1387: break;
1388: case KEY_DSA:
1389: DSA_free(ret->dsa);
1390: ret->dsa = k->dsa;
1391: k->dsa = NULL;
1.1 djm 1392: #ifdef DEBUG_PK
1.63 djm 1393: DSA_print_fp(stderr, ret->dsa, 8);
1.1 djm 1394: #endif
1.63 djm 1395: break;
1396: case KEY_ECDSA:
1397: EC_KEY_free(ret->ecdsa);
1398: ret->ecdsa = k->ecdsa;
1399: ret->ecdsa_nid = k->ecdsa_nid;
1400: k->ecdsa = NULL;
1401: k->ecdsa_nid = -1;
1.1 djm 1402: #ifdef DEBUG_PK
1.63 djm 1403: sshkey_dump_ec_key(ret->ecdsa);
1.1 djm 1404: #endif
1.63 djm 1405: break;
1.85 djm 1406: case KEY_ECDSA_SK:
1407: EC_KEY_free(ret->ecdsa);
1408: ret->ecdsa = k->ecdsa;
1409: ret->ecdsa_nid = k->ecdsa_nid;
1410: ret->sk_application = k->sk_application;
1411: k->ecdsa = NULL;
1412: k->ecdsa_nid = -1;
1413: k->sk_application = NULL;
1414: #ifdef DEBUG_PK
1415: sshkey_dump_ec_key(ret->ecdsa);
1416: fprintf(stderr, "App: %s\n", ret->sk_application);
1417: #endif
1418: break;
1.1 djm 1419: #endif /* WITH_OPENSSL */
1.63 djm 1420: case KEY_ED25519:
1421: freezero(ret->ed25519_pk, ED25519_PK_SZ);
1422: ret->ed25519_pk = k->ed25519_pk;
1423: k->ed25519_pk = NULL;
1.1 djm 1424: #ifdef DEBUG_PK
1.63 djm 1425: /* XXX */
1.1 djm 1426: #endif
1.63 djm 1427: break;
1.90 markus 1428: case KEY_ED25519_SK:
1429: freezero(ret->ed25519_pk, ED25519_PK_SZ);
1430: ret->ed25519_pk = k->ed25519_pk;
1431: ret->sk_application = k->sk_application;
1432: k->ed25519_pk = NULL;
1433: k->sk_application = NULL;
1434: break;
1.62 markus 1435: #ifdef WITH_XMSS
1.63 djm 1436: case KEY_XMSS:
1437: free(ret->xmss_pk);
1438: ret->xmss_pk = k->xmss_pk;
1439: k->xmss_pk = NULL;
1440: free(ret->xmss_state);
1441: ret->xmss_state = k->xmss_state;
1442: k->xmss_state = NULL;
1443: free(ret->xmss_name);
1444: ret->xmss_name = k->xmss_name;
1445: k->xmss_name = NULL;
1446: free(ret->xmss_filename);
1447: ret->xmss_filename = k->xmss_filename;
1448: k->xmss_filename = NULL;
1.62 markus 1449: #ifdef DEBUG_PK
1.63 djm 1450: /* XXX */
1.62 markus 1451: #endif
1.63 djm 1452: break;
1.62 markus 1453: #endif /* WITH_XMSS */
1.63 djm 1454: default:
1.1 djm 1455: sshkey_free(k);
1.63 djm 1456: return SSH_ERR_INTERNAL_ERROR;
1.1 djm 1457: }
1.63 djm 1458: sshkey_free(k);
1459:
1460: /* success */
1461: *cpp = cp;
1462: return 0;
1.1 djm 1463: }
1464:
1465: int
1.19 djm 1466: sshkey_to_base64(const struct sshkey *key, char **b64p)
1.1 djm 1467: {
1.19 djm 1468: int r = SSH_ERR_INTERNAL_ERROR;
1469: struct sshbuf *b = NULL;
1.1 djm 1470: char *uu = NULL;
1.19 djm 1471:
1472: if (b64p != NULL)
1473: *b64p = NULL;
1474: if ((b = sshbuf_new()) == NULL)
1475: return SSH_ERR_ALLOC_FAIL;
1476: if ((r = sshkey_putb(key, b)) != 0)
1477: goto out;
1.81 djm 1478: if ((uu = sshbuf_dtob64_string(b, 0)) == NULL) {
1.19 djm 1479: r = SSH_ERR_ALLOC_FAIL;
1480: goto out;
1481: }
1482: /* Success */
1483: if (b64p != NULL) {
1484: *b64p = uu;
1485: uu = NULL;
1486: }
1487: r = 0;
1488: out:
1489: sshbuf_free(b);
1490: free(uu);
1491: return r;
1492: }
1493:
1.52 djm 1494: int
1.19 djm 1495: sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
1496: {
1497: int r = SSH_ERR_INTERNAL_ERROR;
1498: char *uu = NULL;
1499:
1.48 djm 1500: if ((r = sshkey_to_base64(key, &uu)) != 0)
1501: goto out;
1502: if ((r = sshbuf_putf(b, "%s %s",
1503: sshkey_ssh_name(key), uu)) != 0)
1504: goto out;
1.19 djm 1505: r = 0;
1506: out:
1507: free(uu);
1508: return r;
1509: }
1510:
1511: int
1512: sshkey_write(const struct sshkey *key, FILE *f)
1513: {
1514: struct sshbuf *b = NULL;
1515: int r = SSH_ERR_INTERNAL_ERROR;
1516:
1517: if ((b = sshbuf_new()) == NULL)
1518: return SSH_ERR_ALLOC_FAIL;
1519: if ((r = sshkey_format_text(key, b)) != 0)
1.1 djm 1520: goto out;
1521: if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) {
1522: if (feof(f))
1523: errno = EPIPE;
1.19 djm 1524: r = SSH_ERR_SYSTEM_ERROR;
1.1 djm 1525: goto out;
1526: }
1.19 djm 1527: /* Success */
1528: r = 0;
1.1 djm 1529: out:
1.19 djm 1530: sshbuf_free(b);
1531: return r;
1.1 djm 1532: }
1533:
1534: const char *
1535: sshkey_cert_type(const struct sshkey *k)
1536: {
1537: switch (k->cert->type) {
1538: case SSH2_CERT_TYPE_USER:
1539: return "user";
1540: case SSH2_CERT_TYPE_HOST:
1541: return "host";
1542: default:
1543: return "unknown";
1544: }
1545: }
1546:
1547: #ifdef WITH_OPENSSL
1548: static int
1549: rsa_generate_private_key(u_int bits, RSA **rsap)
1550: {
1551: RSA *private = NULL;
1552: BIGNUM *f4 = NULL;
1553: int ret = SSH_ERR_INTERNAL_ERROR;
1554:
1.49 djm 1555: if (rsap == NULL)
1556: return SSH_ERR_INVALID_ARGUMENT;
1557: if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
1.1 djm 1558: bits > SSHBUF_MAX_BIGNUM * 8)
1.49 djm 1559: return SSH_ERR_KEY_LENGTH;
1.1 djm 1560: *rsap = NULL;
1561: if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
1562: ret = SSH_ERR_ALLOC_FAIL;
1563: goto out;
1564: }
1565: if (!BN_set_word(f4, RSA_F4) ||
1566: !RSA_generate_key_ex(private, bits, f4, NULL)) {
1567: ret = SSH_ERR_LIBCRYPTO_ERROR;
1568: goto out;
1569: }
1570: *rsap = private;
1571: private = NULL;
1572: ret = 0;
1573: out:
1.60 jsing 1574: RSA_free(private);
1575: BN_free(f4);
1.1 djm 1576: return ret;
1577: }
1578:
1579: static int
1580: dsa_generate_private_key(u_int bits, DSA **dsap)
1581: {
1582: DSA *private;
1583: int ret = SSH_ERR_INTERNAL_ERROR;
1584:
1.49 djm 1585: if (dsap == NULL)
1.1 djm 1586: return SSH_ERR_INVALID_ARGUMENT;
1.49 djm 1587: if (bits != 1024)
1588: return SSH_ERR_KEY_LENGTH;
1.1 djm 1589: if ((private = DSA_new()) == NULL) {
1590: ret = SSH_ERR_ALLOC_FAIL;
1591: goto out;
1592: }
1593: *dsap = NULL;
1594: if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1595: NULL, NULL) || !DSA_generate_key(private)) {
1596: ret = SSH_ERR_LIBCRYPTO_ERROR;
1597: goto out;
1598: }
1599: *dsap = private;
1600: private = NULL;
1601: ret = 0;
1602: out:
1.60 jsing 1603: DSA_free(private);
1.1 djm 1604: return ret;
1605: }
1606:
1607: int
1608: sshkey_ecdsa_key_to_nid(EC_KEY *k)
1609: {
1610: EC_GROUP *eg;
1611: int nids[] = {
1612: NID_X9_62_prime256v1,
1613: NID_secp384r1,
1614: NID_secp521r1,
1615: -1
1616: };
1617: int nid;
1618: u_int i;
1619: const EC_GROUP *g = EC_KEY_get0_group(k);
1620:
1621: /*
1622: * The group may be stored in a ASN.1 encoded private key in one of two
1623: * ways: as a "named group", which is reconstituted by ASN.1 object ID
1624: * or explicit group parameters encoded into the key blob. Only the
1625: * "named group" case sets the group NID for us, but we can figure
1626: * it out for the other case by comparing against all the groups that
1627: * are supported.
1628: */
1629: if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1630: return nid;
1631: for (i = 0; nids[i] != -1; i++) {
1.93 djm 1632: if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
1.1 djm 1633: return -1;
1.93 djm 1634: if (EC_GROUP_cmp(g, eg, NULL) == 0)
1.1 djm 1635: break;
1636: EC_GROUP_free(eg);
1637: }
1638: if (nids[i] != -1) {
1639: /* Use the group with the NID attached */
1640: EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1641: if (EC_KEY_set_group(k, eg) != 1) {
1642: EC_GROUP_free(eg);
1643: return -1;
1644: }
1645: }
1646: return nids[i];
1647: }
1648:
1649: static int
1650: ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
1651: {
1652: EC_KEY *private;
1653: int ret = SSH_ERR_INTERNAL_ERROR;
1654:
1.50 djm 1655: if (nid == NULL || ecdsap == NULL)
1.1 djm 1656: return SSH_ERR_INVALID_ARGUMENT;
1.50 djm 1657: if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
1658: return SSH_ERR_KEY_LENGTH;
1.1 djm 1659: *ecdsap = NULL;
1660: if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
1661: ret = SSH_ERR_ALLOC_FAIL;
1662: goto out;
1663: }
1664: if (EC_KEY_generate_key(private) != 1) {
1665: ret = SSH_ERR_LIBCRYPTO_ERROR;
1666: goto out;
1667: }
1668: EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
1669: *ecdsap = private;
1670: private = NULL;
1671: ret = 0;
1672: out:
1.60 jsing 1673: EC_KEY_free(private);
1.1 djm 1674: return ret;
1675: }
1676: #endif /* WITH_OPENSSL */
1677:
1678: int
1679: sshkey_generate(int type, u_int bits, struct sshkey **keyp)
1680: {
1681: struct sshkey *k;
1682: int ret = SSH_ERR_INTERNAL_ERROR;
1683:
1684: if (keyp == NULL)
1685: return SSH_ERR_INVALID_ARGUMENT;
1686: *keyp = NULL;
1687: if ((k = sshkey_new(KEY_UNSPEC)) == NULL)
1688: return SSH_ERR_ALLOC_FAIL;
1689: switch (type) {
1690: case KEY_ED25519:
1691: if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL ||
1692: (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) {
1693: ret = SSH_ERR_ALLOC_FAIL;
1694: break;
1695: }
1696: crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
1697: ret = 0;
1698: break;
1.62 markus 1699: #ifdef WITH_XMSS
1700: case KEY_XMSS:
1701: ret = sshkey_xmss_generate_private_key(k, bits);
1702: break;
1703: #endif /* WITH_XMSS */
1.1 djm 1704: #ifdef WITH_OPENSSL
1705: case KEY_DSA:
1706: ret = dsa_generate_private_key(bits, &k->dsa);
1707: break;
1708: case KEY_ECDSA:
1709: ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid,
1710: &k->ecdsa);
1711: break;
1712: case KEY_RSA:
1713: ret = rsa_generate_private_key(bits, &k->rsa);
1714: break;
1715: #endif /* WITH_OPENSSL */
1716: default:
1717: ret = SSH_ERR_INVALID_ARGUMENT;
1718: }
1719: if (ret == 0) {
1720: k->type = type;
1721: *keyp = k;
1722: } else
1723: sshkey_free(k);
1724: return ret;
1725: }
1726:
1727: int
1728: sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
1729: {
1730: u_int i;
1731: const struct sshkey_cert *from;
1732: struct sshkey_cert *to;
1.67 djm 1733: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 1734:
1.67 djm 1735: if (to_key == NULL || (from = from_key->cert) == NULL)
1.1 djm 1736: return SSH_ERR_INVALID_ARGUMENT;
1737:
1.67 djm 1738: if ((to = cert_new()) == NULL)
1.1 djm 1739: return SSH_ERR_ALLOC_FAIL;
1740:
1.67 djm 1741: if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
1742: (r = sshbuf_putb(to->critical, from->critical)) != 0 ||
1743: (r = sshbuf_putb(to->extensions, from->extensions)) != 0)
1744: goto out;
1.1 djm 1745:
1746: to->serial = from->serial;
1747: to->type = from->type;
1748: if (from->key_id == NULL)
1749: to->key_id = NULL;
1.67 djm 1750: else if ((to->key_id = strdup(from->key_id)) == NULL) {
1751: r = SSH_ERR_ALLOC_FAIL;
1752: goto out;
1753: }
1.1 djm 1754: to->valid_after = from->valid_after;
1755: to->valid_before = from->valid_before;
1756: if (from->signature_key == NULL)
1757: to->signature_key = NULL;
1.67 djm 1758: else if ((r = sshkey_from_private(from->signature_key,
1.1 djm 1759: &to->signature_key)) != 0)
1.67 djm 1760: goto out;
1761: if (from->signature_type != NULL &&
1762: (to->signature_type = strdup(from->signature_type)) == NULL) {
1763: r = SSH_ERR_ALLOC_FAIL;
1764: goto out;
1765: }
1766: if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) {
1767: r = SSH_ERR_INVALID_ARGUMENT;
1768: goto out;
1769: }
1.1 djm 1770: if (from->nprincipals > 0) {
1771: if ((to->principals = calloc(from->nprincipals,
1.67 djm 1772: sizeof(*to->principals))) == NULL) {
1773: r = SSH_ERR_ALLOC_FAIL;
1774: goto out;
1775: }
1.1 djm 1776: for (i = 0; i < from->nprincipals; i++) {
1777: to->principals[i] = strdup(from->principals[i]);
1778: if (to->principals[i] == NULL) {
1779: to->nprincipals = i;
1.67 djm 1780: r = SSH_ERR_ALLOC_FAIL;
1781: goto out;
1.1 djm 1782: }
1783: }
1784: }
1785: to->nprincipals = from->nprincipals;
1.67 djm 1786:
1787: /* success */
1788: cert_free(to_key->cert);
1789: to_key->cert = to;
1790: to = NULL;
1791: r = 0;
1792: out:
1793: cert_free(to);
1794: return r;
1.1 djm 1795: }
1796:
1797: int
1798: sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1799: {
1800: struct sshkey *n = NULL;
1.69 djm 1801: int r = SSH_ERR_INTERNAL_ERROR;
1802: #ifdef WITH_OPENSSL
1803: const BIGNUM *rsa_n, *rsa_e;
1804: BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL;
1805: const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
1806: BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL;
1807: BIGNUM *dsa_pub_key_dup = NULL;
1808: #endif /* WITH_OPENSSL */
1.1 djm 1809:
1.24 djm 1810: *pkp = NULL;
1.85 djm 1811: if ((n = sshkey_new(k->type)) == NULL) {
1812: r = SSH_ERR_ALLOC_FAIL;
1813: goto out;
1814: }
1.1 djm 1815: switch (k->type) {
1816: #ifdef WITH_OPENSSL
1817: case KEY_DSA:
1818: case KEY_DSA_CERT:
1.69 djm 1819: DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
1820: DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
1821: if ((dsa_p_dup = BN_dup(dsa_p)) == NULL ||
1822: (dsa_q_dup = BN_dup(dsa_q)) == NULL ||
1823: (dsa_g_dup = BN_dup(dsa_g)) == NULL ||
1824: (dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) {
1825: r = SSH_ERR_ALLOC_FAIL;
1826: goto out;
1827: }
1828: if (!DSA_set0_pqg(n->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) {
1829: r = SSH_ERR_LIBCRYPTO_ERROR;
1830: goto out;
1.1 djm 1831: }
1.69 djm 1832: dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */
1833: if (!DSA_set0_key(n->dsa, dsa_pub_key_dup, NULL)) {
1834: r = SSH_ERR_LIBCRYPTO_ERROR;
1835: goto out;
1836: }
1837: dsa_pub_key_dup = NULL; /* transferred */
1838:
1.1 djm 1839: break;
1840: case KEY_ECDSA:
1841: case KEY_ECDSA_CERT:
1.85 djm 1842: case KEY_ECDSA_SK:
1843: case KEY_ECDSA_SK_CERT:
1.1 djm 1844: n->ecdsa_nid = k->ecdsa_nid;
1845: n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
1846: if (n->ecdsa == NULL) {
1.69 djm 1847: r = SSH_ERR_ALLOC_FAIL;
1848: goto out;
1.1 djm 1849: }
1850: if (EC_KEY_set_public_key(n->ecdsa,
1851: EC_KEY_get0_public_key(k->ecdsa)) != 1) {
1.69 djm 1852: r = SSH_ERR_LIBCRYPTO_ERROR;
1853: goto out;
1.1 djm 1854: }
1.85 djm 1855: if (k->type != KEY_ECDSA_SK && k->type != KEY_ECDSA_SK_CERT)
1856: break;
1857: /* Append security-key application string */
1858: if ((n->sk_application = strdup(k->sk_application)) == NULL)
1859: goto out;
1.1 djm 1860: break;
1861: case KEY_RSA:
1862: case KEY_RSA_CERT:
1.69 djm 1863: RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
1864: if ((rsa_n_dup = BN_dup(rsa_n)) == NULL ||
1865: (rsa_e_dup = BN_dup(rsa_e)) == NULL) {
1866: r = SSH_ERR_ALLOC_FAIL;
1867: goto out;
1868: }
1869: if (!RSA_set0_key(n->rsa, rsa_n_dup, rsa_e_dup, NULL)) {
1870: r = SSH_ERR_LIBCRYPTO_ERROR;
1871: goto out;
1872: }
1873: rsa_n_dup = rsa_e_dup = NULL; /* transferred */
1.1 djm 1874: break;
1875: #endif /* WITH_OPENSSL */
1876: case KEY_ED25519:
1877: case KEY_ED25519_CERT:
1.90 markus 1878: case KEY_ED25519_SK:
1879: case KEY_ED25519_SK_CERT:
1.1 djm 1880: if (k->ed25519_pk != NULL) {
1881: if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
1.69 djm 1882: r = SSH_ERR_ALLOC_FAIL;
1883: goto out;
1.1 djm 1884: }
1885: memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1886: }
1.90 markus 1887: if (k->type != KEY_ED25519_SK &&
1888: k->type != KEY_ED25519_SK_CERT)
1889: break;
1890: /* Append security-key application string */
1891: if ((n->sk_application = strdup(k->sk_application)) == NULL)
1892: goto out;
1.1 djm 1893: break;
1.62 markus 1894: #ifdef WITH_XMSS
1895: case KEY_XMSS:
1896: case KEY_XMSS_CERT:
1.69 djm 1897: if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0)
1898: goto out;
1.62 markus 1899: if (k->xmss_pk != NULL) {
1.92 markus 1900: u_int32_t left;
1.62 markus 1901: size_t pklen = sshkey_xmss_pklen(k);
1902: if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
1.69 djm 1903: r = SSH_ERR_INTERNAL_ERROR;
1904: goto out;
1.62 markus 1905: }
1906: if ((n->xmss_pk = malloc(pklen)) == NULL) {
1.69 djm 1907: r = SSH_ERR_ALLOC_FAIL;
1908: goto out;
1.62 markus 1909: }
1910: memcpy(n->xmss_pk, k->xmss_pk, pklen);
1.92 markus 1911: /* simulate number of signatures left on pubkey */
1912: left = sshkey_xmss_signatures_left(k);
1913: if (left)
1914: sshkey_xmss_enable_maxsign(n, left);
1.62 markus 1915: }
1916: break;
1917: #endif /* WITH_XMSS */
1.1 djm 1918: default:
1.69 djm 1919: r = SSH_ERR_KEY_TYPE_UNKNOWN;
1920: goto out;
1.1 djm 1921: }
1.69 djm 1922: if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0)
1923: goto out;
1924: /* success */
1.1 djm 1925: *pkp = n;
1.69 djm 1926: n = NULL;
1927: r = 0;
1928: out:
1929: sshkey_free(n);
1.83 djm 1930: #ifdef WITH_OPENSSL
1.69 djm 1931: BN_clear_free(rsa_n_dup);
1932: BN_clear_free(rsa_e_dup);
1933: BN_clear_free(dsa_p_dup);
1934: BN_clear_free(dsa_q_dup);
1935: BN_clear_free(dsa_g_dup);
1936: BN_clear_free(dsa_pub_key_dup);
1.83 djm 1937: #endif /* WITH_OPENSSL */
1.69 djm 1938:
1939: return r;
1.1 djm 1940: }
1941:
1.76 djm 1942: int
1943: sshkey_is_shielded(struct sshkey *k)
1944: {
1945: return k != NULL && k->shielded_private != NULL;
1946: }
1947:
1948: int
1949: sshkey_shield_private(struct sshkey *k)
1950: {
1951: struct sshbuf *prvbuf = NULL;
1952: u_char *prekey = NULL, *enc = NULL, keyiv[SSH_DIGEST_MAX_LENGTH];
1953: struct sshcipher_ctx *cctx = NULL;
1954: const struct sshcipher *cipher;
1955: size_t i, enclen = 0;
1956: struct sshkey *kswap = NULL, tmp;
1957: int r = SSH_ERR_INTERNAL_ERROR;
1958:
1959: #ifdef DEBUG_PK
1960: fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
1961: #endif
1962: if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
1963: r = SSH_ERR_INVALID_ARGUMENT;
1964: goto out;
1965: }
1966: if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
1967: ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
1968: r = SSH_ERR_INTERNAL_ERROR;
1969: goto out;
1970: }
1971:
1972: /* Prepare a random pre-key, and from it an ephemeral key */
1973: if ((prekey = malloc(SSHKEY_SHIELD_PREKEY_LEN)) == NULL) {
1974: r = SSH_ERR_ALLOC_FAIL;
1975: goto out;
1976: }
1977: arc4random_buf(prekey, SSHKEY_SHIELD_PREKEY_LEN);
1978: if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
1979: prekey, SSHKEY_SHIELD_PREKEY_LEN,
1980: keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
1981: goto out;
1982: #ifdef DEBUG_PK
1983: fprintf(stderr, "%s: key+iv\n", __func__);
1984: sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
1985: stderr);
1986: #endif
1987: if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
1988: keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 1)) != 0)
1989: goto out;
1990:
1991: /* Serialise and encrypt the private key using the ephemeral key */
1992: if ((prvbuf = sshbuf_new()) == NULL) {
1993: r = SSH_ERR_ALLOC_FAIL;
1994: goto out;
1995: }
1996: if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0)
1997: goto out;
1998: if ((r = sshkey_private_serialize_opt(k, prvbuf,
1.116 ! djm 1999: SSHKEY_SERIALIZE_SHIELD)) != 0)
1.76 djm 2000: goto out;
2001: /* pad to cipher blocksize */
2002: i = 0;
2003: while (sshbuf_len(prvbuf) % cipher_blocksize(cipher)) {
2004: if ((r = sshbuf_put_u8(prvbuf, ++i & 0xff)) != 0)
2005: goto out;
2006: }
2007: #ifdef DEBUG_PK
2008: fprintf(stderr, "%s: serialised\n", __func__);
2009: sshbuf_dump(prvbuf, stderr);
2010: #endif
2011: /* encrypt */
2012: enclen = sshbuf_len(prvbuf);
2013: if ((enc = malloc(enclen)) == NULL) {
2014: r = SSH_ERR_ALLOC_FAIL;
2015: goto out;
2016: }
2017: if ((r = cipher_crypt(cctx, 0, enc,
2018: sshbuf_ptr(prvbuf), sshbuf_len(prvbuf), 0, 0)) != 0)
2019: goto out;
2020: #ifdef DEBUG_PK
2021: fprintf(stderr, "%s: encrypted\n", __func__);
2022: sshbuf_dump_data(enc, enclen, stderr);
2023: #endif
2024:
2025: /* Make a scrubbed, public-only copy of our private key argument */
2026: if ((r = sshkey_from_private(k, &kswap)) != 0)
2027: goto out;
2028:
2029: /* Swap the private key out (it will be destroyed below) */
2030: tmp = *kswap;
2031: *kswap = *k;
2032: *k = tmp;
2033:
2034: /* Insert the shielded key into our argument */
2035: k->shielded_private = enc;
2036: k->shielded_len = enclen;
2037: k->shield_prekey = prekey;
2038: k->shield_prekey_len = SSHKEY_SHIELD_PREKEY_LEN;
2039: enc = prekey = NULL; /* transferred */
2040: enclen = 0;
1.99 djm 2041:
2042: /* preserve key fields that are required for correct operation */
2043: k->sk_flags = kswap->sk_flags;
1.76 djm 2044:
2045: /* success */
2046: r = 0;
2047:
2048: out:
2049: /* XXX behaviour on error - invalidate original private key? */
2050: cipher_free(cctx);
2051: explicit_bzero(keyiv, sizeof(keyiv));
2052: explicit_bzero(&tmp, sizeof(tmp));
1.78 djm 2053: freezero(enc, enclen);
1.76 djm 2054: freezero(prekey, SSHKEY_SHIELD_PREKEY_LEN);
2055: sshkey_free(kswap);
2056: sshbuf_free(prvbuf);
2057: return r;
2058: }
2059:
2060: int
2061: sshkey_unshield_private(struct sshkey *k)
2062: {
2063: struct sshbuf *prvbuf = NULL;
2064: u_char pad, *cp, keyiv[SSH_DIGEST_MAX_LENGTH];
2065: struct sshcipher_ctx *cctx = NULL;
2066: const struct sshcipher *cipher;
2067: size_t i;
2068: struct sshkey *kswap = NULL, tmp;
2069: int r = SSH_ERR_INTERNAL_ERROR;
2070:
2071: #ifdef DEBUG_PK
2072: fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
2073: #endif
2074: if (!sshkey_is_shielded(k))
2075: return 0; /* nothing to do */
2076:
2077: if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
2078: r = SSH_ERR_INVALID_ARGUMENT;
2079: goto out;
2080: }
2081: if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
2082: ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
2083: r = SSH_ERR_INTERNAL_ERROR;
2084: goto out;
2085: }
2086: /* check size of shielded key blob */
2087: if (k->shielded_len < cipher_blocksize(cipher) ||
2088: (k->shielded_len % cipher_blocksize(cipher)) != 0) {
2089: r = SSH_ERR_INVALID_FORMAT;
2090: goto out;
2091: }
2092:
2093: /* Calculate the ephemeral key from the prekey */
2094: if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
2095: k->shield_prekey, k->shield_prekey_len,
2096: keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
2097: goto out;
2098: if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
2099: keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 0)) != 0)
2100: goto out;
2101: #ifdef DEBUG_PK
2102: fprintf(stderr, "%s: key+iv\n", __func__);
2103: sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
2104: stderr);
2105: #endif
2106:
2107: /* Decrypt and parse the shielded private key using the ephemeral key */
2108: if ((prvbuf = sshbuf_new()) == NULL) {
2109: r = SSH_ERR_ALLOC_FAIL;
2110: goto out;
2111: }
2112: if ((r = sshbuf_reserve(prvbuf, k->shielded_len, &cp)) != 0)
2113: goto out;
2114: /* decrypt */
2115: #ifdef DEBUG_PK
2116: fprintf(stderr, "%s: encrypted\n", __func__);
2117: sshbuf_dump_data(k->shielded_private, k->shielded_len, stderr);
2118: #endif
2119: if ((r = cipher_crypt(cctx, 0, cp,
2120: k->shielded_private, k->shielded_len, 0, 0)) != 0)
2121: goto out;
2122: #ifdef DEBUG_PK
2123: fprintf(stderr, "%s: serialised\n", __func__);
2124: sshbuf_dump(prvbuf, stderr);
2125: #endif
2126: /* Parse private key */
2127: if ((r = sshkey_private_deserialize(prvbuf, &kswap)) != 0)
2128: goto out;
2129: /* Check deterministic padding */
2130: i = 0;
2131: while (sshbuf_len(prvbuf)) {
2132: if ((r = sshbuf_get_u8(prvbuf, &pad)) != 0)
2133: goto out;
2134: if (pad != (++i & 0xff)) {
2135: r = SSH_ERR_INVALID_FORMAT;
2136: goto out;
2137: }
2138: }
2139:
2140: /* Swap the parsed key back into place */
2141: tmp = *kswap;
2142: *kswap = *k;
2143: *k = tmp;
2144:
2145: /* success */
2146: r = 0;
2147:
2148: out:
2149: cipher_free(cctx);
2150: explicit_bzero(keyiv, sizeof(keyiv));
2151: explicit_bzero(&tmp, sizeof(tmp));
2152: sshkey_free(kswap);
2153: sshbuf_free(prvbuf);
2154: return r;
2155: }
2156:
1.1 djm 2157: static int
1.14 djm 2158: cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1.1 djm 2159: {
1.14 djm 2160: struct sshbuf *principals = NULL, *crit = NULL;
2161: struct sshbuf *exts = NULL, *ca = NULL;
2162: u_char *sig = NULL;
2163: size_t signed_len = 0, slen = 0, kidlen = 0;
1.1 djm 2164: int ret = SSH_ERR_INTERNAL_ERROR;
2165:
2166: /* Copy the entire key blob for verification and later serialisation */
1.14 djm 2167: if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0)
1.1 djm 2168: return ret;
2169:
1.20 djm 2170: /* Parse body of certificate up to signature */
2171: if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 ||
1.1 djm 2172: (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
2173: (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
1.4 djm 2174: (ret = sshbuf_froms(b, &principals)) != 0 ||
1.1 djm 2175: (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
2176: (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
1.4 djm 2177: (ret = sshbuf_froms(b, &crit)) != 0 ||
1.20 djm 2178: (ret = sshbuf_froms(b, &exts)) != 0 ||
1.1 djm 2179: (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
1.14 djm 2180: (ret = sshbuf_froms(b, &ca)) != 0) {
1.1 djm 2181: /* XXX debug print error for ret */
2182: ret = SSH_ERR_INVALID_FORMAT;
2183: goto out;
2184: }
2185:
2186: /* Signature is left in the buffer so we can calculate this length */
2187: signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b);
2188:
2189: if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) {
2190: ret = SSH_ERR_INVALID_FORMAT;
2191: goto out;
2192: }
2193:
2194: if (key->cert->type != SSH2_CERT_TYPE_USER &&
2195: key->cert->type != SSH2_CERT_TYPE_HOST) {
2196: ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE;
2197: goto out;
2198: }
2199:
1.4 djm 2200: /* Parse principals section */
2201: while (sshbuf_len(principals) > 0) {
2202: char *principal = NULL;
2203: char **oprincipals = NULL;
2204:
1.1 djm 2205: if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
2206: ret = SSH_ERR_INVALID_FORMAT;
2207: goto out;
2208: }
1.4 djm 2209: if ((ret = sshbuf_get_cstring(principals, &principal,
2210: NULL)) != 0) {
1.1 djm 2211: ret = SSH_ERR_INVALID_FORMAT;
2212: goto out;
2213: }
2214: oprincipals = key->cert->principals;
1.51 deraadt 2215: key->cert->principals = recallocarray(key->cert->principals,
2216: key->cert->nprincipals, key->cert->nprincipals + 1,
2217: sizeof(*key->cert->principals));
1.1 djm 2218: if (key->cert->principals == NULL) {
2219: free(principal);
2220: key->cert->principals = oprincipals;
2221: ret = SSH_ERR_ALLOC_FAIL;
2222: goto out;
2223: }
2224: key->cert->principals[key->cert->nprincipals++] = principal;
2225: }
2226:
1.4 djm 2227: /*
2228: * Stash a copies of the critical options and extensions sections
2229: * for later use.
2230: */
2231: if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 ||
2232: (exts != NULL &&
2233: (ret = sshbuf_putb(key->cert->extensions, exts)) != 0))
1.1 djm 2234: goto out;
2235:
1.4 djm 2236: /*
2237: * Validate critical options and extensions sections format.
2238: */
2239: while (sshbuf_len(crit) != 0) {
2240: if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
2241: (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) {
2242: sshbuf_reset(key->cert->critical);
1.1 djm 2243: ret = SSH_ERR_INVALID_FORMAT;
2244: goto out;
2245: }
2246: }
1.4 djm 2247: while (exts != NULL && sshbuf_len(exts) != 0) {
2248: if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 ||
2249: (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) {
2250: sshbuf_reset(key->cert->extensions);
1.1 djm 2251: ret = SSH_ERR_INVALID_FORMAT;
2252: goto out;
2253: }
2254: }
2255:
1.4 djm 2256: /* Parse CA key and check signature */
1.14 djm 2257: if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) {
1.1 djm 2258: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2259: goto out;
2260: }
2261: if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) {
2262: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2263: goto out;
2264: }
2265: if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1.96 djm 2266: sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0, NULL)) != 0)
1.1 djm 2267: goto out;
1.82 djm 2268: if ((ret = sshkey_get_sigtype(sig, slen,
2269: &key->cert->signature_type)) != 0)
1.67 djm 2270: goto out;
1.4 djm 2271:
2272: /* Success */
1.1 djm 2273: ret = 0;
2274: out:
1.14 djm 2275: sshbuf_free(ca);
1.4 djm 2276: sshbuf_free(crit);
2277: sshbuf_free(exts);
2278: sshbuf_free(principals);
1.1 djm 2279: free(sig);
2280: return ret;
2281: }
2282:
1.83 djm 2283: #ifdef WITH_OPENSSL
1.1 djm 2284: static int
1.69 djm 2285: check_rsa_length(const RSA *rsa)
2286: {
2287: const BIGNUM *rsa_n;
2288:
2289: RSA_get0_key(rsa, &rsa_n, NULL, NULL);
2290: if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
2291: return SSH_ERR_KEY_LENGTH;
2292: return 0;
2293: }
1.83 djm 2294: #endif /* WITH_OPENSSL */
1.69 djm 2295:
2296: static int
1.14 djm 2297: sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
2298: int allow_cert)
1.1 djm 2299: {
1.12 djm 2300: int type, ret = SSH_ERR_INTERNAL_ERROR;
1.62 markus 2301: char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
1.1 djm 2302: struct sshkey *key = NULL;
2303: size_t len;
2304: u_char *pk = NULL;
1.14 djm 2305: struct sshbuf *copy;
1.1 djm 2306: #ifdef WITH_OPENSSL
2307: EC_POINT *q = NULL;
1.69 djm 2308: BIGNUM *rsa_n = NULL, *rsa_e = NULL;
2309: BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
1.1 djm 2310: #endif /* WITH_OPENSSL */
2311:
2312: #ifdef DEBUG_PK /* XXX */
1.14 djm 2313: sshbuf_dump(b, stderr);
1.1 djm 2314: #endif
1.32 djm 2315: if (keyp != NULL)
2316: *keyp = NULL;
1.14 djm 2317: if ((copy = sshbuf_fromb(b)) == NULL) {
2318: ret = SSH_ERR_ALLOC_FAIL;
2319: goto out;
2320: }
1.1 djm 2321: if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
2322: ret = SSH_ERR_INVALID_FORMAT;
2323: goto out;
2324: }
2325:
2326: type = sshkey_type_from_name(ktype);
2327: if (!allow_cert && sshkey_type_is_cert(type)) {
2328: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2329: goto out;
2330: }
2331: switch (type) {
2332: #ifdef WITH_OPENSSL
2333: case KEY_RSA_CERT:
1.14 djm 2334: /* Skip nonce */
1.1 djm 2335: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2336: ret = SSH_ERR_INVALID_FORMAT;
2337: goto out;
2338: }
2339: /* FALLTHROUGH */
2340: case KEY_RSA:
2341: if ((key = sshkey_new(type)) == NULL) {
2342: ret = SSH_ERR_ALLOC_FAIL;
2343: goto out;
2344: }
1.73 djm 2345: if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
2346: sshbuf_get_bignum2(b, &rsa_n) != 0) {
1.1 djm 2347: ret = SSH_ERR_INVALID_FORMAT;
2348: goto out;
2349: }
1.69 djm 2350: if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
2351: ret = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 2352: goto out;
2353: }
1.69 djm 2354: rsa_n = rsa_e = NULL; /* transferred */
2355: if ((ret = check_rsa_length(key->rsa)) != 0)
2356: goto out;
1.1 djm 2357: #ifdef DEBUG_PK
2358: RSA_print_fp(stderr, key->rsa, 8);
2359: #endif
2360: break;
2361: case KEY_DSA_CERT:
1.14 djm 2362: /* Skip nonce */
1.1 djm 2363: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2364: ret = SSH_ERR_INVALID_FORMAT;
2365: goto out;
2366: }
2367: /* FALLTHROUGH */
2368: case KEY_DSA:
2369: if ((key = sshkey_new(type)) == NULL) {
2370: ret = SSH_ERR_ALLOC_FAIL;
2371: goto out;
2372: }
1.73 djm 2373: if (sshbuf_get_bignum2(b, &dsa_p) != 0 ||
2374: sshbuf_get_bignum2(b, &dsa_q) != 0 ||
2375: sshbuf_get_bignum2(b, &dsa_g) != 0 ||
2376: sshbuf_get_bignum2(b, &dsa_pub_key) != 0) {
1.1 djm 2377: ret = SSH_ERR_INVALID_FORMAT;
2378: goto out;
2379: }
1.69 djm 2380: if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) {
2381: ret = SSH_ERR_LIBCRYPTO_ERROR;
2382: goto out;
2383: }
2384: dsa_p = dsa_q = dsa_g = NULL; /* transferred */
2385: if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) {
2386: ret = SSH_ERR_LIBCRYPTO_ERROR;
2387: goto out;
2388: }
2389: dsa_pub_key = NULL; /* transferred */
1.1 djm 2390: #ifdef DEBUG_PK
2391: DSA_print_fp(stderr, key->dsa, 8);
2392: #endif
2393: break;
2394: case KEY_ECDSA_CERT:
1.85 djm 2395: case KEY_ECDSA_SK_CERT:
1.14 djm 2396: /* Skip nonce */
1.1 djm 2397: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2398: ret = SSH_ERR_INVALID_FORMAT;
2399: goto out;
2400: }
2401: /* FALLTHROUGH */
2402: case KEY_ECDSA:
1.85 djm 2403: case KEY_ECDSA_SK:
1.1 djm 2404: if ((key = sshkey_new(type)) == NULL) {
2405: ret = SSH_ERR_ALLOC_FAIL;
2406: goto out;
2407: }
1.12 djm 2408: key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
1.1 djm 2409: if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
2410: ret = SSH_ERR_INVALID_FORMAT;
2411: goto out;
2412: }
2413: if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
2414: ret = SSH_ERR_EC_CURVE_MISMATCH;
2415: goto out;
2416: }
1.60 jsing 2417: EC_KEY_free(key->ecdsa);
1.1 djm 2418: if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
2419: == NULL) {
2420: ret = SSH_ERR_EC_CURVE_INVALID;
2421: goto out;
2422: }
2423: if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
2424: ret = SSH_ERR_ALLOC_FAIL;
2425: goto out;
2426: }
2427: if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
2428: ret = SSH_ERR_INVALID_FORMAT;
2429: goto out;
2430: }
2431: if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
2432: q) != 0) {
2433: ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2434: goto out;
2435: }
2436: if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
2437: /* XXX assume it is a allocation error */
2438: ret = SSH_ERR_ALLOC_FAIL;
2439: goto out;
2440: }
2441: #ifdef DEBUG_PK
2442: sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
2443: #endif
1.85 djm 2444: if (type == KEY_ECDSA_SK || type == KEY_ECDSA_SK_CERT) {
2445: /* Parse additional security-key application string */
2446: if (sshbuf_get_cstring(b, &key->sk_application,
2447: NULL) != 0) {
2448: ret = SSH_ERR_INVALID_FORMAT;
2449: goto out;
2450: }
2451: #ifdef DEBUG_PK
2452: fprintf(stderr, "App: %s\n", key->sk_application);
2453: #endif
2454: }
1.1 djm 2455: break;
2456: #endif /* WITH_OPENSSL */
2457: case KEY_ED25519_CERT:
1.90 markus 2458: case KEY_ED25519_SK_CERT:
1.14 djm 2459: /* Skip nonce */
1.1 djm 2460: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2461: ret = SSH_ERR_INVALID_FORMAT;
2462: goto out;
2463: }
2464: /* FALLTHROUGH */
2465: case KEY_ED25519:
1.90 markus 2466: case KEY_ED25519_SK:
1.1 djm 2467: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2468: goto out;
2469: if (len != ED25519_PK_SZ) {
2470: ret = SSH_ERR_INVALID_FORMAT;
2471: goto out;
2472: }
2473: if ((key = sshkey_new(type)) == NULL) {
2474: ret = SSH_ERR_ALLOC_FAIL;
2475: goto out;
2476: }
1.90 markus 2477: if (type == KEY_ED25519_SK || type == KEY_ED25519_SK_CERT) {
2478: /* Parse additional security-key application string */
2479: if (sshbuf_get_cstring(b, &key->sk_application,
2480: NULL) != 0) {
2481: ret = SSH_ERR_INVALID_FORMAT;
2482: goto out;
2483: }
2484: #ifdef DEBUG_PK
2485: fprintf(stderr, "App: %s\n", key->sk_application);
2486: #endif
2487: }
1.1 djm 2488: key->ed25519_pk = pk;
2489: pk = NULL;
2490: break;
1.62 markus 2491: #ifdef WITH_XMSS
2492: case KEY_XMSS_CERT:
2493: /* Skip nonce */
2494: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2495: ret = SSH_ERR_INVALID_FORMAT;
2496: goto out;
2497: }
2498: /* FALLTHROUGH */
2499: case KEY_XMSS:
2500: if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
2501: goto out;
2502: if ((key = sshkey_new(type)) == NULL) {
2503: ret = SSH_ERR_ALLOC_FAIL;
2504: goto out;
2505: }
2506: if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
2507: goto out;
2508: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2509: goto out;
2510: if (len == 0 || len != sshkey_xmss_pklen(key)) {
2511: ret = SSH_ERR_INVALID_FORMAT;
2512: goto out;
2513: }
2514: key->xmss_pk = pk;
2515: pk = NULL;
2516: if (type != KEY_XMSS_CERT &&
2517: (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
2518: goto out;
2519: break;
2520: #endif /* WITH_XMSS */
1.1 djm 2521: case KEY_UNSPEC:
2522: default:
2523: ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2524: goto out;
2525: }
2526:
2527: /* Parse certificate potion */
1.14 djm 2528: if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
1.1 djm 2529: goto out;
2530:
2531: if (key != NULL && sshbuf_len(b) != 0) {
2532: ret = SSH_ERR_INVALID_FORMAT;
2533: goto out;
2534: }
2535: ret = 0;
1.32 djm 2536: if (keyp != NULL) {
2537: *keyp = key;
2538: key = NULL;
2539: }
1.1 djm 2540: out:
1.14 djm 2541: sshbuf_free(copy);
1.1 djm 2542: sshkey_free(key);
1.62 markus 2543: free(xmss_name);
1.1 djm 2544: free(ktype);
2545: free(curve);
2546: free(pk);
2547: #ifdef WITH_OPENSSL
1.60 jsing 2548: EC_POINT_free(q);
1.69 djm 2549: BN_clear_free(rsa_n);
2550: BN_clear_free(rsa_e);
2551: BN_clear_free(dsa_p);
2552: BN_clear_free(dsa_q);
2553: BN_clear_free(dsa_g);
2554: BN_clear_free(dsa_pub_key);
1.1 djm 2555: #endif /* WITH_OPENSSL */
2556: return ret;
2557: }
2558:
2559: int
2560: sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp)
2561: {
1.14 djm 2562: struct sshbuf *b;
2563: int r;
2564:
2565: if ((b = sshbuf_from(blob, blen)) == NULL)
2566: return SSH_ERR_ALLOC_FAIL;
2567: r = sshkey_from_blob_internal(b, keyp, 1);
2568: sshbuf_free(b);
2569: return r;
2570: }
2571:
2572: int
2573: sshkey_fromb(struct sshbuf *b, struct sshkey **keyp)
2574: {
2575: return sshkey_from_blob_internal(b, keyp, 1);
2576: }
2577:
2578: int
2579: sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2580: {
2581: struct sshbuf *b;
2582: int r;
2583:
2584: if ((r = sshbuf_froms(buf, &b)) != 0)
2585: return r;
2586: r = sshkey_from_blob_internal(b, keyp, 1);
1.58 djm 2587: sshbuf_free(b);
2588: return r;
2589: }
2590:
1.82 djm 2591: int
2592: sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
1.58 djm 2593: {
2594: int r;
2595: struct sshbuf *b = NULL;
2596: char *sigtype = NULL;
2597:
2598: if (sigtypep != NULL)
2599: *sigtypep = NULL;
2600: if ((b = sshbuf_from(sig, siglen)) == NULL)
2601: return SSH_ERR_ALLOC_FAIL;
2602: if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0)
2603: goto out;
2604: /* success */
2605: if (sigtypep != NULL) {
2606: *sigtypep = sigtype;
2607: sigtype = NULL;
2608: }
2609: r = 0;
2610: out:
2611: free(sigtype);
1.14 djm 2612: sshbuf_free(b);
2613: return r;
1.68 djm 2614: }
2615:
2616: /*
2617: *
2618: * Checks whether a certificate's signature type is allowed.
2619: * Returns 0 (success) if the certificate signature type appears in the
2620: * "allowed" pattern-list, or the key is not a certificate to begin with.
2621: * Otherwise returns a ssherr.h code.
2622: */
2623: int
2624: sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed)
2625: {
2626: if (key == NULL || allowed == NULL)
2627: return SSH_ERR_INVALID_ARGUMENT;
2628: if (!sshkey_type_is_cert(key->type))
2629: return 0;
2630: if (key->cert == NULL || key->cert->signature_type == NULL)
2631: return SSH_ERR_INVALID_ARGUMENT;
2632: if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1)
2633: return SSH_ERR_SIGN_ALG_UNSUPPORTED;
2634: return 0;
1.65 djm 2635: }
2636:
2637: /*
2638: * Returns the expected signature algorithm for a given public key algorithm.
2639: */
1.66 djm 2640: const char *
2641: sshkey_sigalg_by_name(const char *name)
1.65 djm 2642: {
2643: const struct keytype *kt;
2644:
2645: for (kt = keytypes; kt->type != -1; kt++) {
2646: if (strcmp(kt->name, name) != 0)
2647: continue;
2648: if (kt->sigalg != NULL)
2649: return kt->sigalg;
2650: if (!kt->cert)
2651: return kt->name;
2652: return sshkey_ssh_name_from_type_nid(
2653: sshkey_type_plain(kt->type), kt->nid);
2654: }
2655: return NULL;
2656: }
2657:
2658: /*
2659: * Verifies that the signature algorithm appearing inside the signature blob
2660: * matches that which was requested.
2661: */
2662: int
2663: sshkey_check_sigtype(const u_char *sig, size_t siglen,
2664: const char *requested_alg)
2665: {
2666: const char *expected_alg;
2667: char *sigtype = NULL;
2668: int r;
2669:
2670: if (requested_alg == NULL)
2671: return 0;
1.66 djm 2672: if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
1.65 djm 2673: return SSH_ERR_INVALID_ARGUMENT;
1.82 djm 2674: if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0)
1.65 djm 2675: return r;
2676: r = strcmp(expected_alg, sigtype) == 0;
2677: free(sigtype);
2678: return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
1.1 djm 2679: }
2680:
2681: int
1.76 djm 2682: sshkey_sign(struct sshkey *key,
1.1 djm 2683: u_char **sigp, size_t *lenp,
1.86 djm 2684: const u_char *data, size_t datalen,
1.111 djm 2685: const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
1.1 djm 2686: {
1.76 djm 2687: int was_shielded = sshkey_is_shielded(key);
2688: int r2, r = SSH_ERR_INTERNAL_ERROR;
2689:
1.1 djm 2690: if (sigp != NULL)
2691: *sigp = NULL;
2692: if (lenp != NULL)
2693: *lenp = 0;
2694: if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2695: return SSH_ERR_INVALID_ARGUMENT;
1.76 djm 2696: if ((r = sshkey_unshield_private(key)) != 0)
2697: return r;
1.1 djm 2698: switch (key->type) {
2699: #ifdef WITH_OPENSSL
2700: case KEY_DSA_CERT:
2701: case KEY_DSA:
1.76 djm 2702: r = ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
2703: break;
1.1 djm 2704: case KEY_ECDSA_CERT:
2705: case KEY_ECDSA:
1.76 djm 2706: r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
2707: break;
1.1 djm 2708: case KEY_RSA_CERT:
2709: case KEY_RSA:
1.76 djm 2710: r = ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
2711: break;
1.1 djm 2712: #endif /* WITH_OPENSSL */
2713: case KEY_ED25519:
2714: case KEY_ED25519_CERT:
1.76 djm 2715: r = ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
1.89 markus 2716: break;
2717: case KEY_ED25519_SK:
2718: case KEY_ED25519_SK_CERT:
1.97 djm 2719: case KEY_ECDSA_SK_CERT:
2720: case KEY_ECDSA_SK:
2721: r = sshsk_sign(sk_provider, key, sigp, lenp, data,
1.111 djm 2722: datalen, compat, sk_pin);
1.76 djm 2723: break;
1.62 markus 2724: #ifdef WITH_XMSS
2725: case KEY_XMSS:
2726: case KEY_XMSS_CERT:
1.76 djm 2727: r = ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
2728: break;
1.62 markus 2729: #endif /* WITH_XMSS */
1.1 djm 2730: default:
1.76 djm 2731: r = SSH_ERR_KEY_TYPE_UNKNOWN;
2732: break;
1.1 djm 2733: }
1.76 djm 2734: if (was_shielded && (r2 = sshkey_shield_private(key)) != 0)
2735: return r2;
2736: return r;
1.1 djm 2737: }
2738:
2739: /*
2740: * ssh_key_verify returns 0 for a correct signature and < 0 on error.
1.59 djm 2741: * If "alg" specified, then the signature must use that algorithm.
1.1 djm 2742: */
2743: int
2744: sshkey_verify(const struct sshkey *key,
2745: const u_char *sig, size_t siglen,
1.96 djm 2746: const u_char *data, size_t dlen, const char *alg, u_int compat,
2747: struct sshkey_sig_details **detailsp)
1.1 djm 2748: {
1.96 djm 2749: if (detailsp != NULL)
2750: *detailsp = NULL;
1.6 djm 2751: if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
1.1 djm 2752: return SSH_ERR_INVALID_ARGUMENT;
2753: switch (key->type) {
2754: #ifdef WITH_OPENSSL
2755: case KEY_DSA_CERT:
2756: case KEY_DSA:
2757: return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
2758: case KEY_ECDSA_CERT:
2759: case KEY_ECDSA:
2760: return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
1.85 djm 2761: case KEY_ECDSA_SK_CERT:
2762: case KEY_ECDSA_SK:
2763: return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen,
1.96 djm 2764: compat, detailsp);
1.1 djm 2765: case KEY_RSA_CERT:
2766: case KEY_RSA:
1.59 djm 2767: return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
1.1 djm 2768: #endif /* WITH_OPENSSL */
2769: case KEY_ED25519:
2770: case KEY_ED25519_CERT:
2771: return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
1.87 markus 2772: case KEY_ED25519_SK:
2773: case KEY_ED25519_SK_CERT:
2774: return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen,
1.96 djm 2775: compat, detailsp);
1.62 markus 2776: #ifdef WITH_XMSS
2777: case KEY_XMSS:
2778: case KEY_XMSS_CERT:
2779: return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
2780: #endif /* WITH_XMSS */
1.1 djm 2781: default:
2782: return SSH_ERR_KEY_TYPE_UNKNOWN;
2783: }
2784: }
2785:
2786: /* Convert a plain key to their _CERT equivalent */
2787: int
1.20 djm 2788: sshkey_to_certified(struct sshkey *k)
1.1 djm 2789: {
2790: int newtype;
2791:
2792: switch (k->type) {
2793: #ifdef WITH_OPENSSL
2794: case KEY_RSA:
1.20 djm 2795: newtype = KEY_RSA_CERT;
1.1 djm 2796: break;
2797: case KEY_DSA:
1.20 djm 2798: newtype = KEY_DSA_CERT;
1.1 djm 2799: break;
2800: case KEY_ECDSA:
2801: newtype = KEY_ECDSA_CERT;
2802: break;
1.85 djm 2803: case KEY_ECDSA_SK:
2804: newtype = KEY_ECDSA_SK_CERT;
2805: break;
1.1 djm 2806: #endif /* WITH_OPENSSL */
1.90 markus 2807: case KEY_ED25519_SK:
2808: newtype = KEY_ED25519_SK_CERT;
2809: break;
1.1 djm 2810: case KEY_ED25519:
2811: newtype = KEY_ED25519_CERT;
2812: break;
1.62 markus 2813: #ifdef WITH_XMSS
2814: case KEY_XMSS:
2815: newtype = KEY_XMSS_CERT;
2816: break;
2817: #endif /* WITH_XMSS */
1.1 djm 2818: default:
2819: return SSH_ERR_INVALID_ARGUMENT;
2820: }
2821: if ((k->cert = cert_new()) == NULL)
2822: return SSH_ERR_ALLOC_FAIL;
2823: k->type = newtype;
2824: return 0;
2825: }
2826:
2827: /* Convert a certificate to its raw key equivalent */
2828: int
2829: sshkey_drop_cert(struct sshkey *k)
2830: {
2831: if (!sshkey_type_is_cert(k->type))
2832: return SSH_ERR_KEY_TYPE_UNKNOWN;
2833: cert_free(k->cert);
2834: k->cert = NULL;
2835: k->type = sshkey_type_plain(k->type);
2836: return 0;
2837: }
2838:
2839: /* Sign a certified key, (re-)generating the signed certblob. */
2840: int
1.53 djm 2841: sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
1.111 djm 2842: const char *sk_provider, const char *sk_pin,
2843: sshkey_certify_signer *signer, void *signer_ctx)
1.1 djm 2844: {
2845: struct sshbuf *principals = NULL;
2846: u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
2847: size_t i, ca_len, sig_len;
2848: int ret = SSH_ERR_INTERNAL_ERROR;
1.67 djm 2849: struct sshbuf *cert = NULL;
2850: char *sigtype = NULL;
1.69 djm 2851: #ifdef WITH_OPENSSL
2852: const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
2853: #endif /* WITH_OPENSSL */
1.1 djm 2854:
2855: if (k == NULL || k->cert == NULL ||
2856: k->cert->certblob == NULL || ca == NULL)
2857: return SSH_ERR_INVALID_ARGUMENT;
2858: if (!sshkey_is_cert(k))
2859: return SSH_ERR_KEY_TYPE_UNKNOWN;
2860: if (!sshkey_type_is_valid_ca(ca->type))
2861: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2862:
1.67 djm 2863: /*
2864: * If no alg specified as argument but a signature_type was set,
2865: * then prefer that. If both were specified, then they must match.
2866: */
2867: if (alg == NULL)
2868: alg = k->cert->signature_type;
2869: else if (k->cert->signature_type != NULL &&
2870: strcmp(alg, k->cert->signature_type) != 0)
2871: return SSH_ERR_INVALID_ARGUMENT;
1.75 djm 2872:
2873: /*
2874: * If no signing algorithm or signature_type was specified and we're
2875: * using a RSA key, then default to a good signature algorithm.
2876: */
2877: if (alg == NULL && ca->type == KEY_RSA)
2878: alg = "rsa-sha2-512";
1.67 djm 2879:
1.1 djm 2880: if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2881: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2882:
2883: cert = k->cert->certblob; /* for readability */
2884: sshbuf_reset(cert);
2885: if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0)
2886: goto out;
2887:
2888: /* -v01 certs put nonce first */
2889: arc4random_buf(&nonce, sizeof(nonce));
1.20 djm 2890: if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
2891: goto out;
1.1 djm 2892:
2893: /* XXX this substantially duplicates to_blob(); refactor */
2894: switch (k->type) {
2895: #ifdef WITH_OPENSSL
2896: case KEY_DSA_CERT:
1.69 djm 2897: DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
2898: DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
2899: if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 ||
2900: (ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 ||
2901: (ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 ||
2902: (ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0)
1.1 djm 2903: goto out;
2904: break;
2905: case KEY_ECDSA_CERT:
1.85 djm 2906: case KEY_ECDSA_SK_CERT:
1.1 djm 2907: if ((ret = sshbuf_put_cstring(cert,
2908: sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 ||
2909: (ret = sshbuf_put_ec(cert,
2910: EC_KEY_get0_public_key(k->ecdsa),
2911: EC_KEY_get0_group(k->ecdsa))) != 0)
2912: goto out;
1.85 djm 2913: if (k->type == KEY_ECDSA_SK_CERT) {
2914: if ((ret = sshbuf_put_cstring(cert,
2915: k->sk_application)) != 0)
2916: goto out;
2917: }
1.1 djm 2918: break;
2919: case KEY_RSA_CERT:
1.69 djm 2920: RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
2921: if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 ||
2922: (ret = sshbuf_put_bignum2(cert, rsa_n)) != 0)
1.1 djm 2923: goto out;
2924: break;
2925: #endif /* WITH_OPENSSL */
2926: case KEY_ED25519_CERT:
1.94 djm 2927: case KEY_ED25519_SK_CERT:
1.1 djm 2928: if ((ret = sshbuf_put_string(cert,
2929: k->ed25519_pk, ED25519_PK_SZ)) != 0)
2930: goto out;
1.94 djm 2931: if (k->type == KEY_ED25519_SK_CERT) {
2932: if ((ret = sshbuf_put_cstring(cert,
2933: k->sk_application)) != 0)
2934: goto out;
2935: }
1.1 djm 2936: break;
1.62 markus 2937: #ifdef WITH_XMSS
2938: case KEY_XMSS_CERT:
2939: if (k->xmss_name == NULL) {
2940: ret = SSH_ERR_INVALID_ARGUMENT;
2941: goto out;
2942: }
2943: if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) ||
2944: (ret = sshbuf_put_string(cert,
2945: k->xmss_pk, sshkey_xmss_pklen(k))) != 0)
2946: goto out;
2947: break;
2948: #endif /* WITH_XMSS */
1.1 djm 2949: default:
2950: ret = SSH_ERR_INVALID_ARGUMENT;
1.15 djm 2951: goto out;
1.1 djm 2952: }
2953:
1.20 djm 2954: if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 ||
2955: (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
1.1 djm 2956: (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
2957: goto out;
2958:
2959: if ((principals = sshbuf_new()) == NULL) {
2960: ret = SSH_ERR_ALLOC_FAIL;
2961: goto out;
2962: }
2963: for (i = 0; i < k->cert->nprincipals; i++) {
2964: if ((ret = sshbuf_put_cstring(principals,
2965: k->cert->principals[i])) != 0)
2966: goto out;
2967: }
2968: if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
2969: (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
2970: (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
1.20 djm 2971: (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 ||
2972: (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 ||
2973: (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
1.1 djm 2974: (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
2975: goto out;
2976:
2977: /* Sign the whole mess */
1.53 djm 2978: if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
1.111 djm 2979: sshbuf_len(cert), alg, sk_provider, sk_pin, 0, signer_ctx)) != 0)
1.1 djm 2980: goto out;
1.67 djm 2981: /* Check and update signature_type against what was actually used */
1.82 djm 2982: if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
1.67 djm 2983: goto out;
2984: if (alg != NULL && strcmp(alg, sigtype) != 0) {
2985: ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
2986: goto out;
2987: }
2988: if (k->cert->signature_type == NULL) {
2989: k->cert->signature_type = sigtype;
2990: sigtype = NULL;
2991: }
1.1 djm 2992: /* Append signature and we are done */
2993: if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
2994: goto out;
2995: ret = 0;
2996: out:
2997: if (ret != 0)
2998: sshbuf_reset(cert);
1.29 mmcc 2999: free(sig_blob);
3000: free(ca_blob);
1.67 djm 3001: free(sigtype);
1.31 mmcc 3002: sshbuf_free(principals);
1.1 djm 3003: return ret;
1.53 djm 3004: }
3005:
3006: static int
1.76 djm 3007: default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
1.53 djm 3008: const u_char *data, size_t datalen,
1.111 djm 3009: const char *alg, const char *sk_provider, const char *sk_pin,
3010: u_int compat, void *ctx)
1.53 djm 3011: {
3012: if (ctx != NULL)
3013: return SSH_ERR_INVALID_ARGUMENT;
1.86 djm 3014: return sshkey_sign(key, sigp, lenp, data, datalen, alg,
1.111 djm 3015: sk_provider, sk_pin, compat);
1.53 djm 3016: }
3017:
3018: int
1.86 djm 3019: sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg,
1.111 djm 3020: const char *sk_provider, const char *sk_pin)
1.53 djm 3021: {
1.111 djm 3022: return sshkey_certify_custom(k, ca, alg, sk_provider, sk_pin,
1.86 djm 3023: default_key_sign, NULL);
1.1 djm 3024: }
3025:
3026: int
3027: sshkey_cert_check_authority(const struct sshkey *k,
1.114 djm 3028: int want_host, int require_principal, int wildcard_pattern,
1.1 djm 3029: const char *name, const char **reason)
3030: {
3031: u_int i, principal_matches;
3032: time_t now = time(NULL);
3033:
1.102 markus 3034: if (reason == NULL)
3035: return SSH_ERR_INVALID_ARGUMENT;
1.114 djm 3036: if (!sshkey_is_cert(k)) {
3037: *reason = "Key is not a certificate";
3038: return SSH_ERR_KEY_CERT_INVALID;
3039: }
1.1 djm 3040: if (want_host) {
3041: if (k->cert->type != SSH2_CERT_TYPE_HOST) {
3042: *reason = "Certificate invalid: not a host certificate";
3043: return SSH_ERR_KEY_CERT_INVALID;
3044: }
3045: } else {
3046: if (k->cert->type != SSH2_CERT_TYPE_USER) {
3047: *reason = "Certificate invalid: not a user certificate";
3048: return SSH_ERR_KEY_CERT_INVALID;
3049: }
3050: }
3051: if (now < 0) {
3052: /* yikes - system clock before epoch! */
3053: *reason = "Certificate invalid: not yet valid";
3054: return SSH_ERR_KEY_CERT_INVALID;
3055: }
3056: if ((u_int64_t)now < k->cert->valid_after) {
3057: *reason = "Certificate invalid: not yet valid";
3058: return SSH_ERR_KEY_CERT_INVALID;
3059: }
3060: if ((u_int64_t)now >= k->cert->valid_before) {
3061: *reason = "Certificate invalid: expired";
3062: return SSH_ERR_KEY_CERT_INVALID;
3063: }
3064: if (k->cert->nprincipals == 0) {
3065: if (require_principal) {
3066: *reason = "Certificate lacks principal list";
3067: return SSH_ERR_KEY_CERT_INVALID;
3068: }
3069: } else if (name != NULL) {
3070: principal_matches = 0;
3071: for (i = 0; i < k->cert->nprincipals; i++) {
1.114 djm 3072: if (wildcard_pattern) {
3073: if (match_pattern(k->cert->principals[i],
3074: name)) {
3075: principal_matches = 1;
3076: break;
3077: }
3078: } else if (strcmp(name, k->cert->principals[i]) == 0) {
1.1 djm 3079: principal_matches = 1;
3080: break;
3081: }
3082: }
3083: if (!principal_matches) {
3084: *reason = "Certificate invalid: name is not a listed "
3085: "principal";
3086: return SSH_ERR_KEY_CERT_INVALID;
3087: }
1.114 djm 3088: }
3089: return 0;
3090: }
3091:
3092: int
3093: sshkey_cert_check_host(const struct sshkey *key, const char *host,
3094: int wildcard_principals, const char *ca_sign_algorithms,
3095: const char **reason)
3096: {
3097: int r;
3098:
3099: if ((r = sshkey_cert_check_authority(key, 1, 0, wildcard_principals,
3100: host, reason)) != 0)
3101: return r;
3102: if (sshbuf_len(key->cert->critical) != 0) {
3103: *reason = "Certificate contains unsupported critical options";
3104: return SSH_ERR_KEY_CERT_INVALID;
3105: }
3106: if (ca_sign_algorithms != NULL &&
3107: (r = sshkey_check_cert_sigtype(key, ca_sign_algorithms)) != 0) {
3108: *reason = "Certificate signed with disallowed algorithm";
3109: return SSH_ERR_KEY_CERT_INVALID;
1.1 djm 3110: }
3111: return 0;
1.27 djm 3112: }
3113:
3114: size_t
3115: sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
3116: {
1.113 dtucker 3117: char from[32], to[32], ret[128];
1.27 djm 3118: time_t tt;
3119: struct tm *tm;
3120:
3121: *from = *to = '\0';
3122: if (cert->valid_after == 0 &&
3123: cert->valid_before == 0xffffffffffffffffULL)
3124: return strlcpy(s, "forever", l);
3125:
3126: if (cert->valid_after != 0) {
3127: /* XXX revisit INT_MAX in 2038 :) */
3128: tt = cert->valid_after > INT_MAX ?
3129: INT_MAX : cert->valid_after;
3130: tm = localtime(&tt);
3131: strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
3132: }
3133: if (cert->valid_before != 0xffffffffffffffffULL) {
3134: /* XXX revisit INT_MAX in 2038 :) */
3135: tt = cert->valid_before > INT_MAX ?
3136: INT_MAX : cert->valid_before;
3137: tm = localtime(&tt);
3138: strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
3139: }
3140:
3141: if (cert->valid_after == 0)
3142: snprintf(ret, sizeof(ret), "before %s", to);
3143: else if (cert->valid_before == 0xffffffffffffffffULL)
3144: snprintf(ret, sizeof(ret), "after %s", from);
3145: else
3146: snprintf(ret, sizeof(ret), "from %s to %s", from, to);
3147:
3148: return strlcpy(s, ret, l);
1.1 djm 3149: }
3150:
3151: int
1.76 djm 3152: sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
1.62 markus 3153: enum sshkey_serialize_rep opts)
1.1 djm 3154: {
3155: int r = SSH_ERR_INTERNAL_ERROR;
1.76 djm 3156: int was_shielded = sshkey_is_shielded(key);
3157: struct sshbuf *b = NULL;
1.69 djm 3158: #ifdef WITH_OPENSSL
3159: const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
3160: const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key;
3161: #endif /* WITH_OPENSSL */
1.1 djm 3162:
1.76 djm 3163: if ((r = sshkey_unshield_private(key)) != 0)
3164: return r;
3165: if ((b = sshbuf_new()) == NULL)
3166: return SSH_ERR_ALLOC_FAIL;
1.1 djm 3167: if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
3168: goto out;
3169: switch (key->type) {
3170: #ifdef WITH_OPENSSL
3171: case KEY_RSA:
1.69 djm 3172: RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
3173: RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
3174: RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
3175: if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
3176: (r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
3177: (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
3178: (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
3179: (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
3180: (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
1.1 djm 3181: goto out;
3182: break;
3183: case KEY_RSA_CERT:
3184: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3185: r = SSH_ERR_INVALID_ARGUMENT;
3186: goto out;
3187: }
1.69 djm 3188: RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
3189: RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
3190: RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
1.1 djm 3191: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
1.69 djm 3192: (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
3193: (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
3194: (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
3195: (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
1.1 djm 3196: goto out;
3197: break;
3198: case KEY_DSA:
1.69 djm 3199: DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
3200: DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key);
3201: if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
3202: (r = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
3203: (r = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
3204: (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 ||
3205: (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
1.1 djm 3206: goto out;
3207: break;
3208: case KEY_DSA_CERT:
3209: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3210: r = SSH_ERR_INVALID_ARGUMENT;
3211: goto out;
3212: }
1.69 djm 3213: DSA_get0_key(key->dsa, NULL, &dsa_priv_key);
1.1 djm 3214: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
1.69 djm 3215: (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
1.1 djm 3216: goto out;
3217: break;
3218: case KEY_ECDSA:
3219: if ((r = sshbuf_put_cstring(b,
3220: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
3221: (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
3222: (r = sshbuf_put_bignum2(b,
3223: EC_KEY_get0_private_key(key->ecdsa))) != 0)
3224: goto out;
3225: break;
3226: case KEY_ECDSA_CERT:
3227: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3228: r = SSH_ERR_INVALID_ARGUMENT;
3229: goto out;
3230: }
3231: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3232: (r = sshbuf_put_bignum2(b,
3233: EC_KEY_get0_private_key(key->ecdsa))) != 0)
3234: goto out;
3235: break;
1.85 djm 3236: case KEY_ECDSA_SK:
3237: if ((r = sshbuf_put_cstring(b,
3238: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
3239: (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
3240: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
3241: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
3242: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
3243: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
3244: goto out;
3245: break;
3246: case KEY_ECDSA_SK_CERT:
3247: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3248: r = SSH_ERR_INVALID_ARGUMENT;
3249: goto out;
3250: }
3251: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3252: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
3253: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
3254: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
3255: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
3256: goto out;
3257: break;
1.1 djm 3258: #endif /* WITH_OPENSSL */
3259: case KEY_ED25519:
3260: if ((r = sshbuf_put_string(b, key->ed25519_pk,
3261: ED25519_PK_SZ)) != 0 ||
3262: (r = sshbuf_put_string(b, key->ed25519_sk,
3263: ED25519_SK_SZ)) != 0)
3264: goto out;
3265: break;
3266: case KEY_ED25519_CERT:
3267: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3268: r = SSH_ERR_INVALID_ARGUMENT;
3269: goto out;
3270: }
3271: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3272: (r = sshbuf_put_string(b, key->ed25519_pk,
3273: ED25519_PK_SZ)) != 0 ||
3274: (r = sshbuf_put_string(b, key->ed25519_sk,
3275: ED25519_SK_SZ)) != 0)
3276: goto out;
3277: break;
1.90 markus 3278: case KEY_ED25519_SK:
3279: if ((r = sshbuf_put_string(b, key->ed25519_pk,
3280: ED25519_PK_SZ)) != 0 ||
3281: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
3282: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
3283: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
3284: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
3285: goto out;
3286: break;
3287: case KEY_ED25519_SK_CERT:
3288: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3289: r = SSH_ERR_INVALID_ARGUMENT;
3290: goto out;
3291: }
3292: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3293: (r = sshbuf_put_string(b, key->ed25519_pk,
3294: ED25519_PK_SZ)) != 0 ||
3295: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
3296: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
3297: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
3298: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
3299: goto out;
3300: break;
1.62 markus 3301: #ifdef WITH_XMSS
3302: case KEY_XMSS:
3303: if (key->xmss_name == NULL) {
3304: r = SSH_ERR_INVALID_ARGUMENT;
3305: goto out;
3306: }
3307: if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
3308: (r = sshbuf_put_string(b, key->xmss_pk,
3309: sshkey_xmss_pklen(key))) != 0 ||
3310: (r = sshbuf_put_string(b, key->xmss_sk,
3311: sshkey_xmss_sklen(key))) != 0 ||
3312: (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
3313: goto out;
3314: break;
3315: case KEY_XMSS_CERT:
3316: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
3317: key->xmss_name == NULL) {
3318: r = SSH_ERR_INVALID_ARGUMENT;
3319: goto out;
3320: }
3321: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3322: (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
3323: (r = sshbuf_put_string(b, key->xmss_pk,
3324: sshkey_xmss_pklen(key))) != 0 ||
3325: (r = sshbuf_put_string(b, key->xmss_sk,
3326: sshkey_xmss_sklen(key))) != 0 ||
3327: (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
3328: goto out;
3329: break;
3330: #endif /* WITH_XMSS */
1.1 djm 3331: default:
3332: r = SSH_ERR_INVALID_ARGUMENT;
3333: goto out;
3334: }
1.76 djm 3335: /*
3336: * success (but we still need to append the output to buf after
3337: * possibly re-shielding the private key)
3338: */
1.1 djm 3339: r = 0;
3340: out:
1.76 djm 3341: if (was_shielded)
3342: r = sshkey_shield_private(key);
3343: if (r == 0)
3344: r = sshbuf_putb(buf, b);
3345: sshbuf_free(b);
3346:
1.1 djm 3347: return r;
3348: }
3349:
3350: int
1.76 djm 3351: sshkey_private_serialize(struct sshkey *key, struct sshbuf *b)
1.62 markus 3352: {
3353: return sshkey_private_serialize_opt(key, b,
3354: SSHKEY_SERIALIZE_DEFAULT);
3355: }
3356:
3357: int
1.1 djm 3358: sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3359: {
1.62 markus 3360: char *tname = NULL, *curve = NULL, *xmss_name = NULL;
1.115 djm 3361: char *expect_sk_application = NULL;
1.1 djm 3362: struct sshkey *k = NULL;
1.14 djm 3363: size_t pklen = 0, sklen = 0;
1.1 djm 3364: int type, r = SSH_ERR_INTERNAL_ERROR;
3365: u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
1.115 djm 3366: u_char *expect_ed25519_pk = NULL;
1.62 markus 3367: u_char *xmss_pk = NULL, *xmss_sk = NULL;
1.1 djm 3368: #ifdef WITH_OPENSSL
3369: BIGNUM *exponent = NULL;
1.69 djm 3370: BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
3371: BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
3372: BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
3373: BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
1.1 djm 3374: #endif /* WITH_OPENSSL */
3375:
3376: if (kp != NULL)
3377: *kp = NULL;
3378: if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
3379: goto out;
3380: type = sshkey_type_from_name(tname);
1.108 djm 3381: if (sshkey_type_is_cert(type)) {
3382: /*
3383: * Certificate key private keys begin with the certificate
3384: * itself. Make sure this matches the type of the enclosing
3385: * private key.
3386: */
3387: if ((r = sshkey_froms(buf, &k)) != 0)
3388: goto out;
3389: if (k->type != type) {
3390: r = SSH_ERR_KEY_CERT_MISMATCH;
3391: goto out;
3392: }
3393: /* For ECDSA keys, the group must match too */
3394: if (k->type == KEY_ECDSA &&
3395: k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) {
3396: r = SSH_ERR_KEY_CERT_MISMATCH;
3397: goto out;
3398: }
1.115 djm 3399: /*
3400: * Several fields are redundant between certificate and
3401: * private key body, we require these to match.
3402: */
3403: expect_sk_application = k->sk_application;
3404: expect_ed25519_pk = k->ed25519_pk;
3405: k->sk_application = NULL;
3406: k->ed25519_pk = NULL;
1.108 djm 3407: } else {
1.70 djm 3408: if ((k = sshkey_new(type)) == NULL) {
1.1 djm 3409: r = SSH_ERR_ALLOC_FAIL;
3410: goto out;
3411: }
1.108 djm 3412: }
3413: switch (type) {
3414: #ifdef WITH_OPENSSL
3415: case KEY_DSA:
1.73 djm 3416: if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 ||
3417: (r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 ||
3418: (r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 ||
1.108 djm 3419: (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0)
1.69 djm 3420: goto out;
3421: if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) {
3422: r = SSH_ERR_LIBCRYPTO_ERROR;
3423: goto out;
3424: }
3425: dsa_p = dsa_q = dsa_g = NULL; /* transferred */
1.108 djm 3426: if (!DSA_set0_key(k->dsa, dsa_pub_key, NULL)) {
1.69 djm 3427: r = SSH_ERR_LIBCRYPTO_ERROR;
1.1 djm 3428: goto out;
1.69 djm 3429: }
1.108 djm 3430: dsa_pub_key = NULL; /* transferred */
3431: /* FALLTHROUGH */
1.1 djm 3432: case KEY_DSA_CERT:
1.108 djm 3433: if ((r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
1.84 djm 3434: goto out;
1.69 djm 3435: if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) {
3436: r = SSH_ERR_LIBCRYPTO_ERROR;
3437: goto out;
3438: }
3439: dsa_priv_key = NULL; /* transferred */
1.1 djm 3440: break;
3441: case KEY_ECDSA:
3442: if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
3443: r = SSH_ERR_INVALID_ARGUMENT;
3444: goto out;
3445: }
3446: if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
3447: goto out;
3448: if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
3449: r = SSH_ERR_EC_CURVE_MISMATCH;
3450: goto out;
3451: }
3452: k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
1.73 djm 3453: if (k->ecdsa == NULL) {
1.1 djm 3454: r = SSH_ERR_LIBCRYPTO_ERROR;
3455: goto out;
3456: }
1.108 djm 3457: if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0)
1.1 djm 3458: goto out;
1.108 djm 3459: /* FALLTHROUGH */
1.1 djm 3460: case KEY_ECDSA_CERT:
1.108 djm 3461: if ((r = sshbuf_get_bignum2(buf, &exponent)) != 0)
1.1 djm 3462: goto out;
3463: if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
3464: r = SSH_ERR_LIBCRYPTO_ERROR;
3465: goto out;
3466: }
3467: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
1.22 jsg 3468: EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
1.1 djm 3469: (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
3470: goto out;
3471: break;
1.85 djm 3472: case KEY_ECDSA_SK:
3473: if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
3474: r = SSH_ERR_INVALID_ARGUMENT;
3475: goto out;
3476: }
3477: if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
3478: goto out;
3479: if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
3480: r = SSH_ERR_EC_CURVE_MISMATCH;
3481: goto out;
3482: }
3483: if ((k->sk_key_handle = sshbuf_new()) == NULL ||
3484: (k->sk_reserved = sshbuf_new()) == NULL) {
3485: r = SSH_ERR_ALLOC_FAIL;
3486: goto out;
3487: }
3488: k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
3489: if (k->ecdsa == NULL) {
3490: r = SSH_ERR_LIBCRYPTO_ERROR;
3491: goto out;
3492: }
3493: if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
3494: (r = sshbuf_get_cstring(buf, &k->sk_application,
3495: NULL)) != 0 ||
3496: (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
3497: (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
3498: (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
3499: goto out;
3500: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
3501: EC_KEY_get0_public_key(k->ecdsa))) != 0)
3502: goto out;
3503: break;
3504: case KEY_ECDSA_SK_CERT:
3505: if ((k->sk_key_handle = sshbuf_new()) == NULL ||
3506: (k->sk_reserved = sshbuf_new()) == NULL) {
3507: r = SSH_ERR_ALLOC_FAIL;
3508: goto out;
3509: }
3510: if ((r = sshbuf_get_cstring(buf, &k->sk_application,
3511: NULL)) != 0 ||
3512: (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
3513: (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
3514: (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
3515: goto out;
3516: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
3517: EC_KEY_get0_public_key(k->ecdsa))) != 0)
3518: goto out;
3519: break;
1.1 djm 3520: case KEY_RSA:
1.73 djm 3521: if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 ||
1.108 djm 3522: (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0)
1.1 djm 3523: goto out;
1.108 djm 3524: if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, NULL)) {
1.69 djm 3525: r = SSH_ERR_LIBCRYPTO_ERROR;
3526: goto out;
3527: }
1.108 djm 3528: rsa_n = rsa_e = NULL; /* transferred */
3529: /* FALLTHROUGH */
1.1 djm 3530: case KEY_RSA_CERT:
1.108 djm 3531: if ((r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
1.73 djm 3532: (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
3533: (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
3534: (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
1.1 djm 3535: goto out;
1.69 djm 3536: if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) {
3537: r = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 3538: goto out;
3539: }
1.69 djm 3540: rsa_d = NULL; /* transferred */
3541: if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) {
3542: r = SSH_ERR_LIBCRYPTO_ERROR;
3543: goto out;
3544: }
3545: rsa_p = rsa_q = NULL; /* transferred */
3546: if ((r = check_rsa_length(k->rsa)) != 0)
3547: goto out;
3548: if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
3549: goto out;
1.1 djm 3550: break;
3551: #endif /* WITH_OPENSSL */
3552: case KEY_ED25519:
1.108 djm 3553: case KEY_ED25519_CERT:
1.1 djm 3554: if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3555: (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3556: goto out;
3557: if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3558: r = SSH_ERR_INVALID_FORMAT;
3559: goto out;
3560: }
3561: k->ed25519_pk = ed25519_pk;
3562: k->ed25519_sk = ed25519_sk;
1.84 djm 3563: ed25519_pk = ed25519_sk = NULL; /* transferred */
1.1 djm 3564: break;
1.90 markus 3565: case KEY_ED25519_SK:
1.108 djm 3566: case KEY_ED25519_SK_CERT:
1.90 markus 3567: if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0)
3568: goto out;
3569: if (pklen != ED25519_PK_SZ) {
3570: r = SSH_ERR_INVALID_FORMAT;
3571: goto out;
3572: }
3573: if ((k->sk_key_handle = sshbuf_new()) == NULL ||
3574: (k->sk_reserved = sshbuf_new()) == NULL) {
3575: r = SSH_ERR_ALLOC_FAIL;
3576: goto out;
3577: }
3578: if ((r = sshbuf_get_cstring(buf, &k->sk_application,
3579: NULL)) != 0 ||
3580: (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
3581: (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
3582: (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
3583: goto out;
3584: k->ed25519_pk = ed25519_pk;
3585: ed25519_pk = NULL; /* transferred */
3586: break;
1.62 markus 3587: #ifdef WITH_XMSS
3588: case KEY_XMSS:
1.108 djm 3589: case KEY_XMSS_CERT:
1.62 markus 3590: if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
3591: (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3592: (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
1.110 markus 3593: goto out;
3594: if (type == KEY_XMSS &&
3595: (r = sshkey_xmss_init(k, xmss_name)) != 0)
1.62 markus 3596: goto out;
3597: if (pklen != sshkey_xmss_pklen(k) ||
3598: sklen != sshkey_xmss_sklen(k)) {
3599: r = SSH_ERR_INVALID_FORMAT;
3600: goto out;
3601: }
3602: k->xmss_pk = xmss_pk;
3603: k->xmss_sk = xmss_sk;
3604: xmss_pk = xmss_sk = NULL;
3605: /* optional internal state */
3606: if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3607: goto out;
3608: break;
3609: #endif /* WITH_XMSS */
1.1 djm 3610: default:
3611: r = SSH_ERR_KEY_TYPE_UNKNOWN;
3612: goto out;
3613: }
3614: #ifdef WITH_OPENSSL
3615: /* enable blinding */
3616: switch (k->type) {
3617: case KEY_RSA:
3618: case KEY_RSA_CERT:
3619: if (RSA_blinding_on(k->rsa, NULL) != 1) {
3620: r = SSH_ERR_LIBCRYPTO_ERROR;
3621: goto out;
3622: }
3623: break;
3624: }
3625: #endif /* WITH_OPENSSL */
1.115 djm 3626: if ((expect_sk_application != NULL && (k->sk_application == NULL ||
3627: strcmp(expect_sk_application, k->sk_application) != 0)) ||
3628: (expect_ed25519_pk != NULL && (k->ed25519_pk == NULL ||
1.116 ! djm 3629: memcmp(expect_ed25519_pk, k->ed25519_pk, ED25519_PK_SZ) != 0))) {
1.115 djm 3630: r = SSH_ERR_KEY_CERT_MISMATCH;
3631: goto out;
3632: }
1.1 djm 3633: /* success */
3634: r = 0;
3635: if (kp != NULL) {
3636: *kp = k;
3637: k = NULL;
3638: }
3639: out:
3640: free(tname);
3641: free(curve);
3642: #ifdef WITH_OPENSSL
1.60 jsing 3643: BN_clear_free(exponent);
1.69 djm 3644: BN_clear_free(dsa_p);
3645: BN_clear_free(dsa_q);
3646: BN_clear_free(dsa_g);
3647: BN_clear_free(dsa_pub_key);
3648: BN_clear_free(dsa_priv_key);
3649: BN_clear_free(rsa_n);
3650: BN_clear_free(rsa_e);
3651: BN_clear_free(rsa_d);
3652: BN_clear_free(rsa_p);
3653: BN_clear_free(rsa_q);
3654: BN_clear_free(rsa_iqmp);
1.1 djm 3655: #endif /* WITH_OPENSSL */
3656: sshkey_free(k);
1.61 jsing 3657: freezero(ed25519_pk, pklen);
3658: freezero(ed25519_sk, sklen);
1.62 markus 3659: free(xmss_name);
3660: freezero(xmss_pk, pklen);
3661: freezero(xmss_sk, sklen);
1.115 djm 3662: free(expect_sk_application);
3663: free(expect_ed25519_pk);
1.1 djm 3664: return r;
3665: }
3666:
3667: #ifdef WITH_OPENSSL
3668: int
3669: sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
3670: {
3671: EC_POINT *nq = NULL;
1.93 djm 3672: BIGNUM *order = NULL, *x = NULL, *y = NULL, *tmp = NULL;
1.1 djm 3673: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
1.40 djm 3674:
3675: /*
3676: * NB. This assumes OpenSSL has already verified that the public
3677: * point lies on the curve. This is done by EC_POINT_oct2point()
3678: * implicitly calling EC_POINT_is_on_curve(). If this code is ever
3679: * reachable with public points not unmarshalled using
3680: * EC_POINT_oct2point then the caller will need to explicitly check.
3681: */
1.1 djm 3682:
3683: /*
3684: * We shouldn't ever hit this case because bignum_get_ecpoint()
3685: * refuses to load GF2m points.
3686: */
3687: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3688: NID_X9_62_prime_field)
3689: goto out;
3690:
3691: /* Q != infinity */
3692: if (EC_POINT_is_at_infinity(group, public))
3693: goto out;
3694:
1.93 djm 3695: if ((x = BN_new()) == NULL ||
3696: (y = BN_new()) == NULL ||
3697: (order = BN_new()) == NULL ||
3698: (tmp = BN_new()) == NULL) {
1.1 djm 3699: ret = SSH_ERR_ALLOC_FAIL;
3700: goto out;
3701: }
3702:
3703: /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
1.93 djm 3704: if (EC_GROUP_get_order(group, order, NULL) != 1 ||
1.1 djm 3705: EC_POINT_get_affine_coordinates_GFp(group, public,
1.93 djm 3706: x, y, NULL) != 1) {
1.1 djm 3707: ret = SSH_ERR_LIBCRYPTO_ERROR;
3708: goto out;
3709: }
3710: if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
3711: BN_num_bits(y) <= BN_num_bits(order) / 2)
3712: goto out;
3713:
3714: /* nQ == infinity (n == order of subgroup) */
3715: if ((nq = EC_POINT_new(group)) == NULL) {
3716: ret = SSH_ERR_ALLOC_FAIL;
3717: goto out;
3718: }
1.93 djm 3719: if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) {
1.1 djm 3720: ret = SSH_ERR_LIBCRYPTO_ERROR;
3721: goto out;
3722: }
3723: if (EC_POINT_is_at_infinity(group, nq) != 1)
3724: goto out;
3725:
3726: /* x < order - 1, y < order - 1 */
3727: if (!BN_sub(tmp, order, BN_value_one())) {
3728: ret = SSH_ERR_LIBCRYPTO_ERROR;
3729: goto out;
3730: }
3731: if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0)
3732: goto out;
3733: ret = 0;
3734: out:
1.93 djm 3735: BN_clear_free(x);
3736: BN_clear_free(y);
3737: BN_clear_free(order);
3738: BN_clear_free(tmp);
1.60 jsing 3739: EC_POINT_free(nq);
1.1 djm 3740: return ret;
3741: }
3742:
3743: int
3744: sshkey_ec_validate_private(const EC_KEY *key)
3745: {
1.93 djm 3746: BIGNUM *order = NULL, *tmp = NULL;
1.1 djm 3747: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
3748:
1.93 djm 3749: if ((order = BN_new()) == NULL || (tmp = BN_new()) == NULL) {
1.1 djm 3750: ret = SSH_ERR_ALLOC_FAIL;
3751: goto out;
3752: }
3753:
3754: /* log2(private) > log2(order)/2 */
1.93 djm 3755: if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, NULL) != 1) {
1.1 djm 3756: ret = SSH_ERR_LIBCRYPTO_ERROR;
3757: goto out;
3758: }
3759: if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
3760: BN_num_bits(order) / 2)
3761: goto out;
3762:
3763: /* private < order - 1 */
3764: if (!BN_sub(tmp, order, BN_value_one())) {
3765: ret = SSH_ERR_LIBCRYPTO_ERROR;
3766: goto out;
3767: }
3768: if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0)
3769: goto out;
3770: ret = 0;
3771: out:
1.93 djm 3772: BN_clear_free(order);
3773: BN_clear_free(tmp);
1.1 djm 3774: return ret;
3775: }
3776:
3777: void
3778: sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
3779: {
1.93 djm 3780: BIGNUM *x = NULL, *y = NULL;
1.1 djm 3781:
3782: if (point == NULL) {
3783: fputs("point=(NULL)\n", stderr);
3784: return;
3785: }
1.93 djm 3786: if ((x = BN_new()) == NULL || (y = BN_new()) == NULL) {
3787: fprintf(stderr, "%s: BN_new failed\n", __func__);
3788: goto out;
1.1 djm 3789: }
3790: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3791: NID_X9_62_prime_field) {
3792: fprintf(stderr, "%s: group is not a prime field\n", __func__);
1.93 djm 3793: goto out;
1.1 djm 3794: }
1.93 djm 3795: if (EC_POINT_get_affine_coordinates_GFp(group, point,
3796: x, y, NULL) != 1) {
1.1 djm 3797: fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
3798: __func__);
1.93 djm 3799: goto out;
1.1 djm 3800: }
3801: fputs("x=", stderr);
3802: BN_print_fp(stderr, x);
3803: fputs("\ny=", stderr);
3804: BN_print_fp(stderr, y);
3805: fputs("\n", stderr);
1.93 djm 3806: out:
3807: BN_clear_free(x);
3808: BN_clear_free(y);
1.1 djm 3809: }
3810:
3811: void
3812: sshkey_dump_ec_key(const EC_KEY *key)
3813: {
3814: const BIGNUM *exponent;
3815:
3816: sshkey_dump_ec_point(EC_KEY_get0_group(key),
3817: EC_KEY_get0_public_key(key));
3818: fputs("exponent=", stderr);
3819: if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
3820: fputs("(NULL)", stderr);
3821: else
3822: BN_print_fp(stderr, EC_KEY_get0_private_key(key));
3823: fputs("\n", stderr);
3824: }
3825: #endif /* WITH_OPENSSL */
3826:
3827: static int
1.76 djm 3828: sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob,
1.1 djm 3829: const char *passphrase, const char *comment, const char *ciphername,
3830: int rounds)
3831: {
1.4 djm 3832: u_char *cp, *key = NULL, *pubkeyblob = NULL;
1.1 djm 3833: u_char salt[SALT_LEN];
1.4 djm 3834: char *b64 = NULL;
1.1 djm 3835: size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
3836: u_int check;
3837: int r = SSH_ERR_INTERNAL_ERROR;
1.36 djm 3838: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 3839: const struct sshcipher *cipher;
3840: const char *kdfname = KDFNAME;
3841: struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
3842:
3843: if (rounds <= 0)
3844: rounds = DEFAULT_ROUNDS;
3845: if (passphrase == NULL || !strlen(passphrase)) {
3846: ciphername = "none";
3847: kdfname = "none";
3848: } else if (ciphername == NULL)
3849: ciphername = DEFAULT_CIPHERNAME;
1.47 djm 3850: if ((cipher = cipher_by_name(ciphername)) == NULL) {
1.1 djm 3851: r = SSH_ERR_INVALID_ARGUMENT;
3852: goto out;
3853: }
3854:
3855: if ((kdf = sshbuf_new()) == NULL ||
3856: (encoded = sshbuf_new()) == NULL ||
3857: (encrypted = sshbuf_new()) == NULL) {
3858: r = SSH_ERR_ALLOC_FAIL;
3859: goto out;
3860: }
3861: blocksize = cipher_blocksize(cipher);
3862: keylen = cipher_keylen(cipher);
3863: ivlen = cipher_ivlen(cipher);
3864: authlen = cipher_authlen(cipher);
3865: if ((key = calloc(1, keylen + ivlen)) == NULL) {
3866: r = SSH_ERR_ALLOC_FAIL;
3867: goto out;
3868: }
3869: if (strcmp(kdfname, "bcrypt") == 0) {
3870: arc4random_buf(salt, SALT_LEN);
3871: if (bcrypt_pbkdf(passphrase, strlen(passphrase),
3872: salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) {
3873: r = SSH_ERR_INVALID_ARGUMENT;
3874: goto out;
3875: }
3876: if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 ||
3877: (r = sshbuf_put_u32(kdf, rounds)) != 0)
3878: goto out;
3879: } else if (strcmp(kdfname, "none") != 0) {
3880: /* Unsupported KDF type */
3881: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3882: goto out;
3883: }
3884: if ((r = cipher_init(&ciphercontext, cipher, key, keylen,
3885: key + keylen, ivlen, 1)) != 0)
3886: goto out;
3887:
3888: if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 ||
3889: (r = sshbuf_put_cstring(encoded, ciphername)) != 0 ||
3890: (r = sshbuf_put_cstring(encoded, kdfname)) != 0 ||
3891: (r = sshbuf_put_stringb(encoded, kdf)) != 0 ||
3892: (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */
3893: (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 ||
3894: (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0)
3895: goto out;
3896:
3897: /* set up the buffer that will be encrypted */
3898:
3899: /* Random check bytes */
3900: check = arc4random();
3901: if ((r = sshbuf_put_u32(encrypted, check)) != 0 ||
3902: (r = sshbuf_put_u32(encrypted, check)) != 0)
3903: goto out;
3904:
3905: /* append private key and comment*/
1.62 markus 3906: if ((r = sshkey_private_serialize_opt(prv, encrypted,
1.116 ! djm 3907: SSHKEY_SERIALIZE_FULL)) != 0 ||
1.1 djm 3908: (r = sshbuf_put_cstring(encrypted, comment)) != 0)
3909: goto out;
3910:
3911: /* padding */
3912: i = 0;
3913: while (sshbuf_len(encrypted) % blocksize) {
3914: if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0)
3915: goto out;
3916: }
3917:
3918: /* length in destination buffer */
3919: if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0)
3920: goto out;
3921:
3922: /* encrypt */
3923: if ((r = sshbuf_reserve(encoded,
3924: sshbuf_len(encrypted) + authlen, &cp)) != 0)
3925: goto out;
1.36 djm 3926: if ((r = cipher_crypt(ciphercontext, 0, cp,
1.1 djm 3927: sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
3928: goto out;
3929:
1.81 djm 3930: sshbuf_reset(blob);
1.1 djm 3931:
1.81 djm 3932: /* assemble uuencoded key */
3933: if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0 ||
3934: (r = sshbuf_dtob64(encoded, blob, 1)) != 0 ||
3935: (r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
1.1 djm 3936: goto out;
3937:
3938: /* success */
3939: r = 0;
3940:
3941: out:
3942: sshbuf_free(kdf);
3943: sshbuf_free(encoded);
3944: sshbuf_free(encrypted);
1.36 djm 3945: cipher_free(ciphercontext);
1.1 djm 3946: explicit_bzero(salt, sizeof(salt));
1.100 jsg 3947: if (key != NULL)
3948: freezero(key, keylen + ivlen);
3949: if (pubkeyblob != NULL)
3950: freezero(pubkeyblob, pubkeylen);
3951: if (b64 != NULL)
3952: freezero(b64, strlen(b64));
1.1 djm 3953: return r;
3954: }
3955:
3956: static int
1.103 djm 3957: private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp)
1.1 djm 3958: {
3959: const u_char *cp;
3960: size_t encoded_len;
1.103 djm 3961: int r;
3962: u_char last;
1.1 djm 3963: struct sshbuf *encoded = NULL, *decoded = NULL;
3964:
1.103 djm 3965: if (blob == NULL || decodedp == NULL)
3966: return SSH_ERR_INVALID_ARGUMENT;
3967:
3968: *decodedp = NULL;
1.1 djm 3969:
3970: if ((encoded = sshbuf_new()) == NULL ||
1.103 djm 3971: (decoded = sshbuf_new()) == NULL) {
1.1 djm 3972: r = SSH_ERR_ALLOC_FAIL;
3973: goto out;
3974: }
3975:
3976: /* check preamble */
3977: cp = sshbuf_ptr(blob);
3978: encoded_len = sshbuf_len(blob);
3979: if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) ||
3980: memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) {
3981: r = SSH_ERR_INVALID_FORMAT;
3982: goto out;
3983: }
3984: cp += MARK_BEGIN_LEN;
3985: encoded_len -= MARK_BEGIN_LEN;
3986:
3987: /* Look for end marker, removing whitespace as we go */
3988: while (encoded_len > 0) {
3989: if (*cp != '\n' && *cp != '\r') {
3990: if ((r = sshbuf_put_u8(encoded, *cp)) != 0)
3991: goto out;
3992: }
3993: last = *cp;
3994: encoded_len--;
3995: cp++;
3996: if (last == '\n') {
3997: if (encoded_len >= MARK_END_LEN &&
3998: memcmp(cp, MARK_END, MARK_END_LEN) == 0) {
3999: /* \0 terminate */
4000: if ((r = sshbuf_put_u8(encoded, 0)) != 0)
4001: goto out;
4002: break;
4003: }
4004: }
4005: }
4006: if (encoded_len == 0) {
4007: r = SSH_ERR_INVALID_FORMAT;
4008: goto out;
4009: }
4010:
4011: /* decode base64 */
1.4 djm 4012: if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0)
1.1 djm 4013: goto out;
4014:
4015: /* check magic */
4016: if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) ||
4017: memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
4018: r = SSH_ERR_INVALID_FORMAT;
4019: goto out;
4020: }
1.103 djm 4021: /* success */
4022: *decodedp = decoded;
4023: decoded = NULL;
4024: r = 0;
4025: out:
4026: sshbuf_free(encoded);
4027: sshbuf_free(decoded);
4028: return r;
4029: }
4030:
4031: static int
1.104 djm 4032: private2_decrypt(struct sshbuf *decoded, const char *passphrase,
4033: struct sshbuf **decryptedp, struct sshkey **pubkeyp)
1.103 djm 4034: {
4035: char *ciphername = NULL, *kdfname = NULL;
4036: const struct sshcipher *cipher = NULL;
4037: int r = SSH_ERR_INTERNAL_ERROR;
4038: size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0;
4039: struct sshbuf *kdf = NULL, *decrypted = NULL;
4040: struct sshcipher_ctx *ciphercontext = NULL;
1.104 djm 4041: struct sshkey *pubkey = NULL;
1.103 djm 4042: u_char *key = NULL, *salt = NULL, *dp;
4043: u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
4044:
1.104 djm 4045: if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL)
1.103 djm 4046: return SSH_ERR_INVALID_ARGUMENT;
4047:
4048: *decryptedp = NULL;
1.104 djm 4049: *pubkeyp = NULL;
1.103 djm 4050:
4051: if ((decrypted = sshbuf_new()) == NULL) {
4052: r = SSH_ERR_ALLOC_FAIL;
4053: goto out;
4054: }
4055:
1.1 djm 4056: /* parse public portion of key */
4057: if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
4058: (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
4059: (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
4060: (r = sshbuf_froms(decoded, &kdf)) != 0 ||
1.103 djm 4061: (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
4062: goto out;
4063:
4064: if (nkeys != 1) {
4065: /* XXX only one key supported at present */
4066: r = SSH_ERR_INVALID_FORMAT;
4067: goto out;
4068: }
4069:
1.104 djm 4070: if ((r = sshkey_froms(decoded, &pubkey)) != 0 ||
1.1 djm 4071: (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
4072: goto out;
4073:
4074: if ((cipher = cipher_by_name(ciphername)) == NULL) {
4075: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
4076: goto out;
4077: }
4078: if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
4079: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
4080: goto out;
4081: }
1.101 markus 4082: if (strcmp(kdfname, "none") == 0 && strcmp(ciphername, "none") != 0) {
1.1 djm 4083: r = SSH_ERR_INVALID_FORMAT;
1.101 markus 4084: goto out;
4085: }
4086: if ((passphrase == NULL || strlen(passphrase) == 0) &&
4087: strcmp(kdfname, "none") != 0) {
4088: /* passphrase required */
4089: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
1.1 djm 4090: goto out;
4091: }
4092:
4093: /* check size of encrypted key blob */
4094: blocksize = cipher_blocksize(cipher);
4095: if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
4096: r = SSH_ERR_INVALID_FORMAT;
4097: goto out;
4098: }
4099:
4100: /* setup key */
4101: keylen = cipher_keylen(cipher);
4102: ivlen = cipher_ivlen(cipher);
1.18 djm 4103: authlen = cipher_authlen(cipher);
1.1 djm 4104: if ((key = calloc(1, keylen + ivlen)) == NULL) {
4105: r = SSH_ERR_ALLOC_FAIL;
4106: goto out;
4107: }
4108: if (strcmp(kdfname, "bcrypt") == 0) {
4109: if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 ||
4110: (r = sshbuf_get_u32(kdf, &rounds)) != 0)
4111: goto out;
4112: if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
4113: key, keylen + ivlen, rounds) < 0) {
4114: r = SSH_ERR_INVALID_FORMAT;
4115: goto out;
4116: }
4117: }
4118:
1.18 djm 4119: /* check that an appropriate amount of auth data is present */
1.84 djm 4120: if (sshbuf_len(decoded) < authlen ||
4121: sshbuf_len(decoded) - authlen < encrypted_len) {
1.18 djm 4122: r = SSH_ERR_INVALID_FORMAT;
4123: goto out;
4124: }
4125:
1.1 djm 4126: /* decrypt private portion of key */
4127: if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
4128: (r = cipher_init(&ciphercontext, cipher, key, keylen,
4129: key + keylen, ivlen, 0)) != 0)
4130: goto out;
1.36 djm 4131: if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
1.18 djm 4132: encrypted_len, 0, authlen)) != 0) {
1.1 djm 4133: /* an integrity error here indicates an incorrect passphrase */
4134: if (r == SSH_ERR_MAC_INVALID)
4135: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4136: goto out;
4137: }
1.18 djm 4138: if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
1.1 djm 4139: goto out;
4140: /* there should be no trailing data */
4141: if (sshbuf_len(decoded) != 0) {
4142: r = SSH_ERR_INVALID_FORMAT;
4143: goto out;
4144: }
4145:
4146: /* check check bytes */
4147: if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 ||
4148: (r = sshbuf_get_u32(decrypted, &check2)) != 0)
4149: goto out;
4150: if (check1 != check2) {
4151: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4152: goto out;
4153: }
1.103 djm 4154: /* success */
4155: *decryptedp = decrypted;
4156: decrypted = NULL;
1.104 djm 4157: *pubkeyp = pubkey;
4158: pubkey = NULL;
1.103 djm 4159: r = 0;
4160: out:
4161: cipher_free(ciphercontext);
4162: free(ciphername);
4163: free(kdfname);
1.104 djm 4164: sshkey_free(pubkey);
1.103 djm 4165: if (salt != NULL) {
4166: explicit_bzero(salt, slen);
4167: free(salt);
4168: }
4169: if (key != NULL) {
4170: explicit_bzero(key, keylen + ivlen);
4171: free(key);
4172: }
4173: sshbuf_free(kdf);
4174: sshbuf_free(decrypted);
4175: return r;
4176: }
1.1 djm 4177:
1.103 djm 4178: /* Check deterministic padding after private key */
4179: static int
4180: private2_check_padding(struct sshbuf *decrypted)
4181: {
4182: u_char pad;
4183: size_t i;
4184: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 4185:
4186: i = 0;
4187: while (sshbuf_len(decrypted)) {
4188: if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
4189: goto out;
4190: if (pad != (++i & 0xff)) {
4191: r = SSH_ERR_INVALID_FORMAT;
4192: goto out;
4193: }
4194: }
1.103 djm 4195: /* success */
4196: r = 0;
4197: out:
4198: explicit_bzero(&pad, sizeof(pad));
4199: explicit_bzero(&i, sizeof(i));
4200: return r;
4201: }
4202:
4203: static int
4204: sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4205: struct sshkey **keyp, char **commentp)
4206: {
4207: char *comment = NULL;
4208: int r = SSH_ERR_INTERNAL_ERROR;
4209: struct sshbuf *decoded = NULL, *decrypted = NULL;
1.104 djm 4210: struct sshkey *k = NULL, *pubkey = NULL;
1.103 djm 4211:
4212: if (keyp != NULL)
4213: *keyp = NULL;
4214: if (commentp != NULL)
4215: *commentp = NULL;
4216:
4217: /* Undo base64 encoding and decrypt the private section */
4218: if ((r = private2_uudecode(blob, &decoded)) != 0 ||
1.104 djm 4219: (r = private2_decrypt(decoded, passphrase,
4220: &decrypted, &pubkey)) != 0)
1.103 djm 4221: goto out;
1.105 djm 4222:
4223: if (type != KEY_UNSPEC &&
4224: sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
4225: r = SSH_ERR_KEY_TYPE_MISMATCH;
4226: goto out;
4227: }
1.103 djm 4228:
4229: /* Load the private key and comment */
4230: if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
4231: (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
4232: goto out;
4233:
4234: /* Check deterministic padding after private section */
4235: if ((r = private2_check_padding(decrypted)) != 0)
4236: goto out;
1.1 djm 4237:
1.104 djm 4238: /* Check that the public key in the envelope matches the private key */
4239: if (!sshkey_equal(pubkey, k)) {
4240: r = SSH_ERR_INVALID_FORMAT;
4241: goto out;
4242: }
1.1 djm 4243:
4244: /* success */
4245: r = 0;
4246: if (keyp != NULL) {
4247: *keyp = k;
4248: k = NULL;
4249: }
4250: if (commentp != NULL) {
4251: *commentp = comment;
4252: comment = NULL;
4253: }
4254: out:
4255: free(comment);
4256: sshbuf_free(decoded);
4257: sshbuf_free(decrypted);
4258: sshkey_free(k);
1.104 djm 4259: sshkey_free(pubkey);
1.1 djm 4260: return r;
4261: }
4262:
1.107 djm 4263: static int
4264: sshkey_parse_private2_pubkey(struct sshbuf *blob, int type,
4265: struct sshkey **keyp)
4266: {
4267: int r = SSH_ERR_INTERNAL_ERROR;
4268: struct sshbuf *decoded = NULL;
4269: struct sshkey *pubkey = NULL;
4270: u_int nkeys = 0;
4271:
4272: if (keyp != NULL)
4273: *keyp = NULL;
4274:
4275: if ((r = private2_uudecode(blob, &decoded)) != 0)
4276: goto out;
4277: /* parse public key from unencrypted envelope */
4278: if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
4279: (r = sshbuf_skip_string(decoded)) != 0 || /* cipher */
4280: (r = sshbuf_skip_string(decoded)) != 0 || /* KDF alg */
4281: (r = sshbuf_skip_string(decoded)) != 0 || /* KDF hint */
4282: (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
4283: goto out;
4284:
4285: if (nkeys != 1) {
4286: /* XXX only one key supported at present */
4287: r = SSH_ERR_INVALID_FORMAT;
4288: goto out;
4289: }
4290:
4291: /* Parse the public key */
4292: if ((r = sshkey_froms(decoded, &pubkey)) != 0)
4293: goto out;
4294:
4295: if (type != KEY_UNSPEC &&
4296: sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
4297: r = SSH_ERR_KEY_TYPE_MISMATCH;
4298: goto out;
4299: }
4300:
4301: /* success */
4302: r = 0;
4303: if (keyp != NULL) {
4304: *keyp = pubkey;
4305: pubkey = NULL;
4306: }
4307: out:
4308: sshbuf_free(decoded);
4309: sshkey_free(pubkey);
4310: return r;
4311: }
4312:
1.1 djm 4313: #ifdef WITH_OPENSSL
1.80 djm 4314: /* convert SSH v2 key to PEM or PKCS#8 format */
1.1 djm 4315: static int
1.80 djm 4316: sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
4317: int format, const char *_passphrase, const char *comment)
1.1 djm 4318: {
1.76 djm 4319: int was_shielded = sshkey_is_shielded(key);
1.1 djm 4320: int success, r;
4321: int blen, len = strlen(_passphrase);
4322: u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
4323: const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
1.57 djm 4324: char *bptr;
1.1 djm 4325: BIO *bio = NULL;
1.76 djm 4326: struct sshbuf *blob;
1.80 djm 4327: EVP_PKEY *pkey = NULL;
1.1 djm 4328:
4329: if (len > 0 && len <= 4)
4330: return SSH_ERR_PASSPHRASE_TOO_SHORT;
1.76 djm 4331: if ((blob = sshbuf_new()) == NULL)
1.1 djm 4332: return SSH_ERR_ALLOC_FAIL;
1.76 djm 4333: if ((bio = BIO_new(BIO_s_mem())) == NULL) {
1.80 djm 4334: r = SSH_ERR_ALLOC_FAIL;
4335: goto out;
4336: }
4337: if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
4338: r = SSH_ERR_ALLOC_FAIL;
4339: goto out;
1.76 djm 4340: }
4341: if ((r = sshkey_unshield_private(key)) != 0)
4342: goto out;
1.1 djm 4343:
4344: switch (key->type) {
4345: case KEY_DSA:
1.80 djm 4346: if (format == SSHKEY_PRIVATE_PEM) {
4347: success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
4348: cipher, passphrase, len, NULL, NULL);
4349: } else {
4350: success = EVP_PKEY_set1_DSA(pkey, key->dsa);
4351: }
1.1 djm 4352: break;
4353: case KEY_ECDSA:
1.80 djm 4354: if (format == SSHKEY_PRIVATE_PEM) {
4355: success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
4356: cipher, passphrase, len, NULL, NULL);
4357: } else {
4358: success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
4359: }
1.1 djm 4360: break;
4361: case KEY_RSA:
1.80 djm 4362: if (format == SSHKEY_PRIVATE_PEM) {
4363: success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
4364: cipher, passphrase, len, NULL, NULL);
4365: } else {
4366: success = EVP_PKEY_set1_RSA(pkey, key->rsa);
4367: }
1.1 djm 4368: break;
4369: default:
4370: success = 0;
4371: break;
4372: }
4373: if (success == 0) {
4374: r = SSH_ERR_LIBCRYPTO_ERROR;
4375: goto out;
4376: }
1.80 djm 4377: if (format == SSHKEY_PRIVATE_PKCS8) {
4378: if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher,
4379: passphrase, len, NULL, NULL)) == 0) {
4380: r = SSH_ERR_LIBCRYPTO_ERROR;
4381: goto out;
4382: }
4383: }
1.1 djm 4384: if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
4385: r = SSH_ERR_INTERNAL_ERROR;
4386: goto out;
4387: }
4388: if ((r = sshbuf_put(blob, bptr, blen)) != 0)
4389: goto out;
4390: r = 0;
4391: out:
1.76 djm 4392: if (was_shielded)
4393: r = sshkey_shield_private(key);
4394: if (r == 0)
4395: r = sshbuf_putb(buf, blob);
1.80 djm 4396:
4397: EVP_PKEY_free(pkey);
1.76 djm 4398: sshbuf_free(blob);
1.1 djm 4399: BIO_free(bio);
4400: return r;
4401: }
4402: #endif /* WITH_OPENSSL */
4403:
4404: /* Serialise "key" to buffer "blob" */
4405: int
4406: sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
4407: const char *passphrase, const char *comment,
1.80 djm 4408: int format, const char *openssh_format_cipher, int openssh_format_rounds)
1.1 djm 4409: {
4410: switch (key->type) {
1.9 markus 4411: #ifdef WITH_OPENSSL
1.1 djm 4412: case KEY_DSA:
4413: case KEY_ECDSA:
4414: case KEY_RSA:
1.80 djm 4415: break; /* see below */
1.1 djm 4416: #endif /* WITH_OPENSSL */
4417: case KEY_ED25519:
1.90 markus 4418: case KEY_ED25519_SK:
1.62 markus 4419: #ifdef WITH_XMSS
4420: case KEY_XMSS:
4421: #endif /* WITH_XMSS */
1.85 djm 4422: #ifdef WITH_OPENSSL
4423: case KEY_ECDSA_SK:
4424: #endif /* WITH_OPENSSL */
1.1 djm 4425: return sshkey_private_to_blob2(key, blob, passphrase,
1.80 djm 4426: comment, openssh_format_cipher, openssh_format_rounds);
1.1 djm 4427: default:
4428: return SSH_ERR_KEY_TYPE_UNKNOWN;
4429: }
1.80 djm 4430:
4431: #ifdef WITH_OPENSSL
4432: switch (format) {
4433: case SSHKEY_PRIVATE_OPENSSH:
4434: return sshkey_private_to_blob2(key, blob, passphrase,
4435: comment, openssh_format_cipher, openssh_format_rounds);
4436: case SSHKEY_PRIVATE_PEM:
4437: case SSHKEY_PRIVATE_PKCS8:
4438: return sshkey_private_to_blob_pem_pkcs8(key, blob,
4439: format, passphrase, comment);
4440: default:
4441: return SSH_ERR_INVALID_ARGUMENT;
4442: }
4443: #endif /* WITH_OPENSSL */
1.1 djm 4444: }
4445:
4446: #ifdef WITH_OPENSSL
1.8 djm 4447: static int
1.52 djm 4448: translate_libcrypto_error(unsigned long pem_err)
4449: {
4450: int pem_reason = ERR_GET_REASON(pem_err);
4451:
4452: switch (ERR_GET_LIB(pem_err)) {
4453: case ERR_LIB_PEM:
4454: switch (pem_reason) {
4455: case PEM_R_BAD_PASSWORD_READ:
4456: case PEM_R_PROBLEMS_GETTING_PASSWORD:
4457: case PEM_R_BAD_DECRYPT:
4458: return SSH_ERR_KEY_WRONG_PASSPHRASE;
4459: default:
4460: return SSH_ERR_INVALID_FORMAT;
4461: }
4462: case ERR_LIB_EVP:
4463: switch (pem_reason) {
4464: case EVP_R_BAD_DECRYPT:
4465: return SSH_ERR_KEY_WRONG_PASSPHRASE;
1.69 djm 4466: #ifdef EVP_R_BN_DECODE_ERROR
1.52 djm 4467: case EVP_R_BN_DECODE_ERROR:
1.69 djm 4468: #endif
1.52 djm 4469: case EVP_R_DECODE_ERROR:
4470: #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
4471: case EVP_R_PRIVATE_KEY_DECODE_ERROR:
4472: #endif
4473: return SSH_ERR_INVALID_FORMAT;
4474: default:
4475: return SSH_ERR_LIBCRYPTO_ERROR;
4476: }
4477: case ERR_LIB_ASN1:
4478: return SSH_ERR_INVALID_FORMAT;
4479: }
4480: return SSH_ERR_LIBCRYPTO_ERROR;
4481: }
4482:
4483: static void
4484: clear_libcrypto_errors(void)
4485: {
4486: while (ERR_get_error() != 0)
4487: ;
4488: }
4489:
4490: /*
4491: * Translate OpenSSL error codes to determine whether
4492: * passphrase is required/incorrect.
4493: */
4494: static int
4495: convert_libcrypto_error(void)
4496: {
4497: /*
4498: * Some password errors are reported at the beginning
4499: * of the error queue.
4500: */
4501: if (translate_libcrypto_error(ERR_peek_error()) ==
4502: SSH_ERR_KEY_WRONG_PASSPHRASE)
4503: return SSH_ERR_KEY_WRONG_PASSPHRASE;
4504: return translate_libcrypto_error(ERR_peek_last_error());
4505: }
4506:
4507: static int
1.1 djm 4508: sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
1.8 djm 4509: const char *passphrase, struct sshkey **keyp)
1.1 djm 4510: {
4511: EVP_PKEY *pk = NULL;
4512: struct sshkey *prv = NULL;
4513: BIO *bio = NULL;
4514: int r;
4515:
1.32 djm 4516: if (keyp != NULL)
4517: *keyp = NULL;
1.1 djm 4518:
4519: if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
4520: return SSH_ERR_ALLOC_FAIL;
4521: if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
4522: (int)sshbuf_len(blob)) {
4523: r = SSH_ERR_ALLOC_FAIL;
4524: goto out;
4525: }
4526:
1.52 djm 4527: clear_libcrypto_errors();
1.1 djm 4528: if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
4529: (char *)passphrase)) == NULL) {
1.116 ! djm 4530: /*
! 4531: * libcrypto may return various ASN.1 errors when attempting
! 4532: * to parse a key with an incorrect passphrase.
! 4533: * Treat all format errors as "incorrect passphrase" if a
! 4534: * passphrase was supplied.
! 4535: */
1.71 djm 4536: if (passphrase != NULL && *passphrase != '\0')
4537: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4538: else
4539: r = convert_libcrypto_error();
1.1 djm 4540: goto out;
4541: }
1.69 djm 4542: if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA &&
1.1 djm 4543: (type == KEY_UNSPEC || type == KEY_RSA)) {
4544: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
4545: r = SSH_ERR_ALLOC_FAIL;
4546: goto out;
4547: }
4548: prv->rsa = EVP_PKEY_get1_RSA(pk);
4549: prv->type = KEY_RSA;
4550: #ifdef DEBUG_PK
4551: RSA_print_fp(stderr, prv->rsa, 8);
4552: #endif
4553: if (RSA_blinding_on(prv->rsa, NULL) != 1) {
4554: r = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 4555: goto out;
4556: }
1.69 djm 4557: if ((r = check_rsa_length(prv->rsa)) != 0)
1.1 djm 4558: goto out;
1.69 djm 4559: } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
1.1 djm 4560: (type == KEY_UNSPEC || type == KEY_DSA)) {
4561: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
4562: r = SSH_ERR_ALLOC_FAIL;
4563: goto out;
4564: }
4565: prv->dsa = EVP_PKEY_get1_DSA(pk);
4566: prv->type = KEY_DSA;
4567: #ifdef DEBUG_PK
4568: DSA_print_fp(stderr, prv->dsa, 8);
4569: #endif
1.69 djm 4570: } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC &&
1.1 djm 4571: (type == KEY_UNSPEC || type == KEY_ECDSA)) {
4572: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
4573: r = SSH_ERR_ALLOC_FAIL;
4574: goto out;
4575: }
4576: prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
4577: prv->type = KEY_ECDSA;
4578: prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
4579: if (prv->ecdsa_nid == -1 ||
4580: sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
4581: sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
4582: EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
4583: sshkey_ec_validate_private(prv->ecdsa) != 0) {
4584: r = SSH_ERR_INVALID_FORMAT;
4585: goto out;
4586: }
4587: #ifdef DEBUG_PK
4588: if (prv != NULL && prv->ecdsa != NULL)
4589: sshkey_dump_ec_key(prv->ecdsa);
4590: #endif
4591: } else {
4592: r = SSH_ERR_INVALID_FORMAT;
4593: goto out;
4594: }
4595: r = 0;
1.32 djm 4596: if (keyp != NULL) {
4597: *keyp = prv;
4598: prv = NULL;
4599: }
1.1 djm 4600: out:
4601: BIO_free(bio);
1.60 jsing 4602: EVP_PKEY_free(pk);
1.30 mmcc 4603: sshkey_free(prv);
1.1 djm 4604: return r;
4605: }
4606: #endif /* WITH_OPENSSL */
4607:
4608: int
4609: sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
4610: const char *passphrase, struct sshkey **keyp, char **commentp)
4611: {
1.42 djm 4612: int r = SSH_ERR_INTERNAL_ERROR;
4613:
1.32 djm 4614: if (keyp != NULL)
4615: *keyp = NULL;
1.1 djm 4616: if (commentp != NULL)
4617: *commentp = NULL;
4618:
4619: switch (type) {
4620: case KEY_ED25519:
1.62 markus 4621: case KEY_XMSS:
1.106 djm 4622: /* No fallback for new-format-only keys */
1.1 djm 4623: return sshkey_parse_private2(blob, type, passphrase,
4624: keyp, commentp);
1.106 djm 4625: default:
1.42 djm 4626: r = sshkey_parse_private2(blob, type, passphrase, keyp,
4627: commentp);
1.106 djm 4628: /* Only fallback to PEM parser if a format error occurred. */
4629: if (r != SSH_ERR_INVALID_FORMAT)
1.42 djm 4630: return r;
1.1 djm 4631: #ifdef WITH_OPENSSL
1.8 djm 4632: return sshkey_parse_private_pem_fileblob(blob, type,
4633: passphrase, keyp);
1.1 djm 4634: #else
4635: return SSH_ERR_INVALID_FORMAT;
4636: #endif /* WITH_OPENSSL */
4637: }
4638: }
4639:
4640: int
4641: sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
1.23 tim 4642: struct sshkey **keyp, char **commentp)
1.1 djm 4643: {
4644: if (keyp != NULL)
4645: *keyp = NULL;
4646: if (commentp != NULL)
4647: *commentp = NULL;
4648:
1.23 tim 4649: return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
4650: passphrase, keyp, commentp);
1.96 djm 4651: }
4652:
4653: void
4654: sshkey_sig_details_free(struct sshkey_sig_details *details)
4655: {
4656: freezero(details, sizeof(*details));
1.107 djm 4657: }
4658:
4659: int
4660: sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type,
4661: struct sshkey **pubkeyp)
4662: {
4663: int r = SSH_ERR_INTERNAL_ERROR;
4664:
4665: if (pubkeyp != NULL)
4666: *pubkeyp = NULL;
4667: /* only new-format private keys bundle a public key inside */
4668: if ((r = sshkey_parse_private2_pubkey(blob, type, pubkeyp)) != 0)
4669: return r;
4670: return 0;
1.1 djm 4671: }
1.62 markus 4672:
4673: #ifdef WITH_XMSS
4674: /*
4675: * serialize the key with the current state and forward the state
4676: * maxsign times.
4677: */
4678: int
1.77 djm 4679: sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
1.112 dtucker 4680: u_int32_t maxsign, int printerror)
1.62 markus 4681: {
4682: int r, rupdate;
4683:
4684: if (maxsign == 0 ||
4685: sshkey_type_plain(k->type) != KEY_XMSS)
4686: return sshkey_private_serialize_opt(k, b,
4687: SSHKEY_SERIALIZE_DEFAULT);
1.112 dtucker 4688: if ((r = sshkey_xmss_get_state(k, printerror)) != 0 ||
1.62 markus 4689: (r = sshkey_private_serialize_opt(k, b,
4690: SSHKEY_SERIALIZE_STATE)) != 0 ||
4691: (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
4692: goto out;
4693: r = 0;
4694: out:
1.112 dtucker 4695: if ((rupdate = sshkey_xmss_update_state(k, printerror)) != 0) {
1.62 markus 4696: if (r == 0)
4697: r = rupdate;
4698: }
4699: return r;
4700: }
4701:
4702: u_int32_t
4703: sshkey_signatures_left(const struct sshkey *k)
4704: {
4705: if (sshkey_type_plain(k->type) == KEY_XMSS)
4706: return sshkey_xmss_signatures_left(k);
4707: return 0;
4708: }
4709:
4710: int
4711: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4712: {
4713: if (sshkey_type_plain(k->type) != KEY_XMSS)
4714: return SSH_ERR_INVALID_ARGUMENT;
4715: return sshkey_xmss_enable_maxsign(k, maxsign);
4716: }
4717:
4718: int
4719: sshkey_set_filename(struct sshkey *k, const char *filename)
4720: {
4721: if (k == NULL)
4722: return SSH_ERR_INVALID_ARGUMENT;
4723: if (sshkey_type_plain(k->type) != KEY_XMSS)
4724: return 0;
4725: if (filename == NULL)
4726: return SSH_ERR_INVALID_ARGUMENT;
4727: if ((k->xmss_filename = strdup(filename)) == NULL)
4728: return SSH_ERR_ALLOC_FAIL;
4729: return 0;
4730: }
4731: #else
4732: int
1.76 djm 4733: sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
1.112 dtucker 4734: u_int32_t maxsign, int printerror)
1.62 markus 4735: {
4736: return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
4737: }
4738:
4739: u_int32_t
4740: sshkey_signatures_left(const struct sshkey *k)
4741: {
4742: return 0;
4743: }
4744:
4745: int
4746: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4747: {
4748: return SSH_ERR_INVALID_ARGUMENT;
4749: }
4750:
4751: int
4752: sshkey_set_filename(struct sshkey *k, const char *filename)
4753: {
4754: if (k == NULL)
4755: return SSH_ERR_INVALID_ARGUMENT;
4756: return 0;
4757: }
4758: #endif /* WITH_XMSS */