]> git.proxmox.com Git - rustc.git/blobdiff - vendor/constant_time_eq/src/lib.rs
New upstream version 1.52.1+dfsg1
[rustc.git] / vendor / constant_time_eq / src / lib.rs
diff --git a/vendor/constant_time_eq/src/lib.rs b/vendor/constant_time_eq/src/lib.rs
new file mode 100644 (file)
index 0000000..a37121a
--- /dev/null
@@ -0,0 +1,105 @@
+#![no_std]
+
+// This function is non-inline to prevent the optimizer from looking inside it.
+#[inline(never)]
+fn constant_time_ne(a: &[u8], b: &[u8]) -> u8 {
+    assert!(a.len() == b.len());
+
+    // These useless slices make the optimizer elide the bounds checks.
+    // See the comment in clone_from_slice() added on Rust commit 6a7bc47.
+    let len = a.len();
+    let a = &a[..len];
+    let b = &b[..len];
+
+    let mut tmp = 0;
+    for i in 0..len {
+        tmp |= a[i] ^ b[i];
+    }
+    tmp // The compare with 0 must happen outside this function.
+}
+
+/// Compares two equal-sized byte strings in constant time.
+///
+/// # Examples
+///
+/// ```
+/// use constant_time_eq::constant_time_eq;
+///
+/// assert!(constant_time_eq(b"foo", b"foo"));
+/// assert!(!constant_time_eq(b"foo", b"bar"));
+/// assert!(!constant_time_eq(b"bar", b"baz"));
+/// # assert!(constant_time_eq(b"", b""));
+///
+/// // Not equal-sized, so won't take constant time.
+/// assert!(!constant_time_eq(b"foo", b""));
+/// assert!(!constant_time_eq(b"foo", b"quux"));
+/// ```
+#[inline]
+pub fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
+    a.len() == b.len() && constant_time_ne(a, b) == 0
+}
+
+// Fixed-size variants for the most common sizes.
+
+macro_rules! constant_time_ne_n {
+    ($ne:ident, $n:expr) => {
+        // This function is non-inline to prevent the optimizer from looking inside it.
+        #[inline(never)]
+        fn $ne(a: &[u8; $n], b: &[u8; $n]) -> u8 {
+            let mut tmp = 0;
+            for i in 0..$n {
+                tmp |= a[i] ^ b[i];
+            }
+            tmp // The compare with 0 must happen outside this function.
+        }
+    };
+}
+
+constant_time_ne_n!(constant_time_ne_16, 16);
+constant_time_ne_n!(constant_time_ne_32, 32);
+constant_time_ne_n!(constant_time_ne_64, 64);
+
+/// Compares two 128-bit byte strings in constant time.
+///
+/// # Examples
+///
+/// ```
+/// use constant_time_eq::constant_time_eq_16;
+///
+/// assert!(constant_time_eq_16(&[3; 16], &[3; 16]));
+/// assert!(!constant_time_eq_16(&[3; 16], &[7; 16]));
+/// ```
+#[inline]
+pub fn constant_time_eq_16(a: &[u8; 16], b: &[u8; 16]) -> bool {
+    constant_time_ne_16(a, b) == 0
+}
+
+/// Compares two 256-bit byte strings in constant time.
+///
+/// # Examples
+///
+/// ```
+/// use constant_time_eq::constant_time_eq_32;
+///
+/// assert!(constant_time_eq_32(&[3; 32], &[3; 32]));
+/// assert!(!constant_time_eq_32(&[3; 32], &[7; 32]));
+/// ```
+#[inline]
+pub fn constant_time_eq_32(a: &[u8; 32], b: &[u8; 32]) -> bool {
+    constant_time_ne_32(a, b) == 0
+}
+
+/// Compares two 512-bit byte strings in constant time.
+///
+/// # Examples
+///
+/// ```
+/// use constant_time_eq::constant_time_eq_64;
+///
+/// assert!(constant_time_eq_64(&[3; 64], &[3; 64]));
+/// assert!(!constant_time_eq_64(&[3; 64], &[7; 64]));
+/// ```
+#[inline]
+pub fn constant_time_eq_64(a: &[u8; 64], b: &[u8; 64]) -> bool {
+    constant_time_ne_64(a, b) == 0
+}