int ssls_decode_master_secret( DSSL_Session* sess ) { EVP_MD *md; DSSL_CipherSuite* suite = NULL; switch( sess->version ) { case SSL3_VERSION: return ssl3_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); case TLS1_VERSION: return tls1_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, "master secret", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); default: DEBUG_TRACE1("ssls_decode_master_secret - version: 0x%02X\n", sess->version); if (sess->version == TLS1_1_VERSION) { DEBUG_TRACE0("ssls_decode_master_secret - supported for 1.1\n"); return tls1_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, "master secret", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); } else if (sess->version == TLS1_2_VERSION) { DEBUG_TRACE0("ssls_decode_master_secret - supported for 1.2\n"); /* suite = DSSL_GetSSL3CipherSuite( sess->cipher_suite ); md=EVP_get_digestbyname(suite->digest); */ return tls12_PRF( "SHA256"/*suite->digest*/, sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, "master secret", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); } else { DEBUG_TRACE0("ssls_decode_master_secret - DSSL_E_NOT_IMPL\n"); return NM_ERROR( DSSL_E_NOT_IMPL ); } } }
int ssls_decode_master_secret( DSSL_Session* sess ) { switch( sess->version ) { case SSL3_VERSION: return ssl3_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); case TLS1_VERSION: return tls1_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, "master secret", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); default: return NM_ERROR( DSSL_E_NOT_IMPL ); } }
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 ) { DEBUG_TRACE0("ssls_generate_keys - failed to find cipher suite\n"); return NM_ERROR( DSSL_E_SSL_CANNOT_DECRYPT ); } if (suite->enc != NULL && strlen(suite->enc) < 32) strcpy(sess->cipher_encoding, suite->enc); if (suite->digest != NULL && strlen(suite->digest) < 32) strcpy(sess->cipher_digest, suite->digest); 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 || sess->version == TLS1_1_VERSION) { DEBUG_TRACE0("ssls_generate_keys - calling tls1_PRF\n"); 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 if( sess->version == TLS1_2_VERSION) { DEBUG_TRACE0("ssls_generate_keys - calling tls12_PRF\n"); rc = tls12_PRF( "SHA256"/*sess->cipher_digest*/, 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 { DEBUG_TRACE0("ssls_generate_keys - calling ssl3_PRF\n"); 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 || sess->version == TLS1_1_VERSION ) { DEBUG_TRACE0("ssls_generate_keys - calling tls1_PRF (2)\n"); 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 if( sess->version == TLS1_2_VERSION) { DEBUG_TRACE1("ssls_generate_keys - calling tls12_PRF (2) - sess->cipher_digest: %s\n", sess->cipher_digest); tls12_PRF( "SHA256"/*sess->cipher_digest*/,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 ); tls12_PRF( "SHA256"/*sess->cipher_digest*/,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; DEBUG_TRACE0("ssls_generate_keys - MD5_CTX handling\n"); _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 || sess->version == TLS1_1_VERSION ) { DEBUG_TRACE0("ssls_generate_keys - calling tls1_PRF (3)\n"); 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 if( sess->version == TLS1_2_VERSION) { DEBUG_TRACE1("ssls_generate_keys - calling tls12_PRF (3) - sess->cipher_digest: %s\n", sess->cipher_digest); tls12_PRF( "SHA256"/*sess->cipher_digest*/, 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; DEBUG_TRACE0("ssls_generate_keys - MD5_CTX handling (2)\n"); _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 ) { DEBUG_TRACE0("ssls_generate_keys - EVP_CIPHER_CTX_init\n"); 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 ); } else { DEBUG_TRACE0("ssls_generate_keys - not calling EVP_CIPHER_CTX_init\n"); } /* 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 ) { DEBUG_TRACE1("ssls_generate_keys - identified digest. len: %d\n", digest_len); _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; }