xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/wycheproof-0.4.0/src/lib.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 //! # Wycheproof test vectors
2 //!
3 //! Wycheproof is a set of cryptographic tests created by a team at Google which
4 //! checks for common bugs and corner cases in cryptographic code.
5 //!
6 //! This crate is a convenient repacking of the Wycheproof JSON-formatted test
7 //! data with deserialization to easily usable structs.
8 //!
9 //! Hex and base64 encoded data is all decoded to binary `Vec<u8>` for your
10 //! convenience. Large integers (such as those used in the primality tests) are
11 //! left as big-endian byte arrays rather than being decoded to `num_bigint` due
12 //! to the proliferation of different multi-precision integers libraries in use
13 //! in the Rust ecosystem.
14 //!
15 //! Each submodule of this crate includes a set of structs: a `TestName` which
16 //! specifies which individual test is desired, a `TestSet` which is the set of
17 //! data associated with the `TestName`. Each `TestSet` contains one or more
18 //! `TestGroups`, which in turn contain some amount of test-specific
19 //! configuration information along with a list of `Test` which are the actual
20 //! tests.
21 //!
22 //! Each test has an expected result which is either `Valid`, `Invalid`, or
23 //! `Acceptable`. `Acceptable` just means that the test is technically valid but
24 //! might still be rejected for various reasons, for instance because the hash
25 //! function that was used is too weak for proper security.
26 //!
27 //! # Examples
28 //!
29 //! ```
30 //! fn print_gcm() {
31 //!     // Print all AES-GCM test vector data
32 //!     let test_set = wycheproof::aead::TestSet::load(wycheproof::aead::TestName::AesGcm).unwrap();
33 //!
34 //!     for test_group in test_set.test_groups {
35 //!         println!(
36 //!             "* Group key size:{} tag size:{} nonce size:{}",
37 //!             test_group.key_size, test_group.tag_size, test_group.nonce_size,
38 //!         );
39 //!         for test in test_group.tests {
40 //!             println!(
41 //!                 "Test:{} Key:{} AAD:{} PT:{} CT:{} Tag:{}",
42 //!                 test.tc_id,
43 //!                 hex::encode(test.key),
44 //!                 hex::encode(test.aad),
45 //!                 hex::encode(test.pt),
46 //!                 hex::encode(test.ct),
47 //!                 hex::encode(test.tag)
48 //!             );
49 //!         }
50 //!     }
51 //! }
52 //! ```
53 //!
54 //! ```
55 //! // Iterate over all of the AEAD tests
56 //! for aead in wycheproof::aead::TestName::all() {
57 //!    println!("{:?}", aead);
58 //! }
59 //! ```
60 
61 #![forbid(unsafe_code)]
62 
63 use serde::{de::Error, Deserialize, Deserializer};
64 use std::collections::HashMap;
65 
66 /// The error type
67 #[derive(Debug)]
68 pub enum WycheproofError {
69     /// Named data set was not found
70     NoDataSet,
71     /// The JSON parsed but was found to be invalid somehow
72     InvalidData,
73     /// The JSON parsing failed
74     ParsingFailed(Box<dyn std::error::Error>),
75 }
76 
77 impl std::fmt::Display for WycheproofError {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result78     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
79         match self {
80             Self::NoDataSet => write!(f, "No data set matches provided name"),
81             Self::InvalidData => write!(f, "Data set seems to be invalid"),
82             Self::ParsingFailed(e) => write!(f, "Parsing JSON failed {}", e),
83         }
84     }
85 }
86 
87 impl std::error::Error for WycheproofError {}
88 
vec_from_hex<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error>89 fn vec_from_hex<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
90     let s: &str = Deserialize::deserialize(deserializer)?;
91     hex::decode(s).map_err(D::Error::custom)
92 }
93 
combine_header<'de, D: Deserializer<'de>>(deserializer: D) -> Result<String, D::Error>94 fn combine_header<'de, D: Deserializer<'de>>(deserializer: D) -> Result<String, D::Error> {
95     let h: Vec<String> = Deserialize::deserialize(deserializer)?;
96     let combined = h.join(" ");
97     Ok(combined)
98 }
99 
100 macro_rules! define_typeid {
101     ( $name:ident => $( $tag:expr ),* ) => {
102         #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
103         struct $name {}
104 
105         impl<'de> Deserialize<'de> for $name {
106             fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
107                 let s: &str = Deserialize::deserialize(deserializer)?;
108 
109                 match s {
110                     $(
111                         $tag => Ok(Self {}),
112                     )*
113                     unknown => Err(D::Error::custom(format!("unexpected type {} for {}", unknown, stringify!($name)))),
114                 }
115             }
116         }
117     }
118 }
119 
120 macro_rules! define_algorithm_map {
121     ( $( $json_str:expr => $enum_elem:ident ),* $(,)?) => {
122         #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Deserialize)]
123         pub enum Algorithm {
124             $(
125                 #[serde(rename = $json_str)]
126                 $enum_elem,
127             )*
128         }
129     }
130 }
131 
132 macro_rules! define_test_set_names {
133     ( $( $enum_name:ident => $test_name:expr ),* $(,)?) => {
134         #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Deserialize)]
135         pub enum TestName {
136             $(
137                 $enum_name,
138             )*
139         }
140 
141         impl TestName {
142             pub fn json_data(&self) -> &'static str {
143                 match self {
144                     $(
145                         Self::$enum_name => include_str!(concat!("data/", $test_name, "_test.json")),
146                     )*
147                 }
148             }
149 
150             pub fn all() -> Vec<TestName> {
151                 vec![
152                     $(
153                         Self::$enum_name,
154                     )*
155                 ]
156             }
157         }
158 
159         impl std::str::FromStr for TestName {
160             type Err = WycheproofError;
161 
162             fn from_str(s: &str) -> Result<Self, Self::Err> {
163                 match s {
164                     $(
165                         $test_name => Ok(Self::$enum_name),
166                     )*
167                         _ => Err(WycheproofError::NoDataSet),
168                 }
169             }
170         }
171     }
172 }
173 
174 macro_rules! define_test_flags {
175     ( $( $flag:ident ),* $(,)?) => {
176         #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Deserialize)]
177         pub enum TestFlag {
178             $(
179                 $flag,
180             )*
181         }
182     }
183 }
184 
185 macro_rules! define_test_group {
186     ( $( $($json_name:literal =>)? $field_name:ident: $type:ty $(| $deser_fn:expr)? ),* $(,)?) => {
187         #[derive(Debug, Clone, Hash, Eq, PartialEq, Deserialize)]
188         #[serde(deny_unknown_fields)]
189         pub struct TestGroup {
190             $(
191             $(#[serde(deserialize_with = $deser_fn)])?
192             $(#[serde(rename = $json_name)])?
193             pub $field_name: $type,
194             )*
195             #[serde(rename = "type")]
196             typ: TestGroupTypeId,
197             pub tests: Vec<Test>,
198         }
199     }
200 }
201 
202 macro_rules! define_test {
203     ( $( $($json_name:literal =>)? $field_name:ident: $type:ty ),* $(,)?) => {
204         #[derive(Debug, Clone, Hash, Eq, PartialEq, Deserialize)]
205         #[serde(deny_unknown_fields)]
206         pub struct Test {
207             #[serde(rename = "tcId")]
208             pub tc_id: usize,
209             pub comment: String,
210             $(
211             #[serde(deserialize_with = "vec_from_hex")]
212             $(#[serde(rename = $json_name)])?
213             pub $field_name: $type,
214             )*
215             pub result: TestResult,
216             #[serde(default)]
217             pub flags: Vec<TestFlag>,
218         }
219     }
220 }
221 
222 macro_rules! define_test_ex {
223     ( $( $($json_name:literal =>)? $field_name:ident: $type:ty $(| $deser_fn:expr)? ),* $(,)?) => {
224         #[derive(Debug, Clone, Hash, Eq, PartialEq, Deserialize)]
225         #[serde(deny_unknown_fields)]
226         pub struct Test {
227             #[serde(rename = "tcId")]
228             pub tc_id: usize,
229             pub comment: String,
230             $(
231             $(#[serde(deserialize_with = $deser_fn)])?
232             $(#[serde(rename = $json_name)])?
233             pub $field_name: $type,
234             )*
235             pub result: TestResult,
236             #[serde(default)]
237             pub flags: Vec<TestFlag>,
238         }
239     }
240 }
241 
242 macro_rules! define_test_set {
243     ( $schema_type:expr, $( $schema_name:expr ),* ) => {
244 
245         #[derive(Debug, Clone, Hash, Eq, PartialEq)]
246         pub struct TestSchema {
247             pub schema: String,
248         }
249 
250         impl<'de> Deserialize<'de> for TestSchema {
251             fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
252                 let s: &str = Deserialize::deserialize(deserializer)?;
253 
254                 match s {
255                     $(
256                         $schema_name => Ok(Self { schema: s.to_string() }),
257                     )*
258                         unknown => Err(D::Error::custom(format!("unknown {} schema {}", $schema_type, unknown))),
259                 }
260             }
261         }
262 
263         #[doc = "A group of "]
264         #[doc = $schema_type]
265         #[doc = " tests."]
266         #[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
267         #[serde(deny_unknown_fields)]
268         pub struct TestSet {
269             pub algorithm: Algorithm,
270             #[serde(rename = "generatorVersion")]
271             pub generator_version: String,
272             #[serde(rename = "numberOfTests")]
273             pub number_of_tests: usize,
274             #[serde(deserialize_with = "combine_header")]
275             pub header: String,
276             pub notes: HashMap<TestFlag, String>,
277             schema: TestSchema,
278             #[serde(rename = "testGroups")]
279             pub test_groups: Vec<TestGroup>,
280         }
281 
282         impl TestSet {
283             fn check(obj: Self) -> Result<Self, WycheproofError> {
284                 let actual_number_of_tests: usize =
285                     obj.test_groups.iter().map(|tg| tg.tests.len()).sum();
286                 if obj.number_of_tests != actual_number_of_tests {
287                     return Err(WycheproofError::InvalidData);
288                 }
289                 Ok(obj)
290             }
291 
292             pub fn load(test: TestName) -> Result<Self, WycheproofError> {
293                 match serde_json::from_str(test.json_data()) {
294                     Ok(set) => Self::check(set),
295                     Err(e) => Err(WycheproofError::ParsingFailed(Box::new(e))),
296                 }
297             }
298         }
299     };
300 }
301 
302 /// The expected result of a Wycheproof test
303 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Deserialize)]
304 pub enum TestResult {
305     /// The test is expected to pass
306     #[serde(rename = "valid")]
307     Valid,
308     /// The test is expected to fail
309     #[serde(rename = "invalid")]
310     Invalid,
311     /// The test is allowed to pass but may reasonably fail for policy reasons
312     /// (eg for a valid signature when the hash function used is too weak)
313     #[serde(rename = "acceptable")]
314     Acceptable,
315 }
316 
317 impl TestResult {
318     /// Return true if this test *must* fail
must_fail(&self) -> bool319     pub fn must_fail(&self) -> bool {
320         match self {
321             Self::Valid => false,
322             Self::Acceptable => false,
323             Self::Invalid => true,
324         }
325     }
326 }
327 
328 /// Prime order elliptic curves
329 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Deserialize)]
330 pub enum EllipticCurve {
331     #[serde(rename = "secp224r1")]
332     Secp224r1,
333     #[serde(rename = "secp256r1", alias = "P-256")]
334     Secp256r1,
335     #[serde(rename = "secp384r1", alias = "P-384")]
336     Secp384r1,
337     #[serde(rename = "secp521r1", alias = "P-521")]
338     Secp521r1,
339 
340     #[serde(rename = "secp224k1")]
341     Secp224k1,
342     #[serde(rename = "secp256k1", alias = "P-256K")]
343     Secp256k1,
344 
345     #[serde(rename = "brainpoolP224r1")]
346     Brainpool224r1,
347     #[serde(rename = "brainpoolP256r1")]
348     Brainpool256r1,
349     #[serde(rename = "brainpoolP320r1")]
350     Brainpool320r1,
351     #[serde(rename = "brainpoolP384r1")]
352     Brainpool384r1,
353     #[serde(rename = "brainpoolP512r1")]
354     Brainpool512r1,
355 
356     #[serde(rename = "brainpoolP224t1")]
357     Brainpool224t1,
358     #[serde(rename = "brainpoolP256t1")]
359     Brainpool256t1,
360     #[serde(rename = "brainpoolP320t1")]
361     Brainpool320t1,
362     #[serde(rename = "brainpoolP384t1")]
363     Brainpool384t1,
364     #[serde(rename = "brainpoolP512t1")]
365     Brainpool512t1,
366 }
367 
368 /// Hash Function identifiers
369 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Deserialize)]
370 pub enum HashFunction {
371     #[serde(rename = "SHA-1")]
372     Sha1,
373 
374     #[serde(rename = "SHA-224")]
375     Sha2_224,
376     #[serde(rename = "SHA-256")]
377     Sha2_256,
378     #[serde(rename = "SHA-384")]
379     Sha2_384,
380     #[serde(rename = "SHA-512")]
381     Sha2_512,
382 
383     #[serde(rename = "SHA-512/224")]
384     Sha2_512_224,
385 
386     #[serde(rename = "SHA-512/256")]
387     Sha2_512_256,
388 
389     #[serde(rename = "SHA3-224")]
390     Sha3_224,
391     #[serde(rename = "SHA3-256")]
392     Sha3_256,
393     #[serde(rename = "SHA3-384")]
394     Sha3_384,
395     #[serde(rename = "SHA3-512")]
396     Sha3_512,
397 }
398 
399 /// MGF identifiers
400 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Deserialize)]
401 pub enum Mgf {
402     #[serde(rename = "MGF1")]
403     Mgf1,
404 }
405 
406 /// Edwards curves
407 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Deserialize)]
408 pub enum EdwardsCurve {
409     #[serde(alias = "edwards25519")]
410     Ed25519,
411     #[serde(alias = "edwards448")]
412     Ed448,
413 }
414 
415 /// Montgomery curves
416 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Deserialize)]
417 pub enum MontgomeryCurve {
418     #[serde(alias = "curve25519")]
419     X25519,
420     #[serde(alias = "curve448")]
421     X448,
422 }
423 
424 mod jwk;
425 pub use jwk::*;
426 
427 pub mod aead;
428 pub mod cipher;
429 pub mod daead;
430 pub mod dsa;
431 pub mod ecdh;
432 pub mod ecdsa;
433 pub mod eddsa;
434 pub mod hkdf;
435 pub mod keywrap;
436 pub mod mac;
437 pub mod mac_with_iv;
438 pub mod primality;
439 pub mod rsa_oaep;
440 pub mod rsa_pkcs1_decrypt;
441 pub mod rsa_pkcs1_sign;
442 pub mod rsa_pkcs1_verify;
443 pub mod rsa_pss_verify;
444 pub mod xdh;
445