comparison common-kex.c @ 753:d63ef1e211ea

Take transmit and receive keys into use separately
author Matt Johnston <matt@ucc.asn.au>
date Thu, 04 Apr 2013 00:18:50 +0800
parents 465fefc4f6e0
children a389a2a7aa96
comparison
equal deleted inserted replaced
752:24172f555f9c 753:d63ef1e211ea
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_zstreams();
86 #endif 86 #endif
87 static void read_kex_algos(); 87 static void read_kex_algos();
88 /* helper function for gen_new_keys */ 88 /* helper function for gen_new_keys */
157 TRACE(("DATAALLOWED=0")) 157 TRACE(("DATAALLOWED=0"))
158 TRACE(("-> KEXINIT")) 158 TRACE(("-> KEXINIT"))
159 159
160 } 160 }
161 161
162 /* *** NOTE regarding (send|recv)_msg_newkeys *** 162 void switch_keys() {
163 * Changed by mihnea from the original kex.c to set dataallowed after a 163 TRACE2(("enter switch_keys"))
164 * completed key exchange, no matter the order in which it was performed. 164 if (!(ses.kexstate.sentkexinit && ses.kexstate.recvkexinit)) {
165 * This enables client mode without affecting server functionality. 165 dropbear_exit("Unexpected newkeys message");
166 */ 166 }
167
168 if (!ses.keys) {
169 ses.keys = m_malloc(sizeof(*ses.newkeys));
170 }
171 if (ses.kexstate.recvnewkeys && ses.newkeys->recv.valid) {
172 TRACE(("switch_keys recv"))
173 ses.keys->recv = ses.newkeys->recv;
174 m_burn(&ses.newkeys->recv, sizeof(ses.newkeys->recv));
175 ses.newkeys->recv.valid = 0;
176 }
177 if (ses.kexstate.sentnewkeys && ses.newkeys->trans.valid) {
178 TRACE(("switch_keys trans"))
179 ses.keys->trans = ses.newkeys->trans;
180 m_burn(&ses.newkeys->trans, sizeof(ses.newkeys->trans));
181 ses.newkeys->trans.valid = 0;
182 }
183 if (ses.kexstate.sentnewkeys && ses.kexstate.recvnewkeys)
184 {
185 TRACE(("switch_keys done"))
186 ses.keys->algo_kex = ses.newkeys->algo_kex;
187 ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
188 ses.keys->allow_compress = 0;
189 m_free(ses.newkeys);
190 ses.newkeys = NULL;
191 kexinitialise();
192 }
193 TRACE2(("leave switch_keys"))
194 }
167 195
168 /* Bring new keys into use after a key exchange, and let the client know*/ 196 /* Bring new keys into use after a key exchange, and let the client know*/
169 void send_msg_newkeys() { 197 void send_msg_newkeys() {
170 198
171 TRACE(("enter send_msg_newkeys")) 199 TRACE(("enter send_msg_newkeys"))
172 200
173 /* generate the kexinit request */ 201 /* generate the kexinit request */
174 CHECKCLEARTOWRITE(); 202 CHECKCLEARTOWRITE();
175 buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS); 203 buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS);
176 encrypt_packet(); 204 encrypt_packet();
177 205
178 206
179 /* set up our state */ 207 /* set up our state */
180 if (ses.kexstate.recvnewkeys) { 208 ses.kexstate.sentnewkeys = 1;
181 TRACE(("while RECVNEWKEYS=1")) 209 ses.kexstate.donefirstkex = 1;
182 gen_new_keys(); 210 ses.dataallowed = 1; /* we can send other packets again now */
183 kexinitialise(); /* we've finished with this kex */ 211 gen_new_keys();
184 TRACE((" -> DATAALLOWED=1")) 212 switch_keys();
185 ses.dataallowed = 1; /* we can send other packets again now */ 213
186 ses.kexstate.donefirstkex = 1;
187 } else {
188 ses.kexstate.sentnewkeys = 1;
189 TRACE(("SENTNEWKEYS=1"))
190 }
191
192 TRACE(("-> MSG_NEWKEYS"))
193 TRACE(("leave send_msg_newkeys")) 214 TRACE(("leave send_msg_newkeys"))
194 } 215 }
195 216
196 /* Bring the new keys into use after a key exchange */ 217 /* Bring the new keys into use after a key exchange */
197 void recv_msg_newkeys() { 218 void recv_msg_newkeys() {
198 219
199 TRACE(("<- MSG_NEWKEYS"))
200 TRACE(("enter recv_msg_newkeys")) 220 TRACE(("enter recv_msg_newkeys"))
201 221
202 /* simply check if we've sent SSH_MSG_NEWKEYS, and if so, 222 ses.kexstate.recvnewkeys = 1;
203 * switch to the new keys */ 223 switch_keys();
204 if (ses.kexstate.sentnewkeys) {
205 TRACE(("while SENTNEWKEYS=1"))
206 gen_new_keys();
207 kexinitialise(); /* we've finished with this kex */
208 TRACE((" -> DATAALLOWED=1"))
209 ses.dataallowed = 1; /* we can send other packets again now */
210 ses.kexstate.donefirstkex = 1;
211 } else {
212 TRACE(("RECVNEWKEYS=1"))
213 ses.kexstate.recvnewkeys = 1;
214 }
215 224
216 TRACE(("leave recv_msg_newkeys")) 225 TRACE(("leave recv_msg_newkeys"))
217 } 226 }
218 227
219 228
291 * This occurs after the DH key-exchange. 300 * This occurs after the DH key-exchange.
292 * 301 *
293 * ses.newkeys is the new set of keys which are generated, these are only 302 * ses.newkeys is the new set of keys which are generated, these are only
294 * taken into use after both sides have sent a newkeys message */ 303 * taken into use after both sides have sent a newkeys message */
295 304
296 /* Originally from kex.c, generalized for cli/svr mode --mihnea */ 305 static void gen_new_keys() {
297 void gen_new_keys() {
298 306
299 unsigned char C2S_IV[MAX_IV_LEN]; 307 unsigned char C2S_IV[MAX_IV_LEN];
300 unsigned char C2S_key[MAX_KEY_LEN]; 308 unsigned char C2S_key[MAX_KEY_LEN];
301 unsigned char S2C_IV[MAX_IV_LEN]; 309 unsigned char S2C_IV[MAX_IV_LEN];
302 unsigned char S2C_key[MAX_KEY_LEN]; 310 unsigned char S2C_key[MAX_KEY_LEN];
380 388
381 #ifndef DISABLE_ZLIB 389 #ifndef DISABLE_ZLIB
382 gen_new_zstreams(); 390 gen_new_zstreams();
383 #endif 391 #endif
384 392
385 /* Switch over to the new keys */ 393 /* Ready to switch over */
386 m_burn(ses.keys, sizeof(struct key_context)); 394 ses.newkeys->trans.valid = 1;
387 m_free(ses.keys); 395 ses.newkeys->recv.valid = 1;
388 ses.keys = ses.newkeys;
389 ses.newkeys = NULL;
390 396
391 m_burn(C2S_IV, sizeof(C2S_IV)); 397 m_burn(C2S_IV, sizeof(C2S_IV));
392 m_burn(C2S_key, sizeof(C2S_key)); 398 m_burn(C2S_key, sizeof(C2S_key));
393 m_burn(S2C_IV, sizeof(S2C_IV)); 399 m_burn(S2C_IV, sizeof(S2C_IV));
394 m_burn(S2C_key, sizeof(S2C_key)); 400 m_burn(S2C_key, sizeof(S2C_key));