use crate::cert::{CertificateChoices, IssuerAndSerialNumber};
use crate::content_info::CmsVersion;
use crate::revocation::RevocationInfoChoices;
use alloc::vec;
use core::cmp::Ordering;
use der::asn1::{ObjectIdentifier, OctetString, SetOfVec};
use der::{Any, Choice, DerOrd, Sequence, ValueOrd};
use spki::AlgorithmIdentifierOwned;
use x509_cert::{
attr::Attributes, certificate::Certificate, ext::pkix::SubjectKeyIdentifier, impl_newtype,
};
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
pub struct SignedData {
pub version: CmsVersion,
pub digest_algorithms: DigestAlgorithmIdentifiers,
pub encap_content_info: EncapsulatedContentInfo,
#[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")]
pub certificates: Option<CertificateSet>,
#[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")]
pub crls: Option<RevocationInfoChoices>,
pub signer_infos: SignerInfos,
}
pub type DigestAlgorithmIdentifiers = SetOfVec<AlgorithmIdentifierOwned>;
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct CertificateSet(pub SetOfVec<CertificateChoices>);
impl_newtype!(CertificateSet, SetOfVec<CertificateChoices>);
impl TryFrom<vec::Vec<CertificateChoices>> for CertificateSet {
type Error = der::Error;
fn try_from(vec: vec::Vec<CertificateChoices>) -> der::Result<CertificateSet> {
Ok(CertificateSet(SetOfVec::try_from(vec)?))
}
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct SignerInfos(pub SetOfVec<SignerInfo>);
impl_newtype!(SignerInfos, SetOfVec<SignerInfo>);
impl TryFrom<vec::Vec<SignerInfo>> for SignerInfos {
type Error = der::Error;
fn try_from(vec: vec::Vec<SignerInfo>) -> der::Result<SignerInfos> {
Ok(SignerInfos(SetOfVec::try_from(vec)?))
}
}
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
pub struct EncapsulatedContentInfo {
pub econtent_type: ObjectIdentifier,
#[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")]
pub econtent: Option<Any>,
}
#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
pub struct SignerInfo {
pub version: CmsVersion,
pub sid: SignerIdentifier,
pub digest_alg: AlgorithmIdentifierOwned,
#[asn1(
context_specific = "0",
tag_mode = "IMPLICIT",
constructed = "true",
optional = "true"
)]
pub signed_attrs: Option<SignedAttributes>,
pub signature_algorithm: AlgorithmIdentifierOwned,
pub signature: SignatureValue,
#[asn1(
context_specific = "1",
tag_mode = "IMPLICIT",
constructed = "true",
optional = "true"
)]
pub unsigned_attrs: Option<UnsignedAttributes>,
}
pub type SignedAttributes = Attributes;
#[derive(Clone, Debug, Eq, PartialEq, Choice)]
#[allow(missing_docs)]
pub enum SignerIdentifier {
IssuerAndSerialNumber(IssuerAndSerialNumber),
#[asn1(context_specific = "0", tag_mode = "IMPLICIT")]
SubjectKeyIdentifier(SubjectKeyIdentifier),
}
impl ValueOrd for SignerIdentifier {
fn value_cmp(&self, other: &Self) -> der::Result<Ordering> {
use der::Encode;
self.to_der()?.der_cmp(&other.to_der()?)
}
}
impl From<&Certificate> for SignerIdentifier {
fn from(cert: &Certificate) -> Self {
let tbs = cert.tbs_certificate();
match tbs.get_extension::<SubjectKeyIdentifier>() {
Ok(Some((_critical, ski))) => Self::SubjectKeyIdentifier(ski),
_ => {
let isn = IssuerAndSerialNumber {
issuer: tbs.issuer().clone(),
serial_number: tbs.serial_number().clone(),
};
Self::IssuerAndSerialNumber(isn)
}
}
}
}
pub type UnsignedAttributes = Attributes;
pub type SignatureValue = OctetString;