diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-20 22:48:41 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-20 22:48:41 +0100 |
commit | dd2577f21a55e5a4d039590f76efa3f7faa3a135 (patch) | |
tree | 86425e9d25a609cafd591821b5f723bd990c31ef /networking/tls.c | |
parent | 0af5265180877f4e8fbf8f1d9f2999b3fd2205d3 (diff) | |
download | busybox-w32-dd2577f21a55e5a4d039590f76efa3f7faa3a135.tar.gz busybox-w32-dd2577f21a55e5a4d039590f76efa3f7faa3a135.tar.bz2 busybox-w32-dd2577f21a55e5a4d039590f76efa3f7faa3a135.zip |
tls: send SNI in the client hello
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/tls.c')
-rw-r--r-- | networking/tls.c | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/networking/tls.c b/networking/tls.c index 80e3bc662..8fa532947 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -228,6 +228,8 @@ struct record_hdr { | |||
228 | typedef struct tls_state { | 228 | typedef struct tls_state { |
229 | int fd; | 229 | int fd; |
230 | 230 | ||
231 | //TODO: store just the DER key here, parse/use/delete it when sending client key | ||
232 | //this way it will stay key type agnostic here. | ||
231 | psRsaKey_t server_rsa_pub_key; | 233 | psRsaKey_t server_rsa_pub_key; |
232 | 234 | ||
233 | sha256_ctx_t handshake_sha256_ctx; | 235 | sha256_ctx_t handshake_sha256_ctx; |
@@ -1066,7 +1068,7 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) | |||
1066 | /* | 1068 | /* |
1067 | * TLS Handshake routines | 1069 | * TLS Handshake routines |
1068 | */ | 1070 | */ |
1069 | static int xread_tls_handshake_block(tls_state_t *tls, int min_len) | 1071 | static int tls_xread_handshake_block(tls_state_t *tls, int min_len) |
1070 | { | 1072 | { |
1071 | struct record_hdr *xhdr; | 1073 | struct record_hdr *xhdr; |
1072 | int len = tls_xread_record(tls); | 1074 | int len = tls_xread_record(tls); |
@@ -1098,7 +1100,7 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un | |||
1098 | } | 1100 | } |
1099 | 1101 | ||
1100 | //TODO: implement RFC 5746 (Renegotiation Indication Extension) - some servers will refuse to work with us otherwise | 1102 | //TODO: implement RFC 5746 (Renegotiation Indication Extension) - some servers will refuse to work with us otherwise |
1101 | static void send_client_hello(tls_state_t *tls) | 1103 | static void send_client_hello(tls_state_t *tls, const char *sni) |
1102 | { | 1104 | { |
1103 | struct client_hello { | 1105 | struct client_hello { |
1104 | uint8_t type; | 1106 | uint8_t type; |
@@ -1111,28 +1113,58 @@ static void send_client_hello(tls_state_t *tls) | |||
1111 | uint8_t cipherid[2 * 1]; /* actually variable */ | 1113 | uint8_t cipherid[2 * 1]; /* actually variable */ |
1112 | uint8_t comprtypes_len; | 1114 | uint8_t comprtypes_len; |
1113 | uint8_t comprtypes[1]; /* actually variable */ | 1115 | uint8_t comprtypes[1]; /* actually variable */ |
1116 | /* Extensions (SNI shown): | ||
1117 | * hi,lo // len of all extensions | ||
1118 | * 0x00,0x00 // extension_type: "Server Name" | ||
1119 | * 0x00,0x0e // list len (there can be more than one SNI) | ||
1120 | * 0x00,0x0c // len of 1st Server Name Indication | ||
1121 | * 0x00 // name type: host_name | ||
1122 | * 0x00,0x09 // name len | ||
1123 | * "localhost" // name | ||
1124 | */ | ||
1114 | }; | 1125 | }; |
1115 | struct client_hello *record = tls_get_outbuf(tls, sizeof(*record)); | 1126 | struct client_hello *record; |
1116 | 1127 | int len; | |
1117 | fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, sizeof(*record)); | 1128 | int sni_len = sni ? strnlen(sni, 127) : 0; |
1129 | |||
1130 | len = sizeof(*record); | ||
1131 | if (sni_len) | ||
1132 | len += 11 + strlen(sni); | ||
1133 | record = tls_get_outbuf(tls, len); | ||
1134 | memset(record, 0, len); | ||
1135 | fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, len); | ||
1118 | record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ | 1136 | record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ |
1119 | record->proto_min = TLS_MIN; /* can be higher than one in record headers */ | 1137 | record->proto_min = TLS_MIN; /* can be higher than one in record headers */ |
1120 | tls_get_random(record->rand32, sizeof(record->rand32)); | 1138 | tls_get_random(record->rand32, sizeof(record->rand32)); |
1121 | if (TLS_DEBUG_FIXED_SECRETS) | 1139 | if (TLS_DEBUG_FIXED_SECRETS) |
1122 | memset(record->rand32, 0x11, sizeof(record->rand32)); | 1140 | memset(record->rand32, 0x11, sizeof(record->rand32)); |
1123 | memcpy(tls->client_and_server_rand32, record->rand32, sizeof(record->rand32)); | 1141 | memcpy(tls->client_and_server_rand32, record->rand32, sizeof(record->rand32)); |
1124 | record->session_id_len = 0; | 1142 | /* record->session_id_len = 0; - already is */ |
1125 | record->cipherid_len16_hi = 0; | 1143 | /* record->cipherid_len16_hi = 0; */ |
1126 | record->cipherid_len16_lo = 2 * 1; | 1144 | record->cipherid_len16_lo = 2 * 1; |
1127 | record->cipherid[0] = CIPHER_ID >> 8; | 1145 | record->cipherid[0] = CIPHER_ID >> 8; |
1128 | record->cipherid[1] = CIPHER_ID & 0xff; | 1146 | record->cipherid[1] = CIPHER_ID & 0xff; |
1129 | record->comprtypes_len = 1; | 1147 | record->comprtypes_len = 1; |
1130 | record->comprtypes[0] = 0; | 1148 | /* record->comprtypes[0] = 0; */ |
1131 | 1149 | ||
1132 | //TODO: send options, at least SNI. | 1150 | if (sni_len) { |
1151 | uint8_t *p = (void*)(record + 1); | ||
1152 | //p[0] = 0; // | ||
1153 | p[1] = sni_len + 9; //ext_len | ||
1154 | //p[2] = 0; // | ||
1155 | //p[3] = 0; //extension_type | ||
1156 | //p[4] = 0; // | ||
1157 | p[5] = sni_len + 5; //list len | ||
1158 | //p[6] = 0; // | ||
1159 | p[7] = sni_len + 3; //len of 1st SNI | ||
1160 | //p[8] = 0; //name type | ||
1161 | //p[9] = 0; // | ||
1162 | p[10] = sni_len; //name len | ||
1163 | memcpy(&p[11], sni, sni_len); | ||
1164 | } | ||
1133 | 1165 | ||
1134 | dbg(">> CLIENT_HELLO\n"); | 1166 | dbg(">> CLIENT_HELLO\n"); |
1135 | xwrite_and_update_handshake_hash(tls, sizeof(*record)); | 1167 | xwrite_and_update_handshake_hash(tls, len); |
1136 | } | 1168 | } |
1137 | 1169 | ||
1138 | static void get_server_hello(tls_state_t *tls) | 1170 | static void get_server_hello(tls_state_t *tls) |
@@ -1149,10 +1181,11 @@ static void get_server_hello(tls_state_t *tls) | |||
1149 | uint8_t comprtype; | 1181 | uint8_t comprtype; |
1150 | /* extensions may follow, but only those which client offered in its Hello */ | 1182 | /* extensions may follow, but only those which client offered in its Hello */ |
1151 | }; | 1183 | }; |
1184 | |||
1152 | struct server_hello *hp; | 1185 | struct server_hello *hp; |
1153 | uint8_t *cipherid; | 1186 | uint8_t *cipherid; |
1154 | 1187 | ||
1155 | xread_tls_handshake_block(tls, 74); | 1188 | tls_xread_handshake_block(tls, 74); |
1156 | 1189 | ||
1157 | hp = (void*)tls->inbuf; | 1190 | hp = (void*)tls->inbuf; |
1158 | // 74 bytes: | 1191 | // 74 bytes: |
@@ -1199,7 +1232,7 @@ static void get_server_cert(tls_state_t *tls) | |||
1199 | uint8_t *certbuf; | 1232 | uint8_t *certbuf; |
1200 | int len, len1; | 1233 | int len, len1; |
1201 | 1234 | ||
1202 | len = xread_tls_handshake_block(tls, 10); | 1235 | len = tls_xread_handshake_block(tls, 10); |
1203 | 1236 | ||
1204 | xhdr = (void*)tls->inbuf; | 1237 | xhdr = (void*)tls->inbuf; |
1205 | certbuf = (void*)(xhdr + 1); | 1238 | certbuf = (void*)(xhdr + 1); |
@@ -1416,7 +1449,7 @@ static void send_client_finished(tls_state_t *tls) | |||
1416 | xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE); | 1449 | xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE); |
1417 | } | 1450 | } |
1418 | 1451 | ||
1419 | static void tls_handshake(tls_state_t *tls) | 1452 | static void tls_handshake(tls_state_t *tls, const char *sni) |
1420 | { | 1453 | { |
1421 | // Client RFC 5246 Server | 1454 | // Client RFC 5246 Server |
1422 | // (*) - optional messages, not always sent | 1455 | // (*) - optional messages, not always sent |
@@ -1437,7 +1470,7 @@ static void tls_handshake(tls_state_t *tls) | |||
1437 | // Application Data <------> Application Data | 1470 | // Application Data <------> Application Data |
1438 | int len; | 1471 | int len; |
1439 | 1472 | ||
1440 | send_client_hello(tls); | 1473 | send_client_hello(tls, sni); |
1441 | get_server_hello(tls); | 1474 | get_server_hello(tls); |
1442 | 1475 | ||
1443 | // RFC 5246 | 1476 | // RFC 5246 |
@@ -1451,7 +1484,7 @@ static void tls_handshake(tls_state_t *tls) | |||
1451 | // (for example, kernel.org does not even accept DH_anon cipher id) | 1484 | // (for example, kernel.org does not even accept DH_anon cipher id) |
1452 | get_server_cert(tls); | 1485 | get_server_cert(tls); |
1453 | 1486 | ||
1454 | len = xread_tls_handshake_block(tls, 4); | 1487 | len = tls_xread_handshake_block(tls, 4); |
1455 | if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_SERVER_KEY_EXCHANGE) { | 1488 | if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_SERVER_KEY_EXCHANGE) { |
1456 | // 459 bytes: | 1489 | // 459 bytes: |
1457 | // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... | 1490 | // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... |
@@ -1460,7 +1493,7 @@ static void tls_handshake(tls_state_t *tls) | |||
1460 | // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... | 1493 | // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... |
1461 | dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len); | 1494 | dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len); |
1462 | //probably need to save it | 1495 | //probably need to save it |
1463 | xread_tls_handshake_block(tls, 4); | 1496 | tls_xread_handshake_block(tls, 4); |
1464 | } | 1497 | } |
1465 | 1498 | ||
1466 | // if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { | 1499 | // if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { |
@@ -1472,7 +1505,7 @@ static void tls_handshake(tls_state_t *tls) | |||
1472 | // Client certificates are sent using the Certificate structure | 1505 | // Client certificates are sent using the Certificate structure |
1473 | // defined in Section 7.4.2." | 1506 | // defined in Section 7.4.2." |
1474 | // (i.e. the same format as server certs) | 1507 | // (i.e. the same format as server certs) |
1475 | // xread_tls_handshake_block(tls, 4); | 1508 | // tls_xread_handshake_block(tls, 4); |
1476 | // } | 1509 | // } |
1477 | 1510 | ||
1478 | if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) | 1511 | if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) |
@@ -1546,7 +1579,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) | |||
1546 | 1579 | ||
1547 | tls = new_tls_state(); | 1580 | tls = new_tls_state(); |
1548 | tls->fd = cfd; | 1581 | tls->fd = cfd; |
1549 | tls_handshake(tls); | 1582 | tls_handshake(tls, argv[1]); |
1550 | 1583 | ||
1551 | /* Select loop copying stdin to cfd, and cfd to stdout */ | 1584 | /* Select loop copying stdin to cfd, and cfd to stdout */ |
1552 | FD_ZERO(&readfds); | 1585 | FD_ZERO(&readfds); |