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