1 /* $OpenBSD: sshkey.c,v 1.66 2018/07/03 13:20:25 djm Exp $ */
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.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
30 #include <sys/types.h>
31 #include <netinet/in.h>
34 #include <openssl/evp.h>
35 #include <openssl/err.h>
36 #include <openssl/pem.h>
39 #include "crypto_api.h"
48 #endif /* HAVE_UTIL_H */
56 #define SSHKEY_INTERNAL
58 #include "sshkey-xmss.h"
61 #include "xmss_fast.h"
63 /* openssh private key file format */
64 #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
65 #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
66 #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
67 #define MARK_END_LEN (sizeof(MARK_END) - 1)
68 #define KDFNAME "bcrypt"
69 #define AUTH_MAGIC "openssh-key-v1"
71 #define DEFAULT_CIPHERNAME "aes256-ctr"
72 #define DEFAULT_ROUNDS 16
74 /* Version identification string for SSH v1 identity files. */
75 #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
77 int sshkey_private_serialize_opt(const struct sshkey *key,
78 struct sshbuf *buf, enum sshkey_serialize_rep);
79 static int sshkey_from_blob_internal(struct sshbuf *buf,
80 struct sshkey **keyp, int allow_cert);
82 /* Supported key types */
85 const char *shortname;
92 static const struct keytype keytypes[] = {
93 { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
94 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
95 KEY_ED25519_CERT, 0, 1, 0 },
97 { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
98 { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
99 KEY_XMSS_CERT, 0, 1, 0 },
100 #endif /* WITH_XMSS */
102 { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
103 { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
104 { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
105 { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
106 # ifdef OPENSSL_HAS_ECC
107 { "ecdsa-sha2-nistp256", "ECDSA", NULL,
108 KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
109 { "ecdsa-sha2-nistp384", "ECDSA", NULL,
110 KEY_ECDSA, NID_secp384r1, 0, 0 },
111 # ifdef OPENSSL_HAS_NISTP521
112 { "ecdsa-sha2-nistp521", "ECDSA", NULL,
113 KEY_ECDSA, NID_secp521r1, 0, 0 },
114 # endif /* OPENSSL_HAS_NISTP521 */
115 # endif /* OPENSSL_HAS_ECC */
116 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
117 KEY_RSA_CERT, 0, 1, 0 },
118 { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
119 "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
120 { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
121 "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
122 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
123 KEY_DSA_CERT, 0, 1, 0 },
124 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
125 KEY_RSA_CERT, 0, 1, 0 },
126 { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
127 "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
128 { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
129 "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
130 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
131 KEY_DSA_CERT, 0, 1, 0 },
132 # ifdef OPENSSL_HAS_ECC
133 { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
134 KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
135 { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
136 KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
137 # ifdef OPENSSL_HAS_NISTP521
138 { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
139 KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
140 # endif /* OPENSSL_HAS_NISTP521 */
141 # endif /* OPENSSL_HAS_ECC */
142 #endif /* WITH_OPENSSL */
143 { NULL, NULL, NULL, -1, -1, 0, 0 }
147 sshkey_type(const struct sshkey *k)
149 const struct keytype *kt;
151 for (kt = keytypes; kt->type != -1; kt++) {
152 if (kt->type == k->type)
153 return kt->shortname;
159 sshkey_ssh_name_from_type_nid(int type, int nid)
161 const struct keytype *kt;
163 for (kt = keytypes; kt->type != -1; kt++) {
164 if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
167 return "ssh-unknown";
171 sshkey_type_is_cert(int type)
173 const struct keytype *kt;
175 for (kt = keytypes; kt->type != -1; kt++) {
176 if (kt->type == type)
183 sshkey_ssh_name(const struct sshkey *k)
185 return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
189 sshkey_ssh_name_plain(const struct sshkey *k)
191 return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type),
196 sshkey_type_from_name(const char *name)
198 const struct keytype *kt;
200 for (kt = keytypes; kt->type != -1; kt++) {
201 /* Only allow shortname matches for plain key types */
202 if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
203 (!kt->cert && strcasecmp(kt->shortname, name) == 0))
210 sshkey_ecdsa_nid_from_name(const char *name)
212 const struct keytype *kt;
214 for (kt = keytypes; kt->type != -1; kt++) {
215 if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
217 if (kt->name != NULL && strcmp(name, kt->name) == 0)
224 sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
226 char *tmp, *ret = NULL;
227 size_t nlen, rlen = 0;
228 const struct keytype *kt;
230 for (kt = keytypes; kt->type != -1; kt++) {
231 if (kt->name == NULL)
233 if (!include_sigonly && kt->sigonly)
235 if ((certs_only && !kt->cert) || (plain_only && kt->cert))
239 nlen = strlen(kt->name);
240 if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
245 memcpy(ret + rlen, kt->name, nlen + 1);
252 sshkey_names_valid2(const char *names, int allow_wildcard)
255 const struct keytype *kt;
258 if (names == NULL || strcmp(names, "") == 0)
260 if ((s = cp = strdup(names)) == NULL)
262 for ((p = strsep(&cp, ",")); p && *p != '\0';
263 (p = strsep(&cp, ","))) {
264 type = sshkey_type_from_name(p);
265 if (type == KEY_UNSPEC) {
266 if (allow_wildcard) {
268 * Try matching key types against the string.
269 * If any has a positive or negative match then
270 * the component is accepted.
272 for (kt = keytypes; kt->type != -1; kt++) {
273 if (match_pattern_list(kt->name,
289 sshkey_size(const struct sshkey *k)
295 return BN_num_bits(k->rsa->n);
298 return BN_num_bits(k->dsa->p);
301 return sshkey_curve_nid_to_bits(k->ecdsa_nid);
302 #endif /* WITH_OPENSSL */
304 case KEY_ED25519_CERT:
307 return 256; /* XXX */
313 sshkey_type_is_valid_ca(int type)
328 sshkey_is_cert(const struct sshkey *k)
332 return sshkey_type_is_cert(k->type);
335 /* Return the cert-less equivalent to a certified key type */
337 sshkey_type_plain(int type)
346 case KEY_ED25519_CERT:
356 /* XXX: these are really begging for a table-driven approach */
358 sshkey_curve_name_to_nid(const char *name)
360 if (strcmp(name, "nistp256") == 0)
361 return NID_X9_62_prime256v1;
362 else if (strcmp(name, "nistp384") == 0)
363 return NID_secp384r1;
364 # ifdef OPENSSL_HAS_NISTP521
365 else if (strcmp(name, "nistp521") == 0)
366 return NID_secp521r1;
367 # endif /* OPENSSL_HAS_NISTP521 */
373 sshkey_curve_nid_to_bits(int nid)
376 case NID_X9_62_prime256v1:
380 # ifdef OPENSSL_HAS_NISTP521
383 # endif /* OPENSSL_HAS_NISTP521 */
390 sshkey_ecdsa_bits_to_nid(int bits)
394 return NID_X9_62_prime256v1;
396 return NID_secp384r1;
397 # ifdef OPENSSL_HAS_NISTP521
399 return NID_secp521r1;
400 # endif /* OPENSSL_HAS_NISTP521 */
407 sshkey_curve_nid_to_name(int nid)
410 case NID_X9_62_prime256v1:
414 # ifdef OPENSSL_HAS_NISTP521
417 # endif /* OPENSSL_HAS_NISTP521 */
424 sshkey_ec_nid_to_hash_alg(int nid)
426 int kbits = sshkey_curve_nid_to_bits(nid);
431 /* RFC5656 section 6.2.1 */
433 return SSH_DIGEST_SHA256;
434 else if (kbits <= 384)
435 return SSH_DIGEST_SHA384;
437 return SSH_DIGEST_SHA512;
439 #endif /* WITH_OPENSSL */
442 cert_free(struct sshkey_cert *cert)
448 sshbuf_free(cert->certblob);
449 sshbuf_free(cert->critical);
450 sshbuf_free(cert->extensions);
452 for (i = 0; i < cert->nprincipals; i++)
453 free(cert->principals[i]);
454 free(cert->principals);
455 sshkey_free(cert->signature_key);
456 freezero(cert, sizeof(*cert));
459 static struct sshkey_cert *
462 struct sshkey_cert *cert;
464 if ((cert = calloc(1, sizeof(*cert))) == NULL)
466 if ((cert->certblob = sshbuf_new()) == NULL ||
467 (cert->critical = sshbuf_new()) == NULL ||
468 (cert->extensions = sshbuf_new()) == NULL) {
473 cert->principals = NULL;
474 cert->signature_key = NULL;
485 #endif /* WITH_OPENSSL */
487 if ((k = calloc(1, sizeof(*k))) == NULL)
495 k->ed25519_sk = NULL;
496 k->ed25519_pk = NULL;
503 if ((rsa = RSA_new()) == NULL ||
504 (rsa->n = BN_new()) == NULL ||
505 (rsa->e = BN_new()) == NULL) {
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) {
527 /* Cannot do anything until we know the group */
529 #endif /* WITH_OPENSSL */
531 case KEY_ED25519_CERT:
534 /* no need to prealloc */
543 if (sshkey_is_cert(k)) {
544 if ((k->cert = cert_new()) == NULL) {
554 sshkey_add_private(struct sshkey *k)
560 #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)
561 if (bn_maybe_alloc_failed(k->rsa->d) ||
562 bn_maybe_alloc_failed(k->rsa->iqmp) ||
563 bn_maybe_alloc_failed(k->rsa->q) ||
564 bn_maybe_alloc_failed(k->rsa->p) ||
565 bn_maybe_alloc_failed(k->rsa->dmq1) ||
566 bn_maybe_alloc_failed(k->rsa->dmp1))
567 return SSH_ERR_ALLOC_FAIL;
571 if (bn_maybe_alloc_failed(k->dsa->priv_key))
572 return SSH_ERR_ALLOC_FAIL;
574 #undef bn_maybe_alloc_failed
577 /* Cannot do anything until we know the group */
579 #endif /* WITH_OPENSSL */
581 case KEY_ED25519_CERT:
584 /* no need to prealloc */
589 return SSH_ERR_INVALID_ARGUMENT;
595 sshkey_new_private(int type)
597 struct sshkey *k = sshkey_new(type);
601 if (sshkey_add_private(k) != 0) {
609 sshkey_free(struct sshkey *k)
625 # ifdef OPENSSL_HAS_ECC
628 EC_KEY_free(k->ecdsa);
631 # endif /* OPENSSL_HAS_ECC */
632 #endif /* WITH_OPENSSL */
634 case KEY_ED25519_CERT:
635 freezero(k->ed25519_pk, ED25519_PK_SZ);
636 k->ed25519_pk = NULL;
637 freezero(k->ed25519_sk, ED25519_SK_SZ);
638 k->ed25519_sk = NULL;
643 freezero(k->xmss_pk, sshkey_xmss_pklen(k));
645 freezero(k->xmss_sk, sshkey_xmss_sklen(k));
647 sshkey_xmss_free_state(k);
650 free(k->xmss_filename);
651 k->xmss_filename = NULL;
653 #endif /* WITH_XMSS */
659 if (sshkey_is_cert(k))
661 freezero(k, sizeof(*k));
665 cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
667 if (a == NULL && b == NULL)
669 if (a == NULL || b == NULL)
671 if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob))
673 if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob),
674 sshbuf_len(a->certblob)) != 0)
680 * Compare public portions of key only, allowing comparisons between
681 * certificates and plain keys too.
684 sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
686 #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
688 #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
690 if (a == NULL || b == NULL ||
691 sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
698 return a->rsa != NULL && b->rsa != NULL &&
699 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
700 BN_cmp(a->rsa->n, b->rsa->n) == 0;
703 return a->dsa != NULL && b->dsa != NULL &&
704 BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
705 BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
706 BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
707 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
708 # ifdef OPENSSL_HAS_ECC
711 if (a->ecdsa == NULL || b->ecdsa == NULL ||
712 EC_KEY_get0_public_key(a->ecdsa) == NULL ||
713 EC_KEY_get0_public_key(b->ecdsa) == NULL)
715 if ((bnctx = BN_CTX_new()) == NULL)
717 if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
718 EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
719 EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
720 EC_KEY_get0_public_key(a->ecdsa),
721 EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
727 # endif /* OPENSSL_HAS_ECC */
728 #endif /* WITH_OPENSSL */
730 case KEY_ED25519_CERT:
731 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
732 memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
736 return a->xmss_pk != NULL && b->xmss_pk != NULL &&
737 sshkey_xmss_pklen(a) == sshkey_xmss_pklen(b) &&
738 memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) == 0;
739 #endif /* WITH_XMSS */
747 sshkey_equal(const struct sshkey *a, const struct sshkey *b)
749 if (a == NULL || b == NULL || a->type != b->type)
751 if (sshkey_is_cert(a)) {
752 if (!cert_compare(a->cert, b->cert))
755 return sshkey_equal_public(a, b);
759 to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
760 enum sshkey_serialize_rep opts)
762 int type, ret = SSH_ERR_INTERNAL_ERROR;
763 const char *typename;
766 return SSH_ERR_INVALID_ARGUMENT;
768 if (sshkey_is_cert(key)) {
769 if (key->cert == NULL)
770 return SSH_ERR_EXPECTED_CERT;
771 if (sshbuf_len(key->cert->certblob) == 0)
772 return SSH_ERR_KEY_LACKS_CERTBLOB;
774 type = force_plain ? sshkey_type_plain(key->type) : key->type;
775 typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
782 #endif /* WITH_OPENSSL */
783 case KEY_ED25519_CERT:
786 #endif /* WITH_XMSS */
787 /* Use the existing blob */
788 /* XXX modified flag? */
789 if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
794 if (key->dsa == NULL)
795 return SSH_ERR_INVALID_ARGUMENT;
796 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
797 (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
798 (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
799 (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
800 (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0)
803 # ifdef OPENSSL_HAS_ECC
805 if (key->ecdsa == NULL)
806 return SSH_ERR_INVALID_ARGUMENT;
807 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
808 (ret = sshbuf_put_cstring(b,
809 sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
810 (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
815 if (key->rsa == NULL)
816 return SSH_ERR_INVALID_ARGUMENT;
817 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
818 (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
819 (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0)
822 #endif /* WITH_OPENSSL */
824 if (key->ed25519_pk == NULL)
825 return SSH_ERR_INVALID_ARGUMENT;
826 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
827 (ret = sshbuf_put_string(b,
828 key->ed25519_pk, ED25519_PK_SZ)) != 0)
833 if (key->xmss_name == NULL || key->xmss_pk == NULL ||
834 sshkey_xmss_pklen(key) == 0)
835 return SSH_ERR_INVALID_ARGUMENT;
836 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
837 (ret = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
838 (ret = sshbuf_put_string(b,
839 key->xmss_pk, sshkey_xmss_pklen(key))) != 0 ||
840 (ret = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
843 #endif /* WITH_XMSS */
845 return SSH_ERR_KEY_TYPE_UNKNOWN;
851 sshkey_putb(const struct sshkey *key, struct sshbuf *b)
853 return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT);
857 sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b,
858 enum sshkey_serialize_rep opts)
863 if ((tmp = sshbuf_new()) == NULL)
864 return SSH_ERR_ALLOC_FAIL;
865 r = to_blob_buf(key, tmp, 0, opts);
867 r = sshbuf_put_stringb(b, tmp);
873 sshkey_puts(const struct sshkey *key, struct sshbuf *b)
875 return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT);
879 sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)
881 return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT);
885 to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain,
886 enum sshkey_serialize_rep opts)
888 int ret = SSH_ERR_INTERNAL_ERROR;
890 struct sshbuf *b = NULL;
896 if ((b = sshbuf_new()) == NULL)
897 return SSH_ERR_ALLOC_FAIL;
898 if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0)
904 if ((*blobp = malloc(len)) == NULL) {
905 ret = SSH_ERR_ALLOC_FAIL;
908 memcpy(*blobp, sshbuf_ptr(b), len);
917 sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
919 return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT);
923 sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
925 return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT);
929 sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
930 u_char **retp, size_t *lenp)
932 u_char *blob = NULL, *ret = NULL;
934 int r = SSH_ERR_INTERNAL_ERROR;
940 if (ssh_digest_bytes(dgst_alg) == 0) {
941 r = SSH_ERR_INVALID_ARGUMENT;
944 if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT))
947 if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
948 r = SSH_ERR_ALLOC_FAIL;
951 if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
952 ret, SSH_DIGEST_MAX_LENGTH)) != 0)
960 *lenp = ssh_digest_bytes(dgst_alg);
965 explicit_bzero(blob, blob_len);
972 fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
975 size_t plen = strlen(alg) + 1;
976 size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
979 if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
981 strlcpy(ret, alg, rlen);
982 strlcat(ret, ":", rlen);
983 if (dgst_raw_len == 0)
985 if ((r = b64_ntop(dgst_raw, dgst_raw_len,
986 ret + plen, rlen - plen)) == -1) {
990 /* Trim padding characters from end */
991 ret[strcspn(ret, "=")] = '\0';
996 fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
998 char *retval, hex[5];
999 size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
1001 if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
1003 strlcpy(retval, alg, rlen);
1004 strlcat(retval, ":", rlen);
1005 for (i = 0; i < dgst_raw_len; i++) {
1006 snprintf(hex, sizeof(hex), "%s%02x",
1007 i > 0 ? ":" : "", dgst_raw[i]);
1008 strlcat(retval, hex, rlen);
1014 fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
1016 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
1017 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
1018 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
1019 u_int i, j = 0, rounds, seed = 1;
1022 rounds = (dgst_raw_len / 2) + 1;
1023 if ((retval = calloc(rounds, 6)) == NULL)
1026 for (i = 0; i < rounds; i++) {
1027 u_int idx0, idx1, idx2, idx3, idx4;
1028 if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
1029 idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
1031 idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
1032 idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
1034 retval[j++] = vowels[idx0];
1035 retval[j++] = consonants[idx1];
1036 retval[j++] = vowels[idx2];
1037 if ((i + 1) < rounds) {
1038 idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
1039 idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
1040 retval[j++] = consonants[idx3];
1042 retval[j++] = consonants[idx4];
1043 seed = ((seed * 5) +
1044 ((((u_int)(dgst_raw[2 * i])) * 7) +
1045 ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
1051 retval[j++] = vowels[idx0];
1052 retval[j++] = consonants[idx1];
1053 retval[j++] = vowels[idx2];
1062 * Draw an ASCII-Art representing the fingerprint so human brain can
1063 * profit from its built-in pattern recognition ability.
1064 * This technique is called "random art" and can be found in some
1065 * scientific publications like this original paper:
1067 * "Hash Visualization: a New Technique to improve Real-World Security",
1068 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
1069 * Techniques and E-Commerce (CrypTEC '99)
1070 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
1072 * The subject came up in a talk by Dan Kaminsky, too.
1074 * If you see the picture is different, the key is different.
1075 * If the picture looks the same, you still know nothing.
1077 * The algorithm used here is a worm crawling over a discrete plane,
1078 * leaving a trace (augmenting the field) everywhere it goes.
1079 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
1080 * makes the respective movement vector be ignored for this turn.
1081 * Graphs are not unambiguous, because circles in graphs can be
1082 * walked in either direction.
1086 * Field sizes for the random art. Have to be odd, so the starting point
1087 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
1088 * Else pictures would be too dense, and drawing the frame would
1089 * fail, too, because the key type would not fit in anymore.
1092 #define FLDSIZE_Y (FLDBASE + 1)
1093 #define FLDSIZE_X (FLDBASE * 2 + 1)
1095 fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
1096 const struct sshkey *k)
1099 * Chars to be used after each other every time the worm
1100 * intersects with itself. Matter of taste.
1102 char *augmentation_string = " .o+=*BOX@%&#/^SE";
1103 char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
1104 u_char field[FLDSIZE_X][FLDSIZE_Y];
1105 size_t i, tlen, hlen;
1108 size_t len = strlen(augmentation_string) - 1;
1110 if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
1113 /* initialize field */
1114 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
1118 /* process raw key */
1119 for (i = 0; i < dgst_raw_len; i++) {
1121 /* each byte conveys four 2-bit move commands */
1122 input = dgst_raw[i];
1123 for (b = 0; b < 4; b++) {
1124 /* evaluate 2 bit, rest is shifted later */
1125 x += (input & 0x1) ? 1 : -1;
1126 y += (input & 0x2) ? 1 : -1;
1128 /* assure we are still in bounds */
1131 x = MINIMUM(x, FLDSIZE_X - 1);
1132 y = MINIMUM(y, FLDSIZE_Y - 1);
1134 /* augment the field */
1135 if (field[x][y] < len - 2)
1141 /* mark starting point and end point*/
1142 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
1145 /* assemble title */
1146 r = snprintf(title, sizeof(title), "[%s %u]",
1147 sshkey_type(k), sshkey_size(k));
1148 /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
1149 if (r < 0 || r > (int)sizeof(title))
1150 r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
1151 tlen = (r <= 0) ? 0 : strlen(title);
1153 /* assemble hash ID. */
1154 r = snprintf(hash, sizeof(hash), "[%s]", alg);
1155 hlen = (r <= 0) ? 0 : strlen(hash);
1157 /* output upper border */
1160 for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
1162 memcpy(p, title, tlen);
1164 for (i += tlen; i < FLDSIZE_X; i++)
1169 /* output content */
1170 for (y = 0; y < FLDSIZE_Y; y++) {
1172 for (x = 0; x < FLDSIZE_X; x++)
1173 *p++ = augmentation_string[MINIMUM(field[x][y], len)];
1178 /* output lower border */
1180 for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
1182 memcpy(p, hash, hlen);
1184 for (i += hlen; i < FLDSIZE_X; i++)
1192 sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1193 enum sshkey_fp_rep dgst_rep)
1195 char *retval = NULL;
1197 size_t dgst_raw_len;
1199 if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
1202 case SSH_FP_DEFAULT:
1203 if (dgst_alg == SSH_DIGEST_MD5) {
1204 retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1205 dgst_raw, dgst_raw_len);
1207 retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1208 dgst_raw, dgst_raw_len);
1212 retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1213 dgst_raw, dgst_raw_len);
1216 retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1217 dgst_raw, dgst_raw_len);
1219 case SSH_FP_BUBBLEBABBLE:
1220 retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
1222 case SSH_FP_RANDOMART:
1223 retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
1224 dgst_raw, dgst_raw_len, k);
1227 explicit_bzero(dgst_raw, dgst_raw_len);
1231 explicit_bzero(dgst_raw, dgst_raw_len);
1237 peek_type_nid(const char *s, size_t l, int *nid)
1239 const struct keytype *kt;
1241 for (kt = keytypes; kt->type != -1; kt++) {
1242 if (kt->name == NULL || strlen(kt->name) != l)
1244 if (memcmp(s, kt->name, l) == 0) {
1246 if (kt->type == KEY_ECDSA || kt->type == KEY_ECDSA_CERT)
1254 /* XXX this can now be made const char * */
1256 sshkey_read(struct sshkey *ret, char **cpp)
1259 char *cp, *blobcopy;
1261 int r, type, curve_nid = -1;
1262 struct sshbuf *blob;
1265 return SSH_ERR_INVALID_ARGUMENT;
1267 switch (ret->type) {
1274 case KEY_ECDSA_CERT:
1276 case KEY_ED25519_CERT:
1280 #endif /* WITH_XMSS */
1283 return SSH_ERR_INVALID_ARGUMENT;
1288 space = strcspn(cp, " \t");
1289 if (space == strlen(cp))
1290 return SSH_ERR_INVALID_FORMAT;
1291 if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC)
1292 return SSH_ERR_INVALID_FORMAT;
1294 /* skip whitespace */
1295 for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1298 return SSH_ERR_INVALID_FORMAT;
1299 if (ret->type != KEY_UNSPEC && ret->type != type)
1300 return SSH_ERR_KEY_TYPE_MISMATCH;
1301 if ((blob = sshbuf_new()) == NULL)
1302 return SSH_ERR_ALLOC_FAIL;
1304 /* find end of keyblob and decode */
1305 space = strcspn(cp, " \t");
1306 if ((blobcopy = strndup(cp, space)) == NULL) {
1308 return SSH_ERR_ALLOC_FAIL;
1310 if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) {
1316 if ((r = sshkey_fromb(blob, &k)) != 0) {
1322 /* skip whitespace and leave cp at start of comment */
1323 for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1326 /* ensure type of blob matches type at start of line */
1327 if (k->type != type) {
1329 return SSH_ERR_KEY_TYPE_MISMATCH;
1331 if (sshkey_type_plain(type) == KEY_ECDSA && curve_nid != k->ecdsa_nid) {
1333 return SSH_ERR_EC_CURVE_MISMATCH;
1336 /* Fill in ret from parsed key */
1338 if (sshkey_is_cert(ret)) {
1339 if (!sshkey_is_cert(k)) {
1341 return SSH_ERR_EXPECTED_CERT;
1343 if (ret->cert != NULL)
1344 cert_free(ret->cert);
1345 ret->cert = k->cert;
1348 switch (sshkey_type_plain(ret->type)) {
1355 RSA_print_fp(stderr, ret->rsa, 8);
1363 DSA_print_fp(stderr, ret->dsa, 8);
1366 # ifdef OPENSSL_HAS_ECC
1368 EC_KEY_free(ret->ecdsa);
1369 ret->ecdsa = k->ecdsa;
1370 ret->ecdsa_nid = k->ecdsa_nid;
1374 sshkey_dump_ec_key(ret->ecdsa);
1377 # endif /* OPENSSL_HAS_ECC */
1378 #endif /* WITH_OPENSSL */
1380 freezero(ret->ed25519_pk, ED25519_PK_SZ);
1381 ret->ed25519_pk = k->ed25519_pk;
1382 k->ed25519_pk = NULL;
1390 ret->xmss_pk = k->xmss_pk;
1392 free(ret->xmss_state);
1393 ret->xmss_state = k->xmss_state;
1394 k->xmss_state = NULL;
1395 free(ret->xmss_name);
1396 ret->xmss_name = k->xmss_name;
1397 k->xmss_name = NULL;
1398 free(ret->xmss_filename);
1399 ret->xmss_filename = k->xmss_filename;
1400 k->xmss_filename = NULL;
1405 #endif /* WITH_XMSS */
1408 return SSH_ERR_INTERNAL_ERROR;
1419 sshkey_to_base64(const struct sshkey *key, char **b64p)
1421 int r = SSH_ERR_INTERNAL_ERROR;
1422 struct sshbuf *b = NULL;
1427 if ((b = sshbuf_new()) == NULL)
1428 return SSH_ERR_ALLOC_FAIL;
1429 if ((r = sshkey_putb(key, b)) != 0)
1431 if ((uu = sshbuf_dtob64(b)) == NULL) {
1432 r = SSH_ERR_ALLOC_FAIL;
1448 sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
1450 int r = SSH_ERR_INTERNAL_ERROR;
1453 if ((r = sshkey_to_base64(key, &uu)) != 0)
1455 if ((r = sshbuf_putf(b, "%s %s",
1456 sshkey_ssh_name(key), uu)) != 0)
1465 sshkey_write(const struct sshkey *key, FILE *f)
1467 struct sshbuf *b = NULL;
1468 int r = SSH_ERR_INTERNAL_ERROR;
1470 if ((b = sshbuf_new()) == NULL)
1471 return SSH_ERR_ALLOC_FAIL;
1472 if ((r = sshkey_format_text(key, b)) != 0)
1474 if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) {
1477 r = SSH_ERR_SYSTEM_ERROR;
1488 sshkey_cert_type(const struct sshkey *k)
1490 switch (k->cert->type) {
1491 case SSH2_CERT_TYPE_USER:
1493 case SSH2_CERT_TYPE_HOST:
1502 rsa_generate_private_key(u_int bits, RSA **rsap)
1504 RSA *private = NULL;
1506 int ret = SSH_ERR_INTERNAL_ERROR;
1509 return SSH_ERR_INVALID_ARGUMENT;
1510 if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
1511 bits > SSHBUF_MAX_BIGNUM * 8)
1512 return SSH_ERR_KEY_LENGTH;
1514 if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
1515 ret = SSH_ERR_ALLOC_FAIL;
1518 if (!BN_set_word(f4, RSA_F4) ||
1519 !RSA_generate_key_ex(private, bits, f4, NULL)) {
1520 ret = SSH_ERR_LIBCRYPTO_ERROR;
1533 dsa_generate_private_key(u_int bits, DSA **dsap)
1536 int ret = SSH_ERR_INTERNAL_ERROR;
1539 return SSH_ERR_INVALID_ARGUMENT;
1541 return SSH_ERR_KEY_LENGTH;
1542 if ((private = DSA_new()) == NULL) {
1543 ret = SSH_ERR_ALLOC_FAIL;
1547 if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1548 NULL, NULL) || !DSA_generate_key(private)) {
1549 ret = SSH_ERR_LIBCRYPTO_ERROR;
1560 # ifdef OPENSSL_HAS_ECC
1562 sshkey_ecdsa_key_to_nid(EC_KEY *k)
1566 NID_X9_62_prime256v1,
1568 # ifdef OPENSSL_HAS_NISTP521
1570 # endif /* OPENSSL_HAS_NISTP521 */
1576 const EC_GROUP *g = EC_KEY_get0_group(k);
1579 * The group may be stored in a ASN.1 encoded private key in one of two
1580 * ways: as a "named group", which is reconstituted by ASN.1 object ID
1581 * or explicit group parameters encoded into the key blob. Only the
1582 * "named group" case sets the group NID for us, but we can figure
1583 * it out for the other case by comparing against all the groups that
1586 if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1588 if ((bnctx = BN_CTX_new()) == NULL)
1590 for (i = 0; nids[i] != -1; i++) {
1591 if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) {
1595 if (EC_GROUP_cmp(g, eg, bnctx) == 0)
1600 if (nids[i] != -1) {
1601 /* Use the group with the NID attached */
1602 EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1603 if (EC_KEY_set_group(k, eg) != 1) {
1612 ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
1615 int ret = SSH_ERR_INTERNAL_ERROR;
1617 if (nid == NULL || ecdsap == NULL)
1618 return SSH_ERR_INVALID_ARGUMENT;
1619 if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
1620 return SSH_ERR_KEY_LENGTH;
1622 if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
1623 ret = SSH_ERR_ALLOC_FAIL;
1626 if (EC_KEY_generate_key(private) != 1) {
1627 ret = SSH_ERR_LIBCRYPTO_ERROR;
1630 EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
1635 EC_KEY_free(private);
1638 # endif /* OPENSSL_HAS_ECC */
1639 #endif /* WITH_OPENSSL */
1642 sshkey_generate(int type, u_int bits, struct sshkey **keyp)
1645 int ret = SSH_ERR_INTERNAL_ERROR;
1648 return SSH_ERR_INVALID_ARGUMENT;
1650 if ((k = sshkey_new(KEY_UNSPEC)) == NULL)
1651 return SSH_ERR_ALLOC_FAIL;
1654 if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL ||
1655 (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) {
1656 ret = SSH_ERR_ALLOC_FAIL;
1659 crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
1664 ret = sshkey_xmss_generate_private_key(k, bits);
1666 #endif /* WITH_XMSS */
1669 ret = dsa_generate_private_key(bits, &k->dsa);
1671 # ifdef OPENSSL_HAS_ECC
1673 ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid,
1676 # endif /* OPENSSL_HAS_ECC */
1678 ret = rsa_generate_private_key(bits, &k->rsa);
1680 #endif /* WITH_OPENSSL */
1682 ret = SSH_ERR_INVALID_ARGUMENT;
1693 sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
1696 const struct sshkey_cert *from;
1697 struct sshkey_cert *to;
1698 int ret = SSH_ERR_INTERNAL_ERROR;
1700 if (to_key->cert != NULL) {
1701 cert_free(to_key->cert);
1702 to_key->cert = NULL;
1705 if ((from = from_key->cert) == NULL)
1706 return SSH_ERR_INVALID_ARGUMENT;
1708 if ((to = to_key->cert = cert_new()) == NULL)
1709 return SSH_ERR_ALLOC_FAIL;
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)
1716 to->serial = from->serial;
1717 to->type = from->type;
1718 if (from->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)
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;
1744 to->nprincipals = from->nprincipals;
1749 sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1751 struct sshkey *n = NULL;
1752 int ret = SSH_ERR_INTERNAL_ERROR;
1759 if ((n = sshkey_new(k->type)) == NULL)
1760 return SSH_ERR_ALLOC_FAIL;
1761 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
1762 (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
1763 (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
1764 (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) {
1766 return SSH_ERR_ALLOC_FAIL;
1769 # ifdef OPENSSL_HAS_ECC
1771 case KEY_ECDSA_CERT:
1772 if ((n = sshkey_new(k->type)) == NULL)
1773 return SSH_ERR_ALLOC_FAIL;
1774 n->ecdsa_nid = k->ecdsa_nid;
1775 n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
1776 if (n->ecdsa == NULL) {
1778 return SSH_ERR_ALLOC_FAIL;
1780 if (EC_KEY_set_public_key(n->ecdsa,
1781 EC_KEY_get0_public_key(k->ecdsa)) != 1) {
1783 return SSH_ERR_LIBCRYPTO_ERROR;
1786 # endif /* OPENSSL_HAS_ECC */
1789 if ((n = sshkey_new(k->type)) == NULL)
1790 return SSH_ERR_ALLOC_FAIL;
1791 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
1792 (BN_copy(n->rsa->e, k->rsa->e) == NULL)) {
1794 return SSH_ERR_ALLOC_FAIL;
1797 #endif /* WITH_OPENSSL */
1799 case KEY_ED25519_CERT:
1800 if ((n = sshkey_new(k->type)) == NULL)
1801 return SSH_ERR_ALLOC_FAIL;
1802 if (k->ed25519_pk != NULL) {
1803 if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
1805 return SSH_ERR_ALLOC_FAIL;
1807 memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1813 if ((n = sshkey_new(k->type)) == NULL)
1814 return SSH_ERR_ALLOC_FAIL;
1815 if ((ret = sshkey_xmss_init(n, k->xmss_name)) != 0) {
1819 if (k->xmss_pk != NULL) {
1820 size_t pklen = sshkey_xmss_pklen(k);
1821 if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
1823 return SSH_ERR_INTERNAL_ERROR;
1825 if ((n->xmss_pk = malloc(pklen)) == NULL) {
1827 return SSH_ERR_ALLOC_FAIL;
1829 memcpy(n->xmss_pk, k->xmss_pk, pklen);
1832 #endif /* WITH_XMSS */
1834 return SSH_ERR_KEY_TYPE_UNKNOWN;
1836 if (sshkey_is_cert(k)) {
1837 if ((ret = sshkey_cert_copy(k, n)) != 0) {
1847 cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1849 struct sshbuf *principals = NULL, *crit = NULL;
1850 struct sshbuf *exts = NULL, *ca = NULL;
1852 size_t signed_len = 0, slen = 0, kidlen = 0;
1853 int ret = SSH_ERR_INTERNAL_ERROR;
1855 /* Copy the entire key blob for verification and later serialisation */
1856 if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0)
1859 /* Parse body of certificate up to signature */
1860 if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 ||
1861 (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
1862 (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
1863 (ret = sshbuf_froms(b, &principals)) != 0 ||
1864 (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
1865 (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
1866 (ret = sshbuf_froms(b, &crit)) != 0 ||
1867 (ret = sshbuf_froms(b, &exts)) != 0 ||
1868 (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
1869 (ret = sshbuf_froms(b, &ca)) != 0) {
1870 /* XXX debug print error for ret */
1871 ret = SSH_ERR_INVALID_FORMAT;
1875 /* Signature is left in the buffer so we can calculate this length */
1876 signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b);
1878 if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) {
1879 ret = SSH_ERR_INVALID_FORMAT;
1883 if (key->cert->type != SSH2_CERT_TYPE_USER &&
1884 key->cert->type != SSH2_CERT_TYPE_HOST) {
1885 ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE;
1889 /* Parse principals section */
1890 while (sshbuf_len(principals) > 0) {
1891 char *principal = NULL;
1892 char **oprincipals = NULL;
1894 if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
1895 ret = SSH_ERR_INVALID_FORMAT;
1898 if ((ret = sshbuf_get_cstring(principals, &principal,
1900 ret = SSH_ERR_INVALID_FORMAT;
1903 oprincipals = key->cert->principals;
1904 key->cert->principals = recallocarray(key->cert->principals,
1905 key->cert->nprincipals, key->cert->nprincipals + 1,
1906 sizeof(*key->cert->principals));
1907 if (key->cert->principals == NULL) {
1909 key->cert->principals = oprincipals;
1910 ret = SSH_ERR_ALLOC_FAIL;
1913 key->cert->principals[key->cert->nprincipals++] = principal;
1917 * Stash a copies of the critical options and extensions sections
1920 if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 ||
1922 (ret = sshbuf_putb(key->cert->extensions, exts)) != 0))
1926 * Validate critical options and extensions sections format.
1928 while (sshbuf_len(crit) != 0) {
1929 if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
1930 (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) {
1931 sshbuf_reset(key->cert->critical);
1932 ret = SSH_ERR_INVALID_FORMAT;
1936 while (exts != NULL && sshbuf_len(exts) != 0) {
1937 if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 ||
1938 (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) {
1939 sshbuf_reset(key->cert->extensions);
1940 ret = SSH_ERR_INVALID_FORMAT;
1945 /* Parse CA key and check signature */
1946 if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) {
1947 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1950 if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) {
1951 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1954 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1955 sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
1964 sshbuf_free(principals);
1970 sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
1973 int type, ret = SSH_ERR_INTERNAL_ERROR;
1974 char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
1975 struct sshkey *key = NULL;
1978 struct sshbuf *copy;
1979 #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
1981 #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
1983 #ifdef DEBUG_PK /* XXX */
1984 sshbuf_dump(b, stderr);
1988 if ((copy = sshbuf_fromb(b)) == NULL) {
1989 ret = SSH_ERR_ALLOC_FAIL;
1992 if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
1993 ret = SSH_ERR_INVALID_FORMAT;
1997 type = sshkey_type_from_name(ktype);
1998 if (!allow_cert && sshkey_type_is_cert(type)) {
1999 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2006 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2007 ret = SSH_ERR_INVALID_FORMAT;
2012 if ((key = sshkey_new(type)) == NULL) {
2013 ret = SSH_ERR_ALLOC_FAIL;
2016 if (sshbuf_get_bignum2(b, key->rsa->e) != 0 ||
2017 sshbuf_get_bignum2(b, key->rsa->n) != 0) {
2018 ret = SSH_ERR_INVALID_FORMAT;
2021 if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
2022 ret = SSH_ERR_KEY_LENGTH;
2026 RSA_print_fp(stderr, key->rsa, 8);
2031 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2032 ret = SSH_ERR_INVALID_FORMAT;
2037 if ((key = sshkey_new(type)) == NULL) {
2038 ret = SSH_ERR_ALLOC_FAIL;
2041 if (sshbuf_get_bignum2(b, key->dsa->p) != 0 ||
2042 sshbuf_get_bignum2(b, key->dsa->q) != 0 ||
2043 sshbuf_get_bignum2(b, key->dsa->g) != 0 ||
2044 sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) {
2045 ret = SSH_ERR_INVALID_FORMAT;
2049 DSA_print_fp(stderr, key->dsa, 8);
2052 case KEY_ECDSA_CERT:
2054 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2055 ret = SSH_ERR_INVALID_FORMAT;
2059 # ifdef OPENSSL_HAS_ECC
2061 if ((key = sshkey_new(type)) == NULL) {
2062 ret = SSH_ERR_ALLOC_FAIL;
2065 key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
2066 if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
2067 ret = SSH_ERR_INVALID_FORMAT;
2070 if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
2071 ret = SSH_ERR_EC_CURVE_MISMATCH;
2074 EC_KEY_free(key->ecdsa);
2075 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
2077 ret = SSH_ERR_EC_CURVE_INVALID;
2080 if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
2081 ret = SSH_ERR_ALLOC_FAIL;
2084 if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
2085 ret = SSH_ERR_INVALID_FORMAT;
2088 if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
2090 ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2093 if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
2094 /* XXX assume it is a allocation error */
2095 ret = SSH_ERR_ALLOC_FAIL;
2099 sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
2102 # endif /* OPENSSL_HAS_ECC */
2103 #endif /* WITH_OPENSSL */
2104 case KEY_ED25519_CERT:
2106 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2107 ret = SSH_ERR_INVALID_FORMAT;
2112 if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2114 if (len != ED25519_PK_SZ) {
2115 ret = SSH_ERR_INVALID_FORMAT;
2118 if ((key = sshkey_new(type)) == NULL) {
2119 ret = SSH_ERR_ALLOC_FAIL;
2122 key->ed25519_pk = pk;
2128 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2129 ret = SSH_ERR_INVALID_FORMAT;
2134 if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
2136 if ((key = sshkey_new(type)) == NULL) {
2137 ret = SSH_ERR_ALLOC_FAIL;
2140 if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
2142 if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2144 if (len == 0 || len != sshkey_xmss_pklen(key)) {
2145 ret = SSH_ERR_INVALID_FORMAT;
2150 if (type != KEY_XMSS_CERT &&
2151 (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
2154 #endif /* WITH_XMSS */
2157 ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2161 /* Parse certificate potion */
2162 if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
2165 if (key != NULL && sshbuf_len(b) != 0) {
2166 ret = SSH_ERR_INVALID_FORMAT;
2181 #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
2183 #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
2188 sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp)
2193 if ((b = sshbuf_from(blob, blen)) == NULL)
2194 return SSH_ERR_ALLOC_FAIL;
2195 r = sshkey_from_blob_internal(b, keyp, 1);
2201 sshkey_fromb(struct sshbuf *b, struct sshkey **keyp)
2203 return sshkey_from_blob_internal(b, keyp, 1);
2207 sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2212 if ((r = sshbuf_froms(buf, &b)) != 0)
2214 r = sshkey_from_blob_internal(b, keyp, 1);
2220 get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
2223 struct sshbuf *b = NULL;
2224 char *sigtype = NULL;
2226 if (sigtypep != NULL)
2228 if ((b = sshbuf_from(sig, siglen)) == NULL)
2229 return SSH_ERR_ALLOC_FAIL;
2230 if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0)
2233 if (sigtypep != NULL) {
2234 *sigtypep = sigtype;
2245 * Returns the expected signature algorithm for a given public key algorithm.
2248 sshkey_sigalg_by_name(const char *name)
2250 const struct keytype *kt;
2252 for (kt = keytypes; kt->type != -1; kt++) {
2253 if (strcmp(kt->name, name) != 0)
2255 if (kt->sigalg != NULL)
2259 return sshkey_ssh_name_from_type_nid(
2260 sshkey_type_plain(kt->type), kt->nid);
2266 * Verifies that the signature algorithm appearing inside the signature blob
2267 * matches that which was requested.
2270 sshkey_check_sigtype(const u_char *sig, size_t siglen,
2271 const char *requested_alg)
2273 const char *expected_alg;
2274 char *sigtype = NULL;
2277 if (requested_alg == NULL)
2279 if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
2280 return SSH_ERR_INVALID_ARGUMENT;
2281 if ((r = get_sigtype(sig, siglen, &sigtype)) != 0)
2283 r = strcmp(expected_alg, sigtype) == 0;
2285 return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
2289 sshkey_sign(const struct sshkey *key,
2290 u_char **sigp, size_t *lenp,
2291 const u_char *data, size_t datalen, const char *alg, u_int compat)
2297 if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2298 return SSH_ERR_INVALID_ARGUMENT;
2299 switch (key->type) {
2303 return ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
2304 # ifdef OPENSSL_HAS_ECC
2305 case KEY_ECDSA_CERT:
2307 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
2308 # endif /* OPENSSL_HAS_ECC */
2311 return ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
2312 #endif /* WITH_OPENSSL */
2314 case KEY_ED25519_CERT:
2315 return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
2319 return ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
2320 #endif /* WITH_XMSS */
2322 return SSH_ERR_KEY_TYPE_UNKNOWN;
2327 * ssh_key_verify returns 0 for a correct signature and < 0 on error.
2328 * If "alg" specified, then the signature must use that algorithm.
2331 sshkey_verify(const struct sshkey *key,
2332 const u_char *sig, size_t siglen,
2333 const u_char *data, size_t dlen, const char *alg, u_int compat)
2335 if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2336 return SSH_ERR_INVALID_ARGUMENT;
2337 switch (key->type) {
2341 return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
2342 # ifdef OPENSSL_HAS_ECC
2343 case KEY_ECDSA_CERT:
2345 return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
2346 # endif /* OPENSSL_HAS_ECC */
2349 return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
2350 #endif /* WITH_OPENSSL */
2352 case KEY_ED25519_CERT:
2353 return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
2357 return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
2358 #endif /* WITH_XMSS */
2360 return SSH_ERR_KEY_TYPE_UNKNOWN;
2364 /* Converts a private to a public key */
2366 sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
2369 int ret = SSH_ERR_INTERNAL_ERROR;
2372 if ((pk = calloc(1, sizeof(*pk))) == NULL)
2373 return SSH_ERR_ALLOC_FAIL;
2375 pk->flags = k->flags;
2376 pk->ecdsa_nid = k->ecdsa_nid;
2380 pk->ed25519_pk = NULL;
2381 pk->ed25519_sk = NULL;
2388 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2392 if ((pk->rsa = RSA_new()) == NULL ||
2393 (pk->rsa->e = BN_dup(k->rsa->e)) == NULL ||
2394 (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) {
2395 ret = SSH_ERR_ALLOC_FAIL;
2400 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2404 if ((pk->dsa = DSA_new()) == NULL ||
2405 (pk->dsa->p = BN_dup(k->dsa->p)) == NULL ||
2406 (pk->dsa->q = BN_dup(k->dsa->q)) == NULL ||
2407 (pk->dsa->g = BN_dup(k->dsa->g)) == NULL ||
2408 (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) {
2409 ret = SSH_ERR_ALLOC_FAIL;
2413 case KEY_ECDSA_CERT:
2414 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2417 # ifdef OPENSSL_HAS_ECC
2419 pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid);
2420 if (pk->ecdsa == NULL) {
2421 ret = SSH_ERR_ALLOC_FAIL;
2424 if (EC_KEY_set_public_key(pk->ecdsa,
2425 EC_KEY_get0_public_key(k->ecdsa)) != 1) {
2426 ret = SSH_ERR_LIBCRYPTO_ERROR;
2430 # endif /* OPENSSL_HAS_ECC */
2431 #endif /* WITH_OPENSSL */
2432 case KEY_ED25519_CERT:
2433 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2437 if (k->ed25519_pk != NULL) {
2438 if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
2439 ret = SSH_ERR_ALLOC_FAIL;
2442 memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
2447 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2451 if ((ret = sshkey_xmss_init(pk, k->xmss_name)) != 0)
2453 if (k->xmss_pk != NULL) {
2454 size_t pklen = sshkey_xmss_pklen(k);
2456 if (pklen == 0 || sshkey_xmss_pklen(pk) != pklen) {
2457 ret = SSH_ERR_INTERNAL_ERROR;
2460 if ((pk->xmss_pk = malloc(pklen)) == NULL) {
2461 ret = SSH_ERR_ALLOC_FAIL;
2464 memcpy(pk->xmss_pk, k->xmss_pk, pklen);
2467 #endif /* WITH_XMSS */
2469 ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2478 /* Convert a plain key to their _CERT equivalent */
2480 sshkey_to_certified(struct sshkey *k)
2487 newtype = KEY_RSA_CERT;
2490 newtype = KEY_DSA_CERT;
2493 newtype = KEY_ECDSA_CERT;
2495 #endif /* WITH_OPENSSL */
2497 newtype = KEY_ED25519_CERT;
2501 newtype = KEY_XMSS_CERT;
2503 #endif /* WITH_XMSS */
2505 return SSH_ERR_INVALID_ARGUMENT;
2507 if ((k->cert = cert_new()) == NULL)
2508 return SSH_ERR_ALLOC_FAIL;
2513 /* Convert a certificate to its raw key equivalent */
2515 sshkey_drop_cert(struct sshkey *k)
2517 if (!sshkey_type_is_cert(k->type))
2518 return SSH_ERR_KEY_TYPE_UNKNOWN;
2521 k->type = sshkey_type_plain(k->type);
2525 /* Sign a certified key, (re-)generating the signed certblob. */
2527 sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2528 sshkey_certify_signer *signer, void *signer_ctx)
2530 struct sshbuf *principals = NULL;
2531 u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
2532 size_t i, ca_len, sig_len;
2533 int ret = SSH_ERR_INTERNAL_ERROR;
2534 struct sshbuf *cert;
2536 if (k == NULL || k->cert == NULL ||
2537 k->cert->certblob == NULL || ca == NULL)
2538 return SSH_ERR_INVALID_ARGUMENT;
2539 if (!sshkey_is_cert(k))
2540 return SSH_ERR_KEY_TYPE_UNKNOWN;
2541 if (!sshkey_type_is_valid_ca(ca->type))
2542 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2544 if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2545 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2547 cert = k->cert->certblob; /* for readability */
2549 if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0)
2552 /* -v01 certs put nonce first */
2553 arc4random_buf(&nonce, sizeof(nonce));
2554 if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
2557 /* XXX this substantially duplicates to_blob(); refactor */
2561 if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 ||
2562 (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 ||
2563 (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 ||
2564 (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0)
2567 # ifdef OPENSSL_HAS_ECC
2568 case KEY_ECDSA_CERT:
2569 if ((ret = sshbuf_put_cstring(cert,
2570 sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 ||
2571 (ret = sshbuf_put_ec(cert,
2572 EC_KEY_get0_public_key(k->ecdsa),
2573 EC_KEY_get0_group(k->ecdsa))) != 0)
2576 # endif /* OPENSSL_HAS_ECC */
2578 if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 ||
2579 (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0)
2582 #endif /* WITH_OPENSSL */
2583 case KEY_ED25519_CERT:
2584 if ((ret = sshbuf_put_string(cert,
2585 k->ed25519_pk, ED25519_PK_SZ)) != 0)
2590 if (k->xmss_name == NULL) {
2591 ret = SSH_ERR_INVALID_ARGUMENT;
2594 if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) ||
2595 (ret = sshbuf_put_string(cert,
2596 k->xmss_pk, sshkey_xmss_pklen(k))) != 0)
2599 #endif /* WITH_XMSS */
2601 ret = SSH_ERR_INVALID_ARGUMENT;
2605 if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 ||
2606 (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
2607 (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
2610 if ((principals = sshbuf_new()) == NULL) {
2611 ret = SSH_ERR_ALLOC_FAIL;
2614 for (i = 0; i < k->cert->nprincipals; i++) {
2615 if ((ret = sshbuf_put_cstring(principals,
2616 k->cert->principals[i])) != 0)
2619 if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
2620 (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
2621 (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
2622 (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 ||
2623 (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 ||
2624 (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
2625 (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
2628 /* Sign the whole mess */
2629 if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
2630 sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
2633 /* Append signature and we are done */
2634 if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
2642 sshbuf_free(principals);
2647 default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
2648 const u_char *data, size_t datalen,
2649 const char *alg, u_int compat, void *ctx)
2652 return SSH_ERR_INVALID_ARGUMENT;
2653 return sshkey_sign(key, sigp, lenp, data, datalen, alg, compat);
2657 sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
2659 return sshkey_certify_custom(k, ca, alg, default_key_sign, NULL);
2663 sshkey_cert_check_authority(const struct sshkey *k,
2664 int want_host, int require_principal,
2665 const char *name, const char **reason)
2667 u_int i, principal_matches;
2668 time_t now = time(NULL);
2674 if (k->cert->type != SSH2_CERT_TYPE_HOST) {
2675 *reason = "Certificate invalid: not a host certificate";
2676 return SSH_ERR_KEY_CERT_INVALID;
2679 if (k->cert->type != SSH2_CERT_TYPE_USER) {
2680 *reason = "Certificate invalid: not a user certificate";
2681 return SSH_ERR_KEY_CERT_INVALID;
2685 /* yikes - system clock before epoch! */
2686 *reason = "Certificate invalid: not yet valid";
2687 return SSH_ERR_KEY_CERT_INVALID;
2689 if ((u_int64_t)now < k->cert->valid_after) {
2690 *reason = "Certificate invalid: not yet valid";
2691 return SSH_ERR_KEY_CERT_INVALID;
2693 if ((u_int64_t)now >= k->cert->valid_before) {
2694 *reason = "Certificate invalid: expired";
2695 return SSH_ERR_KEY_CERT_INVALID;
2697 if (k->cert->nprincipals == 0) {
2698 if (require_principal) {
2699 *reason = "Certificate lacks principal list";
2700 return SSH_ERR_KEY_CERT_INVALID;
2702 } else if (name != NULL) {
2703 principal_matches = 0;
2704 for (i = 0; i < k->cert->nprincipals; i++) {
2705 if (strcmp(name, k->cert->principals[i]) == 0) {
2706 principal_matches = 1;
2710 if (!principal_matches) {
2711 *reason = "Certificate invalid: name is not a listed "
2713 return SSH_ERR_KEY_CERT_INVALID;
2720 sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
2722 char from[32], to[32], ret[64];
2727 if (cert->valid_after == 0 &&
2728 cert->valid_before == 0xffffffffffffffffULL)
2729 return strlcpy(s, "forever", l);
2731 if (cert->valid_after != 0) {
2732 /* XXX revisit INT_MAX in 2038 :) */
2733 tt = cert->valid_after > INT_MAX ?
2734 INT_MAX : cert->valid_after;
2735 tm = localtime(&tt);
2736 strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
2738 if (cert->valid_before != 0xffffffffffffffffULL) {
2739 /* XXX revisit INT_MAX in 2038 :) */
2740 tt = cert->valid_before > INT_MAX ?
2741 INT_MAX : cert->valid_before;
2742 tm = localtime(&tt);
2743 strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
2746 if (cert->valid_after == 0)
2747 snprintf(ret, sizeof(ret), "before %s", to);
2748 else if (cert->valid_before == 0xffffffffffffffffULL)
2749 snprintf(ret, sizeof(ret), "after %s", from);
2751 snprintf(ret, sizeof(ret), "from %s to %s", from, to);
2753 return strlcpy(s, ret, l);
2757 sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b,
2758 enum sshkey_serialize_rep opts)
2760 int r = SSH_ERR_INTERNAL_ERROR;
2762 if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
2764 switch (key->type) {
2767 if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 ||
2768 (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
2769 (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
2770 (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
2771 (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
2772 (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
2776 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2777 r = SSH_ERR_INVALID_ARGUMENT;
2780 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2781 (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
2782 (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
2783 (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
2784 (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
2788 if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
2789 (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
2790 (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
2791 (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 ||
2792 (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
2796 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2797 r = SSH_ERR_INVALID_ARGUMENT;
2800 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2801 (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
2804 # ifdef OPENSSL_HAS_ECC
2806 if ((r = sshbuf_put_cstring(b,
2807 sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
2808 (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
2809 (r = sshbuf_put_bignum2(b,
2810 EC_KEY_get0_private_key(key->ecdsa))) != 0)
2813 case KEY_ECDSA_CERT:
2814 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2815 r = SSH_ERR_INVALID_ARGUMENT;
2818 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2819 (r = sshbuf_put_bignum2(b,
2820 EC_KEY_get0_private_key(key->ecdsa))) != 0)
2823 # endif /* OPENSSL_HAS_ECC */
2824 #endif /* WITH_OPENSSL */
2826 if ((r = sshbuf_put_string(b, key->ed25519_pk,
2827 ED25519_PK_SZ)) != 0 ||
2828 (r = sshbuf_put_string(b, key->ed25519_sk,
2829 ED25519_SK_SZ)) != 0)
2832 case KEY_ED25519_CERT:
2833 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2834 r = SSH_ERR_INVALID_ARGUMENT;
2837 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2838 (r = sshbuf_put_string(b, key->ed25519_pk,
2839 ED25519_PK_SZ)) != 0 ||
2840 (r = sshbuf_put_string(b, key->ed25519_sk,
2841 ED25519_SK_SZ)) != 0)
2846 if (key->xmss_name == NULL) {
2847 r = SSH_ERR_INVALID_ARGUMENT;
2850 if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
2851 (r = sshbuf_put_string(b, key->xmss_pk,
2852 sshkey_xmss_pklen(key))) != 0 ||
2853 (r = sshbuf_put_string(b, key->xmss_sk,
2854 sshkey_xmss_sklen(key))) != 0 ||
2855 (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
2859 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
2860 key->xmss_name == NULL) {
2861 r = SSH_ERR_INVALID_ARGUMENT;
2864 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2865 (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
2866 (r = sshbuf_put_string(b, key->xmss_pk,
2867 sshkey_xmss_pklen(key))) != 0 ||
2868 (r = sshbuf_put_string(b, key->xmss_sk,
2869 sshkey_xmss_sklen(key))) != 0 ||
2870 (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
2873 #endif /* WITH_XMSS */
2875 r = SSH_ERR_INVALID_ARGUMENT;
2885 sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
2887 return sshkey_private_serialize_opt(key, b,
2888 SSHKEY_SERIALIZE_DEFAULT);
2892 sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
2894 char *tname = NULL, *curve = NULL, *xmss_name = NULL;
2895 struct sshkey *k = NULL;
2896 size_t pklen = 0, sklen = 0;
2897 int type, r = SSH_ERR_INTERNAL_ERROR;
2898 u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
2899 u_char *xmss_pk = NULL, *xmss_sk = NULL;
2901 BIGNUM *exponent = NULL;
2902 #endif /* WITH_OPENSSL */
2906 if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
2908 type = sshkey_type_from_name(tname);
2912 if ((k = sshkey_new_private(type)) == NULL) {
2913 r = SSH_ERR_ALLOC_FAIL;
2916 if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 ||
2917 (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 ||
2918 (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 ||
2919 (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 ||
2920 (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
2924 if ((r = sshkey_froms(buf, &k)) != 0 ||
2925 (r = sshkey_add_private(k)) != 0 ||
2926 (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
2929 # ifdef OPENSSL_HAS_ECC
2931 if ((k = sshkey_new_private(type)) == NULL) {
2932 r = SSH_ERR_ALLOC_FAIL;
2935 if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
2936 r = SSH_ERR_INVALID_ARGUMENT;
2939 if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
2941 if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
2942 r = SSH_ERR_EC_CURVE_MISMATCH;
2945 k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
2946 if (k->ecdsa == NULL || (exponent = BN_new()) == NULL) {
2947 r = SSH_ERR_LIBCRYPTO_ERROR;
2950 if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
2951 (r = sshbuf_get_bignum2(buf, exponent)))
2953 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
2954 r = SSH_ERR_LIBCRYPTO_ERROR;
2957 if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
2958 EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
2959 (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
2962 case KEY_ECDSA_CERT:
2963 if ((exponent = BN_new()) == NULL) {
2964 r = SSH_ERR_LIBCRYPTO_ERROR;
2967 if ((r = sshkey_froms(buf, &k)) != 0 ||
2968 (r = sshkey_add_private(k)) != 0 ||
2969 (r = sshbuf_get_bignum2(buf, exponent)) != 0)
2971 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
2972 r = SSH_ERR_LIBCRYPTO_ERROR;
2975 if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
2976 EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
2977 (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
2980 # endif /* OPENSSL_HAS_ECC */
2982 if ((k = sshkey_new_private(type)) == NULL) {
2983 r = SSH_ERR_ALLOC_FAIL;
2986 if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 ||
2987 (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 ||
2988 (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
2989 (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
2990 (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
2991 (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
2992 (r = ssh_rsa_generate_additional_parameters(k)) != 0)
2994 if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
2995 r = SSH_ERR_KEY_LENGTH;
3000 if ((r = sshkey_froms(buf, &k)) != 0 ||
3001 (r = sshkey_add_private(k)) != 0 ||
3002 (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
3003 (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
3004 (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
3005 (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
3006 (r = ssh_rsa_generate_additional_parameters(k)) != 0)
3008 if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
3009 r = SSH_ERR_KEY_LENGTH;
3013 #endif /* WITH_OPENSSL */
3015 if ((k = sshkey_new_private(type)) == NULL) {
3016 r = SSH_ERR_ALLOC_FAIL;
3019 if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3020 (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3022 if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3023 r = SSH_ERR_INVALID_FORMAT;
3026 k->ed25519_pk = ed25519_pk;
3027 k->ed25519_sk = ed25519_sk;
3028 ed25519_pk = ed25519_sk = NULL;
3030 case KEY_ED25519_CERT:
3031 if ((r = sshkey_froms(buf, &k)) != 0 ||
3032 (r = sshkey_add_private(k)) != 0 ||
3033 (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3034 (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3036 if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3037 r = SSH_ERR_INVALID_FORMAT;
3040 k->ed25519_pk = ed25519_pk;
3041 k->ed25519_sk = ed25519_sk;
3042 ed25519_pk = ed25519_sk = NULL;
3046 if ((k = sshkey_new_private(type)) == NULL) {
3047 r = SSH_ERR_ALLOC_FAIL;
3050 if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
3051 (r = sshkey_xmss_init(k, xmss_name)) != 0 ||
3052 (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3053 (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
3055 if (pklen != sshkey_xmss_pklen(k) ||
3056 sklen != sshkey_xmss_sklen(k)) {
3057 r = SSH_ERR_INVALID_FORMAT;
3060 k->xmss_pk = xmss_pk;
3061 k->xmss_sk = xmss_sk;
3062 xmss_pk = xmss_sk = NULL;
3063 /* optional internal state */
3064 if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3068 if ((r = sshkey_froms(buf, &k)) != 0 ||
3069 (r = sshkey_add_private(k)) != 0 ||
3070 (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
3071 (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3072 (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
3074 if (strcmp(xmss_name, k->xmss_name)) {
3075 r = SSH_ERR_INVALID_FORMAT;
3078 if (pklen != sshkey_xmss_pklen(k) ||
3079 sklen != sshkey_xmss_sklen(k)) {
3080 r = SSH_ERR_INVALID_FORMAT;
3083 k->xmss_pk = xmss_pk;
3084 k->xmss_sk = xmss_sk;
3085 xmss_pk = xmss_sk = NULL;
3086 /* optional internal state */
3087 if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3090 #endif /* WITH_XMSS */
3092 r = SSH_ERR_KEY_TYPE_UNKNOWN;
3096 /* enable blinding */
3100 if (RSA_blinding_on(k->rsa, NULL) != 1) {
3101 r = SSH_ERR_LIBCRYPTO_ERROR;
3106 #endif /* WITH_OPENSSL */
3117 BN_clear_free(exponent);
3118 #endif /* WITH_OPENSSL */
3120 freezero(ed25519_pk, pklen);
3121 freezero(ed25519_sk, sklen);
3123 freezero(xmss_pk, pklen);
3124 freezero(xmss_sk, sklen);
3128 #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
3130 sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
3133 EC_POINT *nq = NULL;
3134 BIGNUM *order, *x, *y, *tmp;
3135 int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
3138 * NB. This assumes OpenSSL has already verified that the public
3139 * point lies on the curve. This is done by EC_POINT_oct2point()
3140 * implicitly calling EC_POINT_is_on_curve(). If this code is ever
3141 * reachable with public points not unmarshalled using
3142 * EC_POINT_oct2point then the caller will need to explicitly check.
3145 if ((bnctx = BN_CTX_new()) == NULL)
3146 return SSH_ERR_ALLOC_FAIL;
3147 BN_CTX_start(bnctx);
3150 * We shouldn't ever hit this case because bignum_get_ecpoint()
3151 * refuses to load GF2m points.
3153 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3154 NID_X9_62_prime_field)
3158 if (EC_POINT_is_at_infinity(group, public))
3161 if ((x = BN_CTX_get(bnctx)) == NULL ||
3162 (y = BN_CTX_get(bnctx)) == NULL ||
3163 (order = BN_CTX_get(bnctx)) == NULL ||
3164 (tmp = BN_CTX_get(bnctx)) == NULL) {
3165 ret = SSH_ERR_ALLOC_FAIL;
3169 /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
3170 if (EC_GROUP_get_order(group, order, bnctx) != 1 ||
3171 EC_POINT_get_affine_coordinates_GFp(group, public,
3172 x, y, bnctx) != 1) {
3173 ret = SSH_ERR_LIBCRYPTO_ERROR;
3176 if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
3177 BN_num_bits(y) <= BN_num_bits(order) / 2)
3180 /* nQ == infinity (n == order of subgroup) */
3181 if ((nq = EC_POINT_new(group)) == NULL) {
3182 ret = SSH_ERR_ALLOC_FAIL;
3185 if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) {
3186 ret = SSH_ERR_LIBCRYPTO_ERROR;
3189 if (EC_POINT_is_at_infinity(group, nq) != 1)
3192 /* x < order - 1, y < order - 1 */
3193 if (!BN_sub(tmp, order, BN_value_one())) {
3194 ret = SSH_ERR_LIBCRYPTO_ERROR;
3197 if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0)
3207 sshkey_ec_validate_private(const EC_KEY *key)
3210 BIGNUM *order, *tmp;
3211 int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
3213 if ((bnctx = BN_CTX_new()) == NULL)
3214 return SSH_ERR_ALLOC_FAIL;
3215 BN_CTX_start(bnctx);
3217 if ((order = BN_CTX_get(bnctx)) == NULL ||
3218 (tmp = BN_CTX_get(bnctx)) == NULL) {
3219 ret = SSH_ERR_ALLOC_FAIL;
3223 /* log2(private) > log2(order)/2 */
3224 if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) {
3225 ret = SSH_ERR_LIBCRYPTO_ERROR;
3228 if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
3229 BN_num_bits(order) / 2)
3232 /* private < order - 1 */
3233 if (!BN_sub(tmp, order, BN_value_one())) {
3234 ret = SSH_ERR_LIBCRYPTO_ERROR;
3237 if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0)
3246 sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
3251 if (point == NULL) {
3252 fputs("point=(NULL)\n", stderr);
3255 if ((bnctx = BN_CTX_new()) == NULL) {
3256 fprintf(stderr, "%s: BN_CTX_new failed\n", __func__);
3259 BN_CTX_start(bnctx);
3260 if ((x = BN_CTX_get(bnctx)) == NULL ||
3261 (y = BN_CTX_get(bnctx)) == NULL) {
3262 fprintf(stderr, "%s: BN_CTX_get failed\n", __func__);
3265 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3266 NID_X9_62_prime_field) {
3267 fprintf(stderr, "%s: group is not a prime field\n", __func__);
3270 if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y,
3272 fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
3276 fputs("x=", stderr);
3277 BN_print_fp(stderr, x);
3278 fputs("\ny=", stderr);
3279 BN_print_fp(stderr, y);
3280 fputs("\n", stderr);
3285 sshkey_dump_ec_key(const EC_KEY *key)
3287 const BIGNUM *exponent;
3289 sshkey_dump_ec_point(EC_KEY_get0_group(key),
3290 EC_KEY_get0_public_key(key));
3291 fputs("exponent=", stderr);
3292 if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
3293 fputs("(NULL)", stderr);
3295 BN_print_fp(stderr, EC_KEY_get0_private_key(key));
3296 fputs("\n", stderr);
3298 #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
3301 sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
3302 const char *passphrase, const char *comment, const char *ciphername,
3305 u_char *cp, *key = NULL, *pubkeyblob = NULL;
3306 u_char salt[SALT_LEN];
3308 size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
3310 int r = SSH_ERR_INTERNAL_ERROR;
3311 struct sshcipher_ctx *ciphercontext = NULL;
3312 const struct sshcipher *cipher;
3313 const char *kdfname = KDFNAME;
3314 struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
3317 rounds = DEFAULT_ROUNDS;
3318 if (passphrase == NULL || !strlen(passphrase)) {
3319 ciphername = "none";
3321 } else if (ciphername == NULL)
3322 ciphername = DEFAULT_CIPHERNAME;
3323 if ((cipher = cipher_by_name(ciphername)) == NULL) {
3324 r = SSH_ERR_INVALID_ARGUMENT;
3328 if ((kdf = sshbuf_new()) == NULL ||
3329 (encoded = sshbuf_new()) == NULL ||
3330 (encrypted = sshbuf_new()) == NULL) {
3331 r = SSH_ERR_ALLOC_FAIL;
3334 blocksize = cipher_blocksize(cipher);
3335 keylen = cipher_keylen(cipher);
3336 ivlen = cipher_ivlen(cipher);
3337 authlen = cipher_authlen(cipher);
3338 if ((key = calloc(1, keylen + ivlen)) == NULL) {
3339 r = SSH_ERR_ALLOC_FAIL;
3342 if (strcmp(kdfname, "bcrypt") == 0) {
3343 arc4random_buf(salt, SALT_LEN);
3344 if (bcrypt_pbkdf(passphrase, strlen(passphrase),
3345 salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) {
3346 r = SSH_ERR_INVALID_ARGUMENT;
3349 if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 ||
3350 (r = sshbuf_put_u32(kdf, rounds)) != 0)
3352 } else if (strcmp(kdfname, "none") != 0) {
3353 /* Unsupported KDF type */
3354 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3357 if ((r = cipher_init(&ciphercontext, cipher, key, keylen,
3358 key + keylen, ivlen, 1)) != 0)
3361 if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 ||
3362 (r = sshbuf_put_cstring(encoded, ciphername)) != 0 ||
3363 (r = sshbuf_put_cstring(encoded, kdfname)) != 0 ||
3364 (r = sshbuf_put_stringb(encoded, kdf)) != 0 ||
3365 (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */
3366 (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 ||
3367 (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0)
3370 /* set up the buffer that will be encrypted */
3372 /* Random check bytes */
3373 check = arc4random();
3374 if ((r = sshbuf_put_u32(encrypted, check)) != 0 ||
3375 (r = sshbuf_put_u32(encrypted, check)) != 0)
3378 /* append private key and comment*/
3379 if ((r = sshkey_private_serialize_opt(prv, encrypted,
3380 SSHKEY_SERIALIZE_FULL)) != 0 ||
3381 (r = sshbuf_put_cstring(encrypted, comment)) != 0)
3386 while (sshbuf_len(encrypted) % blocksize) {
3387 if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0)
3391 /* length in destination buffer */
3392 if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0)
3396 if ((r = sshbuf_reserve(encoded,
3397 sshbuf_len(encrypted) + authlen, &cp)) != 0)
3399 if ((r = cipher_crypt(ciphercontext, 0, cp,
3400 sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
3404 if ((b64 = sshbuf_dtob64(encoded)) == NULL) {
3405 r = SSH_ERR_ALLOC_FAIL;
3410 if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0)
3412 for (i = 0; i < strlen(b64); i++) {
3413 if ((r = sshbuf_put_u8(blob, b64[i])) != 0)
3415 /* insert line breaks */
3416 if (i % 70 == 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3419 if (i % 70 != 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3421 if ((r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
3429 sshbuf_free(encoded);
3430 sshbuf_free(encrypted);
3431 cipher_free(ciphercontext);
3432 explicit_bzero(salt, sizeof(salt));
3434 explicit_bzero(key, keylen + ivlen);
3437 if (pubkeyblob != NULL) {
3438 explicit_bzero(pubkeyblob, pubkeylen);
3442 explicit_bzero(b64, strlen(b64));
3449 sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3450 struct sshkey **keyp, char **commentp)
3452 char *comment = NULL, *ciphername = NULL, *kdfname = NULL;
3453 const struct sshcipher *cipher = NULL;
3455 int r = SSH_ERR_INTERNAL_ERROR;
3457 size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;
3458 struct sshbuf *encoded = NULL, *decoded = NULL;
3459 struct sshbuf *kdf = NULL, *decrypted = NULL;
3460 struct sshcipher_ctx *ciphercontext = NULL;
3461 struct sshkey *k = NULL;
3462 u_char *key = NULL, *salt = NULL, *dp, pad, last;
3463 u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
3467 if (commentp != NULL)
3470 if ((encoded = sshbuf_new()) == NULL ||
3471 (decoded = sshbuf_new()) == NULL ||
3472 (decrypted = sshbuf_new()) == NULL) {
3473 r = SSH_ERR_ALLOC_FAIL;
3477 /* check preamble */
3478 cp = sshbuf_ptr(blob);
3479 encoded_len = sshbuf_len(blob);
3480 if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) ||
3481 memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) {
3482 r = SSH_ERR_INVALID_FORMAT;
3485 cp += MARK_BEGIN_LEN;
3486 encoded_len -= MARK_BEGIN_LEN;
3488 /* Look for end marker, removing whitespace as we go */
3489 while (encoded_len > 0) {
3490 if (*cp != '\n' && *cp != '\r') {
3491 if ((r = sshbuf_put_u8(encoded, *cp)) != 0)
3498 if (encoded_len >= MARK_END_LEN &&
3499 memcmp(cp, MARK_END, MARK_END_LEN) == 0) {
3501 if ((r = sshbuf_put_u8(encoded, 0)) != 0)
3507 if (encoded_len == 0) {
3508 r = SSH_ERR_INVALID_FORMAT;
3513 if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0)
3517 if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) ||
3518 memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
3519 r = SSH_ERR_INVALID_FORMAT;
3522 /* parse public portion of key */
3523 if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
3524 (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
3525 (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
3526 (r = sshbuf_froms(decoded, &kdf)) != 0 ||
3527 (r = sshbuf_get_u32(decoded, &nkeys)) != 0 ||
3528 (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */
3529 (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
3532 if ((cipher = cipher_by_name(ciphername)) == NULL) {
3533 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3536 if ((passphrase == NULL || strlen(passphrase) == 0) &&
3537 strcmp(ciphername, "none") != 0) {
3538 /* passphrase required */
3539 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3542 if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
3543 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3546 if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
3547 r = SSH_ERR_INVALID_FORMAT;
3551 /* XXX only one key supported */
3552 r = SSH_ERR_INVALID_FORMAT;
3556 /* check size of encrypted key blob */
3557 blocksize = cipher_blocksize(cipher);
3558 if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
3559 r = SSH_ERR_INVALID_FORMAT;
3564 keylen = cipher_keylen(cipher);
3565 ivlen = cipher_ivlen(cipher);
3566 authlen = cipher_authlen(cipher);
3567 if ((key = calloc(1, keylen + ivlen)) == NULL) {
3568 r = SSH_ERR_ALLOC_FAIL;
3571 if (strcmp(kdfname, "bcrypt") == 0) {
3572 if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 ||
3573 (r = sshbuf_get_u32(kdf, &rounds)) != 0)
3575 if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
3576 key, keylen + ivlen, rounds) < 0) {
3577 r = SSH_ERR_INVALID_FORMAT;
3582 /* check that an appropriate amount of auth data is present */
3583 if (sshbuf_len(decoded) < encrypted_len + authlen) {
3584 r = SSH_ERR_INVALID_FORMAT;
3588 /* decrypt private portion of key */
3589 if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
3590 (r = cipher_init(&ciphercontext, cipher, key, keylen,
3591 key + keylen, ivlen, 0)) != 0)
3593 if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
3594 encrypted_len, 0, authlen)) != 0) {
3595 /* an integrity error here indicates an incorrect passphrase */
3596 if (r == SSH_ERR_MAC_INVALID)
3597 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3600 if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
3602 /* there should be no trailing data */
3603 if (sshbuf_len(decoded) != 0) {
3604 r = SSH_ERR_INVALID_FORMAT;
3608 /* check check bytes */
3609 if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 ||
3610 (r = sshbuf_get_u32(decrypted, &check2)) != 0)
3612 if (check1 != check2) {
3613 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3617 /* Load the private key and comment */
3618 if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
3619 (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
3622 /* Check deterministic padding */
3624 while (sshbuf_len(decrypted)) {
3625 if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
3627 if (pad != (++i & 0xff)) {
3628 r = SSH_ERR_INVALID_FORMAT;
3633 /* XXX decode pubkey and check against private */
3641 if (commentp != NULL) {
3642 *commentp = comment;
3647 cipher_free(ciphercontext);
3652 explicit_bzero(salt, slen);
3656 explicit_bzero(key, keylen + ivlen);
3659 sshbuf_free(encoded);
3660 sshbuf_free(decoded);
3662 sshbuf_free(decrypted);
3669 /* convert SSH v2 key in OpenSSL PEM format */
3671 sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
3672 const char *_passphrase, const char *comment)
3675 int blen, len = strlen(_passphrase);
3676 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
3677 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
3681 if (len > 0 && len <= 4)
3682 return SSH_ERR_PASSPHRASE_TOO_SHORT;
3683 if ((bio = BIO_new(BIO_s_mem())) == NULL)
3684 return SSH_ERR_ALLOC_FAIL;
3686 switch (key->type) {
3688 success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
3689 cipher, passphrase, len, NULL, NULL);
3691 #ifdef OPENSSL_HAS_ECC
3693 success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
3694 cipher, passphrase, len, NULL, NULL);
3698 success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
3699 cipher, passphrase, len, NULL, NULL);
3706 r = SSH_ERR_LIBCRYPTO_ERROR;
3709 if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
3710 r = SSH_ERR_INTERNAL_ERROR;
3713 if ((r = sshbuf_put(blob, bptr, blen)) != 0)
3720 #endif /* WITH_OPENSSL */
3722 /* Serialise "key" to buffer "blob" */
3724 sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3725 const char *passphrase, const char *comment,
3726 int force_new_format, const char *new_format_cipher, int new_format_rounds)
3728 switch (key->type) {
3733 if (force_new_format) {
3734 return sshkey_private_to_blob2(key, blob, passphrase,
3735 comment, new_format_cipher, new_format_rounds);
3737 return sshkey_private_pem_to_blob(key, blob,
3738 passphrase, comment);
3739 #endif /* WITH_OPENSSL */
3743 #endif /* WITH_XMSS */
3744 return sshkey_private_to_blob2(key, blob, passphrase,
3745 comment, new_format_cipher, new_format_rounds);
3747 return SSH_ERR_KEY_TYPE_UNKNOWN;
3754 translate_libcrypto_error(unsigned long pem_err)
3756 int pem_reason = ERR_GET_REASON(pem_err);
3758 switch (ERR_GET_LIB(pem_err)) {
3760 switch (pem_reason) {
3761 case PEM_R_BAD_PASSWORD_READ:
3762 case PEM_R_PROBLEMS_GETTING_PASSWORD:
3763 case PEM_R_BAD_DECRYPT:
3764 return SSH_ERR_KEY_WRONG_PASSPHRASE;
3766 return SSH_ERR_INVALID_FORMAT;
3769 switch (pem_reason) {
3770 case EVP_R_BAD_DECRYPT:
3771 return SSH_ERR_KEY_WRONG_PASSPHRASE;
3772 case EVP_R_BN_DECODE_ERROR:
3773 case EVP_R_DECODE_ERROR:
3774 #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
3775 case EVP_R_PRIVATE_KEY_DECODE_ERROR:
3777 return SSH_ERR_INVALID_FORMAT;
3779 return SSH_ERR_LIBCRYPTO_ERROR;
3782 return SSH_ERR_INVALID_FORMAT;
3784 return SSH_ERR_LIBCRYPTO_ERROR;
3788 clear_libcrypto_errors(void)
3790 while (ERR_get_error() != 0)
3795 * Translate OpenSSL error codes to determine whether
3796 * passphrase is required/incorrect.
3799 convert_libcrypto_error(void)
3802 * Some password errors are reported at the beginning
3803 * of the error queue.
3805 if (translate_libcrypto_error(ERR_peek_error()) ==
3806 SSH_ERR_KEY_WRONG_PASSPHRASE)
3807 return SSH_ERR_KEY_WRONG_PASSPHRASE;
3808 return translate_libcrypto_error(ERR_peek_last_error());
3812 sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
3813 const char *passphrase, struct sshkey **keyp)
3815 EVP_PKEY *pk = NULL;
3816 struct sshkey *prv = NULL;
3823 if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
3824 return SSH_ERR_ALLOC_FAIL;
3825 if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
3826 (int)sshbuf_len(blob)) {
3827 r = SSH_ERR_ALLOC_FAIL;
3831 clear_libcrypto_errors();
3832 if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
3833 (char *)passphrase)) == NULL) {
3834 r = convert_libcrypto_error();
3837 if (pk->type == EVP_PKEY_RSA &&
3838 (type == KEY_UNSPEC || type == KEY_RSA)) {
3839 if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3840 r = SSH_ERR_ALLOC_FAIL;
3843 prv->rsa = EVP_PKEY_get1_RSA(pk);
3844 prv->type = KEY_RSA;
3846 RSA_print_fp(stderr, prv->rsa, 8);
3848 if (RSA_blinding_on(prv->rsa, NULL) != 1) {
3849 r = SSH_ERR_LIBCRYPTO_ERROR;
3852 if (BN_num_bits(prv->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
3853 r = SSH_ERR_KEY_LENGTH;
3856 } else if (pk->type == EVP_PKEY_DSA &&
3857 (type == KEY_UNSPEC || type == KEY_DSA)) {
3858 if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3859 r = SSH_ERR_ALLOC_FAIL;
3862 prv->dsa = EVP_PKEY_get1_DSA(pk);
3863 prv->type = KEY_DSA;
3865 DSA_print_fp(stderr, prv->dsa, 8);
3867 #ifdef OPENSSL_HAS_ECC
3868 } else if (pk->type == EVP_PKEY_EC &&
3869 (type == KEY_UNSPEC || type == KEY_ECDSA)) {
3870 if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3871 r = SSH_ERR_ALLOC_FAIL;
3874 prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
3875 prv->type = KEY_ECDSA;
3876 prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
3877 if (prv->ecdsa_nid == -1 ||
3878 sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
3879 sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
3880 EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
3881 sshkey_ec_validate_private(prv->ecdsa) != 0) {
3882 r = SSH_ERR_INVALID_FORMAT;
3886 if (prv != NULL && prv->ecdsa != NULL)
3887 sshkey_dump_ec_key(prv->ecdsa);
3889 #endif /* OPENSSL_HAS_ECC */
3891 r = SSH_ERR_INVALID_FORMAT;
3905 #endif /* WITH_OPENSSL */
3908 sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
3909 const char *passphrase, struct sshkey **keyp, char **commentp)
3911 int r = SSH_ERR_INTERNAL_ERROR;
3915 if (commentp != NULL)
3923 return sshkey_parse_private_pem_fileblob(blob, type,
3925 #endif /* WITH_OPENSSL */
3929 #endif /* WITH_XMSS */
3930 return sshkey_parse_private2(blob, type, passphrase,
3933 r = sshkey_parse_private2(blob, type, passphrase, keyp,
3935 /* Do not fallback to PEM parser if only passphrase is wrong. */
3936 if (r == 0 || r == SSH_ERR_KEY_WRONG_PASSPHRASE)
3939 return sshkey_parse_private_pem_fileblob(blob, type,
3942 return SSH_ERR_INVALID_FORMAT;
3943 #endif /* WITH_OPENSSL */
3945 return SSH_ERR_KEY_TYPE_UNKNOWN;
3950 sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
3951 struct sshkey **keyp, char **commentp)
3955 if (commentp != NULL)
3958 return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
3959 passphrase, keyp, commentp);
3964 * serialize the key with the current state and forward the state
3968 sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
3969 u_int32_t maxsign, sshkey_printfn *pr)
3974 sshkey_type_plain(k->type) != KEY_XMSS)
3975 return sshkey_private_serialize_opt(k, b,
3976 SSHKEY_SERIALIZE_DEFAULT);
3977 if ((r = sshkey_xmss_get_state(k, pr)) != 0 ||
3978 (r = sshkey_private_serialize_opt(k, b,
3979 SSHKEY_SERIALIZE_STATE)) != 0 ||
3980 (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
3984 if ((rupdate = sshkey_xmss_update_state(k, pr)) != 0) {
3992 sshkey_signatures_left(const struct sshkey *k)
3994 if (sshkey_type_plain(k->type) == KEY_XMSS)
3995 return sshkey_xmss_signatures_left(k);
4000 sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4002 if (sshkey_type_plain(k->type) != KEY_XMSS)
4003 return SSH_ERR_INVALID_ARGUMENT;
4004 return sshkey_xmss_enable_maxsign(k, maxsign);
4008 sshkey_set_filename(struct sshkey *k, const char *filename)
4011 return SSH_ERR_INVALID_ARGUMENT;
4012 if (sshkey_type_plain(k->type) != KEY_XMSS)
4014 if (filename == NULL)
4015 return SSH_ERR_INVALID_ARGUMENT;
4016 if ((k->xmss_filename = strdup(filename)) == NULL)
4017 return SSH_ERR_ALLOC_FAIL;
4022 sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
4023 u_int32_t maxsign, sshkey_printfn *pr)
4025 return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
4029 sshkey_signatures_left(const struct sshkey *k)
4035 sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4037 return SSH_ERR_INVALID_ARGUMENT;
4041 sshkey_set_filename(struct sshkey *k, const char *filename)
4044 return SSH_ERR_INVALID_ARGUMENT;
4047 #endif /* WITH_XMSS */