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 zeroize::{Zeroize, ZeroizeOnDrop};
8
9#[derive(Clone, Zeroize, ZeroizeOnDrop, Debug)]
12pub struct Scalar(SecretBuffer<P192_SCALAR_SIZE>);
13
14impl Scalar {
15 pub fn new(mut data: [u8; P192_SCALAR_SIZE]) -> Result<Self> {
18 Self::reduce_scalar_bytes(&mut data)?;
19 Ok(Scalar(SecretBuffer::new(data)))
20 }
21
22 fn from_bytes_unchecked(bytes: [u8; P192_SCALAR_SIZE]) -> Self {
24 Scalar(SecretBuffer::new(bytes))
25 }
26
27 pub fn from_secret_buffer(buffer: SecretBuffer<P192_SCALAR_SIZE>) -> Result<Self> {
29 let mut tmp = [0u8; P192_SCALAR_SIZE];
30 tmp.copy_from_slice(buffer.as_ref());
31 Self::new(tmp)
32 }
33
34 pub fn as_secret_buffer(&self) -> &SecretBuffer<P192_SCALAR_SIZE> {
36 &self.0
37 }
38
39 pub fn serialize(&self) -> [u8; P192_SCALAR_SIZE] {
41 let mut out = [0u8; P192_SCALAR_SIZE];
42 out.copy_from_slice(self.0.as_ref());
43 out
44 }
45
46 pub fn deserialize(bytes: &[u8]) -> Result<Self> {
48 validate::length("P-192 Scalar", bytes.len(), P192_SCALAR_SIZE)?;
49 let mut tmp = [0u8; P192_SCALAR_SIZE];
50 tmp.copy_from_slice(bytes);
51 Self::new(tmp)
52 }
53
54 pub fn is_zero(&self) -> bool {
56 self.0.as_ref().iter().all(|&b| b == 0)
57 }
58
59 #[inline(always)]
61 fn to_le_limbs(bytes_be: &[u8; 24]) -> [u32; 6] {
62 let mut limbs = [0u32; 6];
63 for (i, limb) in limbs.iter_mut().enumerate() {
64 let offset = (5 - i) * 4; *limb = u32::from_be_bytes([
66 bytes_be[offset],
67 bytes_be[offset + 1],
68 bytes_be[offset + 2],
69 bytes_be[offset + 3],
70 ]);
71 }
72 limbs
73 }
74
75 #[inline(always)]
77 fn limbs_to_be(limbs: &[u32; 6]) -> [u8; 24] {
78 let mut out = [0u8; 24];
79 for (i, &limb) in limbs.iter().enumerate() {
80 let b = limb.to_be_bytes();
81 let offset = (5 - i) * 4;
82 out[offset..offset + 4].copy_from_slice(&b);
83 }
84 out
85 }
86
87 pub fn add_mod_n(&self, other: &Self) -> Result<Self> {
89 let a_limbs = Self::to_le_limbs(&self.serialize());
90 let b_limbs = Self::to_le_limbs(&other.serialize());
91 let mut r = [0u32; 6];
92 let mut carry: u64 = 0;
93 for ((&a_limb, &b_limb), r_limb) in a_limbs.iter().zip(b_limbs.iter()).zip(r.iter_mut()) {
94 let tmp = a_limb as u64 + b_limb as u64 + carry;
95 *r_limb = tmp as u32;
96 carry = tmp >> 32;
97 }
98 if carry == 1 || Self::geq(&r, &Self::N_LIMBS) {
100 Self::sub_in_place(&mut r, &Self::N_LIMBS);
101 }
102 Ok(Self::from_bytes_unchecked(Self::limbs_to_be(&r)))
103 }
104
105 pub fn sub_mod_n(&self, other: &Self) -> Result<Self> {
107 let a_limbs = Self::to_le_limbs(&self.serialize());
108 let b_limbs = Self::to_le_limbs(&other.serialize());
109 let mut r = [0u32; 6];
110 let mut borrow: i64 = 0;
111 for ((&a_limb, &b_limb), r_limb) in a_limbs.iter().zip(b_limbs.iter()).zip(r.iter_mut()) {
112 let tmp = a_limb as i64 - b_limb as i64 - borrow;
113 if tmp < 0 {
114 *r_limb = (tmp + (1i64 << 32)) as u32;
115 borrow = 1;
116 } else {
117 *r_limb = tmp as u32;
118 borrow = 0;
119 }
120 }
121 if borrow == 1 {
122 let mut c: u64 = 0;
124 for (&n_limb, r_limb) in Self::N_LIMBS.iter().zip(r.iter_mut()) {
125 let tmp = *r_limb as u64 + n_limb as u64 + c;
126 *r_limb = tmp as u32;
127 c = tmp >> 32;
128 }
129 }
130 Ok(Self::from_bytes_unchecked(Self::limbs_to_be(&r)))
131 }
132
133 pub fn mul_mod_n(&self, other: &Self) -> Result<Self> {
135 let mut acc = Self::from_bytes_unchecked([0u8; 24]);
136 let self_val = self.clone();
137
138 for &byte in other.serialize().iter() {
139 for i in (0..8).rev() {
140 acc = acc.add_mod_n(&acc)?; if ((byte >> i) & 1) == 1 {
142 acc = acc.add_mod_n(&self_val)?; }
144 }
145 }
146 Ok(acc)
147 }
148
149 pub fn inv_mod_n(&self) -> Result<Self> {
151 if self.is_zero() {
152 return Err(Error::param("P-192 Scalar", "Inverse of zero"));
153 }
154
155 const N_MINUS_2: [u8; 24] = [
158 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE,
159 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x2F,
160 ];
161
162 let mut result = {
164 let mut one = [0u8; 24];
165 one[23] = 1;
166 Scalar::from_bytes_unchecked(one)
167 };
168 let base = self.clone();
169
170 for &byte in N_MINUS_2.iter() {
171 for i in (0..8).rev() {
172 result = result.mul_mod_n(&result)?; if ((byte >> i) & 1) == 1 {
174 result = result.mul_mod_n(&base)?; }
176 }
177 }
178
179 Ok(result)
180 }
181
182 pub fn negate(&self) -> Self {
184 if self.is_zero() {
185 return Self::from_bytes_unchecked([0u8; 24]);
186 }
187 let a_limbs = Self::to_le_limbs(&self.serialize());
188 let mut r = [0u32; 6];
189 let n = Self::N_LIMBS;
190 let mut borrow: i64 = 0;
191 for ((&n_limb, &a_limb), r_limb) in n.iter().zip(a_limbs.iter()).zip(r.iter_mut()) {
192 let tmp = n_limb as i64 - a_limb as i64 - borrow;
193 if tmp < 0 {
194 *r_limb = (tmp + (1i64 << 32)) as u32;
195 borrow = 1;
196 } else {
197 *r_limb = tmp as u32;
198 borrow = 0;
199 }
200 }
201 Self::from_bytes_unchecked(Self::limbs_to_be(&r))
202 }
203
204 fn reduce_scalar_bytes(bytes: &mut [u8; 24]) -> Result<()> {
206 let order = &NIST_P192.n;
207 if bytes.iter().all(|&b| b == 0) {
209 return Err(Error::param("P-192 Scalar", "Scalar cannot be zero"));
210 }
211 let mut gt = 0u8;
213 let mut lt = 0u8;
214 for i in 0..24 {
215 let x = bytes[i];
216 let y = order[i];
217 gt |= ((x > y) as u8) & (!lt);
218 lt |= ((x < y) as u8) & (!gt);
219 }
220 if gt == 1 || (lt == 0 && gt == 0) {
222 let mut borrow = 0u16;
223 for i in (0..24).rev() {
224 let v = (bytes[i] as i16) - (order[i] as i16) - (borrow as i16);
225 if v < 0 {
226 bytes[i] = (v + 256) as u8;
227 borrow = 1;
228 } else {
229 bytes[i] = v as u8;
230 borrow = 0;
231 }
232 }
233 }
234 if bytes.iter().all(|&b| b == 0) {
236 return Err(Error::param("P-192 Scalar", "Reduction resulted in zero"));
237 }
238 Ok(())
239 }
240
241 #[inline(always)]
243 fn geq(a: &[u32; 6], b: &[u32; 6]) -> bool {
244 for i in (0..6).rev() {
245 if a[i] > b[i] {
246 return true;
247 }
248 if a[i] < b[i] {
249 return false;
250 }
251 }
252 true
253 }
254
255 #[inline(always)]
257 fn sub_in_place(a: &mut [u32; 6], b: &[u32; 6]) {
258 let mut borrow = 0u64;
259 for (a_limb, &b_limb) in a.iter_mut().zip(b.iter()) {
260 let tmp = (*a_limb as u64)
261 .wrapping_sub(b_limb as u64)
262 .wrapping_sub(borrow);
263 *a_limb = tmp as u32;
264 borrow = (tmp >> 63) & 1;
265 }
266 }
267
268 const N_LIMBS: [u32; 6] = [
271 0xB4D22831, 0x146BC9B1, 0x99DEF836, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, ];
274}