comparison common-kex.c @ 761:ac2158e3e403 ecc

ecc kind of works, needs fixing/testing
author Matt Johnston <matt@ucc.asn.au>
date Sun, 07 Apr 2013 01:36:42 +0800
parents 76fba0856749
children a78a38e402d1
comparison
equal deleted inserted replaced
760:f336d232fc63 761:ac2158e3e403
85 #endif 85 #endif
86 static void read_kex_algos(); 86 static void read_kex_algos();
87 /* helper function for gen_new_keys */ 87 /* helper function for gen_new_keys */
88 static void hashkeys(unsigned char *out, int outlen, 88 static void hashkeys(unsigned char *out, int outlen,
89 const hash_state * hs, unsigned const char X); 89 const hash_state * hs, unsigned const char X);
90 static void finish_kexhashbuf(void);
90 91
91 92
92 /* Send our list of algorithms we can use */ 93 /* Send our list of algorithms we can use */
93 void send_msg_kexinit() { 94 void send_msg_kexinit() {
94 95
256 hash_state hs2; 257 hash_state hs2;
257 int offset; 258 int offset;
258 259
259 memcpy(&hs2, hs, sizeof(hash_state)); 260 memcpy(&hs2, hs, sizeof(hash_state));
260 sha1_process(&hs2, &X, 1); 261 sha1_process(&hs2, &X, 1);
261 sha1_process(&hs2, ses.session_id, SHA1_HASH_SIZE); 262 sha1_process(&hs2, ses.session_id->data, ses.session_id->len);
262 sha1_done(&hs2, out); 263 sha1_done(&hs2, out);
263 for (offset = SHA1_HASH_SIZE; 264 for (offset = SHA1_HASH_SIZE;
264 offset < outlen; 265 offset < outlen;
265 offset += SHA1_HASH_SIZE) 266 offset += SHA1_HASH_SIZE)
266 { 267 {
299 300
300 sha1_init(&hs); 301 sha1_init(&hs);
301 sha1_process_mp(&hs, ses.dh_K); 302 sha1_process_mp(&hs, ses.dh_K);
302 mp_clear(ses.dh_K); 303 mp_clear(ses.dh_K);
303 m_free(ses.dh_K); 304 m_free(ses.dh_K);
304 sha1_process(&hs, ses.hash, SHA1_HASH_SIZE); 305 sha1_process(&hs, ses.hash->data, ses.hash->len);
305 m_burn(ses.hash, SHA1_HASH_SIZE); 306 buf_burn(ses.hash);
307 buf_free(ses.hash);
308 ses.hash = NULL;
306 309
307 if (IS_DROPBEAR_CLIENT) { 310 if (IS_DROPBEAR_CLIENT) {
308 trans_IV = C2S_IV; 311 trans_IV = C2S_IV;
309 recv_IV = S2C_IV; 312 recv_IV = S2C_IV;
310 trans_key = C2S_key; 313 trans_key = C2S_key;
594 sign_key *hostkey) { 597 sign_key *hostkey) {
595 598
596 mp_int dh_p; 599 mp_int dh_p;
597 mp_int *dh_e = NULL, *dh_f = NULL; 600 mp_int *dh_e = NULL, *dh_f = NULL;
598 601
599 hash_state hs;
600
601 /* read the prime and generator*/ 602 /* read the prime and generator*/
602 m_mp_init(&dh_p); 603 m_mp_init(&dh_p);
603 load_dh_p(&dh_p); 604 load_dh_p(&dh_p);
604 605
605 /* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */ 606 /* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */
637 buf_putmpint(ses.kexhashbuf, dh_f); 638 buf_putmpint(ses.kexhashbuf, dh_f);
638 /* K, the shared secret */ 639 /* K, the shared secret */
639 buf_putmpint(ses.kexhashbuf, ses.dh_K); 640 buf_putmpint(ses.kexhashbuf, ses.dh_K);
640 641
641 /* calculate the hash H to sign */ 642 /* calculate the hash H to sign */
642 sha1_init(&hs); 643 finish_kexhashbuf();
644 }
645
646 #ifdef DROPBEAR_ECDH
647 struct kex_ecdh_param *gen_kexecdh_param() {
648 struct kex_ecdh_param *param = m_malloc(sizeof(*param));
649 if (ecc_make_key_ex(NULL, dropbear_ltc_prng,
650 &param->key, ses.newkeys->algo_kex->ecc_curve->dp) != CRYPT_OK) {
651 dropbear_exit("ECC error");
652 }
653 return param;
654 }
655
656 void free_kexecdh_param(struct kex_ecdh_param *param) {
657 ecc_free(&param->key);
658 m_free(param);
659
660 }
661 void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them,
662 sign_key *hostkey) {
663 const struct dropbear_kex *algo_kex = ses.newkeys->algo_kex;
664 hash_state hs;
665 // public keys from client and server
666 ecc_key *Q_C, *Q_S, *Q_them;
667
668 // XXX load Q_them
669 Q_them = buf_get_ecc_pubkey(pub_them, algo_kex->ecc_curve);
670
671 ses.dh_K = dropbear_ecc_shared_secret(Q_them, &param->key);
672
673 /* From here on, the code needs to work with the _same_ vars on each side,
674 * not vice-versaing for client/server */
675 if (IS_DROPBEAR_CLIENT) {
676 Q_C = &param->key;
677 Q_S = Q_them;
678 } else {
679 Q_C = Q_them;
680 Q_S = &param->key;
681 }
682
683 /* Create the remainder of the hash buffer, to generate the exchange hash */
684 /* K_S, the host key */
685 buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey);
686 /* Q_C, client's ephemeral public key octet string */
687 buf_put_ecc_pubkey_string(ses.kexhashbuf, Q_C);
688 /* Q_S, server's ephemeral public key octet string */
689 buf_put_ecc_pubkey_string(ses.kexhashbuf, Q_S);
690 /* K, the shared secret */
691 buf_putmpint(ses.kexhashbuf, ses.dh_K);
692
693 /* calculate the hash H to sign */
694 algo_kex->hashdesc->init(&hs);
643 buf_setpos(ses.kexhashbuf, 0); 695 buf_setpos(ses.kexhashbuf, 0);
644 sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len), 696 algo_kex->hashdesc->process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
645 ses.kexhashbuf->len); 697 ses.kexhashbuf->len);
646 698
647 ses.hash = m_malloc(SHA1_HASH_SIZE); 699 /* calculate the hash H to sign */
648 } 700 finish_kexhashbuf();
649 sha1_done(&hs, ses.hash); 701 }
702 #endif
703
704 static void finish_kexhashbuf(void) {
705 hash_state hs;
706 const struct ltc_hash_descriptor *hashdesc = ses.newkeys->algo_kex->hashdesc;
707
708 hashdesc->init(&hs);
709 buf_setpos(ses.kexhashbuf, 0);
710 hashdesc->process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
711 ses.kexhashbuf->len);
712 ses.hash = buf_new(hashdesc->hashsize);
713 hashdesc->done(&hs, buf_getwriteptr(ses.hash, hashdesc->hashsize));
714 buf_setlen(ses.hash, hashdesc->hashsize);
650 715
651 buf_burn(ses.kexhashbuf); 716 buf_burn(ses.kexhashbuf);
652 buf_free(ses.kexhashbuf); 717 buf_free(ses.kexhashbuf);
653 ses.kexhashbuf = NULL; 718 ses.kexhashbuf = NULL;
654 719
655 /* first time around, we set the session_id to H */ 720 /* first time around, we set the session_id to H */
656 if (ses.session_id == NULL) { 721 if (ses.session_id == NULL) {
657 /* create the session_id, this never needs freeing */ 722 /* create the session_id, this never needs freeing */
658 ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE); 723 ses.session_id = buf_newcopy(ses.hash);
659 memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE); 724 }
660 } 725
661 } 726 }
662
663 #ifdef DROPBEAR_ECDH
664 struct kex_ecdh_param *gen_kexecdh_param() {
665 struct kex_ecdh_param *param = m_malloc(sizeof(*param));
666 if (ecc_make_key_ex(NULL, dropbear_ltc_prng,
667 &param->key, ses.newkeys->algo_kex->ecc_curve->dp) != CRYPT_OK) {
668 dropbear_exit("ECC error");
669 }
670 return param;
671 }
672
673 void free_kexecdh_param(struct kex_ecdh_param *param) {
674 ecc_free(&param->key);
675 m_free(param);
676
677 }
678 void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them,
679 sign_key *hostkey) {
680 const struct dropbear_kex *algo_kex = ses.newkeys->algo_kex;
681 hash_state hs;
682 // public keys from client and server
683 ecc_key *Q_C, *Q_S, *Q_them;
684
685 // XXX load Q_them
686 Q_them = buf_get_ecc_pubkey(pub_them, algo_kex->ecc_curve);
687
688 ses.dh_K = dropbear_ecc_shared_secret(Q_them, param->key);
689
690 /* From here on, the code needs to work with the _same_ vars on each side,
691 * not vice-versaing for client/server */
692 if (IS_DROPBEAR_CLIENT) {
693 Q_C = param->key;
694 Q_S = Q_them;
695 } else {
696 Q_C = Q_them;
697 Q_S = param->key;
698 }
699
700 /* Create the remainder of the hash buffer, to generate the exchange hash */
701 /* K_S, the host key */
702 buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey);
703 /* Q_C, client's ephemeral public key octet string */
704 buf_put_ecc_pubkey_string(Q_C);
705 /* Q_S, server's ephemeral public key octet string */
706 buf_put_ecc_pubkey_string(Q_S);
707 /* K, the shared secret */
708 buf_putmpint(ses.kexhashbuf, ses.dh_K);
709
710 /* calculate the hash H to sign */
711 algo_kex->hashdesc->init(&hs);
712 buf_setpos(ses.kexhashbuf, 0);
713 algo_kex->hashdesc->process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
714 ses.kexhashbuf->len);
715 if (!ses.hash) {
716 ses.hash = m_malloc(algo_kex->hashdesc->hashsize);
717 }
718 algo_kex->hashdesc->done(&hs, ses.hash);
719
720 buf_burn(ses.kexhashbuf);
721 buf_free(ses.kexhashbuf);
722 ses.kexhashbuf = NULL;
723
724 /* first time around, we set the session_id to H */
725 if (ses.session_id == NULL) {
726 /* create the session_id, this never needs freeing */
727 ses.session_id = m_malloc(algo_kex->hashdesc->hashsize);
728 memcpy(ses.session_id, ses.hash, algo_kex->hashdesc->hashsize);
729 }
730
731 }
732 #endif
733 727
734 /* read the other side's algo list. buf_match_algo is a callback to match 728 /* read the other side's algo list. buf_match_algo is a callback to match
735 * algos for the client or server. */ 729 * algos for the client or server. */
736 static void read_kex_algos() { 730 static void read_kex_algos() {
737 731