środa, 21 lipca 2021

STM32 - H723ZG - mbedtls - SHA, AES

W tym poście chciałbym opisać obsługę algorytmu SHA oraz AES z wykorzystaniem biblioteki MBEDTLS. 

[Źródło: https://www.st.com/en/evaluation-tools/nucleo-h723zg.html]

Poniżej znajdują się wykorzystywane przeze mnie funkcje.

Funkcja sprawdzające działanie SHA1:

  1. void mbedtls_sha1_test_funct(void)
  2. {
  3.     unsigned char data[] = "DATATEST123456789ab";
  4.     unsigned char encryptedData[32] = {0x00};
  5.  
  6.     mbedtls_sha1_context sha1_ctx;
  7.     mbedtls_sha1_init(&sha1_ctx);
  8.     mbedtls_sha1_starts(&sha1_ctx);
  9.     mbedtls_sha1_update(&sha1_ctx, data, strlen((char *)data));
  10.     mbedtls_sha1_finish(&sha1_ctx, encryptedData);
  11.  
  12.     printf("\r\n data:%s \r\n encryptedData sha1:", data);
  13.  
  14.     mbedtls_sha1_free(&sha1_ctx);
  15.  
  16.     for(uint8_t i=0; i<32; i++) {
  17.         printf("%02x", encryptedData[i]);
  18.     }
  19.  
  20.     printf("\r\n");
  21. }

Funkcja sprawdzająca działanie SHA224:

  1. void mbedtls_sha224_test_funct(void)
  2. {
  3.     unsigned char data[] = "DATATEST123456789ab";
  4.     unsigned char encryptedData[32] = {0x00};
  5.  
  6.     mbedtls_sha256_context sha224_ctx;
  7.     mbedtls_sha256_init(&sha224_ctx);
  8.  
  9.     mbedtls_sha256_starts(&sha224_ctx, 1);
  10.     mbedtls_sha256_update(&sha224_ctx, data, strlen((char *)data));
  11.     mbedtls_sha256_finish(&sha224_ctx, encryptedData);
  12.  
  13.     printf("\r\n data:%s \r\n encryptedData sha224:", data);
  14.     mbedtls_sha256_free(&sha224_ctx);
  15.  
  16.     for(uint8_t i=0; i<32; i++) {
  17.         printf("%02x", encryptedData[i]);
  18.     }
  19.  
  20.     printf("\r\n");
  21. }

Funkcja sprawdzająca działanie SHA256:

  1. void mbedtls_sha256_test_funct(void)
  2. {
  3.     unsigned char data[] = "DATATEST123456789ab";
  4.     unsigned char encryptedData[32] = {0x00};
  5.  
  6.     mbedtls_sha256_context sha256_ctx;
  7.     mbedtls_sha256_init(&sha256_ctx);
  8.  
  9.     //Drugi parametr w funkcji mbedtls_sha256_starts definiuje jak będę szyfrowane dane:
  10.     //is224 = 0 -> sha256
  11.     //is224 = 1 -> sha224
  12.  
  13.     mbedtls_sha256_starts(&sha256_ctx, 0);
  14.     mbedtls_sha256_update(&sha256_ctx, data, strlen((char *)data));
  15.     mbedtls_sha256_finish(&sha256_ctx, encryptedData);
  16.  
  17.     printf("\r\n data:%s \r\n encryptedData sha256:", data);
  18.     mbedtls_sha256_free(&sha256_ctx);
  19.  
  20.     for(uint8_t i=0; i<32; i++) {
  21.         printf("%02x", encryptedData[i]);
  22.     }
  23.  
  24.     printf("\r\n");
  25. }

Sprawdzenie działania SHA1 można wykonać na tej stronie. Wyświetli ona następujący wynik:


Lub na tej dla SHA1, SHA224, SHA256:




Funkcje po interfejsie UART zwrócą dane pasujące do tych wygenerowanych na powyższych zrzutach ze strony internetowej.



Poniżej funkcja testująca działanie AES ECB:

  1. void mbedtls_aes_ecb_test_funct(void)
  2. {
  3.     mbedtls_aes_context aes_ctx;
  4.  
  5.     unsigned char key[16] = "123PWMGUJ8HDYjd8";
  6.     unsigned char plain[16] = "abcdefthujsokdjr";
  7.     unsigned char decipher_data[16] = {0};
  8.     unsigned char cipher[16] = {0};
  9.  
  10.     mbedtls_aes_init(&aes_ctx);
  11.     mbedtls_aes_setkey_enc(&aes_ctx, key, 128);
  12.     mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, plain, cipher);
  13.     mbedtls_aes_setkey_dec(&aes_ctx, key, 128);
  14.     mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_DECRYPT, cipher, decipher_data);
  15.     mbedtls_aes_free(&aes_ctx);
  16.    
  17.     #if defined(DEBUG_ENABLE)
  18.  
  19.     printf("\r\n AES ECB TEST: \r\n");
  20.  
  21.     printf("\r\n key: ");
  22.     for(uint8_t loop = 0; loop<16; loop++) { printf("%c", key[loop]); }
  23.  
  24.     printf("\r\n plain: ");
  25.     for(uint8_t loop = 0; loop<16; loop++) { printf("%c", plain[loop]); }
  26.  
  27.     printf("\r\n crypt data: ");
  28.     for(uint8_t loop = 0; loop<16; loop++) {  printf("%c", cipher[loop]);  }
  29.  
  30.     printf("\r\n dec_plain: ");
  31.     for(uint8_t loop = 0; loop<16; loop++) {  printf("%c", decipher_data[loop]);  }
  32.     printf("\r\n");
  33.    
  34.     #endif
  35. }

