diff options
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 85 |
1 files changed, 49 insertions, 36 deletions
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: kex.c,v 1.26 2001/04/03 19:53:29 markus Exp $"); | 26 | RCSID("$OpenBSD: kex.c,v 1.27 2001/04/03 23:32:11 markus Exp $"); |
27 | 27 | ||
28 | #include <openssl/crypto.h> | 28 | #include <openssl/crypto.h> |
29 | 29 | ||
@@ -131,7 +131,7 @@ kex_input_newkeys(int type, int plen, void *ctxt) | |||
131 | for (i = 30; i <= 49; i++) | 131 | for (i = 30; i <= 49; i++) |
132 | dispatch_set(i, &kex_protocol_error); | 132 | dispatch_set(i, &kex_protocol_error); |
133 | buffer_clear(&kex->peer); | 133 | buffer_clear(&kex->peer); |
134 | buffer_clear(&kex->my); | 134 | /* buffer_clear(&kex->my); */ |
135 | kex->flags &= ~KEX_INIT_SENT; | 135 | kex->flags &= ~KEX_INIT_SENT; |
136 | } | 136 | } |
137 | 137 | ||
@@ -152,7 +152,6 @@ kex_input_kexinit(int type, int plen, void *ctxt) | |||
152 | int dlen; | 152 | int dlen; |
153 | Kex *kex = (Kex *)ctxt; | 153 | Kex *kex = (Kex *)ctxt; |
154 | 154 | ||
155 | dispatch_set(SSH2_MSG_KEXINIT, &kex_protocol_error); | ||
156 | debug("SSH2_MSG_KEXINIT received"); | 155 | debug("SSH2_MSG_KEXINIT received"); |
157 | 156 | ||
158 | ptr = packet_get_raw(&dlen); | 157 | ptr = packet_get_raw(&dlen); |
@@ -274,18 +273,20 @@ choose_hostkeyalg(Kex *k, char *client, char *server) | |||
274 | } | 273 | } |
275 | 274 | ||
276 | void | 275 | void |
277 | kex_choose_conf(Kex *k) | 276 | kex_choose_conf(Kex *kex) |
278 | { | 277 | { |
278 | Newkeys *newkeys; | ||
279 | char **my, **peer; | 279 | char **my, **peer; |
280 | char **cprop, **sprop; | 280 | char **cprop, **sprop; |
281 | int nenc, nmac, ncomp; | ||
281 | int mode; | 282 | int mode; |
282 | int ctos; /* direction: if true client-to-server */ | 283 | int ctos; /* direction: if true client-to-server */ |
283 | int need; | 284 | int need; |
284 | 285 | ||
285 | my = kex_buf2prop(&k->my); | 286 | my = kex_buf2prop(&kex->my); |
286 | peer = kex_buf2prop(&k->peer); | 287 | peer = kex_buf2prop(&kex->peer); |
287 | 288 | ||
288 | if (k->server) { | 289 | if (kex->server) { |
289 | cprop=peer; | 290 | cprop=peer; |
290 | sprop=my; | 291 | sprop=my; |
291 | } else { | 292 | } else { |
@@ -294,42 +295,44 @@ kex_choose_conf(Kex *k) | |||
294 | } | 295 | } |
295 | 296 | ||
296 | for (mode = 0; mode < MODE_MAX; mode++) { | 297 | for (mode = 0; mode < MODE_MAX; mode++) { |
297 | int nenc, nmac, ncomp; | 298 | newkeys = xmalloc(sizeof(*newkeys)); |
298 | ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN); | 299 | memset(newkeys, 0, sizeof(*newkeys)); |
300 | kex->keys[mode] = newkeys; | ||
301 | ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); | ||
299 | nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; | 302 | nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; |
300 | nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; | 303 | nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; |
301 | ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; | 304 | ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; |
302 | choose_enc (&k->enc [mode], cprop[nenc], sprop[nenc]); | 305 | choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]); |
303 | choose_mac (&k->mac [mode], cprop[nmac], sprop[nmac]); | 306 | choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]); |
304 | choose_comp(&k->comp[mode], cprop[ncomp], sprop[ncomp]); | 307 | choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); |
305 | debug("kex: %s %s %s %s", | 308 | debug("kex: %s %s %s %s", |
306 | ctos ? "client->server" : "server->client", | 309 | ctos ? "client->server" : "server->client", |
307 | k->enc[mode].name, | 310 | newkeys->enc.name, |
308 | k->mac[mode].name, | 311 | newkeys->mac.name, |
309 | k->comp[mode].name); | 312 | newkeys->comp.name); |
310 | } | 313 | } |
311 | choose_kex(k, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); | 314 | choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); |
312 | choose_hostkeyalg(k, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], | 315 | choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], |
313 | sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); | 316 | sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); |
314 | need = 0; | 317 | need = 0; |
315 | for (mode = 0; mode < MODE_MAX; mode++) { | 318 | for (mode = 0; mode < MODE_MAX; mode++) { |
316 | if (need < k->enc[mode].cipher->key_len) | 319 | newkeys = kex->keys[mode]; |
317 | need = k->enc[mode].cipher->key_len; | 320 | if (need < newkeys->enc.cipher->key_len) |
318 | if (need < k->enc[mode].cipher->block_size) | 321 | need = newkeys->enc.cipher->key_len; |
319 | need = k->enc[mode].cipher->block_size; | 322 | if (need < newkeys->enc.cipher->block_size) |
320 | if (need < k->mac[mode].key_len) | 323 | need = newkeys->enc.cipher->block_size; |
321 | need = k->mac[mode].key_len; | 324 | if (need < newkeys->mac.key_len) |
325 | need = newkeys->mac.key_len; | ||
322 | } | 326 | } |
323 | /* XXX need runden? */ | 327 | /* XXX need runden? */ |
324 | k->we_need = need; | 328 | kex->we_need = need; |
325 | 329 | ||
326 | kex_prop_free(my); | 330 | kex_prop_free(my); |
327 | kex_prop_free(peer); | 331 | kex_prop_free(peer); |
328 | |||
329 | } | 332 | } |
330 | 333 | ||
331 | u_char * | 334 | u_char * |
332 | derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret) | 335 | derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret) |
333 | { | 336 | { |
334 | Buffer b; | 337 | Buffer b; |
335 | EVP_MD *evp_md = EVP_sha1(); | 338 | EVP_MD *evp_md = EVP_sha1(); |
@@ -346,7 +349,7 @@ derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret) | |||
346 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */ | 349 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */ |
347 | EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */ | 350 | EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */ |
348 | EVP_DigestUpdate(&md, &c, 1); /* key id */ | 351 | EVP_DigestUpdate(&md, &c, 1); /* key id */ |
349 | EVP_DigestUpdate(&md, hash, mdsz); /* session id */ | 352 | EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); |
350 | EVP_DigestFinal(&md, digest, NULL); | 353 | EVP_DigestFinal(&md, digest, NULL); |
351 | 354 | ||
352 | /* expand */ | 355 | /* expand */ |
@@ -365,26 +368,36 @@ derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret) | |||
365 | return digest; | 368 | return digest; |
366 | } | 369 | } |
367 | 370 | ||
371 | Newkeys *x_newkeys[MODE_MAX]; | ||
372 | |||
368 | #define NKEYS 6 | 373 | #define NKEYS 6 |
369 | void | 374 | void |
370 | kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret) | 375 | kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) |
371 | { | 376 | { |
372 | int i; | 377 | Newkeys *newkeys; |
373 | int mode; | ||
374 | int ctos; | ||
375 | u_char *keys[NKEYS]; | 378 | u_char *keys[NKEYS]; |
379 | int i, mode, ctos; | ||
376 | 380 | ||
377 | for (i = 0; i < NKEYS; i++) | 381 | for (i = 0; i < NKEYS; i++) |
378 | keys[i] = derive_key('A'+i, k->we_need, hash, shared_secret); | 382 | keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret); |
379 | 383 | ||
384 | debug("kex_derive_keys"); | ||
380 | for (mode = 0; mode < MODE_MAX; mode++) { | 385 | for (mode = 0; mode < MODE_MAX; mode++) { |
381 | ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN); | 386 | newkeys = kex->keys[mode]; |
382 | k->enc[mode].iv = keys[ctos ? 0 : 1]; | 387 | ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); |
383 | k->enc[mode].key = keys[ctos ? 2 : 3]; | 388 | newkeys->enc.iv = keys[ctos ? 0 : 1]; |
384 | k->mac[mode].key = keys[ctos ? 4 : 5]; | 389 | newkeys->enc.key = keys[ctos ? 2 : 3]; |
390 | newkeys->mac.key = keys[ctos ? 4 : 5]; | ||
391 | x_newkeys[mode] = newkeys; | ||
385 | } | 392 | } |
386 | } | 393 | } |
387 | 394 | ||
395 | Newkeys * | ||
396 | kex_get_newkeys(int mode) | ||
397 | { | ||
398 | return x_newkeys[mode]; | ||
399 | } | ||
400 | |||
388 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) | 401 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) |
389 | void | 402 | void |
390 | dump_digest(char *msg, u_char *digest, int len) | 403 | dump_digest(char *msg, u_char *digest, int len) |