Browse Source

restructured files

cbocovic 9 years ago
parent
commit
0e40bc2cb3
6 changed files with 481 additions and 460 deletions
  1. 2 2
      server/Makefile
  2. 406 0
      server/crypto.c
  3. 15 0
      server/crypto.h
  4. 25 411
      server/flow.c
  5. 4 7
      server/flow.h
  6. 29 40
      server/slitheen-proxy.c

+ 2 - 2
server/Makefile

@@ -4,12 +4,12 @@ TARGETS=slitheen-proxy
 
 all: $(TARGETS)
 
-slitheen-proxy.o flow.o rserv.o ptwist168.o util.o:: ptwist.h rserv.h flow.h slitheen.h util.h
+slitheen-proxy.o flow.o rserv.o ptwist168.o util.o crypto.o:: ptwist.h rserv.h flow.h slitheen.h util.h crypto.h
 
 rserv: rserv.o ptwist168.o
 	gcc -g -o $@ $^ -lssl -lcrypto
 
-slitheen-proxy: slitheen-proxy.o flow.o rserv.o ptwist168.o util.o util.h ptwist.h rserv.h flow.h slitheen.h
+slitheen-proxy: slitheen-proxy.o flow.o rserv.o ptwist168.o util.o crypto.o crypto.h util.h ptwist.h rserv.h flow.h slitheen.h
 	gcc -g -o $@ $^ -I/home/slitheen/Documents/include/openssl libssl.a libcrypto.a -lpcap -lpthread -ldl
 
 clean:

+ 406 - 0
server/crypto.c

