From 390aa23db2f99bc30a473250a5bbfe20444bb3d2 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 26 Mar 2019 21:04:51 -0600 Subject: [PATCH] Rename Maybe to CtOption, and do not expose submodule. --- src/{maybe.rs => ctoption.rs} | 78 +++++++++++++++++------------------ src/fq.rs | 14 +++---- src/fr.rs | 14 +++---- src/lib.rs | 8 ++-- 4 files changed, 57 insertions(+), 57 deletions(-) rename src/{maybe.rs => ctoption.rs} (75%) diff --git a/src/maybe.rs b/src/ctoption.rs similarity index 75% rename from src/maybe.rs rename to src/ctoption.rs index 82e64e0..783eeff 100644 --- a/src/maybe.rs +++ b/src/ctoption.rs @@ -1,13 +1,13 @@ -//! This module provides a "Maybe" abstraction as a constant-time +//! This module provides a "CtOption" abstraction as a constant-time //! alternative for APIs that want to return optional values. //! Ideally, this would be merged into upstream `subtle` at some //! point. use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; -/// The `Maybe` type represents an optional value similar to the +/// The `CtOption` type represents an optional value similar to the /// [`Option`](core::option::Option) type but is intended for -/// use in constant time APIs. Any given `Maybe` is either +/// use in constant time APIs. Any given `CtOption` is either /// `Some` or `None`, but unlike `Option` these variants are /// not exposed. The `is_some()` method is used to determine if the /// value is `Some`, and `unwrap_or`/`unwrap_or_else` methods are @@ -21,20 +21,20 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; /// about the result in constant time, and returning an incorrect /// value burdens the caller and increases the chance of bugs. #[derive(Clone, Copy, Debug)] -pub struct Maybe { +pub struct CtOption { value: T, is_some: Choice, } -impl Maybe { - /// This method is used to construct a new `Maybe` and takes +impl CtOption { + /// This method is used to construct a new `CtOption` and takes /// a value of type `T`, and a `Choice` that determines whether /// the optional value should be `Some` or not. If `is_some` is /// false, the value will still be stored but its value is never /// exposed. #[inline] - pub fn new(value: T, is_some: Choice) -> Maybe { - Maybe { value, is_some } + pub fn new(value: T, is_some: Choice) -> CtOption { + CtOption { value, is_some } } /// This returns the underlying value but panics if it @@ -80,7 +80,7 @@ impl Maybe { } /// Returns a `None` value if the option is `None`, otherwise - /// returns a `Maybe` enclosing the value of the provided closure. + /// returns a `CtOption` enclosing the value of the provided closure. /// The closure is given the enclosed value or, if the option is /// `None`, it is provided a dummy value computed using /// `Default::default()`. @@ -88,12 +88,12 @@ impl Maybe { /// This operates in constant time, because the provided closure /// is always called. #[inline] - pub fn map(self, f: F) -> Maybe + pub fn map(self, f: F) -> CtOption where T: Default + ConditionallySelectable, F: FnOnce(T) -> U, { - Maybe::new( + CtOption::new( f(T::conditional_select( &T::default(), &self.value, @@ -111,10 +111,10 @@ impl Maybe { /// This operates in constant time, because the provided closure /// is always called. #[inline] - pub fn and_then(self, f: F) -> Maybe + pub fn and_then(self, f: F) -> CtOption where T: Default + ConditionallySelectable, - F: FnOnce(T) -> Maybe, + F: FnOnce(T) -> CtOption, { let mut tmp = f(T::conditional_select( &T::default(), @@ -127,9 +127,9 @@ impl Maybe { } } -impl ConditionallySelectable for Maybe { +impl ConditionallySelectable for CtOption { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - Maybe::new( + CtOption::new( T::conditional_select(&a.value, &b.value, choice), // TODO: subtle crate currently doesn't implement ConditionallySelectable // for Choice so we must unwrap these manually. @@ -142,11 +142,11 @@ impl ConditionallySelectable for Maybe { } } -impl ConstantTimeEq for Maybe { - /// Two `Maybe`s are equal if they are both `Some` and +impl ConstantTimeEq for CtOption { + /// Two `CtOption`s are equal if they are both `Some` and /// their values are equal, or both `None`. #[inline] - fn ct_eq(&self, rhs: &Maybe) -> Choice { + fn ct_eq(&self, rhs: &CtOption) -> Choice { let a = self.is_some(); let b = rhs.is_some(); @@ -155,11 +155,11 @@ impl ConstantTimeEq for Maybe { } #[test] -fn test_maybe() { - let a = Maybe::new(10, Choice::from(1)); - let b = Maybe::new(9, Choice::from(1)); - let c = Maybe::new(10, Choice::from(0)); - let d = Maybe::new(9, Choice::from(0)); +fn test_ctoption() { + let a = CtOption::new(10, Choice::from(1)); + let b = CtOption::new(9, Choice::from(1)); + let c = CtOption::new(10, Choice::from(0)); + let d = CtOption::new(9, Choice::from(0)); // Test is_some / is_none assert!(bool::from(a.is_some())); @@ -186,16 +186,16 @@ fn test_maybe() { assert!(bool::from(c.ct_eq(&d))); // Test unwrap_or - assert_eq!(Maybe::new(1, Choice::from(1)).unwrap_or(2), 1); - assert_eq!(Maybe::new(1, Choice::from(0)).unwrap_or(2), 2); + assert_eq!(CtOption::new(1, Choice::from(1)).unwrap_or(2), 1); + assert_eq!(CtOption::new(1, Choice::from(0)).unwrap_or(2), 2); // Test unwrap_or_else - assert_eq!(Maybe::new(1, Choice::from(1)).unwrap_or_else(|| 2), 1); - assert_eq!(Maybe::new(1, Choice::from(0)).unwrap_or_else(|| 2), 2); + assert_eq!(CtOption::new(1, Choice::from(1)).unwrap_or_else(|| 2), 1); + assert_eq!(CtOption::new(1, Choice::from(0)).unwrap_or_else(|| 2), 2); // Test map assert_eq!( - Maybe::new(1, Choice::from(1)) + CtOption::new(1, Choice::from(1)) .map(|v| { assert_eq!(v, 1); 2 @@ -204,7 +204,7 @@ fn test_maybe() { 2 ); assert_eq!( - Maybe::new(1, Choice::from(0)) + CtOption::new(1, Choice::from(0)) .map(|_| 2) .is_none() .unwrap_u8(), @@ -213,35 +213,35 @@ fn test_maybe() { // Test and_then assert_eq!( - Maybe::new(1, Choice::from(1)) + CtOption::new(1, Choice::from(1)) .and_then(|v| { assert_eq!(v, 1); - Maybe::new(2, Choice::from(0)) + CtOption::new(2, Choice::from(0)) }) .is_none() .unwrap_u8(), 1 ); assert_eq!( - Maybe::new(1, Choice::from(1)) + CtOption::new(1, Choice::from(1)) .and_then(|v| { assert_eq!(v, 1); - Maybe::new(2, Choice::from(1)) + CtOption::new(2, Choice::from(1)) }) .unwrap(), 2 ); assert_eq!( - Maybe::new(1, Choice::from(0)) - .and_then(|_| Maybe::new(2, Choice::from(0))) + CtOption::new(1, Choice::from(0)) + .and_then(|_| CtOption::new(2, Choice::from(0))) .is_none() .unwrap_u8(), 1 ); assert_eq!( - Maybe::new(1, Choice::from(0)) - .and_then(|_| Maybe::new(2, Choice::from(1))) + CtOption::new(1, Choice::from(0)) + .and_then(|_| CtOption::new(2, Choice::from(1))) .is_none() .unwrap_u8(), 1 @@ -250,8 +250,8 @@ fn test_maybe() { #[test] #[should_panic] -fn unwrap_none_maybe() { +fn unwrap_none_ctoption() { // This test might fail (in release mode?) if the // compiler decides to optimize it away. - Maybe::new(10, Choice::from(0)).unwrap(); + CtOption::new(10, Choice::from(0)).unwrap(); } diff --git a/src/fq.rs b/src/fq.rs index 41fbbf4..bd190fd 100644 --- a/src/fq.rs +++ b/src/fq.rs @@ -4,8 +4,8 @@ use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use byteorder::{ByteOrder, LittleEndian}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; -use crate::maybe::Maybe; use crate::util::{adc, mac, sbb}; +use crate::CtOption; /// Represents an element of `GF(q)`. // The internal representation of this type is four 64-bit unsigned @@ -208,7 +208,7 @@ impl Fq { /// Attempts to convert a little-endian byte representation of /// a field element into an element of `Fq`, failing if the input /// is not canonical (is not smaller than q). - pub fn from_bytes(bytes: [u8; 32]) -> Maybe { + pub fn from_bytes(bytes: [u8; 32]) -> CtOption { let mut tmp = Fq([0, 0, 0, 0]); tmp.0[0] = LittleEndian::read_u64(&bytes[0..8]); @@ -231,7 +231,7 @@ impl Fq { // (a.R^{-1} * R^2) / R = a.R tmp *= &R2; - Maybe::new(tmp, Choice::from(is_some)) + CtOption::new(tmp, Choice::from(is_some)) } /// Converts an element of `Fq` into a byte representation in @@ -324,7 +324,7 @@ impl Fq { } /// Computes the square root of this element, if it exists. - pub fn sqrt(&self) -> Maybe { + pub fn sqrt(&self) -> CtOption { // Tonelli-Shank's algorithm for q mod 16 = 1 // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) @@ -366,7 +366,7 @@ impl Fq { v = k; } - Maybe::new( + CtOption::new( x, (&x * &x).ct_eq(self), // Only return Some if it's the square root. ) @@ -409,7 +409,7 @@ impl Fq { /// Computes the multiplicative inverse of this element, /// failing if the element is zero. - pub fn invert(&self) -> Maybe { + pub fn invert(&self) -> CtOption { #[inline(always)] fn square_assign_multi(n: &mut Fq, num_times: usize) { for _ in 0..num_times { @@ -504,7 +504,7 @@ impl Fq { square_assign_multi(&mut t0, 5); t0.mul_assign(&t1); - Maybe::new(t0, !self.ct_eq(&Self::zero())) + CtOption::new(t0, !self.ct_eq(&Self::zero())) } #[inline] diff --git a/src/fr.rs b/src/fr.rs index 91210be..7f65094 100644 --- a/src/fr.rs +++ b/src/fr.rs @@ -4,8 +4,8 @@ use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use byteorder::{ByteOrder, LittleEndian}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; -use crate::maybe::Maybe; use crate::util::{adc, mac, sbb}; +use crate::CtOption; /// Represents an element of `GF(r)`. // The internal representation of this type is four 64-bit unsigned @@ -190,7 +190,7 @@ impl Fr { /// Attempts to convert a little-endian byte representation of /// a field element into an element of `Fr`, failing if the input /// is not canonical (is not smaller than r). - pub fn from_bytes(bytes: [u8; 32]) -> Maybe { + pub fn from_bytes(bytes: [u8; 32]) -> CtOption { let mut tmp = Fr([0, 0, 0, 0]); tmp.0[0] = LittleEndian::read_u64(&bytes[0..8]); @@ -213,7 +213,7 @@ impl Fr { // (a.R^{-1} * R^2) / R = a.R tmp *= &R2; - Maybe::new(tmp, Choice::from(is_some)) + CtOption::new(tmp, Choice::from(is_some)) } /// Converts an element of `Fr` into a byte representation in @@ -306,7 +306,7 @@ impl Fr { } /// Computes the square root of this element, if it exists. - pub fn sqrt(&self) -> Maybe { + pub fn sqrt(&self) -> CtOption { // Because r = 3 (mod 4) // sqrt can be done with only one exponentiation, // via the computation of self^((r + 1) // 4) (mod r) @@ -317,7 +317,7 @@ impl Fr { 0x039f6d3a994cebea, ]); - Maybe::new( + CtOption::new( sqrt, (&sqrt * &sqrt).ct_eq(self), // Only return Some if it's the square root. ) @@ -360,7 +360,7 @@ impl Fr { /// Computes the multiplicative inverse of this element, /// failing if the element is zero. - pub fn invert(&self) -> Maybe { + pub fn invert(&self) -> CtOption { #[inline(always)] fn square_assign_multi(n: &mut Fr, num_times: usize) { for _ in 0..num_times { @@ -462,7 +462,7 @@ impl Fr { square_assign_multi(&mut t0, 7); t0.mul_assign(&t1); - Maybe::new(t0, !self.ct_eq(&Self::zero())) + CtOption::new(t0, !self.ct_eq(&Self::zero())) } #[inline] diff --git a/src/lib.rs b/src/lib.rs index 6755e51..ba5529b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,8 +41,8 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; #[macro_use] mod util; -pub mod maybe; -use maybe::Maybe; +mod ctoption; +pub use ctoption::CtOption; mod fq; mod fr; @@ -318,7 +318,7 @@ impl AffinePoint { /// Attempts to interpret a byte representation of an /// affine point, failing if the element is not on /// the curve or non-canonical. - pub fn from_bytes(mut b: [u8; 32]) -> Maybe { + pub fn from_bytes(mut b: [u8; 32]) -> CtOption { // Grab the sign bit from the representation let sign = b[31] >> 7; @@ -348,7 +348,7 @@ impl AffinePoint { let u_negated = -u; let final_u = Fq::conditional_select(&u, &u_negated, flip_sign); - Maybe::new(AffinePoint { u: final_u, v }, Choice::from(1u8)) + CtOption::new(AffinePoint { u: final_u, v }, Choice::from(1u8)) }) }) }