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