use crate::initialized;
use crate::types::algorithm::Cipher;
use crate::types::key::Id;
use crate::types::status::{Result, Status};
fn crypt(
encrypt: bool,
key_id: Id,
alg: Cipher,
plaintext: &[u8],
iv: &[u8],
ciphertext: &mut [u8],
) -> Result<usize> {
initialized()?;
let mut operation: psa_crypto_sys::psa_cipher_operation_t =
unsafe { psa_crypto_sys::psa_cipher_operation_init() };
Status::from(unsafe {
(if encrypt {
psa_crypto_sys::psa_cipher_encrypt_setup
} else {
psa_crypto_sys::psa_cipher_decrypt_setup
})(&mut operation, key_id.0, alg.into())
})
.to_result()?;
let mut output_length = 0;
let mut output_length_finish = 0;
match (|| {
Status::from(unsafe {
psa_crypto_sys::psa_cipher_set_iv(&mut operation, iv.as_ptr(), iv.len())
})
.to_result()?;
Status::from(unsafe {
psa_crypto_sys::psa_cipher_update(
&mut operation,
plaintext.as_ptr(),
plaintext.len(),
ciphertext.as_mut_ptr(),
ciphertext.len(),
&mut output_length,
)
})
.to_result()?;
Status::from(unsafe {
psa_crypto_sys::psa_cipher_finish(
&mut operation,
ciphertext.as_mut_ptr().add(output_length),
ciphertext.len() - output_length,
&mut output_length_finish,
)
})
.to_result()?;
Ok(())
})() {
Ok(()) => (),
Err(x) => {
Status::from(unsafe { psa_crypto_sys::psa_cipher_abort(&mut operation) })
.to_result()?;
return Err(x);
}
}
Ok(output_length + output_length_finish)
}
pub fn encrypt(
key_id: Id,
alg: Cipher,
plaintext: &[u8],
iv: &[u8],
ciphertext: &mut [u8],
) -> Result<usize> {
crypt(true, key_id, alg, plaintext, iv, ciphertext)
}
pub fn decrypt(
key_id: Id,
alg: Cipher,
ciphertext: &[u8],
iv: &[u8],
plaintext: &mut [u8],
) -> Result<usize> {
crypt(false, key_id, alg, ciphertext, iv, plaintext)
}