diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-20 20:27:06 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-20 20:27:06 +0100 |
commit | 3916139ac4b9f60d7b958e5b2d88a277753dcc74 (patch) | |
tree | f87620df1eef5f976d73f801dcbae54ee6173735 /networking/tls.c | |
parent | 9731ca7611e19827702eb8c690fb6c3b37403319 (diff) | |
download | busybox-w32-3916139ac4b9f60d7b958e5b2d88a277753dcc74.tar.gz busybox-w32-3916139ac4b9f60d7b958e5b2d88a277753dcc74.tar.bz2 busybox-w32-3916139ac4b9f60d7b958e5b2d88a277753dcc74.zip |
tls: make input buffer grow as needed
As it turns out, it goes only up to "inbuf_size:4608"
for kernel.org - fixed 18kb buffer was x4 larger than necessary.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/tls.c')
-rw-r--r-- | networking/tls.c | 132 |
1 files changed, 83 insertions, 49 deletions
diff --git a/networking/tls.c b/networking/tls.c index 000d2aedc..55ad2d83f 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -181,6 +181,42 @@ enum { | |||
181 | OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */ | 181 | OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */ |
182 | OUTBUF_SFX = SHA256_OUTSIZE + AES_BLOCKSIZE, /* MAC + padding */ | 182 | OUTBUF_SFX = SHA256_OUTSIZE + AES_BLOCKSIZE, /* MAC + padding */ |
183 | MAX_OUTBUF = MAX_TLS_RECORD - OUTBUF_PFX - OUTBUF_SFX, | 183 | MAX_OUTBUF = MAX_TLS_RECORD - OUTBUF_PFX - OUTBUF_SFX, |
184 | |||
185 | // RFC 5246 | ||
186 | // | 6.2.1. Fragmentation | ||
187 | // | The record layer fragments information blocks into TLSPlaintext | ||
188 | // | records carrying data in chunks of 2^14 bytes or less. Client | ||
189 | // | message boundaries are not preserved in the record layer (i.e., | ||
190 | // | multiple client messages of the same ContentType MAY be coalesced | ||
191 | // | into a single TLSPlaintext record, or a single message MAY be | ||
192 | // | fragmented across several records) | ||
193 | // |... | ||
194 | // | length | ||
195 | // | The length (in bytes) of the following TLSPlaintext.fragment. | ||
196 | // | The length MUST NOT exceed 2^14. | ||
197 | // |... | ||
198 | // | 6.2.2. Record Compression and Decompression | ||
199 | // |... | ||
200 | // | Compression must be lossless and may not increase the content length | ||
201 | // | by more than 1024 bytes. If the decompression function encounters a | ||
202 | // | TLSCompressed.fragment that would decompress to a length in excess of | ||
203 | // | 2^14 bytes, it MUST report a fatal decompression failure error. | ||
204 | // |... | ||
205 | // | length | ||
206 | // | The length (in bytes) of the following TLSCompressed.fragment. | ||
207 | // | The length MUST NOT exceed 2^14 + 1024. | ||
208 | // |... | ||
209 | // | 6.2.3. Record Payload Protection | ||
210 | // | The encryption and MAC functions translate a TLSCompressed | ||
211 | // | structure into a TLSCiphertext. The decryption functions reverse | ||
212 | // | the process. The MAC of the record also includes a sequence | ||
213 | // | number so that missing, extra, or repeated messages are | ||
214 | // | detectable. | ||
215 | // |... | ||
216 | // | length | ||
217 | // | The length (in bytes) of the following TLSCiphertext.fragment. | ||
218 | // | The length MUST NOT exceed 2^14 + 2048. | ||
219 | MAX_INBUF = (1 << 14) + 2048, | ||
184 | }; | 220 | }; |
185 | 221 | ||
186 | struct record_hdr { | 222 | struct record_hdr { |
@@ -218,36 +254,10 @@ typedef struct tls_state { | |||
218 | int outbuf_size; | 254 | int outbuf_size; |
219 | uint8_t *outbuf; | 255 | uint8_t *outbuf; |
220 | 256 | ||
221 | // RFC 5246 | 257 | int inbuf_size; |
222 | // | 6.2.1. Fragmentation | 258 | int ofs_to_buffered; |
223 | // | The record layer fragments information blocks into TLSPlaintext | 259 | int buffered_size; |
224 | // | records carrying data in chunks of 2^14 bytes or less. Client | 260 | uint8_t *inbuf; |
225 | // | message boundaries are not preserved in the record layer (i.e., | ||
226 | // | multiple client messages of the same ContentType MAY be coalesced | ||
227 | // | into a single TLSPlaintext record, or a single message MAY be | ||
228 | // | fragmented across several records) | ||
229 | // |... | ||
230 | // | length | ||
231 | // | The length (in bytes) of the following TLSPlaintext.fragment. | ||
232 | // | The length MUST NOT exceed 2^14. | ||
233 | // |... | ||
234 | // | 6.2.2. Record Compression and Decompression | ||
235 | // |... | ||
236 | // | Compression must be lossless and may not increase the content length | ||
237 | // | by more than 1024 bytes. If the decompression function encounters a | ||
238 | // | TLSCompressed.fragment that would decompress to a length in excess of | ||
239 | // | 2^14 bytes, it MUST report a fatal decompression failure error. | ||
240 | // |... | ||
241 | // | length | ||
242 | // | The length (in bytes) of the following TLSCompressed.fragment. | ||
243 | // | The length MUST NOT exceed 2^14 + 1024. | ||
244 | // | ||
245 | // Since our buffer also contains 5-byte headers, make it a bit bigger: | ||
246 | int insize; | ||
247 | int tail; | ||
248 | //needed? | ||
249 | uint64_t align____; | ||
250 | uint8_t inbuf[20*1024]; | ||
251 | } tls_state_t; | 261 | } tls_state_t; |
252 | 262 | ||
253 | 263 | ||
@@ -483,10 +493,21 @@ static tls_state_t *new_tls_state(void) | |||
483 | 493 | ||
484 | static void tls_error_die(tls_state_t *tls) | 494 | static void tls_error_die(tls_state_t *tls) |
485 | { | 495 | { |
486 | dump_tls_record(tls->inbuf, tls->insize + tls->tail); | 496 | dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size); |
487 | bb_error_msg_and_die("TODO: useful diagnostic about %p", tls); | 497 | bb_error_msg_and_die("TODO: useful diagnostic about %p", tls); |
488 | } | 498 | } |
489 | 499 | ||
500 | #if 0 //UNUSED | ||
501 | static void tls_free_inbuf(tls_state_t *tls) | ||
502 | { | ||
503 | if (tls->buffered_size == 0) { | ||
504 | free(tls->inbuf); | ||
505 | tls->inbuf_size = 0; | ||
506 | tls->inbuf = NULL; | ||
507 | } | ||
508 | } | ||
509 | #endif | ||
510 | |||
490 | static void tls_free_outbuf(tls_state_t *tls) | 511 | static void tls_free_outbuf(tls_state_t *tls) |
491 | { | 512 | { |
492 | free(tls->outbuf); | 513 | free(tls->outbuf); |
@@ -683,13 +704,13 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) | |||
683 | 704 | ||
684 | static int tls_has_buffered_record(tls_state_t *tls) | 705 | static int tls_has_buffered_record(tls_state_t *tls) |
685 | { | 706 | { |
686 | int buffered = tls->tail; | 707 | int buffered = tls->buffered_size; |
687 | struct record_hdr *xhdr; | 708 | struct record_hdr *xhdr; |
688 | int rec_size; | 709 | int rec_size; |
689 | 710 | ||
690 | if (buffered < RECHDR_LEN) | 711 | if (buffered < RECHDR_LEN) |
691 | return 0; | 712 | return 0; |
692 | xhdr = (void*)(tls->inbuf + tls->insize); | 713 | xhdr = (void*)(tls->inbuf + tls->ofs_to_buffered); |
693 | rec_size = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); | 714 | rec_size = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); |
694 | if (buffered < rec_size) | 715 | if (buffered < rec_size) |
695 | return 0; | 716 | return 0; |
@@ -704,23 +725,25 @@ static int tls_xread_record(tls_state_t *tls) | |||
704 | int target; | 725 | int target; |
705 | 726 | ||
706 | again: | 727 | again: |
707 | dbg("insize:%u tail:%u\n", tls->insize, tls->tail); | 728 | dbg("ofs_to_buffered:%u buffered_size:%u\n", tls->ofs_to_buffered, tls->buffered_size); |
708 | total = tls->tail; | 729 | total = tls->buffered_size; |
709 | if (total != 0) { | 730 | if (total != 0) { |
710 | memmove(tls->inbuf, tls->inbuf + tls->insize, total); | 731 | memmove(tls->inbuf, tls->inbuf + tls->ofs_to_buffered, total); |
711 | //dbg("<< remaining at %d [%d] ", tls->insize, total); | 732 | //dbg("<< remaining at %d [%d] ", tls->ofs_to_buffered, total); |
712 | //dump_raw_in("<< %s\n", tls->inbuf, total); | 733 | //dump_raw_in("<< %s\n", tls->inbuf, total); |
713 | } | 734 | } |
714 | errno = 0; | 735 | errno = 0; |
715 | target = sizeof(tls->inbuf); | 736 | target = MAX_INBUF; |
716 | for (;;) { | 737 | for (;;) { |
717 | if (total >= RECHDR_LEN && target == sizeof(tls->inbuf)) { | 738 | int rem; |
739 | |||
740 | if (total >= RECHDR_LEN && target == MAX_INBUF) { | ||
718 | xhdr = (void*)tls->inbuf; | 741 | xhdr = (void*)tls->inbuf; |
719 | target = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); | 742 | target = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); |
720 | if (target >= sizeof(tls->inbuf)) { | 743 | if (target > MAX_INBUF) { |
721 | /* malformed input (too long): yell and die */ | 744 | /* malformed input (too long): yell and die */ |
722 | tls->tail = 0; | 745 | tls->buffered_size = 0; |
723 | tls->insize = total; | 746 | tls->ofs_to_buffered = total; |
724 | tls_error_die(tls); | 747 | tls_error_die(tls); |
725 | } | 748 | } |
726 | /* can also check type/proto_maj/proto_min here */ | 749 | /* can also check type/proto_maj/proto_min here */ |
@@ -732,12 +755,22 @@ static int tls_xread_record(tls_state_t *tls) | |||
732 | /* if total >= target, we have a full packet (and possibly more)... */ | 755 | /* if total >= target, we have a full packet (and possibly more)... */ |
733 | if (total - target >= 0) | 756 | if (total - target >= 0) |
734 | break; | 757 | break; |
735 | sz = safe_read(tls->fd, tls->inbuf + total, sizeof(tls->inbuf) - total); | 758 | /* input buffer is grown only as needed */ |
759 | rem = tls->inbuf_size - total; | ||
760 | if (rem == 0) { | ||
761 | tls->inbuf_size += MAX_INBUF / 8; | ||
762 | if (tls->inbuf_size > MAX_INBUF) | ||
763 | tls->inbuf_size = MAX_INBUF; | ||
764 | dbg("inbuf_size:%d\n", tls->inbuf_size); | ||
765 | rem = tls->inbuf_size - total; | ||
766 | tls->inbuf = xrealloc(tls->inbuf, tls->inbuf_size); | ||
767 | } | ||
768 | sz = safe_read(tls->fd, tls->inbuf + total, rem); | ||
736 | if (sz <= 0) { | 769 | if (sz <= 0) { |
737 | if (sz == 0 && total == 0) { | 770 | if (sz == 0 && total == 0) { |
738 | /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */ | 771 | /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */ |
739 | dbg("EOF (without TLS shutdown) from peer\n"); | 772 | dbg("EOF (without TLS shutdown) from peer\n"); |
740 | tls->tail = 0; | 773 | tls->buffered_size = 0; |
741 | goto end; | 774 | goto end; |
742 | } | 775 | } |
743 | bb_perror_msg_and_die("short read, have only %d", total); | 776 | bb_perror_msg_and_die("short read, have only %d", total); |
@@ -745,10 +778,10 @@ static int tls_xread_record(tls_state_t *tls) | |||
745 | dump_raw_in("<< %s\n", tls->inbuf + total, sz); | 778 | dump_raw_in("<< %s\n", tls->inbuf + total, sz); |
746 | total += sz; | 779 | total += sz; |
747 | } | 780 | } |
748 | tls->tail = total - target; | 781 | tls->buffered_size = total - target; |
749 | tls->insize = target; | 782 | tls->ofs_to_buffered = target; |
750 | //dbg("<< stashing at %d [%d] ", tls->insize, tls->tail); | 783 | //dbg("<< stashing at %d [%d] ", tls->ofs_to_buffered, tls->buffered_size); |
751 | //dump_hex("<< %s\n", tls->inbuf + tls->insize, tls->tail); | 784 | //dump_hex("<< %s\n", tls->inbuf + tls->ofs_to_buffered, tls->buffered_size); |
752 | 785 | ||
753 | sz = target - RECHDR_LEN; | 786 | sz = target - RECHDR_LEN; |
754 | 787 | ||
@@ -1547,7 +1580,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) | |||
1547 | * doubt it's ok to do it "raw" | 1580 | * doubt it's ok to do it "raw" |
1548 | */ | 1581 | */ |
1549 | FD_CLR(STDIN_FILENO, &readfds); | 1582 | FD_CLR(STDIN_FILENO, &readfds); |
1550 | tls_free_outbuf(tls); | 1583 | tls_free_outbuf(tls); /* mem usage optimization */ |
1551 | } else { | 1584 | } else { |
1552 | if (nread == inbuf_size) { | 1585 | if (nread == inbuf_size) { |
1553 | /* TLS has per record overhead, if input comes fast, | 1586 | /* TLS has per record overhead, if input comes fast, |
@@ -1570,6 +1603,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) | |||
1570 | */ | 1603 | */ |
1571 | //FD_CLR(cfd, &readfds); | 1604 | //FD_CLR(cfd, &readfds); |
1572 | //close(STDOUT_FILENO); | 1605 | //close(STDOUT_FILENO); |
1606 | //tls_free_inbuf(tls); /* mem usage optimization */ | ||
1573 | //continue; | 1607 | //continue; |
1574 | break; | 1608 | break; |
1575 | } | 1609 | } |