diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-18 20:37:24 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-18 20:37:24 +0100 |
| commit | b5dfc3dfd69ec20358827f8ecb2a42ca4b290f03 (patch) | |
| tree | 33eb3dbcb3fef142cdb55e7f45085a7041c77aec | |
| parent | b7e9ae6e9f8b1683774e2a69b943cec31c94f5a2 (diff) | |
| download | busybox-w32-b5dfc3dfd69ec20358827f8ecb2a42ca4b290f03.tar.gz busybox-w32-b5dfc3dfd69ec20358827f8ecb2a42ca4b290f03.tar.bz2 busybox-w32-b5dfc3dfd69ec20358827f8ecb2a42ca4b290f03.zip | |
tls: teach it to send AES256-encrypted data
>> CLIENT_HELLO
wrote 50 bytes
insize:0 tail:0
got block len:74
got HANDSHAKE
<< SERVER_HELLO
insize:79 tail:0
got block len:2397
got HANDSHAKE
<< CERTIFICATE
key bytes:271, first:0x00
server_rsa_pub_key.size:256
insize:2402 tail:0
got block len:4
got HANDSHAKE
<< SERVER_HELLO_DONE
>> CLIENT_KEY_EXCHANGE
wrote 267 bytes
master secret:c51df5b1e3b3f57373cdd8ea28e8ce562059636cf9f585d0b89c7f4bacec97e674d7b91f93e7b500cb64637f240c3b78
client_write_MAC_key:3b0b7e2bab241b629c37eb3a3824f09b39fe71a00876b0c8026dda16ef0d2f82
client_write_key:d36e801470ed2f0a8fc886ac25df57ffbe4265d06e3192122c4ef4df1e32fab2
>> CHANGE_CIPHER_SPEC
from secret: c51df5b1e3b3f57373cdd8ea28e8ce562059636cf9f585d0b89c7f4bacec97e674d7b91f93e7b500cb64637f240c3b78
from labelSeed: 636c69656e742066696e6973686564b22e0e6008b8ee218cc02e4a93e4a42b570535f9b57662e262d43b379d125b69
=> digest: a45bfee8ed6507a2a9920d0c
>> FINISHED
before crypt: 5 hdr + 16 data + 32 hash bytes
writing 5 + 16 IV + 64 encrypted bytes, padding_length:0x0f
wrote 85 bytes
insize:9 tail:0
got block len:1
<< CHANGE_CIPHER_SPEC
insize:6 tail:0
got block len:80
< hdr_type:22 ver:3.3 len:80 type:21 len24:9541723 |1591985b...a3da|
The last line is the server's FINISHED response, encrypted.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | networking/tls.c | 159 |
1 files changed, 148 insertions, 11 deletions
diff --git a/networking/tls.c b/networking/tls.c index 4986c991d..2b1e36110 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
| @@ -143,14 +143,25 @@ | |||
| 143 | //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE | 143 | //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE |
| 144 | //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE | 144 | //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE |
| 145 | //#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? | 145 | //#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? |
| 146 | #define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) | ||
| 147 | //#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE | 146 | //#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE |
| 148 | //^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck) | 147 | //^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck) |
| 149 | //test TLS_RSA_WITH_AES_128_CBC_SHA, in tls 1.2 it's mandated to be always supported | 148 | //test TLS_RSA_WITH_AES_128_CBC_SHA, in TLS 1.2 it's mandated to be always supported |
| 149 | |||
| 150 | // works against "openssl s_server -cipher NULL" | ||
| 151 | // and against wolfssl-3.9.10-stable/examples/server/server.c: | ||
| 152 | //#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) | ||
| 153 | // "works", meaning | ||
| 154 | // "can send encrypted FINISHED to wolfssl-3.9.10-stable/examples/server/server.c", | ||
| 155 | // don't yet read its encrypted answers: | ||
| 156 | #define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE | ||
| 150 | 157 | ||
| 151 | enum { | 158 | enum { |
| 152 | SHA256_INSIZE = 64, | 159 | SHA256_INSIZE = 64, |
| 153 | SHA256_OUTSIZE = 32, | 160 | SHA256_OUTSIZE = 32, |
| 161 | |||
| 162 | AES_BLOCKSIZE = 16, | ||
| 163 | AES128_KEYSIZE = 16, | ||
| 164 | AES256_KEYSIZE = 32, | ||
| 154 | }; | 165 | }; |
| 155 | 166 | ||
| 156 | struct record_hdr { | 167 | struct record_hdr { |
| @@ -172,6 +183,9 @@ typedef struct tls_state { | |||
| 172 | uint8_t encrypt_on_write; | 183 | uint8_t encrypt_on_write; |
| 173 | uint8_t decrypt_on_read; | 184 | uint8_t decrypt_on_read; |
| 174 | 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]; | ||
| 187 | uint8_t client_write_key[AES256_KEYSIZE]; | ||
| 188 | uint8_t server_write_key[AES256_KEYSIZE]; | ||
| 175 | // RFC 5246 | 189 | // RFC 5246 |
| 176 | // sequence number | 190 | // sequence number |
| 177 | // Each connection state contains a sequence number, which is | 191 | // Each connection state contains a sequence number, which is |
| @@ -208,7 +222,10 @@ typedef struct tls_state { | |||
| 208 | // Since our buffer also contains 5-byte headers, make it a bit bigger: | 222 | // Since our buffer also contains 5-byte headers, make it a bit bigger: |
| 209 | int insize; | 223 | int insize; |
| 210 | int tail; | 224 | int tail; |
| 211 | uint8_t inbuf[18*1024]; | 225 | //needed? |
| 226 | uint64_t align____; | ||
| 227 | uint8_t inbuf[20*1024]; | ||
| 228 | uint8_t outbuf[20*1024]; | ||
| 212 | } tls_state_t; | 229 | } tls_state_t; |
| 213 | 230 | ||
| 214 | 231 | ||
| @@ -512,13 +529,114 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size | |||
| 512 | NULL); | 529 | NULL); |
| 513 | tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); | 530 | tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); |
| 514 | 531 | ||
| 515 | xhdr->len16_lo += SHA256_OUTSIZE; | 532 | if (CIPHER_ID == TLS_RSA_WITH_NULL_SHA256) { |
| 516 | xwrite(tls->fd, buf, size); | 533 | /* No encryption, only signing */ |
| 517 | xhdr->len16_lo -= SHA256_OUTSIZE; | 534 | xhdr->len16_lo += SHA256_OUTSIZE; |
| 518 | dbg("wrote %u bytes\n", size); | 535 | //FIXME: overflow into len16_hi? |
| 536 | xwrite(tls->fd, buf, size); | ||
| 537 | xhdr->len16_lo -= SHA256_OUTSIZE; | ||
| 538 | dbg("wrote %u bytes\n", size); | ||
| 539 | |||
| 540 | xwrite(tls->fd, mac_hash, sizeof(mac_hash)); | ||
| 541 | dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); | ||
| 542 | return; | ||
| 543 | } | ||
| 544 | |||
| 545 | // RFC 5246 | ||
| 546 | // 6.2.3.2. CBC Block Cipher | ||
| 547 | // For block ciphers (such as 3DES or AES), the encryption and MAC | ||
| 548 | // functions convert TLSCompressed.fragment structures to and from block | ||
| 549 | // TLSCiphertext.fragment structures. | ||
| 550 | // struct { | ||
| 551 | // opaque IV[SecurityParameters.record_iv_length]; | ||
| 552 | // block-ciphered struct { | ||
| 553 | // opaque content[TLSCompressed.length]; | ||
| 554 | // opaque MAC[SecurityParameters.mac_length]; | ||
| 555 | // uint8 padding[GenericBlockCipher.padding_length]; | ||
| 556 | // uint8 padding_length; | ||
| 557 | // }; | ||
| 558 | // } GenericBlockCipher; | ||
| 559 | //... | ||
| 560 | // IV | ||
| 561 | // The Initialization Vector (IV) SHOULD be chosen at random, and | ||
| 562 | // MUST be unpredictable. Note that in versions of TLS prior to 1.1, | ||
| 563 | // there was no IV field (...). For block ciphers, the IV length is | ||
| 564 | // of length SecurityParameters.record_iv_length, which is equal to the | ||
| 565 | // SecurityParameters.block_size. | ||
| 566 | // padding | ||
| 567 | // Padding that is added to force the length of the plaintext to be | ||
| 568 | // an integral multiple of the block cipher's block length. | ||
| 569 | // padding_length | ||
| 570 | // The padding length MUST be such that the total size of the | ||
| 571 | // GenericBlockCipher structure is a multiple of the cipher's block | ||
| 572 | // length. Legal values range from zero to 255, inclusive. | ||
| 573 | //... | ||
| 574 | // Appendix C. Cipher Suite Definitions | ||
| 575 | //... | ||
| 576 | // Key IV Block | ||
| 577 | // Cipher Type Material Size Size | ||
| 578 | // ------------ ------ -------- ---- ----- | ||
| 579 | // NULL Stream 0 0 N/A | ||
| 580 | // RC4_128 Stream 16 0 N/A | ||
| 581 | // 3DES_EDE_CBC Block 24 8 8 | ||
| 582 | // AES_128_CBC Block 16 16 16 | ||
| 583 | // AES_256_CBC Block 32 16 16 | ||
| 584 | { | ||
| 585 | psCipherContext_t ctx; | ||
| 586 | uint8_t *p; | ||
| 587 | uint8_t padding_length; | ||
| 588 | |||
| 589 | /* Build IV+content+MAC+padding in outbuf */ | ||
| 590 | tls_get_random(tls->outbuf, AES_BLOCKSIZE); /* IV */ | ||
| 591 | p = tls->outbuf + AES_BLOCKSIZE; | ||
| 592 | size -= sizeof(*xhdr); | ||
| 593 | dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, sizeof(mac_hash)); | ||
| 594 | p = mempcpy(p, buf + sizeof(*xhdr), size); /* content */ | ||
| 595 | p = mempcpy(p, mac_hash, sizeof(mac_hash)); /* MAC */ | ||
| 596 | size += sizeof(mac_hash); | ||
| 597 | // RFC is talking nonsense: | ||
| 598 | // Padding that is added to force the length of the plaintext to be | ||
| 599 | // an integral multiple of the block cipher's block length. | ||
| 600 | // WRONG. _padding+padding_length_, not just _padding_, | ||
| 601 | // pads the data. | ||
| 602 | // IOW: padding_length is the last byte of padding[] array, | ||
| 603 | // contrary to what RFC depicts. | ||
| 604 | // | ||
| 605 | // What actually happens is that there is always padding. | ||
| 606 | // If you need one byte to reach BLOCKSIZE, this byte is 0x00. | ||
| 607 | // If you need two bytes, they are both 0x01. | ||
| 608 | // If you need three, they are 0x02,0x02,0x02. And so on. | ||
| 609 | // If you need no bytes to reach BLOCKSIZE, you have to pad a full | ||
| 610 | // BLOCKSIZE with bytes of value (BLOCKSIZE-1). | ||
| 611 | // It's ok to have more than minimum padding, but we do minimum. | ||
| 612 | padding_length = (~size) & (AES_BLOCKSIZE - 1); | ||
| 613 | do { | ||
| 614 | *p++ = padding_length; /* padding */ | ||
| 615 | size++; | ||
| 616 | } while ((size & (AES_BLOCKSIZE - 1)) != 0); | ||
| 617 | |||
| 618 | /* Encrypt content+MAC+padding in place */ | ||
| 619 | psAesInit(&ctx, tls->outbuf, /* IV */ | ||
| 620 | tls->client_write_key, sizeof(tls->client_write_key) | ||
| 621 | ); | ||
| 622 | psAesEncrypt(&ctx, | ||
| 623 | tls->outbuf + AES_BLOCKSIZE, /* plaintext */ | ||
| 624 | tls->outbuf + AES_BLOCKSIZE, /* ciphertext */ | ||
| 625 | size | ||
| 626 | ); | ||
| 519 | 627 | ||
| 520 | xwrite(tls->fd, mac_hash, sizeof(mac_hash)); | 628 | /* Write out */ |
| 521 | dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); | 629 | dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n", |
| 630 | AES_BLOCKSIZE, size, padding_length); | ||
| 631 | size += AES_BLOCKSIZE; /* + IV */ | ||
| 632 | xhdr->len16_hi = size >> 8; | ||
| 633 | xhdr->len16_lo = size & 0xff; | ||
| 634 | xwrite(tls->fd, xhdr, sizeof(*xhdr)); | ||
| 635 | xwrite(tls->fd, tls->outbuf, size); | ||
| 636 | dbg("wrote %u bytes\n", sizeof(*xhdr) + size); | ||
| 637 | //restore xhdr->len16_hi = ; | ||
| 638 | //restore xhdr->len16_lo = ; | ||
| 639 | } | ||
| 522 | } | 640 | } |
| 523 | 641 | ||
| 524 | static int xread_tls_block(tls_state_t *tls) | 642 | static int xread_tls_block(tls_state_t *tls) |
| @@ -1048,14 +1166,30 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
| 1048 | // server_write_key[SecurityParameters.enc_key_length] | 1166 | // server_write_key[SecurityParameters.enc_key_length] |
| 1049 | // client_write_IV[SecurityParameters.fixed_iv_length] | 1167 | // client_write_IV[SecurityParameters.fixed_iv_length] |
| 1050 | // server_write_IV[SecurityParameters.fixed_iv_length] | 1168 | // server_write_IV[SecurityParameters.fixed_iv_length] |
| 1169 | |||
| 1170 | |||
| 1171 | // Key IV Block | ||
| 1172 | // Cipher Type Material Size Size | ||
| 1173 | // ------------ ------ -------- ---- ----- | ||
| 1174 | // NULL Stream 0 0 N/A | ||
| 1175 | // RC4_128 Stream 16 0 N/A | ||
| 1176 | // 3DES_EDE_CBC Block 24 8 8 | ||
| 1177 | // AES_128_CBC Block 16 16 16 | ||
| 1178 | // AES_256_CBC Block 32 16 16 | ||
| 1179 | |||
| 1051 | { | 1180 | { |
| 1052 | uint8_t tmp64[64]; | 1181 | uint8_t tmp64[64]; |
| 1053 | /* make server_rand32 + client_rand32 */ | 1182 | |
| 1183 | /* make "server_rand32 + client_rand32" */ | ||
| 1054 | memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); | 1184 | memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); |
| 1055 | memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); | 1185 | memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); |
| 1056 | 1186 | ||
| 1057 | prf_hmac_sha256( | 1187 | prf_hmac_sha256( |
| 1058 | tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), | 1188 | tls->client_write_MAC_key, 2 * (SHA256_OUTSIZE + AES256_KEYSIZE), |
| 1189 | // also fills: | ||
| 1190 | // server_write_MAC_key[SHA256_OUTSIZE] | ||
| 1191 | // client_write_key[AES256_KEYSIZE] | ||
| 1192 | // server_write_key[AES256_KEYSIZE] | ||
| 1059 | tls->master_secret, sizeof(tls->master_secret), | 1193 | tls->master_secret, sizeof(tls->master_secret), |
| 1060 | "key expansion", | 1194 | "key expansion", |
| 1061 | tmp64, 64 | 1195 | tmp64, 64 |
| @@ -1063,6 +1197,9 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
| 1063 | dump_hex("client_write_MAC_key:%s\n", | 1197 | dump_hex("client_write_MAC_key:%s\n", |
| 1064 | tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key) | 1198 | tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key) |
| 1065 | ); | 1199 | ); |
| 1200 | dump_hex("client_write_key:%s\n", | ||
| 1201 | tls->client_write_key, sizeof(tls->client_write_key) | ||
| 1202 | ); | ||
| 1066 | } | 1203 | } |
| 1067 | } | 1204 | } |
| 1068 | 1205 | ||
