aboutsummaryrefslogtreecommitdiff
path: root/networking/tls.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-23 01:08:16 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-23 01:08:16 +0100
commit9a647c326a41e8160d53e6cb5470161a44c0e8cf (patch)
tree1fef73df291e5c5897aef1bb32b65206caacf879 /networking/tls.c
parente1f90d13fa07d2974908470ce818ef956b7740f2 (diff)
downloadbusybox-9a647c326a41e8160d53e6cb5470161a44c0e8cf.tar.gz
separate TLS code into a library, use in in wget
A new applet, ssl_client, is the TLS debug thing now. It doubles as wget's NOMMU helper. In MMU mode, wget still forks, but then directly calls TLS code, without execing. This can also be applied to sendmail/popmail (SMTPS / SMTP+starttls support) and nc --ssl (ncat, nmap's nc clone, has such option). function old new delta tls_handshake - 1691 +1691 tls_run_copy_loop - 443 +443 ssl_client_main - 128 +128 packed_usage 30978 31007 +29 wget_main 2508 2535 +27 applet_names 2553 2560 +7 ... xwrite_encrypted 360 342 -18 tls_main 2127 - -2127 ------------------------------------------------------------------------------ (add/remove: 4/1 grow/shrink: 13/8 up/down: 2351/-2195) Total: 156 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/tls.c')
-rw-r--r--networking/tls.c151
1 files changed, 45 insertions, 106 deletions
diff --git a/networking/tls.c b/networking/tls.c
index b111e4bb4..29cc5b9f3 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -4,11 +4,9 @@
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
//config:config TLS
-//config: bool "tls (debugging)"
+//config: bool #No description makes it a hidden option
//config: default n
-//applet:IF_TLS(APPLET(tls, BB_DIR_USR_BIN, BB_SUID_DROP))
-
//kbuild:lib-$(CONFIG_TLS) += tls.o
//kbuild:lib-$(CONFIG_TLS) += tls_pstm.o
//kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o
@@ -18,12 +16,7 @@
//kbuild:lib-$(CONFIG_TLS) += tls_aes.o
////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o
-//usage:#define tls_trivial_usage
-//usage: "HOST[:PORT]"
-//usage:#define tls_full_usage "\n\n"
-
#include "tls.h"
-//#include "common_bufsiz.h"
#define TLS_DEBUG 1
#define TLS_DEBUG_HASH 0
@@ -165,13 +158,6 @@
#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE
enum {
- SHA256_INSIZE = 64,
- SHA256_OUTSIZE = 32,
-
- AES_BLOCKSIZE = 16,
- AES128_KEYSIZE = 16,
- AES256_KEYSIZE = 32,
-
RSA_PREMASTER_SIZE = 48,
RECHDR_LEN = 5,
@@ -225,20 +211,7 @@ struct record_hdr {
uint8_t len16_hi, len16_lo;
};
-typedef struct tls_state {
- int fd;
-
- int min_encrypted_len_on_read;
- uint8_t encrypt_on_write;
-
- uint8_t *outbuf;
- int outbuf_size;
-
- int inbuf_size;
- int ofs_to_buffered;
- int buffered_size;
- uint8_t *inbuf;
-
+struct tls_handshake_data {
//TODO: store just the DER key here, parse/use/delete it when sending client key
//this way it will stay key type agnostic here.
psRsaKey_t server_rsa_pub_key;
@@ -247,22 +220,7 @@ typedef struct tls_state {
// these two are unused after finished messages are exchanged:
sha256_ctx_t handshake_sha256_ctx;
uint8_t master_secret[48];
-
- // RFC 5246
- // sequence number
- // Each connection state contains a sequence number, which is
- // maintained separately for read and write states. The sequence
- // number MUST be set to zero whenever a connection state is made the
- // active state. Sequence numbers are of type uint64 and may not
- // exceed 2^64-1.
- /*uint64_t read_seq64_be;*/
- uint64_t write_seq64_be;
-
- uint8_t client_write_MAC_key[SHA256_OUTSIZE];
- uint8_t server_write_MAC_key[SHA256_OUTSIZE];
- uint8_t client_write_key[AES256_KEYSIZE];
- uint8_t server_write_key[AES256_KEYSIZE];
-} tls_state_t;
+};
static unsigned get24be(const uint8_t *p)
@@ -487,14 +445,6 @@ static void prf_hmac_sha256(
#undef SEED
}
-static tls_state_t *new_tls_state(void)
-{
- tls_state_t *tls = xzalloc(sizeof(*tls));
- tls->fd = -1;
- sha256_begin(&tls->handshake_sha256_ctx);
- return tls;
-}
-
static void tls_error_die(tls_state_t *tls)
{
dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size);
@@ -597,7 +547,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
xhdr->len16_hi = size >> 8;
xhdr->len16_lo = size & 0xff;
dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
- xwrite(tls->fd, xhdr, RECHDR_LEN + size);
+ xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size);
return;
}
@@ -681,7 +631,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
xhdr->len16_hi = size >> 8;
xhdr->len16_lo = size & 0xff;
dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
- xwrite(tls->fd, xhdr, RECHDR_LEN + size);
+ xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
dbg("wrote %u bytes\n", (int)RECHDR_LEN + size);
}
@@ -697,10 +647,10 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size)
xhdr->len16_hi = size >> 8;
xhdr->len16_lo = size & 0xff;
dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
- xwrite(tls->fd, xhdr, RECHDR_LEN + size);
+ xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
dbg("wrote %u bytes\n", (int)RECHDR_LEN + size);
/* Handshake hash does not include record headers */
- sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, buf, size);
+ sha256_hash_dbg(">> sha256:%s", &tls->hsd->handshake_sha256_ctx, buf, size);
return;
}
xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE);
@@ -769,7 +719,7 @@ static int tls_xread_record(tls_state_t *tls)
rem = tls->inbuf_size - total;
tls->inbuf = xrealloc(tls->inbuf, tls->inbuf_size);
}
- sz = safe_read(tls->fd, tls->inbuf + total, rem);
+ sz = safe_read(tls->ifd, tls->inbuf + total, rem);
if (sz <= 0) {
if (sz == 0 && total == 0) {
/* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */
@@ -848,7 +798,7 @@ static int tls_xread_record(tls_state_t *tls)
* in our FINISHED record must include data of incoming packets too!
*/
if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) {
- sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz);
+ sha256_hash_dbg("<< sha256:%s", &tls->hsd->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz);
}
end:
dbg("got block len:%u\n", sz);
@@ -1059,12 +1009,12 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
xfunc_die();
der++;
der = enter_der_item(der, &end); /* enter SEQ */
- /* memset(tls->server_rsa_pub_key, 0, sizeof(tls->server_rsa_pub_key)); - already is */
- der_binary_to_pstm(&tls->server_rsa_pub_key.N, der, end); /* modulus */
+ /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */
+ der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */
der = skip_der_item(der, end);
- der_binary_to_pstm(&tls->server_rsa_pub_key.e, der, end); /* exponent */
- tls->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->server_rsa_pub_key.N);
- dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size);
+ der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */
+ tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N);
+ dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size);
}
/*
@@ -1140,7 +1090,7 @@ static void send_client_hello(tls_state_t *tls, const char *sni)
tls_get_random(record->rand32, sizeof(record->rand32));
if (TLS_DEBUG_FIXED_SECRETS)
memset(record->rand32, 0x11, sizeof(record->rand32));
- memcpy(tls->client_and_server_rand32, record->rand32, sizeof(record->rand32));
+ memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32));
/* record->session_id_len = 0; - already is */
/* record->cipherid_len16_hi = 0; */
record->cipherid_len16_lo = 2 * 1;
@@ -1225,7 +1175,7 @@ static void get_server_hello(tls_state_t *tls)
}
dbg("<< SERVER_HELLO\n");
- memcpy(tls->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32));
+ memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32));
}
static void get_server_cert(tls_state_t *tls)
@@ -1282,7 +1232,7 @@ static void send_client_key_exchange(tls_state_t *tls)
rsa_premaster[0] = TLS_MAJ;
rsa_premaster[1] = TLS_MIN;
len = psRsaEncryptPub(/*pool:*/ NULL,
- /* psRsaKey_t* */ &tls->server_rsa_pub_key,
+ /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key,
rsa_premaster, /*inlen:*/ sizeof(rsa_premaster),
record->key, sizeof(record->key),
data_param_ignored
@@ -1310,12 +1260,12 @@ static void send_client_key_exchange(tls_state_t *tls)
// The master secret is always exactly 48 bytes in length. The length
// of the premaster secret will vary depending on key exchange method.
prf_hmac_sha256(
- tls->master_secret, sizeof(tls->master_secret),
+ tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
rsa_premaster, sizeof(rsa_premaster),
"master secret",
- tls->client_and_server_rand32, sizeof(tls->client_and_server_rand32)
+ tls->hsd->client_and_server_rand32, sizeof(tls->hsd->client_and_server_rand32)
);
- dump_hex("master secret:%s\n", tls->master_secret, sizeof(tls->master_secret));
+ dump_hex("master secret:%s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret));
// RFC 5246
// 6.3. Key Calculation
@@ -1354,8 +1304,8 @@ static void send_client_key_exchange(tls_state_t *tls)
uint8_t tmp64[64];
/* make "server_rand32 + client_rand32" */
- memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32);
- memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32);
+ memcpy(&tmp64[0] , &tls->hsd->client_and_server_rand32[32], 32);
+ memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32);
prf_hmac_sha256(
tls->client_write_MAC_key, 2 * (SHA256_OUTSIZE + AES256_KEYSIZE),
@@ -1363,7 +1313,7 @@ static void send_client_key_exchange(tls_state_t *tls)
// server_write_MAC_key[SHA256_OUTSIZE]
// client_write_key[AES256_KEYSIZE]
// server_write_key[AES256_KEYSIZE]
- tls->master_secret, sizeof(tls->master_secret),
+ tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
"key expansion",
tmp64, 64
);
@@ -1384,7 +1334,7 @@ static const uint8_t rec_CHANGE_CIPHER_SPEC[] = {
static void send_change_cipher_spec(tls_state_t *tls)
{
dbg(">> CHANGE_CIPHER_SPEC\n");
- xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC));
+ xwrite(tls->ofd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC));
}
// 7.4.9. Finished
@@ -1436,13 +1386,13 @@ static void send_client_finished(tls_state_t *tls)
fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record));
- sha256_peek(&tls->handshake_sha256_ctx, handshake_hash);
+ sha256_peek(&tls->hsd->handshake_sha256_ctx, handshake_hash);
prf_hmac_sha256(record->prf_result, sizeof(record->prf_result),
- tls->master_secret, sizeof(tls->master_secret),
+ tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
"client finished",
handshake_hash, sizeof(handshake_hash)
);
- dump_hex("from secret: %s\n", tls->master_secret, sizeof(tls->master_secret));
+ dump_hex("from secret: %s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret));
dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1);
dump_hex("%s\n", handshake_hash, sizeof(handshake_hash));
dump_hex("=> digest: %s\n", record->prf_result, sizeof(record->prf_result));
@@ -1451,7 +1401,7 @@ static void send_client_finished(tls_state_t *tls)
xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE);
}
-static void tls_handshake(tls_state_t *tls, const char *sni)
+void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni)
{
// Client RFC 5246 Server
// (*) - optional messages, not always sent
@@ -1472,6 +1422,9 @@ static void tls_handshake(tls_state_t *tls, const char *sni)
// Application Data <------> Application Data
int len;
+ tls->hsd = xzalloc(sizeof(*tls->hsd));
+ sha256_begin(&tls->hsd->handshake_sha256_ctx);
+
send_client_hello(tls, sni);
get_server_hello(tls);
@@ -1541,6 +1494,12 @@ static void tls_handshake(tls_state_t *tls, const char *sni)
tls_error_die(tls);
dbg("<< FINISHED\n");
/* application data can be sent/received */
+
+ /* free handshake data */
+// if (PARANOIA)
+// memset(tls->hsd, 0, sizeof(*tls->hsd));
+ free(tls->hsd);
+ tls->hsd = NULL;
}
static void tls_xwrite(tls_state_t *tls, int len)
@@ -1557,35 +1516,17 @@ static void tls_xwrite(tls_state_t *tls, int len)
// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost'
// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL
// openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256
-//
-// Talk to kernel.org:
-// printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox tls kernel.org
-int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int tls_main(int argc UNUSED_PARAM, char **argv)
+void FAST_FUNC tls_run_copy_loop(tls_state_t *tls)
{
- tls_state_t *tls;
fd_set readfds;
int inbuf_size;
const int INBUF_STEP = 4 * 1024;
- int cfd;
-
- // INIT_G();
- // getopt32(argv, "myopts")
-
- if (!argv[1])
- bb_show_usage();
-
- cfd = create_and_connect_stream_or_die(argv[1], 443);
-
- tls = new_tls_state();
- tls->fd = cfd;
- tls_handshake(tls, argv[1]);
-
- /* Select loop copying stdin to cfd, and cfd to stdout */
+//TODO: convert to poll
+ /* Select loop copying stdin to ofd, and ifd to stdout */
FD_ZERO(&readfds);
- FD_SET(cfd, &readfds);
+ FD_SET(tls->ifd, &readfds);
FD_SET(STDIN_FILENO, &readfds);
inbuf_size = INBUF_STEP;
@@ -1594,7 +1535,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv)
int nread;
testfds = readfds;
- if (select(cfd + 1, &testfds, NULL, NULL, NULL) < 0)
+ if (select(tls->ifd + 1, &testfds, NULL, NULL, NULL) < 0)
bb_perror_msg_and_die("select");
if (FD_ISSET(STDIN_FILENO, &testfds)) {
@@ -1608,7 +1549,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv)
/* Close outgoing half-connection so they get EOF,
* but leave incoming alone so we can see response
*/
- //shutdown(cfd, SHUT_WR);
+ //shutdown(tls->ofd, SHUT_WR);
/* But TLS has no way to encode this,
* doubt it's ok to do it "raw"
*/
@@ -1626,7 +1567,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv)
tls_xwrite(tls, nread);
}
}
- if (FD_ISSET(cfd, &testfds)) {
+ if (FD_ISSET(tls->ifd, &testfds)) {
dbg("NETWORK HAS DATA\n");
read_record:
nread = tls_xread_record(tls);
@@ -1634,7 +1575,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv)
/* TLS protocol has no real concept of one-sided shutdowns:
* if we get "TLS EOF" from the peer, writes will fail too
*/
- //FD_CLR(cfd, &readfds);
+ //FD_CLR(tls->ifd, &readfds);
//close(STDOUT_FILENO);
//tls_free_inbuf(tls); /* mem usage optimization */
//continue;
@@ -1650,6 +1591,4 @@ int tls_main(int argc UNUSED_PARAM, char **argv)
goto read_record;
}
}
-
- return EXIT_SUCCESS;
}