diff options
-rw-r--r-- | Makefile.in | 3 | ||||
-rw-r--r-- | pathnames.h | 3 | ||||
-rw-r--r-- | ssh-ecdsa-sk.c | 180 | ||||
-rw-r--r-- | sshkey.c | 205 | ||||
-rw-r--r-- | sshkey.h | 19 |
5 files changed, 381 insertions, 29 deletions
diff --git a/Makefile.in b/Makefile.in index adb1977e2..f22c83673 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -91,7 +91,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ | |||
91 | log.o match.o moduli.o nchan.o packet.o \ | 91 | log.o match.o moduli.o nchan.o packet.o \ |
92 | readpass.o ttymodes.o xmalloc.o addrmatch.o \ | 92 | readpass.o ttymodes.o xmalloc.o addrmatch.o \ |
93 | atomicio.o dispatch.o mac.o misc.o utf8.o \ | 93 | atomicio.o dispatch.o mac.o misc.o utf8.o \ |
94 | monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ | 94 | monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ |
95 | ssh-rsa.o dh.o \ | ||
95 | msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ | 96 | msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ |
96 | ssh-pkcs11.o smult_curve25519_ref.o \ | 97 | ssh-pkcs11.o smult_curve25519_ref.o \ |
97 | poly1305.o chacha.o cipher-chachapoly.o \ | 98 | poly1305.o chacha.o cipher-chachapoly.o \ |
diff --git a/pathnames.h b/pathnames.h index cb44caa4d..2e0c7b15b 100644 --- a/pathnames.h +++ b/pathnames.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: pathnames.h,v 1.28 2018/02/23 15:58:37 markus Exp $ */ | 1 | /* $OpenBSD: pathnames.h,v 1.29 2019/10/31 21:15:14 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -77,6 +77,7 @@ | |||
77 | #define _PATH_SSH_CLIENT_ID_RSA _PATH_SSH_USER_DIR "/id_rsa" | 77 | #define _PATH_SSH_CLIENT_ID_RSA _PATH_SSH_USER_DIR "/id_rsa" |
78 | #define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519" | 78 | #define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519" |
79 | #define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss" | 79 | #define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss" |
80 | #define _PATH_SSH_CLIENT_ID_ECDSA_SK _PATH_SSH_USER_DIR "/id_ecdsa_sk" | ||
80 | 81 | ||
81 | /* | 82 | /* |
82 | * Configuration file in user's home directory. This file need not be | 83 | * Configuration file in user's home directory. This file need not be |
diff --git a/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c new file mode 100644 index 000000000..6441cd7fa --- /dev/null +++ b/ssh-ecdsa-sk.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* $OpenBSD: ssh-ecdsa-sk.c,v 1.1 2019/10/31 21:15:14 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | ||
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | ||
5 | * Copyright (c) 2019 Google Inc. All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | /* #define DEBUG_SK 1 */ | ||
29 | |||
30 | #include "includes.h" | ||
31 | |||
32 | #include <sys/types.h> | ||
33 | |||
34 | #include <openssl/bn.h> | ||
35 | #include <openssl/ec.h> | ||
36 | #include <openssl/ecdsa.h> | ||
37 | #include <openssl/evp.h> | ||
38 | |||
39 | #include <string.h> | ||
40 | #include <stdio.h> /* needed for DEBUG_SK only */ | ||
41 | |||
42 | #include "sshbuf.h" | ||
43 | #include "ssherr.h" | ||
44 | #include "digest.h" | ||
45 | #define SSHKEY_INTERNAL | ||
46 | #include "sshkey.h" | ||
47 | |||
48 | /* ARGSUSED */ | ||
49 | int | ||
50 | ssh_ecdsa_sk_verify(const struct sshkey *key, | ||
51 | const u_char *signature, size_t signaturelen, | ||
52 | const u_char *data, size_t datalen, u_int compat) | ||
53 | { | ||
54 | ECDSA_SIG *sig = NULL; | ||
55 | BIGNUM *sig_r = NULL, *sig_s = NULL; | ||
56 | u_char sig_flags; | ||
57 | u_char msghash[32], apphash[32], sighash[32]; | ||
58 | u_int sig_counter; | ||
59 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
60 | struct sshbuf *b = NULL, *sigbuf = NULL, *original_signed = NULL; | ||
61 | char *ktype = NULL; | ||
62 | #ifdef DEBUG_SK | ||
63 | char *tmp = NULL; | ||
64 | #endif | ||
65 | |||
66 | if (key == NULL || key->ecdsa == NULL || | ||
67 | sshkey_type_plain(key->type) != KEY_ECDSA_SK || | ||
68 | signature == NULL || signaturelen == 0) | ||
69 | return SSH_ERR_INVALID_ARGUMENT; | ||
70 | |||
71 | if (key->ecdsa_nid != NID_X9_62_prime256v1) | ||
72 | return SSH_ERR_INTERNAL_ERROR; | ||
73 | |||
74 | /* fetch signature */ | ||
75 | if ((b = sshbuf_from(signature, signaturelen)) == NULL) | ||
76 | return SSH_ERR_ALLOC_FAIL; | ||
77 | if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || | ||
78 | sshbuf_froms(b, &sigbuf) != 0) { | ||
79 | ret = SSH_ERR_INVALID_FORMAT; | ||
80 | goto out; | ||
81 | } | ||
82 | if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) { | ||
83 | ret = SSH_ERR_KEY_TYPE_MISMATCH; | ||
84 | goto out; | ||
85 | } | ||
86 | if (sshbuf_len(b) != 0) { | ||
87 | ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; | ||
88 | goto out; | ||
89 | } | ||
90 | |||
91 | /* parse signature */ | ||
92 | if (sshbuf_get_bignum2(sigbuf, &sig_r) != 0 || | ||
93 | sshbuf_get_bignum2(sigbuf, &sig_s) != 0 || | ||
94 | sshbuf_get_u8(sigbuf, &sig_flags) != 0 || | ||
95 | sshbuf_get_u32(sigbuf, &sig_counter) != 0) { | ||
96 | ret = SSH_ERR_INVALID_FORMAT; | ||
97 | goto out; | ||
98 | } | ||
99 | if ((sig = ECDSA_SIG_new()) == NULL) { | ||
100 | ret = SSH_ERR_ALLOC_FAIL; | ||
101 | goto out; | ||
102 | } | ||
103 | if (!ECDSA_SIG_set0(sig, sig_r, sig_s)) { | ||
104 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
105 | goto out; | ||
106 | } | ||
107 | #ifdef DEBUG_SK | ||
108 | fprintf(stderr, "%s: sig_r: %s\n", __func__, (tmp = BN_bn2hex(sig_r))); | ||
109 | free(tmp); | ||
110 | fprintf(stderr, "%s: sig_s: %s\n", __func__, (tmp = BN_bn2hex(sig_s))); | ||
111 | free(tmp); | ||
112 | fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n", | ||
113 | __func__, sig_flags, sig_counter); | ||
114 | #endif | ||
115 | sig_r = sig_s = NULL; /* transferred */ | ||
116 | |||
117 | if (sshbuf_len(sigbuf) != 0) { | ||
118 | ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; | ||
119 | goto out; | ||
120 | } | ||
121 | |||
122 | /* Reconstruct data that was supposedly signed */ | ||
123 | if ((original_signed = sshbuf_new()) == NULL) | ||
124 | return SSH_ERR_ALLOC_FAIL; | ||
125 | if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen, | ||
126 | msghash, sizeof(msghash))) != 0) | ||
127 | goto out; | ||
128 | /* Application value is hashed before signature */ | ||
129 | if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application, | ||
130 | strlen(key->sk_application), apphash, sizeof(apphash))) != 0) | ||
131 | goto out; | ||
132 | #ifdef DEBUG_SK | ||
133 | fprintf(stderr, "%s: hashed message:\n", __func__); | ||
134 | sshbuf_dump_data(msghash, sizeof(msghash), stderr); | ||
135 | #endif | ||
136 | if ((ret = sshbuf_put(original_signed, | ||
137 | apphash, sizeof(apphash))) != 0 || | ||
138 | (ret = sshbuf_put_u8(original_signed, sig_flags)) != 0 || | ||
139 | (ret = sshbuf_put_u32(original_signed, sig_counter)) != 0 || | ||
140 | (ret = sshbuf_put(original_signed, msghash, sizeof(msghash))) != 0) | ||
141 | goto out; | ||
142 | /* Signature is over H(original_signed) */ | ||
143 | if ((ret = ssh_digest_buffer(SSH_DIGEST_SHA256, original_signed, | ||
144 | sighash, sizeof(sighash))) != 0) | ||
145 | goto out; | ||
146 | #ifdef DEBUG_SK | ||
147 | fprintf(stderr, "%s: signed buf:\n", __func__); | ||
148 | sshbuf_dump(original_signed, stderr); | ||
149 | fprintf(stderr, "%s: signed hash:\n", __func__); | ||
150 | sshbuf_dump_data(sighash, sizeof(sighash), stderr); | ||
151 | #endif | ||
152 | |||
153 | /* Verify it */ | ||
154 | switch (ECDSA_do_verify(sighash, sizeof(sighash), sig, key->ecdsa)) { | ||
155 | case 1: | ||
156 | ret = 0; | ||
157 | break; | ||
158 | case 0: | ||
159 | ret = SSH_ERR_SIGNATURE_INVALID; | ||
160 | goto out; | ||
161 | default: | ||
162 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
163 | goto out; | ||
164 | } | ||
165 | |||
166 | out: | ||
167 | explicit_bzero(&sig_flags, sizeof(sig_flags)); | ||
168 | explicit_bzero(&sig_counter, sizeof(sig_counter)); | ||
169 | explicit_bzero(msghash, sizeof(msghash)); | ||
170 | explicit_bzero(sighash, sizeof(msghash)); | ||
171 | explicit_bzero(apphash, sizeof(apphash)); | ||
172 | sshbuf_free(original_signed); | ||
173 | sshbuf_free(sigbuf); | ||
174 | sshbuf_free(b); | ||
175 | ECDSA_SIG_free(sig); | ||
176 | BN_clear_free(sig_r); | ||
177 | BN_clear_free(sig_s); | ||
178 | free(ktype); | ||
179 | return ret; | ||
180 | } | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.84 2019/10/09 00:04:42 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.85 2019/10/31 21:15:14 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. | 4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. |
@@ -125,6 +125,8 @@ static const struct keytype keytypes[] = { | |||
125 | { "ecdsa-sha2-nistp521", "ECDSA", NULL, | 125 | { "ecdsa-sha2-nistp521", "ECDSA", NULL, |
126 | KEY_ECDSA, NID_secp521r1, 0, 0 }, | 126 | KEY_ECDSA, NID_secp521r1, 0, 0 }, |
127 | # endif /* OPENSSL_HAS_NISTP521 */ | 127 | # endif /* OPENSSL_HAS_NISTP521 */ |
128 | { "sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL, | ||
129 | KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 0 }, | ||
128 | # endif /* OPENSSL_HAS_ECC */ | 130 | # endif /* OPENSSL_HAS_ECC */ |
129 | { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, | 131 | { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, |
130 | KEY_RSA_CERT, 0, 1, 0 }, | 132 | KEY_RSA_CERT, 0, 1, 0 }, |
@@ -143,6 +145,8 @@ static const struct keytype keytypes[] = { | |||
143 | { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL, | 145 | { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL, |
144 | KEY_ECDSA_CERT, NID_secp521r1, 1, 0 }, | 146 | KEY_ECDSA_CERT, NID_secp521r1, 1, 0 }, |
145 | # endif /* OPENSSL_HAS_NISTP521 */ | 147 | # endif /* OPENSSL_HAS_NISTP521 */ |
148 | { "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-SK-CERT", NULL, | ||
149 | KEY_ECDSA_SK_CERT, NID_X9_62_prime256v1, 1, 0 }, | ||
146 | # endif /* OPENSSL_HAS_ECC */ | 150 | # endif /* OPENSSL_HAS_ECC */ |
147 | #endif /* WITH_OPENSSL */ | 151 | #endif /* WITH_OPENSSL */ |
148 | { NULL, NULL, NULL, -1, -1, 0, 0 } | 152 | { NULL, NULL, NULL, -1, -1, 0, 0 } |
@@ -211,13 +215,26 @@ sshkey_type_from_name(const char *name) | |||
211 | return KEY_UNSPEC; | 215 | return KEY_UNSPEC; |
212 | } | 216 | } |
213 | 217 | ||
218 | static int | ||
219 | key_type_is_ecdsa_variant(int type) | ||
220 | { | ||
221 | switch (type) { | ||
222 | case KEY_ECDSA: | ||
223 | case KEY_ECDSA_CERT: | ||
224 | case KEY_ECDSA_SK: | ||
225 | case KEY_ECDSA_SK_CERT: | ||
226 | return 1; | ||
227 | } | ||
228 | return 0; | ||
229 | } | ||
230 | |||
214 | int | 231 | int |
215 | sshkey_ecdsa_nid_from_name(const char *name) | 232 | sshkey_ecdsa_nid_from_name(const char *name) |
216 | { | 233 | { |
217 | const struct keytype *kt; | 234 | const struct keytype *kt; |
218 | 235 | ||
219 | for (kt = keytypes; kt->type != -1; kt++) { | 236 | for (kt = keytypes; kt->type != -1; kt++) { |
220 | if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) | 237 | if (!key_type_is_ecdsa_variant(kt->type)) |
221 | continue; | 238 | continue; |
222 | if (kt->name != NULL && strcmp(name, kt->name) == 0) | 239 | if (kt->name != NULL && strcmp(name, kt->name) == 0) |
223 | return kt->nid; | 240 | return kt->nid; |
@@ -313,6 +330,8 @@ sshkey_size(const struct sshkey *k) | |||
313 | return BN_num_bits(dsa_p); | 330 | return BN_num_bits(dsa_p); |
314 | case KEY_ECDSA: | 331 | case KEY_ECDSA: |
315 | case KEY_ECDSA_CERT: | 332 | case KEY_ECDSA_CERT: |
333 | case KEY_ECDSA_SK: | ||
334 | case KEY_ECDSA_SK_CERT: | ||
316 | return sshkey_curve_nid_to_bits(k->ecdsa_nid); | 335 | return sshkey_curve_nid_to_bits(k->ecdsa_nid); |
317 | #endif /* WITH_OPENSSL */ | 336 | #endif /* WITH_OPENSSL */ |
318 | case KEY_ED25519: | 337 | case KEY_ED25519: |
@@ -331,6 +350,7 @@ sshkey_type_is_valid_ca(int type) | |||
331 | case KEY_RSA: | 350 | case KEY_RSA: |
332 | case KEY_DSA: | 351 | case KEY_DSA: |
333 | case KEY_ECDSA: | 352 | case KEY_ECDSA: |
353 | case KEY_ECDSA_SK: | ||
334 | case KEY_ED25519: | 354 | case KEY_ED25519: |
335 | case KEY_XMSS: | 355 | case KEY_XMSS: |
336 | return 1; | 356 | return 1; |
@@ -358,6 +378,8 @@ sshkey_type_plain(int type) | |||
358 | return KEY_DSA; | 378 | return KEY_DSA; |
359 | case KEY_ECDSA_CERT: | 379 | case KEY_ECDSA_CERT: |
360 | return KEY_ECDSA; | 380 | return KEY_ECDSA; |
381 | case KEY_ECDSA_SK_CERT: | ||
382 | return KEY_ECDSA_SK; | ||
361 | case KEY_ED25519_CERT: | 383 | case KEY_ED25519_CERT: |
362 | return KEY_ED25519; | 384 | return KEY_ED25519; |
363 | case KEY_XMSS_CERT: | 385 | case KEY_XMSS_CERT: |
@@ -533,6 +555,8 @@ sshkey_new(int type) | |||
533 | break; | 555 | break; |
534 | case KEY_ECDSA: | 556 | case KEY_ECDSA: |
535 | case KEY_ECDSA_CERT: | 557 | case KEY_ECDSA_CERT: |
558 | case KEY_ECDSA_SK: | ||
559 | case KEY_ECDSA_SK_CERT: | ||
536 | /* Cannot do anything until we know the group */ | 560 | /* Cannot do anything until we know the group */ |
537 | break; | 561 | break; |
538 | #endif /* WITH_OPENSSL */ | 562 | #endif /* WITH_OPENSSL */ |
@@ -577,6 +601,12 @@ sshkey_free(struct sshkey *k) | |||
577 | k->dsa = NULL; | 601 | k->dsa = NULL; |
578 | break; | 602 | break; |
579 | # ifdef OPENSSL_HAS_ECC | 603 | # ifdef OPENSSL_HAS_ECC |
604 | case KEY_ECDSA_SK: | ||
605 | case KEY_ECDSA_SK_CERT: | ||
606 | free(k->sk_application); | ||
607 | sshbuf_free(k->sk_key_handle); | ||
608 | sshbuf_free(k->sk_reserved); | ||
609 | /* FALLTHROUGH */ | ||
580 | case KEY_ECDSA: | 610 | case KEY_ECDSA: |
581 | case KEY_ECDSA_CERT: | 611 | case KEY_ECDSA_CERT: |
582 | EC_KEY_free(k->ecdsa); | 612 | EC_KEY_free(k->ecdsa); |
@@ -676,6 +706,13 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) | |||
676 | BN_cmp(dsa_g_a, dsa_g_b) == 0 && | 706 | BN_cmp(dsa_g_a, dsa_g_b) == 0 && |
677 | BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0; | 707 | BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0; |
678 | # ifdef OPENSSL_HAS_ECC | 708 | # ifdef OPENSSL_HAS_ECC |
709 | case KEY_ECDSA_SK: | ||
710 | case KEY_ECDSA_SK_CERT: | ||
711 | if (a->sk_application == NULL || b->sk_application == NULL) | ||
712 | return 0; | ||
713 | if (strcmp(a->sk_application, b->sk_application) != 0) | ||
714 | return 0; | ||
715 | /* FALLTHROUGH */ | ||
679 | case KEY_ECDSA_CERT: | 716 | case KEY_ECDSA_CERT: |
680 | case KEY_ECDSA: | 717 | case KEY_ECDSA: |
681 | if (a->ecdsa == NULL || b->ecdsa == NULL || | 718 | if (a->ecdsa == NULL || b->ecdsa == NULL || |
@@ -751,6 +788,7 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, | |||
751 | #ifdef WITH_OPENSSL | 788 | #ifdef WITH_OPENSSL |
752 | case KEY_DSA_CERT: | 789 | case KEY_DSA_CERT: |
753 | case KEY_ECDSA_CERT: | 790 | case KEY_ECDSA_CERT: |
791 | case KEY_ECDSA_SK_CERT: | ||
754 | case KEY_RSA_CERT: | 792 | case KEY_RSA_CERT: |
755 | #endif /* WITH_OPENSSL */ | 793 | #endif /* WITH_OPENSSL */ |
756 | case KEY_ED25519_CERT: | 794 | case KEY_ED25519_CERT: |
@@ -777,6 +815,7 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, | |||
777 | break; | 815 | break; |
778 | # ifdef OPENSSL_HAS_ECC | 816 | # ifdef OPENSSL_HAS_ECC |
779 | case KEY_ECDSA: | 817 | case KEY_ECDSA: |
818 | case KEY_ECDSA_SK: | ||
780 | if (key->ecdsa == NULL) | 819 | if (key->ecdsa == NULL) |
781 | return SSH_ERR_INVALID_ARGUMENT; | 820 | return SSH_ERR_INVALID_ARGUMENT; |
782 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || | 821 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
@@ -784,6 +823,11 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, | |||
784 | sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || | 823 | sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || |
785 | (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0) | 824 | (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0) |
786 | return ret; | 825 | return ret; |
826 | if (type == KEY_ECDSA_SK) { | ||
827 | if ((ret = sshbuf_put_cstring(b, | ||
828 | key->sk_application)) != 0) | ||
829 | return ret; | ||
830 | } | ||
787 | break; | 831 | break; |
788 | # endif | 832 | # endif |
789 | case KEY_RSA: | 833 | case KEY_RSA: |
@@ -1217,7 +1261,7 @@ peek_type_nid(const char *s, size_t l, int *nid) | |||
1217 | continue; | 1261 | continue; |
1218 | if (memcmp(s, kt->name, l) == 0) { | 1262 | if (memcmp(s, kt->name, l) == 0) { |
1219 | *nid = -1; | 1263 | *nid = -1; |
1220 | if (kt->type == KEY_ECDSA || kt->type == KEY_ECDSA_CERT) | 1264 | if (key_type_is_ecdsa_variant(kt->type)) |
1221 | *nid = kt->nid; | 1265 | *nid = kt->nid; |
1222 | return kt->type; | 1266 | return kt->type; |
1223 | } | 1267 | } |
@@ -1243,9 +1287,11 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1243 | case KEY_RSA: | 1287 | case KEY_RSA: |
1244 | case KEY_DSA: | 1288 | case KEY_DSA: |
1245 | case KEY_ECDSA: | 1289 | case KEY_ECDSA: |
1290 | case KEY_ECDSA_SK: | ||
1246 | case KEY_ED25519: | 1291 | case KEY_ED25519: |
1247 | case KEY_DSA_CERT: | 1292 | case KEY_DSA_CERT: |
1248 | case KEY_ECDSA_CERT: | 1293 | case KEY_ECDSA_CERT: |
1294 | case KEY_ECDSA_SK_CERT: | ||
1249 | case KEY_RSA_CERT: | 1295 | case KEY_RSA_CERT: |
1250 | case KEY_ED25519_CERT: | 1296 | case KEY_ED25519_CERT: |
1251 | #ifdef WITH_XMSS | 1297 | #ifdef WITH_XMSS |
@@ -1302,7 +1348,7 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1302 | sshkey_free(k); | 1348 | sshkey_free(k); |
1303 | return SSH_ERR_KEY_TYPE_MISMATCH; | 1349 | return SSH_ERR_KEY_TYPE_MISMATCH; |
1304 | } | 1350 | } |
1305 | if (sshkey_type_plain(type) == KEY_ECDSA && curve_nid != k->ecdsa_nid) { | 1351 | if (key_type_is_ecdsa_variant(type) && curve_nid != k->ecdsa_nid) { |
1306 | sshkey_free(k); | 1352 | sshkey_free(k); |
1307 | return SSH_ERR_EC_CURVE_MISMATCH; | 1353 | return SSH_ERR_EC_CURVE_MISMATCH; |
1308 | } | 1354 | } |
@@ -1348,6 +1394,19 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1348 | sshkey_dump_ec_key(ret->ecdsa); | 1394 | sshkey_dump_ec_key(ret->ecdsa); |
1349 | #endif | 1395 | #endif |
1350 | break; | 1396 | break; |
1397 | case KEY_ECDSA_SK: | ||
1398 | EC_KEY_free(ret->ecdsa); | ||
1399 | ret->ecdsa = k->ecdsa; | ||
1400 | ret->ecdsa_nid = k->ecdsa_nid; | ||
1401 | ret->sk_application = k->sk_application; | ||
1402 | k->ecdsa = NULL; | ||
1403 | k->ecdsa_nid = -1; | ||
1404 | k->sk_application = NULL; | ||
1405 | #ifdef DEBUG_PK | ||
1406 | sshkey_dump_ec_key(ret->ecdsa); | ||
1407 | fprintf(stderr, "App: %s\n", ret->sk_application); | ||
1408 | #endif | ||
1409 | break; | ||
1351 | # endif /* OPENSSL_HAS_ECC */ | 1410 | # endif /* OPENSSL_HAS_ECC */ |
1352 | #endif /* WITH_OPENSSL */ | 1411 | #endif /* WITH_OPENSSL */ |
1353 | case KEY_ED25519: | 1412 | case KEY_ED25519: |
@@ -1747,15 +1806,14 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1747 | #endif /* WITH_OPENSSL */ | 1806 | #endif /* WITH_OPENSSL */ |
1748 | 1807 | ||
1749 | *pkp = NULL; | 1808 | *pkp = NULL; |
1809 | if ((n = sshkey_new(k->type)) == NULL) { | ||
1810 | r = SSH_ERR_ALLOC_FAIL; | ||
1811 | goto out; | ||
1812 | } | ||
1750 | switch (k->type) { | 1813 | switch (k->type) { |
1751 | #ifdef WITH_OPENSSL | 1814 | #ifdef WITH_OPENSSL |
1752 | case KEY_DSA: | 1815 | case KEY_DSA: |
1753 | case KEY_DSA_CERT: | 1816 | case KEY_DSA_CERT: |
1754 | if ((n = sshkey_new(k->type)) == NULL) { | ||
1755 | r = SSH_ERR_ALLOC_FAIL; | ||
1756 | goto out; | ||
1757 | } | ||
1758 | |||
1759 | DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); | 1817 | DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); |
1760 | DSA_get0_key(k->dsa, &dsa_pub_key, NULL); | 1818 | DSA_get0_key(k->dsa, &dsa_pub_key, NULL); |
1761 | if ((dsa_p_dup = BN_dup(dsa_p)) == NULL || | 1819 | if ((dsa_p_dup = BN_dup(dsa_p)) == NULL || |
@@ -1780,10 +1838,8 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1780 | # ifdef OPENSSL_HAS_ECC | 1838 | # ifdef OPENSSL_HAS_ECC |
1781 | case KEY_ECDSA: | 1839 | case KEY_ECDSA: |
1782 | case KEY_ECDSA_CERT: | 1840 | case KEY_ECDSA_CERT: |
1783 | if ((n = sshkey_new(k->type)) == NULL) { | 1841 | case KEY_ECDSA_SK: |
1784 | r = SSH_ERR_ALLOC_FAIL; | 1842 | case KEY_ECDSA_SK_CERT: |
1785 | goto out; | ||
1786 | } | ||
1787 | n->ecdsa_nid = k->ecdsa_nid; | 1843 | n->ecdsa_nid = k->ecdsa_nid; |
1788 | n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); | 1844 | n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); |
1789 | if (n->ecdsa == NULL) { | 1845 | if (n->ecdsa == NULL) { |
@@ -1795,14 +1851,15 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1795 | r = SSH_ERR_LIBCRYPTO_ERROR; | 1851 | r = SSH_ERR_LIBCRYPTO_ERROR; |
1796 | goto out; | 1852 | goto out; |
1797 | } | 1853 | } |
1854 | if (k->type != KEY_ECDSA_SK && k->type != KEY_ECDSA_SK_CERT) | ||
1855 | break; | ||
1856 | /* Append security-key application string */ | ||
1857 | if ((n->sk_application = strdup(k->sk_application)) == NULL) | ||
1858 | goto out; | ||
1798 | break; | 1859 | break; |
1799 | # endif /* OPENSSL_HAS_ECC */ | 1860 | # endif /* OPENSSL_HAS_ECC */ |
1800 | case KEY_RSA: | 1861 | case KEY_RSA: |
1801 | case KEY_RSA_CERT: | 1862 | case KEY_RSA_CERT: |
1802 | if ((n = sshkey_new(k->type)) == NULL) { | ||
1803 | r = SSH_ERR_ALLOC_FAIL; | ||
1804 | goto out; | ||
1805 | } | ||
1806 | RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); | 1863 | RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); |
1807 | if ((rsa_n_dup = BN_dup(rsa_n)) == NULL || | 1864 | if ((rsa_n_dup = BN_dup(rsa_n)) == NULL || |
1808 | (rsa_e_dup = BN_dup(rsa_e)) == NULL) { | 1865 | (rsa_e_dup = BN_dup(rsa_e)) == NULL) { |
@@ -1818,10 +1875,6 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1818 | #endif /* WITH_OPENSSL */ | 1875 | #endif /* WITH_OPENSSL */ |
1819 | case KEY_ED25519: | 1876 | case KEY_ED25519: |
1820 | case KEY_ED25519_CERT: | 1877 | case KEY_ED25519_CERT: |
1821 | if ((n = sshkey_new(k->type)) == NULL) { | ||
1822 | r = SSH_ERR_ALLOC_FAIL; | ||
1823 | goto out; | ||
1824 | } | ||
1825 | if (k->ed25519_pk != NULL) { | 1878 | if (k->ed25519_pk != NULL) { |
1826 | if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { | 1879 | if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { |
1827 | r = SSH_ERR_ALLOC_FAIL; | 1880 | r = SSH_ERR_ALLOC_FAIL; |
@@ -1833,10 +1886,6 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1833 | #ifdef WITH_XMSS | 1886 | #ifdef WITH_XMSS |
1834 | case KEY_XMSS: | 1887 | case KEY_XMSS: |
1835 | case KEY_XMSS_CERT: | 1888 | case KEY_XMSS_CERT: |
1836 | if ((n = sshkey_new(k->type)) == NULL) { | ||
1837 | r = SSH_ERR_ALLOC_FAIL; | ||
1838 | goto out; | ||
1839 | } | ||
1840 | if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0) | 1889 | if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0) |
1841 | goto out; | 1890 | goto out; |
1842 | if (k->xmss_pk != NULL) { | 1891 | if (k->xmss_pk != NULL) { |
@@ -2329,6 +2378,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2329 | #endif | 2378 | #endif |
2330 | break; | 2379 | break; |
2331 | case KEY_ECDSA_CERT: | 2380 | case KEY_ECDSA_CERT: |
2381 | case KEY_ECDSA_SK_CERT: | ||
2332 | /* Skip nonce */ | 2382 | /* Skip nonce */ |
2333 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | 2383 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { |
2334 | ret = SSH_ERR_INVALID_FORMAT; | 2384 | ret = SSH_ERR_INVALID_FORMAT; |
@@ -2337,6 +2387,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2337 | /* FALLTHROUGH */ | 2387 | /* FALLTHROUGH */ |
2338 | # ifdef OPENSSL_HAS_ECC | 2388 | # ifdef OPENSSL_HAS_ECC |
2339 | case KEY_ECDSA: | 2389 | case KEY_ECDSA: |
2390 | case KEY_ECDSA_SK: | ||
2340 | if ((key = sshkey_new(type)) == NULL) { | 2391 | if ((key = sshkey_new(type)) == NULL) { |
2341 | ret = SSH_ERR_ALLOC_FAIL; | 2392 | ret = SSH_ERR_ALLOC_FAIL; |
2342 | goto out; | 2393 | goto out; |
@@ -2377,6 +2428,17 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2377 | #ifdef DEBUG_PK | 2428 | #ifdef DEBUG_PK |
2378 | sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); | 2429 | sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); |
2379 | #endif | 2430 | #endif |
2431 | if (type == KEY_ECDSA_SK || type == KEY_ECDSA_SK_CERT) { | ||
2432 | /* Parse additional security-key application string */ | ||
2433 | if (sshbuf_get_cstring(b, &key->sk_application, | ||
2434 | NULL) != 0) { | ||
2435 | ret = SSH_ERR_INVALID_FORMAT; | ||
2436 | goto out; | ||
2437 | } | ||
2438 | #ifdef DEBUG_PK | ||
2439 | fprintf(stderr, "App: %s\n", key->sk_application); | ||
2440 | #endif | ||
2441 | } | ||
2380 | break; | 2442 | break; |
2381 | # endif /* OPENSSL_HAS_ECC */ | 2443 | # endif /* OPENSSL_HAS_ECC */ |
2382 | #endif /* WITH_OPENSSL */ | 2444 | #endif /* WITH_OPENSSL */ |
@@ -2665,6 +2727,10 @@ sshkey_verify(const struct sshkey *key, | |||
2665 | case KEY_ECDSA_CERT: | 2727 | case KEY_ECDSA_CERT: |
2666 | case KEY_ECDSA: | 2728 | case KEY_ECDSA: |
2667 | return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat); | 2729 | return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat); |
2730 | case KEY_ECDSA_SK_CERT: | ||
2731 | case KEY_ECDSA_SK: | ||
2732 | return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen, | ||
2733 | compat); | ||
2668 | # endif /* OPENSSL_HAS_ECC */ | 2734 | # endif /* OPENSSL_HAS_ECC */ |
2669 | case KEY_RSA_CERT: | 2735 | case KEY_RSA_CERT: |
2670 | case KEY_RSA: | 2736 | case KEY_RSA: |
@@ -2700,6 +2766,9 @@ sshkey_to_certified(struct sshkey *k) | |||
2700 | case KEY_ECDSA: | 2766 | case KEY_ECDSA: |
2701 | newtype = KEY_ECDSA_CERT; | 2767 | newtype = KEY_ECDSA_CERT; |
2702 | break; | 2768 | break; |
2769 | case KEY_ECDSA_SK: | ||
2770 | newtype = KEY_ECDSA_SK_CERT; | ||
2771 | break; | ||
2703 | #endif /* WITH_OPENSSL */ | 2772 | #endif /* WITH_OPENSSL */ |
2704 | case KEY_ED25519: | 2773 | case KEY_ED25519: |
2705 | newtype = KEY_ED25519_CERT; | 2774 | newtype = KEY_ED25519_CERT; |
@@ -2797,12 +2866,18 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | |||
2797 | break; | 2866 | break; |
2798 | # ifdef OPENSSL_HAS_ECC | 2867 | # ifdef OPENSSL_HAS_ECC |
2799 | case KEY_ECDSA_CERT: | 2868 | case KEY_ECDSA_CERT: |
2869 | case KEY_ECDSA_SK_CERT: | ||
2800 | if ((ret = sshbuf_put_cstring(cert, | 2870 | if ((ret = sshbuf_put_cstring(cert, |
2801 | sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 || | 2871 | sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 || |
2802 | (ret = sshbuf_put_ec(cert, | 2872 | (ret = sshbuf_put_ec(cert, |
2803 | EC_KEY_get0_public_key(k->ecdsa), | 2873 | EC_KEY_get0_public_key(k->ecdsa), |
2804 | EC_KEY_get0_group(k->ecdsa))) != 0) | 2874 | EC_KEY_get0_group(k->ecdsa))) != 0) |
2805 | goto out; | 2875 | goto out; |
2876 | if (k->type == KEY_ECDSA_SK_CERT) { | ||
2877 | if ((ret = sshbuf_put_cstring(cert, | ||
2878 | k->sk_application)) != 0) | ||
2879 | goto out; | ||
2880 | } | ||
2806 | break; | 2881 | break; |
2807 | # endif /* OPENSSL_HAS_ECC */ | 2882 | # endif /* OPENSSL_HAS_ECC */ |
2808 | case KEY_RSA_CERT: | 2883 | case KEY_RSA_CERT: |
@@ -3082,6 +3157,28 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, | |||
3082 | EC_KEY_get0_private_key(key->ecdsa))) != 0) | 3157 | EC_KEY_get0_private_key(key->ecdsa))) != 0) |
3083 | goto out; | 3158 | goto out; |
3084 | break; | 3159 | break; |
3160 | case KEY_ECDSA_SK: | ||
3161 | if ((r = sshbuf_put_cstring(b, | ||
3162 | sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || | ||
3163 | (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 || | ||
3164 | (r = sshbuf_put_cstring(b, key->sk_application)) != 0 || | ||
3165 | (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || | ||
3166 | (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || | ||
3167 | (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) | ||
3168 | goto out; | ||
3169 | break; | ||
3170 | case KEY_ECDSA_SK_CERT: | ||
3171 | if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { | ||
3172 | r = SSH_ERR_INVALID_ARGUMENT; | ||
3173 | goto out; | ||
3174 | } | ||
3175 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || | ||
3176 | (r = sshbuf_put_cstring(b, key->sk_application)) != 0 || | ||
3177 | (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || | ||
3178 | (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || | ||
3179 | (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) | ||
3180 | goto out; | ||
3181 | break; | ||
3085 | # endif /* OPENSSL_HAS_ECC */ | 3182 | # endif /* OPENSSL_HAS_ECC */ |
3086 | #endif /* WITH_OPENSSL */ | 3183 | #endif /* WITH_OPENSSL */ |
3087 | case KEY_ED25519: | 3184 | case KEY_ED25519: |
@@ -3270,6 +3367,60 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
3270 | (r = sshkey_ec_validate_private(k->ecdsa)) != 0) | 3367 | (r = sshkey_ec_validate_private(k->ecdsa)) != 0) |
3271 | goto out; | 3368 | goto out; |
3272 | break; | 3369 | break; |
3370 | case KEY_ECDSA_SK: | ||
3371 | if ((k = sshkey_new(type)) == NULL) { | ||
3372 | r = SSH_ERR_ALLOC_FAIL; | ||
3373 | goto out; | ||
3374 | } | ||
3375 | if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { | ||
3376 | r = SSH_ERR_INVALID_ARGUMENT; | ||
3377 | goto out; | ||
3378 | } | ||
3379 | if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0) | ||
3380 | goto out; | ||
3381 | if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) { | ||
3382 | r = SSH_ERR_EC_CURVE_MISMATCH; | ||
3383 | goto out; | ||
3384 | } | ||
3385 | if ((k->sk_key_handle = sshbuf_new()) == NULL || | ||
3386 | (k->sk_reserved = sshbuf_new()) == NULL) { | ||
3387 | r = SSH_ERR_ALLOC_FAIL; | ||
3388 | goto out; | ||
3389 | } | ||
3390 | k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); | ||
3391 | if (k->ecdsa == NULL) { | ||
3392 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3393 | goto out; | ||
3394 | } | ||
3395 | if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 || | ||
3396 | (r = sshbuf_get_cstring(buf, &k->sk_application, | ||
3397 | NULL)) != 0 || | ||
3398 | (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || | ||
3399 | (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || | ||
3400 | (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) | ||
3401 | goto out; | ||
3402 | if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa), | ||
3403 | EC_KEY_get0_public_key(k->ecdsa))) != 0) | ||
3404 | goto out; | ||
3405 | break; | ||
3406 | case KEY_ECDSA_SK_CERT: | ||
3407 | if ((r = sshkey_froms(buf, &k)) != 0) | ||
3408 | goto out; | ||
3409 | if ((k->sk_key_handle = sshbuf_new()) == NULL || | ||
3410 | (k->sk_reserved = sshbuf_new()) == NULL) { | ||
3411 | r = SSH_ERR_ALLOC_FAIL; | ||
3412 | goto out; | ||
3413 | } | ||
3414 | if ((r = sshbuf_get_cstring(buf, &k->sk_application, | ||
3415 | NULL)) != 0 || | ||
3416 | (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || | ||
3417 | (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || | ||
3418 | (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) | ||
3419 | goto out; | ||
3420 | if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa), | ||
3421 | EC_KEY_get0_public_key(k->ecdsa))) != 0) | ||
3422 | goto out; | ||
3423 | break; | ||
3273 | # endif /* OPENSSL_HAS_ECC */ | 3424 | # endif /* OPENSSL_HAS_ECC */ |
3274 | case KEY_RSA: | 3425 | case KEY_RSA: |
3275 | if ((k = sshkey_new(type)) == NULL) { | 3426 | if ((k = sshkey_new(type)) == NULL) { |
@@ -4090,6 +4241,9 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, | |||
4090 | #ifdef WITH_XMSS | 4241 | #ifdef WITH_XMSS |
4091 | case KEY_XMSS: | 4242 | case KEY_XMSS: |
4092 | #endif /* WITH_XMSS */ | 4243 | #endif /* WITH_XMSS */ |
4244 | #ifdef WITH_OPENSSL | ||
4245 | case KEY_ECDSA_SK: | ||
4246 | #endif /* WITH_OPENSSL */ | ||
4093 | return sshkey_private_to_blob2(key, blob, passphrase, | 4247 | return sshkey_private_to_blob2(key, blob, passphrase, |
4094 | comment, openssh_format_cipher, openssh_format_rounds); | 4248 | comment, openssh_format_cipher, openssh_format_rounds); |
4095 | default: | 4249 | default: |
@@ -4111,7 +4265,6 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, | |||
4111 | #endif /* WITH_OPENSSL */ | 4265 | #endif /* WITH_OPENSSL */ |
4112 | } | 4266 | } |
4113 | 4267 | ||
4114 | |||
4115 | #ifdef WITH_OPENSSL | 4268 | #ifdef WITH_OPENSSL |
4116 | static int | 4269 | static int |
4117 | translate_libcrypto_error(unsigned long pem_err) | 4270 | translate_libcrypto_error(unsigned long pem_err) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.h,v 1.34 2019/09/03 08:31:20 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.h,v 1.35 2019/10/31 21:15:14 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -65,6 +65,8 @@ enum sshkey_types { | |||
65 | KEY_ED25519_CERT, | 65 | KEY_ED25519_CERT, |
66 | KEY_XMSS, | 66 | KEY_XMSS, |
67 | KEY_XMSS_CERT, | 67 | KEY_XMSS_CERT, |
68 | KEY_ECDSA_SK, | ||
69 | KEY_ECDSA_SK_CERT, | ||
68 | KEY_UNSPEC | 70 | KEY_UNSPEC |
69 | }; | 71 | }; |
70 | 72 | ||
@@ -118,18 +120,30 @@ struct sshkey_cert { | |||
118 | struct sshkey { | 120 | struct sshkey { |
119 | int type; | 121 | int type; |
120 | int flags; | 122 | int flags; |
123 | /* KEY_RSA */ | ||
121 | RSA *rsa; | 124 | RSA *rsa; |
125 | /* KEY_DSA */ | ||
122 | DSA *dsa; | 126 | DSA *dsa; |
127 | /* KEY_ECDSA and KEY_ECDSA_SK */ | ||
123 | int ecdsa_nid; /* NID of curve */ | 128 | int ecdsa_nid; /* NID of curve */ |
124 | EC_KEY *ecdsa; | 129 | EC_KEY *ecdsa; |
130 | /* KEY_ED25519 */ | ||
125 | u_char *ed25519_sk; | 131 | u_char *ed25519_sk; |
126 | u_char *ed25519_pk; | 132 | u_char *ed25519_pk; |
133 | /* KEY_XMSS */ | ||
127 | char *xmss_name; | 134 | char *xmss_name; |
128 | char *xmss_filename; /* for state file updates */ | 135 | char *xmss_filename; /* for state file updates */ |
129 | void *xmss_state; /* depends on xmss_name, opaque */ | 136 | void *xmss_state; /* depends on xmss_name, opaque */ |
130 | u_char *xmss_sk; | 137 | u_char *xmss_sk; |
131 | u_char *xmss_pk; | 138 | u_char *xmss_pk; |
139 | /* KEY_ECDSA_SK */ | ||
140 | char *sk_application; | ||
141 | uint8_t sk_flags; | ||
142 | struct sshbuf *sk_key_handle; | ||
143 | struct sshbuf *sk_reserved; | ||
144 | /* Certificates */ | ||
132 | struct sshkey_cert *cert; | 145 | struct sshkey_cert *cert; |
146 | /* Private key shielding */ | ||
133 | u_char *shielded_private; | 147 | u_char *shielded_private; |
134 | size_t shielded_len; | 148 | size_t shielded_len; |
135 | u_char *shield_prekey; | 149 | u_char *shield_prekey; |
@@ -268,6 +282,9 @@ int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | |||
268 | int ssh_ecdsa_verify(const struct sshkey *key, | 282 | int ssh_ecdsa_verify(const struct sshkey *key, |
269 | const u_char *signature, size_t signaturelen, | 283 | const u_char *signature, size_t signaturelen, |
270 | const u_char *data, size_t datalen, u_int compat); | 284 | const u_char *data, size_t datalen, u_int compat); |
285 | int ssh_ecdsa_sk_verify(const struct sshkey *key, | ||
286 | const u_char *signature, size_t signaturelen, | ||
287 | const u_char *data, size_t datalen, u_int compat); | ||
271 | int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | 288 | int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, |
272 | const u_char *data, size_t datalen, u_int compat); | 289 | const u_char *data, size_t datalen, u_int compat); |
273 | int ssh_ed25519_verify(const struct sshkey *key, | 290 | int ssh_ed25519_verify(const struct sshkey *key, |