summaryrefslogtreecommitdiffstats
path: root/vendor/rfc6979/src/ct_cmp.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
commit2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4 (patch)
tree033cc839730fda84ff08db877037977be94e5e3a /vendor/rfc6979/src/ct_cmp.rs
parentInitial commit. (diff)
downloadcargo-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.rs87
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);
+ }
+}