diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-20 17:59:25 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-20 18:04:04 +0100 |
commit | e7863f394e6a963d1e2c6af77ea064442d3ef594 (patch) | |
tree | ee638eb584ad34fdc16219dde8f476cc81bcdadb | |
parent | 6e511393f90a30c93c445c3d1ed6090e79e7384b (diff) | |
download | busybox-w32-e7863f394e6a963d1e2c6af77ea064442d3ef594.tar.gz busybox-w32-e7863f394e6a963d1e2c6af77ea064442d3ef594.tar.bz2 busybox-w32-e7863f394e6a963d1e2c6af77ea064442d3ef594.zip |
tls: was psAesDecrypt'ing one block too many, trashing buffered data
For the first time
printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox tls kernel.org
successfully reads entire server response and TLS shutdown.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/tls.c | 136 |
1 files changed, 73 insertions, 63 deletions
diff --git a/networking/tls.c b/networking/tls.c index 2674997ff..cdce1004e 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -26,7 +26,7 @@ | |||
26 | //#include "common_bufsiz.h" | 26 | //#include "common_bufsiz.h" |
27 | 27 | ||
28 | #define TLS_DEBUG 1 | 28 | #define TLS_DEBUG 1 |
29 | #define TLS_DEBUG_HASH 1 | 29 | #define TLS_DEBUG_HASH 0 |
30 | #define TLS_DEBUG_DER 0 | 30 | #define TLS_DEBUG_DER 0 |
31 | #define TLS_DEBUG_FIXED_SECRETS 0 | 31 | #define TLS_DEBUG_FIXED_SECRETS 0 |
32 | 32 | ||
@@ -42,6 +42,18 @@ | |||
42 | # define dbg_der(...) ((void)0) | 42 | # define dbg_der(...) ((void)0) |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | #if 0 | ||
46 | # define dump_raw_out(...) dump_hex(__VA_ARGS__) | ||
47 | #else | ||
48 | # define dump_raw_out(...) ((void)0) | ||
49 | #endif | ||
50 | |||
51 | #if 1 | ||
52 | # define dump_raw_in(...) dump_hex(__VA_ARGS__) | ||
53 | #else | ||
54 | # define dump_raw_in(...) ((void)0) | ||
55 | #endif | ||
56 | |||
45 | #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 | 57 | #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 |
46 | #define RECORD_TYPE_ALERT 21 | 58 | #define RECORD_TYPE_ALERT 21 |
47 | #define RECORD_TYPE_HANDSHAKE 22 | 59 | #define RECORD_TYPE_HANDSHAKE 22 |
@@ -482,49 +494,11 @@ static void *tls_get_outbuf(tls_state_t *tls, int len) | |||
482 | return tls->outbuf + OUTBUF_PFX; | 494 | return tls->outbuf + OUTBUF_PFX; |
483 | } | 495 | } |
484 | 496 | ||
485 | // RFC 5246 | ||
486 | // 6.2.3.1. Null or Standard Stream Cipher | ||
487 | // | ||
488 | // Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6) | ||
489 | // convert TLSCompressed.fragment structures to and from stream | ||
490 | // TLSCiphertext.fragment structures. | ||
491 | // | ||
492 | // stream-ciphered struct { | ||
493 | // opaque content[TLSCompressed.length]; | ||
494 | // opaque MAC[SecurityParameters.mac_length]; | ||
495 | // } GenericStreamCipher; | ||
496 | // | ||
497 | // The MAC is generated as: | ||
498 | // MAC(MAC_write_key, seq_num + | ||
499 | // TLSCompressed.type + | ||
500 | // TLSCompressed.version + | ||
501 | // TLSCompressed.length + | ||
502 | // TLSCompressed.fragment); | ||
503 | // where "+" denotes concatenation. | ||
504 | // seq_num | ||
505 | // The sequence number for this record. | ||
506 | // MAC | ||
507 | // The MAC algorithm specified by SecurityParameters.mac_algorithm. | ||
508 | // | ||
509 | // Note that the MAC is computed before encryption. The stream cipher | ||
510 | // encrypts the entire block, including the MAC. | ||
511 | //... | ||
512 | // Appendix C. Cipher Suite Definitions | ||
513 | //... | ||
514 | // Key IV Block | ||
515 | // Cipher Type Material Size Size | ||
516 | // ------------ ------ -------- ---- ----- | ||
517 | // AES_128_CBC Block 16 16 16 | ||
518 | // AES_256_CBC Block 32 16 16 | ||
519 | // | ||
520 | // MAC Algorithm mac_length mac_key_length | ||
521 | // -------- ----------- ---------- -------------- | ||
522 | // SHA HMAC-SHA1 20 20 | ||
523 | // SHA256 HMAC-SHA256 32 32 | ||
524 | static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) | 497 | static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) |
525 | { | 498 | { |
526 | uint8_t *buf = tls->outbuf + OUTBUF_PFX; | 499 | uint8_t *buf = tls->outbuf + OUTBUF_PFX; |
527 | struct record_hdr *xhdr; | 500 | struct record_hdr *xhdr; |
501 | uint8_t padding_length; | ||
528 | 502 | ||
529 | xhdr = (void*)(buf - RECHDR_LEN); | 503 | xhdr = (void*)(buf - RECHDR_LEN); |
530 | if (CIPHER_ID != TLS_RSA_WITH_NULL_SHA256) | 504 | if (CIPHER_ID != TLS_RSA_WITH_NULL_SHA256) |
@@ -549,17 +523,49 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) | |||
549 | 523 | ||
550 | size += SHA256_OUTSIZE; | 524 | size += SHA256_OUTSIZE; |
551 | 525 | ||
526 | // RFC 5246 | ||
527 | // 6.2.3.1. Null or Standard Stream Cipher | ||
528 | // | ||
529 | // Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6) | ||
530 | // convert TLSCompressed.fragment structures to and from stream | ||
531 | // TLSCiphertext.fragment structures. | ||
532 | // | ||
533 | // stream-ciphered struct { | ||
534 | // opaque content[TLSCompressed.length]; | ||
535 | // opaque MAC[SecurityParameters.mac_length]; | ||
536 | // } GenericStreamCipher; | ||
537 | // | ||
538 | // The MAC is generated as: | ||
539 | // MAC(MAC_write_key, seq_num + | ||
540 | // TLSCompressed.type + | ||
541 | // TLSCompressed.version + | ||
542 | // TLSCompressed.length + | ||
543 | // TLSCompressed.fragment); | ||
544 | // where "+" denotes concatenation. | ||
545 | // seq_num | ||
546 | // The sequence number for this record. | ||
547 | // MAC | ||
548 | // The MAC algorithm specified by SecurityParameters.mac_algorithm. | ||
549 | // | ||
550 | // Note that the MAC is computed before encryption. The stream cipher | ||
551 | // encrypts the entire block, including the MAC. | ||
552 | //... | ||
553 | // Appendix C. Cipher Suite Definitions | ||
554 | //... | ||
555 | // MAC Algorithm mac_length mac_key_length | ||
556 | // -------- ----------- ---------- -------------- | ||
557 | // SHA HMAC-SHA1 20 20 | ||
558 | // SHA256 HMAC-SHA256 32 32 | ||
552 | if (CIPHER_ID == TLS_RSA_WITH_NULL_SHA256) { | 559 | if (CIPHER_ID == TLS_RSA_WITH_NULL_SHA256) { |
553 | /* No encryption, only signing */ | 560 | /* No encryption, only signing */ |
554 | xhdr->len16_hi = size >> 8; | 561 | xhdr->len16_hi = size >> 8; |
555 | xhdr->len16_lo = size & 0xff; | 562 | xhdr->len16_lo = size & 0xff; |
556 | dump_hex(">> %s\n", xhdr, RECHDR_LEN + size); | 563 | dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); |
557 | xwrite(tls->fd, xhdr, RECHDR_LEN + size); | 564 | xwrite(tls->fd, xhdr, RECHDR_LEN + size); |
558 | dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size); | 565 | dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size); |
559 | return; | 566 | return; |
560 | } | 567 | } |
561 | 568 | ||
562 | // RFC 5246 | ||
563 | // 6.2.3.2. CBC Block Cipher | 569 | // 6.2.3.2. CBC Block Cipher |
564 | // For block ciphers (such as 3DES or AES), the encryption and MAC | 570 | // For block ciphers (such as 3DES or AES), the encryption and MAC |
565 | // functions convert TLSCompressed.fragment structures to and from block | 571 | // functions convert TLSCompressed.fragment structures to and from block |
@@ -595,10 +601,6 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) | |||
595 | // ------------ ------ -------- ---- ----- | 601 | // ------------ ------ -------- ---- ----- |
596 | // AES_128_CBC Block 16 16 16 | 602 | // AES_128_CBC Block 16 16 16 |
597 | // AES_256_CBC Block 32 16 16 | 603 | // AES_256_CBC Block 32 16 16 |
598 | { | ||
599 | psCipherContext_t ctx; | ||
600 | uint8_t *p; | ||
601 | uint8_t padding_length; | ||
602 | 604 | ||
603 | /* Build IV+content+MAC+padding in outbuf */ | 605 | /* Build IV+content+MAC+padding in outbuf */ |
604 | tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ | 606 | tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ |
@@ -618,22 +620,23 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) | |||
618 | // If you need no bytes to reach BLOCKSIZE, you have to pad a full | 620 | // If you need no bytes to reach BLOCKSIZE, you have to pad a full |
619 | // BLOCKSIZE with bytes of value (BLOCKSIZE-1). | 621 | // BLOCKSIZE with bytes of value (BLOCKSIZE-1). |
620 | // It's ok to have more than minimum padding, but we do minimum. | 622 | // It's ok to have more than minimum padding, but we do minimum. |
621 | p = buf + size; | ||
622 | padding_length = (~size) & (AES_BLOCKSIZE - 1); | 623 | padding_length = (~size) & (AES_BLOCKSIZE - 1); |
623 | do { | 624 | do { |
624 | *p++ = padding_length; /* padding */ | 625 | buf[size++] = padding_length; /* padding */ |
625 | size++; | ||
626 | } while ((size & (AES_BLOCKSIZE - 1)) != 0); | 626 | } while ((size & (AES_BLOCKSIZE - 1)) != 0); |
627 | 627 | ||
628 | /* Encrypt content+MAC+padding in place */ | 628 | /* Encrypt content+MAC+padding in place */ |
629 | psAesInit(&ctx, buf - AES_BLOCKSIZE, /* IV */ | 629 | { |
630 | psCipherContext_t ctx; | ||
631 | psAesInit(&ctx, buf - AES_BLOCKSIZE, /* IV */ | ||
630 | tls->client_write_key, sizeof(tls->client_write_key) | 632 | tls->client_write_key, sizeof(tls->client_write_key) |
631 | ); | 633 | ); |
632 | psAesEncrypt(&ctx, | 634 | psAesEncrypt(&ctx, |
633 | buf, /* plaintext */ | 635 | buf, /* plaintext */ |
634 | buf, /* ciphertext */ | 636 | buf, /* ciphertext */ |
635 | size | 637 | size |
636 | ); | 638 | ); |
639 | } | ||
637 | 640 | ||
638 | /* Write out */ | 641 | /* Write out */ |
639 | dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n", | 642 | dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n", |
@@ -641,10 +644,9 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) | |||
641 | size += AES_BLOCKSIZE; /* + IV */ | 644 | size += AES_BLOCKSIZE; /* + IV */ |
642 | xhdr->len16_hi = size >> 8; | 645 | xhdr->len16_hi = size >> 8; |
643 | xhdr->len16_lo = size & 0xff; | 646 | xhdr->len16_lo = size & 0xff; |
644 | dump_hex(">> %s\n", xhdr, RECHDR_LEN + size); | 647 | dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); |
645 | xwrite(tls->fd, xhdr, RECHDR_LEN + size); | 648 | xwrite(tls->fd, xhdr, RECHDR_LEN + size); |
646 | dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); | 649 | dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); |
647 | } | ||
648 | } | 650 | } |
649 | 651 | ||
650 | static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) | 652 | static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) |
@@ -658,7 +660,7 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) | |||
658 | xhdr->proto_min = TLS_MIN; | 660 | xhdr->proto_min = TLS_MIN; |
659 | xhdr->len16_hi = size >> 8; | 661 | xhdr->len16_hi = size >> 8; |
660 | xhdr->len16_lo = size & 0xff; | 662 | xhdr->len16_lo = size & 0xff; |
661 | dump_hex(">> %s\n", xhdr, RECHDR_LEN + size); | 663 | dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); |
662 | xwrite(tls->fd, xhdr, RECHDR_LEN + size); | 664 | xwrite(tls->fd, xhdr, RECHDR_LEN + size); |
663 | dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); | 665 | dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); |
664 | /* Handshake hash does not include record headers */ | 666 | /* Handshake hash does not include record headers */ |
@@ -677,10 +679,13 @@ static int xread_tls_block(tls_state_t *tls) | |||
677 | 679 | ||
678 | again: | 680 | again: |
679 | dbg("insize:%u tail:%u\n", tls->insize, tls->tail); | 681 | dbg("insize:%u tail:%u\n", tls->insize, tls->tail); |
680 | if (tls->tail != 0) | ||
681 | memmove(tls->inbuf, tls->inbuf + tls->insize, tls->tail); | ||
682 | errno = 0; | ||
683 | total = tls->tail; | 682 | total = tls->tail; |
683 | if (total != 0) { | ||
684 | memmove(tls->inbuf, tls->inbuf + tls->insize, total); | ||
685 | //dbg("<< remaining at %d [%d] ", tls->insize, total); | ||
686 | //dump_raw_in("<< %s\n", tls->inbuf, total); | ||
687 | } | ||
688 | errno = 0; | ||
684 | target = sizeof(tls->inbuf); | 689 | target = sizeof(tls->inbuf); |
685 | for (;;) { | 690 | for (;;) { |
686 | if (total >= RECHDR_LEN && target == sizeof(tls->inbuf)) { | 691 | if (total >= RECHDR_LEN && target == sizeof(tls->inbuf)) { |
@@ -692,7 +697,11 @@ static int xread_tls_block(tls_state_t *tls) | |||
692 | tls->insize = total; | 697 | tls->insize = total; |
693 | tls_error_die(tls); | 698 | tls_error_die(tls); |
694 | } | 699 | } |
695 | // can also check type/proto_maj/proto_min here | 700 | /* can also check type/proto_maj/proto_min here */ |
701 | dbg("xhdr type:%d ver:%d.%d len:%d\n", | ||
702 | xhdr->type, xhdr->proto_maj, xhdr->proto_min, | ||
703 | 0x100 * xhdr->len16_hi + xhdr->len16_lo | ||
704 | ); | ||
696 | } | 705 | } |
697 | /* if total >= target, we have a full packet (and possibly more)... */ | 706 | /* if total >= target, we have a full packet (and possibly more)... */ |
698 | if (total - target >= 0) | 707 | if (total - target >= 0) |
@@ -707,12 +716,13 @@ static int xread_tls_block(tls_state_t *tls) | |||
707 | } | 716 | } |
708 | bb_perror_msg_and_die("short read, have only %d", total); | 717 | bb_perror_msg_and_die("short read, have only %d", total); |
709 | } | 718 | } |
710 | dbg("read():%d\n", sz); | 719 | dump_raw_in("<< %s\n", tls->inbuf + total, sz); |
711 | total += sz; | 720 | total += sz; |
712 | } | 721 | } |
713 | tls->tail = total - target; | 722 | tls->tail = total - target; |
714 | tls->insize = target; | 723 | tls->insize = target; |
715 | dbg("new insize:%u tail:%u\n", tls->insize, tls->tail); | 724 | //dbg("<< stashing at %d [%d] ", tls->insize, tls->tail); |
725 | //dump_hex("<< %s\n", tls->inbuf + tls->insize, tls->tail); | ||
716 | 726 | ||
717 | sz = target - RECHDR_LEN; | 727 | sz = target - RECHDR_LEN; |
718 | 728 | ||
@@ -734,7 +744,7 @@ static int xread_tls_block(tls_state_t *tls) | |||
734 | psAesDecrypt(&ctx, | 744 | psAesDecrypt(&ctx, |
735 | p + AES_BLOCKSIZE, /* ciphertext */ | 745 | p + AES_BLOCKSIZE, /* ciphertext */ |
736 | p + AES_BLOCKSIZE, /* plaintext */ | 746 | p + AES_BLOCKSIZE, /* plaintext */ |
737 | sz | 747 | sz - AES_BLOCKSIZE |
738 | ); | 748 | ); |
739 | padding_len = p[sz - 1]; | 749 | padding_len = p[sz - 1]; |
740 | dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[AES_BLOCKSIZE], padding_len); | 750 | dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[AES_BLOCKSIZE], padding_len); |