From: Nathan Wagner Date: Sun, 17 Feb 2019 20:46:20 +0000 (+0000) Subject: fix bug with dhe cbc mode X-Git-Tag: v0.6.0~5 X-Git-Url: https://pd.if.org/git/?p=zpackage;a=commitdiff_plain;h=4eb87b5be87fdff504476d1798d558367d3f6f3e fix bug with dhe cbc mode --- diff --git a/Makefile b/Makefile index 480ca11..4de8408 100644 --- a/Makefile +++ b/Makefile @@ -237,9 +237,12 @@ TLSOBJ= tlse.o x25519.o chacha.o base64.o pem.o forward.o handshake.o \ crypto/x25519.o: $(addprefix crypto/ref10/, $(X255OBJ)) ld -o $@ -r $+ -crypto/%.o: CFLAGS+=-Icrypto -DTFM_DESC -DTFM_NO_ASM -Itomsfastmath/src/headers \ +crypto/%.o: CFLAGS+=-Icrypto -DTFM_DESC -DTFM_NO_ASM \ + -Itomsfastmath/src/headers \ -Wno-pointer-sign -Wno-missing-braces -Ilibtomcrypt/src/headers +# -DDEBUG + # /usr/musl/bin/musl-clang -Wall -Wextra -Wno-missing-braces -Werror -Wno-pointer-sign -I. -DTFM_DESC -DTFM_NO_ASM -I ../libtomcrypt/src/headers -I ../tomsfastmath/src/headers -DSTRICT_TLS -DIGNORE_SESSION_ID --rtlib=compiler-rt -c -o tlse.o tlse.c #/usr/musl/bin/musl-clang -Wall -Wextra -Wno-missing-braces -Werror -Wno-pointer-sign -I. -DTFM_DESC -DTFM_NO_ASM -I ../libtomcrypt/src/headers -I ../tomsfastmath/src/headers -DSTRICT_TLS -DIGNORE_SESSION_ID --rtlib=compiler-rt -c -o tlse.o tlse.c diff --git a/crypto/handshake.c b/crypto/handshake.c index ed81920..264ecb9 100644 --- a/crypto/handshake.c +++ b/crypto/handshake.c @@ -681,33 +681,38 @@ static void append_dhe(struct TLSContext *ctx, struct tls_buffer *buf) { unsigned long dh_g_len = sizeof dh_g; unsigned long dh_Ys_len = sizeof dh_Ys; + ENTER; if (tls_dh_export_pqY(dh_p, &dh_p_len, dh_g, &dh_g_len, dh_Ys, &dh_Ys_len, ctx->dhe)) { DEBUG_PRINT("ERROR EXPORTING DHE KEY %p\n", ctx->dhe); buf->error = 1; tls_dhe_free(ctx); + LEAVE;; return; } + tls_buffer_append_byte(buf, 0x10); tls_dhe_free(ctx); DEBUG_DUMP_HEX_LABEL("Yc", dh_Ys, dh_Ys_len); tls_buffer_append24(buf, dh_Ys_len + 2); - tls_buffer_append16(buf, dh_Ys_len); tls_buffer_append(buf, dh_Ys, dh_Ys_len); + LEAVE; } static void append_ecdhe(struct TLSContext *ctx, struct tls_buffer *buf) { unsigned char out[TLS_MAX_RSA_KEY]; unsigned long out_len = TLS_MAX_RSA_KEY; - //fprintf(stderr, "ecc dhe\n"); + ENTER; if (ecc_ansi_x963_export(ctx->ecc_dhe, out, &out_len)) { DEBUG_PRINT("Error exporting ECC key\n"); buf->error = 1; + LEAVE;; + return; } tls_ecc_dhe_free(ctx); @@ -717,6 +722,7 @@ static void append_ecdhe(struct TLSContext *ctx, struct tls_buffer *buf) { tls_buffer_append_byte(buf, out_len); tls_buffer_append(buf, out, out_len); + LEAVE; } static void set_record_size(struct tls_buffer *b) { @@ -730,6 +736,7 @@ struct TLSPacket *tls_client_key_exchange(struct TLSContext *context) { struct tls_buffer cke; struct TLSPacket *p; + ENTER; tls_buffer_init(&cke, 42); tls_buffer_append_byte(&cke, 0x16); tls_buffer_append16(&cke, 0x0303); @@ -748,6 +755,7 @@ struct TLSPacket *tls_client_key_exchange(struct TLSContext *context) { context->connection_status = 2; tls_packet_update(p); + LEAVE; return p; } @@ -808,12 +816,14 @@ static int tls_build_random(struct TLSPacket *packet) { void tls_send_client_key_exchange(struct TLSContext *context) { struct TLSPacket *packet; + ENTER; int ephemeral = tls_cipher_is_ephemeral(context); if (ephemeral && context->premaster_key && context->premaster_key_len) { //fprintf(stderr, "YYYY\n"); packet = tls_client_key_exchange(context); tls_queue_packet(packet); + LEAVE; return; if (ephemeral == 1) { /* dhe */ @@ -824,6 +834,7 @@ void tls_send_client_key_exchange(struct TLSContext *context) { /* TODO should never happen, should always require * either DHE or ECC DHE */ fprintf(stderr, "ZZZZ build random\n"); + LEAVE; return; packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0); tls_packet_uint8(packet, 0x10); @@ -832,6 +843,7 @@ void tls_send_client_key_exchange(struct TLSContext *context) { context->connection_status = 2; tls_packet_update(packet); tls_queue_packet(packet); + LEAVE; return; } @@ -879,6 +891,7 @@ int tls_parse_server_hello(struct TLSContext *ctx, const unsigned char *buf, siz /* two bytes server version */ uint16_t server_ver = get16(buf+i); i+=2; + DEBUG_PRINTLN("server version = %04x\n", server_ver); if (server_ver != ctx->version) { /* TODO allow (or not) downgrade to v1.2 */ return TLS_UNEXPECTED_MESSAGE; @@ -908,9 +921,11 @@ int tls_parse_server_hello(struct TLSContext *ctx, const unsigned char *buf, siz /* two bytes cipher suite selected */ ctx->cipher = get16(buf+i); i+=2; + DEBUG_PRINTLN("server cipher = %04x\n", ctx->cipher); if (!tls_cipher_supported(ctx, ctx->cipher)) { ctx->cipher = 0; DEBUG_PRINT("NO CIPHER SUPPORTED\n"); + MARK; return TLS_NO_COMMON_CIPHER; } @@ -954,6 +969,7 @@ int tls_parse_server_hello(struct TLSContext *ctx, const unsigned char *buf, siz continue; } if (i+elen > len) { + MARK; return TLS_BROKEN_PACKET; } @@ -1006,7 +1022,7 @@ int tls_parse_server_hello(struct TLSContext *ctx, const unsigned char *buf, siz } /* if ctx->curve */ if (selected) { - fprintf(stderr, "SELECTED CURVE %s\n", + DEBUG_PRINTLN("SELECTED CURVE %s\n", ctx->curve->name); } case 0x0010: @@ -1047,6 +1063,7 @@ int tls_parse_server_hello(struct TLSContext *ctx, const unsigned char *buf, siz case 0xff01: /* renegotiation info */ //fprintf(stderr, "renegotiation info\n"); /* ignore, we don't support renegotiation */ + MARK; break; case 0x0033: /* key share */ /* TODO parse key share */ @@ -1054,6 +1071,7 @@ int tls_parse_server_hello(struct TLSContext *ctx, const unsigned char *buf, siz break; case 0x000b: /* signature algorithms */ + MARK; break; case 0x002b: /* supported versions */ /* should be two bytes of 0x00 0x02 @@ -1075,5 +1093,6 @@ int tls_parse_server_hello(struct TLSContext *ctx, const unsigned char *buf, siz } #endif + MARK; return 1; } diff --git a/crypto/parse_message.c b/crypto/parse_message.c index e4e7b15..8f72299 100644 --- a/crypto/parse_message.c +++ b/crypto/parse_message.c @@ -29,6 +29,18 @@ #define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) #endif +#ifdef DEBUG +static char *tls_alert_msg_name(int code) { + switch (code) { + case 0: return "close_notify"; break; + case 10: return "unexpected_message"; break; + case 20: return "bad_record_mac"; break; + default: break; + } + return "unknown alert"; +} +#endif + static uint16_t get16(const unsigned char *buf) { uint16_t res; @@ -293,14 +305,23 @@ static int decrypt_other(struct TLSContext *context, uint16_t length, int *buf, struct tls_buffer *pt_buffer) { int err; + ENTER; + tls_buffer_expand(pt_buffer, length); + DEBUG_PRINTLN("cbc_decrypt(%p, %p, %lu, %p)\n", + buf+header_size, pt_buffer->buffer, + (unsigned long)length, &context->crypto.ctx_remote.aes_remote); err = cbc_decrypt(buf+header_size, pt_buffer->buffer, length, &context->crypto.ctx_remote.aes_remote); if (err) { - DEBUG_PRINT("Decryption error %i\n", (int) err); + DEBUG_PRINTLN("Decryption error %d %s\n", err, + error_to_string(err)); + LEAVE; return TLS_BROKEN_PACKET; } + pt_buffer->len = length; unsigned char padding_byte = pt_buffer->buffer[length - 1]; unsigned char padding = padding_byte + 1; + DEBUG_PRINTLN("cbc padding byte = %d\n", (int)padding_byte); /* poodle check */ int padding_index = length - padding; @@ -309,9 +330,9 @@ static int decrypt_other(struct TLSContext *context, uint16_t length, int int limit = length - 1; for (i = length - padding; i < limit; i++) { if (pt_buffer->buffer[i] != padding_byte) { - DEBUG_PRINT - ("BROKEN PACKET (POODLE ?)\n"); + DEBUG_PRINTLN("BROKEN PACKET (POODLE ?)\n"); tls_alert(context, 1, decrypt_error); + LEAVE; return TLS_BROKEN_PACKET; } } @@ -323,23 +344,24 @@ static int decrypt_other(struct TLSContext *context, uint16_t length, int pt_buffer->len -= padding; } - DEBUG_DUMP_HEX_LABEL("decrypted3", pt_buffer->buffer, decrypted_length); - ptr = pt_buffer->buffer; + DEBUG_DUMP_HEX_LABEL("decrypted", pt_buffer->buffer, decrypted_length); if (decrypted_length > TLS_AES_IV_LENGTH) { decrypted_length -= TLS_AES_IV_LENGTH; - ptr += TLS_AES_IV_LENGTH; tls_buffer_shift(pt_buffer, TLS_AES_IV_LENGTH); } + ptr = pt_buffer->buffer; length = decrypted_length; unsigned int mac_size = tls_mac_length(context); if (length < mac_size || !mac_size) { - DEBUG_PRINT("BROKEN PACKET\n"); + DEBUG_PRINTLN("BROKEN PACKET\n"); tls_alert(context, 1, decrypt_error); + LEAVE; return TLS_BROKEN_PACKET; } + DEBUG_PRINTLN("mac size %u\n", mac_size); length -= mac_size; pt_buffer->len -= mac_size; @@ -352,16 +374,18 @@ static int decrypt_other(struct TLSContext *context, uint16_t length, int ptr, length, hmac_out, mac_size); if (hmac_out_len != mac_size || memcmp(message_hmac, hmac_out, mac_size)) { - DEBUG_PRINT("INTEGRITY CHECK FAILED (msg length %i)\n", + DEBUG_PRINTLN("INTEGRITY CHECK FAILED (msg length %i)\n", length); DEBUG_DUMP_HEX_LABEL("HMAC RECEIVED", message_hmac, mac_size); DEBUG_DUMP_HEX_LABEL("HMAC COMPUTED", hmac_out, hmac_out_len); tls_alert(context, 1, bad_record_mac); + LEAVE; return TLS_INTEGRITY_FAILED; } + LEAVE; return 0; } @@ -408,7 +432,10 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int header_size = res; + ENTER; + if (buf_len < res) { + LEAVE; return TLS_NEED_MORE_DATA; } @@ -418,6 +445,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, buf_pos += 2; if (!tls_supported_version(version)) { + LEAVE; return TLS_NOT_SAFE; } @@ -426,7 +454,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, ptr = buf + buf_pos; - DEBUG_PRINT("Message type: %0x, length: %i\n", (int)type, (int)length); + DEBUG_PRINTLN("Message type: %d, length: %d\n", (int)type, (int)length); /* this buffer can go out of scope */ tls_buffer_init(&pt, 0); @@ -438,6 +466,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, if (!context->crypto.created) { DEBUG_PRINT("Encryption context not created\n"); random_sleep(TLS_MAX_ERROR_SLEEP_uS); + LEAVE; return TLS_BROKEN_PACKET; } @@ -447,12 +476,14 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, if (rv != 0) { tls_buffer_free(&pt); random_sleep(TLS_MAX_ERROR_SLEEP_uS); + LEAVE; return rv; } if (pt.error) { tls_buffer_free(&pt); random_sleep(TLS_MAX_ERROR_SLEEP_uS); + LEAVE; return TLS_NO_MEMORY; } @@ -524,15 +555,14 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, break; /* alert */ case TLS_ALERT: - DEBUG_PRINT("ALERT MESSAGE\n"); + DEBUG_PRINTLN("ALERT MESSAGE\n"); if (length >= 2) { - DEBUG_PRINT("ALERT MESSAGE ...\n"); - DEBUG_DUMP_HEX(ptr, length); int level = ptr[0]; int code = ptr[1]; - DEBUG_PRINT("level = %d, code = %d\n", - level, code); + DEBUG_PRINTLN("level = %d, code = %d\n", level, code); if (level == TLS_ALERT_CRITICAL) { + DEBUG_PRINTLN("critical error: %s\n", + tls_alert_msg_name(code)); context->critical_error = 1; res = TLS_ERROR_ALERT; } @@ -551,12 +581,15 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, tls_buffer_free(&pt); if (payload_res < 0) { + LEAVE; return payload_res; } if (res > 0) { + LEAVE; return header_size + length; } + LEAVE; return res; } diff --git a/crypto/tlse.c b/crypto/tlse.c index 233fe26..a49b447 100644 --- a/crypto/tlse.c +++ b/crypto/tlse.c @@ -61,8 +61,12 @@ #define CHECK_HANDSHAKE_STATE(context, n, limit) { if (context->hs_messages[n] >= limit) { DEBUG_PRINT("* UNEXPECTED MESSAGE (%i)\n", (int)n); payload_res = TLS_UNEXPECTED_MESSAGE; break; } context->hs_messages[n]++; } -//#define MARK fprintf(stderr, "%s %s:%d\n", __FILE__, __func__, __LINE__) -#define MARK +#ifdef DEBUG +int tls_indent = 0; +int tls_indent_i = 0; +#endif + +//#define MARK typedef enum { KEA_dhe_dss, KEA_dhe_rsa, @@ -207,23 +211,65 @@ static uint32_t get24(const unsigned char *buf) { return res; } +#ifdef DEBUG +static char *packet_content_type(int type) { + switch (type) { + case 20: return "change_cipher_spec"; break; + case 21: return "alert"; break; + case 22: return "handshake"; break; + case 23: return "application_data"; break; + default: break; + } + return "unknown content type"; +} + +static char *packet_handshake_type(int type) { + switch (type) { + case 0: return "hello_request"; break; + case 1: return "client_hello"; break; + case 2: return "server_hello"; break; + case 11: return "certificate"; break; + case 12: return "server_key_exchange"; break; + case 13: return "certificate_request"; break; + case 14: return "server_hello_done"; break; + case 15: return "certificate_verify"; break; + case 16: return "client_key_exchange"; break; + case 20: return "finished"; break; + default: break; + } + return "unknown handshake type"; +} +#endif + size_t tls_queue_packet(struct TLSPacket *packet) { + ENTER; if (!packet) { + LEAVE; return -1; } struct TLSContext *context = packet->context; if (!context) { + LEAVE; return -1; } + DEBUG_PRINTLN("sending packet type %d %s\n", (int)packet->buf[0], + packet_content_type(packet->buf[0])); + if (packet->buf[0] == 22) { + DEBUG_PRINTLN("handshake type %d %s\n", (int)packet->buf[5], + packet_handshake_type(packet->buf[5]) + ); + } tls_buffer_append(&context->output_buffer, packet->buf, packet->len); tls_destroy_packet(packet); + LEAVE; return context->output_buffer.len; } static void tls_send_change_cipher_spec(struct TLSContext *context) { + ENTER; struct TLSPacket *packet = tls_create_packet(context, TLS_CHANGE_CIPHER, context->version, 64); @@ -231,6 +277,7 @@ static void tls_send_change_cipher_spec(struct TLSContext *context) { tls_packet_update(packet); context->local_sequence_number = 0; tls_queue_packet(packet); + LEAVE; return; } @@ -277,6 +324,7 @@ static void tls_send_certificate(struct TLSContext *context) { int certificates_count; struct TLSCertificate **certificates; + ENTER; if (context->is_server) { certificates_count = context->certificates_count; certificates = context->certificates; @@ -364,6 +412,7 @@ static void tls_send_certificate(struct TLSContext *context) { } tls_packet_update(packet); tls_queue_packet(packet); + LEAVE; return; } @@ -1237,10 +1286,11 @@ static void tls_prf(struct TLSContext *context, } static void tls_send_finished(struct TLSContext *context) { + ENTER; struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, TLS_MIN_FINISHED_OPAQUE_LEN + 64); - tls_packet_uint8(packet, 0x14); + tls_packet_uint8(packet, 20); if (context->tlsver == TLS_VERSION13) { tls_packet_uint24(packet, tls_mac_length(context)); @@ -1270,6 +1320,7 @@ static void tls_send_finished(struct TLSContext *context) { /* TODO probably need to terminate */ tls_destroy_packet(packet); + LEAVE; return; } @@ -1309,6 +1360,7 @@ static void tls_send_finished(struct TLSContext *context) { tls_packet_update(packet); DEBUG_DUMP_HEX_LABEL("VERIFY DATA", out, out_size); tls_queue_packet(packet); + LEAVE; return; } @@ -3330,6 +3382,7 @@ int tls_parse_certificate(struct TLSContext *context, res += certificate_size; } if (!valid_certificate) { + MARK; return TLS_UNSUPPORTED_CERTIFICATE; } if (res != buf_len) { @@ -3531,6 +3584,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, DEBUG_PRINT(" dh_q: "); dh_res = parse_dh(&buf[res], buf_len - res, &dh_g, &dh_g_len); if (dh_res <= 0) { + MARK; return TLS_BROKEN_PACKET; } res += dh_res; @@ -3540,6 +3594,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, dh_res = parse_dh(&buf[res], buf_len - res, &dh_Ys, &dh_Ys_len); if (dh_res <= 0) { + MARK; return TLS_BROKEN_PACKET; } res += dh_res; @@ -3702,6 +3757,7 @@ static int tls_parse_server_hello_done(const unsigned char *buf, int buf_len) { return TLS_NEED_MORE_DATA; } + MARK; res += size; return res; } @@ -3822,6 +3878,7 @@ int tls_parse_finished(struct TLSContext *context, // fprintf(stderr, "set conn status = %d\n", context->connection_status); + MARK; res += size; return res; } @@ -3949,6 +4006,7 @@ int tls_parse_verify(struct TLSContext *context, const unsigned char *buf, /* TODO This is actually a parse a handshake message */ int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int buf_len) { + ENTER; int orig_len = buf_len; @@ -4241,7 +4299,6 @@ int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, switch (write_packets) { case 1: if (context->client_verified == 2) { - DEBUG_PRINT("<= Building CERTIFICATE \n"); tls_send_certificate(context); context->client_verified = 0; } @@ -4342,6 +4399,7 @@ int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, buf += payload_size; buf_len -= payload_size; } + LEAVE; return orig_len; } @@ -5270,6 +5328,7 @@ int tls_consume_stream(struct TLSContext *context) { /* This is the only place tls_parse_message is called */ int consumed = tls_parse_message(context, buffer+index, length); if (consumed < 0) { + fprintf(stderr, "parse message error: %d\n", consumed); err_flag = consumed; break; } @@ -5602,6 +5661,7 @@ int tls_connect(struct TLSContext *context) { } MARK; if (tls_established(context)) { + MARK; return 1; } MARK; diff --git a/crypto/tlse.h b/crypto/tlse.h index 9645195..8c8e31e 100644 --- a/crypto/tlse.h +++ b/crypto/tlse.h @@ -54,15 +54,26 @@ #endif #ifdef DEBUG -#define DEBUG_PRINTLN(...) do { fprintf(stderr, "line %d: ", __LINE__); fprintf(stderr, __VA_ARGS__); } while (0) -#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) +extern int tls_indent; +extern int tls_indent_i; +#define INDENT do { for (tls_indent_i=0; tls_indent_i < tls_indent; tls_indent_i++) { fprintf(stderr, " "); } } while (0) -#define DEBUG_DUMP_HEX(buf, len) do {int _i_; for (_i_ = 0; _i_ < (int)len; _i_++) { DEBUG_PRINT("%02X ", (unsigned int)(buf)[_i_]); } } while (0) +#define MARKP do { INDENT; fprintf(stderr, "%s %s:%d ", __FILE__, __func__, __LINE__); } while (0) +#define MARK do { INDENT; fprintf(stderr, "%s %s:%d\n", __FILE__, __func__, __LINE__); } while (0) + +#define DEBUG_PRINTLN(...) do { MARKP; fprintf(stderr, __VA_ARGS__); } while (0) +#define DEBUG_PRINTI(...) do { INDENT; fprintf(stderr, __VA_ARGS__); } while (0) +#define DEBUG_PRINT(...) do { fprintf(stderr, __VA_ARGS__); } while (0) + +#define DEBUG_DUMP_HEX(buf, len) do {int _i_; for (_i_ = 0; _i_ < (int)len; _i_++) { DEBUG_PRINT("%02X ", (unsigned int)((unsigned char *)buf)[_i_]); } } while (0) #define DEBUG_INDEX(fields) print_index(fields) #define DEBUG_DUMP(buf, length) fwrite(buf, 1, length, stderr); #define DEBUG_DUMP_HEX_LABEL(title, buf, len) do {fprintf(stderr, "%s (%i): ", title, (int)len); DEBUG_DUMP_HEX(buf, len); fprintf(stderr, "\n");} while (0) + +#define ENTER do { MARKP; fprintf(stderr, "enter function\n"); tls_indent++; } while (0) +#define LEAVE do { tls_indent--; MARKP; fprintf(stderr, "leave function\n");} while (0) #else #define DEBUG_PRINTLN(...) #define DEBUG_PRINT(...) { } @@ -70,6 +81,9 @@ #define DEBUG_INDEX(fields) { } #define DEBUG_DUMP(buf, length) { } #define DEBUG_DUMP_HEX_LABEL(title, buf, len) { } +#define MARK +#define ENTER +#define LEAVE #endif #define TLS_WITH_CHACHA20_POLY1305 @@ -449,6 +463,11 @@ struct TLSContext { struct timespec sleep_until; unsigned short tls13_version; + +#ifdef DEBUG + int level; + uint32_t debug_flags; +#endif }; typedef int (*tls_validation_function)(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len);