- CRYP_HandleTypeDef hcryp;
- __ALIGN_BEGIN static const uint32_t pKeyCRYP[4] __ALIGN_END = {
- 0x12345678,0x12345678,0x12345678,0x12345678};
- __ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
- 0x00000000,0x00000000,0x00000000,0x00000000};
- static void MX_CRYP_Init(void)
- {
- /* USER CODE BEGIN CRYP_Init 0 */
- /* USER CODE END CRYP_Init 0 */
- /* USER CODE BEGIN CRYP_Init 1 */
- /* USER CODE END CRYP_Init 1 */
- hcryp.Instance = CRYP;
- hcryp.Init.DataType = CRYP_DATATYPE_32B;
- hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
- hcryp.Init.pKey = (uint32_t *)pKeyCRYP;
- hcryp.Init.pInitVect = (uint32_t *)pInitVectCRYP;
- hcryp.Init.Algorithm = CRYP_AES_CBC;
- if (HAL_CRYP_Init(&hcryp) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN CRYP_Init 2 */
- /* USER CODE END CRYP_Init 2 */
- }
- #define CRYP_DES_ECB CRYP_CR_ALGOMODE_DES_ECB
- #define CRYP_DES_CBC CRYP_CR_ALGOMODE_DES_CBC
- #define CRYP_TDES_ECB CRYP_CR_ALGOMODE_TDES_ECB
- #define CRYP_TDES_CBC CRYP_CR_ALGOMODE_TDES_CBC
- #define CRYP_AES_ECB CRYP_CR_ALGOMODE_AES_ECB
- #define CRYP_AES_CBC CRYP_CR_ALGOMODE_AES_CBC
- #define CRYP_AES_CTR CRYP_CR_ALGOMODE_AES_CTR
- #define CRYP_AES_GCM CRYP_CR_ALGOMODE_AES_GCM
- #define CRYP_AES_CCM CRYP_CR_ALGOMODE_AES_CCM
Funkcja szyfrująca dane, zdefiniowana w bibliotece HAL wygląda następująco:
- HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
- uint32_t Timeout)
- {
- uint32_t algo;
- HAL_StatusTypeDef status;
- if (hcryp->State == HAL_CRYP_STATE_READY)
- {
- /* Change state Busy */
- hcryp->State = HAL_CRYP_STATE_BUSY;
- /* Process locked */
- __HAL_LOCK(hcryp);
- /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr, pCrypOutBuffPtr and Size parameters*/
- hcryp->CrypInCount = 0U;
- hcryp->CrypOutCount = 0U;
- hcryp->pCrypInBuffPtr = Input;
- hcryp->pCrypOutBuffPtr = Output;
- /* Calculate Size parameter in Byte*/
- if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD)
- {
- hcryp->Size = Size * 4U;
- }
- else
- {
- hcryp->Size = Size;
- }
- /* Set Encryption operating mode*/
- MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_ENCRYPT);
- /* algo get algorithm selected */
- algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE;
- switch (algo)
- {
- case CRYP_DES_ECB:
- case CRYP_DES_CBC:
- case CRYP_TDES_ECB:
- case CRYP_TDES_CBC:
- /*Set Key */
- hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey);
- hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1);
- if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
- {
- hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2);
- hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3);
- hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4);
- hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5);
- }
- /*Set Initialization Vector (IV)*/
- if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
- {
- hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
- hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
- }
- /* Flush FIFO */
- HAL_CRYP_FIFO_FLUSH(hcryp);
- /* Set the phase */
- hcryp->Phase = CRYP_PHASE_PROCESS;
- /* Start DES/TDES encryption process */
- status = CRYP_TDES_Process(hcryp, Timeout);
- break;
- case CRYP_AES_ECB:
- case CRYP_AES_CBC:
- case CRYP_AES_CTR:
- /* AES encryption */
- status = CRYP_AES_Encrypt(hcryp, Timeout);
- break;
- case CRYP_AES_GCM:
- /* AES GCM encryption */
- status = CRYP_AESGCM_Process(hcryp, Timeout);
- break;
- case CRYP_AES_CCM:
- /* AES CCM encryption */
- status = CRYP_AESCCM_Process(hcryp, Timeout);
- break;
- default:
- hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED;
- status = HAL_ERROR;
- break;
- }
- if (status == HAL_OK)
- {
- /* Change the CRYP peripheral state */
- hcryp->State = HAL_CRYP_STATE_READY;
- /* Process unlocked */
- __HAL_UNLOCK(hcryp);
- }
- }
- else
- {
- /* Process unlocked */
- __HAL_UNLOCK(hcryp);
- /* Busy error code field */
- hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
- status = HAL_ERROR;
- }
- /* Return function status */
- return status ;
- }
Powyższa funkcja uruchamia szyfrowanie danych przy użyciu sprzętowego modułu kryptograficznego CRYP. Dostaje dane wejściowe, wskaźnik do bufora przechowującego zaszyfrowane dane, rozmiar danych oraz timeout. Następnie wybiera odpowiedni algorytm szyfrowania z wcześniej zdefiniowanej struktury.
Moduł może także pracować w różnych trybach (Polling, Przerwania czy DMA):
- HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
- uint32_t Timeout);
- HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
- uint32_t Timeout);
- HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
- HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
- HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
- HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
Ok podstawowe elementy są już omówione. Teraz postaram się pokazać różne przykłady użycia tej biblioteki do obsługi danych.
Poniżej pierwszy przykład AES ECB w pollingu.
- static uint32_t plaintext[4] =
- {
- 0x00112233,
- 0x44556677,
- 0x8899AABB,
- 0xCCDDEEFF
- };
- static uint32_t encrypted[4];
- static uint32_t decrypted[4];
- void Test_AES_ECB_Polling(void)
- {
- HAL_StatusTypeDef status;
- memset(encrypted, 0, sizeof(encrypted));
- memset(decrypted, 0, sizeof(decrypted));
- hcryp.Instance = CRYP;
- hcryp.Init.DataType = CRYP_DATATYPE_32B;
- hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
- hcryp.Init.Algorithm = CRYP_AES_ECB;
- hcryp.Init.pKey = (uint32_t *)pKeyCRYP;
- hcryp.Init.pInitVect = (uint32_t *)pInitVectCRYP;
- hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
- status = HAL_CRYP_Init(&hcryp);
- if (status != HAL_OK)
- {
- printf("HAL_CRYP_Init ERROR\r\n");
- return;
- }
- status = HAL_CRYP_Encrypt(&hcryp, plaintext, 4, encrypted, 1000);
- if (status != HAL_OK)
- {
- printf("Encrypt ERROR = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
- return;
- }
- status = HAL_CRYP_Decrypt(&hcryp, encrypted, 4, decrypted, 1000);
- if (status != HAL_OK)
- {
- printf("Decrypt ERROR = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
- return;
- }
- if (memcmp(plaintext, decrypted, sizeof(plaintext)) == 0)
- {
- printf("AES ECB TEST OK\r\n");
- }
- else
- {
- printf("AES ECB TEST FAILED\r\n");
- printf("Plaintext : %08lX %08lX %08lX %08lX\r\n",
- plaintext[0], plaintext[1], plaintext[2], plaintext[3]);
- printf("Decrypted : %08lX %08lX %08lX %08lX\r\n",
- decrypted[0], decrypted[1], decrypted[2], decrypted[3]);
- }
- }
W funkcji testowej ponownie wykonuje inicjalizację modułu. Wydaje mi się, że nie ma potrzeby robić deinit poprzedniej konfiguracji.
Powyższa przykładowa funkcja wchodzi w tą część funkcji HAL_CRYP_Encrypt:
- case CRYP_AES_ECB:
- case CRYP_AES_CBC:
- case CRYP_AES_CTR:
- status = CRYP_AES_Encrypt(hcryp, Timeout);
- break;
Obliczenia można weryfikować nie tylko przez deszyfrowanie ale też z użyciem narzędzi online jak np tutaj:
W tym przypadku musimy zdefiniować IV, z którego AES CBC korzysta:
- __ALIGN_BEGIN static const uint32_t pKeyCRYP[4] __ALIGN_END = {
- 0x12345678,0x12345678,0x12345678,0x12345678};
- __ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
- 0x10111213, 0x14151617, 0x18191A1B, 0x1C1D1E1F};
- static uint32_t plaintext_cbc[4] =
- {
- 0x00112233,
- 0x44556677,
- 0x8899AABB,
- 0xCCDDEEFF
- };
- static uint32_t encrypted_cbc[4];
- static uint32_t decrypted_cbc[4];
- void Test_AES_CBC_Polling(void)
- {
- HAL_StatusTypeDef status;
- memset(encrypted_cbc, 0, sizeof(encrypted_cbc));
- memset(decrypted_cbc, 0, sizeof(decrypted_cbc));
- hcryp.Instance = CRYP;
- hcryp.Init.DataType = CRYP_DATATYPE_32B;
- hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
- hcryp.Init.Algorithm = CRYP_AES_CBC;
- hcryp.Init.pKey = (uint32_t *)pKeyCRYP;
- hcryp.Init.pInitVect = (uint32_t *)pInitVectCRYP;
- hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
- status = HAL_CRYP_Init(&hcryp);
- if (status != HAL_OK)
- {
- printf("HAL_CRYP_Init ERROR\r\n");
- return;
- }
- status = HAL_CRYP_Encrypt(&hcryp, plaintext_cbc, 4, encrypted_cbc, 1000);
- if (status != HAL_OK)
- {
- printf("CBC Encrypt ERROR, ErrorCode = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
- return;
- }
- status = HAL_CRYP_Decrypt(&hcryp, encrypted_cbc, 4, decrypted_cbc, 1000);
- if (status != HAL_OK)
- {
- printf("CBC Decrypt ERROR, ErrorCode = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
- return;
- }
- if (memcmp(plaintext_cbc, decrypted_cbc, sizeof(plaintext_cbc)) == 0)
- {
- printf("AES CBC TEST OK\r\n");
- }
- else
- {
- printf("AES CBC TEST FAILED\r\n");
- }
- }
Procedura jest mniej więcej identyczna do poprzedniej.
Można także skorzystać z przerwań:
- __ALIGN_BEGIN static const uint32_t pKeyCRYP[4] __ALIGN_END = {
- 0x12345678,0x12345678,0x12345678,0x12345678};
- __ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
- 0x10111213, 0x14151617, 0x18191A1B, 0x1C1D1E1F};
- volatile uint8_t cryp_done = 0;
- volatile uint8_t cryp_error = 0;
- void HAL_CRYP_InCpltCallback(CRYP_HandleTypeDef *hcryp)
- {
- printf("CRYP HAL_CRYP_InCpltCallbackr\n");
- }
- void HAL_CRYP_OutCpltCallback(CRYP_HandleTypeDef *hcryp)
- {
- cryp_done = 1;
- printf("CRYP HAL_CRYP_OutCpltCallback\r\n");
- }
- void HAL_CRYP_ErrorCallback(CRYP_HandleTypeDef *hcryp)
- {
- cryp_error = 1;
- printf("CRYP HAL_CRYP_ErrorCallback\r\n");
- }
- void CRYP_IRQHandler(void)
- {
- HAL_CRYP_IRQHandler(&hcryp);
- }
- void Test_AES_ECB_IT(void)
- {
- HAL_StatusTypeDef status;
- cryp_done = 0;
- cryp_error = 0;
- memset(encrypted, 0, sizeof(encrypted));
- hcryp.Instance = CRYP;
- hcryp.Init.DataType = CRYP_DATATYPE_32B;
- hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
- hcryp.Init.Algorithm = CRYP_AES_ECB;
- hcryp.Init.pKey = (uint32_t *)pKeyCRYP;
- hcryp.Init.pInitVect = (uint32_t *)pInitVectCRYP;
- hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
- HAL_CRYP_Init(&hcryp);
- status = HAL_CRYP_Encrypt_IT(&hcryp, plaintext, 4, encrypted);
- if (status != HAL_OK)
- {
- printf("Encrypt IT start ERROR\r\n");
- return;
- }
- while ((cryp_done == 0) && (cryp_error == 0))
- {
- //Zamiast While to można oczywiście wykonywać inne operacje
- //I gdzie indziej sprawdzac status flag.
- //Czekanie na wynik całkowicie usuwa korzyści stosowania przerwań.
- }
- if (cryp_done)
- {
- printf("AES ECB IT TEST OK\r\n");
- }
- if (cryp_error)
- {
- printf("AES ECB IT TEST ERROR, ErrorCode = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
- }
- }
Działanie jak poprzednio. W celu sprawdzenia zakończenia operacji należy monitorować wartości zmiennych cryp_done i cryp_error.
- void HAL_CRYP_MspInit(CRYP_HandleTypeDef* hcryp)
- {
- if(hcryp->Instance==CRYP)
- {
- /* USER CODE BEGIN CRYP_MspInit 0 */
- /* USER CODE END CRYP_MspInit 0 */
- /* Peripheral clock enable */
- __HAL_RCC_CRYP_CLK_ENABLE();
- /* USER CODE BEGIN CRYP_MspInit 1 */
- HAL_NVIC_SetPriority(CRYP_IRQn, 5, 0);
- HAL_NVIC_EnableIRQ(CRYP_IRQn);
- /* USER CODE END CRYP_MspInit 1 */
- }
- }
No i w końcu można także użyć DMA.
- __ALIGN_BEGIN static const uint32_t pKeyCRYP[4] __ALIGN_END = {
- 0x12345678,0x12345678,0x12345678,0x12345678};
- __ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
- 0x00000000,0x00000000,0x00000000,0x00000000};
- DMA_HandleTypeDef hdma_cryp_in;
- DMA_HandleTypeDef hdma_cryp_out;
- static uint32_t encrypted_dma[4];
- static uint32_t decrypted_dma[4];
- void HAL_CRYP_InCpltCallback(CRYP_HandleTypeDef *hcryp)
- {
- printf("CRYP HAL_CRYP_InCpltCallbackr\n");
- }
- void HAL_CRYP_OutCpltCallback(CRYP_HandleTypeDef *hcryp)
- {
- cryp_dma_done = 1;
- }
- void HAL_CRYP_ErrorCallback(CRYP_HandleTypeDef *hcryp)
- {
- cryp_dma_error = 1;
- }
- void CRYP_IRQHandler(void)
- {
- HAL_CRYP_IRQHandler(&hcryp);
- }
- void Test_AES_CBC_DMA_Encrypt(void)
- {
- HAL_StatusTypeDef status;
- cryp_dma_done = 0;
- cryp_dma_error = 0;
- memset(encrypted_dma, 0, sizeof(encrypted_dma));
- hcryp.Instance = CRYP;
- hcryp.Init.DataType = CRYP_DATATYPE_32B;
- hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
- hcryp.Init.Algorithm = CRYP_AES_CBC;
- hcryp.Init.pKey = (uint32_t *)pKeyCRYP;
- hcryp.Init.pInitVect = (uint32_t *)pInitVectCRYP;
- hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
- hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
- status = HAL_CRYP_Init(&hcryp);
- if (status != HAL_OK)
- {
- printf("HAL_CRYP_Init ERROR\r\n");
- return;
- }
- status = HAL_CRYP_Encrypt_DMA(&hcryp, plaintext, 4, encrypted_dma);
- if (status != HAL_OK)
- {
- printf("HAL_CRYP_Encrypt_DMA start ERROR, ErrorCode = 0x%08lX\r\n",
- HAL_CRYP_GetError(&hcryp));
- return;
- }
- while ((cryp_dma_done == 0) && (cryp_dma_error == 0))
- { }
- if (cryp_dma_done)
- {
- printf("AES ECB DMA Encrypt OK\r\n");
- printf("Encrypted: %08lX %08lX %08lX %08lX\r\n",
- encrypted_dma[0], encrypted_dma[1],
- encrypted_dma[2], encrypted_dma[3]);
- }
- }
- void HAL_CRYP_MspInit(CRYP_HandleTypeDef* hcryp)
- {
- if(hcryp->Instance==CRYP)
- {
- /* USER CODE BEGIN CRYP_MspInit 0 */
- /* USER CODE END CRYP_MspInit 0 */
- /* Peripheral clock enable */
- __HAL_RCC_CRYP_CLK_ENABLE();
- /* CRYP DMA Init */
- /* CRYP_IN Init */
- hdma_cryp_in.Instance = DMA1_Stream0;
- hdma_cryp_in.Init.Request = DMA_REQUEST_CRYP_IN;
- hdma_cryp_in.Init.Direction = DMA_MEMORY_TO_PERIPH;
- hdma_cryp_in.Init.PeriphInc = DMA_PINC_DISABLE;
- hdma_cryp_in.Init.MemInc = DMA_MINC_ENABLE;
- hdma_cryp_in.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
- hdma_cryp_in.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
- hdma_cryp_in.Init.Mode = DMA_NORMAL;
- hdma_cryp_in.Init.Priority = DMA_PRIORITY_HIGH;
- hdma_cryp_in.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
- if (HAL_DMA_Init(&hdma_cryp_in) != HAL_OK)
- {
- Error_Handler();
- }
- __HAL_LINKDMA(hcryp,hdmain,hdma_cryp_in);
- /* CRYP_OUT Init */
- hdma_cryp_out.Instance = DMA1_Stream1;
- hdma_cryp_out.Init.Request = DMA_REQUEST_CRYP_OUT;
- hdma_cryp_out.Init.Direction = DMA_PERIPH_TO_MEMORY;
- hdma_cryp_out.Init.PeriphInc = DMA_PINC_DISABLE;
- hdma_cryp_out.Init.MemInc = DMA_MINC_ENABLE;
- hdma_cryp_out.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
- hdma_cryp_out.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
- hdma_cryp_out.Init.Mode = DMA_NORMAL;
- hdma_cryp_out.Init.Priority = DMA_PRIORITY_VERY_HIGH;
- hdma_cryp_out.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
- if (HAL_DMA_Init(&hdma_cryp_out) != HAL_OK)
- {
- Error_Handler();
- }
- __HAL_LINKDMA(hcryp,hdmaout,hdma_cryp_out);
- /* USER CODE BEGIN CRYP_MspInit 1 */
- /* USER CODE END CRYP_MspInit 1 */
- }
- }
- static void MX_DMA_Init(void)
- {
- /* DMA controller clock enable */
- __HAL_RCC_DMA1_CLK_ENABLE();
- /* DMA interrupt init */
- /* DMA1_Stream0_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
- /* DMA1_Stream1_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
- }
- //Test
- Test_AES_ECB_DMA_Encrypt();
- if (cryp_dma_error == 0)
- {
- Test_AES_ECB_DMA_Decrypt();
- }