From 1500b3a50d587adeca7be96b36394f23f2d80a82 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jan 2017 17:06:10 +0100 Subject: tls: if got CERTIFICATE_REQUEST, send an empty CERTIFICATE wolfssl test server is not satisfied by an empty one, but some real servers might be. Signed-off-by: Denys Vlasenko --- networking/tls.c | 65 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 20 deletions(-) (limited to 'networking/tls.c') diff --git a/networking/tls.c b/networking/tls.c index a65da4ad4..dc94a8b9b 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -484,21 +484,24 @@ static void prf_hmac(tls_state_t *tls, static void bad_record_die(tls_state_t *tls, const char *expected, int len) { - bb_error_msg_and_die("got bad TLS record (len:%d) while expecting %s", len, expected); + bb_error_msg("got bad TLS record (len:%d) while expecting %s", len, expected); if (len > 0) { uint8_t *p = tls->inbuf; - while (len > 0) + while (len > 0) { fprintf(stderr, " %02x", *p++); + len--; + } fputc('\n', stderr); } xfunc_die(); } -static void tls_error_die(tls_state_t *tls) +static void tls_error_die(tls_state_t *tls, int line) { dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size); - bb_error_msg_and_die("TODO: useful diagnostic about %p", tls); + bb_error_msg_and_die("tls error at line %d cipher:%04x", line, tls->cipher_id); } +#define tls_error_die(tls) tls_error_die(tls, __LINE__) #if 0 //UNUSED static void tls_free_inbuf(tls_state_t *tls) @@ -1343,6 +1346,26 @@ static void get_server_cert(tls_state_t *tls) find_key_in_der_cert(tls, certbuf + 10, len); } +static void send_empty_client_cert(tls_state_t *tls) +{ + struct client_empty_cert { + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + uint8_t cert_chain_len24_hi, cert_chain_len24_mid, cert_chain_len24_lo; + }; + struct client_empty_cert *record; + + record = tls_get_outbuf(tls, sizeof(*record)); +//FIXME: can just memcpy a ready-made one. + fill_handshake_record_hdr(record, HANDSHAKE_CERTIFICATE, sizeof(*record)); + record->cert_chain_len24_hi = 0; + record->cert_chain_len24_mid = 0; + record->cert_chain_len24_lo = 0; + + dbg(">> CERTIFICATE\n"); + xwrite_and_update_handshake_hash(tls, sizeof(*record)); +} + static void send_client_key_exchange(tls_state_t *tls) { struct client_key_exchange { @@ -1584,23 +1607,25 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len); //probably need to save it - tls_xread_handshake_block(tls, 4); + len = tls_xread_handshake_block(tls, 4); } -// if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { -// dbg("<< CERTIFICATE_REQUEST\n"); -// RFC 5246: (in response to this,) "If no suitable certificate is available, -// the client MUST send a certificate message containing no -// certificates. That is, the certificate_list structure has a -// length of zero. ... -// Client certificates are sent using the Certificate structure -// defined in Section 7.4.2." -// (i.e. the same format as server certs) -// tls_xread_handshake_block(tls, 4); -// } - - if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) - tls_error_die(tls); + if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { + dbg("<< CERTIFICATE_REQUEST\n"); + // RFC 5246: "If no suitable certificate is available, + // the client MUST send a certificate message containing no + // certificates. That is, the certificate_list structure has a + // length of zero. ... + // Client certificates are sent using the Certificate structure + // defined in Section 7.4.2." + // (i.e. the same format as server certs) + send_empty_client_cert(tls); + len = tls_xread_handshake_block(tls, 4); + } + + if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) { + bad_record_die(tls, "'server hello done'", len); + } // 0e 000000 (len:0) dbg("<< SERVER_HELLO_DONE\n"); @@ -1616,7 +1641,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) /* Get CHANGE_CIPHER_SPEC */ len = tls_xread_record(tls); if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) - tls_error_die(tls); + bad_record_die(tls, "switch to encrypted traffic", len); dbg("<< CHANGE_CIPHER_SPEC\n"); if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256) tls->min_encrypted_len_on_read = tls->MAC_size; -- cgit v1.2.3