1 /* $OpenBSD: sshkey.c,v 1.148 2024/12/03 15:53:51 tb 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>
32 #include <netinet/in.h>
35 #include <openssl/evp.h>
36 #include <openssl/err.h>
37 #include <openssl/pem.h>
40 #include "crypto_api.h"
51 #endif /* HAVE_UTIL_H */
59 #define SSHKEY_INTERNAL
65 #include "sshkey-xmss.h"
66 #include "xmss_fast.h"
69 #include "openbsd-compat/openssl-compat.h"
71 /* openssh private key file format */
72 #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
73 #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
74 #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
75 #define MARK_END_LEN (sizeof(MARK_END) - 1)
76 #define KDFNAME "bcrypt"
77 #define AUTH_MAGIC "openssh-key-v1"
79 #define DEFAULT_CIPHERNAME "aes256-ctr"
80 #define DEFAULT_ROUNDS 24
83 * Constants relating to "shielding" support; protection of keys expected
84 * to remain in memory for long durations
86 #define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024)
87 #define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */
88 #define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512
90 int sshkey_private_serialize_opt(struct sshkey
*key
,
91 struct sshbuf
*buf
, enum sshkey_serialize_rep
);
92 static int sshkey_from_blob_internal(struct sshbuf
*buf
,
93 struct sshkey
**keyp
, int allow_cert
);
95 /* Supported key types */
96 extern const struct sshkey_impl sshkey_ed25519_impl
;
97 extern const struct sshkey_impl sshkey_ed25519_cert_impl
;
98 extern const struct sshkey_impl sshkey_ed25519_sk_impl
;
99 extern const struct sshkey_impl sshkey_ed25519_sk_cert_impl
;
101 # ifdef OPENSSL_HAS_ECC
103 extern const struct sshkey_impl sshkey_ecdsa_sk_impl
;
104 extern const struct sshkey_impl sshkey_ecdsa_sk_cert_impl
;
105 extern const struct sshkey_impl sshkey_ecdsa_sk_webauthn_impl
;
106 # endif /* ENABLE_SK */
107 extern const struct sshkey_impl sshkey_ecdsa_nistp256_impl
;
108 extern const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl
;
109 extern const struct sshkey_impl sshkey_ecdsa_nistp384_impl
;
110 extern const struct sshkey_impl sshkey_ecdsa_nistp384_cert_impl
;
111 # ifdef OPENSSL_HAS_NISTP521
112 extern const struct sshkey_impl sshkey_ecdsa_nistp521_impl
;
113 extern const struct sshkey_impl sshkey_ecdsa_nistp521_cert_impl
;
114 # endif /* OPENSSL_HAS_NISTP521 */
115 # endif /* OPENSSL_HAS_ECC */
116 extern const struct sshkey_impl sshkey_rsa_impl
;
117 extern const struct sshkey_impl sshkey_rsa_cert_impl
;
118 extern const struct sshkey_impl sshkey_rsa_sha256_impl
;
119 extern const struct sshkey_impl sshkey_rsa_sha256_cert_impl
;
120 extern const struct sshkey_impl sshkey_rsa_sha512_impl
;
121 extern const struct sshkey_impl sshkey_rsa_sha512_cert_impl
;
123 extern const struct sshkey_impl sshkey_dss_impl
;
124 extern const struct sshkey_impl sshkey_dsa_cert_impl
;
126 #endif /* WITH_OPENSSL */
128 extern const struct sshkey_impl sshkey_xmss_impl
;
129 extern const struct sshkey_impl sshkey_xmss_cert_impl
;
132 const struct sshkey_impl
* const keyimpls
[] = {
133 &sshkey_ed25519_impl
,
134 &sshkey_ed25519_cert_impl
,
136 &sshkey_ed25519_sk_impl
,
137 &sshkey_ed25519_sk_cert_impl
,
140 # ifdef OPENSSL_HAS_ECC
141 &sshkey_ecdsa_nistp256_impl
,
142 &sshkey_ecdsa_nistp256_cert_impl
,
143 &sshkey_ecdsa_nistp384_impl
,
144 &sshkey_ecdsa_nistp384_cert_impl
,
145 # ifdef OPENSSL_HAS_NISTP521
146 &sshkey_ecdsa_nistp521_impl
,
147 &sshkey_ecdsa_nistp521_cert_impl
,
148 # endif /* OPENSSL_HAS_NISTP521 */
150 &sshkey_ecdsa_sk_impl
,
151 &sshkey_ecdsa_sk_cert_impl
,
152 &sshkey_ecdsa_sk_webauthn_impl
,
153 # endif /* ENABLE_SK */
154 # endif /* OPENSSL_HAS_ECC */
157 &sshkey_dsa_cert_impl
,
160 &sshkey_rsa_cert_impl
,
161 &sshkey_rsa_sha256_impl
,
162 &sshkey_rsa_sha256_cert_impl
,
163 &sshkey_rsa_sha512_impl
,
164 &sshkey_rsa_sha512_cert_impl
,
165 #endif /* WITH_OPENSSL */
168 &sshkey_xmss_cert_impl
,
173 static const struct sshkey_impl
*
174 sshkey_impl_from_type(int type
)
178 for (i
= 0; keyimpls
[i
] != NULL
; i
++) {
179 if (keyimpls
[i
]->type
== type
)
185 static const struct sshkey_impl
*
186 sshkey_impl_from_type_nid(int type
, int nid
)
190 for (i
= 0; keyimpls
[i
] != NULL
; i
++) {
191 if (keyimpls
[i
]->type
== type
&&
192 (keyimpls
[i
]->nid
== 0 || keyimpls
[i
]->nid
== nid
))
198 static const struct sshkey_impl
*
199 sshkey_impl_from_key(const struct sshkey
*k
)
203 return sshkey_impl_from_type_nid(k
->type
, k
->ecdsa_nid
);
207 sshkey_type(const struct sshkey
*k
)
209 const struct sshkey_impl
*impl
;
211 if ((impl
= sshkey_impl_from_key(k
)) == NULL
)
213 return impl
->shortname
;
217 sshkey_ssh_name_from_type_nid(int type
, int nid
)
219 const struct sshkey_impl
*impl
;
221 if ((impl
= sshkey_impl_from_type_nid(type
, nid
)) == NULL
)
222 return "ssh-unknown";
227 sshkey_type_is_cert(int type
)
229 const struct sshkey_impl
*impl
;
231 if ((impl
= sshkey_impl_from_type(type
)) == NULL
)
237 sshkey_ssh_name(const struct sshkey
*k
)
239 return sshkey_ssh_name_from_type_nid(k
->type
, k
->ecdsa_nid
);
243 sshkey_ssh_name_plain(const struct sshkey
*k
)
245 return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k
->type
),
250 type_from_name(const char *name
, int allow_short
)
253 const struct sshkey_impl
*impl
;
255 for (i
= 0; keyimpls
[i
] != NULL
; i
++) {
257 if (impl
->name
!= NULL
&& strcmp(name
, impl
->name
) == 0)
259 /* Only allow shortname matches for plain key types */
260 if (allow_short
&& !impl
->cert
&& impl
->shortname
!= NULL
&&
261 strcasecmp(impl
->shortname
, name
) == 0)
268 sshkey_type_from_name(const char *name
)
270 return type_from_name(name
, 0);
274 sshkey_type_from_shortname(const char *name
)
276 return type_from_name(name
, 1);
280 key_type_is_ecdsa_variant(int type
)
286 case KEY_ECDSA_SK_CERT
:
293 sshkey_ecdsa_nid_from_name(const char *name
)
297 for (i
= 0; keyimpls
[i
] != NULL
; i
++) {
298 if (!key_type_is_ecdsa_variant(keyimpls
[i
]->type
))
300 if (keyimpls
[i
]->name
!= NULL
&&
301 strcmp(name
, keyimpls
[i
]->name
) == 0)
302 return keyimpls
[i
]->nid
;
308 sshkey_match_keyname_to_sigalgs(const char *keyname
, const char *sigalgs
)
312 if (sigalgs
== NULL
|| *sigalgs
== '\0' ||
313 (ktype
= sshkey_type_from_name(keyname
)) == KEY_UNSPEC
)
315 else if (ktype
== KEY_RSA
) {
316 return match_pattern_list("ssh-rsa", sigalgs
, 0) == 1 ||
317 match_pattern_list("rsa-sha2-256", sigalgs
, 0) == 1 ||
318 match_pattern_list("rsa-sha2-512", sigalgs
, 0) == 1;
319 } else if (ktype
== KEY_RSA_CERT
) {
320 return match_pattern_list("ssh-rsa-cert-v01@openssh.com",
322 match_pattern_list("rsa-sha2-256-cert-v01@openssh.com",
324 match_pattern_list("rsa-sha2-512-cert-v01@openssh.com",
327 return match_pattern_list(keyname
, sigalgs
, 0) == 1;
331 sshkey_alg_list(int certs_only
, int plain_only
, int include_sigonly
, char sep
)
333 char *tmp
, *ret
= NULL
;
334 size_t i
, nlen
, rlen
= 0;
335 const struct sshkey_impl
*impl
;
337 for (i
= 0; keyimpls
[i
] != NULL
; i
++) {
339 if (impl
->name
== NULL
)
341 if (!include_sigonly
&& impl
->sigonly
)
343 if ((certs_only
&& !impl
->cert
) || (plain_only
&& impl
->cert
))
347 nlen
= strlen(impl
->name
);
348 if ((tmp
= realloc(ret
, rlen
+ nlen
+ 2)) == NULL
) {
353 memcpy(ret
+ rlen
, impl
->name
, nlen
+ 1);
360 sshkey_names_valid2(const char *names
, int allow_wildcard
, int plain_only
)
363 const struct sshkey_impl
*impl
;
366 if (names
== NULL
|| strcmp(names
, "") == 0)
368 if ((s
= cp
= strdup(names
)) == NULL
)
370 for ((p
= strsep(&cp
, ",")); p
&& *p
!= '\0';
371 (p
= strsep(&cp
, ","))) {
372 type
= sshkey_type_from_name(p
);
373 if (type
== KEY_UNSPEC
) {
374 if (allow_wildcard
) {
376 * Try matching key types against the string.
377 * If any has a positive or negative match then
378 * the component is accepted.
381 for (i
= 0; keyimpls
[i
] != NULL
; i
++) {
382 if (match_pattern_list(
383 keyimpls
[i
]->name
, p
, 0) != 0) {
393 } else if (plain_only
&& sshkey_type_is_cert(type
)) {
403 sshkey_size(const struct sshkey
*k
)
405 const struct sshkey_impl
*impl
;
407 if ((impl
= sshkey_impl_from_key(k
)) == NULL
)
409 if (impl
->funcs
->size
!= NULL
)
410 return impl
->funcs
->size(k
);
411 return impl
->keybits
;
415 sshkey_type_is_valid_ca(int type
)
417 const struct sshkey_impl
*impl
;
419 if ((impl
= sshkey_impl_from_type(type
)) == NULL
)
421 /* All non-certificate types may act as CAs */
426 sshkey_is_cert(const struct sshkey
*k
)
430 return sshkey_type_is_cert(k
->type
);
434 sshkey_is_sk(const struct sshkey
*k
)
438 switch (sshkey_type_plain(k
->type
)) {
447 /* Return the cert-less equivalent to a certified key type */
449 sshkey_type_plain(int type
)
458 case KEY_ECDSA_SK_CERT
:
460 case KEY_ED25519_CERT
:
462 case KEY_ED25519_SK_CERT
:
463 return KEY_ED25519_SK
;
471 /* Return the cert equivalent to a plain key type */
473 sshkey_type_certified(int type
)
481 return KEY_ECDSA_CERT
;
483 return KEY_ECDSA_SK_CERT
;
485 return KEY_ED25519_CERT
;
487 return KEY_ED25519_SK_CERT
;
489 return KEY_XMSS_CERT
;
496 static const EVP_MD
*
497 ssh_digest_to_md(int hash_alg
)
500 case SSH_DIGEST_SHA1
:
502 case SSH_DIGEST_SHA256
:
504 case SSH_DIGEST_SHA384
:
506 case SSH_DIGEST_SHA512
:
513 sshkey_pkey_digest_sign(EVP_PKEY
*pkey
, int hash_alg
, u_char
**sigp
,
514 size_t *lenp
, const u_char
*data
, size_t datalen
)
516 EVP_MD_CTX
*ctx
= NULL
;
525 slen
= EVP_PKEY_size(pkey
);
526 if (slen
<= 0 || slen
> SSHBUF_MAX_BIGNUM
||
527 (evpmd
= ssh_digest_to_md(hash_alg
)) == NULL
)
528 return SSH_ERR_INVALID_ARGUMENT
;
530 if ((sig
= malloc(slen
)) == NULL
)
531 return SSH_ERR_ALLOC_FAIL
;
533 if ((ctx
= EVP_MD_CTX_new()) == NULL
) {
534 ret
= SSH_ERR_ALLOC_FAIL
;
537 if (EVP_DigestSignInit(ctx
, NULL
, evpmd
, NULL
, pkey
) != 1 ||
538 EVP_DigestSign(ctx
, sig
, &slen
, data
, datalen
) != 1) {
539 ret
= SSH_ERR_LIBCRYPTO_ERROR
;
545 /* Now owned by the caller */
550 EVP_MD_CTX_free(ctx
);
556 sshkey_pkey_digest_verify(EVP_PKEY
*pkey
, int hash_alg
, const u_char
*data
,
557 size_t datalen
, u_char
*sigbuf
, size_t siglen
)
559 EVP_MD_CTX
*ctx
= NULL
;
560 int ret
= SSH_ERR_INTERNAL_ERROR
;
563 if ((evpmd
= ssh_digest_to_md(hash_alg
)) == NULL
)
564 return SSH_ERR_INVALID_ARGUMENT
;
565 if ((ctx
= EVP_MD_CTX_new()) == NULL
)
566 return SSH_ERR_ALLOC_FAIL
;
567 if (EVP_DigestVerifyInit(ctx
, NULL
, evpmd
, NULL
, pkey
) != 1) {
568 ret
= SSH_ERR_LIBCRYPTO_ERROR
;
571 switch (EVP_DigestVerify(ctx
, sigbuf
, siglen
, data
, datalen
)) {
576 ret
= SSH_ERR_SIGNATURE_INVALID
;
579 ret
= SSH_ERR_LIBCRYPTO_ERROR
;
584 EVP_MD_CTX_free(ctx
);
588 /* XXX: these are really begging for a table-driven approach */
590 sshkey_curve_name_to_nid(const char *name
)
592 if (strcmp(name
, "nistp256") == 0)
593 return NID_X9_62_prime256v1
;
594 else if (strcmp(name
, "nistp384") == 0)
595 return NID_secp384r1
;
596 # ifdef OPENSSL_HAS_NISTP521
597 else if (strcmp(name
, "nistp521") == 0)
598 return NID_secp521r1
;
599 # endif /* OPENSSL_HAS_NISTP521 */
605 sshkey_curve_nid_to_bits(int nid
)
608 case NID_X9_62_prime256v1
:
612 # ifdef OPENSSL_HAS_NISTP521
615 # endif /* OPENSSL_HAS_NISTP521 */
622 sshkey_ecdsa_bits_to_nid(int bits
)
626 return NID_X9_62_prime256v1
;
628 return NID_secp384r1
;
629 # ifdef OPENSSL_HAS_NISTP521
631 return NID_secp521r1
;
632 # endif /* OPENSSL_HAS_NISTP521 */
639 sshkey_curve_nid_to_name(int nid
)
642 case NID_X9_62_prime256v1
:
646 # ifdef OPENSSL_HAS_NISTP521
649 # endif /* OPENSSL_HAS_NISTP521 */
656 sshkey_ec_nid_to_hash_alg(int nid
)
658 int kbits
= sshkey_curve_nid_to_bits(nid
);
663 /* RFC5656 section 6.2.1 */
665 return SSH_DIGEST_SHA256
;
666 else if (kbits
<= 384)
667 return SSH_DIGEST_SHA384
;
669 return SSH_DIGEST_SHA512
;
671 #endif /* WITH_OPENSSL */
674 cert_free(struct sshkey_cert
*cert
)
680 sshbuf_free(cert
->certblob
);
681 sshbuf_free(cert
->critical
);
682 sshbuf_free(cert
->extensions
);
684 for (i
= 0; i
< cert
->nprincipals
; i
++)
685 free(cert
->principals
[i
]);
686 free(cert
->principals
);
687 sshkey_free(cert
->signature_key
);
688 free(cert
->signature_type
);
689 freezero(cert
, sizeof(*cert
));
692 static struct sshkey_cert
*
695 struct sshkey_cert
*cert
;
697 if ((cert
= calloc(1, sizeof(*cert
))) == NULL
)
699 if ((cert
->certblob
= sshbuf_new()) == NULL
||
700 (cert
->critical
= sshbuf_new()) == NULL
||
701 (cert
->extensions
= sshbuf_new()) == NULL
) {
706 cert
->principals
= NULL
;
707 cert
->signature_key
= NULL
;
708 cert
->signature_type
= NULL
;
716 const struct sshkey_impl
*impl
= NULL
;
718 if (type
!= KEY_UNSPEC
&&
719 (impl
= sshkey_impl_from_type(type
)) == NULL
)
722 /* All non-certificate types may act as CAs */
723 if ((k
= calloc(1, sizeof(*k
))) == NULL
)
727 if (impl
!= NULL
&& impl
->funcs
->alloc
!= NULL
) {
728 if (impl
->funcs
->alloc(k
) != 0) {
733 if (sshkey_is_cert(k
)) {
734 if ((k
->cert
= cert_new()) == NULL
) {
743 /* Frees common FIDO fields */
745 sshkey_sk_cleanup(struct sshkey
*k
)
747 free(k
->sk_application
);
748 sshbuf_free(k
->sk_key_handle
);
749 sshbuf_free(k
->sk_reserved
);
750 k
->sk_application
= NULL
;
751 k
->sk_key_handle
= k
->sk_reserved
= NULL
;
754 #if defined(MAP_CONCEAL)
755 # define PREKEY_MMAP_FLAG MAP_CONCEAL
756 #elif defined(MAP_NOCORE)
757 # define PREKEY_MMAP_FLAG MAP_NOCORE
759 # define PREKEY_MMAP_FLAG 0
763 sshkey_prekey_alloc(u_char
**prekeyp
, size_t len
)
768 if ((prekey
= mmap(NULL
, len
, PROT_READ
|PROT_WRITE
,
769 MAP_ANON
|MAP_PRIVATE
|PREKEY_MMAP_FLAG
, -1, 0)) == MAP_FAILED
)
770 return SSH_ERR_SYSTEM_ERROR
;
771 #if defined(MADV_DONTDUMP) && !defined(MAP_CONCEAL) && !defined(MAP_NOCORE)
772 (void)madvise(prekey
, len
, MADV_DONTDUMP
);
779 sshkey_prekey_free(void *prekey
, size_t len
)
787 sshkey_free_contents(struct sshkey
*k
)
789 const struct sshkey_impl
*impl
;
793 if ((impl
= sshkey_impl_from_type(k
->type
)) != NULL
&&
794 impl
->funcs
->cleanup
!= NULL
)
795 impl
->funcs
->cleanup(k
);
796 if (sshkey_is_cert(k
))
798 freezero(k
->shielded_private
, k
->shielded_len
);
799 sshkey_prekey_free(k
->shield_prekey
, k
->shield_prekey_len
);
803 sshkey_free(struct sshkey
*k
)
805 sshkey_free_contents(k
);
806 freezero(k
, sizeof(*k
));
810 cert_compare(struct sshkey_cert
*a
, struct sshkey_cert
*b
)
812 if (a
== NULL
&& b
== NULL
)
814 if (a
== NULL
|| b
== NULL
)
816 if (sshbuf_len(a
->certblob
) != sshbuf_len(b
->certblob
))
818 if (timingsafe_bcmp(sshbuf_ptr(a
->certblob
), sshbuf_ptr(b
->certblob
),
819 sshbuf_len(a
->certblob
)) != 0)
824 /* Compares FIDO-specific pubkey fields only */
826 sshkey_sk_fields_equal(const struct sshkey
*a
, const struct sshkey
*b
)
828 if (a
->sk_application
== NULL
|| b
->sk_application
== NULL
)
830 if (strcmp(a
->sk_application
, b
->sk_application
) != 0)
836 * Compare public portions of key only, allowing comparisons between
837 * certificates and plain keys too.
840 sshkey_equal_public(const struct sshkey
*a
, const struct sshkey
*b
)
842 const struct sshkey_impl
*impl
;
844 if (a
== NULL
|| b
== NULL
||
845 sshkey_type_plain(a
->type
) != sshkey_type_plain(b
->type
))
847 if ((impl
= sshkey_impl_from_type(a
->type
)) == NULL
)
849 return impl
->funcs
->equal(a
, b
);
853 sshkey_equal(const struct sshkey
*a
, const struct sshkey
*b
)
855 if (a
== NULL
|| b
== NULL
|| a
->type
!= b
->type
)
857 if (sshkey_is_cert(a
)) {
858 if (!cert_compare(a
->cert
, b
->cert
))
861 return sshkey_equal_public(a
, b
);
865 /* Serialise common FIDO key parts */
867 sshkey_serialize_sk(const struct sshkey
*key
, struct sshbuf
*b
)
871 if ((r
= sshbuf_put_cstring(b
, key
->sk_application
)) != 0)
878 to_blob_buf(const struct sshkey
*key
, struct sshbuf
*b
, int force_plain
,
879 enum sshkey_serialize_rep opts
)
881 int type
, ret
= SSH_ERR_INTERNAL_ERROR
;
882 const char *typename
;
883 const struct sshkey_impl
*impl
;
886 return SSH_ERR_INVALID_ARGUMENT
;
888 type
= force_plain
? sshkey_type_plain(key
->type
) : key
->type
;
890 if (sshkey_type_is_cert(type
)) {
891 if (key
->cert
== NULL
)
892 return SSH_ERR_EXPECTED_CERT
;
893 if (sshbuf_len(key
->cert
->certblob
) == 0)
894 return SSH_ERR_KEY_LACKS_CERTBLOB
;
895 /* Use the existing blob */
896 if ((ret
= sshbuf_putb(b
, key
->cert
->certblob
)) != 0)
900 if ((impl
= sshkey_impl_from_type(type
)) == NULL
)
901 return SSH_ERR_KEY_TYPE_UNKNOWN
;
903 typename
= sshkey_ssh_name_from_type_nid(type
, key
->ecdsa_nid
);
904 if ((ret
= sshbuf_put_cstring(b
, typename
)) != 0)
906 return impl
->funcs
->serialize_public(key
, b
, opts
);
910 sshkey_putb(const struct sshkey
*key
, struct sshbuf
*b
)
912 return to_blob_buf(key
, b
, 0, SSHKEY_SERIALIZE_DEFAULT
);
916 sshkey_puts_opts(const struct sshkey
*key
, struct sshbuf
*b
,
917 enum sshkey_serialize_rep opts
)
922 if ((tmp
= sshbuf_new()) == NULL
)
923 return SSH_ERR_ALLOC_FAIL
;
924 r
= to_blob_buf(key
, tmp
, 0, opts
);
926 r
= sshbuf_put_stringb(b
, tmp
);
932 sshkey_puts(const struct sshkey
*key
, struct sshbuf
*b
)
934 return sshkey_puts_opts(key
, b
, SSHKEY_SERIALIZE_DEFAULT
);
938 sshkey_putb_plain(const struct sshkey
*key
, struct sshbuf
*b
)
940 return to_blob_buf(key
, b
, 1, SSHKEY_SERIALIZE_DEFAULT
);
944 to_blob(const struct sshkey
*key
, u_char
**blobp
, size_t *lenp
, int force_plain
,
945 enum sshkey_serialize_rep opts
)
947 int ret
= SSH_ERR_INTERNAL_ERROR
;
949 struct sshbuf
*b
= NULL
;
955 if ((b
= sshbuf_new()) == NULL
)
956 return SSH_ERR_ALLOC_FAIL
;
957 if ((ret
= to_blob_buf(key
, b
, force_plain
, opts
)) != 0)
963 if ((*blobp
= malloc(len
)) == NULL
) {
964 ret
= SSH_ERR_ALLOC_FAIL
;
967 memcpy(*blobp
, sshbuf_ptr(b
), len
);
976 sshkey_to_blob(const struct sshkey
*key
, u_char
**blobp
, size_t *lenp
)
978 return to_blob(key
, blobp
, lenp
, 0, SSHKEY_SERIALIZE_DEFAULT
);
982 sshkey_plain_to_blob(const struct sshkey
*key
, u_char
**blobp
, size_t *lenp
)
984 return to_blob(key
, blobp
, lenp
, 1, SSHKEY_SERIALIZE_DEFAULT
);
988 sshkey_fingerprint_raw(const struct sshkey
*k
, int dgst_alg
,
989 u_char
**retp
, size_t *lenp
)
991 u_char
*blob
= NULL
, *ret
= NULL
;
993 int r
= SSH_ERR_INTERNAL_ERROR
;
999 if (ssh_digest_bytes(dgst_alg
) == 0) {
1000 r
= SSH_ERR_INVALID_ARGUMENT
;
1003 if ((r
= to_blob(k
, &blob
, &blob_len
, 1, SSHKEY_SERIALIZE_DEFAULT
))
1006 if ((ret
= calloc(1, SSH_DIGEST_MAX_LENGTH
)) == NULL
) {
1007 r
= SSH_ERR_ALLOC_FAIL
;
1010 if ((r
= ssh_digest_memory(dgst_alg
, blob
, blob_len
,
1011 ret
, SSH_DIGEST_MAX_LENGTH
)) != 0)
1019 *lenp
= ssh_digest_bytes(dgst_alg
);
1024 freezero(blob
, blob_len
);
1029 fingerprint_b64(const char *alg
, u_char
*dgst_raw
, size_t dgst_raw_len
)
1032 size_t plen
= strlen(alg
) + 1;
1033 size_t rlen
= ((dgst_raw_len
+ 2) / 3) * 4 + plen
+ 1;
1035 if (dgst_raw_len
> 65536 || (ret
= calloc(1, rlen
)) == NULL
)
1037 strlcpy(ret
, alg
, rlen
);
1038 strlcat(ret
, ":", rlen
);
1039 if (dgst_raw_len
== 0)
1041 if (b64_ntop(dgst_raw
, dgst_raw_len
, ret
+ plen
, rlen
- plen
) == -1) {
1042 freezero(ret
, rlen
);
1045 /* Trim padding characters from end */
1046 ret
[strcspn(ret
, "=")] = '\0';
1051 fingerprint_hex(const char *alg
, u_char
*dgst_raw
, size_t dgst_raw_len
)
1053 char *retval
, hex
[5];
1054 size_t i
, rlen
= dgst_raw_len
* 3 + strlen(alg
) + 2;
1056 if (dgst_raw_len
> 65536 || (retval
= calloc(1, rlen
)) == NULL
)
1058 strlcpy(retval
, alg
, rlen
);
1059 strlcat(retval
, ":", rlen
);
1060 for (i
= 0; i
< dgst_raw_len
; i
++) {
1061 snprintf(hex
, sizeof(hex
), "%s%02x",
1062 i
> 0 ? ":" : "", dgst_raw
[i
]);
1063 strlcat(retval
, hex
, rlen
);
1069 fingerprint_bubblebabble(u_char
*dgst_raw
, size_t dgst_raw_len
)
1071 char vowels
[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
1072 char consonants
[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
1073 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
1074 u_int i
, j
= 0, rounds
, seed
= 1;
1077 rounds
= (dgst_raw_len
/ 2) + 1;
1078 if ((retval
= calloc(rounds
, 6)) == NULL
)
1081 for (i
= 0; i
< rounds
; i
++) {
1082 u_int idx0
, idx1
, idx2
, idx3
, idx4
;
1083 if ((i
+ 1 < rounds
) || (dgst_raw_len
% 2 != 0)) {
1084 idx0
= (((((u_int
)(dgst_raw
[2 * i
])) >> 6) & 3) +
1086 idx1
= (((u_int
)(dgst_raw
[2 * i
])) >> 2) & 15;
1087 idx2
= ((((u_int
)(dgst_raw
[2 * i
])) & 3) +
1089 retval
[j
++] = vowels
[idx0
];
1090 retval
[j
++] = consonants
[idx1
];
1091 retval
[j
++] = vowels
[idx2
];
1092 if ((i
+ 1) < rounds
) {
1093 idx3
= (((u_int
)(dgst_raw
[(2 * i
) + 1])) >> 4) & 15;
1094 idx4
= (((u_int
)(dgst_raw
[(2 * i
) + 1]))) & 15;
1095 retval
[j
++] = consonants
[idx3
];
1097 retval
[j
++] = consonants
[idx4
];
1098 seed
= ((seed
* 5) +
1099 ((((u_int
)(dgst_raw
[2 * i
])) * 7) +
1100 ((u_int
)(dgst_raw
[(2 * i
) + 1])))) % 36;
1106 retval
[j
++] = vowels
[idx0
];
1107 retval
[j
++] = consonants
[idx1
];
1108 retval
[j
++] = vowels
[idx2
];
1117 * Draw an ASCII-Art representing the fingerprint so human brain can
1118 * profit from its built-in pattern recognition ability.
1119 * This technique is called "random art" and can be found in some
1120 * scientific publications like this original paper:
1122 * "Hash Visualization: a New Technique to improve Real-World Security",
1123 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
1124 * Techniques and E-Commerce (CrypTEC '99)
1125 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
1127 * The subject came up in a talk by Dan Kaminsky, too.
1129 * If you see the picture is different, the key is different.
1130 * If the picture looks the same, you still know nothing.
1132 * The algorithm used here is a worm crawling over a discrete plane,
1133 * leaving a trace (augmenting the field) everywhere it goes.
1134 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
1135 * makes the respective movement vector be ignored for this turn.
1136 * Graphs are not unambiguous, because circles in graphs can be
1137 * walked in either direction.
1141 * Field sizes for the random art. Have to be odd, so the starting point
1142 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
1143 * Else pictures would be too dense, and drawing the frame would
1144 * fail, too, because the key type would not fit in anymore.
1147 #define FLDSIZE_Y (FLDBASE + 1)
1148 #define FLDSIZE_X (FLDBASE * 2 + 1)
1150 fingerprint_randomart(const char *alg
, u_char
*dgst_raw
, size_t dgst_raw_len
,
1151 const struct sshkey
*k
)
1154 * Chars to be used after each other every time the worm
1155 * intersects with itself. Matter of taste.
1157 char *augmentation_string
= " .o+=*BOX@%&#/^SE";
1158 char *retval
, *p
, title
[FLDSIZE_X
], hash
[FLDSIZE_X
];
1159 u_char field
[FLDSIZE_X
][FLDSIZE_Y
];
1160 size_t i
, tlen
, hlen
;
1163 size_t len
= strlen(augmentation_string
) - 1;
1165 if ((retval
= calloc((FLDSIZE_X
+ 3), (FLDSIZE_Y
+ 2))) == NULL
)
1168 /* initialize field */
1169 memset(field
, 0, FLDSIZE_X
* FLDSIZE_Y
* sizeof(char));
1173 /* process raw key */
1174 for (i
= 0; i
< dgst_raw_len
; i
++) {
1176 /* each byte conveys four 2-bit move commands */
1177 input
= dgst_raw
[i
];
1178 for (b
= 0; b
< 4; b
++) {
1179 /* evaluate 2 bit, rest is shifted later */
1180 x
+= (input
& 0x1) ? 1 : -1;
1181 y
+= (input
& 0x2) ? 1 : -1;
1183 /* assure we are still in bounds */
1186 x
= MINIMUM(x
, FLDSIZE_X
- 1);
1187 y
= MINIMUM(y
, FLDSIZE_Y
- 1);
1189 /* augment the field */
1190 if (field
[x
][y
] < len
- 2)
1196 /* mark starting point and end point*/
1197 field
[FLDSIZE_X
/ 2][FLDSIZE_Y
/ 2] = len
- 1;
1200 /* assemble title */
1201 r
= snprintf(title
, sizeof(title
), "[%s %u]",
1202 sshkey_type(k
), sshkey_size(k
));
1203 /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
1204 if (r
< 0 || r
> (int)sizeof(title
))
1205 r
= snprintf(title
, sizeof(title
), "[%s]", sshkey_type(k
));
1206 tlen
= (r
<= 0) ? 0 : strlen(title
);
1208 /* assemble hash ID. */
1209 r
= snprintf(hash
, sizeof(hash
), "[%s]", alg
);
1210 hlen
= (r
<= 0) ? 0 : strlen(hash
);
1212 /* output upper border */
1215 for (i
= 0; i
< (FLDSIZE_X
- tlen
) / 2; i
++)
1217 memcpy(p
, title
, tlen
);
1219 for (i
+= tlen
; i
< FLDSIZE_X
; i
++)
1224 /* output content */
1225 for (y
= 0; y
< FLDSIZE_Y
; y
++) {
1227 for (x
= 0; x
< FLDSIZE_X
; x
++)
1228 *p
++ = augmentation_string
[MINIMUM(field
[x
][y
], len
)];
1233 /* output lower border */
1235 for (i
= 0; i
< (FLDSIZE_X
- hlen
) / 2; i
++)
1237 memcpy(p
, hash
, hlen
);
1239 for (i
+= hlen
; i
< FLDSIZE_X
; i
++)
1247 sshkey_fingerprint(const struct sshkey
*k
, int dgst_alg
,
1248 enum sshkey_fp_rep dgst_rep
)
1250 char *retval
= NULL
;
1252 size_t dgst_raw_len
;
1254 if (sshkey_fingerprint_raw(k
, dgst_alg
, &dgst_raw
, &dgst_raw_len
) != 0)
1257 case SSH_FP_DEFAULT
:
1258 if (dgst_alg
== SSH_DIGEST_MD5
) {
1259 retval
= fingerprint_hex(ssh_digest_alg_name(dgst_alg
),
1260 dgst_raw
, dgst_raw_len
);
1262 retval
= fingerprint_b64(ssh_digest_alg_name(dgst_alg
),
1263 dgst_raw
, dgst_raw_len
);
1267 retval
= fingerprint_hex(ssh_digest_alg_name(dgst_alg
),
1268 dgst_raw
, dgst_raw_len
);
1271 retval
= fingerprint_b64(ssh_digest_alg_name(dgst_alg
),
1272 dgst_raw
, dgst_raw_len
);
1274 case SSH_FP_BUBBLEBABBLE
:
1275 retval
= fingerprint_bubblebabble(dgst_raw
, dgst_raw_len
);
1277 case SSH_FP_RANDOMART
:
1278 retval
= fingerprint_randomart(ssh_digest_alg_name(dgst_alg
),
1279 dgst_raw
, dgst_raw_len
, k
);
1282 freezero(dgst_raw
, dgst_raw_len
);
1285 freezero(dgst_raw
, dgst_raw_len
);
1290 peek_type_nid(const char *s
, size_t l
, int *nid
)
1292 const struct sshkey_impl
*impl
;
1295 for (i
= 0; keyimpls
[i
] != NULL
; i
++) {
1297 if (impl
->name
== NULL
|| strlen(impl
->name
) != l
)
1299 if (memcmp(s
, impl
->name
, l
) == 0) {
1301 if (key_type_is_ecdsa_variant(impl
->type
))
1309 /* XXX this can now be made const char * */
1311 sshkey_read(struct sshkey
*ret
, char **cpp
)
1314 char *cp
, *blobcopy
;
1316 int r
, type
, curve_nid
= -1;
1317 struct sshbuf
*blob
;
1320 return SSH_ERR_INVALID_ARGUMENT
;
1321 if (ret
->type
!= KEY_UNSPEC
&& sshkey_impl_from_type(ret
->type
) == NULL
)
1322 return SSH_ERR_INVALID_ARGUMENT
;
1326 space
= strcspn(cp
, " \t");
1327 if (space
== strlen(cp
))
1328 return SSH_ERR_INVALID_FORMAT
;
1329 if ((type
= peek_type_nid(cp
, space
, &curve_nid
)) == KEY_UNSPEC
)
1330 return SSH_ERR_INVALID_FORMAT
;
1332 /* skip whitespace */
1333 for (cp
+= space
; *cp
== ' ' || *cp
== '\t'; cp
++)
1336 return SSH_ERR_INVALID_FORMAT
;
1337 if (ret
->type
!= KEY_UNSPEC
&& ret
->type
!= type
)
1338 return SSH_ERR_KEY_TYPE_MISMATCH
;
1339 if ((blob
= sshbuf_new()) == NULL
)
1340 return SSH_ERR_ALLOC_FAIL
;
1342 /* find end of keyblob and decode */
1343 space
= strcspn(cp
, " \t");
1344 if ((blobcopy
= strndup(cp
, space
)) == NULL
) {
1346 return SSH_ERR_ALLOC_FAIL
;
1348 if ((r
= sshbuf_b64tod(blob
, blobcopy
)) != 0) {
1354 if ((r
= sshkey_fromb(blob
, &k
)) != 0) {
1360 /* skip whitespace and leave cp at start of comment */
1361 for (cp
+= space
; *cp
== ' ' || *cp
== '\t'; cp
++)
1364 /* ensure type of blob matches type at start of line */
1365 if (k
->type
!= type
) {
1367 return SSH_ERR_KEY_TYPE_MISMATCH
;
1369 if (key_type_is_ecdsa_variant(type
) && curve_nid
!= k
->ecdsa_nid
) {
1371 return SSH_ERR_EC_CURVE_MISMATCH
;
1374 /* Fill in ret from parsed key */
1375 sshkey_free_contents(ret
);
1377 freezero(k
, sizeof(*k
));
1385 sshkey_to_base64(const struct sshkey
*key
, char **b64p
)
1387 int r
= SSH_ERR_INTERNAL_ERROR
;
1388 struct sshbuf
*b
= NULL
;
1393 if ((b
= sshbuf_new()) == NULL
)
1394 return SSH_ERR_ALLOC_FAIL
;
1395 if ((r
= sshkey_putb(key
, b
)) != 0)
1397 if ((uu
= sshbuf_dtob64_string(b
, 0)) == NULL
) {
1398 r
= SSH_ERR_ALLOC_FAIL
;
1414 sshkey_format_text(const struct sshkey
*key
, struct sshbuf
*b
)
1416 int r
= SSH_ERR_INTERNAL_ERROR
;
1419 if ((r
= sshkey_to_base64(key
, &uu
)) != 0)
1421 if ((r
= sshbuf_putf(b
, "%s %s",
1422 sshkey_ssh_name(key
), uu
)) != 0)
1431 sshkey_write(const struct sshkey
*key
, FILE *f
)
1433 struct sshbuf
*b
= NULL
;
1434 int r
= SSH_ERR_INTERNAL_ERROR
;
1436 if ((b
= sshbuf_new()) == NULL
)
1437 return SSH_ERR_ALLOC_FAIL
;
1438 if ((r
= sshkey_format_text(key
, b
)) != 0)
1440 if (fwrite(sshbuf_ptr(b
), sshbuf_len(b
), 1, f
) != 1) {
1443 r
= SSH_ERR_SYSTEM_ERROR
;
1454 sshkey_cert_type(const struct sshkey
*k
)
1456 switch (k
->cert
->type
) {
1457 case SSH2_CERT_TYPE_USER
:
1459 case SSH2_CERT_TYPE_HOST
:
1467 sshkey_check_rsa_length(const struct sshkey
*k
, int min_size
)
1472 if (k
== NULL
|| k
->pkey
== NULL
||
1473 (k
->type
!= KEY_RSA
&& k
->type
!= KEY_RSA_CERT
))
1475 nbits
= EVP_PKEY_bits(k
->pkey
);
1476 if (nbits
< SSH_RSA_MINIMUM_MODULUS_SIZE
||
1477 (min_size
> 0 && nbits
< min_size
))
1478 return SSH_ERR_KEY_LENGTH
;
1479 #endif /* WITH_OPENSSL */
1483 #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
1485 sshkey_ecdsa_key_to_nid(const EC_KEY
*k
)
1490 if (k
== NULL
|| (g
= EC_KEY_get0_group(k
)) == NULL
)
1492 if ((nid
= EC_GROUP_get_curve_name(g
)) <= 0)
1498 sshkey_ecdsa_pkey_to_nid(EVP_PKEY
*pkey
)
1500 return sshkey_ecdsa_key_to_nid(EVP_PKEY_get0_EC_KEY(pkey
));
1502 #endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
1505 sshkey_generate(int type
, u_int bits
, struct sshkey
**keyp
)
1508 int ret
= SSH_ERR_INTERNAL_ERROR
;
1509 const struct sshkey_impl
*impl
;
1511 if (keyp
== NULL
|| sshkey_type_is_cert(type
))
1512 return SSH_ERR_INVALID_ARGUMENT
;
1514 if ((impl
= sshkey_impl_from_type(type
)) == NULL
)
1515 return SSH_ERR_KEY_TYPE_UNKNOWN
;
1516 if (impl
->funcs
->generate
== NULL
)
1517 return SSH_ERR_FEATURE_UNSUPPORTED
;
1518 if ((k
= sshkey_new(KEY_UNSPEC
)) == NULL
)
1519 return SSH_ERR_ALLOC_FAIL
;
1521 if ((ret
= impl
->funcs
->generate(k
, bits
)) != 0) {
1531 sshkey_cert_copy(const struct sshkey
*from_key
, struct sshkey
*to_key
)
1534 const struct sshkey_cert
*from
;
1535 struct sshkey_cert
*to
;
1536 int r
= SSH_ERR_INTERNAL_ERROR
;
1538 if (to_key
== NULL
|| (from
= from_key
->cert
) == NULL
)
1539 return SSH_ERR_INVALID_ARGUMENT
;
1541 if ((to
= cert_new()) == NULL
)
1542 return SSH_ERR_ALLOC_FAIL
;
1544 if ((r
= sshbuf_putb(to
->certblob
, from
->certblob
)) != 0 ||
1545 (r
= sshbuf_putb(to
->critical
, from
->critical
)) != 0 ||
1546 (r
= sshbuf_putb(to
->extensions
, from
->extensions
)) != 0)
1549 to
->serial
= from
->serial
;
1550 to
->type
= from
->type
;
1551 if (from
->key_id
== NULL
)
1553 else if ((to
->key_id
= strdup(from
->key_id
)) == NULL
) {
1554 r
= SSH_ERR_ALLOC_FAIL
;
1557 to
->valid_after
= from
->valid_after
;
1558 to
->valid_before
= from
->valid_before
;
1559 if (from
->signature_key
== NULL
)
1560 to
->signature_key
= NULL
;
1561 else if ((r
= sshkey_from_private(from
->signature_key
,
1562 &to
->signature_key
)) != 0)
1564 if (from
->signature_type
!= NULL
&&
1565 (to
->signature_type
= strdup(from
->signature_type
)) == NULL
) {
1566 r
= SSH_ERR_ALLOC_FAIL
;
1569 if (from
->nprincipals
> SSHKEY_CERT_MAX_PRINCIPALS
) {
1570 r
= SSH_ERR_INVALID_ARGUMENT
;
1573 if (from
->nprincipals
> 0) {
1574 if ((to
->principals
= calloc(from
->nprincipals
,
1575 sizeof(*to
->principals
))) == NULL
) {
1576 r
= SSH_ERR_ALLOC_FAIL
;
1579 for (i
= 0; i
< from
->nprincipals
; i
++) {
1580 to
->principals
[i
] = strdup(from
->principals
[i
]);
1581 if (to
->principals
[i
] == NULL
) {
1582 to
->nprincipals
= i
;
1583 r
= SSH_ERR_ALLOC_FAIL
;
1588 to
->nprincipals
= from
->nprincipals
;
1591 cert_free(to_key
->cert
);
1601 sshkey_copy_public_sk(const struct sshkey
*from
, struct sshkey
*to
)
1603 /* Append security-key application string */
1604 if ((to
->sk_application
= strdup(from
->sk_application
)) == NULL
)
1605 return SSH_ERR_ALLOC_FAIL
;
1610 sshkey_from_private(const struct sshkey
*k
, struct sshkey
**pkp
)
1612 struct sshkey
*n
= NULL
;
1613 int r
= SSH_ERR_INTERNAL_ERROR
;
1614 const struct sshkey_impl
*impl
;
1617 if ((impl
= sshkey_impl_from_key(k
)) == NULL
)
1618 return SSH_ERR_KEY_TYPE_UNKNOWN
;
1619 if ((n
= sshkey_new(k
->type
)) == NULL
) {
1620 r
= SSH_ERR_ALLOC_FAIL
;
1623 if ((r
= impl
->funcs
->copy_public(k
, n
)) != 0)
1625 if (sshkey_is_cert(k
) && (r
= sshkey_cert_copy(k
, n
)) != 0)
1637 sshkey_is_shielded(struct sshkey
*k
)
1639 return k
!= NULL
&& k
->shielded_private
!= NULL
;
1643 sshkey_shield_private(struct sshkey
*k
)
1645 struct sshbuf
*prvbuf
= NULL
;
1646 u_char
*prekey
= NULL
, *enc
= NULL
, keyiv
[SSH_DIGEST_MAX_LENGTH
];
1647 struct sshcipher_ctx
*cctx
= NULL
;
1648 const struct sshcipher
*cipher
;
1649 size_t i
, enclen
= 0;
1650 struct sshkey
*kswap
= NULL
, tmp
;
1651 int r
= SSH_ERR_INTERNAL_ERROR
;
1654 fprintf(stderr
, "%s: entering for %s\n", __func__
, sshkey_ssh_name(k
));
1656 if ((cipher
= cipher_by_name(SSHKEY_SHIELD_CIPHER
)) == NULL
) {
1657 r
= SSH_ERR_INVALID_ARGUMENT
;
1660 if (cipher_keylen(cipher
) + cipher_ivlen(cipher
) >
1661 ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH
)) {
1662 r
= SSH_ERR_INTERNAL_ERROR
;
1666 /* Prepare a random pre-key, and from it an ephemeral key */
1667 if ((r
= sshkey_prekey_alloc(&prekey
, SSHKEY_SHIELD_PREKEY_LEN
)) != 0)
1669 arc4random_buf(prekey
, SSHKEY_SHIELD_PREKEY_LEN
);
1670 if ((r
= ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH
,
1671 prekey
, SSHKEY_SHIELD_PREKEY_LEN
,
1672 keyiv
, SSH_DIGEST_MAX_LENGTH
)) != 0)
1675 fprintf(stderr
, "%s: key+iv\n", __func__
);
1676 sshbuf_dump_data(keyiv
, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH
),
1679 if ((r
= cipher_init(&cctx
, cipher
, keyiv
, cipher_keylen(cipher
),
1680 keyiv
+ cipher_keylen(cipher
), cipher_ivlen(cipher
), 1)) != 0)
1683 /* Serialise and encrypt the private key using the ephemeral key */
1684 if ((prvbuf
= sshbuf_new()) == NULL
) {
1685 r
= SSH_ERR_ALLOC_FAIL
;
1688 if (sshkey_is_shielded(k
) && (r
= sshkey_unshield_private(k
)) != 0)
1690 if ((r
= sshkey_private_serialize_opt(k
, prvbuf
,
1691 SSHKEY_SERIALIZE_SHIELD
)) != 0)
1693 /* pad to cipher blocksize */
1695 while (sshbuf_len(prvbuf
) % cipher_blocksize(cipher
)) {
1696 if ((r
= sshbuf_put_u8(prvbuf
, ++i
& 0xff)) != 0)
1700 fprintf(stderr
, "%s: serialised\n", __func__
);
1701 sshbuf_dump(prvbuf
, stderr
);
1704 enclen
= sshbuf_len(prvbuf
);
1705 if ((enc
= malloc(enclen
)) == NULL
) {
1706 r
= SSH_ERR_ALLOC_FAIL
;
1709 if ((r
= cipher_crypt(cctx
, 0, enc
,
1710 sshbuf_ptr(prvbuf
), sshbuf_len(prvbuf
), 0, 0)) != 0)
1713 fprintf(stderr
, "%s: encrypted\n", __func__
);
1714 sshbuf_dump_data(enc
, enclen
, stderr
);
1717 /* Make a scrubbed, public-only copy of our private key argument */
1718 if ((r
= sshkey_from_private(k
, &kswap
)) != 0)
1721 /* Swap the private key out (it will be destroyed below) */
1726 /* Insert the shielded key into our argument */
1727 k
->shielded_private
= enc
;
1728 k
->shielded_len
= enclen
;
1729 k
->shield_prekey
= prekey
;
1730 k
->shield_prekey_len
= SSHKEY_SHIELD_PREKEY_LEN
;
1731 enc
= prekey
= NULL
; /* transferred */
1734 /* preserve key fields that are required for correct operation */
1735 k
->sk_flags
= kswap
->sk_flags
;
1741 /* XXX behaviour on error - invalidate original private key? */
1743 explicit_bzero(keyiv
, sizeof(keyiv
));
1744 explicit_bzero(&tmp
, sizeof(tmp
));
1745 freezero(enc
, enclen
);
1746 sshkey_prekey_free(prekey
, SSHKEY_SHIELD_PREKEY_LEN
);
1748 sshbuf_free(prvbuf
);
1752 /* Check deterministic padding after private key */
1754 private2_check_padding(struct sshbuf
*decrypted
)
1761 while (sshbuf_len(decrypted
)) {
1762 if ((r
= sshbuf_get_u8(decrypted
, &pad
)) != 0)
1764 if (pad
!= (++i
& 0xff)) {
1765 r
= SSH_ERR_INVALID_FORMAT
;
1772 explicit_bzero(&pad
, sizeof(pad
));
1773 explicit_bzero(&i
, sizeof(i
));
1778 sshkey_unshield_private(struct sshkey
*k
)
1780 struct sshbuf
*prvbuf
= NULL
;
1781 u_char
*cp
, keyiv
[SSH_DIGEST_MAX_LENGTH
];
1782 struct sshcipher_ctx
*cctx
= NULL
;
1783 const struct sshcipher
*cipher
;
1784 struct sshkey
*kswap
= NULL
, tmp
;
1785 int r
= SSH_ERR_INTERNAL_ERROR
;
1788 fprintf(stderr
, "%s: entering for %s\n", __func__
, sshkey_ssh_name(k
));
1790 if (!sshkey_is_shielded(k
))
1791 return 0; /* nothing to do */
1793 if ((cipher
= cipher_by_name(SSHKEY_SHIELD_CIPHER
)) == NULL
) {
1794 r
= SSH_ERR_INVALID_ARGUMENT
;
1797 if (cipher_keylen(cipher
) + cipher_ivlen(cipher
) >
1798 ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH
)) {
1799 r
= SSH_ERR_INTERNAL_ERROR
;
1802 /* check size of shielded key blob */
1803 if (k
->shielded_len
< cipher_blocksize(cipher
) ||
1804 (k
->shielded_len
% cipher_blocksize(cipher
)) != 0) {
1805 r
= SSH_ERR_INVALID_FORMAT
;
1809 /* Calculate the ephemeral key from the prekey */
1810 if ((r
= ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH
,
1811 k
->shield_prekey
, k
->shield_prekey_len
,
1812 keyiv
, SSH_DIGEST_MAX_LENGTH
)) != 0)
1814 if ((r
= cipher_init(&cctx
, cipher
, keyiv
, cipher_keylen(cipher
),
1815 keyiv
+ cipher_keylen(cipher
), cipher_ivlen(cipher
), 0)) != 0)
1818 fprintf(stderr
, "%s: key+iv\n", __func__
);
1819 sshbuf_dump_data(keyiv
, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH
),
1823 /* Decrypt and parse the shielded private key using the ephemeral key */
1824 if ((prvbuf
= sshbuf_new()) == NULL
) {
1825 r
= SSH_ERR_ALLOC_FAIL
;
1828 if ((r
= sshbuf_reserve(prvbuf
, k
->shielded_len
, &cp
)) != 0)
1832 fprintf(stderr
, "%s: encrypted\n", __func__
);
1833 sshbuf_dump_data(k
->shielded_private
, k
->shielded_len
, stderr
);
1835 if ((r
= cipher_crypt(cctx
, 0, cp
,
1836 k
->shielded_private
, k
->shielded_len
, 0, 0)) != 0)
1839 fprintf(stderr
, "%s: serialised\n", __func__
);
1840 sshbuf_dump(prvbuf
, stderr
);
1842 /* Parse private key */
1843 if ((r
= sshkey_private_deserialize(prvbuf
, &kswap
)) != 0)
1846 if ((r
= private2_check_padding(prvbuf
)) != 0)
1849 /* Swap the parsed key back into place */
1859 explicit_bzero(keyiv
, sizeof(keyiv
));
1860 explicit_bzero(&tmp
, sizeof(tmp
));
1862 sshbuf_free(prvbuf
);
1867 cert_parse(struct sshbuf
*b
, struct sshkey
*key
, struct sshbuf
*certbuf
)
1869 struct sshbuf
*principals
= NULL
, *crit
= NULL
;
1870 struct sshbuf
*exts
= NULL
, *ca
= NULL
;
1872 size_t signed_len
= 0, slen
= 0, kidlen
= 0;
1873 int ret
= SSH_ERR_INTERNAL_ERROR
;
1875 /* Copy the entire key blob for verification and later serialisation */
1876 if ((ret
= sshbuf_putb(key
->cert
->certblob
, certbuf
)) != 0)
1879 /* Parse body of certificate up to signature */
1880 if ((ret
= sshbuf_get_u64(b
, &key
->cert
->serial
)) != 0 ||
1881 (ret
= sshbuf_get_u32(b
, &key
->cert
->type
)) != 0 ||
1882 (ret
= sshbuf_get_cstring(b
, &key
->cert
->key_id
, &kidlen
)) != 0 ||
1883 (ret
= sshbuf_froms(b
, &principals
)) != 0 ||
1884 (ret
= sshbuf_get_u64(b
, &key
->cert
->valid_after
)) != 0 ||
1885 (ret
= sshbuf_get_u64(b
, &key
->cert
->valid_before
)) != 0 ||
1886 (ret
= sshbuf_froms(b
, &crit
)) != 0 ||
1887 (ret
= sshbuf_froms(b
, &exts
)) != 0 ||
1888 (ret
= sshbuf_get_string_direct(b
, NULL
, NULL
)) != 0 ||
1889 (ret
= sshbuf_froms(b
, &ca
)) != 0) {
1890 /* XXX debug print error for ret */
1891 ret
= SSH_ERR_INVALID_FORMAT
;
1895 /* Signature is left in the buffer so we can calculate this length */
1896 signed_len
= sshbuf_len(key
->cert
->certblob
) - sshbuf_len(b
);
1898 if ((ret
= sshbuf_get_string(b
, &sig
, &slen
)) != 0) {
1899 ret
= SSH_ERR_INVALID_FORMAT
;
1903 if (key
->cert
->type
!= SSH2_CERT_TYPE_USER
&&
1904 key
->cert
->type
!= SSH2_CERT_TYPE_HOST
) {
1905 ret
= SSH_ERR_KEY_CERT_UNKNOWN_TYPE
;
1909 /* Parse principals section */
1910 while (sshbuf_len(principals
) > 0) {
1911 char *principal
= NULL
;
1912 char **oprincipals
= NULL
;
1914 if (key
->cert
->nprincipals
>= SSHKEY_CERT_MAX_PRINCIPALS
) {
1915 ret
= SSH_ERR_INVALID_FORMAT
;
1918 if ((ret
= sshbuf_get_cstring(principals
, &principal
,
1920 ret
= SSH_ERR_INVALID_FORMAT
;
1923 oprincipals
= key
->cert
->principals
;
1924 key
->cert
->principals
= recallocarray(key
->cert
->principals
,
1925 key
->cert
->nprincipals
, key
->cert
->nprincipals
+ 1,
1926 sizeof(*key
->cert
->principals
));
1927 if (key
->cert
->principals
== NULL
) {
1929 key
->cert
->principals
= oprincipals
;
1930 ret
= SSH_ERR_ALLOC_FAIL
;
1933 key
->cert
->principals
[key
->cert
->nprincipals
++] = principal
;
1937 * Stash a copies of the critical options and extensions sections
1940 if ((ret
= sshbuf_putb(key
->cert
->critical
, crit
)) != 0 ||
1942 (ret
= sshbuf_putb(key
->cert
->extensions
, exts
)) != 0))
1946 * Validate critical options and extensions sections format.
1948 while (sshbuf_len(crit
) != 0) {
1949 if ((ret
= sshbuf_get_string_direct(crit
, NULL
, NULL
)) != 0 ||
1950 (ret
= sshbuf_get_string_direct(crit
, NULL
, NULL
)) != 0) {
1951 sshbuf_reset(key
->cert
->critical
);
1952 ret
= SSH_ERR_INVALID_FORMAT
;
1956 while (exts
!= NULL
&& sshbuf_len(exts
) != 0) {
1957 if ((ret
= sshbuf_get_string_direct(exts
, NULL
, NULL
)) != 0 ||
1958 (ret
= sshbuf_get_string_direct(exts
, NULL
, NULL
)) != 0) {
1959 sshbuf_reset(key
->cert
->extensions
);
1960 ret
= SSH_ERR_INVALID_FORMAT
;
1965 /* Parse CA key and check signature */
1966 if (sshkey_from_blob_internal(ca
, &key
->cert
->signature_key
, 0) != 0) {
1967 ret
= SSH_ERR_KEY_CERT_INVALID_SIGN_KEY
;
1970 if (!sshkey_type_is_valid_ca(key
->cert
->signature_key
->type
)) {
1971 ret
= SSH_ERR_KEY_CERT_INVALID_SIGN_KEY
;
1974 if ((ret
= sshkey_verify(key
->cert
->signature_key
, sig
, slen
,
1975 sshbuf_ptr(key
->cert
->certblob
), signed_len
, NULL
, 0, NULL
)) != 0)
1977 if ((ret
= sshkey_get_sigtype(sig
, slen
,
1978 &key
->cert
->signature_type
)) != 0)
1987 sshbuf_free(principals
);
1993 sshkey_deserialize_sk(struct sshbuf
*b
, struct sshkey
*key
)
1995 /* Parse additional security-key application string */
1996 if (sshbuf_get_cstring(b
, &key
->sk_application
, NULL
) != 0)
1997 return SSH_ERR_INVALID_FORMAT
;
2002 sshkey_from_blob_internal(struct sshbuf
*b
, struct sshkey
**keyp
,
2005 int type
, ret
= SSH_ERR_INTERNAL_ERROR
;
2007 struct sshkey
*key
= NULL
;
2008 struct sshbuf
*copy
;
2009 const struct sshkey_impl
*impl
;
2011 #ifdef DEBUG_PK /* XXX */
2012 sshbuf_dump(b
, stderr
);
2016 if ((copy
= sshbuf_fromb(b
)) == NULL
) {
2017 ret
= SSH_ERR_ALLOC_FAIL
;
2020 if (sshbuf_get_cstring(b
, &ktype
, NULL
) != 0) {
2021 ret
= SSH_ERR_INVALID_FORMAT
;
2025 type
= sshkey_type_from_name(ktype
);
2026 if (!allow_cert
&& sshkey_type_is_cert(type
)) {
2027 ret
= SSH_ERR_KEY_CERT_INVALID_SIGN_KEY
;
2030 if ((impl
= sshkey_impl_from_type(type
)) == NULL
) {
2031 ret
= SSH_ERR_KEY_TYPE_UNKNOWN
;
2034 if ((key
= sshkey_new(type
)) == NULL
) {
2035 ret
= SSH_ERR_ALLOC_FAIL
;
2038 if (sshkey_type_is_cert(type
)) {
2039 /* Skip nonce that precedes all certificates */
2040 if (sshbuf_get_string_direct(b
, NULL
, NULL
) != 0) {
2041 ret
= SSH_ERR_INVALID_FORMAT
;
2045 if ((ret
= impl
->funcs
->deserialize_public(ktype
, b
, key
)) != 0)
2048 /* Parse certificate potion */
2049 if (sshkey_is_cert(key
) && (ret
= cert_parse(b
, key
, copy
)) != 0)
2052 if (key
!= NULL
&& sshbuf_len(b
) != 0) {
2053 ret
= SSH_ERR_INVALID_FORMAT
;
2069 sshkey_from_blob(const u_char
*blob
, size_t blen
, struct sshkey
**keyp
)
2074 if ((b
= sshbuf_from(blob
, blen
)) == NULL
)
2075 return SSH_ERR_ALLOC_FAIL
;
2076 r
= sshkey_from_blob_internal(b
, keyp
, 1);
2082 sshkey_fromb(struct sshbuf
*b
, struct sshkey
**keyp
)
2084 return sshkey_from_blob_internal(b
, keyp
, 1);
2088 sshkey_froms(struct sshbuf
*buf
, struct sshkey
**keyp
)
2093 if ((r
= sshbuf_froms(buf
, &b
)) != 0)
2095 r
= sshkey_from_blob_internal(b
, keyp
, 1);
2101 sshkey_get_sigtype(const u_char
*sig
, size_t siglen
, char **sigtypep
)
2104 struct sshbuf
*b
= NULL
;
2105 char *sigtype
= NULL
;
2107 if (sigtypep
!= NULL
)
2109 if ((b
= sshbuf_from(sig
, siglen
)) == NULL
)
2110 return SSH_ERR_ALLOC_FAIL
;
2111 if ((r
= sshbuf_get_cstring(b
, &sigtype
, NULL
)) != 0)
2114 if (sigtypep
!= NULL
) {
2115 *sigtypep
= sigtype
;
2127 * Checks whether a certificate's signature type is allowed.
2128 * Returns 0 (success) if the certificate signature type appears in the
2129 * "allowed" pattern-list, or the key is not a certificate to begin with.
2130 * Otherwise returns a ssherr.h code.
2133 sshkey_check_cert_sigtype(const struct sshkey
*key
, const char *allowed
)
2135 if (key
== NULL
|| allowed
== NULL
)
2136 return SSH_ERR_INVALID_ARGUMENT
;
2137 if (!sshkey_type_is_cert(key
->type
))
2139 if (key
->cert
== NULL
|| key
->cert
->signature_type
== NULL
)
2140 return SSH_ERR_INVALID_ARGUMENT
;
2141 if (match_pattern_list(key
->cert
->signature_type
, allowed
, 0) != 1)
2142 return SSH_ERR_SIGN_ALG_UNSUPPORTED
;
2147 * Returns the expected signature algorithm for a given public key algorithm.
2150 sshkey_sigalg_by_name(const char *name
)
2152 const struct sshkey_impl
*impl
;
2155 for (i
= 0; keyimpls
[i
] != NULL
; i
++) {
2157 if (strcmp(impl
->name
, name
) != 0)
2159 if (impl
->sigalg
!= NULL
)
2160 return impl
->sigalg
;
2163 return sshkey_ssh_name_from_type_nid(
2164 sshkey_type_plain(impl
->type
), impl
->nid
);
2170 * Verifies that the signature algorithm appearing inside the signature blob
2171 * matches that which was requested.
2174 sshkey_check_sigtype(const u_char
*sig
, size_t siglen
,
2175 const char *requested_alg
)
2177 const char *expected_alg
;
2178 char *sigtype
= NULL
;
2181 if (requested_alg
== NULL
)
2183 if ((expected_alg
= sshkey_sigalg_by_name(requested_alg
)) == NULL
)
2184 return SSH_ERR_INVALID_ARGUMENT
;
2185 if ((r
= sshkey_get_sigtype(sig
, siglen
, &sigtype
)) != 0)
2187 r
= strcmp(expected_alg
, sigtype
) == 0;
2189 return r
? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED
;
2193 sshkey_sign(struct sshkey
*key
,
2194 u_char
**sigp
, size_t *lenp
,
2195 const u_char
*data
, size_t datalen
,
2196 const char *alg
, const char *sk_provider
, const char *sk_pin
, u_int compat
)
2198 int was_shielded
= sshkey_is_shielded(key
);
2199 int r2
, r
= SSH_ERR_INTERNAL_ERROR
;
2200 const struct sshkey_impl
*impl
;
2206 if (datalen
> SSH_KEY_MAX_SIGN_DATA_SIZE
)
2207 return SSH_ERR_INVALID_ARGUMENT
;
2208 if ((impl
= sshkey_impl_from_key(key
)) == NULL
)
2209 return SSH_ERR_KEY_TYPE_UNKNOWN
;
2210 if ((r
= sshkey_unshield_private(key
)) != 0)
2212 if (sshkey_is_sk(key
)) {
2213 r
= sshsk_sign(sk_provider
, key
, sigp
, lenp
, data
,
2214 datalen
, compat
, sk_pin
);
2216 if (impl
->funcs
->sign
== NULL
)
2217 r
= SSH_ERR_SIGN_ALG_UNSUPPORTED
;
2219 r
= impl
->funcs
->sign(key
, sigp
, lenp
, data
, datalen
,
2220 alg
, sk_provider
, sk_pin
, compat
);
2223 if (was_shielded
&& (r2
= sshkey_shield_private(key
)) != 0)
2229 * ssh_key_verify returns 0 for a correct signature and < 0 on error.
2230 * If "alg" specified, then the signature must use that algorithm.
2233 sshkey_verify(const struct sshkey
*key
,
2234 const u_char
*sig
, size_t siglen
,
2235 const u_char
*data
, size_t dlen
, const char *alg
, u_int compat
,
2236 struct sshkey_sig_details
**detailsp
)
2238 const struct sshkey_impl
*impl
;
2240 if (detailsp
!= NULL
)
2242 if (siglen
== 0 || dlen
> SSH_KEY_MAX_SIGN_DATA_SIZE
)
2243 return SSH_ERR_INVALID_ARGUMENT
;
2244 if ((impl
= sshkey_impl_from_key(key
)) == NULL
)
2245 return SSH_ERR_KEY_TYPE_UNKNOWN
;
2246 return impl
->funcs
->verify(key
, sig
, siglen
, data
, dlen
,
2247 alg
, compat
, detailsp
);
2250 /* Convert a plain key to their _CERT equivalent */
2252 sshkey_to_certified(struct sshkey
*k
)
2256 if ((newtype
= sshkey_type_certified(k
->type
)) == -1)
2257 return SSH_ERR_INVALID_ARGUMENT
;
2258 if ((k
->cert
= cert_new()) == NULL
)
2259 return SSH_ERR_ALLOC_FAIL
;
2264 /* Convert a certificate to its raw key equivalent */
2266 sshkey_drop_cert(struct sshkey
*k
)
2268 if (!sshkey_type_is_cert(k
->type
))
2269 return SSH_ERR_KEY_TYPE_UNKNOWN
;
2272 k
->type
= sshkey_type_plain(k
->type
);
2276 /* Sign a certified key, (re-)generating the signed certblob. */
2278 sshkey_certify_custom(struct sshkey
*k
, struct sshkey
*ca
, const char *alg
,
2279 const char *sk_provider
, const char *sk_pin
,
2280 sshkey_certify_signer
*signer
, void *signer_ctx
)
2282 const struct sshkey_impl
*impl
;
2283 struct sshbuf
*principals
= NULL
;
2284 u_char
*ca_blob
= NULL
, *sig_blob
= NULL
, nonce
[32];
2285 size_t i
, ca_len
, sig_len
;
2286 int ret
= SSH_ERR_INTERNAL_ERROR
;
2287 struct sshbuf
*cert
= NULL
;
2288 char *sigtype
= NULL
;
2290 if (k
== NULL
|| k
->cert
== NULL
||
2291 k
->cert
->certblob
== NULL
|| ca
== NULL
)
2292 return SSH_ERR_INVALID_ARGUMENT
;
2293 if (!sshkey_is_cert(k
))
2294 return SSH_ERR_KEY_TYPE_UNKNOWN
;
2295 if (!sshkey_type_is_valid_ca(ca
->type
))
2296 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY
;
2297 if ((impl
= sshkey_impl_from_key(k
)) == NULL
)
2298 return SSH_ERR_INTERNAL_ERROR
;
2301 * If no alg specified as argument but a signature_type was set,
2302 * then prefer that. If both were specified, then they must match.
2305 alg
= k
->cert
->signature_type
;
2306 else if (k
->cert
->signature_type
!= NULL
&&
2307 strcmp(alg
, k
->cert
->signature_type
) != 0)
2308 return SSH_ERR_INVALID_ARGUMENT
;
2311 * If no signing algorithm or signature_type was specified and we're
2312 * using a RSA key, then default to a good signature algorithm.
2314 if (alg
== NULL
&& ca
->type
== KEY_RSA
)
2315 alg
= "rsa-sha2-512";
2317 if ((ret
= sshkey_to_blob(ca
, &ca_blob
, &ca_len
)) != 0)
2318 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY
;
2320 cert
= k
->cert
->certblob
; /* for readability */
2322 if ((ret
= sshbuf_put_cstring(cert
, sshkey_ssh_name(k
))) != 0)
2325 /* -v01 certs put nonce first */
2326 arc4random_buf(&nonce
, sizeof(nonce
));
2327 if ((ret
= sshbuf_put_string(cert
, nonce
, sizeof(nonce
))) != 0)
2330 /* Public key next */
2331 if ((ret
= impl
->funcs
->serialize_public(k
, cert
,
2332 SSHKEY_SERIALIZE_DEFAULT
)) != 0)
2335 /* Then remaining cert fields */
2336 if ((ret
= sshbuf_put_u64(cert
, k
->cert
->serial
)) != 0 ||
2337 (ret
= sshbuf_put_u32(cert
, k
->cert
->type
)) != 0 ||
2338 (ret
= sshbuf_put_cstring(cert
, k
->cert
->key_id
)) != 0)
2341 if ((principals
= sshbuf_new()) == NULL
) {
2342 ret
= SSH_ERR_ALLOC_FAIL
;
2345 for (i
= 0; i
< k
->cert
->nprincipals
; i
++) {
2346 if ((ret
= sshbuf_put_cstring(principals
,
2347 k
->cert
->principals
[i
])) != 0)
2350 if ((ret
= sshbuf_put_stringb(cert
, principals
)) != 0 ||
2351 (ret
= sshbuf_put_u64(cert
, k
->cert
->valid_after
)) != 0 ||
2352 (ret
= sshbuf_put_u64(cert
, k
->cert
->valid_before
)) != 0 ||
2353 (ret
= sshbuf_put_stringb(cert
, k
->cert
->critical
)) != 0 ||
2354 (ret
= sshbuf_put_stringb(cert
, k
->cert
->extensions
)) != 0 ||
2355 (ret
= sshbuf_put_string(cert
, NULL
, 0)) != 0 || /* Reserved */
2356 (ret
= sshbuf_put_string(cert
, ca_blob
, ca_len
)) != 0)
2359 /* Sign the whole mess */
2360 if ((ret
= signer(ca
, &sig_blob
, &sig_len
, sshbuf_ptr(cert
),
2361 sshbuf_len(cert
), alg
, sk_provider
, sk_pin
, 0, signer_ctx
)) != 0)
2363 /* Check and update signature_type against what was actually used */
2364 if ((ret
= sshkey_get_sigtype(sig_blob
, sig_len
, &sigtype
)) != 0)
2366 if (alg
!= NULL
&& strcmp(alg
, sigtype
) != 0) {
2367 ret
= SSH_ERR_SIGN_ALG_UNSUPPORTED
;
2370 if (k
->cert
->signature_type
== NULL
) {
2371 k
->cert
->signature_type
= sigtype
;
2374 /* Append signature and we are done */
2375 if ((ret
= sshbuf_put_string(cert
, sig_blob
, sig_len
)) != 0)
2384 sshbuf_free(principals
);
2389 default_key_sign(struct sshkey
*key
, u_char
**sigp
, size_t *lenp
,
2390 const u_char
*data
, size_t datalen
,
2391 const char *alg
, const char *sk_provider
, const char *sk_pin
,
2392 u_int compat
, void *ctx
)
2395 return SSH_ERR_INVALID_ARGUMENT
;
2396 return sshkey_sign(key
, sigp
, lenp
, data
, datalen
, alg
,
2397 sk_provider
, sk_pin
, compat
);
2401 sshkey_certify(struct sshkey
*k
, struct sshkey
*ca
, const char *alg
,
2402 const char *sk_provider
, const char *sk_pin
)
2404 return sshkey_certify_custom(k
, ca
, alg
, sk_provider
, sk_pin
,
2405 default_key_sign
, NULL
);
2409 sshkey_cert_check_authority(const struct sshkey
*k
,
2410 int want_host
, int require_principal
, int wildcard_pattern
,
2411 uint64_t verify_time
, const char *name
, const char **reason
)
2413 u_int i
, principal_matches
;
2416 return SSH_ERR_INVALID_ARGUMENT
;
2417 if (!sshkey_is_cert(k
)) {
2418 *reason
= "Key is not a certificate";
2419 return SSH_ERR_KEY_CERT_INVALID
;
2422 if (k
->cert
->type
!= SSH2_CERT_TYPE_HOST
) {
2423 *reason
= "Certificate invalid: not a host certificate";
2424 return SSH_ERR_KEY_CERT_INVALID
;
2427 if (k
->cert
->type
!= SSH2_CERT_TYPE_USER
) {
2428 *reason
= "Certificate invalid: not a user certificate";
2429 return SSH_ERR_KEY_CERT_INVALID
;
2432 if (verify_time
< k
->cert
->valid_after
) {
2433 *reason
= "Certificate invalid: not yet valid";
2434 return SSH_ERR_KEY_CERT_INVALID
;
2436 if (verify_time
>= k
->cert
->valid_before
) {
2437 *reason
= "Certificate invalid: expired";
2438 return SSH_ERR_KEY_CERT_INVALID
;
2440 if (k
->cert
->nprincipals
== 0) {
2441 if (require_principal
) {
2442 *reason
= "Certificate lacks principal list";
2443 return SSH_ERR_KEY_CERT_INVALID
;
2445 } else if (name
!= NULL
) {
2446 principal_matches
= 0;
2447 for (i
= 0; i
< k
->cert
->nprincipals
; i
++) {
2448 if (wildcard_pattern
) {
2449 if (match_pattern(k
->cert
->principals
[i
],
2451 principal_matches
= 1;
2454 } else if (strcmp(name
, k
->cert
->principals
[i
]) == 0) {
2455 principal_matches
= 1;
2459 if (!principal_matches
) {
2460 *reason
= "Certificate invalid: name is not a listed "
2462 return SSH_ERR_KEY_CERT_INVALID
;
2469 sshkey_cert_check_authority_now(const struct sshkey
*k
,
2470 int want_host
, int require_principal
, int wildcard_pattern
,
2471 const char *name
, const char **reason
)
2475 if ((now
= time(NULL
)) < 0) {
2476 /* yikes - system clock before epoch! */
2477 *reason
= "Certificate invalid: not yet valid";
2478 return SSH_ERR_KEY_CERT_INVALID
;
2480 return sshkey_cert_check_authority(k
, want_host
, require_principal
,
2481 wildcard_pattern
, (uint64_t)now
, name
, reason
);
2485 sshkey_cert_check_host(const struct sshkey
*key
, const char *host
,
2486 int wildcard_principals
, const char *ca_sign_algorithms
,
2487 const char **reason
)
2491 if ((r
= sshkey_cert_check_authority_now(key
, 1, 0, wildcard_principals
,
2492 host
, reason
)) != 0)
2494 if (sshbuf_len(key
->cert
->critical
) != 0) {
2495 *reason
= "Certificate contains unsupported critical options";
2496 return SSH_ERR_KEY_CERT_INVALID
;
2498 if (ca_sign_algorithms
!= NULL
&&
2499 (r
= sshkey_check_cert_sigtype(key
, ca_sign_algorithms
)) != 0) {
2500 *reason
= "Certificate signed with disallowed algorithm";
2501 return SSH_ERR_KEY_CERT_INVALID
;
2507 sshkey_format_cert_validity(const struct sshkey_cert
*cert
, char *s
, size_t l
)
2509 char from
[32], to
[32], ret
[128];
2512 if (cert
->valid_after
== 0 &&
2513 cert
->valid_before
== 0xffffffffffffffffULL
)
2514 return strlcpy(s
, "forever", l
);
2516 if (cert
->valid_after
!= 0)
2517 format_absolute_time(cert
->valid_after
, from
, sizeof(from
));
2518 if (cert
->valid_before
!= 0xffffffffffffffffULL
)
2519 format_absolute_time(cert
->valid_before
, to
, sizeof(to
));
2521 if (cert
->valid_after
== 0)
2522 snprintf(ret
, sizeof(ret
), "before %s", to
);
2523 else if (cert
->valid_before
== 0xffffffffffffffffULL
)
2524 snprintf(ret
, sizeof(ret
), "after %s", from
);
2526 snprintf(ret
, sizeof(ret
), "from %s to %s", from
, to
);
2528 return strlcpy(s
, ret
, l
);
2531 /* Common serialization for FIDO private keys */
2533 sshkey_serialize_private_sk(const struct sshkey
*key
, struct sshbuf
*b
)
2537 if ((r
= sshbuf_put_cstring(b
, key
->sk_application
)) != 0 ||
2538 (r
= sshbuf_put_u8(b
, key
->sk_flags
)) != 0 ||
2539 (r
= sshbuf_put_stringb(b
, key
->sk_key_handle
)) != 0 ||
2540 (r
= sshbuf_put_stringb(b
, key
->sk_reserved
)) != 0)
2547 sshkey_private_serialize_opt(struct sshkey
*key
, struct sshbuf
*buf
,
2548 enum sshkey_serialize_rep opts
)
2550 int r
= SSH_ERR_INTERNAL_ERROR
;
2551 int was_shielded
= sshkey_is_shielded(key
);
2552 struct sshbuf
*b
= NULL
;
2553 const struct sshkey_impl
*impl
;
2555 if ((impl
= sshkey_impl_from_key(key
)) == NULL
)
2556 return SSH_ERR_INTERNAL_ERROR
;
2557 if ((r
= sshkey_unshield_private(key
)) != 0)
2559 if ((b
= sshbuf_new()) == NULL
)
2560 return SSH_ERR_ALLOC_FAIL
;
2561 if ((r
= sshbuf_put_cstring(b
, sshkey_ssh_name(key
))) != 0)
2563 if (sshkey_is_cert(key
)) {
2564 if (key
->cert
== NULL
||
2565 sshbuf_len(key
->cert
->certblob
) == 0) {
2566 r
= SSH_ERR_INVALID_ARGUMENT
;
2569 if ((r
= sshbuf_put_stringb(b
, key
->cert
->certblob
)) != 0)
2572 if ((r
= impl
->funcs
->serialize_private(key
, b
, opts
)) != 0)
2576 * success (but we still need to append the output to buf after
2577 * possibly re-shielding the private key)
2582 r
= sshkey_shield_private(key
);
2584 r
= sshbuf_putb(buf
, b
);
2591 sshkey_private_serialize(struct sshkey
*key
, struct sshbuf
*b
)
2593 return sshkey_private_serialize_opt(key
, b
,
2594 SSHKEY_SERIALIZE_DEFAULT
);
2597 /* Shared deserialization of FIDO private key components */
2599 sshkey_private_deserialize_sk(struct sshbuf
*buf
, struct sshkey
*k
)
2603 if ((k
->sk_key_handle
= sshbuf_new()) == NULL
||
2604 (k
->sk_reserved
= sshbuf_new()) == NULL
)
2605 return SSH_ERR_ALLOC_FAIL
;
2606 if ((r
= sshbuf_get_cstring(buf
, &k
->sk_application
, NULL
)) != 0 ||
2607 (r
= sshbuf_get_u8(buf
, &k
->sk_flags
)) != 0 ||
2608 (r
= sshbuf_get_stringb(buf
, k
->sk_key_handle
)) != 0 ||
2609 (r
= sshbuf_get_stringb(buf
, k
->sk_reserved
)) != 0)
2616 sshkey_private_deserialize(struct sshbuf
*buf
, struct sshkey
**kp
)
2618 const struct sshkey_impl
*impl
;
2620 char *expect_sk_application
= NULL
;
2621 u_char
*expect_ed25519_pk
= NULL
;
2622 struct sshkey
*k
= NULL
;
2623 int type
, r
= SSH_ERR_INTERNAL_ERROR
;
2627 if ((r
= sshbuf_get_cstring(buf
, &tname
, NULL
)) != 0)
2629 type
= sshkey_type_from_name(tname
);
2630 if (sshkey_type_is_cert(type
)) {
2632 * Certificate key private keys begin with the certificate
2633 * itself. Make sure this matches the type of the enclosing
2636 if ((r
= sshkey_froms(buf
, &k
)) != 0)
2638 if (k
->type
!= type
) {
2639 r
= SSH_ERR_KEY_CERT_MISMATCH
;
2642 /* For ECDSA keys, the group must match too */
2643 if (k
->type
== KEY_ECDSA
&&
2644 k
->ecdsa_nid
!= sshkey_ecdsa_nid_from_name(tname
)) {
2645 r
= SSH_ERR_KEY_CERT_MISMATCH
;
2649 * Several fields are redundant between certificate and
2650 * private key body, we require these to match.
2652 expect_sk_application
= k
->sk_application
;
2653 expect_ed25519_pk
= k
->ed25519_pk
;
2654 k
->sk_application
= NULL
;
2655 k
->ed25519_pk
= NULL
;
2656 /* XXX xmss too or refactor */
2658 if ((k
= sshkey_new(type
)) == NULL
) {
2659 r
= SSH_ERR_ALLOC_FAIL
;
2663 if ((impl
= sshkey_impl_from_type(type
)) == NULL
) {
2664 r
= SSH_ERR_INTERNAL_ERROR
;
2667 if ((r
= impl
->funcs
->deserialize_private(tname
, buf
, k
)) != 0)
2670 /* XXX xmss too or refactor */
2671 if ((expect_sk_application
!= NULL
&& (k
->sk_application
== NULL
||
2672 strcmp(expect_sk_application
, k
->sk_application
) != 0)) ||
2673 (expect_ed25519_pk
!= NULL
&& (k
->ed25519_pk
== NULL
||
2674 memcmp(expect_ed25519_pk
, k
->ed25519_pk
, ED25519_PK_SZ
) != 0))) {
2675 r
= SSH_ERR_KEY_CERT_MISMATCH
;
2687 free(expect_sk_application
);
2688 free(expect_ed25519_pk
);
2692 #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
2694 sshkey_ec_validate_public(const EC_GROUP
*group
, const EC_POINT
*public)
2696 EC_POINT
*nq
= NULL
;
2697 BIGNUM
*order
= NULL
, *x
= NULL
, *y
= NULL
, *tmp
= NULL
;
2698 int ret
= SSH_ERR_KEY_INVALID_EC_VALUE
;
2701 * NB. This assumes OpenSSL has already verified that the public
2702 * point lies on the curve. This is done by EC_POINT_oct2point()
2703 * implicitly calling EC_POINT_is_on_curve(). If this code is ever
2704 * reachable with public points not unmarshalled using
2705 * EC_POINT_oct2point then the caller will need to explicitly check.
2709 if (EC_POINT_is_at_infinity(group
, public))
2712 if ((x
= BN_new()) == NULL
||
2713 (y
= BN_new()) == NULL
||
2714 (order
= BN_new()) == NULL
||
2715 (tmp
= BN_new()) == NULL
) {
2716 ret
= SSH_ERR_ALLOC_FAIL
;
2720 /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
2721 if (EC_GROUP_get_order(group
, order
, NULL
) != 1 ||
2722 EC_POINT_get_affine_coordinates_GFp(group
, public,
2724 ret
= SSH_ERR_LIBCRYPTO_ERROR
;
2727 if (BN_num_bits(x
) <= BN_num_bits(order
) / 2 ||
2728 BN_num_bits(y
) <= BN_num_bits(order
) / 2)
2731 /* nQ == infinity (n == order of subgroup) */
2732 if ((nq
= EC_POINT_new(group
)) == NULL
) {
2733 ret
= SSH_ERR_ALLOC_FAIL
;
2736 if (EC_POINT_mul(group
, nq
, NULL
, public, order
, NULL
) != 1) {
2737 ret
= SSH_ERR_LIBCRYPTO_ERROR
;
2740 if (EC_POINT_is_at_infinity(group
, nq
) != 1)
2743 /* x < order - 1, y < order - 1 */
2744 if (!BN_sub(tmp
, order
, BN_value_one())) {
2745 ret
= SSH_ERR_LIBCRYPTO_ERROR
;
2748 if (BN_cmp(x
, tmp
) >= 0 || BN_cmp(y
, tmp
) >= 0)
2754 BN_clear_free(order
);
2761 sshkey_ec_validate_private(const EC_KEY
*key
)
2763 BIGNUM
*order
= NULL
, *tmp
= NULL
;
2764 int ret
= SSH_ERR_KEY_INVALID_EC_VALUE
;
2766 if ((order
= BN_new()) == NULL
|| (tmp
= BN_new()) == NULL
) {
2767 ret
= SSH_ERR_ALLOC_FAIL
;
2771 /* log2(private) > log2(order)/2 */
2772 if (EC_GROUP_get_order(EC_KEY_get0_group(key
), order
, NULL
) != 1) {
2773 ret
= SSH_ERR_LIBCRYPTO_ERROR
;
2776 if (BN_num_bits(EC_KEY_get0_private_key(key
)) <=
2777 BN_num_bits(order
) / 2)
2780 /* private < order - 1 */
2781 if (!BN_sub(tmp
, order
, BN_value_one())) {
2782 ret
= SSH_ERR_LIBCRYPTO_ERROR
;
2785 if (BN_cmp(EC_KEY_get0_private_key(key
), tmp
) >= 0)
2789 BN_clear_free(order
);
2795 sshkey_dump_ec_point(const EC_GROUP
*group
, const EC_POINT
*point
)
2797 BIGNUM
*x
= NULL
, *y
= NULL
;
2799 if (point
== NULL
) {
2800 fputs("point=(NULL)\n", stderr
);
2803 if ((x
= BN_new()) == NULL
|| (y
= BN_new()) == NULL
) {
2804 fprintf(stderr
, "%s: BN_new failed\n", __func__
);
2807 if (EC_POINT_get_affine_coordinates_GFp(group
, point
,
2809 fprintf(stderr
, "%s: EC_POINT_get_affine_coordinates_GFp\n",
2813 fputs("x=", stderr
);
2814 BN_print_fp(stderr
, x
);
2815 fputs("\ny=", stderr
);
2816 BN_print_fp(stderr
, y
);
2817 fputs("\n", stderr
);
2824 sshkey_dump_ec_key(const EC_KEY
*key
)
2826 const BIGNUM
*exponent
;
2828 sshkey_dump_ec_point(EC_KEY_get0_group(key
),
2829 EC_KEY_get0_public_key(key
));
2830 fputs("exponent=", stderr
);
2831 if ((exponent
= EC_KEY_get0_private_key(key
)) == NULL
)
2832 fputs("(NULL)", stderr
);
2834 BN_print_fp(stderr
, EC_KEY_get0_private_key(key
));
2835 fputs("\n", stderr
);
2837 #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
2840 sshkey_private_to_blob2(struct sshkey
*prv
, struct sshbuf
*blob
,
2841 const char *passphrase
, const char *comment
, const char *ciphername
,
2844 u_char
*cp
, *key
= NULL
, *pubkeyblob
= NULL
;
2845 u_char salt
[SALT_LEN
];
2846 size_t i
, pubkeylen
, keylen
, ivlen
, blocksize
, authlen
;
2848 int r
= SSH_ERR_INTERNAL_ERROR
;
2849 struct sshcipher_ctx
*ciphercontext
= NULL
;
2850 const struct sshcipher
*cipher
;
2851 const char *kdfname
= KDFNAME
;
2852 struct sshbuf
*encoded
= NULL
, *encrypted
= NULL
, *kdf
= NULL
;
2855 rounds
= DEFAULT_ROUNDS
;
2856 if (passphrase
== NULL
|| !strlen(passphrase
)) {
2857 ciphername
= "none";
2859 } else if (ciphername
== NULL
)
2860 ciphername
= DEFAULT_CIPHERNAME
;
2861 if ((cipher
= cipher_by_name(ciphername
)) == NULL
) {
2862 r
= SSH_ERR_INVALID_ARGUMENT
;
2866 if ((kdf
= sshbuf_new()) == NULL
||
2867 (encoded
= sshbuf_new()) == NULL
||
2868 (encrypted
= sshbuf_new()) == NULL
) {
2869 r
= SSH_ERR_ALLOC_FAIL
;
2872 blocksize
= cipher_blocksize(cipher
);
2873 keylen
= cipher_keylen(cipher
);
2874 ivlen
= cipher_ivlen(cipher
);
2875 authlen
= cipher_authlen(cipher
);
2876 if ((key
= calloc(1, keylen
+ ivlen
)) == NULL
) {
2877 r
= SSH_ERR_ALLOC_FAIL
;
2880 if (strcmp(kdfname
, "bcrypt") == 0) {
2881 arc4random_buf(salt
, SALT_LEN
);
2882 if (bcrypt_pbkdf(passphrase
, strlen(passphrase
),
2883 salt
, SALT_LEN
, key
, keylen
+ ivlen
, rounds
) < 0) {
2884 r
= SSH_ERR_INVALID_ARGUMENT
;
2887 if ((r
= sshbuf_put_string(kdf
, salt
, SALT_LEN
)) != 0 ||
2888 (r
= sshbuf_put_u32(kdf
, rounds
)) != 0)
2890 } else if (strcmp(kdfname
, "none") != 0) {
2891 /* Unsupported KDF type */
2892 r
= SSH_ERR_KEY_UNKNOWN_CIPHER
;
2895 if ((r
= cipher_init(&ciphercontext
, cipher
, key
, keylen
,
2896 key
+ keylen
, ivlen
, 1)) != 0)
2899 if ((r
= sshbuf_put(encoded
, AUTH_MAGIC
, sizeof(AUTH_MAGIC
))) != 0 ||
2900 (r
= sshbuf_put_cstring(encoded
, ciphername
)) != 0 ||
2901 (r
= sshbuf_put_cstring(encoded
, kdfname
)) != 0 ||
2902 (r
= sshbuf_put_stringb(encoded
, kdf
)) != 0 ||
2903 (r
= sshbuf_put_u32(encoded
, 1)) != 0 || /* number of keys */
2904 (r
= sshkey_to_blob(prv
, &pubkeyblob
, &pubkeylen
)) != 0 ||
2905 (r
= sshbuf_put_string(encoded
, pubkeyblob
, pubkeylen
)) != 0)
2908 /* set up the buffer that will be encrypted */
2910 /* Random check bytes */
2911 check
= arc4random();
2912 if ((r
= sshbuf_put_u32(encrypted
, check
)) != 0 ||
2913 (r
= sshbuf_put_u32(encrypted
, check
)) != 0)
2916 /* append private key and comment*/
2917 if ((r
= sshkey_private_serialize_opt(prv
, encrypted
,
2918 SSHKEY_SERIALIZE_FULL
)) != 0 ||
2919 (r
= sshbuf_put_cstring(encrypted
, comment
)) != 0)
2924 while (sshbuf_len(encrypted
) % blocksize
) {
2925 if ((r
= sshbuf_put_u8(encrypted
, ++i
& 0xff)) != 0)
2929 /* length in destination buffer */
2930 if ((r
= sshbuf_put_u32(encoded
, sshbuf_len(encrypted
))) != 0)
2934 if ((r
= sshbuf_reserve(encoded
,
2935 sshbuf_len(encrypted
) + authlen
, &cp
)) != 0)
2937 if ((r
= cipher_crypt(ciphercontext
, 0, cp
,
2938 sshbuf_ptr(encrypted
), sshbuf_len(encrypted
), 0, authlen
)) != 0)
2943 /* assemble uuencoded key */
2944 if ((r
= sshbuf_put(blob
, MARK_BEGIN
, MARK_BEGIN_LEN
)) != 0 ||
2945 (r
= sshbuf_dtob64(encoded
, blob
, 1)) != 0 ||
2946 (r
= sshbuf_put(blob
, MARK_END
, MARK_END_LEN
)) != 0)
2954 sshbuf_free(encoded
);
2955 sshbuf_free(encrypted
);
2956 cipher_free(ciphercontext
);
2957 explicit_bzero(salt
, sizeof(salt
));
2959 freezero(key
, keylen
+ ivlen
);
2960 if (pubkeyblob
!= NULL
)
2961 freezero(pubkeyblob
, pubkeylen
);
2966 private2_uudecode(struct sshbuf
*blob
, struct sshbuf
**decodedp
)
2972 struct sshbuf
*encoded
= NULL
, *decoded
= NULL
;
2974 if (blob
== NULL
|| decodedp
== NULL
)
2975 return SSH_ERR_INVALID_ARGUMENT
;
2979 if ((encoded
= sshbuf_new()) == NULL
||
2980 (decoded
= sshbuf_new()) == NULL
) {
2981 r
= SSH_ERR_ALLOC_FAIL
;
2985 /* check preamble */
2986 cp
= sshbuf_ptr(blob
);
2987 encoded_len
= sshbuf_len(blob
);
2988 if (encoded_len
< (MARK_BEGIN_LEN
+ MARK_END_LEN
) ||
2989 memcmp(cp
, MARK_BEGIN
, MARK_BEGIN_LEN
) != 0) {
2990 r
= SSH_ERR_INVALID_FORMAT
;
2993 cp
+= MARK_BEGIN_LEN
;
2994 encoded_len
-= MARK_BEGIN_LEN
;
2996 /* Look for end marker, removing whitespace as we go */
2997 while (encoded_len
> 0) {
2998 if (*cp
!= '\n' && *cp
!= '\r') {
2999 if ((r
= sshbuf_put_u8(encoded
, *cp
)) != 0)
3006 if (encoded_len
>= MARK_END_LEN
&&
3007 memcmp(cp
, MARK_END
, MARK_END_LEN
) == 0) {
3009 if ((r
= sshbuf_put_u8(encoded
, 0)) != 0)
3015 if (encoded_len
== 0) {
3016 r
= SSH_ERR_INVALID_FORMAT
;
3021 if ((r
= sshbuf_b64tod(decoded
, (char *)sshbuf_ptr(encoded
))) != 0)
3025 if (sshbuf_len(decoded
) < sizeof(AUTH_MAGIC
) ||
3026 memcmp(sshbuf_ptr(decoded
), AUTH_MAGIC
, sizeof(AUTH_MAGIC
))) {
3027 r
= SSH_ERR_INVALID_FORMAT
;
3031 *decodedp
= decoded
;
3035 sshbuf_free(encoded
);
3036 sshbuf_free(decoded
);
3041 private2_decrypt(struct sshbuf
*decoded
, const char *passphrase
,
3042 struct sshbuf
**decryptedp
, struct sshkey
**pubkeyp
)
3044 char *ciphername
= NULL
, *kdfname
= NULL
;
3045 const struct sshcipher
*cipher
= NULL
;
3046 int r
= SSH_ERR_INTERNAL_ERROR
;
3047 size_t keylen
= 0, ivlen
= 0, authlen
= 0, slen
= 0;
3048 struct sshbuf
*kdf
= NULL
, *decrypted
= NULL
;
3049 struct sshcipher_ctx
*ciphercontext
= NULL
;
3050 struct sshkey
*pubkey
= NULL
;
3051 u_char
*key
= NULL
, *salt
= NULL
, *dp
;
3052 u_int blocksize
, rounds
, nkeys
, encrypted_len
, check1
, check2
;
3054 if (decoded
== NULL
|| decryptedp
== NULL
|| pubkeyp
== NULL
)
3055 return SSH_ERR_INVALID_ARGUMENT
;
3060 if ((decrypted
= sshbuf_new()) == NULL
) {
3061 r
= SSH_ERR_ALLOC_FAIL
;
3065 /* parse public portion of key */
3066 if ((r
= sshbuf_consume(decoded
, sizeof(AUTH_MAGIC
))) != 0 ||
3067 (r
= sshbuf_get_cstring(decoded
, &ciphername
, NULL
)) != 0 ||
3068 (r
= sshbuf_get_cstring(decoded
, &kdfname
, NULL
)) != 0 ||
3069 (r
= sshbuf_froms(decoded
, &kdf
)) != 0 ||
3070 (r
= sshbuf_get_u32(decoded
, &nkeys
)) != 0)
3074 /* XXX only one key supported at present */
3075 r
= SSH_ERR_INVALID_FORMAT
;
3079 if ((r
= sshkey_froms(decoded
, &pubkey
)) != 0 ||
3080 (r
= sshbuf_get_u32(decoded
, &encrypted_len
)) != 0)
3083 if ((cipher
= cipher_by_name(ciphername
)) == NULL
) {
3084 r
= SSH_ERR_KEY_UNKNOWN_CIPHER
;
3087 if (strcmp(kdfname
, "none") != 0 && strcmp(kdfname
, "bcrypt") != 0) {
3088 r
= SSH_ERR_KEY_UNKNOWN_CIPHER
;
3091 if (strcmp(kdfname
, "none") == 0 && strcmp(ciphername
, "none") != 0) {
3092 r
= SSH_ERR_INVALID_FORMAT
;
3095 if ((passphrase
== NULL
|| strlen(passphrase
) == 0) &&
3096 strcmp(kdfname
, "none") != 0) {
3097 /* passphrase required */
3098 r
= SSH_ERR_KEY_WRONG_PASSPHRASE
;
3102 /* check size of encrypted key blob */
3103 blocksize
= cipher_blocksize(cipher
);
3104 if (encrypted_len
< blocksize
|| (encrypted_len
% blocksize
) != 0) {
3105 r
= SSH_ERR_INVALID_FORMAT
;
3110 keylen
= cipher_keylen(cipher
);
3111 ivlen
= cipher_ivlen(cipher
);
3112 authlen
= cipher_authlen(cipher
);
3113 if ((key
= calloc(1, keylen
+ ivlen
)) == NULL
) {
3114 r
= SSH_ERR_ALLOC_FAIL
;
3117 if (strcmp(kdfname
, "bcrypt") == 0) {
3118 if ((r
= sshbuf_get_string(kdf
, &salt
, &slen
)) != 0 ||
3119 (r
= sshbuf_get_u32(kdf
, &rounds
)) != 0)
3121 if (bcrypt_pbkdf(passphrase
, strlen(passphrase
), salt
, slen
,
3122 key
, keylen
+ ivlen
, rounds
) < 0) {
3123 r
= SSH_ERR_INVALID_FORMAT
;
3128 /* check that an appropriate amount of auth data is present */
3129 if (sshbuf_len(decoded
) < authlen
||
3130 sshbuf_len(decoded
) - authlen
< encrypted_len
) {
3131 r
= SSH_ERR_INVALID_FORMAT
;
3135 /* decrypt private portion of key */
3136 if ((r
= sshbuf_reserve(decrypted
, encrypted_len
, &dp
)) != 0 ||
3137 (r
= cipher_init(&ciphercontext
, cipher
, key
, keylen
,
3138 key
+ keylen
, ivlen
, 0)) != 0)
3140 if ((r
= cipher_crypt(ciphercontext
, 0, dp
, sshbuf_ptr(decoded
),
3141 encrypted_len
, 0, authlen
)) != 0) {
3142 /* an integrity error here indicates an incorrect passphrase */
3143 if (r
== SSH_ERR_MAC_INVALID
)
3144 r
= SSH_ERR_KEY_WRONG_PASSPHRASE
;
3147 if ((r
= sshbuf_consume(decoded
, encrypted_len
+ authlen
)) != 0)
3149 /* there should be no trailing data */
3150 if (sshbuf_len(decoded
) != 0) {
3151 r
= SSH_ERR_INVALID_FORMAT
;
3155 /* check check bytes */
3156 if ((r
= sshbuf_get_u32(decrypted
, &check1
)) != 0 ||
3157 (r
= sshbuf_get_u32(decrypted
, &check2
)) != 0)
3159 if (check1
!= check2
) {
3160 r
= SSH_ERR_KEY_WRONG_PASSPHRASE
;
3164 *decryptedp
= decrypted
;
3170 cipher_free(ciphercontext
);
3173 sshkey_free(pubkey
);
3175 explicit_bzero(salt
, slen
);
3179 explicit_bzero(key
, keylen
+ ivlen
);
3183 sshbuf_free(decrypted
);
3188 sshkey_parse_private2(struct sshbuf
*blob
, int type
, const char *passphrase
,
3189 struct sshkey
**keyp
, char **commentp
)
3191 char *comment
= NULL
;
3192 int r
= SSH_ERR_INTERNAL_ERROR
;
3193 struct sshbuf
*decoded
= NULL
, *decrypted
= NULL
;
3194 struct sshkey
*k
= NULL
, *pubkey
= NULL
;
3198 if (commentp
!= NULL
)
3201 /* Undo base64 encoding and decrypt the private section */
3202 if ((r
= private2_uudecode(blob
, &decoded
)) != 0 ||
3203 (r
= private2_decrypt(decoded
, passphrase
,
3204 &decrypted
, &pubkey
)) != 0)
3207 if (type
!= KEY_UNSPEC
&&
3208 sshkey_type_plain(type
) != sshkey_type_plain(pubkey
->type
)) {
3209 r
= SSH_ERR_KEY_TYPE_MISMATCH
;
3213 /* Load the private key and comment */
3214 if ((r
= sshkey_private_deserialize(decrypted
, &k
)) != 0 ||
3215 (r
= sshbuf_get_cstring(decrypted
, &comment
, NULL
)) != 0)
3218 /* Check deterministic padding after private section */
3219 if ((r
= private2_check_padding(decrypted
)) != 0)
3222 /* Check that the public key in the envelope matches the private key */
3223 if (!sshkey_equal(pubkey
, k
)) {
3224 r
= SSH_ERR_INVALID_FORMAT
;
3234 if (commentp
!= NULL
) {
3235 *commentp
= comment
;
3240 sshbuf_free(decoded
);
3241 sshbuf_free(decrypted
);
3243 sshkey_free(pubkey
);
3248 sshkey_parse_private2_pubkey(struct sshbuf
*blob
, int type
,
3249 struct sshkey
**keyp
)
3251 int r
= SSH_ERR_INTERNAL_ERROR
;
3252 struct sshbuf
*decoded
= NULL
;
3253 struct sshkey
*pubkey
= NULL
;
3259 if ((r
= private2_uudecode(blob
, &decoded
)) != 0)
3261 /* parse public key from unencrypted envelope */
3262 if ((r
= sshbuf_consume(decoded
, sizeof(AUTH_MAGIC
))) != 0 ||
3263 (r
= sshbuf_skip_string(decoded
)) != 0 || /* cipher */
3264 (r
= sshbuf_skip_string(decoded
)) != 0 || /* KDF alg */
3265 (r
= sshbuf_skip_string(decoded
)) != 0 || /* KDF hint */
3266 (r
= sshbuf_get_u32(decoded
, &nkeys
)) != 0)
3270 /* XXX only one key supported at present */
3271 r
= SSH_ERR_INVALID_FORMAT
;
3275 /* Parse the public key */
3276 if ((r
= sshkey_froms(decoded
, &pubkey
)) != 0)
3279 if (type
!= KEY_UNSPEC
&&
3280 sshkey_type_plain(type
) != sshkey_type_plain(pubkey
->type
)) {
3281 r
= SSH_ERR_KEY_TYPE_MISMATCH
;
3292 sshbuf_free(decoded
);
3293 sshkey_free(pubkey
);
3298 /* convert SSH v2 key to PEM or PKCS#8 format */
3300 sshkey_private_to_blob_pem_pkcs8(struct sshkey
*key
, struct sshbuf
*buf
,
3301 int format
, const char *_passphrase
, const char *comment
)
3303 int was_shielded
= sshkey_is_shielded(key
);
3305 int blen
, len
= strlen(_passphrase
);
3306 u_char
*passphrase
= (len
> 0) ? (u_char
*)_passphrase
: NULL
;
3307 const EVP_CIPHER
*cipher
= (len
> 0) ? EVP_aes_128_cbc() : NULL
;
3310 struct sshbuf
*blob
;
3311 EVP_PKEY
*pkey
= NULL
;
3313 if (len
> 0 && len
<= 4)
3314 return SSH_ERR_PASSPHRASE_TOO_SHORT
;
3315 if ((blob
= sshbuf_new()) == NULL
)
3316 return SSH_ERR_ALLOC_FAIL
;
3317 if ((bio
= BIO_new(BIO_s_mem())) == NULL
) {
3318 r
= SSH_ERR_ALLOC_FAIL
;
3321 if ((r
= sshkey_unshield_private(key
)) != 0)
3324 switch (key
->type
) {
3327 if (format
== SSHKEY_PRIVATE_PEM
) {
3328 success
= PEM_write_bio_DSAPrivateKey(bio
, key
->dsa
,
3329 cipher
, passphrase
, len
, NULL
, NULL
);
3331 if ((pkey
= EVP_PKEY_new()) == NULL
) {
3332 r
= SSH_ERR_ALLOC_FAIL
;
3335 success
= EVP_PKEY_set1_DSA(pkey
, key
->dsa
);
3339 #ifdef OPENSSL_HAS_ECC
3341 if (format
== SSHKEY_PRIVATE_PEM
) {
3342 success
= PEM_write_bio_ECPrivateKey(bio
,
3343 EVP_PKEY_get0_EC_KEY(key
->pkey
),
3344 cipher
, passphrase
, len
, NULL
, NULL
);
3347 EVP_PKEY_up_ref(key
->pkey
);
3353 if (format
== SSHKEY_PRIVATE_PEM
) {
3354 success
= PEM_write_bio_RSAPrivateKey(bio
,
3355 EVP_PKEY_get0_RSA(key
->pkey
),
3356 cipher
, passphrase
, len
, NULL
, NULL
);
3359 EVP_PKEY_up_ref(key
->pkey
);
3368 r
= SSH_ERR_LIBCRYPTO_ERROR
;
3371 if (format
== SSHKEY_PRIVATE_PKCS8
) {
3372 if ((success
= PEM_write_bio_PrivateKey(bio
, pkey
, cipher
,
3373 passphrase
, len
, NULL
, NULL
)) == 0) {
3374 r
= SSH_ERR_LIBCRYPTO_ERROR
;
3378 if ((blen
= BIO_get_mem_data(bio
, &bptr
)) <= 0) {
3379 r
= SSH_ERR_INTERNAL_ERROR
;
3382 if ((r
= sshbuf_put(blob
, bptr
, blen
)) != 0)
3387 r
= sshkey_shield_private(key
);
3389 r
= sshbuf_putb(buf
, blob
);
3391 EVP_PKEY_free(pkey
);
3396 #endif /* WITH_OPENSSL */
3398 /* Serialise "key" to buffer "blob" */
3400 sshkey_private_to_fileblob(struct sshkey
*key
, struct sshbuf
*blob
,
3401 const char *passphrase
, const char *comment
,
3402 int format
, const char *openssh_format_cipher
, int openssh_format_rounds
)
3404 switch (key
->type
) {
3409 break; /* see below */
3410 #endif /* WITH_OPENSSL */
3412 case KEY_ED25519_SK
:
3415 #endif /* WITH_XMSS */
3418 #endif /* WITH_OPENSSL */
3419 return sshkey_private_to_blob2(key
, blob
, passphrase
,
3420 comment
, openssh_format_cipher
, openssh_format_rounds
);
3422 return SSH_ERR_KEY_TYPE_UNKNOWN
;
3427 case SSHKEY_PRIVATE_OPENSSH
:
3428 return sshkey_private_to_blob2(key
, blob
, passphrase
,
3429 comment
, openssh_format_cipher
, openssh_format_rounds
);
3430 case SSHKEY_PRIVATE_PEM
:
3431 case SSHKEY_PRIVATE_PKCS8
:
3432 return sshkey_private_to_blob_pem_pkcs8(key
, blob
,
3433 format
, passphrase
, comment
);
3435 return SSH_ERR_INVALID_ARGUMENT
;
3437 #endif /* WITH_OPENSSL */
3442 translate_libcrypto_error(unsigned long pem_err
)
3444 int pem_reason
= ERR_GET_REASON(pem_err
);
3446 switch (ERR_GET_LIB(pem_err
)) {
3448 switch (pem_reason
) {
3449 case PEM_R_BAD_PASSWORD_READ
:
3450 #ifdef PEM_R_PROBLEMS_GETTING_PASSWORD
3451 case PEM_R_PROBLEMS_GETTING_PASSWORD
:
3453 #ifdef PEM_R_BAD_DECRYPT
3454 case PEM_R_BAD_DECRYPT
:
3456 return SSH_ERR_KEY_WRONG_PASSPHRASE
;
3458 return SSH_ERR_INVALID_FORMAT
;
3461 switch (pem_reason
) {
3462 #ifdef EVP_R_BAD_DECRYPT
3463 case EVP_R_BAD_DECRYPT
:
3464 return SSH_ERR_KEY_WRONG_PASSPHRASE
;
3466 #ifdef EVP_R_BN_DECODE_ERROR
3467 case EVP_R_BN_DECODE_ERROR
:
3469 case EVP_R_DECODE_ERROR
:
3470 #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
3471 case EVP_R_PRIVATE_KEY_DECODE_ERROR
:
3473 return SSH_ERR_INVALID_FORMAT
;
3475 return SSH_ERR_LIBCRYPTO_ERROR
;
3478 return SSH_ERR_INVALID_FORMAT
;
3480 return SSH_ERR_LIBCRYPTO_ERROR
;
3484 clear_libcrypto_errors(void)
3486 while (ERR_get_error() != 0)
3491 * Translate OpenSSL error codes to determine whether
3492 * passphrase is required/incorrect.
3495 convert_libcrypto_error(void)
3498 * Some password errors are reported at the beginning
3499 * of the error queue.
3501 if (translate_libcrypto_error(ERR_peek_error()) ==
3502 SSH_ERR_KEY_WRONG_PASSPHRASE
)
3503 return SSH_ERR_KEY_WRONG_PASSPHRASE
;
3504 return translate_libcrypto_error(ERR_peek_last_error());
3508 pem_passphrase_cb(char *buf
, int size
, int rwflag
, void *u
)
3510 char *p
= (char *)u
;
3513 if (p
== NULL
|| (len
= strlen(p
)) == 0)
3515 if (size
< 0 || len
> (size_t)size
)
3517 memcpy(buf
, p
, len
);
3522 sshkey_parse_private_pem_fileblob(struct sshbuf
*blob
, int type
,
3523 const char *passphrase
, struct sshkey
**keyp
)
3525 EVP_PKEY
*pk
= NULL
;
3526 struct sshkey
*prv
= NULL
;
3530 EC_KEY
*ecdsa
= NULL
;
3535 if ((bio
= BIO_new(BIO_s_mem())) == NULL
|| sshbuf_len(blob
) > INT_MAX
)
3536 return SSH_ERR_ALLOC_FAIL
;
3537 if (BIO_write(bio
, sshbuf_ptr(blob
), sshbuf_len(blob
)) !=
3538 (int)sshbuf_len(blob
)) {
3539 r
= SSH_ERR_ALLOC_FAIL
;
3543 clear_libcrypto_errors();
3544 if ((pk
= PEM_read_bio_PrivateKey(bio
, NULL
, pem_passphrase_cb
,
3545 (char *)passphrase
)) == NULL
) {
3547 * libcrypto may return various ASN.1 errors when attempting
3548 * to parse a key with an incorrect passphrase.
3549 * Treat all format errors as "incorrect passphrase" if a
3550 * passphrase was supplied.
3552 if (passphrase
!= NULL
&& *passphrase
!= '\0')
3553 r
= SSH_ERR_KEY_WRONG_PASSPHRASE
;
3555 r
= convert_libcrypto_error();
3558 if (EVP_PKEY_base_id(pk
) == EVP_PKEY_RSA
&&
3559 (type
== KEY_UNSPEC
|| type
== KEY_RSA
)) {
3560 if ((prv
= sshkey_new(KEY_UNSPEC
)) == NULL
) {
3561 r
= SSH_ERR_ALLOC_FAIL
;
3564 if ((rsa
= EVP_PKEY_get1_RSA(pk
)) == NULL
) {
3565 r
= SSH_ERR_LIBCRYPTO_ERROR
;
3568 prv
->type
= KEY_RSA
;
3570 RSA_print_fp(stderr
, rsa
, 8);
3572 if (RSA_blinding_on(rsa
, NULL
) != 1 ||
3573 EVP_PKEY_set1_RSA(pk
, rsa
) != 1) {
3574 r
= SSH_ERR_LIBCRYPTO_ERROR
;
3577 EVP_PKEY_up_ref(pk
);
3579 if ((r
= sshkey_check_rsa_length(prv
, 0)) != 0)
3582 } else if (EVP_PKEY_base_id(pk
) == EVP_PKEY_DSA
&&
3583 (type
== KEY_UNSPEC
|| type
== KEY_DSA
)) {
3584 if ((prv
= sshkey_new(KEY_UNSPEC
)) == NULL
) {
3585 r
= SSH_ERR_ALLOC_FAIL
;
3588 prv
->dsa
= EVP_PKEY_get1_DSA(pk
);
3589 prv
->type
= KEY_DSA
;
3591 DSA_print_fp(stderr
, prv
->dsa
, 8);
3594 #ifdef OPENSSL_HAS_ECC
3595 } else if (EVP_PKEY_base_id(pk
) == EVP_PKEY_EC
&&
3596 (type
== KEY_UNSPEC
|| type
== KEY_ECDSA
)) {
3597 if ((prv
= sshkey_new(KEY_UNSPEC
)) == NULL
) {
3598 r
= SSH_ERR_ALLOC_FAIL
;
3601 if ((prv
->ecdsa_nid
= sshkey_ecdsa_fixup_group(pk
)) == -1 ||
3602 (ecdsa
= EVP_PKEY_get1_EC_KEY(pk
)) == NULL
) {
3603 r
= SSH_ERR_LIBCRYPTO_ERROR
;
3606 prv
->type
= KEY_ECDSA
;
3607 if (sshkey_curve_nid_to_name(prv
->ecdsa_nid
) == NULL
||
3608 sshkey_ec_validate_public(EC_KEY_get0_group(ecdsa
),
3609 EC_KEY_get0_public_key(ecdsa
)) != 0 ||
3610 sshkey_ec_validate_private(ecdsa
) != 0) {
3611 r
= SSH_ERR_INVALID_FORMAT
;
3614 EVP_PKEY_up_ref(pk
);
3617 if (prv
!= NULL
&& prv
->pkey
!= NULL
)
3618 sshkey_dump_ec_key(EVP_PKEY_get0_EC_KEY(prv
->pkey
));
3620 #endif /* OPENSSL_HAS_ECC */
3621 #ifdef OPENSSL_HAS_ED25519
3622 } else if (EVP_PKEY_base_id(pk
) == EVP_PKEY_ED25519
&&
3623 (type
== KEY_UNSPEC
|| type
== KEY_ED25519
)) {
3626 if ((prv
= sshkey_new(KEY_UNSPEC
)) == NULL
||
3627 (prv
->ed25519_sk
= calloc(1, ED25519_SK_SZ
)) == NULL
||
3628 (prv
->ed25519_pk
= calloc(1, ED25519_PK_SZ
)) == NULL
) {
3629 r
= SSH_ERR_ALLOC_FAIL
;
3632 prv
->type
= KEY_ED25519
;
3633 len
= ED25519_PK_SZ
;
3634 if (!EVP_PKEY_get_raw_public_key(pk
, prv
->ed25519_pk
, &len
)) {
3635 r
= SSH_ERR_LIBCRYPTO_ERROR
;
3638 if (len
!= ED25519_PK_SZ
) {
3639 r
= SSH_ERR_INVALID_FORMAT
;
3642 len
= ED25519_SK_SZ
- ED25519_PK_SZ
;
3643 if (!EVP_PKEY_get_raw_private_key(pk
, prv
->ed25519_sk
, &len
)) {
3644 r
= SSH_ERR_LIBCRYPTO_ERROR
;
3647 if (len
!= ED25519_SK_SZ
- ED25519_PK_SZ
) {
3648 r
= SSH_ERR_INVALID_FORMAT
;
3651 /* Append the public key to our private key */
3652 memcpy(prv
->ed25519_sk
+ (ED25519_SK_SZ
- ED25519_PK_SZ
),
3653 prv
->ed25519_pk
, ED25519_PK_SZ
);
3655 sshbuf_dump_data(prv
->ed25519_sk
, ED25519_SK_SZ
, stderr
);
3657 #endif /* OPENSSL_HAS_ED25519 */
3659 r
= SSH_ERR_INVALID_FORMAT
;
3671 #ifdef OPENSSL_HAS_ECC
3677 #endif /* WITH_OPENSSL */
3680 sshkey_parse_private_fileblob_type(struct sshbuf
*blob
, int type
,
3681 const char *passphrase
, struct sshkey
**keyp
, char **commentp
)
3683 int r
= SSH_ERR_INTERNAL_ERROR
;
3687 if (commentp
!= NULL
)
3692 /* No fallback for new-format-only keys */
3693 return sshkey_parse_private2(blob
, type
, passphrase
,
3696 r
= sshkey_parse_private2(blob
, type
, passphrase
, keyp
,
3698 /* Only fallback to PEM parser if a format error occurred. */
3699 if (r
!= SSH_ERR_INVALID_FORMAT
)
3702 return sshkey_parse_private_pem_fileblob(blob
, type
,
3705 return SSH_ERR_INVALID_FORMAT
;
3706 #endif /* WITH_OPENSSL */
3711 sshkey_parse_private_fileblob(struct sshbuf
*buffer
, const char *passphrase
,
3712 struct sshkey
**keyp
, char **commentp
)
3716 if (commentp
!= NULL
)
3719 return sshkey_parse_private_fileblob_type(buffer
, KEY_UNSPEC
,
3720 passphrase
, keyp
, commentp
);
3724 sshkey_sig_details_free(struct sshkey_sig_details
*details
)
3726 freezero(details
, sizeof(*details
));
3730 sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf
*blob
, int type
,
3731 struct sshkey
**pubkeyp
)
3733 int r
= SSH_ERR_INTERNAL_ERROR
;
3735 if (pubkeyp
!= NULL
)
3737 /* only new-format private keys bundle a public key inside */
3738 if ((r
= sshkey_parse_private2_pubkey(blob
, type
, pubkeyp
)) != 0)
3745 * serialize the key with the current state and forward the state
3749 sshkey_private_serialize_maxsign(struct sshkey
*k
, struct sshbuf
*b
,
3750 u_int32_t maxsign
, int printerror
)
3755 sshkey_type_plain(k
->type
) != KEY_XMSS
)
3756 return sshkey_private_serialize_opt(k
, b
,
3757 SSHKEY_SERIALIZE_DEFAULT
);
3758 if ((r
= sshkey_xmss_get_state(k
, printerror
)) != 0 ||
3759 (r
= sshkey_private_serialize_opt(k
, b
,
3760 SSHKEY_SERIALIZE_STATE
)) != 0 ||
3761 (r
= sshkey_xmss_forward_state(k
, maxsign
)) != 0)
3765 if ((rupdate
= sshkey_xmss_update_state(k
, printerror
)) != 0) {
3773 sshkey_signatures_left(const struct sshkey
*k
)
3775 if (sshkey_type_plain(k
->type
) == KEY_XMSS
)
3776 return sshkey_xmss_signatures_left(k
);
3781 sshkey_enable_maxsign(struct sshkey
*k
, u_int32_t maxsign
)
3783 if (sshkey_type_plain(k
->type
) != KEY_XMSS
)
3784 return SSH_ERR_INVALID_ARGUMENT
;
3785 return sshkey_xmss_enable_maxsign(k
, maxsign
);
3789 sshkey_set_filename(struct sshkey
*k
, const char *filename
)
3792 return SSH_ERR_INVALID_ARGUMENT
;
3793 if (sshkey_type_plain(k
->type
) != KEY_XMSS
)
3795 if (filename
== NULL
)
3796 return SSH_ERR_INVALID_ARGUMENT
;
3797 if ((k
->xmss_filename
= strdup(filename
)) == NULL
)
3798 return SSH_ERR_ALLOC_FAIL
;
3803 sshkey_private_serialize_maxsign(struct sshkey
*k
, struct sshbuf
*b
,
3804 u_int32_t maxsign
, int printerror
)
3806 return sshkey_private_serialize_opt(k
, b
, SSHKEY_SERIALIZE_DEFAULT
);
3810 sshkey_signatures_left(const struct sshkey
*k
)
3816 sshkey_enable_maxsign(struct sshkey
*k
, u_int32_t maxsign
)
3818 return SSH_ERR_INVALID_ARGUMENT
;
3822 sshkey_set_filename(struct sshkey
*k
, const char *filename
)
3825 return SSH_ERR_INVALID_ARGUMENT
;
3828 #endif /* WITH_XMSS */