/*
* Creation date : Tues Mar 03 09:00:00 2007
* Last modified : %modify_time%
*/
/** @file
* \brief This file contains implementation of 
* AES (Advanced Encryption Standard) functions. 
*
* \version CE2_AES.c#1:csrc:1
* \author Yermalayeu Ihar
* \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
* All Rights reserved
*/

/************************ Include Files ***********************/

#include "CE2_AES.h"
#include "LLF_AES.h"

/************************ Defines *****************************/
/************************ Enums *******************************/
/************************ Typedefs ****************************/
/************************ Global Data *************************/
/************************ Private function prototype **********/
/************************ Private Functions *******************/
/************************ Public Functions ********************/

/**
****************************************************************
* Function Name: 
*  DX_AES
*
* @param IVCounter_ptr [in] - This parameter is the buffer of the IV or 
*                  counters on mode CTR.
*                  In ECB, XCBC, CMAC mode this parameter is not used.
*                  In CBC and MAC modes this parameter should contain the IV values.
*                  In CTR mode this value should contain the init counter.
*                  In XCBC and CMAC modes it may be NULL
*  @param Key_ptr [in] - A pointer to the user's key buffer.
*  @param KeySize [in] - The size of the KEY used by the AES: 128, 192 or 256 bits, 
*            as defined in the enum.
*  @param EncryptDecryptFlag [in] - A flag specifying whether the AES should perform an 
*                       Encrypt operation (0) or a Decrypt operation (1). 
*                       In XCBC and CMAC modes it must be 0.
*  @param OperationMode [in] - The operation mode: ECB, CBC, MAC, CTR, XCBC (PRF and 96), CMAC.
*  @param DataIn_ptr [in] - The pointer to the buffer of the input data to the AES. 
*               The pointer's value does not need to be word-aligned.
*  @param DataInSize [in] - The size of the input data (must be not 0 and must be multiple 
*               of 16 bytes, besides XCBC and CMAC).
*  @param DataOut_ptr [out] - The pointer to the buffer of the output data from the AES. 
*                The pointer does not need to be aligned to 32 bits. 
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code:
*   - CE2_AES_DATA_IN_PTR_ERROR
*   - CE2_AES_DATA_OUT_PTR_ERROR
*   - CE2_AES_DATA_IN_SIZE_ERROR
*   - CE2_AES_IV_COUNTER_PTR_ERROR
*   - CE2_AES_KEY_PTR_ERROR
*   - CE2_AES_KEY_SIZE_ERROR
*   - CE2_AES_OPERATION_MODE_ERROR
*   - CE2_AES_ENCRYPT_DECRYPT_FLAG_ERROR
*
* \brief \b 
* Description:
*  This function is used to operate the AES machine in one 
*  integrated operation.
*
*  \b 
* Algorithm:
*  -# Verify input parameters for validity;
*  -# Call low level function LLF_AES 
*     for AES with using LibTomCrypt.
***************************************************************/
CE2CIMPORT_C CE2Error_t  DX_AES(CE2_AES_IvCounter_t     IVCounter_ptr,       
                             CE2_AES_Key_t           Key_ptr,                 
                             CE2_AES_KeySize_t       KeySize,            
                             CE2_AES_EncryptMode_t   EncryptDecryptFlag, 
                             CE2_AES_OperationMode_t OperationMode ,           
                             DxUint8_t                *DataIn_ptr,        
                             DxUint32_t               DataInSize,         
                             DxUint8_t                *DataOut_ptr )
{
  if (DataIn_ptr == DX_NULL)
    return CE2_AES_DATA_IN_PTR_ERROR;

  if (DataOut_ptr == DX_NULL)
    return CE2_AES_DATA_OUT_PTR_ERROR;

  if (((DataInSize == 0) || (DataInSize%16 != 0)) &&
	  (OperationMode != CE2_AES_CTR_mode) && 
	  (OperationMode != CE2_AES_XCBC_MAC_mode) && 
    (OperationMode != CE2_AES_CMAC_mode))
    return CE2_AES_DATA_IN_SIZE_ERROR;

  if ((IVCounter_ptr == DX_NULL) && 
    (OperationMode != CE2_AES_XCBC_MAC_mode) && 
    (OperationMode != CE2_AES_CMAC_mode) &&
    (OperationMode != CE2_AES_ECB_mode))//?
    return CE2_AES_IV_COUNTER_PTR_ERROR;

  if (Key_ptr == DX_NULL)
    return CE2_AES_KEY_PTR_ERROR;

  if (KeySize < 0 || KeySize >= CE2_AES_KeySizeNumOfOptions ||
	  KeySize == CE2_AES_Key512BitSize)
    return CE2_AES_KEY_SIZE_ERROR;

  if (OperationMode < 0 || OperationMode >= CE2_AES_NumOfModes)
    return CE2_AES_OPERATION_MODE_ERROR;

  if ((EncryptDecryptFlag < 0 || EncryptDecryptFlag >= CE2_AES_EncryptNumOfOptions) ||
    ((EncryptDecryptFlag != CE2_AES_Encrypt) &&
    ((OperationMode == CE2_AES_XCBC_MAC_mode) || (OperationMode == CE2_AES_CMAC_mode))))
    return CE2_AES_ENCRYPT_DECRYPT_FLAG_ERROR;

  return LLF_AES(IVCounter_ptr, Key_ptr, KeySize, EncryptDecryptFlag, 
    OperationMode, DataIn_ptr, DataInSize, DataOut_ptr);
} /* End of DX_AES */

