Browse Source

implemented extended master secret computation

cecylia 7 years ago
parent
commit
5125f72068
4 changed files with 124 additions and 9 deletions
  1. 60 5
      relay_station/crypto.c
  2. 4 0
      relay_station/crypto.h
  3. 59 4
      relay_station/flow.c
  4. 1 0
      relay_station/flow.h

+ 60 - 5
relay_station/crypto.c

@@ -207,6 +207,36 @@ static int nid_list[] = {
     NID_brainpoolP512r1         /* brainpool512r1 (28) */
 };
 
+/** Updates the hash of all TLS handshake messages up to and
+ * including the ClientKeyExchange. This hash is eventually used
+ *  to compute the TLS extended master secret.
+ *
+ *  Inputs:
+ *  	f: the tagged flow
+ *  	hs: A pointer to the start of the handshake message
+ *
+ *  Output:
+ *  	0 on success, 1 on failure
+ */
+int update_handshake_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->hs_md_ctx, hs, hs_len+4);
+
+#ifdef DEBUG_HS
+	printf("SLITHEEN: adding to handshake hash:\n");
+	for(int i=0; i< hs_len + 4; i++){
+		printf("%02x ", hs[i]);
+	}
+	printf("\n");
+#endif
+
+	return 0;
+}
 /** Extracts the server parameters from the server key
  *  exchange message
  *
@@ -694,12 +724,31 @@ int compute_master_secret(flow *f){
 	}
 
 	/*Generate master secret */
-	
-	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->master_secret, f->master_secret, SSL3_MASTER_SECRET_SIZE);
-	}
+        if(f->extended_master_secret){
+
+            //compute session hash
+            EVP_MD_CTX ctx;
+            uint8_t hash[EVP_MAX_MD_SIZE*2];
+            uint32_t hash_len;
+
+            EVP_MD_CTX_init(&ctx);
+            EVP_MD_CTX_copy_ex(&ctx, f->hs_md_ctx);
+            EVP_DigestFinal_ex(&ctx, hash, &hash_len);
+
+            PRF(f, pre_master_secret, pre_master_len, (uint8_t *) TLS_MD_EXTENDED_MASTER_SECRET_CONST, TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, hash, hash_len, NULL, 0, NULL, 0, f->master_secret, SSL3_MASTER_SECRET_SIZE);
+#ifdef DEBUG_HS
+	fprintf(stdout, "Premaster Secret:\n");
+	BIO_dump_fp(stdout, (char *)pre_master_secret, pre_master_len);
+        fprintf(stdout, "Handshake hash:\n");
+	BIO_dump_fp(stdout, (char *)hash, hash_len);
+	fprintf(stdout, "Master Secret:\n");
+	BIO_dump_fp(stdout, (char *)f->master_secret, SSL3_MASTER_SECRET_SIZE);
+#endif
+
+        } else {
+	
+            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);
 
 #ifdef DEBUG_HS
 	fprintf(stdout, "Premaster Secret:\n");
@@ -711,6 +760,12 @@ int compute_master_secret(flow *f){
 	fprintf(stdout, "Master Secret:\n");
 	BIO_dump_fp(stdout, (char *)f->master_secret, SSL3_MASTER_SECRET_SIZE);
 #endif
+        }
+
+	if(f->current_session != NULL){
+		memcpy(f->current_session->master_secret, f->master_secret, SSL3_MASTER_SECRET_SIZE);
+	}
+
 
 	//remove pre_master_secret from memory
 	memset(pre_master_secret, 0, PRE_MASTER_MAX_LEN);

+ 4 - 0
relay_station/crypto.h

@@ -38,6 +38,7 @@
 /* Curves */
 
 
+int update_handshake_hash(flow *f, uint8_t *hs);
 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, uint8_t re);
 int fake_encrypt(flow *f, int32_t incoming);
