use c;
use super::*;
use super::{Mont, elem_sqr_mul, elem_sqr_mul_acc, ab_assign, ra, rab};
macro_rules! p256_limbs {
[$limb_7:expr, $limb_6:expr, $limb_5:expr, $limb_4:expr,
$limb_3:expr, $limb_2:expr, $limb_1:expr, $limb_0:expr] => {
limbs![0, 0, 0, 0,
$limb_7, $limb_6, $limb_5, $limb_4,
$limb_3, $limb_2, $limb_1, $limb_0]
};
}
pub static COMMON_OPS: CommonOps = CommonOps {
num_limbs: 256 / LIMB_BITS,
q: Mont {
p: p256_limbs![0xffffffff, 0x00000001, 0x00000000, 0x00000000,
0x00000000, 0xffffffff, 0xffffffff, 0xffffffff],
rr: p256_limbs![0x00000004, 0xfffffffd, 0xffffffff, 0xfffffffe,
0xfffffffb, 0xffffffff, 0x00000000, 0x00000003],
},
n: ElemDecoded {
limbs: p256_limbs![0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
0xbce6faad, 0xa7179e84, 0xf3b9cac2, 0xfc632551],
},
a: ElemUnreduced {
limbs: p256_limbs![0xfffffffc, 0x00000004, 0x00000000, 0x00000000,
0x00000003, 0xffffffff, 0xffffffff, 0xfffffffc],
},
b: ElemUnreduced {
limbs: p256_limbs![0xdc30061d, 0x04874834, 0xe5a220ab, 0xf7212ed6,
0xacf005cd, 0x78843090, 0xd89cdf62, 0x29c4bddf],
},
elem_add_impl: GFp_nistz256_add,
elem_mul_mont: GFp_nistz256_mul_mont,
elem_sqr_mont: GFp_nistz256_sqr_mont,
point_add_jacobian_impl: GFp_nistz256_point_add,
};
pub static PRIVATE_KEY_OPS: PrivateKeyOps = PrivateKeyOps {
common: &COMMON_OPS,
elem_inv: p256_elem_inv,
point_mul_base_impl: p256_point_mul_base_impl,
point_mul_impl: GFp_nistz256_point_mul,
};
fn p256_elem_inv(a: &ElemUnreduced) -> ElemUnreduced {
#[inline]
fn sqr_mul(a: &ElemUnreduced, squarings: usize, b: &ElemUnreduced)
-> ElemUnreduced {
elem_sqr_mul(&COMMON_OPS, a, squarings, b)
}
#[inline]
fn sqr_mul_acc(a: &mut ElemUnreduced, squarings: usize, b: &ElemUnreduced) {
elem_sqr_mul_acc(&COMMON_OPS, a, squarings, b)
}
let b_1 = &a;
let b_11 = sqr_mul(b_1, 0 + 1, b_1);
let f = sqr_mul(&b_11, 0 + 2, &b_11);
let ff = sqr_mul(&f, 0 + 4, &f);
let ffff = sqr_mul(&ff, 0 + 8, &ff);
let ffffffff = sqr_mul(&ffff, 0 + 16, &ffff);
let mut acc = sqr_mul(&ffffffff, 31 + 1, b_1);
sqr_mul_acc(&mut acc, 96 + 32, &ffffffff);
sqr_mul_acc(&mut acc, 0 + 32, &ffffffff);
sqr_mul_acc(&mut acc, 0 + 16, &ffff);
sqr_mul_acc(&mut acc, 0 + 8, &ff);
sqr_mul_acc(&mut acc, 0 + 4, &f);
sqr_mul_acc(&mut acc, 0 + 2, &b_11);
sqr_mul(&acc, 1 + 1, b_1)
}
fn p256_point_mul_base_impl(g_scalar: &Scalar) -> Point {
let mut r = Point::new_at_infinity();
unsafe {
GFp_nistz256_point_mul_base(r.xyz.as_mut_ptr(),
g_scalar.limbs.as_ptr());
}
r
}
pub static PUBLIC_KEY_OPS: PublicKeyOps = PublicKeyOps { common: &COMMON_OPS };
pub static PUBLIC_SCALAR_OPS: PublicScalarOps = PublicScalarOps {
public_key_ops: &PUBLIC_KEY_OPS,
private_key_ops: &PRIVATE_KEY_OPS,
q_minus_n: ElemDecoded {
limbs: p256_limbs![0, 0, 0, 0, 0x43190553, 0x58e8617b, 0x0c46353d,
0x039cdaae],
},
scalar_inv_to_mont_impl: p256_scalar_inv_to_mont,
scalar_mul_mont: GFp_p256_scalar_mul_mont,
};
fn p256_scalar_inv_to_mont(a: &Scalar) -> ScalarMont {
#[inline]
fn mul(a: &ScalarMont, b: &ScalarMont) -> ScalarMont {
ScalarMont { limbs: rab(GFp_p256_scalar_mul_mont, &a.limbs, &b.limbs) }
}
#[inline]
fn sqr(a: &ScalarMont) -> ScalarMont {
ScalarMont { limbs: ra(GFp_p256_scalar_sqr_mont, &a.limbs) }
}
fn sqr_mul(a: &ScalarMont, squarings: c::int, b: &ScalarMont)
-> ScalarMont {
debug_assert!(squarings >= 1);
let mut tmp = ScalarMont { limbs: [0; MAX_LIMBS] };
unsafe {
GFp_p256_scalar_sqr_rep_mont(tmp.limbs.as_mut_ptr(),
a.limbs.as_ptr(), squarings)
}
mul(&tmp, b)
}
fn sqr_mul_acc(acc: &mut ScalarMont, squarings: c::int, b: &ScalarMont) {
debug_assert!(squarings >= 1);
unsafe {
GFp_p256_scalar_sqr_rep_mont(acc.limbs.as_mut_ptr(),
acc.limbs.as_ptr(), squarings)
}
ab_assign(GFp_p256_scalar_mul_mont, &mut acc.limbs, &b.limbs);
}
fn to_mont(a: &Scalar) -> ScalarMont {
static N_RR: [Limb; MAX_LIMBS] =
p256_limbs![0x66e12d94, 0xf3d95620, 0x2845b239, 0x2b6bec59,
0x4699799c, 0x49bd6fa6, 0x83244c95, 0xbe79eea2];
ScalarMont { limbs: rab(GFp_p256_scalar_mul_mont, &a.limbs, &N_RR) }
}
const B_1: usize = 0;
const B_10: usize = 1;
const B_11: usize = 2;
const B_101: usize = 3;
const B_111: usize = 4;
const B_1010: usize = 5;
const B_1111: usize = 6;
const B_10101: usize = 7;
const B_101111: usize = 8;
const DIGIT_COUNT: usize = 9;
let mut d = [ScalarMont { limbs: [0; MAX_LIMBS] }; DIGIT_COUNT];
d[B_1] = to_mont(a);
d[B_10] = sqr(&d[B_1]);
d[B_11] = mul(&d[B_10], &d[B_1]);
d[B_101] = sqr_mul(&d[B_10], 0 + 1, &d[B_1]);
d[B_111] = mul(&d[B_101], &d[B_10]);
d[B_1010] = sqr(&d[B_101]);
d[B_1111] = mul(&d[B_1010], &d[B_101]);
d[B_10101] = sqr_mul(&d[B_1010], 0 + 1, &d[B_1]);
d[B_101111] = sqr_mul(&d[B_10101], 0 + 1, &d[B_101]);
let ff = sqr_mul(&d[B_1111], 0 + 4, &d[B_1111]);
let ffff = sqr_mul(&ff, 0 + 8, &ff);
let ffffffff = sqr_mul(&ffff, 0 + 16, &ffff);
let mut acc = sqr_mul(&ffffffff, 32 + 32, &ffffffff);
sqr_mul_acc(&mut acc, 0 + 32, &ffffffff);
static REMAINING_WINDOWS: [(u8, u8); 26] = [
( 6, B_101111 as u8),
(2 + 3, B_111 as u8),
(2 + 2, B_11 as u8),
(1 + 4, B_1111 as u8),
( 5, B_10101 as u8),
(1 + 3, B_101 as u8),
(0 + 3, B_101 as u8),
(0 + 3, B_101 as u8),
(2 + 3, B_111 as u8),
(3 + 6, B_101111 as u8),
(2 + 4, B_1111 as u8),
(1 + 1, B_1 as u8),
(4 + 1, B_1 as u8),
(2 + 4, B_1111 as u8),
(2 + 3, B_111 as u8),
(1 + 3, B_111 as u8),
(2 + 3, B_111 as u8),
(2 + 3, B_101 as u8),
(1 + 2, B_11 as u8),
(4 + 6, B_101111 as u8),
( 2, B_11 as u8),
(3 + 2, B_11 as u8),
(3 + 2, B_11 as u8),
(2 + 1, B_1 as u8),
(2 + 5, B_10101 as u8),
(2 + 4, B_1111 as u8),
];
for &(squarings, digit) in &REMAINING_WINDOWS {
sqr_mul_acc(&mut acc, squarings as c::int, &d[digit as usize]);
}
acc
}
extern {
fn GFp_nistz256_add(r: *mut Limb,
a: *const Limb,
b: *const Limb);
fn GFp_nistz256_mul_mont(r: *mut Limb,
a: *const Limb,
b: *const Limb);
fn GFp_nistz256_sqr_mont(r: *mut Limb,
a: *const Limb);
fn GFp_nistz256_point_add(r: *mut Limb,
a: *const Limb,
b: *const Limb);
fn GFp_nistz256_point_mul(r: *mut Limb,
p_scalar: *const Limb,
p_x: *const Limb,
p_y: *const Limb);
fn GFp_nistz256_point_mul_base(r: *mut Limb,
g_scalar: *const Limb);
fn GFp_p256_scalar_mul_mont(r: *mut Limb,
a: *const Limb,
b: *const Limb);
fn GFp_p256_scalar_sqr_mont(r: *mut Limb,
a: *const Limb);
fn GFp_p256_scalar_sqr_rep_mont(r: *mut Limb,
a: *const Limb,
rep: c::int);
}
#[cfg(feature = "internal_benches")]
mod internal_benches {
use super::*;
use super::super::internal_benches::*;
bench_curve!(&[
Scalar { limbs: LIMBS_1 },
Scalar { limbs: LIMBS_ALTERNATING_10, },
Scalar { limbs: p256_limbs![0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
0xbce6faad, 0xa7179e84, 0xf3b9cac2,
0xfc632551 - 1],
},
]);
}