use libc::c_void;
use std::ptr;
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 SealContext {
handle: *mut c_void,
}
impl Drop for SealContext {
fn drop(&mut self)
{
unsafe {
lib::yaca_context_destroy(self.handle)
}
}
}
impl Context for SealContext {
fn get_handle(&self) -> *mut c_void
{
self.handle
}
}
impl ContextWithPadding for SealContext {}
impl ContextWithRc2Supported for SealContext {}
impl ContextWithXcmEncryptProperties for SealContext {
fn set_property_ccm_aad(&self, ccm_aad: &[u8], plaintext_len: usize) -> Result<()>
{
seal_set_input_length(self, plaintext_len)?;
crypto::context_set_property_multiple(self, types::Property::CcmAad, ccm_aad)
}
}
impl SealContext {
pub fn initialize(pub_key: &Key, algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
sym_key_length: &KeyLength) -> Result<(SealContext, Key, Option<Key>)>
{
seal_initialize(pub_key, algo, bcm, sym_key_length)
}
pub fn update(&self, plaintext: &[u8]) -> Result<Vec<u8>>
{
seal_update(self, plaintext)
}
pub fn finalize(&self) -> Result<Vec<u8>>
{
seal_finalize(&self)
}
}
#[inline]
fn seal_initialize(pub_key: &Key, algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
sym_key_length: &KeyLength) -> Result<(SealContext, Key, Option<Key>)>
{
let pub_key = key::get_handle(&pub_key);
let algo = conv::encrypt_rs_to_c(algo);
let bcm = conv::bcm_rs_to_c(bcm);
let sym_key_bit_length = conv::key_length_rs_to_c(sym_key_length);
let mut sym_key = ptr::null();
let mut iv = ptr::null();
let mut handle = ptr::null_mut();
let r = unsafe {
lib::yaca_seal_initialize(&mut handle, pub_key, algo, bcm, sym_key_bit_length,
&mut sym_key, &mut iv)
};
conv::res_c_to_rs(r)?;
debug_assert!(!sym_key.is_null());
debug_assert!(!handle.is_null());
let iv = if !iv.is_null() {
Some(key::new_key(iv))
} else {
None
};
let sym_key = key::new_key(sym_key);
let ctx = SealContext{handle};
Ok((ctx, sym_key, iv))
}
#[inline]
fn seal_set_input_length(ctx: &SealContext, input_len: usize) -> Result<()>
{
common::enc_set_input_length(ctx, input_len, lib::yaca_seal_update)
}
#[inline]
fn seal_update(ctx: &SealContext, plaintext: &[u8]) -> Result<Vec<u8>>
{
common::enc_upd(ctx, plaintext, lib::yaca_seal_update)
}
#[inline]
fn seal_finalize(ctx: &SealContext) -> Result<Vec<u8>>
{
common::enc_fin(ctx, lib::yaca_seal_finalize)
}
pub struct OpenContext {
handle: *mut c_void,
}
impl Drop for OpenContext {
fn drop(&mut self)
{
unsafe {
lib::yaca_context_destroy(self.handle)
}
}
}
impl Context for OpenContext {
fn get_handle(&self) -> *mut c_void
{
self.handle
}
}
impl ContextWithPadding for OpenContext {}
impl ContextWithRc2Supported for OpenContext {}
impl ContextWithXcmDecryptProperties for OpenContext {
fn set_property_ccm_aad(&self, ccm_aad: &[u8], ciphertext_len: usize) -> Result<()>
{
open_set_input_length(self, ciphertext_len)?;
crypto::context_set_property_multiple(self, types::Property::CcmAad, ccm_aad)
}
}
impl OpenContext {
pub fn initialize(prv_key: &Key, algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
sym_key_length: &KeyLength, sym_key: &Key,
iv: Option<&Key>) -> Result<OpenContext>
{
open_initialize(prv_key, algo, bcm, sym_key_length, sym_key, iv)
}
pub fn update(&self, ciphertext: &[u8]) -> Result<Vec<u8>>
{
open_update(self, ciphertext)
}
pub fn finalize(&self) -> Result<Vec<u8>>
{
open_finalize(&self)
}
}
#[inline]
fn open_initialize(prv_key: &Key, algo: &EncryptAlgorithm, bcm: &BlockCipherMode,
sym_key_length: &KeyLength, sym_key: &Key,
iv: Option<&Key>) -> Result<OpenContext>
{
let prv_key = key::get_handle(&prv_key);
let algo = conv::encrypt_rs_to_c(algo);
let bcm = conv::bcm_rs_to_c(bcm);
let sym_key_bit_len = conv::key_length_rs_to_c(&sym_key_length);
let sym_key = key::get_handle(sym_key);
let iv = match iv {
Some(i) => key::get_handle(&i),
None => ptr::null(),
};
let mut handle = ptr::null_mut();
let r = unsafe {
lib::yaca_open_initialize(&mut handle, prv_key, algo, bcm,
sym_key_bit_len, sym_key, iv)
};
conv::res_c_to_rs(r)?;
debug_assert!(!handle.is_null());
Ok(OpenContext{handle})
}
#[inline]
fn open_set_input_length(ctx: &OpenContext, input_len: usize) -> Result<()>
{
common::enc_set_input_length(ctx, input_len, lib::yaca_open_update)
}
#[inline]
fn open_update(ctx: &OpenContext, ciphertext: &[u8]) -> Result<Vec<u8>>
{
common::enc_upd(ctx, ciphertext, lib::yaca_open_update)
}
#[inline]
fn open_finalize(ctx: &OpenContext) -> Result<Vec<u8>>
{
common::enc_fin(ctx, lib::yaca_open_finalize)
}