diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:47:55 +0000 |
commit | 2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4 (patch) | |
tree | 033cc839730fda84ff08db877037977be94e5e3a /vendor/rfc6979/src/ct_cmp.rs | |
parent | Initial commit. (diff) | |
download | cargo-upstream.tar.xz cargo-upstream.zip |
Adding upstream version 0.70.1+ds1.upstream/0.70.1+ds1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/rfc6979/src/ct_cmp.rs')
-rw-r--r-- | vendor/rfc6979/src/ct_cmp.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/vendor/rfc6979/src/ct_cmp.rs b/vendor/rfc6979/src/ct_cmp.rs new file mode 100644 index 0000000..8b216e6 --- /dev/null +++ b/vendor/rfc6979/src/ct_cmp.rs @@ -0,0 +1,87 @@ +//! Constant-time comparison helpers for [`ByteArray`]. + +use crate::{ArrayLength, ByteArray}; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; + +/// Constant-time equals. +pub(crate) fn ct_eq<N: ArrayLength<u8>>(a: &ByteArray<N>, b: &ByteArray<N>) -> Choice { + let mut ret = Choice::from(1); + + for (a, b) in a.iter().zip(b.iter()) { + ret.conditional_assign(&Choice::from(0), !a.ct_eq(b)); + } + + ret +} + +/// Constant-time less than. +/// +/// Inputs are interpreted as big endian integers. +pub(crate) fn ct_lt<N: ArrayLength<u8>>(a: &ByteArray<N>, b: &ByteArray<N>) -> Choice { + let mut borrow = 0; + + // Perform subtraction with borrow a byte-at-a-time, interpreting a + // no-borrow condition as the less-than case + for (&a, &b) in a.iter().zip(b.iter()).rev() { + let c = (b as u16).wrapping_add(borrow >> (u8::BITS - 1)); + borrow = (a as u16).wrapping_sub(c) >> u8::BITS as u8; + } + + !borrow.ct_eq(&0) +} + +#[cfg(test)] +mod tests { + const A: [u8; 4] = [0, 0, 0, 0]; + const B: [u8; 4] = [0, 0, 0, 1]; + const C: [u8; 4] = [0xFF, 0, 0, 0]; + const D: [u8; 4] = [0xFF, 0, 0, 1]; + const E: [u8; 4] = [0xFF, 0xFF, 0xFF, 0xFE]; + const F: [u8; 4] = [0xFF, 0xFF, 0xFF, 0xFF]; + + #[test] + fn ct_eq() { + use super::ct_eq; + + assert_eq!(ct_eq(&A.into(), &A.into()).unwrap_u8(), 1); + assert_eq!(ct_eq(&B.into(), &B.into()).unwrap_u8(), 1); + assert_eq!(ct_eq(&C.into(), &C.into()).unwrap_u8(), 1); + assert_eq!(ct_eq(&D.into(), &D.into()).unwrap_u8(), 1); + assert_eq!(ct_eq(&E.into(), &E.into()).unwrap_u8(), 1); + assert_eq!(ct_eq(&F.into(), &F.into()).unwrap_u8(), 1); + + assert_eq!(ct_eq(&A.into(), &B.into()).unwrap_u8(), 0); + assert_eq!(ct_eq(&C.into(), &D.into()).unwrap_u8(), 0); + assert_eq!(ct_eq(&E.into(), &F.into()).unwrap_u8(), 0); + } + + #[test] + fn ct_lt() { + use super::ct_lt; + + assert_eq!(ct_lt(&A.into(), &A.into()).unwrap_u8(), 0); + assert_eq!(ct_lt(&B.into(), &B.into()).unwrap_u8(), 0); + assert_eq!(ct_lt(&C.into(), &C.into()).unwrap_u8(), 0); + assert_eq!(ct_lt(&D.into(), &D.into()).unwrap_u8(), 0); + assert_eq!(ct_lt(&E.into(), &E.into()).unwrap_u8(), 0); + assert_eq!(ct_lt(&F.into(), &F.into()).unwrap_u8(), 0); + + assert_eq!(ct_lt(&A.into(), &B.into()).unwrap_u8(), 1); + assert_eq!(ct_lt(&A.into(), &C.into()).unwrap_u8(), 1); + assert_eq!(ct_lt(&B.into(), &A.into()).unwrap_u8(), 0); + assert_eq!(ct_lt(&C.into(), &A.into()).unwrap_u8(), 0); + + assert_eq!(ct_lt(&B.into(), &C.into()).unwrap_u8(), 1); + assert_eq!(ct_lt(&B.into(), &D.into()).unwrap_u8(), 1); + assert_eq!(ct_lt(&C.into(), &B.into()).unwrap_u8(), 0); + assert_eq!(ct_lt(&D.into(), &B.into()).unwrap_u8(), 0); + + assert_eq!(ct_lt(&C.into(), &D.into()).unwrap_u8(), 1); + assert_eq!(ct_lt(&C.into(), &E.into()).unwrap_u8(), 1); + assert_eq!(ct_lt(&D.into(), &C.into()).unwrap_u8(), 0); + assert_eq!(ct_lt(&E.into(), &C.into()).unwrap_u8(), 0); + + assert_eq!(ct_lt(&E.into(), &F.into()).unwrap_u8(), 1); + assert_eq!(ct_lt(&F.into(), &E.into()).unwrap_u8(), 0); + } +} |