Skip to content

crypto::ccm

AES-CCM, from RFC 3610 / NIST SP 800-38C.

The cipher on the wire: CCMP protects every WPA2 data frame with AES-128 in CCM mode — counter mode for confidentiality, CBC-MAC for integrity, both from the one AES block operation. ccmp_encrypt/ccmp_decrypt in the crypto table are this with the 802.11 nonce and additional-data framing on top; that framing is protocol glue and lives with the supplicant, while the transform itself is here and generic.

One primitive, two jobs, and why the order matters on decrypt

Section titled “One primitive, two jobs, and why the order matters on decrypt”

Encryption computes the MIC over the plaintext first, then counter-encrypts plaintext and MIC together. Decryption must therefore counter-decrypt first, then recompute the MIC over the recovered plaintext and compare — and it must not reveal the plaintext if the MIC is wrong, because releasing unauthenticated plaintext is the classic CCM misuse. [decrypt] returns an error and zeroes its output on a MIC mismatch.

Parameters are fixed to what CCMP uses and what the RFC 3610 vectors exercise: a 13-byte nonce (so the length field L is 2) and a caller-chosen MIC length M (8 for CCMP).

enum Error {
Mic,
BadLength,
}

Errors from [decrypt].

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

fn decrypt(key: &[u8; 16], nonce: &[u8], aad: &[u8], ciphertext: &[u8], mic: &[u8], out: &mut [u8]) -> Result<(), Error>

Decrypt ciphertext and verify mic under key/nonce/aad.

Writes the recovered plaintext into out only if the MIC verifies; on failure out is zeroed and [Error::Mic] is returned, so unauthenticated plaintext never reaches the caller.

References: Error

fn encrypt(key: &[u8; 16], nonce: &[u8], aad: &[u8], plaintext: &[u8], mic_len: usize, out: &mut [u8]) -> Result<[u8; 16], Error>

Encrypt plaintext under key/nonce with aad authenticated.

Writes the ciphertext (same length as the plaintext) into out, and returns the mic_len-byte MIC. The 802.11 caller appends the MIC to the frame; keeping it separate here avoids a second length to get wrong.

References: Error