ECB jest to prosty sposób szyfrowania, gdzie każdy z bloków wiadomości jest kodowany osobno. 

Funkcja testująca działanie AES CBC:

  1. void mbedtls_aes_cbc_test_funct(void)
  2. {
  3.     mbedtls_aes_context aes_ctx;
  4.  
  5.     unsigned char key[16] = "123PWMGUJ8HDYjd8";
  6.     unsigned char plain[64] = "abcdefthujsokdjrabcdefthujsokdjrabcdefthujsokdjrabcdefthujsokdjr";
  7.     unsigned char iv[16] = {0x23, 0x65, 0xAE, 0xE7, 0x78, 0x67, 0x64, 0x89, 0x90, 0x43, 0x88, 0xAB, 0xEC, 0x45, 0x23, 0xFF};
  8.     unsigned char iv2[16] = {0x23, 0x65, 0xAE, 0xE7, 0x78, 0x67, 0x64, 0x89, 0x90, 0x43, 0x88, 0xAB, 0xEC, 0x45, 0x23, 0xFF};
  9.     unsigned char decipher_data[64] = {0};
  10.     unsigned char cipher[64] = {0};
  11.  
  12.     mbedtls_aes_init(&aes_ctx);
  13.     mbedtls_aes_setkey_enc(&aes_ctx, key, 128);
  14.     mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, 64, iv, plain, cipher);
  15.     mbedtls_aes_setkey_dec(&aes_ctx, key, 128);
  16.     mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, 64, iv2, cipher, decipher_data);
  17.     mbedtls_aes_free(&aes_ctx);
  18.  
  19.     #if defined(DEBUG_ENABLE)
  20.    
  21.     printf("\r\n AES CBC TEST: \r\n");
  22.  
  23.     printf("\r\n key: ");
  24.     for(uint8_t loop = 0; loop<16; loop++) { printf("%c", key[loop]); }
  25.  
  26.     printf("\r\n plain: ");
  27.     for(uint8_t loop = 0; loop<64; loop++) { printf("%c", plain[loop]); }
  28.  
  29.     printf("\r\n cipher: ");
  30.     for(uint8_t loop = 0; loop<64; loop++) {  printf("%c", cipher[loop]);  }
  31.  
  32.     printf("\r\n dec_plain: ");
  33.     for(uint8_t loop = 0; loop<64; loop++) {  printf("%c", decipher_data[loop]);  }
  34.  
  35.     printf("\r\n iv: ");
  36.     for(uint8_t loop = 0; loop<16; loop++) {  printf("%c", iv[loop]);  }
  37.  
  38.     printf("\r\n");
  39.    
  40.     #endif
  41. }

W przypadku powyższego szyfru należy pamiętać, że iv po zaszyfrowaniu wiadomości ulega zmianie. Aby odszyfrować wiadomość trzeba użyć oryginalnej wartości iv, która została użyta do zaszyfrowania wiadomości. Dla powyższej funkcji wartość ta jest wprowadzona do zmiennej iv2.

W przypadku szyfru CBC do każdego bloku dokładany jest XOR. Po takich operacjach następuje szyfrowanie w standardowy sposób.

Bibliografia:


http://www.crypto-it.net/pl/teoria/tryby-szyfrow-blokowych.html