#![allow(clippy::too_many_arguments)]
use crate::error::{Error, Result};
use crate::raw;
use crate::types::{Algorithm, Curve, KeyType};
use alloc::{vec, vec::Vec};
use core::ffi::c_void;
use core::marker::PhantomData;
use core::ptr;
use core::ptr::NonNull;
use core::slice;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PayloadMode<'a> {
Attached(&'a [u8]),
Detached(&'a [u8]),
}
impl<'a> PayloadMode<'a> {
fn sign_parts(self) -> (*const u8, usize, *const u8, usize) {
match self {
Self::Attached(payload) => ptr_len(payload).with_detached(None),
Self::Detached(payload) => (ptr::null(), 0, ptr_or_null(payload), payload.len()),
}
}
}
trait WithDetached {
fn with_detached(self, detached: Option<&[u8]>) -> (*const u8, usize, *const u8, usize);
}
impl WithDetached for (*const u8, usize) {
fn with_detached(self, detached: Option<&[u8]>) -> (*const u8, usize, *const u8, usize) {
match detached {
Some(data) => (self.0, self.1, ptr_or_null(data), data.len()),
None => (self.0, self.1, ptr::null(), 0),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Header {
pub algorithm: i32,
pub kid: Vec<u8>,
pub iv: Vec<u8>,
pub partial_iv: Vec<u8>,
pub content_type: i32,
pub detached: bool,
}
impl Header {
fn from_raw(raw_hdr: &raw::WOLFCOSE_HDR) -> Self {
Self {
algorithm: raw_hdr.alg,
kid: copy_opt(raw_hdr.kid, raw_hdr.kidLen),
iv: copy_opt(raw_hdr.iv, raw_hdr.ivLen),
partial_iv: copy_opt(raw_hdr.partialIv, raw_hdr.partialIvLen),
content_type: raw_hdr.contentType,
detached: (raw_hdr.flags & raw::WOLFCOSE_HDR_FLAG_DETACHED as u8) != 0,
}
}
}
pub struct CoseKey {
raw: raw::WOLFCOSE_KEY,
key_material: Option<Vec<u8>>,
kid: Option<Vec<u8>>,
}
impl CoseKey {
pub fn new() -> Result<Self> {
let mut raw_key = raw::WOLFCOSE_KEY::default();
Error::from_code(unsafe { raw::wc_CoseKey_Init(&mut raw_key) })?;
Ok(Self {
raw: raw_key,
key_material: None,
kid: None,
})
}
pub fn symmetric(material: impl AsRef<[u8]>) -> Result<Self> {
let mut key = Self::new()?;
key.set_symmetric(material)?;
Ok(key)
}
pub fn set_symmetric(&mut self, material: impl AsRef<[u8]>) -> Result<()> {
let material = material.as_ref().to_vec();
let ptr = ptr_or_null(&material);
Error::from_code(unsafe {
raw::wc_CoseKey_SetSymmetric(&mut self.raw, ptr, material.len())
})?;
self.key_material = Some(material);
Ok(())
}
pub unsafe fn set_ecc_raw(&mut self, curve: Curve, ecc_key: NonNull<c_void>) -> Result<()> {
Error::from_code(unsafe {
raw::rb_wc_CoseKey_SetEcc(self.as_raw_mut(), curve.id(), ecc_key.as_ptr())
})
}
pub unsafe fn set_ed25519_raw(&mut self, ed_key: NonNull<c_void>) -> Result<()> {
Error::from_code(unsafe {
raw::rb_wc_CoseKey_SetEd25519(self.as_raw_mut(), ed_key.as_ptr())
})
}
pub unsafe fn set_ed448_raw(&mut self, ed_key: NonNull<c_void>) -> Result<()> {
Error::from_code(unsafe { raw::rb_wc_CoseKey_SetEd448(self.as_raw_mut(), ed_key.as_ptr()) })
}
pub unsafe fn set_dilithium_raw(
&mut self,
algorithm: Algorithm,
dl_key: NonNull<c_void>,
) -> Result<()> {
Error::from_code(unsafe {
raw::rb_wc_CoseKey_SetDilithium(self.as_raw_mut(), algorithm.id(), dl_key.as_ptr())
})
}
pub unsafe fn set_rsa_raw(&mut self, rsa_key: NonNull<c_void>) -> Result<()> {
Error::from_code(unsafe { raw::rb_wc_CoseKey_SetRsa(self.as_raw_mut(), rsa_key.as_ptr()) })
}
pub fn set_kid(&mut self, kid: impl AsRef<[u8]>) {
let kid = kid.as_ref().to_vec();
self.raw.kid = ptr_or_null(&kid);
self.raw.kidLen = kid.len();
self.kid = Some(kid);
}
pub fn set_algorithm(&mut self, algorithm: Algorithm) {
self.raw.alg = algorithm.id();
}
pub fn set_key_type(&mut self, key_type: KeyType) {
self.raw.kty = key_type.id();
}
pub fn set_curve(&mut self, curve: Curve) {
self.raw.crv = curve.id();
}
pub fn set_has_private(&mut self, has_private: bool) {
self.raw.hasPrivate = u8::from(has_private);
}
pub fn has_private(&self) -> bool {
self.raw.hasPrivate != 0
}
pub fn kid(&self) -> Option<&[u8]> {
self.kid.as_deref()
}
pub fn symmetric_material(&self) -> Option<&[u8]> {
self.key_material.as_deref()
}
pub fn encode_into<'out>(&mut self, out: &'out mut [u8]) -> Result<&'out [u8]> {
let mut out_len = 0;
Error::from_code(unsafe {
raw::wc_CoseKey_Encode(&mut self.raw, out.as_mut_ptr(), out.len(), &mut out_len)
})?;
Ok(&out[..out_len])
}
pub fn encode_to_vec(&mut self) -> Result<Vec<u8>> {
with_growing_output(|out| self.encode_into(out).map(|slice| slice.len()))
}
pub fn decode(&mut self, input: &[u8]) -> Result<()> {
Error::from_code(unsafe {
raw::wc_CoseKey_Decode(&mut self.raw, ptr_or_null(input), input.len())
})
}
pub fn as_raw(&self) -> &raw::WOLFCOSE_KEY {
&self.raw
}
pub fn as_raw_mut(&mut self) -> &mut raw::WOLFCOSE_KEY {
&mut self.raw
}
fn as_mut_ptr(&self) -> *mut raw::WOLFCOSE_KEY {
(&self.raw as *const raw::WOLFCOSE_KEY).cast_mut()
}
}
impl Drop for CoseKey {
fn drop(&mut self) {
unsafe { raw::wc_CoseKey_Free(&mut self.raw) }
}
}
pub struct Signature<'a> {
algorithm: Algorithm,
key: &'a CoseKey,
kid: Option<&'a [u8]>,
}
impl<'a> Signature<'a> {
pub fn new(algorithm: Algorithm, key: &'a CoseKey) -> Self {
Self {
algorithm,
key,
kid: None,
}
}
pub fn with_kid(mut self, kid: &'a [u8]) -> Self {
self.kid = Some(kid);
self
}
fn to_raw(&self) -> raw::WOLFCOSE_SIGNATURE {
let kid = self.kid.unwrap_or(&[]);
raw::WOLFCOSE_SIGNATURE {
algId: self.algorithm.id(),
key: self.key.as_mut_ptr(),
kid: ptr_or_null(kid),
kidLen: kid.len(),
}
}
}
pub struct Recipient<'a> {
algorithm: Algorithm,
key: &'a CoseKey,
kid: Option<&'a [u8]>,
}
impl<'a> Recipient<'a> {
pub fn new(algorithm: Algorithm, key: &'a CoseKey) -> Self {
Self {
algorithm,
key,
kid: None,
}
}
pub fn with_kid(mut self, kid: &'a [u8]) -> Self {
self.kid = Some(kid);
self
}
fn to_raw(&self) -> raw::WOLFCOSE_RECIPIENT {
let kid = self.kid.unwrap_or(&[]);
raw::WOLFCOSE_RECIPIENT {
algId: self.algorithm.id(),
key: self.key.as_mut_ptr(),
kid: ptr_or_null(kid),
kidLen: kid.len(),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VerifyOutput<'a> {
pub header: Header,
pub payload: Option<&'a [u8]>,
}
pub type MacVerifyOutput<'a> = VerifyOutput<'a>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DecryptOutput {
pub header: Header,
pub plaintext_len: usize,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Encrypt0DetachedOutput {
pub message_len: usize,
pub ciphertext_len: usize,
}
pub fn sign1_into<'out>(
key: &CoseKey,
algorithm: Algorithm,
kid: Option<&[u8]>,
payload: PayloadMode<'_>,
external_aad: &[u8],
scratch: &mut [u8],
out: &'out mut [u8],
rng: Option<NonNull<raw::WC_RNG>>,
) -> Result<&'out [u8]> {
let kid = kid.unwrap_or(&[]);
let (payload_ptr, payload_len, detached_ptr, detached_len) = payload.sign_parts();
let mut out_len = 0;
Error::from_code(unsafe {
raw::wc_CoseSign1_Sign(
key.as_mut_ptr(),
algorithm.id(),
ptr_or_null(kid),
kid.len(),
payload_ptr,
payload_len,
detached_ptr,
detached_len,
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
out.as_mut_ptr(),
out.len(),
&mut out_len,
rng_ptr(rng),
)
})?;
Ok(&out[..out_len])
}
pub fn sign1_to_vec(
key: &CoseKey,
algorithm: Algorithm,
kid: Option<&[u8]>,
payload: PayloadMode<'_>,
external_aad: &[u8],
scratch: &mut [u8],
rng: Option<NonNull<raw::WC_RNG>>,
) -> Result<Vec<u8>> {
with_growing_output(|out| {
sign1_into(
key,
algorithm,
kid,
payload,
external_aad,
scratch,
out,
rng,
)
.map(|slice| slice.len())
})
}
pub fn verify1<'inbuf>(
key: &CoseKey,
input: &'inbuf [u8],
detached_payload: Option<&[u8]>,
external_aad: &[u8],
scratch: &mut [u8],
) -> Result<VerifyOutput<'inbuf>> {
let mut header = raw::WOLFCOSE_HDR::default();
let mut payload = ptr::null();
let mut payload_len = 0;
let detached = detached_payload.unwrap_or(&[]);
Error::from_code(unsafe {
raw::wc_CoseSign1_Verify(
key.as_mut_ptr(),
ptr_or_null(input),
input.len(),
opt_ptr(detached_payload),
detached.len(),
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
&mut header,
&mut payload,
&mut payload_len,
)
})?;
Ok(VerifyOutput {
header: Header::from_raw(&header),
payload: borrowed_payload(payload, payload_len),
})
}
pub fn encrypt0_into<'out>(
key: &CoseKey,
algorithm: Algorithm,
iv: &[u8],
payload: &[u8],
external_aad: &[u8],
scratch: &mut [u8],
out: &'out mut [u8],
) -> Result<&'out [u8]> {
let mut out_len = 0;
let mut detached_len = 0;
Error::from_code(unsafe {
raw::wc_CoseEncrypt0_Encrypt(
key.as_mut_ptr(),
algorithm.id(),
ptr_or_null(iv),
iv.len(),
ptr_or_null(payload),
payload.len(),
ptr::null_mut(),
0,
&mut detached_len,
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
out.as_mut_ptr(),
out.len(),
&mut out_len,
)
})?;
Ok(&out[..out_len])
}
pub fn encrypt0_to_vec(
key: &CoseKey,
algorithm: Algorithm,
iv: &[u8],
payload: &[u8],
external_aad: &[u8],
scratch: &mut [u8],
) -> Result<Vec<u8>> {
with_growing_output(|out| {
encrypt0_into(key, algorithm, iv, payload, external_aad, scratch, out)
.map(|slice| slice.len())
})
}
pub fn encrypt0_detached_into(
key: &CoseKey,
algorithm: Algorithm,
iv: &[u8],
plaintext: &[u8],
external_aad: &[u8],
scratch: &mut [u8],
out: &mut [u8],
detached_ciphertext: &mut [u8],
) -> Result<Encrypt0DetachedOutput> {
let mut out_len = 0;
let mut detached_len = 0;
Error::from_code(unsafe {
raw::wc_CoseEncrypt0_Encrypt(
key.as_mut_ptr(),
algorithm.id(),
ptr_or_null(iv),
iv.len(),
ptr_or_null(plaintext),
plaintext.len(),
detached_ciphertext.as_mut_ptr(),
detached_ciphertext.len(),
&mut detached_len,
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
out.as_mut_ptr(),
out.len(),
&mut out_len,
)
})?;
Ok(Encrypt0DetachedOutput {
message_len: out_len,
ciphertext_len: detached_len,
})
}
pub fn verify0_into(
key: &CoseKey,
input: &[u8],
detached_ciphertext: Option<&[u8]>,
external_aad: &[u8],
scratch: &mut [u8],
plaintext: &mut [u8],
) -> Result<DecryptOutput> {
decrypt0_into(
key,
input,
detached_ciphertext,
external_aad,
scratch,
plaintext,
)
}
pub fn decrypt0_into(
key: &CoseKey,
input: &[u8],
detached_ciphertext: Option<&[u8]>,
external_aad: &[u8],
scratch: &mut [u8],
plaintext: &mut [u8],
) -> Result<DecryptOutput> {
let mut header = raw::WOLFCOSE_HDR::default();
let mut plaintext_len = 0;
let detached = detached_ciphertext.unwrap_or(&[]);
Error::from_code(unsafe {
raw::wc_CoseEncrypt0_Decrypt(
key.as_mut_ptr(),
ptr_or_null(input),
input.len(),
opt_ptr(detached_ciphertext),
detached.len(),
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
&mut header,
plaintext.as_mut_ptr(),
plaintext.len(),
&mut plaintext_len,
)
})?;
Ok(DecryptOutput {
header: Header::from_raw(&header),
plaintext_len,
})
}
pub fn mac0_into<'out>(
key: &CoseKey,
algorithm: Algorithm,
kid: Option<&[u8]>,
payload: PayloadMode<'_>,
external_aad: &[u8],
scratch: &mut [u8],
out: &'out mut [u8],
) -> Result<&'out [u8]> {
let kid = kid.unwrap_or(&[]);
let (payload_ptr, payload_len, detached_ptr, detached_len) = payload.sign_parts();
let mut out_len = 0;
Error::from_code(unsafe {
raw::wc_CoseMac0_Create(
key.as_raw(),
algorithm.id(),
ptr_or_null(kid),
kid.len(),
payload_ptr,
payload_len,
detached_ptr,
detached_len,
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
out.as_mut_ptr(),
out.len(),
&mut out_len,
)
})?;
Ok(&out[..out_len])
}
pub fn mac0_to_vec(
key: &CoseKey,
algorithm: Algorithm,
kid: Option<&[u8]>,
payload: PayloadMode<'_>,
external_aad: &[u8],
scratch: &mut [u8],
) -> Result<Vec<u8>> {
with_growing_output(|out| {
mac0_into(key, algorithm, kid, payload, external_aad, scratch, out).map(|slice| slice.len())
})
}
pub fn verify_mac0<'inbuf>(
key: &CoseKey,
input: &'inbuf [u8],
detached_payload: Option<&[u8]>,
external_aad: &[u8],
scratch: &mut [u8],
) -> Result<MacVerifyOutput<'inbuf>> {
let mut header = raw::WOLFCOSE_HDR::default();
let mut payload = ptr::null();
let mut payload_len = 0;
let detached = detached_payload.unwrap_or(&[]);
Error::from_code(unsafe {
raw::wc_CoseMac0_Verify(
key.as_raw(),
ptr_or_null(input),
input.len(),
opt_ptr(detached_payload),
detached.len(),
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
&mut header,
&mut payload,
&mut payload_len,
)
})?;
Ok(VerifyOutput {
header: Header::from_raw(&header),
payload: borrowed_payload(payload, payload_len),
})
}
pub fn sign_into<'out>(
signers: &[Signature<'_>],
payload: PayloadMode<'_>,
external_aad: &[u8],
scratch: &mut [u8],
out: &'out mut [u8],
rng: Option<NonNull<raw::WC_RNG>>,
) -> Result<&'out [u8]> {
let raw_signers: Vec<_> = signers.iter().map(Signature::to_raw).collect();
let (payload_ptr, payload_len, detached_ptr, detached_len) = payload.sign_parts();
let mut out_len = 0;
Error::from_code(unsafe {
raw::wc_CoseSign_Sign(
raw_signers.as_ptr(),
raw_signers.len(),
payload_ptr,
payload_len,
detached_ptr,
detached_len,
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
out.as_mut_ptr(),
out.len(),
&mut out_len,
rng_ptr(rng),
)
})?;
Ok(&out[..out_len])
}
pub fn sign_to_vec(
signers: &[Signature<'_>],
payload: PayloadMode<'_>,
external_aad: &[u8],
scratch: &mut [u8],
rng: Option<NonNull<raw::WC_RNG>>,
) -> Result<Vec<u8>> {
with_growing_output(|out| {
sign_into(signers, payload, external_aad, scratch, out, rng).map(|s| s.len())
})
}
pub fn verify_sign<'inbuf>(
key: &CoseKey,
signer_index: usize,
input: &'inbuf [u8],
detached_payload: Option<&[u8]>,
external_aad: &[u8],
scratch: &mut [u8],
) -> Result<VerifyOutput<'inbuf>> {
let mut header = raw::WOLFCOSE_HDR::default();
let mut payload = ptr::null();
let mut payload_len = 0;
let detached = detached_payload.unwrap_or(&[]);
Error::from_code(unsafe {
raw::wc_CoseSign_Verify(
key.as_raw(),
signer_index,
ptr_or_null(input),
input.len(),
opt_ptr(detached_payload),
detached.len(),
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
&mut header,
&mut payload,
&mut payload_len,
)
})?;
Ok(VerifyOutput {
header: Header::from_raw(&header),
payload: borrowed_payload(payload, payload_len),
})
}
pub fn encrypt_into<'out>(
recipients: &[Recipient<'_>],
content_algorithm: Algorithm,
iv: &[u8],
payload: &[u8],
external_aad: &[u8],
scratch: &mut [u8],
out: &'out mut [u8],
rng: Option<NonNull<raw::WC_RNG>>,
) -> Result<&'out [u8]> {
let raw_recipients: Vec<_> = recipients.iter().map(Recipient::to_raw).collect();
let mut out_len = 0;
Error::from_code(unsafe {
raw::wc_CoseEncrypt_Encrypt(
raw_recipients.as_ptr(),
raw_recipients.len(),
content_algorithm.id(),
ptr_or_null(iv),
iv.len(),
ptr_or_null(payload),
payload.len(),
ptr::null(),
0,
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
out.as_mut_ptr(),
out.len(),
&mut out_len,
rng_ptr(rng),
)
})?;
Ok(&out[..out_len])
}
pub fn encrypt_to_vec(
recipients: &[Recipient<'_>],
content_algorithm: Algorithm,
iv: &[u8],
payload: &[u8],
external_aad: &[u8],
scratch: &mut [u8],
rng: Option<NonNull<raw::WC_RNG>>,
) -> Result<Vec<u8>> {
with_growing_output(|out| {
encrypt_into(
recipients,
content_algorithm,
iv,
payload,
external_aad,
scratch,
out,
rng,
)
.map(|slice| slice.len())
})
}
pub fn encrypt_detached_into<'out>(
recipients: &[Recipient<'_>],
content_algorithm: Algorithm,
iv: &[u8],
detached_payload: &[u8],
external_aad: &[u8],
scratch: &mut [u8],
out: &'out mut [u8],
rng: Option<NonNull<raw::WC_RNG>>,
) -> Result<&'out [u8]> {
let raw_recipients: Vec<_> = recipients.iter().map(Recipient::to_raw).collect();
let mut out_len = 0;
Error::from_code(unsafe {
raw::wc_CoseEncrypt_Encrypt(
raw_recipients.as_ptr(),
raw_recipients.len(),
content_algorithm.id(),
ptr_or_null(iv),
iv.len(),
ptr::null(),
0,
ptr_or_null(detached_payload),
detached_payload.len(),
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
out.as_mut_ptr(),
out.len(),
&mut out_len,
rng_ptr(rng),
)
})?;
Ok(&out[..out_len])
}
pub fn decrypt_into(
recipient: &Recipient<'_>,
recipient_index: usize,
input: &[u8],
detached_ciphertext: Option<&[u8]>,
external_aad: &[u8],
scratch: &mut [u8],
plaintext: &mut [u8],
) -> Result<DecryptOutput> {
let raw_recipient = recipient.to_raw();
let mut header = raw::WOLFCOSE_HDR::default();
let mut plaintext_len = 0;
let detached = detached_ciphertext.unwrap_or(&[]);
Error::from_code(unsafe {
raw::wc_CoseEncrypt_Decrypt(
&raw_recipient,
recipient_index,
ptr_or_null(input),
input.len(),
opt_ptr(detached_ciphertext),
detached.len(),
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
&mut header,
plaintext.as_mut_ptr(),
plaintext.len(),
&mut plaintext_len,
)
})?;
Ok(DecryptOutput {
header: Header::from_raw(&header),
plaintext_len,
})
}
pub fn mac_into<'out>(
recipients: &[Recipient<'_>],
algorithm: Algorithm,
payload: PayloadMode<'_>,
external_aad: &[u8],
scratch: &mut [u8],
out: &'out mut [u8],
) -> Result<&'out [u8]> {
let raw_recipients: Vec<_> = recipients.iter().map(Recipient::to_raw).collect();
let (payload_ptr, payload_len, detached_ptr, detached_len) = payload.sign_parts();
let mut out_len = 0;
Error::from_code(unsafe {
raw::wc_CoseMac_Create(
raw_recipients.as_ptr(),
raw_recipients.len(),
algorithm.id(),
payload_ptr,
payload_len,
detached_ptr,
detached_len,
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
out.as_mut_ptr(),
out.len(),
&mut out_len,
)
})?;
Ok(&out[..out_len])
}
pub fn mac_to_vec(
recipients: &[Recipient<'_>],
algorithm: Algorithm,
payload: PayloadMode<'_>,
external_aad: &[u8],
scratch: &mut [u8],
) -> Result<Vec<u8>> {
with_growing_output(|out| {
mac_into(recipients, algorithm, payload, external_aad, scratch, out)
.map(|slice| slice.len())
})
}
pub fn verify_mac<'inbuf>(
recipient: &Recipient<'_>,
recipient_index: usize,
input: &'inbuf [u8],
detached_payload: Option<&[u8]>,
external_aad: &[u8],
scratch: &mut [u8],
) -> Result<MacVerifyOutput<'inbuf>> {
let raw_recipient = recipient.to_raw();
let mut header = raw::WOLFCOSE_HDR::default();
let mut payload = ptr::null();
let mut payload_len = 0;
let detached = detached_payload.unwrap_or(&[]);
Error::from_code(unsafe {
raw::wc_CoseMac_Verify(
&raw_recipient,
recipient_index,
ptr_or_null(input),
input.len(),
opt_ptr(detached_payload),
detached.len(),
ptr_or_null(external_aad),
external_aad.len(),
scratch.as_mut_ptr(),
scratch.len(),
&mut header,
&mut payload,
&mut payload_len,
)
})?;
Ok(VerifyOutput {
header: Header::from_raw(&header),
payload: borrowed_payload(payload, payload_len),
})
}
fn ptr_or_null(data: &[u8]) -> *const u8 {
if data.is_empty() {
ptr::null()
} else {
data.as_ptr()
}
}
fn ptr_len(data: &[u8]) -> (*const u8, usize) {
(ptr_or_null(data), data.len())
}
fn opt_ptr(data: Option<&[u8]>) -> *const u8 {
data.map(ptr_or_null).unwrap_or(ptr::null())
}
fn rng_ptr(rng: Option<NonNull<raw::WC_RNG>>) -> *mut raw::WC_RNG {
rng.map(NonNull::as_ptr).unwrap_or(ptr::null_mut())
}
fn copy_opt(ptr: *const u8, len: usize) -> Vec<u8> {
if ptr.is_null() || len == 0 {
Vec::new()
} else {
unsafe { slice::from_raw_parts(ptr, len).to_vec() }
}
}
fn borrowed_payload<'a>(ptr: *const u8, len: usize) -> Option<&'a [u8]> {
if ptr.is_null() {
None
} else {
Some(unsafe { slice::from_raw_parts(ptr, len) })
}
}
fn with_growing_output(mut f: impl FnMut(&mut [u8]) -> Result<usize>) -> Result<Vec<u8>> {
let mut size = 1024;
loop {
let mut out = vec![0; size];
match f(&mut out) {
Ok(len) => {
out.truncate(len);
return Ok(out);
}
Err(Error::BufferTooSmall) if size < 16 * 1024 * 1024 => size *= 2,
Err(err) => return Err(err),
}
}
}
#[allow(dead_code)]
struct NotSendSync(PhantomData<*mut ()>);