summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2015-01-19 20:16:15 +0000
committerDamien Miller <djm@mindrot.org>2015-01-20 09:19:39 +1100
commit57d10cbe861a235dd269c74fb2fe248469ecee9d (patch)
treec65deed24700490bd3b20300c4829d4d5466ff6d
parent3fdc88a0def4f86aa88a5846ac079dc964c0546a (diff)
upstream commit
adapt kex to sshbuf and struct ssh; ok djm@
-rw-r--r--auth.h13
-rw-r--r--clientloop.c11
-rw-r--r--dh.c59
-rw-r--r--dh.h6
-rw-r--r--kex.c575
-rw-r--r--kex.h127
-rw-r--r--kexc25519.c94
-rw-r--r--kexc25519c.c159
-rw-r--r--kexc25519s.c133
-rw-r--r--kexdh.c87
-rw-r--r--kexdhc.c194
-rw-r--r--kexdhs.c186
-rw-r--r--kexecdh.c81
-rw-r--r--kexecdhc.c207
-rw-r--r--kexecdhs.c190
-rw-r--r--kexgex.c105
-rw-r--r--kexgexc.c287
-rw-r--r--kexgexs.c257
-rw-r--r--monitor.c4
-rw-r--r--monitor_wrap.c6
-rw-r--r--serverloop.c6
-rw-r--r--ssh-keyscan.c14
-rw-r--r--sshconnect2.c12
-rw-r--r--sshd.c47
24 files changed, 1704 insertions, 1156 deletions
diff --git a/auth.h b/auth.h
index c67e4a4d4..60d1c3355 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.h,v 1.79 2014/12/22 07:51:30 djm Exp $ */ 1/* $OpenBSD: auth.h,v 1.80 2015/01/19 20:16:15 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -42,6 +42,7 @@
42#include <krb5.h> 42#include <krb5.h>
43#endif 43#endif
44 44
45struct ssh;
45struct sshkey; 46struct sshkey;
46 47
47typedef struct Authctxt Authctxt; 48typedef struct Authctxt Authctxt;
@@ -202,12 +203,12 @@ check_key_in_hostfiles(struct passwd *, Key *, const char *,
202 203
203/* hostkey handling */ 204/* hostkey handling */
204Key *get_hostkey_by_index(int); 205Key *get_hostkey_by_index(int);
205Key *get_hostkey_public_by_index(int); 206Key *get_hostkey_public_by_index(int, struct ssh *);
206Key *get_hostkey_public_by_type(int); 207Key *get_hostkey_public_by_type(int, struct ssh *);
207Key *get_hostkey_private_by_type(int); 208Key *get_hostkey_private_by_type(int, struct ssh *);
208int get_hostkey_index(Key *); 209int get_hostkey_index(Key *, struct ssh *);
209int ssh1_session_key(BIGNUM *); 210int ssh1_session_key(BIGNUM *);
210void sshd_hostkey_sign(Key *, Key *, u_char **, u_int *, u_char *, u_int); 211int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *, u_char *, size_t, u_int);
211 212
212/* debug messages during authentication */ 213/* debug messages during authentication */
213void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); 214void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
diff --git a/clientloop.c b/clientloop.c
index 672d06989..5a018ac79 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.264 2015/01/19 20:07:45 markus Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.265 2015/01/19 20:16:15 markus 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
@@ -1413,8 +1413,7 @@ client_process_output(fd_set *writeset)
1413static void 1413static void
1414client_process_buffered_input_packets(void) 1414client_process_buffered_input_packets(void)
1415{ 1415{
1416 dispatch_run(DISPATCH_NONBLOCK, &quit_pending, 1416 dispatch_run(DISPATCH_NONBLOCK, &quit_pending, active_state);
1417 compat20 ? active_state->kex : NULL);
1418} 1417}
1419 1418
1420/* scan buf[] for '~' before sending data to the peer */ 1419/* scan buf[] for '~' before sending data to the peer */
@@ -1468,7 +1467,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1468{ 1467{
1469 fd_set *readset = NULL, *writeset = NULL; 1468 fd_set *readset = NULL, *writeset = NULL;
1470 double start_time, total_time; 1469 double start_time, total_time;
1471 int max_fd = 0, max_fd2 = 0, len, rekeying = 0; 1470 int r, max_fd = 0, max_fd2 = 0, len, rekeying = 0;
1472 u_int64_t ibytes, obytes; 1471 u_int64_t ibytes, obytes;
1473 u_int nalloc = 0; 1472 u_int nalloc = 0;
1474 char buf[100]; 1473 char buf[100];
@@ -1598,7 +1597,9 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1598 if (need_rekeying || packet_need_rekeying()) { 1597 if (need_rekeying || packet_need_rekeying()) {
1599 debug("need rekeying"); 1598 debug("need rekeying");
1600 active_state->kex->done = 0; 1599 active_state->kex->done = 0;
1601 kex_send_kexinit(active_state->kex); 1600 if ((r = kex_send_kexinit(active_state)) != 0)
1601 fatal("%s: kex_send_kexinit: %s",
1602 __func__, ssh_err(r));
1602 need_rekeying = 0; 1603 need_rekeying = 0;
1603 } 1604 }
1604 } 1605 }
diff --git a/dh.c b/dh.c
index 3331cda6c..38ad615c5 100644
--- a/dh.c
+++ b/dh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: dh.c,v 1.53 2013/11/21 00:45:44 djm Exp $ */ 1/* $OpenBSD: dh.c,v 1.54 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Niels Provos. All rights reserved. 3 * Copyright (c) 2000 Niels Provos. All rights reserved.
4 * 4 *
@@ -39,6 +39,7 @@
39#include "pathnames.h" 39#include "pathnames.h"
40#include "log.h" 40#include "log.h"
41#include "misc.h" 41#include "misc.h"
42#include "ssherr.h"
42 43
43static int 44static int
44parse_prime(int linenum, char *line, struct dhgroup *dhg) 45parse_prime(int linenum, char *line, struct dhgroup *dhg)
@@ -107,10 +108,11 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
107 goto fail; 108 goto fail;
108 } 109 }
109 110
110 if ((dhg->g = BN_new()) == NULL) 111 if ((dhg->g = BN_new()) == NULL ||
111 fatal("parse_prime: BN_new failed"); 112 (dhg->p = BN_new()) == NULL) {
112 if ((dhg->p = BN_new()) == NULL) 113 error("parse_prime: BN_new failed");
113 fatal("parse_prime: BN_new failed"); 114 goto fail;
115 }
114 if (BN_hex2bn(&dhg->g, gen) == 0) { 116 if (BN_hex2bn(&dhg->g, gen) == 0) {
115 error("moduli:%d: could not parse generator value", linenum); 117 error("moduli:%d: could not parse generator value", linenum);
116 goto fail; 118 goto fail;
@@ -128,7 +130,6 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
128 error("moduli:%d: generator is invalid", linenum); 130 error("moduli:%d: generator is invalid", linenum);
129 goto fail; 131 goto fail;
130 } 132 }
131
132 return 1; 133 return 1;
133 134
134 fail: 135 fail:
@@ -137,7 +138,6 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
137 if (dhg->p != NULL) 138 if (dhg->p != NULL)
138 BN_clear_free(dhg->p); 139 BN_clear_free(dhg->p);
139 dhg->g = dhg->p = NULL; 140 dhg->g = dhg->p = NULL;
140 error("Bad prime description in line %d", linenum);
141 return 0; 141 return 0;
142} 142}
143 143
@@ -200,9 +200,11 @@ choose_dh(int min, int wantbits, int max)
200 break; 200 break;
201 } 201 }
202 fclose(f); 202 fclose(f);
203 if (linenum != which+1) 203 if (linenum != which+1) {
204 fatal("WARNING: line %d disappeared in %s, giving up", 204 logit("WARNING: line %d disappeared in %s, giving up",
205 which, _PATH_DH_PRIMES); 205 which, _PATH_DH_PRIMES);
206 return (dh_new_group14());
207 }
206 208
207 return (dh_new_group(dhg.g, dhg.p)); 209 return (dh_new_group(dhg.g, dhg.p));
208} 210}
@@ -251,22 +253,22 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
251 return 0; 253 return 0;
252} 254}
253 255
254void 256int
255dh_gen_key(DH *dh, int need) 257dh_gen_key(DH *dh, int need)
256{ 258{
257 int pbits; 259 int pbits;
258 260
259 if (need <= 0) 261 if (need < 0 || dh->p == NULL ||
260 fatal("%s: need <= 0", __func__); 262 (pbits = BN_num_bits(dh->p)) <= 0 ||
261 if (dh->p == NULL) 263 need > INT_MAX / 2 || 2 * need >= pbits)
262 fatal("%s: dh->p == NULL", __func__); 264 return SSH_ERR_INVALID_ARGUMENT;
263 if ((pbits = BN_num_bits(dh->p)) <= 0)
264 fatal("%s: bits(p) <= 0", __func__);
265 dh->length = MIN(need * 2, pbits - 1); 265 dh->length = MIN(need * 2, pbits - 1);
266 if (DH_generate_key(dh) == 0) 266 if (DH_generate_key(dh) == 0 ||
267 fatal("%s: key generation failed", __func__); 267 !dh_pub_is_valid(dh, dh->pub_key)) {
268 if (!dh_pub_is_valid(dh, dh->pub_key)) 268 BN_clear_free(dh->priv_key);
269 fatal("%s: generated invalid key", __func__); 269 return SSH_ERR_LIBCRYPTO_ERROR;
270 }
271 return 0;
270} 272}
271 273
272DH * 274DH *
@@ -275,13 +277,12 @@ dh_new_group_asc(const char *gen, const char *modulus)
275 DH *dh; 277 DH *dh;
276 278
277 if ((dh = DH_new()) == NULL) 279 if ((dh = DH_new()) == NULL)
278 fatal("dh_new_group_asc: DH_new"); 280 return NULL;
279 281 if (BN_hex2bn(&dh->p, modulus) == 0 ||
280 if (BN_hex2bn(&dh->p, modulus) == 0) 282 BN_hex2bn(&dh->g, gen) == 0) {
281 fatal("BN_hex2bn p"); 283 DH_free(dh);
282 if (BN_hex2bn(&dh->g, gen) == 0) 284 return NULL;
283 fatal("BN_hex2bn g"); 285 }
284
285 return (dh); 286 return (dh);
286} 287}
287 288
@@ -296,7 +297,7 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus)
296 DH *dh; 297 DH *dh;
297 298
298 if ((dh = DH_new()) == NULL) 299 if ((dh = DH_new()) == NULL)
299 fatal("dh_new_group: DH_new"); 300 return NULL;
300 dh->p = modulus; 301 dh->p = modulus;
301 dh->g = gen; 302 dh->g = gen;
302 303
@@ -344,7 +345,7 @@ dh_new_group14(void)
344 * from RFC4419 section 3. 345 * from RFC4419 section 3.
345 */ 346 */
346 347
347int 348u_int
348dh_estimate(int bits) 349dh_estimate(int bits)
349{ 350{
350 if (bits <= 112) 351 if (bits <= 112)
diff --git a/dh.h b/dh.h
index 48f7b68ea..63a1b1477 100644
--- a/dh.h
+++ b/dh.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: dh.h,v 1.11 2013/10/08 11:42:13 dtucker Exp $ */ 1/* $OpenBSD: dh.h,v 1.12 2015/01/19 20:16:15 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Niels Provos. All rights reserved. 4 * Copyright (c) 2000 Niels Provos. All rights reserved.
@@ -38,10 +38,10 @@ DH *dh_new_group(BIGNUM *, BIGNUM *);
38DH *dh_new_group1(void); 38DH *dh_new_group1(void);
39DH *dh_new_group14(void); 39DH *dh_new_group14(void);
40 40
41void dh_gen_key(DH *, int); 41int dh_gen_key(DH *, int);
42int dh_pub_is_valid(DH *, BIGNUM *); 42int dh_pub_is_valid(DH *, BIGNUM *);
43 43
44int dh_estimate(int); 44u_int dh_estimate(int);
45 45
46/* Min and max values from RFC4419. */ 46/* Min and max values from RFC4419. */
47#define DH_GRP_MIN 1024 47#define DH_GRP_MIN 1024
diff --git a/kex.c b/kex.c
index 92ebaf732..9280dd3f4 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.101 2015/01/19 20:07:45 markus Exp $ */ 1/* $OpenBSD: kex.c,v 1.102 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -37,20 +37,22 @@
37#include <openssl/crypto.h> 37#include <openssl/crypto.h>
38#endif 38#endif
39 39
40#include "xmalloc.h"
41#include "ssh2.h" 40#include "ssh2.h"
42#include "buffer.h"
43#include "packet.h" 41#include "packet.h"
44#include "compat.h" 42#include "compat.h"
45#include "cipher.h" 43#include "cipher.h"
46#include "key.h" 44#include "sshkey.h"
47#include "kex.h" 45#include "kex.h"
48#include "log.h" 46#include "log.h"
49#include "mac.h" 47#include "mac.h"
50#include "match.h" 48#include "match.h"
49#include "misc.h"
51#include "dispatch.h" 50#include "dispatch.h"
52#include "monitor.h" 51#include "monitor.h"
53#include "roaming.h" 52#include "roaming.h"
53
54#include "ssherr.h"
55#include "sshbuf.h"
54#include "digest.h" 56#include "digest.h"
55 57
56#if OPENSSL_VERSION_NUMBER >= 0x00907000L 58#if OPENSSL_VERSION_NUMBER >= 0x00907000L
@@ -62,12 +64,12 @@ extern const EVP_MD *evp_ssh_sha256(void);
62#endif 64#endif
63 65
64/* prototype */ 66/* prototype */
65static void kex_kexinit_finish(Kex *); 67static int kex_choose_conf(struct ssh *);
66static void kex_choose_conf(Kex *); 68static int kex_input_newkeys(int, u_int32_t, void *);
67 69
68struct kexalg { 70struct kexalg {
69 char *name; 71 char *name;
70 int type; 72 u_int type;
71 int ec_nid; 73 int ec_nid;
72 int hash_alg; 74 int hash_alg;
73}; 75};
@@ -99,7 +101,7 @@ static const struct kexalg kexalgs[] = {
99char * 101char *
100kex_alg_list(char sep) 102kex_alg_list(char sep)
101{ 103{
102 char *ret = NULL; 104 char *ret = NULL, *tmp;
103 size_t nlen, rlen = 0; 105 size_t nlen, rlen = 0;
104 const struct kexalg *k; 106 const struct kexalg *k;
105 107
@@ -107,7 +109,11 @@ kex_alg_list(char sep)
107 if (ret != NULL) 109 if (ret != NULL)
108 ret[rlen++] = sep; 110 ret[rlen++] = sep;
109 nlen = strlen(k->name); 111 nlen = strlen(k->name);
110 ret = xrealloc(ret, 1, rlen + nlen + 2); 112 if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
113 free(ret);
114 return NULL;
115 }
116 ret = tmp;
111 memcpy(ret + rlen, k->name, nlen + 1); 117 memcpy(ret + rlen, k->name, nlen + 1);
112 rlen += nlen; 118 rlen += nlen;
113 } 119 }
@@ -134,7 +140,8 @@ kex_names_valid(const char *names)
134 140
135 if (names == NULL || strcmp(names, "") == 0) 141 if (names == NULL || strcmp(names, "") == 0)
136 return 0; 142 return 0;
137 s = cp = xstrdup(names); 143 if ((s = cp = strdup(names)) == NULL)
144 return 0;
138 for ((p = strsep(&cp, ",")); p && *p != '\0'; 145 for ((p = strsep(&cp, ",")); p && *p != '\0';
139 (p = strsep(&cp, ","))) { 146 (p = strsep(&cp, ","))) {
140 if (kex_alg_by_name(p) == NULL) { 147 if (kex_alg_by_name(p) == NULL) {
@@ -149,56 +156,75 @@ kex_names_valid(const char *names)
149} 156}
150 157
151/* put algorithm proposal into buffer */ 158/* put algorithm proposal into buffer */
152static void 159int
153kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) 160kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
154{ 161{
155 u_int i; 162 u_int i;
163 int r;
164
165 sshbuf_reset(b);
156 166
157 buffer_clear(b);
158 /* 167 /*
159 * add a dummy cookie, the cookie will be overwritten by 168 * add a dummy cookie, the cookie will be overwritten by
160 * kex_send_kexinit(), each time a kexinit is set 169 * kex_send_kexinit(), each time a kexinit is set
161 */ 170 */
162 for (i = 0; i < KEX_COOKIE_LEN; i++) 171 for (i = 0; i < KEX_COOKIE_LEN; i++) {
163 buffer_put_char(b, 0); 172 if ((r = sshbuf_put_u8(b, 0)) != 0)
164 for (i = 0; i < PROPOSAL_MAX; i++) 173 return r;
165 buffer_put_cstring(b, proposal[i]); 174 }
166 buffer_put_char(b, 0); /* first_kex_packet_follows */ 175 for (i = 0; i < PROPOSAL_MAX; i++) {
167 buffer_put_int(b, 0); /* uint32 reserved */ 176 if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
177 return r;
178 }
179 if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */
180 (r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */
181 return r;
182 return 0;
168} 183}
169 184
170/* parse buffer and return algorithm proposal */ 185/* parse buffer and return algorithm proposal */
171static char ** 186int
172kex_buf2prop(Buffer *raw, int *first_kex_follows) 187kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
173{ 188{
174 Buffer b; 189 struct sshbuf *b = NULL;
190 u_char v;
175 u_int i; 191 u_int i;
176 char **proposal; 192 char **proposal = NULL;
177 193 int r;
178 proposal = xcalloc(PROPOSAL_MAX, sizeof(char *)); 194
179 195 *propp = NULL;
180 buffer_init(&b); 196 if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
181 buffer_append(&b, buffer_ptr(raw), buffer_len(raw)); 197 return SSH_ERR_ALLOC_FAIL;
182 /* skip cookie */ 198 if ((b = sshbuf_fromb(raw)) == NULL) {
183 for (i = 0; i < KEX_COOKIE_LEN; i++) 199 r = SSH_ERR_ALLOC_FAIL;
184 buffer_get_char(&b); 200 goto out;
201 }
202 if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) /* skip cookie */
203 goto out;
185 /* extract kex init proposal strings */ 204 /* extract kex init proposal strings */
186 for (i = 0; i < PROPOSAL_MAX; i++) { 205 for (i = 0; i < PROPOSAL_MAX; i++) {
187 proposal[i] = buffer_get_cstring(&b,NULL); 206 if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0)
207 goto out;
188 debug2("kex_parse_kexinit: %s", proposal[i]); 208 debug2("kex_parse_kexinit: %s", proposal[i]);
189 } 209 }
190 /* first kex follows / reserved */ 210 /* first kex follows / reserved */
191 i = buffer_get_char(&b); 211 if ((r = sshbuf_get_u8(b, &v)) != 0 ||
212 (r = sshbuf_get_u32(b, &i)) != 0)
213 goto out;
192 if (first_kex_follows != NULL) 214 if (first_kex_follows != NULL)
193 *first_kex_follows = i; 215 *first_kex_follows = i;
194 debug2("kex_parse_kexinit: first_kex_follows %d ", i); 216 debug2("kex_parse_kexinit: first_kex_follows %d ", v);
195 i = buffer_get_int(&b);
196 debug2("kex_parse_kexinit: reserved %u ", i); 217 debug2("kex_parse_kexinit: reserved %u ", i);
197 buffer_free(&b); 218 r = 0;
198 return proposal; 219 *propp = proposal;
220 out:
221 if (r != 0 && proposal != NULL)
222 kex_prop_free(proposal);
223 sshbuf_free(b);
224 return r;
199} 225}
200 226
201static void 227void
202kex_prop_free(char **proposal) 228kex_prop_free(char **proposal)
203{ 229{
204 u_int i; 230 u_int i;
@@ -217,91 +243,103 @@ kex_protocol_error(int type, u_int32_t seq, void *ctxt)
217} 243}
218 244
219static void 245static void
220kex_reset_dispatch(void) 246kex_reset_dispatch(struct ssh *ssh)
221{ 247{
222 dispatch_range(SSH2_MSG_TRANSPORT_MIN, 248 ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
223 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); 249 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
224 dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); 250 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
225} 251}
226 252
227void 253int
228kex_finish(Kex *kex) 254kex_send_newkeys(struct ssh *ssh)
229{ 255{
230 kex_reset_dispatch(); 256 int r;
231 257
232 packet_start(SSH2_MSG_NEWKEYS); 258 kex_reset_dispatch(ssh);
233 packet_send(); 259 if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 ||
234 /* packet_write_wait(); */ 260 (r = sshpkt_send(ssh)) != 0)
261 return r;
235 debug("SSH2_MSG_NEWKEYS sent"); 262 debug("SSH2_MSG_NEWKEYS sent");
236
237 debug("expecting SSH2_MSG_NEWKEYS"); 263 debug("expecting SSH2_MSG_NEWKEYS");
238 packet_read_expect(SSH2_MSG_NEWKEYS); 264 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
239 packet_check_eom(); 265 return 0;
240 debug("SSH2_MSG_NEWKEYS received"); 266}
267
268static int
269kex_input_newkeys(int type, u_int32_t seq, void *ctxt)
270{
271 struct ssh *ssh = ctxt;
272 struct kex *kex = ssh->kex;
273 int r;
241 274
275 debug("SSH2_MSG_NEWKEYS received");
276 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
277 if ((r = sshpkt_get_end(ssh)) != 0)
278 return r;
242 kex->done = 1; 279 kex->done = 1;
243 buffer_clear(kex->peer); 280 sshbuf_reset(kex->peer);
244 /* buffer_clear(kex->my); */ 281 /* sshbuf_reset(kex->my); */
245 kex->flags &= ~KEX_INIT_SENT; 282 kex->flags &= ~KEX_INIT_SENT;
246 free(kex->name); 283 free(kex->name);
247 kex->name = NULL; 284 kex->name = NULL;
285 return 0;
248} 286}
249 287
250void 288int
251kex_send_kexinit(Kex *kex) 289kex_send_kexinit(struct ssh *ssh)
252{ 290{
253 u_int32_t rnd = 0;
254 u_char *cookie; 291 u_char *cookie;
255 u_int i; 292 struct kex *kex = ssh->kex;
293 int r;
256 294
257 if (kex == NULL) { 295 if (kex == NULL)
258 error("kex_send_kexinit: no kex, cannot rekey"); 296 return SSH_ERR_INTERNAL_ERROR;
259 return; 297 if (kex->flags & KEX_INIT_SENT)
260 } 298 return 0;
261 if (kex->flags & KEX_INIT_SENT) {
262 debug("KEX_INIT_SENT");
263 return;
264 }
265 kex->done = 0; 299 kex->done = 0;
266 300
267 /* generate a random cookie */ 301 /* generate a random cookie */
268 if (buffer_len(kex->my) < KEX_COOKIE_LEN) 302 if (sshbuf_len(kex->my) < KEX_COOKIE_LEN)
269 fatal("kex_send_kexinit: kex proposal too short"); 303 return SSH_ERR_INVALID_FORMAT;
270 cookie = buffer_ptr(kex->my); 304 if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL)
271 for (i = 0; i < KEX_COOKIE_LEN; i++) { 305 return SSH_ERR_INTERNAL_ERROR;
272 if (i % 4 == 0) 306 arc4random_buf(cookie, KEX_COOKIE_LEN);
273 rnd = arc4random(); 307
274 cookie[i] = rnd; 308 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
275 rnd >>= 8; 309 (r = sshpkt_putb(ssh, kex->my)) != 0 ||
276 } 310 (r = sshpkt_send(ssh)) != 0)
277 packet_start(SSH2_MSG_KEXINIT); 311 return r;
278 packet_put_raw(buffer_ptr(kex->my), buffer_len(kex->my));
279 packet_send();
280 debug("SSH2_MSG_KEXINIT sent"); 312 debug("SSH2_MSG_KEXINIT sent");
281 kex->flags |= KEX_INIT_SENT; 313 kex->flags |= KEX_INIT_SENT;
314 return 0;
282} 315}
283 316
284/* ARGSUSED */ 317/* ARGSUSED */
285int 318int
286kex_input_kexinit(int type, u_int32_t seq, void *ctxt) 319kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
287{ 320{
288 const char *ptr; 321 struct ssh *ssh = ctxt;
322 struct kex *kex = ssh->kex;
323 const u_char *ptr;
289 u_int i; 324 u_int i;
290 size_t dlen; 325 size_t dlen;
291 Kex *kex = (Kex *)ctxt; 326 int r;
292 327
293 debug("SSH2_MSG_KEXINIT received"); 328 debug("SSH2_MSG_KEXINIT received");
294 if (kex == NULL) 329 if (kex == NULL)
295 fatal("kex_input_kexinit: no kex, cannot rekey"); 330 return SSH_ERR_INVALID_ARGUMENT;
296 331
297 ptr = packet_get_raw(&dlen); 332 ptr = sshpkt_ptr(ssh, &dlen);
298 buffer_append(kex->peer, ptr, dlen); 333 if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
334 return r;
299 335
300 /* discard packet */ 336 /* discard packet */
301 for (i = 0; i < KEX_COOKIE_LEN; i++) 337 for (i = 0; i < KEX_COOKIE_LEN; i++)
302 packet_get_char(); 338 if ((r = sshpkt_get_u8(ssh, NULL)) != 0)
339 return r;
303 for (i = 0; i < PROPOSAL_MAX; i++) 340 for (i = 0; i < PROPOSAL_MAX; i++)
304 free(packet_get_string(NULL)); 341 if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0)
342 return r;
305 /* 343 /*
306 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported 344 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
307 * KEX method has the server move first, but a server might be using 345 * KEX method has the server move first, but a server might be using
@@ -312,12 +350,47 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
312 * for cases where the server *doesn't* go first. I guess we should 350 * for cases where the server *doesn't* go first. I guess we should
313 * ignore it when it is set for these cases, which is what we do now. 351 * ignore it when it is set for these cases, which is what we do now.
314 */ 352 */
315 (void) packet_get_char(); /* first_kex_follows */ 353 if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
316 (void) packet_get_int(); /* reserved */ 354 (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
317 packet_check_eom(); 355 (r = sshpkt_get_end(ssh)) != 0)
356 return r;
318 357
319 kex_kexinit_finish(kex); 358 if (!(kex->flags & KEX_INIT_SENT))
320 return 0; 359 if ((r = kex_send_kexinit(ssh)) != 0)
360 return r;
361 if ((r = kex_choose_conf(ssh)) != 0)
362 return r;
363
364 if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
365 return (kex->kex[kex->kex_type])(ssh);
366
367 return SSH_ERR_INTERNAL_ERROR;
368}
369
370int
371kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp)
372{
373 struct kex *kex;
374 int r;
375
376 *kexp = NULL;
377 if ((kex = calloc(1, sizeof(*kex))) == NULL)
378 return SSH_ERR_ALLOC_FAIL;
379 if ((kex->peer = sshbuf_new()) == NULL ||
380 (kex->my = sshbuf_new()) == NULL) {
381 r = SSH_ERR_ALLOC_FAIL;
382 goto out;
383 }
384 if ((r = kex_prop2buf(kex->my, proposal)) != 0)
385 goto out;
386 kex->done = 0;
387 kex_reset_dispatch(ssh);
388 r = 0;
389 *kexp = kex;
390 out:
391 if (r != 0)
392 kex_free(kex);
393 return r;
321} 394}
322 395
323void 396void
@@ -351,51 +424,53 @@ kex_free_newkeys(struct newkeys *newkeys)
351 free(newkeys); 424 free(newkeys);
352} 425}
353 426
354Kex * 427void
355kex_setup(char *proposal[PROPOSAL_MAX]) 428kex_free(struct kex *kex)
356{ 429{
357 struct kex *kex; 430 u_int mode;
358 431
359 if ((kex = calloc(1, sizeof(*kex))) == NULL) 432#ifdef WITH_OPENSSL
360 fatal("%s: calloc", __func__); 433 if (kex->dh)
361 if ((kex->peer = sshbuf_new()) == NULL || 434 DH_free(kex->dh);
362 (kex->my = sshbuf_new()) == NULL) { 435 if (kex->ec_client_key)
363 fatal("%s: sshbuf_new", __func__); 436 EC_KEY_free(kex->ec_client_key);
437#endif
438 for (mode = 0; mode < MODE_MAX; mode++) {
439 kex_free_newkeys(kex->newkeys[mode]);
440 kex->newkeys[mode] = NULL;
364 } 441 }
365 kex_prop2buf(kex->my, proposal); 442 sshbuf_free(kex->peer);
366 kex->done = 0; 443 sshbuf_free(kex->my);
367 444 free(kex->session_id);
368 kex_send_kexinit(kex); /* we start */ 445 free(kex->client_version_string);
369 kex_reset_dispatch(); 446 free(kex->server_version_string);
370 447 free(kex);
371 return kex;
372} 448}
373 449
374static void 450int
375kex_kexinit_finish(Kex *kex) 451kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
376{ 452{
377 if (!(kex->flags & KEX_INIT_SENT)) 453 int r;
378 kex_send_kexinit(kex); 454
379 455 if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0)
380 kex_choose_conf(kex); 456 return r;
381 457 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
382 if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && 458 kex_free(ssh->kex);
383 kex->kex[kex->kex_type] != NULL) { 459 ssh->kex = NULL;
384 (kex->kex[kex->kex_type])(kex); 460 return r;
385 } else {
386 fatal("Unsupported key exchange %d", kex->kex_type);
387 } 461 }
462 return 0;
388} 463}
389 464
390static void 465static int
391choose_enc(Enc *enc, char *client, char *server) 466choose_enc(struct sshenc *enc, char *client, char *server)
392{ 467{
393 char *name = match_list(client, server, NULL); 468 char *name = match_list(client, server, NULL);
469
394 if (name == NULL) 470 if (name == NULL)
395 fatal("no matching cipher found: client %s server %s", 471 return SSH_ERR_NO_CIPHER_ALG_MATCH;
396 client, server);
397 if ((enc->cipher = cipher_by_name(name)) == NULL) 472 if ((enc->cipher = cipher_by_name(name)) == NULL)
398 fatal("matching cipher is not supported: %s", name); 473 return SSH_ERR_INTERNAL_ERROR;
399 enc->name = name; 474 enc->name = name;
400 enc->enabled = 0; 475 enc->enabled = 0;
401 enc->iv = NULL; 476 enc->iv = NULL;
@@ -403,31 +478,34 @@ choose_enc(Enc *enc, char *client, char *server)
403 enc->key = NULL; 478 enc->key = NULL;
404 enc->key_len = cipher_keylen(enc->cipher); 479 enc->key_len = cipher_keylen(enc->cipher);
405 enc->block_size = cipher_blocksize(enc->cipher); 480 enc->block_size = cipher_blocksize(enc->cipher);
481 return 0;
406} 482}
407 483
408static void 484static int
409choose_mac(Mac *mac, char *client, char *server) 485choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
410{ 486{
411 char *name = match_list(client, server, NULL); 487 char *name = match_list(client, server, NULL);
488
412 if (name == NULL) 489 if (name == NULL)
413 fatal("no matching mac found: client %s server %s", 490 return SSH_ERR_NO_MAC_ALG_MATCH;
414 client, server);
415 if (mac_setup(mac, name) < 0) 491 if (mac_setup(mac, name) < 0)
416 fatal("unsupported mac %s", name); 492 return SSH_ERR_INTERNAL_ERROR;
417 /* truncate the key */ 493 /* truncate the key */
418 if (datafellows & SSH_BUG_HMAC) 494 if (ssh->compat & SSH_BUG_HMAC)
419 mac->key_len = 16; 495 mac->key_len = 16;
420 mac->name = name; 496 mac->name = name;
421 mac->key = NULL; 497 mac->key = NULL;
422 mac->enabled = 0; 498 mac->enabled = 0;
499 return 0;
423} 500}
424 501
425static void 502static int
426choose_comp(Comp *comp, char *client, char *server) 503choose_comp(struct sshcomp *comp, char *client, char *server)
427{ 504{
428 char *name = match_list(client, server, NULL); 505 char *name = match_list(client, server, NULL);
506
429 if (name == NULL) 507 if (name == NULL)
430 fatal("no matching comp found: client %s server %s", client, server); 508 return SSH_ERR_NO_COMPRESS_ALG_MATCH;
431 if (strcmp(name, "zlib@openssh.com") == 0) { 509 if (strcmp(name, "zlib@openssh.com") == 0) {
432 comp->type = COMP_DELAYED; 510 comp->type = COMP_DELAYED;
433 } else if (strcmp(name, "zlib") == 0) { 511 } else if (strcmp(name, "zlib") == 0) {
@@ -435,36 +513,41 @@ choose_comp(Comp *comp, char *client, char *server)
435 } else if (strcmp(name, "none") == 0) { 513 } else if (strcmp(name, "none") == 0) {
436 comp->type = COMP_NONE; 514 comp->type = COMP_NONE;
437 } else { 515 } else {
438 fatal("unsupported comp %s", name); 516 return SSH_ERR_INTERNAL_ERROR;
439 } 517 }
440 comp->name = name; 518 comp->name = name;
519 return 0;
441} 520}
442 521
443static void 522static int
444choose_kex(Kex *k, char *client, char *server) 523choose_kex(struct kex *k, char *client, char *server)
445{ 524{
446 const struct kexalg *kexalg; 525 const struct kexalg *kexalg;
447 526
448 k->name = match_list(client, server, NULL); 527 k->name = match_list(client, server, NULL);
528
449 if (k->name == NULL) 529 if (k->name == NULL)
450 fatal("Unable to negotiate a key exchange method"); 530 return SSH_ERR_NO_KEX_ALG_MATCH;
451 if ((kexalg = kex_alg_by_name(k->name)) == NULL) 531 if ((kexalg = kex_alg_by_name(k->name)) == NULL)
452 fatal("unsupported kex alg %s", k->name); 532 return SSH_ERR_INTERNAL_ERROR;
453 k->kex_type = kexalg->type; 533 k->kex_type = kexalg->type;
454 k->hash_alg = kexalg->hash_alg; 534 k->hash_alg = kexalg->hash_alg;
455 k->ec_nid = kexalg->ec_nid; 535 k->ec_nid = kexalg->ec_nid;
536 return 0;
456} 537}
457 538
458static void 539static int
459choose_hostkeyalg(Kex *k, char *client, char *server) 540choose_hostkeyalg(struct kex *k, char *client, char *server)
460{ 541{
461 char *hostkeyalg = match_list(client, server, NULL); 542 char *hostkeyalg = match_list(client, server, NULL);
543
462 if (hostkeyalg == NULL) 544 if (hostkeyalg == NULL)
463 fatal("no hostkey alg"); 545 return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
464 k->hostkey_type = key_type_from_name(hostkeyalg); 546 k->hostkey_type = sshkey_type_from_name(hostkeyalg);
465 if (k->hostkey_type == KEY_UNSPEC) 547 if (k->hostkey_type == KEY_UNSPEC)
466 fatal("bad hostkey alg '%s'", hostkeyalg); 548 return SSH_ERR_INTERNAL_ERROR;
467 free(hostkeyalg); 549 free(hostkeyalg);
550 return 0;
468} 551}
469 552
470static int 553static int
@@ -491,18 +574,20 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
491 return (1); 574 return (1);
492} 575}
493 576
494static void 577static int
495kex_choose_conf(Kex *kex) 578kex_choose_conf(struct ssh *ssh)
496{ 579{
497 Newkeys *newkeys; 580 struct kex *kex = ssh->kex;
498 char **my, **peer; 581 struct newkeys *newkeys;
582 char **my = NULL, **peer = NULL;
499 char **cprop, **sprop; 583 char **cprop, **sprop;
500 int nenc, nmac, ncomp; 584 int nenc, nmac, ncomp;
501 u_int mode, ctos, need, dh_need, authlen; 585 u_int mode, ctos, need, dh_need, authlen;
502 int first_kex_follows, type; 586 int r, first_kex_follows;
503 587
504 my = kex_buf2prop(kex->my, NULL); 588 if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0 ||
505 peer = kex_buf2prop(kex->peer, &first_kex_follows); 589 (r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
590 goto out;
506 591
507 if (kex->server) { 592 if (kex->server) {
508 cprop=peer; 593 cprop=peer;
@@ -514,8 +599,9 @@ kex_choose_conf(Kex *kex)
514 599
515 /* Check whether server offers roaming */ 600 /* Check whether server offers roaming */
516 if (!kex->server) { 601 if (!kex->server) {
517 char *roaming; 602 char *roaming = match_list(KEX_RESUME,
518 roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL); 603 peer[PROPOSAL_KEX_ALGS], NULL);
604
519 if (roaming) { 605 if (roaming) {
520 kex->roaming = 1; 606 kex->roaming = 1;
521 free(roaming); 607 free(roaming);
@@ -524,28 +610,39 @@ kex_choose_conf(Kex *kex)
524 610
525 /* Algorithm Negotiation */ 611 /* Algorithm Negotiation */
526 for (mode = 0; mode < MODE_MAX; mode++) { 612 for (mode = 0; mode < MODE_MAX; mode++) {
527 newkeys = xcalloc(1, sizeof(*newkeys)); 613 if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
614 r = SSH_ERR_ALLOC_FAIL;
615 goto out;
616 }
528 kex->newkeys[mode] = newkeys; 617 kex->newkeys[mode] = newkeys;
529 ctos = (!kex->server && mode == MODE_OUT) || 618 ctos = (!kex->server && mode == MODE_OUT) ||
530 (kex->server && mode == MODE_IN); 619 (kex->server && mode == MODE_IN);
531 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; 620 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
532 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; 621 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
533 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; 622 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
534 choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc]); 623 if ((r = choose_enc(&newkeys->enc, cprop[nenc],
535 /* ignore mac for authenticated encryption */ 624 sprop[nenc])) != 0)
625 goto out;
536 authlen = cipher_authlen(newkeys->enc.cipher); 626 authlen = cipher_authlen(newkeys->enc.cipher);
537 if (authlen == 0) 627 /* ignore mac for authenticated encryption */
538 choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]); 628 if (authlen == 0 &&
539 choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); 629 (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
630 sprop[nmac])) != 0)
631 goto out;
632 if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
633 sprop[ncomp])) != 0)
634 goto out;
540 debug("kex: %s %s %s %s", 635 debug("kex: %s %s %s %s",
541 ctos ? "client->server" : "server->client", 636 ctos ? "client->server" : "server->client",
542 newkeys->enc.name, 637 newkeys->enc.name,
543 authlen == 0 ? newkeys->mac.name : "<implicit>", 638 authlen == 0 ? newkeys->mac.name : "<implicit>",
544 newkeys->comp.name); 639 newkeys->comp.name);
545 } 640 }
546 choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); 641 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
547 choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], 642 sprop[PROPOSAL_KEX_ALGS])) != 0 ||
548 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); 643 (r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
644 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0)
645 goto out;
549 need = dh_need = 0; 646 need = dh_need = 0;
550 for (mode = 0; mode < MODE_MAX; mode++) { 647 for (mode = 0; mode < MODE_MAX; mode++) {
551 newkeys = kex->newkeys[mode]; 648 newkeys = kex->newkeys[mode];
@@ -564,45 +661,47 @@ kex_choose_conf(Kex *kex)
564 661
565 /* ignore the next message if the proposals do not match */ 662 /* ignore the next message if the proposals do not match */
566 if (first_kex_follows && !proposals_match(my, peer) && 663 if (first_kex_follows && !proposals_match(my, peer) &&
567 !(datafellows & SSH_BUG_FIRSTKEX)) { 664 !(ssh->compat & SSH_BUG_FIRSTKEX))
568 type = packet_read(); 665 ssh->dispatch_skip_packets = 1;
569 debug2("skipping next packet (type %u)", type); 666 r = 0;
570 } 667 out:
571
572 kex_prop_free(my); 668 kex_prop_free(my);
573 kex_prop_free(peer); 669 kex_prop_free(peer);
670 return r;
574} 671}
575 672
576static u_char * 673static int
577derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, 674derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
578 const u_char *shared_secret, u_int slen) 675 const struct sshbuf *shared_secret, u_char **keyp)
579{ 676{
580 Buffer b; 677 struct kex *kex = ssh->kex;
581 struct ssh_digest_ctx *hashctx; 678 struct ssh_digest_ctx *hashctx = NULL;
582 char c = id; 679 char c = id;
583 u_int have; 680 u_int have;
584 size_t mdsz; 681 size_t mdsz;
585 u_char *digest; 682 u_char *digest;
683 int r;
586 684
587 if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) 685 if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
588 fatal("bad kex md size %zu", mdsz); 686 return SSH_ERR_INVALID_ARGUMENT;
589 digest = xmalloc(roundup(need, mdsz)); 687 if ((digest = calloc(1, roundup(need, mdsz))) == NULL) {
590 688 r = SSH_ERR_ALLOC_FAIL;
591 buffer_init(&b); 689 goto out;
592 buffer_append(&b, shared_secret, slen); 690 }
593 691
594 /* K1 = HASH(K || H || "A" || session_id) */ 692 /* K1 = HASH(K || H || "A" || session_id) */
595 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) 693 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
596 fatal("%s: ssh_digest_start failed", __func__); 694 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
597 if (ssh_digest_update_buffer(hashctx, &b) != 0 ||
598 ssh_digest_update(hashctx, hash, hashlen) != 0 || 695 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
599 ssh_digest_update(hashctx, &c, 1) != 0 || 696 ssh_digest_update(hashctx, &c, 1) != 0 ||
600 ssh_digest_update(hashctx, kex->session_id, 697 ssh_digest_update(hashctx, kex->session_id,
601 kex->session_id_len) != 0) 698 kex->session_id_len) != 0 ||
602 fatal("%s: ssh_digest_update failed", __func__); 699 ssh_digest_final(hashctx, digest, mdsz) != 0) {
603 if (ssh_digest_final(hashctx, digest, mdsz) != 0) 700 r = SSH_ERR_LIBCRYPTO_ERROR;
604 fatal("%s: ssh_digest_final failed", __func__); 701 goto out;
702 }
605 ssh_digest_free(hashctx); 703 ssh_digest_free(hashctx);
704 hashctx = NULL;
606 705
607 /* 706 /*
608 * expand key: 707 * expand key:
@@ -610,38 +709,49 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen,
610 * Key = K1 || K2 || ... || Kn 709 * Key = K1 || K2 || ... || Kn
611 */ 710 */
612 for (have = mdsz; need > have; have += mdsz) { 711 for (have = mdsz; need > have; have += mdsz) {
613 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) 712 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
614 fatal("%s: ssh_digest_start failed", __func__); 713 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
615 if (ssh_digest_update_buffer(hashctx, &b) != 0 ||
616 ssh_digest_update(hashctx, hash, hashlen) != 0 || 714 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
617 ssh_digest_update(hashctx, digest, have) != 0) 715 ssh_digest_update(hashctx, digest, have) != 0 ||
618 fatal("%s: ssh_digest_update failed", __func__); 716 ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
619 if (ssh_digest_final(hashctx, digest + have, mdsz) != 0) 717 r = SSH_ERR_LIBCRYPTO_ERROR;
620 fatal("%s: ssh_digest_final failed", __func__); 718 goto out;
719 }
621 ssh_digest_free(hashctx); 720 ssh_digest_free(hashctx);
721 hashctx = NULL;
622 } 722 }
623 buffer_free(&b);
624#ifdef DEBUG_KEX 723#ifdef DEBUG_KEX
625 fprintf(stderr, "key '%c'== ", c); 724 fprintf(stderr, "key '%c'== ", c);
626 dump_digest("key", digest, need); 725 dump_digest("key", digest, need);
627#endif 726#endif
628 return digest; 727 *keyp = digest;
728 digest = NULL;
729 r = 0;
730 out:
731 if (digest)
732 free(digest);
733 ssh_digest_free(hashctx);
734 return r;
629} 735}
630 736
631#define NKEYS 6 737#define NKEYS 6
632void 738int
633kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, 739kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
634 const u_char *shared_secret, u_int slen) 740 const struct sshbuf *shared_secret)
635{ 741{
742 struct kex *kex = ssh->kex;
636 u_char *keys[NKEYS]; 743 u_char *keys[NKEYS];
637 u_int i, mode, ctos; 744 u_int i, j, mode, ctos;
745 int r;
638 746
639 for (i = 0; i < NKEYS; i++) { 747 for (i = 0; i < NKEYS; i++) {
640 keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen, 748 if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
641 shared_secret, slen); 749 shared_secret, &keys[i])) != 0) {
750 for (j = 0; j < i; j++)
751 free(keys[j]);
752 return r;
753 }
642 } 754 }
643
644 debug2("kex_derive_keys");
645 for (mode = 0; mode < MODE_MAX; mode++) { 755 for (mode = 0; mode < MODE_MAX; mode++) {
646 ctos = (!kex->server && mode == MODE_OUT) || 756 ctos = (!kex->server && mode == MODE_OUT) ||
647 (kex->server && mode == MODE_IN); 757 (kex->server && mode == MODE_IN);
@@ -649,54 +759,54 @@ kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen,
649 kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3]; 759 kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
650 kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5]; 760 kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
651 } 761 }
762 return 0;
652} 763}
653 764
654#ifdef WITH_OPENSSL 765#ifdef WITH_OPENSSL
655void 766int
656kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) 767kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen,
768 const BIGNUM *secret)
657{ 769{
658 Buffer shared_secret; 770 struct sshbuf *shared_secret;
659 771 int r;
660 buffer_init(&shared_secret); 772
661 buffer_put_bignum2(&shared_secret, secret); 773 if ((shared_secret = sshbuf_new()) == NULL)
662 kex_derive_keys(kex, hash, hashlen, 774 return SSH_ERR_ALLOC_FAIL;
663 buffer_ptr(&shared_secret), buffer_len(&shared_secret)); 775 if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0)
664 buffer_free(&shared_secret); 776 r = kex_derive_keys(ssh, hash, hashlen, shared_secret);
777 sshbuf_free(shared_secret);
778 return r;
665} 779}
666#endif 780#endif
667 781
668#ifdef WITH_SSH1 782#ifdef WITH_SSH1
669void 783int
670derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, 784derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
671 u_int8_t cookie[8], u_int8_t id[16]) 785 u_int8_t cookie[8], u_int8_t id[16])
672{ 786{
673 u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; 787 u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH];
674 int len; 788 struct ssh_digest_ctx *hashctx = NULL;
675 struct ssh_digest_ctx *hashctx; 789 size_t len;
676 790 int r;
677 if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL)
678 fatal("%s: ssh_digest_start", __func__);
679 791
680 len = BN_num_bytes(host_modulus); 792 len = BN_num_bytes(host_modulus);
681 if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 793 if (len < (512 / 8) || (u_int)len > sizeof(nbuf))
682 fatal("%s: bad host modulus (len %d)", __func__, len); 794 return SSH_ERR_KEY_BITS_MISMATCH;
683 BN_bn2bin(host_modulus, nbuf); 795 if (BN_bn2bin(host_modulus, nbuf) <= 0 ||
684 if (ssh_digest_update(hashctx, nbuf, len) != 0) 796 (hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
685 fatal("%s: ssh_digest_update failed", __func__); 797 ssh_digest_update(hashctx, nbuf, len) != 0 ||
686 798 ssh_digest_update(hashctx, cookie, 8) != 0 ||
687 len = BN_num_bytes(server_modulus); 799 ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) {
688 if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 800 r = SSH_ERR_LIBCRYPTO_ERROR;
689 fatal("%s: bad server modulus (len %d)", __func__, len); 801 goto out;
690 BN_bn2bin(server_modulus, nbuf); 802 }
691 if (ssh_digest_update(hashctx, nbuf, len) != 0 ||
692 ssh_digest_update(hashctx, cookie, 8) != 0)
693 fatal("%s: ssh_digest_update failed", __func__);
694 if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0)
695 fatal("%s: ssh_digest_final failed", __func__);
696 memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); 803 memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5));
697 804 r = 0;
805 out:
806 ssh_digest_free(hashctx);
698 explicit_bzero(nbuf, sizeof(nbuf)); 807 explicit_bzero(nbuf, sizeof(nbuf));
699 explicit_bzero(obuf, sizeof(obuf)); 808 explicit_bzero(obuf, sizeof(obuf));
809 return r;
700} 810}
701#endif 811#endif
702 812
@@ -704,16 +814,7 @@ derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
704void 814void
705dump_digest(char *msg, u_char *digest, int len) 815dump_digest(char *msg, u_char *digest, int len)
706{ 816{
707 int i;
708
709 fprintf(stderr, "%s\n", msg); 817 fprintf(stderr, "%s\n", msg);
710 for (i = 0; i < len; i++) { 818 sshbuf_dump_data(digest, len, stderr);
711 fprintf(stderr, "%02x", digest[i]);
712 if (i%32 == 31)
713 fprintf(stderr, "\n");
714 else if (i%8 == 7)
715 fprintf(stderr, " ");
716 }
717 fprintf(stderr, "\n");
718} 819}
719#endif 820#endif
diff --git a/kex.h b/kex.h
index 1f7c824b6..1798eea4d 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.68 2015/01/19 20:07:45 markus Exp $ */ 1/* $OpenBSD: kex.h,v 1.69 2015/01/19 20:16:15 markus 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.
@@ -30,8 +30,8 @@
30#include "buffer.h" /* XXX for typedef */ 30#include "buffer.h" /* XXX for typedef */
31#include "key.h" /* XXX for typedef */ 31#include "key.h" /* XXX for typedef */
32 32
33#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) 33#ifdef WITH_LEAKMALLOC
34#include <openssl/ec.h> 34#include "leakmalloc.h"
35#endif 35#endif
36 36
37#define KEX_COOKIE_LEN 16 37#define KEX_COOKIE_LEN 16
@@ -50,6 +50,8 @@
50#define COMP_ZLIB 1 50#define COMP_ZLIB 1
51#define COMP_DELAYED 2 51#define COMP_DELAYED 2
52 52
53#define CURVE25519_SIZE 32
54
53enum kex_init_proposals { 55enum kex_init_proposals {
54 PROPOSAL_KEX_ALGS, 56 PROPOSAL_KEX_ALGS,
55 PROPOSAL_SERVER_HOST_KEY_ALGS, 57 PROPOSAL_SERVER_HOST_KEY_ALGS,
@@ -82,12 +84,6 @@ enum kex_exchange {
82 84
83#define KEX_INIT_SENT 0x0001 85#define KEX_INIT_SENT 0x0001
84 86
85typedef struct kex Kex;
86typedef struct sshcomp Comp;
87typedef struct sshmac Mac;
88typedef struct sshenc Enc;
89typedef struct newkeys Newkeys;
90
91struct sshenc { 87struct sshenc {
92 char *name; 88 char *name;
93 const struct sshcipher *cipher; 89 const struct sshcipher *cipher;
@@ -106,8 +102,11 @@ struct sshcomp {
106struct newkeys { 102struct newkeys {
107 struct sshenc enc; 103 struct sshenc enc;
108 struct sshmac mac; 104 struct sshmac mac;
109 struct sshcomp comp; 105 struct sshcomp comp;
110}; 106};
107
108struct ssh;
109
111struct kex { 110struct kex {
112 u_char *session_id; 111 u_char *session_id;
113 size_t session_id_len; 112 size_t session_id_len;
@@ -117,73 +116,87 @@ struct kex {
117 int server; 116 int server;
118 char *name; 117 char *name;
119 int hostkey_type; 118 int hostkey_type;
120 int kex_type; 119 u_int kex_type;
121 int roaming; 120 int roaming;
122 struct sshbuf *my; 121 struct sshbuf *my;
123 struct sshbuf *peer; 122 struct sshbuf *peer;
124 sig_atomic_t done; 123 sig_atomic_t done;
125 int flags; 124 u_int flags;
126 int hash_alg; 125 int hash_alg;
127 int ec_nid; 126 int ec_nid;
128 char *client_version_string; 127 char *client_version_string;
129 char *server_version_string; 128 char *server_version_string;
130 int (*verify_host_key)(Key *); 129 int (*verify_host_key)(struct sshkey *, struct ssh *);
131 Key *(*load_host_public_key)(int); 130 struct sshkey *(*load_host_public_key)(int, struct ssh *);
132 Key *(*load_host_private_key)(int); 131 struct sshkey *(*load_host_private_key)(int, struct ssh *);
133 int (*host_key_index)(Key *); 132 int (*host_key_index)(struct sshkey *, struct ssh *);
134 void (*sign)(Key *, Key *, u_char **, u_int *, u_char *, u_int); 133 int (*sign)(struct sshkey *, struct sshkey *,
135 void (*kex[KEX_MAX])(Kex *); 134 u_char **, size_t *, u_char *, size_t, u_int);
135 int (*kex[KEX_MAX])(struct ssh *);
136 /* kex specific state */
137 DH *dh; /* DH */
138 u_int min, max, nbits; /* GEX */
139 EC_KEY *ec_client_key; /* ECDH */
140 const EC_GROUP *ec_group; /* ECDH */
141 u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 */
142 u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */
136}; 143};
137 144
138int kex_names_valid(const char *); 145int kex_names_valid(const char *);
139char *kex_alg_list(char); 146char *kex_alg_list(char);
140 147
141Kex *kex_setup(char *[PROPOSAL_MAX]); 148int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **);
142void kex_finish(Kex *); 149int kex_setup(struct ssh *, char *[PROPOSAL_MAX]);
143void kex_free_newkeys(struct newkeys *); 150void kex_free_newkeys(struct newkeys *);
151void kex_free(struct kex *);
144 152
145void kex_send_kexinit(Kex *); 153int kex_buf2prop(struct sshbuf *, int *, char ***);
146int kex_input_kexinit(int, u_int32_t, void *); 154int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]);
147void kex_derive_keys(Kex *, u_char *, u_int, const u_char *, u_int); 155void kex_prop_free(char **);
148void kex_derive_keys_bn(Kex *, u_char *, u_int, const BIGNUM *);
149
150void kexdh_client(Kex *);
151void kexdh_server(Kex *);
152void kexgex_client(Kex *);
153void kexgex_server(Kex *);
154void kexecdh_client(Kex *);
155void kexecdh_server(Kex *);
156void kexc25519_client(Kex *);
157void kexc25519_server(Kex *);
158
159void
160kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
161 BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
162void
163kexgex_hash(int, char *, char *, char *, int, char *,
164 int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *,
165 BIGNUM *, BIGNUM *, u_char **, u_int *);
166#ifdef OPENSSL_HAS_ECC
167void
168kex_ecdh_hash(int, const EC_GROUP *, char *, char *, char *, int,
169 char *, int, u_char *, int, const EC_POINT *, const EC_POINT *,
170 const BIGNUM *, u_char **, u_int *);
171#endif
172void
173kex_c25519_hash(int, char *, char *, char *, int,
174 char *, int, u_char *, int, const u_char *, const u_char *,
175 const u_char *, u_int, u_char **, u_int *);
176 156
177#define CURVE25519_SIZE 32 157int kex_send_kexinit(struct ssh *);
178void kexc25519_keygen(u_char[CURVE25519_SIZE], u_char[CURVE25519_SIZE]) 158int kex_input_kexinit(int, u_int32_t, void *);
159int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *);
160int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *);
161int kex_send_newkeys(struct ssh *);
162
163int kexdh_client(struct ssh *);
164int kexdh_server(struct ssh *);
165int kexgex_client(struct ssh *);
166int kexgex_server(struct ssh *);
167int kexecdh_client(struct ssh *);
168int kexecdh_server(struct ssh *);
169int kexc25519_client(struct ssh *);
170int kexc25519_server(struct ssh *);
171
172int kex_dh_hash(const char *, const char *,
173 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
174 const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
175
176int kexgex_hash(int, const char *, const char *,
177 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
178 int, int, int,
179 const BIGNUM *, const BIGNUM *, const BIGNUM *,
180 const BIGNUM *, const BIGNUM *,
181 u_char *, size_t *);
182
183int kex_ecdh_hash(int, const EC_GROUP *, const char *, const char *,
184 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
185 const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *);
186
187int kex_c25519_hash(int, const char *, const char *, const char *, size_t,
188 const char *, size_t, const u_char *, size_t, const u_char *, const u_char *,
189 const u_char *, size_t, u_char *, size_t *);
190
191void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
179 __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) 192 __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
180 __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); 193 __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
181void kexc25519_shared_key(const u_char key[CURVE25519_SIZE], 194int kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
182 const u_char pub[CURVE25519_SIZE], Buffer *out) 195 const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
183 __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) 196 __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
184 __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); 197 __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
185 198
186void 199int
187derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); 200derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]);
188 201
189#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) 202#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
diff --git a/kexc25519.c b/kexc25519.c
index e3afa0055..b6e6c4010 100644
--- a/kexc25519.c
+++ b/kexc25519.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexc25519.c,v 1.7 2014/05/02 03:27:54 djm Exp $ */ 1/* $OpenBSD: kexc25519.c,v 1.8 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -35,13 +35,14 @@
35#include <openssl/bn.h> 35#include <openssl/bn.h>
36#include <openssl/evp.h> 36#include <openssl/evp.h>
37 37
38#include "buffer.h" 38#include "sshbuf.h"
39#include "ssh2.h" 39#include "ssh2.h"
40#include "key.h" 40#include "sshkey.h"
41#include "cipher.h" 41#include "cipher.h"
42#include "kex.h" 42#include "kex.h"
43#include "log.h" 43#include "log.h"
44#include "digest.h" 44#include "digest.h"
45#include "ssherr.h"
45 46
46extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE], 47extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE],
47 const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE]) 48 const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE])
@@ -58,65 +59,70 @@ kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
58 crypto_scalarmult_curve25519(pub, key, basepoint); 59 crypto_scalarmult_curve25519(pub, key, basepoint);
59} 60}
60 61
61void 62int
62kexc25519_shared_key(const u_char key[CURVE25519_SIZE], 63kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
63 const u_char pub[CURVE25519_SIZE], Buffer *out) 64 const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
64{ 65{
65 u_char shared_key[CURVE25519_SIZE]; 66 u_char shared_key[CURVE25519_SIZE];
67 int r;
66 68
67 crypto_scalarmult_curve25519(shared_key, key, pub); 69 crypto_scalarmult_curve25519(shared_key, key, pub);
68#ifdef DEBUG_KEXECDH 70#ifdef DEBUG_KEXECDH
69 dump_digest("shared secret", shared_key, CURVE25519_SIZE); 71 dump_digest("shared secret", shared_key, CURVE25519_SIZE);
70#endif 72#endif
71 buffer_clear(out); 73 sshbuf_reset(out);
72 buffer_put_bignum2_from_string(out, shared_key, CURVE25519_SIZE); 74 r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE);
73 explicit_bzero(shared_key, CURVE25519_SIZE); 75 explicit_bzero(shared_key, CURVE25519_SIZE);
76 return r;
74} 77}
75 78
76void 79int
77kex_c25519_hash( 80kex_c25519_hash(
78 int hash_alg, 81 int hash_alg,
79 char *client_version_string, 82 const char *client_version_string,
80 char *server_version_string, 83 const char *server_version_string,
81 char *ckexinit, int ckexinitlen, 84 const char *ckexinit, size_t ckexinitlen,
82 char *skexinit, int skexinitlen, 85 const char *skexinit, size_t skexinitlen,
83 u_char *serverhostkeyblob, int sbloblen, 86 const u_char *serverhostkeyblob, size_t sbloblen,
84 const u_char client_dh_pub[CURVE25519_SIZE], 87 const u_char client_dh_pub[CURVE25519_SIZE],
85 const u_char server_dh_pub[CURVE25519_SIZE], 88 const u_char server_dh_pub[CURVE25519_SIZE],
86 const u_char *shared_secret, u_int secretlen, 89 const u_char *shared_secret, size_t secretlen,
87 u_char **hash, u_int *hashlen) 90 u_char *hash, size_t *hashlen)
88{ 91{
89 Buffer b; 92 struct sshbuf *b;
90 static u_char digest[SSH_DIGEST_MAX_LENGTH]; 93 int r;
91 94
92 buffer_init(&b); 95 if (*hashlen < ssh_digest_bytes(hash_alg))
93 buffer_put_cstring(&b, client_version_string); 96 return SSH_ERR_INVALID_ARGUMENT;
94 buffer_put_cstring(&b, server_version_string); 97 if ((b = sshbuf_new()) == NULL)
95 98 return SSH_ERR_ALLOC_FAIL;
96 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ 99 if ((r = sshbuf_put_cstring(b, client_version_string)) < 0 ||
97 buffer_put_int(&b, ckexinitlen+1); 100 (r = sshbuf_put_cstring(b, server_version_string)) < 0 ||
98 buffer_put_char(&b, SSH2_MSG_KEXINIT); 101 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
99 buffer_append(&b, ckexinit, ckexinitlen); 102 (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 ||
100 buffer_put_int(&b, skexinitlen+1); 103 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 ||
101 buffer_put_char(&b, SSH2_MSG_KEXINIT); 104 (r = sshbuf_put(b, ckexinit, ckexinitlen)) < 0 ||
102 buffer_append(&b, skexinit, skexinitlen); 105 (r = sshbuf_put_u32(b, skexinitlen+1)) < 0 ||
103 106 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 ||
104 buffer_put_string(&b, serverhostkeyblob, sbloblen); 107 (r = sshbuf_put(b, skexinit, skexinitlen)) < 0 ||
105 buffer_put_string(&b, client_dh_pub, CURVE25519_SIZE); 108 (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) < 0 ||
106 buffer_put_string(&b, server_dh_pub, CURVE25519_SIZE); 109 (r = sshbuf_put_string(b, client_dh_pub, CURVE25519_SIZE)) < 0 ||
107 buffer_append(&b, shared_secret, secretlen); 110 (r = sshbuf_put_string(b, server_dh_pub, CURVE25519_SIZE)) < 0 ||
108 111 (r = sshbuf_put(b, shared_secret, secretlen)) < 0) {
112 sshbuf_free(b);
113 return r;
114 }
109#ifdef DEBUG_KEX 115#ifdef DEBUG_KEX
110 buffer_dump(&b); 116 sshbuf_dump(b, stderr);
111#endif 117#endif
112 if (ssh_digest_buffer(hash_alg, &b, digest, sizeof(digest)) != 0) 118 if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
113 fatal("%s: digest_buffer failed", __func__); 119 sshbuf_free(b);
114 120 return SSH_ERR_LIBCRYPTO_ERROR;
115 buffer_free(&b); 121 }
116 122 sshbuf_free(b);
123 *hashlen = ssh_digest_bytes(hash_alg);
117#ifdef DEBUG_KEX 124#ifdef DEBUG_KEX
118 dump_digest("hash", digest, ssh_digest_bytes(hash_alg)); 125 dump_digest("hash", hash, *hashlen);
119#endif 126#endif
120 *hash = digest; 127 return 0;
121 *hashlen = ssh_digest_bytes(hash_alg);
122} 128}
diff --git a/kexc25519c.c b/kexc25519c.c
index ffb537ef6..833ce0544 100644
--- a/kexc25519c.c
+++ b/kexc25519c.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexc25519c.c,v 1.5 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: kexc25519c.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -33,97 +33,136 @@
33#include <string.h> 33#include <string.h>
34#include <signal.h> 34#include <signal.h>
35 35
36#include "xmalloc.h" 36#include "sshkey.h"
37#include "buffer.h"
38#include "key.h"
39#include "cipher.h" 37#include "cipher.h"
40#include "kex.h" 38#include "kex.h"
41#include "log.h" 39#include "log.h"
42#include "packet.h" 40#include "packet.h"
43#include "ssh2.h" 41#include "ssh2.h"
42#include "sshbuf.h"
43#include "digest.h"
44#include "ssherr.h"
44 45
45void 46static int
46kexc25519_client(Kex *kex) 47input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt);
47{
48 Key *server_host_key;
49 u_char client_key[CURVE25519_SIZE];
50 u_char client_pubkey[CURVE25519_SIZE];
51 u_char *server_pubkey = NULL;
52 u_char *server_host_key_blob = NULL, *signature = NULL;
53 u_char *hash;
54 u_int slen, sbloblen, hashlen;
55 Buffer shared_secret;
56
57 kexc25519_keygen(client_key, client_pubkey);
58 48
59 packet_start(SSH2_MSG_KEX_ECDH_INIT); 49int
60 packet_put_string(client_pubkey, sizeof(client_pubkey)); 50kexc25519_client(struct ssh *ssh)
61 packet_send(); 51{
62 debug("sending SSH2_MSG_KEX_ECDH_INIT"); 52 struct kex *kex = ssh->kex;
53 int r;
63 54
55 kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey);
64#ifdef DEBUG_KEXECDH 56#ifdef DEBUG_KEXECDH
65 dump_digest("client private key:", client_key, sizeof(client_key)); 57 dump_digest("client private key:", kex->c25519_client_key,
58 sizeof(kex->c25519_client_key));
66#endif 59#endif
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)
64 return r;
67 65
68 debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); 66 debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
69 packet_read_expect(SSH2_MSG_KEX_ECDH_REPLY); 67 ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_c25519_reply);
68 return 0;
69}
70
71static int
72input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt)
73{
74 struct ssh *ssh = ctxt;
75 struct kex *kex = ssh->kex;
76 struct sshkey *server_host_key = NULL;
77 struct sshbuf *shared_secret = NULL;
78 u_char *server_pubkey = NULL;
79 u_char *server_host_key_blob = NULL, *signature = NULL;
80 u_char hash[SSH_DIGEST_MAX_LENGTH];
81 size_t slen, pklen, sbloblen, hashlen;
82 int r;
83
84 if (kex->verify_host_key == NULL) {
85 r = SSH_ERR_INVALID_ARGUMENT;
86 goto out;
87 }
70 88
71 /* hostkey */ 89 /* hostkey */
72 server_host_key_blob = packet_get_string(&sbloblen); 90 if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
73 server_host_key = key_from_blob(server_host_key_blob, sbloblen); 91 &sbloblen)) != 0 ||
74 if (server_host_key == NULL) 92 (r = sshkey_from_blob(server_host_key_blob, sbloblen,
75 fatal("cannot decode server_host_key_blob"); 93 &server_host_key)) != 0)
76 if (server_host_key->type != kex->hostkey_type) 94 goto out;
77 fatal("type mismatch for decoded server_host_key_blob"); 95 if (server_host_key->type != kex->hostkey_type) {
78 if (kex->verify_host_key == NULL) 96 r = SSH_ERR_KEY_TYPE_MISMATCH;
79 fatal("cannot verify server_host_key"); 97 goto out;
80 if (kex->verify_host_key(server_host_key) == -1) 98 }
81 fatal("server_host_key verification failed"); 99 if (kex->verify_host_key(server_host_key, ssh) == -1) {
100 r = SSH_ERR_SIGNATURE_INVALID;
101 goto out;
102 }
82 103
83 /* Q_S, server public key */ 104 /* Q_S, server public key */
84 server_pubkey = packet_get_string(&slen); 105 /* signed H */
85 if (slen != CURVE25519_SIZE) 106 if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 ||
86 fatal("Incorrect size for server Curve25519 pubkey: %d", slen); 107 (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
108 (r = sshpkt_get_end(ssh)) != 0)
109 goto out;
110 if (pklen != CURVE25519_SIZE) {
111 r = SSH_ERR_SIGNATURE_INVALID;
112 goto out;
113 }
87 114
88#ifdef DEBUG_KEXECDH 115#ifdef DEBUG_KEXECDH
89 dump_digest("server public key:", server_pubkey, CURVE25519_SIZE); 116 dump_digest("server public key:", server_pubkey, CURVE25519_SIZE);
90#endif 117#endif
91 118
92 /* signed H */ 119 if ((shared_secret = sshbuf_new()) == NULL) {
93 signature = packet_get_string(&slen); 120 r = SSH_ERR_ALLOC_FAIL;
94 packet_check_eom(); 121 goto out;
95 122 }
96 buffer_init(&shared_secret); 123 if ((r = kexc25519_shared_key(kex->c25519_client_key, server_pubkey,
97 kexc25519_shared_key(client_key, server_pubkey, &shared_secret); 124 shared_secret)) < 0)
125 goto out;
98 126
99 /* calc and verify H */ 127 /* calc and verify H */
100 kex_c25519_hash( 128 hashlen = sizeof(hash);
129 if ((r = kex_c25519_hash(
101 kex->hash_alg, 130 kex->hash_alg,
102 kex->client_version_string, 131 kex->client_version_string,
103 kex->server_version_string, 132 kex->server_version_string,
104 buffer_ptr(kex->my), buffer_len(kex->my), 133 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
105 buffer_ptr(kex->peer), buffer_len(kex->peer), 134 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
106 server_host_key_blob, sbloblen, 135 server_host_key_blob, sbloblen,
107 client_pubkey, 136 kex->c25519_client_pubkey,
108 server_pubkey, 137 server_pubkey,
109 buffer_ptr(&shared_secret), buffer_len(&shared_secret), 138 sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
110 &hash, &hashlen 139 hash, &hashlen)) < 0)
111 ); 140 goto out;
112 free(server_host_key_blob); 141
113 free(server_pubkey); 142 if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
114 if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) 143 ssh->compat)) != 0)
115 fatal("key_verify failed for server_host_key"); 144 goto out;
116 key_free(server_host_key);
117 free(signature);
118 145
119 /* save session id */ 146 /* save session id */
120 if (kex->session_id == NULL) { 147 if (kex->session_id == NULL) {
121 kex->session_id_len = hashlen; 148 kex->session_id_len = hashlen;
122 kex->session_id = xmalloc(kex->session_id_len); 149 kex->session_id = malloc(kex->session_id_len);
150 if (kex->session_id == NULL) {
151 r = SSH_ERR_ALLOC_FAIL;
152 goto out;
153 }
123 memcpy(kex->session_id, hash, kex->session_id_len); 154 memcpy(kex->session_id, hash, kex->session_id_len);
124 } 155 }
125 kex_derive_keys(kex, hash, hashlen, 156
126 buffer_ptr(&shared_secret), buffer_len(&shared_secret)); 157 if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
127 buffer_free(&shared_secret); 158 r = kex_send_newkeys(ssh);
128 kex_finish(kex); 159out:
160 explicit_bzero(hash, sizeof(hash));
161 explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
162 free(server_host_key_blob);
163 free(server_pubkey);
164 free(signature);
165 sshkey_free(server_host_key);
166 sshbuf_free(shared_secret);
167 return r;
129} 168}
diff --git a/kexc25519s.c b/kexc25519s.c
index ba6f546f4..912b0afb1 100644
--- a/kexc25519s.c
+++ b/kexc25519s.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexc25519s.c,v 1.5 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: kexc25519s.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -30,97 +30,128 @@
30#include <string.h> 30#include <string.h>
31#include <signal.h> 31#include <signal.h>
32 32
33#include "xmalloc.h" 33#include "sshkey.h"
34#include "buffer.h"
35#include "key.h"
36#include "cipher.h" 34#include "cipher.h"
35#include "digest.h"
37#include "kex.h" 36#include "kex.h"
38#include "log.h" 37#include "log.h"
39#include "packet.h" 38#include "packet.h"
40#include "ssh2.h" 39#include "ssh2.h"
40#include "sshbuf.h"
41#include "ssherr.h"
41 42
42void 43static int input_kex_c25519_init(int, u_int32_t, void *);
43kexc25519_server(Kex *kex) 44
45int
46kexc25519_server(struct ssh *ssh)
47{
48 debug("expecting SSH2_MSG_KEX_ECDH_INIT");
49 ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_c25519_init);
50 return 0;
51}
52
53static int
54input_kex_c25519_init(int type, u_int32_t seq, void *ctxt)
44{ 55{
45 Key *server_host_private, *server_host_public; 56 struct ssh *ssh = ctxt;
57 struct kex *kex = ssh->kex;
58 struct sshkey *server_host_private, *server_host_public;
59 struct sshbuf *shared_secret = NULL;
46 u_char *server_host_key_blob = NULL, *signature = NULL; 60 u_char *server_host_key_blob = NULL, *signature = NULL;
47 u_char server_key[CURVE25519_SIZE]; 61 u_char server_key[CURVE25519_SIZE];
48 u_char *client_pubkey = NULL; 62 u_char *client_pubkey = NULL;
49 u_char server_pubkey[CURVE25519_SIZE]; 63 u_char server_pubkey[CURVE25519_SIZE];
50 u_char *hash; 64 u_char hash[SSH_DIGEST_MAX_LENGTH];
51 u_int slen, sbloblen, hashlen; 65 size_t slen, pklen, sbloblen, hashlen;
52 Buffer shared_secret; 66 int r;
53 67
54 /* generate private key */ 68 /* generate private key */
55 kexc25519_keygen(server_key, server_pubkey); 69 kexc25519_keygen(server_key, server_pubkey);
56#ifdef DEBUG_KEXECDH 70#ifdef DEBUG_KEXECDH
57 dump_digest("server private key:", server_key, sizeof(server_key)); 71 dump_digest("server private key:", server_key, sizeof(server_key));
58#endif 72#endif
59
60 if (kex->load_host_public_key == NULL || 73 if (kex->load_host_public_key == NULL ||
61 kex->load_host_private_key == NULL) 74 kex->load_host_private_key == NULL) {
62 fatal("Cannot load hostkey"); 75 r = SSH_ERR_INVALID_ARGUMENT;
63 server_host_public = kex->load_host_public_key(kex->hostkey_type); 76 goto out;
64 if (server_host_public == NULL) 77 }
65 fatal("Unsupported hostkey type %d", kex->hostkey_type); 78 if ((server_host_public = kex->load_host_public_key(kex->hostkey_type,
66 server_host_private = kex->load_host_private_key(kex->hostkey_type); 79 ssh)) == NULL ||
67 80 (server_host_private = kex->load_host_private_key(kex->hostkey_type,
68 debug("expecting SSH2_MSG_KEX_ECDH_INIT"); 81 ssh)) == NULL) {
69 packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); 82 r = SSH_ERR_NO_HOSTKEY_LOADED;
70 client_pubkey = packet_get_string(&slen); 83 goto out;
71 if (slen != CURVE25519_SIZE) 84 }
72 fatal("Incorrect size for server Curve25519 pubkey: %d", slen);
73 packet_check_eom();
74 85
86 if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 ||
87 (r = sshpkt_get_end(ssh)) != 0)
88 goto out;
89 if (pklen != CURVE25519_SIZE) {
90 r = SSH_ERR_SIGNATURE_INVALID;
91 goto out;
92 }
75#ifdef DEBUG_KEXECDH 93#ifdef DEBUG_KEXECDH
76 dump_digest("client public key:", client_pubkey, CURVE25519_SIZE); 94 dump_digest("client public key:", client_pubkey, CURVE25519_SIZE);
77#endif 95#endif
78 96
79 buffer_init(&shared_secret); 97 if ((shared_secret = sshbuf_new()) == NULL) {
80 kexc25519_shared_key(server_key, client_pubkey, &shared_secret); 98 r = SSH_ERR_ALLOC_FAIL;
99 goto out;
100 }
101 if ((r = kexc25519_shared_key(server_key, client_pubkey,
102 shared_secret)) < 0)
103 goto out;
81 104
82 /* calc H */ 105 /* calc H */
83 key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); 106 if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
84 kex_c25519_hash( 107 &sbloblen)) != 0)
108 goto out;
109 hashlen = sizeof(hash);
110 if ((r = kex_c25519_hash(
85 kex->hash_alg, 111 kex->hash_alg,
86 kex->client_version_string, 112 kex->client_version_string,
87 kex->server_version_string, 113 kex->server_version_string,
88 buffer_ptr(kex->peer), buffer_len(kex->peer), 114 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
89 buffer_ptr(kex->my), buffer_len(kex->my), 115 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
90 server_host_key_blob, sbloblen, 116 server_host_key_blob, sbloblen,
91 client_pubkey, 117 client_pubkey,
92 server_pubkey, 118 server_pubkey,
93 buffer_ptr(&shared_secret), buffer_len(&shared_secret), 119 sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
94 &hash, &hashlen 120 hash, &hashlen)) < 0)
95 ); 121 goto out;
96 122
97 /* save session id := H */ 123 /* save session id := H */
98 if (kex->session_id == NULL) { 124 if (kex->session_id == NULL) {
99 kex->session_id_len = hashlen; 125 kex->session_id_len = hashlen;
100 kex->session_id = xmalloc(kex->session_id_len); 126 kex->session_id = malloc(kex->session_id_len);
127 if (kex->session_id == NULL) {
128 r = SSH_ERR_ALLOC_FAIL;
129 goto out;
130 }
101 memcpy(kex->session_id, hash, kex->session_id_len); 131 memcpy(kex->session_id, hash, kex->session_id_len);
102 } 132 }
103 133
104 /* sign H */ 134 /* sign H */
105 kex->sign(server_host_private, server_host_public, &signature, &slen, 135 if ((r = kex->sign(server_host_private, server_host_public,
106 hash, hashlen); 136 &signature, &slen, hash, hashlen, ssh->compat)) < 0)
107 137 goto out;
108 /* destroy_sensitive_data(); */
109 138
110 /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ 139 /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
111 packet_start(SSH2_MSG_KEX_ECDH_REPLY); 140 if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
112 packet_put_string(server_host_key_blob, sbloblen); 141 (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
113 packet_put_string(server_pubkey, sizeof(server_pubkey)); 142 (r = sshpkt_put_string(ssh, server_pubkey, sizeof(server_pubkey))) != 0 ||
114 packet_put_string(signature, slen); 143 (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
115 packet_send(); 144 (r = sshpkt_send(ssh)) != 0)
116 145 goto out;
117 free(signature); 146
147 if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
148 r = kex_send_newkeys(ssh);
149out:
150 explicit_bzero(hash, sizeof(hash));
151 explicit_bzero(server_key, sizeof(server_key));
118 free(server_host_key_blob); 152 free(server_host_key_blob);
119 /* have keys, free server key */ 153 free(signature);
120 free(client_pubkey); 154 free(client_pubkey);
121 155 sshbuf_free(shared_secret);
122 kex_derive_keys(kex, hash, hashlen, 156 return r;
123 buffer_ptr(&shared_secret), buffer_len(&shared_secret));
124 buffer_free(&shared_secret);
125 kex_finish(kex);
126} 157}
diff --git a/kexdh.c b/kexdh.c
index 2c1dfb6f5..feea6697d 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexdh.c,v 1.24 2014/01/09 23:20:00 djm Exp $ */ 1/* $OpenBSD: kexdh.c,v 1.25 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -33,58 +33,61 @@
33 33
34#include <openssl/evp.h> 34#include <openssl/evp.h>
35 35
36#include "buffer.h"
37#include "ssh2.h" 36#include "ssh2.h"
38#include "key.h" 37#include "sshkey.h"
39#include "cipher.h" 38#include "cipher.h"
40#include "kex.h" 39#include "kex.h"
40#include "ssherr.h"
41#include "sshbuf.h"
41#include "digest.h" 42#include "digest.h"
42#include "log.h"
43 43
44void 44int
45kex_dh_hash( 45kex_dh_hash(
46 char *client_version_string, 46 const char *client_version_string,
47 char *server_version_string, 47 const char *server_version_string,
48 char *ckexinit, int ckexinitlen, 48 const u_char *ckexinit, size_t ckexinitlen,
49 char *skexinit, int skexinitlen, 49 const u_char *skexinit, size_t skexinitlen,
50 u_char *serverhostkeyblob, int sbloblen, 50 const u_char *serverhostkeyblob, size_t sbloblen,
51 BIGNUM *client_dh_pub, 51 const BIGNUM *client_dh_pub,
52 BIGNUM *server_dh_pub, 52 const BIGNUM *server_dh_pub,
53 BIGNUM *shared_secret, 53 const BIGNUM *shared_secret,
54 u_char **hash, u_int *hashlen) 54 u_char *hash, size_t *hashlen)
55{ 55{
56 Buffer b; 56 struct sshbuf *b;
57 static u_char digest[SSH_DIGEST_MAX_LENGTH]; 57 int r;
58
59 buffer_init(&b);
60 buffer_put_cstring(&b, client_version_string);
61 buffer_put_cstring(&b, server_version_string);
62
63 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
64 buffer_put_int(&b, ckexinitlen+1);
65 buffer_put_char(&b, SSH2_MSG_KEXINIT);
66 buffer_append(&b, ckexinit, ckexinitlen);
67 buffer_put_int(&b, skexinitlen+1);
68 buffer_put_char(&b, SSH2_MSG_KEXINIT);
69 buffer_append(&b, skexinit, skexinitlen);
70
71 buffer_put_string(&b, serverhostkeyblob, sbloblen);
72 buffer_put_bignum2(&b, client_dh_pub);
73 buffer_put_bignum2(&b, server_dh_pub);
74 buffer_put_bignum2(&b, shared_secret);
75 58
59 if (*hashlen < ssh_digest_bytes(SSH_DIGEST_SHA1))
60 return SSH_ERR_INVALID_ARGUMENT;
61 if ((b = sshbuf_new()) == NULL)
62 return SSH_ERR_ALLOC_FAIL;
63 if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
64 (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
65 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
66 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
67 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
68 (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
69 (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
70 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
71 (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
72 (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
73 (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 ||
74 (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 ||
75 (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
76 sshbuf_free(b);
77 return r;
78 }
76#ifdef DEBUG_KEX 79#ifdef DEBUG_KEX
77 buffer_dump(&b); 80 sshbuf_dump(b, stderr);
78#endif 81#endif
79 if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, digest, sizeof(digest)) != 0) 82 if (ssh_digest_buffer(SSH_DIGEST_SHA1, b, hash, *hashlen) != 0) {
80 fatal("%s: ssh_digest_buffer failed", __func__); 83 sshbuf_free(b);
81 84 return SSH_ERR_LIBCRYPTO_ERROR;
82 buffer_free(&b); 85 }
83 86 sshbuf_free(b);
87 *hashlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
84#ifdef DEBUG_KEX 88#ifdef DEBUG_KEX
85 dump_digest("hash", digest, ssh_digest_bytes(SSH_DIGEST_SHA1)); 89 dump_digest("hash", hash, *hashlen);
86#endif 90#endif
87 *hash = digest; 91 return 0;
88 *hashlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
89} 92}
90#endif /* WITH_OPENSSL */ 93#endif /* WITH_OPENSSL */
diff --git a/kexdhc.c b/kexdhc.c
index cd12df33d..52b752295 100644
--- a/kexdhc.c
+++ b/kexdhc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexdhc.c,v 1.16 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: kexdhc.c,v 1.17 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -36,129 +36,175 @@
36#include <string.h> 36#include <string.h>
37#include <signal.h> 37#include <signal.h>
38 38
39#include "xmalloc.h" 39#include "sshkey.h"
40#include "buffer.h"
41#include "key.h"
42#include "cipher.h" 40#include "cipher.h"
41#include "digest.h"
43#include "kex.h" 42#include "kex.h"
44#include "log.h" 43#include "log.h"
45#include "packet.h" 44#include "packet.h"
46#include "dh.h" 45#include "dh.h"
47#include "ssh2.h" 46#include "ssh2.h"
47#include "dispatch.h"
48#include "compat.h"
49#include "ssherr.h"
50#include "sshbuf.h"
48 51
49void 52static int input_kex_dh(int, u_int32_t, void *);
50kexdh_client(Kex *kex) 53
54int
55kexdh_client(struct ssh *ssh)
51{ 56{
52 BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; 57 struct kex *kex = ssh->kex;
53 DH *dh; 58 int r;
54 Key *server_host_key;
55 u_char *server_host_key_blob = NULL, *signature = NULL;
56 u_char *kbuf, *hash;
57 u_int klen, slen, sbloblen, hashlen;
58 int kout;
59 59
60 /* generate and send 'e', client DH public key */ 60 /* generate and send 'e', client DH public key */
61 switch (kex->kex_type) { 61 switch (kex->kex_type) {
62 case KEX_DH_GRP1_SHA1: 62 case KEX_DH_GRP1_SHA1:
63 dh = dh_new_group1(); 63 kex->dh = dh_new_group1();
64 break; 64 break;
65 case KEX_DH_GRP14_SHA1: 65 case KEX_DH_GRP14_SHA1:
66 dh = dh_new_group14(); 66 kex->dh = dh_new_group14();
67 break; 67 break;
68 default: 68 default:
69 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); 69 r = SSH_ERR_INVALID_ARGUMENT;
70 goto out;
71 }
72 if (kex->dh == NULL) {
73 r = SSH_ERR_ALLOC_FAIL;
74 goto out;
70 } 75 }
71 dh_gen_key(dh, kex->we_need * 8);
72 packet_start(SSH2_MSG_KEXDH_INIT);
73 packet_put_bignum2(dh->pub_key);
74 packet_send();
75
76 debug("sending SSH2_MSG_KEXDH_INIT"); 76 debug("sending SSH2_MSG_KEXDH_INIT");
77 if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 ||
78 (r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 ||
79 (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 ||
80 (r = sshpkt_send(ssh)) != 0)
81 goto out;
77#ifdef DEBUG_KEXDH 82#ifdef DEBUG_KEXDH
78 DHparams_print_fp(stderr, dh); 83 DHparams_print_fp(stderr, kex->dh);
79 fprintf(stderr, "pub= "); 84 fprintf(stderr, "pub= ");
80 BN_print_fp(stderr, dh->pub_key); 85 BN_print_fp(stderr, kex->dh->pub_key);
81 fprintf(stderr, "\n"); 86 fprintf(stderr, "\n");
82#endif 87#endif
83
84 debug("expecting SSH2_MSG_KEXDH_REPLY"); 88 debug("expecting SSH2_MSG_KEXDH_REPLY");
85 packet_read_expect(SSH2_MSG_KEXDH_REPLY); 89 ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh);
90 r = 0;
91 out:
92 return r;
93}
86 94
95static int
96input_kex_dh(int type, u_int32_t seq, void *ctxt)
97{
98 struct ssh *ssh = ctxt;
99 struct kex *kex = ssh->kex;
100 BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
101 struct sshkey *server_host_key = NULL;
102 u_char *kbuf = NULL, *server_host_key_blob = NULL, *signature = NULL;
103 u_char hash[SSH_DIGEST_MAX_LENGTH];
104 size_t klen = 0, slen, sbloblen, hashlen;
105 int kout, r;
106
107 if (kex->verify_host_key == NULL) {
108 r = SSH_ERR_INVALID_ARGUMENT;
109 goto out;
110 }
87 /* key, cert */ 111 /* key, cert */
88 server_host_key_blob = packet_get_string(&sbloblen); 112 if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
89 server_host_key = key_from_blob(server_host_key_blob, sbloblen); 113 &sbloblen)) != 0 ||
90 if (server_host_key == NULL) 114 (r = sshkey_from_blob(server_host_key_blob, sbloblen,
91 fatal("cannot decode server_host_key_blob"); 115 &server_host_key)) != 0)
92 if (server_host_key->type != kex->hostkey_type) 116 goto out;
93 fatal("type mismatch for decoded server_host_key_blob"); 117 if (server_host_key->type != kex->hostkey_type) {
94 if (kex->verify_host_key == NULL) 118 r = SSH_ERR_KEY_TYPE_MISMATCH;
95 fatal("cannot verify server_host_key"); 119 goto out;
96 if (kex->verify_host_key(server_host_key) == -1) 120 }
97 fatal("server_host_key verification failed"); 121 if (kex->verify_host_key(server_host_key, ssh) == -1) {
98 122 r = SSH_ERR_SIGNATURE_INVALID;
123 goto out;
124 }
99 /* DH parameter f, server public DH key */ 125 /* DH parameter f, server public DH key */
100 if ((dh_server_pub = BN_new()) == NULL) 126 if ((dh_server_pub = BN_new()) == NULL) {
101 fatal("dh_server_pub == NULL"); 127 r = SSH_ERR_ALLOC_FAIL;
102 packet_get_bignum2(dh_server_pub); 128 goto out;
103 129 }
130 /* signed H */
131 if ((r = sshpkt_get_bignum2(ssh, dh_server_pub)) != 0 ||
132 (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
133 (r = sshpkt_get_end(ssh)) != 0)
134 goto out;
104#ifdef DEBUG_KEXDH 135#ifdef DEBUG_KEXDH
105 fprintf(stderr, "dh_server_pub= "); 136 fprintf(stderr, "dh_server_pub= ");
106 BN_print_fp(stderr, dh_server_pub); 137 BN_print_fp(stderr, dh_server_pub);
107 fprintf(stderr, "\n"); 138 fprintf(stderr, "\n");
108 debug("bits %d", BN_num_bits(dh_server_pub)); 139 debug("bits %d", BN_num_bits(dh_server_pub));
109#endif 140#endif
141 if (!dh_pub_is_valid(kex->dh, dh_server_pub)) {
142 sshpkt_disconnect(ssh, "bad server public DH value");
143 r = SSH_ERR_MESSAGE_INCOMPLETE;
144 goto out;
145 }
110 146
111 /* signed H */ 147 klen = DH_size(kex->dh);
112 signature = packet_get_string(&slen); 148 if ((kbuf = malloc(klen)) == NULL ||
113 packet_check_eom(); 149 (shared_secret = BN_new()) == NULL) {
114 150 r = SSH_ERR_ALLOC_FAIL;
115 if (!dh_pub_is_valid(dh, dh_server_pub)) 151 goto out;
116 packet_disconnect("bad server public DH value"); 152 }
117 153 if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 ||
118 klen = DH_size(dh); 154 BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
119 kbuf = xmalloc(klen); 155 r = SSH_ERR_LIBCRYPTO_ERROR;
120 if ((kout = DH_compute_key(kbuf, dh_server_pub, dh)) < 0) 156 goto out;
121 fatal("DH_compute_key: failed"); 157 }
122#ifdef DEBUG_KEXDH 158#ifdef DEBUG_KEXDH
123 dump_digest("shared secret", kbuf, kout); 159 dump_digest("shared secret", kbuf, kout);
124#endif 160#endif
125 if ((shared_secret = BN_new()) == NULL)
126 fatal("kexdh_client: BN_new failed");
127 if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
128 fatal("kexdh_client: BN_bin2bn failed");
129 explicit_bzero(kbuf, klen);
130 free(kbuf);
131 161
132 /* calc and verify H */ 162 /* calc and verify H */
133 kex_dh_hash( 163 hashlen = sizeof(hash);
164 if ((r = kex_dh_hash(
134 kex->client_version_string, 165 kex->client_version_string,
135 kex->server_version_string, 166 kex->server_version_string,
136 buffer_ptr(kex->my), buffer_len(kex->my), 167 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
137 buffer_ptr(kex->peer), buffer_len(kex->peer), 168 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
138 server_host_key_blob, sbloblen, 169 server_host_key_blob, sbloblen,
139 dh->pub_key, 170 kex->dh->pub_key,
140 dh_server_pub, 171 dh_server_pub,
141 shared_secret, 172 shared_secret,
142 &hash, &hashlen 173 hash, &hashlen)) != 0)
143 ); 174 goto out;
144 free(server_host_key_blob);
145 BN_clear_free(dh_server_pub);
146 DH_free(dh);
147 175
148 if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) 176 if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
149 fatal("key_verify failed for server_host_key"); 177 ssh->compat)) != 0)
150 key_free(server_host_key); 178 goto out;
151 free(signature);
152 179
153 /* save session id */ 180 /* save session id */
154 if (kex->session_id == NULL) { 181 if (kex->session_id == NULL) {
155 kex->session_id_len = hashlen; 182 kex->session_id_len = hashlen;
156 kex->session_id = xmalloc(kex->session_id_len); 183 kex->session_id = malloc(kex->session_id_len);
184 if (kex->session_id == NULL) {
185 r = SSH_ERR_ALLOC_FAIL;
186 goto out;
187 }
157 memcpy(kex->session_id, hash, kex->session_id_len); 188 memcpy(kex->session_id, hash, kex->session_id_len);
158 } 189 }
159 190
160 kex_derive_keys_bn(kex, hash, hashlen, shared_secret); 191 if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
161 BN_clear_free(shared_secret); 192 r = kex_send_newkeys(ssh);
162 kex_finish(kex); 193 out:
194 explicit_bzero(hash, sizeof(hash));
195 DH_free(kex->dh);
196 kex->dh = NULL;
197 if (dh_server_pub)
198 BN_clear_free(dh_server_pub);
199 if (kbuf) {
200 explicit_bzero(kbuf, klen);
201 free(kbuf);
202 }
203 if (shared_secret)
204 BN_clear_free(shared_secret);
205 sshkey_free(server_host_key);
206 free(server_host_key_blob);
207 free(signature);
208 return r;
163} 209}
164#endif /* WITH_OPENSSL */ 210#endif /* WITH_OPENSSL */
diff --git a/kexdhs.c b/kexdhs.c
index 34a215f8c..182657ac9 100644
--- a/kexdhs.c
+++ b/kexdhs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexdhs.c,v 1.19 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: kexdhs.c,v 1.20 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -35,55 +35,88 @@
35 35
36#include <openssl/dh.h> 36#include <openssl/dh.h>
37 37
38#include "xmalloc.h" 38#include "sshkey.h"
39#include "buffer.h"
40#include "key.h"
41#include "cipher.h" 39#include "cipher.h"
40#include "digest.h"
42#include "kex.h" 41#include "kex.h"
43#include "log.h" 42#include "log.h"
44#include "packet.h" 43#include "packet.h"
45#include "dh.h" 44#include "dh.h"
46#include "ssh2.h" 45#include "ssh2.h"
47 46
48void 47#include "dispatch.h"
49kexdh_server(Kex *kex) 48#include "compat.h"
49#include "ssherr.h"
50#include "sshbuf.h"
51
52static int input_kex_dh_init(int, u_int32_t, void *);
53
54int
55kexdh_server(struct ssh *ssh)
50{ 56{
51 BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; 57 struct kex *kex = ssh->kex;
52 DH *dh; 58 int r;
53 Key *server_host_public, *server_host_private;
54 u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
55 u_int sbloblen, klen, hashlen, slen;
56 int kout;
57 59
58 /* generate server DH public key */ 60 /* generate server DH public key */
59 switch (kex->kex_type) { 61 switch (kex->kex_type) {
60 case KEX_DH_GRP1_SHA1: 62 case KEX_DH_GRP1_SHA1:
61 dh = dh_new_group1(); 63 kex->dh = dh_new_group1();
62 break; 64 break;
63 case KEX_DH_GRP14_SHA1: 65 case KEX_DH_GRP14_SHA1:
64 dh = dh_new_group14(); 66 kex->dh = dh_new_group14();
65 break; 67 break;
66 default: 68 default:
67 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); 69 r = SSH_ERR_INVALID_ARGUMENT;
70 goto out;
68 } 71 }
69 dh_gen_key(dh, kex->we_need * 8); 72 if (kex->dh == NULL) {
73 r = SSH_ERR_ALLOC_FAIL;
74 goto out;
75 }
76 if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
77 goto out;
70 78
71 debug("expecting SSH2_MSG_KEXDH_INIT"); 79 debug("expecting SSH2_MSG_KEXDH_INIT");
72 packet_read_expect(SSH2_MSG_KEXDH_INIT); 80 ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init);
81 r = 0;
82 out:
83 return r;
84}
85
86int
87input_kex_dh_init(int type, u_int32_t seq, void *ctxt)
88{
89 struct ssh *ssh = ctxt;
90 struct kex *kex = ssh->kex;
91 BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
92 struct sshkey *server_host_public, *server_host_private;
93 u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
94 u_char hash[SSH_DIGEST_MAX_LENGTH];
95 size_t sbloblen, slen;
96 size_t klen = 0, hashlen;
97 int kout, r;
73 98
74 if (kex->load_host_public_key == NULL || 99 if (kex->load_host_public_key == NULL ||
75 kex->load_host_private_key == NULL) 100 kex->load_host_private_key == NULL) {
76 fatal("Cannot load hostkey"); 101 r = SSH_ERR_INVALID_ARGUMENT;
77 server_host_public = kex->load_host_public_key(kex->hostkey_type); 102 goto out;
78 if (server_host_public == NULL) 103 }
79 fatal("Unsupported hostkey type %d", kex->hostkey_type); 104 if ((server_host_public = kex->load_host_public_key(kex->hostkey_type,
80 server_host_private = kex->load_host_private_key(kex->hostkey_type); 105 ssh)) == NULL ||
106 (server_host_private = kex->load_host_private_key(kex->hostkey_type,
107 ssh)) == NULL) {
108 r = SSH_ERR_NO_HOSTKEY_LOADED;
109 goto out;
110 }
81 111
82 /* key, cert */ 112 /* key, cert */
83 if ((dh_client_pub = BN_new()) == NULL) 113 if ((dh_client_pub = BN_new()) == NULL) {
84 fatal("dh_client_pub == NULL"); 114 r = SSH_ERR_ALLOC_FAIL;
85 packet_get_bignum2(dh_client_pub); 115 goto out;
86 packet_check_eom(); 116 }
117 if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 ||
118 (r = sshpkt_get_end(ssh)) != 0)
119 goto out;
87 120
88#ifdef DEBUG_KEXDH 121#ifdef DEBUG_KEXDH
89 fprintf(stderr, "dh_client_pub= "); 122 fprintf(stderr, "dh_client_pub= ");
@@ -93,71 +126,90 @@ kexdh_server(Kex *kex)
93#endif 126#endif
94 127
95#ifdef DEBUG_KEXDH 128#ifdef DEBUG_KEXDH
96 DHparams_print_fp(stderr, dh); 129 DHparams_print_fp(stderr, kex->dh);
97 fprintf(stderr, "pub= "); 130 fprintf(stderr, "pub= ");
98 BN_print_fp(stderr, dh->pub_key); 131 BN_print_fp(stderr, kex->dh->pub_key);
99 fprintf(stderr, "\n"); 132 fprintf(stderr, "\n");
100#endif 133#endif
101 if (!dh_pub_is_valid(dh, dh_client_pub)) 134 if (!dh_pub_is_valid(kex->dh, dh_client_pub)) {
102 packet_disconnect("bad client public DH value"); 135 sshpkt_disconnect(ssh, "bad client public DH value");
136 r = SSH_ERR_MESSAGE_INCOMPLETE;
137 goto out;
138 }
103 139
104 klen = DH_size(dh); 140 klen = DH_size(kex->dh);
105 kbuf = xmalloc(klen); 141 if ((kbuf = malloc(klen)) == NULL ||
106 if ((kout = DH_compute_key(kbuf, dh_client_pub, dh)) < 0) 142 (shared_secret = BN_new()) == NULL) {
107 fatal("DH_compute_key: failed"); 143 r = SSH_ERR_ALLOC_FAIL;
144 goto out;
145 }
146 if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 ||
147 BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
148 r = SSH_ERR_LIBCRYPTO_ERROR;
149 goto out;
150 }
108#ifdef DEBUG_KEXDH 151#ifdef DEBUG_KEXDH
109 dump_digest("shared secret", kbuf, kout); 152 dump_digest("shared secret", kbuf, kout);
110#endif 153#endif
111 if ((shared_secret = BN_new()) == NULL) 154 if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
112 fatal("kexdh_server: BN_new failed"); 155 &sbloblen)) != 0)
113 if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) 156 goto out;
114 fatal("kexdh_server: BN_bin2bn failed");
115 explicit_bzero(kbuf, klen);
116 free(kbuf);
117
118 key_to_blob(server_host_public, &server_host_key_blob, &sbloblen);
119
120 /* calc H */ 157 /* calc H */
121 kex_dh_hash( 158 hashlen = sizeof(hash);
159 if ((r = kex_dh_hash(
122 kex->client_version_string, 160 kex->client_version_string,
123 kex->server_version_string, 161 kex->server_version_string,
124 buffer_ptr(kex->peer), buffer_len(kex->peer), 162 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
125 buffer_ptr(kex->my), buffer_len(kex->my), 163 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
126 server_host_key_blob, sbloblen, 164 server_host_key_blob, sbloblen,
127 dh_client_pub, 165 dh_client_pub,
128 dh->pub_key, 166 kex->dh->pub_key,
129 shared_secret, 167 shared_secret,
130 &hash, &hashlen 168 hash, &hashlen)) != 0)
131 ); 169 goto out;
132 BN_clear_free(dh_client_pub);
133 170
134 /* save session id := H */ 171 /* save session id := H */
135 if (kex->session_id == NULL) { 172 if (kex->session_id == NULL) {
136 kex->session_id_len = hashlen; 173 kex->session_id_len = hashlen;
137 kex->session_id = xmalloc(kex->session_id_len); 174 kex->session_id = malloc(kex->session_id_len);
175 if (kex->session_id == NULL) {
176 r = SSH_ERR_ALLOC_FAIL;
177 goto out;
178 }
138 memcpy(kex->session_id, hash, kex->session_id_len); 179 memcpy(kex->session_id, hash, kex->session_id_len);
139 } 180 }
140 181
141 /* sign H */ 182 /* sign H */
142 kex->sign(server_host_private, server_host_public, &signature, &slen, 183 if ((r = kex->sign(server_host_private, server_host_public,
143 hash, hashlen); 184 &signature, &slen, hash, hashlen, ssh->compat)) < 0)
185 goto out;
144 186
145 /* destroy_sensitive_data(); */ 187 /* destroy_sensitive_data(); */
146 188
147 /* send server hostkey, DH pubkey 'f' and singed H */ 189 /* send server hostkey, DH pubkey 'f' and singed H */
148 packet_start(SSH2_MSG_KEXDH_REPLY); 190 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 ||
149 packet_put_string(server_host_key_blob, sbloblen); 191 (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
150 packet_put_bignum2(dh->pub_key); /* f */ 192 (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */
151 packet_put_string(signature, slen); 193 (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
152 packet_send(); 194 (r = sshpkt_send(ssh)) != 0)
153 195 goto out;
154 free(signature); 196
197 if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
198 r = kex_send_newkeys(ssh);
199 out:
200 explicit_bzero(hash, sizeof(hash));
201 DH_free(kex->dh);
202 kex->dh = NULL;
203 if (dh_client_pub)
204 BN_clear_free(dh_client_pub);
205 if (kbuf) {
206 explicit_bzero(kbuf, klen);
207 free(kbuf);
208 }
209 if (shared_secret)
210 BN_clear_free(shared_secret);
155 free(server_host_key_blob); 211 free(server_host_key_blob);
156 /* have keys, free DH */ 212 free(signature);
157 DH_free(dh); 213 return r;
158
159 kex_derive_keys_bn(kex, hash, hashlen, shared_secret);
160 BN_clear_free(shared_secret);
161 kex_finish(kex);
162} 214}
163#endif /* WITH_OPENSSL */ 215#endif /* WITH_OPENSSL */
diff --git a/kexecdh.c b/kexecdh.c
index 3115d13d1..2a4fec6b1 100644
--- a/kexecdh.c
+++ b/kexecdh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexecdh.c,v 1.5 2014/01/09 23:20:00 djm Exp $ */ 1/* $OpenBSD: kexecdh.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -38,60 +38,63 @@
38#include <openssl/ec.h> 38#include <openssl/ec.h>
39#include <openssl/ecdh.h> 39#include <openssl/ecdh.h>
40 40
41#include "buffer.h"
42#include "ssh2.h" 41#include "ssh2.h"
43#include "key.h" 42#include "sshkey.h"
44#include "cipher.h" 43#include "cipher.h"
45#include "kex.h" 44#include "kex.h"
46#include "log.h" 45#include "sshbuf.h"
47#include "digest.h" 46#include "digest.h"
47#include "ssherr.h"
48 48
49void 49int
50kex_ecdh_hash( 50kex_ecdh_hash(
51 int hash_alg, 51 int hash_alg,
52 const EC_GROUP *ec_group, 52 const EC_GROUP *ec_group,
53 char *client_version_string, 53 const char *client_version_string,
54 char *server_version_string, 54 const char *server_version_string,
55 char *ckexinit, int ckexinitlen, 55 const u_char *ckexinit, size_t ckexinitlen,
56 char *skexinit, int skexinitlen, 56 const u_char *skexinit, size_t skexinitlen,
57 u_char *serverhostkeyblob, int sbloblen, 57 const u_char *serverhostkeyblob, size_t sbloblen,
58 const EC_POINT *client_dh_pub, 58 const EC_POINT *client_dh_pub,
59 const EC_POINT *server_dh_pub, 59 const EC_POINT *server_dh_pub,
60 const BIGNUM *shared_secret, 60 const BIGNUM *shared_secret,
61 u_char **hash, u_int *hashlen) 61 u_char *hash, size_t *hashlen)
62{ 62{
63 Buffer b; 63 struct sshbuf *b;
64 static u_char digest[SSH_DIGEST_MAX_LENGTH]; 64 int r;
65
66 buffer_init(&b);
67 buffer_put_cstring(&b, client_version_string);
68 buffer_put_cstring(&b, server_version_string);
69
70 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
71 buffer_put_int(&b, ckexinitlen+1);
72 buffer_put_char(&b, SSH2_MSG_KEXINIT);
73 buffer_append(&b, ckexinit, ckexinitlen);
74 buffer_put_int(&b, skexinitlen+1);
75 buffer_put_char(&b, SSH2_MSG_KEXINIT);
76 buffer_append(&b, skexinit, skexinitlen);
77
78 buffer_put_string(&b, serverhostkeyblob, sbloblen);
79 buffer_put_ecpoint(&b, ec_group, client_dh_pub);
80 buffer_put_ecpoint(&b, ec_group, server_dh_pub);
81 buffer_put_bignum2(&b, shared_secret);
82 65
66 if (*hashlen < ssh_digest_bytes(hash_alg))
67 return SSH_ERR_INVALID_ARGUMENT;
68 if ((b = sshbuf_new()) == NULL)
69 return SSH_ERR_ALLOC_FAIL;
70 if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
71 (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
72 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
73 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
74 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
75 (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
76 (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
77 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
78 (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
79 (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
80 (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 ||
81 (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 ||
82 (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
83 sshbuf_free(b);
84 return r;
85 }
83#ifdef DEBUG_KEX 86#ifdef DEBUG_KEX
84 buffer_dump(&b); 87 sshbuf_dump(b, stderr);
85#endif 88#endif
86 if (ssh_digest_buffer(hash_alg, &b, digest, sizeof(digest)) != 0) 89 if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
87 fatal("%s: ssh_digest_buffer failed", __func__); 90 sshbuf_free(b);
88 91 return SSH_ERR_LIBCRYPTO_ERROR;
89 buffer_free(&b); 92 }
90 93 sshbuf_free(b);
94 *hashlen = ssh_digest_bytes(hash_alg);
91#ifdef DEBUG_KEX 95#ifdef DEBUG_KEX
92 dump_digest("hash", digest, ssh_digest_bytes(hash_alg)); 96 dump_digest("hash", hash, *hashlen);
93#endif 97#endif
94 *hash = digest; 98 return 0;
95 *hashlen = ssh_digest_bytes(hash_alg);
96} 99}
97#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ 100#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
diff --git a/kexecdhc.c b/kexecdhc.c
index df811c1c8..3f362c5b1 100644
--- a/kexecdhc.c
+++ b/kexecdhc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexecdhc.c,v 1.8 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: kexecdhc.c,v 1.9 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -34,126 +34,193 @@
34#include <string.h> 34#include <string.h>
35#include <signal.h> 35#include <signal.h>
36 36
37#include "xmalloc.h" 37#include <openssl/ecdh.h>
38#include "buffer.h" 38
39#include "key.h" 39#include "sshkey.h"
40#include "cipher.h" 40#include "cipher.h"
41#include "digest.h"
41#include "kex.h" 42#include "kex.h"
42#include "log.h" 43#include "log.h"
43#include "packet.h" 44#include "packet.h"
44#include "dh.h" 45#include "dh.h"
45#include "ssh2.h" 46#include "ssh2.h"
47#include "dispatch.h"
48#include "compat.h"
49#include "ssherr.h"
50#include "sshbuf.h"
46 51
47#include <openssl/ecdh.h> 52static int input_kex_ecdh_reply(int, u_int32_t, void *);
48 53
49void 54int
50kexecdh_client(Kex *kex) 55kexecdh_client(struct ssh *ssh)
51{ 56{
52 EC_KEY *client_key; 57 struct kex *kex = ssh->kex;
53 EC_POINT *server_public; 58 EC_KEY *client_key = NULL;
54 const EC_GROUP *group; 59 const EC_GROUP *group;
55 BIGNUM *shared_secret; 60 const EC_POINT *public_key;
56 Key *server_host_key; 61 int r;
57 u_char *server_host_key_blob = NULL, *signature = NULL;
58 u_char *kbuf, *hash;
59 u_int klen, slen, sbloblen, hashlen;
60 62
61 if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) 63 if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
62 fatal("%s: EC_KEY_new_by_curve_name failed", __func__); 64 r = SSH_ERR_ALLOC_FAIL;
63 if (EC_KEY_generate_key(client_key) != 1) 65 goto out;
64 fatal("%s: EC_KEY_generate_key failed", __func__); 66 }
67 if (EC_KEY_generate_key(client_key) != 1) {
68 r = SSH_ERR_LIBCRYPTO_ERROR;
69 goto out;
70 }
65 group = EC_KEY_get0_group(client_key); 71 group = EC_KEY_get0_group(client_key);
72 public_key = EC_KEY_get0_public_key(client_key);
66 73
67 packet_start(SSH2_MSG_KEX_ECDH_INIT); 74 if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
68 packet_put_ecpoint(group, EC_KEY_get0_public_key(client_key)); 75 (r = sshpkt_put_ec(ssh, public_key, group)) != 0 ||
69 packet_send(); 76 (r = sshpkt_send(ssh)) != 0)
77 goto out;
70 debug("sending SSH2_MSG_KEX_ECDH_INIT"); 78 debug("sending SSH2_MSG_KEX_ECDH_INIT");
71 79
72#ifdef DEBUG_KEXECDH 80#ifdef DEBUG_KEXECDH
73 fputs("client private key:\n", stderr); 81 fputs("client private key:\n", stderr);
74 key_dump_ec_key(client_key); 82 sshkey_dump_ec_key(client_key);
75#endif 83#endif
84 kex->ec_client_key = client_key;
85 kex->ec_group = group;
86 client_key = NULL; /* owned by the kex */
76 87
77 debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); 88 debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
78 packet_read_expect(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 if (client_key)
93 EC_KEY_free(client_key);
94 return r;
95}
96
97static int
98input_kex_ecdh_reply(int type, u_int32_t seq, void *ctxt)
99{
100 struct ssh *ssh = ctxt;
101 struct kex *kex = ssh->kex;
102 const EC_GROUP *group;
103 EC_POINT *server_public = NULL;
104 EC_KEY *client_key;
105 BIGNUM *shared_secret = NULL;
106 struct sshkey *server_host_key = NULL;
107 u_char *server_host_key_blob = NULL, *signature = NULL;
108 u_char *kbuf = NULL;
109 u_char hash[SSH_DIGEST_MAX_LENGTH];
110 size_t slen, sbloblen;
111 size_t klen = 0, hashlen;
112 int r;
113
114 if (kex->verify_host_key == NULL) {
115 r = SSH_ERR_INVALID_ARGUMENT;
116 goto out;
117 }
118 group = kex->ec_group;
119 client_key = kex->ec_client_key;
79 120
80 /* hostkey */ 121 /* hostkey */
81 server_host_key_blob = packet_get_string(&sbloblen); 122 if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
82 server_host_key = key_from_blob(server_host_key_blob, sbloblen); 123 &sbloblen)) != 0 ||
83 if (server_host_key == NULL) 124 (r = sshkey_from_blob(server_host_key_blob, sbloblen,
84 fatal("cannot decode server_host_key_blob"); 125 &server_host_key)) != 0)
85 if (server_host_key->type != kex->hostkey_type) 126 goto out;
86 fatal("type mismatch for decoded server_host_key_blob"); 127 if (server_host_key->type != kex->hostkey_type) {
87 if (kex->verify_host_key == NULL) 128 r = SSH_ERR_KEY_TYPE_MISMATCH;
88 fatal("cannot verify server_host_key"); 129 goto out;
89 if (kex->verify_host_key(server_host_key) == -1) 130 }
90 fatal("server_host_key verification failed"); 131 if (kex->verify_host_key(server_host_key, ssh) == -1) {
132 r = SSH_ERR_SIGNATURE_INVALID;
133 goto out;
134 }
91 135
92 /* Q_S, server public key */ 136 /* Q_S, server public key */
93 if ((server_public = EC_POINT_new(group)) == NULL) 137 /* signed H */
94 fatal("%s: EC_POINT_new failed", __func__); 138 if ((server_public = EC_POINT_new(group)) == NULL) {
95 packet_get_ecpoint(group, server_public); 139 r = SSH_ERR_ALLOC_FAIL;
96 140 goto out;
97 if (key_ec_validate_public(group, server_public) != 0) 141 }
98 fatal("%s: invalid server public key", __func__); 142 if ((r = sshpkt_get_ec(ssh, server_public, group)) != 0 ||
143 (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
144 (r = sshpkt_get_end(ssh)) != 0)
145 goto out;
99 146
100#ifdef DEBUG_KEXECDH 147#ifdef DEBUG_KEXECDH
101 fputs("server public key:\n", stderr); 148 fputs("server public key:\n", stderr);
102 key_dump_ec_point(group, server_public); 149 sshkey_dump_ec_point(group, server_public);
103#endif 150#endif
104 151 if (sshkey_ec_validate_public(group, server_public) != 0) {
105 /* signed H */ 152 sshpkt_disconnect(ssh, "invalid server public key");
106 signature = packet_get_string(&slen); 153 r = SSH_ERR_MESSAGE_INCOMPLETE;
107 packet_check_eom(); 154 goto out;
155 }
108 156
109 klen = (EC_GROUP_get_degree(group) + 7) / 8; 157 klen = (EC_GROUP_get_degree(group) + 7) / 8;
110 kbuf = xmalloc(klen); 158 if ((kbuf = malloc(klen)) == NULL ||
159 (shared_secret = BN_new()) == NULL) {
160 r = SSH_ERR_ALLOC_FAIL;
161 goto out;
162 }
111 if (ECDH_compute_key(kbuf, klen, server_public, 163 if (ECDH_compute_key(kbuf, klen, server_public,
112 client_key, NULL) != (int)klen) 164 client_key, NULL) != (int)klen ||
113 fatal("%s: ECDH_compute_key failed", __func__); 165 BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
166 r = SSH_ERR_LIBCRYPTO_ERROR;
167 goto out;
168 }
114 169
115#ifdef DEBUG_KEXECDH 170#ifdef DEBUG_KEXECDH
116 dump_digest("shared secret", kbuf, klen); 171 dump_digest("shared secret", kbuf, klen);
117#endif 172#endif
118 if ((shared_secret = BN_new()) == NULL)
119 fatal("%s: BN_new failed", __func__);
120 if (BN_bin2bn(kbuf, klen, shared_secret) == NULL)
121 fatal("%s: BN_bin2bn failed", __func__);
122 explicit_bzero(kbuf, klen);
123 free(kbuf);
124
125 /* calc and verify H */ 173 /* calc and verify H */
126 kex_ecdh_hash( 174 hashlen = sizeof(hash);
175 if ((r = kex_ecdh_hash(
127 kex->hash_alg, 176 kex->hash_alg,
128 group, 177 group,
129 kex->client_version_string, 178 kex->client_version_string,
130 kex->server_version_string, 179 kex->server_version_string,
131 buffer_ptr(kex->my), buffer_len(kex->my), 180 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
132 buffer_ptr(kex->peer), buffer_len(kex->peer), 181 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
133 server_host_key_blob, sbloblen, 182 server_host_key_blob, sbloblen,
134 EC_KEY_get0_public_key(client_key), 183 EC_KEY_get0_public_key(client_key),
135 server_public, 184 server_public,
136 shared_secret, 185 shared_secret,
137 &hash, &hashlen 186 hash, &hashlen)) != 0)
138 ); 187 goto out;
139 free(server_host_key_blob);
140 EC_POINT_clear_free(server_public);
141 EC_KEY_free(client_key);
142 188
143 if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) 189 if ((r = sshkey_verify(server_host_key, signature, slen, hash,
144 fatal("key_verify failed for server_host_key"); 190 hashlen, ssh->compat)) != 0)
145 key_free(server_host_key); 191 goto out;
146 free(signature);
147 192
148 /* save session id */ 193 /* save session id */
149 if (kex->session_id == NULL) { 194 if (kex->session_id == NULL) {
150 kex->session_id_len = hashlen; 195 kex->session_id_len = hashlen;
151 kex->session_id = xmalloc(kex->session_id_len); 196 kex->session_id = malloc(kex->session_id_len);
197 if (kex->session_id == NULL) {
198 r = SSH_ERR_ALLOC_FAIL;
199 goto out;
200 }
152 memcpy(kex->session_id, hash, kex->session_id_len); 201 memcpy(kex->session_id, hash, kex->session_id_len);
153 } 202 }
154 203
155 kex_derive_keys_bn(kex, hash, hashlen, shared_secret); 204 if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
156 BN_clear_free(shared_secret); 205 r = kex_send_newkeys(ssh);
157 kex_finish(kex); 206 out:
207 explicit_bzero(hash, sizeof(hash));
208 if (kex->ec_client_key) {
209 EC_KEY_free(kex->ec_client_key);
210 kex->ec_client_key = NULL;
211 }
212 if (server_public)
213 EC_POINT_clear_free(server_public);
214 if (kbuf) {
215 explicit_bzero(kbuf, klen);
216 free(kbuf);
217 }
218 if (shared_secret)
219 BN_clear_free(shared_secret);
220 sshkey_free(server_host_key);
221 free(server_host_key_blob);
222 free(signature);
223 return r;
158} 224}
159#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ 225#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
226
diff --git a/kexecdhs.c b/kexecdhs.c
index 6bfad04cf..6b8d95d9c 100644
--- a/kexecdhs.c
+++ b/kexecdhs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexecdhs.c,v 1.11 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: kexecdhs.c,v 1.12 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -32,124 +32,176 @@
32#include <string.h> 32#include <string.h>
33#include <signal.h> 33#include <signal.h>
34 34
35#include "xmalloc.h" 35#include <openssl/ecdh.h>
36#include "buffer.h" 36
37#include "key.h" 37#include "sshkey.h"
38#include "cipher.h" 38#include "cipher.h"
39#include "digest.h"
39#include "kex.h" 40#include "kex.h"
40#include "log.h" 41#include "log.h"
41#include "packet.h" 42#include "packet.h"
42#include "ssh2.h" 43#include "ssh2.h"
43 44
44#include <openssl/ecdh.h> 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, void *);
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}
45 59
46void 60static int
47kexecdh_server(Kex *kex) 61input_kex_ecdh_init(int type, u_int32_t seq, void *ctxt)
48{ 62{
63 struct ssh *ssh = ctxt;
64 struct kex *kex = ssh->kex;
49 EC_POINT *client_public; 65 EC_POINT *client_public;
50 EC_KEY *server_key; 66 EC_KEY *server_key = NULL;
51 const EC_GROUP *group; 67 const EC_GROUP *group;
52 BIGNUM *shared_secret; 68 const EC_POINT *public_key;
53 Key *server_host_private, *server_host_public; 69 BIGNUM *shared_secret = NULL;
70 struct sshkey *server_host_private, *server_host_public;
54 u_char *server_host_key_blob = NULL, *signature = NULL; 71 u_char *server_host_key_blob = NULL, *signature = NULL;
55 u_char *kbuf, *hash; 72 u_char *kbuf = NULL;
56 u_int klen, slen, sbloblen, hashlen; 73 u_char hash[SSH_DIGEST_MAX_LENGTH];
57 74 size_t slen, sbloblen;
58 if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) 75 size_t klen = 0, hashlen;
59 fatal("%s: EC_KEY_new_by_curve_name failed", __func__); 76 int r;
60 if (EC_KEY_generate_key(server_key) != 1) 77
61 fatal("%s: EC_KEY_generate_key failed", __func__); 78 if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
79 r = SSH_ERR_ALLOC_FAIL;
80 goto out;
81 }
82 if (EC_KEY_generate_key(server_key) != 1) {
83 r = SSH_ERR_LIBCRYPTO_ERROR;
84 goto out;
85 }
62 group = EC_KEY_get0_group(server_key); 86 group = EC_KEY_get0_group(server_key);
63 87
64#ifdef DEBUG_KEXECDH 88#ifdef DEBUG_KEXECDH
65 fputs("server private key:\n", stderr); 89 fputs("server private key:\n", stderr);
66 key_dump_ec_key(server_key); 90 sshkey_dump_ec_key(server_key);
67#endif 91#endif
68 92
69 if (kex->load_host_public_key == NULL || 93 if (kex->load_host_public_key == NULL ||
70 kex->load_host_private_key == NULL) 94 kex->load_host_private_key == NULL) {
71 fatal("Cannot load hostkey"); 95 r = SSH_ERR_INVALID_ARGUMENT;
72 server_host_public = kex->load_host_public_key(kex->hostkey_type); 96 goto out;
73 if (server_host_public == NULL) 97 }
74 fatal("Unsupported hostkey type %d", kex->hostkey_type); 98 if ((server_host_public = kex->load_host_public_key(kex->hostkey_type,
75 server_host_private = kex->load_host_private_key(kex->hostkey_type); 99 ssh)) == NULL ||
76 100 (server_host_private = kex->load_host_private_key(kex->hostkey_type,
77 debug("expecting SSH2_MSG_KEX_ECDH_INIT"); 101 ssh)) == NULL) {
78 packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); 102 r = SSH_ERR_NO_HOSTKEY_LOADED;
79 if ((client_public = EC_POINT_new(group)) == NULL) 103 goto out;
80 fatal("%s: EC_POINT_new failed", __func__); 104 }
81 packet_get_ecpoint(group, client_public); 105 if ((client_public = EC_POINT_new(group)) == NULL) {
82 packet_check_eom(); 106 r = SSH_ERR_ALLOC_FAIL;
83 107 goto out;
84 if (key_ec_validate_public(group, client_public) != 0) 108 }
85 fatal("%s: invalid client public key", __func__); 109 if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 ||
110 (r = sshpkt_get_end(ssh)) != 0)
111 goto out;
86 112
87#ifdef DEBUG_KEXECDH 113#ifdef DEBUG_KEXECDH
88 fputs("client public key:\n", stderr); 114 fputs("client public key:\n", stderr);
89 key_dump_ec_point(group, client_public); 115 sshkey_dump_ec_point(group, client_public);
90#endif 116#endif
117 if (sshkey_ec_validate_public(group, client_public) != 0) {
118 sshpkt_disconnect(ssh, "invalid client public key");
119 r = SSH_ERR_MESSAGE_INCOMPLETE;
120 goto out;
121 }
91 122
92 /* Calculate shared_secret */ 123 /* Calculate shared_secret */
93 klen = (EC_GROUP_get_degree(group) + 7) / 8; 124 klen = (EC_GROUP_get_degree(group) + 7) / 8;
94 kbuf = xmalloc(klen); 125 if ((kbuf = malloc(klen)) == NULL ||
126 (shared_secret = BN_new()) == NULL) {
127 r = SSH_ERR_ALLOC_FAIL;
128 goto out;
129 }
95 if (ECDH_compute_key(kbuf, klen, client_public, 130 if (ECDH_compute_key(kbuf, klen, client_public,
96 server_key, NULL) != (int)klen) 131 server_key, NULL) != (int)klen ||
97 fatal("%s: ECDH_compute_key failed", __func__); 132 BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
133 r = SSH_ERR_LIBCRYPTO_ERROR;
134 goto out;
135 }
98 136
99#ifdef DEBUG_KEXDH 137#ifdef DEBUG_KEXECDH
100 dump_digest("shared secret", kbuf, klen); 138 dump_digest("shared secret", kbuf, klen);
101#endif 139#endif
102 if ((shared_secret = BN_new()) == NULL)
103 fatal("%s: BN_new failed", __func__);
104 if (BN_bin2bn(kbuf, klen, shared_secret) == NULL)
105 fatal("%s: BN_bin2bn failed", __func__);
106 explicit_bzero(kbuf, klen);
107 free(kbuf);
108
109 /* calc H */ 140 /* calc H */
110 key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); 141 if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
111 kex_ecdh_hash( 142 &sbloblen)) != 0)
143 goto out;
144 hashlen = sizeof(hash);
145 if ((r = kex_ecdh_hash(
112 kex->hash_alg, 146 kex->hash_alg,
113 group, 147 group,
114 kex->client_version_string, 148 kex->client_version_string,
115 kex->server_version_string, 149 kex->server_version_string,
116 buffer_ptr(kex->peer), buffer_len(kex->peer), 150 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
117 buffer_ptr(kex->my), buffer_len(kex->my), 151 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
118 server_host_key_blob, sbloblen, 152 server_host_key_blob, sbloblen,
119 client_public, 153 client_public,
120 EC_KEY_get0_public_key(server_key), 154 EC_KEY_get0_public_key(server_key),
121 shared_secret, 155 shared_secret,
122 &hash, &hashlen 156 hash, &hashlen)) != 0)
123 ); 157 goto out;
124 EC_POINT_clear_free(client_public);
125 158
126 /* save session id := H */ 159 /* save session id := H */
127 if (kex->session_id == NULL) { 160 if (kex->session_id == NULL) {
128 kex->session_id_len = hashlen; 161 kex->session_id_len = hashlen;
129 kex->session_id = xmalloc(kex->session_id_len); 162 kex->session_id = malloc(kex->session_id_len);
163 if (kex->session_id == NULL) {
164 r = SSH_ERR_ALLOC_FAIL;
165 goto out;
166 }
130 memcpy(kex->session_id, hash, kex->session_id_len); 167 memcpy(kex->session_id, hash, kex->session_id_len);
131 } 168 }
132 169
133 /* sign H */ 170 /* sign H */
134 kex->sign(server_host_private, server_host_public, &signature, &slen, 171 if ((r = kex->sign(server_host_private, server_host_public,
135 hash, hashlen); 172 &signature, &slen, hash, hashlen, ssh->compat)) < 0)
173 goto out;
136 174
137 /* destroy_sensitive_data(); */ 175 /* destroy_sensitive_data(); */
138 176
177 public_key = EC_KEY_get0_public_key(server_key);
139 /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ 178 /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
140 packet_start(SSH2_MSG_KEX_ECDH_REPLY); 179 if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
141 packet_put_string(server_host_key_blob, sbloblen); 180 (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
142 packet_put_ecpoint(group, EC_KEY_get0_public_key(server_key)); 181 (r = sshpkt_put_ec(ssh, public_key, group)) != 0 ||
143 packet_put_string(signature, slen); 182 (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
144 packet_send(); 183 (r = sshpkt_send(ssh)) != 0)
145 184 goto out;
146 free(signature); 185
186 if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
187 r = kex_send_newkeys(ssh);
188 out:
189 explicit_bzero(hash, sizeof(hash));
190 if (kex->ec_client_key) {
191 EC_KEY_free(kex->ec_client_key);
192 kex->ec_client_key = NULL;
193 }
194 if (server_key)
195 EC_KEY_free(server_key);
196 if (kbuf) {
197 explicit_bzero(kbuf, klen);
198 free(kbuf);
199 }
200 if (shared_secret)
201 BN_clear_free(shared_secret);
147 free(server_host_key_blob); 202 free(server_host_key_blob);
148 /* have keys, free server key */ 203 free(signature);
149 EC_KEY_free(server_key); 204 return r;
150
151 kex_derive_keys_bn(kex, hash, hashlen, shared_secret);
152 BN_clear_free(shared_secret);
153 kex_finish(kex);
154} 205}
155#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ 206#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
207
diff --git a/kexgex.c b/kexgex.c
index d1fa1a063..8b0d83332 100644
--- a/kexgex.c
+++ b/kexgex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexgex.c,v 1.28 2014/01/09 23:20:00 djm Exp $ */ 1/* $OpenBSD: kexgex.c,v 1.29 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Niels Provos. All rights reserved. 3 * Copyright (c) 2000 Niels Provos. All rights reserved.
4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -33,69 +33,70 @@
33#include <openssl/evp.h> 33#include <openssl/evp.h>
34#include <signal.h> 34#include <signal.h>
35 35
36#include "buffer.h" 36#include "sshkey.h"
37#include "key.h"
38#include "cipher.h" 37#include "cipher.h"
39#include "kex.h" 38#include "kex.h"
40#include "ssh2.h" 39#include "ssh2.h"
40#include "ssherr.h"
41#include "sshbuf.h"
41#include "digest.h" 42#include "digest.h"
42#include "log.h"
43 43
44void 44int
45kexgex_hash( 45kexgex_hash(
46 int hash_alg, 46 int hash_alg,
47 char *client_version_string, 47 const char *client_version_string,
48 char *server_version_string, 48 const char *server_version_string,
49 char *ckexinit, int ckexinitlen, 49 const u_char *ckexinit, size_t ckexinitlen,
50 char *skexinit, int skexinitlen, 50 const u_char *skexinit, size_t skexinitlen,
51 u_char *serverhostkeyblob, int sbloblen, 51 const u_char *serverhostkeyblob, size_t sbloblen,
52 int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen, 52 int min, int wantbits, int max,
53 BIGNUM *client_dh_pub, 53 const BIGNUM *prime,
54 BIGNUM *server_dh_pub, 54 const BIGNUM *gen,
55 BIGNUM *shared_secret, 55 const BIGNUM *client_dh_pub,
56 u_char **hash, u_int *hashlen) 56 const BIGNUM *server_dh_pub,
57 const BIGNUM *shared_secret,
58 u_char *hash, size_t *hashlen)
57{ 59{
58 Buffer b; 60 struct sshbuf *b;
59 static u_char digest[SSH_DIGEST_MAX_LENGTH]; 61 int r;
60 62
61 buffer_init(&b); 63 if (*hashlen < ssh_digest_bytes(SSH_DIGEST_SHA1))
62 buffer_put_cstring(&b, client_version_string); 64 return SSH_ERR_INVALID_ARGUMENT;
63 buffer_put_cstring(&b, server_version_string); 65 if ((b = sshbuf_new()) == NULL)
64 66 return SSH_ERR_ALLOC_FAIL;
65 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ 67 if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
66 buffer_put_int(&b, ckexinitlen+1); 68 (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
67 buffer_put_char(&b, SSH2_MSG_KEXINIT); 69 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
68 buffer_append(&b, ckexinit, ckexinitlen); 70 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
69 buffer_put_int(&b, skexinitlen+1); 71 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
70 buffer_put_char(&b, SSH2_MSG_KEXINIT); 72 (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
71 buffer_append(&b, skexinit, skexinitlen); 73 (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
72 74 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
73 buffer_put_string(&b, serverhostkeyblob, sbloblen); 75 (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
74 if (min == -1 || max == -1) 76 (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
75 buffer_put_int(&b, wantbits); 77 (min != -1 && (r = sshbuf_put_u32(b, min)) != 0) ||
76 else { 78 (r = sshbuf_put_u32(b, wantbits)) != 0 ||
77 buffer_put_int(&b, min); 79 (max != -1 && (r = sshbuf_put_u32(b, max)) != 0) ||
78 buffer_put_int(&b, wantbits); 80 (r = sshbuf_put_bignum2(b, prime)) != 0 ||
79 buffer_put_int(&b, max); 81 (r = sshbuf_put_bignum2(b, gen)) != 0 ||
82 (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 ||
83 (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 ||
84 (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
85 sshbuf_free(b);
86 return r;
80 } 87 }
81 buffer_put_bignum2(&b, prime);
82 buffer_put_bignum2(&b, gen);
83 buffer_put_bignum2(&b, client_dh_pub);
84 buffer_put_bignum2(&b, server_dh_pub);
85 buffer_put_bignum2(&b, shared_secret);
86
87#ifdef DEBUG_KEXDH 88#ifdef DEBUG_KEXDH
88 buffer_dump(&b); 89 sshbuf_dump(b, stderr);
89#endif 90#endif
90 if (ssh_digest_buffer(hash_alg, &b, digest, sizeof(digest)) != 0) 91 if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
91 fatal("%s: ssh_digest_buffer failed", __func__); 92 sshbuf_free(b);
92 93 return SSH_ERR_LIBCRYPTO_ERROR;
93 buffer_free(&b); 94 }
94 95 sshbuf_free(b);
95#ifdef DEBUG_KEX
96 dump_digest("hash", digest, ssh_digest_bytes(hash_alg));
97#endif
98 *hash = digest;
99 *hashlen = ssh_digest_bytes(hash_alg); 96 *hashlen = ssh_digest_bytes(hash_alg);
97#ifdef DEBUG_KEXDH
98 dump_digest("hash", hash, *hashlen);
99#endif
100 return 0;
100} 101}
101#endif /* WITH_OPENSSL */ 102#endif /* WITH_OPENSSL */
diff --git a/kexgexc.c b/kexgexc.c
index 18d09cfb0..0898824f3 100644
--- a/kexgexc.c
+++ b/kexgexc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexgexc.c,v 1.18 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: kexgexc.c,v 1.19 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Niels Provos. All rights reserved. 3 * Copyright (c) 2000 Niels Provos. All rights reserved.
4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -37,174 +37,237 @@
37#include <string.h> 37#include <string.h>
38#include <signal.h> 38#include <signal.h>
39 39
40#include "xmalloc.h" 40#include "sshkey.h"
41#include "buffer.h"
42#include "key.h"
43#include "cipher.h" 41#include "cipher.h"
42#include "digest.h"
44#include "kex.h" 43#include "kex.h"
45#include "log.h" 44#include "log.h"
46#include "packet.h" 45#include "packet.h"
47#include "dh.h" 46#include "dh.h"
48#include "ssh2.h" 47#include "ssh2.h"
49#include "compat.h" 48#include "compat.h"
49#include "dispatch.h"
50#include "ssherr.h"
51#include "sshbuf.h"
50 52
51void 53static int input_kex_dh_gex_group(int, u_int32_t, void *);
52kexgex_client(Kex *kex) 54static int input_kex_dh_gex_reply(int, u_int32_t, void *);
55
56int
57kexgex_client(struct ssh *ssh)
53{ 58{
54 BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; 59 struct kex *kex = ssh->kex;
55 BIGNUM *p = NULL, *g = NULL; 60 int r;
56 Key *server_host_key; 61 u_int nbits;
57 u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
58 u_int klen, slen, sbloblen, hashlen;
59 int kout;
60 int min, max, nbits;
61 DH *dh;
62 62
63 nbits = dh_estimate(kex->dh_need * 8); 63 nbits = dh_estimate(kex->dh_need * 8);
64 64
65 if (datafellows & SSH_OLD_DHGEX) { 65 kex->min = DH_GRP_MIN;
66 kex->max = DH_GRP_MAX;
67 kex->nbits = nbits;
68 if (ssh->compat & SSH_OLD_DHGEX) {
66 /* Old GEX request */ 69 /* Old GEX request */
67 packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD); 70 if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST_OLD))
68 packet_put_int(nbits); 71 != 0 ||
69 min = DH_GRP_MIN; 72 (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 ||
70 max = DH_GRP_MAX; 73 (r = sshpkt_send(ssh)) != 0)
71 74 goto out;
72 debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD(%u) sent", nbits); 75 debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD(%u) sent", kex->nbits);
73 } else { 76 } else {
74 /* New GEX request */ 77 /* New GEX request */
75 min = DH_GRP_MIN; 78 if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 ||
76 max = DH_GRP_MAX; 79 (r = sshpkt_put_u32(ssh, kex->min)) != 0 ||
77 packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST); 80 (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 ||
78 packet_put_int(min); 81 (r = sshpkt_put_u32(ssh, kex->max)) != 0 ||
79 packet_put_int(nbits); 82 (r = sshpkt_send(ssh)) != 0)
80 packet_put_int(max); 83 goto out;
81
82 debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent", 84 debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent",
83 min, nbits, max); 85 kex->min, kex->nbits, kex->max);
84 } 86 }
85#ifdef DEBUG_KEXDH 87#ifdef DEBUG_KEXDH
86 fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n", 88 fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
87 min, nbits, max); 89 kex->min, kex->nbits, kex->max);
88#endif 90#endif
89 packet_send(); 91 ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP,
90 92 &input_kex_dh_gex_group);
91 debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP"); 93 r = 0;
92 packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP); 94 out:
95 return r;
96}
93 97
94 if ((p = BN_new()) == NULL) 98static int
95 fatal("BN_new"); 99input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt)
96 packet_get_bignum2(p); 100{
97 if ((g = BN_new()) == NULL) 101 struct ssh *ssh = ctxt;
98 fatal("BN_new"); 102 struct kex *kex = ssh->kex;
99 packet_get_bignum2(g); 103 BIGNUM *p = NULL, *g = NULL;
100 packet_check_eom(); 104 int r, bits;
101 105
102 if (BN_num_bits(p) < min || BN_num_bits(p) > max) 106 debug("got SSH2_MSG_KEX_DH_GEX_GROUP");
103 fatal("DH_GEX group out of range: %d !< %d !< %d",
104 min, BN_num_bits(p), max);
105 107
106 dh = dh_new_group(g, p); 108 if ((p = BN_new()) == NULL ||
107 dh_gen_key(dh, kex->we_need * 8); 109 (g = BN_new()) == NULL) {
110 r = SSH_ERR_ALLOC_FAIL;
111 goto out;
112 }
113 if ((r = sshpkt_get_bignum2(ssh, p)) != 0 ||
114 (r = sshpkt_get_bignum2(ssh, g)) != 0 ||
115 (r = sshpkt_get_end(ssh)) != 0)
116 goto out;
117 if ((bits = BN_num_bits(p)) < 0 ||
118 (u_int)bits < kex->min || (u_int)bits > kex->max) {
119 r = SSH_ERR_DH_GEX_OUT_OF_RANGE;
120 goto out;
121 }
122 if ((kex->dh = dh_new_group(g, p)) == NULL) {
123 r = SSH_ERR_ALLOC_FAIL;
124 goto out;
125 }
126 p = g = NULL; /* belong to kex->dh now */
108 127
128 /* generate and send 'e', client DH public key */
129 if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 ||
130 (r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 ||
131 (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 ||
132 (r = sshpkt_send(ssh)) != 0)
133 goto out;
134 debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
109#ifdef DEBUG_KEXDH 135#ifdef DEBUG_KEXDH
110 DHparams_print_fp(stderr, dh); 136 DHparams_print_fp(stderr, kex->dh);
111 fprintf(stderr, "pub= "); 137 fprintf(stderr, "pub= ");
112 BN_print_fp(stderr, dh->pub_key); 138 BN_print_fp(stderr, kex->dh->pub_key);
113 fprintf(stderr, "\n"); 139 fprintf(stderr, "\n");
114#endif 140#endif
141 ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL);
142 ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply);
143 r = 0;
144out:
145 if (p)
146 BN_clear_free(p);
147 if (g)
148 BN_clear_free(g);
149 return r;
150}
115 151
116 debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); 152static int
117 /* generate and send 'e', client DH public key */ 153input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt)
118 packet_start(SSH2_MSG_KEX_DH_GEX_INIT); 154{
119 packet_put_bignum2(dh->pub_key); 155 struct ssh *ssh = ctxt;
120 packet_send(); 156 struct kex *kex = ssh->kex;
121 157 BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
122 debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY"); 158 struct sshkey *server_host_key = NULL;
123 packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY); 159 u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
160 u_char hash[SSH_DIGEST_MAX_LENGTH];
161 size_t klen = 0, slen, sbloblen, hashlen;
162 int kout, r;
124 163
164 debug("got SSH2_MSG_KEX_DH_GEX_REPLY");
165 if (kex->verify_host_key == NULL) {
166 r = SSH_ERR_INVALID_ARGUMENT;
167 goto out;
168 }
125 /* key, cert */ 169 /* key, cert */
126 server_host_key_blob = packet_get_string(&sbloblen); 170 if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
127 server_host_key = key_from_blob(server_host_key_blob, sbloblen); 171 &sbloblen)) != 0 ||
128 if (server_host_key == NULL) 172 (r = sshkey_from_blob(server_host_key_blob, sbloblen,
129 fatal("cannot decode server_host_key_blob"); 173 &server_host_key)) != 0)
130 if (server_host_key->type != kex->hostkey_type) 174 goto out;
131 fatal("type mismatch for decoded server_host_key_blob"); 175 if (server_host_key->type != kex->hostkey_type) {
132 if (kex->verify_host_key == NULL) 176 r = SSH_ERR_KEY_TYPE_MISMATCH;
133 fatal("cannot verify server_host_key"); 177 goto out;
134 if (kex->verify_host_key(server_host_key) == -1) 178 }
135 fatal("server_host_key verification failed"); 179 if (kex->verify_host_key(server_host_key, ssh) == -1) {
136 180 r = SSH_ERR_SIGNATURE_INVALID;
181 goto out;
182 }
137 /* DH parameter f, server public DH key */ 183 /* DH parameter f, server public DH key */
138 if ((dh_server_pub = BN_new()) == NULL) 184 if ((dh_server_pub = BN_new()) == NULL) {
139 fatal("dh_server_pub == NULL"); 185 r = SSH_ERR_ALLOC_FAIL;
140 packet_get_bignum2(dh_server_pub); 186 goto out;
141 187 }
188 /* signed H */
189 if ((r = sshpkt_get_bignum2(ssh, dh_server_pub)) != 0 ||
190 (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
191 (r = sshpkt_get_end(ssh)) != 0)
192 goto out;
142#ifdef DEBUG_KEXDH 193#ifdef DEBUG_KEXDH
143 fprintf(stderr, "dh_server_pub= "); 194 fprintf(stderr, "dh_server_pub= ");
144 BN_print_fp(stderr, dh_server_pub); 195 BN_print_fp(stderr, dh_server_pub);
145 fprintf(stderr, "\n"); 196 fprintf(stderr, "\n");
146 debug("bits %d", BN_num_bits(dh_server_pub)); 197 debug("bits %d", BN_num_bits(dh_server_pub));
147#endif 198#endif
199 if (!dh_pub_is_valid(kex->dh, dh_server_pub)) {
200 sshpkt_disconnect(ssh, "bad server public DH value");
201 r = SSH_ERR_MESSAGE_INCOMPLETE;
202 goto out;
203 }
148 204
149 /* signed H */ 205 klen = DH_size(kex->dh);
150 signature = packet_get_string(&slen); 206 if ((kbuf = malloc(klen)) == NULL ||
151 packet_check_eom(); 207 (shared_secret = BN_new()) == NULL) {
152 208 r = SSH_ERR_ALLOC_FAIL;
153 if (!dh_pub_is_valid(dh, dh_server_pub)) 209 goto out;
154 packet_disconnect("bad server public DH value"); 210 }
155 211 if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 ||
156 klen = DH_size(dh); 212 BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
157 kbuf = xmalloc(klen); 213 r = SSH_ERR_LIBCRYPTO_ERROR;
158 if ((kout = DH_compute_key(kbuf, dh_server_pub, dh)) < 0) 214 goto out;
159 fatal("DH_compute_key: failed"); 215 }
160#ifdef DEBUG_KEXDH 216#ifdef DEBUG_KEXDH
161 dump_digest("shared secret", kbuf, kout); 217 dump_digest("shared secret", kbuf, kout);
162#endif 218#endif
163 if ((shared_secret = BN_new()) == NULL) 219 if (ssh->compat & SSH_OLD_DHGEX)
164 fatal("kexgex_client: BN_new failed"); 220 kex->min = kex->max = -1;
165 if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
166 fatal("kexgex_client: BN_bin2bn failed");
167 explicit_bzero(kbuf, klen);
168 free(kbuf);
169
170 if (datafellows & SSH_OLD_DHGEX)
171 min = max = -1;
172 221
173 /* calc and verify H */ 222 /* calc and verify H */
174 kexgex_hash( 223 hashlen = sizeof(hash);
224 if ((r = kexgex_hash(
175 kex->hash_alg, 225 kex->hash_alg,
176 kex->client_version_string, 226 kex->client_version_string,
177 kex->server_version_string, 227 kex->server_version_string,
178 buffer_ptr(kex->my), buffer_len(kex->my), 228 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
179 buffer_ptr(kex->peer), buffer_len(kex->peer), 229 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
180 server_host_key_blob, sbloblen, 230 server_host_key_blob, sbloblen,
181 min, nbits, max, 231 kex->min, kex->nbits, kex->max,
182 dh->p, dh->g, 232 kex->dh->p, kex->dh->g,
183 dh->pub_key, 233 kex->dh->pub_key,
184 dh_server_pub, 234 dh_server_pub,
185 shared_secret, 235 shared_secret,
186 &hash, &hashlen 236 hash, &hashlen)) != 0)
187 ); 237 goto out;
188
189 /* have keys, free DH */
190 DH_free(dh);
191 free(server_host_key_blob);
192 BN_clear_free(dh_server_pub);
193 238
194 if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) 239 if ((r = sshkey_verify(server_host_key, signature, slen, hash,
195 fatal("key_verify failed for server_host_key"); 240 hashlen, ssh->compat)) != 0)
196 key_free(server_host_key); 241 goto out;
197 free(signature);
198 242
199 /* save session id */ 243 /* save session id */
200 if (kex->session_id == NULL) { 244 if (kex->session_id == NULL) {
201 kex->session_id_len = hashlen; 245 kex->session_id_len = hashlen;
202 kex->session_id = xmalloc(kex->session_id_len); 246 kex->session_id = malloc(kex->session_id_len);
247 if (kex->session_id == NULL) {
248 r = SSH_ERR_ALLOC_FAIL;
249 goto out;
250 }
203 memcpy(kex->session_id, hash, kex->session_id_len); 251 memcpy(kex->session_id, hash, kex->session_id_len);
204 } 252 }
205 kex_derive_keys_bn(kex, hash, hashlen, shared_secret);
206 BN_clear_free(shared_secret);
207 253
208 kex_finish(kex); 254 if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
255 r = kex_send_newkeys(ssh);
256 out:
257 explicit_bzero(hash, sizeof(hash));
258 DH_free(kex->dh);
259 kex->dh = NULL;
260 if (dh_server_pub)
261 BN_clear_free(dh_server_pub);
262 if (kbuf) {
263 explicit_bzero(kbuf, klen);
264 free(kbuf);
265 }
266 if (shared_secret)
267 BN_clear_free(shared_secret);
268 sshkey_free(server_host_key);
269 free(server_host_key_blob);
270 free(signature);
271 return r;
209} 272}
210#endif /* WITH_OPENSSL */ 273#endif /* WITH_OPENSSL */
diff --git a/kexgexs.c b/kexgexs.c
index 1021e0bf6..6e2b009b5 100644
--- a/kexgexs.c
+++ b/kexgexs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexgexs.c,v 1.20 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: kexgexs.c,v 1.21 2015/01/19 20:16:15 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Niels Provos. All rights reserved. 3 * Copyright (c) 2000 Niels Provos. All rights reserved.
4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -37,10 +37,9 @@
37 37
38#include <openssl/dh.h> 38#include <openssl/dh.h>
39 39
40#include "xmalloc.h" 40#include "sshkey.h"
41#include "buffer.h"
42#include "key.h"
43#include "cipher.h" 41#include "cipher.h"
42#include "digest.h"
44#include "kex.h" 43#include "kex.h"
45#include "log.h" 44#include "log.h"
46#include "packet.h" 45#include "packet.h"
@@ -51,33 +50,43 @@
51#include "ssh-gss.h" 50#include "ssh-gss.h"
52#endif 51#endif
53#include "monitor_wrap.h" 52#include "monitor_wrap.h"
53#include "dispatch.h"
54#include "ssherr.h"
55#include "sshbuf.h"
54 56
55void 57static int input_kex_dh_gex_request(int, u_int32_t, void *);
56kexgex_server(Kex *kex) 58static int input_kex_dh_gex_init(int, u_int32_t, void *);
59
60int
61kexgex_server(struct ssh *ssh)
57{ 62{
58 BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; 63 ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST_OLD,
59 Key *server_host_public, *server_host_private; 64 &input_kex_dh_gex_request);
60 DH *dh; 65 ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST,
61 u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; 66 &input_kex_dh_gex_request);
62 u_int sbloblen, klen, slen, hashlen; 67 debug("expecting SSH2_MSG_KEX_DH_GEX_REQUEST");
63 int omin = -1, min = -1, omax = -1, max = -1, onbits = -1, nbits = -1; 68 return 0;
64 int type, kout; 69}
70
71static int
72input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
73{
74 struct ssh *ssh = ctxt;
75 struct kex *kex = ssh->kex;
76 int r;
77 u_int min = 0, max = 0, nbits = 0;
65 78
66 if (kex->load_host_public_key == NULL ||
67 kex->load_host_private_key == NULL)
68 fatal("Cannot load hostkey");
69 server_host_public = kex->load_host_public_key(kex->hostkey_type);
70 if (server_host_public == NULL)
71 fatal("Unsupported hostkey type %d", kex->hostkey_type);
72 server_host_private = kex->load_host_private_key(kex->hostkey_type);
73
74 type = packet_read();
75 switch (type) { 79 switch (type) {
76 case SSH2_MSG_KEX_DH_GEX_REQUEST: 80 case SSH2_MSG_KEX_DH_GEX_REQUEST:
77 debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); 81 debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
78 omin = min = packet_get_int(); 82 if ((r = sshpkt_get_u32(ssh, &min)) != 0 ||
79 onbits = nbits = packet_get_int(); 83 (r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
80 omax = max = packet_get_int(); 84 (r = sshpkt_get_u32(ssh, &max)) != 0 ||
85 (r = sshpkt_get_end(ssh)) != 0)
86 goto out;
87 kex->nbits = nbits;
88 kex->min = min;
89 kex->max = max;
81 min = MAX(DH_GRP_MIN, min); 90 min = MAX(DH_GRP_MIN, min);
82 max = MIN(DH_GRP_MAX, max); 91 max = MIN(DH_GRP_MAX, max);
83 nbits = MAX(DH_GRP_MIN, nbits); 92 nbits = MAX(DH_GRP_MIN, nbits);
@@ -85,45 +94,88 @@ kexgex_server(Kex *kex)
85 break; 94 break;
86 case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: 95 case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD:
87 debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received"); 96 debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received");
88 onbits = nbits = packet_get_int(); 97 if ((r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
98 (r = sshpkt_get_end(ssh)) != 0)
99 goto out;
100 kex->nbits = nbits;
89 /* unused for old GEX */ 101 /* unused for old GEX */
90 omin = min = DH_GRP_MIN; 102 kex->min = min = DH_GRP_MIN;
91 omax = max = DH_GRP_MAX; 103 kex->max = max = DH_GRP_MAX;
92 break; 104 break;
93 default: 105 default:
94 fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type); 106 r = SSH_ERR_INVALID_ARGUMENT;
107 goto out;
95 } 108 }
96 packet_check_eom();
97 109
98 if (omax < omin || onbits < omin || omax < onbits) 110 if (kex->max < kex->min || kex->nbits < kex->min ||
99 fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d", 111 kex->max < kex->nbits) {
100 omin, onbits, omax); 112 r = SSH_ERR_DH_GEX_OUT_OF_RANGE;
113 goto out;
114 }
101 115
102 /* Contact privileged parent */ 116 /* Contact privileged parent */
103 dh = PRIVSEP(choose_dh(min, nbits, max)); 117 kex->dh = PRIVSEP(choose_dh(min, nbits, max));
104 if (dh == NULL) 118 if (kex->dh == NULL) {
105 packet_disconnect("Protocol error: no matching DH grp found"); 119 sshpkt_disconnect(ssh, "no matching DH grp found");
106 120 r = SSH_ERR_ALLOC_FAIL;
121 goto out;
122 }
107 debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); 123 debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
108 packet_start(SSH2_MSG_KEX_DH_GEX_GROUP); 124 if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 ||
109 packet_put_bignum2(dh->p); 125 (r = sshpkt_put_bignum2(ssh, kex->dh->p)) != 0 ||
110 packet_put_bignum2(dh->g); 126 (r = sshpkt_put_bignum2(ssh, kex->dh->g)) != 0 ||
111 packet_send(); 127 (r = sshpkt_send(ssh)) != 0)
112 128 goto out;
113 /* flush */
114 packet_write_wait();
115 129
116 /* Compute our exchange value in parallel with the client */ 130 /* Compute our exchange value in parallel with the client */
117 dh_gen_key(dh, kex->we_need * 8); 131 if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
132 goto out;
133
134 /* old KEX does not use min/max in kexgex_hash() */
135 if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)
136 kex->min = kex->max = -1;
118 137
119 debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); 138 debug("expecting SSH2_MSG_KEX_DH_GEX_INIT");
120 packet_read_expect(SSH2_MSG_KEX_DH_GEX_INIT); 139 ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init);
140 r = 0;
141 out:
142 return r;
143}
144
145static int
146input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt)
147{
148 struct ssh *ssh = ctxt;
149 struct kex *kex = ssh->kex;
150 BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
151 struct sshkey *server_host_public, *server_host_private;
152 u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
153 u_char hash[SSH_DIGEST_MAX_LENGTH];
154 size_t sbloblen, slen;
155 size_t klen = 0, hashlen;
156 int kout, r;
157
158 if (kex->load_host_public_key == NULL ||
159 kex->load_host_private_key == NULL) {
160 r = SSH_ERR_INVALID_ARGUMENT;
161 goto out;
162 }
163 if ((server_host_public = kex->load_host_public_key(kex->hostkey_type,
164 ssh)) == NULL ||
165 (server_host_private = kex->load_host_private_key(kex->hostkey_type,
166 ssh)) == NULL) {
167 r = SSH_ERR_NO_HOSTKEY_LOADED;
168 goto out;
169 }
121 170
122 /* key, cert */ 171 /* key, cert */
123 if ((dh_client_pub = BN_new()) == NULL) 172 if ((dh_client_pub = BN_new()) == NULL) {
124 fatal("dh_client_pub == NULL"); 173 r = SSH_ERR_ALLOC_FAIL;
125 packet_get_bignum2(dh_client_pub); 174 goto out;
126 packet_check_eom(); 175 }
176 if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 ||
177 (r = sshpkt_get_end(ssh)) != 0)
178 goto out;
127 179
128#ifdef DEBUG_KEXDH 180#ifdef DEBUG_KEXDH
129 fprintf(stderr, "dh_client_pub= "); 181 fprintf(stderr, "dh_client_pub= ");
@@ -133,79 +185,92 @@ kexgex_server(Kex *kex)
133#endif 185#endif
134 186
135#ifdef DEBUG_KEXDH 187#ifdef DEBUG_KEXDH
136 DHparams_print_fp(stderr, dh); 188 DHparams_print_fp(stderr, kex->dh);
137 fprintf(stderr, "pub= "); 189 fprintf(stderr, "pub= ");
138 BN_print_fp(stderr, dh->pub_key); 190 BN_print_fp(stderr, kex->dh->pub_key);
139 fprintf(stderr, "\n"); 191 fprintf(stderr, "\n");
140#endif 192#endif
141 if (!dh_pub_is_valid(dh, dh_client_pub)) 193 if (!dh_pub_is_valid(kex->dh, dh_client_pub)) {
142 packet_disconnect("bad client public DH value"); 194 sshpkt_disconnect(ssh, "bad client public DH value");
195 r = SSH_ERR_MESSAGE_INCOMPLETE;
196 goto out;
197 }
143 198
144 klen = DH_size(dh); 199 klen = DH_size(kex->dh);
145 kbuf = xmalloc(klen); 200 if ((kbuf = malloc(klen)) == NULL ||
146 if ((kout = DH_compute_key(kbuf, dh_client_pub, dh)) < 0) 201 (shared_secret = BN_new()) == NULL) {
147 fatal("DH_compute_key: failed"); 202 r = SSH_ERR_ALLOC_FAIL;
203 goto out;
204 }
205 if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 ||
206 BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
207 r = SSH_ERR_LIBCRYPTO_ERROR;
208 goto out;
209 }
148#ifdef DEBUG_KEXDH 210#ifdef DEBUG_KEXDH
149 dump_digest("shared secret", kbuf, kout); 211 dump_digest("shared secret", kbuf, kout);
150#endif 212#endif
151 if ((shared_secret = BN_new()) == NULL) 213 if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
152 fatal("kexgex_server: BN_new failed"); 214 &sbloblen)) != 0)
153 if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) 215 goto out;
154 fatal("kexgex_server: BN_bin2bn failed");
155 explicit_bzero(kbuf, klen);
156 free(kbuf);
157
158 key_to_blob(server_host_public, &server_host_key_blob, &sbloblen);
159
160 if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)
161 omin = min = omax = max = -1;
162
163 /* calc H */ 216 /* calc H */
164 kexgex_hash( 217 hashlen = sizeof(hash);
218 if ((r = kexgex_hash(
165 kex->hash_alg, 219 kex->hash_alg,
166 kex->client_version_string, 220 kex->client_version_string,
167 kex->server_version_string, 221 kex->server_version_string,
168 buffer_ptr(kex->peer), buffer_len(kex->peer), 222 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
169 buffer_ptr(kex->my), buffer_len(kex->my), 223 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
170 server_host_key_blob, sbloblen, 224 server_host_key_blob, sbloblen,
171 omin, onbits, omax, 225 kex->min, kex->nbits, kex->max,
172 dh->p, dh->g, 226 kex->dh->p, kex->dh->g,
173 dh_client_pub, 227 dh_client_pub,
174 dh->pub_key, 228 kex->dh->pub_key,
175 shared_secret, 229 shared_secret,
176 &hash, &hashlen 230 hash, &hashlen)) != 0)
177 ); 231 goto out;
178 BN_clear_free(dh_client_pub);
179 232
180 /* save session id := H */ 233 /* save session id := H */
181 if (kex->session_id == NULL) { 234 if (kex->session_id == NULL) {
182 kex->session_id_len = hashlen; 235 kex->session_id_len = hashlen;
183 kex->session_id = xmalloc(kex->session_id_len); 236 kex->session_id = malloc(kex->session_id_len);
237 if (kex->session_id == NULL) {
238 r = SSH_ERR_ALLOC_FAIL;
239 goto out;
240 }
184 memcpy(kex->session_id, hash, kex->session_id_len); 241 memcpy(kex->session_id, hash, kex->session_id_len);
185 } 242 }
186 243
187 /* sign H */ 244 /* sign H */
188 kex->sign(server_host_private, server_host_public, &signature, &slen, 245 if ((r = kex->sign(server_host_private, server_host_public,
189 hash, hashlen); 246 &signature, &slen, hash, hashlen, ssh->compat)) < 0)
247 goto out;
190 248
191 /* destroy_sensitive_data(); */ 249 /* destroy_sensitive_data(); */
192 250
193 /* send server hostkey, DH pubkey 'f' and singed H */ 251 /* send server hostkey, DH pubkey 'f' and singed H */
194 debug("SSH2_MSG_KEX_DH_GEX_REPLY sent"); 252 if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 ||
195 packet_start(SSH2_MSG_KEX_DH_GEX_REPLY); 253 (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
196 packet_put_string(server_host_key_blob, sbloblen); 254 (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */
197 packet_put_bignum2(dh->pub_key); /* f */ 255 (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
198 packet_put_string(signature, slen); 256 (r = sshpkt_send(ssh)) != 0)
199 packet_send(); 257 goto out;
200 258
201 free(signature); 259 if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
260 r = kex_send_newkeys(ssh);
261 out:
262 DH_free(kex->dh);
263 kex->dh = NULL;
264 if (dh_client_pub)
265 BN_clear_free(dh_client_pub);
266 if (kbuf) {
267 explicit_bzero(kbuf, klen);
268 free(kbuf);
269 }
270 if (shared_secret)
271 BN_clear_free(shared_secret);
202 free(server_host_key_blob); 272 free(server_host_key_blob);
203 /* have keys, free DH */ 273 free(signature);
204 DH_free(dh); 274 return r;
205
206 kex_derive_keys_bn(kex, hash, hashlen, shared_secret);
207 BN_clear_free(shared_secret);
208
209 kex_finish(kex);
210} 275}
211#endif /* WITH_OPENSSL */ 276#endif /* WITH_OPENSSL */
diff --git a/monitor.c b/monitor.c
index 6ee291128..40fff097d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.139 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: monitor.c,v 1.140 2015/01/19 20:16:15 markus 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>
@@ -717,7 +717,7 @@ mm_answer_sign(int sock, Buffer *m)
717 datafellows)) != 0) 717 datafellows)) != 0)
718 fatal("%s: sshkey_sign failed: %s", 718 fatal("%s: sshkey_sign failed: %s",
719 __func__, ssh_err(r)); 719 __func__, ssh_err(r));
720 } else if ((key = get_hostkey_public_by_index(keyid)) != NULL && 720 } else if ((key = get_hostkey_public_by_index(keyid, active_state)) != NULL &&
721 auth_sock > 0) { 721 auth_sock > 0) {
722 if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, 722 if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen,
723 p, datlen, datafellows)) != 0) { 723 p, datlen, datafellows)) != 0) {
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 84df481d8..c0935dc69 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor_wrap.c,v 1.82 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: monitor_wrap.c,v 1.83 2015/01/19 20:16:15 markus 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>
@@ -221,13 +221,13 @@ mm_choose_dh(int min, int nbits, int max)
221int 221int
222mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) 222mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
223{ 223{
224 Kex *kex = *pmonitor->m_pkex; 224 struct kex *kex = *pmonitor->m_pkex;
225 Buffer m; 225 Buffer m;
226 226
227 debug3("%s entering", __func__); 227 debug3("%s entering", __func__);
228 228
229 buffer_init(&m); 229 buffer_init(&m);
230 buffer_put_int(&m, kex->host_key_index(key)); 230 buffer_put_int(&m, kex->host_key_index(key, active_state));
231 buffer_put_string(&m, data, datalen); 231 buffer_put_string(&m, data, datalen);
232 232
233 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m); 233 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
diff --git a/serverloop.c b/serverloop.c
index edf6a813f..83a1e010d 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: serverloop.c,v 1.174 2015/01/19 20:07:45 markus Exp $ */ 1/* $OpenBSD: serverloop.c,v 1.175 2015/01/19 20:16:15 markus 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
@@ -544,7 +544,7 @@ drain_output(void)
544static void 544static void
545process_buffered_input_packets(void) 545process_buffered_input_packets(void)
546{ 546{
547 dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? active_state->kex : NULL); 547 dispatch_run(DISPATCH_NONBLOCK, NULL, active_state);
548} 548}
549 549
550/* 550/*
@@ -874,7 +874,7 @@ server_loop2(Authctxt *authctxt)
874 if (packet_need_rekeying()) { 874 if (packet_need_rekeying()) {
875 debug("need rekeying"); 875 debug("need rekeying");
876 active_state->kex->done = 0; 876 active_state->kex->done = 0;
877 kex_send_kexinit(active_state->kex); 877 kex_send_kexinit(active_state);
878 } 878 }
879 } 879 }
880 process_input(readset); 880 process_input(readset);
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index 84301b6ff..223ac58f1 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keyscan.c,v 1.93 2014/12/11 08:20:09 djm Exp $ */ 1/* $OpenBSD: ssh-keyscan.c,v 1.94 2015/01/19 20:16:15 markus 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 *
@@ -100,7 +100,7 @@ typedef struct Connection {
100 char *c_namelist; /* Pointer to other possible addresses */ 100 char *c_namelist; /* Pointer to other possible addresses */
101 char *c_output_name; /* Hostname of connection for output */ 101 char *c_output_name; /* Hostname of connection for output */
102 char *c_data; /* Data read from this fd */ 102 char *c_data; /* Data read from this fd */
103 Kex *c_kex; /* The key-exchange struct for ssh2 */ 103 struct kex *c_kex; /* The key-exchange struct for ssh2 */
104 struct timeval c_tv; /* Time at which connection gets aborted */ 104 struct timeval c_tv; /* Time at which connection gets aborted */
105 TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */ 105 TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */
106} con; 106} con;
@@ -221,7 +221,7 @@ keygrab_ssh1(con *c)
221#endif 221#endif
222 222
223static int 223static int
224hostjump(Key *hostkey) 224hostjump(Key *hostkey, struct ssh *ssh)
225{ 225{
226 kexjmp_key = hostkey; 226 kexjmp_key = hostkey;
227 longjmp(kexjmp, 1); 227 longjmp(kexjmp, 1);
@@ -247,7 +247,7 @@ static Key *
247keygrab_ssh2(con *c) 247keygrab_ssh2(con *c)
248{ 248{
249 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; 249 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
250 int j; 250 int r, j;
251 251
252 packet_set_connection(c->c_fd, c->c_fd); 252 packet_set_connection(c->c_fd, c->c_fd);
253 enable_compat20(); 253 enable_compat20();
@@ -256,7 +256,9 @@ keygrab_ssh2(con *c)
256 (c->c_keytype == KT_RSA ? "ssh-rsa" : 256 (c->c_keytype == KT_RSA ? "ssh-rsa" :
257 (c->c_keytype == KT_ED25519 ? "ssh-ed25519" : 257 (c->c_keytype == KT_ED25519 ? "ssh-ed25519" :
258 "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521")); 258 "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"));
259 c->c_kex = kex_setup(myproposal); 259 if ((r = kex_setup(active_state, myproposal)) < 0)
260 fatal("%s: kex_setup: %s", __func__, ssh_err(r));
261 c->c_kex = active_state->kex;
260#ifdef WITH_OPENSSL 262#ifdef WITH_OPENSSL
261 c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 263 c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
262 c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 264 c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
@@ -269,7 +271,7 @@ keygrab_ssh2(con *c)
269 271
270 if (!(j = setjmp(kexjmp))) { 272 if (!(j = setjmp(kexjmp))) {
271 nonfatal_fatal = 1; 273 nonfatal_fatal = 1;
272 dispatch_run(DISPATCH_BLOCK, &c->c_kex->done, c->c_kex); 274 dispatch_run(DISPATCH_BLOCK, &c->c_kex->done, active_state);
273 fprintf(stderr, "Impossible! dispatch_run() returned!\n"); 275 fprintf(stderr, "Impossible! dispatch_run() returned!\n");
274 exit(1); 276 exit(1);
275 } 277 }
diff --git a/sshconnect2.c b/sshconnect2.c
index e0d129996..e5802abcc 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.218 2015/01/19 20:07:45 markus Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.219 2015/01/19 20:16:15 markus 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.
@@ -92,7 +92,7 @@ char *xxx_host;
92struct sockaddr *xxx_hostaddr; 92struct sockaddr *xxx_hostaddr;
93 93
94static int 94static int
95verify_host_key_callback(Key *hostkey) 95verify_host_key_callback(Key *hostkey, struct ssh *ssh)
96{ 96{
97 if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) 97 if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
98 fatal("Host key verification failed."); 98 fatal("Host key verification failed.");
@@ -157,7 +157,7 @@ void
157ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 157ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
158{ 158{
159 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; 159 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
160 Kex *kex; 160 struct kex *kex;
161 161
162 xxx_host = host; 162 xxx_host = host;
163 xxx_hostaddr = hostaddr; 163 xxx_hostaddr = hostaddr;
@@ -204,8 +204,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
204 (time_t)options.rekey_interval); 204 (time_t)options.rekey_interval);
205 205
206 /* start key exchange */ 206 /* start key exchange */
207 kex = kex_setup(myproposal); 207 kex_setup(active_state, myproposal);
208 active_state->kex = kex; 208 kex = active_state->kex;
209#ifdef WITH_OPENSSL 209#ifdef WITH_OPENSSL
210 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 210 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
211 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 211 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
@@ -218,7 +218,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
218 kex->server_version_string=server_version_string; 218 kex->server_version_string=server_version_string;
219 kex->verify_host_key=&verify_host_key_callback; 219 kex->verify_host_key=&verify_host_key_callback;
220 220
221 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 221 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
222 222
223 if (options.use_roaming && !kex->roaming) { 223 if (options.use_roaming && !kex->roaming) {
224 debug("Roaming not allowed by server"); 224 debug("Roaming not allowed by server");
diff --git a/sshd.c b/sshd.c
index e45303988..21d8dd699 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.434 2015/01/19 19:52:16 markus Exp $ */ 1/* $OpenBSD: sshd.c,v 1.435 2015/01/19 20:16:15 markus 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
@@ -836,7 +836,7 @@ list_hostkey_types(void)
836} 836}
837 837
838static Key * 838static Key *
839get_hostkey_by_type(int type, int need_private) 839get_hostkey_by_type(int type, int need_private, struct ssh *ssh)
840{ 840{
841 int i; 841 int i;
842 Key *key; 842 Key *key;
@@ -865,15 +865,15 @@ get_hostkey_by_type(int type, int need_private)
865} 865}
866 866
867Key * 867Key *
868get_hostkey_public_by_type(int type) 868get_hostkey_public_by_type(int type, struct ssh *ssh)
869{ 869{
870 return get_hostkey_by_type(type, 0); 870 return get_hostkey_by_type(type, 0, ssh);
871} 871}
872 872
873Key * 873Key *
874get_hostkey_private_by_type(int type) 874get_hostkey_private_by_type(int type, struct ssh *ssh)
875{ 875{
876 return get_hostkey_by_type(type, 1); 876 return get_hostkey_by_type(type, 1, ssh);
877} 877}
878 878
879Key * 879Key *
@@ -885,7 +885,7 @@ get_hostkey_by_index(int ind)
885} 885}
886 886
887Key * 887Key *
888get_hostkey_public_by_index(int ind) 888get_hostkey_public_by_index(int ind, struct ssh *ssh)
889{ 889{
890 if (ind < 0 || ind >= options.num_host_key_files) 890 if (ind < 0 || ind >= options.num_host_key_files)
891 return (NULL); 891 return (NULL);
@@ -893,7 +893,7 @@ get_hostkey_public_by_index(int ind)
893} 893}
894 894
895int 895int
896get_hostkey_index(Key *key) 896get_hostkey_index(Key *key, struct ssh *ssh)
897{ 897{
898 int i; 898 int i;
899 899
@@ -2432,29 +2432,30 @@ do_ssh1_kex(void)
2432} 2432}
2433#endif 2433#endif
2434 2434
2435void 2435int
2436sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, 2436sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen,
2437 u_char *data, u_int dlen) 2437 u_char *data, size_t dlen, u_int flag)
2438{ 2438{
2439 int r; 2439 int r;
2440 u_int xxx_slen, xxx_dlen = dlen;
2440 2441
2441 if (privkey) { 2442 if (privkey) {
2442 if (PRIVSEP(key_sign(privkey, signature, slen, data, dlen) < 0)) 2443 if (PRIVSEP(key_sign(privkey, signature, &xxx_slen, data, xxx_dlen) < 0))
2443 fatal("%s: key_sign failed", __func__); 2444 fatal("%s: key_sign failed", __func__);
2445 if (slen)
2446 *slen = xxx_slen;
2444 } else if (use_privsep) { 2447 } else if (use_privsep) {
2445 if (mm_key_sign(pubkey, signature, slen, data, dlen) < 0) 2448 if (mm_key_sign(pubkey, signature, &xxx_slen, data, xxx_dlen) < 0)
2446 fatal("%s: pubkey_sign failed", __func__); 2449 fatal("%s: pubkey_sign failed", __func__);
2450 if (slen)
2451 *slen = xxx_slen;
2447 } else { 2452 } else {
2448 size_t xxx_slen; 2453 if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slen,
2449
2450 if ((r = ssh_agent_sign(auth_sock, pubkey, signature, &xxx_slen,
2451 data, dlen, datafellows)) != 0) 2454 data, dlen, datafellows)) != 0)
2452 fatal("%s: ssh_agent_sign failed: %s", 2455 fatal("%s: ssh_agent_sign failed: %s",
2453 __func__, ssh_err(r)); 2456 __func__, ssh_err(r));
2454 /* XXX: Old API is u_int; new size_t */
2455 if (slen != NULL)
2456 *slen = xxx_slen;
2457 } 2457 }
2458 return 0;
2458} 2459}
2459 2460
2460/* 2461/*
@@ -2464,7 +2465,7 @@ static void
2464do_ssh2_kex(void) 2465do_ssh2_kex(void)
2465{ 2466{
2466 char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; 2467 char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
2467 Kex *kex; 2468 struct kex *kex;
2468 2469
2469 if (options.ciphers != NULL) { 2470 if (options.ciphers != NULL) {
2470 myproposal[PROPOSAL_ENC_ALGS_CTOS] = 2471 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
@@ -2500,8 +2501,8 @@ do_ssh2_kex(void)
2500 list_hostkey_types()); 2501 list_hostkey_types());
2501 2502
2502 /* start key exchange */ 2503 /* start key exchange */
2503 kex = kex_setup(myproposal); 2504 kex_setup(active_state, myproposal);
2504 active_state->kex = kex; 2505 kex = active_state->kex;
2505#ifdef WITH_OPENSSL 2506#ifdef WITH_OPENSSL
2506 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 2507 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
2507 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 2508 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
@@ -2518,7 +2519,7 @@ do_ssh2_kex(void)
2518 kex->host_key_index=&get_hostkey_index; 2519 kex->host_key_index=&get_hostkey_index;
2519 kex->sign = sshd_hostkey_sign; 2520 kex->sign = sshd_hostkey_sign;
2520 2521
2521 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 2522 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
2522 2523
2523 session_id2 = kex->session_id; 2524 session_id2 = kex->session_id;
2524 session_id2_len = kex->session_id_len; 2525 session_id2_len = kex->session_id_len;