1use json::JsonValue;
2use rand::Rng;
3
4use crate::{
5 parser::{TestCase, TestGroupData, TestResult},
6 util::{Direction, IVMode, TestType},
7 AcvpError, AcvpResult,
8};
9
10#[derive(Debug, Clone, Eq, PartialEq)]
11pub struct MsgAuth {
12 algorithm: String,
13 tcid: u32,
14 test_type: TestType,
15 direction: Direction,
16 res_json: JsonValue,
17 pub key: Vec<u8>,
18 pub key1: Vec<u8>,
19 pub key2: Vec<u8>,
20 pub key3: Vec<u8>,
21 pub iv: Vec<u8>,
22 pub ivmode: IVMode,
23 pub msg: Vec<u8>,
24 pub aad: Vec<u8>,
25 pub tag: Vec<u8>,
26 pub taglen: usize,
27}
28
29impl TestCase for MsgAuth {
30 fn new(testjson: &str, tgdata: &TestGroupData) -> AcvpResult<Self> {
31 let test = match json::parse(testjson) {
32 Ok(test) => test,
33 Err(_e) => {
34 return Err(AcvpError {
35 code: -libc::EINVAL,
36 message: "Failed to parse testcase JSON for SHash".to_string(),
37 });
38 }
39 };
40 let tcid = crate::util::get_acvp_u32("tcId", &test)?;
41
42 let mut msg = Vec::new();
43 if test.has_key("msg") {
44 let msghex = crate::util::get_acvp_str("msg", &test)?;
45 msg = crate::util::hex2bin(&msghex)?;
46 } else if test.has_key("message") {
47 let msghex = crate::util::get_acvp_str("message", &test)?;
48 msg = crate::util::hex2bin(&msghex)?;
49 } else if test.has_key("plainText") {
50 let msghex = crate::util::get_acvp_str("plainText", &test)?;
51 msg = crate::util::hex2bin(&msghex)?;
52 } else if test.has_key("cipherText") {
53 let msghex = crate::util::get_acvp_str("cipherText", &test)?;
54 msg = crate::util::hex2bin(&msghex)?;
55 } else if test.has_key("pt") {
56 let msghex = crate::util::get_acvp_str("pt", &test)?;
57 msg = crate::util::hex2bin(&msghex)?;
58 } else if test.has_key("ct") {
59 let msghex = crate::util::get_acvp_str("ct", &test)?;
60 msg = crate::util::hex2bin(&msghex)?;
61 }
62
63 let mut aad = Vec::new();
64 if test.has_key("aad") {
65 let aadhex = crate::util::get_acvp_str("aad", &test)?;
66 aad = crate::util::hex2bin(&aadhex)?;
67 }
68
69 let mut key = Vec::new();
70 if test.has_key("key") {
71 let keyhex = crate::util::get_acvp_str("key", &test)?;
72 key = crate::util::hex2bin(&keyhex)?;
73 }
74
75 let mut key1 = Vec::new();
76 let mut key2 = Vec::new();
77 let mut key3 = Vec::new();
78 if test.has_key("key1") && test.has_key("key2") && test.has_key("key3") {
79 let keyhex = crate::util::get_acvp_str("key1", &test)?;
80 key1 = crate::util::hex2bin(&keyhex)?;
81 let keyhex = crate::util::get_acvp_str("key2", &test)?;
82 key2 = crate::util::hex2bin(&keyhex)?;
83 let keyhex = crate::util::get_acvp_str("key3", &test)?;
84 key3 = crate::util::hex2bin(&keyhex)?;
85 }
86
87 let mut iv = Vec::new();
88 if test.has_key("iv") {
89 let ivhex = crate::util::get_acvp_str("iv", &test)?;
90 iv = crate::util::hex2bin(&ivhex)?;
91 } else if tgdata.ivmode == IVMode::Internal {
92 let mut rng = rand::thread_rng();
93 iv = (0..tgdata.ivlen).map(|_| rng.gen_range(0..255)).collect();
94 }
95
96 let mut tag = Vec::new();
97 if test.has_key("tag") {
98 let taghex = crate::util::get_acvp_str("tag", &test)?;
99 tag = crate::util::hex2bin(&taghex)?;
100 } else if test.has_key("mac") {
101 let taghex = crate::util::get_acvp_str("mac", &test)?;
102 tag = crate::util::hex2bin(&taghex)?;
103 }
104
105 if tag.is_empty() && tgdata.direction == Direction::Decrypt {
109 if tgdata.payload_len == 0 {
110 tag = msg.clone();
111 msg = Vec::new();
112 } else {
113 tag = msg[tgdata.payload_len..].to_vec();
114 msg = msg[..tgdata.payload_len].to_vec();
115 }
116 }
117
118 Ok(MsgAuth {
119 algorithm: tgdata.algorithm.to_string(),
120 tcid,
121 test_type: tgdata.test_type,
122 direction: tgdata.direction,
123 res_json: JsonValue::new_object(),
124 key,
125 key1,
126 key2,
127 key3,
128 iv,
129 ivmode: tgdata.ivmode,
130 msg,
131 aad,
132 tag,
133 taglen: tgdata.taglen,
134 })
135 }
136
137 fn get_result(&self) -> AcvpResult<JsonValue> {
138 if self.res_json.is_empty() {
139 return Err(AcvpError {
140 code: -libc::EINVAL,
141 message: "The result is not yet set, call set_*_result APIs".to_string(),
142 });
143 }
144 Ok(self.res_json.clone())
145 }
146
147 fn dump_result(&self) -> AcvpResult<String> {
148 if self.res_json.is_empty() {
149 return Err(AcvpError {
150 code: -libc::EINVAL,
151 message: "The result is not yet set, call set_result API".to_string(),
152 });
153 }
154 Ok(self.res_json.dump())
155 }
156
157 fn pretty_result(&self) -> AcvpResult<String> {
158 if self.res_json.is_empty() {
159 return Err(AcvpError {
160 code: -libc::EINVAL,
161 message: "The result is not yet set, call set_result API".to_string(),
162 });
163 }
164 Ok(self.res_json.pretty(3))
165 }
166}
167
168#[derive(Debug, Clone, Eq, PartialEq)]
169pub struct MsgAuthOutput {
170 pub out: Vec<u8>,
171 pub tag: Vec<u8>,
172}
173
174impl MsgAuthOutput {
175 pub fn new(out: Vec<u8>, tag: Vec<u8>) -> Self {
176 MsgAuthOutput { out, tag }
177 }
178}
179
180impl TestResult<Vec<u8>> for MsgAuth {
181 fn set_result(&mut self, result: Vec<u8>) -> AcvpResult<()> {
182 let mut res = JsonValue::new_object();
183 res["tcId"] = self.tcid.into();
184 if self.algorithm.contains("HMAC")
185 || self.algorithm.contains("TDES")
186 || self.algorithm.contains("CMAC")
187 {
188 res["mac"] = hex::encode(result).to_ascii_uppercase().into();
189 } else if self.algorithm.contains("GMAC") {
190 res["tag"] = hex::encode(result).to_ascii_uppercase().into();
191 } else if self.algorithm.contains("GCM") {
192 res["pt"] = hex::encode(result).to_ascii_uppercase().into();
193 } else {
194 match self.direction {
195 Direction::Decrypt | Direction::Verify => {
196 res["pt"] = hex::encode(result).to_ascii_uppercase().into();
197 }
198 Direction::Encrypt | Direction::Generate => {
199 res["ct"] = hex::encode(result).to_ascii_uppercase().into();
200 }
201 Direction::Nil => {
202 return Err(AcvpError {
203 code: -libc::EINVAL,
204 message: "Invalid direction for MsgAuth algorithm".to_string(),
205 });
206 }
207 };
208 }
209 self.res_json = res;
210 Ok(())
211 }
212}
213
214impl TestResult<MsgAuthOutput> for MsgAuth {
215 fn set_result(&mut self, result: MsgAuthOutput) -> AcvpResult<()> {
216 let mut res = JsonValue::new_array();
217 res["tcId"] = self.tcid.into();
218 if self.ivmode == IVMode::Internal {
219 res["iv"] = hex::encode(&self.iv).to_ascii_uppercase().into();
220 }
221 if self.algorithm.contains("CCM") {
222 let mut ct = result.out;
223 ct.extend(result.tag.iter());
224 res["ct"] = hex::encode(ct).to_ascii_uppercase().into();
225 } else {
226 res["ct"] = hex::encode(result.out).to_ascii_uppercase().into();
227 res["tag"] = hex::encode(result.tag).to_ascii_uppercase().into();
228 }
229 self.res_json = res;
230 Ok(())
231 }
232}
233
234impl TestResult<bool> for MsgAuth {
235 fn set_result(&mut self, result: bool) -> AcvpResult<()> {
236 self.res_json = json::object! {
237 tcId: self.tcid,
238 testPassed: result,
239 };
240 Ok(())
241 }
242}