|
@@ -2,6 +2,7 @@
|
|
|
#include <stdlib.h>
|
|
|
#include <stdint.h>
|
|
|
#include "flow.h"
|
|
|
+#include <openssl/evp.h>
|
|
|
#include <openssl/dh.h>
|
|
|
#include <openssl/bn.h>
|
|
|
#include <openssl/err.h>
|
|
@@ -45,6 +46,10 @@ flow *add_flow(flow newFlow) {
|
|
|
newFlow.in_encrypted = 0;
|
|
|
newFlow.out_encrypted = 0;
|
|
|
newFlow.packet_chain = NULL;
|
|
|
+ newFlow.finish_md_ctx = EVP_MD_CTX_create();
|
|
|
+ const EVP_MD *md = EVP_sha384();
|
|
|
+ EVP_DigestInit_ex(newFlow.finish_md_ctx, md, NULL);
|
|
|
+
|
|
|
*ptr = newFlow;
|
|
|
|
|
|
table->len ++;
|
|
@@ -105,15 +110,16 @@ int update_flow(flow *f) {
|
|
|
case HS:
|
|
|
p = record;
|
|
|
p += RECORD_HEADER_LEN;
|
|
|
- handshake_hdr = (struct handshake_header*) p;
|
|
|
|
|
|
//int size_hs = HANDSHAKE_MESSAGE_LEN(handshake_hdr);
|
|
|
printf("Handshake Message:\n");
|
|
|
- f->state = handshake_hdr->type;
|
|
|
|
|
|
if((incoming && f->in_encrypted) || (!incoming && f->out_encrypted)){
|
|
|
- decrypt_fin(f, p);
|
|
|
+ decrypt_fin(f, p, record_len - RECORD_HEADER_LEN, incoming);
|
|
|
+ p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
|
|
}
|
|
|
+ handshake_hdr = (struct handshake_header*) p;
|
|
|
+ f->state = handshake_hdr->type;
|
|
|
|
|
|
/* Now see if there's anything extra to do */
|
|
|
switch(f->state){
|
|
@@ -121,18 +127,22 @@ int update_flow(flow *f) {
|
|
|
case TLS_CLNT_HELLO:
|
|
|
/* Expecting server hello msg */
|
|
|
printf("Received client hello!\n");
|
|
|
+ //update_finish_hash(f, p);
|
|
|
break;
|
|
|
case TLS_SERV_HELLO:
|
|
|
extract_server_random(f, p);
|
|
|
+ //update_finish_hash(f, p);
|
|
|
printf("Received server hello!\n");
|
|
|
break;
|
|
|
case TLS_NEW_SESS:
|
|
|
printf("Received new session ticket!\n");
|
|
|
break;
|
|
|
case TLS_CERT:
|
|
|
+ //update_finish_hash(f, p);
|
|
|
printf("Received certificate!\n");
|
|
|
break;
|
|
|
case TLS_SRVR_KEYEX:
|
|
|
+ //update_finish_hash(f, p);
|
|
|
printf("Received server key exchange!\n");
|
|
|
/* Need to extract server params */
|
|
|
if(extract_parameters(f, p)){
|
|
@@ -143,22 +153,26 @@ int update_flow(flow *f) {
|
|
|
}
|
|
|
break;
|
|
|
case TLS_CERT_REQ:
|
|
|
+ //update_finish_hash(f, p);
|
|
|
printf("Received certificate request!\n");
|
|
|
break;
|
|
|
case TLS_SRVR_HELLO_DONE:
|
|
|
+ //update_finish_hash(f, p);
|
|
|
printf("Received server hello done!\n");
|
|
|
break;
|
|
|
case TLS_CERT_VERIFY:
|
|
|
+ //update_finish_hash(f, p);
|
|
|
printf("Received certificate verify!\n");
|
|
|
break;
|
|
|
case TLS_CLNT_KEYEX:
|
|
|
+ //update_finish_hash(f, p);
|
|
|
printf("Received client key exchange!\n");
|
|
|
break;
|
|
|
case TLS_FINISHED:
|
|
|
printf("Received finished message!\n");
|
|
|
break;
|
|
|
default:
|
|
|
- printf("Error?\n");
|
|
|
+ printf("Error? %02x\n",p[0]);
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
@@ -172,6 +186,8 @@ int update_flow(flow *f) {
|
|
|
} else {
|
|
|
f->out_encrypted = 1;
|
|
|
}
|
|
|
+ /*Initialize ciphers */
|
|
|
+ init_ciphers(f);
|
|
|
break;
|
|
|
case ALERT:
|
|
|
printf("Alert\n");
|
|
@@ -339,6 +355,22 @@ int add_packet(flow *f, uint8_t *p){
|
|
|
|
|
|
/** UTILITY **/
|
|
|
|
|
|
+int update_finish_hash(flow *f, uint8_t *hs){
|
|
|
+ EVP_MD_CTX *ctx = f->finish_md_ctx;
|
|
|
+ //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);
|
|
|
+
|
|
|
+ /* Now compute SHA384(secret, A+seed)
|
|
|
+ * can't sign update, don't have master secret yet*/
|
|
|
+ EVP_DigestUpdate(&ctx, hs, hs_len);
|
|
|
+
|
|
|
+ return 1;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
int extract_parameters(flow *f, uint8_t *hs){
|
|
|
DH *dh;
|
|
|
uint8_t *p;
|
|
@@ -353,11 +385,6 @@ int extract_parameters(flow *f, uint8_t *hs){
|
|
|
/* Extract prime modulus */
|
|
|
n2s(p,i);
|
|
|
|
|
|
- printf("Server p:\n");
|
|
|
- for(int j=0; j<i; j++){
|
|
|
- printf("%02x ",p[j]);
|
|
|
- }
|
|
|
- printf("\n");
|
|
|
if(!(dh->p = BN_bin2bn(p,i,NULL))){
|
|
|
return 1;
|
|
|
}
|
|
@@ -366,11 +393,6 @@ int extract_parameters(flow *f, uint8_t *hs){
|
|
|
/* Extract generator */
|
|
|
n2s(p,i);
|
|
|
|
|
|
- printf("Server g:\n");
|
|
|
- for(int j=0; j<i; j++){
|
|
|
- printf("%02x ",p[j]);
|
|
|
- }
|
|
|
- printf("\n");
|
|
|
if(!(dh->g = BN_bin2bn(p,i,NULL))){
|
|
|
return 1;
|
|
|
}
|
|
@@ -379,11 +401,6 @@ int extract_parameters(flow *f, uint8_t *hs){
|
|
|
/* Extract server public value */
|
|
|
n2s(p,i);
|
|
|
|
|
|
- printf("Server pub_key:\n");
|
|
|
- for(int j=0; j<i; j++){
|
|
|
- printf("%02x ",p[j]);
|
|
|
- }
|
|
|
- printf("\n");
|
|
|
if(!(dh->pub_key = BN_bin2bn(p,i,NULL))){
|
|
|
return 1;
|
|
|
}
|
|
@@ -393,8 +410,95 @@ int extract_parameters(flow *f, uint8_t *hs){
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/* Decrypt the TLS FINISHED message */
|
|
|
-int decrypt_fin(flow *f, uint8_t *hs){
|
|
|
+/* Decrypt the TLS FINISHED message
|
|
|
+ * Verify that the data is:
|
|
|
+ * PRF(master_secret, finished_label, Hash(handshake_messages))*/
|
|
|
+int decrypt_fin(flow *f, uint8_t *hs, int32_t len, int32_t incoming){
|
|
|
+ //const struct handshake_header *hs_hdr;
|
|
|
+ uint8_t *p = hs;
|
|
|
+ //EVP_MD_CTX ctx;
|
|
|
+ //uint8_t hash[EVP_MAX_MD_SIZE];
|
|
|
+ //int32_t hash_len;
|
|
|
+
|
|
|
+ //EVP_MD_CTX_init(&ctx);
|
|
|
+
|
|
|
+ //decrypt
|
|
|
+ EVP_CIPHER_CTX *ds = (incoming) ? f->read_ctx : f->write_ctx;
|
|
|
+ if(ds == NULL){
|
|
|
+ printf("FAIL\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ if(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];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+//#ifdef KSSL_DEBUG
|
|
|
+ {
|
|
|
+ fprintf(stderr, "\t\tIV: ");
|
|
|
+ for (int i = 0; i < ds->cipher->iv_len; i++)
|
|
|
+ fprintf(stderr, "%02X", ds->iv[i]);
|
|
|
+ fprintf(stderr, "\n");
|
|
|
+ }
|
|
|
+//#endif /* KSSL_DEBUG */
|
|
|
+
|
|
|
+
|
|
|
+ int32_t bs = EVP_CIPHER_block_size(ds->cipher);
|
|
|
+ //padding stuff? TODO: understand this
|
|
|
+ uint8_t buf[13];
|
|
|
+ memset(buf, 0, 8);
|
|
|
+ buf[8] = 0x16;
|
|
|
+ buf[9] = 0x03;
|
|
|
+ buf[10] = 0x03;
|
|
|
+ buf[11] = 0x00; //len >> 8;
|
|
|
+ buf[12] = 0x28; //len *0xff;
|
|
|
+ printf("buf: \n");
|
|
|
+ for(int z=0; z< 13; z++){
|
|
|
+ printf("%02x ", buf[z]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ int32_t pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
|
|
|
+ 13, buf);
|
|
|
+ printf("pad: %d\n", pad);
|
|
|
+
|
|
|
+ printf("Decrypting (%d bytes):\n", len);
|
|
|
+ for(int i=0; i<len; i++){
|
|
|
+ printf("%02x ", p[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ int32_t n = EVP_Cipher(ds, p, p, len); //decrypt in place
|
|
|
+
|
|
|
+ p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
|
|
+ len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
|
|
+ //print out decrypted record
|
|
|
+ printf("Record (decrypted %d/%d bytes): \n", n, len);
|
|
|
+ for(int i=0; i<n; i++){
|
|
|
+ printf("%02x ", p[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ /*get context
|
|
|
+
|
|
|
+ //get header length
|
|
|
+ hs_hdr = (struct handshake_header*) p;
|
|
|
+ uint32_t fin_length = HANDSHAKE_MESSAGE_LEN(hs_hdr);
|
|
|
+ p += HANDSHAKE_HEADER_LEN;
|
|
|
+
|
|
|
+ //finalize hash of handshake msgs
|
|
|
+ EVP_MD_CTX_copy_ex(&ctx, f->finish_md_ctx);
|
|
|
+ EVP_DigestFinal(&ctx, hash, &hash_len);
|
|
|
+
|
|
|
+ //now use pseudorandom function
|
|
|
+ uint8_t *output = calloc(1, fin_length);
|
|
|
+ PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, finished_label, finished_label_len, hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
|
|
|
+
|
|
|
+ //now compare
|
|
|
+
|
|
|
+*/
|
|
|
+
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
@@ -445,26 +549,18 @@ int compute_master_secret(flow *f){
|
|
|
dh_clnt->priv_key = priv_key;
|
|
|
|
|
|
// Compute master key
|
|
|
- uint8_t master_secret[SSL3_MASTER_SECRET_SIZE];
|
|
|
uint8_t *pre_master_secret = calloc(1, 256);//TODO: find right length
|
|
|
|
|
|
- int32_t len = DH_compute_key(pre_master_secret, dh_srvr->pub_key, dh_clnt);
|
|
|
+ DH_compute_key(pre_master_secret, dh_srvr->pub_key, dh_clnt);
|
|
|
|
|
|
- printf("Output of compute key:\n");
|
|
|
- for(int j=0; j<len; j++){
|
|
|
- printf("%02x ", pre_master_secret[j]);
|
|
|
- }
|
|
|
- printf("\n");
|
|
|
-
|
|
|
- PRF(pre_master_secret, f->client_random, f->server_random,
|
|
|
- master_secret);
|
|
|
+ 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 ", master_secret[i]);
|
|
|
+ printf("%02x ", f->master_secret[i]);
|
|
|
}
|
|
|
printf("\n");
|
|
|
|
|
@@ -488,7 +584,12 @@ void extract_server_random(flow *f, uint8_t *hs){
|
|
|
}
|
|
|
|
|
|
/* PRF using sha384, as defined in RFC 5246 */
|
|
|
-int PRF(uint8_t *secret, uint8_t *client_random, uint8_t *server_random, uint8_t *output){
|
|
|
+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;
|
|
@@ -497,7 +598,7 @@ int PRF(uint8_t *secret, uint8_t *client_random, uint8_t *server_random, uint8_t
|
|
|
uint8_t A[EVP_MAX_MD_SIZE];
|
|
|
size_t len, A_len;
|
|
|
int chunk = EVP_MD_size(md);
|
|
|
- int remaining = SSL_MAX_MASTER_KEY_LENGTH;
|
|
|
+ int remaining = output_len;
|
|
|
|
|
|
uint8_t *out = output;
|
|
|
|
|
@@ -506,25 +607,43 @@ int PRF(uint8_t *secret, uint8_t *client_random, uint8_t *server_random, uint8_t
|
|
|
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, PRE_MASTER_LEN);
|
|
|
+ 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);
|
|
|
- EVP_DigestSignUpdate(&ctx, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE);
|
|
|
- EVP_DigestSignUpdate(&ctx, client_random, SSL3_RANDOM_SIZE);
|
|
|
- EVP_DigestSignUpdate(&ctx, server_random, SSL3_RANDOM_SIZE);
|
|
|
+ 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) */
|
|
|
+ /* 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);
|
|
|
- EVP_DigestSignUpdate(&ctx, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE);
|
|
|
- EVP_DigestSignUpdate(&ctx, client_random, SSL3_RANDOM_SIZE);
|
|
|
- EVP_DigestSignUpdate(&ctx, server_random, SSL3_RANDOM_SIZE);
|
|
|
+ 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);
|
|
@@ -542,3 +661,94 @@ int PRF(uint8_t *secret, uint8_t *client_random, uint8_t *server_random, uint8_t
|
|
|
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);
|
|
|
+ fprintf(stderr, "\t\tIV: ");
|
|
|
+ for (int i = 0; i < r_ctx->cipher->iv_len; i++)
|
|
|
+ fprintf(stderr, "%02X", r_ctx->iv[i]);
|
|
|
+ fprintf(stderr, "\n");
|
|
|
+ fprintf(stderr, "\t\tIV: ");
|
|
|
+ for (int i = 0; i < w_ctx->cipher->iv_len; i++)
|
|
|
+ fprintf(stderr, "%02X", w_ctx->iv[i]);
|
|
|
+ fprintf(stderr, "\n");
|
|
|
+ f->read_ctx = r_ctx;
|
|
|
+ f->write_ctx = w_ctx;
|
|
|
+}
|