comparison common-kex.c @ 759:76fba0856749 ecc

More changes for KEX and ECDH. Set up hash descriptors, make ECC code work, ses.hash and ses.session_id are now buffers (doesn't compile)
author Matt Johnston <matt@ucc.asn.au>
date Fri, 29 Mar 2013 00:28:09 +0800
parents 230666086711
children ac2158e3e403
comparison
equal deleted inserted replaced
758:1c607a62d235 759:76fba0856749
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 "random.h"
36 #include "runopts.h" 36 #include "runopts.h"
37 #include "ecc.h"
37 38
38 /* diffie-hellman-group1-sha1 value for p */ 39 /* diffie-hellman-group1-sha1 value for p */
39 const unsigned char dh_p_1[DH_P_1_LEN] = { 40 const unsigned char dh_p_1[DH_P_1_LEN] = {
40 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 41 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
41 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 42 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
640 /* calculate the hash H to sign */ 641 /* calculate the hash H to sign */
641 sha1_init(&hs); 642 sha1_init(&hs);
642 buf_setpos(ses.kexhashbuf, 0); 643 buf_setpos(ses.kexhashbuf, 0);
643 sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len), 644 sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
644 ses.kexhashbuf->len); 645 ses.kexhashbuf->len);
646
647 ses.hash = m_malloc(SHA1_HASH_SIZE);
648 }
645 sha1_done(&hs, ses.hash); 649 sha1_done(&hs, ses.hash);
646 650
647 buf_burn(ses.kexhashbuf); 651 buf_burn(ses.kexhashbuf);
648 buf_free(ses.kexhashbuf); 652 buf_free(ses.kexhashbuf);
649 ses.kexhashbuf = NULL; 653 ses.kexhashbuf = NULL;
658 662
659 #ifdef DROPBEAR_ECDH 663 #ifdef DROPBEAR_ECDH
660 struct kex_ecdh_param *gen_kexecdh_param() { 664 struct kex_ecdh_param *gen_kexecdh_param() {
661 struct kex_ecdh_param *param = m_malloc(sizeof(*param)); 665 struct kex_ecdh_param *param = m_malloc(sizeof(*param));
662 if (ecc_make_key_ex(NULL, dropbear_ltc_prng, 666 if (ecc_make_key_ex(NULL, dropbear_ltc_prng,
663 &param->key, ses.newkeys->algo_kex->ecc_curve) != CRYPT_OK) { 667 &param->key, ses.newkeys->algo_kex->ecc_curve->dp) != CRYPT_OK) {
664 dropbear_exit("ECC error") 668 dropbear_exit("ECC error");
665 } 669 }
666 return param; 670 return param;
667 } 671 }
668 672
669 void free_kexecdh_param(struct kex_ecdh_param *param) { 673 void free_kexecdh_param(struct kex_ecdh_param *param) {
671 m_free(param); 675 m_free(param);
672 676
673 } 677 }
674 void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them, 678 void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them,
675 sign_key *hostkey) { 679 sign_key *hostkey) {
676 680 const struct dropbear_kex *algo_kex = ses.newkeys->algo_kex;
677 hash_state hs; 681 hash_state hs;
678 // public keys from client and server 682 // public keys from client and server
679 ecc_key *Q_C, *Q_S, *Q_them; 683 ecc_key *Q_C, *Q_S, *Q_them;
680 684
681 oj // XXX load Q_them 685 // XXX load Q_them
682 Q_them = buf_get_ecc_key_string() 686 Q_them = buf_get_ecc_pubkey(pub_them, algo_kex->ecc_curve);
683 687
684 ses.dh_K = dropbear_ecc_shared_secret(); 688 ses.dh_K = dropbear_ecc_shared_secret(Q_them, param->key);
685
686 /* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */
687 if (mp_cmp(dh_pub_them, &dh_p) != MP_LT
688 || mp_cmp_d(dh_pub_them, 0) != MP_GT) {
689 dropbear_exit("Diffie-Hellman error");
690 }
691
692 /* K = e^y mod p = f^x mod p */
693 ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int));
694 m_mp_init(ses.dh_K);
695 if (mp_exptmod(dh_pub_them, &param->priv, &dh_p, ses.dh_K) != MP_OKAY) {
696 dropbear_exit("Diffie-Hellman error");
697 }
698
699 /* clear no longer needed vars */
700 mp_clear_multi(&dh_p, NULL);
701 689
702 /* From here on, the code needs to work with the _same_ vars on each side, 690 /* From here on, the code needs to work with the _same_ vars on each side,
703 * not vice-versaing for client/server */ 691 * not vice-versaing for client/server */
704 if (IS_DROPBEAR_CLIENT) { 692 if (IS_DROPBEAR_CLIENT) {
705 dh_e = &param->pub; 693 Q_C = param->key;
706 dh_f = dh_pub_them; 694 Q_S = Q_them;
707 } else { 695 } else {
708 dh_e = dh_pub_them; 696 Q_C = Q_them;
709 dh_f = &param->pub; 697 Q_S = param->key;
710 } 698 }
711 699
712 /* Create the remainder of the hash buffer, to generate the exchange hash */ 700 /* Create the remainder of the hash buffer, to generate the exchange hash */
713 /* K_S, the host key */ 701 /* K_S, the host key */
714 buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey); 702 buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey);
715 /* e, exchange value sent by the client */ 703 /* Q_C, client's ephemeral public key octet string */
716 buf_putmpint(ses.kexhashbuf, dh_e); 704 buf_put_ecc_pubkey_string(Q_C);
717 /* f, exchange value sent by the server */ 705 /* Q_S, server's ephemeral public key octet string */
718 buf_putmpint(ses.kexhashbuf, dh_f); 706 buf_put_ecc_pubkey_string(Q_S);
719 /* K, the shared secret */ 707 /* K, the shared secret */
720 buf_putmpint(ses.kexhashbuf, ses.dh_K); 708 buf_putmpint(ses.kexhashbuf, ses.dh_K);
721 709
722 /* calculate the hash H to sign */ 710 /* calculate the hash H to sign */
723 sha1_init(&hs); 711 algo_kex->hashdesc->init(&hs);
724 buf_setpos(ses.kexhashbuf, 0); 712 buf_setpos(ses.kexhashbuf, 0);
725 sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len), 713 algo_kex->hashdesc->process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
726 ses.kexhashbuf->len); 714 ses.kexhashbuf->len);
727 sha1_done(&hs, ses.hash); 715 if (!ses.hash) {
716 ses.hash = m_malloc(algo_kex->hashdesc->hashsize);
717 }
718 algo_kex->hashdesc->done(&hs, ses.hash);
728 719
729 buf_burn(ses.kexhashbuf); 720 buf_burn(ses.kexhashbuf);
730 buf_free(ses.kexhashbuf); 721 buf_free(ses.kexhashbuf);
731 ses.kexhashbuf = NULL; 722 ses.kexhashbuf = NULL;
732 723
733 /* first time around, we set the session_id to H */ 724 /* first time around, we set the session_id to H */
734 if (ses.session_id == NULL) { 725 if (ses.session_id == NULL) {
735 /* create the session_id, this never needs freeing */ 726 /* create the session_id, this never needs freeing */
736 ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE); 727 ses.session_id = m_malloc(algo_kex->hashdesc->hashsize);
737 memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE); 728 memcpy(ses.session_id, ses.hash, algo_kex->hashdesc->hashsize);
738 } 729 }
739 730
740 } 731 }
741 #endif 732 #endif
742 733