/**
****************************************************************
* Function Name: 
*  CE2_AES_Wrap
*
* @param DataIn_ptr [in] - A pointer to plain text data to be wrapped
*               NOTE: Overlapping between the data input and data output buffer
*               is not allowed, except the inplace case that is legal . 			
* @param DataInLen [in]  - Length of data in bytes. DataLen must be multiple of 
*               8 bytes and  must be in range [16,  2^28].
* @param KeyData [in] - A pointer to  key data (key encryption key - KEK). 
* @param KeySize [in] - Enumerator variable, defines length of key.
* @param WrapDataOut_ptr [out] - A pointer to buffer for output of wrapped data.
* @param WrapDataLen_ptr [in/out] - A pointer to a buffer for input of size of 
*                    user passed buffer and for output actual 
*                    size of unwrapped data in bytes. Buffer size must 
*                    be not less than DataLen+CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES.                         
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code:
*   - CE2_AES_WRAP_ILLEGAL_DATA_PTR_ERROR
*   - CE2_AES_WRAP_DATA_LENGTH_ERROR
*   - CE2_AES_WRAP_KEY_PTR_ERROR
*   - CE2_AES_WRAP_KEY_LENGTH_ERROR                  
*   - CE2_AES_WRAP_ILLEGAL_WRAP_DATA_PTR_ERROR      
*   - CE2_AES_WRAP_ILLEGAL_WRAP_DATA_LEN_PTR_ERROR  
*   - CE2_AES_WRAP_ILLEGAL_WRAP_DATA_LENGTH_ERROR
*
* \brief \b 
* Description:
*   The CE2_AES_Wrap function implements the following algorithm 
*   (rfc3394, Sept. 2002)
*  Inputs:  Plaintext DataIn, n 64-bit values {P1, P2, ..., Pn}, 
*   KeyData, K (the KEK).                
*  Outputs: Ciphertext, WrapDataOut (n+1) 64-bit values {C0, C1, ..., Cn}.
*
*  \b 
* Algorithm:
* -# Verify input parameters for validity;
* -# Call low level function LLF_AES_Wrap 
*    for AES wraping with using LibTomCrypt.
***************************************************************/
CE2CIMPORT_C  CE2Error_t CE2_AES_Wrap (
                DxUint8_t            *DataIn_ptr,      /*in*/   
                DxUint32_t            DataInLen,       /*in*/
                CE2_AES_Key_t        KeyData,         /*in*/
                CE2_AES_KeySize_t    KeySize,         /*in*/
                DxUint8_t            *WrapDataOut_ptr, /*out*/
                DxUint32_t           *WrapDataLen_ptr  /*in/out*/ )
{
  if (DataIn_ptr == DX_NULL)
    return CE2_AES_WRAP_ILLEGAL_DATA_PTR_ERROR;

  if (DataInLen < CE2_AES_WRAP_DATA_MIN_SIZE_IN_BYTES ||
    DataInLen > CE2_AES_WRAP_DATA_MAX_SIZE_IN_BYTES ||
    DataInLen%CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES != 0)
    return CE2_AES_WRAP_DATA_LENGTH_ERROR;

  if (KeyData == DX_NULL)
    return CE2_AES_WRAP_KEY_PTR_ERROR;

  if (KeySize < 0 || KeySize >= CE2_AES_KeySizeNumOfOptions ||
	  KeySize == CE2_AES_Key512BitSize)
    return CE2_AES_WRAP_KEY_LENGTH_ERROR;

  if (WrapDataOut_ptr == DX_NULL)
    return CE2_AES_WRAP_ILLEGAL_WRAP_DATA_PTR_ERROR;

  if (WrapDataLen_ptr == DX_NULL)
    return CE2_AES_WRAP_ILLEGAL_WRAP_DATA_LEN_PTR_ERROR;  

  if (*WrapDataLen_ptr < DataInLen + CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES)  
    return CE2_AES_WRAP_ILLEGAL_WRAP_DATA_LENGTH_ERROR;
  *WrapDataLen_ptr = DataInLen + CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES;

  return LLF_AES_Wrap(DataIn_ptr, DataInLen, KeyData, 
    KeySize, WrapDataOut_ptr, WrapDataLen_ptr);
} /* End of CE2_AES_Wrap */

