use {
crate::asn1::rfc3281::AttributeCertificate,
bcder::{
decode::{Constructed, DecodeError, Source},
encode,
encode::{PrimitiveContent, Values},
BitString, Captured, ConstOid, Integer, Mode, OctetString, Oid, Tag,
},
std::{
fmt::{Debug, Formatter},
io::Write,
ops::{Deref, DerefMut},
},
x509_certificate::{asn1time::*, rfc3280::*, rfc5280::*, rfc5652::*},
};
pub const OID_ID_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 1]);
pub const OID_ID_SIGNED_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 2]);
pub const OID_ENVELOPE_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 3]);
pub const OID_DIGESTED_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 5]);
pub const OID_ENCRYPTED_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 6]);
pub const OID_AUTHENTICATED_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 16, 1, 2]);
pub const OID_CONTENT_TYPE: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 3]);
pub const OID_MESSAGE_DIGEST: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 4]);
pub const OID_SIGNING_TIME: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 5]);
pub const OID_COUNTER_SIGNATURE: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 6]);
#[derive(Clone, Debug)]
pub struct ContentInfo {
pub content_type: ContentType,
pub content: Captured,
}
impl PartialEq for ContentInfo {
fn eq(&self, other: &Self) -> bool {
self.content_type == other.content_type
&& self.content.as_slice() == other.content.as_slice()
}
}
impl Eq for ContentInfo {}
impl ContentInfo {
pub fn take_opt_from<S: Source>(
cons: &mut Constructed<S>,
) -> Result<Option<Self>, DecodeError<S::Error>> {
cons.take_opt_sequence(|cons| Self::from_sequence(cons))
}
pub fn from_sequence<S: Source>(
cons: &mut Constructed<S>,
) -> Result<Self, DecodeError<S::Error>> {
let content_type = ContentType::take_from(cons)?;
let content = cons.take_constructed_if(Tag::CTX_0, |cons| cons.capture_all())?;
Ok(Self {
content_type,
content,
})
}
}
impl Values for ContentInfo {
fn encoded_len(&self, mode: Mode) -> usize {
encode::sequence((self.content_type.encode_ref(), &self.content)).encoded_len(mode)
}
fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
encode::sequence((self.content_type.encode_ref(), &self.content))
.write_encoded(mode, target)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SignedData {
pub version: CmsVersion,
pub digest_algorithms: DigestAlgorithmIdentifiers,
pub content_info: EncapsulatedContentInfo,
pub certificates: Option<CertificateSet>,
pub crls: Option<RevocationInfoChoices>,
pub signer_infos: SignerInfos,
}
impl SignedData {
pub fn decode_ber(data: &[u8]) -> Result<Self, DecodeError<std::convert::Infallible>> {
Constructed::decode(data, bcder::Mode::Ber, Self::decode)
}
pub fn decode<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
cons.take_sequence(|cons| {
let oid = Oid::take_from(cons)?;
if oid != OID_ID_SIGNED_DATA {
return Err(cons.content_err("expected signed data OID"));
}
cons.take_constructed_if(Tag::CTX_0, Self::take_from)
})
}
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
cons.take_sequence(|cons| {
let version = CmsVersion::take_from(cons)?;
let digest_algorithms = DigestAlgorithmIdentifiers::take_from(cons)?;
let content_info = EncapsulatedContentInfo::take_from(cons)?;
let certificates =
cons.take_opt_constructed_if(Tag::CTX_0, |cons| CertificateSet::take_from(cons))?;
let crls = cons.take_opt_constructed_if(Tag::CTX_1, |cons| {
RevocationInfoChoices::take_from(cons)
})?;
let signer_infos = SignerInfos::take_from(cons)?;
Ok(Self {
version,
digest_algorithms,
content_info,
certificates,
crls,
signer_infos,
})
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((
OID_ID_SIGNED_DATA.encode_ref(),
encode::sequence_as(
Tag::CTX_0,
encode::sequence((
self.version.encode(),
self.digest_algorithms.encode_ref(),
self.content_info.encode_ref(),
self.certificates
.as_ref()
.map(|certs| certs.encode_ref_as(Tag::CTX_0)),
self.signer_infos.encode_ref(),
)),
),
))
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct DigestAlgorithmIdentifiers(Vec<DigestAlgorithmIdentifier>);
impl Deref for DigestAlgorithmIdentifiers {
type Target = Vec<DigestAlgorithmIdentifier>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for DigestAlgorithmIdentifiers {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl DigestAlgorithmIdentifiers {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
cons.take_set(|cons| {
let mut identifiers = Vec::new();
while let Some(identifier) = AlgorithmIdentifier::take_opt_from(cons)? {
identifiers.push(identifier);
}
Ok(Self(identifiers))
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::set(&self.0)
}
}
pub type DigestAlgorithmIdentifier = AlgorithmIdentifier;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct SignerInfos(Vec<SignerInfo>);
impl Deref for SignerInfos {
type Target = Vec<SignerInfo>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for SignerInfos {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl SignerInfos {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
cons.take_set(|cons| {
let mut infos = Vec::new();
while let Some(info) = SignerInfo::take_opt_from(cons)? {
infos.push(info);
}
Ok(Self(infos))
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::set(&self.0)
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct EncapsulatedContentInfo {
pub content_type: ContentType,
pub content: Option<OctetString>,
}
impl Debug for EncapsulatedContentInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut s = f.debug_struct("EncapsulatedContentInfo");
s.field("content_type", &format_args!("{}", self.content_type));
s.field(
"content",
&format_args!(
"{:?}",
self.content
.as_ref()
.map(|x| hex::encode(x.clone().to_bytes().as_ref()))
),
);
s.finish()
}
}
impl EncapsulatedContentInfo {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
cons.take_sequence(|cons| {
let content_type = ContentType::take_from(cons)?;
let content =
cons.take_opt_constructed_if(Tag::CTX_0, |cons| OctetString::take_from(cons))?;
Ok(Self {
content_type,
content,
})
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((
self.content_type.encode_ref(),
self.content
.as_ref()
.map(|content| encode::sequence_as(Tag::CTX_0, content.encode_ref())),
))
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct SignerInfo {
pub version: CmsVersion,
pub sid: SignerIdentifier,
pub digest_algorithm: DigestAlgorithmIdentifier,
pub signed_attributes: Option<SignedAttributes>,
pub signature_algorithm: SignatureAlgorithmIdentifier,
pub signature: SignatureValue,
pub unsigned_attributes: Option<UnsignedAttributes>,
pub signed_attributes_data: Option<Vec<u8>>,
}
impl SignerInfo {
pub fn take_opt_from<S: Source>(
cons: &mut Constructed<S>,
) -> Result<Option<Self>, DecodeError<S::Error>> {
cons.take_opt_sequence(|cons| Self::from_sequence(cons))
}
pub fn from_sequence<S: Source>(
cons: &mut Constructed<S>,
) -> Result<Self, DecodeError<S::Error>> {
let version = CmsVersion::take_from(cons)?;
let sid = SignerIdentifier::take_from(cons)?;
let digest_algorithm = DigestAlgorithmIdentifier::take_from(cons)?;
let signed_attributes = cons.take_opt_constructed_if(Tag::CTX_0, |cons| {
let der = cons.capture_all()?;
let der_data = der.as_slice().to_vec();
Ok((
Constructed::decode(der.as_slice(), bcder::Mode::Der, |cons| {
SignedAttributes::take_from_set(cons)
})
.map_err(|e| e.convert())?,
der_data,
))
})?;
let (signed_attributes, signed_attributes_data) = if let Some((x, y)) = signed_attributes {
(Some(x), Some(y))
} else {
(None, None)
};
let signature_algorithm = SignatureAlgorithmIdentifier::take_from(cons)?;
let signature = SignatureValue::take_from(cons)?;
let unsigned_attributes = cons
.take_opt_constructed_if(Tag::CTX_1, |cons| UnsignedAttributes::take_from_set(cons))?;
Ok(Self {
version,
sid,
digest_algorithm,
signed_attributes,
signature_algorithm,
signature,
unsigned_attributes,
signed_attributes_data,
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((
u8::from(self.version).encode(),
&self.sid,
&self.digest_algorithm,
self.signed_attributes
.as_ref()
.map(|attrs| SignedAttributesDer::new(attrs.clone(), Some(Tag::CTX_0))),
&self.signature_algorithm,
self.signature.encode_ref(),
self.unsigned_attributes
.as_ref()
.map(|attrs| attrs.encode_ref_as(Tag::CTX_1)),
))
}
pub fn signed_attributes_digested_content(&self) -> Result<Option<Vec<u8>>, std::io::Error> {
if let Some(signed_attributes) = &self.signed_attributes {
if let Some(existing_data) = &self.signed_attributes_data {
let mut buffer = Vec::with_capacity(existing_data.len() + 8);
buffer.write_all(&[0x31])?;
if existing_data.len() < 0x80 {
buffer.write_all(&[existing_data.len() as u8])?;
} else if existing_data.len() < 0x100 {
buffer.write_all(&[0x81, existing_data.len() as u8])?;
} else if existing_data.len() < 0x10000 {
buffer.write_all(&[
0x82,
(existing_data.len() >> 8) as u8,
existing_data.len() as u8,
])?;
} else if existing_data.len() < 0x1000000 {
buffer.write_all(&[
0x83,
(existing_data.len() >> 16) as u8,
(existing_data.len() >> 8) as u8,
existing_data.len() as u8,
])?;
} else {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"signed attributes length too long",
));
}
buffer.write_all(existing_data)?;
Ok(Some(buffer))
} else {
let signed_attributes = signed_attributes.as_sorted()?;
let mut der = Vec::new();
signed_attributes.write_encoded(Mode::Der, &mut der)?;
Ok(Some(der))
}
} else {
Ok(None)
}
}
}
impl Debug for SignerInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut s = f.debug_struct("SignerInfo");
s.field("version", &self.version);
s.field("sid", &self.sid);
s.field("digest_algorithm", &self.digest_algorithm);
s.field("signed_attributes", &self.signed_attributes);
s.field("signature_algorithm", &self.signature_algorithm);
s.field(
"signature",
&format_args!(
"{}",
hex::encode(self.signature.clone().into_bytes().as_ref())
),
);
s.field("unsigned_attributes", &self.unsigned_attributes);
s.field(
"signed_attributes_data",
&format_args!(
"{:?}",
self.signed_attributes_data.as_ref().map(hex::encode)
),
);
s.finish()
}
}
impl Values for SignerInfo {
fn encoded_len(&self, mode: Mode) -> usize {
self.encode_ref().encoded_len(mode)
}
fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
self.encode_ref().write_encoded(mode, target)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SignerIdentifier {
IssuerAndSerialNumber(IssuerAndSerialNumber),
SubjectKeyIdentifier(SubjectKeyIdentifier),
}
impl SignerIdentifier {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
if let Some(identifier) =
cons.take_opt_constructed_if(Tag::CTX_0, |cons| SubjectKeyIdentifier::take_from(cons))?
{
Ok(Self::SubjectKeyIdentifier(identifier))
} else {
Ok(Self::IssuerAndSerialNumber(
IssuerAndSerialNumber::take_from(cons)?,
))
}
}
}
impl Values for SignerIdentifier {
fn encoded_len(&self, mode: Mode) -> usize {
match self {
Self::IssuerAndSerialNumber(v) => v.encode_ref().encoded_len(mode),
Self::SubjectKeyIdentifier(v) => v.encode_ref_as(Tag::CTX_0).encoded_len(mode),
}
}
fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
match self {
Self::IssuerAndSerialNumber(v) => v.encode_ref().write_encoded(mode, target),
Self::SubjectKeyIdentifier(v) => {
v.encode_ref_as(Tag::CTX_0).write_encoded(mode, target)
}
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct SignedAttributes(Vec<Attribute>);
impl Deref for SignedAttributes {
type Target = Vec<Attribute>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for SignedAttributes {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl SignedAttributes {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
cons.take_set(|cons| Self::take_from_set(cons))
}
pub fn take_from_set<S: Source>(
cons: &mut Constructed<S>,
) -> Result<Self, DecodeError<S::Error>> {
let mut attributes = Vec::new();
while let Some(attribute) = Attribute::take_opt_from(cons)? {
attributes.push(attribute);
}
Ok(Self(attributes))
}
pub fn as_sorted(&self) -> Result<Self, std::io::Error> {
let mut attributes = self
.0
.iter()
.map(|x| {
let mut encoded = vec![];
x.encode_ref().write_encoded(Mode::Der, &mut encoded)?;
Ok((encoded, x.clone()))
})
.collect::<Result<Vec<(_, _)>, std::io::Error>>()?;
attributes.sort_by(|(a, _), (b, _)| a.cmp(b));
Ok(Self(
attributes.into_iter().map(|(_, x)| x).collect::<Vec<_>>(),
))
}
fn encode_ref(&self) -> impl Values + '_ {
encode::set(encode::slice(&self.0, |x| x.clone().encode()))
}
fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
encode::set_as(tag, encode::slice(&self.0, |x| x.clone().encode()))
}
}
impl Values for SignedAttributes {
fn encoded_len(&self, _: Mode) -> usize {
self.encode_ref().encoded_len(Mode::Der)
}
fn write_encoded<W: Write>(&self, _: Mode, target: &mut W) -> Result<(), std::io::Error> {
self.encode_ref().write_encoded(Mode::Der, target)
}
}
pub struct SignedAttributesDer(SignedAttributes, Option<Tag>);
impl SignedAttributesDer {
pub fn new(sa: SignedAttributes, tag: Option<Tag>) -> Self {
Self(sa, tag)
}
}
impl Values for SignedAttributesDer {
fn encoded_len(&self, _: Mode) -> usize {
if let Some(tag) = &self.1 {
self.0.encode_ref_as(*tag).encoded_len(Mode::Der)
} else {
self.0.encode_ref().encoded_len(Mode::Der)
}
}
fn write_encoded<W: Write>(&self, _: Mode, target: &mut W) -> Result<(), std::io::Error> {
if let Some(tag) = &self.1 {
self.0.encode_ref_as(*tag).write_encoded(Mode::Der, target)
} else {
self.0.encode_ref().write_encoded(Mode::Der, target)
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct UnsignedAttributes(Vec<Attribute>);
impl Deref for UnsignedAttributes {
type Target = Vec<Attribute>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for UnsignedAttributes {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl UnsignedAttributes {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
cons.take_set(|cons| Self::take_from_set(cons))
}
pub fn take_from_set<S: Source>(
cons: &mut Constructed<S>,
) -> Result<Self, DecodeError<S::Error>> {
let mut attributes = Vec::new();
while let Some(attribute) = Attribute::take_opt_from(cons)? {
attributes.push(attribute);
}
Ok(Self(attributes))
}
pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
encode::set_as(tag, encode::slice(&self.0, |x| x.clone().encode()))
}
}
pub type SignatureValue = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EnvelopedData {
pub version: CmsVersion,
pub originator_info: Option<OriginatorInfo>,
pub recipient_infos: RecipientInfos,
pub encrypted_content_info: EncryptedContentInfo,
pub unprotected_attributes: Option<UnprotectedAttributes>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OriginatorInfo {
pub certs: Option<CertificateSet>,
pub crls: Option<RevocationInfoChoices>,
}
pub type RecipientInfos = Vec<RecipientInfo>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EncryptedContentInfo {
pub content_type: ContentType,
pub content_encryption_algorithms: ContentEncryptionAlgorithmIdentifier,
pub encrypted_content: Option<EncryptedContent>,
}
pub type EncryptedContent = OctetString;
pub type UnprotectedAttributes = Vec<Attribute>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RecipientInfo {
KeyTransRecipientInfo(KeyTransRecipientInfo),
KeyAgreeRecipientInfo(KeyAgreeRecipientInfo),
KekRecipientInfo(KekRecipientInfo),
PasswordRecipientInfo(PasswordRecipientInfo),
OtherRecipientInfo(OtherRecipientInfo),
}
pub type EncryptedKey = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeyTransRecipientInfo {
pub version: CmsVersion,
pub rid: RecipientIdentifier,
pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
pub encrypted_key: EncryptedKey,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RecipientIdentifier {
IssuerAndSerialNumber(IssuerAndSerialNumber),
SubjectKeyIdentifier(SubjectKeyIdentifier),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeyAgreeRecipientInfo {
pub version: CmsVersion,
pub originator: OriginatorIdentifierOrKey,
pub ukm: Option<UserKeyingMaterial>,
pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
pub recipient_encrypted_keys: RecipientEncryptedKeys,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum OriginatorIdentifierOrKey {
IssuerAndSerialNumber(IssuerAndSerialNumber),
SubjectKeyIdentifier(SubjectKeyIdentifier),
OriginatorKey(OriginatorPublicKey),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OriginatorPublicKey {
pub algorithm: AlgorithmIdentifier,
pub public_key: BitString,
}
type RecipientEncryptedKeys = Vec<RecipientEncryptedKey>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RecipientEncryptedKey {
pub rid: KeyAgreeRecipientInfo,
pub encrypted_key: EncryptedKey,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum KeyAgreeRecipientIdentifier {
IssuerAndSerialNumber(IssuerAndSerialNumber),
RKeyId(RecipientKeyIdentifier),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RecipientKeyIdentifier {
pub subject_key_identifier: SubjectKeyIdentifier,
pub date: Option<GeneralizedTime>,
pub other: Option<OtherKeyAttribute>,
}
type SubjectKeyIdentifier = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KekRecipientInfo {
pub version: CmsVersion,
pub kek_id: KekIdentifier,
pub kek_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
pub encrypted_key: EncryptedKey,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KekIdentifier {
pub key_identifier: OctetString,
pub date: Option<GeneralizedTime>,
pub other: Option<OtherKeyAttribute>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PasswordRecipientInfo {
pub version: CmsVersion,
pub key_derivation_algorithm: Option<KeyDerivationAlgorithmIdentifier>,
pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
pub encrypted_key: EncryptedKey,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherRecipientInfo {
pub ori_type: Oid,
pub ori_value: Option<()>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DigestedData {
pub version: CmsVersion,
pub digest_algorithm: DigestAlgorithmIdentifier,
pub content_type: EncapsulatedContentInfo,
pub digest: Digest,
}
pub type Digest = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EncryptedData {
pub version: CmsVersion,
pub encrypted_content_info: EncryptedContentInfo,
pub unprotected_attributes: Option<UnprotectedAttributes>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AuthenticatedData {
pub version: CmsVersion,
pub originator_info: Option<OriginatorInfo>,
pub recipient_infos: RecipientInfos,
pub mac_algorithm: MessageAuthenticationCodeAlgorithm,
pub digest_algorithm: Option<DigestAlgorithmIdentifier>,
pub content_info: EncapsulatedContentInfo,
pub authenticated_attributes: Option<AuthAttributes>,
pub mac: MessageAuthenticationCode,
pub unauthenticated_attributes: Option<UnauthAttributes>,
}
pub type AuthAttributes = Vec<Attribute>;
pub type UnauthAttributes = Vec<Attribute>;
pub type MessageAuthenticationCode = OctetString;
pub type SignatureAlgorithmIdentifier = AlgorithmIdentifier;
pub type KeyEncryptionAlgorithmIdentifier = AlgorithmIdentifier;
pub type ContentEncryptionAlgorithmIdentifier = AlgorithmIdentifier;
pub type MessageAuthenticationCodeAlgorithm = AlgorithmIdentifier;
pub type KeyDerivationAlgorithmIdentifier = AlgorithmIdentifier;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RevocationInfoChoices(Vec<RevocationInfoChoice>);
impl RevocationInfoChoices {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
Err(cons.content_err("RevocationInfoChoices parsing not implemented"))
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RevocationInfoChoice {
Crl(Box<CertificateList>),
Other(OtherRevocationInfoFormat),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherRevocationInfoFormat {
pub other_rev_info_info_format: Oid,
pub other_rev_info: Option<()>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum CertificateChoices {
Certificate(Box<Certificate>),
AttributeCertificateV2(Box<AttributeCertificateV2>),
Other(Box<OtherCertificateFormat>),
}
impl CertificateChoices {
pub fn take_opt_from<S: Source>(
cons: &mut Constructed<S>,
) -> Result<Option<Self>, DecodeError<S::Error>> {
cons.take_opt_constructed_if(Tag::CTX_0, |cons| -> Result<(), DecodeError<S::Error>> {
Err(cons.content_err("ExtendedCertificate parsing not implemented"))
})?;
cons.take_opt_constructed_if(Tag::CTX_1, |cons| -> Result<(), DecodeError<S::Error>> {
Err(cons.content_err("AttributeCertificateV1 parsing not implemented"))
})?;
if let Some(certificate) = cons
.take_opt_constructed_if(Tag::CTX_2, |cons| AttributeCertificateV2::take_from(cons))?
{
Ok(Some(Self::AttributeCertificateV2(Box::new(certificate))))
} else if let Some(certificate) = cons
.take_opt_constructed_if(Tag::CTX_3, |cons| OtherCertificateFormat::take_from(cons))?
{
Ok(Some(Self::Other(Box::new(certificate))))
} else if let Some(certificate) =
cons.take_opt_constructed(|_, cons| Certificate::from_sequence(cons))?
{
Ok(Some(Self::Certificate(Box::new(certificate))))
} else {
Ok(None)
}
}
pub fn encode_ref(&self) -> impl Values + '_ {
match self {
Self::Certificate(cert) => cert.encode_ref(),
Self::AttributeCertificateV2(_) => unimplemented!(),
Self::Other(_) => unimplemented!(),
}
}
}
impl Values for CertificateChoices {
fn encoded_len(&self, mode: Mode) -> usize {
self.encode_ref().encoded_len(mode)
}
fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
self.encode_ref().write_encoded(mode, target)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherCertificateFormat {
pub other_cert_format: Oid,
pub other_cert: Option<()>,
}
impl OtherCertificateFormat {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
Err(cons.content_err("OtherCertificateFormat parsing not implemented"))
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct CertificateSet(Vec<CertificateChoices>);
impl Deref for CertificateSet {
type Target = Vec<CertificateChoices>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for CertificateSet {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl CertificateSet {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
let mut certs = Vec::new();
while let Some(cert) = CertificateChoices::take_opt_from(cons)? {
certs.push(cert);
}
Ok(Self(certs))
}
pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
encode::set_as(tag, &self.0)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct IssuerAndSerialNumber {
pub issuer: Name,
pub serial_number: CertificateSerialNumber,
}
impl IssuerAndSerialNumber {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
cons.take_sequence(|cons| {
let issuer = Name::take_from(cons)?;
let serial_number = Integer::take_from(cons)?;
Ok(Self {
issuer,
serial_number,
})
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((self.issuer.encode_ref(), (&self.serial_number).encode()))
}
}
pub type CertificateSerialNumber = Integer;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CmsVersion {
V0 = 0,
V1 = 1,
V2 = 2,
V3 = 3,
V4 = 4,
V5 = 5,
}
impl CmsVersion {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
match cons.take_primitive_if(Tag::INTEGER, Integer::i8_from_primitive)? {
0 => Ok(Self::V0),
1 => Ok(Self::V1),
2 => Ok(Self::V2),
3 => Ok(Self::V3),
4 => Ok(Self::V4),
5 => Ok(Self::V5),
_ => Err(cons.content_err("unexpected CMSVersion")),
}
}
pub fn encode(self) -> impl Values {
u8::from(self).encode()
}
}
impl From<CmsVersion> for u8 {
fn from(v: CmsVersion) -> u8 {
match v {
CmsVersion::V0 => 0,
CmsVersion::V1 => 1,
CmsVersion::V2 => 2,
CmsVersion::V3 => 3,
CmsVersion::V4 => 4,
CmsVersion::V5 => 5,
}
}
}
pub type UserKeyingMaterial = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherKeyAttribute {
pub key_attribute_id: Oid,
pub key_attribute: Option<()>,
}
pub type ContentType = Oid;
pub type MessageDigest = OctetString;
pub type SigningTime = Time;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Time {
UtcTime(UtcTime),
GeneralizedTime(GeneralizedTime),
}
impl Time {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
if let Some(utc) =
cons.take_opt_primitive_if(Tag::UTC_TIME, |prim| UtcTime::from_primitive(prim))?
{
Ok(Self::UtcTime(utc))
} else if let Some(generalized) = cons
.take_opt_primitive_if(Tag::GENERALIZED_TIME, |prim| {
GeneralizedTime::from_primitive_no_fractional_or_timezone_offsets(prim)
})?
{
Ok(Self::GeneralizedTime(generalized))
} else {
Err(cons.content_err("invalid Time value"))
}
}
}
impl From<Time> for chrono::DateTime<chrono::Utc> {
fn from(t: Time) -> Self {
match t {
Time::UtcTime(utc) => *utc,
Time::GeneralizedTime(gt) => gt.into(),
}
}
}
pub type CounterSignature = SignerInfo;
pub type AttributeCertificateV2 = AttributeCertificate;