@@ -0,0 +1,406 @@
+#include <openssl/evp.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+#include "crypto.h"
+#include "flow.h"
+#include "slitheen.h"
+
+int update_finish_hash(flow *f, uint8_t *hs){
+	//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);
+	
+	EVP_DigestUpdate(f->finish_md_ctx, hs, hs_len+4);
+
+	return 1;
+	
+}
+
+int extract_parameters(flow *f, uint8_t *hs){
+	DH *dh;
+	uint8_t *p;
+	long i;
+
+	p = hs + HANDSHAKE_HEADER_LEN;
+
+	if((dh = DH_new()) == NULL){
+		return 1;
+	}
+
+	/* Extract prime modulus */
+	n2s(p,i);
+
+	if(!(dh->p = BN_bin2bn(p,i,NULL))){
+		return 1;
+	}
+	p += i;
+
+	/* Extract generator */
+	n2s(p,i);
+
+	if(!(dh->g = BN_bin2bn(p,i,NULL))){
+		return 1;
+	}
+	p += i;
+
+	/* Extract server public value */
+	n2s(p,i);
+
+	if(!(dh->pub_key = BN_bin2bn(p,i,NULL))){
+		return 1;
+	}
+
+	f->dh = dh;
+	return 0;
+}
+
+/* Decrypt the TLS FINISHED message
+ * Verify that the data is:
+ * 	PRF(master_secret, finished_label, Hash(handshake_messages))*/
+int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incoming, int32_t type){
+	uint8_t *p = input;
+	
+	EVP_CIPHER_CTX *ds = (incoming) ? f->read_ctx : f->write_ctx;
+	if(ds == NULL){
+		printf("FAIL\n");
+		return 1;
+	}
+	uint8_t *seq = (incoming) ? f->read_seq : f->write_seq;
+
+	if(f->application && (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];
+		}
+	}
+
+//	printf("\t\tiv: ");
+//	for(int i=0; i<ds->cipher->iv_len; i++){
+//		printf("%02X ", ds->iv[i]);
+//	}
+//	printf("\n");
+
+	int32_t bs = EVP_CIPHER_block_size(ds->cipher);
+	//padding stuff? TODO: understand this
+	uint8_t buf[13];
+	memcpy(buf, seq, 8);
+	for(int i=7; i>=0; i--){
+		++seq[i];
+		if(seq[i] != 0)
+			break;
+	}
+	buf[8] = type;
+	buf[9] = 0x03;
+	buf[10] = 0x03;
+	buf[11] = len >> 8; //len >> 8;
+	buf[12] = len & 0xff;//len *0xff;
+	int32_t pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
+			13, buf);
+	//printf("buf: ");
+	//for(int i=0; i<13; i++){
+//		printf("%02x ", buf[i]);
+//	}
+//	printf("\n");
+
+/*	printf("Decrypting: ");
+	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
+	if(n<0) return 0;
+/*	printf("Decrypted: ");
+	for(int i=0; i<n; i++){
+		printf("%02x ", p[i]);
+	}
+	printf("\n");
+	printf("decrypted %d/%d bytes.\n", n, len);*/
+	p[EVP_GCM_TLS_EXPLICIT_IV_LEN+n] = '\0';
+
+	return 1;
+}
+
+int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
+	EVP_MD_CTX ctx;
+	uint8_t hash[EVP_MAX_MD_SIZE];
+	int32_t hash_len;
+
+	EVP_MD_CTX_init(&ctx);
+	
+	//get header length
+	struct handshake_header *hs_hdr;
+	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_ex(&ctx, hash, &hash_len);
+
+	//now use pseudorandom function
+	uint8_t *output = calloc(1, fin_length);
+	if(incoming){
+		PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
+	} else {
+		PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
+	}
+
+	//now compare
+	if(CRYPTO_memcmp(p, output, fin_length) != 0){
+		printf("VERIFY FAILED\n");
+		return 0;
+	} else {
+		printf("VERIFY PASSED\n");
+	}
+
+	return 1;
+}
+
+int compute_master_secret(flow *f){
+	DH *dh_srvr = NULL;
+	DH *dh_clnt = NULL;
+	BN_CTX *ctx;
+	BN_MONT_CTX *mont = NULL;
+	BIGNUM *pub_key = NULL, *priv_key = NULL;
+
+	ctx = BN_CTX_new();
+
+	dh_srvr = f->dh;
+	dh_clnt = DHparams_dup(dh_srvr);
+
+    uint32_t l = dh_clnt->length ? dh_clnt->length : BN_num_bits(dh_clnt->p) - 1;
+    int32_t bytes = (l+7) / 8;
+
+    uint8_t *buf = (uint8_t *)OPENSSL_malloc(bytes);
+    if (buf == NULL){
+        BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE);
+        return 1;
+    }
+
+	pub_key = BN_new();
+	priv_key = BN_new();
+
+	for(int i=0; i<bytes; i++){
+		buf[i] = f->key[i%16];
+	}
+
+    if (!BN_bin2bn(buf, bytes, priv_key))
+		return 1;
+
+    {
+        BIGNUM *prk;
+
+		prk = priv_key;
+
+        if (!dh_clnt->meth->bn_mod_exp(dh_clnt, pub_key, dh_clnt->g, prk, dh_clnt->p, ctx, mont)){
+			printf("FAIL\n");
+            return 1;
+		}
+    }
+
+    dh_clnt->pub_key = pub_key;
+    dh_clnt->priv_key = priv_key;
+
+	// Compute master key 
+	uint8_t *pre_master_secret = calloc(1, 256);//TODO: find right length
+
+	DH_compute_key(pre_master_secret, dh_srvr->pub_key, dh_clnt);
+	
+	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 ", f->master_secret[i]);
+	}
+	printf("\n");*/
+	
+	free(pre_master_secret);
+	DH_free(dh_srvr);
+	DH_free(dh_clnt);
+	return 0;
+}
+
+void extract_server_random(flow *f, uint8_t *hs){
+
+	uint8_t *p;
+
+	p = hs + HANDSHAKE_HEADER_LEN;
+
+	p+=2; //skip version
+
+	memcpy(f->server_random, p, SSL3_RANDOM_SIZE);
+
+}
+
+/* PRF using sha384, as defined in RFC 5246 */
+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;
+	const EVP_MD *md = EVP_sha384();
+
+	uint8_t A[EVP_MAX_MD_SIZE];
+	size_t len, A_len;
+	int chunk = EVP_MD_size(md);
+	int remaining = output_len;
+
+	uint8_t *out = output;
+
+	EVP_MD_CTX_init(&ctx);
+	EVP_MD_CTX_init(&ctx_tmp);
+	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, secret_len);
+
+	/* Calculate first A value */
+	EVP_DigestSignInit(&ctx_init, NULL, md, NULL, mac_key);
+	EVP_MD_CTX_copy_ex(&ctx, &ctx_init);
+	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+seed) */
+		EVP_MD_CTX_copy_ex(&ctx, &ctx_init);
+		EVP_DigestSignUpdate(&ctx, A, A_len);
+		EVP_MD_CTX_copy_ex(&ctx_tmp, &ctx);
+		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);
+			out += len;
+			remaining -= len;
+
+			/* Next A value */
+			EVP_DigestSignFinal(&ctx_tmp, A, &A_len);
+		} else {
+			EVP_DigestSignFinal(&ctx, A, &A_len);
+			memcpy(out, A, remaining);
+			remaining -= remaining;
+		}
+	}
+	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);
+
+	f->read_ctx = r_ctx;
+	f->write_ctx = w_ctx;
+
+	return 0;
+}

