dcrypt_algorithms/ec/p384/
scalar.rs1use crate::ec::p384::constants::P384_SCALAR_SIZE;
4use crate::error::{validate, Error, Result};
5use dcrypt_common::security::SecretBuffer;
6use dcrypt_params::traditional::ecdsa::NIST_P384;
7use subtle::{Choice, ConditionallySelectable};
8use zeroize::{Zeroize, ZeroizeOnDrop};
9
10#[derive(Clone, Zeroize, ZeroizeOnDrop, Debug)]
15pub struct Scalar(SecretBuffer<P384_SCALAR_SIZE>);
16
17impl Scalar {
18 pub fn new(mut data: [u8; P384_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; P384_SCALAR_SIZE]) -> Self {
33 Scalar(SecretBuffer::new(bytes))
34 }
35
36 pub fn from_secret_buffer(buffer: SecretBuffer<P384_SCALAR_SIZE>) -> Result<Self> {
41 let mut bytes = [0u8; P384_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<P384_SCALAR_SIZE> {
50 &self.0
51 }
52
53 pub fn serialize(&self) -> [u8; P384_SCALAR_SIZE] {
58 let mut result = [0u8; P384_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-384 Scalar", bytes.len(), P384_SCALAR_SIZE)?;
69
70 let mut scalar_bytes = [0u8; P384_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)]
86 fn to_le_limbs(bytes_be: &[u8; 48]) -> [u32; 12] {
87 let mut limbs = [0u32; 12];
88 for (i, limb) in limbs.iter_mut().enumerate() {
89 let start = 44 - i * 4;
91 *limb = u32::from_le_bytes([
92 bytes_be[start + 3],
93 bytes_be[start + 2],
94 bytes_be[start + 1],
95 bytes_be[start],
96 ]);
97 }
98 limbs
99 }
100
101 #[inline(always)]
104 fn limbs_to_be(limbs: &[u32; 12]) -> [u8; 48] {
105 let mut out = [0u8; 48];
106 for (i, &w) in limbs.iter().enumerate() {
107 let le = w.to_le_bytes();
108 let start = 44 - i * 4;
109 out[start] = le[3];
110 out[start + 1] = le[2];
111 out[start + 2] = le[1];
112 out[start + 3] = le[0];
113 }
114 out
115 }
116
117 pub fn add_mod_n(&self, other: &Self) -> Result<Self> {
119 let a = Self::to_le_limbs(&self.serialize());
120 let b = Self::to_le_limbs(&other.serialize());
121
122 let mut r = [0u32; 12];
123 let mut carry = 0u64;
124
125 for i in 0..12 {
127 let tmp = a[i] as u64 + b[i] as u64 + carry;
128 r[i] = tmp as u32;
129 carry = tmp >> 32;
130 }
131
132 let unreduced = Self::from_bytes_unchecked(Self::limbs_to_be(&r));
133 let mut reduced = r;
134 let borrow = Self::sub_in_place(&mut reduced, &Self::N_LIMBS);
135 let need_reduce = Choice::from((carry as u8) | ((borrow ^ 1) as u8));
136
137 Ok(Self::conditional_select(
138 &unreduced,
139 &Self::from_bytes_unchecked(Self::limbs_to_be(&reduced)),
140 need_reduce,
141 ))
142 }
143
144 pub fn sub_mod_n(&self, other: &Self) -> Result<Self> {
146 let a = Self::to_le_limbs(&self.serialize());
147 let b = Self::to_le_limbs(&other.serialize());
148
149 let mut r = [0u32; 12];
150 let mut borrow = 0u64;
151
152 for (i, r_limb) in r.iter_mut().enumerate() {
153 let tmp = (a[i] as u64).wrapping_sub(b[i] as u64).wrapping_sub(borrow);
154 *r_limb = tmp as u32;
155 borrow = (tmp >> 63) & 1;
156 }
157
158 let unreduced = Self::from_bytes_unchecked(Self::limbs_to_be(&r));
159 let mut reduced = r;
160 let mut carry = 0u64;
161 for (i, r_limb) in reduced.iter_mut().enumerate() {
162 let tmp = *r_limb as u64 + Self::N_LIMBS[i] as u64 + carry;
163 *r_limb = tmp as u32;
164 carry = tmp >> 32;
165 }
166
167 Ok(Self::conditional_select(
168 &unreduced,
169 &Self::from_bytes_unchecked(Self::limbs_to_be(&reduced)),
170 Choice::from(borrow as u8),
171 ))
172 }
173
174 pub fn mul_mod_n(&self, other: &Self) -> Result<Self> {
179 let mut acc = Self::from_bytes_unchecked([0u8; P384_SCALAR_SIZE]);
181
182 for byte in other.serialize() {
184 for i in (0..8).rev() {
185 acc = acc.add_mod_n(&acc)?;
188
189 let acc_plus_self = acc.add_mod_n(self)?;
190 let choice = Choice::from((byte >> i) & 1);
191 acc = Self::conditional_select(&acc, &acc_plus_self, choice);
192 }
193 }
194
195 Ok(acc)
196 }
197
198 pub fn inv_mod_n(&self) -> Result<Self> {
200 if self.is_zero() {
202 return Err(Error::param("P-384 Scalar", "Cannot invert zero scalar"));
203 }
204
205 const N_MINUS_2: [u8; 48] = [
209 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
210 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x63, 0x4D, 0x81,
211 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC,
212 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x71,
213 ];
214
215 let mut one_bytes = [0x00; 48];
216 one_bytes[47] = 0x01;
217 let mut result = Self::new(one_bytes)?;
218 let base = self.clone();
219
220 for byte in N_MINUS_2 {
221 for bit in (0..8).rev() {
222 result = result.mul_mod_n(&result)?;
223 if (byte >> bit) & 1 == 1 {
224 result = result.mul_mod_n(&base)?;
225 }
226 }
227 }
228
229 Ok(result)
230 }
231
232 pub fn negate(&self) -> Self {
237 if self.is_zero() {
239 return Self::from_bytes_unchecked([0u8; P384_SCALAR_SIZE]);
240 }
241
242 let n_limbs = Self::N_LIMBS;
244 let self_limbs = Self::to_le_limbs(&self.serialize());
245 let mut res = [0u32; 12];
246
247 let mut borrow = 0i64;
249 for i in 0..12 {
250 let tmp = n_limbs[i] as i64 - self_limbs[i] as i64 - borrow;
251 if tmp < 0 {
252 res[i] = (tmp + (1i64 << 32)) as u32;
253 borrow = 1;
254 } else {
255 res[i] = tmp as u32;
256 borrow = 0;
257 }
258 }
259
260 debug_assert_eq!(borrow, 0);
262
263 Self::from_bytes_unchecked(Self::limbs_to_be(&res))
264 }
265
266 fn reduce_scalar_bytes(bytes: &mut [u8; P384_SCALAR_SIZE]) -> Result<()> {
279 let order = &NIST_P384.n;
280
281 if bytes.iter().all(|&b| b == 0) {
283 return Err(Error::param("P-384 Scalar", "Scalar cannot be zero"));
284 }
285
286 let mut gt = 0u8; let mut lt = 0u8; for i in 0..P384_SCALAR_SIZE {
292 let x = bytes[i];
293 let y = order[i];
294 gt |= ((x > y) as u8) & (!lt);
295 lt |= ((x < y) as u8) & (!gt);
296 }
297
298 if gt == 1 || (lt == 0 && gt == 0) {
299 let mut borrow = 0u16;
301 let mut temp_bytes = *bytes;
302
303 for i in (0..P384_SCALAR_SIZE).rev() {
304 let diff = (temp_bytes[i] as i16) - (order[i] as i16) - (borrow as i16);
305 if diff < 0 {
306 temp_bytes[i] = (diff + 256) as u8;
307 borrow = 1;
308 } else {
309 temp_bytes[i] = diff as u8;
310 borrow = 0;
311 }
312 }
313
314 *bytes = temp_bytes;
315 }
316
317 if bytes.iter().all(|&b| b == 0) {
319 return Err(Error::param(
320 "P-384 Scalar",
321 "Reduction resulted in zero scalar",
322 ));
323 }
324
325 Ok(())
326 }
327
328 const N_LIMBS: [u32; 12] = [
332 0xCCC5_2973,
333 0xECEC_196A,
334 0x48B0_A77A,
335 0x581A_0DB2,
336 0xF437_2DDF,
337 0xC763_4D81,
338 0xFFFF_FFFF,
339 0xFFFF_FFFF,
340 0xFFFF_FFFF,
341 0xFFFF_FFFF,
342 0xFFFF_FFFF,
343 0xFFFF_FFFF,
344 ];
345
346 #[inline(always)]
347 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
348 let a_bytes = a.serialize();
349 let b_bytes = b.serialize();
350 let mut out = [0u8; P384_SCALAR_SIZE];
351 for i in 0..P384_SCALAR_SIZE {
352 out[i] = u8::conditional_select(&a_bytes[i], &b_bytes[i], choice);
353 }
354 Self::from_bytes_unchecked(out)
355 }
356
357 #[inline(always)]
359 fn geq(a: &[u32; 12], b: &[u32; 12]) -> bool {
360 for i in (0..12).rev() {
361 if a[i] > b[i] {
362 return true;
363 }
364 if a[i] < b[i] {
365 return false;
366 }
367 }
368 true }
370
371 #[inline(always)]
373 fn sub_in_place(a: &mut [u32; 12], b: &[u32; 12]) -> u64 {
374 let mut borrow = 0u64;
375 for i in 0..12 {
376 let tmp = (a[i] as u64).wrapping_sub(b[i] as u64).wrapping_sub(borrow);
377 a[i] = tmp as u32;
378 borrow = (tmp >> 63) & 1;
379 }
380 borrow
381 }
382}