dcrypt_algorithms/ec/p192/
scalar.rs1use crate::ec::p192::constants::P192_SCALAR_SIZE;
4use crate::error::{validate, Error, Result};
5use dcrypt_common::security::SecretBuffer;
6use dcrypt_params::traditional::ecdsa::NIST_P192;
7use subtle::{Choice, ConditionallySelectable};
8use zeroize::{Zeroize, ZeroizeOnDrop};
9
10#[derive(Clone, Zeroize, ZeroizeOnDrop, Debug)]
13pub struct Scalar(SecretBuffer<P192_SCALAR_SIZE>);
14
15impl Scalar {
16 pub fn new(mut data: [u8; P192_SCALAR_SIZE]) -> Result<Self> {
19 Self::reduce_scalar_bytes(&mut data)?;
20 Ok(Scalar(SecretBuffer::new(data)))
21 }
22
23 fn from_bytes_unchecked(bytes: [u8; P192_SCALAR_SIZE]) -> Self {
25 Scalar(SecretBuffer::new(bytes))
26 }
27
28 pub fn from_secret_buffer(buffer: SecretBuffer<P192_SCALAR_SIZE>) -> Result<Self> {
30 let mut tmp = [0u8; P192_SCALAR_SIZE];
31 tmp.copy_from_slice(buffer.as_ref());
32 Self::new(tmp)
33 }
34
35 pub fn as_secret_buffer(&self) -> &SecretBuffer<P192_SCALAR_SIZE> {
37 &self.0
38 }
39
40 pub fn serialize(&self) -> [u8; P192_SCALAR_SIZE] {
42 let mut out = [0u8; P192_SCALAR_SIZE];
43 out.copy_from_slice(self.0.as_ref());
44 out
45 }
46
47 pub fn deserialize(bytes: &[u8]) -> Result<Self> {
49 validate::length("P-192 Scalar", bytes.len(), P192_SCALAR_SIZE)?;
50 let mut tmp = [0u8; P192_SCALAR_SIZE];
51 tmp.copy_from_slice(bytes);
52 Self::new(tmp)
53 }
54
55 pub fn is_zero(&self) -> bool {
57 self.0.as_ref().iter().all(|&b| b == 0)
58 }
59
60 #[inline(always)]
62 fn to_le_limbs(bytes_be: &[u8; 24]) -> [u32; 6] {
63 let mut limbs = [0u32; 6];
64 for (i, limb) in limbs.iter_mut().enumerate() {
65 let offset = (5 - i) * 4; *limb = u32::from_be_bytes([
67 bytes_be[offset],
68 bytes_be[offset + 1],
69 bytes_be[offset + 2],
70 bytes_be[offset + 3],
71 ]);
72 }
73 limbs
74 }
75
76 #[inline(always)]
78 fn limbs_to_be(limbs: &[u32; 6]) -> [u8; 24] {
79 let mut out = [0u8; 24];
80 for (i, &limb) in limbs.iter().enumerate() {
81 let b = limb.to_be_bytes();
82 let offset = (5 - i) * 4;
83 out[offset..offset + 4].copy_from_slice(&b);
84 }
85 out
86 }
87
88 pub fn add_mod_n(&self, other: &Self) -> Result<Self> {
90 let a_limbs = Self::to_le_limbs(&self.serialize());
91 let b_limbs = Self::to_le_limbs(&other.serialize());
92 let mut r = [0u32; 6];
93 let mut carry: u64 = 0;
94 for ((&a_limb, &b_limb), r_limb) in a_limbs.iter().zip(b_limbs.iter()).zip(r.iter_mut()) {
95 let tmp = a_limb as u64 + b_limb as u64 + carry;
96 *r_limb = tmp as u32;
97 carry = tmp >> 32;
98 }
99 let unreduced = Self::from_bytes_unchecked(Self::limbs_to_be(&r));
100 let mut reduced = r;
101 let borrow = Self::sub_in_place(&mut reduced, &Self::N_LIMBS);
102 let need_reduce = Choice::from((carry as u8) | ((borrow ^ 1) as u8));
103
104 Ok(Self::conditional_select(
105 &unreduced,
106 &Self::from_bytes_unchecked(Self::limbs_to_be(&reduced)),
107 need_reduce,
108 ))
109 }
110
111 pub fn sub_mod_n(&self, other: &Self) -> Result<Self> {
113 let a_limbs = Self::to_le_limbs(&self.serialize());
114 let b_limbs = Self::to_le_limbs(&other.serialize());
115 let mut r = [0u32; 6];
116 let mut borrow: u64 = 0;
117 for ((&a_limb, &b_limb), r_limb) in a_limbs.iter().zip(b_limbs.iter()).zip(r.iter_mut()) {
118 let tmp = (a_limb as u64)
119 .wrapping_sub(b_limb as u64)
120 .wrapping_sub(borrow);
121 *r_limb = tmp as u32;
122 borrow = (tmp >> 63) & 1;
123 }
124 let unreduced = Self::from_bytes_unchecked(Self::limbs_to_be(&r));
125 let mut reduced = r;
126 let mut carry: u64 = 0;
127 for (&n_limb, r_limb) in Self::N_LIMBS.iter().zip(reduced.iter_mut()) {
128 let tmp = *r_limb as u64 + n_limb as u64 + carry;
129 *r_limb = tmp as u32;
130 carry = tmp >> 32;
131 }
132
133 Ok(Self::conditional_select(
134 &unreduced,
135 &Self::from_bytes_unchecked(Self::limbs_to_be(&reduced)),
136 Choice::from(borrow as u8),
137 ))
138 }
139
140 pub fn mul_mod_n(&self, other: &Self) -> Result<Self> {
142 let mut acc = Self::from_bytes_unchecked([0u8; 24]);
143 let self_val = self.clone();
144
145 for &byte in other.serialize().iter() {
146 for i in (0..8).rev() {
147 acc = acc.add_mod_n(&acc)?; let acc_plus_self = acc.add_mod_n(&self_val)?; let choice = Choice::from((byte >> i) & 1);
150 acc = Self::conditional_select(&acc, &acc_plus_self, choice);
151 }
152 }
153 Ok(acc)
154 }
155
156 pub fn inv_mod_n(&self) -> Result<Self> {
158 if self.is_zero() {
159 return Err(Error::param("P-192 Scalar", "Inverse of zero"));
160 }
161
162 const N_MINUS_2: [u8; 24] = [
165 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE,
166 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x2F,
167 ];
168
169 let mut result = {
171 let mut one = [0u8; 24];
172 one[23] = 1;
173 Scalar::from_bytes_unchecked(one)
174 };
175 let base = self.clone();
176
177 for &byte in N_MINUS_2.iter() {
178 for i in (0..8).rev() {
179 result = result.mul_mod_n(&result)?; if ((byte >> i) & 1) == 1 {
181 result = result.mul_mod_n(&base)?; }
183 }
184 }
185
186 Ok(result)
187 }
188
189 pub fn negate(&self) -> Self {
191 if self.is_zero() {
192 return Self::from_bytes_unchecked([0u8; 24]);
193 }
194 let a_limbs = Self::to_le_limbs(&self.serialize());
195 let mut r = [0u32; 6];
196 let n = Self::N_LIMBS;
197 let mut borrow: i64 = 0;
198 for ((&n_limb, &a_limb), r_limb) in n.iter().zip(a_limbs.iter()).zip(r.iter_mut()) {
199 let tmp = n_limb as i64 - a_limb as i64 - borrow;
200 if tmp < 0 {
201 *r_limb = (tmp + (1i64 << 32)) as u32;
202 borrow = 1;
203 } else {
204 *r_limb = tmp as u32;
205 borrow = 0;
206 }
207 }
208 Self::from_bytes_unchecked(Self::limbs_to_be(&r))
209 }
210
211 fn reduce_scalar_bytes(bytes: &mut [u8; 24]) -> Result<()> {
213 let order = &NIST_P192.n;
214 if bytes.iter().all(|&b| b == 0) {
216 return Err(Error::param("P-192 Scalar", "Scalar cannot be zero"));
217 }
218 let mut gt = 0u8;
220 let mut lt = 0u8;
221 for i in 0..24 {
222 let x = bytes[i];
223 let y = order[i];
224 gt |= ((x > y) as u8) & (!lt);
225 lt |= ((x < y) as u8) & (!gt);
226 }
227 if gt == 1 || (lt == 0 && gt == 0) {
229 let mut borrow = 0u16;
230 for i in (0..24).rev() {
231 let v = (bytes[i] as i16) - (order[i] as i16) - (borrow as i16);
232 if v < 0 {
233 bytes[i] = (v + 256) as u8;
234 borrow = 1;
235 } else {
236 bytes[i] = v as u8;
237 borrow = 0;
238 }
239 }
240 }
241 if bytes.iter().all(|&b| b == 0) {
243 return Err(Error::param("P-192 Scalar", "Reduction resulted in zero"));
244 }
245 Ok(())
246 }
247
248 #[inline(always)]
250 fn geq(a: &[u32; 6], b: &[u32; 6]) -> bool {
251 for i in (0..6).rev() {
252 if a[i] > b[i] {
253 return true;
254 }
255 if a[i] < b[i] {
256 return false;
257 }
258 }
259 true
260 }
261
262 #[inline(always)]
264 fn sub_in_place(a: &mut [u32; 6], b: &[u32; 6]) -> u64 {
265 let mut borrow = 0u64;
266 for (a_limb, &b_limb) in a.iter_mut().zip(b.iter()) {
267 let tmp = (*a_limb as u64)
268 .wrapping_sub(b_limb as u64)
269 .wrapping_sub(borrow);
270 *a_limb = tmp as u32;
271 borrow = (tmp >> 63) & 1;
272 }
273 borrow
274 }
275
276 const N_LIMBS: [u32; 6] = [
279 0xB4D22831, 0x146BC9B1, 0x99DEF836, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, ];
282
283 #[inline(always)]
284 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
285 let a_bytes = a.serialize();
286 let b_bytes = b.serialize();
287 let mut out = [0u8; P192_SCALAR_SIZE];
288 for i in 0..P192_SCALAR_SIZE {
289 out[i] = u8::conditional_select(&a_bytes[i], &b_bytes[i], choice);
290 }
291 Self::from_bytes_unchecked(out)
292 }
293}