Skip to content

Commit 67d9417

Browse files
author
Yiming Lin
committed
Adds CMAC
1 parent 4b35869 commit 67d9417

File tree

8 files changed

+10059
-0
lines changed

8 files changed

+10059
-0
lines changed

aws-lc-rs/src/cmac.rs

Lines changed: 635 additions & 0 deletions
Large diffs are not rendered by default.

aws-lc-rs/src/cmac/tests/fips.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0 OR ISC
3+
4+
#![cfg(debug_assertions)]
5+
6+
use crate::cmac::{sign, verify, Key, AES_128, AES_192, AES_256, TDES_FOR_LEGACY_USE_ONLY};
7+
use crate::fips::{assert_fips_status_indicator, FipsServiceStatus};
8+
use crate::rand::{self, SystemRandom};
9+
10+
const TEST_MESSAGE: &str = "test message";
11+
12+
macro_rules! cmac_api {
13+
($name:ident, $alg:expr, $key_len:expr, $expect:path) => {
14+
#[test]
15+
fn $name() {
16+
let rng = SystemRandom::new();
17+
18+
let key_value: [u8; $key_len] = rand::generate(&rng).unwrap().expose();
19+
20+
let s_key = Key::new($alg, key_value.as_ref());
21+
22+
let tag = assert_fips_status_indicator!(
23+
sign(&s_key, TEST_MESSAGE.as_bytes()),
24+
$expect
25+
);
26+
27+
let v_key = Key::new($alg, key_value.as_ref());
28+
29+
assert_fips_status_indicator!(
30+
verify(&v_key, TEST_MESSAGE.as_bytes(), tag.as_ref()),
31+
$expect
32+
).unwrap();
33+
}
34+
};
35+
}
36+
37+
cmac_api!(aes_128, AES_128, 16, FipsServiceStatus::Approved);
38+
cmac_api!(aes_192, AES_192, 24, FipsServiceStatus::NonApproved);
39+
cmac_api!(aes_256, AES_256, 32, FipsServiceStatus::Approved);
40+
cmac_api!(tdes, TDES_FOR_LEGACY_USE_ONLY, 24, FipsServiceStatus::NonApproved);

aws-lc-rs/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ extern crate aws_lc_sys as aws_lc;
163163

164164
pub mod aead;
165165
pub mod agreement;
166+
pub mod cmac;
166167
pub mod constant_time;
167168
pub mod digest;
168169
pub mod error;

