k256/arithmetic/field/
field_impl.rs
1use 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 pub const ZERO: Self = Self {
27 value: FieldElementUnsafeImpl::ZERO,
28 magnitude: 1,
29 normalized: true,
30 };
31
32 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 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 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 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 & 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}