+ 15 - 0
server/crypto.h

@@ -0,0 +1,15 @@
+#ifndef _CRYPTO_H_
+#define _CRYPTO_H_
+#include "flow.h"
+
+# define n2s(c,s)        ((s=(((unsigned int)(c[0]))<< 8)| \
+							(((unsigned int)(c[1]))    )),c+=2)
+
+int extract_parameters(flow *f, uint8_t *hs);
+int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incoming, int32_t type);
+void extract_server_random(flow *f, uint8_t *hs);
+int compute_master_secret(flow *f);
+
+#define PRE_MASTER_LEN 256
+
+#endif /* _CRYPTO_H_ */

+ 25 - 411
server/flow.c

@@ -1,17 +1,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <pthread.h>
+#include <errno.h>
 #include "flow.h"
-#include <openssl/evp.h>
-#include <openssl/dh.h>
-#include <openssl/bn.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
-#include <openssl/ssl.h>
+#include "crypto.h"
 #include "slitheen.h"
 
-#define PRE_MASTER_LEN 256
-
 static flow_table *table;
 
 /* Initialize the table of tagged flows */
@@ -45,11 +40,14 @@ flow *add_flow(flow newFlow) {
 	newFlow.state = TLS_CLNT_HELLO;
 	newFlow.in_encrypted = 0;
 	newFlow.out_encrypted = 0;
+	newFlow.application = 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);
 
+	memset(newFlow.read_seq, 0, 8);
+	memset(newFlow.write_seq, 0, 8);
 	*ptr = newFlow;
 
 	table->len ++;
