use std::ptr;
use bindings::{
themis_secure_cell_decrypt_context_imprint, themis_secure_cell_decrypt_seal,
themis_secure_cell_decrypt_seal_with_passphrase, themis_secure_cell_decrypt_token_protect,
themis_secure_cell_encrypt_context_imprint, themis_secure_cell_encrypt_seal,
themis_secure_cell_encrypt_seal_with_passphrase, themis_secure_cell_encrypt_token_protect,
};
use crate::error::{Error, ErrorKind, Result};
use crate::keys::KeyBytes;
use crate::utils::into_raw_parts;
#[derive(Debug)]
pub struct SecureCell {
master_key: KeyBytes,
}
#[derive(Debug)]
pub struct SecureCellWithPassphrase {
passphrase: KeyBytes,
}
impl SecureCell {
pub fn with_key(symmetric_key: impl AsRef<[u8]>) -> Result<SecureCell> {
Ok(SecureCell {
master_key: KeyBytes::copy_slice(symmetric_key.as_ref())?,
})
}
pub fn with_passphrase(passphrase: impl AsRef<[u8]>) -> Result<SecureCellWithPassphrase> {
Ok(SecureCellWithPassphrase {
passphrase: KeyBytes::copy_slice(passphrase.as_ref())?,
})
}
pub fn seal(self) -> SecureCellSeal {
SecureCellSeal(self)
}
pub fn token_protect(self) -> SecureCellTokenProtect {
SecureCellTokenProtect(self)
}
pub fn context_imprint(self) -> SecureCellContextImprint {
SecureCellContextImprint(self)
}
}
impl SecureCellWithPassphrase {
pub fn seal(self) -> SecureCellSealWithPassphrase {
SecureCellSealWithPassphrase(self)
}
}
#[derive(Debug)]
pub struct SecureCellSeal(SecureCell);
impl SecureCellSeal {
pub fn encrypt(&self, message: impl AsRef<[u8]>) -> Result<Vec<u8>> {
self.encrypt_with_context(message, &[])
}
pub fn encrypt_with_context(
&self,
message: impl AsRef<[u8]>,
context: impl AsRef<[u8]>,
) -> Result<Vec<u8>> {
encrypt_seal(
self.0.master_key.as_bytes(),
context.as_ref(),
message.as_ref(),
)
}
pub fn decrypt(&self, message: impl AsRef<[u8]>) -> Result<Vec<u8>> {
self.decrypt_with_context(message, &[])
}
pub fn decrypt_with_context(
&self,
message: impl AsRef<[u8]>,
context: impl AsRef<[u8]>,
) -> Result<Vec<u8>> {
decrypt_seal(
self.0.master_key.as_bytes(),
context.as_ref(),
message.as_ref(),
)
}
}
#[derive(Debug)]
pub struct SecureCellSealWithPassphrase(SecureCellWithPassphrase);
impl SecureCellSealWithPassphrase {
pub fn encrypt(&self, message: impl AsRef<[u8]>) -> Result<Vec<u8>> {
self.encrypt_with_context(message, &[])
}
pub fn encrypt_with_context(
&self,
message: impl AsRef<[u8]>,
context: impl AsRef<[u8]>,
) -> Result<Vec<u8>> {
encrypt_seal_with_passphrase(
self.0.passphrase.as_bytes(),
context.as_ref(),
message.as_ref(),
)
}
pub fn decrypt(&self, message: impl AsRef<[u8]>) -> Result<Vec<u8>> {
self.decrypt_with_context(message, &[])
}
pub fn decrypt_with_context(
&self,
message: impl AsRef<[u8]>,
context: impl AsRef<[u8]>,
) -> Result<Vec<u8>> {
decrypt_seal_with_passphrase(
self.0.passphrase.as_bytes(),
context.as_ref(),
message.as_ref(),
)
}
}
fn encrypt_seal(master_key: &[u8], user_context: &[u8], message: &[u8]) -> Result<Vec<u8>> {
let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (user_context_ptr, user_context_len) = into_raw_parts(user_context);
let (message_ptr, message_len) = into_raw_parts(message);
let mut encrypted_message = Vec::new();
let mut encrypted_message_len = 0;
unsafe {
let status = themis_secure_cell_encrypt_seal(
master_key_ptr,
master_key_len,
user_context_ptr,
user_context_len,
message_ptr,
message_len,
ptr::null_mut(),
&mut encrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
encrypted_message.reserve(encrypted_message_len as usize);
unsafe {
let status = themis_secure_cell_encrypt_seal(
master_key_ptr,
master_key_len,
user_context_ptr,
user_context_len,
message_ptr,
message_len,
encrypted_message.as_mut_ptr(),
&mut encrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(encrypted_message_len <= encrypted_message.capacity());
encrypted_message.set_len(encrypted_message_len as usize);
}
Ok(encrypted_message)
}
fn decrypt_seal(master_key: &[u8], user_context: &[u8], message: &[u8]) -> Result<Vec<u8>> {
let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (user_context_ptr, user_context_len) = into_raw_parts(user_context);
let (message_ptr, message_len) = into_raw_parts(message);
let mut decrypted_message = Vec::new();
let mut decrypted_message_len = 0;
unsafe {
let status = themis_secure_cell_decrypt_seal(
master_key_ptr,
master_key_len,
user_context_ptr,
user_context_len,
message_ptr,
message_len,
ptr::null_mut(),
&mut decrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
decrypted_message.reserve(decrypted_message_len as usize);
unsafe {
let status = themis_secure_cell_decrypt_seal(
master_key_ptr,
master_key_len,
user_context_ptr,
user_context_len,
message_ptr,
message_len,
decrypted_message.as_mut_ptr(),
&mut decrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(decrypted_message_len <= decrypted_message.capacity());
decrypted_message.set_len(decrypted_message_len as usize);
}
Ok(decrypted_message)
}
fn encrypt_seal_with_passphrase(
passphrase: &[u8],
context: &[u8],
message: &[u8],
) -> Result<Vec<u8>> {
let (passphrase_ptr, passphrase_len) = into_raw_parts(passphrase);
let (context_ptr, context_len) = into_raw_parts(context);
let (message_ptr, message_len) = into_raw_parts(message);
let mut encrypted_message = Vec::new();
let mut encrypted_message_len = 0;
unsafe {
let status = themis_secure_cell_encrypt_seal_with_passphrase(
passphrase_ptr,
passphrase_len,
context_ptr,
context_len,
message_ptr,
message_len,
ptr::null_mut(),
&mut encrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
encrypted_message.reserve(encrypted_message_len as usize);
unsafe {
let status = themis_secure_cell_encrypt_seal_with_passphrase(
passphrase_ptr,
passphrase_len,
context_ptr,
context_len,
message_ptr,
message_len,
encrypted_message.as_mut_ptr(),
&mut encrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(encrypted_message_len <= encrypted_message.capacity());
encrypted_message.set_len(encrypted_message_len as usize);
}
Ok(encrypted_message)
}
fn decrypt_seal_with_passphrase(
passphrase: &[u8],
context: &[u8],
message: &[u8],
) -> Result<Vec<u8>> {
let (passphrase_ptr, passphrase_len) = into_raw_parts(passphrase);
let (context_ptr, context_len) = into_raw_parts(context);
let (message_ptr, message_len) = into_raw_parts(message);
let mut decrypted_message = Vec::new();
let mut decrypted_message_len = 0;
unsafe {
let status = themis_secure_cell_decrypt_seal_with_passphrase(
passphrase_ptr,
passphrase_len,
context_ptr,
context_len,
message_ptr,
message_len,
ptr::null_mut(),
&mut decrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
decrypted_message.reserve(decrypted_message_len as usize);
unsafe {
let status = themis_secure_cell_decrypt_seal_with_passphrase(
passphrase_ptr,
passphrase_len,
context_ptr,
context_len,
message_ptr,
message_len,
decrypted_message.as_mut_ptr(),
&mut decrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(decrypted_message_len <= decrypted_message.capacity());
decrypted_message.set_len(decrypted_message_len as usize);
}
Ok(decrypted_message)
}
#[derive(Debug)]
pub struct SecureCellTokenProtect(SecureCell);
impl SecureCellTokenProtect {
pub fn encrypt(&self, message: impl AsRef<[u8]>) -> Result<(Vec<u8>, Vec<u8>)> {
self.encrypt_with_context(message, &[])
}
pub fn encrypt_with_context(
&self,
message: impl AsRef<[u8]>,
context: impl AsRef<[u8]>,
) -> Result<(Vec<u8>, Vec<u8>)> {
encrypt_token_protect(
self.0.master_key.as_bytes(),
context.as_ref(),
message.as_ref(),
)
}
pub fn decrypt(&self, message: impl AsRef<[u8]>, token: impl AsRef<[u8]>) -> Result<Vec<u8>> {
self.decrypt_with_context(message, token, &[])
}
pub fn decrypt_with_context(
&self,
message: impl AsRef<[u8]>,
token: impl AsRef<[u8]>,
context: impl AsRef<[u8]>,
) -> Result<Vec<u8>> {
decrypt_token_protect(
self.0.master_key.as_bytes(),
context.as_ref(),
message.as_ref(),
token.as_ref(),
)
}
}
fn encrypt_token_protect(
master_key: &[u8],
user_context: &[u8],
message: &[u8],
) -> Result<(Vec<u8>, Vec<u8>)> {
let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (user_context_ptr, user_context_len) = into_raw_parts(user_context);
let (message_ptr, message_len) = into_raw_parts(message);
let mut token = Vec::new();
let mut token_len = 0;
let mut encrypted_message = Vec::new();
let mut encrypted_message_len = 0;
unsafe {
let status = themis_secure_cell_encrypt_token_protect(
master_key_ptr,
master_key_len,
user_context_ptr,
user_context_len,
message_ptr,
message_len,
ptr::null_mut(),
&mut token_len,
ptr::null_mut(),
&mut encrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
token.reserve(token_len as usize);
encrypted_message.reserve(encrypted_message_len as usize);
unsafe {
let status = themis_secure_cell_encrypt_token_protect(
master_key_ptr,
master_key_len,
user_context_ptr,
user_context_len,
message_ptr,
message_len,
token.as_mut_ptr(),
&mut token_len,
encrypted_message.as_mut_ptr(),
&mut encrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(token_len <= token.capacity());
token.set_len(token_len as usize);
debug_assert!(encrypted_message_len <= encrypted_message.capacity());
encrypted_message.set_len(encrypted_message_len as usize);
}
Ok((encrypted_message, token))
}
fn decrypt_token_protect(
master_key: &[u8],
user_context: &[u8],
message: &[u8],
token: &[u8],
) -> Result<Vec<u8>> {
let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (user_context_ptr, user_context_len) = into_raw_parts(user_context);
let (message_ptr, message_len) = into_raw_parts(message);
let (token_ptr, token_len) = into_raw_parts(token);
let mut decrypted_message = Vec::new();
let mut decrypted_message_len = 0;
unsafe {
let status = themis_secure_cell_decrypt_token_protect(
master_key_ptr,
master_key_len,
user_context_ptr,
user_context_len,
message_ptr,
message_len,
token_ptr,
token_len,
ptr::null_mut(),
&mut decrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
decrypted_message.reserve(decrypted_message_len as usize);
unsafe {
let status = themis_secure_cell_decrypt_token_protect(
master_key_ptr,
master_key_len,
user_context_ptr,
user_context_len,
message_ptr,
message_len,
token_ptr,
token_len,
decrypted_message.as_mut_ptr(),
&mut decrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(decrypted_message_len <= decrypted_message.capacity());
decrypted_message.set_len(decrypted_message_len as usize);
}
Ok(decrypted_message)
}
#[derive(Debug)]
pub struct SecureCellContextImprint(SecureCell);
impl SecureCellContextImprint {
pub fn encrypt_with_context(
&self,
message: impl AsRef<[u8]>,
context: impl AsRef<[u8]>,
) -> Result<Vec<u8>> {
encrypt_context_imprint(
self.0.master_key.as_bytes(),
message.as_ref(),
context.as_ref(),
)
}
pub fn decrypt_with_context(
&self,
message: impl AsRef<[u8]>,
context: impl AsRef<[u8]>,
) -> Result<Vec<u8>> {
decrypt_context_imprint(
self.0.master_key.as_bytes(),
message.as_ref(),
context.as_ref(),
)
}
}
fn encrypt_context_imprint(master_key: &[u8], message: &[u8], context: &[u8]) -> Result<Vec<u8>> {
let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (message_ptr, message_len) = into_raw_parts(message);
let (context_ptr, context_len) = into_raw_parts(context);
let mut encrypted_message = Vec::new();
let mut encrypted_message_len = 0;
unsafe {
let status = themis_secure_cell_encrypt_context_imprint(
master_key_ptr,
master_key_len,
message_ptr,
message_len,
context_ptr,
context_len,
ptr::null_mut(),
&mut encrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
encrypted_message.reserve(encrypted_message_len as usize);
unsafe {
let status = themis_secure_cell_encrypt_context_imprint(
master_key_ptr,
master_key_len,
message_ptr,
message_len,
context_ptr,
context_len,
encrypted_message.as_mut_ptr(),
&mut encrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(encrypted_message_len <= encrypted_message.capacity());
encrypted_message.set_len(encrypted_message_len as usize);
}
Ok(encrypted_message)
}
fn decrypt_context_imprint(master_key: &[u8], message: &[u8], context: &[u8]) -> Result<Vec<u8>> {
let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (message_ptr, message_len) = into_raw_parts(message);
let (context_ptr, context_len) = into_raw_parts(context);
let mut decrypted_message = Vec::new();
let mut decrypted_message_len = 0;
unsafe {
let status = themis_secure_cell_decrypt_context_imprint(
master_key_ptr,
master_key_len,
message_ptr,
message_len,
context_ptr,
context_len,
ptr::null_mut(),
&mut decrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
decrypted_message.reserve(decrypted_message_len as usize);
unsafe {
let status = themis_secure_cell_decrypt_context_imprint(
master_key_ptr,
master_key_len,
message_ptr,
message_len,
context_ptr,
context_len,
decrypted_message.as_mut_ptr(),
&mut decrypted_message_len,
);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(decrypted_message_len <= decrypted_message.capacity());
decrypted_message.set_len(decrypted_message_len as usize);
}
Ok(decrypted_message)
}