use std::fmt;
use std::ptr;
use bindings::{themis_gen_sym_key, themis_get_asym_key_kind, themis_is_valid_asym_key};
use zeroize::Zeroize;
use crate::error::{Error, ErrorKind, Result};
use crate::utils::into_raw_parts;
#[derive(Clone, Eq, PartialEq, Hash)]
pub(crate) struct KeyBytes(Vec<u8>);
impl KeyBytes {
pub fn from_vec(bytes: Vec<u8>) -> Result<KeyBytes> {
if bytes.is_empty() {
Err(Error::with_kind(ErrorKind::InvalidParameter))
} else {
Ok(KeyBytes(bytes))
}
}
pub fn copy_slice(bytes: &[u8]) -> Result<KeyBytes> {
KeyBytes::from_vec(bytes.to_vec())
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
}
impl fmt::Debug for KeyBytes {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "KeyBytes({} bytes)", self.0.len())
}
}
impl Drop for KeyBytes {
fn drop(&mut self) {
self.0.zeroize();
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct RsaPrivateKey {
inner: KeyBytes,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct RsaPublicKey {
inner: KeyBytes,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct RsaKeyPair {
private_key: KeyBytes,
public_key: KeyBytes,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct EcdsaPrivateKey {
inner: KeyBytes,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct EcdsaPublicKey {
inner: KeyBytes,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct EcdsaKeyPair {
private_key: KeyBytes,
public_key: KeyBytes,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct PrivateKey {
inner: KeyBytes,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct PublicKey {
inner: KeyBytes,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct KeyPair {
private_key: KeyBytes,
public_key: KeyBytes,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum KeyKind {
RsaPrivate,
RsaPublic,
EcdsaPrivate,
EcdsaPublic,
}
impl RsaKeyPair {
pub fn split(self) -> (RsaPrivateKey, RsaPublicKey) {
(
RsaPrivateKey {
inner: self.private_key,
},
RsaPublicKey {
inner: self.public_key,
},
)
}
pub fn join(private_key: RsaPrivateKey, public_key: RsaPublicKey) -> RsaKeyPair {
RsaKeyPair {
private_key: private_key.inner,
public_key: public_key.inner,
}
}
}
impl EcdsaKeyPair {
pub fn split(self) -> (EcdsaPrivateKey, EcdsaPublicKey) {
(
EcdsaPrivateKey {
inner: self.private_key,
},
EcdsaPublicKey {
inner: self.public_key,
},
)
}
pub fn join(private_key: EcdsaPrivateKey, public_key: EcdsaPublicKey) -> EcdsaKeyPair {
EcdsaKeyPair {
private_key: private_key.inner,
public_key: public_key.inner,
}
}
}
impl KeyPair {
pub(crate) fn private_key_bytes(&self) -> &[u8] {
self.private_key.as_bytes()
}
pub(crate) fn public_key_bytes(&self) -> &[u8] {
self.public_key.as_bytes()
}
pub fn split(self) -> (PrivateKey, PublicKey) {
(
PrivateKey {
inner: self.private_key,
},
PublicKey {
inner: self.public_key,
},
)
}
pub fn try_join(
private_key: impl Into<PrivateKey>,
public_key: impl Into<PublicKey>,
) -> Result<KeyPair> {
let (private_key, public_key) = (private_key.into(), public_key.into());
match (private_key.kind(), public_key.kind()) {
(KeyKind::RsaPrivate, KeyKind::RsaPublic) => {}
(KeyKind::EcdsaPrivate, KeyKind::EcdsaPublic) => {}
_ => {
return Err(Error::with_kind(ErrorKind::InvalidParameter));
}
}
Ok(KeyPair {
private_key: private_key.inner,
public_key: public_key.inner,
})
}
}
impl RsaPrivateKey {
pub fn try_from_slice(bytes: impl AsRef<[u8]>) -> Result<Self> {
let key = KeyBytes::copy_slice(bytes.as_ref())?;
match get_key_kind(&key)? {
KeyKind::RsaPrivate => Ok(Self { inner: key }),
_ => Err(Error::with_kind(ErrorKind::InvalidParameter)),
}
}
pub(crate) fn from_vec(bytes: Vec<u8>) -> Self {
let key = KeyBytes::from_vec(bytes).expect("invalid empty key");
debug_assert_eq!(get_key_kind(&key), Ok(KeyKind::RsaPrivate));
Self { inner: key }
}
}
impl RsaPublicKey {
pub fn try_from_slice(bytes: impl AsRef<[u8]>) -> Result<Self> {
let key = KeyBytes::copy_slice(bytes.as_ref())?;
match get_key_kind(&key)? {
KeyKind::RsaPublic => Ok(Self { inner: key }),
_ => Err(Error::with_kind(ErrorKind::InvalidParameter)),
}
}
pub(crate) fn from_vec(bytes: Vec<u8>) -> Self {
let key = KeyBytes::from_vec(bytes).expect("invalid empty key");
debug_assert_eq!(get_key_kind(&key), Ok(KeyKind::RsaPublic));
Self { inner: key }
}
}
impl EcdsaPrivateKey {
pub fn try_from_slice(bytes: impl AsRef<[u8]>) -> Result<Self> {
let key = KeyBytes::copy_slice(bytes.as_ref())?;
match get_key_kind(&key)? {
KeyKind::EcdsaPrivate => Ok(Self { inner: key }),
_ => Err(Error::with_kind(ErrorKind::InvalidParameter)),
}
}
pub(crate) fn from_vec(bytes: Vec<u8>) -> Self {
let key = KeyBytes::from_vec(bytes).expect("invalid empty key");
debug_assert_eq!(get_key_kind(&key), Ok(KeyKind::EcdsaPrivate));
Self { inner: key }
}
}
impl EcdsaPublicKey {
pub fn try_from_slice(bytes: impl AsRef<[u8]>) -> Result<Self> {
let key = KeyBytes::copy_slice(bytes.as_ref())?;
match get_key_kind(&key)? {
KeyKind::EcdsaPublic => Ok(Self { inner: key }),
_ => Err(Error::with_kind(ErrorKind::InvalidParameter)),
}
}
pub(crate) fn from_vec(bytes: Vec<u8>) -> Self {
let key = KeyBytes::from_vec(bytes).expect("invalid empty key");
debug_assert_eq!(get_key_kind(&key), Ok(KeyKind::EcdsaPublic));
Self { inner: key }
}
}
impl PrivateKey {
pub fn kind(&self) -> KeyKind {
get_key_kind_trusted(&self.inner)
}
pub fn try_from_slice(bytes: impl AsRef<[u8]>) -> Result<Self> {
let key = KeyBytes::copy_slice(bytes.as_ref())?;
match get_key_kind(&key)? {
KeyKind::RsaPrivate => Ok(Self { inner: key }),
KeyKind::EcdsaPrivate => Ok(Self { inner: key }),
_ => Err(Error::with_kind(ErrorKind::InvalidParameter)),
}
}
}
impl PublicKey {
pub fn kind(&self) -> KeyKind {
get_key_kind_trusted(&self.inner)
}
pub fn try_from_slice(bytes: impl AsRef<[u8]>) -> Result<Self> {
let key = KeyBytes::copy_slice(bytes.as_ref())?;
match get_key_kind(&key)? {
KeyKind::RsaPublic => Ok(Self { inner: key }),
KeyKind::EcdsaPublic => Ok(Self { inner: key }),
_ => Err(Error::with_kind(ErrorKind::InvalidParameter)),
}
}
}
fn get_key_kind(key: &KeyBytes) -> Result<KeyKind> {
is_valid_themis_key(key)?;
try_get_key_kind(key)
}
fn get_key_kind_trusted(key: &KeyBytes) -> KeyKind {
debug_assert!(is_valid_themis_key(key).is_ok());
try_get_key_kind(key).expect("get_key_kind_trusted() called for invalid key")
}
fn is_valid_themis_key(key: &KeyBytes) -> Result<()> {
let (ptr, len) = into_raw_parts(key.as_bytes());
let status = unsafe { themis_is_valid_asym_key(ptr, len) };
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
Ok(())
}
fn try_get_key_kind(key: &KeyBytes) -> Result<KeyKind> {
use bindings::themis_key_kind::*;
let (ptr, len) = into_raw_parts(key.as_bytes());
let kind = unsafe { themis_get_asym_key_kind(ptr, len) };
match kind {
THEMIS_KEY_RSA_PRIVATE => Ok(KeyKind::RsaPrivate),
THEMIS_KEY_RSA_PUBLIC => Ok(KeyKind::RsaPublic),
THEMIS_KEY_EC_PRIVATE => Ok(KeyKind::EcdsaPrivate),
THEMIS_KEY_EC_PUBLIC => Ok(KeyKind::EcdsaPublic),
THEMIS_KEY_INVALID => Err(Error::with_kind(ErrorKind::InvalidParameter)),
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct SymmetricKey {
inner: KeyBytes,
}
impl SymmetricKey {
pub fn new() -> Self {
match Self::try_gen_sym_key() {
Ok(key) => key,
Err(e) => panic!("themis_gen_sym_key() failed: {}", e),
}
}
fn try_gen_sym_key() -> Result<Self> {
let mut key = Vec::new();
let mut key_len = 0;
unsafe {
let status = themis_gen_sym_key(ptr::null_mut(), &mut key_len);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::BufferTooSmall {
return Err(error);
}
}
key.reserve(key_len);
unsafe {
let status = themis_gen_sym_key(key.as_mut_ptr(), &mut key_len);
let error = Error::from_themis_status(status);
if error.kind() != ErrorKind::Success {
return Err(error);
}
debug_assert!(key_len <= key.capacity());
key.set_len(key_len as usize);
}
Ok(Self {
inner: KeyBytes::from_vec(key).expect("invalid empty key"),
})
}
pub fn try_from_slice(bytes: impl AsRef<[u8]>) -> Result<Self> {
Ok(Self {
inner: KeyBytes::copy_slice(bytes.as_ref())?,
})
}
}
impl Default for SymmetricKey {
fn default() -> Self {
SymmetricKey::new()
}
}
impl AsRef<[u8]> for RsaPrivateKey {
fn as_ref(&self) -> &[u8] {
self.inner.as_bytes()
}
}
impl AsRef<[u8]> for RsaPublicKey {
fn as_ref(&self) -> &[u8] {
self.inner.as_bytes()
}
}
impl AsRef<[u8]> for EcdsaPrivateKey {
fn as_ref(&self) -> &[u8] {
self.inner.as_bytes()
}
}
impl AsRef<[u8]> for EcdsaPublicKey {
fn as_ref(&self) -> &[u8] {
self.inner.as_bytes()
}
}
impl AsRef<[u8]> for PrivateKey {
fn as_ref(&self) -> &[u8] {
self.inner.as_bytes()
}
}
impl AsRef<[u8]> for PublicKey {
fn as_ref(&self) -> &[u8] {
self.inner.as_bytes()
}
}
impl AsRef<[u8]> for SymmetricKey {
fn as_ref(&self) -> &[u8] {
self.inner.as_bytes()
}
}
impl From<RsaPrivateKey> for PrivateKey {
fn from(private_key: RsaPrivateKey) -> PrivateKey {
PrivateKey {
inner: private_key.inner,
}
}
}
impl From<RsaPublicKey> for PublicKey {
fn from(public_key: RsaPublicKey) -> PublicKey {
PublicKey {
inner: public_key.inner,
}
}
}
impl From<EcdsaPrivateKey> for PrivateKey {
fn from(private_key: EcdsaPrivateKey) -> PrivateKey {
PrivateKey {
inner: private_key.inner,
}
}
}
impl From<EcdsaPublicKey> for PublicKey {
fn from(public_key: EcdsaPublicKey) -> PublicKey {
PublicKey {
inner: public_key.inner,
}
}
}
impl From<RsaKeyPair> for KeyPair {
fn from(key_pair: RsaKeyPair) -> KeyPair {
KeyPair {
private_key: key_pair.private_key,
public_key: key_pair.public_key,
}
}
}
impl From<EcdsaKeyPair> for KeyPair {
fn from(key_pair: EcdsaKeyPair) -> KeyPair {
KeyPair {
private_key: key_pair.private_key,
public_key: key_pair.public_key,
}
}
}