TUKS MCU Introductory course / TUKS-COURSE-2-LED
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l4xx_hal_cryp_ex.c Source File

stm32l4xx_hal_cryp_ex.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_cryp_ex.c
00004   * @author  MCD Application Team
00005   * @version V1.5.1
00006   * @date    31-May-2016
00007   * @brief   CRYPEx HAL module driver.
00008   *          This file provides firmware functions to manage the extended
00009   *          functionalities of the Cryptography (CRYP) peripheral.  
00010   *         
00011   ******************************************************************************
00012   * @attention
00013   *
00014   * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
00015   *
00016   * Redistribution and use in source and binary forms, with or without modification,
00017   * are permitted provided that the following conditions are met:
00018   *   1. Redistributions of source code must retain the above copyright notice,
00019   *      this list of conditions and the following disclaimer.
00020   *   2. Redistributions in binary form must reproduce the above copyright notice,
00021   *      this list of conditions and the following disclaimer in the documentation
00022   *      and/or other materials provided with the distribution.
00023   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00024   *      may be used to endorse or promote products derived from this software
00025   *      without specific prior written permission.
00026   *
00027   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00028   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00029   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00030   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00031   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00032   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00033   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00034   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00035   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037   *
00038   ******************************************************************************  
00039   */ 
00040 
00041 /* Includes ------------------------------------------------------------------*/
00042 #include "stm32l4xx_hal.h"
00043 
00044 #ifdef HAL_CRYP_MODULE_ENABLED
00045 
00046 #if defined (STM32L442xx) || defined (STM32L443xx) || defined(STM32L485xx) || defined(STM32L486xx)
00047 
00048 /** @addtogroup STM32L4xx_HAL_Driver
00049   * @{
00050   */
00051 
00052 /** @defgroup CRYPEx CRYPEx
00053   * @brief CRYP Extended HAL module driver
00054   * @{
00055   */
00056 
00057 /* Private typedef -----------------------------------------------------------*/
00058 /* Private define ------------------------------------------------------------*/
00059 /** @defgroup CRYPEx_Private_Constants CRYPEx Private Constants
00060   * @{
00061   */
00062 #define CRYP_CCF_TIMEOUTVALUE                      22000  /*!< CCF flag raising time-out value */
00063 #define CRYP_BUSY_TIMEOUTVALUE                     22000  /*!< BUSY flag reset time-out value  */
00064 
00065 #define CRYP_POLLING_OFF                             0x0  /*!< No polling when padding */
00066 #define CRYP_POLLING_ON                              0x1  /*!< Polling when padding    */
00067 /**
00068   * @}
00069   */
00070 
00071 /* Private macro -------------------------------------------------------------*/
00072 /* Private variables ---------------------------------------------------------*/
00073 /* Private function prototypes -----------------------------------------------*/
00074 /** @defgroup CRYPEx_Private_Functions CRYPEx Private Functions
00075  * @{
00076  */
00077 static HAL_StatusTypeDef CRYP_ProcessData(CRYP_HandleTypeDef *hcryp, uint8_t* Input, uint16_t Ilength, uint8_t* Output, uint32_t Timeout);
00078 static HAL_StatusTypeDef CRYP_ReadKey(CRYP_HandleTypeDef *hcryp, uint8_t* Output, uint32_t Timeout);
00079 static void CRYP_SetDMAConfig(CRYP_HandleTypeDef *hcryp, uint32_t inputaddr, uint16_t Size, uint32_t outputaddr);
00080 static void CRYP_GCMCMAC_SetDMAConfig(CRYP_HandleTypeDef *hcryp, uint32_t inputaddr, uint16_t Size, uint32_t outputaddr);
00081 static void CRYP_GCMCMAC_DMAInCplt(DMA_HandleTypeDef *hdma);
00082 static void CRYP_GCMCMAC_DMAError(DMA_HandleTypeDef *hdma);
00083 static void CRYP_GCMCMAC_DMAOutCplt(DMA_HandleTypeDef *hdma);
00084 static HAL_StatusTypeDef CRYP_WaitOnCCFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
00085 static HAL_StatusTypeDef CRYP_WaitOnBusyFlagReset(CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
00086 static void CRYP_DMAInCplt(DMA_HandleTypeDef *hdma);
00087 static void CRYP_DMAOutCplt(DMA_HandleTypeDef *hdma);
00088 static void CRYP_DMAError(DMA_HandleTypeDef *hdma);
00089 static void CRYP_Padding(CRYP_HandleTypeDef *hcryp, uint32_t difflength, uint32_t polling);
00090 /**
00091   * @}
00092   */
00093 
00094 /* Exported functions ---------------------------------------------------------*/
00095 
00096 /** @defgroup CRYPEx_Exported_Functions CRYPEx Exported Functions
00097   * @{
00098   */
00099 
00100 
00101 /** @defgroup CRYPEx_Exported_Functions_Group1 Extended callback function 
00102  *  @brief    Extended callback functions. 
00103  *
00104 @verbatim   
00105  ===============================================================================
00106                  ##### Extended callback functions #####
00107  =============================================================================== 
00108     [..]  This section provides callback function:
00109       (+) Computation completed.
00110 
00111 @endverbatim
00112   * @{
00113   */
00114 
00115 
00116 /**
00117   * @brief  Computation completed callbacks.
00118   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
00119   *         the configuration information for CRYP module
00120   * @retval None
00121   */
00122 __weak void HAL_CRYPEx_ComputationCpltCallback(CRYP_HandleTypeDef *hcryp)
00123 {
00124   /* Prevent unused argument(s) compilation warning */
00125   UNUSED(hcryp);
00126 
00127   /* NOTE : This function should not be modified; when the callback is needed,
00128             the HAL_CRYPEx_ComputationCpltCallback can be implemented in the user file
00129    */ 
00130 }
00131 
00132 /**
00133   * @}
00134   */
00135 
00136 /** @defgroup CRYPEx_Exported_Functions_Group2 AES extended processing functions 
00137  *  @brief   Extended processing functions. 
00138  *
00139 @verbatim   
00140   ==============================================================================
00141                       ##### AES extended processing functions #####
00142   ==============================================================================  
00143     [..]  This section provides functions allowing to:
00144       (+) Encrypt plaintext or decrypt cipher text using AES algorithm in different chaining modes.
00145           Functions are generic (handles ECB, CBC and CTR and all modes) and are only differentiated
00146           based on the processing type. Three processing types are available:
00147           (++) Polling mode
00148           (++) Interrupt mode
00149           (++) DMA mode
00150       (+) Generate and authentication tag in addition to encrypt/decrypt a plain/cipher text using AES 
00151           algorithm in different chaining modes.
00152           Functions are generic (handles GCM, GMAC and CMAC) and process only one phase so that steps
00153           can be skipped if so required. Functions are only differentiated based on the processing type. 
00154           Three processing types are available:
00155           (++) Polling mode
00156           (++) Interrupt mode
00157           (++) DMA mode          
00158 
00159 @endverbatim
00160   * @{
00161   */
00162 
00163 /**
00164   * @brief  Carry out in polling mode the ciphering or deciphering operation according to
00165   *         hcryp->Init structure fields, all operating modes (encryption, key derivation and/or decryption) and 
00166   *         chaining modes ECB, CBC and CTR are managed by this function in polling mode.
00167   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
00168   *         the configuration information for CRYP module
00169   * @param  pInputData: Pointer to the plain text in case of encryption or cipher text in case of decryption
00170   *                     or key derivation+decryption.
00171   *                     Parameter is meaningless in case of key derivation.      
00172   * @param  Size: Length of the input data buffer in bytes, must be a multiple of 16.
00173   *               Parameter is meaningless in case of key derivation.  
00174   * @param  pOutputData: Pointer to the cipher text in case of encryption or plain text in case of 
00175   *                     decryption/key derivation+decryption, or pointer to the derivative keys in
00176   *                     case of key derivation only.   
00177   * @param  Timeout: Specify Timeout value 
00178   * @retval HAL status
00179   */
00180 HAL_StatusTypeDef HAL_CRYPEx_AES(CRYP_HandleTypeDef *hcryp, uint8_t *pInputData, uint16_t Size, uint8_t *pOutputData, uint32_t Timeout)
00181 {
00182 
00183   if (hcryp->State == HAL_CRYP_STATE_READY)
00184   {
00185     /* Check parameters setting */
00186     if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_KEYDERIVATION)
00187     {
00188       if (pOutputData == NULL) 
00189       {
00190         return  HAL_ERROR;
00191       }
00192     }
00193     else
00194     {
00195       if ((pInputData == NULL) || (pOutputData == NULL) || (Size == 0))
00196       {
00197         return  HAL_ERROR;
00198       }
00199     }
00200     
00201     /* Process Locked */
00202     __HAL_LOCK(hcryp);
00203   
00204     /* Change the CRYP state */
00205     hcryp->State = HAL_CRYP_STATE_BUSY;
00206   
00207     /* Call CRYP_ReadKey() API if the operating mode is set to
00208        key derivation, CRYP_ProcessData() otherwise  */
00209     if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_KEYDERIVATION)
00210     {
00211       if(CRYP_ReadKey(hcryp, pOutputData, Timeout) != HAL_OK)
00212       {
00213         return HAL_TIMEOUT;
00214       }    
00215     }
00216     else
00217     {
00218       if(CRYP_ProcessData(hcryp, pInputData, Size, pOutputData, Timeout) != HAL_OK)
00219       {
00220         return HAL_TIMEOUT;
00221       }
00222     }
00223   
00224     /* If the state has not been set to SUSPENDED, set it to
00225        READY, otherwise keep it as it is */
00226     if (hcryp->State != HAL_CRYP_STATE_SUSPENDED)
00227     {
00228       hcryp->State = HAL_CRYP_STATE_READY;
00229     }
00230   
00231     /* Process Unlocked */
00232     __HAL_UNLOCK(hcryp);
00233   
00234     return HAL_OK;
00235   }
00236   else
00237   {
00238     return HAL_BUSY;
00239   }
00240 }
00241 
00242 
00243 
00244 /**
00245   * @brief  Carry out in interrupt mode the ciphering or deciphering operation according to
00246   *         hcryp->Init structure fields, all operating modes (encryption, key derivation and/or decryption) and 
00247   *         chaining modes ECB, CBC and CTR are managed by this function in interrupt mode.
00248   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
00249   *         the configuration information for CRYP module
00250   * @param  pInputData: Pointer to the plain text in case of encryption or cipher text in case of decryption
00251   *                     or key derivation+decryption.
00252   *                     Parameter is meaningless in case of key derivation.      
00253   * @param  Size: Length of the input data buffer in bytes, must be a multiple of 16.
00254   *               Parameter is meaningless in case of key derivation.  
00255   * @param  pOutputData: Pointer to the cipher text in case of encryption or plain text in case of 
00256   *                     decryption/key derivation+decryption, or pointer to the derivative keys in 
00257   *                     case of key derivation only.    
00258   * @retval HAL status
00259   */
00260 HAL_StatusTypeDef HAL_CRYPEx_AES_IT(CRYP_HandleTypeDef *hcryp,  uint8_t *pInputData, uint16_t Size, uint8_t *pOutputData)
00261 {
00262   uint32_t inputaddr = 0;
00263   
00264   if(hcryp->State == HAL_CRYP_STATE_READY)
00265   {
00266     /* Check parameters setting */
00267     if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_KEYDERIVATION)
00268     {
00269       if (pOutputData == NULL) 
00270       {
00271         return  HAL_ERROR;
00272       }
00273     }
00274     else
00275     {
00276       if ((pInputData == NULL) || (pOutputData == NULL) || (Size == 0))
00277       {
00278         return  HAL_ERROR;
00279       }
00280     }
00281     /* Process Locked */
00282     __HAL_LOCK(hcryp);
00283     
00284     /* If operating mode is not limited to key derivation only,
00285        get the buffers addresses and sizes */
00286     if (hcryp->Init.OperatingMode != CRYP_ALGOMODE_KEYDERIVATION)
00287     {
00288 
00289       hcryp->CrypInCount = Size;
00290       hcryp->pCrypInBuffPtr = pInputData;
00291       hcryp->pCrypOutBuffPtr = pOutputData;
00292       hcryp->CrypOutCount = Size;
00293     }
00294     
00295     /* Change the CRYP state */
00296     hcryp->State = HAL_CRYP_STATE_BUSY;
00297   
00298       /* Process Unlocked */
00299     __HAL_UNLOCK(hcryp);
00300     
00301     /* Enable Computation Complete Flag and Error Interrupts */
00302     __HAL_CRYP_ENABLE_IT(CRYP_IT_CCFIE|CRYP_IT_ERRIE);
00303     
00304     
00305     /* If operating mode is key derivation only, the input data have 
00306        already been entered during the initialization process. For
00307        the other operating modes, they are fed to the CRYP hardware 
00308        block at this point. */
00309     if (hcryp->Init.OperatingMode != CRYP_ALGOMODE_KEYDERIVATION)
00310     {
00311       /* Initiate the processing under interrupt in entering 
00312          the first input data */
00313       inputaddr = (uint32_t)hcryp->pCrypInBuffPtr;
00314       /* Increment/decrement instance pointer/counter */
00315       hcryp->pCrypInBuffPtr += 16;
00316       hcryp->CrypInCount -= 16;
00317       /* Write the first input block in the Data Input register */
00318       hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00319       inputaddr+=4;
00320       hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00321       inputaddr+=4;
00322       hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
00323       inputaddr+=4;
00324       hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00325     }
00326     
00327     /* Return function status */
00328     return HAL_OK;
00329   }
00330   else
00331   {
00332     return HAL_BUSY;   
00333   }
00334 }
00335   
00336   
00337   
00338 
00339 
00340 /**
00341   * @brief  Carry out in DMA mode the ciphering or deciphering operation according to
00342   *         hcryp->Init structure fields.
00343   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
00344   *         the configuration information for CRYP module
00345   * @param  pInputData: Pointer to the plain text in case of encryption or cipher text in case of decryption
00346   *                     or key derivation+decryption.    
00347   * @param  Size: Length of the input data buffer in bytes, must be a multiple of 16.
00348   * @param  pOutputData: Pointer to the cipher text in case of encryption or plain text in case of 
00349   *                     decryption/key derivation+decryption.
00350   * @note   Chaining modes ECB, CBC and CTR are managed by this function in DMA mode.   
00351   * @note   Supported operating modes are encryption, decryption and key derivation with decryption. 
00352   * @note   No DMA channel is provided for key derivation only and therefore, access to AES_KEYRx 
00353   *         registers must be done by software.   
00354   * @note   This API is not applicable to key derivation only; for such a mode, access to AES_KEYRx 
00355   *         registers must be done by software thru HAL_CRYPEx_AES() or HAL_CRYPEx_AES_IT() APIs.
00356   * @note   pInputData and pOutputData buffers must be 32-bit aligned to ensure a correct DMA transfer to and from the IP.   
00357   * @retval HAL status
00358   */
00359 HAL_StatusTypeDef HAL_CRYPEx_AES_DMA(CRYP_HandleTypeDef *hcryp,  uint8_t *pInputData, uint16_t Size, uint8_t *pOutputData)
00360 {
00361   uint32_t inputaddr = 0;
00362   uint32_t outputaddr = 0;
00363   
00364   if (hcryp->State == HAL_CRYP_STATE_READY)
00365   {
00366     /* Check parameters setting */
00367     if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_KEYDERIVATION)
00368     {
00369       /* no DMA channel is provided for key derivation operating mode, 
00370          access to AES_KEYRx registers must be done by software */
00371       return  HAL_ERROR;
00372     }
00373     else
00374     {
00375       if ((pInputData == NULL) || (pOutputData == NULL) || (Size == 0))
00376       {
00377         return  HAL_ERROR;
00378       }
00379     }
00380     
00381     
00382     /* Process Locked */
00383     __HAL_LOCK(hcryp);
00384     
00385     inputaddr  = (uint32_t)pInputData;
00386     outputaddr = (uint32_t)pOutputData;
00387     
00388     /* Change the CRYP state */
00389     hcryp->State = HAL_CRYP_STATE_BUSY;
00390     
00391     /* Set the input and output addresses and start DMA transfer */ 
00392     CRYP_SetDMAConfig(hcryp, inputaddr, Size, outputaddr);
00393     
00394     /* Process Unlocked */
00395     __HAL_UNLOCK(hcryp);
00396     
00397     /* Return function status */
00398     return HAL_OK;
00399   }
00400   else
00401   {
00402     return HAL_BUSY;   
00403   }
00404 }
00405   
00406 
00407 
00408 
00409 
00410 
00411 /**
00412   * @brief  Carry out in polling mode the authentication tag generation as well as the ciphering or deciphering 
00413   *         operation according to hcryp->Init structure fields. 
00414   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
00415   *         the configuration information for CRYP module
00416   * @param  pInputData: 
00417   *         - pointer to payload data in GCM payload phase, 
00418   *         - pointer to B0 block in CMAC header phase,
00419   *         - pointer to C block in CMAC final phase. 
00420   *         - Parameter is meaningless in case of GCM/GMAC init, header and final phases.                                       
00421   * @param  Size: 
00422   *         - length of the input payload data buffer in bytes,
00423   *         - length of B0 block (in bytes) in CMAC header phase,
00424   *         - length of C block (in bytes) in CMAC final phase.
00425   *         - Parameter is meaningless in case of GCM/GMAC init and header phases.                                
00426   * @param  pOutputData: 
00427   *         - pointer to plain or cipher text in GCM payload phase, 
00428   *         - pointer to authentication tag in GCM/GMAC and CMAC final phases.
00429   *         - Parameter is meaningless in case of GCM/GMAC init and header phases
00430   *           and in case of CMAC header phase.  
00431   * @param  Timeout: Specify Timeout value 
00432   * @note   Supported operating modes are encryption and decryption, supported chaining modes are GCM, GMAC and CMAC.
00433   * @note   Phases are singly processed according to hcryp->Init.GCMCMACPhase so that steps in these specific chaining modes 
00434   *         can be skipped by the user if so required.          
00435   * @retval HAL status
00436   */
00437 HAL_StatusTypeDef HAL_CRYPEx_AES_Auth(CRYP_HandleTypeDef *hcryp, uint8_t *pInputData, uint64_t Size, uint8_t *pOutputData, uint32_t Timeout)
00438 {
00439   uint32_t index          = 0;
00440   uint32_t inputaddr      = 0;
00441   uint32_t outputaddr     = 0;
00442   uint32_t tagaddr        = 0;
00443   uint64_t headerlength   = 0; 
00444   uint64_t inputlength    = 0;
00445   uint64_t payloadlength  = 0; 
00446   uint32_t difflength     = 0;
00447   uint32_t addhoc_process = 0;  
00448   
00449   if (hcryp->State == HAL_CRYP_STATE_READY)
00450   {
00451     /* input/output parameters check */
00452     if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_HEADER_PHASE)
00453     {
00454       if ((hcryp->Init.Header != NULL) && (hcryp->Init.HeaderSize == 0))
00455       {
00456         return  HAL_ERROR;
00457       }
00458       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
00459       {
00460         /* In case of CMAC header phase resumption, we can have pInputData = NULL and  Size = 0 */
00461         if (((pInputData != NULL) && (Size == 0)) || ((pInputData == NULL) && (Size != 0)))
00462         {
00463           return  HAL_ERROR;
00464         }
00465       }
00466     }
00467     else if (hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE)
00468     {   
00469       if ((pInputData == NULL) || (pOutputData == NULL) || (Size == 0))
00470       {
00471         return  HAL_ERROR;
00472       }
00473     }
00474     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_FINAL_PHASE)
00475     {
00476       if (pOutputData == NULL)
00477       {
00478         return  HAL_ERROR;
00479       }
00480       if ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC) && (pInputData == NULL))
00481       {
00482         return  HAL_ERROR;
00483       }
00484     }
00485       
00486       
00487     /* Process Locked */
00488     __HAL_LOCK(hcryp);
00489   
00490     /* Change the CRYP state */
00491     hcryp->State = HAL_CRYP_STATE_BUSY;
00492   
00493     /*=====================*/
00494     /* GCM/GMAC init phase */
00495     /*=====================*/
00496     /* In case of init phase, the input data (Key and Initialization Vector) have 
00497        already been entered during the initialization process. Therefore, the
00498        API just waits for the CCF flag to be set. */
00499     if (hcryp->Init.GCMCMACPhase == CRYP_GCM_INIT_PHASE)
00500     {
00501       /* just wait for hash computation */
00502       if(CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK)  
00503       { 
00504         hcryp->State = HAL_CRYP_STATE_READY;        
00505         __HAL_UNLOCK(hcryp);
00506         return HAL_TIMEOUT;
00507       }
00508       
00509       /* Clear CCF Flag */
00510       __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
00511       /* Mark that the initialization phase is over */
00512       hcryp->Phase = HAL_CRYP_PHASE_INIT_OVER;
00513     }
00514     /*===============================*/
00515     /* GCM/GMAC or CMAC header phase */
00516     /*===============================*/
00517     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_HEADER_PHASE)
00518     {      
00519       /* Set header phase; for GCM or GMAC, set data-byte at this point */
00520       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC)
00521       {
00522         MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH|AES_CR_DATATYPE, CRYP_GCMCMAC_HEADER_PHASE|hcryp->Init.DataType);
00523       }
00524       else
00525       {
00526         MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCMCMAC_HEADER_PHASE);
00527       }
00528          
00529       /* Enable the Peripheral */
00530       __HAL_CRYP_ENABLE();
00531       
00532       /* in case of CMAC, enter B0 block in header phase, before the header itself. */
00533       /* If Size = 0 (possible case of resumption after CMAC header phase suspension),
00534          skip these steps and go directly to header buffer feeding to the HW */
00535       if ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC) && (Size != 0))
00536       {
00537         inputaddr = (uint32_t)pInputData; 
00538         
00539         for(index=0; (index < Size); index += 16)
00540         {
00541           /* Write the Input block in the Data Input register */
00542           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00543           inputaddr+=4;
00544           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00545           inputaddr+=4;
00546           hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
00547           inputaddr+=4;
00548           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00549           inputaddr+=4;
00550           
00551           if(CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK)  
00552           { 
00553             hcryp->State = HAL_CRYP_STATE_READY;        
00554             __HAL_UNLOCK(hcryp);
00555             return HAL_TIMEOUT;
00556           }
00557           /* Clear CCF Flag */
00558           __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);           
00559 
00560           /* If the suspension flag has been raised and if the processing is not about
00561            to end, suspend processing */  
00562           if ((hcryp->SuspendRequest == HAL_CRYP_SUSPEND) && ((index+16) < Size))        
00563           {
00564             /* reset SuspendRequest */
00565             hcryp->SuspendRequest = HAL_CRYP_SUSPEND_NONE;
00566             /* Change the CRYP state */
00567             hcryp->State = HAL_CRYP_STATE_SUSPENDED;
00568             /* Mark that the header phase is over */
00569             hcryp->Phase = HAL_CRYP_PHASE_HEADER_SUSPENDED;
00570             
00571            /* Save current reading and writing locations of Input and Output buffers */
00572            hcryp->pCrypInBuffPtr  =  (uint8_t *)inputaddr;
00573            /* Save the total number of bytes (B blocks + header) that remain to be 
00574               processed at this point */
00575            hcryp->CrypInCount     =  hcryp->Init.HeaderSize + Size - (index+16);
00576         
00577            /* Process Unlocked */
00578             __HAL_UNLOCK(hcryp);
00579         
00580             return HAL_OK;
00581           } 
00582         } /* for(index=0; (index < Size); index += 16) */             
00583       }
00584       
00585       /* Enter header */  
00586       inputaddr = (uint32_t)hcryp->Init.Header; 
00587       /* Local variable headerlength is a number of bytes multiple of 128 bits,
00588          remaining header data (if any) are handled after this loop */
00589       headerlength =  (((hcryp->Init.HeaderSize)/16)*16) ; 
00590       if ((hcryp->Init.HeaderSize % 16) != 0)
00591       {
00592         difflength = (uint32_t) (hcryp->Init.HeaderSize - headerlength);   
00593       }
00594       for(index=0; index < headerlength; index += 16)
00595       {
00596         /* Write the Input block in the Data Input register */
00597         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00598         inputaddr+=4;
00599         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00600         inputaddr+=4;
00601         hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
00602         inputaddr+=4;
00603         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00604         inputaddr+=4;
00605         
00606         if(CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK)  
00607         { 
00608           hcryp->State = HAL_CRYP_STATE_READY;        
00609           __HAL_UNLOCK(hcryp);
00610           return HAL_TIMEOUT;
00611         }
00612         /* Clear CCF Flag */
00613         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR); 
00614         
00615         /* If the suspension flag has been raised and if the processing is not about
00616          to end, suspend processing */  
00617         if ((hcryp->SuspendRequest == HAL_CRYP_SUSPEND) && ((index+16) < headerlength))        
00618         {
00619           /* reset SuspendRequest */
00620           hcryp->SuspendRequest = HAL_CRYP_SUSPEND_NONE;
00621           /* Change the CRYP state */
00622           hcryp->State = HAL_CRYP_STATE_SUSPENDED;
00623           /* Mark that the header phase is over */
00624           hcryp->Phase = HAL_CRYP_PHASE_HEADER_SUSPENDED;
00625           
00626          /* Save current reading and writing locations of Input and Output buffers */
00627          hcryp->pCrypInBuffPtr  =  (uint8_t *)inputaddr;
00628          /* Save the total number of bytes that remain to be processed at this point */
00629           hcryp->CrypInCount =  hcryp->Init.HeaderSize - (index+16);
00630       
00631          /* Process Unlocked */
00632           __HAL_UNLOCK(hcryp);
00633       
00634           return HAL_OK;
00635         }       
00636       }
00637       
00638       /* Case header length is not a multiple of 16 bytes */
00639       if (difflength != 0)
00640       {
00641         hcryp->pCrypInBuffPtr  =  (uint8_t *)inputaddr;
00642         CRYP_Padding(hcryp, difflength, CRYP_POLLING_ON);   
00643       }       
00644       
00645       /* Mark that the header phase is over */
00646       hcryp->Phase = HAL_CRYP_PHASE_HEADER_OVER;
00647     }
00648     /*========================*/
00649     /* GCM/GMAC payload phase */
00650     /*========================*/
00651     else if (hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE)
00652     {
00653       
00654       MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCM_PAYLOAD_PHASE);
00655       
00656       /* if the header phase has been bypassed, AES must be enabled again */
00657       if (hcryp->Phase == HAL_CRYP_PHASE_INIT_OVER)
00658       {
00659         __HAL_CRYP_ENABLE();  
00660       }
00661       
00662       inputaddr  = (uint32_t)pInputData;
00663       outputaddr = (uint32_t)pOutputData;
00664       
00665       /* Enter payload */
00666       /* Specific handling to manage payload last block size less than 128 bits
00667         when GCM encryption or decryption is selected */
00668       if ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC) && \
00669           ((Size % 16) != 0))
00670       {
00671         payloadlength = (Size/16) * 16;
00672         difflength = (uint32_t) (Size - payloadlength);
00673         addhoc_process = 1;
00674       }
00675       else
00676       {
00677         payloadlength = Size;
00678         addhoc_process = 0;      
00679       }
00680             
00681       /* Feed payload */  
00682       for(index=0; index < payloadlength; index += 16)
00683       {
00684         /* Write the Input block in the Data Input register */
00685         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00686         inputaddr+=4;
00687         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00688         inputaddr+=4;
00689         hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
00690         inputaddr+=4;
00691         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00692         inputaddr+=4;
00693         
00694         if(CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK)  
00695         { 
00696           hcryp->State = HAL_CRYP_STATE_READY;        
00697           __HAL_UNLOCK(hcryp);
00698           return HAL_TIMEOUT;
00699         }
00700           
00701         /* Clear CCF Flag */
00702         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
00703         
00704         /* Retrieve output data: read the output block 
00705            from the Data Output Register */
00706         *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
00707         outputaddr+=4;
00708         *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
00709         outputaddr+=4;
00710         *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
00711         outputaddr+=4;
00712         *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
00713         outputaddr+=4;
00714        
00715         /* If the suspension flag has been raised and if the processing is not about
00716          to end, suspend processing */  
00717         if ((hcryp->SuspendRequest == HAL_CRYP_SUSPEND) && ((index+16) < payloadlength))
00718         {
00719           /* no flag waiting under IRQ handling */
00720           if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_ENCRYPT)
00721           {
00722             /* Ensure that Busy flag is reset */
00723             if(CRYP_WaitOnBusyFlagReset(hcryp, CRYP_BUSY_TIMEOUTVALUE) != HAL_OK)  
00724             {   
00725               hcryp->State = HAL_CRYP_STATE_READY;        
00726               __HAL_UNLOCK(hcryp);
00727               return HAL_TIMEOUT;
00728             }
00729           }               
00730           /* reset SuspendRequest */
00731           hcryp->SuspendRequest = HAL_CRYP_SUSPEND_NONE;
00732           /* Change the CRYP state */
00733           hcryp->State = HAL_CRYP_STATE_SUSPENDED;
00734           /* Mark that the header phase is over */
00735           hcryp->Phase = HAL_CRYP_PHASE_HEADER_SUSPENDED;
00736           
00737           /* Save current reading and writing locations of Input and Output buffers */
00738           hcryp->pCrypOutBuffPtr =  (uint8_t *)outputaddr;
00739           hcryp->pCrypInBuffPtr  =  (uint8_t *)inputaddr;
00740           /* Save the number of bytes that remain to be processed at this point */
00741           hcryp->CrypInCount     =  Size - (index+16);          
00742         
00743           /* Process Unlocked */
00744           __HAL_UNLOCK(hcryp);
00745         
00746           return HAL_OK;
00747         }            
00748         
00749       }
00750       
00751       /* Additional processing to manage GCM encryption and decryption cases when 
00752          payload last block size less than 128 bits */
00753       if (addhoc_process == 1)
00754       {
00755         
00756         hcryp->pCrypInBuffPtr  =  (uint8_t *)inputaddr;
00757         hcryp->pCrypOutBuffPtr =  (uint8_t *)outputaddr;        
00758         CRYP_Padding(hcryp, difflength, CRYP_POLLING_ON); 
00759        
00760       } /* (addhoc_process == 1) */
00761          
00762       /* Mark that the payload phase is over */
00763       hcryp->Phase = HAL_CRYP_PHASE_PAYLOAD_OVER;         
00764     }
00765     /*==============================*/
00766     /* GCM/GMAC or CMAC final phase */
00767     /*==============================*/
00768     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_FINAL_PHASE)
00769     {    
00770       tagaddr = (uint32_t)pOutputData;
00771       
00772       MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCMCMAC_FINAL_PHASE);
00773       
00774       /* if the header and payload phases have been bypassed, AES must be enabled again */
00775       if (hcryp->Phase == HAL_CRYP_PHASE_INIT_OVER)
00776       {
00777         __HAL_CRYP_ENABLE();  
00778       }
00779       
00780       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC)
00781       {
00782         headerlength = hcryp->Init.HeaderSize * 8; /* Header length in bits */
00783         inputlength = Size * 8;                    /* input length in bits */ 
00784         
00785            
00786         if(hcryp->Init.DataType == CRYP_DATATYPE_1B)
00787         {
00788           hcryp->Instance->DINR = __RBIT((headerlength)>>32);
00789           hcryp->Instance->DINR = __RBIT(headerlength);
00790           hcryp->Instance->DINR = __RBIT((inputlength)>>32);
00791           hcryp->Instance->DINR = __RBIT(inputlength);
00792         }
00793         else if(hcryp->Init.DataType == CRYP_DATATYPE_8B)
00794         {
00795           hcryp->Instance->DINR = __REV((headerlength)>>32);
00796           hcryp->Instance->DINR = __REV(headerlength);
00797           hcryp->Instance->DINR = __REV((inputlength)>>32);
00798           hcryp->Instance->DINR = __REV(inputlength);
00799         } 
00800         else if(hcryp->Init.DataType == CRYP_DATATYPE_16B)
00801         {
00802           hcryp->Instance->DINR = __ROR((headerlength)>>32, 16);
00803           hcryp->Instance->DINR = __ROR(headerlength, 16);
00804           hcryp->Instance->DINR = __ROR((inputlength)>>32, 16);
00805           hcryp->Instance->DINR = __ROR(inputlength, 16);          
00806         }
00807         else if(hcryp->Init.DataType == CRYP_DATATYPE_32B)
00808         {
00809           hcryp->Instance->DINR = (uint32_t)(headerlength>>32);
00810           hcryp->Instance->DINR = (uint32_t)(headerlength);
00811           hcryp->Instance->DINR = (uint32_t)(inputlength>>32);
00812           hcryp->Instance->DINR = (uint32_t)(inputlength);
00813         }
00814       }
00815       else if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
00816       {
00817         inputaddr  = (uint32_t)pInputData;
00818         /* Enter the last block made of a 128-bit value formatted
00819            from the original B0 packet. */
00820         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00821         inputaddr+=4;
00822         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00823         inputaddr+=4;
00824         hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
00825         inputaddr+=4;
00826         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
00827       }
00828       
00829       
00830       if(CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK)  
00831       { 
00832           hcryp->State = HAL_CRYP_STATE_READY;        
00833           __HAL_UNLOCK(hcryp);
00834           return HAL_TIMEOUT;
00835       }
00836 
00837       /* Read the Auth TAG in the Data Out register */
00838       *(uint32_t*)(tagaddr) = hcryp->Instance->DOUTR;
00839       tagaddr+=4;
00840       *(uint32_t*)(tagaddr) = hcryp->Instance->DOUTR;
00841       tagaddr+=4;
00842       *(uint32_t*)(tagaddr) = hcryp->Instance->DOUTR;
00843       tagaddr+=4;
00844       *(uint32_t*)(tagaddr) = hcryp->Instance->DOUTR; 
00845          
00846 
00847       /* Clear CCF Flag */
00848       __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
00849       /* Mark that the final phase is over */
00850       hcryp->Phase = HAL_CRYP_PHASE_FINAL_OVER;
00851       /* Disable the Peripheral */
00852       __HAL_CRYP_DISABLE();
00853     }
00854     /*=================================================*/
00855     /* case incorrect hcryp->Init.GCMCMACPhase setting */
00856     /*=================================================*/
00857     else
00858     {
00859       hcryp->State = HAL_CRYP_STATE_ERROR; 
00860       __HAL_UNLOCK(hcryp); 
00861       return HAL_ERROR;
00862     }
00863  
00864     /* Change the CRYP state */
00865     hcryp->State = HAL_CRYP_STATE_READY;
00866   
00867     /* Process Unlocked */
00868     __HAL_UNLOCK(hcryp);
00869   
00870     return HAL_OK;
00871   }
00872   else
00873   {
00874     return HAL_BUSY;
00875   }
00876 }
00877 
00878 
00879 
00880 
00881 /**
00882   * @brief  Carry out in interrupt mode the authentication tag generation as well as the ciphering or deciphering 
00883   *         operation according to hcryp->Init structure fields. 
00884   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
00885   *         the configuration information for CRYP module
00886   * @param  pInputData: 
00887   *         - pointer to payload data in GCM payload phase,
00888   *         - pointer to B0 block in CMAC header phase,
00889   *         - pointer to C block in CMAC final phase.
00890   *         Parameter is meaningless in case of GCM/GMAC init, header and final phases.         
00891   * @param  Size: 
00892   *         - length of the input payload data buffer in bytes,
00893   *         - length of B0 block (in bytes) in CMAC header phase,
00894   *         - length of C block (in bytes) in CMAC final phase.
00895   *         - Parameter is meaningless in case of GCM/GMAC init and header phases.             
00896   * @param  pOutputData: 
00897   *         - pointer to plain or cipher text in GCM payload phase, 
00898   *         - pointer to authentication tag in GCM/GMAC and CMAC final phases.
00899   *         - Parameter is meaningless in case of GCM/GMAC init and header phases
00900   *           and in case of CMAC header phase.
00901   * @note   Supported operating modes are encryption and decryption, supported chaining modes are GCM, GMAC and CMAC.
00902   * @note   Phases are singly processed according to hcryp->Init.GCMCMACPhase so that steps in these specific chaining modes 
00903   *         can be skipped by the user if so required.                                 
00904   * @retval HAL status
00905   */
00906 HAL_StatusTypeDef HAL_CRYPEx_AES_Auth_IT(CRYP_HandleTypeDef *hcryp, uint8_t *pInputData, uint64_t Size, uint8_t *pOutputData)
00907 {
00908 
00909   uint32_t inputaddr      = 0;
00910   uint64_t headerlength   = 0;
00911   uint64_t inputlength    = 0;
00912   uint32_t index          = 0;
00913   uint32_t addhoc_process = 0; 
00914   uint32_t difflength     = 0;
00915   uint32_t difflengthmod4 = 0;
00916   uint32_t mask[3]        = {0x0FF, 0x0FFFF, 0x0FFFFFF};     
00917  
00918 
00919   if (hcryp->State == HAL_CRYP_STATE_READY)
00920   {
00921     /* input/output parameters check */
00922     if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_HEADER_PHASE)
00923     {
00924       if ((hcryp->Init.Header != NULL) && (hcryp->Init.HeaderSize == 0))
00925       {
00926         return  HAL_ERROR;
00927       }
00928       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
00929       {
00930         /* In case of CMAC header phase resumption, we can have pInputData = NULL and  Size = 0 */
00931         if (((pInputData != NULL) && (Size == 0)) || ((pInputData == NULL) && (Size != 0)))
00932         {
00933           return  HAL_ERROR;
00934         }
00935       }      
00936     }
00937     else if (hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE)
00938     {   
00939       if ((pInputData == NULL) || (pOutputData == NULL) || (Size == 0))
00940       {
00941         return  HAL_ERROR;
00942       }
00943     }
00944     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_FINAL_PHASE)
00945     {
00946       if (pOutputData == NULL)
00947       {
00948         return  HAL_ERROR;
00949       }
00950       if ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC) && (pInputData == NULL))
00951       {
00952         return  HAL_ERROR;
00953       }
00954     }
00955     
00956     
00957     /* Process Locked */
00958     __HAL_LOCK(hcryp);
00959     
00960     /* Change the CRYP state */
00961     hcryp->State = HAL_CRYP_STATE_BUSY;
00962     
00963     /* Process Unlocked */
00964     __HAL_UNLOCK(hcryp);
00965                            
00966     /* Enable Computation Complete Flag and Error Interrupts */
00967     __HAL_CRYP_ENABLE_IT(CRYP_IT_CCFIE|CRYP_IT_ERRIE);
00968 
00969 
00970 
00971     /*=====================*/
00972     /* GCM/GMAC init phase */
00973     /*=====================*/
00974     if (hcryp->Init.GCMCMACPhase == CRYP_GCM_INIT_PHASE)
00975     {    
00976     /* In case of init phase, the input data (Key and Initialization Vector) have 
00977        already been entered during the initialization process. Therefore, the
00978        software just waits for the CCF interrupt to be raised and which will
00979        be handled by CRYP_AES_Auth_IT() API. */
00980     }
00981     /*===============================*/
00982     /* GCM/GMAC or CMAC header phase */
00983     /*===============================*/   
00984     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_HEADER_PHASE)
00985     {
00986       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
00987       {
00988         /* In case of CMAC, B blocks are first entered, before the header.
00989            Therefore, B blocks and the header are entered back-to-back
00990            as if it was only one single block. 
00991            However, in case of resumption after suspension, if all the
00992            B blocks have been entered (in that case, Size = 0), only the
00993            remainder of the non-processed header bytes are entered. */
00994           if (Size != 0)
00995           {
00996             hcryp->CrypInCount = Size + hcryp->Init.HeaderSize;
00997             hcryp->pCrypInBuffPtr = pInputData;
00998           }
00999           else
01000           {
01001             hcryp->CrypInCount = hcryp->Init.HeaderSize;
01002             hcryp->pCrypInBuffPtr = hcryp->Init.Header;
01003           }
01004       }
01005       else
01006       {
01007         /* Get the header addresses and sizes */
01008         hcryp->CrypInCount = hcryp->Init.HeaderSize;
01009         hcryp->pCrypInBuffPtr = hcryp->Init.Header;
01010       }    
01011     
01012       inputaddr = (uint32_t)hcryp->pCrypInBuffPtr;
01013       
01014       /* Set header phase; for GCM or GMAC, set data-byte at this point */
01015       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC)
01016       {
01017         MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH|AES_CR_DATATYPE, CRYP_GCMCMAC_HEADER_PHASE|hcryp->Init.DataType);
01018       }
01019       else
01020       {
01021         MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCMCMAC_HEADER_PHASE);
01022       }
01023        
01024       /* Enable the Peripheral */
01025       __HAL_CRYP_ENABLE();
01026     
01027       /* Increment/decrement instance pointer/counter */
01028       if (hcryp->CrypInCount == 0)
01029       {
01030         /* Case of no header */
01031         hcryp->State = HAL_CRYP_STATE_READY; 
01032         return HAL_OK;        
01033       }
01034       else if (hcryp->CrypInCount < 16)
01035       {
01036         hcryp->CrypInCount = 0;
01037         addhoc_process = 1;  
01038         difflength = (uint32_t) (hcryp->Init.HeaderSize);
01039         difflengthmod4 = difflength%4;              
01040       }
01041       else
01042       {
01043         hcryp->pCrypInBuffPtr += 16;
01044         hcryp->CrypInCount -= 16;
01045       }
01046       
01047       
01048       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
01049       { 
01050         if (hcryp->CrypInCount == hcryp->Init.HeaderSize)
01051         {
01052           /* All B blocks will have been entered after the next
01053              four DINR writing, so point at header buffer for
01054              the next iteration */
01055           hcryp->pCrypInBuffPtr = hcryp->Init.Header;
01056         }
01057       }       
01058     
01059       /* Enter header first block to initiate the process
01060          in the Data Input register */
01061       if (addhoc_process == 0)
01062       { 
01063         /* Header has size equal or larger than 128 bits */        
01064         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01065         inputaddr+=4;
01066         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01067         inputaddr+=4;
01068         hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
01069         inputaddr+=4;
01070         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01071       }
01072       else
01073       {
01074         /* Header has size less than 128 bits */ 
01075         /* Enter complete words when possible */
01076         for(index=0; index < (difflength/4); index ++)
01077         {
01078           /* Write the Input block in the Data Input register */
01079           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01080           inputaddr+=4;
01081         }
01082         /* Enter incomplete word padded with zeroes if applicable 
01083           (case of header length not a multiple of 32-bits) */
01084         if (difflengthmod4 != 0)
01085         {         
01086           hcryp->Instance->DINR = ((*(uint32_t*)(inputaddr)) & mask[difflengthmod4-1]);
01087         }         
01088         /* Pad with zero-words to reach 128-bit long block and wrap-up header feeding to the IP */
01089         for(index=0; index < (4 - ((difflength+3)/4)); index ++)         
01090         {
01091           hcryp->Instance->DINR = 0;
01092         }                 
01093       
01094       }
01095     }
01096     /*========================*/
01097     /* GCM/GMAC payload phase */
01098     /*========================*/
01099     else if (hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE)
01100     {
01101       /* Get the buffer addresses and sizes */
01102       hcryp->CrypInCount = Size;
01103       hcryp->pCrypInBuffPtr = pInputData;
01104       hcryp->pCrypOutBuffPtr = pOutputData;
01105       hcryp->CrypOutCount = Size; 
01106     
01107       inputaddr = (uint32_t)hcryp->pCrypInBuffPtr;
01108       
01109       MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCM_PAYLOAD_PHASE);
01110        
01111       /* if the header phase has been bypassed, AES must be enabled again */
01112       if (hcryp->Phase == HAL_CRYP_PHASE_INIT_OVER)
01113       {
01114         __HAL_CRYP_ENABLE();  
01115       }
01116     
01117      /* Specific handling to manage payload size less than 128 bits
01118         when GCM encryption or decryption is selected */
01119       if ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC) && \
01120           (Size < 16))
01121       {
01122         /* Software workaround applied to GCM encryption only */ 
01123         if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_ENCRYPT)
01124         {
01125           /* Change the mode configured in CHMOD bits of CR register to select CTR mode */   
01126           __HAL_CRYP_SET_CHAININGMODE(CRYP_CHAINMODE_AES_CTR);
01127         }
01128 
01129         /* Set hcryp->CrypInCount to 0 (no more data to enter) */ 
01130         hcryp->CrypInCount = 0;  
01131 
01132         /*  Insert the last block (which size is inferior to 128 bits) padded with zeroes, 
01133             to have a complete block of 128 bits */              
01134         difflength = (uint32_t) (Size);
01135         difflengthmod4 = difflength%4;                 
01136         /*  Insert the last block (which size is inferior to 128 bits) padded with zeroes 
01137             to have a complete block of 128 bits */
01138         for(index=0; index < (difflength/4); index ++)
01139         {
01140           /* Write the Input block in the Data Input register */
01141           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01142           inputaddr+=4;
01143         }
01144         /* If required, manage input data size not multiple of 32 bits */
01145         if (difflengthmod4 != 0)
01146         {         
01147           hcryp->Instance->DINR = ((*(uint32_t*)(inputaddr)) & mask[difflengthmod4-1]);
01148         }         
01149         /* Wrap-up in padding with zero-words if applicable */
01150         for(index=0; index < (4 - ((difflength+3)/4)); index ++)        
01151         {
01152           hcryp->Instance->DINR = 0;
01153         }               
01154       }
01155       else
01156       {        
01157         /* Increment/decrement instance pointer/counter */
01158         hcryp->pCrypInBuffPtr += 16;
01159         hcryp->CrypInCount -= 16;
01160         
01161         /* Enter payload first block to initiate the process
01162            in the Data Input register */
01163         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01164         inputaddr+=4;
01165         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01166         inputaddr+=4;
01167         hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
01168         inputaddr+=4;
01169         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01170       }
01171     }
01172     /*==============================*/
01173     /* GCM/GMAC or CMAC final phase */
01174     /*==============================*/
01175     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_FINAL_PHASE)
01176     {
01177        hcryp->pCrypOutBuffPtr = pOutputData;
01178        
01179        MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCMCMAC_FINAL_PHASE);
01180        
01181       /* if the header and payload phases have been bypassed, AES must be enabled again */
01182       if (hcryp->Phase == HAL_CRYP_PHASE_INIT_OVER)
01183       {
01184         __HAL_CRYP_ENABLE();  
01185       }
01186       
01187       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC)
01188       {             
01189         headerlength = hcryp->Init.HeaderSize * 8; /* Header length in bits */
01190         inputlength = Size * 8;                   /* input length in bits */ 
01191         /* Write the number of bits in the header on 64 bits followed by the number
01192            of bits in the payload on 64 bits as well */
01193         if(hcryp->Init.DataType == CRYP_DATATYPE_1B)
01194         {
01195           hcryp->Instance->DINR = __RBIT((headerlength)>>32);
01196           hcryp->Instance->DINR = __RBIT(headerlength);
01197           hcryp->Instance->DINR = __RBIT((inputlength)>>32);
01198           hcryp->Instance->DINR = __RBIT(inputlength);
01199         }
01200         else if(hcryp->Init.DataType == CRYP_DATATYPE_8B)
01201         {
01202           hcryp->Instance->DINR = __REV((headerlength)>>32);
01203           hcryp->Instance->DINR = __REV(headerlength);
01204           hcryp->Instance->DINR = __REV((inputlength)>>32);
01205           hcryp->Instance->DINR = __REV(inputlength);
01206         }
01207         else if(hcryp->Init.DataType == CRYP_DATATYPE_16B)
01208         {
01209           hcryp->Instance->DINR = __ROR((headerlength)>>32, 16);
01210           hcryp->Instance->DINR = __ROR(headerlength, 16);
01211           hcryp->Instance->DINR = __ROR((inputlength)>>32, 16);
01212           hcryp->Instance->DINR = __ROR(inputlength, 16);             
01213         }
01214         else if(hcryp->Init.DataType == CRYP_DATATYPE_32B)
01215         {
01216           hcryp->Instance->DINR = (uint32_t)(headerlength>>32);
01217           hcryp->Instance->DINR = (uint32_t)(headerlength);
01218           hcryp->Instance->DINR = (uint32_t)(inputlength>>32);
01219           hcryp->Instance->DINR = (uint32_t)(inputlength);
01220         }
01221       }
01222       else if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
01223       {
01224         inputaddr  = (uint32_t)pInputData;
01225         /* Enter the last block made of a 128-bit value formatted
01226            from the original B0 packet. */
01227         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01228         inputaddr+=4;
01229         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01230         inputaddr+=4;
01231         hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
01232         inputaddr+=4;
01233         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01234         inputaddr+=4;
01235       }
01236     }
01237     /*=================================================*/
01238     /* case incorrect hcryp->Init.GCMCMACPhase setting */
01239     /*=================================================*/
01240     else
01241     {
01242       hcryp->State = HAL_CRYP_STATE_ERROR; 
01243       return HAL_ERROR;
01244     }
01245   
01246     return HAL_OK;
01247   }
01248   else
01249   {
01250     return HAL_BUSY;
01251   }
01252 }
01253 
01254 
01255 
01256 
01257 /**
01258   * @brief  Carry out in DMA mode the authentication tag generation as well as the ciphering or deciphering 
01259   *         operation according to hcryp->Init structure fields. 
01260   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01261   *         the configuration information for CRYP module
01262   * @param  pInputData: 
01263   *         - pointer to payload data in GCM payload phase,
01264   *         - pointer to B0 block in CMAC header phase,
01265   *         - pointer to C block in CMAC final phase.
01266   *         - Parameter is meaningless in case of GCM/GMAC init, header and final phases.        
01267   * @param  Size: 
01268   *         - length of the input payload data buffer in bytes,
01269   *         - length of B block (in bytes) in CMAC header phase,
01270   *         - length of C block (in bytes) in CMAC final phase.   
01271   *         - Parameter is meaningless in case of GCM/GMAC init and header phases.         
01272   * @param  pOutputData: 
01273   *         - pointer to plain or cipher text in GCM payload phase,   
01274   *         - pointer to authentication tag in GCM/GMAC and CMAC final phases.
01275   *         - Parameter is meaningless in case of GCM/GMAC init and header phases
01276   *           and in case of CMAC header phase.
01277   * @note   Supported operating modes are encryption and decryption, supported chaining modes are GCM, GMAC and CMAC.
01278   * @note   Phases are singly processed according to hcryp->Init.GCMCMACPhase so that steps in these specific chaining modes 
01279   *         can be skipped by the user if so required.
01280   * @note   pInputData and pOutputData buffers must be 32-bit aligned to ensure a correct DMA transfer to and from the IP.            
01281   * @retval HAL status
01282   */
01283 HAL_StatusTypeDef HAL_CRYPEx_AES_Auth_DMA(CRYP_HandleTypeDef *hcryp, uint8_t *pInputData, uint64_t Size, uint8_t *pOutputData)
01284 {
01285   uint32_t inputaddr      = 0;
01286   uint32_t outputaddr     = 0;
01287   uint32_t tagaddr        = 0;
01288   uint64_t headerlength   = 0;
01289   uint64_t inputlength    = 0;
01290   uint64_t payloadlength  = 0;
01291        
01292   
01293   if (hcryp->State == HAL_CRYP_STATE_READY)
01294   {
01295     /* input/output parameters check */
01296     if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_HEADER_PHASE)
01297     {
01298       if ((hcryp->Init.Header != NULL) && (hcryp->Init.HeaderSize == 0))
01299       {
01300         return  HAL_ERROR;
01301       }
01302       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
01303       {
01304         if ((pInputData == NULL) || (Size == 0))
01305         {
01306           return  HAL_ERROR;
01307         }
01308       }      
01309     }
01310     else if (hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE)
01311     {   
01312       if ((pInputData == NULL) || (pOutputData == NULL) || (Size == 0))
01313       {
01314         return  HAL_ERROR;
01315       }
01316     }
01317     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_FINAL_PHASE)
01318     {
01319       if (pOutputData == NULL)
01320       {
01321         return  HAL_ERROR;
01322       }
01323       if ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC) && (pInputData == NULL))
01324       {
01325         return  HAL_ERROR;
01326       }
01327     }
01328     
01329     
01330     /* Process Locked */
01331     __HAL_LOCK(hcryp);
01332   
01333     /* Change the CRYP state */
01334     hcryp->State = HAL_CRYP_STATE_BUSY;
01335   
01336     /*=====================*/
01337     /* GCM/GMAC init phase */
01338     /*=====================*/
01339     /* In case of init phase, the input data (Key and Initialization Vector) have 
01340        already been entered during the initialization process. No DMA transfer is
01341        required at that point therefore, the software just waits for the CCF flag 
01342        to be raised. */
01343     if (hcryp->Init.GCMCMACPhase == CRYP_GCM_INIT_PHASE)
01344     {
01345       /* just wait for hash computation */
01346       if(CRYP_WaitOnCCFlag(hcryp, CRYP_CCF_TIMEOUTVALUE) != HAL_OK)  
01347       { 
01348         hcryp->State = HAL_CRYP_STATE_READY;        
01349         __HAL_UNLOCK(hcryp);
01350         return HAL_TIMEOUT;
01351       }
01352       
01353       /* Clear CCF Flag */
01354       __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
01355       /* Mark that the initialization phase is over */
01356       hcryp->Phase = HAL_CRYP_PHASE_INIT_OVER;
01357       hcryp->State = HAL_CRYP_STATE_READY;
01358     }
01359     /*===============================*/
01360     /* GCM/GMAC or CMAC header phase */
01361     /*===============================*/     
01362     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_HEADER_PHASE)
01363     {
01364       /* Set header phase; for GCM or GMAC, set data-byte at this point */
01365       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC)
01366       {
01367         MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH|AES_CR_DATATYPE, CRYP_GCMCMAC_HEADER_PHASE|hcryp->Init.DataType);
01368       }
01369       else
01370       {
01371         MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCMCMAC_HEADER_PHASE);
01372       }
01373       
01374       /* enter first B0 block in polling mode (no DMA transfer for B0) */
01375       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
01376       {
01377          /* Enable the CRYP peripheral */
01378         __HAL_CRYP_ENABLE();
01379   
01380         inputaddr  = (uint32_t)pInputData;
01381         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01382         inputaddr+=4;
01383         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01384         inputaddr+=4;
01385         hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
01386         inputaddr+=4;
01387         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01388       
01389         if(CRYP_WaitOnCCFlag(hcryp, CRYP_CCF_TIMEOUTVALUE) != HAL_OK)  
01390         { 
01391           hcryp->State = HAL_CRYP_STATE_READY;        
01392           __HAL_UNLOCK(hcryp);
01393           return HAL_TIMEOUT;
01394         }
01395         /* Clear CCF Flag */
01396         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
01397       }
01398       
01399       /* No header case */
01400       if (hcryp->Init.Header == NULL)
01401       {
01402         hcryp->State = HAL_CRYP_STATE_READY;   
01403         /* Mark that the header phase is over */
01404         hcryp->Phase = HAL_CRYP_PHASE_HEADER_OVER; 
01405         /* Process Unlocked */
01406         __HAL_UNLOCK(hcryp);
01407   
01408         return HAL_OK;             
01409       }
01410       
01411       inputaddr = (uint32_t)hcryp->Init.Header;
01412       if ((hcryp->Init.HeaderSize % 16) != 0)
01413       {
01414 
01415         if (hcryp->Init.HeaderSize < 16)        
01416         {
01417           /*difflength = (uint32_t) (hcryp->Init.HeaderSize);*/ 
01418           
01419           CRYP_Padding(hcryp, (uint32_t) (hcryp->Init.HeaderSize), CRYP_POLLING_OFF);     
01420           
01421           hcryp->State = HAL_CRYP_STATE_READY;   
01422           /* Mark that the header phase is over */
01423           hcryp->Phase = HAL_CRYP_PHASE_HEADER_OVER;  
01424           
01425           /* CCF flag indicating header phase AES processing completion 
01426              will be checked at the start of the next phase:
01427             - payload phase (GCM)
01428             - final phase (GMAC or CMAC).  */                     
01429         }
01430         else
01431         {
01432           /* Local variable headerlength is a number of bytes multiple of 128 bits,
01433             remaining header data (if any) are handled after this loop */
01434           headerlength =  (((hcryp->Init.HeaderSize)/16)*16) ;         
01435           /* Store the ending transfer point */
01436           hcryp->pCrypInBuffPtr = hcryp->Init.Header + headerlength;
01437           hcryp->CrypInCount = (uint32_t)(hcryp->Init.HeaderSize - headerlength); /* remainder */
01438         
01439           /* Set the input and output addresses and start DMA transfer */ 
01440           /* (incomplete DMA transfer, will be wrapped up after completion of
01441              the first one (initiated here) with data padding */
01442           CRYP_GCMCMAC_SetDMAConfig(hcryp, inputaddr, headerlength, 0);
01443         }                          
01444       }
01445       else
01446       {
01447         hcryp->CrypInCount = 0;
01448         /* Set the input address and start DMA transfer */ 
01449         CRYP_GCMCMAC_SetDMAConfig(hcryp, inputaddr, hcryp->Init.HeaderSize, 0);            
01450       }
01451       
01452 
01453     }
01454     /*========================*/
01455     /* GCM/GMAC payload phase */
01456     /*========================*/
01457     else if (hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE)
01458     {
01459       /* Coming from header phase, wait for CCF flag to be raised 
01460           if header present and fed to the IP in the previous phase */
01461       if (hcryp->Init.Header != NULL)
01462       {
01463         if(CRYP_WaitOnCCFlag(hcryp, CRYP_CCF_TIMEOUTVALUE) != HAL_OK)  
01464         { 
01465           hcryp->State = HAL_CRYP_STATE_READY;        
01466           __HAL_UNLOCK(hcryp);
01467           return HAL_TIMEOUT;
01468         }
01469       }
01470       else
01471       {
01472         /* Enable the Peripheral since wasn't in header phase (no header case) */
01473         __HAL_CRYP_ENABLE();
01474       }
01475       /* Clear CCF Flag */
01476       __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);     
01477     
01478       MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCM_PAYLOAD_PHASE);
01479       
01480       /* Specific handling to manage payload size less than 128 bits
01481         when GCM encryption or decryption is selected */ 
01482       if ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC) && \
01483           ((Size % 16) != 0))
01484       {
01485         inputaddr  = (uint32_t)pInputData;
01486         outputaddr = (uint32_t)pOutputData;      
01487         if (Size < 16)
01488         {
01489           /* Block is now entered in polling mode, no actual gain in resorting to DMA */
01490           /*difflength = (uint32_t)Size;*/
01491           hcryp->pCrypInBuffPtr  =  (uint8_t *)inputaddr;
01492           hcryp->pCrypOutBuffPtr =  (uint8_t *)outputaddr;
01493             
01494           CRYP_Padding(hcryp, (uint32_t)Size, CRYP_POLLING_ON); 
01495           
01496           /* Change the CRYP state to ready */
01497           hcryp->State = HAL_CRYP_STATE_READY;
01498           /* Mark that the payload phase is over */
01499           hcryp->Phase = HAL_CRYP_PHASE_PAYLOAD_OVER; 
01500   
01501           /* Call output data transfer complete callback */
01502           HAL_CRYP_OutCpltCallback(hcryp);
01503         }
01504         else
01505         {
01506           payloadlength = (Size/16) * 16;          
01507           
01508           /* Store the ending transfer points */
01509           hcryp->pCrypInBuffPtr = pInputData + payloadlength;
01510           hcryp->pCrypOutBuffPtr = pOutputData + payloadlength;
01511           hcryp->CrypInCount = (uint32_t)(Size - payloadlength); /* remainder */
01512         
01513           /* Set the input and output addresses and start DMA transfer */ 
01514           /* (incomplete DMA transfer, will be wrapped up with data padding  
01515              after completion of the one initiated here) */
01516           CRYP_GCMCMAC_SetDMAConfig(hcryp, inputaddr, payloadlength, outputaddr);                      
01517         }
01518       }
01519       else
01520       { 
01521         hcryp->CrypInCount = 0;                          
01522         inputaddr  = (uint32_t)pInputData;
01523         outputaddr = (uint32_t)pOutputData;
01524         
01525         /* Set the input and output addresses and start DMA transfer */ 
01526         CRYP_GCMCMAC_SetDMAConfig(hcryp, inputaddr, Size, outputaddr);         
01527       }  
01528     }
01529     /*==============================*/
01530     /* GCM/GMAC or CMAC final phase */
01531     /*==============================*/
01532     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_FINAL_PHASE)
01533     {
01534       /* If coming from header phase (GMAC or CMAC case), 
01535          wait for CCF flag to be raised */
01536       if (READ_BIT(hcryp->Instance->CR, AES_CR_GCMPH) == CRYP_GCMCMAC_HEADER_PHASE)
01537       {   
01538         if(CRYP_WaitOnCCFlag(hcryp, CRYP_CCF_TIMEOUTVALUE) != HAL_OK)  
01539         { 
01540           hcryp->State = HAL_CRYP_STATE_READY;        
01541           __HAL_UNLOCK(hcryp);
01542           return HAL_TIMEOUT;
01543         }
01544         /* Clear CCF Flag */
01545         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
01546       }        
01547       
01548       tagaddr = (uint32_t)pOutputData;
01549       
01550       MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCMCMAC_FINAL_PHASE);
01551       
01552       /* if the header and payload phases have been bypassed, AES must be enabled again */
01553       if (hcryp->Phase == HAL_CRYP_PHASE_INIT_OVER)
01554       {
01555         __HAL_CRYP_ENABLE();  
01556       }
01557       
01558       if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC)
01559       {
01560         headerlength = hcryp->Init.HeaderSize * 8; /* Header length in bits */
01561         inputlength = Size * 8;  /* input length in bits */ 
01562         /* Write the number of bits in the header on 64 bits followed by the number
01563            of bits in the payload on 64 bits as well */
01564         if(hcryp->Init.DataType == CRYP_DATATYPE_1B)
01565         {
01566           hcryp->Instance->DINR = __RBIT((headerlength)>>32);
01567           hcryp->Instance->DINR = __RBIT(headerlength);
01568           hcryp->Instance->DINR = __RBIT((inputlength)>>32);
01569           hcryp->Instance->DINR = __RBIT(inputlength);
01570         }
01571         else if(hcryp->Init.DataType == CRYP_DATATYPE_8B)
01572         {
01573           hcryp->Instance->DINR = __REV((headerlength)>>32);
01574           hcryp->Instance->DINR = __REV(headerlength);
01575           hcryp->Instance->DINR = __REV((inputlength)>>32);
01576           hcryp->Instance->DINR = __REV(inputlength);
01577         }
01578         else if(hcryp->Init.DataType == CRYP_DATATYPE_16B)
01579         {
01580           hcryp->Instance->DINR = __ROR((headerlength)>>32, 16);
01581           hcryp->Instance->DINR = __ROR(headerlength, 16);
01582           hcryp->Instance->DINR = __ROR((inputlength)>>32, 16);
01583           hcryp->Instance->DINR = __ROR(inputlength, 16);            
01584         }
01585         else if(hcryp->Init.DataType == CRYP_DATATYPE_32B)
01586         {
01587           hcryp->Instance->DINR = (uint32_t)(headerlength>>32);
01588           hcryp->Instance->DINR = (uint32_t)(headerlength);
01589           hcryp->Instance->DINR = (uint32_t)(inputlength>>32);
01590           hcryp->Instance->DINR = (uint32_t)(inputlength);
01591         }
01592       }
01593       else if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
01594       {
01595         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
01596         
01597         inputaddr  = (uint32_t)pInputData;
01598         /* Enter the last block made of a 128-bit value formatted
01599            from the original B0 packet. */
01600         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01601         inputaddr+=4;
01602         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01603         inputaddr+=4;
01604         hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
01605         inputaddr+=4;
01606         hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
01607         inputaddr+=4;
01608       }
01609       
01610       /* No DMA transfer is required at that point therefore, the software 
01611          just waits for the CCF flag to be raised. */
01612       if(CRYP_WaitOnCCFlag(hcryp, CRYP_CCF_TIMEOUTVALUE) != HAL_OK)  
01613       { 
01614           hcryp->State = HAL_CRYP_STATE_READY;        
01615           __HAL_UNLOCK(hcryp);
01616           return HAL_TIMEOUT;
01617       }
01618       /* Clear CCF Flag */
01619       __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
01620       /* Read the Auth TAG in the IN FIFO */
01621       *(uint32_t*)(tagaddr) = hcryp->Instance->DOUTR;
01622       tagaddr+=4;
01623       *(uint32_t*)(tagaddr) = hcryp->Instance->DOUTR;
01624       tagaddr+=4;
01625       *(uint32_t*)(tagaddr) = hcryp->Instance->DOUTR;
01626       tagaddr+=4;
01627       *(uint32_t*)(tagaddr) = hcryp->Instance->DOUTR;
01628   
01629       /* Mark that the final phase is over */
01630       hcryp->Phase = HAL_CRYP_PHASE_FINAL_OVER;
01631       hcryp->State = HAL_CRYP_STATE_READY;
01632       /* Disable the Peripheral */
01633       __HAL_CRYP_DISABLE();
01634     }
01635     /*=================================================*/
01636     /* case incorrect hcryp->Init.GCMCMACPhase setting */
01637     /*=================================================*/
01638     else
01639     {
01640       hcryp->State = HAL_CRYP_STATE_ERROR;
01641       __HAL_UNLOCK(hcryp); 
01642       return HAL_ERROR;
01643     }    
01644   
01645     /* Process Unlocked */
01646     __HAL_UNLOCK(hcryp);
01647   
01648     return HAL_OK;
01649   }
01650   else
01651   {
01652     return HAL_BUSY;
01653   }
01654 }
01655 
01656 /**
01657   * @}
01658   */
01659 
01660 /** @defgroup CRYPEx_Exported_Functions_Group3 AES suspension/resumption functions 
01661  *  @brief   Extended processing functions. 
01662  *
01663 @verbatim   
01664   ==============================================================================
01665                     ##### AES extended suspension and resumption functions #####
01666   ==============================================================================  
01667     [..]  This section provides functions allowing to:
01668       (+) save in memory the Initialization Vector, the Key registers, the Control register or
01669           the Suspend registers when a process is suspended by a higher priority message
01670       (+) write back in CRYP hardware block the saved values listed above when the suspended
01671           lower priority message processing is resumed.     
01672 
01673 @endverbatim
01674   * @{
01675   */
01676 
01677 
01678 /**
01679   * @brief  In case of message processing suspension, read the Initialization Vector. 
01680   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01681   *         the configuration information for CRYP module.    
01682   * @param  Output: Pointer to the buffer containing the saved Initialization Vector.
01683   * @note   This value has to be stored for reuse by writing the AES_IVRx registers
01684   *         as soon as the interrupted processing has to be resumed.
01685   *         Applicable to all chaining modes.    
01686   * @note   AES must be disabled when reading or resetting the IV values.   
01687   * @retval None
01688   */
01689 void HAL_CRYPEx_Read_IVRegisters(CRYP_HandleTypeDef *hcryp, uint8_t* Output)
01690 {
01691   uint32_t outputaddr = (uint32_t)Output;
01692     
01693   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->IVR3);
01694   outputaddr+=4;
01695   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->IVR2);
01696   outputaddr+=4;
01697   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->IVR1);
01698   outputaddr+=4;
01699   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->IVR0);
01700 }
01701 
01702 /**
01703   * @brief  In case of message processing resumption, rewrite the Initialization
01704   *         Vector in the AES_IVRx registers.
01705   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01706   *         the configuration information for CRYP module.      
01707   * @param  Input: Pointer to the buffer containing the saved Initialization Vector to
01708   *         write back in the CRYP hardware block. 
01709   * @note   Applicable to all chaining modes.       
01710   * @note   AES must be disabled when reading or resetting the IV values.     
01711   * @retval None
01712   */
01713 void HAL_CRYPEx_Write_IVRegisters(CRYP_HandleTypeDef *hcryp, uint8_t* Input)
01714 {
01715   uint32_t ivaddr = (uint32_t)Input;
01716   
01717   hcryp->Instance->IVR3 = __REV(*(uint32_t*)(ivaddr));
01718   ivaddr+=4;
01719   hcryp->Instance->IVR2 = __REV(*(uint32_t*)(ivaddr));
01720   ivaddr+=4;
01721   hcryp->Instance->IVR1 = __REV(*(uint32_t*)(ivaddr));
01722   ivaddr+=4;
01723   hcryp->Instance->IVR0 = __REV(*(uint32_t*)(ivaddr));
01724 }
01725 
01726 
01727 /**
01728   * @brief  In case of message GCM/GMAC or CMAC processing suspension, read the Suspend Registers.
01729   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01730   *         the configuration information for CRYP module.  
01731   * @param  Output: Pointer to the buffer containing the saved Suspend Registers.
01732   * @note   These values have to be stored for reuse by writing back the AES_SUSPxR registers
01733   *         as soon as the interrupted processing has to be resumed.       
01734   * @retval None
01735   */
01736 void HAL_CRYPEx_Read_SuspendRegisters(CRYP_HandleTypeDef *hcryp, uint8_t* Output)
01737 {
01738   uint32_t outputaddr = (uint32_t)Output;
01739   
01740   /* In case of GCM payload phase encryption, check that suspension can be carried out */
01741   if (READ_BIT(hcryp->Instance->CR, (AES_CR_GCMPH|AES_CR_MODE)) == (CRYP_GCM_PAYLOAD_PHASE|CRYP_ALGOMODE_ENCRYPT))
01742   {
01743     /* Ensure that Busy flag is reset */
01744     if(CRYP_WaitOnBusyFlagReset(hcryp, CRYP_BUSY_TIMEOUTVALUE) != HAL_OK)  
01745     { 
01746       hcryp->ErrorCode |= HAL_CRYP_BUSY_ERROR;
01747       hcryp->State = HAL_CRYP_STATE_ERROR;
01748               
01749       /* Process Unlocked */
01750       __HAL_UNLOCK(hcryp);  
01751     
01752       HAL_CRYP_ErrorCallback(hcryp);
01753       return ;
01754     }
01755   } 
01756     
01757   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->SUSP7R);
01758   outputaddr+=4;
01759   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->SUSP6R);
01760   outputaddr+=4;
01761   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->SUSP5R);
01762   outputaddr+=4;
01763   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->SUSP4R);
01764   outputaddr+=4;
01765   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->SUSP3R);
01766   outputaddr+=4;
01767   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->SUSP2R);
01768   outputaddr+=4;
01769   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->SUSP1R); 
01770   outputaddr+=4;
01771   *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->SUSP0R);   
01772 }
01773 
01774 /**
01775   * @brief  In case of message GCM/GMAC or CMAC processing resumption, rewrite the Suspend
01776   *         Registers in the AES_SUSPxR registers.
01777   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01778   *         the configuration information for CRYP module.    
01779   * @param  Input: Pointer to the buffer containing the saved suspend registers to
01780   *         write back in the CRYP hardware block. 
01781   * @retval None
01782   */
01783 void HAL_CRYPEx_Write_SuspendRegisters(CRYP_HandleTypeDef *hcryp, uint8_t* Input)
01784 {
01785   uint32_t ivaddr = (uint32_t)Input;
01786   
01787   hcryp->Instance->SUSP7R = __REV(*(uint32_t*)(ivaddr));
01788   ivaddr+=4;
01789   hcryp->Instance->SUSP6R = __REV(*(uint32_t*)(ivaddr));
01790   ivaddr+=4;
01791   hcryp->Instance->SUSP5R = __REV(*(uint32_t*)(ivaddr));
01792   ivaddr+=4;
01793   hcryp->Instance->SUSP4R = __REV(*(uint32_t*)(ivaddr));
01794   ivaddr+=4;
01795   hcryp->Instance->SUSP3R = __REV(*(uint32_t*)(ivaddr));
01796   ivaddr+=4;
01797   hcryp->Instance->SUSP2R = __REV(*(uint32_t*)(ivaddr));
01798   ivaddr+=4;
01799   hcryp->Instance->SUSP1R = __REV(*(uint32_t*)(ivaddr));
01800   ivaddr+=4;
01801   hcryp->Instance->SUSP0R = __REV(*(uint32_t*)(ivaddr));  
01802 }
01803 
01804 
01805 /**
01806   * @brief  In case of message GCM/GMAC or CMAC processing suspension, read the Key Registers.
01807   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01808   *         the configuration information for CRYP module.   
01809   * @param  Output: Pointer to the buffer containing the saved Key Registers. 
01810   * @param  KeySize: Indicates the key size (128 or 256 bits).
01811   * @note   These values have to be stored for reuse by writing back the AES_KEYRx registers
01812   *         as soon as the interrupted processing has to be resumed.           
01813   * @retval None
01814   */
01815 void HAL_CRYPEx_Read_KeyRegisters(CRYP_HandleTypeDef *hcryp, uint8_t* Output, uint32_t KeySize)
01816 {
01817   uint32_t keyaddr = (uint32_t)Output;
01818   
01819   if (KeySize == CRYP_KEYSIZE_256B)
01820   {
01821     *(uint32_t*)(keyaddr) = __REV(hcryp->Instance->KEYR7);
01822     keyaddr+=4;
01823     *(uint32_t*)(keyaddr) = __REV(hcryp->Instance->KEYR6);
01824     keyaddr+=4;
01825     *(uint32_t*)(keyaddr) = __REV(hcryp->Instance->KEYR5);
01826     keyaddr+=4;
01827     *(uint32_t*)(keyaddr) = __REV(hcryp->Instance->KEYR4);
01828     keyaddr+=4;                 
01829   }  
01830   
01831   *(uint32_t*)(keyaddr) = __REV(hcryp->Instance->KEYR3);
01832   keyaddr+=4;
01833   *(uint32_t*)(keyaddr) = __REV(hcryp->Instance->KEYR2);
01834   keyaddr+=4;
01835   *(uint32_t*)(keyaddr) = __REV(hcryp->Instance->KEYR1);
01836   keyaddr+=4;
01837   *(uint32_t*)(keyaddr) = __REV(hcryp->Instance->KEYR0); 
01838 }
01839 
01840 /**
01841   * @brief  In case of message GCM/GMAC or CMAC processing resumption, rewrite the Key
01842   *         Registers in the AES_KEYRx registers.
01843   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01844   *         the configuration information for CRYP module.   
01845   * @param  Input: Pointer to the buffer containing the saved key registers to
01846   *         write back in the CRYP hardware block. 
01847   * @param  KeySize: Indicates the key size (128 or 256 bits)     
01848   * @retval None
01849   */
01850 void HAL_CRYPEx_Write_KeyRegisters(CRYP_HandleTypeDef *hcryp, uint8_t* Input, uint32_t KeySize)
01851 {  
01852   uint32_t keyaddr = (uint32_t)Input;
01853   
01854   if (KeySize == CRYP_KEYSIZE_256B)
01855   {
01856     hcryp->Instance->KEYR7 = __REV(*(uint32_t*)(keyaddr));
01857     keyaddr+=4;
01858     hcryp->Instance->KEYR6 = __REV(*(uint32_t*)(keyaddr));
01859     keyaddr+=4;
01860     hcryp->Instance->KEYR5 = __REV(*(uint32_t*)(keyaddr));
01861     keyaddr+=4;
01862     hcryp->Instance->KEYR4 = __REV(*(uint32_t*)(keyaddr));
01863     keyaddr+=4;      
01864   }  
01865   
01866     hcryp->Instance->KEYR3 = __REV(*(uint32_t*)(keyaddr));
01867     keyaddr+=4;
01868     hcryp->Instance->KEYR2 = __REV(*(uint32_t*)(keyaddr));
01869     keyaddr+=4;
01870     hcryp->Instance->KEYR1 = __REV(*(uint32_t*)(keyaddr));
01871     keyaddr+=4;
01872     hcryp->Instance->KEYR0 = __REV(*(uint32_t*)(keyaddr));    
01873 }
01874 
01875 
01876 /**
01877   * @brief  In case of message GCM/GMAC or CMAC processing suspension, read the Control Register.
01878   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01879   *         the configuration information for CRYP module.   
01880   * @param  Output: Pointer to the buffer containing the saved Control Register.
01881   * @note   This values has to be stored for reuse by writing back the AES_CR register
01882   *         as soon as the interrupted processing has to be resumed.          
01883   * @retval None
01884   */
01885 void HAL_CRYPEx_Read_ControlRegister(CRYP_HandleTypeDef *hcryp, uint8_t* Output)
01886 {
01887   *(uint32_t*)(Output) = hcryp->Instance->CR;    
01888 }
01889 
01890 /**
01891   * @brief  In case of message GCM/GMAC or CMAC processing resumption, rewrite the Control
01892   *         Registers in the AES_CR register.
01893   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01894   *         the configuration information for CRYP module.   
01895   * @param  Input: Pointer to the buffer containing the saved Control Register to
01896   *         write back in the CRYP hardware block.   
01897   * @retval None
01898   */
01899 void HAL_CRYPEx_Write_ControlRegister(CRYP_HandleTypeDef *hcryp, uint8_t* Input)
01900 {  
01901   hcryp->Instance->CR = *(uint32_t*)(Input);
01902   /* At the same time, set handle state back to READY to be able to resume the AES calculations 
01903      without the processing APIs returning HAL_BUSY when called. */
01904   hcryp->State        = HAL_CRYP_STATE_READY;
01905 }
01906 
01907 /**
01908   * @brief  Request CRYP processing suspension when in polling or interruption mode.
01909   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
01910   *         the configuration information for CRYP module. 
01911   * @note   Set the handle field SuspendRequest to the appropriate value so that 
01912   *         the on-going CRYP processing is suspended as soon as the required 
01913   *         conditions are met.
01914   * @note   It is advised not to suspend the CRYP processing when the DMA controller 
01915   *         is managing the data transfer     
01916   * @retval None
01917   */
01918 void HAL_CRYPEx_ProcessSuspend(CRYP_HandleTypeDef *hcryp)  
01919 {
01920   /* Set Handle Suspend Request field */
01921   hcryp->SuspendRequest = HAL_CRYP_SUSPEND;
01922 }
01923 
01924 /**
01925   * @}
01926   */
01927 
01928 /**
01929   * @}
01930   */
01931 
01932 /** @addtogroup CRYPEx_Private_Functions
01933   * @{
01934   */
01935 
01936 /**
01937   * @brief  DMA CRYP Input Data process complete callback
01938   *         for GCM, GMAC or CMAC chainging modes.
01939   * @note   Specific setting of hcryp fields are required only
01940   *         in the case of header phase where no output data DMA
01941   *         transfer is on-going (only input data transfer is enabled
01942   *         in such a case).      
01943   * @param  hdma: DMA handle.
01944   * @retval None
01945   */
01946 static void CRYP_GCMCMAC_DMAInCplt(DMA_HandleTypeDef *hdma)  
01947 {
01948   uint32_t difflength     = 0;
01949   
01950   CRYP_HandleTypeDef* hcryp = (CRYP_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
01951   
01952   /* Disable the DMA transfer for input request  */
01953   CLEAR_BIT(hcryp->Instance->CR, AES_CR_DMAINEN);
01954 
01955   if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_HEADER_PHASE)
01956   { 
01957   
01958     if (hcryp->CrypInCount != 0)
01959     {
01960       /* Last block is now entered in polling mode, no actual gain in resorting to DMA */
01961       difflength = hcryp->CrypInCount;
01962       hcryp->CrypInCount = 0;
01963       
01964       CRYP_Padding(hcryp, difflength, CRYP_POLLING_OFF);      
01965     }
01966     hcryp->State = HAL_CRYP_STATE_READY;   
01967     /* Mark that the header phase is over */
01968     hcryp->Phase = HAL_CRYP_PHASE_HEADER_OVER;
01969   }
01970   /* CCF flag indicating header phase AES processing completion 
01971      will be checked at the start of the next phase:
01972      - payload phase (GCM)
01973      - final phase (GMAC or CMAC).
01974     This allows to avoid the Wait on Flag within the IRQ handling.  */
01975   
01976   /* Call input data transfer complete callback */
01977   HAL_CRYP_InCpltCallback(hcryp);
01978 }
01979 
01980 /**
01981   * @brief  DMA CRYP Output Data process complete callback
01982   *         for GCM, GMAC or CMAC chainging modes.
01983   * @note   This callback is called only in the payload phase.  
01984   * @param  hdma: DMA handle.
01985   * @retval None
01986   */
01987 static void CRYP_GCMCMAC_DMAOutCplt(DMA_HandleTypeDef *hdma)
01988 {
01989   uint32_t difflength     = 0;
01990   CRYP_HandleTypeDef* hcryp = (CRYP_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
01991   
01992   /* Disable the DMA transfer for output request */
01993   CLEAR_BIT(hcryp->Instance->CR, AES_CR_DMAOUTEN);
01994 
01995   /* Clear CCF Flag */
01996   __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
01997   
01998   /* Initiate additional transfer to wrap-up data feeding to the IP */
01999   if (hcryp->CrypInCount != 0)
02000   {
02001     /* Last block is now entered in polling mode, no actual gain in resorting to DMA */
02002     difflength = hcryp->CrypInCount;
02003     hcryp->CrypInCount = 0;
02004     
02005     CRYP_Padding(hcryp, difflength, CRYP_POLLING_ON); 
02006   }  
02007   
02008   /* Change the CRYP state to ready */
02009   hcryp->State = HAL_CRYP_STATE_READY;
02010   /* Mark that the payload phase is over */
02011   hcryp->Phase = HAL_CRYP_PHASE_PAYLOAD_OVER; 
02012   
02013   /* Call output data transfer complete callback */
02014   HAL_CRYP_OutCpltCallback(hcryp);
02015 }
02016 
02017 /**
02018   * @brief  DMA CRYP communication error callback
02019   *         for GCM, GMAC or CMAC chainging modes.
02020   * @param  hdma: DMA handle
02021   * @retval None
02022   */
02023 static void CRYP_GCMCMAC_DMAError(DMA_HandleTypeDef *hdma)
02024 {
02025   CRYP_HandleTypeDef* hcryp = (CRYP_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
02026   
02027   hcryp->State= HAL_CRYP_STATE_ERROR;
02028   hcryp->ErrorCode |= HAL_CRYP_DMA_ERROR;
02029   HAL_CRYP_ErrorCallback(hcryp);
02030   /* Clear Error Flag */
02031   __HAL_CRYP_CLEAR_FLAG(CRYP_ERR_CLEAR);
02032 }
02033 
02034 
02035 
02036 /** 
02037   * @brief  Handle CRYP block input/output data handling under interruption
02038   *         for GCM, GMAC or CMAC chainging modes.  
02039   * @note   The function is called under interruption only, once
02040   *         interruptions have been enabled by HAL_CRYPEx_AES_Auth_IT().  
02041   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
02042   *         the configuration information for CRYP module
02043   * @retval HAL status
02044   */
02045 HAL_StatusTypeDef CRYP_AES_Auth_IT(CRYP_HandleTypeDef *hcryp)
02046 {
02047   uint32_t inputaddr   = 0x0;
02048   uint32_t outputaddr  = 0x0; 
02049   uint32_t index       = 0x0;
02050   uint32_t addhoc_process = 0; 
02051   uint32_t difflength     = 0;
02052   uint32_t difflengthmod4 = 0;
02053   uint32_t mask[3]        = {0x0FF, 0x0FFFF, 0x0FFFFFF};
02054   uint32_t intermediate_data[4] = {0};        
02055   
02056   if(hcryp->State == HAL_CRYP_STATE_BUSY)
02057   {
02058     /*=====================*/
02059     /* GCM/GMAC init phase */
02060     /*=====================*/  
02061     if (hcryp->Init.GCMCMACPhase == CRYP_GCM_INIT_PHASE)
02062     {
02063       /* Clear Computation Complete Flag */
02064       __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02065       /* Disable Computation Complete Flag and Errors Interrupts */
02066       __HAL_CRYP_DISABLE_IT(CRYP_IT_CCFIE|CRYP_IT_ERRIE);
02067       /* Change the CRYP state */
02068       hcryp->State = HAL_CRYP_STATE_READY;
02069     
02070       /* Mark that the initialization phase is over */
02071       hcryp->Phase = HAL_CRYP_PHASE_INIT_OVER;
02072           
02073       /* Process Unlocked */
02074       __HAL_UNLOCK(hcryp);
02075       /* Call computation complete callback */
02076       HAL_CRYPEx_ComputationCpltCallback(hcryp);
02077       return HAL_OK;
02078     }
02079     /*===============================*/
02080     /* GCM/GMAC or CMAC header phase */
02081     /*===============================*/    
02082     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_HEADER_PHASE)
02083     {
02084       /* Check if all input header data have been entered */
02085       if (hcryp->CrypInCount == 0)
02086       {
02087         /* Clear Computation Complete Flag */
02088         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02089         /* Disable Computation Complete Flag and Errors Interrupts */
02090         __HAL_CRYP_DISABLE_IT(CRYP_IT_CCFIE|CRYP_IT_ERRIE);
02091         /* Change the CRYP state */
02092         hcryp->State = HAL_CRYP_STATE_READY;
02093        /* Mark that the header phase is over */
02094         hcryp->Phase = HAL_CRYP_PHASE_HEADER_OVER;
02095       
02096        /* Process Unlocked */
02097         __HAL_UNLOCK(hcryp);
02098       
02099         /* Call computation complete callback */
02100         HAL_CRYPEx_ComputationCpltCallback(hcryp);
02101       
02102         return HAL_OK;
02103       }
02104       /* If suspension flag has been raised, suspend processing */
02105       else if (hcryp->SuspendRequest == HAL_CRYP_SUSPEND)
02106       {
02107         /* Clear CCF Flag */
02108         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02109        
02110         /* reset SuspendRequest */
02111         hcryp->SuspendRequest = HAL_CRYP_SUSPEND_NONE;
02112         /* Disable Computation Complete Flag and Errors Interrupts */
02113         __HAL_CRYP_DISABLE_IT(CRYP_IT_CCFIE|CRYP_IT_ERRIE);
02114         /* Change the CRYP state */
02115         hcryp->State = HAL_CRYP_STATE_SUSPENDED;
02116         /* Mark that the header phase is over */
02117         hcryp->Phase = HAL_CRYP_PHASE_HEADER_SUSPENDED;
02118       
02119        /* Process Unlocked */
02120         __HAL_UNLOCK(hcryp);
02121       
02122         return HAL_OK;
02123       }      
02124       else /* Carry on feeding input data to the CRYP hardware block */
02125       {
02126         /* Clear Computation Complete Flag */
02127         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02128         /* Get the last Input data address */
02129         inputaddr = (uint32_t)hcryp->pCrypInBuffPtr;
02130       
02131         /* Increment/decrement instance pointer/counter */
02132         if (hcryp->CrypInCount < 16)
02133         {
02134           difflength = hcryp->CrypInCount;        
02135           hcryp->CrypInCount = 0;
02136           addhoc_process = 1;  
02137           difflengthmod4 = difflength%4;              
02138         }
02139         else
02140         {
02141           hcryp->pCrypInBuffPtr += 16;
02142           hcryp->CrypInCount -= 16;
02143         }        
02144         
02145         if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)
02146         { 
02147           if (hcryp->CrypInCount == hcryp->Init.HeaderSize)
02148           {
02149             /* All B blocks will have been entered after the next
02150               four DINR writing, so point at header buffer for
02151               the next iteration */
02152             hcryp->pCrypInBuffPtr = hcryp->Init.Header;
02153           }
02154         }           
02155       
02156         /* Write the Input block in the Data Input register */
02157         if (addhoc_process == 0)
02158         {         
02159           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02160           inputaddr+=4;
02161           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02162           inputaddr+=4;
02163           hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
02164           inputaddr+=4;
02165           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02166         }
02167         else
02168         {
02169           /* Header remainder has size less than 128 bits */ 
02170           /* Enter complete words when possible */
02171           for(index=0; index < (difflength/4); index ++)
02172           {
02173             /* Write the Input block in the Data Input register */
02174             hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02175             inputaddr+=4;
02176           }
02177           /* Enter incomplete word padded with zeroes if applicable 
02178             (case of header length not a multiple of 32-bits) */
02179           if (difflengthmod4 != 0)
02180           {         
02181             hcryp->Instance->DINR = ((*(uint32_t*)(inputaddr)) & mask[difflengthmod4-1]);
02182           }         
02183           /* Pad with zero-words to reach 128-bit long block and wrap-up header feeding to the IP */
02184           for(index=0; index < (4 - ((difflength+3)/4)); index ++)         
02185           {
02186             hcryp->Instance->DINR = 0;
02187           }          
02188         }
02189       
02190         return HAL_OK;      
02191       }
02192     }
02193     /*========================*/
02194     /* GCM/GMAC payload phase */
02195     /*========================*/    
02196     else if (hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE)
02197     {
02198       /* Get the last output data address */
02199       outputaddr = (uint32_t)hcryp->pCrypOutBuffPtr;
02200       
02201      /* Specific handling to manage payload size less than 128 bits
02202         when GCM encryption or decryption is selected.
02203         Check here if the last block output data are read */
02204       if ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC) && \
02205           (hcryp->CrypOutCount < 16)                                && \
02206           (hcryp->CrypOutCount > 0))
02207       {
02208         addhoc_process = 1;
02209         difflength = hcryp->CrypOutCount;
02210         difflengthmod4 = difflength%4; 
02211         hcryp->CrypOutCount = 0;   /* mark that no more output data will be needed */       
02212         /* Retrieve intermediate data */
02213         for(index=0; index < 4; index ++)
02214         {
02215           intermediate_data[index] = hcryp->Instance->DOUTR;                 
02216         } 
02217         /* Retrieve last words of cyphered data */
02218         /* First, retrieve complete output words */
02219         for(index=0; index < (difflength/4); index ++)
02220         {
02221           *(uint32_t*)(outputaddr) = intermediate_data[index];
02222           outputaddr+=4; 
02223         } 
02224         /* Next, retrieve partial output word if applicable;
02225            at the same time, start masking intermediate data 
02226            with a mask of zeros of same size than the padding
02227            applied to the last block of payload */ 
02228         if (difflengthmod4 != 0)
02229         {
02230           intermediate_data[difflength/4] &= mask[difflengthmod4-1];
02231           *(uint32_t*)(outputaddr) = intermediate_data[difflength/4];            
02232         }           
02233    
02234         if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_ENCRYPT)
02235         { 
02236           /* Change again CHMOD configuration to GCM mode */
02237           __HAL_CRYP_SET_CHAININGMODE(CRYP_CHAINMODE_AES_GCM_GMAC); 
02238         
02239           /* Select FINAL phase */
02240           MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCMCMAC_FINAL_PHASE);  
02241         
02242           /* Before inserting the intermediate data, carry on masking operation
02243              with a mask of zeros of same size than the padding applied to the last block of payload */
02244           for(index=0; index < (4 - ((difflength+3)/4)); index ++)        
02245           {
02246             intermediate_data[(difflength+3)/4+index] = 0;
02247           }  
02248         
02249           /* Insert intermediate data to trigger an additional DOUTR reading round */
02250           /* Clear Computation Complete Flag before entering new block */
02251           __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02252           for(index=0; index < 4; index ++)
02253           {
02254             hcryp->Instance->DINR = intermediate_data[index];          
02255           }
02256         }
02257         else
02258         {
02259           /* Deciphering case: payload phase is now over */
02260           /* Clear Computation Complete Flag */
02261           __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);        
02262           /* Disable Computation Complete Flag and Errors Interrupts */
02263           __HAL_CRYP_DISABLE_IT(CRYP_IT_CCFIE|CRYP_IT_ERRIE);
02264           /* Change the CRYP state */
02265           hcryp->State = HAL_CRYP_STATE_READY;
02266           /* Mark that the payload phase is over */
02267           hcryp->Phase = HAL_CRYP_PHASE_PAYLOAD_OVER;
02268       
02269           /* Process Unlocked */
02270           __HAL_UNLOCK(hcryp);
02271       
02272           /* Call computation complete callback */
02273           HAL_CRYPEx_ComputationCpltCallback(hcryp);
02274         }
02275         return HAL_OK;
02276       }
02277       else  
02278       { 
02279         if (hcryp->CrypOutCount != 0)
02280         { 
02281           /* Usual case (different than GCM last block < 128 bits ciphering) */ 
02282           /* Retrieve the last block available from the CRYP hardware block:
02283             read the output block from the Data Output Register */
02284           *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02285           outputaddr+=4;
02286           *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02287           outputaddr+=4;
02288           *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02289           outputaddr+=4;
02290           *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02291           
02292           /* Increment/decrement instance pointer/counter */
02293           hcryp->pCrypOutBuffPtr += 16;
02294           hcryp->CrypOutCount -= 16;                    
02295         }
02296         else
02297         {          
02298           /* Software work-around: additional DOUTR reading round to discard the data */
02299           for(index=0; index < 4; index ++)
02300           {
02301             intermediate_data[index] = hcryp->Instance->DOUTR;                 
02302           } 
02303           
02304         }
02305       }            
02306       
02307       /* Check if all output text has been retrieved */
02308       if (hcryp->CrypOutCount == 0)
02309       {
02310         /* Make sure that software-work around is not running before disabling
02311           the interruptions (indeed, if software work-around is running, the 
02312           interruptions must not be disabled to allow the additional DOUTR 
02313           reading round */
02314         if (addhoc_process == 0)
02315         {
02316           /* Clear Computation Complete Flag */
02317           __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);        
02318           /* Disable Computation Complete Flag and Errors Interrupts */
02319           __HAL_CRYP_DISABLE_IT(CRYP_IT_CCFIE|CRYP_IT_ERRIE);
02320           /* Change the CRYP state */
02321           hcryp->State = HAL_CRYP_STATE_READY;
02322          /* Mark that the payload phase is over */
02323           hcryp->Phase = HAL_CRYP_PHASE_PAYLOAD_OVER;
02324       
02325          /* Process Unlocked */
02326           __HAL_UNLOCK(hcryp);
02327       
02328           /* Call computation complete callback */
02329           HAL_CRYPEx_ComputationCpltCallback(hcryp);
02330         }
02331       
02332         return HAL_OK;
02333       }
02334       /* If suspension flag has been raised, suspend processing */
02335       else if (hcryp->SuspendRequest == HAL_CRYP_SUSPEND)
02336       {     
02337         /* Clear CCF Flag */
02338         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02339        
02340         /* reset SuspendRequest */
02341         hcryp->SuspendRequest = HAL_CRYP_SUSPEND_NONE;
02342         /* Disable Computation Complete Flag and Errors Interrupts */
02343         __HAL_CRYP_DISABLE_IT(CRYP_IT_CCFIE|CRYP_IT_ERRIE);
02344         /* Change the CRYP state */
02345         hcryp->State = HAL_CRYP_STATE_SUSPENDED;
02346         /* Mark that the header phase is over */
02347         hcryp->Phase = HAL_CRYP_PHASE_HEADER_SUSPENDED;
02348       
02349        /* Process Unlocked */
02350         __HAL_UNLOCK(hcryp);
02351       
02352         return HAL_OK;
02353       }            
02354       else /* Output data are still expected, carry on feeding the CRYP
02355                hardware block with input data */
02356       {
02357         /* Clear Computation Complete Flag */
02358         __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);          
02359         /* Get the last Input data address */
02360         inputaddr = (uint32_t)hcryp->pCrypInBuffPtr;
02361       
02362         /* Usual input data feeding case */
02363         if (hcryp->CrypInCount < 16)
02364         {
02365           difflength = (uint32_t) (hcryp->CrypInCount);
02366           difflengthmod4 = difflength%4;
02367           hcryp->CrypInCount = 0; 
02368           
02369           /* Software workaround applied to GCM encryption only */ 
02370           if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_ENCRYPT)
02371           {
02372             /* Change the mode configured in CHMOD bits of CR register to select CTR mode */   
02373             __HAL_CRYP_SET_CHAININGMODE(CRYP_CHAINMODE_AES_CTR);
02374           }            
02375           
02376           /*  Insert the last block (which size is inferior to 128 bits) padded with zeroes 
02377               to have a complete block of 128 bits */
02378           for(index=0; index < (difflength/4); index ++)
02379           {
02380             /* Write the Input block in the Data Input register */
02381             hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02382             inputaddr+=4;
02383           }
02384           /* If required, manage input data size not multiple of 32 bits */
02385           if (difflengthmod4 != 0)
02386           {         
02387             hcryp->Instance->DINR = ((*(uint32_t*)(inputaddr)) & mask[difflengthmod4-1]);
02388           }         
02389           /* Wrap-up in padding with zero-words if applicable */
02390           for(index=0; index < (4 - ((difflength+3)/4)); index ++)        
02391           {
02392             hcryp->Instance->DINR = 0;
02393           }                           
02394                                     
02395         }
02396         else
02397         {
02398           hcryp->pCrypInBuffPtr += 16;
02399           hcryp->CrypInCount -= 16;
02400           
02401           /* Write the Input block in the Data Input register */
02402           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02403           inputaddr+=4;
02404           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02405           inputaddr+=4;
02406           hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
02407           inputaddr+=4;
02408           hcryp->Instance->DINR = *(uint32_t*)(inputaddr);            
02409         }            
02410                   
02411     
02412         return HAL_OK;      
02413       }
02414     }
02415     /*==============================*/
02416     /* GCM/GMAC or CMAC final phase */
02417     /*==============================*/    
02418     else if (hcryp->Init.GCMCMACPhase == CRYP_GCMCMAC_FINAL_PHASE)
02419     {
02420       /* Clear Computation Complete Flag */
02421       __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);  
02422             
02423       /* Get the last output data address */
02424       outputaddr = (uint32_t)hcryp->pCrypOutBuffPtr;
02425       
02426       /* Retrieve the last expected data from the CRYP hardware block:
02427          read the output block from the Data Output Register */
02428       *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02429       outputaddr+=4;
02430       *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02431       outputaddr+=4;
02432       *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02433       outputaddr+=4;
02434       *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02435   
02436       /* Disable Computation Complete Flag and Errors Interrupts */
02437       __HAL_CRYP_DISABLE_IT(CRYP_IT_CCFIE|CRYP_IT_ERRIE);
02438       /* Change the CRYP state */
02439       hcryp->State = HAL_CRYP_STATE_READY;
02440       /* Mark that the header phase is over */
02441       hcryp->Phase = HAL_CRYP_PHASE_FINAL_OVER;
02442       
02443       /* Disable the Peripheral */
02444       __HAL_CRYP_DISABLE();
02445       /* Process Unlocked */
02446        __HAL_UNLOCK(hcryp);
02447       
02448       /* Call computation complete callback */
02449       HAL_CRYPEx_ComputationCpltCallback(hcryp);
02450       
02451       return HAL_OK;
02452     }
02453     else
02454     {
02455       /* Clear Computation Complete Flag */
02456       __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);       
02457       hcryp->State = HAL_CRYP_STATE_ERROR; 
02458       __HAL_UNLOCK(hcryp); 
02459       return HAL_ERROR; 
02460     }
02461   }
02462   else
02463   {
02464     return HAL_BUSY; 
02465   }  
02466 }
02467     
02468   
02469   
02470 /** 
02471   * @brief  Set the DMA configuration and start the DMA transfer
02472   *         for GCM, GMAC or CMAC chainging modes.   
02473   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
02474   *         the configuration information for CRYP module.
02475   * @param  inputaddr: Address of the Input buffer.
02476   * @param  Size: Size of the Input buffer un bytes, must be a multiple of 16.
02477   * @param  outputaddr: Address of the Output buffer, null pointer when no output DMA stream
02478   *         has to be configured.  
02479   * @retval None
02480   */
02481 static void CRYP_GCMCMAC_SetDMAConfig(CRYP_HandleTypeDef *hcryp, uint32_t inputaddr, uint16_t Size, uint32_t outputaddr)
02482 {
02483 
02484   /* Set the input CRYP DMA transfer complete callback */
02485   hcryp->hdmain->XferCpltCallback = CRYP_GCMCMAC_DMAInCplt;
02486   /* Set the DMA error callback */
02487   hcryp->hdmain->XferErrorCallback = CRYP_GCMCMAC_DMAError;
02488   
02489   if (outputaddr != 0) 
02490   { 
02491     /* Set the output CRYP DMA transfer complete callback */
02492     hcryp->hdmaout->XferCpltCallback = CRYP_GCMCMAC_DMAOutCplt;
02493     /* Set the DMA error callback */
02494     hcryp->hdmaout->XferErrorCallback = CRYP_GCMCMAC_DMAError;
02495   }
02496   
02497   /* Enable the CRYP peripheral */
02498   __HAL_CRYP_ENABLE();
02499   
02500   /* Enable the DMA input stream */
02501   HAL_DMA_Start_IT(hcryp->hdmain, inputaddr, (uint32_t)&hcryp->Instance->DINR, Size/4);
02502   
02503   /* Enable the DMA input request */
02504   SET_BIT(hcryp->Instance->CR, AES_CR_DMAINEN);
02505 
02506   
02507   if (outputaddr != 0) 
02508   {   
02509     /* Enable the DMA output stream */
02510     HAL_DMA_Start_IT(hcryp->hdmaout, (uint32_t)&hcryp->Instance->DOUTR, outputaddr, Size/4);
02511   
02512     /* Enable the DMA output request */
02513     SET_BIT(hcryp->Instance->CR, AES_CR_DMAOUTEN);
02514   }
02515 }  
02516 
02517 
02518 
02519 /**
02520   * @brief  Write/read input/output data in polling mode.
02521   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
02522   *         the configuration information for CRYP module.
02523   * @param  Input: Pointer to the Input buffer.
02524   * @param  Ilength: Length of the Input buffer in bytes, must be a multiple of 16.
02525   * @param  Output: Pointer to the returned buffer.
02526   * @param  Timeout: Specify Timeout value.  
02527   * @retval HAL status
02528   */
02529 static HAL_StatusTypeDef CRYP_ProcessData(CRYP_HandleTypeDef *hcryp, uint8_t* Input, uint16_t Ilength, uint8_t* Output, uint32_t Timeout)
02530 {
02531   uint32_t index = 0;
02532   uint32_t inputaddr  = (uint32_t)Input;
02533   uint32_t outputaddr = (uint32_t)Output;
02534   
02535 
02536   for(index=0; (index < Ilength); index += 16)
02537   {
02538     /* Write the Input block in the Data Input register */
02539     hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02540     inputaddr+=4;
02541     hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02542     inputaddr+=4;
02543     hcryp->Instance->DINR  = *(uint32_t*)(inputaddr);
02544     inputaddr+=4;
02545     hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02546     inputaddr+=4;
02547     
02548     /* Wait for CCF flag to be raised */
02549     if(CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK)  
02550     { 
02551       hcryp->State = HAL_CRYP_STATE_READY;        
02552       __HAL_UNLOCK(hcryp);
02553       return HAL_TIMEOUT;
02554     }
02555       
02556     /* Clear CCF Flag */
02557     __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02558     
02559     /* Read the Output block from the Data Output Register */
02560     *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02561     outputaddr+=4;
02562     *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02563     outputaddr+=4;
02564     *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02565     outputaddr+=4;
02566     *(uint32_t*)(outputaddr) = hcryp->Instance->DOUTR;
02567     outputaddr+=4;
02568     
02569     /* If the suspension flag has been raised and if the processing is not about
02570        to end, suspend processing */
02571     if ((hcryp->SuspendRequest == HAL_CRYP_SUSPEND) && ((index+16) < Ilength))
02572     {
02573       /* Reset SuspendRequest */
02574       hcryp->SuspendRequest = HAL_CRYP_SUSPEND_NONE;
02575       
02576       /* Save current reading and writing locations of Input and Output buffers */
02577       hcryp->pCrypOutBuffPtr =  (uint8_t *)outputaddr;
02578       hcryp->pCrypInBuffPtr  =  (uint8_t *)inputaddr;
02579       /* Save the number of bytes that remain to be processed at this point */
02580       hcryp->CrypInCount     =  Ilength - (index+16);
02581       
02582       /* Change the CRYP state */
02583       hcryp->State = HAL_CRYP_STATE_SUSPENDED;
02584       
02585       return HAL_OK;
02586     }
02587     
02588     
02589   }
02590   /* Return function status */
02591   return HAL_OK;
02592 
02593 }
02594 
02595 
02596 
02597 
02598 
02599 /**
02600   * @brief  Read derivative key in polling mode when CRYP hardware block is set
02601   *         in key derivation operating mode (mode 2).
02602   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
02603   *         the configuration information for CRYP module.
02604   * @param  Output: Pointer to the returned buffer.
02605   * @param  Timeout: Specify Timeout value.  
02606   * @retval HAL status
02607   */
02608 static HAL_StatusTypeDef CRYP_ReadKey(CRYP_HandleTypeDef *hcryp, uint8_t* Output, uint32_t Timeout)
02609 {
02610   uint32_t outputaddr = (uint32_t)Output;
02611   
02612   /* Wait for CCF flag to be raised */  
02613   if(CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK)  
02614   { 
02615     hcryp->State = HAL_CRYP_STATE_READY;        
02616     __HAL_UNLOCK(hcryp);
02617     return HAL_TIMEOUT;
02618   }
02619   /* Clear CCF Flag */
02620   __HAL_CRYP_CLEAR_FLAG( CRYP_CCF_CLEAR);
02621   
02622     /* Read the derivative key from the AES_KEYRx registers */
02623   if (hcryp->Init.KeySize == CRYP_KEYSIZE_256B)
02624   {   
02625     *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->KEYR7);
02626     outputaddr+=4;
02627     *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->KEYR6);
02628     outputaddr+=4;
02629     *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->KEYR5);
02630     outputaddr+=4;
02631     *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->KEYR4);
02632     outputaddr+=4;
02633   }
02634   
02635     *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->KEYR3);
02636     outputaddr+=4;
02637     *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->KEYR2);
02638     outputaddr+=4;
02639     *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->KEYR1);
02640     outputaddr+=4;
02641     *(uint32_t*)(outputaddr) = __REV(hcryp->Instance->KEYR0);
02642 
02643     
02644   /* Return function status */
02645   return HAL_OK;
02646 }
02647 
02648 /**
02649   * @brief  Set the DMA configuration and start the DMA transfer.
02650   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
02651   *         the configuration information for CRYP module.
02652   * @param  inputaddr: Address of the Input buffer.
02653   * @param  Size: Size of the Input buffer in bytes, must be a multiple of 16.
02654   * @param  outputaddr: Address of the Output buffer.
02655   * @retval None
02656   */
02657 static void CRYP_SetDMAConfig(CRYP_HandleTypeDef *hcryp, uint32_t inputaddr, uint16_t Size, uint32_t outputaddr)
02658 {
02659   /* Set the CRYP DMA transfer complete callback */
02660   hcryp->hdmain->XferCpltCallback = CRYP_DMAInCplt;
02661   /* Set the DMA error callback */
02662   hcryp->hdmain->XferErrorCallback = CRYP_DMAError;
02663   
02664   /* Set the CRYP DMA transfer complete callback */
02665   hcryp->hdmaout->XferCpltCallback = CRYP_DMAOutCplt;
02666   /* Set the DMA error callback */
02667   hcryp->hdmaout->XferErrorCallback = CRYP_DMAError;
02668 
02669   /* Enable the DMA input stream */
02670   HAL_DMA_Start_IT(hcryp->hdmain, inputaddr, (uint32_t)&hcryp->Instance->DINR, Size/4);
02671 
02672   /* Enable the DMA output stream */
02673   HAL_DMA_Start_IT(hcryp->hdmaout, (uint32_t)&hcryp->Instance->DOUTR, outputaddr, Size/4);
02674 
02675   /* Enable In and Out DMA requests */
02676   SET_BIT(hcryp->Instance->CR, (AES_CR_DMAINEN | AES_CR_DMAOUTEN));
02677   
02678   /* Enable the CRYP peripheral */
02679   __HAL_CRYP_ENABLE();
02680 }
02681 
02682 
02683 /**
02684   * @brief  Handle CRYP hardware block Timeout when waiting for CCF flag to be raised.
02685   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
02686   *         the configuration information for CRYP module.      
02687   * @param  Timeout: Timeout duration.
02688   * @retval HAL status
02689   */
02690 static HAL_StatusTypeDef CRYP_WaitOnCCFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
02691 {
02692   uint32_t tickstart = 0;
02693   
02694   /* Get timeout */
02695   tickstart = HAL_GetTick();
02696   
02697   while(HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF))
02698   {    
02699     /* Check for the Timeout */
02700     if(Timeout != HAL_MAX_DELAY)
02701     {
02702       if((HAL_GetTick() - tickstart ) > Timeout)
02703       {    
02704         return HAL_TIMEOUT;
02705       }
02706     }
02707   }
02708   return HAL_OK; 
02709 }
02710 
02711 /**
02712   * @brief  Wait for Busy Flag to be reset during a GCM payload encryption process suspension. 
02713   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
02714   *         the configuration information for CRYP module.         
02715   * @param  Timeout: Timeout duration.
02716   * @retval HAL status
02717   */
02718 static HAL_StatusTypeDef CRYP_WaitOnBusyFlagReset(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
02719 {
02720   uint32_t tickstart = 0;
02721   
02722   /* Get timeout */
02723   tickstart = HAL_GetTick();
02724   
02725   while(HAL_IS_BIT_SET(hcryp->Instance->SR, AES_SR_BUSY))
02726   {    
02727     /* Check for the Timeout */
02728     if(Timeout != HAL_MAX_DELAY)
02729     {
02730       if((HAL_GetTick() - tickstart ) > Timeout)
02731       {    
02732         return HAL_TIMEOUT;
02733       }
02734     }
02735   }
02736   return HAL_OK; 
02737 }
02738 
02739 
02740 /**
02741   * @brief  DMA CRYP Input Data process complete callback.
02742   * @param  hdma: DMA handle.
02743   * @retval None
02744   */
02745 static void CRYP_DMAInCplt(DMA_HandleTypeDef *hdma)  
02746 {
02747   CRYP_HandleTypeDef* hcryp = (CRYP_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
02748   
02749   /* Disable the DMA transfer for input request  */
02750   CLEAR_BIT(hcryp->Instance->CR, AES_CR_DMAINEN);
02751   
02752   /* Call input data transfer complete callback */
02753   HAL_CRYP_InCpltCallback(hcryp);
02754 }
02755 
02756 /**
02757   * @brief  DMA CRYP Output Data process complete callback.
02758   * @param  hdma: DMA handle.
02759   * @retval None
02760   */
02761 static void CRYP_DMAOutCplt(DMA_HandleTypeDef *hdma)
02762 {  
02763   CRYP_HandleTypeDef* hcryp = (CRYP_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
02764   
02765   /* Disable the DMA transfer for output request */
02766   CLEAR_BIT(hcryp->Instance->CR, AES_CR_DMAOUTEN);
02767 
02768   /* Clear CCF Flag */
02769   __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02770   
02771   /* Disable CRYP */
02772   __HAL_CRYP_DISABLE();
02773   
02774   /* Change the CRYP state to ready */
02775   hcryp->State = HAL_CRYP_STATE_READY;
02776   
02777   /* Call output data transfer complete callback */
02778   HAL_CRYP_OutCpltCallback(hcryp);
02779 }
02780 
02781 /**
02782   * @brief  DMA CRYP communication error callback. 
02783   * @param  hdma: DMA handle.
02784   * @retval None
02785   */
02786 static void CRYP_DMAError(DMA_HandleTypeDef *hdma)
02787 {
02788   CRYP_HandleTypeDef* hcryp = (CRYP_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
02789   
02790   hcryp->State= HAL_CRYP_STATE_ERROR;
02791   hcryp->ErrorCode |= HAL_CRYP_DMA_ERROR;  
02792   HAL_CRYP_ErrorCallback(hcryp);
02793   /* Clear Error Flag */
02794   __HAL_CRYP_CLEAR_FLAG(CRYP_ERR_CLEAR);
02795 }
02796 
02797 /**
02798   * @brief  Last header or payload block padding when size is not a multiple of 128 bits. 
02799   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
02800   *         the configuration information for CRYP module.         
02801   * @param  difflength: size remainder after having fed all complete 128-bit blocks.
02802   * @param  polling: specifies whether or not polling on CCF must be done after having
02803   *                  entered a complete block.     
02804   * @retval None
02805   */
02806 static void CRYP_Padding(CRYP_HandleTypeDef *hcryp, uint32_t difflength, uint32_t polling)
02807 {
02808   uint32_t index          = 0;
02809   uint32_t difflengthmod4 = difflength%4;
02810   uint32_t inputaddr      = (uint32_t)hcryp->pCrypInBuffPtr; 
02811   uint32_t outputaddr     = (uint32_t)hcryp->pCrypOutBuffPtr;   
02812   uint32_t mask[3]        = {0x0FF, 0x0FFFF, 0x0FFFFFF};  
02813   uint32_t intermediate_data[4] = {0};
02814   
02815   /* Software workaround applied to GCM encryption only */
02816   if ((hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE) &&       
02817       (hcryp->Init.OperatingMode == CRYP_ALGOMODE_ENCRYPT))
02818   {
02819     /* Change the mode configured in CHMOD bits of CR register to select CTR mode */   
02820     __HAL_CRYP_SET_CHAININGMODE(CRYP_CHAINMODE_AES_CTR);
02821   }  
02822   
02823   /* Wrap-up entering header data */
02824   /* Enter complete words when possible */
02825   for(index=0; index < (difflength/4); index ++)
02826   {
02827     /* Write the Input block in the Data Input register */
02828     hcryp->Instance->DINR = *(uint32_t*)(inputaddr);
02829     inputaddr+=4;
02830   }
02831   /* Enter incomplete word padded with zeroes if applicable 
02832     (case of header length not a multiple of 32-bits) */
02833   if (difflengthmod4 != 0)
02834   {         
02835     hcryp->Instance->DINR = ((*(uint32_t*)(inputaddr)) & mask[difflengthmod4-1]);
02836   }         
02837   /* Pad with zero-words to reach 128-bit long block and wrap-up header feeding to the IP */
02838   for(index=0; index < (4 - ((difflength+3)/4)); index ++)         
02839   {
02840     hcryp->Instance->DINR = 0;
02841   } 
02842         
02843   if (polling == CRYP_POLLING_ON)
02844   {
02845         if(CRYP_WaitOnCCFlag(hcryp, CRYP_CCF_TIMEOUTVALUE) != HAL_OK)  
02846     { 
02847         hcryp->State = HAL_CRYP_STATE_READY;        
02848         __HAL_UNLOCK(hcryp);
02849        HAL_CRYP_ErrorCallback(hcryp);
02850       } 
02851 
02852     /* Clear CCF Flag */
02853     __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02854   }
02855         
02856     /* if payload */
02857   if (hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE)
02858     {       
02859        
02860     /* Retrieve intermediate data */
02861     for(index=0; index < 4; index ++)
02862     {
02863       intermediate_data[index] = hcryp->Instance->DOUTR;                 
02864     }     
02865     /* Retrieve last words of cyphered data */
02866     /* First, retrieve complete output words */
02867     for(index=0; index < (difflength/4); index ++)
02868     {
02869       *(uint32_t*)(outputaddr) = intermediate_data[index];
02870       outputaddr+=4; 
02871     } 
02872     /* Next, retrieve partial output word if applicable;
02873        at the same time, start masking intermediate data 
02874        with a mask of zeros of same size than the padding
02875        applied to the last block of payload */ 
02876     if (difflengthmod4 != 0)
02877     {
02878       intermediate_data[difflength/4] &= mask[difflengthmod4-1];
02879       *(uint32_t*)(outputaddr) = intermediate_data[difflength/4];            
02880     }           
02881     
02882     /* Software workaround applied to GCM encryption only */           
02883     if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_ENCRYPT)
02884     {
02885       /* Change again CHMOD configuration to GCM mode */
02886       __HAL_CRYP_SET_CHAININGMODE(CRYP_CHAINMODE_AES_GCM_GMAC);  
02887       
02888       /* Select FINAL phase */
02889       MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_GCMCMAC_FINAL_PHASE);
02890       
02891       /* Before inserting the intermediate data, carry on masking operation
02892          with a mask of zeros of same size than the padding applied to the last block of payload */
02893       for(index=0; index < (4 - ((difflength+3)/4)); index ++)        
02894       {
02895         intermediate_data[(difflength+3)/4+index] = 0;
02896       }   
02897       /* Insert intermediate data */
02898       for(index=0; index < 4; index ++)
02899       {
02900         hcryp->Instance->DINR = intermediate_data[index];          
02901       } 
02902       
02903       /*  Wait for completion, and read data on DOUT. This data is to discard. */ 
02904       if(CRYP_WaitOnCCFlag(hcryp, CRYP_CCF_TIMEOUTVALUE) != HAL_OK)  
02905       { 
02906         hcryp->State = HAL_CRYP_STATE_READY;        
02907         __HAL_UNLOCK(hcryp);
02908         HAL_CRYP_ErrorCallback(hcryp);
02909       } 
02910          
02911       /* Read data to discard */ 
02912       /* Clear CCF Flag */
02913       __HAL_CRYP_CLEAR_FLAG(CRYP_CCF_CLEAR);
02914       for(index=0; index < 4; index ++)
02915       {
02916         intermediate_data[index] = hcryp->Instance->DOUTR;        
02917       }  
02918         
02919       } /* if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_ENCRYPT) */
02920     }   /* if (hcryp->Init.GCMCMACPhase == CRYP_GCM_PAYLOAD_PHASE) */
02921         
02922 }
02923 
02924 /**
02925   * @}
02926   */
02927 
02928 /**
02929   * @}
02930   */
02931 
02932 /**
02933   * @}
02934   */
02935 
02936 #endif /* defined (STM32L442xx) || defined (STM32L443xx) || defined(STM32L485xx) || defined(STM32L486xx) */  
02937 
02938 #endif /* HAL_CRYP_MODULE_ENABLED */
02939 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/