#![cfg(lms)]
#[cfg(all(lms_make_key, random))]
use crate::random::RNG;
use crate::sys;
use core::mem::MaybeUninit;
pub struct Lms {
ws_key: sys::LmsKey,
}
#[cfg(lms_sha256_256)]
impl Lms {
pub const PARM_NONE: u32 = sys::wc_LmsParm_WC_LMS_PARM_NONE;
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: &mut RNG) -> Result<(), i32> {
let rc = unsafe { sys::wc_LmsKey_MakeKey(&mut self.ws_key, &mut 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 = sig.len() as u32;
let rc = unsafe {
sys::wc_LmsKey_Sign(
&mut self.ws_key,
sig.as_mut_ptr(),
&mut sig_sz,
msg.as_ptr(),
msg.len() as core::ffi::c_int,
)
};
if rc != 0 {
return Err(rc);
}
Ok(sig_sz as usize)
}
#[cfg(lms_make_key)]
pub fn 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 = out.len() as u32;
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 rc = unsafe {
sys::wc_LmsKey_ImportPubRaw(&mut self.ws_key, data.as_ptr(), data.len() as u32)
};
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 rc = unsafe {
sys::wc_LmsKey_Verify(
&mut self.ws_key,
sig.as_ptr(),
sig.len() as u32,
msg.as_ptr(),
msg.len() as core::ffi::c_int,
)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
pub fn get_kid(&mut self) -> Result<&[u8], 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);
}
let slice = unsafe { core::slice::from_raw_parts(kid_ptr, kid_sz as usize) };
Ok(slice)
}
}
impl Drop for Lms {
fn drop(&mut self) {
unsafe {
sys::wc_LmsKey_Free(&mut self.ws_key);
}
}
}