acvp_parser/
parser.rs

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    // For AEAD
39    pub taglen: usize,
40    pub payload_len: usize,
41    pub ivmode: IVMode,
42    pub ivlen: usize,
43    // For SKCipher
44    pub direction: Direction,
45    // For AKCipher
46    // pub hash_alg: String,
47    // pub sig_type: String,
48    // pub n: Vec<u8>,
49    // pub e: Vec<u8>,
50    // For DRBG
51    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}