@@ -72,4 +73,7 @@ int check_tag(byte key[16], const byte privkey[PTWIST_BYTES],
 #define SLITHEEN_SUPER_CONST "SLITHEEN_SUPER_ENCRYPT"
 #define SLITHEEN_SUPER_CONST_SIZE 22
 
+#define TLS_MD_EXTENDED_MASTER_SECRET_CONST "extended master secret"
+#define TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE 22
+
 #endif

+ 59 - 4
relay_station/flow.c

@@ -142,6 +142,10 @@ flow *add_flow(struct packet_info *info) {
 	new_flow->ecdh = NULL;
 	new_flow->dh = NULL;
 
+	new_flow->hs_md_ctx = EVP_MD_CTX_create();
+	const EVP_MD *md = EVP_sha256();
+	EVP_DigestInit_ex(new_flow->hs_md_ctx, md, NULL);
+
 	new_flow->cipher = NULL;
 	new_flow->clnt_read_ctx = NULL;
 	new_flow->clnt_write_ctx = NULL;
@@ -255,6 +259,12 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 						fprintf(stderr, "Error checking session, might cause problems\n");
 					}
 
+					if(update_handshake_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
+						remove_flow(f);
+						goto err;
+					}
+
 					break;
 				case TLS_SERV_HELLO:
 #ifdef DEBUG_HS
@@ -279,6 +289,11 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 						remove_flow(f);
 						goto err;
 					}
+					if(update_handshake_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
+						remove_flow(f);
+						goto err;
+					}
 					break;
 				case TLS_NEW_SESS:
 #ifdef DEBUG_HS
@@ -291,10 +306,20 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 				case TLS_CERT:
 #ifdef DEBUG_HS
 					printf("Received cert\n");
+					if(update_handshake_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
+						remove_flow(f);
+						goto err;
+					}
 #endif
 					break;
                                 case TLS_CERT_STATUS:
                                         printf("Received certificate status\n");
+					if(update_handshake_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
+						remove_flow(f);
+						goto err;
+					}
                                         break;
 				case TLS_SRVR_KEYEX:
 #ifdef DEBUG_HS
@@ -306,32 +331,57 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 						goto err;
 					}
 
-					if(compute_master_secret(f)){
-						printf("Error computing master secret\n");
+					if(update_handshake_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
 						remove_flow(f);
 						goto err;
-
 					}
 
 					break;
 
 				case TLS_CERT_REQ:
+					if(update_handshake_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
+						remove_flow(f);
+						goto err;
+					}
 					break;
 				case TLS_SRVR_HELLO_DONE:
 #ifdef DEBUG_HS
 					printf("Received server hello done\n");
 #endif
+					if(update_handshake_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
+						remove_flow(f);
+						goto err;
+					}
 					break;
 				case TLS_CERT_VERIFY:
 #ifdef DEBUG_HS
 					printf("received cert verify\n");
 #endif
+					if(update_handshake_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
+						remove_flow(f);
+						goto err;
+					}
 					break;
 
 				case TLS_CLNT_KEYEX:
 #ifdef DEBUG_HS
 					printf("Received client key exchange\n");
 #endif
+					if(update_handshake_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
+						remove_flow(f);
+						goto err;
+					}
+					if(compute_master_secret(f)){
+						printf("Error computing master secret\n");
+						remove_flow(f);
+						goto err;
+
+					}
 					break;
 				case TLS_FINISHED:
 #ifdef DEBUG_HS
@@ -510,6 +560,10 @@ int remove_flow(flow *f) {
     }
 
 	//Clean up cipher ctxs
+	EVP_MD_CTX_cleanup(f->hs_md_ctx);
+	if(f->hs_md_ctx != NULL){
+		EVP_MD_CTX_destroy(f->hs_md_ctx);
+	}
 	if(f->clnt_read_ctx != NULL){
 		EVP_CIPHER_CTX_cleanup(f->clnt_read_ctx);
 		OPENSSL_free(f->clnt_read_ctx);
@@ -869,7 +923,6 @@ int check_extensions(flow *f, uint8_t *hs, uint32_t len){
 		}
                 if(type == 0x17){//Extended Master Secret
                     f->extended_master_secret = 1;
-                    printf("Extended master secret extension\n");
                 }
 		p += ext_len;
 		extensions_len -= (4 + ext_len);
@@ -926,6 +979,8 @@ int verify_extensions(flow *f, uint8_t *hs, uint32_t len){
     //Check to make sure both client and server included extension
     if(!f->extended_master_secret || !extended_master_secret){
         f->extended_master_secret = 0;
+    } else {
+        printf("Extended master secret extension\n");
     }
 
     return 0;

+ 1 - 0
relay_station/flow.h

@@ -176,6 +176,7 @@ typedef struct flow_st {
 	EVP_CIPHER_CTX *srvr_write_ctx;
 	EVP_MD_CTX *read_mac_ctx;
 	EVP_MD_CTX *write_mac_ctx;
+        EVP_MD_CTX *hs_md_ctx;
 
 	uint8_t client_random[SSL3_RANDOM_SIZE];
 	uint8_t server_random[SSL3_RANDOM_SIZE];