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