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_params::traditional::ecdsa::NIST_P224;
7use subtle::{Choice, ConditionallySelectable};
8use zeroize::{Zeroize, ZeroizeOnDrop};
9
10#[derive(Clone, Zeroize, ZeroizeOnDrop, Debug)]
15pub struct Scalar(SecretBuffer<P224_SCALAR_SIZE>);
16
17impl Scalar {
18 pub fn new(mut data: [u8; P224_SCALAR_SIZE]) -> Result<Self> {
24 Self::reduce_scalar_bytes(&mut data)?;
25 Ok(Scalar(SecretBuffer::new(data)))
26 }
27
28 fn from_bytes_unchecked(bytes: [u8; P224_SCALAR_SIZE]) -> Self {
33 Scalar(SecretBuffer::new(bytes))
34 }
35
36 pub fn from_secret_buffer(buffer: SecretBuffer<P224_SCALAR_SIZE>) -> Result<Self> {
41 let mut bytes = [0u8; P224_SCALAR_SIZE];
42 bytes.copy_from_slice(buffer.as_ref());
43
44 Self::reduce_scalar_bytes(&mut bytes)?;
45 Ok(Scalar(SecretBuffer::new(bytes)))
46 }
47
48 pub fn as_secret_buffer(&self) -> &SecretBuffer<P224_SCALAR_SIZE> {
50 &self.0
51 }
52
53 pub fn serialize(&self) -> [u8; P224_SCALAR_SIZE] {
58 let mut result = [0u8; P224_SCALAR_SIZE];
59 result.copy_from_slice(self.0.as_ref());
60 result
61 }
62
63 pub fn deserialize(bytes: &[u8]) -> Result<Self> {
68 validate::length("P-224 Scalar", bytes.len(), P224_SCALAR_SIZE)?;
69
70 let mut scalar_bytes = [0u8; P224_SCALAR_SIZE];
71 scalar_bytes.copy_from_slice(bytes);
72
73 Self::new(scalar_bytes)
74 }
75
76 pub fn is_zero(&self) -> bool {
81 self.0.as_ref().iter().all(|&b| b == 0)
82 }
83
84 #[inline(always)]
87 fn to_le_limbs(bytes_be: &[u8; 28]) -> [u32; 7] {
88 let mut limbs = [0u32; 7];
89
90 for i in 0..7 {
94 let offset = i * 4;
95 limbs[6 - i] = u32::from_be_bytes([
96 bytes_be[offset],
97 bytes_be[offset + 1],
98 bytes_be[offset + 2],
99 bytes_be[offset + 3],
100 ]);
101 }
102 limbs
103 }
104
105 #[inline(always)]
108 fn limbs_to_be(limbs: &[u32; 7]) -> [u8; 28] {
109 let mut out = [0u8; 28];
110
111 for i in 0..7 {
115 let bytes = limbs[6 - i].to_be_bytes();
116 let offset = i * 4;
117 out[offset..offset + 4].copy_from_slice(&bytes);
118 }
119 out
120 }
121
122 pub fn add_mod_n(&self, other: &Self) -> Result<Self> {
124 let self_limbs = Self::to_le_limbs(&self.serialize());
125 let other_limbs = Self::to_le_limbs(&other.serialize());
126
127 let mut r = [0u32; 7];
128 let mut carry = 0u64;
129
130 for (i, result) in r.iter_mut().enumerate() {
132 let tmp = self_limbs[i] as u64 + other_limbs[i] as u64 + carry;
133 *result = tmp as u32;
134 carry = tmp >> 32;
135 }
136
137 let unreduced = Self::from_bytes_unchecked(Self::limbs_to_be(&r));
138 let mut reduced = r;
139 let borrow = Self::sub_in_place(&mut reduced, &Self::N_LIMBS);
140 let need_reduce = Choice::from((carry as u8) | ((borrow ^ 1) as u8));
141
142 Ok(Self::conditional_select(
143 &unreduced,
144 &Self::from_bytes_unchecked(Self::limbs_to_be(&reduced)),
145 need_reduce,
146 ))
147 }
148
149 pub fn sub_mod_n(&self, other: &Self) -> Result<Self> {
151 let self_limbs = Self::to_le_limbs(&self.serialize());
152 let other_limbs = Self::to_le_limbs(&other.serialize());
153
154 let mut r = [0u32; 7];
155 let mut borrow = 0u64;
156
157 for (i, result) in r.iter_mut().enumerate() {
158 let tmp = (self_limbs[i] as u64)
159 .wrapping_sub(other_limbs[i] as u64)
160 .wrapping_sub(borrow);
161 *result = tmp as u32;
162 borrow = (tmp >> 63) & 1;
163 }
164
165 let unreduced = Self::from_bytes_unchecked(Self::limbs_to_be(&r));
166 let mut reduced = r;
167 let mut carry = 0u64;
168 for (i, result) in reduced.iter_mut().enumerate() {
169 let tmp = *result as u64 + Self::N_LIMBS[i] as u64 + carry;
170 *result = tmp as u32;
171 carry = tmp >> 32;
172 }
173
174 Ok(Self::conditional_select(
175 &unreduced,
176 &Self::from_bytes_unchecked(Self::limbs_to_be(&reduced)),
177 Choice::from(borrow as u8),
178 ))
179 }
180
181 pub fn mul_mod_n(&self, other: &Self) -> Result<Self> {
186 let mut acc = Self::from_bytes_unchecked([0u8; P224_SCALAR_SIZE]);
188
189 for byte in other.serialize() {
191 for i in (0..8).rev() {
192 acc = acc.add_mod_n(&acc)?;
195
196 let acc_plus_self = acc.add_mod_n(self)?;
197 let choice = Choice::from((byte >> i) & 1);
198 acc = Self::conditional_select(&acc, &acc_plus_self, choice);
199 }
200 }
201
202 Ok(acc)
203 }
204
205 pub fn inv_mod_n(&self) -> Result<Self> {
208 if self.is_zero() {
210 return Err(Error::param("P-224 Scalar", "Cannot invert zero scalar"));
211 }
212
213 let mut exp = NIST_P224.n; let mut borrow = 2u16;
217 for i in (0..P224_SCALAR_SIZE).rev() {
218 let v = exp[i] as i16 - (borrow as i16);
219 if v < 0 {
220 exp[i] = (v + 256) as u8;
221 borrow = 1;
222 } else {
223 exp[i] = v as u8;
224 borrow = 0;
225 }
226 }
227
228 let mut result = {
234 let mut one = [0u8; P224_SCALAR_SIZE];
235 one[P224_SCALAR_SIZE - 1] = 1;
236 Self::from_bytes_unchecked(one)
238 };
239 let base = self.clone();
240
241 for byte in exp {
242 for bit in (0..8).rev() {
243 result = result.mul_mod_n(&result)?;
245 if (byte >> bit) & 1 == 1 {
247 result = result.mul_mod_n(&base)?;
248 }
249 }
250 }
251
252 Ok(result)
253 }
254
255 pub fn negate(&self) -> Self {
260 if self.is_zero() {
262 return Self::from_bytes_unchecked([0u8; P224_SCALAR_SIZE]);
263 }
264
265 let n_limbs = Self::N_LIMBS;
267 let self_limbs = Self::to_le_limbs(&self.serialize());
268 let mut res = [0u32; 7];
269
270 let mut borrow = 0i64;
272 for (i, result) in res.iter_mut().enumerate() {
273 let tmp = n_limbs[i] as i64 - self_limbs[i] as i64 - borrow;
274 if tmp < 0 {
275 *result = (tmp + (1i64 << 32)) as u32;
276 borrow = 1;
277 } else {
278 *result = tmp as u32;
279 borrow = 0;
280 }
281 }
282
283 debug_assert_eq!(borrow, 0);
285
286 Self::from_bytes_unchecked(Self::limbs_to_be(&res))
287 }
288
289 fn reduce_scalar_bytes(bytes: &mut [u8; P224_SCALAR_SIZE]) -> Result<()> {
302 let order = &NIST_P224.n;
303
304 if bytes.iter().all(|&b| b == 0) {
306 return Err(Error::param("P-224 Scalar", "Scalar cannot be zero"));
307 }
308
309 let mut gt = 0u8; let mut lt = 0u8; for i in 0..P224_SCALAR_SIZE {
315 let x = bytes[i];
316 let y = order[i];
317 gt |= ((x > y) as u8) & (!lt);
318 lt |= ((x < y) as u8) & (!gt);
319 }
320 let ge = gt | ((!lt) & 1); if ge == 1 {
323 let mut borrow = 0u16;
325 let mut temp_bytes = *bytes;
326
327 for i in (0..P224_SCALAR_SIZE).rev() {
328 let diff = (temp_bytes[i] as i16) - (order[i] as i16) - (borrow as i16);
329 if diff < 0 {
330 temp_bytes[i] = (diff + 256) as u8;
331 borrow = 1;
332 } else {
333 temp_bytes[i] = diff as u8;
334 borrow = 0;
335 }
336 }
337
338 *bytes = temp_bytes;
339 }
340
341 if bytes.iter().all(|&b| b == 0) {
343 return Err(Error::param(
344 "P-224 Scalar",
345 "Reduction resulted in zero scalar",
346 ));
347 }
348
349 Ok(())
350 }
351
352 const N_LIMBS: [u32; 7] = [
354 0x5C5C_2A3D,
355 0x13DD_2945,
356 0xE0B8_F03E,
357 0xFFFF_16A2,
358 0xFFFF_FFFF,
359 0xFFFF_FFFF,
360 0xFFFF_FFFF,
361 ];
362
363 #[inline(always)]
364 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
365 let a_bytes = a.serialize();
366 let b_bytes = b.serialize();
367 let mut out = [0u8; P224_SCALAR_SIZE];
368 for i in 0..P224_SCALAR_SIZE {
369 out[i] = u8::conditional_select(&a_bytes[i], &b_bytes[i], choice);
370 }
371 Self::from_bytes_unchecked(out)
372 }
373
374 #[inline(always)]
376 fn geq(a: &[u32; 7], b: &[u32; 7]) -> bool {
377 for i in (0..7).rev() {
378 if a[i] > b[i] {
379 return true;
380 }
381 if a[i] < b[i] {
382 return false;
383 }
384 }
385 true }
387
388 #[inline(always)]
390 fn sub_in_place(a: &mut [u32; 7], b: &[u32; 7]) -> u64 {
391 let mut borrow = 0u64;
392 for (i, elem) in a.iter_mut().enumerate() {
393 let tmp = (*elem as u64)
394 .wrapping_sub(b[i] as u64)
395 .wrapping_sub(borrow);
396 *elem = tmp as u32;
397 borrow = (tmp >> 63) & 1; }
399 borrow
400 }
401}