Beispiel #1
0
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 );
		}
	}
}
Beispiel #2
0
int ssls_set_session_version( DSSL_Session* sess, uint16_t ver )
{
	int rc = DSSL_RC_OK;

	sess->version = ver;

	switch( ver )
	{
	case SSL3_VERSION:
		DEBUG_TRACE0("ssls_set_session_version - SSL3_VERSION\n");
		sess->decode_finished_proc = ssl3_decode_finished;
		sess->caclulate_mac_proc  = ssl3_calculate_mac;
		/* convert SSL v2 CHALLENGE to SSL v3+ CLIENT_RANDOM */
		if(sess->flags & SSF_SSLV2_CHALLENGE) 
			ssls_convert_v2challenge(sess);
		break;

	case TLS1_VERSION:
		DEBUG_TRACE0("ssls_set_session_version - TLS1_VERSION\n");
		sess->decode_finished_proc = tls1_decode_finished;
		sess->caclulate_mac_proc = tls1_calculate_mac;
		/* convert SSL v2 CHALLENGE to SSL v3+ CLIENT_RANDOM */
		if(sess->flags & SSF_SSLV2_CHALLENGE) 
			ssls_convert_v2challenge(sess);
		break;

	case SSL2_VERSION:
		DEBUG_TRACE0("ssls_set_session_version - SSL2_VERSION\n");
		sess->decode_finished_proc = NULL;
		sess->caclulate_mac_proc = ssl2_calculate_mac;
		break;

	case TLS1_1_VERSION:
	case TLS1_2_VERSION:
		DEBUG_TRACE0("ssls_set_session_version - TLS1_X_VERSION\n");
		sess->decode_finished_proc = tls1_decode_finished;
		sess->caclulate_mac_proc = tls1_calculate_mac;
		if(sess->flags & SSF_SSLV2_CHALLENGE) 
			ssls_convert_v2challenge(sess);
		break;

	default:
		DEBUG_TRACE0("ssls_set_session_version - unsupported.. \n");
		rc = NM_ERROR( DSSL_E_SSL_UNKNOWN_VERSION );
		break;
	}

	return rc;
}
Beispiel #3
0
void DSSL_SessionDeInit( DSSL_Session* s )
{
#ifdef NM_TRACE_SSL_SESSIONS
	DEBUG_TRACE0( "DSSL_SessionDeInit\n" );
#endif

	if( s->env ) DSSL_EnvOnSessionClosing( s->env, s );

	dssl_decoder_stack_deinit( &s->c_dec );
	dssl_decoder_stack_deinit( &s->s_dec );

	ssls_free_extension_data(s);

	EVP_MD_CTX_cleanup( &s->handshake_digest_md5 );
	EVP_MD_CTX_cleanup( &s->handshake_digest_sha );
}
Beispiel #4
0
void DSSL_SessionInit( DSSL_Env* env, DSSL_Session* s, DSSL_ServerInfo* si )
{
	_ASSERT( s );

#ifdef NM_TRACE_SSL_SESSIONS
	DEBUG_TRACE0( "DSSL_SessionInit\n" );
#endif
	memset( s, 0, sizeof(*s) );

	s->ssl_si = si;
	s->env = env;

	dssl_decoder_stack_init( &s->c_dec );
	dssl_decoder_stack_init( &s->s_dec );

	EVP_MD_CTX_init( &s->handshake_digest_md5 );
	EVP_MD_CTX_init( &s->handshake_digest_sha );
}
Beispiel #5
0
static int ssl_decrypt_record( dssl_decoder_stack* stack, u_char* data, uint32_t len, 
					  u_char** out, uint32_t* out_len, int *buffer_aquired,int *block_size )
{
	u_char* buf = NULL;
	uint32_t buf_len = len;
	int rc = DSSL_RC_OK;
	const EVP_CIPHER* c = NULL;
	int func_ret = 0;
	int i = 0;

	DEBUG_TRACE3("ssl_decrypt_record - len: %d, out_len: %d, buffer_aquired: %d\n", len, *out_len, buffer_aquired);

	_ASSERT( stack );
	_ASSERT( stack->sess );
	_ASSERT( stack->cipher );

	rc = ssls_get_decrypt_buffer( stack->sess, &buf, buf_len );
	DEBUG_TRACE1("ssl_decrypt_record - calling ssls_get_decrypt_buffer ended. ret: %d\n", rc);

	// test
	//memset(buf, 0x77, DSSL_MAX_COMPRESSED_LENGTH);
	/*
	for (i = 0; i < 128; i++)
	{
		printf("ssl_decrypt_record(1) - buf[%d]: 0x%02X, data: 0x%02X\n", i, buf[i], data[i]);
	}
	*/

	if( rc != DSSL_RC_OK ) return rc;

	*buffer_aquired = 1;

	c = EVP_CIPHER_CTX_cipher( stack->cipher );
	*block_size = EVP_CIPHER_block_size( c );

	DEBUG_TRACE1("ssl_decrypt_record - calling EVP_CIPHER_block_size ended. ret: %d\n", *block_size);

	if( *block_size != 1 )
	{
		if( len == 0 || (len % *block_size) != 0 )
		{
			DEBUG_TRACE0("ssl_decrypt_record - DSSL_E_SSL_DECRYPTION_ERROR(after EVP_CIPHER_block_size)\n");
			return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR );
		}
	}

	func_ret = EVP_Cipher(stack->cipher, buf, data, len );
	DEBUG_TRACE1("ssl_decrypt_record - calling EVP_Cipher ret: %d\n", func_ret);

	buf_len = len;
	DEBUG_TRACE1("ssl_decrypt_record - buf_len: %d\n", buf_len);

	/*
	for (i = 0; i < 128; i++)
	{
		printf("ssl_decrypt_record(2) - buf[%d]: 0x%02X, data: 0x%02X\n", i, buf[i], data[i]);
	}
	*/

	/* strip the padding */
	if( *block_size > 1 )
	{
		if( buf[len-1] >= buf_len - 1 ) {
			DEBUG_TRACE0("ssl_decrypt_record - DSSL_E_SSL_DECRYPTION_ERROR(after EVP_Cipher)\n");
			return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR );
		}
		buf_len -= buf[len-1] + 1;
	}

	*out = buf;
	*out_len = buf_len;

	return DSSL_RC_OK;
}
Beispiel #6
0
int ssl3_record_layer_decoder( void* decoder_stack, NM_PacketDir dir,
		u_char* data, uint32_t len, uint32_t* processed )
{
	int rc = DSSL_E_UNSPECIFIED_ERROR;
	uint32_t recLen = 0, totalRecLen = 0;
	uint8_t record_type = 0;
	dssl_decoder_stack* stack = (dssl_decoder_stack*) decoder_stack;
	dssl_decoder* next_decoder = NULL;
	int decrypt_buffer_aquired = 0;
	int decompress_buffer_aquired = 0;
	int i = 0;
	char * data2 = NULL;
	uint32_t recLen2 = 0;
	int block_size = 0;


	DEBUG_TRACE1("ssl_record_layer_decoder - start. len: %d\n", len);

	_ASSERT( stack );
	_ASSERT( processed );
	_ASSERT( stack->sess );

	/*
	for (i=0; i < len; i++)
	{
		printf("0x%02X ", data[i]);
	}
	*/

	if( stack->state > SS_Established )
	{
#ifdef NM_TRACE_SSL_RECORD
		DEBUG_TRACE1( "[!]Unexpected SSL record after %s", 
			( (stack->state == SS_FatalAlert) ? "fatal alert" : "close_notify alert") );
#endif
		return NM_ERROR( DSSL_E_SSL_UNEXPECTED_TRANSMISSION );
	}

	/* special case for a first client hello */
	DEBUG_TRACE1("ssl_record_layer_decoder - version: 0x%02X\n", stack->sess->version);
	if( stack->sess->version == 0 )
	{
		_ASSERT( dir == ePacketDirFromClient );
		rc = ssl_decode_first_client_hello( stack->sess, data, len, processed );
		return rc;
	}

	if( len < SSL3_HEADER_LEN ) return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
	if( data[1] != 3) return NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR );

	/* Decode record type */
	record_type = data[0];
	totalRecLen = recLen = MAKE_UINT16( data[3], data[4] );
	DEBUG_TRACE1("ssl_record_layer_decoder - record_type: %d\n", record_type);
	DEBUG_TRACE1("ssl_record_layer_decoder - recLen: %d\n", recLen);

	/*
	for (i = 0; i < 128; i++)
	{
		printf("ssl_tls_record_layer_decoder - data before skip header size [%d]: %d\n", i, data[i]);
	}
	*/

	data += SSL3_HEADER_LEN;
	len -= SSL3_HEADER_LEN;

	DEBUG_TRACE1("ssl_record_layer_decoder - len after header adjustments: %d\n", len);
	/*
	for (i=0; i < len; i++)
	{
		printf("0x%02X ", data[i]);
	}
	*/

