comparison packet.c @ 533:805ae74ec024

Encrypt in-place, avoid an extra malloc
author Matt Johnston <matt@ucc.asn.au>
date Sun, 01 Mar 2009 14:38:25 +0000
parents c67c8c0c6c35
children 0431915df79f
comparison
equal deleted inserted replaced
532:c67c8c0c6c35 533:805ae74ec024
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 void read_packet_init();
39 static void writemac(buffer * outputbuffer, buffer * clearwritebuf); 39 static void make_mac(buffer * clearwritebuf, unsigned char *output_mac);
40 static int checkmac(buffer* hashbuf, buffer* readbuf); 40 static int checkmac(buffer* hashbuf, buffer* readbuf);
41 41
42 #define ZLIB_COMPRESS_INCR 20 /* this is 12 bytes + 0.1% of 8000 bytes */ 42 #define ZLIB_COMPRESS_INCR 20 /* this is 12 bytes + 0.1% of 8000 bytes */
43 #define ZLIB_DECOMPRESS_INCR 100 43 #define ZLIB_DECOMPRESS_INCR 100
44 #ifndef DISABLE_ZLIB 44 #ifndef DISABLE_ZLIB
447 /* encrypt the writepayload, putting into writebuf, ready for write_packet() 447 /* encrypt the writepayload, putting into writebuf, ready for write_packet()
448 * to put on the wire */ 448 * to put on the wire */
449 void encrypt_packet() { 449 void encrypt_packet() {
450 450
451 unsigned char padlen; 451 unsigned char padlen;
452 unsigned char blocksize, macsize; 452 unsigned char blocksize, mac_size;
453 buffer * writebuf; /* the packet which will go on the wire */ 453 buffer * writebuf; /* the packet which will go on the wire. This is
454 buffer * clearwritebuf; /* unencrypted, possibly compressed */ 454 encrypted in-place. */
455 unsigned char type; 455 unsigned char type;
456 unsigned int len; 456 unsigned int len, encrypt_buf_size;
457 unsigned char mac_bytes[MAX_MAC_LEN];
457 458
458 type = ses.writepayload->data[0]; 459 type = ses.writepayload->data[0];
459 TRACE(("enter encrypt_packet()")) 460 TRACE(("enter encrypt_packet()"))
460 TRACE(("encrypt_packet type is %d", type)) 461 TRACE(("encrypt_packet type is %d", type))
461 462
466 enqueue_reply_packet(); 467 enqueue_reply_packet();
467 return; 468 return;
468 } 469 }
469 470
470 blocksize = ses.keys->trans_algo_crypt->blocksize; 471 blocksize = ses.keys->trans_algo_crypt->blocksize;
471 macsize = ses.keys->trans_algo_mac->hashsize; 472 mac_size = ses.keys->trans_algo_mac->hashsize;
472 473
473 /* Encrypted packet len is payload+5, then worst case is if we are 3 away 474 /* Encrypted packet len is payload+5, then worst case is if we are 3 away
474 * from a blocksize multiple. In which case we need to pad to the 475 * from a blocksize multiple. In which case we need to pad to the
475 * multiple, then add another blocksize (or MIN_PACKET_LEN) */ 476 * multiple, then add another blocksize (or MIN_PACKET_LEN) */
476 len = (ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3; 477 encrypt_buf_size = (ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3;
478 /* add space for the MAC at the end */
479 encrypt_buf_size += mac_size;
477 480
478 #ifndef DISABLE_ZLIB 481 #ifndef DISABLE_ZLIB
479 len += ZLIB_COMPRESS_INCR; /* bit of a kludge, but we can't know len*/ 482 encrypt_buf_size += ZLIB_COMPRESS_INCR; /* bit of a kludge, but we can't know len*/
480 #endif 483 #endif
481 clearwritebuf = buf_new(len); 484 writebuf = buf_new(encrypt_buf_size);
482 buf_setlen(clearwritebuf, PACKET_PAYLOAD_OFF); 485 buf_setlen(writebuf, PACKET_PAYLOAD_OFF);
483 buf_setpos(clearwritebuf, PACKET_PAYLOAD_OFF); 486 buf_setpos(writebuf, PACKET_PAYLOAD_OFF);
484 487
485 buf_setpos(ses.writepayload, 0); 488 buf_setpos(ses.writepayload, 0);
486 489
487 #ifndef DISABLE_ZLIB 490 #ifndef DISABLE_ZLIB
488 /* compression */ 491 /* compression */
489 if (is_compress_trans()) { 492 if (is_compress_trans()) {
490 buf_compress(clearwritebuf, ses.writepayload, ses.writepayload->len); 493 buf_compress(writebuf, ses.writepayload, ses.writepayload->len);
491 } else 494 } else
492 #endif 495 #endif
493 { 496 {
494 memcpy(buf_getwriteptr(clearwritebuf, ses.writepayload->len), 497 memcpy(buf_getwriteptr(writebuf, ses.writepayload->len),
495 buf_getptr(ses.writepayload, ses.writepayload->len), 498 buf_getptr(ses.writepayload, ses.writepayload->len),
496 ses.writepayload->len); 499 ses.writepayload->len);
497 buf_incrwritepos(clearwritebuf, ses.writepayload->len); 500 buf_incrwritepos(writebuf, ses.writepayload->len);
498 } 501 }
499 502
500 /* finished with payload */ 503 /* finished with payload */
501 buf_setpos(ses.writepayload, 0); 504 buf_setpos(ses.writepayload, 0);
502 buf_setlen(ses.writepayload, 0); 505 buf_setlen(ses.writepayload, 0);
503 506
504 /* length of padding - packet length must be a multiple of blocksize, 507 /* length of padding - packet length must be a multiple of blocksize,
505 * with a minimum of 4 bytes of padding */ 508 * with a minimum of 4 bytes of padding */
506 padlen = blocksize - (clearwritebuf->len) % blocksize; 509 padlen = blocksize - (writebuf->len) % blocksize;
507 if (padlen < 4) { 510 if (padlen < 4) {
508 padlen += blocksize; 511 padlen += blocksize;
509 } 512 }
510 /* check for min packet length */ 513 /* check for min packet length */
511 if (clearwritebuf->len + padlen < MIN_PACKET_LEN) { 514 if (writebuf->len + padlen < MIN_PACKET_LEN) {
512 padlen += blocksize; 515 padlen += blocksize;
513 } 516 }
514 517
515 buf_setpos(clearwritebuf, 0); 518 buf_setpos(writebuf, 0);
516 /* packet length excluding the packetlength uint32 */ 519 /* packet length excluding the packetlength uint32 */
517 buf_putint(clearwritebuf, clearwritebuf->len + padlen - 4); 520 buf_putint(writebuf, writebuf->len + padlen - 4);
518 521
519 /* padding len */ 522 /* padding len */
520 buf_putbyte(clearwritebuf, padlen); 523 buf_putbyte(writebuf, padlen);
521 /* actual padding */ 524 /* actual padding */
522 buf_setpos(clearwritebuf, clearwritebuf->len); 525 buf_setpos(writebuf, writebuf->len);
523 buf_incrlen(clearwritebuf, padlen); 526 buf_incrlen(writebuf, padlen);
524 genrandom(buf_getptr(clearwritebuf, padlen), padlen); 527 genrandom(buf_getptr(writebuf, padlen), padlen);
525 528
526 /* do the actual encryption */ 529 make_mac(writebuf, mac_bytes);
527 buf_setpos(clearwritebuf, 0); 530
528 /* create a new writebuffer, this is freed when it has been put on the 531 /* do the actual encryption, in-place */
529 * wire by writepacket() */ 532 buf_setpos(writebuf, 0);
530 writebuf = buf_new(clearwritebuf->len + macsize); 533 /* encrypt it in-place*/
531 534 len = writebuf->len;
532 /* encrypt it */
533 len = clearwritebuf->len;
534 if (ses.keys->trans_crypt_mode->encrypt( 535 if (ses.keys->trans_crypt_mode->encrypt(
535 buf_getptr(clearwritebuf, len), 536 buf_getptr(writebuf, len),
536 buf_getwriteptr(writebuf, len), 537 buf_getwriteptr(writebuf, len),
537 len, 538 len,
538 &ses.keys->trans_cipher_state) != CRYPT_OK) { 539 &ses.keys->trans_cipher_state) != CRYPT_OK) {
539 dropbear_exit("error encrypting"); 540 dropbear_exit("error encrypting");
540 } 541 }
541 buf_incrpos(clearwritebuf, len); 542 buf_incrpos(writebuf, len);
542 buf_incrwritepos(writebuf, len); 543
543 544 /* stick the MAC on it */
544 /* now add a hmac and we're done */ 545 buf_putbytes(writebuf, mac_bytes, mac_size);
545 writemac(writebuf, clearwritebuf); 546
546 547 /* enqueue the packet for sending. It will get freed after transmission. */
547 /* clearwritebuf is finished with */
548 buf_free(clearwritebuf);
549 clearwritebuf = NULL;
550
551 /* enqueue the packet for sending */
552 buf_setpos(writebuf, 0); 548 buf_setpos(writebuf, 0);
553 enqueue(&ses.writequeue, (void*)writebuf); 549 enqueue(&ses.writequeue, (void*)writebuf);
554 550
555 /* Update counts */ 551 /* Update counts */
556 ses.kexstate.datatrans += writebuf->len; 552 ses.kexstate.datatrans += writebuf->len;
559 TRACE(("leave encrypt_packet()")) 555 TRACE(("leave encrypt_packet()"))
560 } 556 }
561 557
562 558
563 /* Create the packet mac, and append H(seqno|clearbuf) to the output */ 559 /* Create the packet mac, and append H(seqno|clearbuf) to the output */
564 static void writemac(buffer * outputbuffer, buffer * clearwritebuf) { 560 /* output_mac must have ses.keys->trans_algo_mac->hashsize bytes. */
565 561 static void make_mac(buffer * clearwritebuf, unsigned char *output_mac) {
566 unsigned int macsize;
567 unsigned char seqbuf[4]; 562 unsigned char seqbuf[4];
568 unsigned char tempbuf[MAX_MAC_LEN];
569 unsigned long bufsize; 563 unsigned long bufsize;
570 hmac_state hmac; 564 hmac_state hmac;
571 565
572 TRACE(("enter writemac")) 566 TRACE(("enter writemac"))
573 567
574 macsize = ses.keys->trans_algo_mac->hashsize; 568 if (ses.keys->trans_algo_mac->hashsize > 0) {
575 if (macsize > 0) {
576 /* calculate the mac */ 569 /* calculate the mac */
577 if (hmac_init(&hmac, 570 if (hmac_init(&hmac,
578 find_hash(ses.keys->trans_algo_mac->hashdesc->name), 571 find_hash(ses.keys->trans_algo_mac->hashdesc->name),
579 ses.keys->transmackey, 572 ses.keys->transmackey,
580 ses.keys->trans_algo_mac->keysize) != CRYPT_OK) { 573 ses.keys->trans_algo_mac->keysize) != CRYPT_OK) {
594 clearwritebuf->len), 587 clearwritebuf->len),
595 clearwritebuf->len) != CRYPT_OK) { 588 clearwritebuf->len) != CRYPT_OK) {
596 dropbear_exit("HMAC error"); 589 dropbear_exit("HMAC error");
597 } 590 }
598 591
599 bufsize = sizeof(tempbuf); 592 bufsize = MAX_MAC_LEN;
600 if (hmac_done(&hmac, tempbuf, &bufsize) 593 if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) {
601 != CRYPT_OK) {
602 dropbear_exit("HMAC error"); 594 dropbear_exit("HMAC error");
603 } 595 }
604 buf_putbytes(outputbuffer, tempbuf, macsize);
605 } 596 }
606 TRACE(("leave writemac")) 597 TRACE(("leave writemac"))
607 } 598 }
608 599
609 #ifndef DISABLE_ZLIB 600 #ifndef DISABLE_ZLIB