curve25519-dalek-source/src/util.rs

99 lines
2.5 KiB
Rust
Raw Normal View History

2016-12-08 05:12:00 +00:00
// -*- mode: rust; -*-
//
// To the extent possible under law, the authors have waived all copyright and
// related or neighboring rights to curve25519-dalek, using the Creative
// Commons "CC0" public domain dedication. See
// <http://creativecommons.org/publicdomain/zero/.0/> for full details.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - Henry de Valence <hdevalence@hdevalence.ca>
//! Utility functions and tools for constant-time comparisons.
2017-02-20 22:20:43 +00:00
use core::ops::Neg;
/// Trait for items which can be conditionally assigned in constant time.
pub trait CTAssignable {
/// If `choice == 1u8`, assign `other` to `self`.
/// Otherwise, leave `self` unchanged.
/// Executes in constant time.
fn conditional_assign(&mut self, other: &Self, choice: u8);
}
/// Trait for items which can be conditionally negated in constant time.
///
/// Note: it is not necessary to implement this trait, as a generic
/// implementation is provided.
pub trait CTNegateable
{
/// Conditionally negate an element if `choice == 1u8`.
fn conditional_negate(&mut self, choice: u8);
}
impl<T> CTNegateable for T
2017-02-20 22:20:43 +00:00
where T: CTAssignable, for<'a> &'a T: Neg<Output=T>
{
fn conditional_negate(&mut self, choice: u8) {
// Need to cast to eliminate mutability
let self_neg: T = -(self as &T);
self.conditional_assign(&self_neg, choice);
}
2017-02-20 22:20:43 +00:00
}
2016-12-08 05:12:00 +00:00
/// Check equality of two bytes in constant time.
///
/// # Return
///
/// Returns 1 if `a == b` and 0 otherwise.
#[inline(always)]
pub fn bytes_equal_ct(a: u8, b: u8) -> u8 {
let mut x: u8;
x = !(a ^ b);
x &= x >> 4;
x &= x >> 2;
x &= x >> 1;
x
}
/// Test if a byte is non-zero in constant time.
///
/// ```rust,ignore
/// let mut x: u8;
/// x = 0;
/// assert!(byte_is_nonzero(x));
/// x = 3;
/// assert!(byte_is_nonzero(x) == 1);
/// ```
///
/// # Return
///
/// * If b != 0, returns 1u8.
/// * If b == 0, returns 0u8.
#[inline(always)]
pub fn byte_is_nonzero(b: u8) -> u8 {
let mut x = b;
x |= x >> 4;
x |= x >> 2;
x |= x >> 1;
(x & 1)
}
/// Check equality of two 32-byte arrays in constant time.
///
/// # Return
///
/// Returns 1 if `a == b` and 0 otherwise.
#[inline(always)]
// We don't use this in curve25519-dalek, but it's useful for e.g. an ed25519 implementation.
#[allow(dead_code)]
pub fn arrays_equal_ct(a: &[u8; 32], b: &[u8; 32]) -> u8 {
let mut x: u8 = 0;
for i in 0..32 {
x |= a[i] ^ b[i];
}
bytes_equal_ct(x, 0)
}