Compute digests using HASH Processor | STM32L4 | HASH | CMSIS

HASH Processor

The HASH Processor in the STM32L4S5xxx microcontroller supports the Secure Hash Algorithm (SHA-1, SHA-224, SHA-256), the MD5 (Message Digest Algorithm 5), and the HMAC (Keyed-Hash Message Authentication Code) algorithm. For a single block of message, the processor requires 66 clock cycles for SHA-2 and MD5, and 82 clock cycles for SHA-1 mode of operation to compute the digests. Read more about the HASH Processor on the STMicroelectronics STM32L5.






HASH Processor Registers

HASH Processor has several registers for Control, Status, Interrupt Configurations and Digest Calculation. The registers that we will be using are:
  1. HASH Control Register (HASH_CR)
  2. HASH Data Input Register (HASH_DIN)
  3. HASH Start Register (HAS_STR)
  4. HASH Digest Register x (HASH_HRx) [x = 0 .. 4]
  5. HASH Supplementary Digest Register x (HASH_HRx) [x = 5 .. 7]
  6. HASH Status Register (HASH_SR)
In addition to these, there are HASH Context Swap Registers that contain the complete internal register states of the hash processor. They are useful when a suspend/resume operation has to be performed because a high-priority task needs to use the hash processor while it is already used by another task.

Configuration of HASH Processor

First, we have to initialize the HASH Processor to our requirements using the HASH_CR register, where we have to choose the Algorithm and the HASH/HMAC mode in addition to other important parameters. From there, we have to input the Message block into the HASH_DIN register in blocks of 4 bytes. When all of the data have been written to the HASH_DIN register, start processing the digest calculation. Wait for the digest calculation to be complete, and then start reading the HASH_HRx registers according to the digest length. For inputting messages to the HASH_DIN register, we can also opt for DMA transfers that will free up the load on the CPU, since the message size would be large.

Walkthrough

Initialization














The HASH Processor is on the AHB2 Bus in the STM32L4S5ZI. To enable the HASH Core, we have to set the HASHEN bit in the RCC_AHB2ENR register. We should wait for the HASHEN bit to be set to verify a clock is supplied to the HASH Core. Moreover, we can disable the clock to the HASH Core to save power when not in use by resetting the HASHEN bit.

Write Data to the HASH Processor































The HASH Processor takes input as 512-bit blocks (64 bytes) for all of the supported algorithms including MD5, SHA1, SHA224 and SHA256. The input message for which we need to calculate the digest may not be 64 bytes long, but we assume it to be a multiple of 64 bytes for ease of operation. We can use block size less than 64 bytes, but then we will have to enable padding to pad the vacant spaces. To write the Message data to the HASH_DIN registers, we will calculate the Input message size by iterating through the message array and then calculating the block size. Then we will feed the input message one block at a time using a nested for loop. After we write 16 words (64 bytes) to the HASH_DIN register, we will wait for the input FIFO to be empty so that we can input the next block. When all blocks are written to the HASH Core, we will return to the function that called the HASH_WriteData() function. 

Read Digest from HASH Processor

The HASH Processor has a maximum of 8 registers to store the computed digests, from HASH_HR0 to HASH_HR7. Each of these registers contains a 32-bit word. For MD5, we will read till HASH_HR3, for SHA1 we read upto HASH_HR4, for SHA224 we read upto HASH_HR6 and for SHA256 we read till HASH_HR7. Based on the number of words, different cases can be executed. Note that, I haven't initialized a character array to store the digests, rather this driver implementation will print the digests directly to the serial terminal. If the user wants to store this HASH digest for later use or for verification, we can store it in an array and write it to an external non-volatile memory.

MD5 Algorithm


The MD5 implementation on the HASH Processor follows the below steps. 
  1. Set MD5 as the Hash Algorithm
  2. Set Operating Mode to HASH Mode
  3. Set the input data type as Byte
  4. Set the Number of Valid Bits in the Last Word
  5. Set the INIT bit in the HASH_CR register to start the Message Calculation
  6. Write Input Data to HASH_DIN register
  7. Set the DCAL bit in the HASH_STR register to start the Digest Calculation
  8. Wait for the DINIS bit to be set in the HASH_SR register
  9. Read the Message digest from the HASH_HRx registers.
MD5 (Message Digest Algorithm 5) is a cryptographic hash function that produces a 128-bit hash value from an input message of any length. It was designed by Ronald Rivest in 1991 as an improvement over earlier hash functions. However, due to vulnerabilities discovered over time, it is no longer considered secure for cryptographic purposes, and its use is discouraged in favor of more secure hash functions.

SHA-1 Algorithm


The SHA-1 implementation on the HASH Processor follows the below steps. 
  1. Set SHA-1 as the Hash Algorithm
  2. Set Operating Mode to HASH Mode
  3. Set the input data type as Byte
  4. Set the Number of Valid Bits in the Last Word
  5. Set the INIT bit in the HASH_CR register to start the Message Calculation
  6. Write Input Data to HASH_DIN register
  7. Set the DCAL bit in the HASH_STR register to start the Digest Calculation
  8. Wait for the DINIS bit to be set in the HASH_SR register
  9. Read the Message digest from the HASH_HRx registers.
