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 zeroize::{Zeroize, ZeroizeOnDrop};
8
9#[derive(Clone, Zeroize, ZeroizeOnDrop, Debug)]
14pub struct Scalar(SecretBuffer<P384_SCALAR_SIZE>);
15
16impl Scalar {
17 pub fn new(mut data: [u8; P384_SCALAR_SIZE]) -> Result<Self> {
23 Self::reduce_scalar_bytes(&mut data)?;
24 Ok(Scalar(SecretBuffer::new(data)))
25 }
26
27 fn from_bytes_unchecked(bytes: [u8; P384_SCALAR_SIZE]) -> Self {
32 Scalar(SecretBuffer::new(bytes))
33 }
34
35 pub fn from_secret_buffer(buffer: SecretBuffer<P384_SCALAR_SIZE>) -> Result<Self> {
40 let mut bytes = [0u8; P384_SCALAR_SIZE];
41 bytes.copy_from_slice(buffer.as_ref());
42
43 Self::reduce_scalar_bytes(&mut bytes)?;
44 Ok(Scalar(SecretBuffer::new(bytes)))
45 }
46
47 pub fn as_secret_buffer(&self) -> &SecretBuffer<P384_SCALAR_SIZE> {
49 &self.0
50 }
51
52 pub fn serialize(&self) -> [u8; P384_SCALAR_SIZE] {
57 let mut result = [0u8; P384_SCALAR_SIZE];
58 result.copy_from_slice(self.0.as_ref());
59 result
60 }
61
62 pub fn deserialize(bytes: &[u8]) -> Result<Self> {
67 validate::length("P-384 Scalar", bytes.len(), P384_SCALAR_SIZE)?;
68
69 let mut scalar_bytes = [0u8; P384_SCALAR_SIZE];
70 scalar_bytes.copy_from_slice(bytes);
71
72 Self::new(scalar_bytes)
73 }
74
75 pub fn is_zero(&self) -> bool {
80 self.0.as_ref().iter().all(|&b| b == 0)
81 }
82
83 #[inline(always)]
85 fn to_le_limbs(bytes_be: &[u8; 48]) -> [u32; 12] {
86 let mut limbs = [0u32; 12];
87 for (i, limb) in limbs.iter_mut().enumerate() {
88 let start = 44 - i * 4;
90 *limb = u32::from_le_bytes([
91 bytes_be[start + 3],
92 bytes_be[start + 2],
93 bytes_be[start + 1],
94 bytes_be[start],
95 ]);
96 }
97 limbs
98 }
99
100 #[inline(always)]
103 fn limbs_to_be(limbs: &[u32; 12]) -> [u8; 48] {
104 let mut out = [0u8; 48];
105 for (i, &w) in limbs.iter().enumerate() {
106 let le = w.to_le_bytes();
107 let start = 44 - i * 4;
108 out[start] = le[3];
109 out[start + 1] = le[2];
110 out[start + 2] = le[1];
111 out[start + 3] = le[0];
112 }
113 out
114 }
115
116 pub fn add_mod_n(&self, other: &Self) -> Result<Self> {
118 let a = Self::to_le_limbs(&self.serialize());
119 let b = Self::to_le_limbs(&other.serialize());
120
121 let mut r = [0u32; 12];
122 let mut carry = 0u64;
123
124 for i in 0..12 {
126 let tmp = a[i] as u64 + b[i] as u64 + carry;
127 r[i] = tmp as u32;
128 carry = tmp >> 32;
129 }
130
131 if carry == 1 || Self::geq(&r, &Self::N_LIMBS) {
133 Self::sub_in_place(&mut r, &Self::N_LIMBS);
134 }
135
136 Ok(Self::from_bytes_unchecked(Self::limbs_to_be(&r)))
137 }
138
139 pub fn sub_mod_n(&self, other: &Self) -> Result<Self> {
141 let a = Self::to_le_limbs(&self.serialize());
142 let b = Self::to_le_limbs(&other.serialize());
143
144 let mut r = [0u32; 12];
145 let mut borrow = 0i64;
146
147 for (i, r_limb) in r.iter_mut().enumerate() {
148 let tmp = a[i] as i64 - b[i] as i64 - borrow;
149 if tmp < 0 {
150 *r_limb = (tmp + (1i64 << 32)) as u32;
151 borrow = 1;
152 } else {
153 *r_limb = tmp as u32;
154 borrow = 0;
155 }
156 }
157
158 if borrow == 1 {
160 let mut c = 0u64;
161 for (i, r_limb) in r.iter_mut().enumerate() {
162 let tmp = *r_limb as u64 + Self::N_LIMBS[i] as u64 + c;
163 *r_limb = tmp as u32;
164 c = tmp >> 32;
165 }
166 }
167
168 Ok(Self::from_bytes_unchecked(Self::limbs_to_be(&r)))
169 }
170
171 pub fn mul_mod_n(&self, other: &Self) -> Result<Self> {
176 let mut acc = Self::from_bytes_unchecked([0u8; P384_SCALAR_SIZE]);
178
179 for byte in other.serialize() {
181 for i in (0..8).rev() {
182 acc = acc.add_mod_n(&acc)?;
185
186 if (byte >> i) & 1 == 1 {
188 acc = acc.add_mod_n(self)?;
189 }
190 }
191 }
192
193 Ok(acc)
194 }
195
196 pub fn inv_mod_n(&self) -> Result<Self> {
198 if self.is_zero() {
200 return Err(Error::param("P-384 Scalar", "Cannot invert zero scalar"));
201 }
202
203 const N_MINUS_2: [u8; 48] = [
207 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
208 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x63, 0x4D, 0x81,
209 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC,
210 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x71,
211 ];
212
213 let mut one_bytes = [0x00; 48];
214 one_bytes[47] = 0x01;
215 let mut result = Self::new(one_bytes)?;
216 let base = self.clone();
217
218 for byte in N_MINUS_2 {
219 for bit in (0..8).rev() {
220 result = result.mul_mod_n(&result)?;
221 if (byte >> bit) & 1 == 1 {
222 result = result.mul_mod_n(&base)?;
223 }
224 }
225 }
226
227 Ok(result)
228 }
229
230 pub fn negate(&self) -> Self {
235 if self.is_zero() {
237 return Self::from_bytes_unchecked([0u8; P384_SCALAR_SIZE]);
238 }
239
240 let n_limbs = Self::N_LIMBS;
242 let self_limbs = Self::to_le_limbs(&self.serialize());
243 let mut res = [0u32; 12];
244
245 let mut borrow = 0i64;
247 for i in 0..12 {
248 let tmp = n_limbs[i] as i64 - self_limbs[i] as i64 - borrow;
249 if tmp < 0 {
250 res[i] = (tmp + (1i64 << 32)) as u32;
251 borrow = 1;
252 } else {
253 res[i] = tmp as u32;
254 borrow = 0;
255 }
256 }
257
258 debug_assert_eq!(borrow, 0);
260
261 Self::from_bytes_unchecked(Self::limbs_to_be(&res))
262 }
263
264 fn reduce_scalar_bytes(bytes: &mut [u8; P384_SCALAR_SIZE]) -> Result<()> {
277 let order = &NIST_P384.n;
278
279 if bytes.iter().all(|&b| b == 0) {
281 return Err(Error::param("P-384 Scalar", "Scalar cannot be zero"));
282 }
283
284 let mut gt = 0u8; let mut lt = 0u8; for i in 0..P384_SCALAR_SIZE {
290 let x = bytes[i];
291 let y = order[i];
292 gt |= ((x > y) as u8) & (!lt);
293 lt |= ((x < y) as u8) & (!gt);
294 }
295
296 if gt == 1 || (lt == 0 && gt == 0) {
297 let mut borrow = 0u16;
299 let mut temp_bytes = *bytes;
300
301 for i in (0..P384_SCALAR_SIZE).rev() {
302 let diff = (temp_bytes[i] as i16) - (order[i] as i16) - (borrow as i16);
303 if diff < 0 {
304 temp_bytes[i] = (diff + 256) as u8;
305 borrow = 1;
306 } else {
307 temp_bytes[i] = diff as u8;
308 borrow = 0;
309 }
310 }
311
312 *bytes = temp_bytes;
313 }
314
315 if bytes.iter().all(|&b| b == 0) {
317 return Err(Error::param(
318 "P-384 Scalar",
319 "Reduction resulted in zero scalar",
320 ));
321 }
322
323 Ok(())
324 }
325
326 const N_LIMBS: [u32; 12] = [
330 0xCCC5_2973,
331 0xECEC_196A,
332 0x48B0_A77A,
333 0x581A_0DB2,
334 0xF437_2DDF,
335 0xC763_4D81,
336 0xFFFF_FFFF,
337 0xFFFF_FFFF,
338 0xFFFF_FFFF,
339 0xFFFF_FFFF,
340 0xFFFF_FFFF,
341 0xFFFF_FFFF,
342 ];
343
344 #[inline(always)]
346 fn geq(a: &[u32; 12], b: &[u32; 12]) -> bool {
347 for i in (0..12).rev() {
348 if a[i] > b[i] {
349 return true;
350 }
351 if a[i] < b[i] {
352 return false;
353 }
354 }
355 true }
357
358 #[inline(always)]
360 fn sub_in_place(a: &mut [u32; 12], b: &[u32; 12]) {
361 let mut borrow = 0u64;
362 for i in 0..12 {
363 let tmp = (a[i] as u64).wrapping_sub(b[i] as u64).wrapping_sub(borrow);
364 a[i] = tmp as u32;
365 borrow = (tmp >> 63) & 1;
366 }
367 }
368}