1 // Copyright 2020 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 use ring::{constant_time, error, rand};
16 
17 #[cfg(target_arch = "wasm32")]
18 use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure};
19 
20 #[cfg(target_arch = "wasm32")]
21 wasm_bindgen_test_configure!(run_in_browser);
22 
23 // This logic is loosly based on BoringSSL's `TEST(ConstantTimeTest, MemCmp)`.
24 #[test]
test_verify_slices_are_equal()25 fn test_verify_slices_are_equal() {
26     let initial: [u8; 256] = rand::generate(&rand::SystemRandom::new()).unwrap().expose();
27 
28     {
29         let copy = initial;
30         for len in 0..copy.len() {
31             // Not equal because the lengths do not match.
32             assert_eq!(
33                 constant_time::verify_slices_are_equal(&initial, &copy[..len]),
34                 Err(error::Unspecified)
35             );
36             // Equal lengths and equal contents.
37             assert_eq!(
38                 constant_time::verify_slices_are_equal(&initial[..len], &copy[..len]),
39                 Ok(())
40             );
41         }
42         // Equal lengths and equal contents.
43         assert_eq!(
44             constant_time::verify_slices_are_equal(&initial, &copy),
45             Ok(())
46         );
47     }
48 
49     for i in 0..initial.len() {
50         for bit in 0..8 {
51             let mut copy = initial;
52             copy[i] ^= 1u8 << bit;
53 
54             for len in 0..=initial.len() {
55                 // We flipped at least one bit in `copy`.
56                 assert_ne!(&initial[..], &copy[..]);
57 
58                 let a = &initial[..len];
59                 let b = &copy[..len];
60 
61                 let expected_result = if i < len {
62                     // The flipped bit is within `b` so `a` and `b` are not equal.
63                     Err(error::Unspecified)
64                 } else {
65                     // The flipped bit is outside of `b` so `a` and `b` are equal.
66                     Ok(())
67                 };
68                 assert_eq!(a == b, expected_result.is_ok()); // Sanity check.
69                 assert_eq!(
70                     constant_time::verify_slices_are_equal(a, b),
71                     expected_result
72                 );
73                 assert_eq!(
74                     constant_time::verify_slices_are_equal(b, a),
75                     expected_result
76                 );
77             }
78         }
79     }
80 }
81