acvp_parser/
drbg.rs

1use json::JsonValue;
2
3use crate::{
4    parser::{TestCase, TestResult},
5    util::TestType,
6    AcvpError, AcvpResult,
7};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum DrbgMode {
11    SHA1,
12    SHA256,
13    SHA384,
14    SHA512,
15    AES128,
16    AES192,
17    AES256,
18    Nil,
19}
20
21impl std::str::FromStr for DrbgMode {
22    fn from_str(s: &str) -> Result<Self, Self::Err> {
23        match s {
24            "SHA-1" => Ok(Self::SHA1),
25            "SHA2-256" => Ok(Self::SHA256),
26            "SHA2-384" => Ok(Self::SHA384),
27            "SHA2-512" => Ok(Self::SHA512),
28            "AES-128" => Ok(Self::AES128),
29            "AES-192" => Ok(Self::AES192),
30            "AES-256" => Ok(Self::AES256),
31            _ => {
32                return Err(AcvpError {
33                    code: -libc::EINVAL,
34                    message: format!("Mode '{}' is not valid", s),
35                });
36            }
37        }
38    }
39
40    type Err = AcvpError;
41}
42
43#[derive(Debug, Clone, Eq, PartialEq)]
44pub struct DrbgOtherInput {
45    pub iuse: String,
46    pub addtl_input: Vec<u8>,
47    pub entropy_input: Vec<u8>,
48}
49
50impl DrbgOtherInput {
51    pub fn new(testjson: &JsonValue) -> AcvpResult<Self> {
52        let iuse = crate::util::get_acvp_str("intendedUse", testjson)?;
53        let addtlhex = crate::util::get_acvp_str("additionalInput", testjson)?;
54        let addtl_input = crate::util::hex2bin(&addtlhex)?;
55
56        let eihex = crate::util::get_acvp_str("entropyInput", testjson)?;
57        let entropy_input = crate::util::hex2bin(&eihex)?;
58
59        Ok(DrbgOtherInput {
60            iuse,
61            addtl_input,
62            entropy_input,
63        })
64    }
65}
66
67#[derive(Debug, Clone, Eq, PartialEq)]
68pub struct Drbg {
69    algorithm: String,
70    tcid: u32,
71    test_type: TestType,
72    res_json: JsonValue,
73    pub entropy_input: Vec<u8>,
74    pub nonce: Vec<u8>,
75    pub perso_string: Vec<u8>,
76    pub other_input: Vec<DrbgOtherInput>,
77}
78
79impl TestCase for Drbg {
80    fn new(test: &str, tgdata: &crate::parser::TestGroupData) -> AcvpResult<Self>
81    where
82        Self: Sized,
83    {
84        let testjson = match json::parse(test) {
85            Ok(t) => t,
86            Err(_e) => {
87                return Err(AcvpError {
88                    code: -libc::EINVAL,
89                    message: String::from("Failed to parse JSON data for DRBG"),
90                });
91            }
92        };
93
94        let tcid = crate::util::get_acvp_u32("tcId", &testjson)?;
95
96        let eihex = crate::util::get_acvp_str("entropyInput", &testjson)?;
97        let entropy_input = crate::util::hex2bin(&eihex)?;
98
99        let noncehex = crate::util::get_acvp_str("nonce", &testjson)?;
100        let nonce = crate::util::hex2bin(&noncehex)?;
101
102        let pshex = crate::util::get_acvp_str("persoString", &testjson)?;
103        let perso_string = crate::util::hex2bin(&pshex)?;
104
105        let oi = &testjson["otherInput"];
106
107        if !oi.is_array() {
108            return Err(AcvpError {
109                code: -libc::EINVAL,
110                message: String::from("other input for DRBG vector is not an array"),
111            });
112        }
113
114        let mut other_input = Vec::new();
115        for inp in oi.members() {
116            other_input.push(DrbgOtherInput::new(inp)?);
117        }
118
119        Ok(Drbg {
120            algorithm: tgdata.algorithm.to_string(),
121            tcid,
122            test_type: tgdata.test_type,
123            res_json: JsonValue::new_object(),
124            entropy_input,
125            nonce,
126            perso_string,
127            other_input,
128        })
129    }
130
131    fn get_result(&self) -> AcvpResult<JsonValue> {
132        if self.res_json.is_empty() {
133            return Err(AcvpError {
134                code: -libc::EINVAL,
135                message: "The result is not yet set, call set_*_result APIs".to_string(),
136            });
137        }
138        Ok(self.res_json.clone())
139    }
140
141    fn dump_result(&self) -> AcvpResult<String> {
142        if self.res_json.is_empty() {
143            return Err(AcvpError {
144                code: -libc::EINVAL,
145                message: "The result is not yet set, call set_*_result APIs".to_string(),
146            });
147        }
148        Ok(self.res_json.dump())
149    }
150
151    fn pretty_result(&self) -> AcvpResult<String> {
152        if self.res_json.is_empty() {
153            return Err(AcvpError {
154                code: -libc::EINVAL,
155                message: "The result is not yet set, call set_*_result APIs".to_string(),
156            });
157        }
158        Ok(self.res_json.pretty(3))
159    }
160}
161
162impl TestResult<Vec<u8>> for Drbg {
163    fn set_result(&mut self, res: Vec<u8>) -> AcvpResult<()> {
164        let rethex = hex::encode(res).to_ascii_uppercase();
165        self.res_json = json::object! {
166            tcId: self.tcid,
167            returnedBits: rethex,
168        };
169        Ok(())
170    }
171}