Crates.io | aes-ccm |
lib.rs | aes-ccm |
version | 0.5.0 |
source | src |
created_at | 2019-08-19 11:31:59.559668 |
updated_at | 2020-06-13 14:29:16.605521 |
description | A pure-Rust, #![no_std], zero-allocation AES-CCM implementation ported from TinyCrypt using RustCrypto's AES. |
homepage | |
repository | https://github.com/martindisch/aes-ccm |
max_upload_size | |
id | 158074 |
size | 75,159 |
A pure-Rust, #![no_std]
, zero-allocation AES-CCM implementation ported
from TinyCrypt using RustCrypto's AES (with support for optionally
swapping in hardware-backed implementations).
It implements the aead::AeadInPlace
trait, so it can be used
effortlessly together with other implementations.
CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of operation defined in SP 800-38C.
This implementation accepts:
The implementation accepts payloads of any length between 0 and 2^16 bytes and associated data of any length between 0 and (2^16 - 2^8) bytes.
use aes_ccm::{
aead::{consts::U8, Aead, NewAead, Payload},
Aes128Ccm,
};
let key = [
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
];
// `U8` represents the tag size as a `typenum` unsigned (8-bytes here)
let ccm = Aes128Ccm::<U8>::new(&key.into());
let nonce = [
0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, 0xA1, 0xA2, 0xA3,
0xA4, 0xA5,
];
let msg = [
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
0x1E,
];
let associated_data = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
let ciphertext = ccm
.encrypt(
&nonce.into(),
Payload {
aad: &associated_data,
msg: &msg,
},
)
.unwrap();
let plaintext = ccm
.decrypt(
&nonce.into(),
Payload {
aad: &associated_data,
msg: &ciphertext,
},
)
.unwrap();
assert_eq!(&msg[..], plaintext.as_slice());
alloc
requirement)This crate has an optional alloc
feature which can be disabled in e.g.
microcontroller environments that don't have a heap.
The AeadInPlace::encrypt_in_place
and AeadInPlace::decrypt_in_place
methods accept any type that impls the aead::Buffer
trait which
contains the plaintext for encryption or ciphertext for decryption.
Note that if you enable the heapless
feature of this crate,
you will receive an impl of aead::Buffer
for heapless::Vec
(re-exported from the aead
crate as aead::heapless::Vec
),
which can then be passed as the buffer
parameter to the in-place encrypt
and decrypt methods:
use aes_ccm::{
aead::{
consts::{U128, U8},
heapless::Vec,
AeadInPlace, NewAead,
},
Aes128Ccm,
};
let key = [
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
];
// `U8` represents the tag size as a `typenum` unsigned (8-bytes here)
let ccm = Aes128Ccm::<U8>::new(&key.into());
let nonce = [
0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, 0xA1, 0xA2, 0xA3,
0xA4, 0xA5,
];
let associated_data = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
let plaintext = [
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
0x1E,
];
let mut buffer: Vec<u8, U128> = Vec::new();
buffer.extend_from_slice(&plaintext).unwrap();
// Encrypt `buffer` in-place, replacing the plaintext contents with
// ciphertext
ccm.encrypt_in_place(&nonce.into(), &associated_data, &mut buffer)
.unwrap();
// `buffer` now contains the message ciphertext
assert_ne!(&buffer, &plaintext);
// Decrypt `buffer` in-place, replacing its ciphertext contents with the
// original plaintext
ccm.decrypt_in_place(&nonce.into(), &associated_data, &mut buffer)
.unwrap();
assert_eq!(&buffer, &plaintext);
I'm not a cryptographer and this hasn't been audited in any way. It is however a careful port of TinyCrypt, so if it's sound, then this should be too.
The MAC length parameter is an important parameter to estimate the security against collision attacks (that aim at finding different messages that produce the same authentication tag). The implementation accepts any even integer between 4 and 16, as suggested in SP 800-38C.
RFC 3610, which also specifies CCM, presents a few relevant security suggestions, such as:
Licensed under either of
at your option.
This is a port of TinyCrypt's CCM mode, its license file is in LICENSE-3RD-PARTY.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.