diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-02-06 13:33:00 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-02-06 13:33:00 +0100 |
commit | 98066662aa15a21627ef8a3fb7318b6ee301df22 (patch) | |
tree | 72e25833d383db2df735c950ea65cab9856d48b1 /networking/tls.c | |
parent | 5740e15de55baa343955196c641baeaec8a73b5c (diff) | |
download | busybox-w32-98066662aa15a21627ef8a3fb7318b6ee301df22.tar.gz busybox-w32-98066662aa15a21627ef8a3fb7318b6ee301df22.tar.bz2 busybox-w32-98066662aa15a21627ef8a3fb7318b6ee301df22.zip |
tls: fix hash calculations if client cert is requested and sent
Symptoms: connecting to
openssl s_server -cert vsftpd.pem -port 990 -debug -cipher AES128-SHA
works, but with "-verify 1" option added it does not.
function old new delta
tls_xread_record 474 499 +25
tls_handshake 1582 1607 +25
bad_record_die 98 110 +12
tls_run_copy_loop 282 293 +11
tls_xread_handshake_block 58 51 -7
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/1 up/down: 73/-7) Total: 66 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/tls.c')
-rw-r--r-- | networking/tls.c | 94 |
1 files changed, 54 insertions, 40 deletions
diff --git a/networking/tls.c b/networking/tls.c index fd3cb0dba..7936afca2 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -84,23 +84,23 @@ | |||
84 | # define dbg_der(...) ((void)0) | 84 | # define dbg_der(...) ((void)0) |
85 | #endif | 85 | #endif |
86 | 86 | ||
87 | #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 | 87 | #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 /* 0x14 */ |
88 | #define RECORD_TYPE_ALERT 21 | 88 | #define RECORD_TYPE_ALERT 21 /* 0x15 */ |
89 | #define RECORD_TYPE_HANDSHAKE 22 | 89 | #define RECORD_TYPE_HANDSHAKE 22 /* 0x16 */ |
90 | #define RECORD_TYPE_APPLICATION_DATA 23 | 90 | #define RECORD_TYPE_APPLICATION_DATA 23 /* 0x17 */ |
91 | 91 | ||
92 | #define HANDSHAKE_HELLO_REQUEST 0 | 92 | #define HANDSHAKE_HELLO_REQUEST 0 /* 0x00 */ |
93 | #define HANDSHAKE_CLIENT_HELLO 1 | 93 | #define HANDSHAKE_CLIENT_HELLO 1 /* 0x01 */ |
94 | #define HANDSHAKE_SERVER_HELLO 2 | 94 | #define HANDSHAKE_SERVER_HELLO 2 /* 0x02 */ |
95 | #define HANDSHAKE_HELLO_VERIFY_REQUEST 3 | 95 | #define HANDSHAKE_HELLO_VERIFY_REQUEST 3 /* 0x03 */ |
96 | #define HANDSHAKE_NEW_SESSION_TICKET 4 | 96 | #define HANDSHAKE_NEW_SESSION_TICKET 4 /* 0x04 */ |
97 | #define HANDSHAKE_CERTIFICATE 11 | 97 | #define HANDSHAKE_CERTIFICATE 11 /* 0x0b */ |
98 | #define HANDSHAKE_SERVER_KEY_EXCHANGE 12 | 98 | #define HANDSHAKE_SERVER_KEY_EXCHANGE 12 /* 0x0c */ |
99 | #define HANDSHAKE_CERTIFICATE_REQUEST 13 | 99 | #define HANDSHAKE_CERTIFICATE_REQUEST 13 /* 0x0d */ |
100 | #define HANDSHAKE_SERVER_HELLO_DONE 14 | 100 | #define HANDSHAKE_SERVER_HELLO_DONE 14 /* 0x0e */ |
101 | #define HANDSHAKE_CERTIFICATE_VERIFY 15 | 101 | #define HANDSHAKE_CERTIFICATE_VERIFY 15 /* 0x0f */ |
102 | #define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 | 102 | #define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 /* 0x10 */ |
103 | #define HANDSHAKE_FINISHED 20 | 103 | #define HANDSHAKE_FINISHED 20 /* 0x14 */ |
104 | 104 | ||
105 | #define SSL_NULL_WITH_NULL_NULL 0x0000 | 105 | #define SSL_NULL_WITH_NULL_NULL 0x0000 |
106 | #define SSL_RSA_WITH_NULL_MD5 0x0001 | 106 | #define SSL_RSA_WITH_NULL_MD5 0x0001 |
@@ -512,10 +512,12 @@ static void bad_record_die(tls_state_t *tls, const char *expected, int len) | |||
512 | bb_error_msg("got bad TLS record (len:%d) while expecting %s", len, expected); | 512 | bb_error_msg("got bad TLS record (len:%d) while expecting %s", len, expected); |
513 | if (len > 0) { | 513 | if (len > 0) { |
514 | uint8_t *p = tls->inbuf; | 514 | uint8_t *p = tls->inbuf; |
515 | while (len > 0) { | 515 | if (len > 99) |
516 | len = 99; /* don't flood, a few lines should be enough */ | ||
517 | do { | ||
516 | fprintf(stderr, " %02x", *p++); | 518 | fprintf(stderr, " %02x", *p++); |
517 | len--; | 519 | len--; |
518 | } | 520 | } while (len != 0); |
519 | fputc('\n', stderr); | 521 | fputc('\n', stderr); |
520 | } | 522 | } |
521 | xfunc_die(); | 523 | xfunc_die(); |
@@ -671,9 +673,11 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) | |||
671 | // AES_128_CBC Block 16 16 16 | 673 | // AES_128_CBC Block 16 16 16 |
672 | // AES_256_CBC Block 32 16 16 | 674 | // AES_256_CBC Block 32 16 16 |
673 | 675 | ||
674 | /* Fill IV and padding in outbuf */ | ||
675 | tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ | 676 | tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ |
676 | dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, tls->MAC_size); | 677 | dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", |
678 | size - tls->MAC_size, tls->MAC_size); | ||
679 | |||
680 | /* Fill IV and padding in outbuf */ | ||
677 | // RFC is talking nonsense: | 681 | // RFC is talking nonsense: |
678 | // "Padding that is added to force the length of the plaintext to be | 682 | // "Padding that is added to force the length of the plaintext to be |
679 | // an integral multiple of the block cipher's block length." | 683 | // an integral multiple of the block cipher's block length." |
@@ -773,7 +777,7 @@ static const char *alert_text(int code) | |||
773 | return itoa(code); | 777 | return itoa(code); |
774 | } | 778 | } |
775 | 779 | ||
776 | static int tls_xread_record(tls_state_t *tls) | 780 | static int tls_xread_record(tls_state_t *tls, const char *expected) |
777 | { | 781 | { |
778 | struct record_hdr *xhdr; | 782 | struct record_hdr *xhdr; |
779 | int sz; | 783 | int sz; |
@@ -796,13 +800,16 @@ static int tls_xread_record(tls_state_t *tls) | |||
796 | if (total >= RECHDR_LEN && target == MAX_INBUF) { | 800 | if (total >= RECHDR_LEN && target == MAX_INBUF) { |
797 | xhdr = (void*)tls->inbuf; | 801 | xhdr = (void*)tls->inbuf; |
798 | target = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); | 802 | target = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); |
799 | if (target > MAX_INBUF) { | 803 | |
800 | /* malformed input (too long): yell and die */ | 804 | if (target > MAX_INBUF /* malformed input (too long) */ |
801 | tls->buffered_size = 0; | 805 | || xhdr->proto_maj != TLS_MAJ |
802 | tls->ofs_to_buffered = total; | 806 | || xhdr->proto_min != TLS_MIN |
803 | tls_error_die(tls); | 807 | ) { |
808 | sz = total < target ? total : target; | ||
809 | if (sz > 24) | ||
810 | sz = 24; /* don't flood */ | ||
811 | bad_record_die(tls, expected, sz); | ||
804 | } | 812 | } |
805 | /* can also check type/proto_maj/proto_min here */ | ||
806 | dbg("xhdr type:%d ver:%d.%d len:%d\n", | 813 | dbg("xhdr type:%d ver:%d.%d len:%d\n", |
807 | xhdr->type, xhdr->proto_maj, xhdr->proto_min, | 814 | xhdr->type, xhdr->proto_maj, xhdr->proto_min, |
808 | 0x100 * xhdr->len16_hi + xhdr->len16_lo | 815 | 0x100 * xhdr->len16_hi + xhdr->len16_lo |
@@ -1137,13 +1144,11 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) | |||
1137 | static int tls_xread_handshake_block(tls_state_t *tls, int min_len) | 1144 | static int tls_xread_handshake_block(tls_state_t *tls, int min_len) |
1138 | { | 1145 | { |
1139 | struct record_hdr *xhdr; | 1146 | struct record_hdr *xhdr; |
1140 | int len = tls_xread_record(tls); | 1147 | int len = tls_xread_record(tls, "handshake record"); |
1141 | 1148 | ||
1142 | xhdr = (void*)tls->inbuf; | 1149 | xhdr = (void*)tls->inbuf; |
1143 | if (len < min_len | 1150 | if (len < min_len |
1144 | || xhdr->type != RECORD_TYPE_HANDSHAKE | 1151 | || xhdr->type != RECORD_TYPE_HANDSHAKE |
1145 | || xhdr->proto_maj != TLS_MAJ | ||
1146 | || xhdr->proto_min != TLS_MIN | ||
1147 | ) { | 1152 | ) { |
1148 | bad_record_die(tls, "handshake record", len); | 1153 | bad_record_die(tls, "handshake record", len); |
1149 | } | 1154 | } |
@@ -1195,7 +1200,9 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
1195 | // 0023 0000 - session_ticket | 1200 | // 0023 0000 - session_ticket |
1196 | // 000a 0008 0006001700180019 - supported_groups | 1201 | // 000a 0008 0006001700180019 - supported_groups |
1197 | // 000b 0002 0100 - ec_point_formats | 1202 | // 000b 0002 0100 - ec_point_formats |
1198 | // 000d 0016 00140401040305010503060106030301030302010203 - signature_algorithms | 1203 | // 000d 0016 0014 0401 0403 0501 0503 0601 0603 0301 0303 0201 0203 - signature_algorithms |
1204 | // wolfssl library sends this option, RFC 7627 (closes a security weakness, some servers may require it. TODO?): | ||
1205 | // 0017 0000 - extended master secret | ||
1199 | }; | 1206 | }; |
1200 | struct client_hello *record; | 1207 | struct client_hello *record; |
1201 | int len; | 1208 | int len; |
@@ -1354,7 +1361,7 @@ static void get_server_cert(tls_state_t *tls) | |||
1354 | xhdr = (void*)tls->inbuf; | 1361 | xhdr = (void*)tls->inbuf; |
1355 | certbuf = (void*)(xhdr + 1); | 1362 | certbuf = (void*)(xhdr + 1); |
1356 | if (certbuf[0] != HANDSHAKE_CERTIFICATE) | 1363 | if (certbuf[0] != HANDSHAKE_CERTIFICATE) |
1357 | tls_error_die(tls); | 1364 | bad_record_die(tls, "certificate", len); |
1358 | dbg("<< CERTIFICATE\n"); | 1365 | dbg("<< CERTIFICATE\n"); |
1359 | // 4392 bytes: | 1366 | // 4392 bytes: |
1360 | // 0b 00|11|24 00|11|21 00|05|b0 30|82|05|ac|30|82|04|94|a0|03|02|01|02|02|11|00|9f|85|bf|66|4b|0c|dd|af|ca|50|86|79|50|1b|2b|e4|30|0d... | 1367 | // 0b 00|11|24 00|11|21 00|05|b0 30|82|05|ac|30|82|04|94|a0|03|02|01|02|02|11|00|9f|85|bf|66|4b|0c|dd|af|ca|50|86|79|50|1b|2b|e4|30|0d... |
@@ -1611,6 +1618,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) | |||
1611 | // <------- Finished | 1618 | // <------- Finished |
1612 | // Application Data <------> Application Data | 1619 | // Application Data <------> Application Data |
1613 | int len; | 1620 | int len; |
1621 | int got_cert_req; | ||
1614 | 1622 | ||
1615 | send_client_hello_and_alloc_hsd(tls, sni); | 1623 | send_client_hello_and_alloc_hsd(tls, sni); |
1616 | get_server_hello(tls); | 1624 | get_server_hello(tls); |
@@ -1638,7 +1646,8 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) | |||
1638 | len = tls_xread_handshake_block(tls, 4); | 1646 | len = tls_xread_handshake_block(tls, 4); |
1639 | } | 1647 | } |
1640 | 1648 | ||
1641 | if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { | 1649 | got_cert_req = (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST); |
1650 | if (got_cert_req) { | ||
1642 | dbg("<< CERTIFICATE_REQUEST\n"); | 1651 | dbg("<< CERTIFICATE_REQUEST\n"); |
1643 | // RFC 5246: "If no suitable certificate is available, | 1652 | // RFC 5246: "If no suitable certificate is available, |
1644 | // the client MUST send a certificate message containing no | 1653 | // the client MUST send a certificate message containing no |
@@ -1647,7 +1656,9 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) | |||
1647 | // Client certificates are sent using the Certificate structure | 1656 | // Client certificates are sent using the Certificate structure |
1648 | // defined in Section 7.4.2." | 1657 | // defined in Section 7.4.2." |
1649 | // (i.e. the same format as server certs) | 1658 | // (i.e. the same format as server certs) |
1650 | send_empty_client_cert(tls); | 1659 | |
1660 | /*send_empty_client_cert(tls); - WRONG (breaks handshake hash calc) */ | ||
1661 | /* need to hash _all_ server replies first, up to ServerHelloDone */ | ||
1651 | len = tls_xread_handshake_block(tls, 4); | 1662 | len = tls_xread_handshake_block(tls, 4); |
1652 | } | 1663 | } |
1653 | 1664 | ||
@@ -1657,6 +1668,9 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) | |||
1657 | // 0e 000000 (len:0) | 1668 | // 0e 000000 (len:0) |
1658 | dbg("<< SERVER_HELLO_DONE\n"); | 1669 | dbg("<< SERVER_HELLO_DONE\n"); |
1659 | 1670 | ||
1671 | if (got_cert_req) | ||
1672 | send_empty_client_cert(tls); | ||
1673 | |||
1660 | send_client_key_exchange(tls); | 1674 | send_client_key_exchange(tls); |
1661 | 1675 | ||
1662 | send_change_cipher_spec(tls); | 1676 | send_change_cipher_spec(tls); |
@@ -1667,7 +1681,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) | |||
1667 | send_client_finished(tls); | 1681 | send_client_finished(tls); |
1668 | 1682 | ||
1669 | /* Get CHANGE_CIPHER_SPEC */ | 1683 | /* Get CHANGE_CIPHER_SPEC */ |
1670 | len = tls_xread_record(tls); | 1684 | len = tls_xread_record(tls, "switch to encrypted traffic"); |
1671 | if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) | 1685 | if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) |
1672 | bad_record_die(tls, "switch to encrypted traffic", len); | 1686 | bad_record_die(tls, "switch to encrypted traffic", len); |
1673 | dbg("<< CHANGE_CIPHER_SPEC\n"); | 1687 | dbg("<< CHANGE_CIPHER_SPEC\n"); |
@@ -1685,9 +1699,9 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) | |||
1685 | } | 1699 | } |
1686 | 1700 | ||
1687 | /* Get (encrypted) FINISHED from the server */ | 1701 | /* Get (encrypted) FINISHED from the server */ |
1688 | len = tls_xread_record(tls); | 1702 | len = tls_xread_record(tls, "'server finished'"); |
1689 | if (len < 4 || tls->inbuf[RECHDR_LEN] != HANDSHAKE_FINISHED) | 1703 | if (len < 4 || tls->inbuf[RECHDR_LEN] != HANDSHAKE_FINISHED) |
1690 | tls_error_die(tls); | 1704 | bad_record_die(tls, "'server finished'", len); |
1691 | dbg("<< FINISHED\n"); | 1705 | dbg("<< FINISHED\n"); |
1692 | /* application data can be sent/received */ | 1706 | /* application data can be sent/received */ |
1693 | 1707 | ||
@@ -1763,7 +1777,7 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) | |||
1763 | if (pfds[1].revents) { | 1777 | if (pfds[1].revents) { |
1764 | dbg("NETWORK HAS DATA\n"); | 1778 | dbg("NETWORK HAS DATA\n"); |
1765 | read_record: | 1779 | read_record: |
1766 | nread = tls_xread_record(tls); | 1780 | nread = tls_xread_record(tls, "encrypted data"); |
1767 | if (nread < 1) { | 1781 | if (nread < 1) { |
1768 | /* TLS protocol has no real concept of one-sided shutdowns: | 1782 | /* TLS protocol has no real concept of one-sided shutdowns: |
1769 | * if we get "TLS EOF" from the peer, writes will fail too | 1783 | * if we get "TLS EOF" from the peer, writes will fail too |
@@ -1775,7 +1789,7 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) | |||
1775 | break; | 1789 | break; |
1776 | } | 1790 | } |
1777 | if (tls->inbuf[0] != RECORD_TYPE_APPLICATION_DATA) | 1791 | if (tls->inbuf[0] != RECORD_TYPE_APPLICATION_DATA) |
1778 | bb_error_msg_and_die("unexpected record type %d", tls->inbuf[0]); | 1792 | bad_record_die(tls, "encrypted data", nread); |
1779 | xwrite(STDOUT_FILENO, tls->inbuf + RECHDR_LEN, nread); | 1793 | xwrite(STDOUT_FILENO, tls->inbuf + RECHDR_LEN, nread); |
1780 | /* We may already have a complete next record buffered, | 1794 | /* We may already have a complete next record buffered, |
1781 | * can process it without network reads (and possible blocking) | 1795 | * can process it without network reads (and possible blocking) |