use libc::c_void;
use crate::yaca_common as common;
use crate::yaca_lib as lib;
use crate::yaca_conv as conv;
use crate::crypto::{Context, ContextWithPadding, ContextWithRc2Supported,
ContextWithXcmEncryptProperties, ContextWithXcmDecryptProperties};
use crate::*;
pub struct EncryptContext {
handle: *mut c_void,
}
impl Drop for EncryptContext {
fn drop(&mut self)
{
unsafe {
lib::yaca_context_destroy(self.handle)
}
}
}
impl Context for EncryptContext {
fn get_handle(&self) -> *mut c_void
{
self.handle
}
}
impl ContextWithPadding for EncryptContext {}
impl ContextWithRc2Supported for EncryptContext {}
impl ContextWithXcmEncryptProperties for EncryptContext {
fn set_property_ccm_aad(&self, ccm_aad: &[u8], plaintext_len: usize) -> Result<()>
{
encrypt_set_input_length(self, plaintext_len)?;
crypto::context_set_property_multiple(self, types::Property::CcmAad, ccm_aad)
}
}
impl EncryptContext {
pub fn get_iv_length(algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
key_length: &KeyLength) -> Result<Option<KeyLength>>
{
encrypt_get_iv_length(algo, bcm, key_length)
}
pub fn initialize(algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
sym_key: &Key, iv: Option<&Key>) -> Result<EncryptContext>
{
encrypt_initialize(algo, bcm, sym_key, iv)
}
pub fn update(&self, plaintext: &[u8]) -> Result<Vec<u8>>
{
encrypt_update(self, plaintext)
}
pub fn finalize(&self) -> Result<Vec<u8>>
{
encrypt_finalize(&self)
}
}
#[inline]
fn encrypt_get_iv_length(algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
key_length: &KeyLength) -> Result<Option<KeyLength>>
{
let algo = conv::encrypt_rs_to_c(algo);
let bcm = conv::bcm_rs_to_c(bcm);
let key_bit_len = conv::key_length_rs_to_c(key_length);
let mut iv_bit_len = 0;
let r = unsafe {
lib::yaca_encrypt_get_iv_bit_length(algo, bcm, key_bit_len, &mut iv_bit_len)
};
conv::res_c_to_rs(r)?;
debug_assert!(iv_bit_len <= std::u16::MAX as usize);
match iv_bit_len {
0 => Ok(None),
x => Ok(Some(KeyLength::Bits(x as u16))),
}
}
#[inline]
fn encrypt_initialize(algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
sym_key: &Key, iv: Option<&Key>) -> Result<EncryptContext>
{
let handle = common::enc_init(algo, bcm, sym_key, iv, lib::yaca_encrypt_initialize)?;
Ok(EncryptContext{handle})
}
#[inline]
fn encrypt_set_input_length(ctx: &EncryptContext, input_len: usize) -> Result<()>
{
common::enc_set_input_length(ctx, input_len, lib::yaca_encrypt_update)
}
#[inline]
fn encrypt_update(ctx: &EncryptContext, plaintext: &[u8]) -> Result<Vec<u8>>
{
common::enc_upd(ctx, plaintext, lib::yaca_encrypt_update)
}
#[inline]
fn encrypt_finalize(ctx: &EncryptContext) -> Result<Vec<u8>>
{
common::enc_fin(ctx, lib::yaca_encrypt_finalize)
}
pub struct DecryptContext {
handle: *mut c_void,
}
impl Drop for DecryptContext {
fn drop(&mut self)
{
unsafe {
lib::yaca_context_destroy(self.handle)
}
}
}
impl Context for DecryptContext {
fn get_handle(&self) -> *mut c_void
{
self.handle
}
}
impl ContextWithPadding for DecryptContext {}
impl ContextWithRc2Supported for DecryptContext {}
impl ContextWithXcmDecryptProperties for DecryptContext {
fn set_property_ccm_aad(&self, ccm_aad: &[u8], ciphertext_len: usize) -> Result<()>
{
decrypt_set_input_length(self, ciphertext_len)?;
crypto::context_set_property_multiple(self, types::Property::CcmAad, ccm_aad)
}
}
impl DecryptContext {
pub fn initialize(algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
sym_key: &Key, iv: Option<&Key>) -> Result<DecryptContext>
{
decrypt_initialize(algo, bcm, sym_key, iv)
}
pub fn update(&self, ciphertext: &[u8]) -> Result<Vec<u8>>
{
decrypt_update(self, ciphertext)
}
pub fn finalize(&self) -> Result<Vec<u8>>
{
decrypt_finalize(&self)
}
}
#[inline]
fn decrypt_initialize(algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
sym_key: &Key, iv: Option<&Key>) -> Result<DecryptContext>
{
let handle = common::enc_init(algo, bcm, sym_key, iv, lib::yaca_decrypt_initialize)?;
Ok(DecryptContext{handle})
}
#[inline]
fn decrypt_set_input_length(ctx: &DecryptContext, input_len: usize) -> Result<()>
{
common::enc_set_input_length(ctx, input_len, lib::yaca_decrypt_update)
}
#[inline]
fn decrypt_update(ctx: &DecryptContext, ciphertext: &[u8]) -> Result<Vec<u8>>
{
common::enc_upd(ctx, ciphertext, lib::yaca_decrypt_update)
}
#[inline]
fn decrypt_finalize(ctx: &DecryptContext) -> Result<Vec<u8>>
{
common::enc_fin(ctx, lib::yaca_decrypt_finalize)
}