czwartek, 11 czerwca 2026

STM32H7 - CRYP

W tym poście chciałbym opisać działanie modułu kryptograficznego CRYP. Służy do szybkiego szyfrowania i deszyfrowania danych bez użycia CPU. 


Funkcje bezpieczeństwa w STM32:


Moduł obsługuje takie algorytmy jak AES 128, 196, 256, TDES, DES. W różnych trybach pracy jak ECB, CBC, CTR czy GCM. Tryby pracy zależne od wybranego algorytmu.

Wykorzystuje się go do szyfrowania danych w pamięci, szyfrowania komunikacji (TLS, SSL), ochrony oprogramowania i do innych do których szyfrowanie jest potrzebne. Ponieważ jest to osobny moduł to działanie będzie szybsze niż implementacja w programie. Dodatkowo będzie niższe zużycie CPU oraz energii.  

W CubeMX aktywujemy go po wybraniu:

Pojawiają się dodatkowe parametry do ustawienia:


Na potrzeby testu sprawdzę działanie dla AES CBC:

Do początkowych parametrów podajemy rodzaj danych, wielkość klucza, klucz i wektor początkowy. Po inicjalizacji przekazujemy dane do wykonania.

CubeMx wygeneruje następujący kod inicjalizacji:

  1. CRYP_HandleTypeDef hcryp;
  2. __ALIGN_BEGIN static const uint32_t pKeyCRYP[4] __ALIGN_END = {
  3.                             0x12345678,0x12345678,0x12345678,0x12345678};
  4. __ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
  5.                             0x00000000,0x00000000,0x00000000,0x00000000};
  6.  
  7. static void MX_CRYP_Init(void)
  8. {
  9.   /* USER CODE BEGIN CRYP_Init 0 */
  10.   /* USER CODE END CRYP_Init 0 */
  11.   /* USER CODE BEGIN CRYP_Init 1 */
  12.   /* USER CODE END CRYP_Init 1 */
  13.   hcryp.Instance = CRYP;
  14.   hcryp.Init.DataType = CRYP_DATATYPE_32B;
  15.   hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
  16.   hcryp.Init.pKey = (uint32_t *)pKeyCRYP;
  17.   hcryp.Init.pInitVect = (uint32_t *)pInitVectCRYP;
  18.   hcryp.Init.Algorithm = CRYP_AES_CBC;
  19.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
  20.   {
  21.     Error_Handler();
  22.   }
  23.   /* USER CODE BEGIN CRYP_Init 2 */
  24.   /* USER CODE END CRYP_Init 2 */
  25. }

Można wybrać takie algorytmy:

  1. #define CRYP_DES_ECB     CRYP_CR_ALGOMODE_DES_ECB
  2. #define CRYP_DES_CBC     CRYP_CR_ALGOMODE_DES_CBC
  3. #define CRYP_TDES_ECB    CRYP_CR_ALGOMODE_TDES_ECB
  4. #define CRYP_TDES_CBC    CRYP_CR_ALGOMODE_TDES_CBC
  5. #define CRYP_AES_ECB     CRYP_CR_ALGOMODE_AES_ECB
  6. #define CRYP_AES_CBC     CRYP_CR_ALGOMODE_AES_CBC
  7. #define CRYP_AES_CTR     CRYP_CR_ALGOMODE_AES_CTR
  8. #define CRYP_AES_GCM     CRYP_CR_ALGOMODE_AES_GCM
  9. #define CRYP_AES_CCM     CRYP_CR_ALGOMODE_AES_CCM

