use crate::nist::arith::Field;
use crate::p256::{Fn as Scalar, Fp};
use ic_core::ct::Choice;
macro_rules! probes {
($t:ty, $reduce:ident, $add:ident, $sub:ident, $mul:ident, $neg:ident, $cmov:ident, $eq:ident, $odd:ident) => {
#[inline(always)]
pub fn $reduce(a: &[u8; 32]) -> [u8; 32] {
<$t>::from_bytes_reduced(a).to_bytes()
}
#[inline(always)]
pub fn $add(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
<$t>::from_bytes_reduced(a)
.add(&<$t>::from_bytes_reduced(b))
.to_bytes()
}
#[inline(always)]
pub fn $sub(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
<$t>::from_bytes_reduced(a)
.sub(&<$t>::from_bytes_reduced(b))
.to_bytes()
}
#[inline(always)]
pub fn $mul(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
<$t>::from_bytes_reduced(a)
.mul(&<$t>::from_bytes_reduced(b))
.to_bytes()
}
#[inline(always)]
pub fn $neg(a: &[u8; 32]) -> [u8; 32] {
<$t>::from_bytes_reduced(a).neg().to_bytes()
}
#[inline(always)]
pub fn $cmov(flag: u8, a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
let mut x = <$t>::from_bytes_reduced(a);
<$t as Field>::cmov(
&mut x,
&<$t>::from_bytes_reduced(b),
Choice::from_u8(flag & 1),
);
x.to_bytes()
}
#[inline(always)]
pub fn $eq(a: &[u8; 32], b: &[u8; 32]) -> u8 {
<$t>::from_bytes_reduced(a)
.ct_eq(&<$t>::from_bytes_reduced(b))
.unwrap_u8()
}
#[inline(always)]
pub fn $odd(a: &[u8; 32]) -> u8 {
<$t>::from_bytes_reduced(a).is_odd().unwrap_u8()
}
};
}
probes!(Fp, fp_reduce, fp_add, fp_sub, fp_mul, fp_neg, fp_cmov, fp_eq, fp_is_odd);
probes!(Scalar, fn_reduce, fn_add, fn_sub, fn_mul, fn_neg, fn_cmov, fn_eq, fn_is_odd);
#[cfg(not(ic_approved_only))]
#[inline(always)]
pub fn ed25519_reduce_wide(x: &[u8; 64]) -> [u8; 32] {
crate::scalar::reduce_wide(x)
}
#[cfg(not(ic_approved_only))]
#[inline(always)]
pub fn ed25519_mul_add(a: &[u8; 32], b: &[u8; 32], c: &[u8; 32]) -> [u8; 32] {
crate::scalar::mul_add(a, b, c)
}
#[cfg(all(
not(ic_approved_only),
target_arch = "x86_64",
not(any(ic_limb32, ic_ec_portable))
))]
pub mod x86 {
use crate::fe64::edwards;
pub use crate::fe64::edwards::{Ws, Ws2};
use crate::fe64::Fe64;
pub use crate::f51x4::probes as ifma;
#[inline(always)]
pub fn fe64_mul(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
Fe64::from_bytes(a).mul(&Fe64::from_bytes(b)).to_bytes()
}
#[inline(always)]
pub fn fe64_square(a: &[u8; 32]) -> [u8; 32] {
Fe64::from_bytes(a).square().to_bytes()
}
#[inline(always)]
pub fn fe64_add(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
Fe64::from_bytes(a).add(&Fe64::from_bytes(b)).to_bytes()
}
#[inline(always)]
pub fn fe64_sub(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
Fe64::from_bytes(a).sub(&Fe64::from_bytes(b)).to_bytes()
}
#[inline(always)]
pub fn fe64_mul121666(a: &[u8; 32]) -> [u8; 32] {
Fe64::from_bytes(a).mul121666().to_bytes()
}
#[inline(always)]
pub fn fe64_invert(a: &[u8; 32]) -> [u8; 32] {
Fe64::from_bytes(a).invert().to_bytes()
}
#[inline(always)]
pub fn x25519_step(ws: &mut [u64; 76], swap: u64) {
crate::fe64::ladder_step(ws, swap & 1)
}
#[inline(always)]
pub fn ed25519_madd_ext2(ws: &mut Ws2) {
edwards::madd_ext2(ws);
}
#[inline(always)]
pub fn ed25519_dbl_nadd(ws: &mut Ws) {
edwards::dbl(ws);
edwards::to_proj(ws);
edwards::dbl(ws);
edwards::to_ext(ws);
edwards::nadd(ws);
edwards::to_ext(ws);
}
}
#[cfg(target_arch = "x86_64")]
pub use crate::nist::p256_x86::{mul_adx as fp_mul_adx, square_adx as fp_square_adx};
#[cfg(target_arch = "x86_64")]
pub use crate::nist::p256_x86_point::{
add_adx as point_add_adx, add_affine_adx as point_add_affine_adx,
double_adx as point_double_adx,
};
#[cfg(target_arch = "x86_64")]
pub use crate::nist::mont_x86::mul_p384_n as p384_fn_mul_adx;
#[cfg(target_arch = "x86_64")]
pub use crate::nist::p384_x86_point::{
add_adx as p384_point_add_adx, add_affine_adx as p384_point_add_affine_adx,
double_adx as p384_point_double_adx, fmul_adx as p384_fp_mul_adx, fsqr_adx as p384_fp_sqr_adx,
};
#[cfg(all(target_arch = "x86_64", not(ic_limb32)))]
#[inline(always)]
pub fn p384_fp_invert(a: &[u64; 6]) -> [u64; 6] {
crate::nist::safegcd::invert_384::<crate::p384::FpModulus>(a)
}
#[cfg(all(target_arch = "x86_64", not(ic_limb32)))]
#[inline(always)]
pub fn p256_fp_invert(a: &[u64; 4]) -> [u64; 4] {
crate::nist::safegcd::invert::<crate::p256::FpModulus>(a)
}
#[cfg(all(target_arch = "x86_64", not(ic_limb32)))]
#[inline(always)]
pub fn p256_fn_invert(a: &[u64; 4]) -> [u64; 4] {
crate::nist::safegcd::invert::<crate::p256::FnModulus>(a)
}