Skip to content

crypto::hmac

HMAC, from RFC 2104, over the hashes in this crate.

Every authenticated step of the handshake is an HMAC: the key confirmation in the 4-way exchange, the key derivation (PBKDF2 and the PRF are both HMAC in a loop), and the message integrity check. It is written once, generic over a [Hash], so HMAC-SHA1 and HMAC-SHA256 are the same code with a different digest — there is no second place for the block-size or the ipad/opad constants to drift.

The key is secret; the shape must not depend on it

Section titled “The key is secret; the shape must not depend on it”

HMAC’s only data-dependent step is hashing the key when it is longer than a block, and that path runs the hash, which is itself data-independent. The pad construction and the two hash passes are fixed regardless of key or message content, so there is no secret-dependent branch here.

trait Hash: Clone {
fn new() -> Self
fn update(&mut self, data: &[u8])
fn finish_into(self, out: &mut [u8])
}

A hash this crate can drive as an HMAC core.

The three things HMAC needs of a hash: its block size (for the pads), its digest size, and the ability to hash a stream. Implemented for Sha1 and Sha256 below.

fn hmac<H>(key: &[u8], data: &[u8], out: &mut [u8])

Compute HMAC-H of data under key into out.

out is filled to H::OUTPUT bytes; a shorter out takes a truncated tag, which is what CMAC and some KDF steps want and is done by the caller slicing, not here.

fn hmac_sha1(key: &[u8], data: &[u8]) -> [u8; 20]

HMAC-SHA1 of data under key. Twenty-byte tag.

fn hmac_sha256(key: &[u8], data: &[u8]) -> [u8; 32]

HMAC-SHA256 of data under key. Thirty-two-byte tag.