1#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
9mod scalar_asm {
10 use super::Scalar;
11
12 unsafe extern "C" {
13 fn blvm_secp256k1_scalar_mul_512(l8: *mut u64, a: *const Scalar, b: *const Scalar);
16
17 fn blvm_secp256k1_scalar_reduce_512(r: *mut Scalar, l: *const u64) -> u64;
20 }
21
22 #[inline(always)]
23 pub(super) unsafe fn scalar_mul_512_asm(l: *mut u64, a: *const Scalar, b: *const Scalar) {
24 unsafe {
25 blvm_secp256k1_scalar_mul_512(l, a, b);
26 }
27 }
28
29 #[inline(always)]
30 pub(super) unsafe fn scalar_reduce_512_asm(r: *mut Scalar, l: *const u64) -> u64 {
31 unsafe { blvm_secp256k1_scalar_reduce_512(r, l) }
32 }
33}
34
35use num_bigint::BigUint;
36use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
37
38#[repr(C)]
40#[derive(Clone, Copy, Debug)]
41pub struct Scalar {
42 pub d: [u64; 4],
43}
44
45const N_0: u64 = 0xBFD25E8CD0364141;
47const N_1: u64 = 0xBAAEDCE6AF48A03B;
48const N_2: u64 = 0xFFFFFFFFFFFFFFFE;
49const N_3: u64 = 0xFFFFFFFFFFFFFFFF;
50
51const N_C_0: u64 = 0x402DA1732FC9BEBF;
53const N_C_1: u64 = 0x4551231950B75FC4;
54const N_C_2: u64 = 1;
55
56const N_H_0: u64 = 0xDFE92F46681B20A0;
58const N_H_1: u64 = 0x5D576E7357A4501D;
59const N_H_2: u64 = 0xFFFFFFFFFFFFFFFF;
60const N_H_3: u64 = 0x7FFFFFFFFFFFFFFF;
61
62#[allow(dead_code)]
64const N: Scalar = Scalar {
65 d: [N_0, N_1, N_2, N_3],
66};
67
68const LAMBDA: Scalar = Scalar {
69 d: [
70 0xDF02967C1B23BD72,
71 0x122E22EA20816678,
72 0xA5261C028812645A,
73 0x5363AD4CC05C30E0,
74 ],
75};
76
77impl Scalar {
78 pub fn zero() -> Self {
79 Self { d: [0, 0, 0, 0] }
80 }
81
82 pub fn one() -> Self {
83 Self { d: [1, 0, 0, 0] }
84 }
85
86 pub fn set_int(&mut self, v: u32) {
87 self.d[0] = v as u64;
88 self.d[1] = 0;
89 self.d[2] = 0;
90 self.d[3] = 0;
91 }
92
93 pub fn set_b32(&mut self, bin: &[u8; 32]) -> bool {
95 self.d[0] = read_be64(&bin[24..32]);
96 self.d[1] = read_be64(&bin[16..24]);
97 self.d[2] = read_be64(&bin[8..16]);
98 self.d[3] = read_be64(&bin[0..8]);
99 let overflow = self.check_overflow();
100 self.reduce(overflow as u64);
101 overflow
102 }
103
104 pub fn get_b32(&self, bin: &mut [u8; 32]) {
105 write_be64(&mut bin[0..8], self.d[3]);
106 write_be64(&mut bin[8..16], self.d[2]);
107 write_be64(&mut bin[16..24], self.d[1]);
108 write_be64(&mut bin[24..32], self.d[0]);
109 }
110
111 fn check_overflow(&self) -> bool {
112 let mut yes = 0u64;
113 let mut no = 0u64;
114 no |= (self.d[3] < N_3) as u64;
115 no |= (self.d[2] < N_2) as u64;
116 yes |= (self.d[2] > N_2) as u64 & !no;
117 no |= (self.d[1] < N_1) as u64;
118 yes |= (self.d[1] > N_1) as u64 & !no;
119 yes |= (self.d[0] >= N_0) as u64 & !no;
120 yes != 0
121 }
122
123 fn reduce(&mut self, overflow: u64) {
124 let mut t: u128 = self.d[0] as u128 + (overflow as u128 * N_C_0 as u128);
125 self.d[0] = t as u64;
126 t >>= 64;
127 t += self.d[1] as u128 + (overflow as u128 * N_C_1 as u128);
128 self.d[1] = t as u64;
129 t >>= 64;
130 t += self.d[2] as u128 + (overflow as u128 * N_C_2 as u128);
131 self.d[2] = t as u64;
132 t >>= 64;
133 t += self.d[3] as u128;
134 self.d[3] = t as u64;
135 }
136
137 pub fn is_zero(&self) -> bool {
138 (self.d[0] | self.d[1] | self.d[2] | self.d[3]) == 0
139 }
140
141 pub fn is_one(&self) -> bool {
142 (self.d[0] ^ 1) | self.d[1] | self.d[2] | self.d[3] == 0
143 }
144
145 pub fn is_odd(&self) -> bool {
147 self.d[0] & 1 != 0
148 }
149
150 pub(crate) fn is_even(&self) -> bool {
152 self.d[0] & 1 == 0
153 }
154
155 #[allow(dead_code)]
157 fn sub(&mut self, a: &Scalar, b: &Scalar) {
158 let mut neg_b = Scalar::zero();
159 neg_b.negate(b);
160 self.add(a, &neg_b);
161 }
162
163 #[allow(dead_code)]
165 fn half(&mut self) {
166 self.d[0] = (self.d[0] >> 1) | (self.d[1] << 63);
167 self.d[1] = (self.d[1] >> 1) | (self.d[2] << 63);
168 self.d[2] = (self.d[2] >> 1) | (self.d[3] << 63);
169 self.d[3] >>= 1;
170 }
171
172 #[allow(dead_code)]
174 fn half_add_n(&mut self) {
175 let mut t: u128 = self.d[0] as u128 + N_0 as u128;
176 let c0 = t as u64;
177 let mut c1 = (t >> 64) as u64;
178 t = self.d[1] as u128 + N_1 as u128 + c1 as u128;
179 c1 = t as u64;
180 let mut c2 = (t >> 64) as u64;
181 t = self.d[2] as u128 + N_2 as u128 + c2 as u128;
182 c2 = t as u64;
183 let mut c3 = (t >> 64) as u64;
184 t = self.d[3] as u128 + N_3 as u128 + c3 as u128;
185 c3 = t as u64;
186 let c4 = (t >> 64) as u64;
187 self.d[0] = (c0 >> 1) | (c1 << 63);
188 self.d[1] = (c1 >> 1) | (c2 << 63);
189 self.d[2] = (c2 >> 1) | (c3 << 63);
190 self.d[3] = (c3 >> 1) | (c4 << 63);
191 self.reduce(self.check_overflow() as u64);
192 }
193
194 pub fn div2(&mut self) {
200 let add_mask = 0u64.wrapping_sub(self.d[0] & 1);
202 let mut t: u128 = self.d[0] as u128 + (N_0 & add_mask) as u128;
203 let c0 = t as u64;
204 t >>= 64;
205 t += self.d[1] as u128 + (N_1 & add_mask) as u128;
206 let c1 = t as u64;
207 t >>= 64;
208 t += self.d[2] as u128 + (N_2 & add_mask) as u128;
209 let c2 = t as u64;
210 t >>= 64;
211 t += self.d[3] as u128 + (N_3 & add_mask) as u128;
212 let c3 = t as u64;
213 let c4 = (t >> 64) as u64;
214 self.d[0] = (c0 >> 1) | (c1 << 63);
215 self.d[1] = (c1 >> 1) | (c2 << 63);
216 self.d[2] = (c2 >> 1) | (c3 << 63);
217 self.d[3] = (c3 >> 1) | (c4 << 63);
218 self.reduce(self.check_overflow() as u64);
221 }
222
223 pub fn half_modn(&mut self, a: &Scalar) {
225 *self = *a;
226 self.div2();
227 }
228
229 #[allow(dead_code)]
231 fn add_no_reduce(a: &Scalar, b: &Scalar) -> [u64; 5] {
232 let mut t: u128 = a.d[0] as u128 + b.d[0] as u128;
233 let c0 = t as u64;
234 let mut c1 = (t >> 64) as u64;
235 t = a.d[1] as u128 + b.d[1] as u128 + c1 as u128;
236 c1 = t as u64;
237 let mut c2 = (t >> 64) as u64;
238 t = a.d[2] as u128 + b.d[2] as u128 + c2 as u128;
239 c2 = t as u64;
240 let mut c3 = (t >> 64) as u64;
241 t = a.d[3] as u128 + b.d[3] as u128 + c3 as u128;
242 c3 = t as u64;
243 let c4 = (t >> 64) as u64;
244 [c0, c1, c2, c3, c4]
245 }
246
247 #[allow(dead_code)]
249 fn set_from_5limb_half(&mut self, c: &[u64; 5]) {
250 self.d[0] = (c[0] >> 1) | (c[1] << 63);
251 self.d[1] = (c[1] >> 1) | (c[2] << 63);
252 self.d[2] = (c[2] >> 1) | (c[3] << 63);
253 self.d[3] = (c[3] >> 1) | (c[4] << 63);
254 self.reduce(self.check_overflow() as u64);
255 }
256
257 #[allow(dead_code)]
259 fn sub_half(&mut self, a: &Scalar, b: &Scalar) {
260 self.sub(a, b);
261 self.div2();
262 }
263
264 pub fn add(&mut self, a: &Scalar, b: &Scalar) -> bool {
265 let mut t: u128 = a.d[0] as u128 + b.d[0] as u128;
266 self.d[0] = t as u64;
267 t >>= 64;
268 t += a.d[1] as u128 + b.d[1] as u128;
269 self.d[1] = t as u64;
270 t >>= 64;
271 t += a.d[2] as u128 + b.d[2] as u128;
272 self.d[2] = t as u64;
273 t >>= 64;
274 t += a.d[3] as u128 + b.d[3] as u128;
275 self.d[3] = t as u64;
276 t >>= 64;
277 let overflow = t as u64 + self.check_overflow() as u64;
278 debug_assert!(overflow <= 1);
279 self.reduce(overflow);
280 overflow != 0
281 }
282
283 pub fn negate(&mut self, a: &Scalar) {
284 let nz = a.d[0] | a.d[1] | a.d[2] | a.d[3];
286 let nonzero = 0u64.wrapping_sub((nz != 0) as u64);
287 let mut t: u128 = (!a.d[0]) as u128 + (N_0 + 1) as u128;
288 self.d[0] = (t as u64) & nonzero;
289 t >>= 64;
290 t += (!a.d[1]) as u128 + N_1 as u128;
291 self.d[1] = (t as u64) & nonzero;
292 t >>= 64;
293 t += (!a.d[2]) as u128 + N_2 as u128;
294 self.d[2] = (t as u64) & nonzero;
295 t >>= 64;
296 t += (!a.d[3]) as u128 + N_3 as u128;
297 self.d[3] = (t as u64) & nonzero;
298 }
299
300 pub fn mul(&mut self, a: &Scalar, b: &Scalar) {
301 let mut l = [0u64; 8];
302 scalar_mul_512(&mut l, a, b);
303 scalar_reduce_512(self, &l);
304 }
305
306 pub fn split_lambda(r1: &mut Scalar, r2: &mut Scalar, k: &Scalar) {
308 const MINUS_B1: Scalar = Scalar {
309 d: [
310 (0x6F547FA9u64 << 32) | 0x0ABFE4C3,
311 (0xE4437ED6u64 << 32) | 0x010E8828,
312 0,
313 0,
314 ],
315 };
316 const MINUS_B2: Scalar = Scalar {
317 d: [
318 (0xD765CDA8u64 << 32) | 0x3DB1562C,
319 (0x8A280AC5u64 << 32) | 0x0774346D,
320 (0xFFFFFFFFu64 << 32) | 0xFFFFFFFE,
321 (0xFFFFFFFFu64 << 32) | 0xFFFFFFFF,
322 ],
323 };
324 const G1: Scalar = Scalar {
325 d: [
326 (0xE893209Au64 << 32) | 0x45DBB031,
327 (0x3DAA8A14u64 << 32) | 0x71E8CA7F,
328 (0xE86C90E4u64 << 32) | 0x9284EB15,
329 (0x3086D221u64 << 32) | 0xA7D46BCD,
330 ],
331 };
332 const G2: Scalar = Scalar {
333 d: [
334 (0x1571B4AEu64 << 32) | 0x8AC47F71,
335 (0x221208ACu64 << 32) | 0x9DF506C6,
336 (0x6F547FA9u64 << 32) | 0x0ABFE4C4,
337 (0xE4437ED6u64 << 32) | 0x010E8828,
338 ],
339 };
340
341 let mut c1 = Scalar::zero();
342 let mut c2 = Scalar::zero();
343 scalar_mul_shift_var(&mut c1, k, &G1, 384);
344 scalar_mul_shift_var(&mut c2, k, &G2, 384);
345 let mut t = Scalar::zero();
346 t.mul(&c1, &MINUS_B1);
347 c1 = t;
348 t.mul(&c2, &MINUS_B2);
349 c2 = t;
350 r2.add(&c1, &c2);
351 r1.mul(r2, &LAMBDA);
352 let mut neg = Scalar::zero();
353 neg.negate(r1);
354 r1.add(&neg, k);
355 }
356
357 pub fn get_bits_limb32(&self, offset: u32, count: u32) -> u32 {
360 debug_assert!(count > 0 && count <= 32);
361 debug_assert!((offset + count - 1) >> 6 == offset >> 6);
362 let limb = offset >> 6;
363 let shift = offset & 0x3F;
364 let mask = if count == 32 {
365 u32::MAX
366 } else {
367 (1u32 << count) - 1
368 };
369 ((self.d[limb as usize] >> shift) as u32) & mask
370 }
371
372 pub fn get_bits_var(&self, offset: u32, count: u32) -> u32 {
374 debug_assert!(count > 0 && count <= 32);
375 debug_assert!(offset + count <= 256);
376 if (offset + count - 1) >> 6 == offset >> 6 {
377 self.get_bits_limb32(offset, count)
378 } else {
379 let limb = (offset >> 6) as usize;
380 let shift = offset & 0x3F;
381 let mask = if count == 32 {
382 u32::MAX
383 } else {
384 (1u32 << count) - 1
385 };
386 let lo = self.d[limb] >> shift;
387 let hi = self.d[limb + 1].wrapping_shl(64u32 - shift);
388 ((lo | hi) as u32) & mask
389 }
390 }
391
392 pub fn split_128(r1: &mut Scalar, r2: &mut Scalar, k: &Scalar) {
393 r1.d[0] = k.d[0];
394 r1.d[1] = k.d[1];
395 r1.d[2] = 0;
396 r1.d[3] = 0;
397 r2.d[0] = k.d[2];
398 r2.d[1] = k.d[3];
399 r2.d[2] = 0;
400 r2.d[3] = 0;
401 }
402
403 pub fn inv(&mut self, a: &Scalar) {
407 if a.is_zero() {
408 *self = Scalar::zero();
409 return;
410 }
411 #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
412 {
413 use crate::modinv64::{SECP256K1_SCALAR_MODINV_MODINFO, modinv64};
414 let mut x = scalar_to_signed62(a);
415 modinv64(&mut x, &SECP256K1_SCALAR_MODINV_MODINFO);
416 scalar_from_signed62(self, &x);
417 }
418 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
419 {
420 let a_big = scalar_to_biguint(a);
421 let n_big = scalar_to_biguint(&N);
422 let exp = &n_big - 2u32;
423 let inv_big = a_big.modpow(&exp, &n_big);
424 biguint_to_scalar(self, &inv_big);
425 }
426 }
427
428 pub fn inv_var(&mut self, a: &Scalar) {
430 self.inv(a);
431 }
432
433 pub fn is_high(&self) -> bool {
435 let mut yes = 0u64;
436 let mut no = 0u64;
437 no |= (self.d[3] < N_H_3) as u64;
438 yes |= (self.d[3] > N_H_3) as u64 & !no;
439 no |= (self.d[2] < N_H_2) as u64 & !yes;
440 no |= (self.d[1] < N_H_1) as u64 & !yes;
441 yes |= (self.d[1] > N_H_1) as u64 & !no;
442 yes |= (self.d[0] > N_H_0) as u64 & !no;
443 yes != 0
444 }
445
446 pub fn cond_negate(&mut self, flag: i32) -> i32 {
451 let mask = 0u64.wrapping_sub((flag != 0) as u64); let nonzero = 0u64.wrapping_sub((!self.is_zero()) as u64); let mut t: u128 = (self.d[0] ^ mask) as u128;
455 t += ((N_0 + 1) & mask) as u128;
456 self.d[0] = (t as u64) & nonzero;
457 t >>= 64;
458 t += (self.d[1] ^ mask) as u128;
459 t += (N_1 & mask) as u128;
460 self.d[1] = (t as u64) & nonzero;
461 t >>= 64;
462 t += (self.d[2] ^ mask) as u128;
463 t += (N_2 & mask) as u128;
464 self.d[2] = (t as u64) & nonzero;
465 t >>= 64;
466 t += (self.d[3] ^ mask) as u128;
467 t += (N_3 & mask) as u128;
468 self.d[3] = (t as u64) & nonzero;
469 ((mask >> 63) as i32) * 2 - 1
473 }
474}
475
476impl ConstantTimeEq for Scalar {
477 fn ct_eq(&self, other: &Self) -> Choice {
478 self.d[0].ct_eq(&other.d[0])
479 & self.d[1].ct_eq(&other.d[1])
480 & self.d[2].ct_eq(&other.d[2])
481 & self.d[3].ct_eq(&other.d[3])
482 }
483}
484
485impl ConditionallySelectable for Scalar {
486 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
487 Self {
488 d: [
489 u64::conditional_select(&a.d[0], &b.d[0], choice),
490 u64::conditional_select(&a.d[1], &b.d[1], choice),
491 u64::conditional_select(&a.d[2], &b.d[2], choice),
492 u64::conditional_select(&a.d[3], &b.d[3], choice),
493 ],
494 }
495 }
496}
497
498#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
500fn scalar_to_signed62(a: &Scalar) -> crate::modinv64::Signed62 {
501 const M62: u64 = u64::MAX >> 2;
502 let d = &a.d;
503 crate::modinv64::Signed62 {
504 v: [
505 (d[0] & M62) as i64,
506 ((d[0] >> 62 | d[1] << 2) & M62) as i64,
507 ((d[1] >> 60 | d[2] << 4) & M62) as i64,
508 ((d[2] >> 58 | d[3] << 6) & M62) as i64,
509 (d[3] >> 56) as i64,
510 ],
511 }
512}
513
514#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
516fn scalar_from_signed62(r: &mut Scalar, a: &crate::modinv64::Signed62) {
517 let v = &a.v;
518 r.d[0] = (v[0] as u64) | ((v[1] as u64) << 62);
519 r.d[1] = ((v[1] as u64) >> 2) | ((v[2] as u64) << 60);
520 r.d[2] = ((v[2] as u64) >> 4) | ((v[3] as u64) << 58);
521 r.d[3] = ((v[3] as u64) >> 6) | ((v[4] as u64) << 56);
522}
523
524#[allow(dead_code)]
525fn scalar_to_biguint(s: &Scalar) -> BigUint {
526 let mut bytes = [0u8; 32];
527 s.get_b32(&mut bytes);
528 BigUint::from_bytes_be(&bytes)
529}
530
531#[allow(dead_code)]
532fn biguint_to_scalar(r: &mut Scalar, b: &BigUint) {
533 let bytes = b.to_bytes_be();
534 let mut buf = [0u8; 32];
535 let len = bytes.len().min(32);
536 let start = 32 - len;
537 buf[start..].copy_from_slice(&bytes[..len]);
538 r.set_b32(&buf);
539}
540
541fn read_be64(b: &[u8]) -> u64 {
542 u64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]])
543}
544
545fn write_be64(b: &mut [u8], v: u64) {
546 b[0..8].copy_from_slice(&v.to_be_bytes());
547}
548
549fn scalar_mul_512(l: &mut [u64; 8], a: &Scalar, b: &Scalar) {
550 #[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
551 {
552 unsafe {
553 scalar_asm::scalar_mul_512_asm(l.as_mut_ptr(), a, b);
554 }
555 }
556 #[cfg(not(all(target_arch = "x86_64", not(target_os = "windows"))))]
557 {
558 scalar_mul_512_rust(l, a, b);
559 }
560}
561
562#[cfg(not(all(target_arch = "x86_64", not(target_os = "windows"))))]
563fn scalar_mul_512_rust(l: &mut [u64; 8], a: &Scalar, b: &Scalar) {
564 let mut c0: u64 = 0;
565 let mut c1: u64 = 0;
566 let mut c2: u32 = 0;
567
568 macro_rules! muladd_fast {
569 ($a:expr, $b:expr) => {{
570 let prod = ($a as u128) * ($b as u128);
571 let prod_lo = prod as u64;
572 let prod_hi = (prod >> 64) as u64;
573 let (lo, o) = c0.overflowing_add(prod_lo);
574 c0 = lo;
575 c1 += prod_hi + o as u64; }};
577 }
578 macro_rules! muladd {
579 ($a:expr, $b:expr) => {{
580 let prod = ($a as u128) * ($b as u128);
581 let hi = (prod >> 64) as u64;
582 let (lo, o1) = c0.overflowing_add(prod as u64);
583 c0 = lo;
584 let th = hi + o1 as u64;
585 let (mid, o2) = c1.overflowing_add(th);
586 c1 = mid;
587 c2 += o2 as u32;
588 }};
589 }
590 macro_rules! sumadd {
591 ($a:expr) => {{
592 let (lo, o) = c0.overflowing_add($a);
593 c0 = lo;
594 c1 += o as u64;
595 c2 += (c1 == 0 && o) as u32;
596 }};
597 }
598 macro_rules! extract {
599 () => {{
600 let n = c0;
601 c0 = c1;
602 c1 = c2 as u64;
603 c2 = 0;
604 n
605 }};
606 }
607 macro_rules! extract_fast {
608 () => {{
609 let n = c0;
610 c0 = c1;
611 c1 = 0;
612 n
613 }};
614 }
615
616 muladd_fast!(a.d[0], b.d[0]);
617 l[0] = extract_fast!();
618 muladd!(a.d[0], b.d[1]);
619 muladd!(a.d[1], b.d[0]);
620 l[1] = extract!();
621 muladd!(a.d[0], b.d[2]);
622 muladd!(a.d[1], b.d[1]);
623 muladd!(a.d[2], b.d[0]);
624 l[2] = extract!();
625 muladd!(a.d[0], b.d[3]);
626 muladd!(a.d[1], b.d[2]);
627 muladd!(a.d[2], b.d[1]);
628 muladd!(a.d[3], b.d[0]);
629 l[3] = extract!();
630 muladd!(a.d[1], b.d[3]);
631 muladd!(a.d[2], b.d[2]);
632 muladd!(a.d[3], b.d[1]);
633 l[4] = extract!();
634 muladd!(a.d[2], b.d[3]);
635 muladd!(a.d[3], b.d[2]);
636 l[5] = extract!();
637 muladd_fast!(a.d[3], b.d[3]);
638 l[6] = extract_fast!();
639 l[7] = c0;
640}
641
642#[allow(dead_code)]
643fn limbs_512_to_biguint(l: &[u64; 8]) -> BigUint {
644 let mut acc = BigUint::from(0u64);
645 for (i, &limb) in l.iter().enumerate() {
646 acc += BigUint::from(limb) << (64 * i);
647 }
648 acc
649}
650
651#[cfg(not(all(target_arch = "x86_64", not(target_os = "windows"))))]
654fn scalar_reduce_512_limbs(r: &mut Scalar, l: &[u64; 8]) {
655 let n0 = l[4];
656 let n1 = l[5];
657 let n2 = l[6];
658 let n3 = l[7];
659
660 let mut c0: u64 = l[0];
661 let mut c1: u64 = 0;
662 let mut c2: u32 = 0;
663
664 macro_rules! muladd_fast {
665 ($a:expr, $b:expr) => {{
666 let prod = ($a as u128) * ($b as u128);
667 let (lo, o) = c0.overflowing_add(prod as u64);
668 c0 = lo;
669 c1 += (prod >> 64) as u64 + o as u64;
670 }};
671 }
672 macro_rules! muladd {
673 ($a:expr, $b:expr) => {{
674 let prod = ($a as u128) * ($b as u128);
675 let (lo, o1) = c0.overflowing_add(prod as u64);
676 c0 = lo;
677 let th = (prod >> 64) as u64 + o1 as u64;
678 let (mid, o2) = c1.overflowing_add(th);
679 c1 = mid;
680 c2 += o2 as u32;
681 }};
682 }
683 macro_rules! sumadd_fast {
684 ($a:expr) => {{
685 let (lo, o) = c0.overflowing_add($a);
686 c0 = lo;
687 c1 += o as u64;
688 }};
689 }
690 macro_rules! sumadd {
691 ($a:expr) => {{
692 let (lo, o) = c0.overflowing_add($a);
693 c0 = lo;
694 let (mid, o2) = c1.overflowing_add(o as u64);
695 c1 = mid;
696 c2 += o2 as u32;
697 }};
698 }
699 macro_rules! extract {
700 () => {{
701 let n = c0;
702 c0 = c1;
703 c1 = c2 as u64;
704 c2 = 0;
705 n
706 }};
707 }
708 macro_rules! extract_fast {
709 () => {{
710 let n = c0;
711 c0 = c1;
712 c1 = 0;
713 n
714 }};
715 }
716
717 muladd_fast!(n0, N_C_0);
719 let m0 = extract_fast!();
720 sumadd_fast!(l[1]);
721 muladd!(n1, N_C_0);
722 muladd!(n0, N_C_1);
723 let m1 = extract!();
724 sumadd!(l[2]);
725 muladd!(n2, N_C_0);
726 muladd!(n1, N_C_1);
727 sumadd!(n0);
728 let m2 = extract!();
729 sumadd!(l[3]);
730 muladd!(n3, N_C_0);
731 muladd!(n2, N_C_1);
732 sumadd!(n1);
733 let m3 = extract!();
734 muladd!(n3, N_C_1);
735 sumadd!(n2);
736 let m4 = extract!();
737 sumadd_fast!(n3);
738 let m5 = extract_fast!();
739 let m6 = c0 as u32;
740
741 c0 = m0;
743 c1 = 0;
744 c2 = 0;
745 muladd_fast!(m4, N_C_0);
746 let p0 = extract_fast!();
747 sumadd_fast!(m1);
748 muladd!(m5, N_C_0);
749 muladd!(m4, N_C_1);
750 let p1 = extract!();
751 sumadd!(m2);
752 muladd!(m6 as u64, N_C_0);
753 muladd!(m5, N_C_1);
754 sumadd!(m4);
755 let p2 = extract!();
756 sumadd_fast!(m3);
757 muladd_fast!(m6 as u64, N_C_1);
758 sumadd_fast!(m5);
759 let p3 = extract_fast!();
760 let p4 = (c0 + m6 as u64) as u32;
761
762 let mut t: u128 = p0 as u128;
764 t += (N_C_0 as u128) * (p4 as u128);
765 r.d[0] = t as u64;
766 t >>= 64;
767 t += p1 as u128;
768 t += (N_C_1 as u128) * (p4 as u128);
769 r.d[1] = t as u64;
770 t >>= 64;
771 t += p2 as u128;
772 t += p4 as u128;
773 r.d[2] = t as u64;
774 t >>= 64;
775 t += p3 as u128;
776 r.d[3] = t as u64;
777 let c = (t >> 64) as u64;
778
779 scalar_reduce(r, c + scalar_check_overflow(r));
781}
782
783fn scalar_reduce(r: &mut Scalar, overflow: u64) {
785 let of = overflow as u128;
786 let mut t: u128 = r.d[0] as u128;
787 t += of * (N_C_0 as u128);
788 r.d[0] = t as u64;
789 t >>= 64;
790 t += r.d[1] as u128;
791 t += of * (N_C_1 as u128);
792 r.d[1] = t as u64;
793 t >>= 64;
794 t += r.d[2] as u128;
795 t += of * (N_C_2 as u128);
796 r.d[2] = t as u64;
797 t >>= 64;
798 r.d[3] = (t as u64).wrapping_add(r.d[3]);
799}
800
801fn scalar_check_overflow(r: &Scalar) -> u64 {
803 let mut yes = 0u64;
804 let mut no = 0u64;
805 no |= (r.d[3] < N_3) as u64;
806 no |= (r.d[2] < N_2) as u64;
807 yes |= (r.d[2] > N_2) as u64 & !no;
808 no |= (r.d[1] < N_1) as u64;
809 yes |= (r.d[1] > N_1) as u64 & !no;
810 yes |= (r.d[0] >= N_0) as u64 & !no;
811 yes
812}
813
814fn scalar_reduce_512(r: &mut Scalar, l: &[u64; 8]) {
815 #[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
816 {
817 let c = unsafe { scalar_asm::scalar_reduce_512_asm(r, l.as_ptr()) };
818 scalar_reduce(r, c + scalar_check_overflow(r));
819 }
820 #[cfg(not(all(target_arch = "x86_64", not(target_os = "windows"))))]
821 {
822 scalar_reduce_512_limbs(r, l);
823 }
824}
825
826#[cfg(test)]
827#[test]
828fn test_scalar_reduce_n_plus_1() {
829 let l = [N_0 + 1, N_1, N_2, N_3, 0, 0, 0, 0];
830 let mut r = Scalar::zero();
831 scalar_reduce_512(&mut r, &l);
832 assert!(r.is_one(), "(n+1) mod n = 1, got r.d = {:?}", r.d);
833}
834
835#[cfg(test)]
836#[test]
837fn test_scalar_mul_inv2_times_2() {
838 let inv2_hex = "7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1";
839 let inv2_bytes = hex::decode(inv2_hex).unwrap();
840 let mut buf = [0u8; 32];
841 buf.copy_from_slice(&inv2_bytes);
842 let mut inv2 = Scalar::zero();
843 inv2.set_b32(&buf);
844 let mut two = Scalar::zero();
845 two.set_int(2);
846 let mut l = [0u64; 8];
847 scalar_mul_512(&mut l, &inv2, &two);
848 let mut r = Scalar::zero();
849 scalar_reduce_512(&mut r, &l);
850 assert!(r.is_one(), "inv2*2 mod n = 1");
851}
852
853fn scalar_mul_shift_var(r: &mut Scalar, a: &Scalar, b: &Scalar, shift: u32) {
854 assert!(shift >= 256);
855 let mut l = [0u64; 8];
856 scalar_mul_512(&mut l, a, b);
857 let shiftlimbs = (shift >> 6) as usize;
858 let shiftlow = shift & 0x3F;
859 let shifthigh = 64 - shiftlow;
860 r.d[0] = if shift < 512 {
861 (l[shiftlimbs] >> shiftlow)
862 | (if shift < 448 && shiftlow != 0 {
863 l[1 + shiftlimbs] << shifthigh
864 } else {
865 0
866 })
867 } else {
868 0
869 };
870 r.d[1] = if shift < 448 {
871 (l[1 + shiftlimbs] >> shiftlow)
872 | (if shift < 384 && shiftlow != 0 {
873 l[2 + shiftlimbs] << shifthigh
874 } else {
875 0
876 })
877 } else {
878 0
879 };
880 r.d[2] = if shift < 384 {
881 (l[2 + shiftlimbs] >> shiftlow)
882 | (if shift < 320 && shiftlow != 0 {
883 l[3 + shiftlimbs] << shifthigh
884 } else {
885 0
886 })
887 } else {
888 0
889 };
890 r.d[3] = if shift < 320 {
891 l[3 + shiftlimbs] >> shiftlow
892 } else {
893 0
894 };
895 let bit = (l[(shift - 1) as usize >> 6] >> ((shift - 1) & 0x3F)) & 1;
896 scalar_cadd_bit(r, 0, bit != 0);
897}
898
899fn scalar_cadd_bit(r: &mut Scalar, bit: u32, flag: bool) {
900 let bit = if flag { bit } else { bit + 256 };
901 if bit >= 256 {
902 return;
903 }
904 let mut t: u128 = r.d[0] as u128
905 + if (bit >> 6) == 0 {
906 1u128 << (bit & 0x3F)
907 } else {
908 0
909 };
910 r.d[0] = t as u64;
911 t >>= 64;
912 t += r.d[1] as u128
913 + if (bit >> 6) == 1 {
914 1u128 << (bit & 0x3F)
915 } else {
916 0
917 };
918 r.d[1] = t as u64;
919 t >>= 64;
920 t += r.d[2] as u128
921 + if (bit >> 6) == 2 {
922 1u128 << (bit & 0x3F)
923 } else {
924 0
925 };
926 r.d[2] = t as u64;
927 t >>= 64;
928 t += r.d[3] as u128
929 + if (bit >> 6) == 3 {
930 1u128 << (bit & 0x3F)
931 } else {
932 0
933 };
934 r.d[3] = t as u64;
935}
936
937#[cfg(test)]
938mod tests {
939 use super::*;
940
941 #[test]
942 fn test_split_lambda_identity() {
943 let mut k = Scalar::zero();
945 k.set_int(42);
946
947 let mut r1 = Scalar::zero();
948 let mut r2 = Scalar::zero();
949 Scalar::split_lambda(&mut r1, &mut r2, &k);
950
951 let mut lambda_r2 = Scalar::zero();
952 lambda_r2.mul(&r2, &LAMBDA);
953 let mut check = Scalar::zero();
954 check.add(&r1, &lambda_r2);
955 assert!(bool::from(check.ct_eq(&k)), "r1 + lambda*r2 should equal k");
956 }
957
958 #[test]
959 fn test_split_lambda_neg_three() {
960 let mut three = Scalar::zero();
961 three.set_int(3);
962 let mut k = Scalar::zero();
963 k.negate(&three); let mut r1 = Scalar::zero();
966 let mut r2 = Scalar::zero();
967 Scalar::split_lambda(&mut r1, &mut r2, &k);
968
969 let mut lambda_r2 = Scalar::zero();
970 lambda_r2.mul(&r2, &LAMBDA);
971 let mut check = Scalar::zero();
972 check.add(&r1, &lambda_r2);
973 assert!(
974 bool::from(check.ct_eq(&k)),
975 "r1 + lambda*r2 should equal k for k=-3"
976 );
977 }
978
979 #[test]
980 fn test_split_lambda_ecdsa_scalar() {
981 let mut k = Scalar::zero();
982 k.d = [
983 11125243483441707226,
984 2149109665766520832,
985 14302025600096445326,
986 4162584031737161978,
987 ];
988
989 let n_big = scalar_to_biguint(&N);
990
991 let mut r1 = Scalar::zero();
992 let mut r2 = Scalar::zero();
993 Scalar::split_lambda(&mut r1, &mut r2, &k);
994
995 let r1_big = scalar_to_biguint(&r1);
996 let r2_big = scalar_to_biguint(&r2);
997 let n_half = &n_big / BigUint::from(2u64);
998 let r1_abs = if r1_big > n_half {
999 &n_big - &r1_big
1000 } else {
1001 r1_big.clone()
1002 };
1003 let r2_abs = if r2_big > n_half {
1004 &n_big - &r2_big
1005 } else {
1006 r2_big.clone()
1007 };
1008 assert!(
1009 r1_abs.bits() <= 128,
1010 "|r1| exceeds 128 bits: {}",
1011 r1_abs.bits()
1012 );
1013 assert!(
1014 r2_abs.bits() <= 128,
1015 "|r2| exceeds 128 bits: {}",
1016 r2_abs.bits()
1017 );
1018
1019 let mut lambda_r2 = Scalar::zero();
1020 lambda_r2.mul(&r2, &LAMBDA);
1021 let mut check = Scalar::zero();
1022 check.add(&r1, &lambda_r2);
1023 assert!(bool::from(check.ct_eq(&k)), "r1 + lambda*r2 should equal k");
1024 }
1025
1026 #[test]
1027 fn test_split_128_identity() {
1028 let mut k = Scalar::zero();
1030 k.set_int(0x1234_5678);
1031
1032 let mut r1 = Scalar::zero();
1033 let mut r2 = Scalar::zero();
1034 Scalar::split_128(&mut r1, &mut r2, &k);
1035
1036 let mut two_128 = Scalar::zero();
1037 two_128.d[2] = 1;
1038 let mut r2_shifted = Scalar::zero();
1039 r2_shifted.mul(&r2, &two_128);
1040 let mut check = Scalar::zero();
1041 check.add(&r1, &r2_shifted);
1042 assert!(bool::from(check.ct_eq(&k)), "r1 + 2^128*r2 should equal k");
1043 }
1044}