@@ -69,7 +67,6 @@ int update_flow(flow *f) {
 	int record_len;
 	int data_len;
 
-
 	//printf("record version(major): %d.\n", (record_hdr->version&0xFF00)>>8);
 	//printf("record version(minor): %d.\n", record_hdr->version&0xFF);
 	//printf("record length: %d.\n", RECORD_LEN(record_hdr));
@@ -115,8 +112,10 @@ int update_flow(flow *f) {
 			printf("Handshake Message:\n");
 
 			if((incoming && f->in_encrypted) || (!incoming && f->out_encrypted)){
-				decrypt_fin(f, p, record_len - RECORD_HEADER_LEN, incoming);
+				encrypt(f, p, p, record_len - RECORD_HEADER_LEN, incoming, 0x16);
 				p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+				if(incoming) f->in_encrypted = 2;
+				else f->out_encrypted = 2;
 			}
 			handshake_hdr = (struct handshake_header*) p;
 			f->state = handshake_hdr->type;
@@ -175,6 +174,10 @@ int update_flow(flow *f) {
 					verify_finish_hash(f,p, incoming);
 					update_finish_hash(f, p);
 					printf("Received finished message!\n");
+					if((f->in_encrypted == 2) && (f->out_encrypted == 2)){
+						printf("Handshake complete!\n");
+						f->application = 1;
+					}
 					break;
 				default:
 					printf("Error? %02x\n",p[0]);
@@ -183,6 +186,7 @@ int update_flow(flow *f) {
 			break;
 		case APP:
 			printf("Application Data\n");
+			//decrypt this
 			break;
 		case CCS:
 			printf("Change of Cipher Spec\n");
@@ -195,7 +199,12 @@ int update_flow(flow *f) {
 			init_ciphers(f);
 			break;
 		case ALERT:
-			printf("Alert\n");
+			p = record;
+			p += RECORD_HEADER_LEN;
+
+			encrypt(f, p, p, record_len - RECORD_HEADER_LEN, incoming, 0x16);
+			p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+			printf("Alert: %02x %02x\n", p[0], p[1]);
 			break;
 		case HB:
 			printf("Heartbeat\n");
@@ -204,15 +213,17 @@ int update_flow(flow *f) {
 			printf("Error: Not a Record\n");
 			//TODO: later figure this out, for now delete
 			f->packet_chain = f->packet_chain->next;
+
 			if( f->packet_chain != NULL){
 				update_flow(f);
 			}
 			return 0;
 	}
 
+	f->seq_num = current->seq_num;
+
 	if(record_len == data_len){
 		/* record ended on packet boundary */
-		//printf("record consumed packet\n");
 		f->packet_chain = current->next;
 	} else {
 		/* need to update data */
@@ -346,411 +357,14 @@ int add_packet(flow *f, uint8_t *p){
 			new_packet->next = next;
 			previous->next = new_packet;
 		}
-		printf("Flow: %d > %d (%s)\n", ip_hdr->src.s_addr, ip_hdr->dst.s_addr, (new_packet->incoming)? "incoming":"outgoing");
+		/*printf("Flow: %d > %d (%s)\n", ip_hdr->src.s_addr, ip_hdr->dst.s_addr, (new_packet->incoming)? "incoming":"outgoing");
 		printf("ID number: %u\n", htonl(ip_hdr->id));
 		printf("Sequence number: %u\n", htonl(tcp_hdr->sequence_num));
 		printf("Acknowledgement number: %u\n", htonl(tcp_hdr->ack_num));
-		printf("Length: %d\n", new_packet->data_len);
+		printf("Length: %d\n", new_packet->data_len);*/
 
 	}
 	
 	return 0;
 
 }
-
-/** UTILITY **/
-
-int update_finish_hash(flow *f, uint8_t *hs){
-	//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);
-	
-	EVP_DigestUpdate(f->finish_md_ctx, hs, hs_len+4);
-
-	return 1;
-	
-}
-
-int extract_parameters(flow *f, uint8_t *hs){
-	DH *dh;
-	uint8_t *p;
-	long i;
-
-	p = hs + HANDSHAKE_HEADER_LEN;
-
-	if((dh = DH_new()) == NULL){
-		return 1;
-	}
-
-	/* Extract prime modulus */
-	n2s(p,i);
-
-	if(!(dh->p = BN_bin2bn(p,i,NULL))){
-		return 1;
-	}
-	p += i;
-
-	/* Extract generator */
-	n2s(p,i);
-
-	if(!(dh->g = BN_bin2bn(p,i,NULL))){
-		return 1;
-	}
-	p += i;
-
-	/* Extract server public value */
-	n2s(p,i);
-
-	if(!(dh->pub_key = BN_bin2bn(p,i,NULL))){
-		return 1;
-	}
-
-	f->dh = dh;
-	printf("Param extraction: success!\n");
-	return 0;
-}
-
-/* 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);
-
-
-	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
-
-	return 1;
-}
-
-int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
-	EVP_MD_CTX ctx;
-	uint8_t hash[EVP_MAX_MD_SIZE];
-	int32_t hash_len;
-
-	EVP_MD_CTX_init(&ctx);
-	
-	//get header length
-	struct handshake_header *hs_hdr;
-	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_ex(&ctx, hash, &hash_len);
-
-	//now use pseudorandom function
-	uint8_t *output = calloc(1, fin_length);
-	if(incoming){
-		PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
-	} else {
-		PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
-	}
-
-	//now compare
-	if(CRYPTO_memcmp(p, output, fin_length) != 0){
-		printf("VERIFY FAILED\n");
-		return 0;
-	} else {
-		printf("VERIFY PASSED\n");
-	}
-
-	return 1;
-}
-
-int compute_master_secret(flow *f){
-	DH *dh_srvr = NULL;
-	DH *dh_clnt = NULL;
-	BN_CTX *ctx;
-	BN_MONT_CTX *mont = NULL;
-	BIGNUM *pub_key = NULL, *priv_key = NULL;
-
-	ctx = BN_CTX_new();
-
-	dh_srvr = f->dh;
-	dh_clnt = DHparams_dup(dh_srvr);
-
-    uint32_t l = dh_clnt->length ? dh_clnt->length : BN_num_bits(dh_clnt->p) - 1;
-    int32_t bytes = (l+7) / 8;
-
-    uint8_t *buf = (uint8_t *)OPENSSL_malloc(bytes);
-    if (buf == NULL){
-        BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE);
-        return 1;
-    }
-
-	pub_key = BN_new();
-	priv_key = BN_new();
-
-	for(int i=0; i<bytes; i++){
-		buf[i] = f->key[i%16];
-	}
-
-    if (!BN_bin2bn(buf, bytes, priv_key))
-		return 1;
-
-    {
-        BIGNUM *prk;
-
-		prk = priv_key;
-
-        if (!dh_clnt->meth->bn_mod_exp(dh_clnt, pub_key, dh_clnt->g, prk, dh_clnt->p, ctx, mont)){
-			printf("FAIL\n");
-            return 1;
-		}
-		printf("here\n");
-    }
-
-    dh_clnt->pub_key = pub_key;
-    dh_clnt->priv_key = priv_key;
-
-	// Compute master key 
-	uint8_t *pre_master_secret = calloc(1, 256);//TODO: find right length
-
-	DH_compute_key(pre_master_secret, dh_srvr->pub_key, dh_clnt);
-	
-	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 ", f->master_secret[i]);
-	}
-	printf("\n");
-	
-	free(pre_master_secret);
-	DH_free(dh_srvr);
-	DH_free(dh_clnt);
-	return 0;
-}
-
-void extract_server_random(flow *f, uint8_t *hs){
-
-	uint8_t *p;
-
-	p = hs + HANDSHAKE_HEADER_LEN;
-
-	p+=2; //skip version
-
-	memcpy(f->server_random, p, SSL3_RANDOM_SIZE);
-	printf("got server random\n");
-
-}
-
-/* PRF using sha384, as defined in RFC 5246 */
-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;
-	const EVP_MD *md = EVP_sha384();
-
-	uint8_t A[EVP_MAX_MD_SIZE];
-	size_t len, A_len;
-	int chunk = EVP_MD_size(md);
-	int remaining = output_len;
-
-	uint8_t *out = output;
-
-	EVP_MD_CTX_init(&ctx);
-	EVP_MD_CTX_init(&ctx_tmp);
-	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, secret_len);
-
-	/* Calculate first A value */
-	EVP_DigestSignInit(&ctx_init, NULL, md, NULL, mac_key);
-	EVP_MD_CTX_copy_ex(&ctx, &ctx_init);
-	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+seed) */
-		EVP_MD_CTX_copy_ex(&ctx, &ctx_init);
-		EVP_DigestSignUpdate(&ctx, A, A_len);
-		EVP_MD_CTX_copy_ex(&ctx_tmp, &ctx);
-		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);
-			out += len;
-			remaining -= len;
-
-			/* Next A value */
-			EVP_DigestSignFinal(&ctx_tmp, A, &A_len);
-		} else {
-			EVP_DigestSignFinal(&ctx, A, &A_len);
-			memcpy(out, A, remaining);
-			remaining -= remaining;
-		}
-	}
-	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);
-
-	f->read_ctx = r_ctx;
-	f->write_ctx = w_ctx;
-}

