Mercurial > dropbear
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 ¶m->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(¶m->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, ¶m->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 = ¶m->key; | |
677 Q_S = Q_them; | |
678 } else { | |
679 Q_C = Q_them; | |
680 Q_S = ¶m->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 ¶m->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(¶m->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 |