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