Hello, Where is the symmetric key stored during an SSL transaction? There is a place for it (deep) inside of the ssl structure at ssl->s3->tmp.key_block with length of ssl->s3->tmp.key_block_length However these are never populated on any connection that I make. It seems odd to me that encryption/decryption can happen without a symmetric key, but at surface value that seems to be what is happening. I have done quite a bit of digging on this and found a function (or 4) that is supposed to generate the key block (tls1_generate_key_block() and all the functions it calls), and then I can partition it out the keys according to the TLSv1 RFC (http://www.ietf.org/rfc/rfc2246.txt page 14) but it seems that whenever I do this I cannot use this key to decrypt the data from the transaction (using the IV from the key block as well). So either my Key, or IV, or both are incorrect. The "label" I am using (as per TLSv1 spec) is "key expansion" however I have no idea if that is the correct value. I've attached the code I am currently using to generate the key block. It's a lot to digest, but it's better to be more verbose, than lacking in detail. Long story short, if there is a better way to access the the session key I would like to know about it. Thank you for any input or feedback you can provide.
-Sam -- Sam Jantz Software Engineer
/* Copyright (C) 1995-1998 Eric Young (e...@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (e...@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (t...@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (e...@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (t...@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* ==================================================================== * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-c...@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (e...@cryptsoft.com). This product includes software written by Tim * Hudson (t...@cryptsoft.com). * */ /* ==================================================================== * Copyright 2005 Nokia. All rights reserved. * * The portions of the attached software ("Contribution") is developed by * Nokia Corporation and is licensed pursuant to the OpenSSL open source * license. * * The Contribution, originally written by Mika Kousa and Pasi Eronen of * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites * support (see RFC 4279) to OpenSSL. * * No patent licenses or other rights except those expressly stated in * the OpenSSL open source license shall be deemed granted or received * expressly, by implication, estoppel, or otherwise. * * No assurances are provided by Nokia that the Contribution does not * infringe the patent or other intellectual property rights of any third * party or that the license provides you with all the necessary rights * to make use of the Contribution. * * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR * OTHERWISE. */ #ifndef GET_SESSION_KEY_H #define GET_SESSION_KEY_H #define SSL_MD_MD5_IDX 0 #define SSL_MD_SHA1_IDX 1 #define SSL_MD_GOST94_IDX 2 #define SSL_MD_GOST89MAC_IDX 3 #define SSL_MD_NUM_IDX 4 #define TLS1_PRF_DGST_SHIFT 8 #define SSL_HANDSHAKE_MAC_MD5 0x10 #define SSL_HANDSHAKE_MAC_SHA 0x20 #define SSL_HANDSHAKE_MAC_GOST94 0x40 #define SSL_ENC_DES_IDX 0 #define SSL_ENC_3DES_IDX 1 #define SSL_ENC_RC4_IDX 2 #define SSL_ENC_RC2_IDX 3 #define SSL_ENC_IDEA_IDX 4 #define SSL_ENC_NULL_IDX 5 #define SSL_ENC_AES128_IDX 6 #define SSL_ENC_AES256_IDX 7 #define SSL_ENC_CAMELLIA128_IDX 8 #define SSL_ENC_CAMELLIA256_IDX 9 #define SSL_ENC_GOST89_IDX 10 #define SSL_ENC_SEED_IDX 11 #define SSL_ENC_NUM_IDX 12 #define SSL_MD5 0x00000001L #define SSL_SHA1 0x00000002L #define SSL_GOST94 0x00000004L #define SSL_GOST89MAC 0x00000008L #define SSL_DES 0x00000001L #define SSL_3DES 0x00000002L #define SSL_RC4 0x00000004L #define SSL_RC2 0x00000008L #define SSL_IDEA 0x00000010L #define SSL_eNULL 0x00000020L #define SSL_AES128 0x00000040L #define SSL_AES256 0x00000080L #define SSL_CAMELLIA128 0x00000100L #define SSL_CAMELLIA256 0x00000200L #define SSL_eGOST2814789CNT 0x00000400L #define SSL_SEED 0x00000800L #define SSL_AES (SSL_AES128|SSL_AES256) #define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256) #define SSL_COMP_NULL_IDX 0 #define SSL_COMP_ZLIB_IDX 1 #define SSL_COMP_NUM_IDX 2 //tls and sslv3 session key aquisition functions. #include <stdio.h> #include <iostream> #include <openssl/ssl.h> #include <openssl/engine.h> #include <openssl/evp.h> #include <openssl/hmac.h> #include <openssl/md5.h> #include <openssl/crypto.h> #include <openssl/objects.h> #include <openssl/comp.h> #include "proxythread.h" #include <string> using namespace globalvel; using namespace std; //Static members: static int ssl_handshake_digest_flag[SSL_MD_NUM_IDX]={ SSL_HANDSHAKE_MAC_MD5,SSL_HANDSHAKE_MAC_SHA, SSL_HANDSHAKE_MAC_GOST94,0 }; static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={ NULL,NULL,NULL,NULL }; static int ssl_mac_secret_size[SSL_MD_NUM_IDX]={ 0,0,0,0 }; static int ssl_mac_pkey_id[SSL_MD_NUM_IDX]={ EVP_PKEY_HMAC,EVP_PKEY_HMAC,EVP_PKEY_HMAC,NID_undef }; static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={ NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, }; static STACK_OF(SSL_COMP) *ssl_comp_methods=NULL; //Meta functions: int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md) { if (idx <0||idx>=SSL_MD_NUM_IDX) { return 0; } if (ssl_handshake_digest_flag[idx]==0) return 0; *mask = ssl_handshake_digest_flag[idx]; *md = ssl_digest_methods[idx]; return 1; } static void loadDigest(){ ssl_cipher_methods[SSL_ENC_DES_IDX]= EVP_get_cipherbyname(SN_des_cbc); ssl_cipher_methods[SSL_ENC_3DES_IDX]= EVP_get_cipherbyname(SN_des_ede3_cbc); ssl_cipher_methods[SSL_ENC_RC4_IDX]= EVP_get_cipherbyname(SN_rc4); ssl_cipher_methods[SSL_ENC_RC2_IDX]= EVP_get_cipherbyname(SN_rc2_cbc); #ifndef OPENSSL_NO_IDEA ssl_cipher_methods[SSL_ENC_IDEA_IDX]= EVP_get_cipherbyname(SN_idea_cbc); #else ssl_cipher_methods[SSL_ENC_IDEA_IDX]= NULL; #endif ssl_cipher_methods[SSL_ENC_AES128_IDX]= EVP_get_cipherbyname(SN_aes_128_cbc); ssl_cipher_methods[SSL_ENC_AES256_IDX]= EVP_get_cipherbyname(SN_aes_256_cbc); ssl_cipher_methods[SSL_ENC_CAMELLIA128_IDX]= EVP_get_cipherbyname(SN_camellia_128_cbc); ssl_cipher_methods[SSL_ENC_CAMELLIA256_IDX]= EVP_get_cipherbyname(SN_camellia_256_cbc); ssl_cipher_methods[SSL_ENC_GOST89_IDX]= EVP_get_cipherbyname(SN_gost89_cnt); ssl_cipher_methods[SSL_ENC_SEED_IDX]= EVP_get_cipherbyname(SN_seed_cbc); ssl_digest_methods[SSL_MD_MD5_IDX]= EVP_get_digestbyname(SN_md5); ssl_mac_secret_size[SSL_MD_MD5_IDX]= EVP_MD_size(ssl_digest_methods[SSL_MD_MD5_IDX]); OPENSSL_assert(ssl_mac_secret_size[SSL_MD_MD5_IDX] >= 0); ssl_digest_methods[SSL_MD_SHA1_IDX]= EVP_get_digestbyname(SN_sha1); ssl_mac_secret_size[SSL_MD_SHA1_IDX]= EVP_MD_size(ssl_digest_methods[SSL_MD_SHA1_IDX]); OPENSSL_assert(ssl_mac_secret_size[SSL_MD_SHA1_IDX] >= 0); ssl_digest_methods[SSL_MD_GOST94_IDX]= EVP_get_digestbyname(SN_id_GostR3411_94); if (ssl_digest_methods[SSL_MD_GOST94_IDX]) { ssl_mac_secret_size[SSL_MD_GOST94_IDX]= EVP_MD_size(ssl_digest_methods[SSL_MD_GOST94_IDX]); OPENSSL_assert(ssl_mac_secret_size[SSL_MD_GOST94_IDX] >= 0); } ssl_digest_methods[SSL_MD_GOST89MAC_IDX]= EVP_get_digestbyname(SN_id_Gost28147_89_MAC); //ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac"); //if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]) { ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX]=32; //} return; } static int sk_comp_cmp(const SSL_COMP * const *a, const SSL_COMP * const *b) { return((*a)->id-(*b)->id); } static void load_builtin_compressions(void) { int got_write_lock = 0; CRYPTO_r_lock(CRYPTO_LOCK_SSL); if (ssl_comp_methods == NULL) { CRYPTO_r_unlock(CRYPTO_LOCK_SSL); CRYPTO_w_lock(CRYPTO_LOCK_SSL); got_write_lock = 1; if (ssl_comp_methods == NULL) { SSL_COMP *comp = NULL; MemCheck_off(); ssl_comp_methods=sk_SSL_COMP_new(sk_comp_cmp); if (ssl_comp_methods != NULL) { comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP)); if (comp != NULL) { comp->method=COMP_zlib(); if (comp->method && comp->method->type == NID_undef) OPENSSL_free(comp); else { comp->id=SSL_COMP_ZLIB_IDX; comp->name=comp->method->name; sk_SSL_COMP_push(ssl_comp_methods,comp); } } } MemCheck_on(); } } if (got_write_lock) CRYPTO_w_unlock(CRYPTO_LOCK_SSL); else CRYPTO_r_unlock(CRYPTO_LOCK_SSL); } void ssl3_cleanup_key_block(SSL *s) { if (s->s3->tmp.key_block != NULL) { OPENSSL_cleanse(s->s3->tmp.key_block, s->s3->tmp.key_block_length); OPENSSL_free(s->s3->tmp.key_block); s->s3->tmp.key_block=NULL; } s->s3->tmp.key_block_length=0; } int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size,SSL_COMP **comp, SSL* ssl) { int i; const SSL_CIPHER *c; c=SSL_get_current_cipher(ssl); if (c == NULL) return(0); if (comp != NULL) { SSL_COMP ctmp; #ifndef OPENSSL_NO_COMP load_builtin_compressions(); #endif *comp=NULL; ctmp.id=s->compress_meth; if (ssl_comp_methods != NULL) { i=sk_SSL_COMP_find(ssl_comp_methods,&ctmp); if (i >= 0) *comp=sk_SSL_COMP_value(ssl_comp_methods,i); else *comp=NULL; } } if ((enc == NULL) || (md == NULL)) return(0); //modified to search for the cipher name in the cipher string. This prevents the null error that was happening. string ciphName(SSL_CIPHER_get_name(c)); if(string::npos != ciphName.find("RC4")){ i=SSL_ENC_RC4_IDX; }else if(string::npos != ciphName.find("3DES")){ i=SSL_ENC_3DES_IDX; }else if(string::npos != ciphName.find("DES")){ i=SSL_ENC_DES_IDX; }else if(string::npos != ciphName.find("RC2")){ i=SSL_ENC_RC2_IDX; }else if(string::npos != ciphName.find("IDEA")){ i=SSL_ENC_IDEA_IDX; }else if(string::npos != ciphName.find("eNULL")){ i=SSL_ENC_NULL_IDX; }else if(string::npos != ciphName.find("AES128")){ i=SSL_ENC_AES128_IDX; }else if(string::npos != ciphName.find("AES256")){ i=SSL_ENC_AES256_IDX; }else if(string::npos != ciphName.find("CAMELLIA128")){ i=SSL_ENC_CAMELLIA128_IDX; }else if(string::npos != ciphName.find("CAMELLIA256")){ i=SSL_ENC_CAMELLIA256_IDX; }else if(string::npos != ciphName.find("eGOST2814789CNT")){ i=SSL_ENC_GOST89_IDX; }else if(string::npos != ciphName.find("SEED")){ i=SSL_ENC_SEED_IDX; }else{ cerr << "Unrecognized cipher" << endl; i=-1; } if ((i < 0) || (i > SSL_ENC_NUM_IDX)) *enc=NULL; else { if (i == SSL_ENC_NULL_IDX) *enc=EVP_enc_null(); else *enc=ssl_cipher_methods[i]; } //Modified search for cipher name, and use it. if(string::npos != ciphName.find("MD5")){ i=SSL_MD_MD5_IDX; }else if(string::npos != ciphName.find("SHA")){ i=SSL_MD_SHA1_IDX; }else if(string::npos != ciphName.find("GOST94")){ i=SSL_MD_GOST94_IDX; }else if(string::npos != ciphName.find("GOST89MAC")){ i=SSL_MD_GOST89MAC_IDX; }else{ i = -1; } if ((i < 0) || (i > SSL_MD_NUM_IDX)) { *md=NULL; if (mac_pkey_type!=NULL) *mac_pkey_type = NID_undef; if (mac_secret_size!=NULL) *mac_secret_size = 0; } else { *md=ssl_digest_methods[i]; if (mac_pkey_type!=NULL) *mac_pkey_type = ssl_mac_pkey_id[i]; if (mac_secret_size!=NULL) *mac_secret_size = ssl_mac_secret_size[i]; } if ((*enc != NULL) && (*md != NULL) && (!mac_pkey_type||*mac_pkey_type != NID_undef)) return(1); else return(0); } //End meta functions //Session key stuff: static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, int sec_len, const void *seed1, int seed1_len, const void *seed2, int seed2_len, const void *seed3, int seed3_len, const void *seed4, int seed4_len, const void *seed5, int seed5_len, unsigned char *out, int olen) { int chunk,n; unsigned int j; HMAC_CTX ctx; HMAC_CTX ctx_tmp; unsigned char A1[EVP_MAX_MD_SIZE]; unsigned int A1_len; int ret = 0; chunk=EVP_MD_size(md); OPENSSL_assert(chunk >= 0); HMAC_CTX_init(&ctx); HMAC_CTX_init(&ctx_tmp); if (!HMAC_Init_ex(&ctx,sec,sec_len,md, NULL)) goto err; if (!HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL)) goto err; if (seed1 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed1,seed1_len)) goto err; if (seed2 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed2,seed2_len)) goto err; if (seed3 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed3,seed3_len)) goto err; if (seed4 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed4,seed4_len)) goto err; if (seed5 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed5,seed5_len)) goto err; if (!HMAC_Final(&ctx,A1,&A1_len)) goto err; n=0; for (;;) { if (!HMAC_Init_ex(&ctx,NULL,0,NULL,NULL)) /* re-init */ goto err; if (!HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL)) /* re-init */ goto err; if (!HMAC_Update(&ctx,A1,A1_len)) goto err; if (!HMAC_Update(&ctx_tmp,A1,A1_len)) goto err; if (seed1 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed1,seed1_len)) goto err; if (seed2 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed2,seed2_len)) goto err; if (seed3 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed3,seed3_len)) goto err; if (seed4 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed4,seed4_len)) goto err; if (seed5 != NULL && !HMAC_Update(&ctx,(unsigned char *)seed5,seed5_len)) goto err; if (olen > chunk) { if (!HMAC_Final(&ctx,out,&j)) goto err; out+=j; olen-=j; if (!HMAC_Final(&ctx_tmp,A1,&A1_len)) /* calc the next A1 value */ goto err; } else /* last one */ { if (!HMAC_Final(&ctx,A1,&A1_len)) goto err; memcpy(out,A1,olen); break; } } ret = 1; err: HMAC_CTX_cleanup(&ctx); HMAC_CTX_cleanup(&ctx_tmp); OPENSSL_cleanse(A1,sizeof(A1)); return ret; } //The PRF used to generate key blocks static int tls1_PRF(long digest_mask, const void *seed1, int seed1_len, const void *seed2, int seed2_len, const void *seed3, int seed3_len, const void *seed4, int seed4_len, const void *seed5, int seed5_len, const unsigned char *sec, int slen, unsigned char *out1, unsigned char *out2, int olen) { int len,i,idx,count; const unsigned char *S1; long m; const EVP_MD *md; int ret = 0; /* Count number of digests and partition sec evenly */ count=0; for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) { if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) count++; } if(count < 1) count = 1; len=slen/count; S1=sec; memset(out1,0,olen); for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) { if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) { if (!md) { continue;//nothing to do here, so go to next itteration. } if (!tls1_P_hash(md ,S1,len+(slen&1), seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,seed4,seed4_len,seed5,seed5_len, out2,olen)){ goto err; } S1+=len; for (i=0; i<olen; i++) { out1[i]^=out2[i]; } } } ret = 1; err: return ret; } static int tls1_generate_key_block(SSL *s, unsigned char *km, unsigned char *tmp, int num, SSL_SESSION* ses) { int ret; long bits = 0xFFFFFFFFFFFFFFFF; ret = tls1_PRF(bits, //s->s3->tmp.new_cipher->algorithm2, TLS_MD_CLIENT_WRITE_KEY_CONST,TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE, s->s3->server_random,SSL3_RANDOM_SIZE, s->s3->client_random,SSL3_RANDOM_SIZE, NULL,0,NULL,0, ses->master_key,ses->master_key_length, km,tmp,num); return ret; } //Main Function that gets the session key. static int getSessionKey(SSL* ssl, ProxyThread * thread){ SSL_SESSION* ses = SSL_get1_session(ssl); if(ses->ssl_version != SSL2_VERSION){ loadDigest(); unsigned char *p1,*p2=NULL; const EVP_CIPHER *c; const EVP_MD *hash; int num; SSL_COMP *comp; int mac_type= NID_undef,mac_secret_size=0; if (ssl->s3->tmp.key_block_length != 0) return(1); if (!ssl_cipher_get_evp(ses,&c,&hash,&mac_type,&mac_secret_size,&comp, ssl)) { cout << "failhat" << endl; SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE); return(1); } ssl->s3->tmp.new_sym_enc=c; ssl->s3->tmp.new_hash=hash; ssl->s3->tmp.new_mac_pkey_type = mac_type; ssl->s3->tmp.new_mac_secret_size = mac_secret_size; num=EVP_CIPHER_key_length(c)+mac_secret_size+EVP_CIPHER_iv_length(c); num*=2; ssl3_cleanup_key_block(ssl); if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL) { SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE); goto err; } ssl->s3->tmp.key_block_length=num; ssl->s3->tmp.key_block=p1; if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL) { SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE); goto err; } //generate the key block here if(!tls1_generate_key_block(ssl, p1, p2, num, ses)) goto err; /* Keys are generated in this order: (RFC 2246 [TLSv1 Protocol]) client write MAC secret server write MAC secret client write key server write key client write IV server write IV */ int offset = 2*mac_secret_size; int keySize = EVP_CIPHER_key_length(c); unsigned char client_session_key[keySize]; for(int i=0;i<keySize;i++){ client_session_key[i] = ssl->s3->tmp.key_block[i+offset]; } offset += (2*keySize); keySize = EVP_CIPHER_iv_length(c); unsigned char client_iv[keySize]; for(int i=0;i<keySize;i++){ client_iv[i] = ssl->s3->tmp.key_block[i+offset]; } const char * ver = (ssl->version == 769)?"TLSv1":"SSLv3"; printf("Version: %s\n", ver); printf("Client Session Key:\t"); int count = 1; string ciphName = SSL_get_cipher_name(ssl); if(ciphName.find("DES-CBC3-SHA")!= string::npos){ count = 3; } for(int j=0;j<count;j++){ for(int i=0;i<EVP_CIPHER_key_length(c);i++) printf("%02X", client_session_key[i]); } printf("\t Key Size: %d\nClient IV:\t\t", EVP_CIPHER_key_length(c)); for(int i=0;i<EVP_CIPHER_iv_length(c);i++) printf("%02X", client_iv[i]); printf("\t\t\t\t\t IV SIZE: %d\n", keySize); }else{ //it's sslv2, kill the connection. thread->shutdown(); SSL_SESSION_free(ses); return 1; } SSL_SESSION_free(ses); return 0; err: thread->shutdown(); SSL_SESSION_free(ses); return 1; } #endif /*GET_SESSION_KEY_H*/