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