use core::cell::UnsafeCell;
use crate::error::{check, len_as_u32, WolfCryptError};
use wolfcrypt_rs::{
wc_ed448_export_public, wc_ed448_free, wc_ed448_import_private_key,
wc_ed448_import_private_only,
wc_ed448_import_public, wc_ed448_init, wc_ed448_make_key,
wc_ed448_make_public, wc_ed448_sign_msg, wc_ed448_verify_msg,
wc_ed448_key, wc_FreeRng, wc_InitRng, WC_RNG,
};
const ED448_KEY_SIZE: usize = 57;
const ED448_SIG_SIZE: usize = 114;
#[derive(Clone, Debug)]
pub struct Ed448Signature([u8; ED448_SIG_SIZE]);
impl Ed448Signature {
pub fn from_bytes(bytes: &[u8; ED448_SIG_SIZE]) -> Self {
Self(*bytes)
}
pub fn to_bytes(&self) -> [u8; ED448_SIG_SIZE] {
self.0
}
}
impl AsRef<[u8]> for Ed448Signature {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl TryFrom<&[u8]> for Ed448Signature {
type Error = signature_trait::Error;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
let arr: [u8; ED448_SIG_SIZE] = bytes
.try_into()
.map_err(|_| signature_trait::Error::new())?;
Ok(Self(arr))
}
}
impl signature_trait::SignatureEncoding for Ed448Signature {
type Repr = [u8; ED448_SIG_SIZE];
}
impl From<Ed448Signature> for [u8; ED448_SIG_SIZE] {
fn from(sig: Ed448Signature) -> Self {
sig.0
}
}
impl From<[u8; ED448_SIG_SIZE]> for Ed448Signature {
fn from(bytes: [u8; ED448_SIG_SIZE]) -> Self {
Self(bytes)
}
}
pub struct Ed448SigningKey {
key: UnsafeCell<wc_ed448_key>,
rng: UnsafeCell<WC_RNG>,
}
unsafe impl Send for Ed448SigningKey {}
impl Ed448SigningKey {
pub fn from_seed(seed: &[u8; ED448_KEY_SIZE]) -> Result<Self, WolfCryptError> {
let mut key = wc_ed448_key::zeroed();
let rc = unsafe { wc_ed448_init(&mut key) };
check(rc, "wc_ed448_init")?;
let rc = unsafe {
wc_ed448_import_private_only(seed.as_ptr(), ED448_KEY_SIZE as u32, &mut key)
};
check(rc, "wc_ed448_import_private_only")?;
let mut pub_buf = [0u8; ED448_KEY_SIZE];
let rc = unsafe {
wc_ed448_make_public(&mut key, pub_buf.as_mut_ptr(), ED448_KEY_SIZE as u32)
};
check(rc, "wc_ed448_make_public")?;
let rc = unsafe {
wc_ed448_import_private_key(
seed.as_ptr(),
ED448_KEY_SIZE as u32,
pub_buf.as_ptr(),
ED448_KEY_SIZE as u32,
&mut key,
)
};
check(rc, "wc_ed448_import_private_key")?;
let mut rng = WC_RNG::zeroed();
let rc = unsafe { wc_InitRng(&mut rng) };
check(rc, "wc_InitRng")?;
Ok(Self {
key: UnsafeCell::new(key),
rng: UnsafeCell::new(rng),
})
}
pub fn generate(rng: &mut crate::rand::WolfRng) -> Result<Self, WolfCryptError> {
let mut key = wc_ed448_key::zeroed();
let rc = unsafe { wc_ed448_init(&mut key) };
check(rc, "wc_ed448_init")?;
let rc = unsafe {
wc_ed448_make_key(&mut rng.rng, ED448_KEY_SIZE as i32, &mut key)
};
check(rc, "wc_ed448_make_key")?;
let mut own_rng = WC_RNG::zeroed();
let rc = unsafe { wc_InitRng(&mut own_rng) };
check(rc, "wc_InitRng")?;
Ok(Self {
key: UnsafeCell::new(key),
rng: UnsafeCell::new(own_rng),
})
}
pub fn verifying_key(&self) -> Ed448VerifyingKey {
let mut pub_buf = [0u8; ED448_KEY_SIZE];
let mut pub_len: u32 = ED448_KEY_SIZE as u32;
let rc = unsafe {
wc_ed448_export_public(
self.key.get() as *const _,
pub_buf.as_mut_ptr(),
&mut pub_len,
)
};
assert_eq!(rc, 0, "wc_ed448_export_public failed (key not initialized)");
Ed448VerifyingKey::from_bytes(&pub_buf)
.expect("exported public key must be valid")
}
}
impl Drop for Ed448SigningKey {
fn drop(&mut self) {
unsafe {
wc_ed448_free(self.key.get_mut());
wc_FreeRng(self.rng.get_mut());
}
}
}
impl signature_trait::Signer<Ed448Signature> for Ed448SigningKey {
fn try_sign(&self, msg: &[u8]) -> Result<Ed448Signature, signature_trait::Error> {
let mut sig_buf = [0u8; ED448_SIG_SIZE];
let mut sig_len: u32 = ED448_SIG_SIZE as u32;
let rc = unsafe {
wc_ed448_sign_msg(
msg.as_ptr(),
len_as_u32(msg.len()),
sig_buf.as_mut_ptr(),
&mut sig_len,
self.key.get(),
core::ptr::null(),
0,
)
};
if rc != 0 {
return Err(signature_trait::Error::new());
}
Ok(Ed448Signature(sig_buf))
}
}
pub struct Ed448VerifyingKey {
key: UnsafeCell<wc_ed448_key>,
pub_bytes: [u8; ED448_KEY_SIZE],
}
unsafe impl Send for Ed448VerifyingKey {}
impl Ed448VerifyingKey {
pub fn from_bytes(bytes: &[u8; ED448_KEY_SIZE]) -> Result<Self, WolfCryptError> {
let mut key = wc_ed448_key::zeroed();
let rc = unsafe { wc_ed448_init(&mut key) };
check(rc, "wc_ed448_init")?;
let rc = unsafe {
wc_ed448_import_public(bytes.as_ptr(), ED448_KEY_SIZE as u32, &mut key)
};
check(rc, "wc_ed448_import_public")?;
Ok(Self {
key: UnsafeCell::new(key),
pub_bytes: *bytes,
})
}
pub fn as_bytes(&self) -> &[u8; ED448_KEY_SIZE] {
&self.pub_bytes
}
}
impl Drop for Ed448VerifyingKey {
fn drop(&mut self) {
unsafe {
wc_ed448_free(self.key.get_mut());
}
}
}
impl signature_trait::Verifier<Ed448Signature> for Ed448VerifyingKey {
fn verify(
&self,
msg: &[u8],
signature: &Ed448Signature,
) -> Result<(), signature_trait::Error> {
let sig_bytes = signature.to_bytes();
let mut result: i32 = 0;
let rc = unsafe {
wc_ed448_verify_msg(
sig_bytes.as_ptr(),
len_as_u32(sig_bytes.len()),
msg.as_ptr(),
len_as_u32(msg.len()),
&mut result,
self.key.get(),
core::ptr::null(),
0,
)
};
if rc != 0 || result != 1 {
return Err(signature_trait::Error::new());
}
Ok(())
}
}