dcrypt_algorithms/ec/p224/
scalar.rs1use crate::ec::p224::constants::P224_SCALAR_SIZE;
4use crate::error::{validate, Error, Result};
5use dcrypt_common::security::SecretBuffer;
6use dcrypt_internal::constant_time::{Choice, ConditionallySelectable};
7use dcrypt_internal::zeroing::{Zeroize, ZeroizeOnDrop, Zeroizing};
8use dcrypt_params::traditional::ecdsa::NIST_P224;
9
10#[derive(Clone, Debug)]
15pub struct Scalar(SecretBuffer<P224_SCALAR_SIZE>);
16
17impl Zeroize for Scalar {
18 fn zeroize(&mut self) {
19 self.0.zeroize();
20 }
21}
22
23impl Drop for Scalar {
24 fn drop(&mut self) {
25 self.zeroize();
26 }
27}
28
29impl ZeroizeOnDrop for Scalar {}
30
31impl Scalar {
32 pub fn new(data: [u8; P224_SCALAR_SIZE]) -> Result<Self> {
37 Self::from_secret_buffer(SecretBuffer::new(data))
38 }
39
40 pub fn from_bytes_reduced(data: [u8; P224_SCALAR_SIZE]) -> Self {
47 let mut protected = SecretBuffer::new(data);
48 Self::reduce_scalar_bytes_allow_zero(&mut protected);
49 Self::from_secret_buffer_unchecked(protected)
50 }
51
52 fn from_secret_buffer_unchecked(buffer: SecretBuffer<P224_SCALAR_SIZE>) -> Self {
57 Scalar(buffer)
58 }
59
60 pub fn from_secret_buffer(buffer: SecretBuffer<P224_SCALAR_SIZE>) -> Result<Self> {
65 Self::validate_canonical_nonzero(buffer.as_ref())?;
66 Ok(Self::from_secret_buffer_unchecked(buffer))
67 }
68
69 pub fn as_secret_buffer(&self) -> &SecretBuffer<P224_SCALAR_SIZE> {
71 &self.0
72 }
73
74 pub fn serialize(&self) -> SecretBuffer<P224_SCALAR_SIZE> {
80 self.0.clone()
81 }
82
83 pub fn deserialize(bytes: &[u8]) -> Result<Self> {
88 validate::length("P-224 Scalar", bytes.len(), P224_SCALAR_SIZE)?;
89
90 let mut protected = SecretBuffer::zeroed();
91 protected.as_mut().copy_from_slice(bytes);
92 Self::from_secret_buffer(protected)
93 }
94
95 pub fn is_zero(&self) -> bool {
100 let mut any = 0u8;
101 for &byte in self.0.as_ref() {
102 any |= byte;
103 }
104 any == 0
105 }
106
107 #[inline(always)]
110 fn to_le_limbs(bytes_be: &[u8]) -> Zeroizing<[u32; 7]> {
111 let mut limbs = Zeroizing::new([0u32; 7]);
112
113 for i in 0..7 {
117 let offset = i * 4;
118 limbs[6 - i] = ((bytes_be[offset] as u32) << 24)
119 | ((bytes_be[offset + 1] as u32) << 16)
120 | ((bytes_be[offset + 2] as u32) << 8)
121 | bytes_be[offset + 3] as u32;
122 }
123 limbs
124 }
125
126 #[inline(always)]
129 fn limbs_to_secret_buffer(limbs: &[u32; 7]) -> SecretBuffer<P224_SCALAR_SIZE> {
130 let mut out = SecretBuffer::zeroed();
131
132 for i in 0..7 {
136 let limb = limbs[6 - i];
137 let offset = i * 4;
138 out[offset] = (limb >> 24) as u8;
139 out[offset + 1] = (limb >> 16) as u8;
140 out[offset + 2] = (limb >> 8) as u8;
141 out[offset + 3] = limb as u8;
142 }
143 out
144 }
145
146 pub fn add_mod_n(&self, other: &Self) -> Result<Self> {
148 let self_limbs = Self::to_le_limbs(self.0.as_ref());
149 let other_limbs = Self::to_le_limbs(other.0.as_ref());
150
151 let mut r = Zeroizing::new([0u32; 7]);
152 let mut carry = 0u64;
153
154 for (i, result) in r.iter_mut().enumerate() {
156 let tmp = self_limbs[i] as u64 + other_limbs[i] as u64 + carry;
157 *result = tmp as u32;
158 carry = tmp >> 32;
159 }
160
161 let unreduced = Self::from_secret_buffer_unchecked(Self::limbs_to_secret_buffer(&r));
162 let borrow = Self::sub_in_place(&mut r, &Self::N_LIMBS);
163 let need_reduce = Choice::from((carry as u8) | ((borrow ^ 1) as u8));
164 let reduced = Self::from_secret_buffer_unchecked(Self::limbs_to_secret_buffer(&r));
165
166 Ok(Self::conditional_select(&unreduced, &reduced, need_reduce))
167 }
168
169 pub fn sub_mod_n(&self, other: &Self) -> Result<Self> {
171 let self_limbs = Self::to_le_limbs(self.0.as_ref());
172 let other_limbs = Self::to_le_limbs(other.0.as_ref());
173
174 let mut r = Zeroizing::new([0u32; 7]);
175 let mut borrow = 0u64;
176
177 for (i, result) in r.iter_mut().enumerate() {
178 let tmp = (self_limbs[i] as u64)
179 .wrapping_sub(other_limbs[i] as u64)
180 .wrapping_sub(borrow);
181 *result = tmp as u32;
182 borrow = (tmp >> 63) & 1;
183 }
184
185 let unreduced = Self::from_secret_buffer_unchecked(Self::limbs_to_secret_buffer(&r));
186 let mut carry = 0u64;
187 for (i, result) in r.iter_mut().enumerate() {
188 let tmp = *result as u64 + Self::N_LIMBS[i] as u64 + carry;
189 *result = tmp as u32;
190 carry = tmp >> 32;
191 }
192 let reduced = Self::from_secret_buffer_unchecked(Self::limbs_to_secret_buffer(&r));
193
194 Ok(Self::conditional_select(
195 &unreduced,
196 &reduced,
197 Choice::from(borrow as u8),
198 ))
199 }
200
201 pub fn mul_mod_n(&self, other: &Self) -> Result<Self> {
206 let mut acc = Self::zero();
208
209 for &byte in other.0.as_ref() {
211 for i in (0..8).rev() {
212 acc = acc.add_mod_n(&acc)?;
215
216 let acc_plus_self = acc.add_mod_n(self)?;
217 let choice = Choice::from((byte >> i) & 1);
218 acc = Self::conditional_select(&acc, &acc_plus_self, choice);
219 }
220 }
221
222 Ok(acc)
223 }
224
225 pub fn inv_mod_n(&self) -> Result<Self> {
228 if self.is_zero() {
230 return Err(Error::param("P-224 Scalar", "Cannot invert zero scalar"));
231 }
232
233 let mut exp = Zeroizing::new(NIST_P224.n); let mut borrow = 2u16;
237 for i in (0..P224_SCALAR_SIZE).rev() {
238 let v = exp[i] as i16 - (borrow as i16);
239 if v < 0 {
240 exp[i] = (v + 256) as u8;
241 borrow = 1;
242 } else {
243 exp[i] = v as u8;
244 borrow = 0;
245 }
246 }
247
248 let mut result = { Self::one() };
254 let base = self.clone();
255
256 for &byte in exp.iter() {
257 for bit in (0..8).rev() {
258 result = result.mul_mod_n(&result)?;
260 if (byte >> bit) & 1 == 1 {
262 result = result.mul_mod_n(&base)?;
263 }
264 }
265 }
266
267 Ok(result)
268 }
269
270 pub fn negate(&self) -> Self {
275 let self_limbs = Self::to_le_limbs(self.0.as_ref());
277 let mut res = Zeroizing::new([0u32; 7]);
278
279 let mut borrow = 0u64;
281 for (i, result) in res.iter_mut().enumerate() {
282 let tmp = (Self::N_LIMBS[i] as u64)
283 .wrapping_sub(self_limbs[i] as u64)
284 .wrapping_sub(borrow);
285 *result = tmp as u32;
286 borrow = (tmp >> 63) & 1;
287 }
288 let negated = Self::from_secret_buffer_unchecked(Self::limbs_to_secret_buffer(&res));
289 Self::conditional_select(&negated, &Self::zero(), Choice::from(self.is_zero() as u8))
290 }
291
292 fn validate_canonical_nonzero(bytes: &[u8]) -> Result<()> {
295 let mut any = 0u8;
296 for &byte in bytes {
297 any |= byte;
298 }
299 if any == 0 {
300 return Err(Error::param("P-224 Scalar", "Scalar cannot be zero"));
301 }
302
303 let (_, borrow) = Self::subtract_order(bytes);
304 if borrow == 0 {
305 return Err(Error::param(
306 "P-224 Scalar",
307 "Scalar must be less than the group order",
308 ));
309 }
310
311 Ok(())
312 }
313
314 fn reduce_scalar_bytes_allow_zero(bytes: &mut SecretBuffer<P224_SCALAR_SIZE>) {
316 let (candidate, borrow) = Self::subtract_order(bytes.as_ref());
317 let reduce = Choice::from(borrow ^ 1);
318 *bytes = Self::select_secret_buffer(bytes, &candidate, reduce);
319 }
320
321 #[inline(always)]
322 fn subtract_order(bytes: &[u8]) -> (SecretBuffer<P224_SCALAR_SIZE>, u8) {
323 let mut result = SecretBuffer::zeroed();
324 let mut borrow = 0u8;
325 for i in (0..P224_SCALAR_SIZE).rev() {
326 let (difference, borrow_order) = bytes[i].overflowing_sub(NIST_P224.n[i]);
327 let (difference, borrow_previous) = difference.overflowing_sub(borrow);
328 result[i] = difference;
329 borrow = (borrow_order | borrow_previous) as u8;
330 }
331 (result, borrow)
332 }
333
334 const N_LIMBS: [u32; 7] = [
336 0x5C5C_2A3D,
337 0x13DD_2945,
338 0xE0B8_F03E,
339 0xFFFF_16A2,
340 0xFFFF_FFFF,
341 0xFFFF_FFFF,
342 0xFFFF_FFFF,
343 ];
344
345 #[inline(never)]
346 fn select_secret_buffer(
347 a: &SecretBuffer<P224_SCALAR_SIZE>,
348 b: &SecretBuffer<P224_SCALAR_SIZE>,
349 choice: Choice,
350 ) -> SecretBuffer<P224_SCALAR_SIZE> {
351 let mut out = SecretBuffer::zeroed();
352 for i in 0..P224_SCALAR_SIZE {
353 out[i] = u8::conditional_select(&a[i], &b[i], choice);
354 }
355 out
356 }
357
358 #[inline(always)]
359 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
360 Self::from_secret_buffer_unchecked(Self::select_secret_buffer(&a.0, &b.0, choice))
361 }
362
363 fn zero() -> Self {
364 Self::from_secret_buffer_unchecked(SecretBuffer::zeroed())
365 }
366
367 fn one() -> Self {
368 let mut one = SecretBuffer::zeroed();
369 one[P224_SCALAR_SIZE - 1] = 1;
370 Self::from_secret_buffer_unchecked(one)
371 }
372
373 #[inline(always)]
375 fn sub_in_place(a: &mut [u32; 7], b: &[u32; 7]) -> u64 {
376 let mut borrow = 0u64;
377 for (i, elem) in a.iter_mut().enumerate() {
378 let tmp = (*elem as u64)
379 .wrapping_sub(b[i] as u64)
380 .wrapping_sub(borrow);
381 *elem = tmp as u32;
382 borrow = (tmp >> 63) & 1; }
384 borrow
385 }
386}