Chapter 37: W55MH32’s AES - Implementing AES Hardware Encryption on WIZnet W55MH32
Chapter 37: W55MH32’s AES - Implementing AES Hardware Encryption on WIZnet W55MH32

Implementing AES Hardware Encryption on WIZnet W55MH32
1. Introduction
The WIZnet W55MH32 is a high-performance microcontroller featuring an ARM Cortex-M3 core with integrated hardware cryptographic acceleration. Among the supported cryptographic algorithms, AES (Advanced Encryption Standard) is essential for modern embedded security applications. This application note provides a comprehensive overview of the AES algorithm, how it is supported in hardware on the W55MH32, and its application in secure protocols such as SSL/TLS, as well as other embedded use cases.
2. Overview of AES Algorithm
What is AES?
AES is a symmetric block cipher standardized by NIST in FIPS PUB 197. It encrypts data in 128-bit (16-byte) blocks and supports key lengths of 128, 192, or 256 bits. W55MH32 implements AES-128 (128-bit key) encryption and decryption with hardware acceleration, supporting both ECB (Electronic Codebook) and CBC (Cipher Block Chaining) modes.
AES Block Structure
AES operates on a 4×4 byte matrix called the state. The encryption process consists of multiple rounds, where each round applies the following transformations:
SubBytes -- Byte-wise substitution using an S-box.
ShiftRows -- Cyclically shift rows in the state matrix.
MixColumns -- Matrix multiplication over finite field to diffuse input.
AddRoundKey -- XOR state with the current round key.
For AES-128, 10 rounds are performed. The decryption process applies inverse operations in reverse order.
3. AES Operating Modes Supported in W55MH32
W55MH32's AES hardware engine supports the following standard block cipher modes:
ECB (Electronic Codebook Mode)
Each 128-bit block is encrypted independently.
Simple, fast, and parallelizable.
Limitation: Identical plaintext blocks yield identical ciphertext blocks (pattern leakage).
Usage: Suitable for random or fixed-length records; not ideal for streaming or structured data.
CBC (Cipher Block Chaining Mode)
Each plaintext block is XORed with the previous ciphertext block before encryption.
Requires an Initialization Vector (IV) for the first block.
Advantage: Prevents data pattern leakage; provides better confidentiality.
Usage: Recommended for general-purpose encryption where data patterns must be hidden.
4. AES Operation in W55MH32 Hardware
The AES engine in W55MH32 provides efficient and secure block encryption/decryption using register- or DMA-based data transfer. Below is a typical flow:
AES Encryption/Decryption Procedure:
Initialize AES parameters:
Select AES mode (ECB or CBC).
Configure key (128-bit).
Provide IV (for CBC).
Load input data:
Feed 16-byte plaintext block(s) into the hardware module.
Trigger encryption/decryption:
AES engine processes the data in hardware.
Retrieve result:
Output 16-byte ciphertext or plaintext block.
Hardware Benefits:
Eliminates need for software-based AES libraries.
Reduces CPU load significantly.
Achieves consistent timing and power profile (important for side-channel resistance).
5. Role of AES in SSL/TLS Protocols
AES plays a critical role in SSL/TLS, which secures internet communication (e.g., HTTPS, MQTT over TLS):
During TLS handshake:
Session keys are negotiated using asymmetric cryptography (e.g., RSA, ECDHE).
Once agreed, a symmetric cipher like AES is used for all bulk data encryption.
AES is typically used in:
CBC mode in older TLS versions (TLS 1.0--1.2).
GCM mode (an AEAD variant of CTR + authentication) in TLS 1.2+.
In W55MH32, AES-CBC is especially relevant for:
TLS clients or servers with hardware offload.
Encrypted embedded communication with constrained memory and performance requirements.
Why AES matters for TLS:
Provides fast, secure encryption for large data payloads.
Combines well with MAC (HMAC) for ensuring data integrity.
Is widely adopted and required for modern secure communication standards.
6. Application Scenarios for AES in W55MH32
W55MH32's hardware AES capability can be applied in various embedded and IoT use cases:
Secure Firmware Updates\ Encrypt firmware images before delivery and decrypt on-device to protect against tampering.
TLS/SSL Encrypted Communication\ Offload TLS data encryption using AES-CBC in embedded web servers, MQTT clients, etc.
Local Data Storage Encryption\ Encrypt configuration files, credentials, or sensor logs stored in external flash.
Encrypted Serial or Wireless Communication\ Secure UART, SPI, or RF data channels between devices using AES-CBC streams.
Authentication Tokens / Challenge-Response\ Use AES to generate or verify secure authentication payloads.
7. Progress
For using this hardware AES, it is required to do the following steps.
Step 1: Header files
For activating the AES feature, it is required to include the AES header file from WIZnet's encryption library.
Step 2: AES procedures
In AES procedure, it required to input all variables into the structure for AES and operate AES. It will be the same for EBC and CBC methods but it is required to add an extra IV variables for CBC method.
// Input all variables into the CallDes structure
// pu8In – Input data
callAes.pu8In = au8Plain;
// u32InLen indicates the size of input data (64 bytes)
callAes.u32InLen = AES_TEST_LEN;
// au8Result – Output data
callAes.pu8Out = au8Result;
// u32OutLen indicates the size of output data (64 bytes)
callDes.u32OutLen = DES_TEST_LEN;
// u16Opt is the method selection for encrypting messages using ECB
callAes.u16Opt = WIZ_AES_OPT_BLK_ECB | WIZ_AES_OPT_MODE_ENCRYPT | WIZ_AES_OPT_KEY_128;
// Or you can change it to decrypt messages
callAes.u16Opt = WIZ_AES_OPT_BLK_ECB | WIZ_AES_OPT_MODE_DECRYPT | WIZ_AES_OPT_KEY_128;
// pu8Key is the key used for encrypting or decrypting messages
callAes.pu8Key = au8Key;
// Run hardware AES
WIZDES_EncDec(&callAes);
// Other cases:
// pu8IV is the IV used for encrypting or decrypting messages
callAes.pu8IV = au8Iv;
// u16Opt is the method selection for encrypting messages using CBC
callAes.u16Opt = WIZ_AES_OPT_BLK_CBC | WIZ_AES_OPT_MODE_ENCRYPT | WIZ_AES_OPT_KEY_128;
// Or you can change it to decrypt messages
callAes.u16Opt = WIZ_AES_OPT_BLK_CBC | WIZ_AES_OPT_MODE_DECRYPT | WIZ_AES_OPT_KEY_128;
Step 3: Main Code
In this main code, it contains the method for operating AES in both condition
Main code for ECB
void AES_Func_Test()
{
uint8_t ausPlain[AES_TEST_LEN] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30};
uint8_t ausAESCipher_ECB[AES_TEST_LEN] = {0x31, 0x0E, 0x06, 0x66, 0x72, 0x5B, 0x3B, 0x36, 0x60, 0x14, 0x05, 0x04, 0x52, 0xFA, 0x64, 0x5A,
0x03, 0x62, 0xB6, 0x5C, 0x75, 0x78, 0xCA, 0x5A, 0xAA, 0x9E, 0x5D, 0x70, 0x29, 0x31, 0x2E, 0x43,
0x07, 0x02, 0x0A, 0x0E, 0x75, 0x2A, 0x47, 0x22, 0xB9, 0xF0, 0x2A, 0x06, 0x03, 0x2E, 0xA0, 0x59};
uint8_t ausAESCipher_CBC[AES_TEST_LEN] = {0x65, 0x05, 0x00, 0x0A, 0x0E, 0x15, 0x04, 0x07, 0x0B, 0x55, 0x27, 0x07, 0x0A, 0x02, 0x00, 0x2A,
0x0A, 0x05, 0x07, 0x01, 0x0C, 0x1A, 0x15, 0x01, 0x20, 0x01, 0x27, 0x07, 0x01, 0x12, 0x0D, 0x0E,
0x0E, 0x02, 0x0B, 0x0A, 0x05, 0x2A, 0x01, 0x02, 0x03, 0x04, 0x2A, 0x06, 0x03, 0x2E, 0xA0, 0x59};
uint8_t ausResult[AES_TEST_LEN] = {0};
uint8_t ausPR[AES_TEST_LEN] = {0};
uint8_t ausIV[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
uint8_t ausKey[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
WIZ_SYN_CRYPTO_CAL_t callAes;
printf("The AES data input is :\r\n");
for (i = 0; i < AES_TEST_LEN; i++)
{
printf("%02X", ausPlain[i]);
}
printf("\r\n");
printf("The AES key is :\r\n");
for (i = 0; i < 16; i++)
{
printf("%02X", ausKey[i]);
}
printf("\r\n");
printf("The AES IV is :\r\n");
for (i = 0; i < 16; i++)
{
printf("%02X", ausIV[i]);
}
printf("\r\n");
memset((uint8_t *)&callAes, 0, sizeof(callAes));
//ECB ENC
callAes.pu8In = ausPlain;
callAes.ui32InLen = AES_TEST_LEN;
callAes.pu8Out = ausResult;
callAes.ui32OutLen = AES_TEST_LEN;
callAes.pu8Key = ausKey;
callAes.ui32Key = WIZ_AES_KEY_SIZE_128 | WIZ_AES_OP_MODE_ECB | WIZ_AES_OP_MODE_ENCRYPT;
callAes.ui32Ctrl = WIZC_CalcBuffCrc((uint8_t *)&callAes, sizeof(WIZ_SYN_CRYPTO_CAL_t) - 8);
WIZAES_EncDec(&callAes);
printf("The AES (ECB) encrypted message is :\r\n");
for (i = 0; i < AES_TEST_LEN; i++)
{
printf("%02X", ausResult[i]);
}
printf("\r\n");
//_tprintf((0 == memcmp(ausAESCipher_ECB, ausResult, AES_TEST_LEN)), "wiz_aes_128_ecb_ENC test\r\n");
memset((uint8_t *)&callAes, 0, sizeof(callAes));
//ECB DEC
callAes.pu8In = ausResult;
callAes.ui32InLen = AES_TEST_LEN;
callAes.pu8Out = ausPR;
callAes.ui32OutLen = AES_TEST_LEN;
// 后续代码因截图限制未完全展示,以上为可见部分提取
}
Main code for CBC
memset((uint8_t *)&callAes, 0, sizeof(callAes));
//CBC ENC
callAes.pu8In = ausPlain;
callAes.u32InLen = AES_TEST_LEN;
callAes.pu8Out = ausResult;
callAes.u32OutLen = AES_TEST_LEN;
callAes.pu8IV = ausIV;
callAes.pu8Key = ausKey;
callAes.ulOpt = WIZ_AES_OPT_BLK_CBC | WIZ_AES_OPT_MODE_ENCRYPT | WIZ_AES_OPT_KEY_128;
callAes.u32Crc = WIZCRC_CalcBuff(0xffff, &callAes, sizeof(WIZ_SYN_CRYPTO_CALL) - 4);
WIZAES_EncDec(&callAes);
printf("The AES (CBC) encrypted message is \r\n");
for (i = 0; i < AES_TEST_LEN; i++)
{
printf("%02x", ausResult[i]);
}
printf("\r\n");
//_tprintf((0 == memcmp(ausAESCipher_CBC, ausResult, AES_TEST_LEN)), "wiz_aes_128_cbc ENC test\n");
memset((uint8_t *)&callAes, 0, sizeof(callAes));
//CBC DEC
callAes.pu8In = ausAESCipher_CBC;
callAes.u32InLen = AES_TEST_LEN;
callAes.pu8Out = ausResult;
callAes.u32OutLen = AES_TEST_LEN;
callAes.pu8IV = ausIV;
callAes.pu8Key = ausKey;
callAes.ulOpt = WIZ_AES_OPT_BLK_CBC | WIZ_AES_OPT_MODE_DECRYPT | WIZ_AES_OPT_KEY_128;
callAes.u32Crc = WIZCRC_CalcBuff(0xffff, &callAes, sizeof(WIZ_SYN_CRYPTO_CALL) - 4);
WIZAES_EncDec(&callAes);
printf("The AES (CBC) decrypted message is \r\n");
for (i = 0; i < AES_TEST_LEN; i++)
{
printf("%02x", ausPR[i]);
}
printf("\r\n");
//_tprintf((0 == memcmp(ausPlain, ausResult, AES_TEST_LEN)), "wiz_aes_128_cbc DEC test\n");
void AES_Test()
{
AES_Func_Test();
}
Step 4: Testing Result
After the program has been downloaded to the W55MH32's EVB, it shows the following results.
AES (All in hex value):
Key and AI value:
0102030405060708090a0b0c0d0e0f10
Input message :
0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40
Encrypted Output message (ECB):
34c33b7f14fd53dcea25e01a02e16727d721a0f194231822f398706dd1fff2b70328d32575fa476f38f624d673eaa09ba9050c10ce1904e750597797a172b0f0
Decrypted Output message (ECB):
0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40
Encrypted Output message (CBC):
dbf184112eb9111659712bafcff2ab24f72d2c50445d1d3bebf8b50d323288b4f628d8a653b220e27937bb4149cdd3646778adad93b9811d4fb505b9f424efb9
Decrypted Output message (CBC):
0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40
Python results
from Crypto.Cipher import AES
# Key and IV (both 16 bytes)
key = bytes.fromhex("0102030405060708090a0b0c0d0e0f10")
iv = bytes.fromhex("0102030405060708090a0b0c0d0e0f10")
# Data to encrypt (64 bytes = 4 blocks of 16 bytes)
data = bytes.fromhex(
"0102030405060708090a0b0c0d0e0f10"
"1112131415161718191a1b1c1d1e1f20"
"2122232425262728292a2b2c2d2e2f30"
"3132333435363738393a3b3c3d3e3f40"
)
cipher = AES.new(key, AES.MODE_ECB)
# Encrypt (no padding needed)
ciphertext = cipher.encrypt(data)
# Decrypt
plaintext = cipher.decrypt(ciphertext)
# Output
print("AES ECB Encrypted:", ciphertext.hex())
print("AES ECB Decrypted:", plaintext.hex())
# Encrypt using CBC (no padding)
cipher_enc = AES.new(key, AES.MODE_CBC, iv)
ciphertext = cipher_enc.encrypt(data)
# Decrypt using CBC (no padding)
cipher_dec = AES.new(key, AES.MODE_CBC, iv)
decrypted = cipher_dec.decrypt(ciphertext)
# Output
print("AES CBC Encrypted:", ciphertext.hex())
print("AES CBC Decrypted:", decrypted.hex())
8. Conclusion
The AES hardware encryption engine on the WIZnet W55MH32 enables efficient, secure block cipher operations using AES-128 in ECB and CBC modes. By offloading encryption tasks from the CPU, W55MH32 offers high performance and energy efficiency for security-critical embedded applications. AES is a foundational element of modern cryptographic protocols like TLS/SSL, and is essential for ensuring data for AES-ECB and AES-CBC makes W55MH32 ideal for implementing secure channels, encrypted memory, and authenticated control in IoT and