comparison common-kex.c @ 773:a9f2a6ae4eb5

merge
author Matt Johnston <matt@ucc.asn.au>
date Sun, 14 Apr 2013 22:49:19 +0800
parents a389a2a7aa96
children 2f1c199b6e4b
comparison
equal deleted inserted replaced
772:7fc0aeada79c 773:a9f2a6ae4eb5
78 78
79 /* Same for group1 and group14 */ 79 /* Same for group1 and group14 */
80 static const int DH_G_VAL = 2; 80 static const int DH_G_VAL = 2;
81 81
82 static void kexinitialise(); 82 static void kexinitialise();
83 void gen_new_keys(); 83 static void gen_new_keys();
84 #ifndef DISABLE_ZLIB 84 #ifndef DISABLE_ZLIB
85 static void gen_new_zstreams(); 85 static void gen_new_zstream_recv();
86 static void gen_new_zstream_trans();
86 #endif 87 #endif
87 static void read_kex_algos(); 88 static void read_kex_algos();
88 /* helper function for gen_new_keys */ 89 /* helper function for gen_new_keys */
89 static void hashkeys(unsigned char *out, int outlen, 90 static void hashkeys(unsigned char *out, int outlen,
90 const hash_state * hs, unsigned const char X); 91 const hash_state * hs, unsigned const char X);
129 buf_putstring(ses.writepayload, "", 0); 130 buf_putstring(ses.writepayload, "", 0);
130 131
131 /* languages_server_to_client */ 132 /* languages_server_to_client */
132 buf_putstring(ses.writepayload, "", 0); 133 buf_putstring(ses.writepayload, "", 0);
133 134
134 /* first_kex_packet_follows - unimplemented for now */ 135 /* first_kex_packet_follows */
135 buf_putbyte(ses.writepayload, 0x00); 136 buf_putbyte(ses.writepayload, (ses.send_kex_first_guess != NULL));
136 137
137 /* reserved unit32 */ 138 /* reserved unit32 */
138 buf_putint(ses.writepayload, 0); 139 buf_putint(ses.writepayload, 0);
139 140
140 /* set up transmitted kex packet buffer for hashing. 141 /* set up transmitted kex packet buffer for hashing.
142 ses.transkexinit = buf_newcopy(ses.writepayload); 143 ses.transkexinit = buf_newcopy(ses.writepayload);
143 144
144 encrypt_packet(); 145 encrypt_packet();
145 ses.dataallowed = 0; /* don't send other packets during kex */ 146 ses.dataallowed = 0; /* don't send other packets during kex */
146 147
148 ses.kexstate.sentkexinit = 1;
149
150 ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
151
152 if (ses.send_kex_first_guess) {
153 ses.newkeys->algo_kex = sshkex[0].val;
154 ses.newkeys->algo_hostkey = sshhostkey[0].val;
155 ses.send_kex_first_guess();
156 }
157
147 TRACE(("DATAALLOWED=0")) 158 TRACE(("DATAALLOWED=0"))
148 TRACE(("-> KEXINIT")) 159 TRACE(("-> KEXINIT"))
149 ses.kexstate.sentkexinit = 1; 160
150 } 161 }
151 162
152 /* *** NOTE regarding (send|recv)_msg_newkeys *** 163 static void switch_keys() {
153 * Changed by mihnea from the original kex.c to set dataallowed after a 164 TRACE2(("enter switch_keys"))
154 * completed key exchange, no matter the order in which it was performed. 165 if (!(ses.kexstate.sentkexinit && ses.kexstate.recvkexinit)) {
155 * This enables client mode without affecting server functionality. 166 dropbear_exit("Unexpected newkeys message");
156 */ 167 }
168
169 if (!ses.keys) {
170 ses.keys = m_malloc(sizeof(*ses.newkeys));
171 }
172 if (ses.kexstate.recvnewkeys && ses.newkeys->recv.valid) {
173 TRACE(("switch_keys recv"))
174 gen_new_zstream_recv();
175 ses.keys->recv = ses.newkeys->recv;
176 m_burn(&ses.newkeys->recv, sizeof(ses.newkeys->recv));
177 ses.newkeys->recv.valid = 0;
178 }
179 if (ses.kexstate.sentnewkeys && ses.newkeys->trans.valid) {
180 TRACE(("switch_keys trans"))
181 gen_new_zstream_trans();
182 ses.keys->trans = ses.newkeys->trans;
183 m_burn(&ses.newkeys->trans, sizeof(ses.newkeys->trans));
184 ses.newkeys->trans.valid = 0;
185 }
186 if (ses.kexstate.sentnewkeys && ses.kexstate.recvnewkeys)
187 {
188 TRACE(("switch_keys done"))
189 ses.keys->algo_kex = ses.newkeys->algo_kex;
190 ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
191 ses.keys->allow_compress = 0;
192 m_free(ses.newkeys);
193 ses.newkeys = NULL;
194 kexinitialise();
195 }
196 TRACE2(("leave switch_keys"))
197 }
157 198
158 /* Bring new keys into use after a key exchange, and let the client know*/ 199 /* Bring new keys into use after a key exchange, and let the client know*/
159 void send_msg_newkeys() { 200 void send_msg_newkeys() {
160 201
161 TRACE(("enter send_msg_newkeys")) 202 TRACE(("enter send_msg_newkeys"))
162 203
163 /* generate the kexinit request */ 204 /* generate the kexinit request */
164 CHECKCLEARTOWRITE(); 205 CHECKCLEARTOWRITE();
165 buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS); 206 buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS);
166 encrypt_packet(); 207 encrypt_packet();
208
167 209
168
169 /* set up our state */ 210 /* set up our state */
170 if (ses.kexstate.recvnewkeys) { 211 ses.kexstate.sentnewkeys = 1;
171 TRACE(("while RECVNEWKEYS=1")) 212 ses.kexstate.donefirstkex = 1;
172 gen_new_keys(); 213 ses.dataallowed = 1; /* we can send other packets again now */
173 kexinitialise(); /* we've finished with this kex */ 214 gen_new_keys();
174 TRACE((" -> DATAALLOWED=1")) 215 switch_keys();
175 ses.dataallowed = 1; /* we can send other packets again now */ 216
176 ses.kexstate.donefirstkex = 1;
177 } else {
178 ses.kexstate.sentnewkeys = 1;
179 TRACE(("SENTNEWKEYS=1"))
180 }
181
182 TRACE(("-> MSG_NEWKEYS"))
183 TRACE(("leave send_msg_newkeys")) 217 TRACE(("leave send_msg_newkeys"))
184 } 218 }
185 219
186 /* Bring the new keys into use after a key exchange */ 220 /* Bring the new keys into use after a key exchange */
187 void recv_msg_newkeys() { 221 void recv_msg_newkeys() {
188 222
189 TRACE(("<- MSG_NEWKEYS"))
190 TRACE(("enter recv_msg_newkeys")) 223 TRACE(("enter recv_msg_newkeys"))
191 224
192 /* simply check if we've sent SSH_MSG_NEWKEYS, and if so, 225 ses.kexstate.recvnewkeys = 1;
193 * switch to the new keys */ 226 switch_keys();
194 if (ses.kexstate.sentnewkeys) {
195 TRACE(("while SENTNEWKEYS=1"))
196 gen_new_keys();
197 kexinitialise(); /* we've finished with this kex */
198 TRACE((" -> DATAALLOWED=1"))
199 ses.dataallowed = 1; /* we can send other packets again now */
200 ses.kexstate.donefirstkex = 1;
201 } else {
202 TRACE(("RECVNEWKEYS=1"))
203 ses.kexstate.recvnewkeys = 1;
204 }
205 227
206 TRACE(("leave recv_msg_newkeys")) 228 TRACE(("leave recv_msg_newkeys"))
207 } 229 }
208 230
209 231
234 /* sent/recv'd MSG_NEWKEYS */ 256 /* sent/recv'd MSG_NEWKEYS */
235 ses.kexstate.recvnewkeys = 0; 257 ses.kexstate.recvnewkeys = 0;
236 ses.kexstate.sentnewkeys = 0; 258 ses.kexstate.sentnewkeys = 0;
237 259
238 /* first_packet_follows */ 260 /* first_packet_follows */
239 ses.kexstate.firstfollows = 0; 261 ses.kexstate.them_firstfollows = 0;
240 262
241 ses.kexstate.datatrans = 0; 263 ses.kexstate.datatrans = 0;
242 ses.kexstate.datarecv = 0; 264 ses.kexstate.datarecv = 0;
265
266 ses.kexstate.our_first_follows_matches = 0;
243 267
244 ses.kexstate.lastkextime = time(NULL); 268 ses.kexstate.lastkextime = time(NULL);
245 269
246 } 270 }
247 271
279 * This occurs after the DH key-exchange. 303 * This occurs after the DH key-exchange.
280 * 304 *
281 * ses.newkeys is the new set of keys which are generated, these are only 305 * ses.newkeys is the new set of keys which are generated, these are only
282 * taken into use after both sides have sent a newkeys message */ 306 * taken into use after both sides have sent a newkeys message */
283 307
284 /* Originally from kex.c, generalized for cli/svr mode --mihnea */ 308 static void gen_new_keys() {
285 void gen_new_keys() {
286 309
287 unsigned char C2S_IV[MAX_IV_LEN]; 310 unsigned char C2S_IV[MAX_IV_LEN];
288 unsigned char C2S_key[MAX_KEY_LEN]; 311 unsigned char C2S_key[MAX_KEY_LEN];
289 unsigned char S2C_IV[MAX_IV_LEN]; 312 unsigned char S2C_IV[MAX_IV_LEN];
290 unsigned char S2C_key[MAX_KEY_LEN]; 313 unsigned char S2C_key[MAX_KEY_LEN];
364 hashkeys(ses.newkeys->recv.mackey, 387 hashkeys(ses.newkeys->recv.mackey,
365 ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter); 388 ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter);
366 ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hashdesc->name); 389 ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hashdesc->name);
367 } 390 }
368 391
369 #ifndef DISABLE_ZLIB 392 /* Ready to switch over */
370 gen_new_zstreams(); 393 ses.newkeys->trans.valid = 1;
371 #endif 394 ses.newkeys->recv.valid = 1;
372
373 /* Switch over to the new keys */
374 m_burn(ses.keys, sizeof(struct key_context));
375 m_free(ses.keys);
376 ses.keys = ses.newkeys;
377 ses.newkeys = NULL;
378 395
379 m_burn(C2S_IV, sizeof(C2S_IV)); 396 m_burn(C2S_IV, sizeof(C2S_IV));
380 m_burn(C2S_key, sizeof(C2S_key)); 397 m_burn(C2S_key, sizeof(C2S_key));
381 m_burn(S2C_IV, sizeof(S2C_IV)); 398 m_burn(S2C_IV, sizeof(S2C_IV));
382 m_burn(S2C_key, sizeof(S2C_key)); 399 m_burn(S2C_key, sizeof(S2C_key));
398 && ses.keys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY); 415 && ses.keys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
399 } 416 }
400 417
401 /* Set up new zlib compression streams, close the old ones. Only 418 /* Set up new zlib compression streams, close the old ones. Only
402 * called from gen_new_keys() */ 419 * called from gen_new_keys() */
403 static void gen_new_zstreams() { 420 static void gen_new_zstream_recv() {
404 421
405 /* create new zstreams */ 422 /* create new zstreams */
406 if (ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB 423 if (ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB
407 || ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) { 424 || ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
408 ses.newkeys->recv.zstream = (z_streamp)m_malloc(sizeof(z_stream)); 425 ses.newkeys->recv.zstream = (z_streamp)m_malloc(sizeof(z_stream));
413 dropbear_exit("zlib error"); 430 dropbear_exit("zlib error");
414 } 431 }
415 } else { 432 } else {
416 ses.newkeys->recv.zstream = NULL; 433 ses.newkeys->recv.zstream = NULL;
417 } 434 }
435 /* clean up old keys */
436 if (ses.keys->recv.zstream != NULL) {
437 if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
438 /* Z_DATA_ERROR is ok, just means that stream isn't ended */
439 dropbear_exit("Crypto error");
440 }
441 m_free(ses.keys->recv.zstream);
442 }
443 }
444
445 static void gen_new_zstream_trans() {
418 446
419 if (ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB 447 if (ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB
420 || ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) { 448 || ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
421 ses.newkeys->trans.zstream = (z_streamp)m_malloc(sizeof(z_stream)); 449 ses.newkeys->trans.zstream = (z_streamp)m_malloc(sizeof(z_stream));
422 ses.newkeys->trans.zstream->zalloc = Z_NULL; 450 ses.newkeys->trans.zstream->zalloc = Z_NULL;
430 } 458 }
431 } else { 459 } else {
432 ses.newkeys->trans.zstream = NULL; 460 ses.newkeys->trans.zstream = NULL;
433 } 461 }
434 462
435 /* clean up old keys */
436 if (ses.keys->recv.zstream != NULL) {
437 if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
438 /* Z_DATA_ERROR is ok, just means that stream isn't ended */
439 dropbear_exit("Crypto error");
440 }
441 m_free(ses.keys->recv.zstream);
442 }
443 if (ses.keys->trans.zstream != NULL) { 463 if (ses.keys->trans.zstream != NULL) {
444 if (deflateEnd(ses.keys->trans.zstream) == Z_STREAM_ERROR) { 464 if (deflateEnd(ses.keys->trans.zstream) == Z_STREAM_ERROR) {
445 /* Z_DATA_ERROR is ok, just means that stream isn't ended */ 465 /* Z_DATA_ERROR is ok, just means that stream isn't ended */
446 dropbear_exit("Crypto error"); 466 dropbear_exit("Crypto error");
447 } 467 }
553 573
554 DEF_MP_INT(dh_p); 574 DEF_MP_INT(dh_p);
555 DEF_MP_INT(dh_q); 575 DEF_MP_INT(dh_q);
556 DEF_MP_INT(dh_g); 576 DEF_MP_INT(dh_g);
557 577
558 TRACE(("enter send_msg_kexdh_reply")) 578 TRACE(("enter gen_kexdh_vals"))
559 579
560 m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL); 580 m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL);
561 581
562 /* read the prime and generator*/ 582 /* read the prime and generator*/
563 load_dh_p(&dh_p); 583 load_dh_p(&dh_p);
676 int allgood = 1; /* we AND this with each goodguess and see if its still 696 int allgood = 1; /* we AND this with each goodguess and see if its still
677 true after */ 697 true after */
678 698
679 buf_incrpos(ses.payload, 16); /* start after the cookie */ 699 buf_incrpos(ses.payload, 16); /* start after the cookie */
680 700
681 ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); 701 memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
702
703 #ifdef USE_KEXGUESS2
704 enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
705 #else
706 enum kexguess2_used kexguess2 = KEXGUESS2_NO;
707 #endif
682 708
683 /* kex_algorithms */ 709 /* kex_algorithms */
684 algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess); 710 algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
685 allgood &= goodguess; 711 allgood &= goodguess;
686 if (algo == NULL) { 712 if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
687 erralgo = "kex"; 713 erralgo = "kex";
688 goto error; 714 goto error;
689 } 715 }
716 TRACE(("kexguess2 %d", kexguess2))
690 TRACE(("kex algo %s", algo->name)) 717 TRACE(("kex algo %s", algo->name))
691 ses.newkeys->algo_kex = algo->val; 718 ses.newkeys->algo_kex = algo->val;
692 719
693 /* server_host_key_algorithms */ 720 /* server_host_key_algorithms */
694 algo = ses.buf_match_algo(ses.payload, sshhostkey, &goodguess); 721 algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess);
695 allgood &= goodguess; 722 allgood &= goodguess;
696 if (algo == NULL) { 723 if (algo == NULL) {
697 erralgo = "hostkey"; 724 erralgo = "hostkey";
698 goto error; 725 goto error;
699 } 726 }
700 TRACE(("hostkey algo %s", algo->name)) 727 TRACE(("hostkey algo %s", algo->name))
701 ses.newkeys->algo_hostkey = algo->val; 728 ses.newkeys->algo_hostkey = algo->val;
702 729
703 /* encryption_algorithms_client_to_server */ 730 /* encryption_algorithms_client_to_server */
704 c2s_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess); 731 c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
705 if (c2s_cipher_algo == NULL) { 732 if (c2s_cipher_algo == NULL) {
706 erralgo = "enc c->s"; 733 erralgo = "enc c->s";
707 goto error; 734 goto error;
708 } 735 }
709 TRACE(("enc c2s is %s", c2s_cipher_algo->name)) 736 TRACE(("enc c2s is %s", c2s_cipher_algo->name))
710 737
711 /* encryption_algorithms_server_to_client */ 738 /* encryption_algorithms_server_to_client */
712 s2c_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess); 739 s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
713 if (s2c_cipher_algo == NULL) { 740 if (s2c_cipher_algo == NULL) {
714 erralgo = "enc s->c"; 741 erralgo = "enc s->c";
715 goto error; 742 goto error;
716 } 743 }
717 TRACE(("enc s2c is %s", s2c_cipher_algo->name)) 744 TRACE(("enc s2c is %s", s2c_cipher_algo->name))
718 745
719 /* mac_algorithms_client_to_server */ 746 /* mac_algorithms_client_to_server */
720 c2s_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess); 747 c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
721 if (c2s_hash_algo == NULL) { 748 if (c2s_hash_algo == NULL) {
722 erralgo = "mac c->s"; 749 erralgo = "mac c->s";
723 goto error; 750 goto error;
724 } 751 }
725 TRACE(("hash c2s is %s", c2s_hash_algo->name)) 752 TRACE(("hash c2s is %s", c2s_hash_algo->name))
726 753
727 /* mac_algorithms_server_to_client */ 754 /* mac_algorithms_server_to_client */
728 s2c_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess); 755 s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
729 if (s2c_hash_algo == NULL) { 756 if (s2c_hash_algo == NULL) {
730 erralgo = "mac s->c"; 757 erralgo = "mac s->c";
731 goto error; 758 goto error;
732 } 759 }
733 TRACE(("hash s2c is %s", s2c_hash_algo->name)) 760 TRACE(("hash s2c is %s", s2c_hash_algo->name))
734 761
735 /* compression_algorithms_client_to_server */ 762 /* compression_algorithms_client_to_server */
736 c2s_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess); 763 c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
737 if (c2s_comp_algo == NULL) { 764 if (c2s_comp_algo == NULL) {
738 erralgo = "comp c->s"; 765 erralgo = "comp c->s";
739 goto error; 766 goto error;
740 } 767 }
741 TRACE(("hash c2s is %s", c2s_comp_algo->name)) 768 TRACE(("hash c2s is %s", c2s_comp_algo->name))
742 769
743 /* compression_algorithms_server_to_client */ 770 /* compression_algorithms_server_to_client */
744 s2c_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess); 771 s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
745 if (s2c_comp_algo == NULL) { 772 if (s2c_comp_algo == NULL) {
746 erralgo = "comp s->c"; 773 erralgo = "comp s->c";
747 goto error; 774 goto error;
748 } 775 }
749 TRACE(("hash s2c is %s", s2c_comp_algo->name)) 776 TRACE(("hash s2c is %s", s2c_comp_algo->name))
752 buf_eatstring(ses.payload); 779 buf_eatstring(ses.payload);
753 780
754 /* languages_server_to_client */ 781 /* languages_server_to_client */
755 buf_eatstring(ses.payload); 782 buf_eatstring(ses.payload);
756 783
757 /* first_kex_packet_follows */ 784 /* their first_kex_packet_follows */
758 if (buf_getbool(ses.payload)) { 785 if (buf_getbool(ses.payload)) {
759 ses.kexstate.firstfollows = 1; 786 TRACE(("them kex firstfollows. allgood %d", allgood))
787 ses.kexstate.them_firstfollows = 1;
760 /* if the guess wasn't good, we ignore the packet sent */ 788 /* if the guess wasn't good, we ignore the packet sent */
761 if (!allgood) { 789 if (!allgood) {
762 ses.ignorenext = 1; 790 ses.ignorenext = 1;
763 } 791 }
764 } 792 }
797 ses.newkeys->trans.algo_comp = s2c_comp_algo->val; 825 ses.newkeys->trans.algo_comp = s2c_comp_algo->val;
798 } 826 }
799 827
800 /* reserved for future extensions */ 828 /* reserved for future extensions */
801 buf_getint(ses.payload); 829 buf_getint(ses.payload);
830
831 if (ses.send_kex_first_guess && allgood) {
832 TRACE(("our_first_follows_matches 1"))
833 ses.kexstate.our_first_follows_matches = 1;
834 }
802 return; 835 return;
803 836
804 error: 837 error:
805 dropbear_exit("No matching algo %s", erralgo); 838 dropbear_exit("No matching algo %s", erralgo);
806 } 839 }