/**
****************************************************************
* Function Name: 
*  CE2_AES_Unwrap
*
* @param WrapDataIn_ptr [in] - A pointer to wrapped data to be unwrapped 
*                   NOTE: Overlapping between the data input and 
*                   data output buffer is not allowed, except the 
*                   inplace case that is legal . 			
* @param WrapDataInLen [in] - Length of wrapped data in bytes. DataLen must be 
*                  multiple of 8 bytes and  must be in range [24, 2^29].
* @param KeyData [in] - A pointer to  key data (key encryption key - KEK). 
* @param KeySize [in] - Enumerator variable, defines length of key.
* @param DataOut_ptr [out] - A pointer to buffer for output of unwrapped data.
* @param DataOutLen_ptr [in/out] - A pointer to a buffer for input of size of user 
*                   passed buffer and for output of actual size of 
*                   unwrapped data in bytes. DataOutLen must be 
*                   multiple of 8 bytes and must be not less than 
*                   WrapDataInLen - CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES.
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code:
*   - CE2_AES_UNWRAP_ILLEGAL_WRAP_DATA_PTR_ERROR          
*   - CE2_AES_UNWRAP_WRAP_DATA_LENGTH_ERROR          
*   - CE2_AES_UNWRAP_KEY_LEN_ERROR                   
*   - CE2_AES_UNWRAP_KEY_PTR_ERROR
*   - CE2_AES_UNWRAP_ILLEGAL_DATA_PTR_ERROR         
*   - CE2_AES_UNWRAP_ILLEGAL_DATA_LEN_PTR_ERROR      
*   - CE2_AES_UNWRAP_ILLEGAL_DATA_LENGTH_ERROR      
*
* \brief \b 
* Description:
*   The CE2_AES_Unwrap function performs inverse AES_Wrap transformation 
*   and implements the following algorithm (rfc3394, Sept. 2002): 
*  Inputs:  Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn}, and
*   K  - key (the KEK).
*  Outputs: Plaintext, n 64-bit values {P1, P2, ..., Pn}.
*
*  \b 
* Algorithm:
* -# Verify input parameters for validity;
* -# Call low level function LLF_AES_Unwrap 
*    for AES unwraping with using LibTomCrypt.
***************************************************************/
CE2CIMPORT_C  CE2Error_t CE2_AES_Unwrap(
               DxUint8_t            *WrapDataIn_ptr, /*in*/   
               DxUint32_t            WrapDataInLen,    /*in*/
               CE2_AES_Key_t        KeyData,        /*in*/
               CE2_AES_KeySize_t    KeySize,        /*in*/ 
               DxUint8_t            *DataOut_ptr,    /*out*/
               DxUint32_t           *DataOutLen_ptr     /*in/out*/ )
{
  if (WrapDataIn_ptr == DX_NULL)
    return CE2_AES_UNWRAP_ILLEGAL_WRAP_DATA_PTR_ERROR; 

  if ((WrapDataInLen < CE2_AES_WRAP_DATA_MIN_SIZE_IN_BYTES + 
    CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES) ||
    (WrapDataInLen > CE2_AES_WRAP_DATA_MAX_SIZE_IN_BYTES + 
    CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES) ||
    WrapDataInLen%CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES != 0)
    return CE2_AES_UNWRAP_WRAP_DATA_LENGTH_ERROR; 

  if (KeyData == DX_NULL)
    return CE2_AES_UNWRAP_KEY_PTR_ERROR;

  if (KeySize < 0 || KeySize >= CE2_AES_KeySizeNumOfOptions ||
	  KeySize == CE2_AES_Key512BitSize)
    return CE2_AES_UNWRAP_KEY_LEN_ERROR; 

  if (DataOut_ptr == DX_NULL)
    return CE2_AES_UNWRAP_ILLEGAL_DATA_PTR_ERROR;

  if (DataOutLen_ptr == DX_NULL)
    return CE2_AES_UNWRAP_ILLEGAL_DATA_LEN_PTR_ERROR; 

  if (*DataOutLen_ptr < WrapDataInLen - CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES)
    return CE2_AES_UNWRAP_ILLEGAL_DATA_LENGTH_ERROR;
  *DataOutLen_ptr = WrapDataInLen - CE2_AES_WRAP_BLOCK_SIZE_IN_BYTES;

  return LLF_AES_Unwrap(WrapDataIn_ptr, WrapDataInLen, KeyData,
    KeySize, DataOut_ptr, DataOutLen_ptr);
} /* End of CE2_AES_Unwrap */

