Hi,
I need to use AES CBC 256 encryption/decryption on nrf52840 but since its cyrpto cell only supports AES 128, I tried using mbedtls to do AES 256 encryption. It works fine but if then I add
Hi,
I need to use AES CBC 256 encryption/decryption on nrf52840 but since its cyrpto cell only supports AES 128, I tried using mbedtls to do AES 256 encryption. It works fine but if then I add
CONFIG_NRF_SECURITY=y CONFIG_MBEDTLS=y CONFIG_MBEDTLS_AES_C=y CONFIG_MBEDTLS_CIPHER_MODE_CBC=y CONFIG_ENTROPY_GENERATOR=y
#include <zephyr/kernel.h> #include <mbedtls/aes.h> #include <string.h> #define AES_KEY_SIZE 32 // AES-256 requires 32 bytes (256 bits) #define AES_BLOCK_SIZE 16 #define KEY_SIZE 256 static const uint8_t key[AES_KEY_SIZE] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 }; static uint8_t iv[AES_BLOCK_SIZE] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; // **PKCS#7 Padding** static size_t pkcs7_pad(uint8_t *data, size_t data_len, size_t block_size) { size_t pad_len = block_size - (data_len % block_size); for (size_t i = 0; i < pad_len; i++) { data[data_len + i] = (uint8_t)pad_len; } return data_len + pad_len; } // **PKCS#7 Unpadding** static size_t pkcs7_unpad(uint8_t *data, size_t data_len) { uint8_t pad_len = data[data_len - 1]; // Last byte gives padding size if (pad_len > AES_BLOCK_SIZE || pad_len == 0) { return data_len; // Invalid padding, return as-is } return data_len - pad_len; } // **AES-256-CBC Encryption** static int aes_encrypt(const uint8_t *input, size_t input_len, uint8_t *output, size_t *output_len) { mbedtls_aes_context aes; uint8_t iv_enc[AES_BLOCK_SIZE]; memcpy(iv_enc, iv, AES_BLOCK_SIZE); // Use fresh IV // **PKCS#7 Pad Input** uint8_t padded_input[64]; // Adjust buffer size as needed memcpy(padded_input, input, input_len); *output_len = pkcs7_pad(padded_input, input_len, AES_BLOCK_SIZE); mbedtls_aes_init(&aes); mbedtls_aes_setkey_enc(&aes, key, KEY_SIZE); int ret = mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, *output_len, iv_enc, padded_input, output); mbedtls_aes_free(&aes); return ret; } // **AES-256-CBC Decryption** static int aes_decrypt(const uint8_t *input, size_t input_len, uint8_t *output, size_t *output_len) { mbedtls_aes_context aes; uint8_t iv_dec[AES_BLOCK_SIZE]; memcpy(iv_dec, iv, AES_BLOCK_SIZE); // Use fresh IV mbedtls_aes_init(&aes); mbedtls_aes_setkey_dec(&aes, key, KEY_SIZE); int ret = mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, input_len, iv_dec, input, output); mbedtls_aes_free(&aes); // **PKCS#7 Unpad Output** *output_len = pkcs7_unpad(output, input_len); return ret; } // **Main Function** void main(void) { uint8_t plaintext[] = "Hello, AES-256-CBC!"; // 20 bytes uint8_t encrypted[64] = {0}; uint8_t decrypted[64] = {0}; size_t enc_len, dec_len; printf("Plain: %s\n", plaintext); // Encrypt if (aes_encrypt(plaintext, strlen((char *)plaintext), encrypted, &enc_len) != 0) { printf("Encryption failed!\n"); return; } printf("Encrypted: "); for (size_t i = 0; i < enc_len; i++) { printf("%02x", encrypted[i]); } printf("\n"); // Decrypt if (aes_decrypt(encrypted, enc_len, decrypted, &dec_len) != 0) { printf("Decryption failed!\n"); return; } decrypted[dec_len] = '\0'; // Null-terminate string printf("Decrypted: %s\n", decrypted); }
Hi,
I would recommend that you use the PSA crypto APIs, as the legacy APIs are deprecated and will be removed. You can use the Oberon backend fro AES256. To test it you can use the AES CBC sample, modify nrf/samples/crypto/aes_cbc/boards/nrf52840dk_nrf52840.conf so that CONFIG_PSA_CRYPTO_DRIVER_OBERON is enabled isntead of being disabled, and add CONFIG_PSA_WANT_AES_KEY_SIZE_256=y to prj.conf. Lastly, modify the call to psa_set_key_bits() in the sample to set 256 bit key size instead of 128.
This is a full diff of my modifications from SDK 2.9.1 that works for me on the nRF52840 DK:
diff --git a/samples/crypto/aes_cbc/boards/nrf52840dk_nrf52840.conf b/samples/crypto/aes_cbc/boards/nrf52840dk_nrf52840.conf index 1506df21e8..60a0917f5f 100644 --- a/samples/crypto/aes_cbc/boards/nrf52840dk_nrf52840.conf +++ b/samples/crypto/aes_cbc/boards/nrf52840dk_nrf52840.conf @@ -4,7 +4,7 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # # Using hardware crypto accelerator -CONFIG_PSA_CRYPTO_DRIVER_OBERON=n +CONFIG_PSA_CRYPTO_DRIVER_OBERON=y CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y # Mbedtls configuration diff --git a/samples/crypto/aes_cbc/prj.conf b/samples/crypto/aes_cbc/prj.conf index 8b4ddbcf9f..934b132e36 100644 --- a/samples/crypto/aes_cbc/prj.conf +++ b/samples/crypto/aes_cbc/prj.conf @@ -16,7 +16,10 @@ CONFIG_LOG=y # Enable nordic security backend and PSA APIs CONFIG_NRF_SECURITY=y CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_CRYPTO_DRIVER_OBERON=y CONFIG_PSA_WANT_GENERATE_RANDOM=y CONFIG_PSA_WANT_KEY_TYPE_AES=y CONFIG_PSA_WANT_ALG_CBC_NO_PADDING=y + +CONFIG_PSA_WANT_AES_KEY_SIZE_256=y \ No newline at end of file diff --git a/samples/crypto/aes_cbc/src/main.c b/samples/crypto/aes_cbc/src/main.c index 37ab449d8a..2b851c628d 100644 --- a/samples/crypto/aes_cbc/src/main.c +++ b/samples/crypto/aes_cbc/src/main.c @@ -87,7 +87,7 @@ int generate_key(void) psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE); psa_set_key_algorithm(&key_attributes, PSA_ALG_CBC_NO_PADDING); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES); - psa_set_key_bits(&key_attributes, 128); + psa_set_key_bits(&key_attributes, 256); /* Generate a random key. The key is not exposed to the application, * we can use it to encrypt/decrypt using the key handle
Thanks, I could make it run in the sample. I have couple of questions though.
1) Does CONFIG_PSA_CRYPTO_DRIVER_OBERON=y mean that all crypto related work then be run in software and hardware cell will no longer be used for the app?
2) I could make it work in aes_cbc sample based on 2.9.0 but the project I have to port this to is based on 2.4.2. If I upgrade that project, it will open up new work scope, so I tried aes_cbc sample based on 2.4.2 and followed exact steps, but over there I still got -134 at psa_cipher_encrypt_setup. Any guesses what could be wrong?
I get following error when using 2.4.2
error: PSA_WANT_KEY_TYPE_AES (defined at modules/mbedtls/Kconfig.psa:55,
/opt/nordic/ncs/v2.4.2/nrf/modules/trusted-firmware-m/Kconfig.mbedtls_minimal.defconfig:89,
/opt/nordic/ncs/v2.4.2/nrf/modules/trusted-firmware-m/Kconfig.psa.defconfig:11,
modules/mbedtls/Kconfig.psa:55, modules/mbedtls/Kconfig.psa:55) is assigned in a configuration file,
but is not directly user-configurable (has no prompt). It gets its value indirectly from other
symbols. See docs.zephyrproject.org/.../kconfig.html and/or
look up PSA_WANT_KEY_TYPE_AES in the menuconfig/guiconfig interface. The Application Development
Primer, Setting Configuration Values, and Kconfig - Tips and Best Practices sections of the manual
might be helpful too.
I can make it work if I set the following value in ./aes_cbc/boards/nrf52840dk_nrf52840.conf, but I guess that disables the hardware crypto (not something I want).
CONFIG_PSA_CRYPTO_DRIVER_CC3XX=n