#![allow(unsafe_code)]
use core::arch::global_asm;
#[path = "ecdsa_aarch64_tables.rs"]
mod ecdsa_aarch64_tables;
#[cfg(target_os = "macos")]
global_asm!(include_str!(
"asm/rscrypto_p256_scalarmulbase_alt_aarch64_apple_darwin.s"
));
#[cfg(target_os = "macos")]
global_asm!(include_str!("asm/rscrypto_bignum_mod_n256_aarch64_apple_darwin.s"));
#[cfg(target_os = "macos")]
global_asm!(include_str!("asm/rscrypto_bignum_mod_n384_aarch64_apple_darwin.s"));
#[cfg(target_os = "macos")]
global_asm!(include_str!("asm/rscrypto_bignum_montmul_p384_aarch64_apple_darwin.s"));
#[cfg(target_os = "macos")]
global_asm!(include_str!("asm/rscrypto_bignum_montsqr_p384_aarch64_apple_darwin.s"));
#[cfg(target_os = "macos")]
global_asm!(include_str!("asm/rscrypto_bignum_montinv_p384_aarch64_apple_darwin.s"));
#[cfg(target_os = "macos")]
global_asm!(include_str!("asm/rscrypto_bignum_modinv_aarch64_apple_darwin.s"));
#[cfg(target_os = "macos")]
global_asm!(include_str!("asm/rscrypto_p384_montjdouble_alt_aarch64_apple_darwin.s"));
#[cfg(target_os = "macos")]
global_asm!(include_str!("asm/rscrypto_p384_montjmixadd_alt_aarch64_apple_darwin.s"));
#[cfg(target_os = "linux")]
global_asm!(include_str!(
"asm/rscrypto_p256_scalarmulbase_alt_aarch64_unknown_linux.s"
));
#[cfg(target_os = "linux")]
global_asm!(include_str!("asm/rscrypto_bignum_mod_n256_aarch64_unknown_linux.s"));
#[cfg(target_os = "linux")]
global_asm!(include_str!("asm/rscrypto_bignum_mod_n384_aarch64_unknown_linux.s"));
#[cfg(target_os = "linux")]
global_asm!(include_str!("asm/rscrypto_bignum_montmul_p384_aarch64_unknown_linux.s"));
#[cfg(target_os = "linux")]
global_asm!(include_str!("asm/rscrypto_bignum_montsqr_p384_aarch64_unknown_linux.s"));
#[cfg(target_os = "linux")]
global_asm!(include_str!("asm/rscrypto_bignum_montinv_p384_aarch64_unknown_linux.s"));
#[cfg(target_os = "linux")]
global_asm!(include_str!("asm/rscrypto_bignum_modinv_aarch64_unknown_linux.s"));
#[cfg(target_os = "linux")]
global_asm!(include_str!(
"asm/rscrypto_p384_montjdouble_alt_aarch64_unknown_linux.s"
));
#[cfg(target_os = "linux")]
global_asm!(include_str!(
"asm/rscrypto_p384_montjmixadd_alt_aarch64_unknown_linux.s"
));
unsafe extern "C" {
fn rscrypto_p256_scalarmulbase_alt(out: *mut u64, scalar: *const u64, blocksize: u64, table: *const u64);
fn rscrypto_bignum_mod_n256(out: *mut u64, len: u64, input: *const u64);
fn rscrypto_bignum_mod_n384(out: *mut u64, len: u64, input: *const u64);
fn rscrypto_bignum_montmul_p384(out: *mut u64, lhs: *const u64, rhs: *const u64);
fn rscrypto_bignum_montsqr_p384(out: *mut u64, value: *const u64);
fn rscrypto_bignum_montinv_p384(out: *mut u64, value: *const u64);
fn rscrypto_bignum_modinv(k: u64, out: *mut u64, value: *const u64, modulus: *const u64, tmp: *mut u64);
fn rscrypto_p384_montjdouble_alt(out: *mut u64, point: *const u64);
fn rscrypto_p384_montjmixadd_alt(out: *mut u64, lhs: *const u64, rhs: *const u64);
}
#[inline]
pub(super) fn p256_scalarmulbase_generator(scalar: &[u64; 4]) -> [u64; 8] {
let mut out = [0u64; 8];
unsafe {
rscrypto_p256_scalarmulbase_alt(
out.as_mut_ptr(),
scalar.as_ptr(),
ecdsa_aarch64_tables::P256_AARCH64_BASEPOINT_BLOCKSIZE,
ecdsa_aarch64_tables::P256_AARCH64_BASEPOINT_TABLE.as_ptr(),
)
};
out
}
#[inline]
pub(super) fn p256_reduce_order_64(bytes: &[u8; 64]) -> [u64; 4] {
let input = words_from_be_bytes_reversed::<8, 64>(bytes);
let mut out = [0u64; 4];
unsafe { rscrypto_bignum_mod_n256(out.as_mut_ptr(), 8, input.as_ptr()) };
out
}
#[inline]
pub(super) fn p384_reduce_order_96(bytes: &[u8; 96]) -> [u64; 6] {
let input = words_from_be_bytes_reversed::<12, 96>(bytes);
let mut out = [0u64; 6];
unsafe { rscrypto_bignum_mod_n384(out.as_mut_ptr(), 12, input.as_ptr()) };
out
}
#[inline]
pub(super) fn p384_field_mul(lhs: &[u64; 6], rhs: &[u64; 6]) -> [u64; 6] {
let mut out = [0u64; 6];
unsafe { rscrypto_bignum_montmul_p384(out.as_mut_ptr(), lhs.as_ptr(), rhs.as_ptr()) };
out
}
#[inline]
pub(super) fn p384_field_square(value: &[u64; 6]) -> [u64; 6] {
let mut out = [0u64; 6];
unsafe { rscrypto_bignum_montsqr_p384(out.as_mut_ptr(), value.as_ptr()) };
out
}
#[inline]
pub(super) fn p384_field_inverse(value: &[u64; 6]) -> [u64; 6] {
let mut out = [0u64; 6];
unsafe { rscrypto_bignum_montinv_p384(out.as_mut_ptr(), value.as_ptr()) };
out
}
#[inline]
pub(super) fn scalar_inverse<const L: usize>(value: &[u64; L], modulus: &[u64; L]) -> [u64; L] {
let mut out = [0u64; L];
let mut tmp = [0u64; 18];
debug_assert!(L == 4 || L == 6);
unsafe {
rscrypto_bignum_modinv(
L as u64,
out.as_mut_ptr(),
value.as_ptr(),
modulus.as_ptr(),
tmp.as_mut_ptr(),
)
};
out
}
#[inline]
pub(super) fn p384_point_double(point: &[u64; 18]) -> [u64; 18] {
let mut out = [0u64; 18];
unsafe { rscrypto_p384_montjdouble_alt(out.as_mut_ptr(), point.as_ptr()) };
out
}
#[inline]
pub(super) fn p384_point_mixadd(lhs: &[u64; 18], rhs: &[u64; 12]) -> [u64; 18] {
let mut out = [0u64; 18];
unsafe { rscrypto_p384_montjmixadd_alt(out.as_mut_ptr(), lhs.as_ptr(), rhs.as_ptr()) };
out
}
#[inline]
fn words_from_be_bytes_reversed<const WORDS: usize, const BYTES: usize>(bytes: &[u8; BYTES]) -> [u64; WORDS] {
let mut out = [0u64; WORDS];
for (word, chunk) in out.iter_mut().zip(bytes.rchunks_exact(8)) {
let mut limb = [0u8; 8];
limb.copy_from_slice(chunk);
*word = u64::from_be_bytes(limb);
}
out
}