/**
****************************************************************
* Function Name: 
*  DX_AES_GenerateTweakValue
*
* @param Tweak_dst [out] - This parameter is a return value from generator Tweak Value.
* @param Key_ptr [in] - This parameter is a key used for generator.
* @param KeySize [in] - Size of key.
* @param SectorNumber [in] - 64-bit sector number.
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code:
*   - CE2_XTS_AES_ILLEGAL_TWEAK_PTR_ERROR
*   - CE2_XTS_AES_ILLEGAL_KEY_PTR_ERROR
*   - CE2_XTS_AES_ILLEGAL_SECTOR_NUMBER_PTR_ERROR
*
* \brief \b 
* Description:
*  Used for generating sector "tweak"
*
**  \b 
* Algorithm:
*  -# Verify input parameters;
*  -# Call low level function LLF_AES_GenerateTweakValue().
***************************************************************/
CE2CIMPORT_C CE2Error_t DX_AES_GenerateTweakValue(CE2_AES_XTS_Tweak_t Tweak_dst, 
                                            CE2_AES_Key_t       Key_ptr,
											CE2_AES_KeySize_t   KeySize,
                                            CE2_AES_XTS_Tweak_t	SectorNumber)
{
	if (Tweak_dst == DX_NULL)
		return CE2_XTS_AES_ILLEGAL_TWEAK_PTR_ERROR;
	if (Key_ptr == DX_NULL)
		return CE2_XTS_AES_ILLEGAL_KEY_PTR_ERROR;
	if (SectorNumber == DX_NULL)
		return CE2_XTS_AES_ILLEGAL_SECTOR_NUMBER_PTR_ERROR;
	return LLF_AES_GenerateTweakValue( Tweak_dst, Key_ptr, KeySize, SectorNumber );
}
/**
****************************************************************
* Function Name: 
*  CE2_XTS_AES
*
* @param Tweak_ptr [in/out] - Pointer to buffer containing:
*   - Tweak Value (if IsTweakInternal = FALSE) OR 
*   - Sector Number (if IsTweakInternal = TRUE)
*     \note In case tweak value is generated internally it's returned through this parameter
* @param Key_ptr [in] - Pointer to buffer containing: 
*   - AES key used for XTS-AES cipher (if IsTweakInternal = FALSE) OR 
*   - Both: Tweak Key + AES Key concatinated (if TweakInternal = TRUE)
* @param KeySize [in] - Size of Tweak Key and/or AES keys (size of every single key but not size of buffer).
* @param EncryptDecryptFlag [in] - This flag specifies encrypt or decrypt operation to be performed.
* @param DataIn_ptr [in] - A pointer to input data.
* @param DataInSize [in] - Size of input data. It must be at least 16 bytes.
* @param IsTweakInternal [in] - Flag to indicate if tweak value should be generated internally or is put from outside
* @param DataOut_ptr [out] - A pointer to output data.
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code:
*   - CE2_XTS_AES_ILLEGAL_TWEAK_PTR_ERROR
*   - CE2_XTS_AES_ILLEGAL_KEY_PTR_ERROR
*   - CE2_XTS_AES_ILLEGAL_KEY_SIZE_ERROR
*   - CE2_XTS_AES_ILLEGAL_ENCRYPT_MODE_ERROR
*   - CE2_XTS_AES_ILLEGAL_DATAIN_PTR_ERROR
*   - CE2_XTS_AES_TO_SHORT_DATA_SIZE_ERROR
*   - CE2_XTS_AES_ILLEGAL_DATAOUT_PTR_ERROR
*
* \brief \b 
* Description:
*  This function is used to make XTS-AES operations;
*
*  \b 
* Algorithm:
*  -# Verify input parameters;
*  -# Call low level function LLF_XTS_AES().
***************************************************************/
CE2CIMPORT_C CE2Error_t CE2_XTS_AES(CE2_AES_XTS_Tweak_t  Tweak_ptr,
								 CE2_AES_Key_t           Key_ptr,
								 CE2_AES_KeySize_t       KeySize,
								 CE2_AES_EncryptMode_t   EncryptDecryptFlag, 
								 DxUint8_t               *DataIn_ptr,        
								 DxUint32_t              DataInSize,
								 EcDxBool_t				 IsTweakInternal,         
								 DxUint8_t               *DataOut_ptr)
{
	if (Tweak_ptr == DX_NULL)
		return CE2_XTS_AES_ILLEGAL_TWEAK_PTR_ERROR;

	if (Key_ptr == DX_NULL)
		return CE2_XTS_AES_ILLEGAL_KEY_PTR_ERROR;

	if (KeySize < CE2_AES_Key128BitSize || 
		KeySize > CE2_AES_Key512BitSize)
		return CE2_XTS_AES_ILLEGAL_KEY_SIZE_ERROR;

	if (EncryptDecryptFlag < CE2_AES_Encrypt || 
		EncryptDecryptFlag > CE2_AES_Decrypt)
		return CE2_XTS_AES_ILLEGAL_ENCRYPT_MODE_ERROR;

	if (DataIn_ptr == DX_NULL) 
		return CE2_XTS_AES_ILLEGAL_DATAIN_PTR_ERROR;

	if (DataInSize < CE2_AES_BLOCK_SIZE_IN_BYTES)
		return CE2_XTS_AES_TO_SHORT_DATA_SIZE_ERROR;

	if (DataOut_ptr == DX_NULL) 
		return CE2_XTS_AES_ILLEGAL_DATAOUT_PTR_ERROR;

	if ( IsTweakInternal == TRUE ){
		CE2Error_t err;
		DxUint32_t keysize;
		CE2_AES_KeySize_t sizetype;

		switch( KeySize ) {
			case CE2_AES_Key128BitSize:
			case CE2_AES_Key192BitSize:
				return CE2_XTS_AES_ILLEGAL_KEY_SIZE_ERROR;
			case CE2_AES_Key256BitSize:
				keysize = 256/8/2;
				sizetype = CE2_AES_Key128BitSize;
				break;
			case CE2_AES_Key512BitSize:
				keysize = 512/8/2;
				sizetype = CE2_AES_Key256BitSize;
				break;
			default:
				return CE2_ERROR_BASE;
		}
		err = DX_AES_GenerateTweakValue( Tweak_ptr, ((DxUint8_t*)Key_ptr)+keysize, sizetype, Tweak_ptr );
		if (err != CE2_OK ){
			return err;
		}
		return LLF_XTS_AES(Tweak_ptr, Key_ptr, sizetype,
			EncryptDecryptFlag, DataIn_ptr, DataInSize, DataOut_ptr);
	}else{
		switch(KeySize) {
			case CE2_AES_Key192BitSize:
			case CE2_AES_Key512BitSize:
				return CE2_XTS_AES_ILLEGAL_KEY_SIZE_ERROR;
			default:
				break;
		}
		return LLF_XTS_AES(Tweak_ptr, Key_ptr, KeySize,
			EncryptDecryptFlag, DataIn_ptr, DataInSize, DataOut_ptr);
	}
} /* End of CE2_XTS_AES */

