use crate::error::AdesError;
const ID_AA_SIGNATURE_TIME_STAMP_TOKEN: &str = "1.2.840.113549.1.9.16.2.14";
const ID_AA_ETS_REVOCATION_VALUES: &str = "1.2.840.113549.1.9.16.2.24";
pub fn add_signature_timestamp(cms_der: &[u8], tst_der: &[u8]) -> Result<Vec<u8>, AdesError> {
use const_oid::ObjectIdentifier;
use der::asn1::SetOfVec;
use der::{Any, Decode};
use x509_cert::attr::Attribute;
let oid = ObjectIdentifier::new_unwrap(ID_AA_SIGNATURE_TIME_STAMP_TOKEN);
let attr = Attribute {
oid,
values: {
let mut set = SetOfVec::<Any>::new();
set.insert(Any::from_der(tst_der)?)?;
set
},
};
add_unsigned_attr_to_cms(cms_der, attr)
}
pub fn add_revocation_values(cms_der: &[u8], ocsp_resp_der: &[u8]) -> Result<Vec<u8>, AdesError> {
use const_oid::ObjectIdentifier;
use der::asn1::SetOfVec;
use der::{Any, Decode};
use x509_cert::attr::Attribute;
let basic_seq = der_tlv(0x30, ocsp_resp_der); let ocsp_values_inner = der_tlv(0x30, &basic_seq); let ocsp_values = der_ctx_tag(0xa1, &ocsp_values_inner); let rev_values_der = der_tlv(0x30, &ocsp_values);
let oid = ObjectIdentifier::new_unwrap(ID_AA_ETS_REVOCATION_VALUES);
let attr = Attribute {
oid,
values: {
let mut set = SetOfVec::<Any>::new();
set.insert(Any::from_der(&rev_values_der)?)?;
set
},
};
add_unsigned_attr_to_cms(cms_der, attr)
}
fn add_unsigned_attr_to_cms(
cms_der: &[u8],
attr: x509_cert::attr::Attribute,
) -> Result<Vec<u8>, AdesError> {
use cms::{
content_info::ContentInfo,
signed_data::{SignedData, SignerInfos},
};
use der::{Any, Decode, Encode};
let ci = ContentInfo::from_der(cms_der)?;
let sd_der = ci.content.to_der()?;
let mut sd = SignedData::from_der(&sd_der)?;
let si_der = sd
.signer_infos
.0
.as_ref()
.first()
.ok_or(AdesError::NotImplemented("CMS has no signer infos"))?
.to_der()?;
let mut si = cms::signed_data::SignerInfo::from_der(&si_der)?;
let mut unsigned = si.unsigned_attrs.take().unwrap_or_default();
unsigned.insert(attr)?;
si.unsigned_attrs = Some(unsigned);
let mut new_si_set = SignerInfos(Default::default());
new_si_set.0.insert(si)?;
sd.signer_infos = new_si_set;
let new_sd_der = sd.to_der()?;
let new_ci = ContentInfo {
content_type: ci.content_type,
content: Any::from_der(&new_sd_der)?,
};
Ok(new_ci.to_der()?)
}
fn der_tlv(tag: u8, value: &[u8]) -> Vec<u8> {
let len = value.len();
let mut out = vec![tag];
if len < 128 {
out.push(len as u8);
} else if len < 256 {
out.extend_from_slice(&[0x81, len as u8]);
} else if len < 65536 {
out.extend_from_slice(&[0x82, (len >> 8) as u8, (len & 0xff) as u8]);
} else {
out.extend_from_slice(&[
0x83,
(len >> 16) as u8,
(len >> 8) as u8,
(len & 0xff) as u8,
]);
}
out.extend_from_slice(value);
out
}
fn der_ctx_tag(tag: u8, value: &[u8]) -> Vec<u8> {
der_tlv(tag, value)
}