czwartek, 17 kwietnia 2025

STM32 - Funkcje bezpieczeństwa - TRNG

 W tym poście chciałbym opisać funkcje TRNG (ang. True Random Number Generator). 


TRNG jest zaimplementowane w większości układów z rodziny STM32. 


TRNG jest to sprzętowy generator licz losowych opartych na zjawiskach fizycznych. Oznacza to, że generuje on liczby losowe nieprzewidywalne i niereprodukowane. Są one idealne do zastosowań kryptograficznych. 

Dokładny opis [link


TRNG bazuje na źródle szumu analogowego. Generator tworzy zestaw czterech 32-bitowych liczb losowych. Dla przedstawionych danych próbki są dostępne co 864 cykle AHB. 

Trzy flagi statusowe:

  • DRDY - (ang. Data Ready) - dane są gotowe do odczytania z rejestru DR. 
  • SECS - (ang. Seed Error Current Status) - pojawiły się nieprawidłowe dane w ciągu bitów źródła entropii. np. Ponad 64 identyczne bity z rzędu bądź 32 powtarzane wzorce jak 01, 10. 
  • CECS - (ang. Clock Error Current Status) - za niska częstotliwość. 

Trzy przerwania:

  • CEIS - (ang. Clock Error Interrupt Status) - Przerwanie sygnalizujące problem z zegarem.
  • SEIS - (ang. Seed Error Interrupt Status) - Przerwanie sygnalizujące błąd entropii
  • DRDY - (ang. Data Ready Interrupt) - Dane dostępne do odczytu. 

Diagram blokowy wygląda następująco:


Schemat został podzielony na następujące bloki:

  • Analog Seed - źródło entropii generowane na podstawie analogowego szumu.
  • Sampling - proces próbkowania.
  • Digital post-processing/conditioning - Dane ze źródła analogowego są przetwarzane cyfrowo aby poprawić rozkład losowości oraz usunięcie korelacji miedzy bitami. 
  • 4x 32-bit FIFO - bufor dla danych losowych.
  • 32-bit random data register - końcowy punkt z którego można odczytać gotowe dane losowe. 
  • Error management - składa się z dwóch bloków:
    • Clock checker - sprawdzanie poprawności zegara. Zgłaszanie błędów jeśli takie problemy się pojawią.
    • Fault detector - wykrywanie błędów np. związanych z brakiem entropii bądź powtarzalności danych. 

Działanie bloku jest następujące: 

  • Start RNG,
  • Analogowy szum jest próbkowany i przetwarzany.
  • Wynik operacji trafia do FIFO. Następnie do rejestru DR. 
  • Gdy dane są gotowe ustawiana jest flaga DRDY.
  • Jeśli operacja się nie powiedzie, ustawiane są flagi SEIS/CEIS.

Bezpośrednio z CubeMx można uruchomić flagę ClockErrorDetection oraz przerwania od RNG:


Rejestry RNG:

  1. #define RNG_SR_DRDY_Pos     (0U)
  2. #define RNG_SR_DRDY_Msk     (0x1UL << RNG_SR_DRDY_Pos)                       /*!< 0x00000001 */
  3. #define RNG_SR_DRDY         RNG_SR_DRDY_Msk
  4. #define RNG_SR_CECS_Pos     (1U)
  5. #define RNG_SR_CECS_Msk     (0x1UL << RNG_SR_CECS_Pos)                       /*!< 0x00000002 */
  6. #define RNG_SR_CECS         RNG_SR_CECS_Msk
  7. #define RNG_SR_SECS_Pos     (2U)
  8. #define RNG_SR_SECS_Msk     (0x1UL << RNG_SR_SECS_Pos)                       /*!< 0x00000004 */
  9. #define RNG_SR_SECS         RNG_SR_SECS_Msk
  10. #define RNG_SR_CEIS_Pos     (5U)
  11. #define RNG_SR_CEIS_Msk     (0x1UL << RNG_SR_CEIS_Pos)                      /*!< 0x00000020 */
  12. #define RNG_SR_CEIS         RNG_SR_CEIS_Msk
  13. #define RNG_SR_SEIS_Pos     (6U)
  14. #define RNG_SR_SEIS_Msk     (0x1UL << RNG_SR_SEIS_Pos)                     /*!< 0x00000040 */
  15. #define RNG_SR_SEIS         RNG_SR_SEIS_Msk

Dane można odczytać bezpośrednio z rejestrów. Poniżej funkcje pozwalające na takie operacje:

  1. uint8_t RNG_IsDataReady(void)
  2. {
  3.     return (RNG->SR & RNG_SR_DRDY) ? 1 : 0;
  4. }
  5.  
  6. uint8_t RNG_IsClockErrorCurrent(void)
  7. {
  8.     return (RNG->SR & RNG_SR_CECS) ? 1 : 0;
  9. }
  10.  
  11. uint8_t RNG_IsSeedErrorCurrent(void)
  12. {
  13.     return (RNG->SR & RNG_SR_SECS) ? 1 : 0;
  14. }
  15.  
  16. uint8_t RNG_IsClockErrorInterrupt(void)
  17. {
  18.     return (RNG->SR & RNG_SR_CEIS) ? 1 : 0;
  19. }

Testowa funkcja generująca 20 liczb losowych:

  1. for(uint8_t i=0; i<20;i++) {
  2.     uint32_t randomNumber = 0;
  3.     HAL_RNG_GenerateRandomNumber(&hrng, &randomNumber);
  4.     printf("[%.2d] 0x%08lX\r\n",i,randomNumber);
  5. }

Przykładowe generowanie liczb losowych:

  1. [00] 0x4A37657E
  2. [01] 0x982B4CE2
  3. [02] 0x02FF5B05
  4. [03] 0xB63EED7A
  5. [04] 0xC516AF68
  6. [05] 0xBC797E86
  7. [06] 0x094F7622
  8. [07] 0x18E81C6F
  9. [08] 0x9D76AF46
  10. [09] 0x9E3D7359
  11. [10] 0x65986F55
  12. [11] 0x4D296E40
  13. [12] 0x382F13D3
  14. [13] 0xD06EA165
  15. [14] 0x31DD1B3D
  16. [15] 0x431A45BF
  17. [16] 0x7C8327E4
  18. [17] 0x2A79581D
  19. [18] 0xBE549B27
  20. [19] 0x7E678273