CE2CIMPORT_C CE2Error_t CE2_XTS_AES_OLD(CE2_AES_Key_t Key1_ptr, 
										CE2_AES_Key_t Key2_ptr,  
										CE2_AES_KeySize_t KeySize, 
										DxUint64_t SectorNumber,  
										CE2_AES_EncryptMode_t EncryptDecryptFlag,
										DxUint8_t* DataIn_ptr,  
										DxUint32_t DataInSize,  
										DxUint8_t* DataOut_ptr )
{
	CE2Error_t err;
	CE2_AES_XTS_Tweak_t  Tweak_ptr;

	if (Key1_ptr == DX_NULL)
		return CE2_XTS_AES_ILLEGAL_KEY_PTR_ERROR;
	if (Key2_ptr == DX_NULL)
		return CE2_XTS_AES_ILLEGAL_KEY_PTR_ERROR;

	if (KeySize < CE2_AES_Key128BitSize || 
		KeySize > CE2_AES_Key512BitSize)
		return CE2_XTS_AES_ILLEGAL_KEY_SIZE_ERROR;

	if (EncryptDecryptFlag < CE2_AES_Encrypt || 
		EncryptDecryptFlag > CE2_AES_Decrypt)
		return CE2_XTS_AES_ILLEGAL_ENCRYPT_MODE_ERROR;

	if (DataIn_ptr == DX_NULL) 
		return CE2_XTS_AES_ILLEGAL_DATAIN_PTR_ERROR;

	if (DataInSize < CE2_AES_BLOCK_SIZE_IN_BYTES)
		return CE2_XTS_AES_TO_SHORT_DATA_SIZE_ERROR;

	if (DataOut_ptr == DX_NULL) 
		return CE2_XTS_AES_ILLEGAL_DATAOUT_PTR_ERROR;
	err = DX_AES_GenerateTweakValue( Tweak_ptr, Key2_ptr, KeySize, Tweak_ptr );
	if (err != CE2_OK ){
		return err;
	}
	return LLF_XTS_AES(Tweak_ptr, Key1_ptr, KeySize,
		EncryptDecryptFlag, DataIn_ptr, DataInSize, DataOut_ptr);
}

