Mercurial > dropbear
comparison packet.c @ 546:568638be7203 agent-client
propagate from branch 'au.asn.ucc.matt.dropbear' (head 899a8851a5edf840b2f7925bcc26ffe99dcac54d)
to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 6bbab8364de17bd9ecb1dee5ffb796e48c0380d2)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 01 Jul 2009 04:16:32 +0000 |
parents | 21490eea261d |
children | ccdc4c6183c0 |
comparison
equal
deleted
inserted
replaced
500:d588e3ea557a | 546:568638be7203 |
---|---|
33 #include "random.h" | 33 #include "random.h" |
34 #include "service.h" | 34 #include "service.h" |
35 #include "auth.h" | 35 #include "auth.h" |
36 #include "channel.h" | 36 #include "channel.h" |
37 | 37 |
38 static void read_packet_init(); | 38 static int read_packet_init(); |
39 static void writemac(buffer * outputbuffer, buffer * clearwritebuf); | 39 static void make_mac(unsigned int seqno, const struct key_context_directional * key_state, |
40 static int checkmac(buffer* hashbuf, buffer* readbuf); | 40 buffer * clear_buf, unsigned int clear_len, |
41 unsigned char *output_mac); | |
42 static int checkmac(); | |
41 | 43 |
42 #define ZLIB_COMPRESS_INCR 20 /* this is 12 bytes + 0.1% of 8000 bytes */ | 44 #define ZLIB_COMPRESS_INCR 20 /* this is 12 bytes + 0.1% of 8000 bytes */ |
43 #define ZLIB_DECOMPRESS_INCR 100 | 45 #define ZLIB_DECOMPRESS_INCR 100 |
44 #ifndef DISABLE_ZLIB | 46 #ifndef DISABLE_ZLIB |
45 static buffer* buf_decompress(buffer* buf, unsigned int len); | 47 static buffer* buf_decompress(buffer* buf, unsigned int len); |
70 } else { | 72 } else { |
71 dropbear_exit("error writing"); | 73 dropbear_exit("error writing"); |
72 } | 74 } |
73 } | 75 } |
74 | 76 |
77 ses.last_trx_packet_time = time(NULL); | |
75 ses.last_packet_time = time(NULL); | 78 ses.last_packet_time = time(NULL); |
76 | 79 |
77 if (written == 0) { | 80 if (written == 0) { |
78 ses.remoteclosed(); | 81 ses.remoteclosed(); |
79 } | 82 } |
99 int len; | 102 int len; |
100 unsigned int maxlen; | 103 unsigned int maxlen; |
101 unsigned char blocksize; | 104 unsigned char blocksize; |
102 | 105 |
103 TRACE(("enter read_packet")) | 106 TRACE(("enter read_packet")) |
104 blocksize = ses.keys->recv_algo_crypt->blocksize; | 107 blocksize = ses.keys->recv.algo_crypt->blocksize; |
105 | 108 |
106 if (ses.readbuf == NULL || ses.readbuf->len < blocksize) { | 109 if (ses.readbuf == NULL || ses.readbuf->len < blocksize) { |
110 int ret; | |
107 /* In the first blocksize of a packet */ | 111 /* In the first blocksize of a packet */ |
108 | 112 |
109 /* Read the first blocksize of the packet, so we can decrypt it and | 113 /* Read the first blocksize of the packet, so we can decrypt it and |
110 * find the length of the whole packet */ | 114 * find the length of the whole packet */ |
111 read_packet_init(); | 115 ret = read_packet_init(); |
112 | 116 |
113 /* If we don't have the length of decryptreadbuf, we didn't read | 117 if (ret == DROPBEAR_FAILURE) { |
114 * a whole blocksize and should exit */ | 118 /* didn't read enough to determine the length */ |
115 if (ses.decryptreadbuf->len == 0) { | |
116 TRACE(("leave read_packet: packetinit done")) | 119 TRACE(("leave read_packet: packetinit done")) |
117 return; | 120 return; |
118 } | 121 } |
119 } | 122 } |
120 | 123 |
121 /* Attempt to read the remainder of the packet, note that there | 124 /* Attempt to read the remainder of the packet, note that there |
122 * mightn't be any available (EAGAIN) */ | 125 * mightn't be any available (EAGAIN) */ |
123 dropbear_assert(ses.readbuf != NULL); | |
124 maxlen = ses.readbuf->len - ses.readbuf->pos; | 126 maxlen = ses.readbuf->len - ses.readbuf->pos; |
125 len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen); | 127 len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen); |
126 | 128 |
127 if (len == 0) { | 129 if (len == 0) { |
128 ses.remoteclosed(); | 130 ses.remoteclosed(); |
148 TRACE(("leave read_packet")) | 150 TRACE(("leave read_packet")) |
149 } | 151 } |
150 | 152 |
151 /* Function used to read the initial portion of a packet, and determine the | 153 /* Function used to read the initial portion of a packet, and determine the |
152 * length. Only called during the first BLOCKSIZE of a packet. */ | 154 * length. Only called during the first BLOCKSIZE of a packet. */ |
153 static void read_packet_init() { | 155 /* Returns DROPBEAR_SUCCESS if the length is determined, |
156 * DROPBEAR_FAILURE otherwise */ | |
157 static int read_packet_init() { | |
154 | 158 |
155 unsigned int maxlen; | 159 unsigned int maxlen; |
156 int len; | 160 int len; |
157 unsigned char blocksize; | 161 unsigned char blocksize; |
158 unsigned char macsize; | 162 unsigned char macsize; |
159 | 163 |
160 | 164 |
161 blocksize = ses.keys->recv_algo_crypt->blocksize; | 165 blocksize = ses.keys->recv.algo_crypt->blocksize; |
162 macsize = ses.keys->recv_algo_mac->hashsize; | 166 macsize = ses.keys->recv.algo_mac->hashsize; |
163 | 167 |
164 if (ses.readbuf == NULL) { | 168 if (ses.readbuf == NULL) { |
165 /* start of a new packet */ | 169 /* start of a new packet */ |
166 ses.readbuf = buf_new(INIT_READBUF); | 170 ses.readbuf = buf_new(INIT_READBUF); |
167 dropbear_assert(ses.decryptreadbuf == NULL); | |
168 ses.decryptreadbuf = buf_new(blocksize); | |
169 } | 171 } |
170 | 172 |
171 maxlen = blocksize - ses.readbuf->pos; | 173 maxlen = blocksize - ses.readbuf->pos; |
172 | 174 |
173 /* read the rest of the packet if possible */ | 175 /* read the rest of the packet if possible */ |
177 ses.remoteclosed(); | 179 ses.remoteclosed(); |
178 } | 180 } |
179 if (len < 0) { | 181 if (len < 0) { |
180 if (errno == EINTR) { | 182 if (errno == EINTR) { |
181 TRACE(("leave read_packet_init: EINTR")) | 183 TRACE(("leave read_packet_init: EINTR")) |
182 return; | 184 return DROPBEAR_FAILURE; |
183 } | 185 } |
184 dropbear_exit("error reading: %s", strerror(errno)); | 186 dropbear_exit("error reading: %s", strerror(errno)); |
185 } | 187 } |
186 | 188 |
187 buf_incrwritepos(ses.readbuf, len); | 189 buf_incrwritepos(ses.readbuf, len); |
188 | 190 |
189 if ((unsigned int)len != maxlen) { | 191 if ((unsigned int)len != maxlen) { |
190 /* don't have enough bytes to determine length, get next time */ | 192 /* don't have enough bytes to determine length, get next time */ |
191 return; | 193 return DROPBEAR_FAILURE; |
192 } | 194 } |
193 | 195 |
194 /* now we have the first block, need to get packet length, so we decrypt | 196 /* now we have the first block, need to get packet length, so we decrypt |
195 * the first block (only need first 4 bytes) */ | 197 * the first block (only need first 4 bytes) */ |
196 buf_setpos(ses.readbuf, 0); | 198 buf_setpos(ses.readbuf, 0); |
197 if (ses.keys->recv_algo_crypt->cipherdesc == NULL) { | 199 if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), |
198 /* copy it */ | 200 buf_getwriteptr(ses.readbuf, blocksize), |
199 memcpy(buf_getwriteptr(ses.decryptreadbuf, blocksize), | 201 blocksize, |
200 buf_getptr(ses.readbuf, blocksize), | 202 &ses.keys->recv.cipher_state) != CRYPT_OK) { |
201 blocksize); | 203 dropbear_exit("error decrypting"); |
202 } else { | 204 } |
203 /* decrypt it */ | 205 len = buf_getint(ses.readbuf) + 4 + macsize; |
204 if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize), | 206 |
205 buf_getwriteptr(ses.decryptreadbuf,blocksize), | 207 TRACE(("packet size is %d, block %d mac %d", len, blocksize, macsize)) |
206 blocksize, | 208 |
207 &ses.keys->recv_symmetric_struct) != CRYPT_OK) { | |
208 dropbear_exit("error decrypting"); | |
209 } | |
210 } | |
211 buf_setlen(ses.decryptreadbuf, blocksize); | |
212 len = buf_getint(ses.decryptreadbuf) + 4 + macsize; | |
213 | |
214 buf_setpos(ses.readbuf, blocksize); | |
215 | 209 |
216 /* check packet length */ | 210 /* check packet length */ |
217 if ((len > RECV_MAX_PACKET_LEN) || | 211 if ((len > RECV_MAX_PACKET_LEN) || |
218 (len < MIN_PACKET_LEN + macsize) || | 212 (len < MIN_PACKET_LEN + macsize) || |
219 ((len - macsize) % blocksize != 0)) { | 213 ((len - macsize) % blocksize != 0)) { |
220 dropbear_exit("bad packet size %d", len); | 214 dropbear_exit("bad packet size %d", len); |
221 } | 215 } |
222 | 216 |
223 buf_resize(ses.readbuf, len); | 217 if (len > ses.readbuf->size) { |
218 buf_resize(ses.readbuf, len); | |
219 } | |
224 buf_setlen(ses.readbuf, len); | 220 buf_setlen(ses.readbuf, len); |
225 | 221 buf_setpos(ses.readbuf, blocksize); |
222 return DROPBEAR_SUCCESS; | |
226 } | 223 } |
227 | 224 |
228 /* handle the received packet */ | 225 /* handle the received packet */ |
229 void decrypt_packet() { | 226 void decrypt_packet() { |
230 | 227 |
232 unsigned char macsize; | 229 unsigned char macsize; |
233 unsigned int padlen; | 230 unsigned int padlen; |
234 unsigned int len; | 231 unsigned int len; |
235 | 232 |
236 TRACE(("enter decrypt_packet")) | 233 TRACE(("enter decrypt_packet")) |
237 blocksize = ses.keys->recv_algo_crypt->blocksize; | 234 blocksize = ses.keys->recv.algo_crypt->blocksize; |
238 macsize = ses.keys->recv_algo_mac->hashsize; | 235 macsize = ses.keys->recv.algo_mac->hashsize; |
239 | 236 |
240 ses.kexstate.datarecv += ses.readbuf->len; | 237 ses.kexstate.datarecv += ses.readbuf->len; |
241 | 238 |
242 /* we've already decrypted the first blocksize in read_packet_init */ | 239 /* we've already decrypted the first blocksize in read_packet_init */ |
243 buf_setpos(ses.readbuf, blocksize); | 240 buf_setpos(ses.readbuf, blocksize); |
244 | 241 |
245 buf_resize(ses.decryptreadbuf, ses.readbuf->len - macsize); | 242 /* decrypt it in-place */ |
246 buf_setlen(ses.decryptreadbuf, ses.decryptreadbuf->size); | 243 len = ses.readbuf->len - macsize - ses.readbuf->pos; |
247 buf_setpos(ses.decryptreadbuf, blocksize); | 244 if (ses.keys->recv.crypt_mode->decrypt( |
248 | 245 buf_getptr(ses.readbuf, len), |
249 /* decrypt if encryption is set, memcpy otherwise */ | 246 buf_getwriteptr(ses.readbuf, len), |
250 if (ses.keys->recv_algo_crypt->cipherdesc == NULL) { | 247 len, |
251 /* copy it */ | 248 &ses.keys->recv.cipher_state) != CRYPT_OK) { |
252 len = ses.readbuf->len - macsize - blocksize; | 249 dropbear_exit("error decrypting"); |
253 memcpy(buf_getwriteptr(ses.decryptreadbuf, len), | 250 } |
254 buf_getptr(ses.readbuf, len), len); | 251 buf_incrpos(ses.readbuf, len); |
255 } else { | |
256 /* decrypt */ | |
257 while (ses.readbuf->pos < ses.readbuf->len - macsize) { | |
258 if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize), | |
259 buf_getwriteptr(ses.decryptreadbuf, blocksize), | |
260 blocksize, | |
261 &ses.keys->recv_symmetric_struct) != CRYPT_OK) { | |
262 dropbear_exit("error decrypting"); | |
263 } | |
264 buf_incrpos(ses.readbuf, blocksize); | |
265 buf_incrwritepos(ses.decryptreadbuf, blocksize); | |
266 } | |
267 } | |
268 | 252 |
269 /* check the hmac */ | 253 /* check the hmac */ |
270 buf_setpos(ses.readbuf, ses.readbuf->len - macsize); | 254 if (checkmac() != DROPBEAR_SUCCESS) { |
271 if (checkmac(ses.readbuf, ses.decryptreadbuf) != DROPBEAR_SUCCESS) { | |
272 dropbear_exit("Integrity error"); | 255 dropbear_exit("Integrity error"); |
273 } | 256 } |
274 | 257 |
275 /* readbuf no longer required */ | |
276 buf_free(ses.readbuf); | |
277 ses.readbuf = NULL; | |
278 | |
279 /* get padding length */ | 258 /* get padding length */ |
280 buf_setpos(ses.decryptreadbuf, PACKET_PADDING_OFF); | 259 buf_setpos(ses.readbuf, PACKET_PADDING_OFF); |
281 padlen = buf_getbyte(ses.decryptreadbuf); | 260 padlen = buf_getbyte(ses.readbuf); |
282 | 261 |
283 /* payload length */ | 262 /* payload length */ |
284 /* - 4 - 1 is for LEN and PADLEN values */ | 263 /* - 4 - 1 is for LEN and PADLEN values */ |
285 len = ses.decryptreadbuf->len - padlen - 4 - 1; | 264 len = ses.readbuf->len - padlen - 4 - 1; |
286 if ((len > RECV_MAX_PAYLOAD_LEN) || (len < 1)) { | 265 if ((len > RECV_MAX_PAYLOAD_LEN) || (len < 1)) { |
287 dropbear_exit("bad packet size"); | 266 dropbear_exit("bad packet size"); |
288 } | 267 } |
289 | 268 |
290 buf_setpos(ses.decryptreadbuf, PACKET_PAYLOAD_OFF); | 269 buf_setpos(ses.readbuf, PACKET_PAYLOAD_OFF); |
291 | 270 |
292 #ifndef DISABLE_ZLIB | 271 #ifndef DISABLE_ZLIB |
293 if (ses.keys->recv_algo_comp == DROPBEAR_COMP_ZLIB) { | 272 if (is_compress_recv()) { |
294 /* decompress */ | 273 /* decompress */ |
295 ses.payload = buf_decompress(ses.decryptreadbuf, len); | 274 ses.payload = buf_decompress(ses.readbuf, len); |
296 | |
297 } else | 275 } else |
298 #endif | 276 #endif |
299 { | 277 { |
300 /* copy payload */ | 278 /* copy payload */ |
301 ses.payload = buf_new(len); | 279 ses.payload = buf_new(len); |
302 memcpy(ses.payload->data, buf_getptr(ses.decryptreadbuf, len), len); | 280 memcpy(ses.payload->data, buf_getptr(ses.readbuf, len), len); |
303 buf_incrlen(ses.payload, len); | 281 buf_incrlen(ses.payload, len); |
304 } | 282 } |
305 | 283 |
306 buf_free(ses.decryptreadbuf); | 284 buf_free(ses.readbuf); |
307 ses.decryptreadbuf = NULL; | 285 ses.readbuf = NULL; |
308 buf_setpos(ses.payload, 0); | 286 buf_setpos(ses.payload, 0); |
309 | 287 |
310 ses.recvseq++; | 288 ses.recvseq++; |
311 | 289 |
312 TRACE(("leave decrypt_packet")) | 290 TRACE(("leave decrypt_packet")) |
313 } | 291 } |
314 | 292 |
315 /* Checks the mac in hashbuf, for the data in readbuf. | 293 /* Checks the mac at the end of a decrypted readbuf. |
316 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ | 294 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ |
317 static int checkmac(buffer* macbuf, buffer* sourcebuf) { | 295 static int checkmac() { |
318 | 296 |
319 unsigned int macsize; | 297 unsigned char mac_bytes[MAX_MAC_LEN]; |
320 hmac_state hmac; | 298 unsigned int mac_size, contents_len; |
321 unsigned char tempbuf[MAX_MAC_LEN]; | 299 |
322 unsigned long bufsize; | 300 mac_size = ses.keys->trans.algo_mac->hashsize; |
323 unsigned int len; | 301 contents_len = ses.readbuf->len - mac_size; |
324 | 302 |
325 macsize = ses.keys->recv_algo_mac->hashsize; | 303 buf_setpos(ses.readbuf, 0); |
326 if (macsize == 0) { | 304 make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes); |
327 return DROPBEAR_SUCCESS; | |
328 } | |
329 | |
330 /* calculate the mac */ | |
331 if (hmac_init(&hmac, | |
332 find_hash(ses.keys->recv_algo_mac->hashdesc->name), | |
333 ses.keys->recvmackey, | |
334 ses.keys->recv_algo_mac->keysize) | |
335 != CRYPT_OK) { | |
336 dropbear_exit("HMAC error"); | |
337 } | |
338 | |
339 /* sequence number */ | |
340 STORE32H(ses.recvseq, tempbuf); | |
341 if (hmac_process(&hmac, tempbuf, 4) != CRYPT_OK) { | |
342 dropbear_exit("HMAC error"); | |
343 } | |
344 | |
345 buf_setpos(sourcebuf, 0); | |
346 len = sourcebuf->len; | |
347 if (hmac_process(&hmac, buf_getptr(sourcebuf, len), len) != CRYPT_OK) { | |
348 dropbear_exit("HMAC error"); | |
349 } | |
350 | |
351 bufsize = sizeof(tempbuf); | |
352 if (hmac_done(&hmac, tempbuf, &bufsize) != CRYPT_OK) { | |
353 dropbear_exit("HMAC error"); | |
354 } | |
355 | 305 |
356 /* compare the hash */ | 306 /* compare the hash */ |
357 if (memcmp(tempbuf, buf_getptr(macbuf, macsize), macsize) != 0) { | 307 buf_setpos(ses.readbuf, contents_len); |
308 if (memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) { | |
358 return DROPBEAR_FAILURE; | 309 return DROPBEAR_FAILURE; |
359 } else { | 310 } else { |
360 return DROPBEAR_SUCCESS; | 311 return DROPBEAR_SUCCESS; |
361 } | 312 } |
362 } | 313 } |
367 | 318 |
368 int result; | 319 int result; |
369 buffer * ret; | 320 buffer * ret; |
370 z_streamp zstream; | 321 z_streamp zstream; |
371 | 322 |
372 zstream = ses.keys->recv_zstream; | 323 zstream = ses.keys->recv.zstream; |
373 ret = buf_new(len); | 324 ret = buf_new(len); |
374 | 325 |
375 zstream->avail_in = len; | 326 zstream->avail_in = len; |
376 zstream->next_in = buf_getptr(buf, len); | 327 zstream->next_in = buf_getptr(buf, len); |
377 | 328 |
463 /* encrypt the writepayload, putting into writebuf, ready for write_packet() | 414 /* encrypt the writepayload, putting into writebuf, ready for write_packet() |
464 * to put on the wire */ | 415 * to put on the wire */ |
465 void encrypt_packet() { | 416 void encrypt_packet() { |
466 | 417 |
467 unsigned char padlen; | 418 unsigned char padlen; |
468 unsigned char blocksize, macsize; | 419 unsigned char blocksize, mac_size; |
469 buffer * writebuf; /* the packet which will go on the wire */ | 420 buffer * writebuf; /* the packet which will go on the wire. This is |
470 buffer * clearwritebuf; /* unencrypted, possibly compressed */ | 421 encrypted in-place. */ |
471 unsigned char type; | 422 unsigned char type; |
423 unsigned int len, encrypt_buf_size; | |
424 unsigned char mac_bytes[MAX_MAC_LEN]; | |
472 | 425 |
473 type = ses.writepayload->data[0]; | 426 type = ses.writepayload->data[0]; |
474 TRACE(("enter encrypt_packet()")) | 427 TRACE(("enter encrypt_packet()")) |
475 TRACE(("encrypt_packet type is %d", type)) | 428 TRACE(("encrypt_packet type is %d", type)) |
476 | 429 |
480 after the KEX, see maybe_flush_reply_queue */ | 433 after the KEX, see maybe_flush_reply_queue */ |
481 enqueue_reply_packet(); | 434 enqueue_reply_packet(); |
482 return; | 435 return; |
483 } | 436 } |
484 | 437 |
485 blocksize = ses.keys->trans_algo_crypt->blocksize; | 438 blocksize = ses.keys->trans.algo_crypt->blocksize; |
486 macsize = ses.keys->trans_algo_mac->hashsize; | 439 mac_size = ses.keys->trans.algo_mac->hashsize; |
487 | 440 |
488 /* Encrypted packet len is payload+5, then worst case is if we are 3 away | 441 /* Encrypted packet len is payload+5, then worst case is if we are 3 away |
489 * from a blocksize multiple. In which case we need to pad to the | 442 * from a blocksize multiple. In which case we need to pad to the |
490 * multiple, then add another blocksize (or MIN_PACKET_LEN) */ | 443 * multiple, then add another blocksize (or MIN_PACKET_LEN) */ |
491 clearwritebuf = buf_new((ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3 | 444 encrypt_buf_size = (ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3; |
445 /* add space for the MAC at the end */ | |
446 encrypt_buf_size += mac_size; | |
447 | |
492 #ifndef DISABLE_ZLIB | 448 #ifndef DISABLE_ZLIB |
493 + ZLIB_COMPRESS_INCR /* bit of a kludge, but we can't know len*/ | 449 encrypt_buf_size += ZLIB_COMPRESS_INCR; /* bit of a kludge, but we can't know len*/ |
494 #endif | 450 #endif |
495 ); | 451 writebuf = buf_new(encrypt_buf_size); |
496 buf_setlen(clearwritebuf, PACKET_PAYLOAD_OFF); | 452 buf_setlen(writebuf, PACKET_PAYLOAD_OFF); |
497 buf_setpos(clearwritebuf, PACKET_PAYLOAD_OFF); | 453 buf_setpos(writebuf, PACKET_PAYLOAD_OFF); |
498 | 454 |
499 buf_setpos(ses.writepayload, 0); | 455 buf_setpos(ses.writepayload, 0); |
500 | 456 |
501 #ifndef DISABLE_ZLIB | 457 #ifndef DISABLE_ZLIB |
502 /* compression */ | 458 /* compression */ |
503 if (ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB) { | 459 if (is_compress_trans()) { |
504 buf_compress(clearwritebuf, ses.writepayload, ses.writepayload->len); | 460 buf_compress(writebuf, ses.writepayload, ses.writepayload->len); |
505 } else | 461 } else |
506 #endif | 462 #endif |
507 { | 463 { |
508 memcpy(buf_getwriteptr(clearwritebuf, ses.writepayload->len), | 464 memcpy(buf_getwriteptr(writebuf, ses.writepayload->len), |
509 buf_getptr(ses.writepayload, ses.writepayload->len), | 465 buf_getptr(ses.writepayload, ses.writepayload->len), |
510 ses.writepayload->len); | 466 ses.writepayload->len); |
511 buf_incrwritepos(clearwritebuf, ses.writepayload->len); | 467 buf_incrwritepos(writebuf, ses.writepayload->len); |
512 } | 468 } |
513 | 469 |
514 /* finished with payload */ | 470 /* finished with payload */ |
515 buf_setpos(ses.writepayload, 0); | 471 buf_setpos(ses.writepayload, 0); |
516 buf_setlen(ses.writepayload, 0); | 472 buf_setlen(ses.writepayload, 0); |
517 | 473 |
518 /* length of padding - packet length must be a multiple of blocksize, | 474 /* length of padding - packet length must be a multiple of blocksize, |
519 * with a minimum of 4 bytes of padding */ | 475 * with a minimum of 4 bytes of padding */ |
520 padlen = blocksize - (clearwritebuf->len) % blocksize; | 476 padlen = blocksize - (writebuf->len) % blocksize; |
521 if (padlen < 4) { | 477 if (padlen < 4) { |
522 padlen += blocksize; | 478 padlen += blocksize; |
523 } | 479 } |
524 /* check for min packet length */ | 480 /* check for min packet length */ |
525 if (clearwritebuf->len + padlen < MIN_PACKET_LEN) { | 481 if (writebuf->len + padlen < MIN_PACKET_LEN) { |
526 padlen += blocksize; | 482 padlen += blocksize; |
527 } | 483 } |
528 | 484 |
529 buf_setpos(clearwritebuf, 0); | 485 buf_setpos(writebuf, 0); |
530 /* packet length excluding the packetlength uint32 */ | 486 /* packet length excluding the packetlength uint32 */ |
531 buf_putint(clearwritebuf, clearwritebuf->len + padlen - 4); | 487 buf_putint(writebuf, writebuf->len + padlen - 4); |
532 | 488 |
533 /* padding len */ | 489 /* padding len */ |
534 buf_putbyte(clearwritebuf, padlen); | 490 buf_putbyte(writebuf, padlen); |
535 /* actual padding */ | 491 /* actual padding */ |
536 buf_setpos(clearwritebuf, clearwritebuf->len); | 492 buf_setpos(writebuf, writebuf->len); |
537 buf_incrlen(clearwritebuf, padlen); | 493 buf_incrlen(writebuf, padlen); |
538 genrandom(buf_getptr(clearwritebuf, padlen), padlen); | 494 genrandom(buf_getptr(writebuf, padlen), padlen); |
539 | 495 |
540 /* do the actual encryption */ | 496 make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes); |
541 buf_setpos(clearwritebuf, 0); | 497 |
542 /* create a new writebuffer, this is freed when it has been put on the | 498 /* do the actual encryption, in-place */ |
543 * wire by writepacket() */ | 499 buf_setpos(writebuf, 0); |
544 writebuf = buf_new(clearwritebuf->len + macsize); | 500 /* encrypt it in-place*/ |
545 | 501 len = writebuf->len; |
546 if (ses.keys->trans_algo_crypt->cipherdesc == NULL) { | 502 if (ses.keys->trans.crypt_mode->encrypt( |
547 /* copy it */ | 503 buf_getptr(writebuf, len), |
548 memcpy(buf_getwriteptr(writebuf, clearwritebuf->len), | 504 buf_getwriteptr(writebuf, len), |
549 buf_getptr(clearwritebuf, clearwritebuf->len), | 505 len, |
550 clearwritebuf->len); | 506 &ses.keys->trans.cipher_state) != CRYPT_OK) { |
551 buf_incrwritepos(writebuf, clearwritebuf->len); | 507 dropbear_exit("error encrypting"); |
552 } else { | 508 } |
553 /* encrypt it */ | 509 buf_incrpos(writebuf, len); |
554 while (clearwritebuf->pos < clearwritebuf->len) { | 510 |
555 if (cbc_encrypt(buf_getptr(clearwritebuf, blocksize), | 511 /* stick the MAC on it */ |
556 buf_getwriteptr(writebuf, blocksize), | 512 buf_putbytes(writebuf, mac_bytes, mac_size); |
557 blocksize, | 513 |
558 &ses.keys->trans_symmetric_struct) != CRYPT_OK) { | 514 /* enqueue the packet for sending. It will get freed after transmission. */ |
559 dropbear_exit("error encrypting"); | |
560 } | |
561 buf_incrpos(clearwritebuf, blocksize); | |
562 buf_incrwritepos(writebuf, blocksize); | |
563 } | |
564 } | |
565 | |
566 /* now add a hmac and we're done */ | |
567 writemac(writebuf, clearwritebuf); | |
568 | |
569 /* clearwritebuf is finished with */ | |
570 buf_free(clearwritebuf); | |
571 clearwritebuf = NULL; | |
572 | |
573 /* enqueue the packet for sending */ | |
574 buf_setpos(writebuf, 0); | 515 buf_setpos(writebuf, 0); |
575 enqueue(&ses.writequeue, (void*)writebuf); | 516 enqueue(&ses.writequeue, (void*)writebuf); |
576 | 517 |
577 /* Update counts */ | 518 /* Update counts */ |
578 ses.kexstate.datatrans += writebuf->len; | 519 ses.kexstate.datatrans += writebuf->len; |
581 TRACE(("leave encrypt_packet()")) | 522 TRACE(("leave encrypt_packet()")) |
582 } | 523 } |
583 | 524 |
584 | 525 |
585 /* Create the packet mac, and append H(seqno|clearbuf) to the output */ | 526 /* Create the packet mac, and append H(seqno|clearbuf) to the output */ |
586 static void writemac(buffer * outputbuffer, buffer * clearwritebuf) { | 527 /* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */ |
587 | 528 static void make_mac(unsigned int seqno, const struct key_context_directional * key_state, |
588 unsigned int macsize; | 529 buffer * clear_buf, unsigned int clear_len, |
530 unsigned char *output_mac) { | |
589 unsigned char seqbuf[4]; | 531 unsigned char seqbuf[4]; |
590 unsigned char tempbuf[MAX_MAC_LEN]; | |
591 unsigned long bufsize; | 532 unsigned long bufsize; |
592 hmac_state hmac; | 533 hmac_state hmac; |
593 | 534 |
594 TRACE(("enter writemac")) | 535 TRACE(("enter writemac")) |
595 | 536 |
596 macsize = ses.keys->trans_algo_mac->hashsize; | 537 if (key_state->algo_mac->hashsize > 0) { |
597 if (macsize > 0) { | |
598 /* calculate the mac */ | 538 /* calculate the mac */ |
599 if (hmac_init(&hmac, | 539 if (hmac_init(&hmac, |
600 find_hash(ses.keys->trans_algo_mac->hashdesc->name), | 540 key_state->hash_index, |
601 ses.keys->transmackey, | 541 key_state->mackey, |
602 ses.keys->trans_algo_mac->keysize) != CRYPT_OK) { | 542 key_state->algo_mac->keysize) != CRYPT_OK) { |
603 dropbear_exit("HMAC error"); | 543 dropbear_exit("HMAC error"); |
604 } | 544 } |
605 | 545 |
606 /* sequence number */ | 546 /* sequence number */ |
607 STORE32H(ses.transseq, seqbuf); | 547 STORE32H(seqno, seqbuf); |
608 if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) { | 548 if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) { |
609 dropbear_exit("HMAC error"); | 549 dropbear_exit("HMAC error"); |
610 } | 550 } |
611 | 551 |
612 /* the actual contents */ | 552 /* the actual contents */ |
613 buf_setpos(clearwritebuf, 0); | 553 buf_setpos(clear_buf, 0); |
614 if (hmac_process(&hmac, | 554 if (hmac_process(&hmac, |
615 buf_getptr(clearwritebuf, | 555 buf_getptr(clear_buf, clear_len), |
616 clearwritebuf->len), | 556 clear_len) != CRYPT_OK) { |
617 clearwritebuf->len) != CRYPT_OK) { | |
618 dropbear_exit("HMAC error"); | 557 dropbear_exit("HMAC error"); |
619 } | 558 } |
620 | 559 |
621 bufsize = sizeof(tempbuf); | 560 bufsize = MAX_MAC_LEN; |
622 if (hmac_done(&hmac, tempbuf, &bufsize) | 561 if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) { |
623 != CRYPT_OK) { | |
624 dropbear_exit("HMAC error"); | 562 dropbear_exit("HMAC error"); |
625 } | 563 } |
626 buf_putbytes(outputbuffer, tempbuf, macsize); | |
627 } | 564 } |
628 TRACE(("leave writemac")) | 565 TRACE(("leave writemac")) |
629 } | 566 } |
630 | 567 |
631 #ifndef DISABLE_ZLIB | 568 #ifndef DISABLE_ZLIB |
638 | 575 |
639 TRACE(("enter buf_compress")) | 576 TRACE(("enter buf_compress")) |
640 | 577 |
641 while (1) { | 578 while (1) { |
642 | 579 |
643 ses.keys->trans_zstream->avail_in = endpos - src->pos; | 580 ses.keys->trans.zstream->avail_in = endpos - src->pos; |
644 ses.keys->trans_zstream->next_in = | 581 ses.keys->trans.zstream->next_in = |
645 buf_getptr(src, ses.keys->trans_zstream->avail_in); | 582 buf_getptr(src, ses.keys->trans.zstream->avail_in); |
646 | 583 |
647 ses.keys->trans_zstream->avail_out = dest->size - dest->pos; | 584 ses.keys->trans.zstream->avail_out = dest->size - dest->pos; |
648 ses.keys->trans_zstream->next_out = | 585 ses.keys->trans.zstream->next_out = |
649 buf_getwriteptr(dest, ses.keys->trans_zstream->avail_out); | 586 buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out); |
650 | 587 |
651 result = deflate(ses.keys->trans_zstream, Z_SYNC_FLUSH); | 588 result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH); |
652 | 589 |
653 buf_setpos(src, endpos - ses.keys->trans_zstream->avail_in); | 590 buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in); |
654 buf_setlen(dest, dest->size - ses.keys->trans_zstream->avail_out); | 591 buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out); |
655 buf_setpos(dest, dest->len); | 592 buf_setpos(dest, dest->len); |
656 | 593 |
657 if (result != Z_OK) { | 594 if (result != Z_OK) { |
658 dropbear_exit("zlib error"); | 595 dropbear_exit("zlib error"); |
659 } | 596 } |
660 | 597 |
661 if (ses.keys->trans_zstream->avail_in == 0) { | 598 if (ses.keys->trans.zstream->avail_in == 0) { |
662 break; | 599 break; |
663 } | 600 } |
664 | 601 |
665 dropbear_assert(ses.keys->trans_zstream->avail_out == 0); | 602 dropbear_assert(ses.keys->trans.zstream->avail_out == 0); |
666 | 603 |
667 /* the buffer has been filled, we must extend. This only happens in | 604 /* the buffer has been filled, we must extend. This only happens in |
668 * unusual circumstances where the data grows in size after deflate(), | 605 * unusual circumstances where the data grows in size after deflate(), |
669 * but it is possible */ | 606 * but it is possible */ |
670 buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR); | 607 buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR); |