1use json::JsonValue;
2
3use crate::{AcvpError, AcvpResult};
4
5const HASHES: &[&str; 11] = &[
6 "SHA-1",
7 "SHA2-224",
8 "SHA2-256",
9 "SHA2-384",
10 "SHA2-512",
11 "SHA3-224",
12 "SHA3-256",
13 "SHA3-384",
14 "SHA3-512",
15 "SHAKE-128",
16 "SHAKE-256",
17];
18
19const BLKCIPHERS: &[&str; 8] = &[
20 "ACVP-AES-CBC",
21 "ACVP-AES-CTR",
22 "ACVP-AES-ECB",
23 "ACVP-AES-GCM",
24 "ACVP-TDES-ECB",
25 "ACVP-TDES-CBC",
26 "ACVP-TDES-CTR",
27 "ACVP-AES-XTS",
28];
29
30const MACS: &[&str; 14] = &[
31 "HMAC-SHA-1",
32 "HMAC-SHA2-224",
33 "HMAC-SHA2-256",
34 "HMAC-SHA2-384",
35 "HMAC-SHA2-512",
36 "HMAC-SHA3-224",
37 "HMAC-SHA3-256",
38 "HMAC-SHA3-384",
39 "HMAC-SHA3-512",
40 "CMAC-AES",
41 "CMAC-TDES",
42 "ACVP-AES-GCM",
43 "ACVP-AES-GMAC",
44 "ACVP-AES-CCM",
45];
46
47const RNGS: &[&str; 3] = &["hashDRBG", "ctrDRBG", "hmacDRBG"];
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum AcvpAlgorithm {
51 Hash,
52 MsgAuth,
53 BlockCipher,
54 Rng,
55 Nil,
56}
57
58impl AcvpAlgorithm {
59 pub fn alg_type(alg: &str) -> AcvpResult<Self> {
60 if str_lookup(alg, HASHES) {
61 return Ok(Self::Hash);
62 }
63 if str_lookup(alg, MACS) {
64 return Ok(Self::MsgAuth);
65 }
66 if str_lookup(alg, BLKCIPHERS) {
67 return Ok(Self::BlockCipher);
68 }
69 if str_lookup(alg, RNGS) {
70 return Ok(Self::Rng);
71 }
72 Err(AcvpError {
73 code: -libc::EINVAL,
74 message: format!("Uknown type for algorithm '{}'", alg),
75 })
76 }
77}
78
79#[derive(Debug, Clone, Copy, Eq, PartialEq)]
80pub enum TestType {
81 AFT,
82 CTR,
83 MCT,
84 LDT,
85 Nil,
86}
87
88impl TestType {
89 pub fn from_string(ttype: &str) -> AcvpResult<Self> {
90 let test_type = match ttype {
91 "AFT" => TestType::AFT,
92 "CTR" => TestType::CTR,
93 "MCT" => TestType::MCT,
94 "LDT" => TestType::LDT,
95 _ => {
96 return Err(AcvpError {
97 code: -libc::EINVAL,
98 message: format!("Invalid test type '{}'", ttype),
99 });
100 }
101 };
102 Ok(test_type)
103 }
104}
105
106#[derive(Debug, Clone, Copy, Eq, PartialEq)]
107pub enum Direction {
108 Encrypt,
109 Decrypt,
110 Generate,
111 Verify,
112 Nil,
113}
114
115impl Direction {
116 pub fn from_string(direction: &str) -> AcvpResult<Self> {
117 let dir = match direction {
118 "encrypt" => Direction::Encrypt,
119 "decrypt" => Direction::Decrypt,
120 "gen" => Direction::Generate,
121 "ver" => Direction::Verify,
122 _ => {
123 return Err(AcvpError {
124 code: -libc::EINVAL,
125 message: format!("Invalid direction '{}'", direction),
126 });
127 }
128 };
129 Ok(dir)
130 }
131}
132
133#[derive(Debug, Clone, Copy, Eq, PartialEq)]
134pub enum IVMode {
135 Internal,
136 External,
137 Nil,
138}
139
140impl IVMode {
141 pub fn from_string(mode: &str) -> AcvpResult<Self> {
142 let ivmode = match mode {
143 "internal" => IVMode::Internal,
144 "external" => IVMode::External,
145 _ => {
146 return Err(AcvpError {
147 code: -libc::EINVAL,
148 message: format!("Invalid IVGenMode '{}'", mode),
149 });
150 }
151 };
152 Ok(ivmode)
153 }
154}
155
156fn str_lookup(key: &str, arr: &[&str]) -> bool {
157 if let Some(_str) = arr.iter().find(|&s| *s == key) {
158 return true;
159 }
160 false
161}
162
163pub fn get_acvp_str(key: &str, json: &JsonValue) -> AcvpResult<String> {
164 let value = match json[key].as_str() {
165 Some(val) => val,
166 None => {
167 return Err(AcvpError {
168 code: -libc::EINVAL,
169 message: format!("Failed to obtain str value associated with key '{}'", key,),
170 });
171 }
172 };
173 Ok(value.to_string())
174}
175
176pub fn get_acvp_u32(key: &str, json: &JsonValue) -> AcvpResult<u32> {
177 let value = match json[key].as_u32() {
178 Some(val) => val,
179 None => {
180 return Err(AcvpError {
181 code: -libc::EINVAL,
182 message: format!("Failed to obtain u32 value associated with key '{}'", key,),
183 });
184 }
185 };
186 Ok(value)
187}
188
189pub fn get_acvp_bool(key: &str, json: &JsonValue) -> AcvpResult<bool> {
190 let value = match json[key].as_bool() {
191 Some(val) => val,
192 None => {
193 return Err(AcvpError {
194 code: -libc::EINVAL,
195 message: format!(
196 "Failed to obtain boolean value associated with key '{}'",
197 key,
198 ),
199 });
200 }
201 };
202 Ok(value)
203}
204
205pub(crate) fn hex2bin(hex: &str) -> AcvpResult<Vec<u8>> {
206 let bin = match hex::decode(hex) {
207 Ok(bin) => bin,
208 Err(_e) => {
209 return Err(AcvpError {
210 code: -libc::EINVAL,
211 message: format!("Invalid hex string '{}'", hex),
212 });
213 }
214 };
215 Ok(bin)
216}
217
218pub fn get_algorithm_type(vector: &str) -> AcvpResult<AcvpAlgorithm> {
219 let vec = match json::parse(vector) {
220 Ok(vec) => vec,
221 Err(_e) => {
222 return Err(AcvpError {
223 code: -libc::EINVAL,
224 message: "Invalid input vector, failed to get algorithm type".to_string(),
225 });
226 }
227 };
228
229 let mut alg_type = AcvpAlgorithm::Nil;
230 for v in vec.members() {
231 if v.has_key("algorithm") {
232 let alg = get_acvp_str("algorithm", v)?;
233 alg_type = AcvpAlgorithm::alg_type(&alg)?;
234 }
235 }
236 if alg_type == AcvpAlgorithm::Nil {
237 return Err(AcvpError {
238 code: -libc::EINVAL,
239 message: "No 'algorithm' key present in input vector".to_string(),
240 });
241 }
242
243 Ok(alg_type)
244}