Browse Source

added support for ECDHE

cecylia 8 years ago
parent
commit
6d37ae4d53
8 changed files with 495 additions and 114 deletions
  1. 1 1
      bandwidth_data/httpData/runPhantom.sh
  2. 434 87
      server/crypto.c
  3. 5 2
      server/crypto.h
  4. 6 7
      server/flow.c
  5. 7 2
      server/flow.h
  6. 38 6
      server/relay.c
  7. 3 7
      server/slitheen-proxy.c
  8. 1 2
      server/slitheen.h

+ 1 - 1
bandwidth_data/httpData/runPhantom.sh

@@ -1,4 +1,4 @@
 for i in `cat top5k`
 do
-phantomjs --proxy=localhost:8080 --proxy-type=http --ssl-protocol=any --ignore-ssl-errors=true phantomScript.js $i
+./phantomjs --proxy=localhost:8080 --proxy-type=http --ssl-protocol=any --ignore-ssl-errors=true phantomScript.js $i
 done

+ 434 - 87
server/crypto.c

@@ -9,6 +9,66 @@
 #include "flow.h"
 #include "slitheen.h"
 
+#define NID_sect163k1           721
+#define NID_sect163r1           722
+#define NID_sect163r2           723
+#define NID_sect193r1           724
+#define NID_sect193r2           725
+#define NID_sect233k1           726
+#define NID_sect233r1           727
+#define NID_sect239k1           728
+#define NID_sect283k1           729
+#define NID_sect283r1           730
+#define NID_sect409k1           731
+#define NID_sect409r1           732
+#define NID_sect571k1           733
+#define NID_sect571r1           734
+#define NID_secp160k1           708
+#define NID_secp160r1           709
+#define NID_secp160r2           710
+#define NID_secp192k1           711
+#define NID_X9_62_prime192v1            409
+#define NID_secp224k1           712
+#define NID_secp224r1           713
+#define NID_secp256k1           714
+#define NID_X9_62_prime256v1            415
+#define NID_secp384r1           715
+#define NID_secp521r1           716
+#define NID_brainpoolP256r1             927
+#define NID_brainpoolP384r1             931
+#define NID_brainpoolP512r1             933
+
+static int nid_list[] = {
+    NID_sect163k1,              /* sect163k1 (1) */
+    NID_sect163r1,              /* sect163r1 (2) */
+    NID_sect163r2,              /* sect163r2 (3) */
+    NID_sect193r1,              /* sect193r1 (4) */
+    NID_sect193r2,              /* sect193r2 (5) */
+    NID_sect233k1,              /* sect233k1 (6) */
+    NID_sect233r1,              /* sect233r1 (7) */
+    NID_sect239k1,              /* sect239k1 (8) */
+    NID_sect283k1,              /* sect283k1 (9) */
+    NID_sect283r1,              /* sect283r1 (10) */
+    NID_sect409k1,              /* sect409k1 (11) */
+    NID_sect409r1,              /* sect409r1 (12) */
+    NID_sect571k1,              /* sect571k1 (13) */
+    NID_sect571r1,              /* sect571r1 (14) */
+    NID_secp160k1,              /* secp160k1 (15) */
+    NID_secp160r1,              /* secp160r1 (16) */
+    NID_secp160r2,              /* secp160r2 (17) */
+    NID_secp192k1,              /* secp192k1 (18) */
+    NID_X9_62_prime192v1,       /* secp192r1 (19) */
+    NID_secp224k1,              /* secp224k1 (20) */
+    NID_secp224r1,              /* secp224r1 (21) */
+    NID_secp256k1,              /* secp256k1 (22) */
+    NID_X9_62_prime256v1,       /* secp256r1 (23) */
+    NID_secp384r1,              /* secp384r1 (24) */
+    NID_secp521r1,              /* secp521r1 (25) */
+    NID_brainpoolP256r1,        /* brainpoolP256r1 (26) */
+    NID_brainpoolP384r1,        /* brainpoolP384r1 (27) */
+    NID_brainpoolP512r1         /* brainpool512r1 (28) */
+};
+
 /** Updates the hash of all TLS handshake messages upon the
  *  receipt of a new message. This hash is eventually used
  *  to verify the TLS Finished message
@@ -44,41 +104,156 @@ int update_finish_hash(flow *f, uint8_t *hs){
  *  	0 on success, 1 on failure
  */
 int extract_parameters(flow *f, uint8_t *hs){
-	DH *dh;
 	uint8_t *p;
 	long i;
 
+	int ok=1;
+
 	p = hs + HANDSHAKE_HEADER_LEN;
 
-	if((dh = DH_new()) == NULL){
-		return 1;
-	}
+	if(f->keyex_alg == 1){
+		DH *dh;
 
-	/* Extract prime modulus */
-	n2s(p,i);
+		if((dh = DH_new()) == NULL){
+			return 1;
+		}
 
-	if(!(dh->p = BN_bin2bn(p,i,NULL))){
-		return 1;
-	}
-	p += i;
+		/* Extract prime modulus */
+		n2s(p,i);
 
-	/* Extract generator */
-	n2s(p,i);
+		if(!(dh->p = BN_bin2bn(p,i,NULL))){
+			return 1;
+		}
+		p += i;
 
-	if(!(dh->g = BN_bin2bn(p,i,NULL))){
-		return 1;
-	}
-	p += i;
+		/* Extract generator */
+		n2s(p,i);
 
-	/* Extract server public value */
-	n2s(p,i);
+		if(!(dh->g = BN_bin2bn(p,i,NULL))){
+			return 1;
+		}
+		p += i;
 
-	if(!(dh->pub_key = BN_bin2bn(p,i,NULL))){
-		return 1;
-	}
+		/* Extract server public value */
+		n2s(p,i);
 
-	f->dh = dh;
-	return 0;
+		if(!(dh->pub_key = BN_bin2bn(p,i,NULL))){
+			return 1;
+		}
+
+		f->dh = dh;
+	} else if (f->keyex_alg == 2){
+		EC_KEY *ecdh;
+		EC_GROUP *ngroup;
+		const EC_GROUP *group;
+
+		BN_CTX *bn_ctx = NULL;
+		EC_POINT *srvr_ecpoint = NULL;
+		int curve_nid = 0;
+		int encoded_pt_len = 0;
+
+		if((ecdh = EC_KEY_new()) == NULL) {
+			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+			printf("HERE1\n");
+			fflush(stdout);
+			goto err;
+		}
+
+
+		if(p[0] != 0x03){//not a named curve
+			printf("HERE2\n");
+			fflush(stdout);
+			goto err;
+		}
+
+		//int curve_id = (p[1] << 8) + p[2];
+		int curve_id = *(p+2);
+		if((curve_id < 0) || ((unsigned int)curve_id >
+						            sizeof(nid_list) / sizeof(nid_list[0]))){
+			printf("HERE3\n");
+			fflush(stdout);
+			goto err;
+		}
+			
+		curve_nid = nid_list[curve_id-1];
+	
+		/* Extract curve 
+		if(!tls1_check_curve(s, p, 3)) {
+			goto err;
+
+		}
+
+		if((*(p+2) < 1) || ((unsigned int) (*(p+2)) > sizeof(nid_list) / sizeof(nid_list[0]))){
+
+			goto err;
+		}
+		curve_nid = nid_list[*(p+2)];
+		*/
+
+		ngroup = EC_GROUP_new_by_curve_name(curve_nid);
+
+		if(ngroup == NULL){
+			printf("HERE4\n");
+			fflush(stdout);
+			goto err;
+		}
+		if(EC_KEY_set_group(ecdh, ngroup) == 0){
+			printf("HERE5\n");
+			fflush(stdout);
+			goto err;
+		}
+		EC_GROUP_free(ngroup);
+
+		group = EC_KEY_get0_group(ecdh);
+		printf("Curve name is %d\n", EC_GROUP_get_curve_name(group));
+
+		p += 3;
+
+		/* Get EC point */
+		if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) || 
+				((bn_ctx = BN_CTX_new()) == NULL)) {
+			printf("HERE6\n");
+			fflush(stdout);
+			goto err;
+		}
+
+		encoded_pt_len = *p;
+		p += 1;
+
+		printf("point len: %d, message len: %x %x %x\n",encoded_pt_len, hs[1], hs[2], hs[3]);
+
+		if(EC_POINT_oct2point(group, srvr_ecpoint, p, encoded_pt_len, 
+					bn_ctx) == 0){
+			printf("HERE7\n");
+			fflush(stdout);
+			goto err;
+		}
+
+		p += encoded_pt_len;
+
+		EC_KEY_set_public_key(ecdh, srvr_ecpoint);
+
+		f->ecdh = ecdh;
+		ecdh = NULL;
+		BN_CTX_free(bn_ctx);
+		bn_ctx = NULL;
+		EC_POINT_free(srvr_ecpoint);
+		srvr_ecpoint = NULL;
+		ok=0;
+		
+err:
+		if(bn_ctx != NULL){
+			BN_CTX_free(bn_ctx);
+		}
+		if(srvr_ecpoint != NULL){
+			EC_POINT_free(srvr_ecpoint);
+		}
+		if(ecdh != NULL){
+			EC_KEY_free(ecdh);
+		}
+
+	}
+	return ok;
 }
 
 /** MAC a message
@@ -214,9 +389,9 @@ int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
 	//now use pseudorandom function
 	uint8_t *output = calloc(1, fin_length);
 	if(incoming){
-		PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, (uint8_t *) TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
+		PRF(f, f->master_secret, SSL3_MASTER_SECRET_SIZE, (uint8_t *) 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, (uint8_t *) TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
+		PRF(f, f->master_secret, SSL3_MASTER_SECRET_SIZE, (uint8_t *) TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
 	}
 
 	//now compare
@@ -244,102 +419,230 @@ int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
  */
 int compute_master_secret(flow *f){
 	printf("Computing master secret (%x:%d -> %x:%d)...\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
+
 	DH *dh_srvr = NULL;
 	DH *dh_clnt = NULL;
-	BN_CTX *ctx;
-	BN_MONT_CTX *mont = NULL;
-	BIGNUM *pub_key = NULL, *priv_key = NULL;
+	BN_CTX *ctx = NULL;
+	BIGNUM *pub_key = NULL, *priv_key = NULL, *order = NULL;
 
-	ctx = BN_CTX_new();
+	EC_KEY *clnt_ecdh = NULL;
+	EC_POINT *e_pub_key = NULL;
 
-	dh_srvr = f->dh;
-	dh_clnt = DHparams_dup(dh_srvr);
+	int ok =1;
 
-    uint32_t l = dh_clnt->length ? dh_clnt->length : BN_num_bits(dh_clnt->p) - 1;
-    int32_t bytes = (l+7) / 8;
-	printf("length of dh param: %d\n", bytes);
+	uint8_t *pre_master_secret = calloc(1, PRE_MASTER_MAX_LEN);//TODO: find right length
+	int32_t pre_master_len;
+	uint32_t l;
+	int32_t bytes;
 
-    uint8_t *buf = (uint8_t *)OPENSSL_malloc(bytes);
-    if (buf == NULL){
-        BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE);
-		goto err;
-    }
+	uint8_t *buf = NULL;
 
-	pub_key = BN_new();
-	priv_key = BN_new();
+	if(f->keyex_alg == 1){
+		BN_MONT_CTX *mont = NULL;
 
-	printf("key =");
-	for(int i=0; i< 16; i++)
-		printf(" %02x", f->key[i]);
-	printf("\n");
+		ctx = BN_CTX_new();
 
-	PRF(f->key, 16,
-		(uint8_t *) SLITHEEN_KEYGEN_CONST, SLITHEEN_KEYGEN_CONST_SIZE,
-		NULL, 0, NULL, 0, NULL, 0,
-		buf, bytes);
+		dh_srvr = f->dh;
+		dh_clnt = DHparams_dup(dh_srvr);
 
-//#ifdef DEBUG
-	printf("Generated the following rand bytes: ");
-	for(int i=0; i< bytes; i++){
-		printf(" %02x ", buf[i]);
-	}
-	printf("\n");
-//#endif
+		l = dh_clnt->length ? dh_clnt->length : BN_num_bits(dh_clnt->p) - 1;
+		bytes = (l+7) / 8;
+		printf("length of dh param: %d\n", bytes);
 
-    if (!BN_bin2bn(buf, bytes, priv_key))
-		goto err;
+		buf = (uint8_t *)OPENSSL_malloc(bytes);
+		if (buf == NULL){
+			BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
 
-    {
-        BIGNUM *prk;
+		pub_key = BN_new();
+		priv_key = BN_new();
 
-		prk = priv_key;
+		printf("key =");
+		for(int i=0; i< 16; i++)
+			printf(" %02x", f->key[i]);
+		printf("\n");
 
-        if (!dh_clnt->meth->bn_mod_exp(dh_clnt, pub_key, dh_clnt->g, prk, dh_clnt->p, ctx, mont)){
+		PRF(f, f->key, 16,
+			(uint8_t *) SLITHEEN_KEYGEN_CONST, SLITHEEN_KEYGEN_CONST_SIZE,
+			NULL, 0, NULL, 0, NULL, 0,
+			buf, bytes);
+
+	//#ifdef DEBUG
+		printf("Generated the following rand bytes: ");
+		for(int i=0; i< bytes; i++){
+			printf(" %02x ", buf[i]);
+		}
+		printf("\n");
+	//#endif
+
+		if (!BN_bin2bn(buf, bytes, priv_key))
 			goto err;
+
+		{
+			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)){
+				goto err;
+			}
 		}
-    }
 
-    dh_clnt->pub_key = pub_key;
-    dh_clnt->priv_key = priv_key;
+		dh_clnt->pub_key = pub_key;
+		dh_clnt->priv_key = priv_key;
 
-	// Compute master key 
-	uint8_t *pre_master_secret = calloc(1, PRE_MASTER_MAX_LEN);//TODO: find right length
+		pre_master_len = DH_compute_key(pre_master_secret, dh_srvr->pub_key, dh_clnt);
+		
+	} else if(f->keyex_alg == 2){
+		const EC_GROUP *srvr_group = NULL;
+		const EC_POINT *srvr_ecpoint = NULL;
+		EC_KEY *tkey;
+
+		tkey = f->ecdh;
+		if(tkey == NULL){
+			return 1;
+		}
+
+		srvr_group = EC_KEY_get0_group(tkey);
+		srvr_ecpoint = EC_KEY_get0_public_key(tkey);
+
+		if((srvr_group == NULL) || (srvr_ecpoint == NULL)) {
+			return 1;
+		}
+
+		if((clnt_ecdh = EC_KEY_new()) == NULL) {
+			goto err;
+		}
+
+		if(!EC_KEY_set_group(clnt_ecdh, srvr_group)) {
+			goto err;
+		}
 
-	int32_t pre_master_len = DH_compute_key(pre_master_secret, dh_srvr->pub_key, dh_clnt);
+		/* Now generate key from tag */
+		
+		if((order = BN_new()) == NULL){
+			goto err;
+		}
+		if((ctx = BN_CTX_new()) == NULL){
+			goto err;
+		}
+
+		if((priv_key = BN_new()) == NULL){
+			goto err;
+		}
+
+		if(!EC_GROUP_get_order(srvr_group, order, ctx)){
+			goto err;
+		}
+
+		l = BN_num_bits(order)-1;
+		bytes = (l+7)/8;
+
+		buf = (unsigned char *)OPENSSL_malloc(bytes);
+		if(buf == NULL){
+			goto err;
+		}
+
+		PRF(f, f->key, 16, (uint8_t *) SLITHEEN_KEYGEN_CONST, SLITHEEN_KEYGEN_CONST_SIZE,
+				NULL, 0, NULL, 0, NULL, 0, buf, bytes);
+
+		//#ifdef DEBUG
+		printf("Generated the following rand bytes: ");
+		for(int i=0; i< bytes; i++){
+			printf("%02x ", buf[i]);
+		}
+		printf("\n");
+//#endif
+		
+		if(!BN_bin2bn(buf, bytes, priv_key)){
+			goto err;
+		}
+
+		if(EC_KEY_get0_public_key(clnt_ecdh) == NULL){
+			if((e_pub_key = EC_POINT_new(srvr_group)) == NULL){
+				goto err;
+			}
+		} else {
+			e_pub_key = EC_KEY_get0_public_key(clnt_ecdh);
+		}
+
+		if(!EC_POINT_mul(EC_KEY_get0_group(clnt_ecdh), e_pub_key, priv_key, NULL, NULL, ctx)){
+			goto err;
+		}
+
+		EC_KEY_set_private_key(clnt_ecdh, priv_key);
+		EC_KEY_set_public_key(clnt_ecdh, e_pub_key);
+
+
+		/*Compute the master secret */
+		int32_t field_size = EC_GROUP_get_degree(srvr_group);
+		if(field_size <= 0){
+			goto err;
+		}
+		pre_master_len = ECDH_compute_key(pre_master_secret, (field_size + 7) / 8,
+					srvr_ecpoint, clnt_ecdh, NULL);
+		if(pre_master_len <= 0) {
+			goto err;
+		}
+
+	}
+
+	/*Generate master secret */
 	
-	PRF(pre_master_secret, pre_master_len, (uint8_t *) 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);
+	PRF(f, pre_master_secret, pre_master_len, (uint8_t *) 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);
 
 	if(f->current_session != NULL)
 		memcpy(f->current_session, f->master_secret, SSL3_MASTER_SECRET_SIZE);
 
 #ifdef DEBUG
-    fprintf(stdout, "Premaster Secret:\n");
-    BIO_dump_fp(stdout, (char *)pre_master_secret, pre_master_len);
-    fprintf(stdout, "Client Random:\n");
-    BIO_dump_fp(stdout, (char *)f->client_random, SSL3_RANDOM_SIZE);
-    fprintf(stdout, "Server Random:\n");
-    BIO_dump_fp(stdout, (char *)f->server_random, SSL3_RANDOM_SIZE);
-    fprintf(stdout, "Master Secret:\n");
-    BIO_dump_fp(stdout, (char *)f->master_secret, SSL3_MASTER_SECRET_SIZE);
+	fprintf(stdout, "Premaster Secret:\n");
+	BIO_dump_fp(stdout, (char *)pre_master_secret, pre_master_len);
+	fprintf(stdout, "Client Random:\n");
+	BIO_dump_fp(stdout, (char *)f->client_random, SSL3_RANDOM_SIZE);
+	fprintf(stdout, "Server Random:\n");
+	BIO_dump_fp(stdout, (char *)f->server_random, SSL3_RANDOM_SIZE);
+	fprintf(stdout, "Master Secret:\n");
+	BIO_dump_fp(stdout, (char *)f->master_secret, SSL3_MASTER_SECRET_SIZE);
 #endif
 
 	//remove pre_master_secret from memory
 	memset(pre_master_secret, 0, PRE_MASTER_MAX_LEN);
+	ok = 0;
 
 err:
 	if((pub_key != NULL) && (dh_srvr == NULL)){
 		BN_free(pub_key);
 	}
-	if((priv_key != NULL) && (dh_clnt == NULL)){
+	if((priv_key != NULL) && (dh_clnt == NULL) && (EC_KEY_get0_private_key(clnt_ecdh) == NULL)){
 		BN_free(priv_key);
 	}
-	BN_CTX_free(ctx);
+
+	if(ctx != NULL){
+		BN_CTX_free(ctx);
+	}
 
 	OPENSSL_free(buf);
 	free(pre_master_secret);
-	DH_free(dh_srvr);
-	DH_free(dh_clnt);
-	return 0;
+	if(dh_srvr != NULL){
+		DH_free(dh_srvr);
+	}
+	if(dh_clnt != NULL) {
+		DH_free(dh_clnt);
+	}
+	
+	if(order){
+		BN_free(order);
+	}
+	if(e_pub_key != NULL && EC_KEY_get0_public_key(clnt_ecdh) == NULL){
+		EC_POINT_free(e_pub_key);
+	}
+
+	if(clnt_ecdh != NULL){
+		EC_KEY_free(clnt_ecdh);
+	}
+
+	return ok;
 }
 
 /** Saves the random none from the server hello message
@@ -360,6 +663,50 @@ void extract_server_random(flow *f, uint8_t *hs){
 	p+=2; //skip version
 
 	memcpy(f->server_random, p, SSL3_RANDOM_SIZE);
+	p += SSL3_RANDOM_SIZE;
+
+	//skip session id
+	uint8_t id_len = (uint8_t) p[0];
+	p ++;
+	p += id_len;
+
+	//now extract ciphersuite
+	printf("Checking cipher\n");
+
+	if(((p[0] <<8) + p[1]) == 0x9E){
+
+		printf("USING DHE-RSA-AES128-GCM-SHA256\n");
+		f->keyex_alg = 1;
+		f->cipher = EVP_aes_128_gcm();
+		f->message_digest = EVP_sha256();
+		fflush(stdout);
+
+	} else if(((p[0] <<8) + p[1]) == 0x9F){
+		printf("USING DHE-RSA-AES256-GCM-SHA384\n");
+		fflush(stdout);
+		f->keyex_alg = 1;
+		f->cipher = EVP_aes_256_gcm();
+		f->message_digest = EVP_sha384();
+
+	} else if(((p[0] <<8) + p[1]) == 0xC02F){
+		printf("USING ECDHE-RSA-AES128-GCM-SHA256\n");
+		fflush(stdout);
+		f->keyex_alg = 2;
+		f->cipher = EVP_aes_128_gcm();
+		f->message_digest = EVP_sha256();
+
+	} else if(((p[0] <<8) + p[1]) == 0xC030){
+		printf("USING ECDHE-RSA-AES256-GCM-SHA384\n");
+		fflush(stdout);
+		f->keyex_alg = 2;
+		f->cipher = EVP_aes_256_gcm();
+		f->message_digest = EVP_sha384();
+
+	} else {
+		printf("%x %x = %x\n", p[0], p[1], ((p[0] <<8) + p[1]));
+		printf("Error: unsupported cipher\n");
+		fflush(stdout);
+	}
 
 }
 
@@ -377,7 +724,7 @@ void extract_server_random(flow *f, uint8_t *hs){
  *  Output:
  *  	0 on success, 1 on failure
  */
-int PRF(uint8_t *secret, int32_t secret_len,
+int PRF(flow *f, 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,
@@ -386,7 +733,7 @@ int PRF(uint8_t *secret, int32_t secret_len,
 
 	EVP_MD_CTX ctx, ctx_tmp, ctx_init;
 	EVP_PKEY *mac_key;
-	const EVP_MD *md = EVP_sha384();
+	const EVP_MD *md = f->message_digest;
 
 	uint8_t A[EVP_MAX_MD_SIZE];
 	size_t len, A_len;
@@ -474,7 +821,7 @@ int init_ciphers(flow *f){
 	EVP_CIPHER_CTX *w_ctx;
 	EVP_CIPHER_CTX *w_ctx_srvr;
 	EVP_CIPHER_CTX *r_ctx_srvr;
-	const EVP_CIPHER *c = EVP_aes_256_gcm();
+	const EVP_CIPHER *c = f->cipher;
 
 	/* Generate Keys */
 	uint8_t *write_key, *write_iv;
@@ -483,12 +830,12 @@ int init_ciphers(flow *f){
 
 	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_sha384());
+	mac_len = EVP_MD_size(f->message_digest);
 	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,
+	PRF(f, f->master_secret, SSL3_MASTER_SECRET_SIZE,
 			(uint8_t *) TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
 			f->server_random, SSL3_RANDOM_SIZE,
 			f->client_random, SSL3_RANDOM_SIZE,

+ 5 - 2
server/crypto.h

@@ -6,12 +6,15 @@
 #define n2s(c,s)        ((s=(((unsigned int)(c[0]))<< 8)| \
 							(((unsigned int)(c[1]))    )),c+=2)
 
+/* Curves */
+
+
 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, int32_t enc);
 void extract_server_random(flow *f, uint8_t *hs);
 int compute_master_secret(flow *f);
 
-int PRF(uint8_t *secret, int32_t secret_len,
+int PRF(flow *f, 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,
@@ -24,7 +27,7 @@ int init_ciphers(flow *f);
 void update_context(flow *f, uint8_t *input, int32_t len, int32_t incoming, int32_t type, int32_t enc);
 void check_handshake(struct packet_info *info, flow f);
 
-#define PRE_MASTER_MAX_LEN 512
+#define PRE_MASTER_MAX_LEN BUFSIZ
 
 #define SLITHEEN_KEYGEN_CONST "SLITHEEN_KEYGEN"
 #define SLITHEEN_KEYGEN_CONST_SIZE 15

+ 6 - 7
server/flow.c

@@ -60,6 +60,8 @@ flow *add_flow(flow newFlow) {
 	newFlow.outbox = NULL;
 	newFlow.outbox_len = 0;
 	newFlow.outbox_offset = 0;
+	newFlow.partial_record_header = NULL;
+	newFlow.partial_record_header_len = 0;
 	newFlow.remaining_record_len = 0;
 	newFlow.remaining_response_len = 0;
 	newFlow.httpstate = PARSE_HEADER;
@@ -343,9 +345,7 @@ err:
  */
 int remove_flow(flow *f) {
 
-	if(f->finish_md_ctx){
-		EVP_MD_CTX_destroy(f->finish_md_ctx);
-	}
+	EVP_MD_CTX_destroy(f->finish_md_ctx);
 	//Clean up cipher ctxs
 	if(f->clnt_read_ctx != NULL){
 		EVP_CIPHER_CTX_free(f->clnt_read_ctx);
@@ -360,6 +360,7 @@ int remove_flow(flow *f) {
 		EVP_CIPHER_CTX_free(f->srvr_write_ctx);
 	}
 
+	sem_wait(&flow_table_lock);
 	flow_entry *entry = table->first_entry;
 	if(entry->f == f){
 		table->first_entry = entry->next;
@@ -391,8 +392,7 @@ int remove_flow(flow *f) {
 			entry = next;
 		}
 	}
-
-	f = NULL;
+	sem_post(&flow_table_lock);
 
 	return 1;
 }
@@ -415,8 +415,6 @@ int grow_table() {
  */
 flow *check_flow(flow observed){
 	/* Loop through flows in table and see if it exists */
-	
-	sem_wait(&flow_table_lock);
 	int i;
 	flow_entry *entry = table->first_entry;
 	flow *candidate;
@@ -424,6 +422,7 @@ flow *check_flow(flow observed){
 	if(entry == NULL)
 		return NULL;
 
+	sem_wait(&flow_table_lock);
 	/* Check first in this direction */
 	for(i=0; i<table->len; i++){
 		if(entry == NULL){

+ 7 - 2
server/flow.h

@@ -45,8 +45,6 @@ typedef struct data_queue_st {
 
 extern data_queue *downstream_queue;
 
-extern sem_t flow_table_lock;
-
 typedef struct packet_st packet;
 
 typedef struct session_st {
@@ -86,7 +84,11 @@ typedef struct flow_st {
 	queue_block *upstream_queue;
 	uint32_t upstream_remaining;
 	DH *dh;
+	EC_KEY *ecdh;
 
+	const EVP_CIPHER *cipher;
+	const EVP_MD *message_digest;
+	uint8_t keyex_alg;
 	uint8_t handshake_hash[EVP_MAX_MD_SIZE];
 	EVP_MD_CTX *finish_md_ctx;
 	EVP_CIPHER_CTX *clnt_read_ctx;
@@ -115,6 +117,9 @@ typedef struct flow_st {
 	int32_t outbox_len;
 	int32_t outbox_offset;
 
+	uint8_t *partial_record_header;
+	uint8_t partial_record_header_len;
+
 	//locking
 	//pthread_mutex_t flow_lock = PTHREAD_MUTEX_INITIALIZER;
 

+ 38 - 6
server/relay.c

@@ -631,20 +631,47 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 	}
 
 	while(remaining_packet_len > 0){ //while bytes remain in the packet
+		if(remaining_packet_len < RECORD_HEADER_LEN){
+			printf("Error: partial record header: \n");
+			for(int i= 0; i< remaining_packet_len; i++){
+				printf("%02x ", p[i]);
+			}
+			printf("\n");
+			fflush(stdout);
+			f->partial_record_header = calloc(1, RECORD_HEADER_LEN);
+			memcpy(f->partial_record_header, p, remaining_packet_len);
+			f->partial_record_header_len = remaining_packet_len;
+			remaining_packet_len -= remaining_packet_len;
+			break;
+		}
+
+		struct record_header *record_hdr;
+
+		if(f->partial_record_header_len > 0){
+			memcpy(f->partial_record_header+ f->partial_record_header_len, 
+					p, RECORD_HEADER_LEN - f->partial_record_header_len);
+			record_hdr = (struct record_header *) f->partial_record_header;
+			printf("Using partial record\n");
+		} else {
 		
-		struct record_header *record_hdr = (struct record_header*) p;
+			record_hdr = (struct record_header*) p;
+		}
 		uint32_t record_len = RECORD_LEN(record_hdr);
 
-#ifdef DEBUG
+//#ifdef DEBUG
+	fprintf(stdout,"Flow: %x > %x (%s)\n", info->ip_hdr->src.s_addr, info->ip_hdr->dst.s_addr, (info->ip_hdr->src.s_addr != f->src_ip.s_addr)? "incoming":"outgoing");
+	fprintf(stdout,"ID number: %u\n", htonl(info->ip_hdr->id));
+	fprintf(stdout,"Sequence number: %u\n", htonl(info->tcp_hdr->sequence_num));
+	fprintf(stdout,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
 		fprintf(stdout, "Record:\n");
 		for(int i=0; i< RECORD_HEADER_LEN; i++){
-			printf("%02x ", p[i]);
+			printf("%02x ", ((uint8_t *) record_hdr)[i]);
 		}
 		printf("\n");
-#endif
+//#endif
 
-		p += RECORD_HEADER_LEN;
-		remaining_packet_len -= RECORD_HEADER_LEN;
+		p += (RECORD_HEADER_LEN - f->partial_record_header_len);
+		remaining_packet_len -= (RECORD_HEADER_LEN - f->partial_record_header_len);
 
 		uint8_t *record_ptr = p; //points to the beginning of record data
 		uint32_t remaining_record_len = record_len;
@@ -913,6 +940,11 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 
 		p = record_ptr + record_len;
 		remaining_packet_len -= record_len;
+		if(f->partial_record_header_len > 0){
+			f->partial_record_header_len = 0;
+			free(f->partial_record_header);
+			printf("freed partial record\n");
+		}
 
 	}
 

+ 3 - 7
server/slitheen-proxy.c

@@ -32,8 +32,8 @@ int main(int argc, char *argv[]){
 	dev1 = argv[1];
 	dev2 = argv[2];
 
-	snprintf(filter1, 33, "ether src host %s", macaddr1);
-	snprintf(filter2, 33, "ether src host %s", macaddr2);
+	snprintf(filter1, 33, "ether src host %s", macaddr);
+	snprintf(filter2, 33, "ether dst host %s", macaddr);
 
 	init_tables();
 	init_session_cache();
@@ -181,11 +181,7 @@ void process_packet(struct packet_info *info){
 		/* Update TCP state */
 		if(info->tcp_hdr->flags & (FIN | RST) ){
 			/* Remove flow from table, connection ended */
-			sem_wait(&flow_table_lock);
-			if(observed != NULL){
-				remove_flow(observed);
-			}
-			sem_post(&flow_table_lock);
+			remove_flow(observed);
 		}
 
 	}

+ 1 - 2
server/slitheen.h

@@ -4,8 +4,7 @@
 #include <netinet/in.h>
 #include <pcap.h>
 
-#define macaddr1 "00:25:90:5a:26:99"
-#define macaddr2 "00:25:90:c9:5a:09"
+#define macaddr "08:00:27:0e:89:ea"
 
 /* Ethernet addresses are 6 bytes */
 #define ETHER_ADDR_LEN	6