Browse Source

added modified finished message feature to relay station

cecylia 7 years ago
parent
commit
25da55c926
3 changed files with 159 additions and 15 deletions
  1. 66 7
      relay_station/crypto.c
  2. 3 0
      relay_station/crypto.h
  3. 90 8
      relay_station/flow.c

+ 66 - 7
relay_station/crypto.c

@@ -110,6 +110,12 @@ int update_finish_hash(flow *f, uint8_t *hs){
 	
 	EVP_DigestUpdate(f->finish_md_ctx, hs, hs_len+4);
 
+	printf("SLITHEEN: adding to finish mac computation:\n");
+	for(int i=0; i< hs_len + 4; i++){
+		printf("%02x ", hs[i]);
+	}
+	printf("\n");
+
 	return 0;
 }
 
@@ -289,19 +295,20 @@ int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incom
 	seq = (incoming) ? f->read_seq : f->write_seq;
 
 	if(f->application && (ds->iv[EVP_GCM_TLS_FIXED_IV_LEN] == 0)){
+		printf("MERP\n");
 		//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 DEBUG
+//#ifdef DEBUG
 	printf("\t\tiv: ");
 	for(int i=0; i<ds->cipher->iv_len; i++){
 		printf("%02X ", ds->iv[i]);
 	}
 	printf("\n");
-#endif
+//#endif
 
 	uint8_t buf[13];
 	memcpy(buf, seq, 8);
@@ -323,16 +330,18 @@ int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incom
 	if(enc)
 		len += pad;
 
+	printf("len: %d\n", len);
+
 	int32_t n = EVP_Cipher(ds, p, p, len); //decrypt in place
 	if(n<0) return 0;
 
-#ifdef DEBUG
+//#ifdef DEBUG
 	printf("decrypted data:\n");
 	for(int i=0; i< len; i++){
 		printf("%02x ", p[EVP_GCM_TLS_EXPLICIT_IV_LEN+i]);
 	}
 	printf("\n");
-#endif
+//#endif
 
 	if(!enc)
 		p[EVP_GCM_TLS_EXPLICIT_IV_LEN+n] = '\0';
@@ -354,10 +363,11 @@ int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incom
  * 	Output:
  * 		0 on success, 1 on failure
  */
-int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
+int verify_finish_hash(flow *f, uint8_t *hs, int32_t incoming){
 	EVP_MD_CTX ctx;
 	uint8_t hash[EVP_MAX_MD_SIZE];
 	uint32_t hash_len;
+	uint8_t *p = hs;
 
 	EVP_MD_CTX_init(&ctx);
 	
@@ -367,10 +377,18 @@ int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
 	uint32_t fin_length = HANDSHAKE_MESSAGE_LEN(hs_hdr);
 	p += HANDSHAKE_HEADER_LEN;
 
-	//finalize hash of handshake msgs
+	//finalize hash of handshake msgs (have not yet added this one)
 	EVP_MD_CTX_copy_ex(&ctx, f->finish_md_ctx);
 	EVP_DigestFinal_ex(&ctx, hash, &hash_len);
 
+	if(incoming){
+		printf("expected md hash:\n");
+		for(int i=0; i< hash_len; i++){
+			printf("%02x ", hash[i]);
+		}
+		printf("\n");
+	}
+
 	//now use pseudorandom function
 	uint8_t *output = ecalloc(1, fin_length);
 
@@ -386,7 +404,48 @@ int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
 		goto err;
 	}
 
-	//now add in extra input to finished hash and replace
+	//now add extra input seeded with client-relay shared secret
+	if(incoming){
+		uint32_t extra_input_len = SSL3_RANDOM_SIZE;
+		uint8_t *extra_input = calloc(1, extra_input_len);
+
+		PRF(f, f->master_secret, SSL3_MASTER_SECRET_SIZE,
+			(uint8_t *) SLITHEEN_FINISHED_INPUT_CONST, SLITHEEN_FINISHED_INPUT_CONST_SIZE,
+			NULL, 0, NULL, 0, NULL, 0,
+			extra_input, extra_input_len);
+
+		printf("extra input:\n");
+		for(int i=0; i< extra_input_len; i++){
+			printf("%02x ", extra_input[i]);
+		}
+		printf("\n");
+
+		EVP_MD_CTX_copy_ex(&ctx, f->finish_md_ctx);
+		EVP_DigestUpdate(&ctx, extra_input, extra_input_len);
+
+		EVP_DigestFinal_ex(&ctx, hash, &hash_len);
+
+		printf("updated md hash:\n");
+		for(int i=0; i< hash_len; i++){
+			printf("%02x ", hash[i]);
+		}
+		printf("\n");
+
+		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);
+
+		printf("modified mac:\n");
+		for(int i=0; i< fin_length; i++){
+			printf("%02x ", output[i]);
+		}
+		printf("\n");
+
+		//replace existing MAC with modified one
+		memcpy(p, output, fin_length);
+
+	}
 
 	free(output);
 	EVP_MD_CTX_cleanup(&ctx);

