#![allow(unsafe_code)]
use core::arch::global_asm;
use super::POINT_LENGTH;
use crate::platform::{self, caps::x86};
global_asm!(include_str!("asm/rscrypto_x25519_x86_64_linux.s"), options(att_syntax));
unsafe extern "C" {
fn rscrypto_curve25519_x25519_byte(out: *mut u8, scalar: *const u8, point: *const u8);
fn rscrypto_curve25519_x25519_byte_alt(out: *mut u8, scalar: *const u8, point: *const u8);
fn rscrypto_curve25519_x25519base_byte(out: *mut u8, scalar: *const u8);
fn rscrypto_curve25519_x25519base_byte_alt(out: *mut u8, scalar: *const u8);
}
#[inline]
fn has_bmi2_adx() -> bool {
platform::caps().has(x86::BMI2.union(x86::ADX))
}
#[inline]
pub(super) fn x25519(scalar: &[u8; POINT_LENGTH], point: &[u8; POINT_LENGTH]) -> [u8; POINT_LENGTH] {
let mut out = [0u8; POINT_LENGTH];
if has_bmi2_adx() {
unsafe { rscrypto_curve25519_x25519_byte(out.as_mut_ptr(), scalar.as_ptr(), point.as_ptr()) };
} else {
unsafe { rscrypto_curve25519_x25519_byte_alt(out.as_mut_ptr(), scalar.as_ptr(), point.as_ptr()) };
}
out
}
#[inline]
pub(super) fn x25519_base(scalar: &[u8; POINT_LENGTH]) -> [u8; POINT_LENGTH] {
let mut out = [0u8; POINT_LENGTH];
if has_bmi2_adx() {
unsafe { rscrypto_curve25519_x25519base_byte(out.as_mut_ptr(), scalar.as_ptr()) };
} else {
unsafe { rscrypto_curve25519_x25519base_byte_alt(out.as_mut_ptr(), scalar.as_ptr()) };
}
out
}