tls: massage writing for encryption support; finer-grained debug
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
5d1662ea1c
commit
c8ba23bcec
@ -25,7 +25,9 @@
|
|||||||
|
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
|
|
||||||
#define TLS_DEBUG 2
|
#define TLS_DEBUG 1
|
||||||
|
#define TLS_DEBUG_HASH 0
|
||||||
|
#define TLS_DEBUG_DER 0
|
||||||
|
|
||||||
#if TLS_DEBUG
|
#if TLS_DEBUG
|
||||||
# define dbg(...) fprintf(stderr, __VA_ARGS__)
|
# define dbg(...) fprintf(stderr, __VA_ARGS__)
|
||||||
@ -33,6 +35,12 @@
|
|||||||
# define dbg(...) ((void)0)
|
# define dbg(...) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TLS_DEBUG_DER
|
||||||
|
# define dbg_der(...) fprintf(stderr, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
# define dbg_der(...) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20
|
#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20
|
||||||
#define RECORD_TYPE_ALERT 21
|
#define RECORD_TYPE_ALERT 21
|
||||||
#define RECORD_TYPE_HANDSHAKE 22
|
#define RECORD_TYPE_HANDSHAKE 22
|
||||||
@ -269,7 +277,7 @@ static void sha256_peek(sha256_ctx_t *ctx, void *buffer)
|
|||||||
sha256_end(&ctx_copy, buffer);
|
sha256_end(&ctx_copy, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TLS_DEBUG >= 2
|
#if TLS_DEBUG_HASH
|
||||||
static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buffer, size_t len)
|
static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buffer, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t h[SHA256_OUTSIZE];
|
uint8_t h[SHA256_OUTSIZE];
|
||||||
@ -283,7 +291,7 @@ static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buff
|
|||||||
#else
|
#else
|
||||||
# define sha256_hash_dbg(fmt, ctx, buffer, len) \
|
# define sha256_hash_dbg(fmt, ctx, buffer, len) \
|
||||||
sha256_hash(ctx, buffer, len)
|
sha256_hash(ctx, buffer, len)
|
||||||
#endif /* not TLS_DEBUG >= 2 */
|
#endif
|
||||||
|
|
||||||
// RFC 2104
|
// RFC 2104
|
||||||
// HMAC(key, text) based on a hash H (say, sha256) is:
|
// HMAC(key, text) based on a hash H (say, sha256) is:
|
||||||
@ -424,8 +432,7 @@ static void prf_hmac_sha256(
|
|||||||
#undef SEED
|
#undef SEED
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static tls_state_t *new_tls_state(void)
|
||||||
tls_state_t *new_tls_state(void)
|
|
||||||
{
|
{
|
||||||
tls_state_t *tls = xzalloc(sizeof(*tls));
|
tls_state_t *tls = xzalloc(sizeof(*tls));
|
||||||
tls->fd = -1;
|
tls->fd = -1;
|
||||||
@ -488,7 +495,16 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size
|
|||||||
uint8_t mac_hash[SHA256_OUTSIZE];
|
uint8_t mac_hash[SHA256_OUTSIZE];
|
||||||
struct record_hdr *xhdr = buf;
|
struct record_hdr *xhdr = buf;
|
||||||
|
|
||||||
if (tls->encrypt_on_write) {
|
if (!tls->encrypt_on_write) {
|
||||||
|
xwrite(tls->fd, buf, size);
|
||||||
|
dbg("wrote %u bytes\n", size);
|
||||||
|
/* Handshake hash does not include record headers */
|
||||||
|
if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) {
|
||||||
|
sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: convert hmac_sha256 to precomputed
|
//TODO: convert hmac_sha256 to precomputed
|
||||||
hmac_sha256(mac_hash,
|
hmac_sha256(mac_hash,
|
||||||
tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key),
|
tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key),
|
||||||
@ -496,23 +512,14 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size
|
|||||||
buf, size,
|
buf, size,
|
||||||
NULL);
|
NULL);
|
||||||
tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be));
|
tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be));
|
||||||
/* Temporarily change for writing */
|
|
||||||
xhdr->len16_lo += SHA256_OUTSIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
xhdr->len16_lo += SHA256_OUTSIZE;
|
||||||
xwrite(tls->fd, buf, size);
|
xwrite(tls->fd, buf, size);
|
||||||
|
xhdr->len16_lo -= SHA256_OUTSIZE;
|
||||||
dbg("wrote %u bytes\n", size);
|
dbg("wrote %u bytes\n", size);
|
||||||
|
|
||||||
if (tls->encrypt_on_write) {
|
|
||||||
xwrite(tls->fd, mac_hash, sizeof(mac_hash));
|
xwrite(tls->fd, mac_hash, sizeof(mac_hash));
|
||||||
dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash));
|
dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash));
|
||||||
xhdr->len16_lo -= SHA256_OUTSIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handshake hash does not include record headers */
|
|
||||||
if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) {
|
|
||||||
sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xread_tls_block(tls_state_t *tls)
|
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)
|
|||||||
{
|
{
|
||||||
uint8_t *new_der;
|
uint8_t *new_der;
|
||||||
unsigned len = get_der_len(&new_der, der, *endp);
|
unsigned len = get_der_len(&new_der, der, *endp);
|
||||||
dbg("entered der @%p:0x%02x len:%u inner_byte @%p:0x%02x\n", der, der[0], len, new_der, new_der[0]);
|
dbg_der("entered der @%p:0x%02x len:%u inner_byte @%p:0x%02x\n", der, der[0], len, new_der, new_der[0]);
|
||||||
/* Move "end" position to cover only this item */
|
/* Move "end" position to cover only this item */
|
||||||
*endp = new_der + len;
|
*endp = new_der + len;
|
||||||
return new_der;
|
return new_der;
|
||||||
@ -623,7 +630,7 @@ static uint8_t *skip_der_item(uint8_t *der, uint8_t *end)
|
|||||||
unsigned len = get_der_len(&new_der, der, end);
|
unsigned len = get_der_len(&new_der, der, end);
|
||||||
/* Skip body */
|
/* Skip body */
|
||||||
new_der += len;
|
new_der += len;
|
||||||
dbg("skipped der 0x%02x, next byte 0x%02x\n", der[0], new_der[0]);
|
dbg_der("skipped der 0x%02x, next byte 0x%02x\n", der[0], new_der[0]);
|
||||||
return new_der;
|
return new_der;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,7 +639,7 @@ static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end)
|
|||||||
uint8_t *bin_ptr;
|
uint8_t *bin_ptr;
|
||||||
unsigned len = get_der_len(&bin_ptr, der, end);
|
unsigned len = get_der_len(&bin_ptr, der, end);
|
||||||
|
|
||||||
dbg("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]);
|
dbg_der("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]);
|
||||||
pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len);
|
pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len);
|
||||||
pstm_read_unsigned_bin(pstm_n, bin_ptr, len);
|
pstm_read_unsigned_bin(pstm_n, bin_ptr, len);
|
||||||
//return bin + len;
|
//return bin + len;
|
||||||
@ -854,7 +861,7 @@ static void send_client_hello(tls_state_t *tls)
|
|||||||
/* record.comprtypes[0] = 0; */
|
/* record.comprtypes[0] = 0; */
|
||||||
|
|
||||||
//dbg (make it repeatable): memset(record.rand32, 0x11, sizeof(record.rand32));
|
//dbg (make it repeatable): memset(record.rand32, 0x11, sizeof(record.rand32));
|
||||||
dbg(">> HANDSHAKE_CLIENT_HELLO\n");
|
dbg(">> CLIENT_HELLO\n");
|
||||||
xwrite_and_hash(tls, &record, sizeof(record));
|
xwrite_and_hash(tls, &record, sizeof(record));
|
||||||
memcpy(tls->client_and_server_rand32, record.rand32, sizeof(record.rand32));
|
memcpy(tls->client_and_server_rand32, record.rand32, sizeof(record.rand32));
|
||||||
}
|
}
|
||||||
@ -988,7 +995,7 @@ static void send_client_key_exchange(tls_state_t *tls)
|
|||||||
record.xhdr.len16_hi = len >> 8;
|
record.xhdr.len16_hi = len >> 8;
|
||||||
record.xhdr.len16_lo = len & 0xff;
|
record.xhdr.len16_lo = len & 0xff;
|
||||||
|
|
||||||
dbg(">> HANDSHAKE_CLIENT_KEY_EXCHANGE\n");
|
dbg(">> CLIENT_KEY_EXCHANGE\n");
|
||||||
xwrite_and_hash(tls, &record, sizeof(record.xhdr) + len);
|
xwrite_and_hash(tls, &record, sizeof(record.xhdr) + len);
|
||||||
|
|
||||||
// RFC 5246
|
// RFC 5246
|
||||||
@ -1114,13 +1121,13 @@ static void send_change_cipher_spec(tls_state_t *tls)
|
|||||||
// includes all existing cipher suites.
|
// includes all existing cipher suites.
|
||||||
static void send_client_finished(tls_state_t *tls)
|
static void send_client_finished(tls_state_t *tls)
|
||||||
{
|
{
|
||||||
struct client_finished {
|
struct finished {
|
||||||
struct record_hdr xhdr;
|
struct record_hdr xhdr;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t len24_hi, len24_mid, len24_lo;
|
uint8_t len24_hi, len24_mid, len24_lo;
|
||||||
uint8_t prf_result[12];
|
uint8_t prf_result[12];
|
||||||
};
|
};
|
||||||
struct client_finished record;
|
struct finished record;
|
||||||
uint8_t handshake_hash[SHA256_OUTSIZE];
|
uint8_t handshake_hash[SHA256_OUTSIZE];
|
||||||
|
|
||||||
fill_handshake_record_hdr(&record.xhdr, sizeof(record));
|
fill_handshake_record_hdr(&record.xhdr, sizeof(record));
|
||||||
@ -1140,7 +1147,7 @@ static void send_client_finished(tls_state_t *tls)
|
|||||||
//(1) TODO: well, this should be encrypted on send, really.
|
//(1) TODO: well, this should be encrypted on send, really.
|
||||||
//(2) do we really need to also hash it?
|
//(2) do we really need to also hash it?
|
||||||
|
|
||||||
dbg(">> HANDSHAKE_FINISHED\n");
|
dbg(">> FINISHED\n");
|
||||||
xwrite_and_hash(tls, &record, sizeof(record));
|
xwrite_and_hash(tls, &record, sizeof(record));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user