use core::cell::UnsafeCell;
use core::ffi::c_void;
use core::ptr;
use alloc::boxed::Box;
use alloc::vec;
use alloc::vec::Vec;
use crate::error::{len_as_u32, WolfCryptError};
#[cfg(feature = "rsa-direct")]
use crate::error::check;
use wolfcrypt_rs::{
wolfcrypt_rsa_export_private_pkcs1, wolfcrypt_rsa_export_public_spki, wolfcrypt_rsa_free,
wolfcrypt_rsa_generate, wolfcrypt_rsa_import_private_pkcs1, wolfcrypt_rsa_import_public_spki,
wolfcrypt_rsa_key_size_bytes, wolfcrypt_rsa_new, wolfcrypt_rsa_oaep_decrypt_sha256,
wolfcrypt_rsa_oaep_encrypt_sha256, wolfcrypt_rsa_pkcs1v15_decrypt,
wolfcrypt_rsa_pkcs1v15_encrypt, wolfcrypt_rsa_pkcs1v15_sign, wolfcrypt_rsa_pkcs1v15_verify,
wolfcrypt_rsa_pss_sign, wolfcrypt_rsa_pss_verify,
};
const RSA_MIN_SIG_BYTES: usize = 64;
#[derive(Clone, Debug)]
pub struct RsaPkcs1v15Signature(Vec<u8>);
impl AsRef<[u8]> for RsaPkcs1v15Signature {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl signature_trait::SignatureEncoding for RsaPkcs1v15Signature {
type Repr = Box<[u8]>;
}
impl TryFrom<&[u8]> for RsaPkcs1v15Signature {
type Error = signature_trait::Error;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < RSA_MIN_SIG_BYTES {
return Err(signature_trait::Error::new());
}
Ok(Self(bytes.to_vec()))
}
}
impl From<RsaPkcs1v15Signature> for Box<[u8]> {
fn from(sig: RsaPkcs1v15Signature) -> Box<[u8]> {
sig.0.into_boxed_slice()
}
}
#[derive(Clone, Debug)]
pub struct RsaPssSignature(Vec<u8>);
impl AsRef<[u8]> for RsaPssSignature {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl signature_trait::SignatureEncoding for RsaPssSignature {
type Repr = Box<[u8]>;
}
impl TryFrom<&[u8]> for RsaPssSignature {
type Error = signature_trait::Error;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < RSA_MIN_SIG_BYTES {
return Err(signature_trait::Error::new());
}
Ok(Self(bytes.to_vec()))
}
}
impl From<RsaPssSignature> for Box<[u8]> {
fn from(sig: RsaPssSignature) -> Box<[u8]> {
sig.0.into_boxed_slice()
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RsaDigest {
Sha1,
Sha256,
Sha384,
Sha512,
}
impl RsaDigest {
fn hash_bits(self) -> i32 {
match self {
Self::Sha1 => 160,
Self::Sha256 => 256,
Self::Sha384 => 384,
Self::Sha512 => 512,
}
}
}
unsafe fn native_oaep_encrypt_sha256(
ctx: *mut c_void,
plaintext: &[u8],
) -> Result<Vec<u8>, WolfCryptError> {
unsafe {
let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _);
if key_size <= 0 {
return Err(WolfCryptError::Ffi {
code: key_size,
func: "wolfcrypt_rsa_key_size_bytes",
});
}
let mut out = vec![0u8; key_size as usize];
let rc = wolfcrypt_rsa_oaep_encrypt_sha256(
ctx,
plaintext.as_ptr(),
len_as_u32(plaintext.len()),
out.as_mut_ptr(),
key_size as u32,
);
if rc <= 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_oaep_encrypt_sha256",
});
}
out.truncate(rc as usize);
Ok(out)
}
}
unsafe fn native_oaep_decrypt_sha256(
ctx: *mut c_void,
ciphertext: &[u8],
) -> Result<Vec<u8>, WolfCryptError> {
unsafe {
let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _);
if key_size <= 0 {
return Err(WolfCryptError::Ffi {
code: key_size,
func: "wolfcrypt_rsa_key_size_bytes",
});
}
let mut out = vec![0u8; key_size as usize];
let rc = wolfcrypt_rsa_oaep_decrypt_sha256(
ctx,
ciphertext.as_ptr(),
len_as_u32(ciphertext.len()),
out.as_mut_ptr(),
key_size as u32,
);
if rc <= 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_oaep_decrypt_sha256",
});
}
out.truncate(rc as usize);
Ok(out)
}
}
unsafe fn native_pkcs1v15_sign(
ctx: *mut c_void,
msg: &[u8],
hash_bits: i32,
) -> Result<Vec<u8>, WolfCryptError> {
unsafe {
let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _);
if key_size <= 0 {
return Err(WolfCryptError::Ffi {
code: key_size,
func: "wolfcrypt_rsa_key_size_bytes",
});
}
let mut sig = vec![0u8; key_size as usize];
let mut sig_len = key_size as u32;
let rc = wolfcrypt_rsa_pkcs1v15_sign(
ctx,
hash_bits,
msg.as_ptr(),
len_as_u32(msg.len()),
sig.as_mut_ptr(),
&mut sig_len,
);
if rc != 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_pkcs1v15_sign",
});
}
sig.truncate(sig_len as usize);
Ok(sig)
}
}
unsafe fn native_pkcs1v15_verify(
ctx: *mut c_void,
msg: &[u8],
sig: &[u8],
hash_bits: i32,
) -> Result<(), WolfCryptError> {
unsafe {
let rc = wolfcrypt_rsa_pkcs1v15_verify(
ctx,
hash_bits,
msg.as_ptr(),
len_as_u32(msg.len()),
sig.as_ptr(),
len_as_u32(sig.len()),
);
if rc != 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_pkcs1v15_verify",
});
}
Ok(())
}
}
unsafe fn native_pss_sign(
ctx: *mut c_void,
msg: &[u8],
hash_bits: i32,
) -> Result<Vec<u8>, WolfCryptError> {
unsafe {
let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _);
if key_size <= 0 {
return Err(WolfCryptError::Ffi {
code: key_size,
func: "wolfcrypt_rsa_key_size_bytes",
});
}
let mut sig = vec![0u8; key_size as usize];
let mut sig_len = key_size as u32;
let rc = wolfcrypt_rsa_pss_sign(
ctx,
hash_bits,
msg.as_ptr(),
len_as_u32(msg.len()),
sig.as_mut_ptr(),
&mut sig_len,
);
if rc != 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_pss_sign",
});
}
sig.truncate(sig_len as usize);
Ok(sig)
}
}
unsafe fn native_pss_verify(
ctx: *mut c_void,
msg: &[u8],
sig: &[u8],
hash_bits: i32,
) -> Result<(), WolfCryptError> {
unsafe {
let rc = wolfcrypt_rsa_pss_verify(
ctx,
hash_bits,
msg.as_ptr(),
len_as_u32(msg.len()),
sig.as_ptr(),
len_as_u32(sig.len()),
);
if rc != 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_pss_verify",
});
}
Ok(())
}
}
unsafe fn native_pkcs1v15_encrypt(
ctx: *mut c_void,
plaintext: &[u8],
) -> Result<Vec<u8>, WolfCryptError> {
unsafe {
let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _);
if key_size <= 0 {
return Err(WolfCryptError::Ffi {
code: key_size,
func: "wolfcrypt_rsa_key_size_bytes",
});
}
let mut out = vec![0u8; key_size as usize];
let rc = wolfcrypt_rsa_pkcs1v15_encrypt(
ctx,
plaintext.as_ptr(),
len_as_u32(plaintext.len()),
out.as_mut_ptr(),
key_size as u32,
);
if rc <= 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_pkcs1v15_encrypt",
});
}
out.truncate(rc as usize);
Ok(out)
}
}
unsafe fn native_pkcs1v15_decrypt(
ctx: *mut c_void,
ciphertext: &[u8],
) -> Result<Vec<u8>, WolfCryptError> {
unsafe {
let key_size = wolfcrypt_rsa_key_size_bytes(ctx as *const _);
if key_size <= 0 {
return Err(WolfCryptError::Ffi {
code: key_size,
func: "wolfcrypt_rsa_key_size_bytes",
});
}
let mut out = vec![0u8; key_size as usize];
let rc = wolfcrypt_rsa_pkcs1v15_decrypt(
ctx,
ciphertext.as_ptr(),
len_as_u32(ciphertext.len()),
out.as_mut_ptr(),
key_size as u32,
);
if rc <= 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_pkcs1v15_decrypt",
});
}
out.truncate(rc as usize);
Ok(out)
}
}
pub struct RsaPrivateKey {
ctx: UnsafeCell<*mut c_void>,
}
unsafe impl Send for RsaPrivateKey {}
impl RsaPrivateKey {
pub fn from_pkcs1_der(der: &[u8]) -> Result<Self, WolfCryptError> {
unsafe {
let ctx = wolfcrypt_rsa_new();
if ctx.is_null() {
return Err(WolfCryptError::ALLOC_FAILED);
}
let rc = wolfcrypt_rsa_import_private_pkcs1(ctx, der.as_ptr(), len_as_u32(der.len()));
if rc != 0 {
wolfcrypt_rsa_free(ctx);
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_import_private_pkcs1",
});
}
Ok(Self {
ctx: UnsafeCell::new(ctx),
})
}
}
pub fn to_pkcs1_der(&self) -> Result<Vec<u8>, WolfCryptError> {
unsafe {
let ctx = *self.ctx.get();
let mut buf = vec![0u8; 4096];
let mut len = len_as_u32(buf.len());
let rc = wolfcrypt_rsa_export_private_pkcs1(ctx, buf.as_mut_ptr(), &mut len);
if rc != 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_export_private_pkcs1",
});
}
buf.truncate(len as usize);
Ok(buf)
}
}
pub fn generate(bits: u32) -> Result<Self, WolfCryptError> {
unsafe {
let ctx = wolfcrypt_rsa_new();
if ctx.is_null() {
return Err(WolfCryptError::ALLOC_FAILED);
}
let rc = wolfcrypt_rsa_generate(ctx, bits as i32);
if rc != 0 {
wolfcrypt_rsa_free(ctx);
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_generate",
});
}
Ok(Self {
ctx: UnsafeCell::new(ctx),
})
}
}
pub fn public_key(&self) -> RsaPublicKey {
unsafe {
let ctx = *self.ctx.get();
let mut spki = vec![0u8; 4096];
let mut spki_len = len_as_u32(spki.len());
let rc = wolfcrypt_rsa_export_public_spki(ctx, spki.as_mut_ptr(), &mut spki_len);
assert!(rc == 0, "wolfcrypt_rsa_export_public_spki failed: {rc}");
spki.truncate(spki_len as usize);
let new_ctx = wolfcrypt_rsa_new();
assert!(!new_ctx.is_null(), "wolfcrypt_rsa_new returned null");
let rc = wolfcrypt_rsa_import_public_spki(new_ctx, spki.as_ptr(), spki_len);
assert!(rc == 0, "wolfcrypt_rsa_import_public_spki failed: {rc}");
RsaPublicKey {
ctx: UnsafeCell::new(new_ctx),
}
}
}
pub fn sign_pkcs1v15(&self, msg: &[u8]) -> Result<RsaPkcs1v15Signature, WolfCryptError> {
self.sign_pkcs1v15_with_digest(msg, RsaDigest::Sha256)
}
pub fn sign_pkcs1v15_with_digest(
&self,
msg: &[u8],
digest: RsaDigest,
) -> Result<RsaPkcs1v15Signature, WolfCryptError> {
let sig = unsafe { native_pkcs1v15_sign(*self.ctx.get(), msg, digest.hash_bits())? };
Ok(RsaPkcs1v15Signature(sig))
}
pub fn sign_pss(&self, msg: &[u8]) -> Result<RsaPssSignature, WolfCryptError> {
self.sign_pss_with_digest(msg, RsaDigest::Sha256)
}
pub fn sign_pss_with_digest(
&self,
msg: &[u8],
digest: RsaDigest,
) -> Result<RsaPssSignature, WolfCryptError> {
let sig = unsafe { native_pss_sign(*self.ctx.get(), msg, digest.hash_bits())? };
Ok(RsaPssSignature(sig))
}
pub fn encrypt_oaep(&self, plaintext: &[u8]) -> Result<Vec<u8>, WolfCryptError> {
unsafe { native_oaep_encrypt_sha256(*self.ctx.get(), plaintext) }
}
pub fn decrypt_oaep(&self, ciphertext: &[u8]) -> Result<Vec<u8>, WolfCryptError> {
unsafe { native_oaep_decrypt_sha256(*self.ctx.get(), ciphertext) }
}
pub fn encrypt_pkcs1v15(&self, plaintext: &[u8]) -> Result<Vec<u8>, WolfCryptError> {
unsafe { native_pkcs1v15_encrypt(*self.ctx.get(), plaintext) }
}
pub fn decrypt_pkcs1v15(&self, ciphertext: &[u8]) -> Result<Vec<u8>, WolfCryptError> {
unsafe { native_pkcs1v15_decrypt(*self.ctx.get(), ciphertext) }
}
}
impl Drop for RsaPrivateKey {
fn drop(&mut self) {
unsafe {
wolfcrypt_rsa_free(*self.ctx.get());
}
}
}
impl signature_trait::Signer<RsaPkcs1v15Signature> for RsaPrivateKey {
fn try_sign(&self, msg: &[u8]) -> Result<RsaPkcs1v15Signature, signature_trait::Error> {
self.sign_pkcs1v15(msg)
.map_err(|_| signature_trait::Error::new())
}
}
impl signature_trait::Signer<RsaPssSignature> for RsaPrivateKey {
fn try_sign(&self, msg: &[u8]) -> Result<RsaPssSignature, signature_trait::Error> {
self.sign_pss(msg)
.map_err(|_| signature_trait::Error::new())
}
}
pub struct RsaPublicKey {
ctx: UnsafeCell<*mut c_void>,
}
unsafe impl Send for RsaPublicKey {}
impl RsaPublicKey {
pub fn from_der(der: &[u8]) -> Result<Self, WolfCryptError> {
unsafe {
let ctx = wolfcrypt_rsa_new();
if ctx.is_null() {
return Err(WolfCryptError::ALLOC_FAILED);
}
let rc = wolfcrypt_rsa_import_public_spki(ctx, der.as_ptr(), len_as_u32(der.len()));
if rc != 0 {
wolfcrypt_rsa_free(ctx);
return Err(WolfCryptError::Ffi {
code: rc,
func: "wolfcrypt_rsa_import_public_spki",
});
}
Ok(Self {
ctx: UnsafeCell::new(ctx),
})
}
}
pub fn encrypt_oaep(&self, plaintext: &[u8]) -> Result<Vec<u8>, WolfCryptError> {
unsafe { native_oaep_encrypt_sha256(*self.ctx.get(), plaintext) }
}
pub fn encrypt_pkcs1v15(&self, plaintext: &[u8]) -> Result<Vec<u8>, WolfCryptError> {
unsafe { native_pkcs1v15_encrypt(*self.ctx.get(), plaintext) }
}
pub fn verify_pkcs1v15(
&self,
msg: &[u8],
sig: &RsaPkcs1v15Signature,
) -> Result<(), WolfCryptError> {
self.verify_pkcs1v15_with_digest(msg, sig, RsaDigest::Sha256)
}
pub fn verify_pkcs1v15_with_digest(
&self,
msg: &[u8],
sig: &RsaPkcs1v15Signature,
digest: RsaDigest,
) -> Result<(), WolfCryptError> {
unsafe { native_pkcs1v15_verify(*self.ctx.get(), msg, &sig.0, digest.hash_bits()) }
}
pub fn verify_pss(&self, msg: &[u8], sig: &RsaPssSignature) -> Result<(), WolfCryptError> {
self.verify_pss_with_digest(msg, sig, RsaDigest::Sha256)
}
pub fn verify_pss_with_digest(
&self,
msg: &[u8],
sig: &RsaPssSignature,
digest: RsaDigest,
) -> Result<(), WolfCryptError> {
unsafe { native_pss_verify(*self.ctx.get(), msg, &sig.0, digest.hash_bits()) }
}
}
impl Drop for RsaPublicKey {
fn drop(&mut self) {
unsafe {
wolfcrypt_rsa_free(*self.ctx.get());
}
}
}
impl signature_trait::Verifier<RsaPkcs1v15Signature> for RsaPublicKey {
fn verify(
&self,
msg: &[u8],
signature: &RsaPkcs1v15Signature,
) -> Result<(), signature_trait::Error> {
self.verify_pkcs1v15(msg, signature)
.map_err(|_| signature_trait::Error::new())
}
}
impl signature_trait::Verifier<RsaPssSignature> for RsaPublicKey {
fn verify(
&self,
msg: &[u8],
signature: &RsaPssSignature,
) -> Result<(), signature_trait::Error> {
self.verify_pss(msg, signature)
.map_err(|_| signature_trait::Error::new())
}
}
#[cfg(feature = "rsa-direct")]
const RSA_TYPE_PUBLIC_ENCRYPT: i32 = 0;
#[cfg(feature = "rsa-direct")]
const RSA_TYPE_PUBLIC_DECRYPT: i32 = 1;
#[cfg(feature = "rsa-direct")]
const RSA_TYPE_PRIVATE_ENCRYPT: i32 = 2;
#[cfg(feature = "rsa-direct")]
const RSA_TYPE_PRIVATE_DECRYPT: i32 = 3;
#[cfg(feature = "rsa-direct")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RsaDirectType {
PublicEncrypt,
PublicDecrypt,
PrivateEncrypt,
PrivateDecrypt,
}
#[cfg(feature = "rsa-direct")]
impl RsaDirectType {
fn as_c_int(self) -> i32 {
match self {
Self::PublicEncrypt => RSA_TYPE_PUBLIC_ENCRYPT,
Self::PublicDecrypt => RSA_TYPE_PUBLIC_DECRYPT,
Self::PrivateEncrypt => RSA_TYPE_PRIVATE_ENCRYPT,
Self::PrivateDecrypt => RSA_TYPE_PRIVATE_DECRYPT,
}
}
}
#[cfg(feature = "rsa-direct")]
pub struct NativeRsaKey {
key: *mut wolfcrypt_rs::RsaKey,
}
#[cfg(feature = "rsa-direct")]
unsafe impl Send for NativeRsaKey {}
#[cfg(feature = "rsa-direct")]
impl NativeRsaKey {
fn alloc() -> Result<*mut wolfcrypt_rs::RsaKey, WolfCryptError> {
let mut rc: core::ffi::c_int = 0;
let key = unsafe {
wolfcrypt_rs::wc_NewRsaKey(ptr::null_mut(), wolfcrypt_rs::INVALID_DEVID, &mut rc)
};
if key.is_null() {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wc_NewRsaKey",
});
}
Ok(key)
}
#[deprecated(note = "use `generate` instead")]
pub fn generate_native(
bits: u32,
rng: &mut crate::rand::WolfRng,
) -> Result<Self, WolfCryptError> {
Self::generate(bits, rng)
}
pub fn to_pkcs1_der(&self) -> Result<alloc::vec::Vec<u8>, WolfCryptError> {
let mut buf = alloc::vec![0u8; 4096];
let rc = unsafe {
wolfcrypt_rs::wc_RsaKeyToDer(self.key, buf.as_mut_ptr(), len_as_u32(buf.len()))
};
if rc < 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wc_RsaKeyToDer",
});
}
buf.truncate(rc as usize);
Ok(buf)
}
pub fn from_private_der(der: &[u8]) -> Result<Self, WolfCryptError> {
let key = Self::alloc()?;
let mut idx: u32 = 0;
let rc = unsafe {
wolfcrypt_rs::wc_RsaPrivateKeyDecode(der.as_ptr(), &mut idx, key, len_as_u32(der.len()))
};
if rc != 0 {
unsafe {
wolfcrypt_rs::wc_DeleteRsaKey(key, ptr::null_mut());
}
return Err(WolfCryptError::Ffi {
code: rc,
func: "wc_RsaPrivateKeyDecode",
});
}
Ok(Self { key })
}
pub fn from_public_der(der: &[u8]) -> Result<Self, WolfCryptError> {
let key = Self::alloc()?;
let mut idx: u32 = 0;
let rc = unsafe {
wolfcrypt_rs::wc_RsaPublicKeyDecode(der.as_ptr(), &mut idx, key, len_as_u32(der.len()))
};
if rc != 0 {
unsafe {
wolfcrypt_rs::wc_DeleteRsaKey(key, ptr::null_mut());
}
return Err(WolfCryptError::Ffi {
code: rc,
func: "wc_RsaPublicKeyDecode",
});
}
Ok(Self { key })
}
pub fn generate(bits: u32, rng: &mut crate::rand::WolfRng) -> Result<Self, WolfCryptError> {
let key = Self::alloc()?;
let rc = unsafe {
wolfcrypt_rs::wc_MakeRsaKey(
key,
bits as core::ffi::c_int,
65537, &mut rng.rng,
)
};
if rc != 0 {
unsafe {
wolfcrypt_rs::wc_DeleteRsaKey(key, ptr::null_mut());
}
return Err(WolfCryptError::Ffi {
code: rc,
func: "wc_MakeRsaKey",
});
}
Ok(Self { key })
}
pub fn encrypt_size(&self) -> Result<usize, WolfCryptError> {
let sz = unsafe { wolfcrypt_rs::wc_RsaEncryptSize(self.key as *const _) };
if sz <= 0 {
return Err(WolfCryptError::Ffi {
code: sz,
func: "wc_RsaEncryptSize",
});
}
Ok(sz as usize)
}
pub fn rsa_direct(
&mut self,
input: &[u8],
type_: RsaDirectType,
rng: &mut crate::rand::WolfRng,
) -> Result<Vec<u8>, WolfCryptError> {
let key_sz = self.encrypt_size()?;
if input.len() != key_sz {
return Err(WolfCryptError::InvalidInput);
}
let mut out = vec![0u8; key_sz];
let mut out_len: u32 = key_sz as u32;
let rc = unsafe {
wolfcrypt_rs::wc_RsaFunction(
input.as_ptr(),
len_as_u32(input.len()),
out.as_mut_ptr(),
&mut out_len,
type_.as_c_int(),
self.key,
&mut rng.rng,
)
};
check(rc, "wc_RsaFunction")?;
out.truncate(out_len as usize);
Ok(out)
}
pub fn from_raw_components(
n: &[u8],
e: &[u8],
d: &[u8],
p: &[u8],
q: &[u8],
iqmp: &[u8],
) -> Result<Self, WolfCryptError> {
let key = Self::alloc()?;
let rc = unsafe {
wolfcrypt_rs::wc_RsaPrivateKeyDecodeRaw(
n.as_ptr(),
len_as_u32(n.len()),
e.as_ptr(),
len_as_u32(e.len()),
d.as_ptr(),
len_as_u32(d.len()),
iqmp.as_ptr(),
len_as_u32(iqmp.len()),
p.as_ptr(),
len_as_u32(p.len()),
q.as_ptr(),
len_as_u32(q.len()),
ptr::null(),
0, ptr::null(),
0, key,
)
};
if rc != 0 {
unsafe { wolfcrypt_rs::wc_DeleteRsaKey(key, ptr::null_mut()) };
return Err(WolfCryptError::Ffi {
code: rc,
func: "wc_RsaPrivateKeyDecodeRaw",
});
}
Ok(Self { key })
}
pub fn key_size(&self) -> Result<usize, WolfCryptError> {
let rc = unsafe { wolfcrypt_rs::wc_RsaEncryptSize(self.key) };
if rc < 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wc_RsaEncryptSize",
});
}
Ok(rc as usize)
}
pub fn sign_pkcs1v15_raw(
&self,
digest_info: &[u8],
rng: &mut crate::rand::WolfRng,
) -> Result<alloc::vec::Vec<u8>, WolfCryptError> {
let key_sz = self.key_size()?;
let mut out = alloc::vec![0u8; key_sz];
let rc = unsafe {
wolfcrypt_rs::wc_RsaSSL_Sign(
digest_info.as_ptr(),
len_as_u32(digest_info.len()),
out.as_mut_ptr(),
len_as_u32(out.len()),
self.key,
&mut rng.rng,
)
};
if rc < 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wc_RsaSSL_Sign",
});
}
out.truncate(rc as usize);
Ok(out)
}
pub fn verify_pkcs1v15_raw(
&self,
signature: &[u8],
) -> Result<alloc::vec::Vec<u8>, WolfCryptError> {
let key_sz = self.key_size()?;
let mut out = alloc::vec![0u8; key_sz];
let rc = unsafe {
wolfcrypt_rs::wc_RsaSSL_Verify(
signature.as_ptr(),
len_as_u32(signature.len()),
out.as_mut_ptr(),
len_as_u32(out.len()),
self.key,
)
};
if rc < 0 {
return Err(WolfCryptError::Ffi {
code: rc,
func: "wc_RsaSSL_Verify",
});
}
out.truncate(rc as usize);
Ok(out)
}
pub fn export_raw_components(&mut self) -> Result<RsaRawComponents, WolfCryptError> {
let sz = self.key_size()?;
let mut e = alloc::vec![0u8; sz];
let mut n = alloc::vec![0u8; sz];
let mut d = alloc::vec![0u8; sz];
let mut p = alloc::vec![0u8; sz];
let mut q = alloc::vec![0u8; sz];
let mut e_sz = len_as_u32(e.len());
let mut n_sz = len_as_u32(n.len());
let mut d_sz = len_as_u32(d.len());
let mut p_sz = len_as_u32(p.len());
let mut q_sz = len_as_u32(q.len());
let rc = unsafe {
wolfcrypt_rs::wc_RsaExportKey(
self.key,
e.as_mut_ptr(),
&mut e_sz,
n.as_mut_ptr(),
&mut n_sz,
d.as_mut_ptr(),
&mut d_sz,
p.as_mut_ptr(),
&mut p_sz,
q.as_mut_ptr(),
&mut q_sz,
)
};
check(rc, "wc_RsaExportKey")?;
e.truncate(e_sz as usize);
n.truncate(n_sz as usize);
d.truncate(d_sz as usize);
p.truncate(p_sz as usize);
q.truncate(q_sz as usize);
let der = self.to_pkcs1_der()?;
let iqmp = extract_iqmp_from_pkcs1_der(&der)?;
Ok(RsaRawComponents {
e,
n,
d,
p,
q,
iqmp,
})
}
pub fn from_raw_public(n: &[u8], e: &[u8]) -> Result<Self, WolfCryptError> {
let der = build_pkcs1_public_key_der(n, e);
Self::from_public_der(&der)
}
}
#[cfg(feature = "rsa-direct")]
pub struct RsaRawComponents {
pub e: alloc::vec::Vec<u8>,
pub n: alloc::vec::Vec<u8>,
pub d: alloc::vec::Vec<u8>,
pub p: alloc::vec::Vec<u8>,
pub q: alloc::vec::Vec<u8>,
pub iqmp: alloc::vec::Vec<u8>,
}
#[cfg(feature = "rsa-direct")]
fn build_pkcs1_public_key_der(n: &[u8], e: &[u8]) -> alloc::vec::Vec<u8> {
let n_der = der_encode_unsigned_integer(n);
let e_der = der_encode_unsigned_integer(e);
let content_len = n_der.len() + e_der.len();
let mut der = alloc::vec::Vec::with_capacity(content_len + 10);
der.push(0x30); der_push_length(content_len, &mut der);
der.extend_from_slice(&n_der);
der.extend_from_slice(&e_der);
der
}
#[cfg(feature = "rsa-direct")]
fn der_encode_unsigned_integer(bytes: &[u8]) -> alloc::vec::Vec<u8> {
if bytes.is_empty() {
return alloc::vec![0x02, 0x01, 0x00];
}
let significant = match bytes.iter().position(|&b| b != 0) {
Some(i) => &bytes[i..],
None => &bytes[bytes.len() - 1..], };
let needs_pad = significant[0] & 0x80 != 0;
let value_len = significant.len() + usize::from(needs_pad);
let mut out = alloc::vec::Vec::with_capacity(value_len + 4);
out.push(0x02); der_push_length(value_len, &mut out);
if needs_pad {
out.push(0x00);
}
out.extend_from_slice(significant);
out
}
#[cfg(feature = "rsa-direct")]
fn der_push_length(len: usize, out: &mut alloc::vec::Vec<u8>) {
if len < 0x80 {
out.push(len as u8);
} else if len < 0x100 {
out.push(0x81);
out.push(len as u8);
} else if len < 0x10000 {
out.push(0x82);
out.push((len >> 8) as u8);
out.push(len as u8);
} else if len < 0x100_0000 {
out.push(0x83);
out.push((len >> 16) as u8);
out.push((len >> 8) as u8);
out.push(len as u8);
} else {
panic!("DER length {len} exceeds maximum supported (0xFFFFFF)");
}
}
#[cfg(feature = "rsa-direct")]
fn extract_iqmp_from_pkcs1_der(der: &[u8]) -> Result<alloc::vec::Vec<u8>, WolfCryptError> {
let err = || WolfCryptError::Ffi {
code: -1,
func: "extract_iqmp_from_pkcs1_der",
};
let mut pos = 0;
if pos >= der.len() || der[pos] != 0x30 {
return Err(err());
}
pos = pos.checked_add(1).ok_or_else(err)?;
let (_seq_len, hdr) = der_read_len(der, pos).ok_or_else(err)?;
pos = pos.checked_add(hdr).ok_or_else(err)?;
for _ in 0..8 {
pos = der_skip_int(der, pos).ok_or_else(err)?;
}
let val = der_read_int(der, pos).ok_or_else(err)?;
Ok(val.to_vec())
}
#[cfg(feature = "rsa-direct")]
fn der_read_len(data: &[u8], pos: usize) -> Option<(usize, usize)> {
let b = *data.get(pos)?;
if b < 0x80 {
Some((b as usize, 1))
} else {
let n = (b & 0x7f) as usize;
if n == 0 || n > 4 {
return None;
}
let end = pos.checked_add(1)?.checked_add(n)?;
if end > data.len() {
return None;
}
let mut len = 0usize;
for i in 0..n {
len = len.checked_shl(8)? | (*data.get(pos + 1 + i)? as usize);
}
Some((len, 1 + n))
}
}
#[cfg(feature = "rsa-direct")]
fn der_read_int(data: &[u8], pos: usize) -> Option<&[u8]> {
if *data.get(pos)? != 0x02 {
return None;
}
let (len, hdr) = der_read_len(data, pos.checked_add(1)?)?;
let start = pos.checked_add(1)?.checked_add(hdr)?;
let end = start.checked_add(len)?;
if end > data.len() {
return None;
}
let mut val = &data[start..end];
while val.len() > 1 && val[0] == 0 {
val = &val[1..];
}
Some(val)
}
#[cfg(feature = "rsa-direct")]
fn der_skip_int(data: &[u8], pos: usize) -> Option<usize> {
if *data.get(pos)? != 0x02 {
return None;
}
let (len, hdr) = der_read_len(data, pos.checked_add(1)?)?;
let end = pos.checked_add(1)?.checked_add(hdr)?.checked_add(len)?;
if end > data.len() {
return None;
}
Some(end)
}
#[cfg(feature = "rsa-direct")]
impl Drop for NativeRsaKey {
fn drop(&mut self) {
if !self.key.is_null() {
unsafe {
wolfcrypt_rs::wc_DeleteRsaKey(self.key, ptr::null_mut());
}
}
}
}