|
@@ -207,37 +207,6 @@ static int nid_list[] = {
|
|
|
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
|
|
|
- *
|
|
|
- * Inputs:
|
|
|
- * f: the tagged flow
|
|
|
- * hs: A pointer to the start of the handshake message
|
|
|
- *
|
|
|
- * Output:
|
|
|
- * 0 on success, 1 on failure
|
|
|
- */
|
|
|
-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);
|
|
|
-
|
|
|
-#ifdef DEBUG
|
|
|
- printf("SLITHEEN: adding to finish mac computation:\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
|
|
|
*
|
|
@@ -544,128 +513,6 @@ int mark_finished_hash(flow *f, uint8_t *hs){
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/** Verifies the hash in a TLS finished message
|
|
|
- *
|
|
|
- * Adds string derived from the client-relay shared secret to the finished hash.
|
|
|
- * This feature detects and prevents suspicious behaviour in the event of a MiTM
|
|
|
- * or RAD attack.
|
|
|
- *
|
|
|
- * Inputs:
|
|
|
- * f: the tagged flow
|
|
|
- * p: a pointer to the TLS Finished handshake message
|
|
|
- * incoming: the direction of the flow
|
|
|
- *
|
|
|
- * Output:
|
|
|
- * 0 on success, 1 on failure
|
|
|
- */
|
|
|
-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);
|
|
|
-
|
|
|
- //get header length
|
|
|
- struct handshake_header *hs_hdr;
|
|
|
- hs_hdr = (struct handshake_header*) p;
|
|
|
- uint32_t fin_length = HANDSHAKE_MESSAGE_LEN(hs_hdr);
|
|
|
-
|
|
|
- //save old finished to update finished mac hash
|
|
|
- uint8_t *old_finished = emalloc(fin_length+ HANDSHAKE_HEADER_LEN);
|
|
|
- memcpy(old_finished, p, fin_length+HANDSHAKE_HEADER_LEN);
|
|
|
-
|
|
|
- p += HANDSHAKE_HEADER_LEN;
|
|
|
-
|
|
|
- //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);
|
|
|
-
|
|
|
- //now use pseudorandom function
|
|
|
- uint8_t *output = ecalloc(1, fin_length);
|
|
|
-
|
|
|
- if(incoming){
|
|
|
- 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, 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
|
|
|
- if(CRYPTO_memcmp(p, output, fin_length) != 0){
|
|
|
- printf("VERIFY FAILED\n");
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
-#ifdef DEBUG_HS
|
|
|
- printf("Old finished:\n");
|
|
|
- for(int i=0; i< fin_length; i++){
|
|
|
- printf("%02x ", p[i]);
|
|
|
- }
|
|
|
- printf("\n");
|
|
|
-#endif
|
|
|
-
|
|
|
- //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->key, 16,
|
|
|
- (uint8_t *) SLITHEEN_FINISHED_INPUT_CONST, SLITHEEN_FINISHED_INPUT_CONST_SIZE,
|
|
|
- NULL, 0, NULL, 0, NULL, 0,
|
|
|
- extra_input, extra_input_len);
|
|
|
-
|
|
|
-#ifdef DEBUG_HS
|
|
|
- printf("Extra input:\n");
|
|
|
- for(int i=0; i< extra_input_len; i++){
|
|
|
- printf("%02x ", extra_input[i]);
|
|
|
- }
|
|
|
- printf("\n");
|
|
|
-#endif
|
|
|
-
|
|
|
- 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);
|
|
|
-
|
|
|
- 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);
|
|
|
-
|
|
|
- //replace existing MAC with modified one
|
|
|
- memcpy(p, output, fin_length);
|
|
|
-
|
|
|
-#ifdef DEBUG_HS
|
|
|
- printf("New finished:\n");
|
|
|
- for(int i=0; i< fin_length; i++){
|
|
|
- printf("%02x ", p[i]);
|
|
|
- }
|
|
|
- printf("\n");
|
|
|
-#endif
|
|
|
-
|
|
|
- free(extra_input);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if(update_finish_hash(f, old_finished)){
|
|
|
- fprintf(stderr, "Error updating finish hash with FINISHED msg\n");
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- free(old_finished);
|
|
|
-
|
|
|
- free(output);
|
|
|
- EVP_MD_CTX_cleanup(&ctx);
|
|
|
- return 0;
|
|
|
-
|
|
|
-err:
|
|
|
- if(output != NULL)
|
|
|
- free(output);
|
|
|
- if(old_finished != NULL)
|
|
|
- free(old_finished);
|
|
|
- EVP_MD_CTX_cleanup(&ctx);
|
|
|
- return 1;
|
|
|
-}
|
|
|
|
|
|
/** Computes the TLS master secret from the decoy server's
|
|
|
* public key parameters and the leaked secret from the
|