#![allow(clippy::module_name_repetitions)]
use super::{PrivateDecryptingKey, PublicEncryptingKey};
use crate::error::Unspecified;
use crate::fips::indicator_check;
use crate::ptr::LcPtr;
use crate::wolfcrypt_rs::{
EVP_PKEY_CTX_set_rsa_padding, EVP_PKEY_decrypt, EVP_PKEY_decrypt_init, EVP_PKEY_encrypt,
EVP_PKEY_encrypt_init, EVP_PKEY_CTX, RSA_PKCS1_PADDING,
};
use core::fmt::Debug;
pub struct Pkcs1PublicEncryptingKey {
public_key: PublicEncryptingKey,
}
impl Pkcs1PublicEncryptingKey {
pub fn new(public_key: PublicEncryptingKey) -> Result<Self, Unspecified> {
Ok(Self { public_key })
}
pub fn encrypt<'ciphertext>(
&self,
plaintext: &[u8],
ciphertext: &'ciphertext mut [u8],
) -> Result<&'ciphertext mut [u8], Unspecified> {
let mut pkey_ctx = self.public_key.0.create_EVP_PKEY_CTX()?;
if 1 != unsafe { EVP_PKEY_encrypt_init(pkey_ctx.as_mut_ptr()) } {
return Err(Unspecified);
}
configure_pkcs1_crypto_operation(&mut pkey_ctx)?;
let mut out_len = ciphertext.len();
if 1 != indicator_check!(unsafe {
EVP_PKEY_encrypt(
pkey_ctx.as_mut_ptr(),
ciphertext.as_mut_ptr(),
&mut out_len,
plaintext.as_ptr(),
plaintext.len(),
)
}) {
return Err(Unspecified);
}
Ok(&mut ciphertext[..out_len])
}
#[must_use]
pub fn key_size_bytes(&self) -> usize {
self.public_key.key_size_bytes()
}
#[must_use]
pub fn key_size_bits(&self) -> usize {
self.public_key.key_size_bits()
}
#[must_use]
pub fn max_plaintext_size(&self) -> usize {
const RSA_PKCS1_PADDING_SIZE: usize = 11; self.key_size_bytes() - RSA_PKCS1_PADDING_SIZE
}
#[must_use]
pub fn ciphertext_size(&self) -> usize {
self.key_size_bytes()
}
}
impl Debug for Pkcs1PublicEncryptingKey {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Pkcs1PublicEncryptingKey")
.finish_non_exhaustive()
}
}
pub struct Pkcs1PrivateDecryptingKey {
private_key: PrivateDecryptingKey,
}
impl Pkcs1PrivateDecryptingKey {
pub fn new(private_key: PrivateDecryptingKey) -> Result<Self, Unspecified> {
Ok(Self { private_key })
}
pub fn decrypt<'plaintext>(
&self,
ciphertext: &[u8],
plaintext: &'plaintext mut [u8],
) -> Result<&'plaintext mut [u8], Unspecified> {
let mut pkey_ctx = self.private_key.0.create_EVP_PKEY_CTX()?;
if 1 != unsafe { EVP_PKEY_decrypt_init(pkey_ctx.as_mut_ptr()) } {
return Err(Unspecified);
}
configure_pkcs1_crypto_operation(&mut pkey_ctx)?;
let mut out_len = plaintext.len();
if 1 != indicator_check!(unsafe {
EVP_PKEY_decrypt(
pkey_ctx.as_mut_ptr(),
plaintext.as_mut_ptr(),
&mut out_len,
ciphertext.as_ptr(),
ciphertext.len(),
)
}) {
return Err(Unspecified);
}
Ok(&mut plaintext[..out_len])
}
#[must_use]
pub fn key_size_bytes(&self) -> usize {
self.private_key.key_size_bytes()
}
#[must_use]
pub fn key_size_bits(&self) -> usize {
self.private_key.key_size_bits()
}
#[must_use]
pub fn min_output_size(&self) -> usize {
self.key_size_bytes()
}
}
impl Debug for Pkcs1PrivateDecryptingKey {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Pkcs1PrivateDecryptingKey")
.finish_non_exhaustive()
}
}
fn configure_pkcs1_crypto_operation(
evp_pkey_ctx: &mut LcPtr<EVP_PKEY_CTX>,
) -> Result<(), Unspecified> {
if 1 != unsafe { EVP_PKEY_CTX_set_rsa_padding(evp_pkey_ctx.as_mut_ptr(), RSA_PKCS1_PADDING) } {
return Err(Unspecified);
}
Ok(())
}