/**
****************************************************************
* Function Name: 
*  CE2_AES_CCM
*
* @param EncrDecrMode [in] - Enumerator variable defining operation mode (0 - encrypt; 1 - decrypt).
* @param CCM_Key [in] - A buffer, containing the AESCCM key passed by user (predefined size 128 bits).
* @param QFieldSize [in] - Byte-size of formatted field for writing significant bytes of the TextSizeQ 
*                          value. Valid values according to our implementation: [2,3,4]. 
* @param N_ptr [in] - A pointer to Nonce - unique value assigned to all data passed into CCM.
*                     Bytes order - big endian form (MSB is the first).
* @param SizeOfN [in] - The size of the user passed Nonce (in bytes). 	Valid values: 
*                       7 <= SizeOfN <= (15-QFieldSize). 
* @param ADataIn_ptr [in] - A pointer to the additional data buffer. The pointer does 
*                           not need to be aligned. On CSI input mode the pointer must be equal to 
*                           value (0xFFFFFFFC | DataInAlignment). 
* @param ADataInSize [in] - The size of the additional data in bytes;  
* @param TextDataIn_ptr [in] - A pointer to the input text data buffer (plain or cipher according to
*                              encrypt-decrypt mode). The pointer does not need to be aligned.
*                              On CSI input mode the pointer must be equal to value (0xFFFFFFFC | DataInAlignment). 
* @param TextDataInSize [in] - The size of the input text data in bytes;  
* @param TextDataOut_ptr [out] - The output text data pointer (cipher or plain text data). 
* @param TextDataOutSize [in] - The size of the output text data buffer. The size of buffer must be enough 
*                               for output the data:
*                                   - on Encrypt mode: TextDataOutSize >= TextDataInSize + SizeOfT.
*                                   - on Decrypt mode: TextDataOutSize >= TextDataInSize - SizeOfT.
* @param SizeOfT [in] - Size of AES-CCM MAC output T in bytes. Valid values: [4,6,8,10,12,14,16].   
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code:
*   - CE2_AES_CCM_ILLEGAL_KEY_PTR_ERROR
*   - CE2_AES_CCM_KEY_SIZE_ERROR
*   - CE2_AES_CCM_ILLEGAL_NONCE_PTR_ERROR
*   - CE2_AES_CCM_ILLEGAL_HEADER_PTR_ERROR
*   - CE2_AES_CCM_ENCRYPT_DECRYPT_FLAG_ERROR
*   - CE2_AES_CCM_ILLEGAL_DATA_IN_PTR_ERROR
*   - CE2_AES_CCM_ILLEGAL_DATA_OUT_PTR_ERROR
*   - CE2_AES_CCM_ILLEGAL_TAG_PTR_ERROR
*   - CE2_AES_CCM_ILLEGAL_TAG_SIZE_PTR_ERROR
*   - CE2_AES_CCM_TAG_SIZE_ERROR
*
* \brief \b 
* Description:
*  This function is used to perform the AES_CCM operation in one integrated process.
*  The function preforms CCM algorithm according to NIST 800-38C.
*
*  \b 
* Algorithm:
*  -# Verify input parameters;
*  -# Call low level function LLF_AES_CCM().
***************************************************************/
CE2CIMPORT_C CE2Error_t CE2_AES_CCM(CE2_AES_EncryptMode_t  EncrDecrMode,
                                    CE2_AESCCM_Key_t       CCM_Key,
                                    DxUint8_t              QFieldSize,
                                    DxUint8_t             *N_ptr,
                                    DxUint8_t              SizeOfN,
                                    DxUint8_t             *ADataIn_ptr,
                                    DxUint32_t             ADataInSize,
                                    DxUint8_t             *TextDataIn_ptr,
                                    DxUint32_t             TextDataInSize,
                                    DxUint8_t             *TextDataOut_ptr,
                                    DxUint32_t             TextDataOutSize,
                                    DxUint8_t              SizeOfT)
{
  if (CCM_Key == DX_NULL)
    return CE2_AESCCM_INVALID_KEY_POINTER_ERROR;

  if (CE2_AESCCM_QFIELD_MIN_SIZE_BYTES > QFieldSize ||
	  QFieldSize > CE2_AESCCM_QFIELD_MAX_SIZE_BYTES)
    return CE2_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;

  if (N_ptr == DX_NULL)
    return CE2_AESCCM_ILLEGAL_PARAMETER_PTR_ERROR;

  if (CE2_AESCCM_NONCE_MIN_SIZE_BYTES > SizeOfN ||
	  SizeOfN > CE2_AESCCM_NQ_BLOCK_SIZE_BYTES - QFieldSize)
    return CE2_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;

  if (ADataIn_ptr == DX_NULL && ADataIn_ptr != 0)
    return CE2_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;

  if (EncrDecrMode < CE2_AESCCM_Encrypt || 
    EncrDecrMode > CE2_AESCCM_Decrypt)
    return CE2_AESCCM_INVALID_ENCRYPT_MODE_ERROR;

  if (TextDataIn_ptr == DX_NULL) 
    return CE2_AESCCM_DATA_IN_POINTER_INVALID_ERROR;

  if (TextDataOut_ptr == DX_NULL) 
    return CE2_AESCCM_DATA_OUT_POINTER_INVALID_ERROR;

  if (EncrDecrMode == CE2_AESCCM_Encrypt)
  {
    if (TextDataOutSize < TextDataInSize + SizeOfT) 
      return CE2_AESCCM_DATA_OUT_SIZE_INVALID_ERROR;
  }
  else
  {
    if (TextDataOutSize < TextDataInSize) 
      return CE2_AESCCM_DATA_OUT_SIZE_INVALID_ERROR;
  }

  if (CE2_AESCCM_MAC_MIN_SIZE_BYTES > SizeOfT ||
	  SizeOfT > CE2_AESCCM_MAC_MAX_SIZE_BYTES ||
	  SizeOfT % 2 != 0) 
    return CE2_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;

  return LLF_AES_CCM(EncrDecrMode, CCM_Key, QFieldSize, N_ptr, SizeOfN, ADataIn_ptr, 
    ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, TextDataOutSize,
	SizeOfT);
} /* End of CE2_AES_CCM */

