From e69d78c0385525a8e77002bebf47c4dcceaee1f4 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Tue, 17 Jan 2017 17:24:11 +0100
Subject: tls: process CHANGE_CIPHER_SPEC and FINISHED from server

Successfully finishes handshake with test servers using NULL-SHA256
cipher.

The "only" thing remaining before there is a chance
this can actually work with real servers is AES encrypt/decrypt.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 networking/tls.c | 60 ++++++++++++++++++++++++++++++--------------------------
 1 file changed, 32 insertions(+), 28 deletions(-)

diff --git a/networking/tls.c b/networking/tls.c
index 81820e9a1..3df2015a0 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -163,6 +163,7 @@ typedef struct tls_state {
 	uint8_t master_secret[48];
 
 	uint8_t encrypt_on_write;
+	uint8_t decrypt_on_read;
 	uint8_t client_write_MAC_key[SHA256_OUTSIZE];
 // RFC 5246
 // sequence number
@@ -1044,15 +1045,16 @@ static void send_client_key_exchange(tls_state_t *tls)
 	}
 }
 
+static const uint8_t rec_CHANGE_CIPHER_SPEC[] = {
+	RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01,
+	01
+};
+
 static void send_change_cipher_spec(tls_state_t *tls)
 {
-	static const uint8_t rec[] = {
-		RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01,
-		01
-	};
 	/* Not "xwrite_and_hash": this is not a handshake message */
 	dbg(">> CHANGE_CIPHER_SPEC\n");
-	xwrite(tls->fd, rec, sizeof(rec));
+	xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC));
 
 	/* tls->write_seq64_be = 0; - already is */
 	tls->encrypt_on_write = 1;
@@ -1138,16 +1140,6 @@ static void send_client_finished(tls_state_t *tls)
 	xwrite_and_hash(tls, &record, sizeof(record));
 }
 
-static void get_change_cipher_spec(tls_state_t *tls)
-{
-	tls->fd = 0;
-}
-
-static void get_server_finished(tls_state_t *tls)
-{
-	tls->fd = 0;
-}
-
 static void tls_handshake(tls_state_t *tls)
 {
 	// Client              RFC 5246                Server
@@ -1205,20 +1197,32 @@ static void tls_handshake(tls_state_t *tls)
 // (i.e. the same format as server certs)
 //		xread_tls_handshake_block(tls, 4);
 //	}
-	if (tls->inbuf[5] == HANDSHAKE_SERVER_HELLO_DONE) {
-		// 0e 000000 (len:0)
-		dbg("got SERVER_HELLO_DONE\n");
-		send_client_key_exchange(tls);
-		send_change_cipher_spec(tls);
-//we now should be able to send encrypted... as soon as we grok AES.
-		send_client_finished(tls);
-
-		get_change_cipher_spec(tls);
-		get_server_finished(tls);
-//we now should receive encrypted, and application data can be sent/received
-	} else {
+	if (tls->inbuf[5] != HANDSHAKE_SERVER_HELLO_DONE)
 		tls_error_die(tls);
-	}
+	// 0e 000000 (len:0)
+	dbg("got SERVER_HELLO_DONE\n");
+
+	send_client_key_exchange(tls);
+
+	send_change_cipher_spec(tls);
+	/* we now should send encrypted... as soon as we grok AES. */
+
+	send_client_finished(tls);
+
+	/* Get CHANGE_CIPHER_SPEC */
+	len = xread_tls_block(tls);
+	if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0)
+		tls_error_die(tls);
+	dbg("got CHANGE_CIPHER_SPEC\n");
+	tls->decrypt_on_read = 1;
+	/* we now should receive encrypted */
+
+	/* Get (encrypted) FINISHED from the server */
+	len = xread_tls_block(tls);
+	if (len < 4 || tls->inbuf[5] != HANDSHAKE_FINISHED)
+		tls_error_die(tls);
+	dbg("got FINISHED\n");
+	/* application data can be sent/received */
 }
 
 // To run a test server using openssl:
-- 
cgit v1.2.3