]> pd.if.org Git - zpackage/commitdiff
fix bug with dhe cbc mode
authorNathan Wagner <nw@hydaspes.if.org>
Sun, 17 Feb 2019 20:46:20 +0000 (20:46 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Sun, 17 Feb 2019 20:46:20 +0000 (20:46 +0000)
Makefile
crypto/handshake.c
crypto/parse_message.c
crypto/tlse.c
crypto/tlse.h

index 480ca112117d4f4b3f9a5ed9ee7203de89cca962..4de8408d8edbc2d3f0f259a22894f4ff46f9654e 100644 (file)
--- 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
index ed81920629e6f6287c191cb40cd1f19a929b85ea..264ecb93e26f2fad478e84bb9886c6e49f938bcf 100644 (file)
@@ -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;
 }
index e4e7b15ef95a61bd56c4a36169c229c05becba66..8f722992343cd9352b12f8b1696e3623789e3ab5 100644 (file)
 #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;
 }
index 233fe26d9c410e04a9771f888b2b2443c41b9cc0..a49b447101f59c9bfbbd42bdc5246bbcf9eac515 100644 (file)
 
 #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;
index 9645195c92621a6f918734384175e21b99bb3796..8c8e31eaa90b4dee26eef0457d6e9c2db122671c 100644 (file)
 #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);