Mercurial > dropbear
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 |