aws-lc-rs/tests/cmac_tests.rs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use aws_lc_rs::{cmac, test, test_file};
2+
3+
#[test]
4+
fn cavp_cmac_aes128_tests() {
5+
test::run(test_file!("data/cavp_aes128_cmac_tests.txt"), |section, test_case| {
6+
assert_eq!(section, "");
7+
8+
let _count = test_case.consume_usize("Count");
9+
let _klen = test_case.consume_usize("Klen");
10+
let mlen = test_case.consume_usize("Mlen");
11+
let tlen = test_case.consume_usize("Tlen");
12+
let key = test_case.consume_bytes("Key");
13+
let msg = test_case.consume_bytes("Msg");
14+
let mac = test_case.consume_bytes("Mac");
15+
let result = test_case.consume_string("Result");
16+
17+
let input = if mlen == 0 { Vec::new() } else { msg };
18+
let should_pass = result.chars().next().unwrap() == 'P';
19+
20+
let cmac_key = cmac::Key::new(cmac::AES_128, &key);
21+
let signature = cmac::sign(&cmac_key, &input);
22+
23+
// Truncate to tlen
24+
let truncated_sig = &signature.as_ref()[..std::cmp::min(signature.as_ref().len(), tlen)];
25+
26+
if should_pass {
27+
assert_eq!(truncated_sig, &mac);
28+
} else {
29+
assert_ne!(truncated_sig, &mac);
30+
}
31+
32+
Ok(())
33+
});
34+
}
35+
36+
#[test]
37+
fn cavp_cmac_aes192_tests() {
38+
test::run(test_file!("data/cavp_aes192_cmac_tests.txt"), |section, test_case| {
39+
assert_eq!(section, "");
40+
41+
let _count = test_case.consume_usize("Count");
42+
let _klen = test_case.consume_usize("Klen");
43+
let mlen = test_case.consume_usize("Mlen");
44+
let tlen = test_case.consume_usize("Tlen");
45+
let key = test_case.consume_bytes("Key");
46+
let msg = test_case.consume_bytes("Msg");
47+
let mac = test_case.consume_bytes("Mac");
48+
let result = test_case.consume_string("Result");
49+
50+
let input = if mlen == 0 { Vec::new() } else { msg };
51+
let should_pass = result.chars().next().unwrap() == 'P';
52+
53+
let cmac_key = cmac::Key::new(cmac::AES_192, &key);
54+
let signature = cmac::sign(&cmac_key, &input);
55+
56+
// Truncate to tlen
57+
let truncated_sig = &signature.as_ref()[..std::cmp::min(signature.as_ref().len(), tlen)];
58+
59+
if should_pass {
60+
assert_eq!(truncated_sig, &mac);
61+
} else {
62+
assert_ne!(truncated_sig, &mac);
63+
}
64+
65+
Ok(())
66+
});
67+
}
68+
69+
#[test]
70+
fn cavp_cmac_aes256_tests() {
71+
test::run(test_file!("data/cavp_aes256_cmac_tests.txt"), |section, test_case| {
72+
assert_eq!(section, "");
73+
74+
let _count = test_case.consume_usize("Count");
75+
let _klen = test_case.consume_usize("Klen");
76+
let mlen = test_case.consume_usize("Mlen");
77+
let tlen = test_case.consume_usize("Tlen");
78+
let key = test_case.consume_bytes("Key");
79+
let msg = test_case.consume_bytes("Msg");
80+
let mac = test_case.consume_bytes("Mac");
81+
let result = test_case.consume_string("Result");
82+
83+
let input = if mlen == 0 { Vec::new() } else { msg };
84+
let should_pass = result.chars().next().unwrap() == 'P';
85+
86+
let cmac_key = cmac::Key::new(cmac::AES_256, &key);
87+
let signature = cmac::sign(&cmac_key, &input);
88+
89+
// Truncate to tlen
90+
let truncated_sig = &signature.as_ref()[..std::cmp::min(signature.as_ref().len(), tlen)];
91+
92+
if should_pass {
93+
assert_eq!(truncated_sig, &mac);
94+
} else {
95+
assert_ne!(truncated_sig, &mac);
96+
}
97+
98+
Ok(())
99+
});
100+
}
101+
102+
#[test]
103+
fn cavp_cmac_3des_tests() {
104+
test::run(test_file!("data/cavp_3des_cmac_tests.txt"), |section, test_case| {
105+
assert_eq!(section, "");
106+
107+
let _count = test_case.consume_usize("Count");
108+
let _klen = test_case.consume_usize("Klen");
109+
let mlen = test_case.consume_usize("Mlen");
110+
let tlen = test_case.consume_usize("Tlen");
111+
let key1 = test_case.consume_bytes("Key1");
112+
let key2 = test_case.consume_bytes("Key2");
113+
let key3 = test_case.consume_bytes("Key3");
114+
let msg = test_case.consume_bytes("Msg");
115+
let mac = test_case.consume_bytes("Mac");
116+
let result = test_case.consume_string("Result");
117+
118+
// Combine 3DES keys
119+
let mut combined_key = key1;
120+
combined_key.extend(key2);
121+
combined_key.extend(key3);
122+
123+
let input = if mlen == 0 { Vec::new() } else { msg };
124+
let should_pass = result.chars().next().unwrap() == 'P';
125+
126+
let cmac_key = cmac::Key::new(cmac::TDES_FOR_LEGACY_USE_ONLY, &combined_key);
127+
let signature = cmac::sign(&cmac_key, &input);
128+
129+
// Truncate to tlen
130+
let truncated_sig = &signature.as_ref()[..std::cmp::min(signature.as_ref().len(), tlen)];
131+
132+
if should_pass {
133+
assert_eq!(truncated_sig, &mac);
134+
} else {
135+
assert_ne!(truncated_sig, &mac);
136+
}
137+
Ok(())
138+
});
139+
}

0 commit comments

Comments
 (0)