use super::utils::split_alg_id;
use super::{
BackendPrivateKey, BackendPublicKey, BlockCipherProvider, HmacProvider, Pbkdf2Provider,
SecureRandom,
};
use crate::pkcs12_types::{
Pbes2Params, Pbkdf2Params, ID_AES128_CBC, ID_AES192_CBC, ID_AES256_CBC, ID_HMAC_WITH_SHA1,
ID_HMAC_WITH_SHA256, ID_HMAC_WITH_SHA384, ID_HMAC_WITH_SHA512, ID_PBES2, ID_PBKDF2,
};
use synta::{Decoder, Encoding, TagClass};
#[derive(Debug)]
pub enum DefaultCryptoError {
Parse(synta::Error),
UnsupportedAlgorithm(String),
Backend(String),
}
impl std::fmt::Display for DefaultCryptoError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DefaultCryptoError::Parse(e) => write!(f, "ASN.1 error: {:?}", e),
DefaultCryptoError::UnsupportedAlgorithm(s) => {
write!(f, "unsupported algorithm: {}", s)
}
DefaultCryptoError::Backend(s) => write!(f, "crypto backend error: {}", s),
}
}
}
impl std::error::Error for DefaultCryptoError {}
impl From<synta::Error> for DefaultCryptoError {
fn from(e: synta::Error) -> Self {
DefaultCryptoError::Parse(e)
}
}
fn oid_to_aes_params(oid: &[u32]) -> Result<(usize, usize), DefaultCryptoError> {
if oid == ID_AES128_CBC {
Ok((16, 16))
} else if oid == ID_AES192_CBC {
Ok((24, 16))
} else if oid == ID_AES256_CBC {
Ok((32, 16))
} else {
Err(DefaultCryptoError::UnsupportedAlgorithm(format!(
"unsupported cipher OID: {:?}; expected id-aes{{128,192,256}}-cbc",
oid
)))
}
}
fn oid_to_hmac_alg(oid: &[u32]) -> Result<&'static str, DefaultCryptoError> {
if oid == ID_HMAC_WITH_SHA1 {
Ok("sha1")
} else if oid == ID_HMAC_WITH_SHA256 {
Ok("sha256")
} else if oid == ID_HMAC_WITH_SHA384 {
Ok("sha384")
} else if oid == ID_HMAC_WITH_SHA512 {
Ok("sha512")
} else {
Err(DefaultCryptoError::UnsupportedAlgorithm(format!(
"unsupported HMAC PRF OID: {:?}",
oid
)))
}
}
fn decode_octet_string_content(der: &[u8]) -> Result<&[u8], DefaultCryptoError> {
let mut dec = Decoder::new(der, Encoding::Der);
let tag = dec.read_tag()?;
if tag.class() != TagClass::Universal || tag.number() != 4 {
return Err(DefaultCryptoError::UnsupportedAlgorithm(
"expected OCTET STRING for cipher IV parameter".into(),
));
}
let len = dec.read_length()?.definite()?;
let pos = dec.position();
Ok(&der[pos..pos + len])
}
fn build_aes_cbc_alg_id(alg_oid: &[u32], iv: &[u8]) -> Result<Vec<u8>, DefaultCryptoError> {
use synta::{Element, ObjectIdentifier, OctetStringRef};
let oid = ObjectIdentifier::new(alg_oid).map_err(|_| {
DefaultCryptoError::UnsupportedAlgorithm(format!("invalid algorithm OID: {:?}", alg_oid))
})?;
crate::AlgorithmIdentifier {
algorithm: oid,
parameters: Some(Element::OctetString(OctetStringRef::new(iv))),
}
.to_der()
.map_err(DefaultCryptoError::from)
}
fn build_rsa_oaep_sha256_alg_id() -> Result<Vec<u8>, DefaultCryptoError> {
use crate::pkcs1_types::{RsaesOaepParams, ID_MGF1, ID_RSAES_OAEP};
use synta::{Element, ObjectIdentifier};
let sha256_alg_der = {
let oid = ObjectIdentifier::new(crate::ID_SHA256)
.map_err(|_| DefaultCryptoError::UnsupportedAlgorithm("invalid SHA-256 OID".into()))?;
crate::AlgorithmIdentifier {
algorithm: oid,
parameters: None,
}
.to_der()?
};
let mgf1_alg_der = {
let oid = ObjectIdentifier::new(ID_MGF1)
.map_err(|_| DefaultCryptoError::UnsupportedAlgorithm("invalid id-mgf1 OID".into()))?;
let sha256_elem: Element<'_> = Decoder::new(&sha256_alg_der, Encoding::Der).decode()?;
crate::AlgorithmIdentifier {
algorithm: oid,
parameters: Some(sha256_elem),
}
.to_der()?
};
let oaep_params_der = {
let hash_alg: crate::AlgorithmIdentifier<'_> =
Decoder::new(&sha256_alg_der, Encoding::Der).decode()?;
let mask_gen: crate::AlgorithmIdentifier<'_> =
Decoder::new(&mgf1_alg_der, Encoding::Der).decode()?;
RsaesOaepParams {
hash_algorithm: Some(hash_alg),
mask_gen_algorithm: Some(mask_gen),
p_source_algorithm: None,
}
.to_der()?
};
let oaep_oid = ObjectIdentifier::new(ID_RSAES_OAEP).map_err(|_| {
DefaultCryptoError::UnsupportedAlgorithm("invalid id-RSAES-OAEP OID".into())
})?;
let oaep_elem: Element<'_> = Decoder::new(&oaep_params_der, Encoding::Der).decode()?;
crate::AlgorithmIdentifier {
algorithm: oaep_oid,
parameters: Some(oaep_elem),
}
.to_der()
.map_err(DefaultCryptoError::from)
}
fn build_rsa_pkcs1v15_alg_id() -> Result<Vec<u8>, DefaultCryptoError> {
use synta::{Element, Null, ObjectIdentifier};
let oid = ObjectIdentifier::new(crate::RSA_ENCRYPTION).map_err(|_| {
DefaultCryptoError::UnsupportedAlgorithm("invalid rsaEncryption OID".into())
})?;
crate::AlgorithmIdentifier {
algorithm: oid,
parameters: Some(Element::Null(Null)),
}
.to_der()
.map_err(DefaultCryptoError::from)
}
pub struct DefaultCrypto;
impl crate::crypto::Pkcs12Decryptor for DefaultCrypto {
type Error = DefaultCryptoError;
fn decrypt(
&self,
algorithm_der: &[u8],
ciphertext: &[u8],
password: &[u8],
) -> Result<Vec<u8>, DefaultCryptoError> {
let (oid, _, _) = split_alg_id(algorithm_der, DefaultCryptoError::from)?;
if oid.components() != ID_PBES2 {
return Err(DefaultCryptoError::UnsupportedAlgorithm(format!(
"unsupported PKCS#12 encryption OID: {:?}; only id-PBES2 is supported",
oid.components()
)));
}
decrypt_pbes2(algorithm_der, ciphertext, password)
}
}
fn decrypt_pbes2(
algorithm_der: &[u8],
ciphertext: &[u8],
password: &[u8],
) -> Result<Vec<u8>, DefaultCryptoError> {
let (_oid, _, params_der) = split_alg_id(algorithm_der, DefaultCryptoError::from)?;
let mut pdec = Decoder::new(params_der, Encoding::Der);
let pbes2: Pbes2Params = pdec.decode()?;
let (kdf_oid, _, kdf_params_der) = split_alg_id(
pbes2.key_derivation_func.as_bytes(),
DefaultCryptoError::from,
)?;
if kdf_oid.components() != ID_PBKDF2 {
return Err(DefaultCryptoError::UnsupportedAlgorithm(format!(
"unsupported PBES2 KDF OID: {:?}; only id-PBKDF2 is supported",
kdf_oid.components()
)));
}
let mut kp_dec = Decoder::new(kdf_params_der, Encoding::Der);
let kdf_params: Pbkdf2Params = kp_dec.decode()?;
let prf_alg = if let Some(prf_raw) = &kdf_params.prf {
let (prf_oid, _, _) = split_alg_id(prf_raw.as_bytes(), DefaultCryptoError::from)?;
oid_to_hmac_alg(prf_oid.components())?
} else {
"sha1"
};
let (enc_oid, _, enc_params_der) =
split_alg_id(pbes2.encryption_scheme.as_bytes(), DefaultCryptoError::from)?;
let (key_len, _) = oid_to_aes_params(enc_oid.components())?;
let iv = decode_octet_string_content(enc_params_der)?;
let salt = kdf_params.salt.as_bytes();
let iter = kdf_params.iteration_count.as_u64().map_err(|_| {
DefaultCryptoError::UnsupportedAlgorithm(
"PBKDF2 iteration count is out of u64 range".into(),
)
})? as usize;
let key = crate::default_pbkdf2_provider()
.pbkdf2_hmac(prf_alg, password, salt, iter, key_len)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
crate::default_block_cipher_provider()
.aes_cbc_decrypt(&key, iv, ciphertext, true)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))
}
impl crate::crypto::CmsDecryptor for DefaultCrypto {
type Error = DefaultCryptoError;
fn decrypt(
&self,
algorithm_der: &[u8],
ciphertext: &[u8],
key: &[u8],
) -> Result<Vec<u8>, DefaultCryptoError> {
let (oid, _, params_der) = split_alg_id(algorithm_der, DefaultCryptoError::from)?;
let (expected_key_len, _) = oid_to_aes_params(oid.components())?;
if key.len() != expected_key_len {
return Err(DefaultCryptoError::UnsupportedAlgorithm(format!(
"key length mismatch: expected {} bytes for {:?}, got {}",
expected_key_len,
oid.components(),
key.len()
)));
}
let iv = decode_octet_string_content(params_der)?;
crate::default_block_cipher_provider()
.aes_cbc_decrypt(key, iv, ciphertext, true)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))
}
}
impl crate::crypto::Encryptor for DefaultCrypto {
type Error = DefaultCryptoError;
fn encrypt(
&self,
alg_oid: &[u32],
plaintext: &[u8],
key: &[u8],
) -> Result<(Vec<u8>, Vec<u8>), DefaultCryptoError> {
let (expected_key_len, iv_len) = oid_to_aes_params(alg_oid)?;
if key.len() != expected_key_len {
return Err(DefaultCryptoError::UnsupportedAlgorithm(format!(
"key length mismatch: expected {} bytes for {:?}, got {}",
expected_key_len,
alg_oid,
key.len()
)));
}
let mut iv = vec![0u8; iv_len];
crate::default_secure_random()
.rand_bytes(&mut iv)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
let ciphertext = crate::default_block_cipher_provider()
.aes_cbc_encrypt(key, &iv, plaintext, true)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
let alg_id_der = build_aes_cbc_alg_id(alg_oid, &iv)?;
Ok((alg_id_der, ciphertext))
}
}
impl crate::crypto::CmsEncryptor for DefaultCrypto {
fn create_encrypted_data(
&self,
content_type_oid: &[u32],
enc_alg_oid: &[u32],
plaintext: &[u8],
key: &[u8],
) -> Result<Vec<u8>, DefaultCryptoError> {
use crate::cms_rfc5652_types::{EncryptedContentInfo, EncryptedData};
use crate::crypto::Encryptor as _;
use synta::{Integer, ObjectIdentifier, OctetStringRef};
let (enc_alg_id_der, ciphertext) = self.encrypt(enc_alg_oid, plaintext, key)?;
let content_type = ObjectIdentifier::new(content_type_oid).map_err(|_| {
DefaultCryptoError::UnsupportedAlgorithm(format!(
"invalid content-type OID: {:?}",
content_type_oid
))
})?;
let content_encryption_algorithm: crate::AlgorithmIdentifier<'_> =
Decoder::new(&enc_alg_id_der, Encoding::Der).decode()?;
let ed = EncryptedData {
version: Integer::from_i64(0),
encrypted_content_info: EncryptedContentInfo {
content_type,
content_encryption_algorithm,
encrypted_content: Some(OctetStringRef::new(&ciphertext)),
},
unprotected_attrs: None,
};
ed.to_der().map_err(DefaultCryptoError::from)
}
}
fn build_pbes2_alg_id_der(
kdf_salt: &[u8],
iv: &[u8],
iterations: u32,
key_len: u32,
cipher_oid: &[u32],
prf_oid: &[u32],
) -> Result<Vec<u8>, DefaultCryptoError> {
use crate::pkcs12_types::{Pbes2Params, Pbkdf2Params, ID_PBES2, ID_PBKDF2};
use synta::traits::Decode;
use synta::{Element, Null, ObjectIdentifier, OctetStringRef, RawDer};
let prf_alg_der = {
let oid = ObjectIdentifier::new(prf_oid).map_err(|_| {
DefaultCryptoError::UnsupportedAlgorithm("invalid PRF OID components".into())
})?;
crate::AlgorithmIdentifier {
algorithm: oid,
parameters: Some(Element::Null(Null)),
}
.to_der()?
};
let pbkdf2_params_der = Pbkdf2Params {
salt: OctetStringRef::new(kdf_salt),
iteration_count: synta::Integer::from(iterations),
key_length: Some(synta::Integer::from(key_len)),
prf: Some(RawDer(&prf_alg_der)),
}
.to_der()?;
let kdf_alg_der = {
let oid = ObjectIdentifier::new(ID_PBKDF2).map_err(|_| {
DefaultCryptoError::UnsupportedAlgorithm("invalid id-PBKDF2 OID".into())
})?;
let mut dec = Decoder::new(&pbkdf2_params_der, Encoding::Der);
let params_elem: Element<'_> = Element::decode(&mut dec)?;
crate::AlgorithmIdentifier {
algorithm: oid,
parameters: Some(params_elem),
}
.to_der()?
};
let enc_alg_der = build_aes_cbc_alg_id(cipher_oid, iv)?;
let pbes2_params_der = Pbes2Params {
key_derivation_func: RawDer(&kdf_alg_der),
encryption_scheme: RawDer(&enc_alg_der),
}
.to_der()?;
let oid = ObjectIdentifier::new(ID_PBES2)
.map_err(|_| DefaultCryptoError::UnsupportedAlgorithm("invalid id-PBES2 OID".into()))?;
let mut dec = Decoder::new(&pbes2_params_der, Encoding::Der);
let params_elem: Element<'_> = Element::decode(&mut dec)?;
crate::AlgorithmIdentifier {
algorithm: oid,
parameters: Some(params_elem),
}
.to_der()
.map_err(DefaultCryptoError::from)
}
impl crate::crypto::Pkcs12Encryptor for DefaultCrypto {
type Error = DefaultCryptoError;
fn encrypt(
&self,
plaintext: &[u8],
password: &[u8],
) -> Result<(Vec<u8>, Vec<u8>), DefaultCryptoError> {
const ITER: u32 = 600_000;
const KEY_LEN: usize = 32; const IV_LEN: usize = 16;
let mut kdf_salt = vec![0u8; 16];
let mut iv = vec![0u8; IV_LEN];
crate::default_secure_random()
.rand_bytes(&mut kdf_salt)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
crate::default_secure_random()
.rand_bytes(&mut iv)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
let key = crate::default_pbkdf2_provider()
.pbkdf2_hmac("sha256", password, &kdf_salt, ITER as usize, KEY_LEN)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
let ciphertext = crate::default_block_cipher_provider()
.aes_cbc_encrypt(&key, &iv, plaintext, true)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
let alg_id_der = build_pbes2_alg_id_der(
&kdf_salt,
&iv,
ITER,
KEY_LEN as u32,
ID_AES256_CBC,
ID_HMAC_WITH_SHA256,
)?;
Ok((alg_id_der, ciphertext))
}
fn compute_mac(
&self,
auth_safe_content: &[u8],
password: &[u8],
) -> Result<Vec<u8>, DefaultCryptoError> {
use crate::pkcs12_types::{MacData, MacDigestInfo};
use synta::{Element, Null, ObjectIdentifier, OctetStringRef};
const MAC_ITER: u32 = 600_000;
const MAC_KEY_LEN: usize = 32;
let mut mac_salt = [0u8; 8];
crate::default_secure_random()
.rand_bytes(&mut mac_salt)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
let mac_key = crate::default_pbkdf2_provider()
.pbkdf2_hmac(
"sha256",
password,
&mac_salt,
MAC_ITER as usize,
MAC_KEY_LEN,
)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
let hmac_bytes = crate::default_hmac_provider()
.hmac_compute("sha256", &mac_key, auth_safe_content)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
let hmac_oid = ObjectIdentifier::new(ID_HMAC_WITH_SHA256).map_err(|_| {
DefaultCryptoError::UnsupportedAlgorithm(
"invalid id-hmacWithSHA256 OID components".into(),
)
})?;
let dig_alg = crate::AlgorithmIdentifier {
algorithm: hmac_oid,
parameters: Some(Element::Null(Null)),
};
let mac_digest_info = MacDigestInfo {
digest_algorithm: dig_alg,
digest: OctetStringRef::new(&hmac_bytes),
};
let mac_data = MacData {
mac: mac_digest_info,
mac_salt: OctetStringRef::new(&mac_salt),
iterations: synta::Integer::from(MAC_ITER),
};
mac_data.to_der().map_err(DefaultCryptoError::from)
}
}
pub struct DefaultEnvelopedDataDecryptor {
pkcs8_der: Vec<u8>,
}
impl DefaultEnvelopedDataDecryptor {
pub fn new(pkcs8_der: &[u8]) -> Result<Self, DefaultCryptoError> {
if pkcs8_der.is_empty() {
return Err(DefaultCryptoError::UnsupportedAlgorithm(
"empty PKCS#8 DER".into(),
));
}
let key_type = super::utils::key_type_from_pkcs8(pkcs8_der);
if key_type != "rsa" {
return Err(DefaultCryptoError::UnsupportedAlgorithm(format!(
"EnvelopedData decryption requires an RSA private key, got '{}'",
key_type
)));
}
Ok(Self {
pkcs8_der: pkcs8_der.to_vec(),
})
}
}
impl crate::crypto::EnvelopedDataDecryptor for DefaultEnvelopedDataDecryptor {
type Error = DefaultCryptoError;
fn decrypt_enveloped(
&self,
ed: &crate::cms_rfc5652_types::EnvelopedData<'_>,
) -> Result<Vec<u8>, DefaultCryptoError> {
use crate::cms_rfc5652_types::KeyTransRecipientInfo;
use crate::crypto::CmsDecryptor as _;
use synta::tag::{TAG_SEQUENCE, TAG_SET};
use synta::{Tag, TagClass};
let priv_key = BackendPrivateKey::from_pkcs8_der_unchecked(self.pkcs8_der.clone());
let ri_raw = ed.recipient_infos.as_bytes();
let set_tag = Tag::universal_constructed(TAG_SET);
let mut outer = Decoder::new(ri_raw, Encoding::Ber);
let mut inner = outer.enter_constructed(set_tag)?;
let mut cek: Option<Vec<u8>> = None;
while !inner.is_empty() {
let before = inner.remaining();
let elem_tag = inner.peek_tag()?;
inner.read_tag()?;
let elem_len = inner.read_length()?.definite()?;
inner.read_bytes(elem_len)?;
let after = inner.remaining();
let elem_tlv = &before[..before.len() - after.len()];
if elem_tag.class() != TagClass::Universal
|| elem_tag.number() != TAG_SEQUENCE
|| !elem_tag.is_constructed()
{
continue;
}
let ktri: KeyTransRecipientInfo<'_> =
match Decoder::new(elem_tlv, Encoding::Ber).decode() {
Ok(k) => k,
Err(_) => continue,
};
let alg_oid = ktri.key_encryption_algorithm.algorithm.components();
let enc_key_bytes = ktri.encrypted_key.as_bytes();
let decrypted = if alg_oid == crate::oids::RSAES_OAEP {
priv_key.rsa_oaep_decrypt(enc_key_bytes, "sha256")
} else if alg_oid == crate::RSA_ENCRYPTION {
priv_key.rsa_pkcs1v15_decrypt(enc_key_bytes)
} else {
continue;
};
if let Ok(unwrapped) = decrypted {
cek = Some(unwrapped);
break;
}
}
let cek = cek.ok_or_else(|| {
DefaultCryptoError::UnsupportedAlgorithm(
"no KeyTransRecipientInfo could be decrypted with the given private key"
.to_string(),
)
})?;
let alg_der = ed
.encrypted_content_info
.content_encryption_algorithm
.to_der()?;
let ciphertext = ed
.encrypted_content_info
.encrypted_content
.as_ref()
.ok_or_else(|| {
DefaultCryptoError::UnsupportedAlgorithm(
"EnvelopedData has no encryptedContent field".into(),
)
})?
.as_bytes();
DefaultCrypto.decrypt(&alg_der, ciphertext, &cek)
}
}
fn default_build_ktri(
cert_der: &[u8],
key_wrap: crate::crypto::KeyWrapAlgorithm,
cek: &[u8],
) -> Result<Vec<u8>, DefaultCryptoError> {
use crate::cms_2010_types::IssuerAndSerialNumber;
use crate::cms_rfc5652_types::KeyTransRecipientInfo;
use synta::{Integer, OctetStringRef, RawDer};
let synta_cert: crate::Certificate<'_> = Decoder::new(cert_der, Encoding::Der).decode()?;
let cert_ranges = crate::cert_byte_ranges(cert_der).ok_or_else(|| {
DefaultCryptoError::UnsupportedAlgorithm(
"failed to locate SubjectPublicKeyInfo in certificate DER".into(),
)
})?;
let spki_der = cert_der[cert_ranges.subject_public_key_info].to_vec();
let serial_number: Integer = synta_cert.tbs_certificate.serial_number;
let issuer: crate::Name<'_> =
Decoder::new(synta_cert.tbs_certificate.issuer.as_bytes(), Encoding::Der).decode()?;
let pub_key = BackendPublicKey::from_spki_der(spki_der);
let (encrypted_cek, key_enc_alg_der) = match key_wrap {
crate::crypto::KeyWrapAlgorithm::RsaOaepSha256 => {
let ct = pub_key
.rsa_oaep_encrypt(cek, "sha256")
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
(ct, build_rsa_oaep_sha256_alg_id()?)
}
crate::crypto::KeyWrapAlgorithm::RsaPkcs1v15 => {
let ct = pub_key
.rsa_pkcs1v15_encrypt(cek)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
(ct, build_rsa_pkcs1v15_alg_id()?)
}
};
let isn_der = IssuerAndSerialNumber {
issuer,
serial_number,
}
.to_der()?;
let key_encryption_algorithm: crate::AlgorithmIdentifier<'_> =
Decoder::new(&key_enc_alg_der, Encoding::Der).decode()?;
KeyTransRecipientInfo {
version: Integer::from_i64(0),
rid: RawDer(&isn_der),
key_encryption_algorithm,
encrypted_key: OctetStringRef::new(&encrypted_cek),
}
.to_der()
.map_err(DefaultCryptoError::from)
}
pub fn default_prepare_enveloped_data(
plaintext: &[u8],
recipients: &[(&[u8], crate::crypto::KeyWrapAlgorithm)],
content_enc_alg_oid: &[u32],
) -> Result<crate::EnvelopedDataBuilder, DefaultCryptoError> {
use crate::crypto::Encryptor as _;
if recipients.is_empty() {
return Err(DefaultCryptoError::UnsupportedAlgorithm(
"EnvelopedData requires at least one recipient".into(),
));
}
let (cek_len, _) = oid_to_aes_params(content_enc_alg_oid)?;
let mut cek = vec![0u8; cek_len];
crate::default_secure_random()
.rand_bytes(&mut cek)
.map_err(|e| DefaultCryptoError::Backend(e.to_string()))?;
let (enc_alg_id_der, ciphertext) =
DefaultCrypto.encrypt(content_enc_alg_oid, plaintext, &cek)?;
let ktri_ders: Result<Vec<Vec<u8>>, DefaultCryptoError> = recipients
.iter()
.map(|(cert_der, key_wrap)| default_build_ktri(cert_der, *key_wrap, &cek))
.collect();
let ktri_ders = ktri_ders?;
for b in cek.iter_mut() {
unsafe { std::ptr::write_volatile(b, 0) };
}
let mut builder = crate::EnvelopedDataBuilder::new(enc_alg_id_der, ciphertext);
for ktri_der in ktri_ders {
builder = builder.add_recipient_info(ktri_der);
}
Ok(builder)
}
pub fn default_create_enveloped_data(
plaintext: &[u8],
recipients: &[(&[u8], crate::crypto::KeyWrapAlgorithm)],
content_enc_alg_oid: &[u32],
) -> Result<Vec<u8>, DefaultCryptoError> {
use crate::enveloped_data_builder::EnvelopedDataBuilderError;
default_prepare_enveloped_data(plaintext, recipients, content_enc_alg_oid)?
.build()
.map_err(|e| match e {
EnvelopedDataBuilderError::Encode(se) => DefaultCryptoError::Parse(se),
EnvelopedDataBuilderError::InvalidOid(s) => {
DefaultCryptoError::UnsupportedAlgorithm(format!("invalid OID: {s}"))
}
EnvelopedDataBuilderError::NoRecipients => DefaultCryptoError::UnsupportedAlgorithm(
"EnvelopedData requires at least one recipient".into(),
),
})
}