123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281 |
- /// Functions for performing cryptographic operations on the main data structures.
- mod tpm;
- use super::*;
- use openssl::{
- error::ErrorStack,
- encrypt::{Encrypter as OsslEncrypter, Decrypter as OsslDecrypter},
- pkey::{PKey, Public as OsslPublic, Private as OsslPrivate, HasPublic, HasPrivate},
- symm::{Cipher, encrypt as openssl_encrypt, decrypt as openssl_decrypt},
- rand::rand_bytes,
- rsa::{Rsa, Padding as OpensslPadding},
- hash::{hash, MessageDigest},
- sign::{Signer as OsslSigner, Verifier as OsslVerifier}
- };
- use serde_block_tree::{self, to_vec, from_vec, write_to};
- use serde::{
- de::{self, DeserializeOwned, Deserializer, SeqAccess, Visitor},
- ser::{Serializer, SerializeStruct},
- };
- use std::{
- str::FromStr, num::TryFromIntError, marker::PhantomData,
- };
- use strum_macros::{EnumString, EnumDiscriminants, Display};
- use foreign_types::ForeignType;
- /// Data that may or may not be encrypted.
- #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
- pub(crate) enum Cryptotext<T: Serialize> {
- /// The inner value of `T` is plaintext.
- Plain(T),
- /// The inner value is ciphertext.
- Cipher(Vec<u8>),
- }
- /// Errors that can occur during cryptographic operations.
- #[derive(Debug)]
- pub enum Error {
- NoReadCap,
- NoKeyAvailable,
- MissingPrivateKey,
- KeyVariantUnsupported,
- BlockNotEncrypted,
- InvalidHashFormat,
- Serde(serde_block_tree::Error),
- Io(std::io::Error),
- Custom(Box<dyn std::fmt::Debug>)
- }
- impl Error {
- fn custom<E: std::fmt::Debug + 'static>(err: E) -> Self {
- Error::Custom(Box::new(err))
- }
- }
- impl Display for Error {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- match self {
- Error::NoReadCap => write!(f, "no readcap"),
- Error::NoKeyAvailable => write!(f, "no key available"),
- Error::MissingPrivateKey => write!(f, "private key was missing"),
- Error::KeyVariantUnsupported => write!(f, "unsupported key variant"),
- Error::BlockNotEncrypted => write!(f, "block was not encrypted"),
- Error::InvalidHashFormat => write!(f, "invalid format"),
- Error::Serde(serde_err) => serde_err.fmt(f),
- Error::Io(io_err) => io_err.fmt(f),
- Error::Custom(cus) => cus.fmt(f),
- }
- }
- }
- impl From<ErrorStack> for Error {
- fn from(error: ErrorStack) -> Error {
- Error::custom(error)
- }
- }
- impl From<serde_block_tree::Error> for Error {
- fn from(error: serde_block_tree::Error) -> Error {
- Error::Serde(error)
- }
- }
- impl From<std::io::Error> for Error {
- fn from(error: std::io::Error) -> Error {
- Error::Io(error)
- }
- }
- impl From<TryFromIntError> for Error {
- fn from(err: TryFromIntError) -> Self {
- Error::custom(err)
- }
- }
- pub(crate) type Result<T> = std::result::Result<T, Error>;
- trait ConvErr<T> {
- fn conv_err(self) -> Result<T>;
- }
- impl<T, E: Into<Error>> ConvErr<T> for std::result::Result<T, E> {
- /// Converts the error value in self to a `crypto::Error`.
- fn conv_err(self) -> Result<T> {
- self.map_err(|e| e.into())
- }
- }
- /// A cryptographic hash.
- #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hashable, Clone, EnumDiscriminants)]
- #[strum_discriminants(derive(EnumString, Display, Serialize, Deserialize))]
- #[strum_discriminants(name(HashKind))]
- pub(crate) enum Hash {
- Sha2_256([u8; 32]),
- #[serde(with = "BigArray")]
- Sha2_512([u8; 64]),
- }
- impl Default for HashKind {
- fn default() -> HashKind {
- HashKind::Sha2_256
- }
- }
- impl From<HashKind> for MessageDigest {
- fn from(kind: HashKind) -> Self {
- match kind {
- HashKind::Sha2_256 => MessageDigest::sha256(),
- HashKind::Sha2_512 => MessageDigest::sha512(),
- }
- }
- }
- impl Hash {
- /// The character that's used to separate a hash type from its value in its string
- /// representation.
- const HASH_SEP: char = ':';
- fn kind(&self) -> HashKind {
- HashKind::from(self)
- }
- }
- impl From<HashKind> for Hash {
- fn from(discriminant: HashKind) -> Hash {
- match discriminant {
- HashKind::Sha2_512 => Hash::Sha2_512([0u8; 64]),
- HashKind::Sha2_256 => Hash::Sha2_256([0u8; 32])
- }
- }
- }
- impl AsRef<[u8]> for Hash {
- fn as_ref(&self) -> &[u8] {
- match self {
- Hash::Sha2_256(arr) => arr,
- Hash::Sha2_512(arr) => arr
- }
- }
- }
- impl AsMut<[u8]> for Hash {
- fn as_mut(&mut self) -> &mut [u8] {
- match self {
- Hash::Sha2_256(arr) => arr,
- Hash::Sha2_512(arr) => arr
- }
- }
- }
- impl TryFrom<&str> for Hash {
- type Error = Error;
- fn try_from(string: &str) -> Result<Hash> {
- let mut split: Vec<&str> = string.split(Self::HASH_SEP).collect();
- if split.len() != 2 {
- return Err(Error::InvalidHashFormat)
- };
- let second = split.pop().ok_or(Error::InvalidHashFormat)?;
- let first = split.pop().ok_or(Error::InvalidHashFormat)?;
- let mut hash = Hash::from(HashKind::from_str(first)
- .map_err(|_| Error::InvalidHashFormat)?);
- base64_url::decode_to_slice(second, hash.as_mut())
- .map_err(|_| Error::InvalidHashFormat)?;
- Ok(hash)
- }
- }
- impl Display for Hash {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let hash_type: HashKind = self.into();
- let hash_data = base64_url::encode(self.as_ref());
- write!(f, "{}{}{}", hash_type, Hash::HASH_SEP, hash_data)
- }
- }
- pub(crate) const RSA_KEY_BYTES: usize = 384;
- /// A cryptographic signature.
- #[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumDiscriminants)]
- #[strum_discriminants(name(SignatureKind))]
- pub(crate) enum Signature {
- #[serde(with = "BigArray")]
- Rsa([u8; RSA_KEY_BYTES]),
- }
- impl Signature {
- fn new(id: SignatureKind) -> Signature {
- match id {
- SignatureKind::Rsa => Signature::Rsa([0; RSA_KEY_BYTES])
- }
- }
- fn as_slice(&self) -> &[u8] {
- match self {
- Signature::Rsa(buf) => buf.as_slice()
- }
- }
- fn as_mut_slice(&mut self) -> &mut [u8] {
- match self {
- Signature::Rsa(buf) => buf.as_mut_slice()
- }
- }
- }
- impl AsRef<[u8]> for Signature {
- fn as_ref(&self) -> &[u8] {
- self.as_slice()
- }
- }
- impl AsMut<[u8]> for Signature {
- fn as_mut(&mut self) -> &mut [u8] {
- self.as_mut_slice()
- }
- }
- impl Default for Signature {
- fn default() -> Self {
- Signature::Rsa([0; RSA_KEY_BYTES])
- }
- }
- #[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumDiscriminants)]
- #[strum_discriminants(name(SymKeyKind))]
- pub(crate) enum SymKey {
- /// A key for the AES 256 cipher in Cipher Block Chaining mode. Note that this includes the
- /// initialization vector, so that a value of this variant contains all the information needed
- /// to fully initialize a cipher context.
- Aes256Cbc {
- key: [u8; 32],
- iv: [u8; 16],
- },
- /// A key for the AES 256 cipher in counter mode.
- Aes256Ctr {
- key: [u8; 32],
- iv: [u8; 16]
- },
- }
- struct SymParams<'a> {
- cipher: Cipher,
- key: &'a [u8],
- iv: Option<&'a [u8]>,
- }
- /// Returns an array of the given length filled with cryptographically random data.
- fn rand_array<const LEN: usize>() -> Result<[u8; LEN]> {
- let mut array = [0; LEN];
- rand_bytes(&mut array).conv_err()?;
- Ok(array)
- }
- impl SymKey {
- pub(crate) fn generate(kind: SymKeyKind) -> Result<SymKey> {
- match kind {
- SymKeyKind::Aes256Cbc => {
- Ok(SymKey::Aes256Cbc { key: rand_array()?, iv: rand_array()? })
- },
- SymKeyKind::Aes256Ctr => {
- Ok(SymKey::Aes256Ctr { key: rand_array()?, iv: rand_array()? })
- },
- }
- }
- fn params(&self) -> SymParams {
- let (cipher, key, iv) = match self {
- SymKey::Aes256Cbc { key, iv } => (Cipher::aes_256_cbc(), key, Some(iv.as_slice())),
- SymKey::Aes256Ctr { key, iv } => (Cipher::aes_256_ctr(), key, Some(iv.as_slice())),
- };
- SymParams { cipher, key, iv }
- }
- }
- impl Encrypter for SymKey {
- fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- let SymParams { cipher, key, iv } = self.params();
- openssl_encrypt(cipher, key, iv, slice).conv_err()
- }
- }
- impl Decrypter for SymKey {
- fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- let SymParams { cipher, key, iv } = self.params();
- openssl_decrypt(cipher, key, iv, slice).conv_err()
- }
- }
- pub trait Scheme: for<'de> Deserialize<'de> + Serialize + Copy + std::fmt::Debug + PartialEq {
- type Kind: Scheme;
- fn kind(self) -> Self::Kind;
- fn as_enum(self) -> SchemeKind;
- fn message_digest(&self) -> MessageDigest;
- fn padding(&self) -> Option<OpensslPadding>;
- fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>>;
- fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>>;
- fn generate(self) -> Result<AsymKeyPair<Self::Kind>>;
- }
- pub enum SchemeKind {
- Sign(Sign),
- Encrypt(Encrypt),
- }
- #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
- pub enum Encrypt {
- RsaEsOaep(RsaEsOaep),
- }
- impl Scheme for Encrypt {
- type Kind = Encrypt;
- fn kind(self) -> Encrypt {
- self
- }
- fn as_enum(self) -> SchemeKind {
- SchemeKind::Encrypt(self.kind())
- }
- fn message_digest(&self) -> MessageDigest {
- match self {
- Encrypt::RsaEsOaep(inner) => inner.message_digest(),
- }
- }
- fn padding(&self) -> Option<OpensslPadding> {
- match self {
- Encrypt::RsaEsOaep(inner) => inner.padding(),
- }
- }
- fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>> {
- match self {
- Encrypt::RsaEsOaep(inner) => inner.public_from_der(der),
- }
- }
- fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>> {
- match self {
- Encrypt::RsaEsOaep(inner) => inner.private_from_der(der),
- }
- }
- fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
- match self {
- Encrypt::RsaEsOaep(inner) => inner.generate(),
- }
- }
- }
- impl Encrypt {
- pub const RSA_OAEP_3072_SHA_256: Encrypt = Encrypt::RsaEsOaep(RsaEsOaep {
- key_bytes: 384,
- hash_kind: HashKind::Sha2_256,
- });
- }
- #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
- pub enum Sign {
- RsaSsaPss(RsaSsaPss),
- }
- impl Scheme for Sign {
- type Kind = Sign;
- fn kind(self) -> Sign {
- self
- }
- fn as_enum(self) -> SchemeKind {
- SchemeKind::Sign(self.kind())
- }
- fn message_digest(&self) -> MessageDigest {
- match self {
- Sign::RsaSsaPss(inner) => inner.message_digest(),
- }
- }
- fn padding(&self) -> Option<OpensslPadding> {
- match self {
- Sign::RsaSsaPss(inner) => inner.padding(),
- }
- }
- fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>> {
- match self {
- Sign::RsaSsaPss(inner) => inner.public_from_der(der),
- }
- }
- fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>> {
- match self {
- Sign::RsaSsaPss(inner) => inner.private_from_der(der),
- }
- }
- fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
- match self {
- Sign::RsaSsaPss(inner) => inner.generate(),
- }
- }
- }
- impl Sign {
- pub const RSA_PSS_3072_SHA_256: Sign = Sign::RsaSsaPss(RsaSsaPss {
- key_bytes: 384,
- hash_kind: HashKind::Sha2_256,
- });
- fn sig_buf(&self) -> Signature {
- match self {
- Sign::RsaSsaPss(_) => Signature::Rsa([0u8; RSA_KEY_BYTES]),
- }
- }
- }
- #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
- pub struct RsaEsOaep {
- key_bytes: usize,
- hash_kind: HashKind,
- }
- fn generate_rsa<S: Scheme>(scheme: S) -> Result<AsymKeyPair<S>> {
- let key_bits = 8 * u32::try_from(RSA_KEY_BYTES).conv_err()?;
- let key = Rsa::generate(key_bits)?;
- // TODO: Separating the keys this way seems inefficient. Investigate alternatives.
- let public_der = key.public_key_to_der().conv_err()?;
- let private_der = key.private_key_to_der().conv_err()?;
- let public = AsymKey::<Public, S>::new(scheme, &public_der)?;
- let private = AsymKey::<Private, S>::new(scheme, &private_der)?;
- Ok(AsymKeyPair { public, private })
- }
- impl Scheme for RsaEsOaep {
- type Kind = Encrypt;
- fn kind(self) -> Encrypt {
- Encrypt::RsaEsOaep(self)
- }
- fn as_enum(self) -> SchemeKind {
- SchemeKind::Encrypt(self.kind())
- }
- fn message_digest(&self) -> MessageDigest {
- self.hash_kind.into()
- }
- fn padding(&self) -> Option<OpensslPadding> {
- Some(OpensslPadding::PKCS1_OAEP)
- }
- fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>> {
- PKey::public_key_from_der(der).conv_err()
- }
- fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>> {
- PKey::private_key_from_der(der).conv_err()
- }
- fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
- generate_rsa(self.kind())
- }
- }
- impl From<RsaEsOaep> for Encrypt {
- fn from(scheme: RsaEsOaep) -> Self {
- scheme.kind()
- }
- }
- #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
- pub struct RsaSsaPss {
- key_bytes: usize,
- hash_kind: HashKind,
- }
- impl Scheme for RsaSsaPss {
- type Kind = Sign;
- fn kind(self) -> Sign {
- Sign::RsaSsaPss(self)
- }
- fn as_enum(self) -> SchemeKind {
- SchemeKind::Sign(self.kind())
- }
- fn message_digest(&self) -> MessageDigest {
- self.hash_kind.into()
- }
- fn padding(&self) -> Option<OpensslPadding> {
- Some(OpensslPadding::PKCS1_PSS)
- }
- fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>> {
- PKey::public_key_from_der(der).conv_err()
- }
- fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>> {
- PKey::private_key_from_der(der).conv_err()
- }
- fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
- generate_rsa(self.kind())
- }
- }
- impl From<RsaSsaPss> for Sign {
- fn from(scheme: RsaSsaPss) -> Self {
- scheme.kind()
- }
- }
- pub trait KeyPrivacy {}
- #[derive(Clone, Debug)]
- pub enum Public {}
- impl KeyPrivacy for Public {}
- unsafe impl HasPublic for Public {}
- pub enum Private {}
- impl KeyPrivacy for Private {}
- unsafe impl HasPrivate for Private {}
- fn conv_pkey<T, Q>(pkey: PKey<T>) -> PKey<Q> {
- let ptr = pkey.as_ptr();
- let new_pkey = unsafe { PKey::from_ptr(ptr) };
- std::mem::forget(pkey);
- new_pkey
- }
- fn conv_pkey_pub(pkey: PKey<OsslPublic>) -> PKey<Public> {
- conv_pkey(pkey)
- }
- fn conv_pkey_priv(pkey: PKey<OsslPrivate>) -> PKey<Private> {
- conv_pkey(pkey)
- }
- #[derive(Debug, Clone)]
- pub struct AsymKey<P: KeyPrivacy, S: Scheme> {
- scheme: S,
- pkey: PKey<P>,
- }
- pub type AsymKeyPub<S> = AsymKey<Public, S>;
- impl<P: KeyPrivacy, S: Scheme> AsymKey<P, S> {
- fn digest(&self) -> MessageDigest {
- self.scheme.message_digest()
- }
- fn padding(&self) -> Option<OpensslPadding> {
- self.scheme.padding()
- }
- }
- impl<S: Scheme> AsymKey<Public, S> {
- pub(crate) fn new(scheme: S, der: &[u8]) -> Result<AsymKey<Public, S>> {
- let pkey = conv_pkey_pub(scheme.public_from_der(der)?);
- Ok(AsymKey { scheme, pkey })
- }
- fn to_der(&self) -> Result<Vec<u8>> {
- self.pkey.public_key_to_der().conv_err()
- }
- }
- impl<S: Scheme> AsymKey<Private, S> {
- pub(crate) fn new(scheme: S, der: &[u8]) -> Result<AsymKey<Private, S>> {
- let pkey = conv_pkey_priv(scheme.private_from_der(der)?);
- Ok(AsymKey { scheme, pkey })
- }
- }
- impl<P: KeyPrivacy> AsymKey<P, Sign> {
- fn signature_buf(&self) -> Signature {
- self.scheme.sig_buf()
- }
- }
- impl<'de, S: Scheme> Deserialize<'de> for AsymKey<Public, S> {
- fn deserialize<D: Deserializer<'de>>(d: D) -> std::result::Result<Self, D::Error> {
- const FIELDS: &[&str] = &["scheme", "pkey"];
- struct StructVisitor<S: Scheme>(PhantomData<S>);
- impl<'de, S: Scheme> Visitor<'de> for StructVisitor<S> {
- type Value = AsymKey<Public, S>;
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_fmt(format_args!("struct {}", stringify!(AsymKey)))
- }
- fn visit_seq<V: SeqAccess<'de>>(
- self, mut seq: V
- ) -> std::result::Result<Self::Value, V::Error> {
- let scheme: S = seq.next_element()?
- .ok_or_else(|| de::Error::missing_field(FIELDS[0]))?;
- let der: Vec<u8> = seq.next_element()?
- .ok_or_else(|| de::Error::missing_field(FIELDS[1]))?;
- AsymKey::<Public, _>::new(scheme, der.as_slice())
- .map_err(de::Error::custom)
- }
- }
- d.deserialize_struct(
- stringify!(AsymKey), FIELDS, StructVisitor(PhantomData)
- )
- }
- }
- impl<S: Scheme> Serialize for AsymKey<Public, S> {
- fn serialize<T: Serializer>(&self, s: T) -> std::result::Result<T::Ok, T::Error> {
- let mut struct_s = s.serialize_struct(stringify!(AsymKey), 2)?;
- struct_s.serialize_field("scheme", &self.scheme)?;
- let der = self.pkey.public_key_to_der().unwrap();
- struct_s.serialize_field("pkey", der.as_slice())?;
- struct_s.end()
- }
- }
- impl<S: Scheme> PartialEq for AsymKey<Public, S> {
- fn eq(&self, other: &Self) -> bool {
- self.scheme == other.scheme && self.pkey.public_eq(&other.pkey)
- }
- }
- impl Owned for AsymKey<Public, Sign> {
- fn owner_of_kind(&self, kind: HashKind) -> Principal {
- match kind {
- HashKind::Sha2_256 => {
- let mut buf = [0; 32];
- let der = self.to_der().unwrap();
- let bytes = hash(MessageDigest::sha256(), der.as_slice()).unwrap();
- buf.copy_from_slice(&*bytes);
- Principal(Hash::Sha2_256(buf))
- },
- HashKind::Sha2_512 => {
- let mut buf = [0; 64];
- let der = self.to_der().unwrap();
- let bytes = hash(MessageDigest::sha512(), der.as_slice()).unwrap();
- buf.copy_from_slice(&*bytes);
- Principal(Hash::Sha2_512(buf))
- }
- }
- }
- }
- impl Encrypter for AsymKey<Public, Encrypt> {
- fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- let mut encrypter = OsslEncrypter::new(&self.pkey)?;
- if let Some(padding) = self.padding() {
- encrypter.set_rsa_padding(padding)?;
- }
- {
- let Encrypt::RsaEsOaep(inner) = self.scheme;
- encrypter.set_rsa_oaep_md(inner.message_digest())?;
- }
- let buffer_len = encrypter.encrypt_len(slice)?;
- let mut ciphertext = vec![0; buffer_len];
- let ciphertext_len = encrypter.encrypt(slice, &mut ciphertext)?;
- ciphertext.truncate(ciphertext_len);
- Ok(ciphertext)
- }
- }
- impl Decrypter for AsymKey<Private, Encrypt> {
- fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- let mut decrypter = OsslDecrypter::new(&self.pkey).conv_err()?;
- if let Some(padding) = self.padding() {
- decrypter.set_rsa_padding(padding).conv_err()?;
- }
- {
- let Encrypt::RsaEsOaep(inner) = self.scheme;
- decrypter.set_rsa_oaep_md(inner.message_digest())?;
- }
- let buffer_len = decrypter.decrypt_len(slice).conv_err()?;
- let mut plaintext = vec![0; buffer_len];
- let plaintext_len = decrypter.decrypt(slice, &mut plaintext).conv_err()?;
- plaintext.truncate(plaintext_len);
- Ok(plaintext)
- }
- }
- impl Signer for AsymKey<Private, Sign> {
- fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature> {
- let mut signer = OsslSigner::new(self.scheme.message_digest(), &self.pkey)?;
- if let Some(padding) = self.scheme.padding() {
- signer.set_rsa_padding(padding)?;
- }
- for part in parts {
- signer.update(part)?;
- }
- let mut signature = self.scheme.sig_buf();
- signer.sign(signature.as_mut_slice())?;
- Ok(signature)
- }
- }
- impl Verifier for AsymKey<Public, Sign> {
- fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool> {
- let mut verifier = OsslVerifier::new(self.digest(), &self.pkey)?;
- if let Some(padding) = self.scheme.padding() {
- verifier.set_rsa_padding(padding)?;
- }
- for part in parts {
- verifier.update(part)?;
- }
- Ok(verifier.verify(signature)?)
- }
- }
- pub struct AsymKeyPair<S: Scheme> {
- public: AsymKey<Public, S>,
- private: AsymKey<Private, S>,
- }
- impl<S: Scheme> AsymKeyPair<S> {
- pub fn new(scheme: S, public_der: &[u8], private_der: &[u8]) -> Result<AsymKeyPair<S>> {
- let public = AsymKey::<Public, _>::new(scheme, public_der)?;
- let private = AsymKey::<Private, _>::new(scheme, private_der)?;
- Ok(AsymKeyPair { public, private })
- }
- }
- impl Owned for AsymKeyPair<Sign> {
- fn owner_of_kind(&self, kind: HashKind) -> Principal {
- self.public.owner_of_kind(kind)
- }
- }
- impl Encrypter for AsymKeyPair<Encrypt> {
- fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- self.public.encrypt(slice)
- }
- }
- impl Decrypter for AsymKeyPair<Encrypt> {
- fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- self.private.decrypt(slice)
- }
- }
- impl Signer for AsymKeyPair<Sign> {
- fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature> {
- self.private.sign(parts)
- }
- }
- impl Verifier for AsymKeyPair<Sign> {
- fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool> {
- self.public.verify(parts, signature)
- }
- }
- pub struct ConcreteCreds {
- sign: AsymKeyPair<Sign>,
- encrypt: AsymKeyPair<Encrypt>,
- }
- impl ConcreteCreds {
- pub(crate) fn new(sign: AsymKeyPair<Sign>, encrypt: AsymKeyPair<Encrypt>) -> ConcreteCreds {
- ConcreteCreds { sign, encrypt }
- }
- pub(crate) fn generate() -> Result<ConcreteCreds> {
- let encrypt = Encrypt::RSA_OAEP_3072_SHA_256.generate()?;
- let sign = Sign::RSA_PSS_3072_SHA_256.generate()?;
- Ok(ConcreteCreds { sign, encrypt })
- }
- }
- impl Verifier for ConcreteCreds {
- fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool> {
- self.sign.verify(parts, signature)
- }
- }
- impl Encrypter for ConcreteCreds {
- fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- self.encrypt.encrypt(slice)
- }
- }
- impl Owned for ConcreteCreds {
- fn owner_of_kind(&self, kind: HashKind) -> Principal {
- self.sign.owner_of_kind(kind)
- }
- }
- impl CredsPub for ConcreteCreds {}
- impl Signer for ConcreteCreds {
- fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature> {
- self.sign.sign(parts)
- }
- }
- impl Decrypter for ConcreteCreds {
- fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- self.encrypt.decrypt(slice)
- }
- }
- impl CredsPriv for ConcreteCreds {}
- impl Creds for ConcreteCreds {
- fn public(&self) -> &AsymKey<Public, Sign> {
- &self.sign.public
- }
- }
- pub(crate) trait Encrypter {
- fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>>;
- }
- pub(crate) trait Decrypter {
- fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>>;
- }
- pub(crate) trait Signer {
- fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature>;
- }
- pub(crate) trait Verifier {
- fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool>;
- }
- /// Trait for types which can be used as public credentials.
- pub(crate) trait CredsPub: Verifier + Encrypter + Owned {}
- /// Trait for types which contain private credentials.
- pub(crate) trait CredsPriv: Decrypter + Signer {}
- /// Trait for types which contain both public and private credentials.
- pub(crate) trait Creds: CredsPriv + CredsPub {
- fn public(&self) -> &AsymKey<Public, Sign>;
- }
- /// A trait for types which store credentials.
- pub(crate) trait CredStore {
- type CredHandle: Creds;
- /// Returns the node credentials. If credentials haven't been generated, they are generated
- /// stored and returned.
- fn node_creds(&self) -> Result<Self::CredHandle>;
- /// Returns the root credentials. If no root credentials have been generated, or the provided
- /// password is incorrect, then an error is returned.
- fn root_creds(&self, password: &str) -> Result<Self::CredHandle>;
- /// Generates the root credentials and protects them using the given password. If the root
- /// credentials have already been generated then an error is returned.
- fn gen_root_creds(&self, password: &str) -> Result<Self::CredHandle>;
- }
- pub(crate) fn encrypt_block<C: Encrypter + Decrypter>(
- mut block: Block, principal: &Principal, creds: &C
- ) -> Result<Block> {
- let body = match block.body {
- Cryptotext::Cipher(_) => return Ok(block),
- Cryptotext::Plain(body) => body
- };
- let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
- .ok_or(Error::NoReadCap)?;
- let block_key = decrypt(read_cap, creds)?;
- let new_body = block_key.encrypt(&body)?;
- block.body = Cryptotext::Cipher(new_body);
- block.readcaps.insert(principal_owned, encrypt(&block_key, creds)?);
- Ok(block)
- }
- pub(crate) fn decrypt_block<C: Decrypter>(
- mut block: Block, principal: &Principal, creds: &C
- ) -> Result<Block> {
- let body = match block.body {
- Cryptotext::Plain(_) => return Ok(block),
- Cryptotext::Cipher(body) => body
- };
- let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
- .ok_or(Error::NoReadCap)?;
- let block_key = decrypt(read_cap, creds)?;
- let new_body = block_key.decrypt(&body)?;
- block.body = Cryptotext::Plain(new_body);
- block.readcaps.insert(principal_owned, Cryptotext::Plain(block_key));
- Ok(block)
- }
- fn encrypt<T: Serialize, K: Encrypter>(value: &T, key: &K) -> Result<Cryptotext<T>> {
- let data = to_vec(value).conv_err()?;
- let vec = key.encrypt(&data);
- Ok(Cryptotext::Cipher(vec?))
- }
- fn decrypt<T: Serialize + DeserializeOwned, K: Decrypter>(
- cryptotext: Cryptotext<T>, key: &K
- ) -> Result<T> {
- let data = match cryptotext {
- Cryptotext::Plain(value) => return Ok(value),
- Cryptotext::Cipher(data) => data
- };
- let vec = key.decrypt(&data);
- from_vec(&vec?).conv_err()
- }
- #[derive(Serialize)]
- struct HeaderSigInput<'a> {
- path: &'a Path,
- readcaps: &'a HashMap<Principal, Cryptotext<SymKey>>,
- writecap: &'a Writecap,
- }
- impl<'a> From<&'a Block> for HeaderSigInput<'a> {
- fn from(block: &'a Block) -> HeaderSigInput<'a> {
- HeaderSigInput {
- path: &block.path,
- readcaps: &block.readcaps,
- writecap: &block.writecap,
- }
- }
- }
- fn get_body(block: &Block) -> Result<&[u8]> {
- let body = match &block.body {
- Cryptotext::Cipher(body) => body,
- Cryptotext::Plain(_) => {
- return Err(Error::BlockNotEncrypted);
- }
- };
- Ok(body)
- }
- pub(crate) fn sign_block<K: Signer>(
- block: &mut Block, writecap: Writecap, priv_key: &K
- ) -> Result<()> {
- block.writecap = writecap;
- let body = get_body(block)?;
- let sig_input = HeaderSigInput::from(&*block);
- let header = to_vec(&sig_input)?;
- let signature = priv_key.sign([header.as_slice(), body].into_iter())?;
- block.signature = signature;
- Ok(())
- }
- pub(crate) fn verify_block(block: &Block) -> Result<bool> {
- let body = get_body(block)?;
- let sig_input = HeaderSigInput::from(&*block);
- let header = to_vec(&sig_input)?;
- let parts = [header.as_slice(), body].into_iter();
- block.writecap.signing_key.verify(parts, block.signature.as_slice())
- }
- #[derive(Serialize)]
- struct WritecapSigInput<'a> {
- issued_to: &'a Principal,
- path: &'a Path,
- expires: &'a Epoch,
- signing_key: &'a AsymKey<Public, Sign>,
- }
- impl<'a> From<&'a Writecap> for WritecapSigInput<'a> {
- fn from(writecap: &'a Writecap) -> WritecapSigInput<'a> {
- WritecapSigInput {
- issued_to: &writecap.issued_to,
- path: &writecap.path,
- expires: &writecap.expires,
- signing_key: &writecap.signing_key,
- }
- }
- }
- pub(crate) fn sign_writecap<K: Signer>(writecap: &mut Writecap, priv_key: &K) -> Result<()> {
- let sig_input = to_vec(&WritecapSigInput::from(&*writecap))?;
- writecap.signature = priv_key.sign([sig_input.as_slice()].into_iter())?;
- Ok(())
- }
- /// The types of errors which can occur when verifying a writecap chain is authorized to write to
- /// a given path.
- #[derive(Debug, PartialEq)]
- pub(crate) enum WritecapAuthzErr {
- /// The chain is not valid for use on the given path.
- UnauthorizedPath,
- /// At least one writecap in the chain is expired.
- Expired,
- /// The given writecaps do not actually form a chain.
- NotChained,
- /// There is an invalid signature in the chain.
- InvalidSignature,
- /// The principal the root writecap was issued to does not own the given path.
- RootDoesNotOwnPath,
- /// An error occurred while serializing a writecap.
- Serde(String),
- /// A cryptographic error occurred while attempting to verify a writecap.
- Crypto(String),
- }
- /// Verifies that the given `Writecap` actually grants permission to write to the given `Path`.
- pub(crate) fn verify_writecap(
- mut writecap: &Writecap, path: &Path
- ) -> std::result::Result<(), WritecapAuthzErr> {
- let mut prev: Option<&Writecap> = None;
- let mut sig_input = Vec::new();
- let now = Epoch::now();
- loop {
- if !writecap.path.contains(path) {
- return Err(WritecapAuthzErr::UnauthorizedPath);
- }
- if writecap.expires <= now {
- return Err(WritecapAuthzErr::Expired);
- }
- if let Some(prev) = &prev {
- if prev.signing_key.owner_of_kind(writecap.issued_to.kind()) != writecap.issued_to {
- return Err(WritecapAuthzErr::NotChained);
- }
- }
- let sig = WritecapSigInput::from(writecap);
- sig_input.clear();
- write_to(&sig, &mut sig_input).map_err(|e| WritecapAuthzErr::Serde(e.to_string()))?;
- let valid = writecap.signing_key
- .verify([sig_input.as_slice()].into_iter(), writecap.signature.as_slice())
- .map_err(|e| WritecapAuthzErr::Crypto(e.to_string()))?;
- if !valid {
- return Err(WritecapAuthzErr::InvalidSignature);
- }
- match &writecap.next {
- Some(next) => {
- prev = Some(writecap);
- writecap = next;
- },
- None => {
- // We're at the root key. As long as the signer of this writecap is the owner of
- // the path, then the writecap is valid.
- if writecap.signing_key.owner_of_kind(path.owner.kind()) == path.owner {
- return Ok(());
- }
- else {
- return Err(WritecapAuthzErr::RootDoesNotOwnPath)
- }
- }
- }
- }
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- use test_helpers::*;
- fn encrypt_decrypt_block_test_case<C: Creds>(
- mut actual: Block, principal: &Principal, creds: &C
- ) -> Result<()> {
- let expected = actual.clone();
- actual = encrypt_block(actual, principal, creds)?;
- let encrypted = match &actual.body {
- Cryptotext::Cipher(_) => true,
- Cryptotext::Plain(_) => false
- };
- assert!(encrypted);
- actual = decrypt_block(actual, principal, creds)?;
- assert_eq!(expected, actual);
- Ok(())
- }
- #[test]
- fn encrypt_decrypt_block_aes256cbc() -> Result<()> {
- let readcap = make_readcap();
- let principal = readcap.issued_to.clone();
- let block = make_block_with(readcap)?;
- let key = make_key_pair();
- encrypt_decrypt_block_test_case(block, &principal, &key)
- }
- #[test]
- fn encrypt_decrypt_block_aes256ctr() -> Result<()> {
- let readcap = make_readcap();
- let principal = readcap.issued_to.clone();
- let block = make_block_with(readcap)?;
- let key = make_key_pair();
- encrypt_decrypt_block_test_case(block, &principal, &key)
- }
- #[test]
- fn rsa_sign_and_verify() -> Result<()> {
- let key = make_key_pair();
- let header = b"About: lyrics".as_slice();
- let message = b"Everything that feels so good is bad bad bad.".as_slice();
- let signature = key.sign([header, message].into_iter())?;
- let verified = key.verify([header, message].into_iter(), signature.as_slice())?;
- assert_eq!(true, verified);
- Ok(())
- }
- #[test]
- fn sign_verify_block_rsa() -> Result<()> {
- let readcap = make_readcap();
- let principal = readcap.issued_to.clone();
- let mut block = make_block_with(readcap)?;
- let key = make_key_pair();
- let writecap = Writecap {
- issued_to: Principal(Hash::Sha2_256(PRINCIPAL)),
- path: make_path(vec!["contacts", "emergency"]),
- expires: Epoch(1649904316),
- signing_key: key.public().clone(),
- signature: Signature::Rsa(SIGNATURE),
- next: None,
- };
- block = encrypt_block(block, &principal, &key)?;
- sign_block(&mut block, writecap, &key)?;
- assert_eq!(true, verify_block(&block)?);
- Ok(())
- }
- #[test]
- fn hash_to_string() {
- let hash = make_principal().0;
- let string = hash.to_string();
- assert_eq!("Sha2_256:dSip4J0kurN5VhVo_aTipM-ywOOWrqJuRRVQ7aa-bew", string)
- }
- #[test]
- fn hash_to_string_round_trip() -> Result<()> {
- let expected = make_principal().0;
- let string = expected.to_string();
- let actual = Hash::try_from(string.as_str())?;
- assert_eq!(expected, actual);
- Ok(())
- }
- #[test]
- fn verify_writecap_valid() -> Result<()> {
- let writecap = make_writecap()?;
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Ok(()), result);
- Ok(())
- }
- #[test]
- fn verify_writecap_invalid_signature() -> Result<()> {
- let mut writecap = make_writecap()?;
- writecap.signature = Signature::default();
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Err(WritecapAuthzErr::InvalidSignature), result);
- Ok(())
- }
- #[test]
- fn verify_writecap_invalid_path_not_contained() -> Result<()> {
- let writecap = make_writecap()?;
- let mut path = writecap.path.clone();
- path.components.pop();
- // `path` is now a superpath of `writecap.path`, thus the writecap is not authorized to
- // write to it.
- let result = verify_writecap(&writecap, &path);
- assert_eq!(Err(WritecapAuthzErr::UnauthorizedPath), result);
- Ok(())
- }
- #[test]
- fn verify_writecap_invalid_expired() -> Result<()> {
- let mut writecap = make_writecap()?;
- writecap.expires = Epoch::now() - Duration::from_secs(1);
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Err(WritecapAuthzErr::Expired), result);
- Ok(())
- }
- #[test]
- fn verify_writecap_invalid_not_chained() -> Result<()> {
- let (mut root_writecap, root_key) = make_self_signed_writecap()?;
- root_writecap.issued_to = Principal(Hash::Sha2_256([0; 32]));
- sign_writecap(&mut root_writecap, &root_key)?;
- let node_key = AsymKeyPub::new(Sign::RSA_PSS_3072_SHA_256, NODE_PUBLIC_KEY.as_slice())?;
- let node_principal = node_key.owner();
- let writecap = make_writecap_trusted_by(
- root_writecap, root_key, node_principal, vec!["apps", "contacts"])?;
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Err(WritecapAuthzErr::NotChained), result);
- Ok(())
- }
- #[test]
- fn verify_writecap_invalid_root_doesnt_own_path() -> Result<()> {
- let (mut root_writecap, root_key) = make_self_signed_writecap()?;
- let owner = Principal(Hash::Sha2_256([0; 32]));
- root_writecap.path = make_path_with_owner(owner, vec![]);
- sign_writecap(&mut root_writecap, &root_key)?;
- let node_key = AsymKeyPub::new(Sign::RSA_PSS_3072_SHA_256, NODE_PUBLIC_KEY.as_slice())?;
- let node_owner = node_key.owner();
- let writecap = make_writecap_trusted_by(
- root_writecap, root_key, node_owner, vec!["apps", "contacts"])?;
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Err(WritecapAuthzErr::RootDoesNotOwnPath), result);
- Ok(())
- }
- /// Tests that validate the dependencies of this module.
- mod dependency_tests {
- use super::*;
- use openssl::{
- ec::{EcGroup, EcKey},
- nid::Nid,
- };
- /// This test validates that data encrypted with AES 256 CBC can later be decrypted.
- #[test]
- fn aes_256_cbc_roundtrip() {
- use super::*;
- let expected = b"We attack at the crack of noon!";
- let cipher = Cipher::aes_256_cbc();
- let ciphertext = openssl_encrypt(cipher, &KEY, Some(&IV), expected).unwrap();
- let actual = openssl_decrypt(cipher, &KEY, Some(&IV), ciphertext.as_slice()).unwrap();
- assert_eq!(expected, actual.as_slice());
- }
- /// Tests that the keys for the SECP256K1 curve are the expected sizes.
- #[test]
- fn secp256k1_key_lengths() {
- let group = EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
- let key = EcKey::generate(&group).unwrap();
- let public = key.public_key_to_der().unwrap();
- let private = key.private_key_to_der().unwrap();
- let public_len = public.len();
- let private_len = private.len();
- assert_eq!(88, public_len);
- assert_eq!(118, private_len);
- }
- #[test]
- fn ed25519_key_lengths() {
- let key = PKey::generate_x25519().unwrap();
- let public = key.public_key_to_der().unwrap();
- let private = key.private_key_to_der().unwrap();
- let public_len = public.len();
- let private_len = private.len();
- assert_eq!(44, public_len);
- assert_eq!(48, private_len);
- }
- #[test]
- fn rsa_signature_len() -> Result<()> {
- let key = make_key_pair();
- let signature = key.sign([NODE_PUBLIC_KEY.as_slice()].into_iter())?;
- let length = match signature {
- Signature::Rsa(data) => data.len(),
- };
- assert_eq!(RSA_KEY_BYTES, length);
- Ok(())
- }
- }
- }
|