Funkcja szyfrująca dane, zdefiniowana w bibliotece HAL wygląda następująco:

  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
  2.                                    uint32_t Timeout)
  3. {
  4.   uint32_t algo;
  5.   HAL_StatusTypeDef status;
  6.  
  7.   if (hcryp->State == HAL_CRYP_STATE_READY)
  8.   {
  9.     /* Change state Busy */
  10.     hcryp->State = HAL_CRYP_STATE_BUSY;
  11.  
  12.     /* Process locked */
  13.     __HAL_LOCK(hcryp);
  14.  
  15.     /*  Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr, pCrypOutBuffPtr and Size parameters*/
  16.     hcryp->CrypInCount = 0U;
  17.     hcryp->CrypOutCount = 0U;
  18.     hcryp->pCrypInBuffPtr = Input;
  19.     hcryp->pCrypOutBuffPtr = Output;
  20.  
  21.     /*  Calculate Size parameter in Byte*/
  22.     if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD)
  23.     {
  24.       hcryp->Size = Size * 4U;
  25.     }
  26.     else
  27.     {
  28.       hcryp->Size = Size;
  29.     }
  30.  
  31.     /* Set Encryption operating mode*/
  32.     MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_ENCRYPT);
  33.  
  34.     /* algo get algorithm selected */
  35.     algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE;
  36.  
  37.     switch (algo)
  38.     {
  39.       case CRYP_DES_ECB:
  40.       case CRYP_DES_CBC:
  41.       case CRYP_TDES_ECB:
  42.       case CRYP_TDES_CBC:
  43.  
  44.         /*Set Key */
  45.         hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey);
  46.         hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1);
  47.         if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
  48.         {
  49.           hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2);
  50.           hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3);
  51.           hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4);
  52.           hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5);
  53.         }
  54.  
  55.         /*Set Initialization Vector (IV)*/
  56.         if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
  57.         {
  58.           hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
  59.           hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
  60.         }
  61.  
  62.         /* Flush FIFO */
  63.         HAL_CRYP_FIFO_FLUSH(hcryp);
  64.  
  65.         /* Set the phase */
  66.         hcryp->Phase = CRYP_PHASE_PROCESS;
  67.  
  68.         /* Start DES/TDES encryption process */
  69.         status = CRYP_TDES_Process(hcryp, Timeout);
  70.         break;
  71.  
  72.       case CRYP_AES_ECB:
  73.       case CRYP_AES_CBC:
  74.       case CRYP_AES_CTR:
  75.  
  76.         /* AES encryption */
  77.         status = CRYP_AES_Encrypt(hcryp, Timeout);
  78.         break;
  79.  
  80.       case CRYP_AES_GCM:
  81.  
  82.         /* AES GCM encryption */
  83.         status = CRYP_AESGCM_Process(hcryp, Timeout);
  84.         break;
  85.  
  86.       case CRYP_AES_CCM:
  87.  
  88.         /* AES CCM encryption */
  89.         status = CRYP_AESCCM_Process(hcryp, Timeout);
  90.         break;
  91.  
  92.       default:
  93.         hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED;
  94.         status = HAL_ERROR;
  95.         break;
  96.     }
  97.  
  98.     if (status == HAL_OK)
  99.     {
  100.       /* Change the CRYP peripheral state */
  101.       hcryp->State = HAL_CRYP_STATE_READY;
  102.  
  103.       /* Process unlocked */
  104.       __HAL_UNLOCK(hcryp);
  105.     }
  106.   }
  107.   else
  108.   {
  109.     /* Process unlocked */
  110.     __HAL_UNLOCK(hcryp);
  111.  
  112.     /* Busy error code field */
  113.     hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
  114.     status = HAL_ERROR;
  115.   }
  116.  
  117.   /* Return function status */
  118.   return status ;
  119. }

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):

  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
  2.                                    uint32_t Timeout);
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
  4.                                    uint32_t Timeout);
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
  8. 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. 

  1. static uint32_t plaintext[4] =
  2. {
  3.     0x00112233,
  4.     0x44556677,
  5.     0x8899AABB,
  6.     0xCCDDEEFF
  7. };
  8.  
  9. static uint32_t encrypted[4];
  10. static uint32_t decrypted[4];
  11.  
  12. void Test_AES_ECB_Polling(void)
  13. {
  14.     HAL_StatusTypeDef status;
  15.  
  16.     memset(encrypted, 0, sizeof(encrypted));
  17.     memset(decrypted, 0, sizeof(decrypted));
  18.  
  19.     hcryp.Instance = CRYP;
  20.  
  21.     hcryp.Init.DataType      = CRYP_DATATYPE_32B;
  22.     hcryp.Init.KeySize       = CRYP_KEYSIZE_128B;
  23.     hcryp.Init.Algorithm     = CRYP_AES_ECB;
  24.     hcryp.Init.pKey = (uint32_t *)pKeyCRYP;
  25.     hcryp.Init.pInitVect = (uint32_t *)pInitVectCRYP;
  26.     hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
  27.  
  28.     status = HAL_CRYP_Init(&hcryp);
  29.  
  30.     if (status != HAL_OK)
  31.     {
  32.         printf("HAL_CRYP_Init ERROR\r\n");
  33.         return;
  34.     }
  35.    
  36.     status = HAL_CRYP_Encrypt(&hcryp, plaintext, 4, encrypted, 1000);
  37.  
  38.     if (status != HAL_OK)
  39.     {
  40.         printf("Encrypt ERROR = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
  41.         return;
  42.     }
  43.  
  44.     status = HAL_CRYP_Decrypt(&hcryp, encrypted, 4, decrypted, 1000);
  45.  
  46.     if (status != HAL_OK)
  47.     {
  48.         printf("Decrypt ERROR = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
  49.         return;
  50.     }
  51.  
  52.     if (memcmp(plaintext, decrypted, sizeof(plaintext)) == 0)
  53.     {
  54.         printf("AES ECB TEST OK\r\n");
  55.     }
  56.     else
  57.     {
  58.         printf("AES ECB TEST FAILED\r\n");
  59.         printf("Plaintext : %08lX %08lX %08lX %08lX\r\n",
  60.                plaintext[0], plaintext[1], plaintext[2], plaintext[3]);
  61.         printf("Decrypted : %08lX %08lX %08lX %08lX\r\n",
  62.                decrypted[0], decrypted[1], decrypted[2], decrypted[3]);
  63.     }
  64. }

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:

  1. case CRYP_AES_ECB:
  2. case CRYP_AES_CBC:
  3. case CRYP_AES_CTR:
  4.   status = CRYP_AES_Encrypt(hcryp, Timeout);
  5.   break;

Obliczenia można weryfikować nie tylko przez deszyfrowanie ale też z użyciem narzędzi online jak np tutaj:

AES CBC:

W tym przypadku musimy zdefiniować IV, z którego AES CBC korzysta:

  1. __ALIGN_BEGIN static const uint32_t pKeyCRYP[4] __ALIGN_END = {
  2.                             0x12345678,0x12345678,0x12345678,0x12345678};
  3. __ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
  4.                             0x10111213, 0x14151617, 0x18191A1B, 0x1C1D1E1F};
  5.  
  6. static uint32_t plaintext_cbc[4] =
  7. {
  8.     0x00112233,
  9.     0x44556677,
  10.     0x8899AABB,
  11.     0xCCDDEEFF
  12. };
  13.  
  14. static uint32_t encrypted_cbc[4];
  15. static uint32_t decrypted_cbc[4];
  16.  
  17. void Test_AES_CBC_Polling(void)
  18. {
  19.     HAL_StatusTypeDef status;
  20.  
  21.     memset(encrypted_cbc, 0, sizeof(encrypted_cbc));
  22.     memset(decrypted_cbc, 0, sizeof(decrypted_cbc));
  23.  
  24.     hcryp.Instance = CRYP;
  25.  
  26.     hcryp.Init.DataType      = CRYP_DATATYPE_32B;
  27.     hcryp.Init.KeySize       = CRYP_KEYSIZE_128B;
  28.     hcryp.Init.Algorithm     = CRYP_AES_CBC;
  29.     hcryp.Init.pKey          = (uint32_t *)pKeyCRYP;
  30.     hcryp.Init.pInitVect     = (uint32_t *)pInitVectCRYP;
  31.     hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
  32.  
  33.     status = HAL_CRYP_Init(&hcryp);
  34.  
  35.     if (status != HAL_OK)
  36.     {
  37.         printf("HAL_CRYP_Init ERROR\r\n");
  38.         return;
  39.     }
  40.  
  41.     status = HAL_CRYP_Encrypt(&hcryp, plaintext_cbc, 4, encrypted_cbc, 1000);
  42.  
  43.     if (status != HAL_OK)
  44.     {
  45.         printf("CBC Encrypt ERROR, ErrorCode = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
  46.         return;
  47.     }
  48.  
  49.     status = HAL_CRYP_Decrypt(&hcryp, encrypted_cbc, 4, decrypted_cbc, 1000);
  50.  
  51.     if (status != HAL_OK)
  52.     {
  53.         printf("CBC Decrypt ERROR, ErrorCode = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
  54.         return;
  55.     }
  56.  
  57.     if (memcmp(plaintext_cbc, decrypted_cbc, sizeof(plaintext_cbc)) == 0)
  58.     {
  59.         printf("AES CBC TEST OK\r\n");
  60.     }
  61.     else
  62.     {
  63.         printf("AES CBC TEST FAILED\r\n");
  64.     }
  65. }

Procedura jest mniej więcej identyczna do poprzedniej. 

Można także skorzystać z przerwań:

  1. __ALIGN_BEGIN static const uint32_t pKeyCRYP[4] __ALIGN_END = {
  2.                             0x12345678,0x12345678,0x12345678,0x12345678};
  3. __ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
  4.                             0x10111213, 0x14151617, 0x18191A1B, 0x1C1D1E1F};
  5.  
  6. volatile uint8_t cryp_done = 0;
  7. volatile uint8_t cryp_error = 0;
  8.  
  9. void HAL_CRYP_InCpltCallback(CRYP_HandleTypeDef *hcryp)
  10. {
  11.     printf("CRYP HAL_CRYP_InCpltCallbackr\n");
  12. }
  13.  
  14. void HAL_CRYP_OutCpltCallback(CRYP_HandleTypeDef *hcryp)
  15. {
  16.     cryp_done = 1;
  17.     printf("CRYP HAL_CRYP_OutCpltCallback\r\n");
  18. }
  19.  
  20. void HAL_CRYP_ErrorCallback(CRYP_HandleTypeDef *hcryp)
  21. {
  22.     cryp_error = 1;
  23.     printf("CRYP HAL_CRYP_ErrorCallback\r\n");
  24. }
  25.  
  26. void CRYP_IRQHandler(void)
  27. {
  28.     HAL_CRYP_IRQHandler(&hcryp);
  29. }
  30.  
  31. void Test_AES_ECB_IT(void)
  32. {
  33.     HAL_StatusTypeDef status;
  34.  
  35.     cryp_done = 0;
  36.     cryp_error = 0;
  37.  
  38.     memset(encrypted, 0, sizeof(encrypted));
  39.  
  40.     hcryp.Instance = CRYP;
  41.  
  42.     hcryp.Init.DataType      = CRYP_DATATYPE_32B;
  43.     hcryp.Init.KeySize       = CRYP_KEYSIZE_128B;
  44.     hcryp.Init.Algorithm     = CRYP_AES_ECB;
  45.     hcryp.Init.pKey          = (uint32_t *)pKeyCRYP;
  46.     hcryp.Init.pInitVect     = (uint32_t *)pInitVectCRYP;
  47.     hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
  48.  
  49.     HAL_CRYP_Init(&hcryp);
  50.  
  51.     status = HAL_CRYP_Encrypt_IT(&hcryp, plaintext, 4, encrypted);
  52.  
  53.     if (status != HAL_OK)
  54.     {
  55.         printf("Encrypt IT start ERROR\r\n");
  56.         return;
  57.     }
  58.  
  59.     while ((cryp_done == 0) && (cryp_error == 0))
  60.     {
  61.         //Zamiast While to można oczywiście wykonywać inne operacje
  62.         //I gdzie indziej sprawdzac status flag.
  63.         //Czekanie na wynik całkowicie usuwa korzyści stosowania przerwań.
  64.     }
  65.  
  66.     if (cryp_done)
  67.     {
  68.         printf("AES ECB IT TEST OK\r\n");
  69.     }
  70.  
  71.     if (cryp_error)
  72.     {
  73.         printf("AES ECB IT TEST ERROR, ErrorCode = 0x%08lX\r\n", HAL_CRYP_GetError(&hcryp));
  74.     }
  75. }

Działanie jak poprzednio. W celu sprawdzenia zakończenia operacji należy monitorować wartości zmiennych cryp_done i cryp_error. 

Przerwania należy włączyć w HAL_CRYP_MspInit:

  1. void HAL_CRYP_MspInit(CRYP_HandleTypeDef* hcryp)
  2. {
  3.   if(hcryp->Instance==CRYP)
  4.   {
  5.     /* USER CODE BEGIN CRYP_MspInit 0 */
  6.  
  7.     /* USER CODE END CRYP_MspInit 0 */
  8.     /* Peripheral clock enable */
  9.     __HAL_RCC_CRYP_CLK_ENABLE();
  10.     /* USER CODE BEGIN CRYP_MspInit 1 */
  11.  
  12.     HAL_NVIC_SetPriority(CRYP_IRQn, 5, 0);
  13.     HAL_NVIC_EnableIRQ(CRYP_IRQn);
  14.     /* USER CODE END CRYP_MspInit 1 */
  15.  
  16.   }
  17. }

No i w końcu można także użyć DMA. 

  1. __ALIGN_BEGIN static const uint32_t pKeyCRYP[4] __ALIGN_END = {
  2.                             0x12345678,0x12345678,0x12345678,0x12345678};
  3. __ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
  4.                             0x00000000,0x00000000,0x00000000,0x00000000};
  5.  
  6. DMA_HandleTypeDef hdma_cryp_in;
  7. DMA_HandleTypeDef hdma_cryp_out;
  8.  
  9. static uint32_t encrypted_dma[4];
  10. static uint32_t decrypted_dma[4];
  11.  
  12. void HAL_CRYP_InCpltCallback(CRYP_HandleTypeDef *hcryp)
  13. {
  14.     printf("CRYP HAL_CRYP_InCpltCallbackr\n");
  15. }
  16.  
  17. void HAL_CRYP_OutCpltCallback(CRYP_HandleTypeDef *hcryp)
  18. {
  19.     cryp_dma_done = 1;
  20. }
  21.  
  22. void HAL_CRYP_ErrorCallback(CRYP_HandleTypeDef *hcryp)
  23. {
  24.     cryp_dma_error = 1;
  25. }
  26.  
  27. void CRYP_IRQHandler(void)
  28. {
  29.     HAL_CRYP_IRQHandler(&hcryp);
  30. }
  31.  
  32. void Test_AES_CBC_DMA_Encrypt(void)
  33. {
  34.     HAL_StatusTypeDef status;
  35.  
  36.     cryp_dma_done = 0;
  37.     cryp_dma_error = 0;
  38.  
  39.     memset(encrypted_dma, 0, sizeof(encrypted_dma));
  40.  
  41.     hcryp.Instance = CRYP;
  42.  
  43.     hcryp.Init.DataType        = CRYP_DATATYPE_32B;
  44.     hcryp.Init.KeySize         = CRYP_KEYSIZE_128B;
  45.     hcryp.Init.Algorithm       = CRYP_AES_CBC;
  46.     hcryp.Init.pKey          = (uint32_t *)pKeyCRYP;
  47.     hcryp.Init.pInitVect     = (uint32_t *)pInitVectCRYP;
  48.     hcryp.Init.DataWidthUnit   = CRYP_DATAWIDTHUNIT_WORD;
  49.     hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
  50.  
  51.     status = HAL_CRYP_Init(&hcryp);
  52.  
  53.     if (status != HAL_OK)
  54.     {
  55.         printf("HAL_CRYP_Init ERROR\r\n");
  56.         return;
  57.     }
  58.  
  59.     status = HAL_CRYP_Encrypt_DMA(&hcryp, plaintext, 4, encrypted_dma);
  60.  
  61.     if (status != HAL_OK)
  62.     {
  63.         printf("HAL_CRYP_Encrypt_DMA start ERROR, ErrorCode = 0x%08lX\r\n",
  64.                HAL_CRYP_GetError(&hcryp));
  65.         return;
  66.     }
  67.  
  68.     while ((cryp_dma_done == 0) && (cryp_dma_error == 0))
  69.     { }
  70.  
  71.     if (cryp_dma_done)
  72.     {
  73.         printf("AES ECB DMA Encrypt OK\r\n");
  74.         printf("Encrypted: %08lX %08lX %08lX %08lX\r\n",
  75.                encrypted_dma[0], encrypted_dma[1],
  76.                encrypted_dma[2], encrypted_dma[3]);
  77.     }
  78. }
  79.  
  80. void HAL_CRYP_MspInit(CRYP_HandleTypeDef* hcryp)
  81. {
  82.   if(hcryp->Instance==CRYP)
  83.   {
  84.     /* USER CODE BEGIN CRYP_MspInit 0 */
  85.     /* USER CODE END CRYP_MspInit 0 */
  86.     /* Peripheral clock enable */
  87.     __HAL_RCC_CRYP_CLK_ENABLE();
  88.  
  89.     /* CRYP DMA Init */
  90.     /* CRYP_IN Init */
  91.     hdma_cryp_in.Instance = DMA1_Stream0;
  92.     hdma_cryp_in.Init.Request = DMA_REQUEST_CRYP_IN;
  93.     hdma_cryp_in.Init.Direction = DMA_MEMORY_TO_PERIPH;
  94.     hdma_cryp_in.Init.PeriphInc = DMA_PINC_DISABLE;
  95.     hdma_cryp_in.Init.MemInc = DMA_MINC_ENABLE;
  96.     hdma_cryp_in.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  97.     hdma_cryp_in.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  98.     hdma_cryp_in.Init.Mode = DMA_NORMAL;
  99.     hdma_cryp_in.Init.Priority = DMA_PRIORITY_HIGH;
  100.     hdma_cryp_in.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  101.     if (HAL_DMA_Init(&hdma_cryp_in) != HAL_OK)
  102.     {
  103.       Error_Handler();
  104.     }
  105.  
  106.     __HAL_LINKDMA(hcryp,hdmain,hdma_cryp_in);
  107.  
  108.     /* CRYP_OUT Init */
  109.     hdma_cryp_out.Instance = DMA1_Stream1;
  110.     hdma_cryp_out.Init.Request = DMA_REQUEST_CRYP_OUT;
  111.     hdma_cryp_out.Init.Direction = DMA_PERIPH_TO_MEMORY;
  112.     hdma_cryp_out.Init.PeriphInc = DMA_PINC_DISABLE;
  113.     hdma_cryp_out.Init.MemInc = DMA_MINC_ENABLE;
  114.     hdma_cryp_out.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  115.     hdma_cryp_out.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  116.     hdma_cryp_out.Init.Mode = DMA_NORMAL;
  117.     hdma_cryp_out.Init.Priority = DMA_PRIORITY_VERY_HIGH;
  118.     hdma_cryp_out.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  119.     if (HAL_DMA_Init(&hdma_cryp_out) != HAL_OK)
  120.     {
  121.       Error_Handler();
  122.     }
  123.  
  124.     __HAL_LINKDMA(hcryp,hdmaout,hdma_cryp_out);
  125.  
  126.     /* USER CODE BEGIN CRYP_MspInit 1 */
  127.     /* USER CODE END CRYP_MspInit 1 */
  128.  
  129.   }
  130. }
  131.  
  132. static void MX_DMA_Init(void)
  133. {
  134.  
  135.   /* DMA controller clock enable */
  136.   __HAL_RCC_DMA1_CLK_ENABLE();
  137.  
  138.   /* DMA interrupt init */
  139.   /* DMA1_Stream0_IRQn interrupt configuration */
  140.   HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  141.   HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
  142.   /* DMA1_Stream1_IRQn interrupt configuration */
  143.   HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
  144.   HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
  145. }
  146.  
  147. //Test
  148. Test_AES_ECB_DMA_Encrypt();
  149.  
  150. if (cryp_dma_error == 0)
  151. {
  152.     Test_AES_ECB_DMA_Decrypt();
  153. }

Jak widać na wiele sposobów można trzymać wynik korzystając z bloku CRYP. Zastosowanie przerwań czy DMA pozwoli na wykonywanie innych operacji czekając na wynik. Bez konieczności większego obciążania układu.