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