summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in3
-rw-r--r--kex.h12
-rw-r--r--kexecdh.c213
-rw-r--r--kexecdhc.c199
-rw-r--r--kexecdhs.c182
-rw-r--r--kexkemc.c8
-rw-r--r--kexkems.c6
-rw-r--r--monitor.c4
-rw-r--r--ssh-keyscan.c4
-rw-r--r--ssh_api.c6
-rw-r--r--sshconnect2.c4
-rw-r--r--sshd.c4
12 files changed, 193 insertions, 452 deletions
diff --git a/Makefile.in b/Makefile.in
index 3a179a66f..fd539184a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -98,8 +98,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
98 ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ 98 ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \
99 sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ 99 sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \
100 kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ 100 kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
101 kexgexc.o kexecdhc.o \ 101 kexgexc.o kexgexs.o \
102 kexgexs.o kexecdhs.o \
103 sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ 102 sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \
104 platform-pledge.o platform-tracing.o platform-misc.o 103 platform-pledge.o platform-tracing.o platform-misc.o
105 104
diff --git a/kex.h b/kex.h
index de5e473e1..9b4c23670 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.101 2019/01/21 10:28:01 djm Exp $ */ 1/* $OpenBSD: kex.h,v 1.102 2019/01/21 10:29:56 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.
@@ -216,6 +216,11 @@ int kex_dh_enc(struct kex *, const u_char *, size_t, struct sshbuf **,
216 struct sshbuf **); 216 struct sshbuf **);
217int kex_dh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); 217int kex_dh_dec(struct kex *, const u_char *, size_t, struct sshbuf **);
218 218
219int kex_ecdh_keypair(struct kex *);
220int kex_ecdh_enc(struct kex *, const u_char *, size_t, struct sshbuf **,
221 struct sshbuf **);
222int kex_ecdh_dec(struct kex *, const u_char *, size_t, struct sshbuf **);
223
219int kex_c25519_keypair(struct kex *); 224int kex_c25519_keypair(struct kex *);
220int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, 225int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **,
221 struct sshbuf **); 226 struct sshbuf **);
@@ -237,11 +242,6 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *,
237 const BIGNUM *, const u_char *, size_t, 242 const BIGNUM *, const u_char *, size_t,
238 u_char *, size_t *); 243 u_char *, size_t *);
239 244
240int kex_ecdh_hash(int, const EC_GROUP *,
241 const struct sshbuf *, const struct sshbuf *,
242 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
243 const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *);
244
245int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, 245int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *,
246 const u_char *, size_t, const u_char *, size_t, 246 const u_char *, size_t, const u_char *, size_t,
247 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, 247 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
diff --git a/kexecdh.c b/kexecdh.c
index 4380427ea..263f9fd87 100644
--- a/kexecdh.c
+++ b/kexecdh.c
@@ -1,7 +1,7 @@
1/* $OpenBSD: kexecdh.c,v 1.7 2018/12/27 03:25:25 djm Exp $ */ 1/* $OpenBSD: kexecdh.c,v 1.8 2019/01/21 10:29:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 3 * Copyright (c) 2010 Damien Miller. All rights reserved.
4 * Copyright (c) 2019 Markus Friedl. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
@@ -30,71 +30,184 @@
30 30
31#include <sys/types.h> 31#include <sys/types.h>
32 32
33#include <signal.h> 33#include <stdio.h>
34#include <string.h> 34#include <string.h>
35#include <signal.h>
35 36
36#include <openssl/bn.h>
37#include <openssl/evp.h>
38#include <openssl/ec.h>
39#include <openssl/ecdh.h> 37#include <openssl/ecdh.h>
40 38
41#include "ssh2.h"
42#include "sshkey.h" 39#include "sshkey.h"
43#include "cipher.h"
44#include "kex.h" 40#include "kex.h"
45#include "sshbuf.h" 41#include "sshbuf.h"
46#include "digest.h" 42#include "digest.h"
47#include "ssherr.h" 43#include "ssherr.h"
48 44
45static int
46kex_ecdh_dec_key_group(struct kex *, const u_char *, size_t, EC_KEY *key,
47 const EC_GROUP *, struct sshbuf **);
48
49int 49int
50kex_ecdh_hash( 50kex_ecdh_keypair(struct kex *kex)
51 int hash_alg, 51{
52 const EC_GROUP *ec_group, 52 EC_KEY *client_key = NULL;
53 const struct sshbuf *client_version, 53 const EC_GROUP *group;
54 const struct sshbuf *server_version, 54 const EC_POINT *public_key;
55 const u_char *ckexinit, size_t ckexinitlen, 55 struct sshbuf *buf = NULL;
56 const u_char *skexinit, size_t skexinitlen, 56 int r;
57 const u_char *serverhostkeyblob, size_t sbloblen, 57
58 const EC_POINT *client_dh_pub, 58 if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
59 const EC_POINT *server_dh_pub, 59 r = SSH_ERR_ALLOC_FAIL;
60 const BIGNUM *shared_secret, 60 goto out;
61 u_char *hash, size_t *hashlen) 61 }
62 if (EC_KEY_generate_key(client_key) != 1) {
63 r = SSH_ERR_LIBCRYPTO_ERROR;
64 goto out;
65 }
66 group = EC_KEY_get0_group(client_key);
67 public_key = EC_KEY_get0_public_key(client_key);
68
69 if ((buf = sshbuf_new()) == NULL) {
70 r = SSH_ERR_ALLOC_FAIL;
71 goto out;
72 }
73 if ((r = sshbuf_put_ec(buf, public_key, group)) != 0 ||
74 (r = sshbuf_get_u32(buf, NULL)) != 0)
75 goto out;
76#ifdef DEBUG_KEXECDH
77 fputs("client private key:\n", stderr);
78 sshkey_dump_ec_key(client_key);
79#endif
80 kex->ec_client_key = client_key;
81 kex->ec_group = group;
82 client_key = NULL; /* owned by the kex */
83 kex->kem_client_pub = buf;
84 buf = NULL;
85 out:
86 EC_KEY_free(client_key);
87 sshbuf_free(buf);
88 return r;
89}
90
91int
92kex_ecdh_enc(struct kex *kex, const u_char *pkblob, size_t pklen,
93 struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
94{
95 const EC_GROUP *group;
96 const EC_POINT *pub_key;
97 EC_KEY *server_key = NULL;
98 struct sshbuf *server_blob = NULL;
99 int r;
100
101 *server_blobp = NULL;
102 *shared_secretp = NULL;
103
104 if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
105 r = SSH_ERR_ALLOC_FAIL;
106 goto out;
107 }
108 if (EC_KEY_generate_key(server_key) != 1) {
109 r = SSH_ERR_LIBCRYPTO_ERROR;
110 goto out;
111 }
112 group = EC_KEY_get0_group(server_key);
113
114#ifdef DEBUG_KEXECDH
115 fputs("server private key:\n", stderr);
116 sshkey_dump_ec_key(server_key);
117#endif
118 pub_key = EC_KEY_get0_public_key(server_key);
119 if ((server_blob = sshbuf_new()) == NULL) {
120 r = SSH_ERR_ALLOC_FAIL;
121 goto out;
122 }
123 if ((r = sshbuf_put_ec(server_blob, pub_key, group)) != 0 ||
124 (r = sshbuf_get_u32(server_blob, NULL)) != 0)
125 goto out;
126 if ((r = kex_ecdh_dec_key_group(kex, pkblob, pklen, server_key, group,
127 shared_secretp)) != 0)
128 goto out;
129 *server_blobp = server_blob;
130 server_blob = NULL;
131 out:
132 EC_KEY_free(server_key);
133 sshbuf_free(server_blob);
134 return r;
135}
136
137static int
138kex_ecdh_dec_key_group(struct kex *kex, const u_char *pkblob, size_t pklen,
139 EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp)
62{ 140{
63 struct sshbuf *b; 141 struct sshbuf *buf = NULL;
142 BIGNUM *shared_secret = NULL;
143 EC_POINT *dh_pub = NULL;
144 u_char *kbuf = NULL;
145 size_t klen = 0;
64 int r; 146 int r;
65 147
66 if (*hashlen < ssh_digest_bytes(hash_alg)) 148 *shared_secretp = NULL;
67 return SSH_ERR_INVALID_ARGUMENT; 149
68 if ((b = sshbuf_new()) == NULL) 150 if ((buf = sshbuf_new()) == NULL) {
69 return SSH_ERR_ALLOC_FAIL; 151 r = SSH_ERR_ALLOC_FAIL;
70 if ((r = sshbuf_put_stringb(b, client_version)) < 0 || 152 goto out;
71 (r = sshbuf_put_stringb(b, server_version)) < 0 || 153 }
72 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ 154 if ((r = sshbuf_put_u32(buf, pklen)) != 0 ||
73 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || 155 (r = sshbuf_put(buf, pkblob, pklen)) != 0) {
74 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || 156 goto out;
75 (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || 157 }
76 (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || 158 if ((dh_pub = EC_POINT_new(group)) == NULL) {
77 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || 159 r = SSH_ERR_ALLOC_FAIL;
78 (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || 160 goto out;
79 (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || 161 }
80 (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 || 162 if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) {
81 (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 || 163 goto out;
82 (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
83 sshbuf_free(b);
84 return r;
85 } 164 }
86#ifdef DEBUG_KEX 165 sshbuf_reset(buf);
87 sshbuf_dump(b, stderr); 166
167#ifdef DEBUG_KEXECDH
168 fputs("public key:\n", stderr);
169 sshkey_dump_ec_point(group, dh_pub);
88#endif 170#endif
89 if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { 171 if (sshkey_ec_validate_public(group, dh_pub) != 0) {
90 sshbuf_free(b); 172 r = SSH_ERR_MESSAGE_INCOMPLETE;
91 return SSH_ERR_LIBCRYPTO_ERROR; 173 goto out;
174 }
175 klen = (EC_GROUP_get_degree(group) + 7) / 8;
176 if ((kbuf = malloc(klen)) == NULL ||
177 (shared_secret = BN_new()) == NULL) {
178 r = SSH_ERR_ALLOC_FAIL;
179 goto out;
180 }
181 if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen ||
182 BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
183 r = SSH_ERR_LIBCRYPTO_ERROR;
184 goto out;
92 } 185 }
93 sshbuf_free(b); 186#ifdef DEBUG_KEXECDH
94 *hashlen = ssh_digest_bytes(hash_alg); 187 dump_digest("shared secret", kbuf, klen);
95#ifdef DEBUG_KEX
96 dump_digest("hash", hash, *hashlen);
97#endif 188#endif
98 return 0; 189 if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0)
190 goto out;
191 *shared_secretp = buf;
192 buf = NULL;
193 out:
194 EC_POINT_clear_free(dh_pub);
195 BN_clear_free(shared_secret);
196 freezero(kbuf, klen);
197 sshbuf_free(buf);
198 return r;
199}
200
201int
202kex_ecdh_dec(struct kex *kex, const u_char *pkblob, size_t pklen,
203 struct sshbuf **shared_secretp)
204{
205 int r;
206
207 r = kex_ecdh_dec_key_group(kex, pkblob, pklen, kex->ec_client_key,
208 kex->ec_group, shared_secretp);
209 EC_KEY_free(kex->ec_client_key);
210 kex->ec_client_key = NULL;
211 return r;
99} 212}
100#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ 213#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
diff --git a/kexecdhc.c b/kexecdhc.c
deleted file mode 100644
index bfb9f4707..000000000
--- a/kexecdhc.c
+++ /dev/null
@@ -1,199 +0,0 @@
1/* $OpenBSD: kexecdhc.c,v 1.16 2019/01/21 10:07:22 djm Exp $ */
2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "includes.h"
28
29#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
30
31#include <sys/types.h>
32
33#include <stdio.h>
34#include <string.h>
35#include <signal.h>
36
37#include <openssl/ecdh.h>
38
39#include "sshkey.h"
40#include "cipher.h"
41#include "digest.h"
42#include "kex.h"
43#include "log.h"
44#include "packet.h"
45#include "dh.h"
46#include "ssh2.h"
47#include "dispatch.h"
48#include "compat.h"
49#include "ssherr.h"
50#include "sshbuf.h"
51
52static int input_kex_ecdh_reply(int, u_int32_t, struct ssh *);
53
54int
55kexecdh_client(struct ssh *ssh)
56{
57 struct kex *kex = ssh->kex;
58 EC_KEY *client_key = NULL;
59 const EC_GROUP *group;
60 const EC_POINT *public_key;
61 int r;
62
63 if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
64 r = SSH_ERR_ALLOC_FAIL;
65 goto out;
66 }
67 if (EC_KEY_generate_key(client_key) != 1) {
68 r = SSH_ERR_LIBCRYPTO_ERROR;
69 goto out;
70 }
71 group = EC_KEY_get0_group(client_key);
72 public_key = EC_KEY_get0_public_key(client_key);
73
74 if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
75 (r = sshpkt_put_ec(ssh, public_key, group)) != 0 ||
76 (r = sshpkt_send(ssh)) != 0)
77 goto out;
78 debug("sending SSH2_MSG_KEX_ECDH_INIT");
79
80#ifdef DEBUG_KEXECDH
81 fputs("client private key:\n", stderr);
82 sshkey_dump_ec_key(client_key);
83#endif
84 kex->ec_client_key = client_key;
85 kex->ec_group = group;
86 client_key = NULL; /* owned by the kex */
87
88 debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
89 ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_ecdh_reply);
90 r = 0;
91 out:
92 EC_KEY_free(client_key);
93 return r;
94}
95
96static int
97input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh)
98{
99 struct kex *kex = ssh->kex;
100 const EC_GROUP *group;
101 EC_POINT *server_public = NULL;
102 EC_KEY *client_key;
103 BIGNUM *shared_secret = NULL;
104 struct sshkey *server_host_key = NULL;
105 u_char *server_host_key_blob = NULL, *signature = NULL;
106 u_char *kbuf = NULL;
107 u_char hash[SSH_DIGEST_MAX_LENGTH];
108 size_t slen, sbloblen;
109 size_t klen = 0, hashlen;
110 int r;
111
112 group = kex->ec_group;
113 client_key = kex->ec_client_key;
114
115 /* hostkey */
116 if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
117 &sbloblen)) != 0 ||
118 (r = sshkey_from_blob(server_host_key_blob, sbloblen,
119 &server_host_key)) != 0)
120 goto out;
121 if ((r = kex_verify_host_key(ssh, server_host_key)) != 0)
122 goto out;
123
124 /* Q_S, server public key */
125 /* signed H */
126 if ((server_public = EC_POINT_new(group)) == NULL) {
127 r = SSH_ERR_ALLOC_FAIL;
128 goto out;
129 }
130 if ((r = sshpkt_get_ec(ssh, server_public, group)) != 0 ||
131 (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
132 (r = sshpkt_get_end(ssh)) != 0)
133 goto out;
134
135#ifdef DEBUG_KEXECDH
136 fputs("server public key:\n", stderr);
137 sshkey_dump_ec_point(group, server_public);
138#endif
139 if (sshkey_ec_validate_public(group, server_public) != 0) {
140 sshpkt_disconnect(ssh, "invalid server public key");
141 r = SSH_ERR_MESSAGE_INCOMPLETE;
142 goto out;
143 }
144
145 klen = (EC_GROUP_get_degree(group) + 7) / 8;
146 if ((kbuf = malloc(klen)) == NULL ||
147 (shared_secret = BN_new()) == NULL) {
148 r = SSH_ERR_ALLOC_FAIL;
149 goto out;
150 }
151 if (ECDH_compute_key(kbuf, klen, server_public,
152 client_key, NULL) != (int)klen ||
153 BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
154 r = SSH_ERR_LIBCRYPTO_ERROR;
155 goto out;
156 }
157
158#ifdef DEBUG_KEXECDH
159 dump_digest("shared secret", kbuf, klen);
160#endif
161 /* calc and verify H */
162 hashlen = sizeof(hash);
163 if ((r = kex_ecdh_hash(
164 kex->hash_alg,
165 group,
166 kex->client_version,
167 kex->server_version,
168 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
169 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
170 server_host_key_blob, sbloblen,
171 EC_KEY_get0_public_key(client_key),
172 server_public,
173 shared_secret,
174 hash, &hashlen)) != 0)
175 goto out;
176
177 if ((r = sshkey_verify(server_host_key, signature, slen, hash,
178 hashlen, kex->hostkey_alg, ssh->compat)) != 0)
179 goto out;
180
181 if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
182 r = kex_send_newkeys(ssh);
183 out:
184 explicit_bzero(hash, sizeof(hash));
185 EC_KEY_free(kex->ec_client_key);
186 kex->ec_client_key = NULL;
187 EC_POINT_clear_free(server_public);
188 if (kbuf) {
189 explicit_bzero(kbuf, klen);
190 free(kbuf);
191 }
192 BN_clear_free(shared_secret);
193 sshkey_free(server_host_key);
194 free(server_host_key_blob);
195 free(signature);
196 return r;
197}
198#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
199
diff --git a/kexecdhs.c b/kexecdhs.c
deleted file mode 100644
index b9254eed7..000000000
--- a/kexecdhs.c
+++ /dev/null
@@ -1,182 +0,0 @@
1/* $OpenBSD: kexecdhs.c,v 1.21 2019/01/21 10:05:09 djm Exp $ */
2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "includes.h"
28
29#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
30
31#include <sys/types.h>
32#include <string.h>
33#include <signal.h>
34
35#include <openssl/ecdh.h>
36
37#include "sshkey.h"
38#include "cipher.h"
39#include "digest.h"
40#include "kex.h"
41#include "log.h"
42#include "packet.h"
43#include "ssh2.h"
44
45#include "dispatch.h"
46#include "compat.h"
47#include "ssherr.h"
48#include "sshbuf.h"
49
50static int input_kex_ecdh_init(int, u_int32_t, struct ssh *);
51
52int
53kexecdh_server(struct ssh *ssh)
54{
55 debug("expecting SSH2_MSG_KEX_ECDH_INIT");
56 ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_ecdh_init);
57 return 0;
58}
59
60static int
61input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh)
62{
63 struct kex *kex = ssh->kex;
64 EC_POINT *client_public;
65 EC_KEY *server_key = NULL;
66 const EC_GROUP *group;
67 const EC_POINT *public_key;
68 BIGNUM *shared_secret = NULL;
69 struct sshkey *server_host_private, *server_host_public;
70 u_char *server_host_key_blob = NULL, *signature = NULL;
71 u_char *kbuf = NULL;
72 u_char hash[SSH_DIGEST_MAX_LENGTH];
73 size_t slen, sbloblen;
74 size_t klen = 0, hashlen;
75 int r;
76
77 if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
78 r = SSH_ERR_ALLOC_FAIL;
79 goto out;
80 }
81 if (EC_KEY_generate_key(server_key) != 1) {
82 r = SSH_ERR_LIBCRYPTO_ERROR;
83 goto out;
84 }
85 group = EC_KEY_get0_group(server_key);
86
87#ifdef DEBUG_KEXECDH
88 fputs("server private key:\n", stderr);
89 sshkey_dump_ec_key(server_key);
90#endif
91
92 if ((r = kex_load_hostkey(ssh, &server_host_private,
93 &server_host_public)) != 0)
94 goto out;
95 if ((client_public = EC_POINT_new(group)) == NULL) {
96 r = SSH_ERR_ALLOC_FAIL;
97 goto out;
98 }
99 if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 ||
100 (r = sshpkt_get_end(ssh)) != 0)
101 goto out;
102
103#ifdef DEBUG_KEXECDH
104 fputs("client public key:\n", stderr);
105 sshkey_dump_ec_point(group, client_public);
106#endif
107 if (sshkey_ec_validate_public(group, client_public) != 0) {
108 sshpkt_disconnect(ssh, "invalid client public key");
109 r = SSH_ERR_MESSAGE_INCOMPLETE;
110 goto out;
111 }
112
113 /* Calculate shared_secret */
114 klen = (EC_GROUP_get_degree(group) + 7) / 8;
115 if ((kbuf = malloc(klen)) == NULL ||
116 (shared_secret = BN_new()) == NULL) {
117 r = SSH_ERR_ALLOC_FAIL;
118 goto out;
119 }
120 if (ECDH_compute_key(kbuf, klen, client_public,
121 server_key, NULL) != (int)klen ||
122 BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
123 r = SSH_ERR_LIBCRYPTO_ERROR;
124 goto out;
125 }
126
127#ifdef DEBUG_KEXECDH
128 dump_digest("shared secret", kbuf, klen);
129#endif
130 /* calc H */
131 if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
132 &sbloblen)) != 0)
133 goto out;
134 hashlen = sizeof(hash);
135 if ((r = kex_ecdh_hash(
136 kex->hash_alg,
137 group,
138 kex->client_version,
139 kex->server_version,
140 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
141 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
142 server_host_key_blob, sbloblen,
143 client_public,
144 EC_KEY_get0_public_key(server_key),
145 shared_secret,
146 hash, &hashlen)) != 0)
147 goto out;
148
149 /* sign H */
150 if ((r = kex->sign(ssh, server_host_private, server_host_public,
151 &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0)
152 goto out;
153
154 /* destroy_sensitive_data(); */
155
156 public_key = EC_KEY_get0_public_key(server_key);
157 /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
158 if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
159 (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
160 (r = sshpkt_put_ec(ssh, public_key, group)) != 0 ||
161 (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
162 (r = sshpkt_send(ssh)) != 0)
163 goto out;
164
165 if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
166 r = kex_send_newkeys(ssh);
167 out:
168 explicit_bzero(hash, sizeof(hash));
169 EC_KEY_free(kex->ec_client_key);
170 kex->ec_client_key = NULL;
171 EC_KEY_free(server_key);
172 if (kbuf) {
173 explicit_bzero(kbuf, klen);
174 free(kbuf);
175 }
176 BN_clear_free(shared_secret);
177 free(server_host_key_blob);
178 free(signature);
179 return r;
180}
181#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
182
diff --git a/kexkemc.c b/kexkemc.c
index 384a4db59..55055de27 100644
--- a/kexkemc.c
+++ b/kexkemc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexkemc.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ 1/* $OpenBSD: kexkemc.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Markus Friedl. All rights reserved. 3 * Copyright (c) 2019 Markus Friedl. All rights reserved.
4 * 4 *
@@ -55,6 +55,9 @@ kex_kem_client(struct ssh *ssh)
55 case KEX_DH_GRP18_SHA512: 55 case KEX_DH_GRP18_SHA512:
56 r = kex_dh_keypair(kex); 56 r = kex_dh_keypair(kex);
57 break; 57 break;
58 case KEX_ECDH_SHA2:
59 r = kex_ecdh_keypair(kex);
60 break;
58 case KEX_C25519_SHA256: 61 case KEX_C25519_SHA256:
59 r = kex_c25519_keypair(kex); 62 r = kex_c25519_keypair(kex);
60 break; 63 break;
@@ -113,6 +116,9 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh)
113 case KEX_DH_GRP18_SHA512: 116 case KEX_DH_GRP18_SHA512:
114 r = kex_dh_dec(kex, server_pubkey, pklen, &shared_secret); 117 r = kex_dh_dec(kex, server_pubkey, pklen, &shared_secret);
115 break; 118 break;
119 case KEX_ECDH_SHA2:
120 r = kex_ecdh_dec(kex, server_pubkey, pklen, &shared_secret);
121 break;
116 case KEX_C25519_SHA256: 122 case KEX_C25519_SHA256:
117 r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret); 123 r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret);
118 break; 124 break;
diff --git a/kexkems.c b/kexkems.c
index f35906d53..10ef12196 100644
--- a/kexkems.c
+++ b/kexkems.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexkems.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ 1/* $OpenBSD: kexkems.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Markus Friedl. All rights reserved. 3 * Copyright (c) 2019 Markus Friedl. All rights reserved.
4 * 4 *
@@ -77,6 +77,10 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh)
77 r = kex_dh_enc(kex, client_pubkey, pklen, &server_pubkey, 77 r = kex_dh_enc(kex, client_pubkey, pklen, &server_pubkey,
78 &shared_secret); 78 &shared_secret);
79 break; 79 break;
80 case KEX_ECDH_SHA2:
81 r = kex_ecdh_enc(kex, client_pubkey, pklen, &server_pubkey,
82 &shared_secret);
83 break;
80 case KEX_C25519_SHA256: 84 case KEX_C25519_SHA256:
81 r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey, 85 r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey,
82 &shared_secret); 86 &shared_secret);
diff --git a/monitor.c b/monitor.c
index 01204c2cd..d3357b73c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.195 2019/01/21 10:28:02 djm Exp $ */ 1/* $OpenBSD: monitor.c,v 1.196 2019/01/21 10:29:56 djm Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -1685,7 +1685,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor)
1685 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 1685 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
1686 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 1686 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
1687# ifdef OPENSSL_HAS_ECC 1687# ifdef OPENSSL_HAS_ECC
1688 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 1688 kex->kex[KEX_ECDH_SHA2] = kex_kem_server;
1689# endif 1689# endif
1690#endif /* WITH_OPENSSL */ 1690#endif /* WITH_OPENSSL */
1691 kex->kex[KEX_C25519_SHA256] = kex_kem_server; 1691 kex->kex[KEX_C25519_SHA256] = kex_kem_server;
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index 3d2760056..9541ecf4a 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keyscan.c,v 1.123 2019/01/21 10:28:02 djm Exp $ */ 1/* $OpenBSD: ssh-keyscan.c,v 1.124 2019/01/21 10:29:56 djm Exp $ */
2/* 2/*
3 * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. 3 * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
4 * 4 *
@@ -268,7 +268,7 @@ keygrab_ssh2(con *c)
268 c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 268 c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
269 c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 269 c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
270# ifdef OPENSSL_HAS_ECC 270# ifdef OPENSSL_HAS_ECC
271 c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 271 c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client;
272# endif 272# endif
273#endif 273#endif
274 c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; 274 c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client;
diff --git a/ssh_api.c b/ssh_api.c
index ac614e599..b21769d23 100644
--- a/ssh_api.c
+++ b/ssh_api.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh_api.c,v 1.13 2019/01/21 10:28:02 djm Exp $ */ 1/* $OpenBSD: ssh_api.c,v 1.14 2019/01/21 10:29:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2012 Markus Friedl. All rights reserved. 3 * Copyright (c) 2012 Markus Friedl. All rights reserved.
4 * 4 *
@@ -107,7 +107,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
107 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 107 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
108 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 108 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
109# ifdef OPENSSL_HAS_ECC 109# ifdef OPENSSL_HAS_ECC
110 ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 110 ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_server;
111# endif 111# endif
112#endif /* WITH_OPENSSL */ 112#endif /* WITH_OPENSSL */
113 ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_server; 113 ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_server;
@@ -125,7 +125,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
125 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 125 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
126 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 126 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
127# ifdef OPENSSL_HAS_ECC 127# ifdef OPENSSL_HAS_ECC
128 ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 128 ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client;
129# endif 129# endif
130#endif /* WITH_OPENSSL */ 130#endif /* WITH_OPENSSL */
131 ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; 131 ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client;
diff --git a/sshconnect2.c b/sshconnect2.c
index ebeff29bd..aa5160185 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.299 2019/01/21 10:28:02 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.300 2019/01/21 10:29:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -209,7 +209,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
209 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 209 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
210 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 210 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
211# ifdef OPENSSL_HAS_ECC 211# ifdef OPENSSL_HAS_ECC
212 ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 212 ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client;
213# endif 213# endif
214#endif 214#endif
215 ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; 215 ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client;
diff --git a/sshd.c b/sshd.c
index eb92785bf..ddbedd6c6 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.530 2019/01/21 10:28:02 djm Exp $ */ 1/* $OpenBSD: sshd.c,v 1.531 2019/01/21 10:29:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2215,7 +2215,7 @@ do_ssh2_kex(struct ssh *ssh)
2215 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 2215 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
2216 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 2216 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
2217# ifdef OPENSSL_HAS_ECC 2217# ifdef OPENSSL_HAS_ECC
2218 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 2218 kex->kex[KEX_ECDH_SHA2] = kex_kem_server;
2219# endif 2219# endif
2220#endif 2220#endif
2221 kex->kex[KEX_C25519_SHA256] = kex_kem_server; 2221 kex->kex[KEX_C25519_SHA256] = kex_kem_server;