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