Mercurial > dropbear
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 ¶m->key, ses.newkeys->algo_kex->ecc_curve) != CRYPT_OK) { | 667 ¶m->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, ¶m->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 = ¶m->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 = ¶m->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 |