1use std::str::FromStr;
2
3use json::JsonValue;
4
5use crate::{
6 blkcipher::BlkCipherMCTOutput,
7 drbg::DrbgMode,
8 msgauth::MsgAuthOutput,
9 util::{AcvpAlgorithm, Direction, IVMode, TestType},
10 AcvpError, AcvpResult,
11};
12
13pub trait TestGroup {
14 fn new(algorithm: &str, tgjson: &str) -> AcvpResult<Self>
15 where
16 Self: Sized;
17 fn dump(&self) -> String;
18 fn pretty(&self) -> String;
19}
20
21pub trait TestCase {
22 fn new(test: &str, tgdata: &TestGroupData) -> AcvpResult<Self>
23 where
24 Self: Sized;
25 fn get_result(&self) -> AcvpResult<JsonValue>;
26 fn dump_result(&self) -> AcvpResult<String>;
27 fn pretty_result(&self) -> AcvpResult<String>;
28}
29
30pub trait TestResult<T> {
31 fn set_result(&mut self, res: T) -> AcvpResult<()>;
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct TestGroupData {
36 pub algorithm: String,
37 pub test_type: TestType,
38 pub taglen: usize,
40 pub payload_len: usize,
41 pub ivmode: IVMode,
42 pub ivlen: usize,
43 pub direction: Direction,
45 pub drbgmode: DrbgMode,
52 pub prediction_resistance: bool,
53 pub reseed: bool,
54 pub der_func: bool,
55 pub returned_bits_len: usize,
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct AcvpTest<T> {
60 pub tcid: u32,
61 pub tgdata: TestGroupData,
62 pub test: T,
63 test_json: JsonValue,
64}
65
66impl<T: TestCase> TestCase for AcvpTest<T> {
67 fn new(test: &str, tgdata: &TestGroupData) -> AcvpResult<Self> {
68 let tc = match json::parse(test) {
69 Ok(tc) => tc,
70 Err(_e) => {
71 return Err(AcvpError {
72 code: -libc::EINVAL,
73 message: "Failed to parse testcase JSON".to_string(),
74 });
75 }
76 };
77
78 if !tc.has_key("tcId") {
79 return Err(AcvpError {
80 code: -libc::EINVAL,
81 message: "Required field tcID missing from testcase JSON".to_string(),
82 });
83 }
84 let tcid = crate::util::get_acvp_u32("tcId", &tc)?;
85 let test = T::new(test, tgdata)?;
86
87 Ok(AcvpTest {
88 tcid,
89 tgdata: tgdata.clone(),
90 test,
91 test_json: tc,
92 })
93 }
94
95 fn get_result(&self) -> AcvpResult<JsonValue> {
96 self.test.get_result()
97 }
98
99 fn dump_result(&self) -> AcvpResult<String> {
100 self.test.dump_result()
101 }
102
103 fn pretty_result(&self) -> AcvpResult<String> {
104 self.test.pretty_result()
105 }
106}
107
108impl<T: TestResult<bool>> TestResult<bool> for AcvpTest<T> {
109 fn set_result(&mut self, res: bool) -> AcvpResult<()> {
110 self.test.set_result(res)
111 }
112}
113
114impl<T: TestResult<Vec<u8>>> TestResult<Vec<u8>> for AcvpTest<T> {
115 fn set_result(&mut self, res: Vec<u8>) -> AcvpResult<()> {
116 self.test.set_result(res)
117 }
118}
119
120impl<T: TestResult<Vec<Vec<u8>>>> TestResult<Vec<Vec<u8>>> for AcvpTest<T> {
121 fn set_result(&mut self, res: Vec<Vec<u8>>) -> AcvpResult<()> {
122 self.test.set_result(res)
123 }
124}
125
126impl<T: TestResult<Vec<BlkCipherMCTOutput>>> TestResult<Vec<BlkCipherMCTOutput>> for AcvpTest<T> {
127 fn set_result(&mut self, res: Vec<BlkCipherMCTOutput>) -> AcvpResult<()> {
128 self.test.set_result(res)
129 }
130}
131
132impl<T: TestResult<MsgAuthOutput>> TestResult<MsgAuthOutput> for AcvpTest<T> {
133 fn set_result(&mut self, res: MsgAuthOutput) -> AcvpResult<()> {
134 self.test.set_result(res)
135 }
136}
137
138impl<T: Clone + TestCase> AcvpTest<T> {
139 pub fn get_test_data(&self) -> T {
140 self.test.clone()
141 }
142
143 pub fn dump(&self) -> String {
144 self.test_json.dump()
145 }
146
147 pub fn pretty(&self) -> String {
148 self.test_json.pretty(3)
149 }
150}
151
152#[derive(Debug, Clone, PartialEq, Eq)]
153pub struct AcvpTestGroup<T> {
154 test_type: TestType,
155 tgid: u32,
156 pub tests: Vec<AcvpTest<T>>,
157 testgroup_json: JsonValue,
158}
159
160impl<T: TestCase> TestGroup for AcvpTestGroup<T> {
161 fn new(algorithm: &str, tgjson: &str) -> AcvpResult<Self> {
162 let tg = match json::parse(tgjson) {
163 Ok(tg) => tg,
164 Err(_e) => {
165 return Err(AcvpError {
166 code: -libc::EINVAL,
167 message: "Failed to parse testgroup JSON".to_string(),
168 });
169 }
170 };
171 if !tg.has_key("tgId") || !tg.has_key("testType") {
172 return Err(AcvpError {
173 code: -libc::EINVAL,
174 message: "Provided testgroup JSON does not have required fields".to_string(),
175 });
176 }
177 let tgid = crate::util::get_acvp_u32("tgId", &tg)?;
178 let test_type = TestType::from_string(&crate::util::get_acvp_str("testType", &tg)?)?;
179
180 let mut direction = Direction::Nil;
181 if tg.has_key("direction") {
182 direction = Direction::from_string(&crate::util::get_acvp_str("direction", &tg)?)?;
183 }
184
185 let mut taglen = 0;
186 if tg.has_key("tagLen") {
187 let taglen_bits = crate::util::get_acvp_u32("tagLen", &tg)? as usize;
188 taglen = taglen_bits / 8;
189 } else if tg.has_key("macLen") {
190 let taglen_bits = crate::util::get_acvp_u32("macLen", &tg)? as usize;
191 taglen = taglen_bits / 8;
192 }
193
194 let mut payload_len = 0;
195 if tg.has_key("payloadLen") {
196 let payloadlen_bits = crate::util::get_acvp_u32("payloadLen", &tg)? as usize;
197 payload_len = payloadlen_bits / 8;
198 }
199
200 let mut ivmode = IVMode::Nil;
201 if tg.has_key("ivGen") {
202 let ivmode_str = crate::util::get_acvp_str("ivGen", &tg)?;
203 ivmode = IVMode::from_string(&ivmode_str)?;
204 }
205
206 let mut ivlen = 0;
207 if tg.has_key("ivLen") {
208 let ivlen_bits = crate::util::get_acvp_u32("ivLen", &tg)? as usize;
209 ivlen = ivlen_bits / 8;
210 }
211
212 let mut drbgmode = DrbgMode::Nil;
213 if tg.has_key("mode") {
214 let mode = crate::util::get_acvp_str("mode", &tg)?;
215 drbgmode = DrbgMode::from_str(&mode)?;
216 }
217
218 let mut prediction_resistance = false;
219 if tg.has_key("predResistance") {
220 prediction_resistance = crate::util::get_acvp_bool("predResistance", &tg)?;
221 }
222
223 let mut der_func = false;
224 if tg.has_key("derFunc") {
225 der_func = crate::util::get_acvp_bool("derFunc", &tg)?;
226 }
227
228 let mut reseed = false;
229 if tg.has_key("reSeed") {
230 reseed = crate::util::get_acvp_bool("reSeed", &tg)?;
231 }
232
233 let mut returned_bits_len: usize = 0;
234 if tg.has_key("returnedBitsLen") {
235 let returned_bits = crate::util::get_acvp_u32("returnedBitsLen", &tg)? as usize;
236 returned_bits_len = returned_bits / 8;
237 }
238
239 let tgdata = TestGroupData {
240 algorithm: algorithm.to_string(),
241 test_type,
242 taglen,
243 payload_len,
244 ivmode,
245 ivlen,
246 direction,
247 drbgmode,
248 prediction_resistance,
249 der_func,
250 reseed,
251 returned_bits_len,
252 };
253
254 let tcs = &tg["tests"];
255 let mut tests = Vec::new();
256 for tc in tcs.members() {
257 let test = AcvpTest::<T>::new(&tc.dump(), &tgdata)?;
258 tests.push(test)
259 }
260
261 Ok(AcvpTestGroup {
262 test_type,
263 tgid,
264 tests,
265 testgroup_json: tg,
266 })
267 }
268
269 fn dump(&self) -> String {
270 self.testgroup_json.dump()
271 }
272
273 fn pretty(&self) -> String {
274 self.testgroup_json.pretty(3)
275 }
276}
277
278impl<T: TestCase> AcvpTestGroup<T> {
279 pub fn get_result(&self) -> AcvpResult<JsonValue> {
280 let mut results = JsonValue::new_array();
281 for test in &self.tests {
282 let res = test.get_result()?;
283 match results.push(res) {
284 Ok(()) => {}
285 Err(_e) => {
286 return Err(AcvpError {
287 code: -1,
288 message: "Unexpected error pushing to JsonValue array".to_string(),
289 });
290 }
291 }
292 }
293 Ok(json::object! {
294 tgId: self.tgid,
295 tests: results,
296 })
297 }
298
299 pub fn dump_result(&self) -> AcvpResult<String> {
300 let res = self.get_result()?;
301 Ok(res.dump())
302 }
303
304 pub fn pretty_result(&self) -> AcvpResult<String> {
305 let res = self.get_result()?;
306 Ok(res.pretty(3))
307 }
308}
309
310#[derive(Debug, Clone, PartialEq, Eq)]
311pub struct AcvpRequest<T> {
312 pub version: String,
313 pub revision: String,
314 pub vsid: u32,
315 pub algorithm: String,
316 pub alg_type: AcvpAlgorithm,
317 pub is_sample: bool,
318 pub testgroups: Vec<AcvpTestGroup<T>>,
319 request_json: JsonValue,
320}
321
322impl<T: TestCase> AcvpRequest<T> {
323 pub fn new(vector: &str) -> AcvpResult<Self> {
324 let request = match json::parse(vector) {
325 Ok(req) => req,
326 Err(_e) => {
327 return Err(AcvpError {
328 code: -libc::EINVAL,
329 message: "Invalid ACVP Request JSON".to_string(),
330 });
331 }
332 };
333
334 if !request.is_array() {
335 return Err(AcvpError {
336 code: -libc::EINVAL,
337 message: "ACVP Request vector must be a JSON Array".to_string(),
338 });
339 }
340
341 let mut testgroups = Vec::new();
342 let mut algorithm = "".to_string();
343 let mut alg_type = AcvpAlgorithm::Nil;
344 let mut revision = "".to_string();
345 let mut vsid = 0;
346 let mut is_sample = false;
347 let mut version = "".to_string();
348 for req in request.members() {
349 if req.has_key("acvVersion") {
350 version = crate::util::get_acvp_str("acvVersion", req)?;
351 continue;
352 }
353 algorithm = crate::util::get_acvp_str("algorithm", req)?;
354 alg_type = AcvpAlgorithm::alg_type(&algorithm)?;
355 revision = crate::util::get_acvp_str("revision", req)?;
356 vsid = crate::util::get_acvp_u32("vsId", req)?;
357 is_sample = crate::util::get_acvp_bool("isSample", req)?;
358 let tgs = &req["testGroups"];
359
360 for tg in tgs.members() {
361 let testgroup = AcvpTestGroup::<T>::new(&algorithm, &tg.dump())?;
362 testgroups.push(testgroup);
363 }
364 }
365 Ok(AcvpRequest {
366 version,
367 revision,
368 vsid,
369 algorithm,
370 alg_type,
371 is_sample,
372 testgroups,
373 request_json: request,
374 })
375 }
376
377 pub fn get_result(&self) -> AcvpResult<JsonValue> {
378 let mut results = JsonValue::new_array();
379 for tg in &self.testgroups {
380 let res = tg.get_result()?;
381 match results.push(res) {
382 Ok(()) => {}
383 Err(_e) => {
384 return Err(AcvpError {
385 code: -1,
386 message: "Unexpected error pushing to JsonValue array".to_string(),
387 });
388 }
389 }
390 }
391 let vers = json::object! {
392 acvVersion: self.version.clone()
393 };
394 let resp = json::object! {
395 vsId: self.vsid,
396 algorithm: self.algorithm.clone(),
397 revision: self.revision.clone(),
398 isSample: self.is_sample,
399 testGroups: results,
400 };
401 Ok(json::array![vers, resp])
402 }
403
404 pub fn dump_result(&self) -> AcvpResult<String> {
405 let res = self.get_result()?;
406 Ok(res.dump())
407 }
408
409 pub fn pretty_result(&self) -> AcvpResult<String> {
410 let res = self.get_result()?;
411 Ok(res.pretty(3))
412 }
413
414 pub fn dump(&self) -> String {
415 self.request_json.dump()
416 }
417
418 pub fn pretty(&self) -> String {
419 self.request_json.pretty(3)
420 }
421}