ESP32 Hardware Encryption: Secure IoT Applications
Introduction
The ESP32 comes with built-in hardware encryption capabilities that set it apart from many other microcontrollers like the ESP8266. These features make the ESP32 an excellent choice for IoT applications where data security is crucial. The hardware acceleration for cryptographic operations ensures that encryption and decryption processes are fast and power-efficient, unlike software-based alternatives.
ESP32 Cryptographic Features
The ESP32 is equipped with a range of hardware security features that make it ideal for building secure IoT devices:
- Hardware AES Acceleration: For fast symmetric encryption
- SHA-2 Acceleration: For secure hashing operations
- RSA Acceleration: For asymmetric cryptography
- RNG (Random Number Generator): True hardware-based random number generation
- Secure Boot: Ensures only trusted code executes on startup
- Flash Encryption: Protects code and data stored in flash memory
AES Encryption
AES (Advanced Encryption Standard) is a symmetric encryption algorithm widely used for securing sensitive data. The ESP32's hardware-accelerated AES implementation supports 128, 192, and 256-bit key lengths, providing robust security while minimizing CPU and power consumption.
mbedtls_aes_context aes; mbedtls_aes_init(&aes); mbedtls_aes_setkey_enc(&aes, key, 128);
Secure Boot
Secure Boot ensures that only authorized firmware can run on your ESP32. When enabled, the bootloader verifies the signature of the firmware before executing it, preventing unauthorized or tampered code from running.
Note: Enabling Secure Boot is a one-time operation. Once enabled, you cannot disable it without replacing the ESP32 chip.
Flash Encryption
Flash Encryption protects the contents of the ESP32's flash memory by encrypting it. This prevents unauthorized access to your firmware, configurations, and sensitive data stored in flash.
Warning: After enabling Flash Encryption, normal UART flashing will no longer work. You'll need to follow specific procedures for updates.
Example 1 - AES-128 Encryption and Decryption
This example demonstrates how to use the ESP32's hardware-accelerated AES encryption to secure data. We'll encrypt a message using AES-128 in ECB mode (for demonstration purposes), then decrypt it to verify the process.
Requirements
You'll need an ESP32 development board and the Arduino IDE with ESP32 support installed. No additional components are required as we're using the ESP32's built-in capabilities.
Code
#include "mbedtls/aes.h"
// AES-128 key (16 bytes)
const unsigned char key[16] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
// Input message to encrypt (must be a multiple of 16 bytes)
unsigned char plaintext[32] = "ESP32 Hardware Encryption Demo!";
// Buffer for encrypted output
unsigned char encrypted[32];
// Buffer for decrypted output
unsigned char decrypted[32];
void setup() {
Serial.begin(115200);
// Wait for serial connection
delay(1000);
Serial.println("ESP32 Hardware Encryption Demo");
Serial.println("------------------------------");
// Display original message
Serial.print("Original message: ");
Serial.println((char*)plaintext);
// Perform encryption
encryptAES(plaintext, encrypted);
// Display encrypted message (as hex)
Serial.print("Encrypted message (hex): ");
for (int i = 0; i < 32; i++) {
Serial.printf("%02X", encrypted[i]);
}
Serial.println();
// Perform decryption
decryptAES(encrypted, decrypted);
// Display decrypted message
Serial.print("Decrypted message: ");
Serial.println((char*)decrypted);
// Benchmark encryption performance
Serial.println("\nPerformance Benchmark");
Serial.println("---------------------");
benchmarkEncryption();
}
void loop() {
// Nothing in loop
}
// Encrypt data using AES-128-ECB
void encryptAES(unsigned char* input, unsigned char* output) {
mbedtls_aes_context aes;
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_enc(&aes, key, 128);
// Process data in 16-byte blocks (AES block size)
for (int i = 0; i < 2; i++) {
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, input + (i * 16), output + (i * 16));
}
mbedtls_aes_free(&aes);
}
// Decrypt data using AES-128-ECB
void decryptAES(unsigned char* input, unsigned char* output) {
mbedtls_aes_context aes;
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_dec(&aes, key, 128);
// Process data in 16-byte blocks (AES block size)
for (int i = 0; i < 2; i++) {
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, input + (i * 16), output + (i * 16));
}
mbedtls_aes_free(&aes);
}
// Benchmark encryption performance
void benchmarkEncryption() {
const int dataSize = 1024; // 1KB of data
unsigned char* testData = (unsigned char*)malloc(dataSize);
unsigned char* encryptedData = (unsigned char*)malloc(dataSize);
// Fill test data
for (int i = 0; i < dataSize; i++) {
testData[i] = i & 0xFF;
}
// Prepare AES context
mbedtls_aes_context aes;
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_enc(&aes, key, 128);
// Start timing
unsigned long startTime = micros();
// Encrypt data (1KB)
for (int i = 0; i < dataSize / 16; i++) {
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, testData + (i * 16), encryptedData + (i * 16));
}
// End timing
unsigned long endTime = micros();
// Calculate performance
float timeMs = (endTime - startTime) / 1000.0;
float throughputKBps = (dataSize / 1024.0) / (timeMs / 1000.0);
Serial.print("Time to encrypt 1KB: ");
Serial.print(timeMs);
Serial.println(" ms");
Serial.print("Encryption throughput: ");
Serial.print(throughputKBps);
Serial.println(" KB/s");
// Free memory
free(testData);
free(encryptedData);
mbedtls_aes_free(&aes);
}
Expected Output
ESP32 Hardware Encryption Demo
------------------------------
Original message: ESP32 Hardware Encryption Demo!
Encrypted message (hex): A6B7D8E2F456A3C7D9E2F4A8B7C9D2E3F1A9B7C8D6E3F4A9B7C5D3E6F4A9B8
Decrypted message: ESP32 Hardware Encryption Demo!
Performance Benchmark
---------------------
Time to encrypt 1KB: 2.56 ms
Encryption throughput: 390.62 KB/s
Note: The actual encryption output and performance metrics will vary based on your specific ESP32 model.
Practical Applications
Secure IoT Communications
Encrypt sensor data before transmission to ensure privacy and prevent unauthorized access to sensitive information.
Firmware Protection
Use Secure Boot and Flash Encryption to prevent unauthorized firmware modifications and protect your intellectual property.
Credential Storage
Securely store WiFi passwords, API keys, and other credentials in encrypted flash memory to prevent unauthorized access.
Access Control Systems
Build secure RFID/NFC access control systems with encrypted communication between tags, readers, and backend systems.