Annotation of src/usr.bin/ssh/sshkey.c, Revision 1.142
1.142 ! djm 1: /* $OpenBSD: sshkey.c,v 1.141 2023/12/20 00:06:25 jsg 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>
1.138 djm 41: #include <stdlib.h>
1.1 djm 42: #include <string.h>
43: #include <util.h>
1.13 deraadt 44: #include <limits.h>
1.7 djm 45: #include <resolv.h>
1.1 djm 46:
47: #include "ssh2.h"
48: #include "ssherr.h"
49: #include "misc.h"
50: #include "sshbuf.h"
51: #include "cipher.h"
52: #include "digest.h"
53: #define SSHKEY_INTERNAL
54: #include "sshkey.h"
1.11 djm 55: #include "match.h"
1.86 djm 56: #include "ssh-sk.h"
1.1 djm 57:
1.74 dtucker 58: #ifdef WITH_XMSS
59: #include "sshkey-xmss.h"
1.62 markus 60: #include "xmss_fast.h"
1.74 dtucker 61: #endif
1.62 markus 62:
1.1 djm 63: /* openssh private key file format */
64: #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
65: #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
66: #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
67: #define MARK_END_LEN (sizeof(MARK_END) - 1)
68: #define KDFNAME "bcrypt"
69: #define AUTH_MAGIC "openssh-key-v1"
70: #define SALT_LEN 16
1.56 djm 71: #define DEFAULT_CIPHERNAME "aes256-ctr"
1.137 djm 72: #define DEFAULT_ROUNDS 24
1.1 djm 73:
74: /* Version identification string for SSH v1 identity files. */
75: #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
76:
1.76 djm 77: /*
78: * Constants relating to "shielding" support; protection of keys expected
79: * to remain in memory for long durations
80: */
81: #define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024)
82: #define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */
83: #define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512
84:
85: int sshkey_private_serialize_opt(struct sshkey *key,
1.62 markus 86: struct sshbuf *buf, enum sshkey_serialize_rep);
1.14 djm 87: static int sshkey_from_blob_internal(struct sshbuf *buf,
1.1 djm 88: struct sshkey **keyp, int allow_cert);
89:
90: /* Supported key types */
1.123 djm 91: extern const struct sshkey_impl sshkey_ed25519_impl;
92: extern const struct sshkey_impl sshkey_ed25519_cert_impl;
93: extern const struct sshkey_impl sshkey_ed25519_sk_impl;
94: extern const struct sshkey_impl sshkey_ed25519_sk_cert_impl;
95: #ifdef WITH_OPENSSL
96: extern const struct sshkey_impl sshkey_ecdsa_sk_impl;
97: extern const struct sshkey_impl sshkey_ecdsa_sk_cert_impl;
98: extern const struct sshkey_impl sshkey_ecdsa_sk_webauthn_impl;
99: extern const struct sshkey_impl sshkey_ecdsa_nistp256_impl;
100: extern const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl;
101: extern const struct sshkey_impl sshkey_ecdsa_nistp384_impl;
102: extern const struct sshkey_impl sshkey_ecdsa_nistp384_cert_impl;
103: extern const struct sshkey_impl sshkey_ecdsa_nistp521_impl;
104: extern const struct sshkey_impl sshkey_ecdsa_nistp521_cert_impl;
105: extern const struct sshkey_impl sshkey_rsa_impl;
106: extern const struct sshkey_impl sshkey_rsa_cert_impl;
107: extern const struct sshkey_impl sshkey_rsa_sha256_impl;
108: extern const struct sshkey_impl sshkey_rsa_sha256_cert_impl;
109: extern const struct sshkey_impl sshkey_rsa_sha512_impl;
110: extern const struct sshkey_impl sshkey_rsa_sha512_cert_impl;
1.142 ! djm 111: # ifdef WITH_DSA
1.123 djm 112: extern const struct sshkey_impl sshkey_dss_impl;
113: extern const struct sshkey_impl sshkey_dsa_cert_impl;
1.142 ! djm 114: # endif
1.123 djm 115: #endif /* WITH_OPENSSL */
1.62 markus 116: #ifdef WITH_XMSS
1.123 djm 117: extern const struct sshkey_impl sshkey_xmss_impl;
118: extern const struct sshkey_impl sshkey_xmss_cert_impl;
119: #endif
120:
121: const struct sshkey_impl * const keyimpls[] = {
122: &sshkey_ed25519_impl,
123: &sshkey_ed25519_cert_impl,
124: &sshkey_ed25519_sk_impl,
125: &sshkey_ed25519_sk_cert_impl,
126: #ifdef WITH_OPENSSL
127: &sshkey_ecdsa_nistp256_impl,
128: &sshkey_ecdsa_nistp256_cert_impl,
129: &sshkey_ecdsa_nistp384_impl,
130: &sshkey_ecdsa_nistp384_cert_impl,
131: &sshkey_ecdsa_nistp521_impl,
132: &sshkey_ecdsa_nistp521_cert_impl,
133: &sshkey_ecdsa_sk_impl,
134: &sshkey_ecdsa_sk_cert_impl,
135: &sshkey_ecdsa_sk_webauthn_impl,
1.142 ! djm 136: # ifdef WITH_DSA
1.123 djm 137: &sshkey_dss_impl,
138: &sshkey_dsa_cert_impl,
1.142 ! djm 139: # endif
1.123 djm 140: &sshkey_rsa_impl,
141: &sshkey_rsa_cert_impl,
142: &sshkey_rsa_sha256_impl,
143: &sshkey_rsa_sha256_cert_impl,
144: &sshkey_rsa_sha512_impl,
145: &sshkey_rsa_sha512_cert_impl,
1.1 djm 146: #endif /* WITH_OPENSSL */
1.123 djm 147: #ifdef WITH_XMSS
148: &sshkey_xmss_impl,
149: &sshkey_xmss_cert_impl,
150: #endif
151: NULL
1.1 djm 152: };
153:
1.123 djm 154: static const struct sshkey_impl *
155: sshkey_impl_from_type(int type)
156: {
157: int i;
158:
159: for (i = 0; keyimpls[i] != NULL; i++) {
160: if (keyimpls[i]->type == type)
161: return keyimpls[i];
162: }
163: return NULL;
164: }
165:
166: static const struct sshkey_impl *
167: sshkey_impl_from_type_nid(int type, int nid)
168: {
169: int i;
170:
171: for (i = 0; keyimpls[i] != NULL; i++) {
172: if (keyimpls[i]->type == type &&
173: (keyimpls[i]->nid == 0 || keyimpls[i]->nid == nid))
174: return keyimpls[i];
175: }
176: return NULL;
177: }
178:
1.126 djm 179: static const struct sshkey_impl *
180: sshkey_impl_from_key(const struct sshkey *k)
181: {
182: if (k == NULL)
183: return NULL;
184: return sshkey_impl_from_type_nid(k->type, k->ecdsa_nid);
185: }
186:
1.1 djm 187: const char *
188: sshkey_type(const struct sshkey *k)
189: {
1.123 djm 190: const struct sshkey_impl *impl;
1.1 djm 191:
1.126 djm 192: if ((impl = sshkey_impl_from_key(k)) == NULL)
1.123 djm 193: return "unknown";
194: return impl->shortname;
1.1 djm 195: }
196:
197: static const char *
198: sshkey_ssh_name_from_type_nid(int type, int nid)
199: {
1.123 djm 200: const struct sshkey_impl *impl;
1.1 djm 201:
1.123 djm 202: if ((impl = sshkey_impl_from_type_nid(type, nid)) == NULL)
203: return "ssh-unknown";
204: return impl->name;
1.1 djm 205: }
206:
207: int
208: sshkey_type_is_cert(int type)
209: {
1.123 djm 210: const struct sshkey_impl *impl;
1.1 djm 211:
1.123 djm 212: if ((impl = sshkey_impl_from_type(type)) == NULL)
213: return 0;
214: return impl->cert;
1.1 djm 215: }
216:
217: const char *
218: sshkey_ssh_name(const struct sshkey *k)
219: {
220: return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
221: }
222:
223: const char *
224: sshkey_ssh_name_plain(const struct sshkey *k)
225: {
226: return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type),
227: k->ecdsa_nid);
228: }
229:
230: int
231: sshkey_type_from_name(const char *name)
232: {
1.123 djm 233: int i;
234: const struct sshkey_impl *impl;
1.1 djm 235:
1.123 djm 236: for (i = 0; keyimpls[i] != NULL; i++) {
237: impl = keyimpls[i];
1.1 djm 238: /* Only allow shortname matches for plain key types */
1.123 djm 239: if ((impl->name != NULL && strcmp(name, impl->name) == 0) ||
240: (!impl->cert && strcasecmp(impl->shortname, name) == 0))
241: return impl->type;
1.1 djm 242: }
243: return KEY_UNSPEC;
244: }
245:
1.85 djm 246: static int
247: key_type_is_ecdsa_variant(int type)
248: {
249: switch (type) {
250: case KEY_ECDSA:
251: case KEY_ECDSA_CERT:
252: case KEY_ECDSA_SK:
253: case KEY_ECDSA_SK_CERT:
254: return 1;
255: }
256: return 0;
257: }
258:
1.1 djm 259: int
260: sshkey_ecdsa_nid_from_name(const char *name)
261: {
1.123 djm 262: int i;
1.1 djm 263:
1.123 djm 264: for (i = 0; keyimpls[i] != NULL; i++) {
265: if (!key_type_is_ecdsa_variant(keyimpls[i]->type))
1.4 djm 266: continue;
1.123 djm 267: if (keyimpls[i]->name != NULL &&
268: strcmp(name, keyimpls[i]->name) == 0)
269: return keyimpls[i]->nid;
1.4 djm 270: }
1.1 djm 271: return -1;
1.120 djm 272: }
273:
274: int
275: sshkey_match_keyname_to_sigalgs(const char *keyname, const char *sigalgs)
276: {
277: int ktype;
278:
279: if (sigalgs == NULL || *sigalgs == '\0' ||
280: (ktype = sshkey_type_from_name(keyname)) == KEY_UNSPEC)
281: return 0;
282: else if (ktype == KEY_RSA) {
283: return match_pattern_list("ssh-rsa", sigalgs, 0) == 1 ||
284: match_pattern_list("rsa-sha2-256", sigalgs, 0) == 1 ||
285: match_pattern_list("rsa-sha2-512", sigalgs, 0) == 1;
286: } else if (ktype == KEY_RSA_CERT) {
287: return match_pattern_list("ssh-rsa-cert-v01@openssh.com",
288: sigalgs, 0) == 1 ||
289: match_pattern_list("rsa-sha2-256-cert-v01@openssh.com",
290: sigalgs, 0) == 1 ||
291: match_pattern_list("rsa-sha2-512-cert-v01@openssh.com",
292: sigalgs, 0) == 1;
293: } else
294: return match_pattern_list(keyname, sigalgs, 0) == 1;
1.1 djm 295: }
296:
297: char *
1.45 djm 298: sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
1.1 djm 299: {
300: char *tmp, *ret = NULL;
1.123 djm 301: size_t i, nlen, rlen = 0;
302: const struct sshkey_impl *impl;
1.1 djm 303:
1.123 djm 304: for (i = 0; keyimpls[i] != NULL; i++) {
305: impl = keyimpls[i];
306: if (impl->name == NULL)
1.45 djm 307: continue;
1.123 djm 308: if (!include_sigonly && impl->sigonly)
1.1 djm 309: continue;
1.123 djm 310: if ((certs_only && !impl->cert) || (plain_only && impl->cert))
1.1 djm 311: continue;
312: if (ret != NULL)
1.38 djm 313: ret[rlen++] = sep;
1.123 djm 314: nlen = strlen(impl->name);
1.1 djm 315: if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
316: free(ret);
317: return NULL;
318: }
319: ret = tmp;
1.123 djm 320: memcpy(ret + rlen, impl->name, nlen + 1);
1.1 djm 321: rlen += nlen;
322: }
323: return ret;
324: }
325:
326: int
1.136 djm 327: sshkey_names_valid2(const char *names, int allow_wildcard, int plain_only)
1.1 djm 328: {
329: char *s, *cp, *p;
1.123 djm 330: const struct sshkey_impl *impl;
331: int i, type;
1.1 djm 332:
333: if (names == NULL || strcmp(names, "") == 0)
334: return 0;
335: if ((s = cp = strdup(names)) == NULL)
336: return 0;
337: for ((p = strsep(&cp, ",")); p && *p != '\0';
338: (p = strsep(&cp, ","))) {
1.11 djm 339: type = sshkey_type_from_name(p);
340: if (type == KEY_UNSPEC) {
341: if (allow_wildcard) {
342: /*
343: * Try matching key types against the string.
344: * If any has a positive or negative match then
345: * the component is accepted.
346: */
1.123 djm 347: impl = NULL;
348: for (i = 0; keyimpls[i] != NULL; i++) {
349: if (match_pattern_list(
350: keyimpls[i]->name, p, 0) != 0) {
351: impl = keyimpls[i];
1.11 djm 352: break;
1.123 djm 353: }
1.11 djm 354: }
1.123 djm 355: if (impl != NULL)
1.11 djm 356: continue;
357: }
1.136 djm 358: free(s);
359: return 0;
360: } else if (plain_only && sshkey_type_is_cert(type)) {
1.1 djm 361: free(s);
362: return 0;
363: }
364: }
365: free(s);
366: return 1;
367: }
368:
369: u_int
370: sshkey_size(const struct sshkey *k)
371: {
1.123 djm 372: const struct sshkey_impl *impl;
1.69 djm 373:
1.126 djm 374: if ((impl = sshkey_impl_from_key(k)) == NULL)
1.123 djm 375: return 0;
376: if (impl->funcs->size != NULL)
377: return impl->funcs->size(k);
378: return impl->keybits;
1.1 djm 379: }
380:
381: static int
382: sshkey_type_is_valid_ca(int type)
383: {
1.123 djm 384: const struct sshkey_impl *impl;
385:
386: if ((impl = sshkey_impl_from_type(type)) == NULL)
1.1 djm 387: return 0;
1.123 djm 388: /* All non-certificate types may act as CAs */
389: return !impl->cert;
1.1 djm 390: }
391:
392: int
393: sshkey_is_cert(const struct sshkey *k)
394: {
395: if (k == NULL)
396: return 0;
397: return sshkey_type_is_cert(k->type);
398: }
399:
1.90 markus 400: int
401: sshkey_is_sk(const struct sshkey *k)
402: {
403: if (k == NULL)
404: return 0;
405: switch (sshkey_type_plain(k->type)) {
406: case KEY_ECDSA_SK:
407: case KEY_ED25519_SK:
408: return 1;
409: default:
410: return 0;
411: }
412: }
413:
1.1 djm 414: /* Return the cert-less equivalent to a certified key type */
415: int
416: sshkey_type_plain(int type)
417: {
418: switch (type) {
419: case KEY_RSA_CERT:
420: return KEY_RSA;
421: case KEY_DSA_CERT:
422: return KEY_DSA;
423: case KEY_ECDSA_CERT:
424: return KEY_ECDSA;
1.85 djm 425: case KEY_ECDSA_SK_CERT:
426: return KEY_ECDSA_SK;
1.1 djm 427: case KEY_ED25519_CERT:
428: return KEY_ED25519;
1.90 markus 429: case KEY_ED25519_SK_CERT:
430: return KEY_ED25519_SK;
1.62 markus 431: case KEY_XMSS_CERT:
432: return KEY_XMSS;
1.1 djm 433: default:
434: return type;
435: }
436: }
437:
1.131 djm 438: /* Return the cert equivalent to a plain key type */
439: static int
440: sshkey_type_certified(int type)
441: {
442: switch (type) {
443: case KEY_RSA:
444: return KEY_RSA_CERT;
445: case KEY_DSA:
446: return KEY_DSA_CERT;
447: case KEY_ECDSA:
448: return KEY_ECDSA_CERT;
449: case KEY_ECDSA_SK:
450: return KEY_ECDSA_SK_CERT;
451: case KEY_ED25519:
452: return KEY_ED25519_CERT;
453: case KEY_ED25519_SK:
454: return KEY_ED25519_SK_CERT;
455: case KEY_XMSS:
456: return KEY_XMSS_CERT;
457: default:
458: return -1;
459: }
460: }
461:
1.1 djm 462: #ifdef WITH_OPENSSL
463: /* XXX: these are really begging for a table-driven approach */
464: int
465: sshkey_curve_name_to_nid(const char *name)
466: {
467: if (strcmp(name, "nistp256") == 0)
468: return NID_X9_62_prime256v1;
469: else if (strcmp(name, "nistp384") == 0)
470: return NID_secp384r1;
471: else if (strcmp(name, "nistp521") == 0)
472: return NID_secp521r1;
473: else
474: return -1;
475: }
476:
477: u_int
478: sshkey_curve_nid_to_bits(int nid)
479: {
480: switch (nid) {
481: case NID_X9_62_prime256v1:
482: return 256;
483: case NID_secp384r1:
484: return 384;
485: case NID_secp521r1:
486: return 521;
487: default:
488: return 0;
489: }
490: }
491:
492: int
493: sshkey_ecdsa_bits_to_nid(int bits)
494: {
495: switch (bits) {
496: case 256:
497: return NID_X9_62_prime256v1;
498: case 384:
499: return NID_secp384r1;
500: case 521:
501: return NID_secp521r1;
502: default:
503: return -1;
504: }
505: }
506:
507: const char *
508: sshkey_curve_nid_to_name(int nid)
509: {
510: switch (nid) {
511: case NID_X9_62_prime256v1:
512: return "nistp256";
513: case NID_secp384r1:
514: return "nistp384";
515: case NID_secp521r1:
516: return "nistp521";
517: default:
518: return NULL;
519: }
520: }
521:
522: int
523: sshkey_ec_nid_to_hash_alg(int nid)
524: {
525: int kbits = sshkey_curve_nid_to_bits(nid);
526:
527: if (kbits <= 0)
528: return -1;
529:
530: /* RFC5656 section 6.2.1 */
531: if (kbits <= 256)
532: return SSH_DIGEST_SHA256;
533: else if (kbits <= 384)
534: return SSH_DIGEST_SHA384;
535: else
536: return SSH_DIGEST_SHA512;
537: }
538: #endif /* WITH_OPENSSL */
539:
540: static void
541: cert_free(struct sshkey_cert *cert)
542: {
543: u_int i;
544:
545: if (cert == NULL)
546: return;
1.31 mmcc 547: sshbuf_free(cert->certblob);
548: sshbuf_free(cert->critical);
549: sshbuf_free(cert->extensions);
1.29 mmcc 550: free(cert->key_id);
1.1 djm 551: for (i = 0; i < cert->nprincipals; i++)
552: free(cert->principals[i]);
1.29 mmcc 553: free(cert->principals);
1.30 mmcc 554: sshkey_free(cert->signature_key);
1.67 djm 555: free(cert->signature_type);
1.61 jsing 556: freezero(cert, sizeof(*cert));
1.1 djm 557: }
558:
559: static struct sshkey_cert *
560: cert_new(void)
561: {
562: struct sshkey_cert *cert;
563:
564: if ((cert = calloc(1, sizeof(*cert))) == NULL)
565: return NULL;
566: if ((cert->certblob = sshbuf_new()) == NULL ||
567: (cert->critical = sshbuf_new()) == NULL ||
568: (cert->extensions = sshbuf_new()) == NULL) {
569: cert_free(cert);
570: return NULL;
571: }
572: cert->key_id = NULL;
573: cert->principals = NULL;
574: cert->signature_key = NULL;
1.67 djm 575: cert->signature_type = NULL;
1.1 djm 576: return cert;
577: }
578:
579: struct sshkey *
580: sshkey_new(int type)
581: {
582: struct sshkey *k;
1.123 djm 583: const struct sshkey_impl *impl = NULL;
584:
585: if (type != KEY_UNSPEC &&
586: (impl = sshkey_impl_from_type(type)) == NULL)
587: return NULL;
1.1 djm 588:
1.123 djm 589: /* All non-certificate types may act as CAs */
1.1 djm 590: if ((k = calloc(1, sizeof(*k))) == NULL)
591: return NULL;
592: k->type = type;
593: k->ecdsa_nid = -1;
1.123 djm 594: if (impl != NULL && impl->funcs->alloc != NULL) {
595: if (impl->funcs->alloc(k) != 0) {
1.1 djm 596: free(k);
597: return NULL;
598: }
599: }
600: if (sshkey_is_cert(k)) {
601: if ((k->cert = cert_new()) == NULL) {
602: sshkey_free(k);
603: return NULL;
604: }
605: }
606:
607: return k;
608: }
609:
1.124 djm 610: /* Frees common FIDO fields */
611: void
612: sshkey_sk_cleanup(struct sshkey *k)
613: {
614: free(k->sk_application);
615: sshbuf_free(k->sk_key_handle);
616: sshbuf_free(k->sk_reserved);
617: k->sk_application = NULL;
618: k->sk_key_handle = k->sk_reserved = NULL;
619: }
620:
1.126 djm 621: static void
622: sshkey_free_contents(struct sshkey *k)
1.1 djm 623: {
1.123 djm 624: const struct sshkey_impl *impl;
625:
1.1 djm 626: if (k == NULL)
627: return;
1.123 djm 628: if ((impl = sshkey_impl_from_type(k->type)) != NULL &&
629: impl->funcs->cleanup != NULL)
630: impl->funcs->cleanup(k);
1.1 djm 631: if (sshkey_is_cert(k))
632: cert_free(k->cert);
1.76 djm 633: freezero(k->shielded_private, k->shielded_len);
634: freezero(k->shield_prekey, k->shield_prekey_len);
1.126 djm 635: }
636:
637: void
638: sshkey_free(struct sshkey *k)
639: {
640: sshkey_free_contents(k);
1.61 jsing 641: freezero(k, sizeof(*k));
1.1 djm 642: }
643:
644: static int
645: cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
646: {
647: if (a == NULL && b == NULL)
648: return 1;
649: if (a == NULL || b == NULL)
650: return 0;
651: if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob))
652: return 0;
653: if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob),
654: sshbuf_len(a->certblob)) != 0)
655: return 0;
656: return 1;
657: }
658:
1.124 djm 659: /* Compares FIDO-specific pubkey fields only */
660: int
661: sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b)
662: {
663: if (a->sk_application == NULL || b->sk_application == NULL)
664: return 0;
665: if (strcmp(a->sk_application, b->sk_application) != 0)
666: return 0;
667: return 1;
668: }
669:
1.1 djm 670: /*
671: * Compare public portions of key only, allowing comparisons between
672: * certificates and plain keys too.
673: */
674: int
675: sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
676: {
1.124 djm 677: const struct sshkey_impl *impl;
1.1 djm 678:
679: if (a == NULL || b == NULL ||
680: sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
681: return 0;
1.124 djm 682: if ((impl = sshkey_impl_from_type(a->type)) == NULL)
1.1 djm 683: return 0;
1.124 djm 684: return impl->funcs->equal(a, b);
1.1 djm 685: }
686:
687: int
688: sshkey_equal(const struct sshkey *a, const struct sshkey *b)
689: {
690: if (a == NULL || b == NULL || a->type != b->type)
691: return 0;
692: if (sshkey_is_cert(a)) {
693: if (!cert_compare(a->cert, b->cert))
694: return 0;
695: }
696: return sshkey_equal_public(a, b);
697: }
698:
1.125 djm 699:
700: /* Serialise common FIDO key parts */
701: int
702: sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b)
703: {
704: int r;
705:
706: if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0)
707: return r;
708:
709: return 0;
710: }
711:
1.1 djm 712: static int
1.62 markus 713: to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
714: enum sshkey_serialize_rep opts)
1.1 djm 715: {
716: int type, ret = SSH_ERR_INTERNAL_ERROR;
717: const char *typename;
1.125 djm 718: const struct sshkey_impl *impl;
1.1 djm 719:
720: if (key == NULL)
721: return SSH_ERR_INVALID_ARGUMENT;
722:
1.125 djm 723: type = force_plain ? sshkey_type_plain(key->type) : key->type;
724:
725: if (sshkey_type_is_cert(type)) {
1.19 djm 726: if (key->cert == NULL)
727: return SSH_ERR_EXPECTED_CERT;
728: if (sshbuf_len(key->cert->certblob) == 0)
729: return SSH_ERR_KEY_LACKS_CERTBLOB;
1.1 djm 730: /* Use the existing blob */
731: if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
732: return ret;
1.125 djm 733: return 0;
734: }
735: if ((impl = sshkey_impl_from_type(type)) == NULL)
1.1 djm 736: return SSH_ERR_KEY_TYPE_UNKNOWN;
1.125 djm 737:
738: typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
1.129 djm 739: if ((ret = sshbuf_put_cstring(b, typename)) != 0)
740: return ret;
741: return impl->funcs->serialize_public(key, b, opts);
1.1 djm 742: }
743:
744: int
1.14 djm 745: sshkey_putb(const struct sshkey *key, struct sshbuf *b)
1.1 djm 746: {
1.62 markus 747: return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 748: }
749:
750: int
1.62 markus 751: sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b,
752: enum sshkey_serialize_rep opts)
1.14 djm 753: {
754: struct sshbuf *tmp;
755: int r;
756:
757: if ((tmp = sshbuf_new()) == NULL)
758: return SSH_ERR_ALLOC_FAIL;
1.62 markus 759: r = to_blob_buf(key, tmp, 0, opts);
1.14 djm 760: if (r == 0)
761: r = sshbuf_put_stringb(b, tmp);
762: sshbuf_free(tmp);
763: return r;
764: }
765:
766: int
1.62 markus 767: sshkey_puts(const struct sshkey *key, struct sshbuf *b)
768: {
769: return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT);
770: }
771:
772: int
1.14 djm 773: sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)
1.1 djm 774: {
1.62 markus 775: return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 776: }
777:
778: static int
1.62 markus 779: to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain,
780: enum sshkey_serialize_rep opts)
1.1 djm 781: {
782: int ret = SSH_ERR_INTERNAL_ERROR;
783: size_t len;
784: struct sshbuf *b = NULL;
785:
786: if (lenp != NULL)
787: *lenp = 0;
788: if (blobp != NULL)
789: *blobp = NULL;
790: if ((b = sshbuf_new()) == NULL)
791: return SSH_ERR_ALLOC_FAIL;
1.62 markus 792: if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0)
1.1 djm 793: goto out;
794: len = sshbuf_len(b);
795: if (lenp != NULL)
796: *lenp = len;
797: if (blobp != NULL) {
798: if ((*blobp = malloc(len)) == NULL) {
799: ret = SSH_ERR_ALLOC_FAIL;
800: goto out;
801: }
802: memcpy(*blobp, sshbuf_ptr(b), len);
803: }
804: ret = 0;
805: out:
806: sshbuf_free(b);
807: return ret;
808: }
809:
810: int
811: sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
812: {
1.62 markus 813: return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 814: }
815:
816: int
817: sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
818: {
1.62 markus 819: return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 820: }
821:
822: int
1.7 djm 823: sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
1.1 djm 824: u_char **retp, size_t *lenp)
825: {
826: u_char *blob = NULL, *ret = NULL;
827: size_t blob_len = 0;
1.7 djm 828: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 829:
830: if (retp != NULL)
831: *retp = NULL;
832: if (lenp != NULL)
833: *lenp = 0;
1.7 djm 834: if (ssh_digest_bytes(dgst_alg) == 0) {
1.1 djm 835: r = SSH_ERR_INVALID_ARGUMENT;
836: goto out;
837: }
1.62 markus 838: if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT))
839: != 0)
1.1 djm 840: goto out;
841: if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
842: r = SSH_ERR_ALLOC_FAIL;
843: goto out;
844: }
1.7 djm 845: if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
1.1 djm 846: ret, SSH_DIGEST_MAX_LENGTH)) != 0)
847: goto out;
848: /* success */
849: if (retp != NULL) {
850: *retp = ret;
851: ret = NULL;
852: }
853: if (lenp != NULL)
1.7 djm 854: *lenp = ssh_digest_bytes(dgst_alg);
1.1 djm 855: r = 0;
856: out:
857: free(ret);
1.100 jsg 858: if (blob != NULL)
859: freezero(blob, blob_len);
1.1 djm 860: return r;
861: }
862:
863: static char *
1.7 djm 864: fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
865: {
866: char *ret;
867: size_t plen = strlen(alg) + 1;
868: size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
869:
870: if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
871: return NULL;
872: strlcpy(ret, alg, rlen);
873: strlcat(ret, ":", rlen);
874: if (dgst_raw_len == 0)
875: return ret;
1.79 dtucker 876: if (b64_ntop(dgst_raw, dgst_raw_len, ret + plen, rlen - plen) == -1) {
1.61 jsing 877: freezero(ret, rlen);
1.7 djm 878: return NULL;
879: }
880: /* Trim padding characters from end */
881: ret[strcspn(ret, "=")] = '\0';
882: return ret;
883: }
884:
885: static char *
886: fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
1.1 djm 887: {
1.7 djm 888: char *retval, hex[5];
889: size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
1.1 djm 890:
1.7 djm 891: if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
1.1 djm 892: return NULL;
1.7 djm 893: strlcpy(retval, alg, rlen);
894: strlcat(retval, ":", rlen);
1.1 djm 895: for (i = 0; i < dgst_raw_len; i++) {
1.7 djm 896: snprintf(hex, sizeof(hex), "%s%02x",
897: i > 0 ? ":" : "", dgst_raw[i]);
898: strlcat(retval, hex, rlen);
1.1 djm 899: }
900: return retval;
901: }
902:
903: static char *
904: fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
905: {
906: char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
907: char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
908: 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
909: u_int i, j = 0, rounds, seed = 1;
910: char *retval;
911:
912: rounds = (dgst_raw_len / 2) + 1;
913: if ((retval = calloc(rounds, 6)) == NULL)
914: return NULL;
915: retval[j++] = 'x';
916: for (i = 0; i < rounds; i++) {
917: u_int idx0, idx1, idx2, idx3, idx4;
918: if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
919: idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
920: seed) % 6;
921: idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
922: idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
923: (seed / 6)) % 6;
924: retval[j++] = vowels[idx0];
925: retval[j++] = consonants[idx1];
926: retval[j++] = vowels[idx2];
927: if ((i + 1) < rounds) {
928: idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
929: idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
930: retval[j++] = consonants[idx3];
931: retval[j++] = '-';
932: retval[j++] = consonants[idx4];
933: seed = ((seed * 5) +
934: ((((u_int)(dgst_raw[2 * i])) * 7) +
935: ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
936: }
937: } else {
938: idx0 = seed % 6;
939: idx1 = 16;
940: idx2 = seed / 6;
941: retval[j++] = vowels[idx0];
942: retval[j++] = consonants[idx1];
943: retval[j++] = vowels[idx2];
944: }
945: }
946: retval[j++] = 'x';
947: retval[j++] = '\0';
948: return retval;
949: }
950:
951: /*
952: * Draw an ASCII-Art representing the fingerprint so human brain can
953: * profit from its built-in pattern recognition ability.
954: * This technique is called "random art" and can be found in some
955: * scientific publications like this original paper:
956: *
957: * "Hash Visualization: a New Technique to improve Real-World Security",
958: * Perrig A. and Song D., 1999, International Workshop on Cryptographic
959: * Techniques and E-Commerce (CrypTEC '99)
960: * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
961: *
962: * The subject came up in a talk by Dan Kaminsky, too.
963: *
964: * If you see the picture is different, the key is different.
965: * If the picture looks the same, you still know nothing.
966: *
967: * The algorithm used here is a worm crawling over a discrete plane,
968: * leaving a trace (augmenting the field) everywhere it goes.
969: * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
970: * makes the respective movement vector be ignored for this turn.
971: * Graphs are not unambiguous, because circles in graphs can be
972: * walked in either direction.
973: */
974:
975: /*
976: * Field sizes for the random art. Have to be odd, so the starting point
977: * can be in the exact middle of the picture, and FLDBASE should be >=8 .
978: * Else pictures would be too dense, and drawing the frame would
979: * fail, too, because the key type would not fit in anymore.
980: */
981: #define FLDBASE 8
982: #define FLDSIZE_Y (FLDBASE + 1)
983: #define FLDSIZE_X (FLDBASE * 2 + 1)
984: static char *
1.7 djm 985: fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
1.1 djm 986: const struct sshkey *k)
987: {
988: /*
989: * Chars to be used after each other every time the worm
990: * intersects with itself. Matter of taste.
991: */
992: char *augmentation_string = " .o+=*BOX@%&#/^SE";
1.7 djm 993: char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
1.1 djm 994: u_char field[FLDSIZE_X][FLDSIZE_Y];
1.7 djm 995: size_t i, tlen, hlen;
1.1 djm 996: u_int b;
1.3 djm 997: int x, y, r;
1.1 djm 998: size_t len = strlen(augmentation_string) - 1;
999:
1000: if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
1001: return NULL;
1002:
1003: /* initialize field */
1004: memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
1005: x = FLDSIZE_X / 2;
1006: y = FLDSIZE_Y / 2;
1007:
1008: /* process raw key */
1009: for (i = 0; i < dgst_raw_len; i++) {
1010: int input;
1011: /* each byte conveys four 2-bit move commands */
1012: input = dgst_raw[i];
1013: for (b = 0; b < 4; b++) {
1014: /* evaluate 2 bit, rest is shifted later */
1015: x += (input & 0x1) ? 1 : -1;
1016: y += (input & 0x2) ? 1 : -1;
1017:
1018: /* assure we are still in bounds */
1.37 deraadt 1019: x = MAXIMUM(x, 0);
1020: y = MAXIMUM(y, 0);
1021: x = MINIMUM(x, FLDSIZE_X - 1);
1022: y = MINIMUM(y, FLDSIZE_Y - 1);
1.1 djm 1023:
1024: /* augment the field */
1025: if (field[x][y] < len - 2)
1026: field[x][y]++;
1027: input = input >> 2;
1028: }
1029: }
1030:
1031: /* mark starting point and end point*/
1032: field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
1033: field[x][y] = len;
1034:
1.3 djm 1035: /* assemble title */
1036: r = snprintf(title, sizeof(title), "[%s %u]",
1037: sshkey_type(k), sshkey_size(k));
1038: /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
1039: if (r < 0 || r > (int)sizeof(title))
1.7 djm 1040: r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
1041: tlen = (r <= 0) ? 0 : strlen(title);
1042:
1043: /* assemble hash ID. */
1044: r = snprintf(hash, sizeof(hash), "[%s]", alg);
1045: hlen = (r <= 0) ? 0 : strlen(hash);
1.1 djm 1046:
1047: /* output upper border */
1.3 djm 1048: p = retval;
1049: *p++ = '+';
1050: for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
1051: *p++ = '-';
1052: memcpy(p, title, tlen);
1053: p += tlen;
1.7 djm 1054: for (i += tlen; i < FLDSIZE_X; i++)
1.1 djm 1055: *p++ = '-';
1056: *p++ = '+';
1057: *p++ = '\n';
1058:
1059: /* output content */
1060: for (y = 0; y < FLDSIZE_Y; y++) {
1061: *p++ = '|';
1062: for (x = 0; x < FLDSIZE_X; x++)
1.37 deraadt 1063: *p++ = augmentation_string[MINIMUM(field[x][y], len)];
1.1 djm 1064: *p++ = '|';
1065: *p++ = '\n';
1066: }
1067:
1068: /* output lower border */
1069: *p++ = '+';
1.7 djm 1070: for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
1071: *p++ = '-';
1072: memcpy(p, hash, hlen);
1073: p += hlen;
1074: for (i += hlen; i < FLDSIZE_X; i++)
1.1 djm 1075: *p++ = '-';
1076: *p++ = '+';
1077:
1078: return retval;
1079: }
1080:
1081: char *
1.7 djm 1082: sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1.1 djm 1083: enum sshkey_fp_rep dgst_rep)
1084: {
1085: char *retval = NULL;
1086: u_char *dgst_raw;
1087: size_t dgst_raw_len;
1088:
1.7 djm 1089: if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
1.1 djm 1090: return NULL;
1091: switch (dgst_rep) {
1.7 djm 1092: case SSH_FP_DEFAULT:
1093: if (dgst_alg == SSH_DIGEST_MD5) {
1094: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1095: dgst_raw, dgst_raw_len);
1096: } else {
1097: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1098: dgst_raw, dgst_raw_len);
1099: }
1100: break;
1.1 djm 1101: case SSH_FP_HEX:
1.7 djm 1102: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1103: dgst_raw, dgst_raw_len);
1104: break;
1105: case SSH_FP_BASE64:
1106: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1107: dgst_raw, dgst_raw_len);
1.1 djm 1108: break;
1109: case SSH_FP_BUBBLEBABBLE:
1110: retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
1111: break;
1112: case SSH_FP_RANDOMART:
1.7 djm 1113: retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
1114: dgst_raw, dgst_raw_len, k);
1.1 djm 1115: break;
1116: default:
1.100 jsg 1117: freezero(dgst_raw, dgst_raw_len);
1.1 djm 1118: return NULL;
1119: }
1.100 jsg 1120: freezero(dgst_raw, dgst_raw_len);
1.1 djm 1121: return retval;
1122: }
1123:
1.63 djm 1124: static int
1125: peek_type_nid(const char *s, size_t l, int *nid)
1126: {
1.123 djm 1127: const struct sshkey_impl *impl;
1128: int i;
1.63 djm 1129:
1.123 djm 1130: for (i = 0; keyimpls[i] != NULL; i++) {
1131: impl = keyimpls[i];
1132: if (impl->name == NULL || strlen(impl->name) != l)
1.63 djm 1133: continue;
1.123 djm 1134: if (memcmp(s, impl->name, l) == 0) {
1.63 djm 1135: *nid = -1;
1.123 djm 1136: if (key_type_is_ecdsa_variant(impl->type))
1137: *nid = impl->nid;
1138: return impl->type;
1.63 djm 1139: }
1140: }
1141: return KEY_UNSPEC;
1142: }
1.1 djm 1143:
1.63 djm 1144: /* XXX this can now be made const char * */
1.1 djm 1145: int
1146: sshkey_read(struct sshkey *ret, char **cpp)
1147: {
1148: struct sshkey *k;
1.63 djm 1149: char *cp, *blobcopy;
1150: size_t space;
1.1 djm 1151: int r, type, curve_nid = -1;
1152: struct sshbuf *blob;
1.44 dtucker 1153:
1154: if (ret == NULL)
1155: return SSH_ERR_INVALID_ARGUMENT;
1.126 djm 1156: if (ret->type != KEY_UNSPEC && sshkey_impl_from_type(ret->type) == NULL)
1.63 djm 1157: return SSH_ERR_INVALID_ARGUMENT;
1158:
1159: /* Decode type */
1160: cp = *cpp;
1161: space = strcspn(cp, " \t");
1162: if (space == strlen(cp))
1163: return SSH_ERR_INVALID_FORMAT;
1164: if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC)
1165: return SSH_ERR_INVALID_FORMAT;
1166:
1167: /* skip whitespace */
1168: for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1169: ;
1170: if (*cp == '\0')
1171: return SSH_ERR_INVALID_FORMAT;
1172: if (ret->type != KEY_UNSPEC && ret->type != type)
1173: return SSH_ERR_KEY_TYPE_MISMATCH;
1174: if ((blob = sshbuf_new()) == NULL)
1175: return SSH_ERR_ALLOC_FAIL;
1176:
1177: /* find end of keyblob and decode */
1178: space = strcspn(cp, " \t");
1179: if ((blobcopy = strndup(cp, space)) == NULL) {
1180: sshbuf_free(blob);
1181: return SSH_ERR_ALLOC_FAIL;
1182: }
1183: if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) {
1184: free(blobcopy);
1185: sshbuf_free(blob);
1186: return r;
1187: }
1188: free(blobcopy);
1189: if ((r = sshkey_fromb(blob, &k)) != 0) {
1.1 djm 1190: sshbuf_free(blob);
1.63 djm 1191: return r;
1192: }
1193: sshbuf_free(blob);
1194:
1195: /* skip whitespace and leave cp at start of comment */
1196: for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1197: ;
1198:
1199: /* ensure type of blob matches type at start of line */
1200: if (k->type != type) {
1201: sshkey_free(k);
1202: return SSH_ERR_KEY_TYPE_MISMATCH;
1203: }
1.85 djm 1204: if (key_type_is_ecdsa_variant(type) && curve_nid != k->ecdsa_nid) {
1.63 djm 1205: sshkey_free(k);
1206: return SSH_ERR_EC_CURVE_MISMATCH;
1207: }
1208:
1209: /* Fill in ret from parsed key */
1.126 djm 1210: sshkey_free_contents(ret);
1211: *ret = *k;
1212: freezero(k, sizeof(*k));
1.63 djm 1213:
1214: /* success */
1215: *cpp = cp;
1216: return 0;
1.1 djm 1217: }
1218:
1219: int
1.19 djm 1220: sshkey_to_base64(const struct sshkey *key, char **b64p)
1.1 djm 1221: {
1.19 djm 1222: int r = SSH_ERR_INTERNAL_ERROR;
1223: struct sshbuf *b = NULL;
1.1 djm 1224: char *uu = NULL;
1.19 djm 1225:
1226: if (b64p != NULL)
1227: *b64p = NULL;
1228: if ((b = sshbuf_new()) == NULL)
1229: return SSH_ERR_ALLOC_FAIL;
1230: if ((r = sshkey_putb(key, b)) != 0)
1231: goto out;
1.81 djm 1232: if ((uu = sshbuf_dtob64_string(b, 0)) == NULL) {
1.19 djm 1233: r = SSH_ERR_ALLOC_FAIL;
1234: goto out;
1235: }
1236: /* Success */
1237: if (b64p != NULL) {
1238: *b64p = uu;
1239: uu = NULL;
1240: }
1241: r = 0;
1242: out:
1243: sshbuf_free(b);
1244: free(uu);
1245: return r;
1246: }
1247:
1.52 djm 1248: int
1.19 djm 1249: sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
1250: {
1251: int r = SSH_ERR_INTERNAL_ERROR;
1252: char *uu = NULL;
1253:
1.48 djm 1254: if ((r = sshkey_to_base64(key, &uu)) != 0)
1255: goto out;
1256: if ((r = sshbuf_putf(b, "%s %s",
1257: sshkey_ssh_name(key), uu)) != 0)
1258: goto out;
1.19 djm 1259: r = 0;
1260: out:
1261: free(uu);
1262: return r;
1263: }
1264:
1265: int
1266: sshkey_write(const struct sshkey *key, FILE *f)
1267: {
1268: struct sshbuf *b = NULL;
1269: int r = SSH_ERR_INTERNAL_ERROR;
1270:
1271: if ((b = sshbuf_new()) == NULL)
1272: return SSH_ERR_ALLOC_FAIL;
1273: if ((r = sshkey_format_text(key, b)) != 0)
1.1 djm 1274: goto out;
1275: if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) {
1276: if (feof(f))
1277: errno = EPIPE;
1.19 djm 1278: r = SSH_ERR_SYSTEM_ERROR;
1.1 djm 1279: goto out;
1280: }
1.19 djm 1281: /* Success */
1282: r = 0;
1.1 djm 1283: out:
1.19 djm 1284: sshbuf_free(b);
1285: return r;
1.1 djm 1286: }
1287:
1288: const char *
1289: sshkey_cert_type(const struct sshkey *k)
1290: {
1291: switch (k->cert->type) {
1292: case SSH2_CERT_TYPE_USER:
1293: return "user";
1294: case SSH2_CERT_TYPE_HOST:
1295: return "host";
1296: default:
1297: return "unknown";
1298: }
1299: }
1300:
1.134 djm 1301: int
1302: sshkey_check_rsa_length(const struct sshkey *k, int min_size)
1303: {
1304: #ifdef WITH_OPENSSL
1305: const BIGNUM *rsa_n;
1306: int nbits;
1307:
1308: if (k == NULL || k->rsa == NULL ||
1309: (k->type != KEY_RSA && k->type != KEY_RSA_CERT))
1310: return 0;
1311: RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
1312: nbits = BN_num_bits(rsa_n);
1313: if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
1314: (min_size > 0 && nbits < min_size))
1315: return SSH_ERR_KEY_LENGTH;
1316: #endif /* WITH_OPENSSL */
1317: return 0;
1318: }
1319:
1.1 djm 1320: #ifdef WITH_OPENSSL
1321: int
1322: sshkey_ecdsa_key_to_nid(EC_KEY *k)
1323: {
1324: EC_GROUP *eg;
1325: int nids[] = {
1326: NID_X9_62_prime256v1,
1327: NID_secp384r1,
1328: NID_secp521r1,
1329: -1
1330: };
1331: int nid;
1332: u_int i;
1333: const EC_GROUP *g = EC_KEY_get0_group(k);
1334:
1335: /*
1336: * The group may be stored in a ASN.1 encoded private key in one of two
1337: * ways: as a "named group", which is reconstituted by ASN.1 object ID
1338: * or explicit group parameters encoded into the key blob. Only the
1339: * "named group" case sets the group NID for us, but we can figure
1340: * it out for the other case by comparing against all the groups that
1341: * are supported.
1342: */
1343: if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1344: return nid;
1345: for (i = 0; nids[i] != -1; i++) {
1.93 djm 1346: if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
1.1 djm 1347: return -1;
1.93 djm 1348: if (EC_GROUP_cmp(g, eg, NULL) == 0)
1.1 djm 1349: break;
1350: EC_GROUP_free(eg);
1351: }
1352: if (nids[i] != -1) {
1353: /* Use the group with the NID attached */
1354: EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1355: if (EC_KEY_set_group(k, eg) != 1) {
1356: EC_GROUP_free(eg);
1357: return -1;
1358: }
1359: }
1360: return nids[i];
1361: }
1362: #endif /* WITH_OPENSSL */
1363:
1364: int
1365: sshkey_generate(int type, u_int bits, struct sshkey **keyp)
1366: {
1367: struct sshkey *k;
1368: int ret = SSH_ERR_INTERNAL_ERROR;
1.127 djm 1369: const struct sshkey_impl *impl;
1.1 djm 1370:
1.127 djm 1371: if (keyp == NULL || sshkey_type_is_cert(type))
1.1 djm 1372: return SSH_ERR_INVALID_ARGUMENT;
1373: *keyp = NULL;
1.127 djm 1374: if ((impl = sshkey_impl_from_type(type)) == NULL)
1375: return SSH_ERR_KEY_TYPE_UNKNOWN;
1376: if (impl->funcs->generate == NULL)
1377: return SSH_ERR_FEATURE_UNSUPPORTED;
1.1 djm 1378: if ((k = sshkey_new(KEY_UNSPEC)) == NULL)
1379: return SSH_ERR_ALLOC_FAIL;
1.127 djm 1380: k->type = type;
1381: if ((ret = impl->funcs->generate(k, bits)) != 0) {
1382: sshkey_free(k);
1383: return ret;
1.1 djm 1384: }
1.127 djm 1385: /* success */
1386: *keyp = k;
1387: return 0;
1.1 djm 1388: }
1389:
1390: int
1391: sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
1392: {
1393: u_int i;
1394: const struct sshkey_cert *from;
1395: struct sshkey_cert *to;
1.67 djm 1396: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 1397:
1.67 djm 1398: if (to_key == NULL || (from = from_key->cert) == NULL)
1.1 djm 1399: return SSH_ERR_INVALID_ARGUMENT;
1400:
1.67 djm 1401: if ((to = cert_new()) == NULL)
1.1 djm 1402: return SSH_ERR_ALLOC_FAIL;
1403:
1.67 djm 1404: if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
1405: (r = sshbuf_putb(to->critical, from->critical)) != 0 ||
1406: (r = sshbuf_putb(to->extensions, from->extensions)) != 0)
1407: goto out;
1.1 djm 1408:
1409: to->serial = from->serial;
1410: to->type = from->type;
1411: if (from->key_id == NULL)
1412: to->key_id = NULL;
1.67 djm 1413: else if ((to->key_id = strdup(from->key_id)) == NULL) {
1414: r = SSH_ERR_ALLOC_FAIL;
1415: goto out;
1416: }
1.1 djm 1417: to->valid_after = from->valid_after;
1418: to->valid_before = from->valid_before;
1419: if (from->signature_key == NULL)
1420: to->signature_key = NULL;
1.67 djm 1421: else if ((r = sshkey_from_private(from->signature_key,
1.1 djm 1422: &to->signature_key)) != 0)
1.67 djm 1423: goto out;
1424: if (from->signature_type != NULL &&
1425: (to->signature_type = strdup(from->signature_type)) == NULL) {
1426: r = SSH_ERR_ALLOC_FAIL;
1427: goto out;
1428: }
1429: if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) {
1430: r = SSH_ERR_INVALID_ARGUMENT;
1431: goto out;
1432: }
1.1 djm 1433: if (from->nprincipals > 0) {
1434: if ((to->principals = calloc(from->nprincipals,
1.67 djm 1435: sizeof(*to->principals))) == NULL) {
1436: r = SSH_ERR_ALLOC_FAIL;
1437: goto out;
1438: }
1.1 djm 1439: for (i = 0; i < from->nprincipals; i++) {
1440: to->principals[i] = strdup(from->principals[i]);
1441: if (to->principals[i] == NULL) {
1442: to->nprincipals = i;
1.67 djm 1443: r = SSH_ERR_ALLOC_FAIL;
1444: goto out;
1.1 djm 1445: }
1446: }
1447: }
1448: to->nprincipals = from->nprincipals;
1.67 djm 1449:
1450: /* success */
1451: cert_free(to_key->cert);
1452: to_key->cert = to;
1453: to = NULL;
1454: r = 0;
1455: out:
1456: cert_free(to);
1457: return r;
1.1 djm 1458: }
1459:
1460: int
1.128 djm 1461: sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to)
1462: {
1463: /* Append security-key application string */
1464: if ((to->sk_application = strdup(from->sk_application)) == NULL)
1465: return SSH_ERR_ALLOC_FAIL;
1466: return 0;
1467: }
1468:
1469: int
1.1 djm 1470: sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1471: {
1472: struct sshkey *n = NULL;
1.69 djm 1473: int r = SSH_ERR_INTERNAL_ERROR;
1.128 djm 1474: const struct sshkey_impl *impl;
1.1 djm 1475:
1.24 djm 1476: *pkp = NULL;
1.128 djm 1477: if ((impl = sshkey_impl_from_key(k)) == NULL)
1478: return SSH_ERR_KEY_TYPE_UNKNOWN;
1.85 djm 1479: if ((n = sshkey_new(k->type)) == NULL) {
1480: r = SSH_ERR_ALLOC_FAIL;
1481: goto out;
1482: }
1.128 djm 1483: if ((r = impl->funcs->copy_public(k, n)) != 0)
1.69 djm 1484: goto out;
1485: if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0)
1486: goto out;
1487: /* success */
1.1 djm 1488: *pkp = n;
1.69 djm 1489: n = NULL;
1490: r = 0;
1491: out:
1492: sshkey_free(n);
1493: return r;
1.1 djm 1494: }
1495:
1.76 djm 1496: int
1497: sshkey_is_shielded(struct sshkey *k)
1498: {
1499: return k != NULL && k->shielded_private != NULL;
1500: }
1501:
1502: int
1503: sshkey_shield_private(struct sshkey *k)
1504: {
1505: struct sshbuf *prvbuf = NULL;
1506: u_char *prekey = NULL, *enc = NULL, keyiv[SSH_DIGEST_MAX_LENGTH];
1507: struct sshcipher_ctx *cctx = NULL;
1508: const struct sshcipher *cipher;
1509: size_t i, enclen = 0;
1510: struct sshkey *kswap = NULL, tmp;
1511: int r = SSH_ERR_INTERNAL_ERROR;
1512:
1513: #ifdef DEBUG_PK
1514: fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
1515: #endif
1516: if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
1517: r = SSH_ERR_INVALID_ARGUMENT;
1518: goto out;
1519: }
1520: if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
1521: ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
1522: r = SSH_ERR_INTERNAL_ERROR;
1523: goto out;
1524: }
1525:
1526: /* Prepare a random pre-key, and from it an ephemeral key */
1527: if ((prekey = malloc(SSHKEY_SHIELD_PREKEY_LEN)) == NULL) {
1528: r = SSH_ERR_ALLOC_FAIL;
1529: goto out;
1530: }
1531: arc4random_buf(prekey, SSHKEY_SHIELD_PREKEY_LEN);
1532: if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
1533: prekey, SSHKEY_SHIELD_PREKEY_LEN,
1534: keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
1535: goto out;
1536: #ifdef DEBUG_PK
1537: fprintf(stderr, "%s: key+iv\n", __func__);
1538: sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
1539: stderr);
1540: #endif
1541: if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
1542: keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 1)) != 0)
1543: goto out;
1544:
1545: /* Serialise and encrypt the private key using the ephemeral key */
1546: if ((prvbuf = sshbuf_new()) == NULL) {
1547: r = SSH_ERR_ALLOC_FAIL;
1548: goto out;
1549: }
1550: if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0)
1551: goto out;
1552: if ((r = sshkey_private_serialize_opt(k, prvbuf,
1.116 djm 1553: SSHKEY_SERIALIZE_SHIELD)) != 0)
1.76 djm 1554: goto out;
1555: /* pad to cipher blocksize */
1556: i = 0;
1557: while (sshbuf_len(prvbuf) % cipher_blocksize(cipher)) {
1558: if ((r = sshbuf_put_u8(prvbuf, ++i & 0xff)) != 0)
1559: goto out;
1560: }
1561: #ifdef DEBUG_PK
1562: fprintf(stderr, "%s: serialised\n", __func__);
1563: sshbuf_dump(prvbuf, stderr);
1564: #endif
1565: /* encrypt */
1566: enclen = sshbuf_len(prvbuf);
1567: if ((enc = malloc(enclen)) == NULL) {
1568: r = SSH_ERR_ALLOC_FAIL;
1569: goto out;
1570: }
1571: if ((r = cipher_crypt(cctx, 0, enc,
1572: sshbuf_ptr(prvbuf), sshbuf_len(prvbuf), 0, 0)) != 0)
1573: goto out;
1574: #ifdef DEBUG_PK
1575: fprintf(stderr, "%s: encrypted\n", __func__);
1576: sshbuf_dump_data(enc, enclen, stderr);
1577: #endif
1578:
1579: /* Make a scrubbed, public-only copy of our private key argument */
1580: if ((r = sshkey_from_private(k, &kswap)) != 0)
1581: goto out;
1582:
1583: /* Swap the private key out (it will be destroyed below) */
1584: tmp = *kswap;
1585: *kswap = *k;
1586: *k = tmp;
1587:
1588: /* Insert the shielded key into our argument */
1589: k->shielded_private = enc;
1590: k->shielded_len = enclen;
1591: k->shield_prekey = prekey;
1592: k->shield_prekey_len = SSHKEY_SHIELD_PREKEY_LEN;
1593: enc = prekey = NULL; /* transferred */
1594: enclen = 0;
1.99 djm 1595:
1596: /* preserve key fields that are required for correct operation */
1597: k->sk_flags = kswap->sk_flags;
1.76 djm 1598:
1599: /* success */
1600: r = 0;
1601:
1602: out:
1603: /* XXX behaviour on error - invalidate original private key? */
1604: cipher_free(cctx);
1605: explicit_bzero(keyiv, sizeof(keyiv));
1606: explicit_bzero(&tmp, sizeof(tmp));
1.78 djm 1607: freezero(enc, enclen);
1.76 djm 1608: freezero(prekey, SSHKEY_SHIELD_PREKEY_LEN);
1609: sshkey_free(kswap);
1610: sshbuf_free(prvbuf);
1611: return r;
1612: }
1613:
1.121 djm 1614: /* Check deterministic padding after private key */
1615: static int
1616: private2_check_padding(struct sshbuf *decrypted)
1617: {
1618: u_char pad;
1619: size_t i;
1620: int r;
1621:
1622: i = 0;
1623: while (sshbuf_len(decrypted)) {
1624: if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
1625: goto out;
1626: if (pad != (++i & 0xff)) {
1627: r = SSH_ERR_INVALID_FORMAT;
1628: goto out;
1629: }
1630: }
1631: /* success */
1632: r = 0;
1633: out:
1634: explicit_bzero(&pad, sizeof(pad));
1635: explicit_bzero(&i, sizeof(i));
1636: return r;
1637: }
1638:
1.76 djm 1639: int
1640: sshkey_unshield_private(struct sshkey *k)
1641: {
1642: struct sshbuf *prvbuf = NULL;
1.121 djm 1643: u_char *cp, keyiv[SSH_DIGEST_MAX_LENGTH];
1.76 djm 1644: struct sshcipher_ctx *cctx = NULL;
1645: const struct sshcipher *cipher;
1646: struct sshkey *kswap = NULL, tmp;
1647: int r = SSH_ERR_INTERNAL_ERROR;
1648:
1649: #ifdef DEBUG_PK
1650: fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
1651: #endif
1652: if (!sshkey_is_shielded(k))
1653: return 0; /* nothing to do */
1654:
1655: if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
1656: r = SSH_ERR_INVALID_ARGUMENT;
1657: goto out;
1658: }
1659: if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
1660: ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
1661: r = SSH_ERR_INTERNAL_ERROR;
1662: goto out;
1663: }
1664: /* check size of shielded key blob */
1665: if (k->shielded_len < cipher_blocksize(cipher) ||
1666: (k->shielded_len % cipher_blocksize(cipher)) != 0) {
1667: r = SSH_ERR_INVALID_FORMAT;
1668: goto out;
1669: }
1670:
1671: /* Calculate the ephemeral key from the prekey */
1672: if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
1673: k->shield_prekey, k->shield_prekey_len,
1674: keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
1675: goto out;
1676: if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
1677: keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 0)) != 0)
1678: goto out;
1679: #ifdef DEBUG_PK
1680: fprintf(stderr, "%s: key+iv\n", __func__);
1681: sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
1682: stderr);
1683: #endif
1684:
1685: /* Decrypt and parse the shielded private key using the ephemeral key */
1686: if ((prvbuf = sshbuf_new()) == NULL) {
1687: r = SSH_ERR_ALLOC_FAIL;
1688: goto out;
1689: }
1690: if ((r = sshbuf_reserve(prvbuf, k->shielded_len, &cp)) != 0)
1691: goto out;
1692: /* decrypt */
1693: #ifdef DEBUG_PK
1694: fprintf(stderr, "%s: encrypted\n", __func__);
1695: sshbuf_dump_data(k->shielded_private, k->shielded_len, stderr);
1696: #endif
1697: if ((r = cipher_crypt(cctx, 0, cp,
1698: k->shielded_private, k->shielded_len, 0, 0)) != 0)
1699: goto out;
1700: #ifdef DEBUG_PK
1701: fprintf(stderr, "%s: serialised\n", __func__);
1702: sshbuf_dump(prvbuf, stderr);
1703: #endif
1704: /* Parse private key */
1705: if ((r = sshkey_private_deserialize(prvbuf, &kswap)) != 0)
1706: goto out;
1.121 djm 1707:
1708: if ((r = private2_check_padding(prvbuf)) != 0)
1709: goto out;
1.76 djm 1710:
1711: /* Swap the parsed key back into place */
1712: tmp = *kswap;
1713: *kswap = *k;
1714: *k = tmp;
1715:
1716: /* success */
1717: r = 0;
1718:
1719: out:
1720: cipher_free(cctx);
1721: explicit_bzero(keyiv, sizeof(keyiv));
1722: explicit_bzero(&tmp, sizeof(tmp));
1723: sshkey_free(kswap);
1724: sshbuf_free(prvbuf);
1725: return r;
1726: }
1727:
1.1 djm 1728: static int
1.14 djm 1729: cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1.1 djm 1730: {
1.14 djm 1731: struct sshbuf *principals = NULL, *crit = NULL;
1732: struct sshbuf *exts = NULL, *ca = NULL;
1733: u_char *sig = NULL;
1734: size_t signed_len = 0, slen = 0, kidlen = 0;
1.1 djm 1735: int ret = SSH_ERR_INTERNAL_ERROR;
1736:
1737: /* Copy the entire key blob for verification and later serialisation */
1.14 djm 1738: if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0)
1.1 djm 1739: return ret;
1740:
1.20 djm 1741: /* Parse body of certificate up to signature */
1742: if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 ||
1.1 djm 1743: (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
1744: (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
1.4 djm 1745: (ret = sshbuf_froms(b, &principals)) != 0 ||
1.1 djm 1746: (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
1747: (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
1.4 djm 1748: (ret = sshbuf_froms(b, &crit)) != 0 ||
1.20 djm 1749: (ret = sshbuf_froms(b, &exts)) != 0 ||
1.1 djm 1750: (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
1.14 djm 1751: (ret = sshbuf_froms(b, &ca)) != 0) {
1.1 djm 1752: /* XXX debug print error for ret */
1753: ret = SSH_ERR_INVALID_FORMAT;
1754: goto out;
1755: }
1756:
1757: /* Signature is left in the buffer so we can calculate this length */
1758: signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b);
1759:
1760: if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) {
1761: ret = SSH_ERR_INVALID_FORMAT;
1762: goto out;
1763: }
1764:
1765: if (key->cert->type != SSH2_CERT_TYPE_USER &&
1766: key->cert->type != SSH2_CERT_TYPE_HOST) {
1767: ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE;
1768: goto out;
1769: }
1770:
1.4 djm 1771: /* Parse principals section */
1772: while (sshbuf_len(principals) > 0) {
1773: char *principal = NULL;
1774: char **oprincipals = NULL;
1775:
1.1 djm 1776: if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
1777: ret = SSH_ERR_INVALID_FORMAT;
1778: goto out;
1779: }
1.4 djm 1780: if ((ret = sshbuf_get_cstring(principals, &principal,
1781: NULL)) != 0) {
1.1 djm 1782: ret = SSH_ERR_INVALID_FORMAT;
1783: goto out;
1784: }
1785: oprincipals = key->cert->principals;
1.51 deraadt 1786: key->cert->principals = recallocarray(key->cert->principals,
1787: key->cert->nprincipals, key->cert->nprincipals + 1,
1788: sizeof(*key->cert->principals));
1.1 djm 1789: if (key->cert->principals == NULL) {
1790: free(principal);
1791: key->cert->principals = oprincipals;
1792: ret = SSH_ERR_ALLOC_FAIL;
1793: goto out;
1794: }
1795: key->cert->principals[key->cert->nprincipals++] = principal;
1796: }
1797:
1.4 djm 1798: /*
1799: * Stash a copies of the critical options and extensions sections
1800: * for later use.
1801: */
1802: if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 ||
1803: (exts != NULL &&
1804: (ret = sshbuf_putb(key->cert->extensions, exts)) != 0))
1.1 djm 1805: goto out;
1806:
1.4 djm 1807: /*
1808: * Validate critical options and extensions sections format.
1809: */
1810: while (sshbuf_len(crit) != 0) {
1811: if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
1812: (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) {
1813: sshbuf_reset(key->cert->critical);
1.1 djm 1814: ret = SSH_ERR_INVALID_FORMAT;
1815: goto out;
1816: }
1817: }
1.4 djm 1818: while (exts != NULL && sshbuf_len(exts) != 0) {
1819: if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 ||
1820: (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) {
1821: sshbuf_reset(key->cert->extensions);
1.1 djm 1822: ret = SSH_ERR_INVALID_FORMAT;
1823: goto out;
1824: }
1825: }
1826:
1.4 djm 1827: /* Parse CA key and check signature */
1.14 djm 1828: if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) {
1.1 djm 1829: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1830: goto out;
1831: }
1832: if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) {
1833: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1834: goto out;
1835: }
1836: if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1.96 djm 1837: sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0, NULL)) != 0)
1.1 djm 1838: goto out;
1.82 djm 1839: if ((ret = sshkey_get_sigtype(sig, slen,
1840: &key->cert->signature_type)) != 0)
1.67 djm 1841: goto out;
1.4 djm 1842:
1843: /* Success */
1.1 djm 1844: ret = 0;
1845: out:
1.14 djm 1846: sshbuf_free(ca);
1.4 djm 1847: sshbuf_free(crit);
1848: sshbuf_free(exts);
1849: sshbuf_free(principals);
1.1 djm 1850: free(sig);
1851: return ret;
1852: }
1853:
1.122 djm 1854: int
1.129 djm 1855: sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key)
1.122 djm 1856: {
1.129 djm 1857: /* Parse additional security-key application string */
1858: if (sshbuf_get_cstring(b, &key->sk_application, NULL) != 0)
1859: return SSH_ERR_INVALID_FORMAT;
1.69 djm 1860: return 0;
1861: }
1862:
1863: static int
1.14 djm 1864: sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
1865: int allow_cert)
1.1 djm 1866: {
1.12 djm 1867: int type, ret = SSH_ERR_INTERNAL_ERROR;
1.129 djm 1868: char *ktype = NULL;
1.1 djm 1869: struct sshkey *key = NULL;
1.14 djm 1870: struct sshbuf *copy;
1.129 djm 1871: const struct sshkey_impl *impl;
1.1 djm 1872:
1873: #ifdef DEBUG_PK /* XXX */
1.14 djm 1874: sshbuf_dump(b, stderr);
1.1 djm 1875: #endif
1.32 djm 1876: if (keyp != NULL)
1877: *keyp = NULL;
1.14 djm 1878: if ((copy = sshbuf_fromb(b)) == NULL) {
1879: ret = SSH_ERR_ALLOC_FAIL;
1880: goto out;
1881: }
1.1 djm 1882: if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
1883: ret = SSH_ERR_INVALID_FORMAT;
1884: goto out;
1885: }
1886:
1887: type = sshkey_type_from_name(ktype);
1888: if (!allow_cert && sshkey_type_is_cert(type)) {
1889: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1890: goto out;
1891: }
1.129 djm 1892: if ((impl = sshkey_impl_from_type(type)) == NULL) {
1893: ret = SSH_ERR_KEY_TYPE_UNKNOWN;
1894: goto out;
1895: }
1896: if ((key = sshkey_new(type)) == NULL) {
1897: ret = SSH_ERR_ALLOC_FAIL;
1898: goto out;
1899: }
1900: if (sshkey_type_is_cert(type)) {
1.141 jsg 1901: /* Skip nonce that precedes all certificates */
1.1 djm 1902: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
1903: ret = SSH_ERR_INVALID_FORMAT;
1904: goto out;
1905: }
1.129 djm 1906: }
1907: if ((ret = impl->funcs->deserialize_public(ktype, b, key)) != 0)
1.1 djm 1908: goto out;
1909:
1910: /* Parse certificate potion */
1.14 djm 1911: if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
1.1 djm 1912: goto out;
1913:
1914: if (key != NULL && sshbuf_len(b) != 0) {
1915: ret = SSH_ERR_INVALID_FORMAT;
1916: goto out;
1917: }
1918: ret = 0;
1.32 djm 1919: if (keyp != NULL) {
1920: *keyp = key;
1921: key = NULL;
1922: }
1.1 djm 1923: out:
1.14 djm 1924: sshbuf_free(copy);
1.1 djm 1925: sshkey_free(key);
1926: free(ktype);
1927: return ret;
1928: }
1929:
1930: int
1931: sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp)
1932: {
1.14 djm 1933: struct sshbuf *b;
1934: int r;
1935:
1936: if ((b = sshbuf_from(blob, blen)) == NULL)
1937: return SSH_ERR_ALLOC_FAIL;
1938: r = sshkey_from_blob_internal(b, keyp, 1);
1939: sshbuf_free(b);
1940: return r;
1941: }
1942:
1943: int
1944: sshkey_fromb(struct sshbuf *b, struct sshkey **keyp)
1945: {
1946: return sshkey_from_blob_internal(b, keyp, 1);
1947: }
1948:
1949: int
1950: sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
1951: {
1952: struct sshbuf *b;
1953: int r;
1954:
1955: if ((r = sshbuf_froms(buf, &b)) != 0)
1956: return r;
1957: r = sshkey_from_blob_internal(b, keyp, 1);
1.58 djm 1958: sshbuf_free(b);
1959: return r;
1960: }
1961:
1.82 djm 1962: int
1963: sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
1.58 djm 1964: {
1965: int r;
1966: struct sshbuf *b = NULL;
1967: char *sigtype = NULL;
1968:
1969: if (sigtypep != NULL)
1970: *sigtypep = NULL;
1971: if ((b = sshbuf_from(sig, siglen)) == NULL)
1972: return SSH_ERR_ALLOC_FAIL;
1973: if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0)
1974: goto out;
1975: /* success */
1976: if (sigtypep != NULL) {
1977: *sigtypep = sigtype;
1978: sigtype = NULL;
1979: }
1980: r = 0;
1981: out:
1982: free(sigtype);
1.14 djm 1983: sshbuf_free(b);
1984: return r;
1.68 djm 1985: }
1986:
1987: /*
1988: *
1989: * Checks whether a certificate's signature type is allowed.
1990: * Returns 0 (success) if the certificate signature type appears in the
1991: * "allowed" pattern-list, or the key is not a certificate to begin with.
1992: * Otherwise returns a ssherr.h code.
1993: */
1994: int
1995: sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed)
1996: {
1997: if (key == NULL || allowed == NULL)
1998: return SSH_ERR_INVALID_ARGUMENT;
1999: if (!sshkey_type_is_cert(key->type))
2000: return 0;
2001: if (key->cert == NULL || key->cert->signature_type == NULL)
2002: return SSH_ERR_INVALID_ARGUMENT;
2003: if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1)
2004: return SSH_ERR_SIGN_ALG_UNSUPPORTED;
2005: return 0;
1.65 djm 2006: }
2007:
2008: /*
2009: * Returns the expected signature algorithm for a given public key algorithm.
2010: */
1.66 djm 2011: const char *
2012: sshkey_sigalg_by_name(const char *name)
1.65 djm 2013: {
1.123 djm 2014: const struct sshkey_impl *impl;
2015: int i;
1.65 djm 2016:
1.123 djm 2017: for (i = 0; keyimpls[i] != NULL; i++) {
2018: impl = keyimpls[i];
2019: if (strcmp(impl->name, name) != 0)
1.65 djm 2020: continue;
1.123 djm 2021: if (impl->sigalg != NULL)
2022: return impl->sigalg;
2023: if (!impl->cert)
2024: return impl->name;
1.65 djm 2025: return sshkey_ssh_name_from_type_nid(
1.123 djm 2026: sshkey_type_plain(impl->type), impl->nid);
1.65 djm 2027: }
2028: return NULL;
2029: }
2030:
2031: /*
2032: * Verifies that the signature algorithm appearing inside the signature blob
2033: * matches that which was requested.
2034: */
2035: int
2036: sshkey_check_sigtype(const u_char *sig, size_t siglen,
2037: const char *requested_alg)
2038: {
2039: const char *expected_alg;
2040: char *sigtype = NULL;
2041: int r;
2042:
2043: if (requested_alg == NULL)
2044: return 0;
1.66 djm 2045: if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
1.65 djm 2046: return SSH_ERR_INVALID_ARGUMENT;
1.82 djm 2047: if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0)
1.65 djm 2048: return r;
2049: r = strcmp(expected_alg, sigtype) == 0;
2050: free(sigtype);
2051: return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
1.1 djm 2052: }
2053:
2054: int
1.76 djm 2055: sshkey_sign(struct sshkey *key,
1.1 djm 2056: u_char **sigp, size_t *lenp,
1.86 djm 2057: const u_char *data, size_t datalen,
1.111 djm 2058: const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
1.1 djm 2059: {
1.76 djm 2060: int was_shielded = sshkey_is_shielded(key);
2061: int r2, r = SSH_ERR_INTERNAL_ERROR;
1.130 djm 2062: const struct sshkey_impl *impl;
1.76 djm 2063:
1.1 djm 2064: if (sigp != NULL)
2065: *sigp = NULL;
2066: if (lenp != NULL)
2067: *lenp = 0;
2068: if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2069: return SSH_ERR_INVALID_ARGUMENT;
1.130 djm 2070: if ((impl = sshkey_impl_from_key(key)) == NULL)
2071: return SSH_ERR_KEY_TYPE_UNKNOWN;
1.76 djm 2072: if ((r = sshkey_unshield_private(key)) != 0)
2073: return r;
1.130 djm 2074: if (sshkey_is_sk(key)) {
1.97 djm 2075: r = sshsk_sign(sk_provider, key, sigp, lenp, data,
1.111 djm 2076: datalen, compat, sk_pin);
1.130 djm 2077: } else {
2078: if (impl->funcs->sign == NULL)
2079: r = SSH_ERR_SIGN_ALG_UNSUPPORTED;
2080: else {
2081: r = impl->funcs->sign(key, sigp, lenp, data, datalen,
2082: alg, sk_provider, sk_pin, compat);
2083: }
1.1 djm 2084: }
1.76 djm 2085: if (was_shielded && (r2 = sshkey_shield_private(key)) != 0)
2086: return r2;
2087: return r;
1.1 djm 2088: }
2089:
2090: /*
2091: * ssh_key_verify returns 0 for a correct signature and < 0 on error.
1.59 djm 2092: * If "alg" specified, then the signature must use that algorithm.
1.1 djm 2093: */
2094: int
2095: sshkey_verify(const struct sshkey *key,
2096: const u_char *sig, size_t siglen,
1.96 djm 2097: const u_char *data, size_t dlen, const char *alg, u_int compat,
2098: struct sshkey_sig_details **detailsp)
1.1 djm 2099: {
1.130 djm 2100: const struct sshkey_impl *impl;
2101:
1.96 djm 2102: if (detailsp != NULL)
2103: *detailsp = NULL;
1.6 djm 2104: if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
1.1 djm 2105: return SSH_ERR_INVALID_ARGUMENT;
1.130 djm 2106: if ((impl = sshkey_impl_from_key(key)) == NULL)
1.1 djm 2107: return SSH_ERR_KEY_TYPE_UNKNOWN;
1.130 djm 2108: return impl->funcs->verify(key, sig, siglen, data, dlen,
2109: alg, compat, detailsp);
1.1 djm 2110: }
2111:
2112: /* Convert a plain key to their _CERT equivalent */
2113: int
1.20 djm 2114: sshkey_to_certified(struct sshkey *k)
1.1 djm 2115: {
2116: int newtype;
2117:
1.131 djm 2118: if ((newtype = sshkey_type_certified(k->type)) == -1)
1.1 djm 2119: return SSH_ERR_INVALID_ARGUMENT;
2120: if ((k->cert = cert_new()) == NULL)
2121: return SSH_ERR_ALLOC_FAIL;
2122: k->type = newtype;
2123: return 0;
2124: }
2125:
2126: /* Convert a certificate to its raw key equivalent */
2127: int
2128: sshkey_drop_cert(struct sshkey *k)
2129: {
2130: if (!sshkey_type_is_cert(k->type))
2131: return SSH_ERR_KEY_TYPE_UNKNOWN;
2132: cert_free(k->cert);
2133: k->cert = NULL;
2134: k->type = sshkey_type_plain(k->type);
2135: return 0;
2136: }
2137:
2138: /* Sign a certified key, (re-)generating the signed certblob. */
2139: int
1.53 djm 2140: sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
1.111 djm 2141: const char *sk_provider, const char *sk_pin,
2142: sshkey_certify_signer *signer, void *signer_ctx)
1.1 djm 2143: {
1.131 djm 2144: const struct sshkey_impl *impl;
1.1 djm 2145: struct sshbuf *principals = NULL;
2146: u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
2147: size_t i, ca_len, sig_len;
2148: int ret = SSH_ERR_INTERNAL_ERROR;
1.67 djm 2149: struct sshbuf *cert = NULL;
2150: char *sigtype = NULL;
1.1 djm 2151:
2152: if (k == NULL || k->cert == NULL ||
2153: k->cert->certblob == NULL || ca == NULL)
2154: return SSH_ERR_INVALID_ARGUMENT;
2155: if (!sshkey_is_cert(k))
2156: return SSH_ERR_KEY_TYPE_UNKNOWN;
2157: if (!sshkey_type_is_valid_ca(ca->type))
2158: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1.131 djm 2159: if ((impl = sshkey_impl_from_key(k)) == NULL)
2160: return SSH_ERR_INTERNAL_ERROR;
1.1 djm 2161:
1.67 djm 2162: /*
2163: * If no alg specified as argument but a signature_type was set,
2164: * then prefer that. If both were specified, then they must match.
2165: */
2166: if (alg == NULL)
2167: alg = k->cert->signature_type;
2168: else if (k->cert->signature_type != NULL &&
2169: strcmp(alg, k->cert->signature_type) != 0)
2170: return SSH_ERR_INVALID_ARGUMENT;
1.75 djm 2171:
2172: /*
2173: * If no signing algorithm or signature_type was specified and we're
2174: * using a RSA key, then default to a good signature algorithm.
2175: */
2176: if (alg == NULL && ca->type == KEY_RSA)
2177: alg = "rsa-sha2-512";
1.67 djm 2178:
1.1 djm 2179: if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2180: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2181:
2182: cert = k->cert->certblob; /* for readability */
2183: sshbuf_reset(cert);
2184: if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0)
2185: goto out;
2186:
2187: /* -v01 certs put nonce first */
2188: arc4random_buf(&nonce, sizeof(nonce));
1.20 djm 2189: if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
2190: goto out;
1.1 djm 2191:
1.131 djm 2192: /* Public key next */
2193: if ((ret = impl->funcs->serialize_public(k, cert,
2194: SSHKEY_SERIALIZE_DEFAULT)) != 0)
1.15 djm 2195: goto out;
1.1 djm 2196:
1.131 djm 2197: /* Then remaining cert fields */
1.20 djm 2198: if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 ||
2199: (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
1.1 djm 2200: (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
2201: goto out;
2202:
2203: if ((principals = sshbuf_new()) == NULL) {
2204: ret = SSH_ERR_ALLOC_FAIL;
2205: goto out;
2206: }
2207: for (i = 0; i < k->cert->nprincipals; i++) {
2208: if ((ret = sshbuf_put_cstring(principals,
2209: k->cert->principals[i])) != 0)
2210: goto out;
2211: }
2212: if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
2213: (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
2214: (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
1.20 djm 2215: (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 ||
2216: (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 ||
2217: (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
1.1 djm 2218: (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
2219: goto out;
2220:
2221: /* Sign the whole mess */
1.53 djm 2222: if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
1.111 djm 2223: sshbuf_len(cert), alg, sk_provider, sk_pin, 0, signer_ctx)) != 0)
1.1 djm 2224: goto out;
1.67 djm 2225: /* Check and update signature_type against what was actually used */
1.82 djm 2226: if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
1.67 djm 2227: goto out;
2228: if (alg != NULL && strcmp(alg, sigtype) != 0) {
2229: ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
2230: goto out;
2231: }
2232: if (k->cert->signature_type == NULL) {
2233: k->cert->signature_type = sigtype;
2234: sigtype = NULL;
2235: }
1.1 djm 2236: /* Append signature and we are done */
2237: if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
2238: goto out;
2239: ret = 0;
2240: out:
2241: if (ret != 0)
2242: sshbuf_reset(cert);
1.29 mmcc 2243: free(sig_blob);
2244: free(ca_blob);
1.67 djm 2245: free(sigtype);
1.31 mmcc 2246: sshbuf_free(principals);
1.1 djm 2247: return ret;
1.53 djm 2248: }
2249:
2250: static int
1.76 djm 2251: default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
1.53 djm 2252: const u_char *data, size_t datalen,
1.111 djm 2253: const char *alg, const char *sk_provider, const char *sk_pin,
2254: u_int compat, void *ctx)
1.53 djm 2255: {
2256: if (ctx != NULL)
2257: return SSH_ERR_INVALID_ARGUMENT;
1.86 djm 2258: return sshkey_sign(key, sigp, lenp, data, datalen, alg,
1.111 djm 2259: sk_provider, sk_pin, compat);
1.53 djm 2260: }
2261:
2262: int
1.86 djm 2263: sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg,
1.111 djm 2264: const char *sk_provider, const char *sk_pin)
1.53 djm 2265: {
1.111 djm 2266: return sshkey_certify_custom(k, ca, alg, sk_provider, sk_pin,
1.86 djm 2267: default_key_sign, NULL);
1.1 djm 2268: }
2269:
2270: int
2271: sshkey_cert_check_authority(const struct sshkey *k,
1.114 djm 2272: int want_host, int require_principal, int wildcard_pattern,
1.119 djm 2273: uint64_t verify_time, const char *name, const char **reason)
1.1 djm 2274: {
2275: u_int i, principal_matches;
2276:
1.102 markus 2277: if (reason == NULL)
2278: return SSH_ERR_INVALID_ARGUMENT;
1.114 djm 2279: if (!sshkey_is_cert(k)) {
2280: *reason = "Key is not a certificate";
2281: return SSH_ERR_KEY_CERT_INVALID;
2282: }
1.1 djm 2283: if (want_host) {
2284: if (k->cert->type != SSH2_CERT_TYPE_HOST) {
2285: *reason = "Certificate invalid: not a host certificate";
2286: return SSH_ERR_KEY_CERT_INVALID;
2287: }
2288: } else {
2289: if (k->cert->type != SSH2_CERT_TYPE_USER) {
2290: *reason = "Certificate invalid: not a user certificate";
2291: return SSH_ERR_KEY_CERT_INVALID;
2292: }
2293: }
1.119 djm 2294: if (verify_time < k->cert->valid_after) {
1.1 djm 2295: *reason = "Certificate invalid: not yet valid";
2296: return SSH_ERR_KEY_CERT_INVALID;
2297: }
1.119 djm 2298: if (verify_time >= k->cert->valid_before) {
1.1 djm 2299: *reason = "Certificate invalid: expired";
2300: return SSH_ERR_KEY_CERT_INVALID;
2301: }
2302: if (k->cert->nprincipals == 0) {
2303: if (require_principal) {
2304: *reason = "Certificate lacks principal list";
2305: return SSH_ERR_KEY_CERT_INVALID;
2306: }
2307: } else if (name != NULL) {
2308: principal_matches = 0;
2309: for (i = 0; i < k->cert->nprincipals; i++) {
1.114 djm 2310: if (wildcard_pattern) {
2311: if (match_pattern(k->cert->principals[i],
2312: name)) {
2313: principal_matches = 1;
2314: break;
2315: }
2316: } else if (strcmp(name, k->cert->principals[i]) == 0) {
1.1 djm 2317: principal_matches = 1;
2318: break;
2319: }
2320: }
2321: if (!principal_matches) {
2322: *reason = "Certificate invalid: name is not a listed "
2323: "principal";
2324: return SSH_ERR_KEY_CERT_INVALID;
2325: }
1.114 djm 2326: }
2327: return 0;
2328: }
2329:
2330: int
1.119 djm 2331: sshkey_cert_check_authority_now(const struct sshkey *k,
2332: int want_host, int require_principal, int wildcard_pattern,
2333: const char *name, const char **reason)
2334: {
2335: time_t now;
2336:
2337: if ((now = time(NULL)) < 0) {
2338: /* yikes - system clock before epoch! */
2339: *reason = "Certificate invalid: not yet valid";
2340: return SSH_ERR_KEY_CERT_INVALID;
2341: }
2342: return sshkey_cert_check_authority(k, want_host, require_principal,
2343: wildcard_pattern, (uint64_t)now, name, reason);
2344: }
2345:
2346: int
1.114 djm 2347: sshkey_cert_check_host(const struct sshkey *key, const char *host,
2348: int wildcard_principals, const char *ca_sign_algorithms,
2349: const char **reason)
2350: {
2351: int r;
2352:
1.119 djm 2353: if ((r = sshkey_cert_check_authority_now(key, 1, 0, wildcard_principals,
1.114 djm 2354: host, reason)) != 0)
2355: return r;
2356: if (sshbuf_len(key->cert->critical) != 0) {
2357: *reason = "Certificate contains unsupported critical options";
2358: return SSH_ERR_KEY_CERT_INVALID;
2359: }
2360: if (ca_sign_algorithms != NULL &&
2361: (r = sshkey_check_cert_sigtype(key, ca_sign_algorithms)) != 0) {
2362: *reason = "Certificate signed with disallowed algorithm";
2363: return SSH_ERR_KEY_CERT_INVALID;
1.1 djm 2364: }
2365: return 0;
1.27 djm 2366: }
2367:
2368: size_t
2369: sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
2370: {
1.113 dtucker 2371: char from[32], to[32], ret[128];
1.27 djm 2372:
2373: *from = *to = '\0';
2374: if (cert->valid_after == 0 &&
2375: cert->valid_before == 0xffffffffffffffffULL)
2376: return strlcpy(s, "forever", l);
2377:
1.118 dtucker 2378: if (cert->valid_after != 0)
2379: format_absolute_time(cert->valid_after, from, sizeof(from));
2380: if (cert->valid_before != 0xffffffffffffffffULL)
2381: format_absolute_time(cert->valid_before, to, sizeof(to));
1.27 djm 2382:
2383: if (cert->valid_after == 0)
2384: snprintf(ret, sizeof(ret), "before %s", to);
2385: else if (cert->valid_before == 0xffffffffffffffffULL)
2386: snprintf(ret, sizeof(ret), "after %s", from);
2387: else
2388: snprintf(ret, sizeof(ret), "from %s to %s", from, to);
2389:
2390: return strlcpy(s, ret, l);
1.1 djm 2391: }
2392:
1.132 djm 2393: /* Common serialization for FIDO private keys */
2394: int
2395: sshkey_serialize_private_sk(const struct sshkey *key, struct sshbuf *b)
2396: {
2397: int r;
2398:
2399: if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
2400: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
2401: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
2402: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
2403: return r;
2404:
2405: return 0;
2406: }
2407:
1.1 djm 2408: int
1.76 djm 2409: sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
1.62 markus 2410: enum sshkey_serialize_rep opts)
1.1 djm 2411: {
2412: int r = SSH_ERR_INTERNAL_ERROR;
1.76 djm 2413: int was_shielded = sshkey_is_shielded(key);
2414: struct sshbuf *b = NULL;
1.132 djm 2415: const struct sshkey_impl *impl;
1.1 djm 2416:
1.132 djm 2417: if ((impl = sshkey_impl_from_key(key)) == NULL)
2418: return SSH_ERR_INTERNAL_ERROR;
1.76 djm 2419: if ((r = sshkey_unshield_private(key)) != 0)
2420: return r;
2421: if ((b = sshbuf_new()) == NULL)
2422: return SSH_ERR_ALLOC_FAIL;
1.1 djm 2423: if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
2424: goto out;
1.132 djm 2425: if (sshkey_is_cert(key)) {
2426: if (key->cert == NULL ||
2427: sshbuf_len(key->cert->certblob) == 0) {
1.1 djm 2428: r = SSH_ERR_INVALID_ARGUMENT;
2429: goto out;
2430: }
1.132 djm 2431: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0)
1.1 djm 2432: goto out;
1.132 djm 2433: }
2434: if ((r = impl->funcs->serialize_private(key, b, opts)) != 0)
1.1 djm 2435: goto out;
1.132 djm 2436:
1.76 djm 2437: /*
2438: * success (but we still need to append the output to buf after
2439: * possibly re-shielding the private key)
2440: */
1.1 djm 2441: r = 0;
2442: out:
1.76 djm 2443: if (was_shielded)
2444: r = sshkey_shield_private(key);
2445: if (r == 0)
2446: r = sshbuf_putb(buf, b);
2447: sshbuf_free(b);
2448:
1.1 djm 2449: return r;
2450: }
2451:
2452: int
1.76 djm 2453: sshkey_private_serialize(struct sshkey *key, struct sshbuf *b)
1.62 markus 2454: {
2455: return sshkey_private_serialize_opt(key, b,
2456: SSHKEY_SERIALIZE_DEFAULT);
2457: }
2458:
1.133 djm 2459: /* Shared deserialization of FIDO private key components */
2460: int
2461: sshkey_private_deserialize_sk(struct sshbuf *buf, struct sshkey *k)
2462: {
2463: int r;
2464:
2465: if ((k->sk_key_handle = sshbuf_new()) == NULL ||
2466: (k->sk_reserved = sshbuf_new()) == NULL)
2467: return SSH_ERR_ALLOC_FAIL;
2468: if ((r = sshbuf_get_cstring(buf, &k->sk_application, NULL)) != 0 ||
2469: (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
2470: (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
2471: (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
2472: return r;
2473:
2474: return 0;
2475: }
2476:
1.62 markus 2477: int
1.1 djm 2478: sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
2479: {
1.133 djm 2480: const struct sshkey_impl *impl;
2481: char *tname = NULL;
1.115 djm 2482: char *expect_sk_application = NULL;
1.133 djm 2483: u_char *expect_ed25519_pk = NULL;
1.1 djm 2484: struct sshkey *k = NULL;
2485: int type, r = SSH_ERR_INTERNAL_ERROR;
2486:
2487: if (kp != NULL)
2488: *kp = NULL;
2489: if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
2490: goto out;
2491: type = sshkey_type_from_name(tname);
1.108 djm 2492: if (sshkey_type_is_cert(type)) {
2493: /*
2494: * Certificate key private keys begin with the certificate
2495: * itself. Make sure this matches the type of the enclosing
2496: * private key.
2497: */
2498: if ((r = sshkey_froms(buf, &k)) != 0)
2499: goto out;
2500: if (k->type != type) {
2501: r = SSH_ERR_KEY_CERT_MISMATCH;
2502: goto out;
2503: }
2504: /* For ECDSA keys, the group must match too */
2505: if (k->type == KEY_ECDSA &&
2506: k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) {
2507: r = SSH_ERR_KEY_CERT_MISMATCH;
2508: goto out;
2509: }
1.115 djm 2510: /*
2511: * Several fields are redundant between certificate and
2512: * private key body, we require these to match.
2513: */
2514: expect_sk_application = k->sk_application;
2515: expect_ed25519_pk = k->ed25519_pk;
2516: k->sk_application = NULL;
2517: k->ed25519_pk = NULL;
1.133 djm 2518: /* XXX xmss too or refactor */
1.108 djm 2519: } else {
1.70 djm 2520: if ((k = sshkey_new(type)) == NULL) {
1.1 djm 2521: r = SSH_ERR_ALLOC_FAIL;
2522: goto out;
2523: }
1.108 djm 2524: }
1.133 djm 2525: if ((impl = sshkey_impl_from_type(type)) == NULL) {
2526: r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 2527: goto out;
2528: }
1.133 djm 2529: if ((r = impl->funcs->deserialize_private(tname, buf, k)) != 0)
2530: goto out;
2531:
2532: /* XXX xmss too or refactor */
1.115 djm 2533: if ((expect_sk_application != NULL && (k->sk_application == NULL ||
2534: strcmp(expect_sk_application, k->sk_application) != 0)) ||
2535: (expect_ed25519_pk != NULL && (k->ed25519_pk == NULL ||
1.116 djm 2536: memcmp(expect_ed25519_pk, k->ed25519_pk, ED25519_PK_SZ) != 0))) {
1.115 djm 2537: r = SSH_ERR_KEY_CERT_MISMATCH;
2538: goto out;
2539: }
1.1 djm 2540: /* success */
2541: r = 0;
2542: if (kp != NULL) {
2543: *kp = k;
2544: k = NULL;
2545: }
2546: out:
2547: free(tname);
2548: sshkey_free(k);
1.115 djm 2549: free(expect_sk_application);
2550: free(expect_ed25519_pk);
1.1 djm 2551: return r;
2552: }
2553:
2554: #ifdef WITH_OPENSSL
2555: int
2556: sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
2557: {
2558: EC_POINT *nq = NULL;
1.93 djm 2559: BIGNUM *order = NULL, *x = NULL, *y = NULL, *tmp = NULL;
1.1 djm 2560: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
1.40 djm 2561:
2562: /*
2563: * NB. This assumes OpenSSL has already verified that the public
2564: * point lies on the curve. This is done by EC_POINT_oct2point()
2565: * implicitly calling EC_POINT_is_on_curve(). If this code is ever
2566: * reachable with public points not unmarshalled using
2567: * EC_POINT_oct2point then the caller will need to explicitly check.
2568: */
1.1 djm 2569:
2570: /*
2571: * We shouldn't ever hit this case because bignum_get_ecpoint()
2572: * refuses to load GF2m points.
2573: */
2574: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2575: NID_X9_62_prime_field)
2576: goto out;
2577:
2578: /* Q != infinity */
2579: if (EC_POINT_is_at_infinity(group, public))
2580: goto out;
2581:
1.93 djm 2582: if ((x = BN_new()) == NULL ||
2583: (y = BN_new()) == NULL ||
2584: (order = BN_new()) == NULL ||
2585: (tmp = BN_new()) == NULL) {
1.1 djm 2586: ret = SSH_ERR_ALLOC_FAIL;
2587: goto out;
2588: }
2589:
2590: /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
1.93 djm 2591: if (EC_GROUP_get_order(group, order, NULL) != 1 ||
1.1 djm 2592: EC_POINT_get_affine_coordinates_GFp(group, public,
1.93 djm 2593: x, y, NULL) != 1) {
1.1 djm 2594: ret = SSH_ERR_LIBCRYPTO_ERROR;
2595: goto out;
2596: }
2597: if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
2598: BN_num_bits(y) <= BN_num_bits(order) / 2)
2599: goto out;
2600:
2601: /* nQ == infinity (n == order of subgroup) */
2602: if ((nq = EC_POINT_new(group)) == NULL) {
2603: ret = SSH_ERR_ALLOC_FAIL;
2604: goto out;
2605: }
1.93 djm 2606: if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) {
1.1 djm 2607: ret = SSH_ERR_LIBCRYPTO_ERROR;
2608: goto out;
2609: }
2610: if (EC_POINT_is_at_infinity(group, nq) != 1)
2611: goto out;
2612:
2613: /* x < order - 1, y < order - 1 */
2614: if (!BN_sub(tmp, order, BN_value_one())) {
2615: ret = SSH_ERR_LIBCRYPTO_ERROR;
2616: goto out;
2617: }
2618: if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0)
2619: goto out;
2620: ret = 0;
2621: out:
1.93 djm 2622: BN_clear_free(x);
2623: BN_clear_free(y);
2624: BN_clear_free(order);
2625: BN_clear_free(tmp);
1.60 jsing 2626: EC_POINT_free(nq);
1.1 djm 2627: return ret;
2628: }
2629:
2630: int
2631: sshkey_ec_validate_private(const EC_KEY *key)
2632: {
1.93 djm 2633: BIGNUM *order = NULL, *tmp = NULL;
1.1 djm 2634: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2635:
1.93 djm 2636: if ((order = BN_new()) == NULL || (tmp = BN_new()) == NULL) {
1.1 djm 2637: ret = SSH_ERR_ALLOC_FAIL;
2638: goto out;
2639: }
2640:
2641: /* log2(private) > log2(order)/2 */
1.93 djm 2642: if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, NULL) != 1) {
1.1 djm 2643: ret = SSH_ERR_LIBCRYPTO_ERROR;
2644: goto out;
2645: }
2646: if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
2647: BN_num_bits(order) / 2)
2648: goto out;
2649:
2650: /* private < order - 1 */
2651: if (!BN_sub(tmp, order, BN_value_one())) {
2652: ret = SSH_ERR_LIBCRYPTO_ERROR;
2653: goto out;
2654: }
2655: if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0)
2656: goto out;
2657: ret = 0;
2658: out:
1.93 djm 2659: BN_clear_free(order);
2660: BN_clear_free(tmp);
1.1 djm 2661: return ret;
2662: }
2663:
2664: void
2665: sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
2666: {
1.93 djm 2667: BIGNUM *x = NULL, *y = NULL;
1.1 djm 2668:
2669: if (point == NULL) {
2670: fputs("point=(NULL)\n", stderr);
2671: return;
2672: }
1.93 djm 2673: if ((x = BN_new()) == NULL || (y = BN_new()) == NULL) {
2674: fprintf(stderr, "%s: BN_new failed\n", __func__);
2675: goto out;
1.1 djm 2676: }
2677: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2678: NID_X9_62_prime_field) {
2679: fprintf(stderr, "%s: group is not a prime field\n", __func__);
1.93 djm 2680: goto out;
1.1 djm 2681: }
1.93 djm 2682: if (EC_POINT_get_affine_coordinates_GFp(group, point,
2683: x, y, NULL) != 1) {
1.1 djm 2684: fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
2685: __func__);
1.93 djm 2686: goto out;
1.1 djm 2687: }
2688: fputs("x=", stderr);
2689: BN_print_fp(stderr, x);
2690: fputs("\ny=", stderr);
2691: BN_print_fp(stderr, y);
2692: fputs("\n", stderr);
1.93 djm 2693: out:
2694: BN_clear_free(x);
2695: BN_clear_free(y);
1.1 djm 2696: }
2697:
2698: void
2699: sshkey_dump_ec_key(const EC_KEY *key)
2700: {
2701: const BIGNUM *exponent;
2702:
2703: sshkey_dump_ec_point(EC_KEY_get0_group(key),
2704: EC_KEY_get0_public_key(key));
2705: fputs("exponent=", stderr);
2706: if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
2707: fputs("(NULL)", stderr);
2708: else
2709: BN_print_fp(stderr, EC_KEY_get0_private_key(key));
2710: fputs("\n", stderr);
2711: }
2712: #endif /* WITH_OPENSSL */
2713:
2714: static int
1.76 djm 2715: sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob,
1.1 djm 2716: const char *passphrase, const char *comment, const char *ciphername,
2717: int rounds)
2718: {
1.4 djm 2719: u_char *cp, *key = NULL, *pubkeyblob = NULL;
1.1 djm 2720: u_char salt[SALT_LEN];
2721: size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
2722: u_int check;
2723: int r = SSH_ERR_INTERNAL_ERROR;
1.36 djm 2724: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 2725: const struct sshcipher *cipher;
2726: const char *kdfname = KDFNAME;
2727: struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
2728:
2729: if (rounds <= 0)
2730: rounds = DEFAULT_ROUNDS;
2731: if (passphrase == NULL || !strlen(passphrase)) {
2732: ciphername = "none";
2733: kdfname = "none";
2734: } else if (ciphername == NULL)
2735: ciphername = DEFAULT_CIPHERNAME;
1.47 djm 2736: if ((cipher = cipher_by_name(ciphername)) == NULL) {
1.1 djm 2737: r = SSH_ERR_INVALID_ARGUMENT;
2738: goto out;
2739: }
2740:
2741: if ((kdf = sshbuf_new()) == NULL ||
2742: (encoded = sshbuf_new()) == NULL ||
2743: (encrypted = sshbuf_new()) == NULL) {
2744: r = SSH_ERR_ALLOC_FAIL;
2745: goto out;
2746: }
2747: blocksize = cipher_blocksize(cipher);
2748: keylen = cipher_keylen(cipher);
2749: ivlen = cipher_ivlen(cipher);
2750: authlen = cipher_authlen(cipher);
2751: if ((key = calloc(1, keylen + ivlen)) == NULL) {
2752: r = SSH_ERR_ALLOC_FAIL;
2753: goto out;
2754: }
2755: if (strcmp(kdfname, "bcrypt") == 0) {
2756: arc4random_buf(salt, SALT_LEN);
2757: if (bcrypt_pbkdf(passphrase, strlen(passphrase),
2758: salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) {
2759: r = SSH_ERR_INVALID_ARGUMENT;
2760: goto out;
2761: }
2762: if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 ||
2763: (r = sshbuf_put_u32(kdf, rounds)) != 0)
2764: goto out;
2765: } else if (strcmp(kdfname, "none") != 0) {
2766: /* Unsupported KDF type */
2767: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
2768: goto out;
2769: }
2770: if ((r = cipher_init(&ciphercontext, cipher, key, keylen,
2771: key + keylen, ivlen, 1)) != 0)
2772: goto out;
2773:
2774: if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 ||
2775: (r = sshbuf_put_cstring(encoded, ciphername)) != 0 ||
2776: (r = sshbuf_put_cstring(encoded, kdfname)) != 0 ||
2777: (r = sshbuf_put_stringb(encoded, kdf)) != 0 ||
2778: (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */
2779: (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 ||
2780: (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0)
2781: goto out;
2782:
2783: /* set up the buffer that will be encrypted */
2784:
2785: /* Random check bytes */
2786: check = arc4random();
2787: if ((r = sshbuf_put_u32(encrypted, check)) != 0 ||
2788: (r = sshbuf_put_u32(encrypted, check)) != 0)
2789: goto out;
2790:
2791: /* append private key and comment*/
1.62 markus 2792: if ((r = sshkey_private_serialize_opt(prv, encrypted,
1.116 djm 2793: SSHKEY_SERIALIZE_FULL)) != 0 ||
1.1 djm 2794: (r = sshbuf_put_cstring(encrypted, comment)) != 0)
2795: goto out;
2796:
2797: /* padding */
2798: i = 0;
2799: while (sshbuf_len(encrypted) % blocksize) {
2800: if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0)
2801: goto out;
2802: }
2803:
2804: /* length in destination buffer */
2805: if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0)
2806: goto out;
2807:
2808: /* encrypt */
2809: if ((r = sshbuf_reserve(encoded,
2810: sshbuf_len(encrypted) + authlen, &cp)) != 0)
2811: goto out;
1.36 djm 2812: if ((r = cipher_crypt(ciphercontext, 0, cp,
1.1 djm 2813: sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
2814: goto out;
2815:
1.81 djm 2816: sshbuf_reset(blob);
1.1 djm 2817:
1.81 djm 2818: /* assemble uuencoded key */
2819: if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0 ||
2820: (r = sshbuf_dtob64(encoded, blob, 1)) != 0 ||
2821: (r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
1.1 djm 2822: goto out;
2823:
2824: /* success */
2825: r = 0;
2826:
2827: out:
2828: sshbuf_free(kdf);
2829: sshbuf_free(encoded);
2830: sshbuf_free(encrypted);
1.36 djm 2831: cipher_free(ciphercontext);
1.1 djm 2832: explicit_bzero(salt, sizeof(salt));
1.100 jsg 2833: if (key != NULL)
2834: freezero(key, keylen + ivlen);
1.121 djm 2835: if (pubkeyblob != NULL)
1.100 jsg 2836: freezero(pubkeyblob, pubkeylen);
1.1 djm 2837: return r;
2838: }
2839:
2840: static int
1.103 djm 2841: private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp)
1.1 djm 2842: {
2843: const u_char *cp;
2844: size_t encoded_len;
1.103 djm 2845: int r;
2846: u_char last;
1.1 djm 2847: struct sshbuf *encoded = NULL, *decoded = NULL;
2848:
1.103 djm 2849: if (blob == NULL || decodedp == NULL)
2850: return SSH_ERR_INVALID_ARGUMENT;
2851:
2852: *decodedp = NULL;
1.1 djm 2853:
2854: if ((encoded = sshbuf_new()) == NULL ||
1.103 djm 2855: (decoded = sshbuf_new()) == NULL) {
1.1 djm 2856: r = SSH_ERR_ALLOC_FAIL;
2857: goto out;
2858: }
2859:
2860: /* check preamble */
2861: cp = sshbuf_ptr(blob);
2862: encoded_len = sshbuf_len(blob);
2863: if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) ||
2864: memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) {
2865: r = SSH_ERR_INVALID_FORMAT;
2866: goto out;
2867: }
2868: cp += MARK_BEGIN_LEN;
2869: encoded_len -= MARK_BEGIN_LEN;
2870:
2871: /* Look for end marker, removing whitespace as we go */
2872: while (encoded_len > 0) {
2873: if (*cp != '\n' && *cp != '\r') {
2874: if ((r = sshbuf_put_u8(encoded, *cp)) != 0)
2875: goto out;
2876: }
2877: last = *cp;
2878: encoded_len--;
2879: cp++;
2880: if (last == '\n') {
2881: if (encoded_len >= MARK_END_LEN &&
2882: memcmp(cp, MARK_END, MARK_END_LEN) == 0) {
2883: /* \0 terminate */
2884: if ((r = sshbuf_put_u8(encoded, 0)) != 0)
2885: goto out;
2886: break;
2887: }
2888: }
2889: }
2890: if (encoded_len == 0) {
2891: r = SSH_ERR_INVALID_FORMAT;
2892: goto out;
2893: }
2894:
2895: /* decode base64 */
1.4 djm 2896: if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0)
1.1 djm 2897: goto out;
2898:
2899: /* check magic */
2900: if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) ||
2901: memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
2902: r = SSH_ERR_INVALID_FORMAT;
2903: goto out;
2904: }
1.103 djm 2905: /* success */
2906: *decodedp = decoded;
2907: decoded = NULL;
2908: r = 0;
2909: out:
2910: sshbuf_free(encoded);
2911: sshbuf_free(decoded);
2912: return r;
2913: }
2914:
2915: static int
1.104 djm 2916: private2_decrypt(struct sshbuf *decoded, const char *passphrase,
2917: struct sshbuf **decryptedp, struct sshkey **pubkeyp)
1.103 djm 2918: {
2919: char *ciphername = NULL, *kdfname = NULL;
2920: const struct sshcipher *cipher = NULL;
2921: int r = SSH_ERR_INTERNAL_ERROR;
2922: size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0;
2923: struct sshbuf *kdf = NULL, *decrypted = NULL;
2924: struct sshcipher_ctx *ciphercontext = NULL;
1.104 djm 2925: struct sshkey *pubkey = NULL;
1.103 djm 2926: u_char *key = NULL, *salt = NULL, *dp;
2927: u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
2928:
1.104 djm 2929: if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL)
1.103 djm 2930: return SSH_ERR_INVALID_ARGUMENT;
2931:
2932: *decryptedp = NULL;
1.104 djm 2933: *pubkeyp = NULL;
1.103 djm 2934:
2935: if ((decrypted = sshbuf_new()) == NULL) {
2936: r = SSH_ERR_ALLOC_FAIL;
2937: goto out;
2938: }
2939:
1.1 djm 2940: /* parse public portion of key */
2941: if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
2942: (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
2943: (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
2944: (r = sshbuf_froms(decoded, &kdf)) != 0 ||
1.103 djm 2945: (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
2946: goto out;
2947:
2948: if (nkeys != 1) {
2949: /* XXX only one key supported at present */
2950: r = SSH_ERR_INVALID_FORMAT;
2951: goto out;
2952: }
2953:
1.104 djm 2954: if ((r = sshkey_froms(decoded, &pubkey)) != 0 ||
1.1 djm 2955: (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
2956: goto out;
2957:
2958: if ((cipher = cipher_by_name(ciphername)) == NULL) {
2959: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
2960: goto out;
2961: }
2962: if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
2963: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
2964: goto out;
2965: }
1.101 markus 2966: if (strcmp(kdfname, "none") == 0 && strcmp(ciphername, "none") != 0) {
1.1 djm 2967: r = SSH_ERR_INVALID_FORMAT;
1.101 markus 2968: goto out;
2969: }
2970: if ((passphrase == NULL || strlen(passphrase) == 0) &&
2971: strcmp(kdfname, "none") != 0) {
2972: /* passphrase required */
2973: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
1.1 djm 2974: goto out;
2975: }
2976:
2977: /* check size of encrypted key blob */
2978: blocksize = cipher_blocksize(cipher);
2979: if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
2980: r = SSH_ERR_INVALID_FORMAT;
2981: goto out;
2982: }
2983:
2984: /* setup key */
2985: keylen = cipher_keylen(cipher);
2986: ivlen = cipher_ivlen(cipher);
1.18 djm 2987: authlen = cipher_authlen(cipher);
1.1 djm 2988: if ((key = calloc(1, keylen + ivlen)) == NULL) {
2989: r = SSH_ERR_ALLOC_FAIL;
2990: goto out;
2991: }
2992: if (strcmp(kdfname, "bcrypt") == 0) {
2993: if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 ||
2994: (r = sshbuf_get_u32(kdf, &rounds)) != 0)
2995: goto out;
2996: if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
2997: key, keylen + ivlen, rounds) < 0) {
2998: r = SSH_ERR_INVALID_FORMAT;
2999: goto out;
3000: }
3001: }
3002:
1.18 djm 3003: /* check that an appropriate amount of auth data is present */
1.84 djm 3004: if (sshbuf_len(decoded) < authlen ||
3005: sshbuf_len(decoded) - authlen < encrypted_len) {
1.18 djm 3006: r = SSH_ERR_INVALID_FORMAT;
3007: goto out;
3008: }
3009:
1.1 djm 3010: /* decrypt private portion of key */
3011: if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
3012: (r = cipher_init(&ciphercontext, cipher, key, keylen,
3013: key + keylen, ivlen, 0)) != 0)
3014: goto out;
1.36 djm 3015: if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
1.18 djm 3016: encrypted_len, 0, authlen)) != 0) {
1.1 djm 3017: /* an integrity error here indicates an incorrect passphrase */
3018: if (r == SSH_ERR_MAC_INVALID)
3019: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3020: goto out;
3021: }
1.18 djm 3022: if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
1.1 djm 3023: goto out;
3024: /* there should be no trailing data */
3025: if (sshbuf_len(decoded) != 0) {
3026: r = SSH_ERR_INVALID_FORMAT;
3027: goto out;
3028: }
3029:
3030: /* check check bytes */
3031: if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 ||
3032: (r = sshbuf_get_u32(decrypted, &check2)) != 0)
3033: goto out;
3034: if (check1 != check2) {
3035: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3036: goto out;
3037: }
1.103 djm 3038: /* success */
3039: *decryptedp = decrypted;
3040: decrypted = NULL;
1.104 djm 3041: *pubkeyp = pubkey;
3042: pubkey = NULL;
1.103 djm 3043: r = 0;
3044: out:
3045: cipher_free(ciphercontext);
3046: free(ciphername);
3047: free(kdfname);
1.104 djm 3048: sshkey_free(pubkey);
1.103 djm 3049: if (salt != NULL) {
3050: explicit_bzero(salt, slen);
3051: free(salt);
3052: }
3053: if (key != NULL) {
3054: explicit_bzero(key, keylen + ivlen);
3055: free(key);
3056: }
3057: sshbuf_free(kdf);
3058: sshbuf_free(decrypted);
3059: return r;
3060: }
3061:
3062: static int
3063: sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3064: struct sshkey **keyp, char **commentp)
3065: {
3066: char *comment = NULL;
3067: int r = SSH_ERR_INTERNAL_ERROR;
3068: struct sshbuf *decoded = NULL, *decrypted = NULL;
1.104 djm 3069: struct sshkey *k = NULL, *pubkey = NULL;
1.103 djm 3070:
3071: if (keyp != NULL)
3072: *keyp = NULL;
3073: if (commentp != NULL)
3074: *commentp = NULL;
3075:
3076: /* Undo base64 encoding and decrypt the private section */
3077: if ((r = private2_uudecode(blob, &decoded)) != 0 ||
1.104 djm 3078: (r = private2_decrypt(decoded, passphrase,
3079: &decrypted, &pubkey)) != 0)
1.103 djm 3080: goto out;
1.105 djm 3081:
3082: if (type != KEY_UNSPEC &&
3083: sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
3084: r = SSH_ERR_KEY_TYPE_MISMATCH;
3085: goto out;
3086: }
1.103 djm 3087:
3088: /* Load the private key and comment */
3089: if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
3090: (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
3091: goto out;
3092:
3093: /* Check deterministic padding after private section */
3094: if ((r = private2_check_padding(decrypted)) != 0)
3095: goto out;
1.1 djm 3096:
1.104 djm 3097: /* Check that the public key in the envelope matches the private key */
3098: if (!sshkey_equal(pubkey, k)) {
3099: r = SSH_ERR_INVALID_FORMAT;
3100: goto out;
3101: }
1.1 djm 3102:
3103: /* success */
3104: r = 0;
3105: if (keyp != NULL) {
3106: *keyp = k;
3107: k = NULL;
3108: }
3109: if (commentp != NULL) {
3110: *commentp = comment;
3111: comment = NULL;
3112: }
3113: out:
3114: free(comment);
3115: sshbuf_free(decoded);
3116: sshbuf_free(decrypted);
3117: sshkey_free(k);
1.104 djm 3118: sshkey_free(pubkey);
1.1 djm 3119: return r;
3120: }
3121:
1.107 djm 3122: static int
3123: sshkey_parse_private2_pubkey(struct sshbuf *blob, int type,
3124: struct sshkey **keyp)
3125: {
3126: int r = SSH_ERR_INTERNAL_ERROR;
3127: struct sshbuf *decoded = NULL;
3128: struct sshkey *pubkey = NULL;
3129: u_int nkeys = 0;
3130:
3131: if (keyp != NULL)
3132: *keyp = NULL;
3133:
3134: if ((r = private2_uudecode(blob, &decoded)) != 0)
3135: goto out;
3136: /* parse public key from unencrypted envelope */
3137: if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
3138: (r = sshbuf_skip_string(decoded)) != 0 || /* cipher */
3139: (r = sshbuf_skip_string(decoded)) != 0 || /* KDF alg */
3140: (r = sshbuf_skip_string(decoded)) != 0 || /* KDF hint */
3141: (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
3142: goto out;
3143:
3144: if (nkeys != 1) {
3145: /* XXX only one key supported at present */
3146: r = SSH_ERR_INVALID_FORMAT;
3147: goto out;
3148: }
3149:
3150: /* Parse the public key */
3151: if ((r = sshkey_froms(decoded, &pubkey)) != 0)
3152: goto out;
3153:
3154: if (type != KEY_UNSPEC &&
3155: sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
3156: r = SSH_ERR_KEY_TYPE_MISMATCH;
3157: goto out;
3158: }
3159:
3160: /* success */
3161: r = 0;
3162: if (keyp != NULL) {
3163: *keyp = pubkey;
3164: pubkey = NULL;
3165: }
3166: out:
3167: sshbuf_free(decoded);
3168: sshkey_free(pubkey);
3169: return r;
3170: }
3171:
1.1 djm 3172: #ifdef WITH_OPENSSL
1.80 djm 3173: /* convert SSH v2 key to PEM or PKCS#8 format */
1.1 djm 3174: static int
1.80 djm 3175: sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
3176: int format, const char *_passphrase, const char *comment)
1.1 djm 3177: {
1.76 djm 3178: int was_shielded = sshkey_is_shielded(key);
1.1 djm 3179: int success, r;
3180: int blen, len = strlen(_passphrase);
3181: u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
3182: const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
1.57 djm 3183: char *bptr;
1.1 djm 3184: BIO *bio = NULL;
1.76 djm 3185: struct sshbuf *blob;
1.80 djm 3186: EVP_PKEY *pkey = NULL;
1.1 djm 3187:
3188: if (len > 0 && len <= 4)
3189: return SSH_ERR_PASSPHRASE_TOO_SHORT;
1.76 djm 3190: if ((blob = sshbuf_new()) == NULL)
1.1 djm 3191: return SSH_ERR_ALLOC_FAIL;
1.76 djm 3192: if ((bio = BIO_new(BIO_s_mem())) == NULL) {
1.80 djm 3193: r = SSH_ERR_ALLOC_FAIL;
3194: goto out;
3195: }
3196: if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
3197: r = SSH_ERR_ALLOC_FAIL;
3198: goto out;
1.76 djm 3199: }
3200: if ((r = sshkey_unshield_private(key)) != 0)
3201: goto out;
1.1 djm 3202:
3203: switch (key->type) {
1.142 ! djm 3204: #ifdef WITH_DSA
1.1 djm 3205: case KEY_DSA:
1.80 djm 3206: if (format == SSHKEY_PRIVATE_PEM) {
3207: success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
3208: cipher, passphrase, len, NULL, NULL);
3209: } else {
3210: success = EVP_PKEY_set1_DSA(pkey, key->dsa);
3211: }
1.1 djm 3212: break;
1.142 ! djm 3213: #endif
1.1 djm 3214: case KEY_ECDSA:
1.80 djm 3215: if (format == SSHKEY_PRIVATE_PEM) {
3216: success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
3217: cipher, passphrase, len, NULL, NULL);
3218: } else {
3219: success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
3220: }
1.1 djm 3221: break;
3222: case KEY_RSA:
1.80 djm 3223: if (format == SSHKEY_PRIVATE_PEM) {
3224: success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
3225: cipher, passphrase, len, NULL, NULL);
3226: } else {
3227: success = EVP_PKEY_set1_RSA(pkey, key->rsa);
3228: }
1.1 djm 3229: break;
3230: default:
3231: success = 0;
3232: break;
3233: }
3234: if (success == 0) {
3235: r = SSH_ERR_LIBCRYPTO_ERROR;
3236: goto out;
3237: }
1.80 djm 3238: if (format == SSHKEY_PRIVATE_PKCS8) {
3239: if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher,
3240: passphrase, len, NULL, NULL)) == 0) {
3241: r = SSH_ERR_LIBCRYPTO_ERROR;
3242: goto out;
3243: }
3244: }
1.1 djm 3245: if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
3246: r = SSH_ERR_INTERNAL_ERROR;
3247: goto out;
3248: }
3249: if ((r = sshbuf_put(blob, bptr, blen)) != 0)
3250: goto out;
3251: r = 0;
3252: out:
1.76 djm 3253: if (was_shielded)
3254: r = sshkey_shield_private(key);
3255: if (r == 0)
3256: r = sshbuf_putb(buf, blob);
1.80 djm 3257:
3258: EVP_PKEY_free(pkey);
1.76 djm 3259: sshbuf_free(blob);
1.1 djm 3260: BIO_free(bio);
3261: return r;
3262: }
3263: #endif /* WITH_OPENSSL */
3264:
3265: /* Serialise "key" to buffer "blob" */
3266: int
3267: sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3268: const char *passphrase, const char *comment,
1.80 djm 3269: int format, const char *openssh_format_cipher, int openssh_format_rounds)
1.1 djm 3270: {
3271: switch (key->type) {
1.9 markus 3272: #ifdef WITH_OPENSSL
1.1 djm 3273: case KEY_DSA:
3274: case KEY_ECDSA:
3275: case KEY_RSA:
1.80 djm 3276: break; /* see below */
1.1 djm 3277: #endif /* WITH_OPENSSL */
3278: case KEY_ED25519:
1.90 markus 3279: case KEY_ED25519_SK:
1.62 markus 3280: #ifdef WITH_XMSS
3281: case KEY_XMSS:
3282: #endif /* WITH_XMSS */
1.85 djm 3283: #ifdef WITH_OPENSSL
3284: case KEY_ECDSA_SK:
3285: #endif /* WITH_OPENSSL */
1.1 djm 3286: return sshkey_private_to_blob2(key, blob, passphrase,
1.80 djm 3287: comment, openssh_format_cipher, openssh_format_rounds);
1.1 djm 3288: default:
3289: return SSH_ERR_KEY_TYPE_UNKNOWN;
3290: }
1.80 djm 3291:
3292: #ifdef WITH_OPENSSL
3293: switch (format) {
3294: case SSHKEY_PRIVATE_OPENSSH:
3295: return sshkey_private_to_blob2(key, blob, passphrase,
3296: comment, openssh_format_cipher, openssh_format_rounds);
3297: case SSHKEY_PRIVATE_PEM:
3298: case SSHKEY_PRIVATE_PKCS8:
3299: return sshkey_private_to_blob_pem_pkcs8(key, blob,
3300: format, passphrase, comment);
3301: default:
3302: return SSH_ERR_INVALID_ARGUMENT;
3303: }
3304: #endif /* WITH_OPENSSL */
1.1 djm 3305: }
3306:
3307: #ifdef WITH_OPENSSL
1.8 djm 3308: static int
1.52 djm 3309: translate_libcrypto_error(unsigned long pem_err)
3310: {
3311: int pem_reason = ERR_GET_REASON(pem_err);
3312:
3313: switch (ERR_GET_LIB(pem_err)) {
3314: case ERR_LIB_PEM:
3315: switch (pem_reason) {
3316: case PEM_R_BAD_PASSWORD_READ:
3317: case PEM_R_PROBLEMS_GETTING_PASSWORD:
3318: case PEM_R_BAD_DECRYPT:
3319: return SSH_ERR_KEY_WRONG_PASSPHRASE;
3320: default:
3321: return SSH_ERR_INVALID_FORMAT;
3322: }
3323: case ERR_LIB_EVP:
3324: switch (pem_reason) {
3325: case EVP_R_BAD_DECRYPT:
3326: return SSH_ERR_KEY_WRONG_PASSPHRASE;
1.69 djm 3327: #ifdef EVP_R_BN_DECODE_ERROR
1.52 djm 3328: case EVP_R_BN_DECODE_ERROR:
1.69 djm 3329: #endif
1.52 djm 3330: case EVP_R_DECODE_ERROR:
3331: #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
3332: case EVP_R_PRIVATE_KEY_DECODE_ERROR:
3333: #endif
3334: return SSH_ERR_INVALID_FORMAT;
3335: default:
3336: return SSH_ERR_LIBCRYPTO_ERROR;
3337: }
3338: case ERR_LIB_ASN1:
3339: return SSH_ERR_INVALID_FORMAT;
3340: }
3341: return SSH_ERR_LIBCRYPTO_ERROR;
3342: }
3343:
3344: static void
3345: clear_libcrypto_errors(void)
3346: {
3347: while (ERR_get_error() != 0)
3348: ;
3349: }
3350:
3351: /*
3352: * Translate OpenSSL error codes to determine whether
3353: * passphrase is required/incorrect.
3354: */
3355: static int
3356: convert_libcrypto_error(void)
3357: {
3358: /*
3359: * Some password errors are reported at the beginning
3360: * of the error queue.
3361: */
3362: if (translate_libcrypto_error(ERR_peek_error()) ==
3363: SSH_ERR_KEY_WRONG_PASSPHRASE)
3364: return SSH_ERR_KEY_WRONG_PASSPHRASE;
3365: return translate_libcrypto_error(ERR_peek_last_error());
3366: }
3367:
3368: static int
1.1 djm 3369: sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
1.8 djm 3370: const char *passphrase, struct sshkey **keyp)
1.1 djm 3371: {
3372: EVP_PKEY *pk = NULL;
3373: struct sshkey *prv = NULL;
3374: BIO *bio = NULL;
3375: int r;
3376:
1.32 djm 3377: if (keyp != NULL)
3378: *keyp = NULL;
1.1 djm 3379:
3380: if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
3381: return SSH_ERR_ALLOC_FAIL;
3382: if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
3383: (int)sshbuf_len(blob)) {
3384: r = SSH_ERR_ALLOC_FAIL;
3385: goto out;
3386: }
3387:
1.52 djm 3388: clear_libcrypto_errors();
1.1 djm 3389: if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
3390: (char *)passphrase)) == NULL) {
1.116 djm 3391: /*
3392: * libcrypto may return various ASN.1 errors when attempting
3393: * to parse a key with an incorrect passphrase.
3394: * Treat all format errors as "incorrect passphrase" if a
3395: * passphrase was supplied.
3396: */
1.71 djm 3397: if (passphrase != NULL && *passphrase != '\0')
3398: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3399: else
3400: r = convert_libcrypto_error();
1.1 djm 3401: goto out;
3402: }
1.69 djm 3403: if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA &&
1.1 djm 3404: (type == KEY_UNSPEC || type == KEY_RSA)) {
3405: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3406: r = SSH_ERR_ALLOC_FAIL;
3407: goto out;
3408: }
3409: prv->rsa = EVP_PKEY_get1_RSA(pk);
3410: prv->type = KEY_RSA;
3411: #ifdef DEBUG_PK
3412: RSA_print_fp(stderr, prv->rsa, 8);
3413: #endif
3414: if (RSA_blinding_on(prv->rsa, NULL) != 1) {
3415: r = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 3416: goto out;
3417: }
1.122 djm 3418: if ((r = sshkey_check_rsa_length(prv, 0)) != 0)
1.1 djm 3419: goto out;
1.142 ! djm 3420: #ifdef WITH_DSA
1.69 djm 3421: } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
1.1 djm 3422: (type == KEY_UNSPEC || type == KEY_DSA)) {
3423: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3424: r = SSH_ERR_ALLOC_FAIL;
3425: goto out;
3426: }
3427: prv->dsa = EVP_PKEY_get1_DSA(pk);
3428: prv->type = KEY_DSA;
3429: #ifdef DEBUG_PK
3430: DSA_print_fp(stderr, prv->dsa, 8);
1.142 ! djm 3431: #endif
1.1 djm 3432: #endif
1.69 djm 3433: } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC &&
1.1 djm 3434: (type == KEY_UNSPEC || type == KEY_ECDSA)) {
3435: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3436: r = SSH_ERR_ALLOC_FAIL;
3437: goto out;
3438: }
3439: prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
3440: prv->type = KEY_ECDSA;
3441: prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
3442: if (prv->ecdsa_nid == -1 ||
3443: sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
3444: sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
3445: EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
3446: sshkey_ec_validate_private(prv->ecdsa) != 0) {
3447: r = SSH_ERR_INVALID_FORMAT;
3448: goto out;
3449: }
3450: #ifdef DEBUG_PK
3451: if (prv != NULL && prv->ecdsa != NULL)
3452: sshkey_dump_ec_key(prv->ecdsa);
3453: #endif
1.139 djm 3454: } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_ED25519 &&
3455: (type == KEY_UNSPEC || type == KEY_ED25519)) {
1.140 dtucker 3456: size_t len;
3457:
1.139 djm 3458: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL ||
3459: (prv->ed25519_sk = calloc(1, ED25519_SK_SZ)) == NULL ||
3460: (prv->ed25519_pk = calloc(1, ED25519_PK_SZ)) == NULL) {
3461: r = SSH_ERR_ALLOC_FAIL;
3462: goto out;
3463: }
3464: prv->type = KEY_ED25519;
3465: len = ED25519_PK_SZ;
3466: if (!EVP_PKEY_get_raw_public_key(pk, prv->ed25519_pk, &len)) {
3467: r = SSH_ERR_LIBCRYPTO_ERROR;
3468: goto out;
3469: }
3470: if (len != ED25519_PK_SZ) {
3471: r = SSH_ERR_INVALID_FORMAT;
3472: goto out;
3473: }
3474: len = ED25519_SK_SZ - ED25519_PK_SZ;
3475: if (!EVP_PKEY_get_raw_private_key(pk, prv->ed25519_sk, &len)) {
3476: r = SSH_ERR_LIBCRYPTO_ERROR;
3477: goto out;
3478: }
3479: if (len != ED25519_SK_SZ - ED25519_PK_SZ) {
3480: r = SSH_ERR_INVALID_FORMAT;
3481: goto out;
3482: }
3483: /* Append the public key to our private key */
3484: memcpy(prv->ed25519_sk + (ED25519_SK_SZ - ED25519_PK_SZ),
3485: prv->ed25519_pk, ED25519_PK_SZ);
3486: #ifdef DEBUG_PK
3487: sshbuf_dump_data(prv->ed25519_sk, ED25519_SK_SZ, stderr);
3488: #endif
1.1 djm 3489: } else {
3490: r = SSH_ERR_INVALID_FORMAT;
3491: goto out;
3492: }
3493: r = 0;
1.32 djm 3494: if (keyp != NULL) {
3495: *keyp = prv;
3496: prv = NULL;
3497: }
1.1 djm 3498: out:
3499: BIO_free(bio);
1.60 jsing 3500: EVP_PKEY_free(pk);
1.30 mmcc 3501: sshkey_free(prv);
1.1 djm 3502: return r;
3503: }
3504: #endif /* WITH_OPENSSL */
3505:
3506: int
3507: sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
3508: const char *passphrase, struct sshkey **keyp, char **commentp)
3509: {
1.42 djm 3510: int r = SSH_ERR_INTERNAL_ERROR;
3511:
1.32 djm 3512: if (keyp != NULL)
3513: *keyp = NULL;
1.1 djm 3514: if (commentp != NULL)
3515: *commentp = NULL;
3516:
3517: switch (type) {
1.62 markus 3518: case KEY_XMSS:
1.106 djm 3519: /* No fallback for new-format-only keys */
1.1 djm 3520: return sshkey_parse_private2(blob, type, passphrase,
3521: keyp, commentp);
1.106 djm 3522: default:
1.42 djm 3523: r = sshkey_parse_private2(blob, type, passphrase, keyp,
3524: commentp);
1.106 djm 3525: /* Only fallback to PEM parser if a format error occurred. */
3526: if (r != SSH_ERR_INVALID_FORMAT)
1.42 djm 3527: return r;
1.1 djm 3528: #ifdef WITH_OPENSSL
1.8 djm 3529: return sshkey_parse_private_pem_fileblob(blob, type,
3530: passphrase, keyp);
1.1 djm 3531: #else
3532: return SSH_ERR_INVALID_FORMAT;
3533: #endif /* WITH_OPENSSL */
3534: }
3535: }
3536:
3537: int
3538: sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
1.23 tim 3539: struct sshkey **keyp, char **commentp)
1.1 djm 3540: {
3541: if (keyp != NULL)
3542: *keyp = NULL;
3543: if (commentp != NULL)
3544: *commentp = NULL;
3545:
1.23 tim 3546: return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
3547: passphrase, keyp, commentp);
1.96 djm 3548: }
3549:
3550: void
3551: sshkey_sig_details_free(struct sshkey_sig_details *details)
3552: {
3553: freezero(details, sizeof(*details));
1.107 djm 3554: }
3555:
3556: int
3557: sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type,
3558: struct sshkey **pubkeyp)
3559: {
3560: int r = SSH_ERR_INTERNAL_ERROR;
3561:
3562: if (pubkeyp != NULL)
3563: *pubkeyp = NULL;
3564: /* only new-format private keys bundle a public key inside */
3565: if ((r = sshkey_parse_private2_pubkey(blob, type, pubkeyp)) != 0)
3566: return r;
3567: return 0;
1.1 djm 3568: }
1.62 markus 3569:
3570: #ifdef WITH_XMSS
3571: /*
3572: * serialize the key with the current state and forward the state
3573: * maxsign times.
3574: */
3575: int
1.77 djm 3576: sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
1.112 dtucker 3577: u_int32_t maxsign, int printerror)
1.62 markus 3578: {
3579: int r, rupdate;
3580:
3581: if (maxsign == 0 ||
3582: sshkey_type_plain(k->type) != KEY_XMSS)
3583: return sshkey_private_serialize_opt(k, b,
3584: SSHKEY_SERIALIZE_DEFAULT);
1.112 dtucker 3585: if ((r = sshkey_xmss_get_state(k, printerror)) != 0 ||
1.62 markus 3586: (r = sshkey_private_serialize_opt(k, b,
3587: SSHKEY_SERIALIZE_STATE)) != 0 ||
3588: (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
3589: goto out;
3590: r = 0;
3591: out:
1.112 dtucker 3592: if ((rupdate = sshkey_xmss_update_state(k, printerror)) != 0) {
1.62 markus 3593: if (r == 0)
3594: r = rupdate;
3595: }
3596: return r;
3597: }
3598:
3599: u_int32_t
3600: sshkey_signatures_left(const struct sshkey *k)
3601: {
3602: if (sshkey_type_plain(k->type) == KEY_XMSS)
3603: return sshkey_xmss_signatures_left(k);
3604: return 0;
3605: }
3606:
3607: int
3608: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
3609: {
3610: if (sshkey_type_plain(k->type) != KEY_XMSS)
3611: return SSH_ERR_INVALID_ARGUMENT;
3612: return sshkey_xmss_enable_maxsign(k, maxsign);
3613: }
3614:
3615: int
3616: sshkey_set_filename(struct sshkey *k, const char *filename)
3617: {
3618: if (k == NULL)
3619: return SSH_ERR_INVALID_ARGUMENT;
3620: if (sshkey_type_plain(k->type) != KEY_XMSS)
3621: return 0;
3622: if (filename == NULL)
3623: return SSH_ERR_INVALID_ARGUMENT;
3624: if ((k->xmss_filename = strdup(filename)) == NULL)
3625: return SSH_ERR_ALLOC_FAIL;
3626: return 0;
3627: }
3628: #else
3629: int
1.76 djm 3630: sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
1.112 dtucker 3631: u_int32_t maxsign, int printerror)
1.62 markus 3632: {
3633: return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
3634: }
3635:
3636: u_int32_t
3637: sshkey_signatures_left(const struct sshkey *k)
3638: {
3639: return 0;
3640: }
3641:
3642: int
3643: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
3644: {
3645: return SSH_ERR_INVALID_ARGUMENT;
3646: }
3647:
3648: int
3649: sshkey_set_filename(struct sshkey *k, const char *filename)
3650: {
3651: if (k == NULL)
3652: return SSH_ERR_INVALID_ARGUMENT;
3653: return 0;
3654: }
3655: #endif /* WITH_XMSS */