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}