diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-18 06:45:50 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-18 06:45:50 +0100 |
commit | c8ba23bcec94ecbc8ee82053d1b7e299cc839184 (patch) | |
tree | c04686e84bc16f23c30fa1606e751c856853f1d9 /networking/tls.c | |
parent | 5d1662ea1c29f53b6ece93806c4cf218f9b9a5ae (diff) | |
download | busybox-w32-c8ba23bcec94ecbc8ee82053d1b7e299cc839184.tar.gz busybox-w32-c8ba23bcec94ecbc8ee82053d1b7e299cc839184.tar.bz2 busybox-w32-c8ba23bcec94ecbc8ee82053d1b7e299cc839184.zip |
tls: massage writing for encryption support; finer-grained debug
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/tls.c')
-rw-r--r-- | networking/tls.c | 69 |
1 files changed, 38 insertions, 31 deletions
diff --git a/networking/tls.c b/networking/tls.c index 8bcaee9a6..9d1a0fca9 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -25,7 +25,9 @@ | |||
25 | 25 | ||
26 | #include "tls.h" | 26 | #include "tls.h" |
27 | 27 | ||
28 | #define TLS_DEBUG 2 | 28 | #define TLS_DEBUG 1 |
29 | #define TLS_DEBUG_HASH 0 | ||
30 | #define TLS_DEBUG_DER 0 | ||
29 | 31 | ||
30 | #if TLS_DEBUG | 32 | #if TLS_DEBUG |
31 | # define dbg(...) fprintf(stderr, __VA_ARGS__) | 33 | # define dbg(...) fprintf(stderr, __VA_ARGS__) |
@@ -33,6 +35,12 @@ | |||
33 | # define dbg(...) ((void)0) | 35 | # define dbg(...) ((void)0) |
34 | #endif | 36 | #endif |
35 | 37 | ||
38 | #if TLS_DEBUG_DER | ||
39 | # define dbg_der(...) fprintf(stderr, __VA_ARGS__) | ||
40 | #else | ||
41 | # define dbg_der(...) ((void)0) | ||
42 | #endif | ||
43 | |||
36 | #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 | 44 | #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 |
37 | #define RECORD_TYPE_ALERT 21 | 45 | #define RECORD_TYPE_ALERT 21 |
38 | #define RECORD_TYPE_HANDSHAKE 22 | 46 | #define RECORD_TYPE_HANDSHAKE 22 |
@@ -269,7 +277,7 @@ static void sha256_peek(sha256_ctx_t *ctx, void *buffer) | |||
269 | sha256_end(&ctx_copy, buffer); | 277 | sha256_end(&ctx_copy, buffer); |
270 | } | 278 | } |
271 | 279 | ||
272 | #if TLS_DEBUG >= 2 | 280 | #if TLS_DEBUG_HASH |
273 | static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buffer, size_t len) | 281 | static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buffer, size_t len) |
274 | { | 282 | { |
275 | uint8_t h[SHA256_OUTSIZE]; | 283 | uint8_t h[SHA256_OUTSIZE]; |
@@ -283,7 +291,7 @@ static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buff | |||
283 | #else | 291 | #else |
284 | # define sha256_hash_dbg(fmt, ctx, buffer, len) \ | 292 | # define sha256_hash_dbg(fmt, ctx, buffer, len) \ |
285 | sha256_hash(ctx, buffer, len) | 293 | sha256_hash(ctx, buffer, len) |
286 | #endif /* not TLS_DEBUG >= 2 */ | 294 | #endif |
287 | 295 | ||
288 | // RFC 2104 | 296 | // RFC 2104 |
289 | // HMAC(key, text) based on a hash H (say, sha256) is: | 297 | // HMAC(key, text) based on a hash H (say, sha256) is: |
@@ -424,8 +432,7 @@ static void prf_hmac_sha256( | |||
424 | #undef SEED | 432 | #undef SEED |
425 | } | 433 | } |
426 | 434 | ||
427 | static | 435 | static tls_state_t *new_tls_state(void) |
428 | tls_state_t *new_tls_state(void) | ||
429 | { | 436 | { |
430 | tls_state_t *tls = xzalloc(sizeof(*tls)); | 437 | tls_state_t *tls = xzalloc(sizeof(*tls)); |
431 | tls->fd = -1; | 438 | tls->fd = -1; |
@@ -488,31 +495,31 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size | |||
488 | uint8_t mac_hash[SHA256_OUTSIZE]; | 495 | uint8_t mac_hash[SHA256_OUTSIZE]; |
489 | struct record_hdr *xhdr = buf; | 496 | struct record_hdr *xhdr = buf; |
490 | 497 | ||
491 | if (tls->encrypt_on_write) { | 498 | if (!tls->encrypt_on_write) { |
499 | xwrite(tls->fd, buf, size); | ||
500 | dbg("wrote %u bytes\n", size); | ||
501 | /* Handshake hash does not include record headers */ | ||
502 | if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) { | ||
503 | sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5); | ||
504 | } | ||
505 | return; | ||
506 | } | ||
507 | |||
492 | //TODO: convert hmac_sha256 to precomputed | 508 | //TODO: convert hmac_sha256 to precomputed |
493 | hmac_sha256(mac_hash, | 509 | hmac_sha256(mac_hash, |
494 | tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), | 510 | tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), |
495 | &tls->write_seq64_be, sizeof(tls->write_seq64_be), | 511 | &tls->write_seq64_be, sizeof(tls->write_seq64_be), |
496 | buf, size, | 512 | buf, size, |
497 | NULL); | 513 | NULL); |
498 | tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); | 514 | tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); |
499 | /* Temporarily change for writing */ | ||
500 | xhdr->len16_lo += SHA256_OUTSIZE; | ||
501 | } | ||
502 | 515 | ||
516 | xhdr->len16_lo += SHA256_OUTSIZE; | ||
503 | xwrite(tls->fd, buf, size); | 517 | xwrite(tls->fd, buf, size); |
518 | xhdr->len16_lo -= SHA256_OUTSIZE; | ||
504 | dbg("wrote %u bytes\n", size); | 519 | dbg("wrote %u bytes\n", size); |
505 | 520 | ||
506 | if (tls->encrypt_on_write) { | 521 | xwrite(tls->fd, mac_hash, sizeof(mac_hash)); |
507 | xwrite(tls->fd, mac_hash, sizeof(mac_hash)); | 522 | dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); |
508 | dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); | ||
509 | xhdr->len16_lo -= SHA256_OUTSIZE; | ||
510 | } | ||
511 | |||
512 | /* Handshake hash does not include record headers */ | ||
513 | if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) { | ||
514 | sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5); | ||
515 | } | ||
516 | } | 523 | } |
517 | 524 | ||
518 | static int xread_tls_block(tls_state_t *tls) | 525 | static int xread_tls_block(tls_state_t *tls) |
@@ -611,7 +618,7 @@ static uint8_t *enter_der_item(uint8_t *der, uint8_t **endp) | |||
611 | { | 618 | { |
612 | uint8_t *new_der; | 619 | uint8_t *new_der; |
613 | unsigned len = get_der_len(&new_der, der, *endp); | 620 | unsigned len = get_der_len(&new_der, der, *endp); |
614 | dbg("entered der @%p:0x%02x len:%u inner_byte @%p:0x%02x\n", der, der[0], len, new_der, new_der[0]); | 621 | dbg_der("entered der @%p:0x%02x len:%u inner_byte @%p:0x%02x\n", der, der[0], len, new_der, new_der[0]); |
615 | /* Move "end" position to cover only this item */ | 622 | /* Move "end" position to cover only this item */ |
616 | *endp = new_der + len; | 623 | *endp = new_der + len; |
617 | return new_der; | 624 | return new_der; |
@@ -623,7 +630,7 @@ static uint8_t *skip_der_item(uint8_t *der, uint8_t *end) | |||
623 | unsigned len = get_der_len(&new_der, der, end); | 630 | unsigned len = get_der_len(&new_der, der, end); |
624 | /* Skip body */ | 631 | /* Skip body */ |
625 | new_der += len; | 632 | new_der += len; |
626 | dbg("skipped der 0x%02x, next byte 0x%02x\n", der[0], new_der[0]); | 633 | dbg_der("skipped der 0x%02x, next byte 0x%02x\n", der[0], new_der[0]); |
627 | return new_der; | 634 | return new_der; |
628 | } | 635 | } |
629 | 636 | ||
@@ -632,7 +639,7 @@ static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end) | |||
632 | uint8_t *bin_ptr; | 639 | uint8_t *bin_ptr; |
633 | unsigned len = get_der_len(&bin_ptr, der, end); | 640 | unsigned len = get_der_len(&bin_ptr, der, end); |
634 | 641 | ||
635 | dbg("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); | 642 | dbg_der("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); |
636 | pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); | 643 | pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); |
637 | pstm_read_unsigned_bin(pstm_n, bin_ptr, len); | 644 | pstm_read_unsigned_bin(pstm_n, bin_ptr, len); |
638 | //return bin + len; | 645 | //return bin + len; |
@@ -854,7 +861,7 @@ static void send_client_hello(tls_state_t *tls) | |||
854 | /* record.comprtypes[0] = 0; */ | 861 | /* record.comprtypes[0] = 0; */ |
855 | 862 | ||
856 | //dbg (make it repeatable): memset(record.rand32, 0x11, sizeof(record.rand32)); | 863 | //dbg (make it repeatable): memset(record.rand32, 0x11, sizeof(record.rand32)); |
857 | dbg(">> HANDSHAKE_CLIENT_HELLO\n"); | 864 | dbg(">> CLIENT_HELLO\n"); |
858 | xwrite_and_hash(tls, &record, sizeof(record)); | 865 | xwrite_and_hash(tls, &record, sizeof(record)); |
859 | memcpy(tls->client_and_server_rand32, record.rand32, sizeof(record.rand32)); | 866 | memcpy(tls->client_and_server_rand32, record.rand32, sizeof(record.rand32)); |
860 | } | 867 | } |
@@ -988,7 +995,7 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
988 | record.xhdr.len16_hi = len >> 8; | 995 | record.xhdr.len16_hi = len >> 8; |
989 | record.xhdr.len16_lo = len & 0xff; | 996 | record.xhdr.len16_lo = len & 0xff; |
990 | 997 | ||
991 | dbg(">> HANDSHAKE_CLIENT_KEY_EXCHANGE\n"); | 998 | dbg(">> CLIENT_KEY_EXCHANGE\n"); |
992 | xwrite_and_hash(tls, &record, sizeof(record.xhdr) + len); | 999 | xwrite_and_hash(tls, &record, sizeof(record.xhdr) + len); |
993 | 1000 | ||
994 | // RFC 5246 | 1001 | // RFC 5246 |
@@ -1114,13 +1121,13 @@ static void send_change_cipher_spec(tls_state_t *tls) | |||
1114 | // includes all existing cipher suites. | 1121 | // includes all existing cipher suites. |
1115 | static void send_client_finished(tls_state_t *tls) | 1122 | static void send_client_finished(tls_state_t *tls) |
1116 | { | 1123 | { |
1117 | struct client_finished { | 1124 | struct finished { |
1118 | struct record_hdr xhdr; | 1125 | struct record_hdr xhdr; |
1119 | uint8_t type; | 1126 | uint8_t type; |
1120 | uint8_t len24_hi, len24_mid, len24_lo; | 1127 | uint8_t len24_hi, len24_mid, len24_lo; |
1121 | uint8_t prf_result[12]; | 1128 | uint8_t prf_result[12]; |
1122 | }; | 1129 | }; |
1123 | struct client_finished record; | 1130 | struct finished record; |
1124 | uint8_t handshake_hash[SHA256_OUTSIZE]; | 1131 | uint8_t handshake_hash[SHA256_OUTSIZE]; |
1125 | 1132 | ||
1126 | fill_handshake_record_hdr(&record.xhdr, sizeof(record)); | 1133 | fill_handshake_record_hdr(&record.xhdr, sizeof(record)); |
@@ -1134,13 +1141,13 @@ static void send_client_finished(tls_state_t *tls) | |||
1134 | ); | 1141 | ); |
1135 | dump_hex("from secret: %s\n", tls->master_secret, sizeof(tls->master_secret)); | 1142 | dump_hex("from secret: %s\n", tls->master_secret, sizeof(tls->master_secret)); |
1136 | dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); | 1143 | dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); |
1137 | dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); | 1144 | dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); |
1138 | dump_hex("=> digest: %s\n", record.prf_result, sizeof(record.prf_result)); | 1145 | dump_hex("=> digest: %s\n", record.prf_result, sizeof(record.prf_result)); |
1139 | 1146 | ||
1140 | //(1) TODO: well, this should be encrypted on send, really. | 1147 | //(1) TODO: well, this should be encrypted on send, really. |
1141 | //(2) do we really need to also hash it? | 1148 | //(2) do we really need to also hash it? |
1142 | 1149 | ||
1143 | dbg(">> HANDSHAKE_FINISHED\n"); | 1150 | dbg(">> FINISHED\n"); |
1144 | xwrite_and_hash(tls, &record, sizeof(record)); | 1151 | xwrite_and_hash(tls, &record, sizeof(record)); |
1145 | } | 1152 | } |
1146 | 1153 | ||