silk.crypto.aes_ccm.

Encrypt and authenticate data with AES-CCM (NIST SP 800-38C, RFC 3610).

When to use#

Use AesCcm where a protocol names CCM, such as Bluetooth, Zigbee, some TLS 1.2 suites, or Node's aes-128-ccm. For new designs, silk.crypto.aes_gcm is faster and more common.

Details#

The key is 16, 24, or 32 bytes. The nonce is 7 to 13 bytes, and a shorter nonce leaves more room for the message length: a message is at most 2^(8 * (15 - nonce length)) - 1 bytes. The tag is 4, 6, 8, 10, 12, 14, or 16 bytes and is separate from the ciphertext. The associated data (aad) is authenticated but not encrypted. CCM needs the whole message to start, so there is no streaming form. Nothing allocates.

Errors#

The functions return an AesCcmError. All checks come before the first write, and on any error the output buffers do not change. AesCcm.open writes no plaintext unless the tag is correct.

Gotchas#

The same key and nonce must never encrypt two messages. Authentication does not stop replay. The functions do not erase their copies of the key.

Examples#

Encrypt and decrypt#

silk
import silk.crypto.aes_ccm { AesCcm, AesCcmError }
import silk.core.result { Result }

pub fn main() -> i32 {
  let key: [u8; 16] = [3; 16]
  let nonce: [u8; 12] = [9; 12]
  let mut ciphertext: [u8; 5] = [0; 5]
  let mut tag: [u8; 16] = [0; 16]
  if let Result.Failure { error: _ } = AesCcm.seal(&key, &nonce, b"v1", b"hello", &mut ciphertext, &mut tag) {
    return 1
  }
  let mut plaintext: [u8; 5] = [0; 5]
  if let Result.Failure { error: _ } = AesCcm.open(&key, &nonce, b"v1", &ciphertext, &tag, &mut plaintext) {
    return 1
  }
  if plaintext[0] != 104 {
    return 1
  }
  return match AesCcm.open(&key, &nonce, b"v2", &ciphertext, &tag, &mut plaintext) {
    Result<(), AesCcmError>.Failure { error: AesCcmError.AuthenticationFailed } => 0
    _ => 1
  }
}

Import as AesCcm with import silk.crypto.aes_ccm { AesCcm }.

Public declarations: 2.

AesCcmError#

silk
pub enum AesCcmError

The reason that AesCcm.seal or AesCcm.open rejected a call. The checks run in the order of the variants, and the first failure is returned.

InvalidKeyLength#

silk
InvalidKeyLength

The key is not 16, 24, or 32 bytes.

InvalidNonceLength#

silk
InvalidNonceLength

The nonce is not 7 to 13 bytes.

InvalidTagLength#

silk
InvalidTagLength

The tag is not 4, 6, 8, 10, 12, 14, or 16 bytes.

OutputTooSmall#

silk
OutputTooSmall

The output is shorter than the input message.

LimitExceeded#

silk
LimitExceeded

The message is too long for the length field that the nonce length leaves.

AuthenticationFailed#

silk
AuthenticationFailed

The tag is not correct for the key, nonce, associated data, and ciphertext.

Implementation Debug for AesCcmError#

silk
impl Debug for AesCcmError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant, such as InvalidKeyLength.

AesCcm#

silk
pub struct AesCcm

Functions that encrypt and authenticate with AES-CCM (NIST SP 800-38C).

Details#

The key is 16, 24, or 32 bytes, the nonce 7 to 13 bytes, and the tag 4 to 16 bytes in steps of two. The ciphertext has the same length as the plaintext. Nothing allocates. All checks come before the first write.

Gotchas#

The same key and nonce must never encrypt two messages.

Implementation AesCcm#

silk
impl AesCcm

Associated function seal#

silk
pub fn seal(key: &[u8], nonce: &[u8], aad: &[u8], plaintext: &[u8], ciphertext: &mut [u8], tag: &mut [u8]) -> Result<(), AesCcmError>

Encrypts plaintext into ciphertext and writes the tag to tag, whose length picks the tag length.

Errors#

  • InvalidKeyLength if key is not 16, 24, or 32 bytes.

  • InvalidNonceLength if nonce is not 7 to 13 bytes.

  • InvalidTagLength if tag is not 4, 6, 8, 10, 12, 14, or 16 bytes.

  • OutputTooSmall if ciphertext is shorter than plaintext.

  • LimitExceeded if plaintext does not fit the length field.

Associated function open#

silk
pub fn open(key: &[u8], nonce: &[u8], aad: &[u8], ciphertext: &[u8], tag: &[u8], plaintext: &mut [u8]) -> Result<(), AesCcmError>

Checks tag, and if it is correct, decrypts ciphertext into plaintext.

The function checks the tag before it writes plaintext, so it runs the key stream twice.

Errors#

  • InvalidKeyLength if key is not 16, 24, or 32 bytes.

  • InvalidNonceLength if nonce is not 7 to 13 bytes.

  • InvalidTagLength if tag is not 4, 6, 8, 10, 12, 14, or 16 bytes.

  • OutputTooSmall if plaintext is shorter than ciphertext.

  • LimitExceeded if ciphertext does not fit the length field.

  • AuthenticationFailed if the tag is not correct. plaintext does not change.

Category: Cryptography.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.

View the source of this page