int tls1_change_cipher_state(SSL *s, int which) { static const unsigned char empty[]=""; unsigned char *p,*mac_secret; unsigned char *exp_label; unsigned char tmp1[EVP_MAX_KEY_LENGTH]; unsigned char tmp2[EVP_MAX_KEY_LENGTH]; unsigned char iv1[EVP_MAX_IV_LENGTH*2]; unsigned char iv2[EVP_MAX_IV_LENGTH*2]; unsigned char *ms,*key,*iv; int client_write; EVP_CIPHER_CTX *dd; const EVP_CIPHER *c; #ifndef OPENSSL_NO_COMP const SSL_COMP *comp; #endif const EVP_MD *m; int mac_type; int *mac_secret_size; EVP_MD_CTX *mac_ctx; EVP_PKEY *mac_key; int is_export,n,i,j,k,exp_label_len,cl; int reuse_dd = 0; is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); c=s->s3->tmp.new_sym_enc; m=s->s3->tmp.new_hash; mac_type = s->s3->tmp.new_mac_pkey_type; #ifndef OPENSSL_NO_COMP comp=s->s3->tmp.new_compression; #endif #ifdef KSSL_DEBUG fprintf(stderr,"tls1_change_cipher_state(which= %d) w/\n", which); fprintf(stderr,"\talg= %ld/%ld, comp= %p\n", s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, comp); fprintf(stderr,"\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c); fprintf(stderr,"\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n", c->nid,c->block_size,c->key_len,c->iv_len); fprintf(stderr,"\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length); { int i; for (i=0; i<s->s3->tmp.key_block_length; i++) fprintf(stderr,"%02x", s->s3->tmp.key_block[i]); fprintf(stderr,"\n"); } #endif /* KSSL_DEBUG */ if (which & SSL3_CC_READ) { if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; else s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; if (s->enc_read_ctx != NULL) reuse_dd = 1; else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) goto err; else /* make sure it's intialized in case we exit later with an error */ EVP_CIPHER_CTX_init(s->enc_read_ctx); dd= s->enc_read_ctx; mac_ctx=ssl_replace_hash(&s->read_hash,NULL); #ifndef OPENSSL_NO_COMP if (s->expand != NULL) { COMP_CTX_free(s->expand); s->expand=NULL; } if (comp != NULL) { s->expand=COMP_CTX_new(comp->method); if (s->expand == NULL) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); goto err2; } if (s->s3->rrec.comp == NULL) s->s3->rrec.comp=(unsigned char *) OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); if (s->s3->rrec.comp == NULL) goto err; } #endif /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ if (s->version != DTLS1_VERSION) memset(&(s->s3->read_sequence[0]),0,8); mac_secret= &(s->s3->read_mac_secret[0]); mac_secret_size=&(s->s3->read_mac_secret_size); } else { if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; else s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM; if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) reuse_dd = 1; else if ((s->enc_write_ctx=EVP_CIPHER_CTX_new()) == NULL) goto err; dd= s->enc_write_ctx; if (SSL_IS_DTLS(s)) { mac_ctx = EVP_MD_CTX_create(); if (!mac_ctx) goto err; s->write_hash = mac_ctx; } else mac_ctx = ssl_replace_hash(&s->write_hash,NULL); #ifndef OPENSSL_NO_COMP if (s->compress != NULL) { COMP_CTX_free(s->compress); s->compress=NULL; } if (comp != NULL) { s->compress=COMP_CTX_new(comp->method); if (s->compress == NULL) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); goto err2; } } #endif /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ if (s->version != DTLS1_VERSION) memset(&(s->s3->write_sequence[0]),0,8); mac_secret= &(s->s3->write_mac_secret[0]); mac_secret_size = &(s->s3->write_mac_secret_size); } if (reuse_dd) EVP_CIPHER_CTX_cleanup(dd); p=s->s3->tmp.key_block; i=*mac_secret_size=s->s3->tmp.new_mac_secret_size; cl=EVP_CIPHER_key_length(c); j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */ /* If GCM mode only part of IV comes from PRF */ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) k = EVP_GCM_TLS_FIXED_IV_LEN; else k=EVP_CIPHER_iv_length(c); if ( (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || (which == SSL3_CHANGE_CIPHER_SERVER_READ)) { ms= &(p[ 0]); n=i+i; key= &(p[ n]); n+=j+j; iv= &(p[ n]); n+=k+k; exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST; exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE; client_write=1; } else { n=i; ms= &(p[ n]); n+=i+j; key= &(p[ n]); n+=j+k; iv= &(p[ n]); n+=k; exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST; exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE; client_write=0; } if (n > s->s3->tmp.key_block_length) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR); goto err2; } memcpy(mac_secret,ms,i); if (!(EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER)) { mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, mac_secret,*mac_secret_size); EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key); EVP_PKEY_free(mac_key); } #ifdef TLS_DEBUG printf("which = %04X\nmac key=",which); { int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); } #endif if (is_export) { /* In here I set both the read and write key/iv to the * same value since only the correct one will be used :-). */ if (!tls1_PRF(ssl_get_algorithm2(s), exp_label,exp_label_len, s->s3->client_random,SSL3_RANDOM_SIZE, s->s3->server_random,SSL3_RANDOM_SIZE, NULL,0,NULL,0, key,j,tmp1,tmp2,EVP_CIPHER_key_length(c))) goto err2; key=tmp1; if (k > 0) { if (!tls1_PRF(ssl_get_algorithm2(s), TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE, s->s3->client_random,SSL3_RANDOM_SIZE, s->s3->server_random,SSL3_RANDOM_SIZE, NULL,0,NULL,0, empty,0,iv1,iv2,k*2)) goto err2; if (client_write) iv=iv1; else iv= &(iv1[k]); } } s->session->key_arg_length=0; #ifdef KSSL_DEBUG { int i; fprintf(stderr,"EVP_CipherInit_ex(dd,c,key=,iv=,which)\n"); fprintf(stderr,"\tkey= "); for (i=0; i<c->key_len; i++) fprintf(stderr,"%02x", key[i]); fprintf(stderr,"\n"); fprintf(stderr,"\t iv= "); for (i=0; i<c->iv_len; i++) fprintf(stderr,"%02x", iv[i]); fprintf(stderr,"\n"); } #endif /* KSSL_DEBUG */ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) { EVP_CipherInit_ex(dd,c,NULL,key,NULL,(which & SSL3_CC_WRITE)); EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv); } else EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */ if ((EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size) EVP_CIPHER_CTX_ctrl(dd,EVP_CTRL_AEAD_SET_MAC_KEY, *mac_secret_size,mac_secret); #ifdef TLS_DEBUG printf("which = %04X\nkey=",which); { int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); } printf("\niv="); { int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); } printf("\n"); #endif OPENSSL_cleanse(tmp1,sizeof(tmp1)); OPENSSL_cleanse(tmp2,sizeof(tmp1)); OPENSSL_cleanse(iv1,sizeof(iv1)); OPENSSL_cleanse(iv2,sizeof(iv2)); return(1); err: SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE); err2: return(0); }
int tls1_change_cipher_state(SSL *s, int which) { static const unsigned char empty[]=""; unsigned char *p,*key_block,*mac_secret; unsigned char *exp_label,buf[TLS_MD_MAX_CONST_SIZE+ SSL3_RANDOM_SIZE*2]; unsigned char tmp1[EVP_MAX_KEY_LENGTH]; unsigned char tmp2[EVP_MAX_KEY_LENGTH]; unsigned char iv1[EVP_MAX_IV_LENGTH*2]; unsigned char iv2[EVP_MAX_IV_LENGTH*2]; unsigned char *ms,*key,*iv,*er1,*er2; int client_write; EVP_CIPHER_CTX *dd; const EVP_CIPHER *c; const SSL_COMP *comp; const EVP_MD *m; int is_export,n,i,j,k,exp_label_len,cl; int reuse_dd = 0; is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); c=s->s3->tmp.new_sym_enc; m=s->s3->tmp.new_hash; comp=s->s3->tmp.new_compression; key_block=s->s3->tmp.key_block; #ifdef KSSL_DEBUG printf("tls1_change_cipher_state(which= %d) w/\n", which); printf("\talg= %ld, comp= %p\n", s->s3->tmp.new_cipher->algorithms, comp); printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c); printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n", c->nid,c->block_size,c->key_len,c->iv_len); printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length); { int i; for (i=0; i<s->s3->tmp.key_block_length; i++) printf("%02x", key_block[i]); printf("\n"); } #endif /* KSSL_DEBUG */ if (which & SSL3_CC_READ) { if (s->enc_read_ctx != NULL) reuse_dd = 1; else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) goto err; dd= s->enc_read_ctx; s->read_hash=m; if (s->expand != NULL) { COMP_CTX_free(s->expand); s->expand=NULL; } if (comp != NULL) { s->expand=COMP_CTX_new(comp->method); if (s->expand == NULL) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); goto err2; } if (s->s3->rrec.comp == NULL) s->s3->rrec.comp=(unsigned char *) OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); if (s->s3->rrec.comp == NULL) goto err; } memset(&(s->s3->read_sequence[0]),0,8); mac_secret= &(s->s3->read_mac_secret[0]); } else { if (s->enc_write_ctx != NULL) reuse_dd = 1; else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) goto err; if ((s->enc_write_ctx == NULL) && ((s->enc_write_ctx=(EVP_CIPHER_CTX *) OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) goto err; dd= s->enc_write_ctx; s->write_hash=m; if (s->compress != NULL) { COMP_CTX_free(s->compress); s->compress=NULL; } if (comp != NULL) { s->compress=COMP_CTX_new(comp->method); if (s->compress == NULL) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); goto err2; } } memset(&(s->s3->write_sequence[0]),0,8); mac_secret= &(s->s3->write_mac_secret[0]); } if (reuse_dd) EVP_CIPHER_CTX_cleanup(dd); EVP_CIPHER_CTX_init(dd); p=s->s3->tmp.key_block; i=EVP_MD_size(m); cl=EVP_CIPHER_key_length(c); j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */ k=EVP_CIPHER_iv_length(c); er1= &(s->s3->client_random[0]); er2= &(s->s3->server_random[0]); if ( (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || (which == SSL3_CHANGE_CIPHER_SERVER_READ)) { ms= &(p[ 0]); n=i+i; key= &(p[ n]); n+=j+j; iv= &(p[ n]); n+=k+k; exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST; exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE; client_write=1; } else { n=i; ms= &(p[ n]); n+=i+j; key= &(p[ n]); n+=j+k; iv= &(p[ n]); n+=k; exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST; exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE; client_write=0; } if (n > s->s3->tmp.key_block_length) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR); goto err2; } memcpy(mac_secret,ms,i); #ifdef TLS_DEBUG printf("which = %04X\nmac key=",which); { int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); } #endif if (is_export) { /* In here I set both the read and write key/iv to the * same value since only the correct one will be used :-). */ p=buf; memcpy(p,exp_label,exp_label_len); p+=exp_label_len; memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf),key,j, tmp1,tmp2,EVP_CIPHER_key_length(c)); key=tmp1; if (k > 0) { p=buf; memcpy(p,TLS_MD_IV_BLOCK_CONST, TLS_MD_IV_BLOCK_CONST_SIZE); p+=TLS_MD_IV_BLOCK_CONST_SIZE; memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,p-buf,empty,0, iv1,iv2,k*2); if (client_write) iv=iv1; else iv= &(iv1[k]); } } s->session->key_arg_length=0; #ifdef KSSL_DEBUG { int i; printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n"); printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]); printf("\n"); printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]); printf("\n"); } #endif /* KSSL_DEBUG */ EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); #ifdef TLS_DEBUG printf("which = %04X\nkey=",which); { int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); } printf("\niv="); { int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); } printf("\n"); #endif OPENSSL_cleanse(tmp1,sizeof(tmp1)); OPENSSL_cleanse(tmp2,sizeof(tmp1)); OPENSSL_cleanse(iv1,sizeof(iv1)); OPENSSL_cleanse(iv2,sizeof(iv2)); return(1); err: SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE); err2: return(0); }
int ssls_generate_keys( DSSL_Session* sess ) { DSSL_CipherSuite* suite = NULL; const EVP_CIPHER* c = NULL; const EVP_MD* digest = NULL; u_char* c_mac = NULL; u_char* c_wk = NULL; u_char* c_iv = NULL; u_char* s_mac = NULL; u_char* s_wk = NULL; u_char* s_iv = NULL; u_char export_iv_block[EVP_MAX_IV_LENGTH*2]; u_char export_c_wk[EVP_MAX_KEY_LENGTH]; u_char export_s_wk[EVP_MAX_KEY_LENGTH]; u_char keyblock[ TLS_MAX_KEYBLOCK_LEN ]; uint32_t keyblock_len = 0; uint32_t iv_len = 0; uint32_t wk_len = 0; uint32_t digest_len = 0; EVP_CIPHER_CTX* c_cipher = NULL; EVP_CIPHER_CTX* s_cipher = NULL; int rc = DSSL_RC_OK; _ASSERT( sess->c_dec.compression_data_new == NULL ); _ASSERT( sess->s_dec.compression_data_new == NULL ); _ASSERT( sess->c_dec.compression_method_new == 0 ); _ASSERT( sess->s_dec.compression_method_new == 0 ); /* set new compression algorithm */ if( sess->compression_method != 0 ) { sess->s_dec.compression_method_new = sess->compression_method; sess->c_dec.compression_method_new = sess->compression_method; dssl_compr_init( sess->s_dec.compression_method_new, &sess->s_dec.compression_data_new ); dssl_compr_init( sess->c_dec.compression_method_new, &sess->c_dec.compression_data_new ); } if( sess->c_dec.cipher_new != NULL ) { // _ASSERT( FALSE ); EVP_CIPHER_CTX_cleanup( sess->c_dec.cipher_new ); free( sess->c_dec.cipher_new ); sess->c_dec.cipher_new = NULL; } if( sess->s_dec.cipher_new != NULL ) { // _ASSERT( FALSE ); EVP_CIPHER_CTX_cleanup( sess->s_dec.cipher_new ); free( sess->s_dec.cipher_new ); sess->s_dec.cipher_new = NULL; } suite = DSSL_GetSSL3CipherSuite( sess->cipher_suite ); if( !suite ) return NM_ERROR( DSSL_E_SSL_CANNOT_DECRYPT ); c = EVP_get_cipherbyname( suite->enc ); digest = EVP_get_digestbyname( suite->digest ); /* calculate key length and IV length */ if( c != NULL ) { if( DSSL_CipherSuiteExportable( suite ) ) { wk_len = suite->export_key_bits / 8; } else { wk_len = EVP_CIPHER_key_length( c ); } iv_len = EVP_CIPHER_iv_length( c ); } if( digest != NULL ) digest_len = EVP_MD_size( digest ); /* calculate total keyblock length */ keyblock_len = (wk_len + digest_len + iv_len)*2; if( !keyblock_len ) return DSSL_RC_OK; if( sess->version == TLS1_VERSION ) { rc = tls1_PRF( sess->master_secret, sizeof( sess->master_secret ), "key expansion", sess->server_random, SSL3_RANDOM_SIZE, sess->client_random, SSL3_RANDOM_SIZE, keyblock, keyblock_len ); } else { rc = ssl3_PRF( sess->master_secret, sizeof( sess->master_secret ), sess->server_random, SSL3_RANDOM_SIZE, sess->client_random, SSL3_RANDOM_SIZE, keyblock, keyblock_len ); } /* init keying material pointers */ if( rc == DSSL_RC_OK ) { u_char* p = keyblock; if( digest_len ) { c_mac = p; p+= digest_len; s_mac = p; p+= digest_len; } if( c != NULL ) { c_wk = p; p+= wk_len; s_wk = p; p+= wk_len; /* generate final server and client write keys for exportable ciphers */ if( DSSL_CipherSuiteExportable( suite ) ) { int final_wk_len = EVP_CIPHER_key_length( c ); if( sess->version == TLS1_VERSION ) { tls1_PRF( c_wk, wk_len, "client write key", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, export_c_wk, final_wk_len ); tls1_PRF( s_wk, wk_len, "server write key", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, export_s_wk, final_wk_len ); } else { MD5_CTX md5; _ASSERT( sess->version == SSL3_VERSION ); MD5_Init( &md5 ); MD5_Update( &md5, c_wk, wk_len ); MD5_Update( &md5, sess->client_random, SSL3_RANDOM_SIZE ); MD5_Update( &md5, sess->server_random, SSL3_RANDOM_SIZE ); MD5_Final( export_c_wk, &md5 ); MD5_Init( &md5 ); MD5_Update( &md5, s_wk, wk_len ); MD5_Update( &md5, sess->server_random, SSL3_RANDOM_SIZE ); MD5_Update( &md5, sess->client_random, SSL3_RANDOM_SIZE ); MD5_Final( export_s_wk, &md5 ); } c_wk = export_c_wk; s_wk = export_s_wk; wk_len = final_wk_len; } } if( iv_len ) { if( DSSL_CipherSuiteExportable( suite ) ) { if( sess->version == TLS1_VERSION ) { tls1_PRF( NULL, 0, "IV block", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, export_iv_block, iv_len*2 ); } else { MD5_CTX md5; _ASSERT( sess->version == SSL3_VERSION ); MD5_Init( &md5 ); MD5_Update( &md5, sess->client_random, SSL3_RANDOM_SIZE ); MD5_Update( &md5, sess->server_random, SSL3_RANDOM_SIZE ); MD5_Final( export_iv_block, &md5 ); MD5_Init( &md5 ); MD5_Update( &md5, sess->server_random, SSL3_RANDOM_SIZE ); MD5_Update( &md5, sess->client_random, SSL3_RANDOM_SIZE ); MD5_Final( export_iv_block + iv_len, &md5 ); } c_iv = export_iv_block; s_iv = export_iv_block + iv_len; } else { c_iv = p; p+= iv_len; s_iv = p; p+= iv_len; } } else { c_iv = s_iv = NULL; } } /* create ciphers */ if( c != NULL && rc == DSSL_RC_OK ) { c_cipher = (EVP_CIPHER_CTX*) malloc( sizeof(EVP_CIPHER_CTX) ); s_cipher = (EVP_CIPHER_CTX*) malloc( sizeof(EVP_CIPHER_CTX) ); if( !c_cipher || !s_cipher ) { rc = NM_ERROR( DSSL_E_OUT_OF_MEMORY ); } } /* init ciphers */ if( c != NULL && rc == DSSL_RC_OK ) { EVP_CIPHER_CTX_init( c_cipher ); EVP_CipherInit( c_cipher, c, c_wk, c_iv, 0 ); EVP_CIPHER_CTX_init( s_cipher ); EVP_CipherInit( s_cipher, c, s_wk, s_iv, 0 ); } /* set session data */ if( rc == DSSL_RC_OK ) { _ASSERT( sess->c_dec.cipher_new == NULL ); _ASSERT( sess->s_dec.cipher_new == NULL ); sess->c_dec.cipher_new = c_cipher; c_cipher = NULL; sess->s_dec.cipher_new = s_cipher; s_cipher = NULL; if( digest ) { _ASSERT( EVP_MD_size( digest ) == (int)digest_len ); sess->c_dec.md_new = digest; sess->s_dec.md_new = digest; memcpy( sess->c_dec.mac_key_new, c_mac, digest_len ); memcpy( sess->s_dec.mac_key_new, s_mac, digest_len ); } } /* cleanup */ OPENSSL_cleanse( keyblock, keyblock_len ); if( c_cipher ) { free( c_cipher ); c_cipher = NULL; } if( s_cipher ) { free( c_cipher ); c_cipher = NULL; } return rc; }