diff --git a/src/aead.rs b/src/aead.rs
index 40f85e9e4f..4c3eb429c3 100644
--- a/src/aead.rs
+++ b/src/aead.rs
@@ -29,6 +29,7 @@ use core::{
pub use self::{
aes_gcm::{AES_128_GCM, AES_256_GCM},
+ aes_ccm::AES_128_CCM,
chacha20_poly1305::CHACHA20_POLY1305,
less_safe_key::LessSafeKey,
nonce::{Nonce, NONCE_LEN},
@@ -122,6 +123,7 @@ impl Eq for Aad where A: Eq {}
#[allow(clippy::large_enum_variant, variant_size_differences)]
#[derive(Clone)]
enum KeyInner {
+ AesCcm(aes::Key),
AesGcm(aes_gcm::Key),
ChaCha20Poly1305(chacha20_poly1305::Key),
}
@@ -190,6 +192,7 @@ enum AlgorithmID {
AES_128_GCM,
AES_256_GCM,
CHACHA20_POLY1305,
+ AES_128_CCM,
}
impl PartialEq for Algorithm {
@@ -242,6 +245,7 @@ mod block;
mod chacha;
mod chacha20_poly1305;
pub mod chacha20_poly1305_openssh;
+mod aes_ccm;
mod gcm;
mod less_safe_key;
mod nonce;
diff --git a/src/aead/aes_ccm.rs b/src/aead/aes_ccm.rs
new file mode 100644
index 0000000000..cec22f49c4
--- /dev/null
+++ b/src/aead/aes_ccm.rs
@@ -0,0 +1,378 @@
+// Copyright 2016 Brian Smith.
+// Portions Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+use crate::aead::aes::Variant;
+use crate::aead::block::{Block, BLOCK_LEN};
+use crate::aead::{Aad, KeyInner, Nonce, Tag};
+use core::ops::{Range, RangeFrom};
+use core::slice::ChunksExact;
+
+const KEY_LEN: usize = 16;
+
+/// AES-128 in CCM mode as described in [RFC 5116](https://datatracker.ietf.org/doc/html/rfc5116#section-5.3).
+///
+/// Generic CCM is described in both:
+/// - [RFC 3610](https://datatracker.ietf.org/doc/html/rfc3610)
+/// - [NIST 800-38c](https://csrc.nist.gov/publications/detail/sp/800-38c/final)
+///
+/// The variant here uses the following fixed parameters:
+/// - M == 16 - number of octets in the authentication tag
+/// - L == 3 - number of octets in the length field
+///
+/// This implies that the nonce length is 15 - 3 == 12
+///
+/// Note: CCM with these parameters is used in TLS 1.2 and 1.3
+pub static AES_128_CCM: crate::aead::Algorithm = crate::aead::Algorithm {
+ key_len: KEY_LEN,
+ init: aes_128_ccm_init,
+ seal: aes_128_ccm_seal,
+ open: aes_128_ccm_open,
+ id: crate::aead::AlgorithmID::AES_128_CCM,
+ max_input_len: MAX_MESSAGE_LENGTH_PER_NONCE,
+};
+
+fn aes_128_ccm_init(
+ key: &[u8],
+ cpu_features: crate::cpu::Features,
+) -> Result {
+ crate::aead::aes::Key::new(key, Variant::AES_128, cpu_features).map(|k| KeyInner::AesCcm(k))
+}
+
+fn aes_128_ccm_seal(key: &KeyInner, nonce: Nonce, aad: Aad<&[u8]>, in_out: &mut [u8]) -> Tag {
+ let key = match key {
+ KeyInner::AesCcm(x) => x,
+ _ => unreachable!(),
+ };
+
+ let tag = calc_auth_tag(key.clone(), &nonce, aad, in_out);
+
+ let mut stream = BlockStream::new(key.clone(), &nonce);
+
+ let tag = tag ^ stream.next_block();
+
+ stream.apply(in_out, 0..);
+
+ Tag::from(tag.as_ref().clone())
+}
+
+fn aes_128_ccm_open(
+ key: &KeyInner,
+ nonce: Nonce,
+ aad: Aad<&[u8]>,
+ in_out: &mut [u8],
+ src: RangeFrom,
+) -> Tag {
+ // length of the ciphertext (and plaintext)
+ let ct_len = in_out.len() - src.start;
+
+ let key = match key {
+ KeyInner::AesCcm(x) => x,
+ _ => unreachable!(),
+ };
+
+ let mut stream = BlockStream::new(key.clone(), &nonce);
+
+ // save this for after we calculate the tag
+ let tag_block = stream.next_block();
+
+ stream.apply(in_out, src);
+
+ // calculate the tag over the plaintext
+ let tag = calc_auth_tag(key.clone(), &nonce, aad, &in_out[..ct_len]) ^ tag_block;
+
+ Tag::from(tag.as_ref().clone())
+}
+
+/// This limit is set by a 3-byte length encoding when calculating the
+/// authentication tag.
+///
+/// 2^24 - 1
+const MAX_MESSAGE_LENGTH_PER_NONCE: u64 = 16777215;
+
+/// The auth flags
+///
+/// M' = (16-2) / 2 = 7
+/// L' = 3 - 1 = 2
+const AUTH_FLAGS_NO_DATA: u8 = (7 << 3) | 2;
+const AUTH_FLAGS_WITH_DATA: u8 = AUTH_FLAGS_NO_DATA | (1 << 6);
+
+struct AesCbcMac {
+ state: Block,
+ key: crate::aead::aes::Key,
+}
+
+impl AesCbcMac {
+ fn new(key: crate::aead::aes::Key) -> Self {
+ Self {
+ state: Block::zero(),
+ key,
+ }
+ }
+
+ fn update(&mut self, block: Block) {
+ self.state ^= block;
+ self.state = self.key.encrypt_block(self.state);
+ }
+
+ /// consume the MAC and transform into a Tag
+ fn finalize(self) -> Block {
+ self.state
+ }
+}
+
+struct Ranges {
+ pos: usize,
+ end: usize,
+ chunk_size: usize,
+}
+
+impl Iterator for Ranges {
+ type Item = Range;
+
+ fn next(&mut self) -> Option {
+ let rem = self.end.checked_sub(self.pos)?;
+ if rem == 0 {
+ return None;
+ }
+
+ let chunk_len = rem.min(self.chunk_size);
+ let ret = self.pos..self.pos + chunk_len;
+ self.pos += chunk_len;
+ Some(ret)
+ }
+}
+
+fn ranges(
+ start: usize,
+ end: usize,
+ chunk_size: usize,
+) -> impl Iterator- , Range)> {
+ let ranges = Ranges {
+ pos: start,
+ end,
+ chunk_size,
+ };
+
+ ranges.map(move |x| (x.clone(), x.start - start..x.end - start))
+}
+
+/// block stream for encryption
+struct BlockStream {
+ counter: u32,
+ key: crate::aead::aes::Key,
+ state: [u8; BLOCK_LEN],
+}
+
+impl BlockStream {
+ fn new(key: crate::aead::aes::Key, nonce: &Nonce) -> Self {
+ let mut state = [0; BLOCK_LEN];
+
+ state[0] = 2; // Flags = L' = L - 1
+ state[1..13].copy_from_slice(nonce.as_ref());
+
+ // the counter gets portion is written each time `next` is called
+
+ Self {
+ counter: 0,
+ key,
+ state,
+ }
+ }
+
+ /// `src` has the same meaning as elsewhere in the aead module, namely
+ /// it allows us to perform a shift when we decrypt to the front of `in_out`.
+ fn apply(&mut self, in_out: &mut [u8], src: RangeFrom) {
+ for (src, dest) in ranges(src.start, in_out.len(), BLOCK_LEN) {
+ let mut block: [u8; BLOCK_LEN] = [0; BLOCK_LEN];
+ block[..src.len()].copy_from_slice(&in_out[src.clone()]);
+ let encrypted = Block::from(&block) ^ self.next_block();
+ in_out[dest].copy_from_slice(&encrypted.as_ref()[..src.len()]);
+ }
+ }
+
+ fn next_block(&mut self) -> Block {
+ let ctr = self.next_counter();
+ self.state[13..].copy_from_slice(&ctr);
+ self.key.encrypt_block(Block::from(&self.state))
+ }
+
+ fn next_counter(&mut self) -> [u8; 3] {
+ assert!(self.counter < 16777216); // counter must be < 2^24
+ let bytes = self.counter.to_le_bytes();
+ self.counter += 1;
+ [bytes[2], bytes[1], bytes[0]]
+ }
+}
+
+const fn auth_flags(a_data: &Aad<&[u8]>) -> u8 {
+ if a_data.0.is_empty() {
+ AUTH_FLAGS_NO_DATA
+ } else {
+ AUTH_FLAGS_WITH_DATA
+ }
+}
+
+// this looks dangerous but there is a guard in the generic AEAD code that
+// validates that the length is always less than the algorithm per-nonce maximum
+fn get_length_be(input: &[u8]) -> [u8; 3] {
+ // Just in case the ring code that guards this gets changed
+ assert!(crate::polyfill::u64_from_usize(input.len()) <= MAX_MESSAGE_LENGTH_PER_NONCE);
+ // it's simpler to do little endian and then swap the order
+ let bytes = input.len().to_le_bytes();
+ [bytes[2], bytes[1], bytes[0]]
+}
+
+fn calc_block_0(nonce: &Nonce, aad: Aad<&[u8]>, input: &[u8]) -> Block {
+ let mut block: [u8; BLOCK_LEN] = [0; BLOCK_LEN];
+ block[0] = auth_flags(&aad);
+ // bytes 1 -> 12
+ block[1..13].copy_from_slice(nonce.as_ref());
+ // bytes 13 -> 15 are the big endian length
+ block[13..].copy_from_slice(get_length_be(input).as_slice());
+ Block::from(&block)
+}
+
+struct PaddedBlocks<'a> {
+ chunks: ChunksExact<'a, u8>,
+ remainder: Option<&'a [u8]>,
+}
+
+impl<'a> PaddedBlocks<'a> {
+ fn new(input: &'a [u8]) -> Self {
+ let exact = input.chunks_exact(BLOCK_LEN);
+ let remainder = if exact.remainder().is_empty() {
+ None
+ } else {
+ Some(exact.remainder())
+ };
+ Self {
+ chunks: exact,
+ remainder,
+ }
+ }
+}
+
+impl<'a> Iterator for PaddedBlocks<'a> {
+ type Item = Block;
+
+ fn next(&mut self) -> Option {
+ match self.chunks.next() {
+ None => match self.remainder.take() {
+ None => None,
+ Some(x) => {
+ let mut block: [u8; BLOCK_LEN] = [0; BLOCK_LEN];
+ block[0..x.len()].copy_from_slice(x);
+ Some(Block::from(&block))
+ }
+ },
+ Some(x) => {
+ let mut block: [u8; BLOCK_LEN] = [0; BLOCK_LEN];
+ block.copy_from_slice(x);
+ Some(Block::from(&block))
+ }
+ }
+ }
+}
+
+/// If aad is non-empty, return an iterator over the AD blocks
+fn prepare_aad_blocks(aad: Aad<&[u8]>) -> Option + '_> {
+ if aad.0.is_empty() {
+ return None;
+ }
+
+ let mut block: [u8; BLOCK_LEN] = [0; BLOCK_LEN];
+
+ let be_bytes: [u8; 8] = crate::polyfill::u64_from_usize(aad.0.len()).to_be_bytes();
+
+ // copy the length representation into the block and get the
+ // number of bytes in the representation
+ let num_length_bytes: usize = if aad.0.len() < 65280 {
+ // < 2^16 - 2^8
+ block[0..2].copy_from_slice(&be_bytes[6..]);
+ 2
+ } else if aad.0.len() < 4294967296 {
+ // < 2^32
+ block[0] = 0xFF;
+ block[1] = 0xFE;
+ block[2..6].copy_from_slice(&be_bytes[4..]);
+ 6
+ } else {
+ // otherwise it's the < 2^64 case
+ block[0] = 0xFF;
+ block[1] = 0xFF;
+ block[2..10].copy_from_slice(&be_bytes);
+ 10
+ };
+
+ // how much space do we have left in B0?
+ let block_unused_bytes = BLOCK_LEN - num_length_bytes;
+
+ // put as much as we can of the AD in B0
+ let aad_b0_len = aad.0.len().min(block_unused_bytes);
+ let (b0_ad_bytes, remainder) = aad.0.split_at(aad_b0_len);
+ block[num_length_bytes..num_length_bytes + aad_b0_len].copy_from_slice(b0_ad_bytes);
+
+ Some(core::iter::once(Block::from(&block)).chain(PaddedBlocks::new(remainder)))
+}
+
+fn calc_auth_tag(
+ key: crate::aead::aes::Key,
+ nonce: &Nonce,
+ aad: Aad<&[u8]>,
+ input: &[u8],
+) -> Block {
+ let mut mac = AesCbcMac::new(key);
+
+ // setup and mac the first block
+ mac.update(calc_block_0(nonce, aad, input));
+
+ // optional AAD blocks
+ if let Some(blocks) = prepare_aad_blocks(aad) {
+ for b in blocks {
+ mac.update(b);
+ }
+ }
+
+ // input blocks
+ for b in PaddedBlocks::new(input) {
+ mac.update(b);
+ }
+
+ mac.finalize()
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::aead::aes_ccm::ranges;
+
+ #[test]
+ fn range_iterator_full_chunks() {
+ let mut ranges = ranges(0, 6, 3);
+
+ assert_eq!(ranges.next(), Some((0..3, 0..3)));
+ assert_eq!(ranges.next(), Some((3..6, 3..6)));
+ assert_eq!(ranges.next(), None);
+ }
+
+ #[test]
+ fn range_iterator_partial_chunk() {
+ let mut ranges = ranges(2, 10, 3);
+
+ assert_eq!(ranges.next(), Some((2..5, 0..3)));
+ assert_eq!(ranges.next(), Some((5..8, 3..6)));
+ assert_eq!(ranges.next(), Some((8..10, 6..8)));
+ assert_eq!(ranges.next(), None);
+ }
+}
diff --git a/tests/aead_aes_128_ccm_tests.txt b/tests/aead_aes_128_ccm_tests.txt
new file mode 100644
index 0000000000..a4f24485ae
--- /dev/null
+++ b/tests/aead_aes_128_ccm_tests.txt
@@ -0,0 +1,854 @@
+# The relevant RFCs lack test vectors for the parameters M=16, L=3
+#
+# These test vectors were generated using RustCrypto-CCM:
+#
+# https://crates.io/crates/ccm
+#
+# This implementation is generic on M/L. It is tested using all the test vectors in the
+# RFCs + additional test vectors from NIST CAVP:
+#
+# https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program
+#
+#
+# The test vectors are all permutations of input parameters with lengths
+# at block boundary lengths.
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = ""
+AD = ""
+CT = ""
+TAG = b9f650fb3c39bb1bee0e291d33f6ae28
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = a2
+AD = ""
+CT = cc
+TAG = 67dfce21b3f146c22c29a30a15aac61e
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = 31882527cf24dde863b428b652c05c
+AD = ""
+CT = 5f4f7a952d905aae7d69e30ec5d1ce
+TAG = d3deecdf388bf40a2f16ce2ddcdb86b8
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = 2fc5f21ade22af6d758f2f1b891e59f7
+AD = ""
+CT = 4102ada83c96282b6b52e4a31e0fcb4d
+TAG = 70b06cca175fbd738dcf7d991cbdc6ad
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = e27511b7b7cf2b89ff23da9f8918a4ef8b
+AD = ""
+CT = 8cb24e05557baccfe1fe11271e093655b8
+TAG = 130ffcb842d1d552120cda1fc9ade31c
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = ""
+AD = 98
+CT = ""
+TAG = 5fe85a2fceb74859ae606b8ba3d0fd3c
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = b3
+AD = 8c
+CT = dd
+TAG = c7062a12da26238c046b2acb5eafeb36
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = de3b45c35d00d0accf31ad47e75dc6
+AD = dd
+CT = b0fc1a71bfb457ead1ec66ff704c54
+TAG = 39ac210ebbbf5a290a258ec5774790aa
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = c840e881d83eb90c3676bd6d5cbf0f3d
+AD = 04
+CT = a687b7333a8a3e4a28ab76d5cbae9d87
+TAG = 00f31ef743e0cdc5a5ab461fc02c151b
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = c33155f0744cc9a96d5021f4073a9c6bb5
+AD = 0c
+CT = adf60a4296f84eef738dea4c902b0ed186
+TAG = a9ce1e5d900ccf5df5ff467d0fe8d909
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = ""
+AD = 9f9d8538b97f3e80e35f19e8bd75
+CT = ""
+TAG = 255f1d11382c120dafa42bec4079a811
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = ce
+AD = 69c395f4bdc952722754cd74c343
+CT = a0
+TAG = 811ab8675153403117455b9750c45b45
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = f3fd48d97bd685ae52732dd01966ff
+AD = a6252ed03d7dd35da95c83843b1c
+CT = 9d3a176b996202e84caee6688e776d
+TAG = 9ef26a7c13701799c6c9c8a9f4ed6739
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = a022f257665d1058105c6a2d74a7e537
+AD = 46695bd72f926a0d31559b839aa3
+CT = cee5ade584e9971e0e81a195e3b6778d
+TAG = b209fec735c17471a87b83d41d76a9d5
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = 1d2be0ad815455a6aa63af30ca22fb9407
+AD = c9d719ca51effa1928736e6e9f1f
+CT = 73ecbf1f63e0d2e0b4be64885d33692e34
+TAG = a5177dfacdf6e9645f841c272b232864
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = ""
+AD = 57a9443cb2fbab0fa7fbee47e3f72f
+CT = ""
+TAG = d946def63637abb7b339d91354eb7365
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = 97
+AD = 566e5b1d0eccab2a163b90cb368933
+CT = f9
+TAG = 3b70aa8c2664fcea9d09f62dea213596
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = 080f208a3f213242be557db9cce5fb
+AD = 776b77ff5a4dcea62a555c049171ce
+CT = 66c87f38dd95b504a088b6015bf469
+TAG = b2e64c6eb091bef0a1280dd4aceffb6b
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = 74aaed4004bef4a2decca8e7d76aa5c2
+AD = a95291577acd2a9c0d7c89da96d1c2
+CT = 1a6db2f2e60a73e4c011635f407b3778
+TAG = e68e5b2799bcda1cb8bec5e060ed7586
+
+KEY = 00000000000000000000000000000000
+NONCE = 000000000000000000000000
+IN = 51e6cdb150a3aba037115b55d077ff909d
+AD = 05c9afffadb546d28cf59e8b154d95
+CT = 3f219203b2172ce629cc90ed47666d2aae
+TAG = 2ae890239461785075d8b96016957961
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = ""
+AD = ""
+CT = ""
+TAG = e7f6640100be94294f4cf469689e9c65
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 2b
+AD = ""
+CT = ee
+TAG = a15f6a908e231f9e56ab5f864d8a1498
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = f5d9ba0a3559f0a19ab24e802e162d
+AD = ""
+CT = 3015c588ce02066181800566a3136e
+TAG = c5e831f4410cd48dd8220cfe2c401bb2
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = dd3b252682969abc45a75430cad6fc2d
+AD = ""
+CT = 18f75aa479cd6c7c5e951fd647d3bf8a
+TAG = 2b47832121cdc58126e38ffe5714c924
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 9e34a3f4896d3cee0905e25b445702372e
+AD = ""
+CT = 5bf8dc767236ca2e1237a9bdc952419029
+TAG = 6904fb19258c0a00968a39229a694bda
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = ""
+AD = 68
+CT = ""
+TAG = 3bac691451c476887189b553dc64e0f8
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = c1
+AD = bf
+CT = 04
+TAG = 6d34f4553d94b0047a74a3f2b9e4d0cd
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 65745d2f10f45a13852c1c26120898
+AD = c4
+CT = a0b822adebafacd39e1e57c09f0ddb
+TAG = 7c9ef132fb6e42844ddb6ce349408de7
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = c487b6c74ee2dd639aebb3542384898c
+AD = c7
+CT = 014bc945b5b92ba381d9f8b2ae81ca2b
+TAG = a8a172650cc5a8e9e87633685772427b
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 0aa1aefb127ff46eb8d18d70b2b2fb3c5f
+AD = 72
+CT = cf6dd179e92402aea3e3c6963fb7b89b58
+TAG = 2cecb9e6cff4d45fe1a061b0bd39f0d7
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = ""
+AD = f839385dde1a31861de8c8ab4d4d
+CT = ""
+TAG = 07eabe67861f902fc61bd7bf18df4538
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 37
+AD = 03d547955c8b3fd105af5877903e
+CT = f2
+TAG = dbf26c5ea895db0294d75f258d232e3d
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = e469e9cba4e925e5c2429bf358f8ea
+AD = e232e5d1f509486d836ed9ad171e
+CT = 21a596495fb2d325d970d015d5fda9
+TAG = 4e3a82278dc49f7cf0b88ccb8d5abf84
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 47c4f3c983b5358f4012f1cac3c19179
+AD = 3814025139f97dbd9c7c73217533
+CT = 82088c4b78eec34f5b20ba2c4ec4d2de
+TAG = e18e2d4d67a8d45b9016dc89c842225e
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = d0600f696ed84083159caf2ea9b4e47b7a
+AD = b2e26ed7e4fbd413f1ba1baeaf59
+CT = 15ac70eb9583b6430eaee4c824b1a7dc7d
+TAG = eeb78bb4f1397b0e9455d217984b1138
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = ""
+AD = cd85e763f886add95162c469438675
+CT = ""
+TAG = c5e5b6ffd90be92f816137f0347bcfbf
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 49
+AD = e6557c9c2ba537ecfc3ee154fb525b
+CT = 8c
+TAG = e0272021a49a4209365ef9336dc59d26
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 32c0ace1887bb3dabdfcd289c6acd6
+AD = 661a6d280230d459680fd5b6368eaa
+CT = f70cd3637320451aa6ce996f4ba995
+TAG = bb1b8a896da04dee531117e05a60ccd8
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 7b5718436020cf629568c52b239c223f
+AD = ebb6310214eeca68e57f57f4b0a3f9
+CT = be9b67c19b7b39a28e5a8ecdae996198
+TAG = b4c2a5acb491990be53d9401278820d4
+
+KEY = 00000000000000000000000000000000
+NONCE = ffffffffffffffffffffffff
+IN = 866a4cd976d7c5859ad6e9bcebc1d46752
+AD = 64fd51d21b1d9067846c85433a3943
+CT = 43a6335b8d8c334581e4a25a66c497c055
+TAG = 81df2190ea113dbe146bff7b60f8e15e
+
+KEY = 00000000000000000000000000000000
+NONCE = bef5695b0a36abce6a569dc0
+IN = ""
+AD = ""
+CT = ""
+TAG = 473455e2c0f40e7aa0daca6d0255aa5f
+
+KEY = 00000000000000000000000000000000
+NONCE = 190016ffe21ca987059fb86d
+IN = 4f
+AD = ""
+CT = a9
+TAG = 4d05c003cc7d7bb25fe0463ad3dbb8fb
+
+KEY = 00000000000000000000000000000000
+NONCE = 9cf52ba71372715c16b22a6f
+IN = 671b4158875e5c688bdbdaf5c03c60
+AD = ""
+CT = 3c498045a8f3117b26da912048aad3
+TAG = 678bb5db3f8f6b0ea5a0363e04e282a9
+
+KEY = 00000000000000000000000000000000
+NONCE = 17ece976e386677f7de80753
+IN = 174cf517a2ce9a2ec9e6ece7d4bd6868
+AD = ""
+CT = 27b920d343b1e019020a5474d09eb1db
+TAG = 6d2834806a2281bd669fb23d758305a3
+
+KEY = 00000000000000000000000000000000
+NONCE = 87cb09cc1b42b71901ce59d7
+IN = d5a816127ff200667a4e0e48dc1dde77e4
+AD = ""
+CT = 29796fc6a3cfee1db9bff67f118bf1b9f8
+TAG = 20d8450e7e0d0abf13a338d0bcde54e3
+
+KEY = 00000000000000000000000000000000
+NONCE = 76d132c3dd40ae5ebdbe6b86
+IN = ""
+AD = 0f
+CT = ""
+TAG = a01478ac04001c6888f940dee1b955cb
+
+KEY = 00000000000000000000000000000000
+NONCE = ca15ac431d77574f265042d6
+IN = 65
+AD = 7b
+CT = 05
+TAG = 5b187c2f03ba5362ef70de7ef3e13cee
+
+KEY = 00000000000000000000000000000000
+NONCE = 1971cf1b03d948d52948dab0
+IN = 6bb5a984e0a2885c4a61ee5ef10934
+AD = 03
+CT = 1240128738320a72c6949f0c741901
+TAG = 8ae5eddd454a8745aa69587901e8fb72
+
+KEY = 00000000000000000000000000000000
+NONCE = 350f8d5b762a95b1e7298b57
+IN = a0050c8148eaf21ee21b85a7bf193275
+AD = 28
+CT = 4db2aba6ecbe9c85f75dabae55b627fc
+TAG = a07049dacf7ea32c4f0461cd0d573a01
+
+KEY = 00000000000000000000000000000000
+NONCE = 38717ddf4d6959c0c14b81d9
+IN = 23e714908cc024ea5d0199c141eca2ef84
+AD = 7a
+CT = 90fb31bbe76e51cd58daab3dbe95378718
+TAG = 56604f2101a362afd5e8e27c7d1386fa
+
+KEY = 00000000000000000000000000000000
+NONCE = 32c5f9d129771b48af856759
+IN = ""
+AD = b8e63dc49b7981eefa0bdd8660c1
+CT = ""
+TAG = 0950b4f57f7c4418e53094f6b4badd40
+
+KEY = 00000000000000000000000000000000
+NONCE = 8ac02b8773878c3ad9a9fd69
+IN = 3e
+AD = 208155089508fb1a59e262d1d234
+CT = 73
+TAG = e8e97b9961a637d450ebba2e6c12adef
+
+KEY = 00000000000000000000000000000000
+NONCE = 0f3f918f59844b51f8310e55
+IN = e050a589c53371651669fdf003de8d
+AD = 1c282431623808cf1365457401b8
+CT = 88249d2d91c08c3f653d04fbce5b2a
+TAG = b6b3d41cac88520988fb0241d35c4d7c
+
+KEY = 00000000000000000000000000000000
+NONCE = 0c834300bfc1398930b21bc9
+IN = 67c5894b62b370b52a2b79dcdbc2d3b7
+AD = 1b10ff76d83afd763d9c5e1ccc07
+CT = 50eb049ec732f4215e82f5d619005b29
+TAG = 55f043fe92a3f0dae9d29f4c87d4f6ba
+
+KEY = 00000000000000000000000000000000
+NONCE = 65e21521e66aec3ecf920545
+IN = 03acb799afd453903cfb1979c266a879f0
+AD = 023af8ae046eb24895deb6ad3039
+CT = 1fe41123f5e7981ee784503be310d0e2fc
+TAG = 83e237f8093a669a9a8755dd1312d00b
+
+KEY = 00000000000000000000000000000000
+NONCE = b51c4dd3c8763b24d210da6d
+IN = ""
+AD = 22ad7d4e8b6e5b0fa7ac51f3bd9b6f
+CT = ""
+TAG = 74cd0b7de2879b7b108c2189cb5c7ef0
+
+KEY = 00000000000000000000000000000000
+NONCE = cc38cf7c8d5244fb98054f39
+IN = 0e
+AD = 6becf4b5e45d83ad001e178dc74832
+CT = 8f
+TAG = 33db07f2d98181fc9d0c7b975b22e8f4
+
+KEY = 00000000000000000000000000000000
+NONCE = 7399b6cd84d55c7374117320
+IN = cd41a424363cad2b3a678355a459cd
+AD = 729a3007782e0e3f2879d0eff1997c
+CT = b11a59ae97e7726ae76fbd9835fab1
+TAG = 6aa7031a8ac914f7fc7daffe62cbb611
+
+KEY = 00000000000000000000000000000000
+NONCE = 248508aabe35fa6310708b72
+IN = 787ccdb902c2a5733046a7541d03a6af
+AD = d6ed0e3fd3b0d166af5d60e88ebdfa
+CT = 7c0ec5c9cc49379a50f28603450c0428
+TAG = e08d819f1f4459cd1ae4978cb27f2399
+
+KEY = 00000000000000000000000000000000
+NONCE = 766f046ea512002f3d8b329f
+IN = 28dc42b1da4e40295d08335fcc17c10d68
+AD = bcb1adcca736d1f30c516b29c24210
+CT = a7c8d3cf8b12207148819ff4cdfc042781
+TAG = 80f454350eb601109315d61fec2f605c
+
+KEY = 4924e84f52c060ee1619e5b1a0dae006
+NONCE = 000000000000000000000000
+IN = ""
+AD = ""
+CT = ""
+TAG = 6dc174889cbedc3e2f61089ea091d689
+
+KEY = 4412792a5669a01cd0b594d079af37d7
+NONCE = 000000000000000000000000
+IN = 45
+AD = ""
+CT = aa
+TAG = 31122b450b2b140dc7f09da7ee962ec6
+
+KEY = 59d5b2275010318d5b7bb1e6fe7697e5
+NONCE = 000000000000000000000000
+IN = fbcd5b23c1d24e54f59ffb33b488e3
+AD = ""
+CT = 50a831ea5bdf6776ecc11eef489318
+TAG = 849aa8ac7eabe14c9967a9b0ae08e90c
+
+KEY = c273572377e00c5255fdaea791571780
+NONCE = 000000000000000000000000
+IN = 21d21e009fcd3663e97f41d852115402
+AD = ""
+CT = eecb84b2d05c9cf1687b83b2e86fdfca
+TAG = 72af53e82d55c59e07a351513eb07587
+
+KEY = 6e044edb8095bbd2295583fd231a2e30
+NONCE = 000000000000000000000000
+IN = 0dc8ed8b3f646bf7626a25fde11c44a8f5
+AD = ""
+CT = 3a4d0a82e5796706bc8c637630d12da4fe
+TAG = f7a082529b805400cf1d5fa5df6ab71c
+
+KEY = 6503f91ae97213733e23a7a3465801ea
+NONCE = 000000000000000000000000
+IN = ""
+AD = bf
+CT = ""
+TAG = 87de846686729f0f6f67995cc68da3b7
+
+KEY = 46ba69e2c72974afe917d9bed1ccbb96
+NONCE = 000000000000000000000000
+IN = 81
+AD = 69
+CT = 85
+TAG = 398637be5f0dfe88bef82dea95b6d152
+
+KEY = e6facfa1f5d62efe9d92e891205d8ad5
+NONCE = 000000000000000000000000
+IN = 401d55e11093e8e8bb6577321f6094
+AD = e7
+CT = e47db61bf91d50f1f96c6e5113920a
+TAG = a4886aca377baced10cec7f712d747b9
+
+KEY = 25af9d91cb92ea2120f9430ab5a27927
+NONCE = 000000000000000000000000
+IN = 0083c78bb7be0c2011eb32440082d960
+AD = 47
+CT = 828a7d9964c694b446bd90e66770c0fb
+TAG = 1202f711d6e6081ca29a2f88b20f65f6
+
+KEY = 132a938e0ee142f72f07319cafe809a8
+NONCE = 000000000000000000000000
+IN = 38381e1d38991c246c90ddd22739e55bc2
+AD = 3e
+CT = 27d48f133a16b887e7c4ab3a20cb1df49a
+TAG = 12cac311045c0a0baae38439c7039504
+
+KEY = 7527992034c6d9b688e083c222d409b3
+NONCE = 000000000000000000000000
+IN = ""
+AD = 81817cc41c0f5bfe4ea1f6a0180b
+CT = ""
+TAG = 3f03ac1bd144d0a2d69b606782dc0c14
+
+KEY = 474b31973d9dcae7bcede90a77571820
+NONCE = 000000000000000000000000
+IN = 31
+AD = a024c84cd259521d6138d649b81a
+CT = 61
+TAG = 9da56cfd1b3a49e895f63cab93fef226
+
+KEY = e2feda3127a2c21b10d6035f17e47c30
+NONCE = 000000000000000000000000
+IN = e4808472a7292c82c1d3c1ce389ccc
+AD = 6e5770f4bed4b16906fdaf5e368a
+CT = 2cbe2d0a6a0f3165fec8b5e92d977f
+TAG = c719b025b5ceb99f0b5c006b5ae0171c
+
+KEY = b4d9b55dbf5728aa2ad3a88a37613d68
+NONCE = 000000000000000000000000
+IN = 8340c8f62c0d24b7db13d3acac41c1c5
+AD = 84bb31eb6c20c0b2a61359a13f88
+CT = a9a6df864aa142ed8aeddef2a33cef6f
+TAG = 9c25e499a7c081a935162e0f05e5e3a5
+
+KEY = 81edff616f4abf663ddcefdaf97e4574
+NONCE = 000000000000000000000000
+IN = bd7fc45df57146dcf931396564f53bfe24
+AD = e79198db62fda947aba402511480
+CT = 7bd62100421827cef19c7895dc9e9d0c0a
+TAG = 21ce0bcacfd6bb0dce25dd3d84c1d11f
+
+KEY = 5df5a7e0dedfd9be6776197d8448b109
+NONCE = 000000000000000000000000
+IN = ""
+AD = b37cafad6371f477de1cd66c761556
+CT = ""
+TAG = 1af1a381221321ac4d16637df8326b88
+
+KEY = 6a7381fda7c41e74943003696f3d7a50
+NONCE = 000000000000000000000000
+IN = ea
+AD = c7353eb5c7c0a7967d2a83d704e979
+CT = 8d
+TAG = d96cfe8ed7dd807224f17b51977af161
+
+KEY = 1d01e4e13a0dbdd855edfffa1e3e4712
+NONCE = 000000000000000000000000
+IN = afc0f44fd031e8ff0a468ece856895
+AD = 0b617c0ac39435fc7b69377392b676
+CT = e7bf2f58eec81c558b0a994e39c0ce
+TAG = 0b39378406db728e4209c2a2ce5e0483
+
+KEY = 0a89f989aec80f55c59f3a6778eea983
+NONCE = 000000000000000000000000
+IN = b9a6c96a07aee6c1379701d0c9d06054
+AD = f92c2ad004b239e274cf001fa7981d
+CT = dd833ed674914899351aae95fde126c8
+TAG = 74bdd5cb070b23487b01089e4d8865b4
+
+KEY = 4e4894f7f7deef6adb8a56ecc0126eef
+NONCE = 000000000000000000000000
+IN = 737914e07118dfe31708d81b28d3c85ad0
+AD = 5eac9d12253383e5b53677297860a9
+CT = e4d03869eb8638c930a0715f2b868314dc
+TAG = 30a35f60a199ad2dd5f5382ec57edfe8
+
+KEY = 29bc6725a2eb78e00f1515ff664d79e1
+NONCE = ffffffffffffffffffffffff
+IN = ""
+AD = ""
+CT = ""
+TAG = 12163cbb979b648fc65807037221788f
+
+KEY = 482890edbff205813f37a25f04e0c6e8
+NONCE = ffffffffffffffffffffffff
+IN = 44
+AD = ""
+CT = 01
+TAG = f8ee0eba7f440fd0042dbec61b6fcce5
+
+KEY = 81a06b011ae5d3461eb54c90e3e3b17d
+NONCE = ffffffffffffffffffffffff
+IN = 4bc71279dcb82a1df63fe68d6daff0
+AD = ""
+CT = 331aeee072a2baead115b62763cb20
+TAG = c2faa88c3dcac13ec9ddec235935a86c
+
+KEY = fedcb25b65c744d2d94c2b124f964f85
+NONCE = ffffffffffffffffffffffff
+IN = f3616eb0f83999f8c6e752d4246d1a70
+AD = ""
+CT = d932cc31e7c72fc499dd898305a3de84
+TAG = fa801ac9e6467f8adbae6648d69c4e03
+
+KEY = ef0d6124930eeb4d6f9678517336ec2b
+NONCE = ffffffffffffffffffffffff
+IN = a92e4e4e68a2a68f5df0d0748bbaf22606
+AD = ""
+CT = b1a3f0691effbb0a806ede485bb54a74f0
+TAG = e31f3a7bb17bdee6eedd0853ed095c83
+
+KEY = a81958ba1efd790156e904c6d7effe79
+NONCE = ffffffffffffffffffffffff
+IN = ""
+AD = 83
+CT = ""
+TAG = 4cb5f5c94844cda14cbf5d18ebab3f6c
+
+KEY = 929596e90b14fce47414c8aa78631628
+NONCE = ffffffffffffffffffffffff
+IN = 6a
+AD = 3f
+CT = a2
+TAG = cf96ff9a8e48dca90244da89dedb4a82
+
+KEY = d006953df8b57379a2d5316d1440b365
+NONCE = ffffffffffffffffffffffff
+IN = add37f4c4ee6b9c8818e610db1638e
+AD = b2
+CT = e0d2cae20d2bda77c386cf0e0aeac1
+TAG = 14abfd35d3f629a2781941521754b561
+
+KEY = 49600092b33f40565cda55fe869e30cc
+NONCE = ffffffffffffffffffffffff
+IN = f99c3b4078860092e9183414e2fb9cf7
+AD = 3d
+CT = cc541a7de91023c5c2a359ba526fa4fd
+TAG = 4754ceb1f592695e87fe7592e1257266
+
+KEY = cf40652bec0133f8f6bd94896086b736
+NONCE = ffffffffffffffffffffffff
+IN = dbc581e5c2b332da43e80ad144b2e8ac0e
+AD = 66
+CT = c914553cd0a21ca56beeba45f3b8efce9a
+TAG = f173ea118ee13983f00c5f84007520ab
+
+KEY = e5af94aeb76de1aa7d44ea0e68d26063
+NONCE = ffffffffffffffffffffffff
+IN = ""
+AD = 6d4f047a69c75c14ec7a7129cfb2
+CT = ""
+TAG = 09de9520cff7d24c2e945bccb492c317
+
+KEY = fa5b694d9d764c3042dd20f3b7800e5d
+NONCE = ffffffffffffffffffffffff
+IN = 75
+AD = d661c3d96fbd3fa5acbba61cbc0c
+CT = 40
+TAG = 6c3cc5fc5ca98cb3d13bc95891c42662
+
+KEY = 091f71b6df12998ba76c973f4fa549d6
+NONCE = ffffffffffffffffffffffff
+IN = 5fc6d337a9e688809d42c395f01139
+AD = 6c1050058b1969b63f5a3a627c0a
+CT = 4488958472f2799ea165b192b30010
+TAG = 37317f732314d0838775dcae79a6c6b3
+
+KEY = e0d6321dd94da6c991c2b08f24e1be0a
+NONCE = ffffffffffffffffffffffff
+IN = d9db2139f364e988a5528d3a3c327dec
+AD = 7bb029d5f5c5083ffefbeaf978f5
+CT = 868ba129ade9926b2576b1a3281431ec
+TAG = 73d1fa0d9a8d9cfa387bd6121074f81c
+
+KEY = c793a902b645f11d3ed55ead6d218b6d
+NONCE = ffffffffffffffffffffffff
+IN = 87f16d560f167f3c37ac6e9111cefea9d7
+AD = ac1814817e2e9d520b4797c3106f
+CT = ff2441a4693627175ae375f48c40d834ec
+TAG = 066d9e5d72996283d973b022c2a390bd
+
+KEY = 214c3fe0f23678f1de384f6dcf085e9c
+NONCE = ffffffffffffffffffffffff
+IN = ""
+AD = e283c8a9344d804496d84d391a231b
+CT = ""
+TAG = 43bdf83592e8066e717aaaedc05edd92
+
+KEY = d3f30ecbf02a655c7c12419d1e0fc12e
+NONCE = ffffffffffffffffffffffff
+IN = 06
+AD = d78c67ce32dfd84f7dc48e0b65762a
+CT = f2
+TAG = a9fd3f41e3e7f9bdcf09272aa23b9d71
+
+KEY = 514f89aef0411ccd3411ec0c006b5fa3
+NONCE = ffffffffffffffffffffffff
+IN = 90f6693846341b30da39cfce44c8c4
+AD = 6ebd6dd551beb653680d05de31a1b8
+CT = 87722d6852f9998e7f7fa739f218ea
+TAG = b78e03a6bbb98465dcd200ccce94cf49
+
+KEY = 6d215c68020b48df66ab49b3222863ca
+NONCE = ffffffffffffffffffffffff
+IN = 1f7f283c6ebeb5479348593a66f8789e
+AD = 37e3c3156ec71e48aa507c9a7428e1
+CT = d93f714c6d4ecc8de285bbae755fabb8
+TAG = 7b936f5f1350fb47bf8a758c58d75167
+
+KEY = 37ccb561723b27b762f9fb50b26acaf3
+NONCE = ffffffffffffffffffffffff
+IN = c41324da15cdf2c33c3aaf28bff7f34717
+AD = b341763dc2e4e92b4f4b1ceb762d59
+CT = 2bd6ab4f299261de03511d1047676819a1
+TAG = 647e600b233b23764d2ae3d5fc1117a5
+
+KEY = 5102644370c6e4fcdffb8589e074fd7a
+NONCE = 4e23d9c96db6bae70531d51e
+IN = ""
+AD = ""
+CT = ""
+TAG = 1894ae70212b01dcf93f1731674221e0
+
+KEY = 777293968b241e91cfb12a41034aeecf
+NONCE = 5ae55a14e37c00343539e137
+IN = 2e
+AD = ""
+CT = 0d
+TAG = d43ae1ae450699477e7e34edf3c8c02d
+
+KEY = 628858865b9c75ca1e93f5f734c3dfca
+NONCE = 66174c7e1747430f080c9d6a
+IN = e5af3b0482bbd49c5006dcf3121e58
+AD = ""
+CT = a14ff025ac5a81fbbb83a9862b198c
+TAG = 1e3de5ee3b4066ab613a3a7672273c14
+
+KEY = 935ec71ccb19905607ea6e2f470e6e52
+NONCE = a26a063b4aea48f50c9e9970
+IN = 25d1c6fbb9d0ccae72851aba4d4249ae
+AD = ""
+CT = b97de0faff92f7342730c4a613fbb3d4
+TAG = 63cefd83ddc872ad95834a098cf6afcb
+
+KEY = a53350bb9d9f10fcf2145d4a70417284
+NONCE = 888f4340c0b146dc9e567f22
+IN = 4f8cdd4076a5c9dacf8df6106b1a666ff5
+AD = ""
+CT = 92efd3ce3409087a8083ef6511a7334d9e
+TAG = e8314317bd36421af1d0e77394e394af
+
+KEY = fac898917c8fe091c716b5c392065980
+NONCE = 7dc7c5bb0426bbfbcc20d952
+IN = ""
+AD = 17
+CT = ""
+TAG = 31b77a23995f68c4cb9594b985d5f5b7
+
+KEY = f5ded373c9e3391286682bfb8ca7d2d3
+NONCE = 7b7cae98e24f5a3306c22d69
+IN = e3
+AD = 55
+CT = 11
+TAG = 4cec365211d4bf2500f3d008e4b4b28d
+
+KEY = e413df4a4779d74387a8a1b9886a0231
+NONCE = 888472ceaf4c929463d3b8e4
+IN = 40137171110363a5db03dd273553cc
+AD = 0e
+CT = a31be8f36a3bbe7843207c6e6831bf
+TAG = b2b16ca898afcf3599c87fa1f4781a60
+
+KEY = 11ab2f9aff4e1a1db78d77bdcd4ee0ab
+NONCE = bd867f2464c6d636b1e87efe
+IN = 82ef9793e783c5bef19fb9900c5323a7
+AD = 25
+CT = c380592955f9a755ad737b3608f90bdc
+TAG = bd88261105b2b9dbe671fe609272f448
+
+KEY = 48f0130839f6724f608f65516f813c3c
+NONCE = 9e4f2720174d13f1dbd1208a
+IN = 9dc7048b658fc5da999cf6fd80ee5db981
+AD = 71
+CT = d7bdba27f6833227dba75e4e28f869dc29
+TAG = a6e33d6eae10979e461b0873bf61ca8c
+
+KEY = eefdc2951eb476dd3542382fbcf553a4
+NONCE = 81b189cdc2471578307df5c5
+IN = ""
+AD = 1a2d59f5c8074463244c0dea8308
+CT = ""
+TAG = 9e74f8ec967221accbf8810416440856
+
+KEY = 3d1ea75c6c7a7738633200e9ddb96fbd
+NONCE = 0a58b251fa79995bf704cfda
+IN = db
+AD = cf879dd70db9f12776304f3fcbed
+CT = 91
+TAG = 6789599a2dd6bb54a512d684f9da8c15
+
+KEY = f2b842bb46506a5e180fe37f976c3b22
+NONCE = 2b239bd092773813a0f0bc05
+IN = 5f1ac555f4e97b384aaf705e2df1be
+AD = 27873f066cff90e560fd47be4bca
+CT = 298391db6dafc63bb9e2187301daa5
+TAG = ae6a907c294d14ceb9df2a0dbb920d20
+
+KEY = e22e77de032231629897cae79de9cd38
+NONCE = 1fc646b7f760c1c6554328ca
+IN = 66b891cc31d91204997c491f4b3af7a6
+AD = fd1170f2f432cb766b9a7b4296c2
+CT = b3206b0c9fc82387cf352e373ddb0ade
+TAG = 6c9a940a7bdd432a2bcd490040b34bc5
+
+KEY = dda7c98ccac06e1bde6028292b1b2f1a
+NONCE = ad2bb9d948ac319b3678c0bc
+IN = f8e33a0e87eca6e4c9309ed326f456fc94
+AD = 5351484ff29af2cbc06e7eb34e29
+CT = 054be508ecd67aaa61f24c4540dd677a73
+TAG = 4665d92aeebf0223d489b579a8f5b382
+
+KEY = fbff04cfb828d121517f8037c6752063
+NONCE = f03f43541b6f23e7a22e63ad
+IN = ""
+AD = 32301b8cef75e752431d3c5c7512a5
+CT = ""
+TAG = 12dbb04cebdb56f23f9dbb30935b5221
+
+KEY = a1c4dcf42c50ff165a8dbb1f85824356
+NONCE = 41eb958099c4f330ebb40de1
+IN = 71
+AD = 3f52e2ade1c450e91aac0389019f66
+CT = 3f
+TAG = 449a8c351f4345f2c05388c18cd240e8
+
+KEY = d88f42e79bd5f7348c3d1774e82a4e97
+NONCE = 2b688ddd55b26d8b872e8f2d
+IN = 45ca06d39adf2e3536b1c6be66c291
+AD = 62e9f61673a7dfa103384af2b708ee
+CT = a5bfd277dd8ab20e2af11e60f4ab5c
+TAG = 57fccd21f8af8758b9a4de2038b05396
+
+KEY = 91c8cba0985ffd91444091f5aab85159
+NONCE = 814c7a403894d9b51363013f
+IN = 1fab40afb07987ce7a6a4b1c8d11c3bc
+AD = 514f8aa60407debdf48a07e8cf4ef6
+CT = 757a36b7633206d156a6fb5f2e53820e
+TAG = 73670c1e557a1041674fbe9f01b5d66e
+
+KEY = 5552cc402c1129efa00198f3de6ca392
+NONCE = 6bcaea3345cc16fa7d8c5e16
+IN = 05179922aa298f3fd275004992d4093ab2
+AD = ef51766614694da83d02bbb876c99d
+CT = 3cd8117bfce05cfca6f4e66ee10a00189c
+TAG = 4b01a0ef05b2c2427e5dcfba7b2936d2
diff --git a/tests/aead_tests.rs b/tests/aead_tests.rs
index 74db661715..5e85edebab 100644
--- a/tests/aead_tests.rs
+++ b/tests/aead_tests.rs
@@ -83,6 +83,7 @@ test_aead! {
{ AES_128_GCM, "aead_aes_128_gcm_tests.txt" },
{ AES_256_GCM, "aead_aes_256_gcm_tests.txt" },
{ CHACHA20_POLY1305, "aead_chacha20_poly1305_tests.txt" },
+ { AES_128_CCM, "aead_aes_128_ccm_tests.txt" },
}
struct KnownAnswerTestCase<'a> {