/**
****************************************************************
* Function Name: 
*  CE2_AES_GCM
*
* @param Key_ptr [in] - This is a AES key used for CCM cipher.
* @param KeySize [in] - A size in bytes of the AES key.
* @param IV_ptr [in] - A pointer to buffer with IV (Initial Vector). 
*                      It maybe null if IVSize = 0.
* @param IVSize [in] - A size of IV buffer in bytes;
* @param AAD_ptr [in] - A pointer to AAD (Additional Authentication Data) buffer. 
*                       It maybe null if AADSize = 0.
* @param AADSize [in] - A size of AAD buffer in bytes.
* @param EncryptDecryptFlag [in] - This flag specialize encrypt or decrypt operation. 
* @param DataIn_ptr [in] - A pointer to input data.        
* @param DataInSize [in] - Size of input data.         
* @param DataOut_ptr [out] - A pointer to output data.
* @param Tag_ptr [out] - A pointer to output tag buffer. 
* @param TagSize_ptr [in/out] - A pointer to size of tag buffer.
*                               Note: maximal used size of tag is 16 bytes.
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code:
*   - CE2_AES_GCM_ILLEGAL_KEY_PTR_ERROR
*   - CE2_AES_GCM_KEY_SIZE_ERROR
*   - CE2_AES_GCM_ILLEGAL_IV_PTR_ERROR
*   - CE2_AES_GCM_ILLEGAL_AAD_PTR_ERROR
*   - CE2_AES_GCM_ENCRYPT_DECRYPT_FLAG_ERROR
*   - CE2_AES_GCM_ILLEGAL_DATA_IN_PTR_ERROR
*   - CE2_AES_GCM_DATA_IN_SIZE_ERROR
*   - CE2_AES_GCM_ILLEGAL_DATA_OUT_PTR_ERROR
*   - CE2_AES_GCM_ILLEGAL_TAG_PTR_ERROR
*   - CE2_AES_GCM_ILLEGAL_TAG_SIZE_PTR_ERROR
*
* \brief \b 
* Description:
*  This function is used to make GCM operations;
*
*  \b 
* Algorithm:
*  -# Verify input parameters;
*  -# Call low level function LLF_AES_GCM().
***************************************************************/
CE2CIMPORT_C CE2Error_t CE2_AES_GCM(CE2_AES_Key_t         Key_ptr,
                                 CE2_AES_KeySize_t     KeySize,
                                 DxUint8_t             *IV_ptr, 
                                 DxUint32_t            IVSize,
                                 DxUint8_t             *AAD_ptr, 
                                 DxUint32_t            AADSize,
                                 CE2_AES_EncryptMode_t EncryptDecryptFlag, 
                                 DxUint8_t             *DataIn_ptr,        
                                 DxUint32_t            DataInSize,         
                                 DxUint8_t             *DataOut_ptr,
                                 DxUint8_t             *Tag_ptr, 
                                 DxUint32_t            *TagSize_ptr)
{
  if (Key_ptr == DX_NULL)
    return CE2_AES_GCM_ILLEGAL_KEY_PTR_ERROR;

  if (KeySize < CE2_AES_Key128BitSize || 
    KeySize > CE2_AES_Key256BitSize)
    return CE2_AES_GCM_KEY_SIZE_ERROR;

  if (IV_ptr == DX_NULL && IVSize != 0)
    return CE2_AES_GCM_ILLEGAL_IV_PTR_ERROR;

  if (AAD_ptr == DX_NULL && AADSize != 0)
    return CE2_AES_GCM_ILLEGAL_AAD_PTR_ERROR;

  if (EncryptDecryptFlag < CE2_AES_Encrypt || 
    EncryptDecryptFlag > CE2_AES_Decrypt)
    return CE2_AES_GCM_ENCRYPT_DECRYPT_FLAG_ERROR;

  if (DataIn_ptr == DX_NULL) 
    return CE2_AES_GCM_ILLEGAL_DATA_IN_PTR_ERROR;

  if (DataOut_ptr == DX_NULL) 
    return CE2_AES_GCM_ILLEGAL_DATA_OUT_PTR_ERROR;

  if (Tag_ptr == DX_NULL) 
    return CE2_AES_GCM_ILLEGAL_TAG_PTR_ERROR;

  if (TagSize_ptr == DX_NULL) 
    return CE2_AES_GCM_ILLEGAL_TAG_SIZE_PTR_ERROR;

  return LLF_AES_GCM(Key_ptr, KeySize, IV_ptr, IVSize, AAD_ptr, 
    AADSize, EncryptDecryptFlag, DataIn_ptr, DataInSize, DataOut_ptr,
    Tag_ptr, TagSize_ptr);
} /* End of CE2_AES_GCM */