SHA-1 (Secure Hash Algorithm 1) is a cryptographic hash function that produces a 160-bit hash value from an input message of any length. It was designed by the National Security Agency (NSA) and published by the National Institute of Standards and Technology (NIST) in 1995. However, SHA-1 is no longer considered secure against well-funded attackers due to vulnerabilities that allow for collision attacks, where two different inputs produce the same hash value.

SHA-224 Algorithm
























The SHA-224 implementation on the HASH Processor follows the below steps. 
  1. Set SHA-224as the Hash Algorithm
  2. Set Operating Mode to HASH Mode
  3. Set the input data type as Byte
  4. Set the Number of Valid Bits in the Last Word
  5. Set the INIT bit in the HASH_CR register to start the Message Calculation
  6. Write Input Data to HASH_DIN register
  7. Set the DCAL bit in the HASH_STR register to start the Digest Calculation
  8. Wait for the DINIS bit to be set in the HASH_SR register
  9. Read the Message digest from the HASH_HRx registers.
SHA-224 is a variant of the SHA-2 family of cryptographic hash functions. It produces a 224-bit hash value from an input message of any length. SHA-224 is derived from SHA-256, which generates a 256-bit hash. SHA-224 is commonly used in applications where a shorter hash length is acceptable. However, like other SHA-2 variants, SHA-224 is vulnerable to brute-force attacks and is recommended to be used in conjunction with other cryptographic measures to enhance security.

SHA-256 Algorithm




The SHA-256 implementation on the HASH Processor follows the below steps. 
  1. Set SHA-256 as the Hash Algorithm
  2. Set Operating Mode to HASH Mode
  3. Set the input data type as Byte
  4. Set the Number of Valid Bits in the Last Word
  5. Set the INIT bit in the HASH_CR register to start the Message Calculation
  6. Write Input Data to HASH_DIN register
  7. Set the DCAL bit in the HASH_STR register to start the Digest Calculation
  8. Wait for the DINIS bit to be set in the HASH_SR register
  9. Read the Message digest from the HASH_HRx registers.
SHA-256 generates a 256-bit hash value from an input message of any length. SHA-256 is widely used in various security applications and protocols, including TLS, SSL, PGP, SSH, and IPsec. SHA-256 is considered secure and is resistant to collision attacks, where two different inputs produce the same hash value. SHA-256 is recommended for most cryptographic purposes where strong security is required.

HMAC using SHA-256






The HMAC implementation on the HASH Processor follows the below steps. 
  1. Set Operating Mode to HMAC Mode
  2. Set the Key size to 64 bytes
  3. Set SHA-256 as the Hashing Algorithm
  4. Set the Number of Valid bits in the Last Word
  5. Set the INIT bit in the HASH_CR register to start the Message Calculation
  6. Write the Key to the HASH_DIN register
  7. Set the DCAL bit in the HASH_STR register
  8. Wait for the DINIS bit to be set in the HASH_SR register
  9. Write the Message to the HASH_DIN register
  10. Set the Number of Valid bits in the Last Word
  11. Set the DCAL bit in the HASH_STR register
  12. Wait for the DINIS bit to be set in the HASH_SR register
  13. Write the Key to the HASH_DIN register
  14. Set the Number of Valid bits in the Last Word
  15. Set the DCAL bit in the HASH_STR register
  16. Read the Message Digest from the HASH_HRx registers
HMAC (Keyed-Hash Message Authentication Code) using SHA-256 is a method of generating a cryptographic hash-based Message Authentication Code (MAC). It combines a secret key with the message to create a hash that can be used to verify the message's authenticity and integrity. The working of HMAC Operation in brief is as follows:
  • Key Selection: Choose a secret key known only to the sender and recipient.
  • Padding: If the key is shorter than the block size of the hash function (64 bytes for SHA-256), it is padded to match the block size. If the key is longer, it is hashed to produce a shorter key.
  • Inner Padding: The key is XORed with a specific value (0x36) to create the inner padding.
  • Inner Hash: The inner padding is appended to the message, and the SHA-256 hash is calculated on the result.
  • Outer Padding: The key is XORed with a different value (0x5C) to create the outer padding.
  • Final Hash: The outer padding is appended to the inner hash result, and the SHA-256 hash is calculated on the concatenated result.
The resulting hash is the HMAC using SHA-256, which can be sent along with the message. The recipient can use the same key and HMAC generation process to verify the authenticity and integrity of the message by recalculating the HMAC and comparing it to the received HMAC. If the two HMACs match, the message is considered authentic.

Popular posts from this blog

SignGlove: Bridging the Communication Gap for Paralyzed Patients

Cifradopro: A baremetal Hardware Security Module using the STM32L4S5 Cortex-M4 MCU

AESecureIO: Embedded Data Encryption and Decryption System