use {
crate::asn1::{common::*, rfc3280::*, rfc3281::*, rfc5280::*},
bcder::{
decode::{Constructed, Malformed, Source, Unimplemented},
encode,
encode::{PrimitiveContent, Values},
BitString, Captured, ConstOid, Integer, Mode, OctetString, Oid, Tag,
},
std::{
io::Write,
ops::{Deref, DerefMut},
},
};
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>, S::Err> {
cons.take_opt_sequence(|cons| Self::from_sequence(cons))
}
pub fn from_sequence<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
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, bcder::decode::Error> {
Constructed::decode(data, bcder::Mode::Ber, |cons| Self::decode(cons))
}
pub fn decode<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
cons.take_sequence(|cons| {
let oid = Oid::take_from(cons)?;
if oid != OID_ID_SIGNED_DATA {
return Err(Malformed.into());
}
cons.take_constructed_if(Tag::CTX_0, Self::take_from)
})
}
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
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(),
if let Some(certs) = self.certificates.as_ref() {
Some(certs.encode_ref_as(Tag::CTX_0))
} else {
None
},
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, S::Err> {
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, S::Err> {
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, Debug, Eq, PartialEq)]
pub struct EncapsulatedContentInfo {
pub content_type: ContentType,
pub content: Option<OctetString>,
}
impl EncapsulatedContentInfo {
pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
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(),
if let Some(content) = self.content.as_ref() {
Some(encode::sequence_as(Tag::CTX_0, content.encode_ref()))
} else {
None
},
))
}
}
#[derive(Clone, Debug, 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>, S::Err> {
cons.take_opt_sequence(|cons| Self::from_sequence(cons))
}
pub fn from_sequence<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
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)
})?,
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.encode_ref(),
if let Some(attrs) = self.signed_attributes.as_ref() {
Some(attrs.encode_ref_as(Tag::CTX_0))
} else {
None
},
self.signature_algorithm.encode_ref(),
self.signature.encode_ref(),
if let Some(attrs) = self.unsigned_attributes.as_ref() {
Some(attrs.encode_ref_as(Tag::CTX_1))
} else {
None
},
))
}
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 mut der = Vec::new();
signed_attributes
.encode_ref()
.write_encoded(bcder::Mode::Der, &mut der)?;
Ok(Some(der))
}
} else {
Ok(None)
}
}
}
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, S::Err> {
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, S::Err> {
cons.take_set(|cons| Self::take_from_set(cons))
}
pub fn take_from_set<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
let mut attributes = Vec::new();
while let Some(attribute) = Attribute::take_opt_from(cons)? {
attributes.push(attribute);
}
Ok(Self(attributes))
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::set(encode::slice(&self.0, |x| x.clone().encode()))
}
pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
encode::set_as(tag, encode::slice(&self.0, |x| x.clone().encode()))
}
}
#[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, S::Err> {
cons.take_set(|cons| Self::take_from_set(cons))
}
pub fn take_from_set<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
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()))
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Attribute {
pub typ: Oid,
pub values: Vec<AttributeValue>,
}
impl Attribute {
pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> {
cons.take_opt_sequence(|cons| {
let typ = Oid::take_from(cons)?;
let values = cons.take_set(|cons| {
let mut values = Vec::new();
while let Some(value) = AttributeValue::take_opt_from(cons)? {
values.push(value);
}
Ok(values)
})?;
Ok(Self { typ, values })
})
}
pub fn encode_ref(&self) -> impl Values + '_ {
encode::sequence((self.typ.encode_ref(), encode::set(&self.values)))
}
pub fn encode(self) -> impl Values {
encode::sequence((self.typ.encode(), encode::set(self.values)))
}
}
#[derive(Clone, Debug)]
pub struct AttributeValue(Captured);
impl AttributeValue {
pub fn new(captured: Captured) -> Self {
Self(captured)
}
pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> {
let captured = cons.capture_all()?;
if captured.is_empty() {
Ok(None)
} else {
Ok(Some(Self(captured)))
}
}
}
impl Values for AttributeValue {
fn encoded_len(&self, mode: Mode) -> usize {
self.0.encoded_len(mode)
}
fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
self.0.write_encoded(mode, target)
}
}
impl Deref for AttributeValue {
type Target = Captured;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for AttributeValue {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl PartialEq for AttributeValue {
fn eq(&self, other: &Self) -> bool {
self.0.as_slice() == other.0.as_slice()
}
}
impl Eq for AttributeValue {}
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, S::Err> {
Err(Unimplemented.into())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RevocationInfoChoice {
Crl(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>, S::Err> {
cons.take_opt_constructed_if(Tag::CTX_0, |_cons| -> Result<(), S::Err> {
Err(Unimplemented.into())
})?;
cons.take_opt_constructed_if(Tag::CTX_1, |_cons| -> Result<(), S::Err> {
Err(Unimplemented.into())
})?;
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, S::Err> {
Err(Unimplemented.into())
}
}
#[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, S::Err> {
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, S::Err> {
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, S::Err> {
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(Malformed.into()),
}
}
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, S::Err> {
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(prim)
})?
{
Ok(Self::GeneralizedTime(generalized))
} else {
Err(Malformed.into())
}
}
}
impl From<Time> for chrono::DateTime<chrono::Utc> {
fn from(t: Time) -> Self {
match t {
Time::UtcTime(utc) => *utc,
Time::GeneralizedTime(gt) => *gt,
}
}
}
pub type CounterSignature = SignerInfo;
pub type AttributeCertificateV2 = AttributeCertificate;