#![cfg(lms)]
use crate::sys;
use core::mem::MaybeUninit;
#[cfg(all(lms_make_key, random))]
use crate::random::RNG;
pub struct Lms {
ws_key: sys::LmsKey,
}
#[cfg(lms_sha256_256)]
impl Lms {
pub const PARM_L1_H5_W1: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H5_W1;
pub const PARM_L1_H5_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H5_W2;
pub const PARM_L1_H5_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H5_W4;
pub const PARM_L1_H5_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H5_W8;
pub const PARM_L1_H10_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H10_W2;
pub const PARM_L1_H10_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H10_W4;
pub const PARM_L1_H10_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H10_W8;
pub const PARM_L1_H15_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H15_W2;
pub const PARM_L1_H15_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H15_W4;
pub const PARM_L1_H15_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H15_W8;
pub const PARM_L1_H20_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H20_W2;
pub const PARM_L1_H20_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H20_W4;
pub const PARM_L1_H20_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L1_H20_W8;
pub const PARM_L2_H5_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H5_W2;
pub const PARM_L2_H5_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H5_W4;
pub const PARM_L2_H5_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H5_W8;
pub const PARM_L2_H10_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H10_W2;
pub const PARM_L2_H10_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H10_W4;
pub const PARM_L2_H10_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H10_W8;
pub const PARM_L2_H15_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H15_W2;
pub const PARM_L2_H15_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H15_W4;
pub const PARM_L2_H15_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H15_W8;
pub const PARM_L2_H20_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H20_W2;
pub const PARM_L2_H20_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H20_W4;
pub const PARM_L2_H20_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L2_H20_W8;
pub const PARM_L3_H5_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L3_H5_W2;
pub const PARM_L3_H5_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L3_H5_W4;
pub const PARM_L3_H5_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L3_H5_W8;
pub const PARM_L3_H10_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L3_H10_W4;
pub const PARM_L3_H10_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L3_H10_W8;
pub const PARM_L4_H5_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_L4_H5_W2;
pub const PARM_L4_H5_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L4_H5_W4;
pub const PARM_L4_H5_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L4_H5_W8;
pub const PARM_L4_H10_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_L4_H10_W4;
pub const PARM_L4_H10_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_L4_H10_W8;
}
#[cfg(lms_sha256_192)]
impl Lms {
pub const PARM_SHA256_192_L1_H5_W1 : u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H5_W1;
pub const PARM_SHA256_192_L1_H5_W2 : u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H5_W2;
pub const PARM_SHA256_192_L1_H5_W4 : u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H5_W4;
pub const PARM_SHA256_192_L1_H5_W8 : u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H5_W8;
pub const PARM_SHA256_192_L1_H10_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H10_W2;
pub const PARM_SHA256_192_L1_H10_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H10_W4;
pub const PARM_SHA256_192_L1_H10_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H10_W8;
pub const PARM_SHA256_192_L1_H15_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H15_W2;
pub const PARM_SHA256_192_L1_H15_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H15_W4;
pub const PARM_SHA256_192_L1_H20_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H20_W2;
pub const PARM_SHA256_192_L1_H20_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H20_W4;
pub const PARM_SHA256_192_L1_H20_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L1_H20_W8;
pub const PARM_SHA256_192_L2_H10_W2: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L2_H10_W2;
pub const PARM_SHA256_192_L2_H10_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L2_H10_W4;
pub const PARM_SHA256_192_L2_H10_W8: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L2_H10_W8;
pub const PARM_SHA256_192_L3_H5_W2 : u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L3_H5_W2;
pub const PARM_SHA256_192_L3_H5_W4 : u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L3_H5_W4;
pub const PARM_SHA256_192_L3_H5_W8 : u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L3_H5_W8;
pub const PARM_SHA256_192_L3_H10_W4: u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L3_H10_W4;
pub const PARM_SHA256_192_L4_H5_W8 : u32 = sys::wc_LmsParm_WC_LMS_PARM_SHA256_192_L4_H5_W8;
}
impl Lms {
pub const KEY_ID_LEN: usize = sys::WC_LMS_I_LEN as usize;
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
pub fn new_ex(
heap: Option<*mut core::ffi::c_void>,
dev_id: Option<i32>,
) -> Result<Self, i32> {
let heap = match heap {
Some(h) => h,
None => core::ptr::null_mut(),
};
let dev_id = match dev_id {
Some(id) => id,
None => sys::INVALID_DEVID,
};
let mut ws_key: MaybeUninit<sys::LmsKey> = MaybeUninit::uninit();
let rc = unsafe { sys::wc_LmsKey_Init(ws_key.as_mut_ptr(), heap, dev_id) };
if rc != 0 {
return Err(rc);
}
let ws_key = unsafe { ws_key.assume_init() };
let lms = Lms { ws_key };
Ok(lms)
}
pub fn set_parm(&mut self, parm: u32) -> Result<(), i32> {
let rc = unsafe { sys::wc_LmsKey_SetLmsParm(&mut self.ws_key, parm) };
if rc != 0 {
return Err(rc);
}
Ok(())
}
pub fn set_parameters(&mut self, levels: i32, height: i32, winternitz: i32) -> Result<(), i32> {
let rc = unsafe {
sys::wc_LmsKey_SetParameters(&mut self.ws_key, levels, height, winternitz)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
pub fn get_parameters(&self) -> Result<(i32, i32, i32), i32> {
let mut levels = 0i32;
let mut height = 0i32;
let mut winternitz = 0i32;
let rc = unsafe {
sys::wc_LmsKey_GetParameters(
&self.ws_key,
&mut levels,
&mut height,
&mut winternitz,
)
};
if rc != 0 {
return Err(rc);
}
Ok((levels, height, winternitz))
}
#[cfg(lms_make_key)]
pub fn set_write_cb(&mut self, write_cb: sys::wc_lms_write_private_key_cb) -> Result<(), i32> {
let rc = unsafe { sys::wc_LmsKey_SetWriteCb(&mut self.ws_key, write_cb) };
if rc != 0 {
return Err(rc);
}
Ok(())
}
#[cfg(lms_make_key)]
pub fn set_read_cb(&mut self, read_cb: sys::wc_lms_read_private_key_cb) -> Result<(), i32> {
let rc = unsafe { sys::wc_LmsKey_SetReadCb(&mut self.ws_key, read_cb) };
if rc != 0 {
return Err(rc);
}
Ok(())
}
#[cfg(lms_make_key)]
pub unsafe fn set_context(&mut self, context: *mut core::ffi::c_void) -> Result<(), i32> {
let rc = unsafe { sys::wc_LmsKey_SetContext(&mut self.ws_key, context) };
if rc != 0 {
return Err(rc);
}
Ok(())
}
#[cfg(all(lms_make_key, random))]
pub fn make_key(&mut self, rng: &RNG) -> Result<(), i32> {
let rc = unsafe { sys::wc_LmsKey_MakeKey(&mut self.ws_key, rng.wc_rng) };
if rc != 0 {
return Err(rc);
}
Ok(())
}
#[cfg(lms_make_key)]
pub fn reload(&mut self) -> Result<(), i32> {
let rc = unsafe { sys::wc_LmsKey_Reload(&mut self.ws_key) };
if rc != 0 {
return Err(rc);
}
Ok(())
}
#[cfg(lms_make_key)]
pub fn get_priv_len(&self) -> Result<usize, i32> {
let mut len = 0u32;
let rc = unsafe { sys::wc_LmsKey_GetPrivLen(&self.ws_key, &mut len) };
if rc != 0 {
return Err(rc);
}
Ok(len as usize)
}
#[cfg(lms_make_key)]
pub fn sign(&mut self, msg: &[u8], sig: &mut [u8]) -> Result<usize, i32> {
let expected_sig_len = self.get_sig_len()?;
if sig.len() < expected_sig_len {
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
}
let mut sig_sz = crate::buffer_len_to_u32(sig.len())?;
let msg_sz = crate::buffer_len_to_i32(msg.len())?;
let rc = unsafe {
sys::wc_LmsKey_Sign(
&mut self.ws_key,
sig.as_mut_ptr(),
&mut sig_sz,
msg.as_ptr(),
msg_sz,
)
};
if rc != 0 {
return Err(rc);
}
Ok(sig_sz as usize)
}
#[cfg(lms_make_key)]
pub fn has_sigs_left(&mut self) -> Result<bool, i32> {
let rc = unsafe { sys::wc_LmsKey_SigsLeft(&mut self.ws_key) };
if rc < 0 {
return Err(rc);
}
Ok(rc != 0)
}
pub fn get_sig_len(&self) -> Result<usize, i32> {
let mut len = 0u32;
let rc = unsafe { sys::wc_LmsKey_GetSigLen(&self.ws_key, &mut len) };
if rc != 0 {
return Err(rc);
}
Ok(len as usize)
}
pub fn get_pub_len(&self) -> Result<usize, i32> {
let mut len = 0u32;
let rc = unsafe { sys::wc_LmsKey_GetPubLen(&self.ws_key, &mut len) };
if rc != 0 {
return Err(rc);
}
Ok(len as usize)
}
pub fn export_pub_from(&mut self, src: &Lms) -> Result<(), i32> {
let rc = unsafe {
sys::wc_LmsKey_ExportPub(&mut self.ws_key, &src.ws_key)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
pub fn export_pub_raw(&self, out: &mut [u8]) -> Result<usize, i32> {
let mut out_len = crate::buffer_len_to_u32(out.len())?;
let rc = unsafe {
sys::wc_LmsKey_ExportPubRaw(&self.ws_key, out.as_mut_ptr(), &mut out_len)
};
if rc != 0 {
return Err(rc);
}
Ok(out_len as usize)
}
pub fn import_pub_raw(&mut self, data: &[u8]) -> Result<(), i32> {
let data_size = crate::buffer_len_to_u32(data.len())?;
let rc = unsafe {
sys::wc_LmsKey_ImportPubRaw(&mut self.ws_key, data.as_ptr(), data_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
pub fn verify(&mut self, sig: &[u8], msg: &[u8]) -> Result<(), i32> {
let expected_sig_len = self.get_sig_len()?;
if sig.len() != expected_sig_len {
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
}
let sig_sz = crate::buffer_len_to_u32(sig.len())?;
let msg_sz = crate::buffer_len_to_i32(msg.len())?;
let rc = unsafe {
sys::wc_LmsKey_Verify(
&mut self.ws_key,
sig.as_ptr(),
sig_sz,
msg.as_ptr(),
msg_sz,
)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
pub fn get_kid(&mut self, kid: &mut [u8]) -> Result<usize, i32> {
let mut kid_ptr: *const u8 = core::ptr::null();
let mut kid_sz: u32 = 0;
let rc = unsafe {
sys::wc_LmsKey_GetKid(&mut self.ws_key, &mut kid_ptr, &mut kid_sz)
};
if rc != 0 {
return Err(rc);
}
if kid_ptr.is_null() {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let src = unsafe { core::slice::from_raw_parts(kid_ptr, kid_sz as usize) };
if kid.len() < src.len() {
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
}
kid[..src.len()].copy_from_slice(src);
Ok(src.len())
}
}
impl Lms {
fn zeroize(&mut self) {
unsafe { crate::zeroize_raw(&mut self.ws_key); }
}
}
impl Drop for Lms {
fn drop(&mut self) {
unsafe {
sys::wc_LmsKey_Free(&mut self.ws_key);
}
self.zeroize();
}
}