Example #1
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;

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

	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 */
	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] );

	data += SSL3_HEADER_LEN;
	len -= SSL3_HEADER_LEN;

#ifdef NM_TRACE_SSL_RECORD
	DEBUG_TRACE3( "\n==>Decoding SSL v3 Record from %s, type: %d, len: %d\n{\n", ((dir == ePacketDirFromClient)?"client":"server"), (int) record_type, (int) recLen );
#endif

	rc = DSSL_RC_OK;
	if( len < recLen ) { rc = DSSL_RC_WOULD_BLOCK; }

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

	/* 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->sess->version < TLS1_2_VERSION && 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*2];
		u_char* rec_mac = NULL;
		int l = EVP_MD_size( stack->md );
		int ivl = EVP_CIPHER_iv_length( stack->cipher->cipher );

		if ( EVP_CIPH_CBC_MODE == stack->sess->cipher_mode || EVP_CIPH_STREAM_CIPHER == stack->sess->cipher_mode )
			recLen -= l;
		rec_mac = data+recLen;

		memset(mac, 0, sizeof(mac) );
		
		/* TLS 1.1 and later: remove explicit IV for non-stream ciphers */
		if ( EVP_CIPH_CBC_MODE == stack->sess->cipher_mode )
		{
			if (stack->sess->version >= TLS1_1_VERSION )
			{
				if (ivl <= recLen) {
					recLen -= ivl;
					data += ivl;
				}
			}
		}

		/* AEAD ciphers have no mac */
		if ( EVP_CIPH_CBC_MODE == stack->sess->cipher_mode || EVP_CIPH_STREAM_CIPHER == stack->sess->cipher_mode )
		{
			rc = stack->sess->caclulate_mac_proc( stack, record_type, data, recLen, mac );

			if( rc == DSSL_RC_OK )
			{
				rc = memcmp( mac, rec_mac, l ) == 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_TRACE_BUF("decompressed", data, recLen);

	if( rc == DSSL_RC_OK )
	{
		switch( record_type )
		{
			case SSL3_RT_HANDSHAKE:
				next_decoder = &stack->dhandshake;
				break;

			case SSL3_RT_CHANGE_CIPHER_SPEC:
				next_decoder = &stack->dcss;
				break;

			case SSL3_RT_APPLICATION_DATA:
				next_decoder = &stack->dappdata;
				break;
			case SSL3_RT_ALERT:
				next_decoder = &stack->dalert;
				break;

			default:
				rc = NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR );
		}
	}

	if( rc == DSSL_RC_OK )
	{
		_ASSERT( next_decoder != NULL );
		rc = dssl_decoder_process( next_decoder, dir, data, recLen );
	}

	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;
	}

	return rc;
}
Example #2
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;
}