Skip to content

esp32_crypto::sha

The ESP32 SHA accelerator: one-shot SHA-1 and SHA-256 over a byte slice.

The hardware hashes 512-bit blocks and nothing else. It does not pad the message and it does not length-append — those are the caller’s job, and pad_tail does them here, in software, where they can be tested. The block engine only ever sees whole 64-byte blocks.

For each block: wait until not busy, write the 16 words, then pulse START for the first block or CONTINUE for every one after. The hardware keeps the running state in its own registers between blocks; START versus CONTINUE is the only thing that tells it whether to begin from the SHA initial constants or fold into the state already there. After the last block: pulse LOAD, wait idle, then read the digest out of the same text registers.

The message words go in big-endian: esp-idf writes HAL_SWAP32(word) of a little-endian load, which is exactly u32::from_be_bytes of the four message bytes. The digest comes back the same way — each register word is a big-endian slice of the output — so we write it out with to_be_bytes. This is the SHA half of the endianness gotcha in the crate docs, and it is the opposite of AES.

enum ShaKind {
Sha1,
Sha256,
}

Which SHA algorithm. The value is the register-bank offset multiplier the hardware uses (SHA_1_* at +0x80, SHA_256_* at +0x90), so the per-type register addresses fall straight out of it.

Implements: Clone, Copy, Debug, Eq, PartialEq, StructuralPartialEq

unsafe fn sha1(data: &[u8]) -> Result<[u8; 20], crate::CryptoError>

SHA-1 of data.

Takes the SHA accelerator for the duration and gates its clock on and off. Do not call concurrently with another SHA user; the block has one state.

References: CryptoError

unsafe fn sha256(data: &[u8]) -> Result<[u8; 32], crate::CryptoError>

SHA-256 of data.

As [sha1].

References: CryptoError