aboutsummaryrefslogtreecommitdiff
path: root/networking/tls.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-20 20:27:06 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-20 20:27:06 +0100
commit3916139ac4b9f60d7b958e5b2d88a277753dcc74 (patch)
treef87620df1eef5f976d73f801dcbae54ee6173735 /networking/tls.c
parent9731ca7611e19827702eb8c690fb6c3b37403319 (diff)
downloadbusybox-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.c132
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
186struct record_hdr { 222struct 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
484static void tls_error_die(tls_state_t *tls) 494static 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
501static 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
490static void tls_free_outbuf(tls_state_t *tls) 511static 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
684static int tls_has_buffered_record(tls_state_t *tls) 705static 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 }