#ifdef NM_TRACE_SSL_RECORD
	DEBUG_TRACE2( "\n==>Decoding SSL v3 Record, type: %d, len: %d\n{\n", (int) record_type, (int) recLen );
#endif

	rc = DSSL_RC_OK;
	if( len < recLen ) 
	{ 
		rc = DSSL_RC_WOULD_BLOCK; 
		DEBUG_TRACE0("ssl_tls_record_layer_decoder - rc is DSSL_RC_WOULD_BLOCK\n");
	}

	if( rc == DSSL_RC_OK && stack->cipher )
	{
		rc = ssl_decrypt_record( stack, data, recLen, &data, &recLen, &decrypt_buffer_aquired,&block_size );

		DEBUG_TRACE1("ssl_record_layer_decoder - ssl_decrypt_record ret: %d\n", rc);
	}

	/* check if the record length is still within bounds (failed decryption, etc) */
	if( rc == DSSL_RC_OK && (recLen > RFC_2246_MAX_COMPRESSED_LENGTH || 
		recLen > len || (stack->md && recLen < EVP_MD_size(stack->md))) )
	{
		rc = NM_ERROR(DSSL_E_SSL_INVALID_RECORD_LENGTH);
	}

	if( rc == DSSL_RC_OK && stack->md )
	{
		u_char mac[EVP_MAX_MD_SIZE];
		u_char* rec_mac = NULL;
		
		DEBUG_TRACE1("ssl_record_layer_decoder - data using len: %d\n", len);
		/*
		for (i=0; i < len; i++)
		{
			printf("0x%02X ", data[i]);
		}
		*/

		recLen -= EVP_MD_size( stack->md );
		rec_mac = data+recLen;

		memset(mac, 0, sizeof(mac) );
		
		// Fix - skip iv for TLS 1.1
		DEBUG_TRACE1("ssl_record_layer_decoder - stack->version: 0x%02X\n", stack->version);
		DEBUG_TRACE1("ssl_record_layer_decoder - block_size: %d\n", block_size);

		if (stack->version > TLS1_VERSION && block_size > 1)
		{
			DEBUG_TRACE0("ssl_record_layer_decoder - activated fix for TLS 1.1 (skip 16 bytes)\n");

			data2 = data + block_size;
			recLen2 = recLen - block_size;
			rc = stack->sess->caclulate_mac_proc( stack, record_type, data2, recLen2, mac );
		}
		else
		{
			rc = stack->sess->caclulate_mac_proc( stack, record_type, data, recLen, mac );
		}

		DEBUG_TRACE1("ssl_record_layer_decoder - caclulate_mac_proc result: %d\n", rc);
		
		if( rc == DSSL_RC_OK )
		{
			DEBUG_TRACE1("ssl_record_layer_decoder - caclulate_mac_proc memcmp size(i.e. EVP_MD_size(stack->md)): %d\n", EVP_MD_size(stack->md));
			DEBUG_TRACE0("ssl_record_layer_decoder - mac vs. rec_mac:\n");
			if (IsDebugEnabled())
			{
				for (i=0; i < EVP_MD_size(stack->md); i++)
				{
					DEBUG_TRACE2("0x%02X vs. 0x%02X\n", mac[i], rec_mac[i]);
				}
			}
			rc = memcmp( mac, rec_mac, EVP_MD_size(stack->md) ) == 0 ? DSSL_RC_OK : NM_ERROR( DSSL_E_SSL_INVALID_MAC );
		}
	}

	if( rc == DSSL_RC_OK && stack->compression_method != 0 )
	{
		rc = ssl_decompress_record( stack, data, recLen, &data, &recLen, &decompress_buffer_aquired );

		DEBUG_TRACE1("ssl_record_layer_decoder - ssl_decompress_record call ended. rc: %d\n", rc);
	}

	if( rc == DSSL_RC_OK )
	{
		DEBUG_TRACE1("ssl_record_layer_decoder - record_type: %d\n", record_type);
		switch( record_type )
		{
			case SSL3_RT_HANDSHAKE:
				DEBUG_TRACE0("ssl_record_layer_decoder - SSL3_RT_HANDSHAKE\n");
				next_decoder = &stack->dhandshake;
				break;

			case SSL3_RT_CHANGE_CIPHER_SPEC:
				DEBUG_TRACE0("ssl_record_layer_decoder - SSL3_RT_CHANGE_CIPHER_SPEC\n");
				next_decoder = &stack->dcss;
				break;

			case SSL3_RT_APPLICATION_DATA:
				DEBUG_TRACE0("ssl_record_layer_decoder - SSL3_RT_APPLICATION_DATA\n");
				next_decoder = &stack->dappdata;
				break;

			case SSL3_RT_ALERT:
				DEBUG_TRACE0("ssl_record_layer_decoder - SSL3_RT_ALERT\n");
				next_decoder = &stack->dalert;
				break;

			default:
				DEBUG_TRACE0("ssl_record_layer_decoder - record_type not found\n");
				rc = NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR );
		}
	}

	if( rc == DSSL_RC_OK )
	{
		_ASSERT( next_decoder != NULL );
		
		DEBUG_TRACE1("ssl_record_layer_decoder - calling dssl_decoder_process. handler is: %x\n", next_decoder->handler);
		
		// Fix - for TLS 1.1 continue
		if (data2 == NULL)
			rc = dssl_decoder_process( next_decoder, dir, data, recLen );
		else
			rc = dssl_decoder_process( next_decoder, dir, data2, recLen2 );

		DEBUG_TRACE1("ssl_record_layer_decoder - dssl_decoder_process ret: %d\n", rc);
	}

	if( rc == DSSL_RC_OK )
	{
		*processed = totalRecLen + SSL3_HEADER_LEN;
	}

	if( decrypt_buffer_aquired )
	{
		ssls_release_decrypt_buffer( stack->sess );
	}

	if( decompress_buffer_aquired )
	{
		ssls_release_decompress_buffer( stack->sess );
	}