+ 3 - 0
relay_station/crypto.h

@@ -39,6 +39,9 @@ int check_tag(byte key[16], const byte privkey[PTWIST_BYTES],
 #define SLITHEEN_KEYGEN_CONST "SLITHEEN_KEYGEN"
 #define SLITHEEN_KEYGEN_CONST_SIZE 15
 
+#define SLITHEEN_FINISHED_INPUT_CONST "SLITHEEN_FINISH"
+#define SLITHEEN_FINISHED_INPUT_CONST_SIZE 15
+
 #define SLITHEEN_SUPER_SECRET_SIZE 16 //extracted from slitheen ID tag
 #define SLITHEEN_SUPER_CONST "SLITHEEN_SUPER_ENCRYPT"
 #define SLITHEEN_SUPER_CONST_SIZE 22

+ 90 - 8
relay_station/flow.c

@@ -168,9 +168,14 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 			p += RECORD_HEADER_LEN;
 
 			if((incoming && f->in_encrypted) || (!incoming && f->out_encrypted)){
-#ifdef DEBUG_HS
+//#ifdef DEBUG_HS
 				printf("Decrypting finished (%d bytes) (%x:%d -> %x:%d)\n", record_len - RECORD_HEADER_LEN, f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
-#endif
+				printf("Finished ciphertext:\n");
+				for(int i=0; i< record_len; i++){
+					printf("%02x ", record[i]);
+				}
+				printf("\n");
+//#endif
 				int32_t n = encrypt(f, p, p, record_len - RECORD_HEADER_LEN, incoming, 0x16, 0);
 				if(n<=0){
 					printf("Error decrypting finished  (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
@@ -191,9 +196,13 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 					p[0] = 0x20; //trigger error
 				}
 
-				update_context(f, p, n, incoming, 0x16, 0);
-				if(incoming) f->in_encrypted = 2;
-				else f->out_encrypted = 2;
+				if(incoming){
+					f->in_encrypted = 2;
+				} else {
+					f->out_encrypted = 2;
+					update_context(f, p, n, incoming, 0x16, 0);
+				}
+
 			}
 			handshake_hdr = (struct handshake_header*) p;
 			f->state = handshake_hdr->type;
@@ -344,6 +353,25 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 						goto err;
 					}
 
+					//re-encrypt finished message
+					if(incoming){
+						//revert the sequence number
+						memset(f->read_seq, 0, 8);
+
+						int32_t n =  encrypt(f, record+RECORD_HEADER_LEN, record+RECORD_HEADER_LEN, record_len - (RECORD_HEADER_LEN+16), incoming, 0x16, 1);
+
+						printf("New finished ciphertext:\n");
+						for(int i=0; i< record_len; i++){
+							printf("%02x ", record[i]);
+						}
+						printf("\n");
+
+						if(n<=0){
+							printf("Error re-encrypting finished  (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port),
+									f->dst_ip.s_addr, ntohs(f->dst_port));
+						}
+					}
+
 					if((f->in_encrypted == 2) && (f->out_encrypted == 2)){
 						printf("Handshake complete!\n");
 						f->application = 1;
@@ -398,11 +426,9 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 			fflush(stdout);
 			goto err;
 	}
-	free(record);
 	return 0;
 
 err:
-	free(record);
 	return 1;
 }
 
@@ -957,8 +983,13 @@ int add_packet(flow *f, struct packet_info *info){
 		if(new_packet->seq_num == chain->expected_seq_num){
 			chain->expected_seq_num += new_packet->len;
 
+			uint32_t record_offset = 0; //offset into record for updating info with any changes
+			uint32_t info_offset = 0; //offset into info for updating with changes
+			uint32_t info_len = 0; //number of bytes that possibly changed
+
 			//while there is still data left:
 			uint32_t available_data = new_packet->len;
+
 			while(available_data > 0){
 
 				//if full record, give to update_flow
@@ -967,19 +998,30 @@ int add_packet(flow *f, struct packet_info *info){
 					uint8_t *record = emalloc(chain->record_len);
 					uint32_t record_len = chain->record_len;
 					uint32_t tmp_len = chain->record_len;
+
 					packet *next = chain->first_packet;
 					while(tmp_len > 0){
 						if(tmp_len >= next->len){
 							memcpy(record+chain->record_len - tmp_len, next->data, next->len);
+							if(next == new_packet){
+								new_packet = NULL;
+								record_offset = chain->record_len - tmp_len;
+								info_len = next->len;
+							}
+
 							tmp_len -= next->len;
 							chain->first_packet = next->next;
-							if(next == new_packet) new_packet = NULL;
 							free(next->data);
 							free(next);
 							next = chain->first_packet;
 							available_data = 0;
 						} else {
 							memcpy(record+chain->record_len - tmp_len, next->data, tmp_len);
+							if(next == new_packet){
+								record_offset = chain->record_len - tmp_len;
+								info_len = tmp_len;
+							}
+
 							memmove(next->data, next->data+tmp_len, next->len - tmp_len);
 							next->len -= tmp_len;
 							available_data -= tmp_len;
@@ -996,6 +1038,7 @@ int add_packet(flow *f, struct packet_info *info){
 						}
 					}
 					//if handshake is complete, send to relay code
+					//TODO: check to see if this code needs to replace info->data
 					if(f->application == 1){
 						//update packet info and send to replace_packet
 						printf("Packet contains application data!\n");
@@ -1007,6 +1050,45 @@ int add_packet(flow *f, struct packet_info *info){
 						free(copy_info);
 					} else {
 						update_flow(f, record, incoming);
+
+						//check to see if last finished message received
+						if(f->application ==1){
+							//TODO: replace finish message hash
+							printf("Replacing info->data with finished message (%d bytes).\n", info_len);
+
+							printf("Previous bytes:\n");
+							for(int i=0; i<info_len; i++){
+								printf("%02x ", info->app_data[info_offset+i]);
+							}
+							printf("\n");
+							printf("New bytes:\n");
+							for(int i=0; i<info_len; i++){
+								printf("%02x ", record[record_offset+i]);
+							}
+							printf("\n");
+
+							printf("SLITHEEN: Previous packet contents:\n");
+							for(int i=0; i< info->app_data_len; i++){
+								printf("%02x ", info->app_data[i]);
+							}
+							printf("\n");
+							memcpy(info->app_data+info_offset, record+record_offset, info_len);
+							printf("SLITHEEN: Current packet contents:\n");
+							for(int i=0; i< info->app_data_len; i++){
+								printf("%02x ", info->app_data[i]);
+							}
+							printf("\n");
+
+							//update TCP checksum
+							tcp_checksum(info);
+						}
+						free(record);
+
+						if(new_packet != NULL){
+							info_offset += info_len;
+							printf("updating info_offset to %d.\n", info_offset);
+						}
+
 					}
 				} else {
 					chain->remaining_record_len -= new_packet->len;