Browse Source

succesfully decrypting TLS FIN

cbocovic 9 years ago
parent
commit
3f17d5880f
2 changed files with 259 additions and 43 deletions
  1. 252 42
      server/flow.c
  2. 7 1
      server/flow.h

+ 252 - 42
server/flow.c

@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include "flow.h"
+#include <openssl/evp.h>
 #include <openssl/dh.h>
 #include <openssl/bn.h>
 #include <openssl/err.h>
@@ -45,6 +46,10 @@ flow *add_flow(flow newFlow) {
 	newFlow.in_encrypted = 0;
 	newFlow.out_encrypted = 0;
 	newFlow.packet_chain = NULL;
+	newFlow.finish_md_ctx = EVP_MD_CTX_create();
+	const EVP_MD *md = EVP_sha384();
+	EVP_DigestInit_ex(newFlow.finish_md_ctx, md, NULL);
+
 	*ptr = newFlow;
 
 	table->len ++;
@@ -105,15 +110,16 @@ int update_flow(flow *f) {
 		case HS:
 			p = record;
 			p += RECORD_HEADER_LEN;
-			handshake_hdr = (struct handshake_header*) p;
 
 			//int size_hs = HANDSHAKE_MESSAGE_LEN(handshake_hdr);
 			printf("Handshake Message:\n");
-			f->state = handshake_hdr->type;
 
 			if((incoming && f->in_encrypted) || (!incoming && f->out_encrypted)){
-				decrypt_fin(f, p);
+				decrypt_fin(f, p, record_len - RECORD_HEADER_LEN, incoming);
+				p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
 			}
+			handshake_hdr = (struct handshake_header*) p;
+			f->state = handshake_hdr->type;
 
 			/* Now see if there's anything extra to do */
 			switch(f->state){
@@ -121,18 +127,22 @@ int update_flow(flow *f) {
 				case TLS_CLNT_HELLO: 
 					/* Expecting server hello msg */
 					printf("Received client hello!\n");
+					//update_finish_hash(f, p);
 					break;
 				case TLS_SERV_HELLO:
 					extract_server_random(f, p);
+					//update_finish_hash(f, p);
 					printf("Received server hello!\n");
 					break;
 				case TLS_NEW_SESS:
 					printf("Received new session ticket!\n");
 					break;
 				case TLS_CERT:
+					//update_finish_hash(f, p);
 					printf("Received certificate!\n");
 					break;
 				case TLS_SRVR_KEYEX:
+					//update_finish_hash(f, p);
 					printf("Received server key exchange!\n");
 					/* Need to extract server params */
 					if(extract_parameters(f, p)){
@@ -143,22 +153,26 @@ int update_flow(flow *f) {
 					}
 					break;
 				case TLS_CERT_REQ:
+					//update_finish_hash(f, p);
 					printf("Received certificate request!\n");
 					break;
 				case TLS_SRVR_HELLO_DONE:
+					//update_finish_hash(f, p);
 					printf("Received server hello done!\n");
 					break;
 				case TLS_CERT_VERIFY:
+					//update_finish_hash(f, p);
 					printf("Received certificate verify!\n");
 					break;
 				case TLS_CLNT_KEYEX:
+					//update_finish_hash(f, p);
 					printf("Received client key exchange!\n");
 					break;
 				case TLS_FINISHED:
 					printf("Received finished message!\n");
 					break;
 				default:
-					printf("Error?\n");
+					printf("Error? %02x\n",p[0]);
 					break;
 			}
 			break;
@@ -172,6 +186,8 @@ int update_flow(flow *f) {
 			} else {
 				f->out_encrypted = 1;
 			}
+			/*Initialize ciphers */
+			init_ciphers(f);
 			break;
 		case ALERT:
 			printf("Alert\n");
@@ -339,6 +355,22 @@ int add_packet(flow *f, uint8_t *p){
 
 /** UTILITY **/
 
+int update_finish_hash(flow *f, uint8_t *hs){
+	EVP_MD_CTX *ctx = f->finish_md_ctx;
+	//find handshake length
+	const struct handshake_header *hs_hdr;
+	uint8_t *p = hs;
+	hs_hdr = (struct handshake_header*) p;
+	uint32_t hs_len = HANDSHAKE_MESSAGE_LEN(hs_hdr);
+	
+	/* Now compute SHA384(secret, A+seed)
+	 * can't sign update, don't have master secret yet*/
+	EVP_DigestUpdate(&ctx, hs, hs_len);
+
+	return 1;
+	
+}
+
 int extract_parameters(flow *f, uint8_t *hs){
 	DH *dh;
 	uint8_t *p;
@@ -353,11 +385,6 @@ int extract_parameters(flow *f, uint8_t *hs){
 	/* Extract prime modulus */
 	n2s(p,i);
 
-	printf("Server p:\n");
-	for(int j=0; j<i; j++){
-		printf("%02x ",p[j]);
-	}
-	printf("\n");
 	if(!(dh->p = BN_bin2bn(p,i,NULL))){
 		return 1;
 	}
@@ -366,11 +393,6 @@ int extract_parameters(flow *f, uint8_t *hs){
 	/* Extract generator */
 	n2s(p,i);
 
-	printf("Server g:\n");
-	for(int j=0; j<i; j++){
-		printf("%02x ",p[j]);
-	}
-	printf("\n");
 	if(!(dh->g = BN_bin2bn(p,i,NULL))){
 		return 1;
 	}
@@ -379,11 +401,6 @@ int extract_parameters(flow *f, uint8_t *hs){
 	/* Extract server public value */
 	n2s(p,i);
 
-	printf("Server pub_key:\n");
-	for(int j=0; j<i; j++){
-		printf("%02x ",p[j]);
-	}
-	printf("\n");
 	if(!(dh->pub_key = BN_bin2bn(p,i,NULL))){
 		return 1;
 	}
@@ -393,8 +410,95 @@ int extract_parameters(flow *f, uint8_t *hs){
 	return 0;
 }
 
-/* Decrypt the TLS FINISHED message */
-int decrypt_fin(flow *f, uint8_t *hs){
+/* Decrypt the TLS FINISHED message
+ * Verify that the data is:
+ * 	PRF(master_secret, finished_label, Hash(handshake_messages))*/
+int decrypt_fin(flow *f, uint8_t *hs, int32_t len, int32_t incoming){
+	//const struct handshake_header *hs_hdr;
+	uint8_t *p = hs;
+	//EVP_MD_CTX ctx;
+	//uint8_t hash[EVP_MAX_MD_SIZE];
+	//int32_t hash_len;
+
+	//EVP_MD_CTX_init(&ctx);
+
+	//decrypt
+	EVP_CIPHER_CTX *ds = (incoming) ? f->read_ctx : f->write_ctx;
+	if(ds == NULL){
+		printf("FAIL\n");
+		return 1;
+	}
+	if(ds->iv[EVP_GCM_TLS_FIXED_IV_LEN] == 0){
+		//fill in rest of iv
+		for(int i = EVP_GCM_TLS_FIXED_IV_LEN; i< ds->cipher->iv_len; i++){
+			ds->iv[i] = p[i- EVP_GCM_TLS_FIXED_IV_LEN];
+		}
+	}
+
+//#ifdef KSSL_DEBUG
+	{    
+		fprintf(stderr, "\t\tIV: ");
+		for (int i = 0; i < ds->cipher->iv_len; i++) 
+			fprintf(stderr, "%02X", ds->iv[i]);
+		fprintf(stderr, "\n");
+	}    
+//#endif                          /* KSSL_DEBUG */
+
+
+	int32_t bs = EVP_CIPHER_block_size(ds->cipher);
+	//padding stuff? TODO: understand this
+	uint8_t buf[13];
+	memset(buf, 0, 8);
+	buf[8] = 0x16;
+	buf[9] = 0x03;
+	buf[10] = 0x03;
+	buf[11] = 0x00; //len >> 8;
+	buf[12] = 0x28; //len *0xff;
+	printf("buf: \n");
+	for(int z=0; z< 13; z++){
+		printf("%02x ", buf[z]);
+	}
+	printf("\n");
+	int32_t pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
+			13, buf);
+	printf("pad: %d\n", pad);
+
+	printf("Decrypting (%d bytes):\n", len);
+	for(int i=0; i<len; i++){
+		printf("%02x ", p[i]);
+	}
+	printf("\n");
+
+	int32_t n = EVP_Cipher(ds, p, p, len); //decrypt in place
+
+	p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+	len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+	//print out decrypted record
+	printf("Record (decrypted %d/%d bytes): \n", n, len);
+	for(int i=0; i<n; i++){
+		printf("%02x ", p[i]);
+	}
+	printf("\n");
+
+	/*get context
+	
+	//get header length
+	hs_hdr = (struct handshake_header*) p;
+	uint32_t fin_length = HANDSHAKE_MESSAGE_LEN(hs_hdr);
+	p += HANDSHAKE_HEADER_LEN;
+
+	//finalize hash of handshake msgs
+	EVP_MD_CTX_copy_ex(&ctx, f->finish_md_ctx);
+	EVP_DigestFinal(&ctx, hash, &hash_len);
+
+	//now use pseudorandom function
+	uint8_t *output = calloc(1, fin_length);
+	PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, finished_label, finished_label_len, hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
+
+	//now compare
+	
+*/
+
 	return 1;
 }
 
@@ -445,26 +549,18 @@ int compute_master_secret(flow *f){
     dh_clnt->priv_key = priv_key;
 
 	// Compute master key 
-	uint8_t master_secret[SSL3_MASTER_SECRET_SIZE];
 	uint8_t *pre_master_secret = calloc(1, 256);//TODO: find right length
 
-	int32_t len = DH_compute_key(pre_master_secret, dh_srvr->pub_key, dh_clnt);
+	DH_compute_key(pre_master_secret, dh_srvr->pub_key, dh_clnt);
 	
-	printf("Output of compute key:\n");
-	for(int j=0; j<len; j++){
-		printf("%02x ", pre_master_secret[j]);
-	}
-	printf("\n");
-
-	PRF(pre_master_secret, f->client_random, f->server_random,
-			master_secret);
+	PRF(pre_master_secret, PRE_MASTER_LEN, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE, f->client_random, SSL3_RANDOM_SIZE, f->server_random, SSL3_RANDOM_SIZE, NULL, 0, f->master_secret, SSL3_MASTER_SECRET_SIZE);
 
 	//remove pre_master_secret from memory
 	memset(pre_master_secret, 0, PRE_MASTER_LEN);
 
 	printf("master secret:\n");
 	for(int i=0; i< 48; i++){
-		printf("%02x ", master_secret[i]);
+		printf("%02x ", f->master_secret[i]);
 	}
 	printf("\n");
 	
@@ -488,7 +584,12 @@ void extract_server_random(flow *f, uint8_t *hs){
 }
 
 /* PRF using sha384, as defined in RFC 5246 */
-int PRF(uint8_t *secret, uint8_t *client_random, uint8_t *server_random, uint8_t *output){
+int PRF(uint8_t *secret, int32_t secret_len,
+		uint8_t *seed1, int32_t seed1_len,
+		uint8_t *seed2, int32_t seed2_len,
+		uint8_t *seed3, int32_t seed3_len,
+		uint8_t *seed4, int32_t seed4_len,
+		uint8_t *output, int32_t output_len){
 
 	EVP_MD_CTX ctx, ctx_tmp, ctx_init;
 	EVP_PKEY *mac_key;
@@ -497,7 +598,7 @@ int PRF(uint8_t *secret, uint8_t *client_random, uint8_t *server_random, uint8_t
 	uint8_t A[EVP_MAX_MD_SIZE];
 	size_t len, A_len;
 	int chunk = EVP_MD_size(md);
-	int remaining = SSL_MAX_MASTER_KEY_LENGTH;
+	int remaining = output_len;
 
 	uint8_t *out = output;
 
@@ -506,25 +607,43 @@ int PRF(uint8_t *secret, uint8_t *client_random, uint8_t *server_random, uint8_t
 	EVP_MD_CTX_init(&ctx_init);
 	EVP_MD_CTX_set_flags(&ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 
-	mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, secret, PRE_MASTER_LEN);
+	mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, secret, secret_len);
 
 	/* Calculate first A value */
 	EVP_DigestSignInit(&ctx_init, NULL, md, NULL, mac_key);
 	EVP_MD_CTX_copy_ex(&ctx, &ctx_init);
-	EVP_DigestSignUpdate(&ctx, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE);
-	EVP_DigestSignUpdate(&ctx, client_random, SSL3_RANDOM_SIZE);
-	EVP_DigestSignUpdate(&ctx, server_random, SSL3_RANDOM_SIZE);
+	if(seed1 != NULL && seed1_len > 0){
+		EVP_DigestSignUpdate(&ctx, seed1, seed1_len);
+	}
+	if(seed2 != NULL && seed2_len > 0){
+		EVP_DigestSignUpdate(&ctx, seed2, seed2_len);
+	}
+	if(seed3 != NULL && seed3_len > 0){
+		EVP_DigestSignUpdate(&ctx, seed3, seed3_len);
+	}
+	if(seed4 != NULL && seed4_len > 0){
+		EVP_DigestSignUpdate(&ctx, seed4, seed4_len);
+	}
 	EVP_DigestSignFinal(&ctx, A, &A_len);
 
 	//iterate until desired length is achieved
 	while(remaining > 0){
-		/* Now compute SHA384(secret, A) */
+		/* Now compute SHA384(secret, A+seed) */
 		EVP_MD_CTX_copy_ex(&ctx, &ctx_init);
 		EVP_DigestSignUpdate(&ctx, A, A_len);
 		EVP_MD_CTX_copy_ex(&ctx_tmp, &ctx);
-		EVP_DigestSignUpdate(&ctx, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE);
-		EVP_DigestSignUpdate(&ctx, client_random, SSL3_RANDOM_SIZE);
-		EVP_DigestSignUpdate(&ctx, server_random, SSL3_RANDOM_SIZE);
+		if(seed1 != NULL && seed1_len > 0){
+			EVP_DigestSignUpdate(&ctx, seed1, seed1_len);
+		}
+		if(seed2 != NULL && seed2_len > 0){
+			EVP_DigestSignUpdate(&ctx, seed2, seed2_len);
+		}
+		if(seed3 != NULL && seed3_len > 0){
+			EVP_DigestSignUpdate(&ctx, seed3, seed3_len);
+		}
+		if(seed4 != NULL && seed4_len > 0){
+			EVP_DigestSignUpdate(&ctx, seed4, seed4_len);
+		}
 		
 		if(remaining > chunk){
 			EVP_DigestSignFinal(&ctx, out, &len);
@@ -542,3 +661,94 @@ int PRF(uint8_t *secret, uint8_t *client_random, uint8_t *server_random, uint8_t
 	return 1;
 }
 
+/* After receiving change cipher spec, calculate keys from master secret */
+int init_ciphers(flow *f){
+
+	EVP_CIPHER_CTX *r_ctx;
+	EVP_CIPHER_CTX *w_ctx;
+	const EVP_CIPHER *c = EVP_aes_256_gcm();
+
+	/* Generate Keys */
+	uint8_t *write_mac, *write_key, *write_iv;
+	uint8_t *read_mac, *read_key, *read_iv;
+	int32_t mac_len, key_len, iv_len;
+
+	key_len = EVP_CIPHER_key_length(c);
+	iv_len = EVP_CIPHER_iv_length(c); //EVP_GCM_TLS_FIXED_IV_LEN;
+	mac_len = EVP_MD_size(EVP_get_digestbyname(SN_sha384));
+	int32_t total_len = key_len + iv_len + mac_len;
+	total_len *= 2;
+	uint8_t *key_block = calloc(1, total_len);
+
+	PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE,
+			TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+			f->server_random, SSL3_RANDOM_SIZE,
+			f->client_random, SSL3_RANDOM_SIZE,
+			NULL, 0,
+			key_block, total_len);
+
+	printf("keyblock:\n");
+	for(int i=0; i< total_len; i++){
+		printf("%02x ", key_block[i]);
+	}
+	printf("\n");
+
+	iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
+	
+	write_key = key_block;
+	read_key = key_block + key_len;
+	write_iv = key_block + 2*key_len;
+	read_iv = key_block + 2*key_len + iv_len;
+	write_mac = key_block + 2*key_len + 2*iv_len;
+	read_mac = key_block + 2*key_len + 2*iv_len + mac_len;
+
+	/* Initialize Cipher Contexts */
+	r_ctx = EVP_CIPHER_CTX_new();
+	w_ctx = EVP_CIPHER_CTX_new();
+	EVP_CIPHER_CTX_init(r_ctx);
+	EVP_CIPHER_CTX_init(w_ctx);
+
+//#ifdef KSSL_DEBUG
+    {
+        int i;
+        fprintf(stderr, "EVP_CipherInit_ex(r_ctx,c,key=,iv=,which)\n");
+        fprintf(stderr, "\tkey= ");
+        for (i = 0; i < c->key_len; i++)
+            fprintf(stderr, "%02x", read_key[i]);
+        fprintf(stderr, "\n");
+        fprintf(stderr, "\t iv= ");
+        for (i = 0; i < c->iv_len; i++)
+            fprintf(stderr, "%02x", read_iv[i]);
+        fprintf(stderr, "\n");
+    }
+//#endif                          /* KSSL_DEBUG_*/
+    {
+        int i;
+        fprintf(stderr, "EVP_CipherInit_ex(w_ctx,c,key=,iv=,which)\n");
+        fprintf(stderr, "\tkey= ");
+        for (i = 0; i < c->key_len; i++)
+            fprintf(stderr, "%02x", write_key[i]);
+        fprintf(stderr, "\n");
+        fprintf(stderr, "\t iv= ");
+        for (i = 0; i < c->iv_len; i++)
+            fprintf(stderr, "%02x", write_iv[i]);
+        fprintf(stderr, "\n");
+    }
+//#endif                          /* KSSL_DEBUG */
+
+
+	EVP_CipherInit_ex(r_ctx, c, NULL, read_key, NULL, 0);
+	EVP_CipherInit_ex(w_ctx, c, NULL, write_key, NULL, 0);
+	EVP_CIPHER_CTX_ctrl(r_ctx, EVP_CTRL_GCM_SET_IV_FIXED, EVP_GCM_TLS_FIXED_IV_LEN, read_iv);
+	EVP_CIPHER_CTX_ctrl(w_ctx, EVP_CTRL_GCM_SET_IV_FIXED, EVP_GCM_TLS_FIXED_IV_LEN, write_iv);
+	fprintf(stderr, "\t\tIV: ");
+	for (int i = 0; i < r_ctx->cipher->iv_len; i++) 
+		fprintf(stderr, "%02X", r_ctx->iv[i]);
+	fprintf(stderr, "\n");
+		fprintf(stderr, "\t\tIV: ");
+		for (int i = 0; i < w_ctx->cipher->iv_len; i++) 
+			fprintf(stderr, "%02X", w_ctx->iv[i]);
+		fprintf(stderr, "\n");
+	f->read_ctx = r_ctx;
+	f->write_ctx = w_ctx;
+}

+ 7 - 1
server/flow.h

@@ -47,8 +47,14 @@ typedef struct flow_st {
 	packet *packet_chain; /* currently held data */
 	DH *dh;
 
+	uint8_t handshake_hash[EVP_MAX_MD_SIZE];
+	EVP_MD_CTX *finish_md_ctx;
+	EVP_CIPHER_CTX *read_ctx;
+	EVP_CIPHER_CTX *write_ctx;
+
 	uint8_t client_random[SSL3_RANDOM_SIZE];
 	uint8_t server_random[SSL3_RANDOM_SIZE];
+	uint8_t master_secret[SSL3_MASTER_SECRET_SIZE];
 
 } flow;
 
@@ -69,7 +75,7 @@ flow *get_flow(int index);
 int add_packet(flow *f, uint8_t *data);
 
 int extract_parameters(flow *f, uint8_t *hs);
-int decrypt_fin(flow *f, uint8_t *hs);
+int decrypt_fin(flow *f, uint8_t *hs, int32_t len, int32_t incoming);
 void extract_server_random(flow *f, uint8_t *hs);
 int compute_master_secret(flow *f);
 #endif /* __RELAY_H__ */