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
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);
tls_buffer_append_byte(buf, out_len);
tls_buffer_append(buf, out, out_len);
+ LEAVE;
}
static void set_record_size(struct tls_buffer *b) {
struct tls_buffer cke;
struct TLSPacket *p;
+ ENTER;
tls_buffer_init(&cke, 42);
tls_buffer_append_byte(&cke, 0x16);
tls_buffer_append16(&cke, 0x0303);
context->connection_status = 2;
tls_packet_update(p);
+ LEAVE;
return p;
}
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 */
/* 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);
context->connection_status = 2;
tls_packet_update(packet);
tls_queue_packet(packet);
+ LEAVE;
return;
}
/* 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;
/* 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;
}
continue;
}
if (i+elen > len) {
+ MARK;
return TLS_BROKEN_PACKET;
}
}
/* if ctx->curve */
if (selected) {
- fprintf(stderr, "SELECTED CURVE %s\n",
+ DEBUG_PRINTLN("SELECTED CURVE %s\n",
ctx->curve->name);
}
case 0x0010:
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 */
break;
case 0x000b:
/* signature algorithms */
+ MARK;
break;
case 0x002b: /* supported versions */
/* should be two bytes of 0x00 0x02
}
#endif
+ MARK;
return 1;
}
#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;
*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;
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;
}
}
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;
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;
}
int header_size = res;
+ ENTER;
+
if (buf_len < res) {
+ LEAVE;
return TLS_NEED_MORE_DATA;
}
buf_pos += 2;
if (!tls_supported_version(version)) {
+ LEAVE;
return TLS_NOT_SAFE;
}
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);
if (!context->crypto.created) {
DEBUG_PRINT("Encryption context not created\n");
random_sleep(TLS_MAX_ERROR_SLEEP_uS);
+ LEAVE;
return TLS_BROKEN_PACKET;
}
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;
}
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;
}
tls_buffer_free(&pt);
if (payload_res < 0) {
+ LEAVE;
return payload_res;
}
if (res > 0) {
+ LEAVE;
return header_size + length;
}
+ LEAVE;
return res;
}
#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,
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);
tls_packet_update(packet);
context->local_sequence_number = 0;
tls_queue_packet(packet);
+ LEAVE;
return;
}
int certificates_count;
struct TLSCertificate **certificates;
+ ENTER;
if (context->is_server) {
certificates_count = context->certificates_count;
certificates = context->certificates;
}
tls_packet_update(packet);
tls_queue_packet(packet);
+ LEAVE;
return;
}
}
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));
/* TODO probably need to terminate */
tls_destroy_packet(packet);
+ LEAVE;
return;
}
tls_packet_update(packet);
DEBUG_DUMP_HEX_LABEL("VERIFY DATA", out, out_size);
tls_queue_packet(packet);
+ LEAVE;
return;
}
res += certificate_size;
}
if (!valid_certificate) {
+ MARK;
return TLS_UNSUPPORTED_CERTIFICATE;
}
if (res != buf_len) {
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;
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;
return TLS_NEED_MORE_DATA;
}
+ MARK;
res += size;
return res;
}
// fprintf(stderr, "set conn status = %d\n", context->connection_status);
+ MARK;
res += size;
return res;
}
/* 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;
switch (write_packets) {
case 1:
if (context->client_verified == 2) {
- DEBUG_PRINT("<= Building CERTIFICATE \n");
tls_send_certificate(context);
context->client_verified = 0;
}
buf += payload_size;
buf_len -= payload_size;
}
+ LEAVE;
return orig_len;
}
/* 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;
}
}
MARK;
if (tls_established(context)) {
+ MARK;
return 1;
}
MARK;
#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(...) { }
#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
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);