diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-19 00:20:45 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-19 00:20:45 +0100 |
commit | cccf8e735da9eb62f1de021534ca50255d82e931 (patch) | |
tree | 8a2f9965d8000e507056ebb934686fb8f4161f14 | |
parent | a9e186680668056e2c35ce5a99769a7ff0df44cd (diff) | |
download | busybox-w32-cccf8e735da9eb62f1de021534ca50255d82e931.tar.gz busybox-w32-cccf8e735da9eb62f1de021534ca50255d82e931.tar.bz2 busybox-w32-cccf8e735da9eb62f1de021534ca50255d82e931.zip |
tls: teach it to decrypt AES256-encrypted data
This adds decryption only.
There is no MAC verification, code simply throws away MAC.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/tls.c | 73 |
1 files changed, 53 insertions, 20 deletions
diff --git a/networking/tls.c b/networking/tls.c index 6928582df..f3d0bde90 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -181,7 +181,7 @@ typedef struct tls_state { | |||
181 | uint8_t master_secret[48]; | 181 | uint8_t master_secret[48]; |
182 | 182 | ||
183 | uint8_t encrypt_on_write; | 183 | uint8_t encrypt_on_write; |
184 | uint8_t decrypt_on_read; | 184 | int min_encrypted_len_on_read; |
185 | uint8_t client_write_MAC_key[SHA256_OUTSIZE]; | 185 | uint8_t client_write_MAC_key[SHA256_OUTSIZE]; |
186 | uint8_t server_write_MAC_key[SHA256_OUTSIZE]; | 186 | uint8_t server_write_MAC_key[SHA256_OUTSIZE]; |
187 | uint8_t client_write_key[AES256_KEYSIZE]; | 187 | uint8_t client_write_key[AES256_KEYSIZE]; |
@@ -634,7 +634,7 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size | |||
634 | static int xread_tls_block(tls_state_t *tls) | 634 | static int xread_tls_block(tls_state_t *tls) |
635 | { | 635 | { |
636 | struct record_hdr *xhdr; | 636 | struct record_hdr *xhdr; |
637 | int len; | 637 | int sz; |
638 | int total; | 638 | int total; |
639 | int target; | 639 | int target; |
640 | 640 | ||
@@ -658,24 +658,57 @@ static int xread_tls_block(tls_state_t *tls) | |||
658 | /* if total >= target, we have a full packet (and possibly more)... */ | 658 | /* if total >= target, we have a full packet (and possibly more)... */ |
659 | if (total - target >= 0) | 659 | if (total - target >= 0) |
660 | break; | 660 | break; |
661 | len = safe_read(tls->fd, tls->inbuf + total, sizeof(tls->inbuf) - total); | 661 | sz = safe_read(tls->fd, tls->inbuf + total, sizeof(tls->inbuf) - total); |
662 | if (len <= 0) | 662 | if (sz <= 0) |
663 | bb_perror_msg_and_die("short read"); | 663 | bb_perror_msg_and_die("short read"); |
664 | total += len; | 664 | total += sz; |
665 | } | 665 | } |
666 | tls->tail = total - target; | 666 | tls->tail = total - target; |
667 | tls->insize = target; | 667 | tls->insize = target; |
668 | target -= sizeof(*xhdr); | 668 | sz = target - sizeof(*xhdr); |
669 | |||
670 | /* Needs to be decrypted? */ | ||
671 | if (tls->min_encrypted_len_on_read) { | ||
672 | psCipherContext_t ctx; | ||
673 | uint8_t *p = tls->inbuf + sizeof(*xhdr); | ||
674 | int padding_len; | ||
675 | |||
676 | if (sz & (AES_BLOCKSIZE-1) | ||
677 | || sz < tls->min_encrypted_len_on_read | ||
678 | ) { | ||
679 | bb_error_msg_and_die("bad encrypted len:%u", sz); | ||
680 | } | ||
681 | /* Decrypt content+MAC+padding in place */ | ||
682 | psAesInit(&ctx, p, /* IV */ | ||
683 | tls->server_write_key, sizeof(tls->server_write_key) | ||
684 | ); | ||
685 | psAesDecrypt(&ctx, | ||
686 | p + AES_BLOCKSIZE, /* ciphertext */ | ||
687 | p + AES_BLOCKSIZE, /* plaintext */ | ||
688 | sz | ||
689 | ); | ||
690 | padding_len = p[sz - 1]; | ||
691 | dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[AES_BLOCKSIZE], padding_len); | ||
692 | padding_len++; | ||
693 | sz -= AES_BLOCKSIZE + SHA256_OUTSIZE + padding_len; | ||
694 | if (sz < 0) { | ||
695 | bb_error_msg_and_die("bad padding size:%u", padding_len); | ||
696 | } | ||
697 | if (sz != 0) { | ||
698 | /* Skip IV */ | ||
699 | memmove(tls->inbuf + 5, tls->inbuf + 5 + AES_BLOCKSIZE, sz); | ||
700 | } | ||
701 | } | ||
669 | 702 | ||
670 | /* RFC 5246 is not saying it explicitly, but sha256 hash | 703 | /* RFC 5246 is not saying it explicitly, but sha256 hash |
671 | * in our FINISHED record must include data of incoming packets too! | 704 | * in our FINISHED record must include data of incoming packets too! |
672 | */ | 705 | */ |
673 | if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { | 706 | if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { |
674 | sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + 5, target); | 707 | sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + 5, sz); |
675 | } | 708 | } |
676 | 709 | ||
677 | dbg("got block len:%u\n", target); | 710 | dbg("got block len:%u\n", sz); |
678 | return target; | 711 | return sz; |
679 | } | 712 | } |
680 | 713 | ||
681 | /* | 714 | /* |
@@ -1194,9 +1227,6 @@ static void send_change_cipher_spec(tls_state_t *tls) | |||
1194 | /* Not "xwrite_and_hash": this is not a handshake message */ | 1227 | /* Not "xwrite_and_hash": this is not a handshake message */ |
1195 | dbg(">> CHANGE_CIPHER_SPEC\n"); | 1228 | dbg(">> CHANGE_CIPHER_SPEC\n"); |
1196 | xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); | 1229 | xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); |
1197 | |||
1198 | /* tls->write_seq64_be = 0; - already is */ | ||
1199 | tls->encrypt_on_write = 1; | ||
1200 | } | 1230 | } |
1201 | 1231 | ||
1202 | // 7.4.9. Finished | 1232 | // 7.4.9. Finished |
@@ -1335,7 +1365,9 @@ static void tls_handshake(tls_state_t *tls) | |||
1335 | send_client_key_exchange(tls); | 1365 | send_client_key_exchange(tls); |
1336 | 1366 | ||
1337 | send_change_cipher_spec(tls); | 1367 | send_change_cipher_spec(tls); |
1338 | /* we now should send encrypted... as soon as we grok AES. */ | 1368 | /* from now on we should send encrypted */ |
1369 | /* tls->write_seq64_be = 0; - already is */ | ||
1370 | tls->encrypt_on_write = 1; | ||
1339 | 1371 | ||
1340 | send_client_finished(tls); | 1372 | send_client_finished(tls); |
1341 | 1373 | ||
@@ -1344,8 +1376,8 @@ static void tls_handshake(tls_state_t *tls) | |||
1344 | if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) | 1376 | if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) |
1345 | tls_error_die(tls); | 1377 | tls_error_die(tls); |
1346 | dbg("<< CHANGE_CIPHER_SPEC\n"); | 1378 | dbg("<< CHANGE_CIPHER_SPEC\n"); |
1347 | tls->decrypt_on_read = 1; | 1379 | /* all incoming packets now should be encrypted and have IV + MAC + padding */ |
1348 | /* we now should receive encrypted */ | 1380 | tls->min_encrypted_len_on_read = AES_BLOCKSIZE + SHA256_OUTSIZE + AES_BLOCKSIZE; |
1349 | 1381 | ||
1350 | /* Get (encrypted) FINISHED from the server */ | 1382 | /* Get (encrypted) FINISHED from the server */ |
1351 | len = xread_tls_block(tls); | 1383 | len = xread_tls_block(tls); |
@@ -1356,8 +1388,13 @@ static void tls_handshake(tls_state_t *tls) | |||
1356 | } | 1388 | } |
1357 | 1389 | ||
1358 | // To run a test server using openssl: | 1390 | // To run a test server using openssl: |
1391 | // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' | ||
1359 | // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 | 1392 | // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 |
1393 | // | ||
1394 | // Unencryped SHA256 example: | ||
1360 | // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' | 1395 | // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' |
1396 | // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL | ||
1397 | // openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 | ||
1361 | 1398 | ||
1362 | int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1399 | int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1363 | int tls_main(int argc UNUSED_PARAM, char **argv) | 1400 | int tls_main(int argc UNUSED_PARAM, char **argv) |
@@ -1381,12 +1418,8 @@ int tls_main(int argc UNUSED_PARAM, char **argv) | |||
1381 | 1418 | ||
1382 | return EXIT_SUCCESS; | 1419 | return EXIT_SUCCESS; |
1383 | } | 1420 | } |
1384 | |||
1385 | /* Unencryped SHA256 example: | 1421 | /* Unencryped SHA256 example: |
1386 | * $ openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' | 1422 | * s_client says: |
1387 | * $ openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL | ||
1388 | * $ openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 | ||
1389 | * s_client says: | ||
1390 | 1423 | ||
1391 | write to 0x1d750b0 [0x1e6f153] (99 bytes => 99 (0x63)) | 1424 | write to 0x1d750b0 [0x1e6f153] (99 bytes => 99 (0x63)) |
1392 | 0000 - 16 03 01 005e 01 00005a 0303 [4d ef 5c 82 3e ....^...Z..M.\.> >> ClHello | 1425 | 0000 - 16 03 01 005e 01 00005a 0303 [4d ef 5c 82 3e ....^...Z..M.\.> >> ClHello |