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