1 /* $OpenBSD: kexc25519c.c,v 1.8 2017/05/31 04:17:12 djm Exp $ */
3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved.
5 * Copyright (c) 2013 Aris Adamantiadis. 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>
47 input_kex_c25519_reply(int type
, u_int32_t seq
, struct ssh
*ssh
);
50 kexc25519_client(struct ssh
*ssh
)
52 struct kex
*kex
= ssh
->kex
;
55 kexc25519_keygen(kex
->c25519_client_key
, kex
->c25519_client_pubkey
);
57 dump_digest("client private key:", kex
->c25519_client_key
,
58 sizeof(kex
->c25519_client_key
));
60 if ((r
= sshpkt_start(ssh
, SSH2_MSG_KEX_ECDH_INIT
)) != 0 ||
61 (r
= sshpkt_put_string(ssh
, kex
->c25519_client_pubkey
,
62 sizeof(kex
->c25519_client_pubkey
))) != 0 ||
63 (r
= sshpkt_send(ssh
)) != 0)
66 debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
67 ssh_dispatch_set(ssh
, SSH2_MSG_KEX_ECDH_REPLY
, &input_kex_c25519_reply
);
72 input_kex_c25519_reply(int type
, u_int32_t seq
, struct ssh
*ssh
)
74 struct kex
*kex
= ssh
->kex
;
75 struct sshkey
*server_host_key
= NULL
;
76 struct sshbuf
*shared_secret
= NULL
;
77 u_char
*server_pubkey
= NULL
;
78 u_char
*server_host_key_blob
= NULL
, *signature
= NULL
;
79 u_char hash
[SSH_DIGEST_MAX_LENGTH
];
80 size_t slen
, pklen
, sbloblen
, hashlen
;
83 if (kex
->verify_host_key
== NULL
) {
84 r
= SSH_ERR_INVALID_ARGUMENT
;
89 if ((r
= sshpkt_get_string(ssh
, &server_host_key_blob
,
91 (r
= sshkey_from_blob(server_host_key_blob
, sbloblen
,
92 &server_host_key
)) != 0)
94 if (server_host_key
->type
!= kex
->hostkey_type
||
95 (kex
->hostkey_type
== KEY_ECDSA
&&
96 server_host_key
->ecdsa_nid
!= kex
->hostkey_nid
)) {
97 r
= SSH_ERR_KEY_TYPE_MISMATCH
;
100 if (kex
->verify_host_key(server_host_key
, ssh
) == -1) {
101 r
= SSH_ERR_SIGNATURE_INVALID
;
105 /* Q_S, server public key */
107 if ((r
= sshpkt_get_string(ssh
, &server_pubkey
, &pklen
)) != 0 ||
108 (r
= sshpkt_get_string(ssh
, &signature
, &slen
)) != 0 ||
109 (r
= sshpkt_get_end(ssh
)) != 0)
111 if (pklen
!= CURVE25519_SIZE
) {
112 r
= SSH_ERR_SIGNATURE_INVALID
;
117 dump_digest("server public key:", server_pubkey
, CURVE25519_SIZE
);
120 if ((shared_secret
= sshbuf_new()) == NULL
) {
121 r
= SSH_ERR_ALLOC_FAIL
;
124 if ((r
= kexc25519_shared_key(kex
->c25519_client_key
, server_pubkey
,
128 /* calc and verify H */
129 hashlen
= sizeof(hash
);
130 if ((r
= kex_c25519_hash(
132 kex
->client_version_string
,
133 kex
->server_version_string
,
134 sshbuf_ptr(kex
->my
), sshbuf_len(kex
->my
),
135 sshbuf_ptr(kex
->peer
), sshbuf_len(kex
->peer
),
136 server_host_key_blob
, sbloblen
,
137 kex
->c25519_client_pubkey
,
139 sshbuf_ptr(shared_secret
), sshbuf_len(shared_secret
),
140 hash
, &hashlen
)) < 0)
143 if ((r
= sshkey_verify(server_host_key
, signature
, slen
, hash
, hashlen
,
147 /* save session id */
148 if (kex
->session_id
== NULL
) {
149 kex
->session_id_len
= hashlen
;
150 kex
->session_id
= malloc(kex
->session_id_len
);
151 if (kex
->session_id
== NULL
) {
152 r
= SSH_ERR_ALLOC_FAIL
;
155 memcpy(kex
->session_id
, hash
, kex
->session_id_len
);
158 if ((r
= kex_derive_keys(ssh
, hash
, hashlen
, shared_secret
)) == 0)
159 r
= kex_send_newkeys(ssh
);
161 explicit_bzero(hash
, sizeof(hash
));
162 explicit_bzero(kex
->c25519_client_key
, sizeof(kex
->c25519_client_key
));
163 free(server_host_key_blob
);
166 sshkey_free(server_host_key
);
167 sshbuf_free(shared_secret
);