k256/arithmetic/field/
field_impl.rs

1//! A debug layer for lazy-reduction field elements making sure
2//! they are not misused. Ensures the correct normalization and checks magnitudes in operations.
3//! Only enabled when `debug_assertions` feature is on.
4
5use crate::FieldBytes;
6use elliptic_curve::{
7    subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
8    zeroize::Zeroize,
9};
10
11#[cfg(target_pointer_width = "32")]
12use super::field_10x26::FieldElement10x26 as FieldElementUnsafeImpl;
13
14#[cfg(target_pointer_width = "64")]
15use super::field_5x52::FieldElement5x52 as FieldElementUnsafeImpl;
16
17#[derive(Clone, Copy, Debug)]
18pub struct FieldElementImpl {
19    value: FieldElementUnsafeImpl,
20    magnitude: u32,
21    normalized: bool,
22}
23
24impl FieldElementImpl {
25    /// Zero element.
26    pub const ZERO: Self = Self {
27        value: FieldElementUnsafeImpl::ZERO,
28        magnitude: 1,
29        normalized: true,
30    };
31
32    /// Multiplicative identity.
33    pub const ONE: Self = Self {
34        value: FieldElementUnsafeImpl::ONE,
35        magnitude: 1,
36        normalized: true,
37    };
38
39    const fn new_normalized(value: &FieldElementUnsafeImpl) -> Self {
40        Self {
41            value: *value,
42            magnitude: 1,
43            normalized: true,
44        }
45    }
46
47    const fn new_weak_normalized(value: &FieldElementUnsafeImpl) -> Self {
48        Self {
49            value: *value,
50            magnitude: 1,
51            normalized: false,
52        }
53    }
54
55    fn new(value: &FieldElementUnsafeImpl, magnitude: u32) -> Self {
56        debug_assert!(magnitude <= FieldElementUnsafeImpl::max_magnitude());
57        Self {
58            value: *value,
59            magnitude,
60            normalized: false,
61        }
62    }
63
64    pub(crate) const fn from_bytes_unchecked(bytes: &[u8; 32]) -> Self {
65        let value = FieldElementUnsafeImpl::from_bytes_unchecked(bytes);
66        Self::new_normalized(&value)
67    }
68
69    pub(crate) const fn from_u64(val: u64) -> Self {
70        Self::new_normalized(&FieldElementUnsafeImpl::from_u64(val))
71    }
72
73    pub fn from_bytes(bytes: &FieldBytes) -> CtOption<Self> {
74        let value = FieldElementUnsafeImpl::from_bytes(bytes);
75        CtOption::map(value, |x| Self::new_normalized(&x))
76    }
77
78    pub fn to_bytes(self) -> FieldBytes {
79        debug_assert!(self.normalized);
80        self.value.to_bytes()
81    }
82
83    pub fn normalize_weak(&self) -> Self {
84        Self::new_weak_normalized(&self.value.normalize_weak())
85    }
86
87    pub fn normalize(&self) -> Self {
88        Self::new_normalized(&self.value.normalize())
89    }
90
91    pub fn normalizes_to_zero(&self) -> Choice {
92        self.value.normalizes_to_zero()
93    }
94
95    pub fn is_zero(&self) -> Choice {
96        debug_assert!(self.normalized);
97        self.value.is_zero()
98    }
99
100    pub fn is_odd(&self) -> Choice {
101        debug_assert!(self.normalized);
102        self.value.is_odd()
103    }
104
105    pub fn negate(&self, magnitude: u32) -> Self {
106        debug_assert!(self.magnitude <= magnitude);
107        let new_magnitude = magnitude + 1;
108        debug_assert!(new_magnitude <= FieldElementUnsafeImpl::max_magnitude());
109        Self::new(&(self.value.negate(magnitude)), new_magnitude)
110    }
111
112    pub fn add(&self, rhs: &Self) -> Self {
113        let new_magnitude = self.magnitude + rhs.magnitude;
114        debug_assert!(new_magnitude <= FieldElementUnsafeImpl::max_magnitude());
115        Self::new(&(self.value.add(&(rhs.value))), new_magnitude)
116    }
117
118    pub fn mul_single(&self, rhs: u32) -> Self {
119        let new_magnitude = self.magnitude * rhs;
120        debug_assert!(new_magnitude <= FieldElementUnsafeImpl::max_magnitude());
121        Self::new(&(self.value.mul_single(rhs)), new_magnitude)
122    }
123
124    /// Returns self * rhs mod p
125    pub fn mul(&self, rhs: &Self) -> Self {
126        debug_assert!(self.magnitude <= 8);
127        debug_assert!(rhs.magnitude <= 8);
128        Self::new_weak_normalized(&(self.value.mul(&(rhs.value))))
129    }
130
131    /// Returns self * self mod p
132    pub fn square(&self) -> Self {
133        debug_assert!(self.magnitude <= 8);
134        Self::new_weak_normalized(&(self.value.square()))
135    }
136}
137
138impl Default for FieldElementImpl {
139    fn default() -> Self {
140        Self::ZERO
141    }
142}
143
144impl ConditionallySelectable for FieldElementImpl {
145    #[inline(always)]
146    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
147        // 1. It's debug only, so it shouldn't present a security risk
148        // 2. Being normalized does is independent from the field element value;
149        //    elements must be normalized explicitly.
150        let new_normalized = if bool::from(choice) {
151            b.normalized
152        } else {
153            a.normalized
154        };
155        Self {
156            value: FieldElementUnsafeImpl::conditional_select(&(a.value), &(b.value), choice),
157            magnitude: u32::conditional_select(&(a.magnitude), &(b.magnitude), choice),
158            normalized: new_normalized,
159        }
160    }
161}
162
163impl ConstantTimeEq for FieldElementImpl {
164    fn ct_eq(&self, other: &Self) -> Choice {
165        self.value.ct_eq(&(other.value))
166            & self.magnitude.ct_eq(&(other.magnitude))
167            // See the comment in `conditional_select()`
168            & Choice::from((self.normalized == other.normalized) as u8)
169    }
170}
171
172impl Zeroize for FieldElementImpl {
173    fn zeroize(&mut self) {
174        self.value.zeroize();
175        self.magnitude.zeroize();
176        self.normalized.zeroize();
177    }
178}