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);