comparison common-kex.c @ 801:7dcb46da72d9 ecc

merge in HEAD
author Matt Johnston <matt@ucc.asn.au>
date Tue, 21 May 2013 12:09:35 +0800
parents 70625eed40c9 f110d321fe7a
children 724c3e0c8734
comparison
equal deleted inserted replaced
799:c344607b7341 801:7dcb46da72d9
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, unsigned int outlen, 90 static void hashkeys(unsigned char *out, unsigned int outlen,
90 const hash_state * hs, const unsigned char X); 91 const hash_state * hs, const unsigned char X);
130 buf_putstring(ses.writepayload, "", 0); 131 buf_putstring(ses.writepayload, "", 0);
131 132
132 /* languages_server_to_client */ 133 /* languages_server_to_client */
133 buf_putstring(ses.writepayload, "", 0); 134 buf_putstring(ses.writepayload, "", 0);
134 135
135 /* first_kex_packet_follows - unimplemented for now */ 136 /* first_kex_packet_follows */
136 buf_putbyte(ses.writepayload, 0x00); 137 buf_putbyte(ses.writepayload, (ses.send_kex_first_guess != NULL));
137 138
138 /* reserved unit32 */ 139 /* reserved unit32 */
139 buf_putint(ses.writepayload, 0); 140 buf_putint(ses.writepayload, 0);
140 141
141 /* set up transmitted kex packet buffer for hashing. 142 /* set up transmitted kex packet buffer for hashing.
143 ses.transkexinit = buf_newcopy(ses.writepayload); 144 ses.transkexinit = buf_newcopy(ses.writepayload);
144 145
145 encrypt_packet(); 146 encrypt_packet();
146 ses.dataallowed = 0; /* don't send other packets during kex */ 147 ses.dataallowed = 0; /* don't send other packets during kex */
147 148
149 ses.kexstate.sentkexinit = 1;
150
151 ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
152
153 if (ses.send_kex_first_guess) {
154 ses.newkeys->algo_kex = sshkex[0].data;
155 ses.newkeys->algo_hostkey = sshhostkey[0].val;
156 ses.send_kex_first_guess();
157 }
158
148 TRACE(("DATAALLOWED=0")) 159 TRACE(("DATAALLOWED=0"))
149 TRACE(("-> KEXINIT")) 160 TRACE(("-> KEXINIT"))
150 ses.kexstate.sentkexinit = 1; 161
151 } 162 }
152 163
153 /* *** NOTE regarding (send|recv)_msg_newkeys *** 164 static void switch_keys() {
154 * Changed by mihnea from the original kex.c to set dataallowed after a 165 TRACE2(("enter switch_keys"))
155 * completed key exchange, no matter the order in which it was performed. 166 if (!(ses.kexstate.sentkexinit && ses.kexstate.recvkexinit)) {
156 * This enables client mode without affecting server functionality. 167 dropbear_exit("Unexpected newkeys message");
157 */ 168 }
169
170 if (!ses.keys) {
171 ses.keys = m_malloc(sizeof(*ses.newkeys));
172 }
173 if (ses.kexstate.recvnewkeys && ses.newkeys->recv.valid) {
174 TRACE(("switch_keys recv"))
175 #ifndef DISABLE_ZLIB
176 gen_new_zstream_recv();
177 #endif
178 ses.keys->recv = ses.newkeys->recv;
179 m_burn(&ses.newkeys->recv, sizeof(ses.newkeys->recv));
180 ses.newkeys->recv.valid = 0;
181 }
182 if (ses.kexstate.sentnewkeys && ses.newkeys->trans.valid) {
183 TRACE(("switch_keys trans"))
184 #ifndef DISABLE_ZLIB
185 gen_new_zstream_trans();
186 #endif
187 ses.keys->trans = ses.newkeys->trans;
188 m_burn(&ses.newkeys->trans, sizeof(ses.newkeys->trans));
189 ses.newkeys->trans.valid = 0;
190 }
191 if (ses.kexstate.sentnewkeys && ses.kexstate.recvnewkeys)
192 {
193 TRACE(("switch_keys done"))
194 ses.keys->algo_kex = ses.newkeys->algo_kex;
195 ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
196 ses.keys->allow_compress = 0;
197 m_free(ses.newkeys);
198 ses.newkeys = NULL;
199 kexinitialise();
200 }
201 TRACE2(("leave switch_keys"))
202 }
158 203
159 /* Bring new keys into use after a key exchange, and let the client know*/ 204 /* Bring new keys into use after a key exchange, and let the client know*/
160 void send_msg_newkeys() { 205 void send_msg_newkeys() {
161 206
162 TRACE(("enter send_msg_newkeys")) 207 TRACE(("enter send_msg_newkeys"))
163 208
164 /* generate the kexinit request */ 209 /* generate the kexinit request */
165 CHECKCLEARTOWRITE(); 210 CHECKCLEARTOWRITE();
166 buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS); 211 buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS);
167 encrypt_packet(); 212 encrypt_packet();
213
168 214
169
170 /* set up our state */ 215 /* set up our state */
171 if (ses.kexstate.recvnewkeys) { 216 ses.kexstate.sentnewkeys = 1;
172 TRACE(("while RECVNEWKEYS=1")) 217 ses.kexstate.donefirstkex = 1;
173 gen_new_keys(); 218 ses.dataallowed = 1; /* we can send other packets again now */
174 kexinitialise(); /* we've finished with this kex */ 219 gen_new_keys();
175 TRACE((" -> DATAALLOWED=1")) 220 switch_keys();
176 ses.dataallowed = 1; /* we can send other packets again now */ 221
177 ses.kexstate.donefirstkex = 1;
178 } else {
179 ses.kexstate.sentnewkeys = 1;
180 TRACE(("SENTNEWKEYS=1"))
181 }
182
183 TRACE(("-> MSG_NEWKEYS"))
184 TRACE(("leave send_msg_newkeys")) 222 TRACE(("leave send_msg_newkeys"))
185 } 223 }
186 224
187 /* Bring the new keys into use after a key exchange */ 225 /* Bring the new keys into use after a key exchange */
188 void recv_msg_newkeys() { 226 void recv_msg_newkeys() {
189 227
190 TRACE(("<- MSG_NEWKEYS"))
191 TRACE(("enter recv_msg_newkeys")) 228 TRACE(("enter recv_msg_newkeys"))
192 229
193 /* simply check if we've sent SSH_MSG_NEWKEYS, and if so, 230 ses.kexstate.recvnewkeys = 1;
194 * switch to the new keys */ 231 switch_keys();
195 if (ses.kexstate.sentnewkeys) {
196 TRACE(("while SENTNEWKEYS=1"))
197 gen_new_keys();
198 kexinitialise(); /* we've finished with this kex */
199 TRACE((" -> DATAALLOWED=1"))
200 ses.dataallowed = 1; /* we can send other packets again now */
201 ses.kexstate.donefirstkex = 1;
202 } else {
203 TRACE(("RECVNEWKEYS=1"))
204 ses.kexstate.recvnewkeys = 1;
205 }
206 232
207 TRACE(("leave recv_msg_newkeys")) 233 TRACE(("leave recv_msg_newkeys"))
208 } 234 }
209 235
210 236
235 /* sent/recv'd MSG_NEWKEYS */ 261 /* sent/recv'd MSG_NEWKEYS */
236 ses.kexstate.recvnewkeys = 0; 262 ses.kexstate.recvnewkeys = 0;
237 ses.kexstate.sentnewkeys = 0; 263 ses.kexstate.sentnewkeys = 0;
238 264
239 /* first_packet_follows */ 265 /* first_packet_follows */
240 ses.kexstate.firstfollows = 0; 266 ses.kexstate.them_firstfollows = 0;
241 267
242 ses.kexstate.datatrans = 0; 268 ses.kexstate.datatrans = 0;
243 ses.kexstate.datarecv = 0; 269 ses.kexstate.datarecv = 0;
270
271 ses.kexstate.our_first_follows_matches = 0;
244 272
245 ses.kexstate.lastkextime = time(NULL); 273 ses.kexstate.lastkextime = time(NULL);
246 274
247 } 275 }
248 276
282 * This occurs after the DH key-exchange. 310 * This occurs after the DH key-exchange.
283 * 311 *
284 * ses.newkeys is the new set of keys which are generated, these are only 312 * ses.newkeys is the new set of keys which are generated, these are only
285 * taken into use after both sides have sent a newkeys message */ 313 * taken into use after both sides have sent a newkeys message */
286 314
287 /* Originally from kex.c, generalized for cli/svr mode --mihnea */ 315 static void gen_new_keys() {
288 void gen_new_keys() {
289 316
290 unsigned char C2S_IV[MAX_IV_LEN]; 317 unsigned char C2S_IV[MAX_IV_LEN];
291 unsigned char C2S_key[MAX_KEY_LEN]; 318 unsigned char C2S_key[MAX_KEY_LEN];
292 unsigned char S2C_IV[MAX_IV_LEN]; 319 unsigned char S2C_IV[MAX_IV_LEN];
293 unsigned char S2C_key[MAX_KEY_LEN]; 320 unsigned char S2C_key[MAX_KEY_LEN];
365 hashkeys(ses.newkeys->recv.mackey, 392 hashkeys(ses.newkeys->recv.mackey,
366 ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter); 393 ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter);
367 ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hash_desc->name); 394 ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hash_desc->name);
368 } 395 }
369 396
370 #ifndef DISABLE_ZLIB 397 /* Ready to switch over */
371 gen_new_zstreams(); 398 ses.newkeys->trans.valid = 1;
372 #endif 399 ses.newkeys->recv.valid = 1;
373
374 /* Switch over to the new keys */
375 m_burn(ses.keys, sizeof(struct key_context));
376 m_free(ses.keys);
377 ses.keys = ses.newkeys;
378 ses.newkeys = NULL;
379 400
380 m_burn(C2S_IV, sizeof(C2S_IV)); 401 m_burn(C2S_IV, sizeof(C2S_IV));
381 m_burn(C2S_key, sizeof(C2S_key)); 402 m_burn(C2S_key, sizeof(C2S_key));
382 m_burn(S2C_IV, sizeof(S2C_IV)); 403 m_burn(S2C_IV, sizeof(S2C_IV));
383 m_burn(S2C_key, sizeof(S2C_key)); 404 m_burn(S2C_key, sizeof(S2C_key));
399 && ses.keys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY); 420 && ses.keys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
400 } 421 }
401 422
402 /* Set up new zlib compression streams, close the old ones. Only 423 /* Set up new zlib compression streams, close the old ones. Only
403 * called from gen_new_keys() */ 424 * called from gen_new_keys() */
404 static void gen_new_zstreams() { 425 static void gen_new_zstream_recv() {
405 426
406 /* create new zstreams */ 427 /* create new zstreams */
407 if (ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB 428 if (ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB
408 || ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) { 429 || ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
409 ses.newkeys->recv.zstream = (z_streamp)m_malloc(sizeof(z_stream)); 430 ses.newkeys->recv.zstream = (z_streamp)m_malloc(sizeof(z_stream));
414 dropbear_exit("zlib error"); 435 dropbear_exit("zlib error");
415 } 436 }
416 } else { 437 } else {
417 ses.newkeys->recv.zstream = NULL; 438 ses.newkeys->recv.zstream = NULL;
418 } 439 }
440 /* clean up old keys */
441 if (ses.keys->recv.zstream != NULL) {
442 if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
443 /* Z_DATA_ERROR is ok, just means that stream isn't ended */
444 dropbear_exit("Crypto error");
445 }
446 m_free(ses.keys->recv.zstream);
447 }
448 }
449
450 static void gen_new_zstream_trans() {
419 451
420 if (ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB 452 if (ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB
421 || ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) { 453 || ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
422 ses.newkeys->trans.zstream = (z_streamp)m_malloc(sizeof(z_stream)); 454 ses.newkeys->trans.zstream = (z_streamp)m_malloc(sizeof(z_stream));
423 ses.newkeys->trans.zstream->zalloc = Z_NULL; 455 ses.newkeys->trans.zstream->zalloc = Z_NULL;
431 } 463 }
432 } else { 464 } else {
433 ses.newkeys->trans.zstream = NULL; 465 ses.newkeys->trans.zstream = NULL;
434 } 466 }
435 467
436 /* clean up old keys */
437 if (ses.keys->recv.zstream != NULL) {
438 if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
439 /* Z_DATA_ERROR is ok, just means that stream isn't ended */
440 dropbear_exit("Crypto error");
441 }
442 m_free(ses.keys->recv.zstream);
443 }
444 if (ses.keys->trans.zstream != NULL) { 468 if (ses.keys->trans.zstream != NULL) {
445 if (deflateEnd(ses.keys->trans.zstream) == Z_STREAM_ERROR) { 469 if (deflateEnd(ses.keys->trans.zstream) == Z_STREAM_ERROR) {
446 /* Z_DATA_ERROR is ok, just means that stream isn't ended */ 470 /* Z_DATA_ERROR is ok, just means that stream isn't ended */
447 dropbear_exit("Crypto error"); 471 dropbear_exit("Crypto error");
448 } 472 }
521 545
522 /* I_S, the payload of the server's SSH_MSG_KEXINIT */ 546 /* I_S, the payload of the server's SSH_MSG_KEXINIT */
523 buf_putstring(ses.kexhashbuf, 547 buf_putstring(ses.kexhashbuf,
524 ses.transkexinit->data, ses.transkexinit->len); 548 ses.transkexinit->data, ses.transkexinit->len);
525 549
526 ses.requirenext = SSH_MSG_KEXDH_INIT; 550 ses.requirenext[0] = SSH_MSG_KEXDH_INIT;
527 } 551 }
528 552
529 buf_free(ses.transkexinit); 553 buf_free(ses.transkexinit);
530 ses.transkexinit = NULL; 554 ses.transkexinit = NULL;
531 /* the rest of ses.kexhashbuf will be done after DH exchange */ 555 /* the rest of ses.kexhashbuf will be done after DH exchange */
548 572
549 DEF_MP_INT(dh_p); 573 DEF_MP_INT(dh_p);
550 DEF_MP_INT(dh_q); 574 DEF_MP_INT(dh_q);
551 DEF_MP_INT(dh_g); 575 DEF_MP_INT(dh_g);
552 576
553 TRACE(("enter send_msg_kexdh_reply")) 577 TRACE(("enter gen_kexdh_vals"))
554 578
555 struct kex_dh_param *param = m_malloc(sizeof(*param)); 579 struct kex_dh_param *param = m_malloc(sizeof(*param));
556 m_mp_init_multi(&param->pub, &param->priv, NULL); 580 m_mp_init_multi(&param->pub, &param->priv, NULL);
557 581
558 /* read the prime and generator*/ 582 /* read the prime and generator*/
737 int allgood = 1; /* we AND this with each goodguess and see if its still 761 int allgood = 1; /* we AND this with each goodguess and see if its still
738 true after */ 762 true after */
739 763
740 buf_incrpos(ses.payload, 16); /* start after the cookie */ 764 buf_incrpos(ses.payload, 16); /* start after the cookie */
741 765
742 ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); 766 memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
767
768 #ifdef USE_KEXGUESS2
769 enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
770 #else
771 enum kexguess2_used kexguess2 = KEXGUESS2_NO;
772 #endif
743 773
744 /* kex_algorithms */ 774 /* kex_algorithms */
745 algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess); 775 algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
746 allgood &= goodguess; 776 allgood &= goodguess;
747 if (algo == NULL) { 777 if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
748 erralgo = "kex"; 778 erralgo = "kex";
749 goto error; 779 goto error;
750 } 780 }
781 TRACE(("kexguess2 %d", kexguess2))
751 TRACE(("kex algo %s", algo->name)) 782 TRACE(("kex algo %s", algo->name))
752 ses.newkeys->algo_kex = algo->data; 783 ses.newkeys->algo_kex = algo->data;
753 784
754 /* server_host_key_algorithms */ 785 /* server_host_key_algorithms */
755 algo = ses.buf_match_algo(ses.payload, sshhostkey, &goodguess); 786 algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess);
756 allgood &= goodguess; 787 allgood &= goodguess;
757 if (algo == NULL) { 788 if (algo == NULL) {
758 erralgo = "hostkey"; 789 erralgo = "hostkey";
759 goto error; 790 goto error;
760 } 791 }
761 TRACE(("hostkey algo %s", algo->name)) 792 TRACE(("hostkey algo %s", algo->name))
762 ses.newkeys->algo_hostkey = algo->val; 793 ses.newkeys->algo_hostkey = algo->val;
763 794
764 /* encryption_algorithms_client_to_server */ 795 /* encryption_algorithms_client_to_server */
765 c2s_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess); 796 c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
766 if (c2s_cipher_algo == NULL) { 797 if (c2s_cipher_algo == NULL) {
767 erralgo = "enc c->s"; 798 erralgo = "enc c->s";
768 goto error; 799 goto error;
769 } 800 }
770 TRACE(("enc c2s is %s", c2s_cipher_algo->name)) 801 TRACE(("enc c2s is %s", c2s_cipher_algo->name))
771 802
772 /* encryption_algorithms_server_to_client */ 803 /* encryption_algorithms_server_to_client */
773 s2c_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess); 804 s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
774 if (s2c_cipher_algo == NULL) { 805 if (s2c_cipher_algo == NULL) {
775 erralgo = "enc s->c"; 806 erralgo = "enc s->c";
776 goto error; 807 goto error;
777 } 808 }
778 TRACE(("enc s2c is %s", s2c_cipher_algo->name)) 809 TRACE(("enc s2c is %s", s2c_cipher_algo->name))
779 810
780 /* mac_algorithms_client_to_server */ 811 /* mac_algorithms_client_to_server */
781 c2s_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess); 812 c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
782 if (c2s_hash_algo == NULL) { 813 if (c2s_hash_algo == NULL) {
783 erralgo = "mac c->s"; 814 erralgo = "mac c->s";
784 goto error; 815 goto error;
785 } 816 }
786 TRACE(("hash c2s is %s", c2s_hash_algo->name)) 817 TRACE(("hash c2s is %s", c2s_hash_algo->name))
787 818
788 /* mac_algorithms_server_to_client */ 819 /* mac_algorithms_server_to_client */
789 s2c_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess); 820 s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
790 if (s2c_hash_algo == NULL) { 821 if (s2c_hash_algo == NULL) {
791 erralgo = "mac s->c"; 822 erralgo = "mac s->c";
792 goto error; 823 goto error;
793 } 824 }
794 TRACE(("hash s2c is %s", s2c_hash_algo->name)) 825 TRACE(("hash s2c is %s", s2c_hash_algo->name))
795 826
796 /* compression_algorithms_client_to_server */ 827 /* compression_algorithms_client_to_server */
797 c2s_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess); 828 c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
798 if (c2s_comp_algo == NULL) { 829 if (c2s_comp_algo == NULL) {
799 erralgo = "comp c->s"; 830 erralgo = "comp c->s";
800 goto error; 831 goto error;
801 } 832 }
802 TRACE(("hash c2s is %s", c2s_comp_algo->name)) 833 TRACE(("hash c2s is %s", c2s_comp_algo->name))
803 834
804 /* compression_algorithms_server_to_client */ 835 /* compression_algorithms_server_to_client */
805 s2c_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess); 836 s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
806 if (s2c_comp_algo == NULL) { 837 if (s2c_comp_algo == NULL) {
807 erralgo = "comp s->c"; 838 erralgo = "comp s->c";
808 goto error; 839 goto error;
809 } 840 }
810 TRACE(("hash s2c is %s", s2c_comp_algo->name)) 841 TRACE(("hash s2c is %s", s2c_comp_algo->name))
813 buf_eatstring(ses.payload); 844 buf_eatstring(ses.payload);
814 845
815 /* languages_server_to_client */ 846 /* languages_server_to_client */
816 buf_eatstring(ses.payload); 847 buf_eatstring(ses.payload);
817 848
818 /* first_kex_packet_follows */ 849 /* their first_kex_packet_follows */
819 if (buf_getbool(ses.payload)) { 850 if (buf_getbool(ses.payload)) {
820 ses.kexstate.firstfollows = 1; 851 TRACE(("them kex firstfollows. allgood %d", allgood))
852 ses.kexstate.them_firstfollows = 1;
821 /* if the guess wasn't good, we ignore the packet sent */ 853 /* if the guess wasn't good, we ignore the packet sent */
822 if (!allgood) { 854 if (!allgood) {
823 ses.ignorenext = 1; 855 ses.ignorenext = 1;
824 } 856 }
825 } 857 }
858 ses.newkeys->trans.algo_comp = s2c_comp_algo->val; 890 ses.newkeys->trans.algo_comp = s2c_comp_algo->val;
859 } 891 }
860 892
861 /* reserved for future extensions */ 893 /* reserved for future extensions */
862 buf_getint(ses.payload); 894 buf_getint(ses.payload);
895
896 if (ses.send_kex_first_guess && allgood) {
897 TRACE(("our_first_follows_matches 1"))
898 ses.kexstate.our_first_follows_matches = 1;
899 }
863 return; 900 return;
864 901
865 error: 902 error:
866 dropbear_exit("No matching algo %s", erralgo); 903 dropbear_exit("No matching algo %s", erralgo);
867 } 904 }