#ifdef NM_TRACE_SSL_RECORD
	DEBUG_TRACE1( "\n} rc: %d\n", (int) rc);
#endif

	if( stack->state == SS_SeenCloseNotify )
	{
		stack->sess->flags |= SSF_CLOSE_NOTIFY_RECEIVED;
	} else if ( stack->state == SS_FatalAlert )
	{
		stack->sess->flags |= SSF_FATAL_ALERT_RECEIVED;
	}

	DEBUG_TRACE1("ssl_record_layer_decoder - end. rc = %d\n", rc);

	return rc;
}
Beispiel #7
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 ) {
		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;
}
Beispiel #8
0
/* ========== Handshake decoding function ========== */
int ssl3_decode_handshake_record( dssl_decoder_stack* stack, NM_PacketDir dir,
								 u_char* data, uint32_t len, uint32_t* processed )
{
	int rc = DSSL_E_UNSPECIFIED_ERROR;
	uint32_t recLen = 0;
	u_char hs_type = 0;
	u_char* org_data = data;
	DSSL_Session* sess = stack->sess;
	_ASSERT( processed != NULL );
	_ASSERT((sess->flags & SSF_SSLV2_CHALLENGE) == 0);

	if( sess->version == 0 )
	{
		return ssl_decode_first_client_hello( sess, data, len, processed );
	}

	if( len < SSL3_HANDSHAKE_HEADER_LEN ) return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );

	DEBUG_TRACE_BUF("handshake", data, len);
	recLen = (((int32_t)data[1]) << 16) | (((int32_t)data[2]) << 8) | data[3];
	hs_type = data[0];

	data += SSL3_HANDSHAKE_HEADER_LEN;
	len -= SSL3_HANDSHAKE_HEADER_LEN;

	if( len < recLen )return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );

#ifdef NM_TRACE_SSL_HANDSHAKE
	DEBUG_TRACE2( "===>Decoding SSL v3 handshake: %s len: %d...", SSL3_HandshakeTypeToString( hs_type ), (int) recLen );
#endif

	switch( hs_type )
	{
	case SSL3_MT_HELLO_REQUEST:
		rc = ssl3_decode_dummy( sess, data, recLen );
		break;

	case SSL3_MT_CLIENT_HELLO:
		rc = ssl3_decode_client_hello( sess, data, recLen );
		break;

	case SSL3_MT_SERVER_HELLO:
		stack->state = SS_SeenServerHello;
		rc = ssl3_decode_server_hello( sess, data, recLen );
		break;

	case SSL3_MT_CERTIFICATE:
		if( dir == ePacketDirFromServer )
		{
			rc = ssl3_decode_server_certificate( sess, data, recLen );
		}
		else
		{
			rc = ssl3_decode_dummy( sess, data, recLen );
		}
		break;

	case SSL3_MT_SERVER_DONE:
		rc = ssl3_decode_dummy( sess, data, recLen );
		break;

	case SSL3_MT_CLIENT_KEY_EXCHANGE:
		rc = ssl3_decode_client_key_exchange( sess, data, recLen );
		break;

	case SSL3_MT_FINISHED:
		rc = (*sess->decode_finished_proc)( sess, dir, data, recLen );
		if( rc == DSSL_RC_OK ) {
			stack->state = SS_Established;
			ssls_handshake_done( sess );
		}
		break;
		
	case SSL3_MT_CERTIFICATE_STATUS:
		rc = ssl3_decode_dummy( sess, data, recLen );
		break;
	
	case SSL3_MT_SERVER_KEY_EXCHANGE:
		/*at this point it is clear that the session is not decryptable due to ephemeral keys usage.*/
		rc = NM_ERROR( DSSL_E_SSL_CANNOT_DECRYPT_EPHEMERAL );
		break;

	case SSL3_MT_CERTIFICATE_REQUEST:
		/* TODO: track CertificateRequest- client certificate / certificate verify */
		rc = ssl3_decode_dummy( sess, data, recLen );
		break;

	case SSL3_MT_CERTIFICATE_VERIFY:
		/* TODO: track CertificateRequest- client certificate / certificate verify */
		rc = ssl3_decode_dummy( sess, data, recLen );
		break;

	case SSL3_MT_NEWSESSION_TICKET:
		rc = ssl3_decode_new_session_ticket( sess, data, recLen );
		break;

	default:
		rc = NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR );
		break;
	}

	if( rc == DSSL_RC_OK )
	{
		*processed = recLen + SSL3_HANDSHAKE_HEADER_LEN;

		if( hs_type == SSL3_MT_CLIENT_HELLO ) 
		{
			ssl3_init_handshake_digests( sess );
		}

		if( hs_type != SSL3_MT_HELLO_REQUEST )
		{
			ssl3_update_handshake_digests( sess, org_data, *processed );
		}
	}

#ifdef NM_TRACE_SSL_HANDSHAKE
	if( rc == DSSL_RC_OK )
	{
		DEBUG_TRACE0( "OK\n" );
	}
	else
	{
		DEBUG_TRACE1( "Error! (%d)\n", (int)rc );
	}
#endif

	return rc;
}