+ 4 - 7
server/flow.h

@@ -20,9 +20,6 @@
 #define TLS_CLNT_KEYEX 0x10
 #define TLS_FINISHED 0x14
 
-# define n2s(c,s)        ((s=(((unsigned int)(c[0]))<< 8)| \
-							(((unsigned int)(c[1]))    )),c+=2)
-
 struct packet_st{
 	uint32_t seq_num;
 	uint16_t len;
@@ -44,6 +41,7 @@ typedef struct flow_st {
 	int state;		/* TLS handshake state */
 	int in_encrypted;		/* indicates whether incoming flow is encrypted */
 	int out_encrypted;		/* indicates whether outgoing flow is encrypted */
+	int application; /* indicates handshake is complete */
 	packet *packet_chain; /* currently held data */
 	DH *dh;
 
@@ -56,6 +54,9 @@ typedef struct flow_st {
 	uint8_t server_random[SSL3_RANDOM_SIZE];
 	uint8_t master_secret[SSL3_MASTER_SECRET_SIZE];
 
+	uint8_t read_seq[8];
+	uint8_t write_seq[8];
+
 } flow;
 
 typedef struct flow_table_st {
@@ -74,8 +75,4 @@ 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, int32_t len, int32_t incoming);
-void extract_server_random(flow *f, uint8_t *hs);
-int compute_master_secret(flow *f);
 #endif /* __RELAY_H__ */

+ 29 - 40
server/slitheen-proxy.c

@@ -9,6 +9,7 @@
 #include "flow.h"
 #include "slitheen.h"
 #include "util.h"
+#include "relay.h"
 
 void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
 void check_handshake(const struct tcp_header *tcp_hdr, flow f, unsigned char *p, u_short length);
@@ -90,11 +91,11 @@ void check_handshake(const struct tcp_header *tcp_hdr, flow f, unsigned char *pt
 				flow_ptr->key[i] = key[i];
 			}
 
-			printf("KEY \n");
+			/*printf("KEY \n");
 			for(int i=0; i< 16; i++){
 				printf("%02x ", flow_ptr->key[i]);
 			}
-			printf("\n");
+			printf("\n");*/
 			memcpy(flow_ptr->client_random, hello_rand, SSL3_RANDOM_SIZE);
 			
 			printf("Saved new flow\n");
@@ -108,30 +109,30 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pa
 	pcap_t *handle;
 	char errbuf[BUFSIZ];
 	char *writedev = (char *) args;
-	unsigned char *p;
+	//unsigned char *p;
 
-	const struct ip_header *ip_hdr;
+	//const struct ip_header *ip_hdr;
 	//const struct tcp_header *tcp_hdr;
 
 	handle = pcap_open_live(writedev, BUFSIZ, 1, 1000, errbuf);
 	if (handle == NULL){
 		fprintf(stderr, "Couldn't open device %s: %s\n", writedev, errbuf);
 	}
-
+/*
 	p = (unsigned char *) packet;
 	p += ETHER_HEADER_LEN; //skip ethernet header
 	ip_hdr = (struct ip_header*) p;
 	p += IP_HEADER_LEN(ip_hdr);//TODO: remove
 	//tcp_hdr = (struct tcp_header*) p;//TODO: remove
 
-	/* Check to make sure it is an IP packet */
+	// Check to make sure it is an IP packet 
 	if( (ip_hdr->versionihl >>4) != 4)
 		goto end;
 
-	/* Packet may be split over multiple frames. In this case,
-	 * reconstruct the packet before trying to read TLS records
-	 */
-	if((htons(ip_hdr->flagsoff)&MF) || (htons(ip_hdr->flagsoff) &0x1fff) ){ /* this is a fragment */
+	// Packet may be split over multiple frames. In this case,
+	 // reconstruct the packet before trying to read TLS records
+	 //
+	if((htons(ip_hdr->flagsoff)&MF) || (htons(ip_hdr->flagsoff) &0x1fff) ){ /* this is a fragment 
 		printf("MF: %d, OFF: %d.\n", htons(ip_hdr->flagsoff)&MF, htons(ip_hdr->flagsoff)&0x1fff);
 		printf("Received packet fragment.\n");
 		printf("%d packet bytes: \n", IP_HEADER_LEN(ip_hdr));
@@ -147,15 +148,14 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pa
 		if(success){
 			process_packet(complete_packet);
 		}
-		/* TODO: handle errors */
+		/* TODO: handle errors 
 		
-	} else { /*not a fragment, add to packet chain */
+	} else { /*not a fragment, add to packet chain 
 		process_packet(packet);
 	}
 	
 end:
-
-	/* Hand packet to relay module */
+*/
 	if((pcap_inject(handle, packet, header->len)) < 0 ){
 		fprintf(stderr, "Error: %s\n", pcap_geterr(handle));
 	}
@@ -295,32 +295,32 @@ void process_packet(const u_char *packet){
 
 		/* Checks to see if this is a possibly tagged hello msg */
 		if (record_hdr->type == HS){ /* This is a TLS handshake */
-			//printf("record type: %d.\n", record_hdr->type);
-			//printf("record version(major): %d.\n", (record_hdr->version&0xFF00)>>8);
-			//printf("record version(minor): %d.\n", record_hdr->version&0xFF);
-			//printf("record length: %d.\n", RECORD_LEN(record_hdr));
-			//printf("record header bytes:\n");
-			//for(i=0; i<RECORD_HEADER_LEN; i++){
-			//	printf("%02x ", p[i]);
-			//}
-			//printf("\n");
 			p += RECORD_HEADER_LEN;
 			check_handshake(tcp_hdr, newFlow, p, RECORD_LEN(record_hdr));
-			//printf("Length of packet: %d.\n", htons(ip_hdr->len));
 		}
 	}
 
 	/* Now if flow is in table, update state */
 	if((index = check_flow(newFlow))){
 		flow *observed = get_flow(index-1);
+	
+		if(observed->application){
+			replace_packet(observed, packet);
+		} else {
 
+			/* Pass data to packet chain */
+			add_packet(observed, packet);
 
-		/* Pass data to packet chain */
-		add_packet(observed, packet);
+			/* Update flow state */
+			if(observed->packet_chain != NULL){
+				//fork off a thread to update the flow
+				//pid_t pid = fork();
+				//if(pid == 0){//child
+					update_flow(observed);
+				//	exit(0);
+				//}
 
-		/* Update flow state */
-		if(observed->packet_chain != NULL){
-			update_flow(observed);
+			}
 		}
 
 		/* Update TCP state */
@@ -329,17 +329,6 @@ void process_packet(const u_char *packet){
 			remove_flow(index);
 		}
 
-		/* Check to see if TLS finished message has passed */
-		if(observed->state == TLS_FINISHED){
-			//decrypt packet?
-			printf("TLS finished received.\n");
-		} else {
-			//check to see if tls_finished message
-			if(observed->in_encrypted && observed->out_encrypted){ /* decrypt tls finished message */
-				printf("MESSAGE ENCRYPTED\n");
-			}
-
-		}
 	}
 
 }