#include #include #include #include #include #include #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; icipher->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; ifinish_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; ikey[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; }