#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]++; }
+#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;
}
(int) TLS_MAX_KEY_EXPANSION_SIZE);
DEBUG_DUMP_HEX_LABEL("CLIENT KEY", clientkey, key_length);
DEBUG_DUMP_HEX_LABEL("CLIENT IV", clientiv, iv_length);
+#if 0
DEBUG_DUMP_HEX_LABEL("CLIENT MAC KEY",
context->is_server ? context->crypto.
ctx_remote_mac.remote_mac : context->
crypto.ctx_local_mac.local_mac,
mac_length);
+#endif
DEBUG_DUMP_HEX_LABEL("SERVER KEY", serverkey, key_length);
DEBUG_DUMP_HEX_LABEL("SERVER IV", serveriv, iv_length);
+#if 0
DEBUG_DUMP_HEX_LABEL("SERVER MAC KEY",
context->is_server ? context->crypto.
ctx_local_mac.local_mac : context->crypto.
ctx_remote_mac.remote_mac, mac_length);
+#endif
if (context->is_server) {
if (is_aead == 2) {
memcpy(context->crypto.ctx_remote_mac.remote_nonce,
}
int tls_established(struct TLSContext *context) {
- if (context) {
- if (context->critical_error) {
- return -1;
- }
-
- if (context->connection_status == TLS_CONNECTED) {
- return 1;
- }
- }
- return 0;
+ return context && context->connection_status == TLS_CONNECTED;
}
void tls_read_clear(struct TLSContext *context) {
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;
}
if (certificate_verify_alert != no_error) {
+ MARK;
tls_alert(context, 1, certificate_verify_alert);
context->critical_error = 1;
}
if (payload_res < 0) {
switch (payload_res) {
case TLS_UNEXPECTED_MESSAGE:
+ MARK;
tls_alert(context, 1, unexpected_message);
break;
case TLS_COMPRESSION_NOT_SUPPORTED:
+ MARK;
tls_alert(context, 1, decompression_failure_RESERVED);
break;
case TLS_BROKEN_PACKET:
+ MARK;
tls_alert(context, 1, decode_error);
break;
case TLS_NO_MEMORY:
+ MARK;
tls_alert(context, 1, internal_error);
break;
case TLS_NOT_VERIFIED:
+ MARK;
tls_alert(context, 1, bad_record_mac);
break;
case TLS_BAD_CERTIFICATE:
+ MARK;
if (context->is_server) {
/* bad client certificate, continue */
tls_alert(context, 0, bad_certificate);
}
break;
case TLS_UNSUPPORTED_CERTIFICATE:
+ MARK;
tls_alert(context, 1, unsupported_certificate);
break;
case TLS_NO_COMMON_CIPHER:
+ MARK;
tls_alert(context, 1, insufficient_security);
break;
case TLS_NOT_UNDERSTOOD:
+ MARK;
tls_alert(context, 1, internal_error);
break;
case TLS_NO_RENEGOTIATION:
+ MARK;
tls_alert(context, 0, no_renegotiation_RESERVED);
payload_res = 0;
break;
case TLS_DECRYPTION_FAILED:
+ MARK;
tls_alert(context, 1, decryption_failed_RESERVED);
break;
}
if (certificate_verify_alert != no_error) {
payload_res = TLS_BAD_CERTIFICATE;
+ /* TODO this is set but not used */
}
/* except renegotiation */
switch (write_packets) {
case 1:
if (context->client_verified == 2) {
- DEBUG_PRINT("<= Building CERTIFICATE \n");
tls_send_certificate(context);
context->client_verified = 0;
}
}
tls_send_certificate(context);
-
tls_send_certificate_verify(context);
-
tls_send_finished(context);
/* new key */
buf += payload_size;
buf_len -= payload_size;
}
+ LEAVE;
return orig_len;
}
pos += length;
}
+ if (cert_len && cert_data) {
+ int h = find_hash("sha256");
+ size_t len = sizeof cert->fp;
+ hash_memory(h, cert_data,cert_len, cert->fp, &len);
+ }
+
if (level == 2 && cert->sign_key && cert->sign_len
&& cert_len && cert_data) {
free(cert->fingerprint);
/* 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;
}
int res;
ssize_t read_size;
- if (!context || context->fd <= 0 || context->critical_error) {
+ MARK;
+ if (!context || context->fd < 0 || context->critical_error) {
+ if (!context) {
+ MARK;
+ } else if (context->fd < 0) {
+ MARK;
+ } else {
+ MARK;
+ }
+
return TLS_GENERIC_ERROR;
}
+ MARK;
if (context->is_server) {
return TLS_UNEXPECTED_MESSAGE;
}
+ MARK;
res = tls_queue_packet(tls_build_client_hello(context));
+ MARK;
if (res < 0) {
return res;
}
+ MARK;
res = tls_fsync(context);
+ MARK;
if (res < 0) {
return res;
}
return res;
}
}
+ MARK;
if (tls_established(context)) {
+ MARK;
return 1;
}
+ MARK;
if (context->critical_error) {
+ fprintf(stderr, "critical error: %d\n",
+ context->critical_error);
return TLS_GENERIC_ERROR;
}
}
+ MARK;
return read_size;
}
return TLS_GENERIC_ERROR;
}
- if (tls_established(context) != 1) {
+ if (!tls_established(context)) {
return TLS_GENERIC_ERROR;
}