1 /* $OpenBSD: kexgen.c,v 1.8 2021/12/19 22:08:06 djm Exp $ */
3 * Copyright (c) 2019 Markus Friedl. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/types.h>
44 static int input_kex_gen_init(int, u_int32_t
, struct ssh
*);
45 static int input_kex_gen_reply(int type
, u_int32_t seq
, struct ssh
*ssh
);
50 const struct sshbuf
*client_version
,
51 const struct sshbuf
*server_version
,
52 const struct sshbuf
*client_kexinit
,
53 const struct sshbuf
*server_kexinit
,
54 const struct sshbuf
*server_host_key_blob
,
55 const struct sshbuf
*client_pub
,
56 const struct sshbuf
*server_pub
,
57 const struct sshbuf
*shared_secret
,
58 u_char
*hash
, size_t *hashlen
)
63 if (*hashlen
< ssh_digest_bytes(hash_alg
))
64 return SSH_ERR_INVALID_ARGUMENT
;
65 if ((b
= sshbuf_new()) == NULL
)
66 return SSH_ERR_ALLOC_FAIL
;
67 if ((r
= sshbuf_put_stringb(b
, client_version
)) != 0 ||
68 (r
= sshbuf_put_stringb(b
, server_version
)) != 0 ||
69 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
70 (r
= sshbuf_put_u32(b
, sshbuf_len(client_kexinit
) + 1)) != 0 ||
71 (r
= sshbuf_put_u8(b
, SSH2_MSG_KEXINIT
)) != 0 ||
72 (r
= sshbuf_putb(b
, client_kexinit
)) != 0 ||
73 (r
= sshbuf_put_u32(b
, sshbuf_len(server_kexinit
) + 1)) != 0 ||
74 (r
= sshbuf_put_u8(b
, SSH2_MSG_KEXINIT
)) != 0 ||
75 (r
= sshbuf_putb(b
, server_kexinit
)) != 0 ||
76 (r
= sshbuf_put_stringb(b
, server_host_key_blob
)) != 0 ||
77 (r
= sshbuf_put_stringb(b
, client_pub
)) != 0 ||
78 (r
= sshbuf_put_stringb(b
, server_pub
)) != 0 ||
79 (r
= sshbuf_putb(b
, shared_secret
)) != 0) {
84 sshbuf_dump(b
, stderr
);
86 if (ssh_digest_buffer(hash_alg
, b
, hash
, *hashlen
) != 0) {
88 return SSH_ERR_LIBCRYPTO_ERROR
;
91 *hashlen
= ssh_digest_bytes(hash_alg
);
93 dump_digest("hash", hash
, *hashlen
);
99 kex_gen_client(struct ssh
*ssh
)
101 struct kex
*kex
= ssh
->kex
;
104 switch (kex
->kex_type
) {
106 case KEX_DH_GRP1_SHA1
:
107 case KEX_DH_GRP14_SHA1
:
108 case KEX_DH_GRP14_SHA256
:
109 case KEX_DH_GRP16_SHA512
:
110 case KEX_DH_GRP18_SHA512
:
111 r
= kex_dh_keypair(kex
);
114 r
= kex_ecdh_keypair(kex
);
117 case KEX_C25519_SHA256
:
118 r
= kex_c25519_keypair(kex
);
120 case KEX_KEM_SNTRUP761X25519_SHA512
:
121 r
= kex_kem_sntrup761x25519_keypair(kex
);
124 r
= SSH_ERR_INVALID_ARGUMENT
;
129 if ((r
= sshpkt_start(ssh
, SSH2_MSG_KEX_ECDH_INIT
)) != 0 ||
130 (r
= sshpkt_put_stringb(ssh
, kex
->client_pub
)) != 0 ||
131 (r
= sshpkt_send(ssh
)) != 0)
133 debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
134 ssh_dispatch_set(ssh
, SSH2_MSG_KEX_ECDH_REPLY
, &input_kex_gen_reply
);
139 input_kex_gen_reply(int type
, u_int32_t seq
, struct ssh
*ssh
)
141 struct kex
*kex
= ssh
->kex
;
142 struct sshkey
*server_host_key
= NULL
;
143 struct sshbuf
*shared_secret
= NULL
;
144 struct sshbuf
*server_blob
= NULL
;
145 struct sshbuf
*tmp
= NULL
, *server_host_key_blob
= NULL
;
146 u_char
*signature
= NULL
;
147 u_char hash
[SSH_DIGEST_MAX_LENGTH
];
148 size_t slen
, hashlen
;
151 debug("SSH2_MSG_KEX_ECDH_REPLY received");
152 ssh_dispatch_set(ssh
, SSH2_MSG_KEX_ECDH_REPLY
, &kex_protocol_error
);
155 if ((r
= sshpkt_getb_froms(ssh
, &server_host_key_blob
)) != 0)
157 /* sshkey_fromb() consumes its buffer, so make a copy */
158 if ((tmp
= sshbuf_fromb(server_host_key_blob
)) == NULL
) {
159 r
= SSH_ERR_ALLOC_FAIL
;
162 if ((r
= sshkey_fromb(tmp
, &server_host_key
)) != 0)
164 if ((r
= kex_verify_host_key(ssh
, server_host_key
)) != 0)
167 /* Q_S, server public key */
169 if ((r
= sshpkt_getb_froms(ssh
, &server_blob
)) != 0 ||
170 (r
= sshpkt_get_string(ssh
, &signature
, &slen
)) != 0 ||
171 (r
= sshpkt_get_end(ssh
)) != 0)
174 /* compute shared secret */
175 switch (kex
->kex_type
) {
177 case KEX_DH_GRP1_SHA1
:
178 case KEX_DH_GRP14_SHA1
:
179 case KEX_DH_GRP14_SHA256
:
180 case KEX_DH_GRP16_SHA512
:
181 case KEX_DH_GRP18_SHA512
:
182 r
= kex_dh_dec(kex
, server_blob
, &shared_secret
);
185 r
= kex_ecdh_dec(kex
, server_blob
, &shared_secret
);
188 case KEX_C25519_SHA256
:
189 r
= kex_c25519_dec(kex
, server_blob
, &shared_secret
);
191 case KEX_KEM_SNTRUP761X25519_SHA512
:
192 r
= kex_kem_sntrup761x25519_dec(kex
, server_blob
,
196 r
= SSH_ERR_INVALID_ARGUMENT
;
202 /* calc and verify H */
203 hashlen
= sizeof(hash
);
204 if ((r
= kex_gen_hash(
210 server_host_key_blob
,
214 hash
, &hashlen
)) != 0)
217 if ((r
= sshkey_verify(server_host_key
, signature
, slen
, hash
, hashlen
,
218 kex
->hostkey_alg
, ssh
->compat
, NULL
)) != 0)
221 if ((r
= kex_derive_keys(ssh
, hash
, hashlen
, shared_secret
)) != 0 ||
222 (r
= kex_send_newkeys(ssh
)) != 0)
225 /* save initial signature and hostkey */
226 if ((kex
->flags
& KEX_INITIAL
) != 0) {
227 if (kex
->initial_hostkey
!= NULL
|| kex
->initial_sig
!= NULL
) {
228 r
= SSH_ERR_INTERNAL_ERROR
;
231 if ((kex
->initial_sig
= sshbuf_new()) == NULL
) {
232 r
= SSH_ERR_ALLOC_FAIL
;
235 if ((r
= sshbuf_put(kex
->initial_sig
, signature
, slen
)) != 0)
237 kex
->initial_hostkey
= server_host_key
;
238 server_host_key
= NULL
;
242 explicit_bzero(hash
, sizeof(hash
));
243 explicit_bzero(kex
->c25519_client_key
, sizeof(kex
->c25519_client_key
));
244 explicit_bzero(kex
->sntrup761_client_key
,
245 sizeof(kex
->sntrup761_client_key
));
246 sshbuf_free(server_host_key_blob
);
249 sshkey_free(server_host_key
);
250 sshbuf_free(server_blob
);
251 sshbuf_free(shared_secret
);
252 sshbuf_free(kex
->client_pub
);
253 kex
->client_pub
= NULL
;
258 kex_gen_server(struct ssh
*ssh
)
260 debug("expecting SSH2_MSG_KEX_ECDH_INIT");
261 ssh_dispatch_set(ssh
, SSH2_MSG_KEX_ECDH_INIT
, &input_kex_gen_init
);
266 input_kex_gen_init(int type
, u_int32_t seq
, struct ssh
*ssh
)
268 struct kex
*kex
= ssh
->kex
;
269 struct sshkey
*server_host_private
, *server_host_public
;
270 struct sshbuf
*shared_secret
= NULL
;
271 struct sshbuf
*server_pubkey
= NULL
;
272 struct sshbuf
*client_pubkey
= NULL
;
273 struct sshbuf
*server_host_key_blob
= NULL
;
274 u_char
*signature
= NULL
, hash
[SSH_DIGEST_MAX_LENGTH
];
275 size_t slen
, hashlen
;
278 debug("SSH2_MSG_KEX_ECDH_INIT received");
279 ssh_dispatch_set(ssh
, SSH2_MSG_KEX_ECDH_INIT
, &kex_protocol_error
);
281 if ((r
= kex_load_hostkey(ssh
, &server_host_private
,
282 &server_host_public
)) != 0)
285 if ((r
= sshpkt_getb_froms(ssh
, &client_pubkey
)) != 0 ||
286 (r
= sshpkt_get_end(ssh
)) != 0)
289 /* compute shared secret */
290 switch (kex
->kex_type
) {
292 case KEX_DH_GRP1_SHA1
:
293 case KEX_DH_GRP14_SHA1
:
294 case KEX_DH_GRP14_SHA256
:
295 case KEX_DH_GRP16_SHA512
:
296 case KEX_DH_GRP18_SHA512
:
297 r
= kex_dh_enc(kex
, client_pubkey
, &server_pubkey
,
301 r
= kex_ecdh_enc(kex
, client_pubkey
, &server_pubkey
,
305 case KEX_C25519_SHA256
:
306 r
= kex_c25519_enc(kex
, client_pubkey
, &server_pubkey
,
309 case KEX_KEM_SNTRUP761X25519_SHA512
:
310 r
= kex_kem_sntrup761x25519_enc(kex
, client_pubkey
,
311 &server_pubkey
, &shared_secret
);
314 r
= SSH_ERR_INVALID_ARGUMENT
;
321 if ((server_host_key_blob
= sshbuf_new()) == NULL
) {
322 r
= SSH_ERR_ALLOC_FAIL
;
325 if ((r
= sshkey_putb(server_host_public
, server_host_key_blob
)) != 0)
327 hashlen
= sizeof(hash
);
328 if ((r
= kex_gen_hash(
334 server_host_key_blob
,
338 hash
, &hashlen
)) != 0)
342 if ((r
= kex
->sign(ssh
, server_host_private
, server_host_public
,
343 &signature
, &slen
, hash
, hashlen
, kex
->hostkey_alg
)) != 0)
346 /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
347 if ((r
= sshpkt_start(ssh
, SSH2_MSG_KEX_ECDH_REPLY
)) != 0 ||
348 (r
= sshpkt_put_stringb(ssh
, server_host_key_blob
)) != 0 ||
349 (r
= sshpkt_put_stringb(ssh
, server_pubkey
)) != 0 ||
350 (r
= sshpkt_put_string(ssh
, signature
, slen
)) != 0 ||
351 (r
= sshpkt_send(ssh
)) != 0)
354 if ((r
= kex_derive_keys(ssh
, hash
, hashlen
, shared_secret
)) != 0 ||
355 (r
= kex_send_newkeys(ssh
)) != 0)
357 /* retain copy of hostkey used at initial KEX */
358 if (kex
->initial_hostkey
== NULL
&&
359 (r
= sshkey_from_private(server_host_public
,
360 &kex
->initial_hostkey
)) != 0)
364 explicit_bzero(hash
, sizeof(hash
));
365 sshbuf_free(server_host_key_blob
);
367 sshbuf_free(shared_secret
);
368 sshbuf_free(client_pubkey
);
369 sshbuf_free(server_pubkey
);