pub use aead::*;
#[cfg(feature = "aes-gcm")]
pub use aes_gcm::{Aes128Gcm, Aes256Gcm, Key as Aes256GcmKey, Nonce as Aes256GcmNonce};
#[cfg(feature = "transport")]
pub use aes_kw;
use crate::asn1::ObjectIdentifier;
use crate::crypto::common::typenum::Unsigned;
use crate::der::oid::AssociatedOid;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, vec::Vec};
#[cfg(feature = "aes-gcm")]
mod oid_wrappers {
crate::define_oid_wrapper!(
Aes128GcmOid,
"2.16.840.1.101.3.4.1.6"
);
crate::define_oid_wrapper!(
Aes256GcmOid,
"2.16.840.1.101.3.4.1.46"
);
}
#[cfg(feature = "aes-gcm")]
pub use oid_wrappers::*;
trait AeadOps: Send + Sync {
fn encrypt_bytes(&self, nonce: &[u8], plaintext: &[u8]) -> core::result::Result<Vec<u8>, aead::Error>;
fn decrypt_bytes(&self, nonce: &[u8], ciphertext: &[u8]) -> core::result::Result<Vec<u8>, aead::Error>;
fn nonce_size(&self) -> usize;
}
impl<A> AeadOps for A
where
A: Aead + Send + Sync,
{
fn encrypt_bytes(&self, nonce: &[u8], plaintext: &[u8]) -> core::result::Result<Vec<u8>, aead::Error> {
self.encrypt(nonce.into(), plaintext)
}
fn decrypt_bytes(&self, nonce: &[u8], ciphertext: &[u8]) -> core::result::Result<Vec<u8>, aead::Error> {
self.decrypt(nonce.into(), ciphertext)
}
fn nonce_size(&self) -> usize {
<A as AeadCore>::NonceSize::USIZE
}
}
pub struct RuntimeAead {
cipher: Box<dyn AeadOps>,
oid: ObjectIdentifier,
}
impl RuntimeAead {
pub fn new<A>(cipher: A, oid: ObjectIdentifier) -> Self
where
A: Aead + Send + Sync + 'static,
{
Self { cipher: Box::new(cipher), oid }
}
pub fn algorithm_oid(&self) -> ObjectIdentifier {
self.oid
}
pub fn nonce_size(&self) -> usize {
self.cipher.nonce_size()
}
}
#[inline]
fn build_encrypted_content_info(
ciphertext: Vec<u8>,
nonce: &[u8],
content_type: Option<ObjectIdentifier>,
algorithm_oid: ObjectIdentifier,
) -> crate::error::Result<crate::EncryptedContentInfo> {
let content_type = content_type.unwrap_or(crate::oids::DATA);
let nonce_octet_string = crate::der::asn1::OctetString::new(nonce)?;
let parameters = Some(crate::der::Any::encode_from(&nonce_octet_string)?);
let content_enc_alg = crate::AlgorithmIdentifier { oid: algorithm_oid, parameters };
let encrypted_content = Some(crate::der::asn1::OctetString::new(ciphertext)?);
Ok(crate::EncryptedContentInfo { content_type, content_enc_alg, encrypted_content })
}
#[inline]
fn extract_nonce_and_ciphertext(info: &crate::EncryptedContentInfo) -> crate::error::Result<(Vec<u8>, &[u8])> {
let ciphertext = info
.encrypted_content
.as_ref()
.ok_or(crate::TightBeamError::MissingEncryptionInfo)?
.as_bytes();
let nonce_any = info
.content_enc_alg
.parameters
.as_ref()
.ok_or(crate::TightBeamError::MissingEncryptionInfo)?;
let nonce_octet_string: crate::der::asn1::OctetString = nonce_any.decode_as()?;
Ok((nonce_octet_string.into_bytes(), ciphertext))
}
pub trait Encryptor<C>
where
C: AssociatedOid,
{
fn encrypt_content(
&self,
data: impl AsRef<[u8]>,
nonce: impl AsRef<[u8]>,
content_type: Option<ObjectIdentifier>,
) -> crate::error::Result<crate::EncryptedContentInfo>;
}
pub trait Decryptor {
fn decrypt_content(&self, info: &crate::EncryptedContentInfo) -> crate::error::Result<Vec<u8>>;
}
impl<C, A> Encryptor<C> for A
where
C: AssociatedOid,
A: Aead,
{
fn encrypt_content(
&self,
data: impl AsRef<[u8]>,
nonce: impl AsRef<[u8]>,
content_type: Option<ObjectIdentifier>,
) -> crate::error::Result<crate::EncryptedContentInfo> {
let nonce_bytes = nonce.as_ref();
let ciphertext = self.encrypt(nonce_bytes.into(), data.as_ref())?;
build_encrypted_content_info(ciphertext, nonce_bytes, content_type, C::OID)
}
}
impl<A> Decryptor for A
where
A: Aead,
{
fn decrypt_content(&self, info: &crate::EncryptedContentInfo) -> crate::error::Result<Vec<u8>> {
let (nonce_bytes, ciphertext) = extract_nonce_and_ciphertext(info)?;
let plaintext = self.decrypt(nonce_bytes.as_slice().into(), ciphertext)?;
Ok(plaintext)
}
}
impl RuntimeAead {
pub fn encrypt_content(
&self,
data: impl AsRef<[u8]>,
nonce: impl AsRef<[u8]>,
content_type: Option<ObjectIdentifier>,
) -> crate::error::Result<crate::EncryptedContentInfo> {
let nonce_bytes = nonce.as_ref();
let ciphertext = self.cipher.encrypt_bytes(nonce_bytes, data.as_ref())?;
build_encrypted_content_info(ciphertext, nonce_bytes, content_type, self.oid)
}
}
impl Decryptor for RuntimeAead {
fn decrypt_content(&self, info: &crate::EncryptedContentInfo) -> crate::error::Result<Vec<u8>> {
let (nonce_bytes, ciphertext) = extract_nonce_and_ciphertext(info)?;
let plaintext = self.cipher.decrypt_bytes(&nonce_bytes, ciphertext)?;
Ok(plaintext)
}
}