Wiznet makers

ronpang

Published September 22, 2025 © Apache License 2.0 (Apache-2.0)

137 UCC

80 WCC

32 VAR

0 Contests

1 Followers

0 Following

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

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

COMPONENTS
PROJECT DESCRIPTION

W55MH32 Application Note:

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.

#include "wiz_aes.h"

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 confidentiality in both communication and storage. The built-in support for AES-ECB and AES-CBC makes W55MH32 ideal for implementing secure channels, encrypted memory, and authenticated control in IoT and industrial systems.

Documents
Comments Write