1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use core::{
    // cmp::PartialEq,
    fmt::Debug,
    ops::{
        Add,
        AddAssign,
        Neg,
        Sub,
        SubAssign,
        Mul,
        MulAssign,
    },
};

use subtle::{
    ConstantTimeEq,
    ConditionallySelectable,
};

use crate::{
    Error,
    Result,
};

/// Requirements on an implementation of the base field.
///
/// There are *many* ways to implement field arithmetic in
/// the base field of integers modulo 2**255 - 19.
///
/// This trait specifies our requirements, such that end users
/// can experiment with their own ideas.
///
/// This crate, as of now, offers two implementations:
/// - TweetNaCl: a transliteration of the TweetNaCl code to Rust
/// - Haase: a fast implementation in assembly, due to Bjoern Haase
///
/// Planned: Schoolbook: our own attempt at a fast yet readable implementation
///
/// Originally, the plan was to have everything generic over the field
/// implementation, so far we have not been successful in convincing the Rust
/// compiler of this. Therefore, currently the implementations must be selected
/// at compile time using feature flags.
pub trait FieldImplementation
where
    // Self: Sized,
    // Self: Clone,
    Self: Copy,
    // Self: !Copy,  // not sure - curve25519-dalek uses implicit copies, do we want this?

    Self: Debug,
    // Self: Default,  // would want this to return zero I think

    // for<'a, 'b> &'a Self: PartialEq
    Self: ConditionallySelectable,
    for<'b> Self: ConstantTimeEq,

    Self: PartialEq,

    for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
    for<'b> Self: AddAssign<&'b Self>,

    for<'a> &'a Self: Neg<Output = Self>,

    for<'a, 'b> &'a Self: Sub<&'b Self, Output = Self>,
    for<'b> Self: SubAssign<&'b Self>,

    for<'a, 'b> &'a Self: Mul<&'b Self, Output = Self>,
    for<'b> Self: MulAssign<&'b Self>,
    // for<'a> &'a Self: Neg<Output = Self>,
{
    /// Internal representation as limbs
    type Limbs;

    // TODO: maybe have statics outside,
    // and demand functions returning &'static Self instead?
    const ZERO: Self;
    const ONE: Self;
    const D: Self;
    const D2: Self;
    const APLUS2_OVER_FOUR: Self;
    const EDWARDS_BASEPOINT_X: Self;
    const EDWARDS_BASEPOINT_Y: Self;
    const I: Self;
    const MONTGOMERY_BASEPOINT_U: Self;

    // /// swap p and q iff b is true, in constant time
    // // TODO: would be great to mark this with an attribute
    // // like #[constant_time], and have this picked up by a testing
    // // harness, that actually tests this!
    // pub fn conditional_swap(p: &mut FieldElement, q: &mut FieldElement, b: bool);

    // fn reduce(&mut self);

    // /// We don't want to introduce Copy on all our types,
    // /// and be indirect about swap, so we do this ourselves
    // fn conditional_swap(&mut self, other: &mut Self, b: bool);

    /// to canonical representation as little-endian bytes
    fn to_bytes(&self) -> [u8; 32];

    /// construct from possibly non-canonical representation as little-endian bytes
    fn from_unreduced_bytes(bytes: &[u8; 32]) -> Self {
        let unreduced = Self::from_bytes_unchecked(bytes);
        Self::from_bytes_unchecked(&unreduced.to_bytes())
    }

    /// construct from canonical representation as little-endian bytes
    fn from_bytes_unchecked(bytes: &[u8; 32]) -> Self;

    /// construct from canonical representation as little-endian bytes, with validity check
    fn from_bytes(bytes: &[u8; 32]) -> Result<Self> {
        // TODO: convert this into a TryFrom
        let unchecked = Self::from_bytes_unchecked(bytes);
        let canonical_representation = unchecked.to_bytes();
        if bool::from(bytes.ct_eq(&canonical_representation)) {
            Ok(unchecked)
        } else {
            Err(Error::NonCanonicalFieldElement)
        }
    }

    /// parity of field element, viewed as integer modulo 2**255 - 19
    fn parity(&self) -> u8 {
        let d = self.to_bytes();
        d[0] & 1
    }

    /// default implementation, actual implementation may override
    /// this with a faster version
    fn squared(&self) -> Self {
        self * self
    }

    fn inverse(&self) -> Self;
    fn pow2523(&self) -> Self;

}

#[cfg(tweetnacl)]
pub mod tweetnacl;
#[cfg(tweetnacl)]
pub use tweetnacl::{Limbs, FieldElement};

#[cfg(haase)]
pub mod haase;
#[cfg(haase)]
pub use haase::{Limbs, FieldElement};