use libc::{c_void, c_char};
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};
use crate::*;
pub struct SignContext {
handle: *mut c_void,
}
impl Drop for SignContext {
fn drop(&mut self)
{
unsafe {
lib::yaca_context_destroy(self.handle)
}
}
}
impl Context for SignContext {
fn get_handle(&self) -> *mut c_void
{
self.handle
}
}
impl ContextWithPadding for SignContext {}
impl SignContext {
pub fn initialize(algo: &DigestAlgorithm, prv_key: &Key) -> Result<SignContext>
{
sign_initialize(algo, prv_key)
}
pub fn initialize_hmac(algo: &DigestAlgorithm, sym_key: &Key) -> Result<SignContext>
{
sign_initialize_hmac(algo, sym_key)
}
pub fn initialize_cmac(algo: &EncryptAlgorithm, sym_key: &Key) -> Result<SignContext>
{
sign_initialize_cmac(algo, sym_key)
}
pub fn update(&self, message: &[u8]) -> Result<()>
{
sign_update(self, message)
}
pub fn finalize(&self) -> Result<Vec<u8>>
{
sign_finalize(self)
}
}
#[inline]
fn sign_initialize(algo: &DigestAlgorithm, prv_key: &Key) -> Result<SignContext>
{
let handle = common::sign_init(algo, prv_key, lib::yaca_sign_initialize)?;
Ok(SignContext{handle})
}
#[inline]
fn sign_initialize_hmac(algo: &DigestAlgorithm, sym_key: &Key) -> Result<SignContext>
{
let handle = common::sign_init(algo, sym_key, lib::yaca_sign_initialize_hmac)?;
Ok(SignContext{handle})
}
#[inline]
fn sign_initialize_cmac(algo: &EncryptAlgorithm, sym_key: &Key) -> Result<SignContext>
{
let algo = conv::encrypt_rs_to_c(algo);
let sym_key = key::get_handle(sym_key);
let mut handle = ptr::null_mut();
let r = unsafe {
lib::yaca_sign_initialize_cmac(&mut handle, algo, sym_key)
};
conv::res_c_to_rs(r)?;
debug_assert!(!handle.is_null());
Ok(SignContext{handle})
}
#[inline]
fn sign_update(ctx: &SignContext, message: &[u8]) -> Result<()>
{
common::hash_upd(ctx, message, lib::yaca_sign_update)
}
#[inline]
fn sign_finalize(ctx: &SignContext) -> Result<Vec<u8>>
{
common::hash_fin(ctx, lib::yaca_sign_finalize)
}
pub struct VerifyContext {
handle: *mut c_void,
}
impl Drop for VerifyContext {
fn drop(&mut self)
{
unsafe {
lib::yaca_context_destroy(self.handle)
}
}
}
impl Context for VerifyContext {
fn get_handle(&self) -> *mut c_void
{
self.handle
}
}
impl ContextWithPadding for VerifyContext {}
impl VerifyContext {
pub fn initialize(algo: &DigestAlgorithm, pub_key: &Key) -> Result<VerifyContext>
{
verify_initialize(algo, pub_key)
}
pub fn update(&self, message: &[u8]) -> Result<()>
{
verify_update(self, message)
}
pub fn finalize(&self, signature: &[u8]) -> Result<bool>
{
verify_finalize(self, signature)
}
}
#[inline]
fn verify_initialize(algo: &DigestAlgorithm, pub_key: &Key) -> Result<VerifyContext>
{
let handle = common::sign_init(algo, pub_key, lib::yaca_verify_initialize)?;
Ok(VerifyContext{handle})
}
#[inline]
fn verify_update(ctx: &VerifyContext, message: &[u8]) -> Result<()>
{
common::hash_upd(ctx, message, lib::yaca_verify_update)
}
#[inline]
fn verify_finalize(ctx: &VerifyContext, signature: &[u8]) -> Result<bool>
{
let signature_len = signature.len();
let signature = signature.as_ptr() as *const c_char;
let r = unsafe {
lib::yaca_verify_finalize(ctx.handle, signature, signature_len)
};
conv::res_c_to_rs_bool(r)
}