/******************************************************************************
 * @fn      SSP_CCM_InvAuth_Decrypt
 *
 * @brief   Verifies CCM authentication.
 *
 * input parameters
 * @param decrypt if set to 'true' then run decryption and set to 'flase' for
 * authentication only.
 * @param   Mval    - Length of authentication field in octets [0,2,4,6,8,10,12,14 or 16]
 * @param   N       - Pointer to 13-byte Nonce
 * @param   C       - Pointer to octet string 'c' = 'm' || auth tag T
 * @param   len_c   - Length of C[] in octets
 * @param   A       - Pointer to octet string 'a'
 * @param   len_a   - Length of A[] in octets
 * @param   AesKey  - Pointer to AES Key or Pointer to Key Expansion buffer.
 * @param   Cstate  - Pointer to AES state buffer (cannot be part of C[])
 * @param   ccmLVal - ccm L Value to be used.
 *
 * output parameters
 *
 * @param   Cstate[]    - The first Mval bytes contain computed Authentication Tag T
 *
 * @return  0 = Success, 1 = Failure
 *
 */
uint8 SSP_CCM_InvAuth_Decrypt (bool decrypt, uint8 Mval, uint8 *N, uint8 *C, uint16 len_c, uint8 *A,
                       uint16 len_a, uint8 *AesKey, uint8 *Cstate, uint8 ccmLVal)
{

  unsigned char status;
  if((status = CCMInvAuthDecryptStart(decrypt, Mval, N, C, len_c, A, len_a, 0, Cstate,
                                         ccmLVal, false))!= AES_SUCCESS )
  {
    return status;
  }

  /* wait for completion of the operation */
  do
  {
    ASM_NOP;
  }while(!(CCMInvAuthDecryptCheckResult()));


  if((status = CCMInvAuthDecryptGetResult(Mval, C, len_c, Cstate)) != AES_SUCCESS)
  {
    return status;
  }

  return AES_SUCCESS;
}
//*****************************************************************************
//
// brief   AES-CCM decrypt example
//
// param   bDecrypt           if set to true run decryption
// param   pui8Key            pointer to Key
// param   ui8Mval            length of authentication
// param   pui8N              Nonce
// param   C                  input encrypted message
// param   ui16LenC           length of message
// param   pui8A              Additional data
// param   ui16LenA           length of additional data
// param   ui8KeyLocation     location in Key RAM. Must be one of
//                            the following:
//                            KEY_AREA_0
//                            KEY_AREA_1
//                            KEY_AREA_2
//                            KEY_AREA_3
//                            KEY_AREA_4
//                            KEY_AREA_5
//                            KEY_AREA_6
//                            KEY_AREA_7
// param   ui8CCMLVal         Lval for ccm
// param   ui8CCMIntEnable    set to true to enable interrupts and false to 
//                            disable
// param   pui8ExpectedOutput pointer to expected output
// param   pui8Cstate         authentication Tag
// param   ui8CCMIntEnable    set true/false to enable/disable interrupts
// param   pui8ExpectedOutput pointer to Expected Output
//
//return  AES_SUCCESS if successful
//
//*****************************************************************************
uint8_t CCMDecryptExamples(bool bDecrypt,
                              uint8_t* pui8Key,
                              uint8_t ui8Mval,
                              uint8_t *pui8N,
                              uint8_t *pui8C,
                              uint16_t ui16LenC,
                              uint8_t *pui8A,
                              uint16_t ui16LenA,
                              uint8_t ui8KeyLocation,
                              uint8_t *pui8Cstate,
                              uint8_t ui8CCMLVal,
                              uint8_t ui8CCMIntEnable,
                              uint8_t *pui8ExpectedOutput)
{
    uint8_t status;
    if(ui8CCMIntEnable)
    {    
        //
        // example using interrupt service routine
        //
        if((status = AESLoadKey((uint8_t*)pui8Key, ui8KeyLocation)) != 
           AES_SUCCESS)
        {
            return status;
        }
        
        if((status = CCMInvAuthDecryptStart(bDecrypt, ui8Mval, pui8N, pui8C, 
                                            ui16LenC, pui8A, ui16LenA,
                                            ui8KeyLocation, pui8Cstate,
                                            ui8CCMLVal, ui8CCMIntEnable)) != 
           AES_SUCCESS)
        {
            return status;
        }
        
        //
        // wait for completion of the operation
        //
        do
        {
            ASM_NOP;
        }while(ui8CCMIntHandler == 0);
        
        ui8CCMIntHandler = 0;
        
        if((status = CCMInvAuthDecryptGetResult(ui8Mval, pui8C, ui16LenC, 
                                                pui8Cstate)) != AES_SUCCESS)
        {
            return status;
        }
    } 
    else
    {
        //
        // example using polling
        //
        if((status = AESLoadKey((uint8_t*)pui8Key, 
                                ui8KeyLocation)) != AES_SUCCESS)
        {
            return status;
        }
        if((status = CCMInvAuthDecryptStart(bDecrypt, ui8Mval, pui8N, pui8C, 
                                            ui16LenC, pui8A, ui16LenA, 
                                            ui8KeyLocation, pui8Cstate, 
                                            ui8CCMLVal, 
                                            ui8CCMIntEnable))!= AES_SUCCESS )
        {
            return status;
        }
        
        //
        // wait for completion of the operation
        //
        do
        {
            ASM_NOP;
        }while(!(CCMInvAuthDecryptCheckResult()));
        
        if((status = CCMInvAuthDecryptGetResult(ui8Mval, pui8C, ui16LenC, 
                                                pui8Cstate)) != AES_SUCCESS)
        {
            return status;
        }
    }
    
    //
    // Verify CCM output
    //
    if (CCMMemCmp(pui8C,  (uint8_t const *)pui8ExpectedOutput, 
                  (ui16LenC-ui8Mval)) == false)
    {
        return AES_CCM_TEST_ERROR;
    }
    
    return AES_SUCCESS;
}