/rust/registry/src/index.crates.io-1949cf8c6b5b557f/openssl-0.10.62/src/memcmp.rs
Line | Count | Source |
1 | | //! Utilities to safely compare cryptographic values. |
2 | | //! |
3 | | //! Extra care must be taken when comparing values in |
4 | | //! cryptographic code. If done incorrectly, it can lead |
5 | | //! to a [timing attack](https://en.wikipedia.org/wiki/Timing_attack). |
6 | | //! By analyzing the time taken to execute parts of a cryptographic |
7 | | //! algorithm, and attacker can attempt to compromise the |
8 | | //! cryptosystem. |
9 | | //! |
10 | | //! The utilities in this module are designed to be resistant |
11 | | //! to this type of attack. |
12 | | //! |
13 | | //! # Examples |
14 | | //! |
15 | | //! To perform a constant-time comparison of two arrays of the same length but different |
16 | | //! values: |
17 | | //! |
18 | | //! ``` |
19 | | //! use openssl::memcmp::eq; |
20 | | //! |
21 | | //! // We want to compare `a` to `b` and `c`, without giving |
22 | | //! // away through timing analysis that `c` is more similar to `a` |
23 | | //! // than `b`. |
24 | | //! let a = [0, 0, 0]; |
25 | | //! let b = [1, 1, 1]; |
26 | | //! let c = [0, 0, 1]; |
27 | | //! |
28 | | //! // These statements will execute in the same amount of time. |
29 | | //! assert!(!eq(&a, &b)); |
30 | | //! assert!(!eq(&a, &c)); |
31 | | //! ``` |
32 | | use libc::size_t; |
33 | | use openssl_macros::corresponds; |
34 | | |
35 | | /// Returns `true` iff `a` and `b` contain the same bytes. |
36 | | /// |
37 | | /// This operation takes an amount of time dependent on the length of the two |
38 | | /// arrays given, but is independent of the contents of a and b. |
39 | | /// |
40 | | /// # Panics |
41 | | /// |
42 | | /// This function will panic the current task if `a` and `b` do not have the same |
43 | | /// length. |
44 | | /// |
45 | | /// # Examples |
46 | | /// |
47 | | /// To perform a constant-time comparison of two arrays of the same length but different |
48 | | /// values: |
49 | | /// |
50 | | /// ``` |
51 | | /// use openssl::memcmp::eq; |
52 | | /// |
53 | | /// // We want to compare `a` to `b` and `c`, without giving |
54 | | /// // away through timing analysis that `c` is more similar to `a` |
55 | | /// // than `b`. |
56 | | /// let a = [0, 0, 0]; |
57 | | /// let b = [1, 1, 1]; |
58 | | /// let c = [0, 0, 1]; |
59 | | /// |
60 | | /// // These statements will execute in the same amount of time. |
61 | | /// assert!(!eq(&a, &b)); |
62 | | /// assert!(!eq(&a, &c)); |
63 | | /// ``` |
64 | | #[corresponds(CRYPTO_memcmp)] |
65 | 0 | pub fn eq(a: &[u8], b: &[u8]) -> bool { |
66 | 0 | assert!(a.len() == b.len()); |
67 | 0 | let ret = unsafe { |
68 | 0 | ffi::CRYPTO_memcmp( |
69 | 0 | a.as_ptr() as *const _, |
70 | 0 | b.as_ptr() as *const _, |
71 | 0 | a.len() as size_t, |
72 | | ) |
73 | | }; |
74 | 0 | ret == 0 |
75 | 0 | } |
76 | | |
77 | | #[cfg(test)] |
78 | | mod tests { |
79 | | use super::eq; |
80 | | |
81 | | #[test] |
82 | | fn test_eq() { |
83 | | assert!(eq(&[], &[])); |
84 | | assert!(eq(&[1], &[1])); |
85 | | assert!(!eq(&[1, 2, 3], &[1, 2, 4])); |
86 | | } |
87 | | |
88 | | #[test] |
89 | | #[should_panic] |
90 | | fn test_diff_lens() { |
91 | | eq(&[], &[1]); |
92 | | } |
93 | | } |