use std::cmp::Ordering;
use std::ops::{Deref, DerefMut};
use std::fmt;
use std::borrow::Cow;
use crate::{
Error,
Result,
};
pub mod aead;
mod asymmetric;
pub use self::asymmetric::{Signer, Decryptor, KeyPair};
pub(crate) mod backend;
pub mod ecdh;
pub mod hash;
mod key;
pub mod mem;
pub mod mpi;
mod s2k;
pub use s2k::S2K;
pub mod symmetric;
mod types;
pub use types::{
AEADAlgorithm,
Curve,
HashAlgorithm,
PublicKeyAlgorithm,
SymmetricAlgorithm,
};
#[cfg(test)]
mod tests;
pub fn backend() -> String {
use backend::interface::Backend;
backend::Backend::backend()
}
pub fn random<B: AsMut<[u8]>>(mut buf: B) -> Result<()> {
use backend::interface::Backend;
backend::Backend::random(buf.as_mut())
}
#[derive(Clone, PartialEq, Eq)]
pub struct SessionKey(mem::Protected);
assert_send_and_sync!(SessionKey);
impl SessionKey {
pub fn new(size: usize) -> Result<Self> {
let mut sk: mem::Protected = vec![0; size].into();
random(&mut sk)?;
Ok(Self(sk))
}
pub fn as_protected(&self) -> &mem::Protected {
&self.0
}
}
impl Deref for SessionKey {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<[u8]> for SessionKey {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl DerefMut for SessionKey {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl AsMut<[u8]> for SessionKey {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl From<mem::Protected> for SessionKey {
fn from(v: mem::Protected) -> Self {
SessionKey(v)
}
}
impl From<Vec<u8>> for SessionKey {
fn from(v: Vec<u8>) -> Self {
SessionKey(v.into())
}
}
impl From<Box<[u8]>> for SessionKey {
fn from(v: Box<[u8]>) -> Self {
SessionKey(v.into())
}
}
impl From<&[u8]> for SessionKey {
fn from(v: &[u8]) -> Self {
Vec::from(v).into()
}
}
impl fmt::Debug for SessionKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SessionKey ({:?})", self.0)
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct Password(mem::Encrypted);
assert_send_and_sync!(Password);
impl From<Vec<u8>> for Password {
fn from(v: Vec<u8>) -> Self {
Password(mem::Encrypted::new(v.into())
.expect("encrypting memory failed"))
}
}
impl From<Box<[u8]>> for Password {
fn from(v: Box<[u8]>) -> Self {
Password(mem::Encrypted::new(v.into())
.expect("encrypting memory failed"))
}
}
impl From<String> for Password {
fn from(v: String) -> Self {
v.into_bytes().into()
}
}
impl<'a> From<&'a str> for Password {
fn from(v: &'a str) -> Self {
v.to_owned().into()
}
}
impl From<&[u8]> for Password {
fn from(v: &[u8]) -> Self {
Vec::from(v).into()
}
}
impl fmt::Debug for Password {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if cfg!(debug_assertions) {
self.map(|p| write!(f, "Password({:?})", p))
} else {
f.write_str("Password(<Encrypted>)")
}
}
}
impl Password {
pub fn map<F, T>(&self, fun: F) -> T
where F: FnMut(&mem::Protected) -> T
{
self.0.map(fun)
}
}
pub(crate) fn pad(value: &[u8], to: usize) -> Result<Cow<'_, [u8]>>
{
match value.len().cmp(&to) {
Ordering::Equal => Ok(Cow::Borrowed(value)),
Ordering::Less => {
let missing = to - value.len();
let mut v = vec![0; to];
v[missing..].copy_from_slice(value);
Ok(Cow::Owned(v))
}
Ordering::Greater => {
Err(Error::InvalidOperation(
format!("Input value is longer than expected: {} > {}",
value.len(), to)).into())
}
}
}
#[allow(dead_code)]
pub(crate) fn pad_at_least(value: &[u8], to: usize) -> Cow<'_, [u8]>
{
pad(value, to).unwrap_or(Cow::Borrowed(value))
}
#[allow(dead_code)]
pub(crate) fn pad_truncating(value: &[u8], to: usize) -> Cow<'_, [u8]>
{
if value.len() == to {
Cow::Borrowed(value)
} else {
let missing = to.saturating_sub(value.len());
let limit = value.len().min(to);
let mut v = vec![0; to];
v[missing..].copy_from_slice(&value[..limit]);
Cow::Owned(v)
}
}
pub(crate) fn raw_bigint_cmp(mut a: &[u8], mut b: &[u8]) -> Ordering {
while a.get(0) == Some(&0) {
a = &a[1..];
}
while b.get(0) == Some(&0) {
b = &b[1..];
}
a.len().cmp(&b.len())
.then_with(|| a.cmp(b))
}
#[allow(dead_code)]
pub(crate) fn rsa_sort_raw_pq<'a>(p: &'a [u8], q: &'a [u8])
-> (&'a [u8], &'a [u8])
{
match raw_bigint_cmp(p, q) {
Ordering::Less => (p, q),
Ordering::Equal => (p, q),
Ordering::Greater => (q, p),
}
}