Mercurial > dropbear
comparison common-kex.c @ 910:89555751c489 asm
merge up to 2013.63, improve ASM makefile rules a bit
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 27 Feb 2014 21:35:58 +0800 |
parents | 4a74c58e11fc |
children | 7cd89d4e0335 |
comparison
equal
deleted
inserted
replaced
909:e4b75744acab | 910:89555751c489 |
---|---|
30 #include "session.h" | 30 #include "session.h" |
31 #include "kex.h" | 31 #include "kex.h" |
32 #include "ssh.h" | 32 #include "ssh.h" |
33 #include "packet.h" | 33 #include "packet.h" |
34 #include "bignum.h" | 34 #include "bignum.h" |
35 #include "random.h" | 35 #include "dbrandom.h" |
36 #include "runopts.h" | 36 #include "runopts.h" |
37 #include "ecc.h" | |
38 #include "crypto_desc.h" | |
37 | 39 |
38 /* diffie-hellman-group1-sha1 value for p */ | 40 /* diffie-hellman-group1-sha1 value for p */ |
39 #define DH_P_1_LEN 128 | 41 const unsigned char dh_p_1[DH_P_1_LEN] = { |
40 static const unsigned char dh_p_1[DH_P_1_LEN] = { | |
41 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, | 42 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, |
42 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, | 43 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, |
43 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, | 44 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, |
44 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, | 45 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, |
45 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, | 46 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, |
49 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, | 50 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, |
50 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, | 51 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, |
51 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | 52 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
52 | 53 |
53 /* diffie-hellman-group14-sha1 value for p */ | 54 /* diffie-hellman-group14-sha1 value for p */ |
54 #define DH_P_14_LEN 256 | 55 const unsigned char dh_p_14[DH_P_14_LEN] = { |
55 static const unsigned char dh_p_14[DH_P_14_LEN] = { | |
56 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, | 56 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, |
57 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, | 57 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, |
58 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, | 58 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, |
59 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, | 59 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, |
60 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, | 60 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, |
85 static void gen_new_zstream_recv(); | 85 static void gen_new_zstream_recv(); |
86 static void gen_new_zstream_trans(); | 86 static void gen_new_zstream_trans(); |
87 #endif | 87 #endif |
88 static void read_kex_algos(); | 88 static void read_kex_algos(); |
89 /* helper function for gen_new_keys */ | 89 /* helper function for gen_new_keys */ |
90 static void hashkeys(unsigned char *out, int outlen, | 90 static void hashkeys(unsigned char *out, unsigned int outlen, |
91 const hash_state * hs, unsigned const char X); | 91 const hash_state * hs, const unsigned char X); |
92 static void finish_kexhashbuf(void); | |
92 | 93 |
93 | 94 |
94 /* Send our list of algorithms we can use */ | 95 /* Send our list of algorithms we can use */ |
95 void send_msg_kexinit() { | 96 void send_msg_kexinit() { |
96 | 97 |
148 ses.kexstate.sentkexinit = 1; | 149 ses.kexstate.sentkexinit = 1; |
149 | 150 |
150 ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); | 151 ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); |
151 | 152 |
152 if (ses.send_kex_first_guess) { | 153 if (ses.send_kex_first_guess) { |
153 ses.newkeys->algo_kex = sshkex[0].val; | 154 ses.newkeys->algo_kex = sshkex[0].data; |
154 ses.newkeys->algo_hostkey = sshhostkey[0].val; | 155 ses.newkeys->algo_hostkey = sshhostkey[0].val; |
155 ses.send_kex_first_guess(); | 156 ses.send_kex_first_guess(); |
156 } | 157 } |
157 | 158 |
158 TRACE(("DATAALLOWED=0")) | 159 TRACE(("DATAALLOWED=0")) |
277 * already initialised hash_state hs, which should already have processed | 278 * already initialised hash_state hs, which should already have processed |
278 * the dh_K and hash, since these are common. X is the letter 'A', 'B' etc. | 279 * the dh_K and hash, since these are common. X is the letter 'A', 'B' etc. |
279 * out must have at least min(SHA1_HASH_SIZE, outlen) bytes allocated. | 280 * out must have at least min(SHA1_HASH_SIZE, outlen) bytes allocated. |
280 * | 281 * |
281 * See Section 7.2 of rfc4253 (ssh transport) for details */ | 282 * See Section 7.2 of rfc4253 (ssh transport) for details */ |
282 static void hashkeys(unsigned char *out, int outlen, | 283 static void hashkeys(unsigned char *out, unsigned int outlen, |
283 const hash_state * hs, const unsigned char X) { | 284 const hash_state * hs, const unsigned char X) { |
284 | 285 |
286 const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc; | |
285 hash_state hs2; | 287 hash_state hs2; |
286 int offset; | 288 unsigned int offset; |
289 unsigned char tmpout[MAX_HASH_SIZE]; | |
287 | 290 |
288 memcpy(&hs2, hs, sizeof(hash_state)); | 291 memcpy(&hs2, hs, sizeof(hash_state)); |
289 sha1_process(&hs2, &X, 1); | 292 hash_desc->process(&hs2, &X, 1); |
290 sha1_process(&hs2, ses.session_id, SHA1_HASH_SIZE); | 293 hash_desc->process(&hs2, ses.session_id->data, ses.session_id->len); |
291 sha1_done(&hs2, out); | 294 hash_desc->done(&hs2, tmpout); |
292 for (offset = SHA1_HASH_SIZE; | 295 memcpy(out, tmpout, MIN(hash_desc->hashsize, outlen)); |
296 for (offset = hash_desc->hashsize; | |
293 offset < outlen; | 297 offset < outlen; |
294 offset += SHA1_HASH_SIZE) | 298 offset += hash_desc->hashsize) |
295 { | 299 { |
296 /* need to extend */ | 300 /* need to extend */ |
297 unsigned char k2[SHA1_HASH_SIZE]; | |
298 memcpy(&hs2, hs, sizeof(hash_state)); | 301 memcpy(&hs2, hs, sizeof(hash_state)); |
299 sha1_process(&hs2, out, offset); | 302 hash_desc->process(&hs2, out, offset); |
300 sha1_done(&hs2, k2); | 303 hash_desc->done(&hs2, tmpout); |
301 memcpy(&out[offset], k2, MIN(outlen - offset, SHA1_HASH_SIZE)); | 304 memcpy(&out[offset], tmpout, MIN(outlen - offset, hash_desc->hashsize)); |
302 } | 305 } |
306 | |
303 } | 307 } |
304 | 308 |
305 /* Generate the actual encryption/integrity keys, using the results of the | 309 /* Generate the actual encryption/integrity keys, using the results of the |
306 * key exchange, as specified in section 7.2 of the transport rfc 4253. | 310 * key exchange, as specified in section 7.2 of the transport rfc 4253. |
307 * This occurs after the DH key-exchange. | 311 * This occurs after the DH key-exchange. |
317 unsigned char S2C_key[MAX_KEY_LEN]; | 321 unsigned char S2C_key[MAX_KEY_LEN]; |
318 /* unsigned char key[MAX_KEY_LEN]; */ | 322 /* unsigned char key[MAX_KEY_LEN]; */ |
319 unsigned char *trans_IV, *trans_key, *recv_IV, *recv_key; | 323 unsigned char *trans_IV, *trans_key, *recv_IV, *recv_key; |
320 | 324 |
321 hash_state hs; | 325 hash_state hs; |
322 unsigned int C2S_keysize, S2C_keysize; | 326 const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc; |
323 char mactransletter, macrecvletter; /* Client or server specific */ | 327 char mactransletter, macrecvletter; /* Client or server specific */ |
324 | 328 |
325 TRACE(("enter gen_new_keys")) | 329 TRACE(("enter gen_new_keys")) |
326 /* the dh_K and hash are the start of all hashes, we make use of that */ | 330 /* the dh_K and hash are the start of all hashes, we make use of that */ |
327 | 331 |
328 sha1_init(&hs); | 332 hash_desc->init(&hs); |
329 sha1_process_mp(&hs, ses.dh_K); | 333 hash_process_mp(hash_desc, &hs, ses.dh_K); |
330 mp_clear(ses.dh_K); | 334 mp_clear(ses.dh_K); |
331 m_free(ses.dh_K); | 335 m_free(ses.dh_K); |
332 sha1_process(&hs, ses.hash, SHA1_HASH_SIZE); | 336 hash_desc->process(&hs, ses.hash->data, ses.hash->len); |
333 m_burn(ses.hash, SHA1_HASH_SIZE); | 337 buf_burn(ses.hash); |
338 buf_free(ses.hash); | |
339 ses.hash = NULL; | |
334 | 340 |
335 if (IS_DROPBEAR_CLIENT) { | 341 if (IS_DROPBEAR_CLIENT) { |
336 trans_IV = C2S_IV; | 342 trans_IV = C2S_IV; |
337 recv_IV = S2C_IV; | 343 recv_IV = S2C_IV; |
338 trans_key = C2S_key; | 344 trans_key = C2S_key; |
339 recv_key = S2C_key; | 345 recv_key = S2C_key; |
340 C2S_keysize = ses.newkeys->trans.algo_crypt->keysize; | |
341 S2C_keysize = ses.newkeys->recv.algo_crypt->keysize; | |
342 mactransletter = 'E'; | 346 mactransletter = 'E'; |
343 macrecvletter = 'F'; | 347 macrecvletter = 'F'; |
344 } else { | 348 } else { |
345 trans_IV = S2C_IV; | 349 trans_IV = S2C_IV; |
346 recv_IV = C2S_IV; | 350 recv_IV = C2S_IV; |
347 trans_key = S2C_key; | 351 trans_key = S2C_key; |
348 recv_key = C2S_key; | 352 recv_key = C2S_key; |
349 C2S_keysize = ses.newkeys->recv.algo_crypt->keysize; | |
350 S2C_keysize = ses.newkeys->trans.algo_crypt->keysize; | |
351 mactransletter = 'F'; | 353 mactransletter = 'F'; |
352 macrecvletter = 'E'; | 354 macrecvletter = 'E'; |
353 } | 355 } |
354 | 356 |
355 hashkeys(C2S_IV, SHA1_HASH_SIZE, &hs, 'A'); | 357 hashkeys(C2S_IV, sizeof(C2S_IV), &hs, 'A'); |
356 hashkeys(S2C_IV, SHA1_HASH_SIZE, &hs, 'B'); | 358 hashkeys(S2C_IV, sizeof(S2C_IV), &hs, 'B'); |
357 hashkeys(C2S_key, C2S_keysize, &hs, 'C'); | 359 hashkeys(C2S_key, sizeof(C2S_key), &hs, 'C'); |
358 hashkeys(S2C_key, S2C_keysize, &hs, 'D'); | 360 hashkeys(S2C_key, sizeof(S2C_key), &hs, 'D'); |
359 | 361 |
360 if (ses.newkeys->recv.algo_crypt->cipherdesc != NULL) { | 362 if (ses.newkeys->recv.algo_crypt->cipherdesc != NULL) { |
361 int recv_cipher = find_cipher(ses.newkeys->recv.algo_crypt->cipherdesc->name); | 363 int recv_cipher = find_cipher(ses.newkeys->recv.algo_crypt->cipherdesc->name); |
362 if (recv_cipher < 0) | 364 if (recv_cipher < 0) |
363 dropbear_exit("Crypto error"); | 365 dropbear_exit("Crypto error"); |
379 &ses.newkeys->trans.cipher_state) != CRYPT_OK) { | 381 &ses.newkeys->trans.cipher_state) != CRYPT_OK) { |
380 dropbear_exit("Crypto error"); | 382 dropbear_exit("Crypto error"); |
381 } | 383 } |
382 } | 384 } |
383 | 385 |
384 if (ses.newkeys->trans.algo_mac->hashdesc != NULL) { | 386 if (ses.newkeys->trans.algo_mac->hash_desc != NULL) { |
385 hashkeys(ses.newkeys->trans.mackey, | 387 hashkeys(ses.newkeys->trans.mackey, |
386 ses.newkeys->trans.algo_mac->keysize, &hs, mactransletter); | 388 ses.newkeys->trans.algo_mac->keysize, &hs, mactransletter); |
387 ses.newkeys->trans.hash_index = find_hash(ses.newkeys->trans.algo_mac->hashdesc->name); | 389 ses.newkeys->trans.hash_index = find_hash(ses.newkeys->trans.algo_mac->hash_desc->name); |
388 } | 390 } |
389 | 391 |
390 if (ses.newkeys->recv.algo_mac->hashdesc != NULL) { | 392 if (ses.newkeys->recv.algo_mac->hash_desc != NULL) { |
391 hashkeys(ses.newkeys->recv.mackey, | 393 hashkeys(ses.newkeys->recv.mackey, |
392 ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter); | 394 ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter); |
393 ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hashdesc->name); | 395 ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hash_desc->name); |
394 } | 396 } |
395 | 397 |
396 /* Ready to switch over */ | 398 /* Ready to switch over */ |
397 ses.newkeys->trans.valid = 1; | 399 ses.newkeys->trans.valid = 1; |
398 ses.newkeys->recv.valid = 1; | 400 ses.newkeys->recv.valid = 1; |
479 * key exchange. If we haven't already done so, we send the list of our | 481 * key exchange. If we haven't already done so, we send the list of our |
480 * preferred algorithms. The client's requested algorithms are processed, | 482 * preferred algorithms. The client's requested algorithms are processed, |
481 * and we calculate the first portion of the key-exchange-hash for used | 483 * and we calculate the first portion of the key-exchange-hash for used |
482 * later in the key exchange. No response is sent, as the client should | 484 * later in the key exchange. No response is sent, as the client should |
483 * initiate the diffie-hellman key exchange */ | 485 * initiate the diffie-hellman key exchange */ |
484 | |
485 /* Originally from kex.c, generalized for cli/svr mode --mihnea */ | |
486 /* Belongs in common_kex.c where it should be moved after review */ | |
487 void recv_msg_kexinit() { | 486 void recv_msg_kexinit() { |
488 | 487 |
489 unsigned int kexhashbuf_len = 0; | 488 unsigned int kexhashbuf_len = 0; |
490 unsigned int remote_ident_len = 0; | 489 unsigned int remote_ident_len = 0; |
491 unsigned int local_ident_len = 0; | 490 unsigned int local_ident_len = 0; |
524 buf_putstring(ses.kexhashbuf, | 523 buf_putstring(ses.kexhashbuf, |
525 ses.transkexinit->data, ses.transkexinit->len); | 524 ses.transkexinit->data, ses.transkexinit->len); |
526 /* I_S, the payload of the server's SSH_MSG_KEXINIT */ | 525 /* I_S, the payload of the server's SSH_MSG_KEXINIT */ |
527 buf_setpos(ses.payload, 0); | 526 buf_setpos(ses.payload, 0); |
528 buf_putstring(ses.kexhashbuf, ses.payload->data, ses.payload->len); | 527 buf_putstring(ses.kexhashbuf, ses.payload->data, ses.payload->len); |
529 | 528 ses.requirenext = SSH_MSG_KEXDH_REPLY; |
530 } else { | 529 } else { |
531 /* SERVER */ | 530 /* SERVER */ |
532 | 531 |
533 /* read the peer's choice of algos */ | 532 /* read the peer's choice of algos */ |
534 read_kex_algos(); | 533 read_kex_algos(); |
544 | 543 |
545 /* I_S, the payload of the server's SSH_MSG_KEXINIT */ | 544 /* I_S, the payload of the server's SSH_MSG_KEXINIT */ |
546 buf_putstring(ses.kexhashbuf, | 545 buf_putstring(ses.kexhashbuf, |
547 ses.transkexinit->data, ses.transkexinit->len); | 546 ses.transkexinit->data, ses.transkexinit->len); |
548 | 547 |
549 ses.requirenext[0] = SSH_MSG_KEXDH_INIT; | 548 ses.requirenext = SSH_MSG_KEXDH_INIT; |
550 } | 549 } |
551 | 550 |
552 buf_free(ses.transkexinit); | 551 buf_free(ses.transkexinit); |
553 ses.transkexinit = NULL; | 552 ses.transkexinit = NULL; |
554 /* the rest of ses.kexhashbuf will be done after DH exchange */ | 553 /* the rest of ses.kexhashbuf will be done after DH exchange */ |
558 TRACE(("leave recv_msg_kexinit")) | 557 TRACE(("leave recv_msg_kexinit")) |
559 } | 558 } |
560 | 559 |
561 static void load_dh_p(mp_int * dh_p) | 560 static void load_dh_p(mp_int * dh_p) |
562 { | 561 { |
563 switch (ses.newkeys->algo_kex) { | 562 bytes_to_mp(dh_p, ses.newkeys->algo_kex->dh_p_bytes, |
564 case DROPBEAR_KEX_DH_GROUP1: | 563 ses.newkeys->algo_kex->dh_p_len); |
565 bytes_to_mp(dh_p, dh_p_1, DH_P_1_LEN); | |
566 break; | |
567 case DROPBEAR_KEX_DH_GROUP14: | |
568 bytes_to_mp(dh_p, dh_p_14, DH_P_14_LEN); | |
569 break; | |
570 } | |
571 } | 564 } |
572 | 565 |
573 /* Initialises and generate one side of the diffie-hellman key exchange values. | 566 /* Initialises and generate one side of the diffie-hellman key exchange values. |
574 * See the transport rfc 4253 section 8 for details */ | 567 * See the transport rfc 4253 section 8 for details */ |
575 /* dh_pub and dh_priv MUST be already initialised */ | 568 /* dh_pub and dh_priv MUST be already initialised */ |
576 void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) { | 569 struct kex_dh_param *gen_kexdh_param() { |
570 struct kex_dh_param *param = NULL; | |
577 | 571 |
578 DEF_MP_INT(dh_p); | 572 DEF_MP_INT(dh_p); |
579 DEF_MP_INT(dh_q); | 573 DEF_MP_INT(dh_q); |
580 DEF_MP_INT(dh_g); | 574 DEF_MP_INT(dh_g); |
581 | 575 |
582 TRACE(("enter gen_kexdh_vals")) | 576 TRACE(("enter gen_kexdh_vals")) |
583 | 577 |
584 m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL); | 578 param = m_malloc(sizeof(*param)); |
579 m_mp_init_multi(¶m->pub, ¶m->priv, &dh_g, &dh_p, &dh_q, NULL); | |
585 | 580 |
586 /* read the prime and generator*/ | 581 /* read the prime and generator*/ |
587 load_dh_p(&dh_p); | 582 load_dh_p(&dh_p); |
588 | 583 |
589 if (mp_set_int(&dh_g, DH_G_VAL) != MP_OKAY) { | 584 if (mp_set_int(&dh_g, DH_G_VAL) != MP_OKAY) { |
590 dropbear_exit("Diffie-Hellman error"); | 585 dropbear_exit("Diffie-Hellman error"); |
591 } | 586 } |
592 | 587 |
593 /* calculate q = (p-1)/2 */ | 588 /* calculate q = (p-1)/2 */ |
594 /* dh_priv is just a temp var here */ | 589 /* dh_priv is just a temp var here */ |
595 if (mp_sub_d(&dh_p, 1, dh_priv) != MP_OKAY) { | 590 if (mp_sub_d(&dh_p, 1, ¶m->priv) != MP_OKAY) { |
596 dropbear_exit("Diffie-Hellman error"); | 591 dropbear_exit("Diffie-Hellman error"); |
597 } | 592 } |
598 if (mp_div_2(dh_priv, &dh_q) != MP_OKAY) { | 593 if (mp_div_2(¶m->priv, &dh_q) != MP_OKAY) { |
599 dropbear_exit("Diffie-Hellman error"); | 594 dropbear_exit("Diffie-Hellman error"); |
600 } | 595 } |
601 | 596 |
602 /* Generate a private portion 0 < dh_priv < dh_q */ | 597 /* Generate a private portion 0 < dh_priv < dh_q */ |
603 gen_random_mpint(&dh_q, dh_priv); | 598 gen_random_mpint(&dh_q, ¶m->priv); |
604 | 599 |
605 /* f = g^y mod p */ | 600 /* f = g^y mod p */ |
606 if (mp_exptmod(&dh_g, dh_priv, &dh_p, dh_pub) != MP_OKAY) { | 601 if (mp_exptmod(&dh_g, ¶m->priv, &dh_p, ¶m->pub) != MP_OKAY) { |
607 dropbear_exit("Diffie-Hellman error"); | 602 dropbear_exit("Diffie-Hellman error"); |
608 } | 603 } |
609 mp_clear_multi(&dh_g, &dh_p, &dh_q, NULL); | 604 mp_clear_multi(&dh_g, &dh_p, &dh_q, NULL); |
605 return param; | |
606 } | |
607 | |
608 void free_kexdh_param(struct kex_dh_param *param) | |
609 { | |
610 mp_clear_multi(¶m->pub, ¶m->priv, NULL); | |
611 m_free(param); | |
610 } | 612 } |
611 | 613 |
612 /* This function is fairly common between client/server, with some substitution | 614 /* This function is fairly common between client/server, with some substitution |
613 * of dh_e/dh_f etc. Hence these arguments: | 615 * of dh_e/dh_f etc. Hence these arguments: |
614 * dh_pub_us is 'e' for the client, 'f' for the server. dh_pub_them is | 616 * dh_pub_us is 'e' for the client, 'f' for the server. dh_pub_them is |
615 * vice-versa. dh_priv is the x/y value corresponding to dh_pub_us */ | 617 * vice-versa. dh_priv is the x/y value corresponding to dh_pub_us */ |
616 void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them, | 618 void kexdh_comb_key(struct kex_dh_param *param, mp_int *dh_pub_them, |
617 sign_key *hostkey) { | 619 sign_key *hostkey) { |
618 | 620 |
619 mp_int dh_p; | 621 mp_int dh_p; |
620 mp_int *dh_e = NULL, *dh_f = NULL; | 622 mp_int *dh_e = NULL, *dh_f = NULL; |
621 hash_state hs; | |
622 | 623 |
623 /* read the prime and generator*/ | 624 /* read the prime and generator*/ |
624 m_mp_init(&dh_p); | 625 m_mp_init(&dh_p); |
625 load_dh_p(&dh_p); | 626 load_dh_p(&dh_p); |
626 | 627 |
629 || mp_cmp_d(dh_pub_them, 0) != MP_GT) { | 630 || mp_cmp_d(dh_pub_them, 0) != MP_GT) { |
630 dropbear_exit("Diffie-Hellman error"); | 631 dropbear_exit("Diffie-Hellman error"); |
631 } | 632 } |
632 | 633 |
633 /* K = e^y mod p = f^x mod p */ | 634 /* K = e^y mod p = f^x mod p */ |
634 ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int)); | 635 m_mp_alloc_init_multi(&ses.dh_K, NULL); |
635 m_mp_init(ses.dh_K); | 636 if (mp_exptmod(dh_pub_them, ¶m->priv, &dh_p, ses.dh_K) != MP_OKAY) { |
636 if (mp_exptmod(dh_pub_them, dh_priv, &dh_p, ses.dh_K) != MP_OKAY) { | |
637 dropbear_exit("Diffie-Hellman error"); | 637 dropbear_exit("Diffie-Hellman error"); |
638 } | 638 } |
639 | 639 |
640 /* clear no longer needed vars */ | 640 /* clear no longer needed vars */ |
641 mp_clear_multi(&dh_p, NULL); | 641 mp_clear_multi(&dh_p, NULL); |
642 | 642 |
643 /* From here on, the code needs to work with the _same_ vars on each side, | 643 /* From here on, the code needs to work with the _same_ vars on each side, |
644 * not vice-versaing for client/server */ | 644 * not vice-versaing for client/server */ |
645 if (IS_DROPBEAR_CLIENT) { | 645 if (IS_DROPBEAR_CLIENT) { |
646 dh_e = dh_pub_us; | 646 dh_e = ¶m->pub; |
647 dh_f = dh_pub_them; | 647 dh_f = dh_pub_them; |
648 } else { | 648 } else { |
649 dh_e = dh_pub_them; | 649 dh_e = dh_pub_them; |
650 dh_f = dh_pub_us; | 650 dh_f = ¶m->pub; |
651 } | 651 } |
652 | 652 |
653 /* Create the remainder of the hash buffer, to generate the exchange hash */ | 653 /* Create the remainder of the hash buffer, to generate the exchange hash */ |
654 /* K_S, the host key */ | 654 /* K_S, the host key */ |
655 buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey); | 655 buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey); |
659 buf_putmpint(ses.kexhashbuf, dh_f); | 659 buf_putmpint(ses.kexhashbuf, dh_f); |
660 /* K, the shared secret */ | 660 /* K, the shared secret */ |
661 buf_putmpint(ses.kexhashbuf, ses.dh_K); | 661 buf_putmpint(ses.kexhashbuf, ses.dh_K); |
662 | 662 |
663 /* calculate the hash H to sign */ | 663 /* calculate the hash H to sign */ |
664 sha1_init(&hs); | 664 finish_kexhashbuf(); |
665 } | |
666 | |
667 #ifdef DROPBEAR_ECDH | |
668 struct kex_ecdh_param *gen_kexecdh_param() { | |
669 struct kex_ecdh_param *param = m_malloc(sizeof(*param)); | |
670 if (ecc_make_key_ex(NULL, dropbear_ltc_prng, | |
671 ¶m->key, ses.newkeys->algo_kex->ecc_curve->dp) != CRYPT_OK) { | |
672 dropbear_exit("ECC error"); | |
673 } | |
674 return param; | |
675 } | |
676 | |
677 void free_kexecdh_param(struct kex_ecdh_param *param) { | |
678 ecc_free(¶m->key); | |
679 m_free(param); | |
680 | |
681 } | |
682 void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them, | |
683 sign_key *hostkey) { | |
684 const struct dropbear_kex *algo_kex = ses.newkeys->algo_kex; | |
685 /* public keys from client and server */ | |
686 ecc_key *Q_C, *Q_S, *Q_them; | |
687 | |
688 Q_them = buf_get_ecc_raw_pubkey(pub_them, algo_kex->ecc_curve); | |
689 | |
690 ses.dh_K = dropbear_ecc_shared_secret(Q_them, ¶m->key); | |
691 | |
692 /* Create the remainder of the hash buffer, to generate the exchange hash | |
693 See RFC5656 section 4 page 7 */ | |
694 if (IS_DROPBEAR_CLIENT) { | |
695 Q_C = ¶m->key; | |
696 Q_S = Q_them; | |
697 } else { | |
698 Q_C = Q_them; | |
699 Q_S = ¶m->key; | |
700 } | |
701 | |
702 /* K_S, the host key */ | |
703 buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey); | |
704 /* Q_C, client's ephemeral public key octet string */ | |
705 buf_put_ecc_raw_pubkey_string(ses.kexhashbuf, Q_C); | |
706 /* Q_S, server's ephemeral public key octet string */ | |
707 buf_put_ecc_raw_pubkey_string(ses.kexhashbuf, Q_S); | |
708 /* K, the shared secret */ | |
709 buf_putmpint(ses.kexhashbuf, ses.dh_K); | |
710 | |
711 /* calculate the hash H to sign */ | |
712 finish_kexhashbuf(); | |
713 } | |
714 #endif /* DROPBEAR_ECDH */ | |
715 | |
716 #ifdef DROPBEAR_CURVE25519 | |
717 struct kex_curve25519_param *gen_kexcurve25519_param () { | |
718 /* Per http://cr.yp.to/ecdh.html */ | |
719 struct kex_curve25519_param *param = m_malloc(sizeof(*param)); | |
720 const unsigned char basepoint[32] = {9}; | |
721 | |
722 genrandom(param->priv, CURVE25519_LEN); | |
723 param->priv[0] &= 248; | |
724 param->priv[31] &= 127; | |
725 param->priv[31] |= 64; | |
726 | |
727 curve25519_donna(param->pub, param->priv, basepoint); | |
728 | |
729 return param; | |
730 } | |
731 | |
732 void free_kexcurve25519_param(struct kex_curve25519_param *param) | |
733 { | |
734 m_burn(param->priv, CURVE25519_LEN); | |
735 m_free(param); | |
736 } | |
737 | |
738 void kexcurve25519_comb_key(struct kex_curve25519_param *param, buffer *buf_pub_them, | |
739 sign_key *hostkey) { | |
740 unsigned char out[CURVE25519_LEN]; | |
741 const unsigned char* Q_C = NULL; | |
742 const unsigned char* Q_S = NULL; | |
743 | |
744 if (buf_pub_them->len != CURVE25519_LEN) | |
745 { | |
746 dropbear_exit("Bad curve25519"); | |
747 } | |
748 | |
749 curve25519_donna(out, param->priv, buf_pub_them->data); | |
750 m_mp_alloc_init_multi(&ses.dh_K, NULL); | |
751 bytes_to_mp(ses.dh_K, out, CURVE25519_LEN); | |
752 m_burn(out, sizeof(out)); | |
753 | |
754 /* Create the remainder of the hash buffer, to generate the exchange hash. | |
755 See RFC5656 section 4 page 7 */ | |
756 if (IS_DROPBEAR_CLIENT) { | |
757 Q_C = param->pub; | |
758 Q_S = buf_pub_them->data; | |
759 } else { | |
760 Q_S = param->pub; | |
761 Q_C = buf_pub_them->data; | |
762 } | |
763 | |
764 /* K_S, the host key */ | |
765 buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey); | |
766 /* Q_C, client's ephemeral public key octet string */ | |
767 buf_putstring(ses.kexhashbuf, Q_C, CURVE25519_LEN); | |
768 /* Q_S, server's ephemeral public key octet string */ | |
769 buf_putstring(ses.kexhashbuf, Q_S, CURVE25519_LEN); | |
770 /* K, the shared secret */ | |
771 buf_putmpint(ses.kexhashbuf, ses.dh_K); | |
772 | |
773 /* calculate the hash H to sign */ | |
774 finish_kexhashbuf(); | |
775 } | |
776 #endif /* DROPBEAR_CURVE25519 */ | |
777 | |
778 | |
779 | |
780 static void finish_kexhashbuf(void) { | |
781 hash_state hs; | |
782 const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc; | |
783 | |
784 hash_desc->init(&hs); | |
665 buf_setpos(ses.kexhashbuf, 0); | 785 buf_setpos(ses.kexhashbuf, 0); |
666 sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len), | 786 hash_desc->process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len), |
667 ses.kexhashbuf->len); | 787 ses.kexhashbuf->len); |
668 sha1_done(&hs, ses.hash); | 788 ses.hash = buf_new(hash_desc->hashsize); |
789 hash_desc->done(&hs, buf_getwriteptr(ses.hash, hash_desc->hashsize)); | |
790 buf_setlen(ses.hash, hash_desc->hashsize); | |
791 | |
792 #if defined(DEBUG_KEXHASH) && defined(DEBUG_TRACE) | |
793 if (!debug_trace) { | |
794 printhex("kexhashbuf", ses.kexhashbuf->data, ses.kexhashbuf->len); | |
795 printhex("kexhash", ses.hash->data, ses.hash->len); | |
796 } | |
797 #endif | |
669 | 798 |
670 buf_burn(ses.kexhashbuf); | 799 buf_burn(ses.kexhashbuf); |
671 buf_free(ses.kexhashbuf); | 800 buf_free(ses.kexhashbuf); |
672 ses.kexhashbuf = NULL; | 801 ses.kexhashbuf = NULL; |
673 | 802 |
674 /* first time around, we set the session_id to H */ | 803 /* first time around, we set the session_id to H */ |
675 if (ses.session_id == NULL) { | 804 if (ses.session_id == NULL) { |
676 /* create the session_id, this never needs freeing */ | 805 /* create the session_id, this never needs freeing */ |
677 ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE); | 806 ses.session_id = buf_newcopy(ses.hash); |
678 memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE); | 807 } |
679 } | 808 |
680 } | 809 } |
681 | 810 |
682 /* read the other side's algo list. buf_match_algo is a callback to match | 811 /* read the other side's algo list. buf_match_algo is a callback to match |
683 * algos for the client or server. */ | 812 * algos for the client or server. */ |
684 static void read_kex_algos() { | 813 static void read_kex_algos() { |
698 | 827 |
699 int goodguess = 0; | 828 int goodguess = 0; |
700 int allgood = 1; /* we AND this with each goodguess and see if its still | 829 int allgood = 1; /* we AND this with each goodguess and see if its still |
701 true after */ | 830 true after */ |
702 | 831 |
703 buf_incrpos(ses.payload, 16); /* start after the cookie */ | |
704 | |
705 memset(ses.newkeys, 0x0, sizeof(*ses.newkeys)); | |
706 | |
707 #ifdef USE_KEXGUESS2 | 832 #ifdef USE_KEXGUESS2 |
708 enum kexguess2_used kexguess2 = KEXGUESS2_LOOK; | 833 enum kexguess2_used kexguess2 = KEXGUESS2_LOOK; |
709 #else | 834 #else |
710 enum kexguess2_used kexguess2 = KEXGUESS2_NO; | 835 enum kexguess2_used kexguess2 = KEXGUESS2_NO; |
711 #endif | 836 #endif |
837 | |
838 buf_incrpos(ses.payload, 16); /* start after the cookie */ | |
839 | |
840 memset(ses.newkeys, 0x0, sizeof(*ses.newkeys)); | |
712 | 841 |
713 /* kex_algorithms */ | 842 /* kex_algorithms */ |
714 algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess); | 843 algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess); |
715 allgood &= goodguess; | 844 allgood &= goodguess; |
716 if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) { | 845 if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) { |
717 erralgo = "kex"; | 846 erralgo = "kex"; |
718 goto error; | 847 goto error; |
719 } | 848 } |
720 TRACE(("kexguess2 %d", kexguess2)) | 849 TRACE(("kexguess2 %d", kexguess2)) |
721 TRACE(("kex algo %s", algo->name)) | 850 TRACE(("kex algo %s", algo->name)) |
722 ses.newkeys->algo_kex = algo->val; | 851 ses.newkeys->algo_kex = algo->data; |
723 | 852 |
724 /* server_host_key_algorithms */ | 853 /* server_host_key_algorithms */ |
725 algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess); | 854 algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess); |
726 allgood &= goodguess; | 855 allgood &= goodguess; |
727 if (algo == NULL) { | 856 if (algo == NULL) { |