use std::ffi::c_void;
use std::mem::forget;
use std::os::raw::c_ulong;
use std::ptr::null_mut;
use crate::bindgen::{self};
use crate::error::convert_seal_error;
use crate::error::Result;
use crate::serialization::CompressionType;
use crate::{try_seal, FromBytes, Modulus, ToBytes};
use serde::{Deserialize, Serialize};
mod bfv;
pub use bfv::BFVEncryptionParametersBuilder;
mod ckks;
pub use ckks::CKKSEncryptionParametersBuilder;
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SchemeType {
None = 0x0,
Bfv = 0x1,
Ckks = 0x2,
}
impl SchemeType {
pub fn from_u8(val: u8) -> Self {
match val {
0x0 => SchemeType::None,
0x1 => SchemeType::Bfv,
0x2 => SchemeType::Ckks,
_ => panic!("Illegal scheme type"),
}
}
pub fn to_u8(&self) -> u8 {
*self as u8
}
}
#[derive(Debug)]
pub struct EncryptionParameters {
pub(crate) handle: *mut c_void,
}
unsafe impl Sync for EncryptionParameters {}
unsafe impl Send for EncryptionParameters {}
impl EncryptionParameters {
pub fn new(scheme: SchemeType) -> Result<Self> {
let mut handle: *mut c_void = null_mut();
convert_seal_error(unsafe { bindgen::EncParams_Create1(scheme as u8, &mut handle) })?;
Ok(Self {
handle,
})
}
pub const fn block_size() -> u8 {
4
}
pub fn get_handle(&self) -> *mut c_void {
self.handle
}
pub fn get_poly_modulus_degree(&self) -> u64 {
let mut degree: u64 = 0;
unsafe {
convert_seal_error(bindgen::EncParams_GetPolyModulusDegree(
self.handle,
&mut degree,
))
.expect("Internal error");
};
degree
}
pub fn get_scheme(&self) -> SchemeType {
let mut scheme: u8 = 0;
unsafe {
convert_seal_error(bindgen::EncParams_GetScheme(self.handle, &mut scheme))
.expect("Internal error");
};
SchemeType::from_u8(scheme)
}
pub fn get_plain_modulus(&self) -> Modulus {
let mut borrowed_modulus = null_mut();
unsafe {
convert_seal_error(bindgen::EncParams_GetPlainModulus(
self.handle,
&mut borrowed_modulus,
))
.expect("Internal error")
};
let borrowed_modulus = unsafe { Modulus::new_unchecked_from_handle(borrowed_modulus) };
let ret = borrowed_modulus.clone();
forget(borrowed_modulus);
ret
}
pub fn get_coefficient_modulus(&self) -> Vec<Modulus> {
let mut len: u64 = 0;
unsafe {
convert_seal_error(bindgen::EncParams_GetCoeffModulus(
self.handle,
&mut len,
null_mut(),
))
.expect("Internal error")
};
let mut borrowed_modulus = Vec::with_capacity(len as usize);
let borrowed_modulus_ptr = borrowed_modulus.as_mut_ptr();
unsafe {
convert_seal_error(bindgen::EncParams_GetCoeffModulus(
self.handle,
&mut len,
borrowed_modulus_ptr,
))
.expect("Internal error");
borrowed_modulus.set_len(len as usize);
};
borrowed_modulus
.iter()
.map(|h| {
let modulus = unsafe { Modulus::new_unchecked_from_handle(*h) };
let ret = modulus.clone();
forget(modulus);
ret
})
.collect()
}
pub fn get_parms_id(&self) -> u64 {
let mut parms_id: c_ulong = 0;
unsafe {
convert_seal_error(bindgen::EncParams_GetParmsId(self.handle, &mut parms_id))
.expect("Internal error");
}
parms_id
}
pub fn set_coefficient_modulus(
&mut self,
modulus: Vec<Modulus>,
) -> Result<()> {
unsafe {
let modulus_ref = modulus
.iter()
.map(|m| m.get_handle())
.collect::<Vec<*mut c_void>>();
let modulus_ptr = modulus_ref.as_ptr() as *mut *mut c_void;
try_seal!(bindgen::EncParams_SetCoeffModulus(
self.handle,
modulus.len() as u64,
modulus_ptr
))
}
}
pub fn set_poly_modulus_degree(
&mut self,
degree: u64,
) -> Result<()> {
convert_seal_error(unsafe { bindgen::EncParams_SetPolyModulusDegree(self.handle, degree) })
}
pub fn set_plain_modulus(
&mut self,
modulus: Modulus,
) -> Result<()> {
convert_seal_error(unsafe {
bindgen::EncParams_SetPlainModulus1(self.handle, modulus.get_handle())
})
}
pub fn set_plain_modulus_u64(
&mut self,
modulus: u64,
) -> Result<()> {
convert_seal_error(unsafe { bindgen::EncParams_SetPlainModulus2(self.handle, modulus) })
}
}
#[derive(Debug, PartialEq)]
pub enum CoefficientModulusType {
NotSet,
Modulus(Vec<Modulus>),
}
#[derive(Debug, PartialEq)]
pub enum PlainModulusType {
NotSet,
Constant(u64),
Modulus(Modulus),
}
impl Drop for EncryptionParameters {
fn drop(&mut self) {
convert_seal_error(unsafe { bindgen::EncParams_Destroy(self.handle) })
.expect("Internal error in EncryptionParameters::drop().");
}
}
impl ToBytes for EncryptionParameters {
fn as_bytes(&self) -> Result<Vec<u8>> {
let mut num_bytes: i64 = 0;
convert_seal_error(unsafe {
bindgen::EncParams_SaveSize(self.handle, CompressionType::ZStd as u8, &mut num_bytes)
})?;
let mut data: Vec<u8> = Vec::with_capacity(num_bytes as usize);
let mut bytes_written: i64 = 0;
convert_seal_error(unsafe {
let data_ptr = data.as_mut_ptr();
bindgen::EncParams_Save(
self.handle,
data_ptr,
num_bytes as u64,
CompressionType::ZStd as u8,
&mut bytes_written,
)
})?;
unsafe { data.set_len(bytes_written as usize) };
Ok(data)
}
}
impl FromBytes for EncryptionParameters {
type State = SchemeType;
fn from_bytes(
scheme: &SchemeType,
bytes: &[u8],
) -> Result<Self> {
let key = Self::new(*scheme)?;
let mut bytes_read = 0;
convert_seal_error(unsafe {
bindgen::EncParams_Load(
key.handle,
bytes.as_ptr() as *mut u8,
bytes.len() as u64,
&mut bytes_read,
)
})?;
Ok(key)
}
}