c2pa-rs

A fork of https://github.com/contentauth/c2pa-rs/
git clone git://archive.git.mtrnord.blog/mtrnords-photography-manager/c2pa-rs.git
Log | Files | Refs | README

commit 603902851ba8b8f74d02c1b76250b6d440193eda
parent 070ca2fc1a8cfbf0a7ec9193ed4511a778ae4b98
Author: Eric Scouten <scouten@adobe.com>
Date:   Wed,  5 Apr 2023 11:13:47 -0400

(MINOR) Update several X509-related crate dependencies (#225)

* Update x509-certificate to 0.19.0 in /sdk
* Update bcder from 0.6.0 to 0.71 in /sdk (required by the x509-cert upgrade)
* Update asn1 code which had been copied from cryptographic-message-syntax crate (helps with upgrade to bcder dependency)

NOTE: MSRV is increased to 1.65.0 by this PR, thus the (MINOR) tag.
Diffstat:
M.github/workflows/ci.yml | 2+-
MREADME.md | 2+-
Mmake_test_images/Cargo.toml | 2+-
Msdk/Cargo.toml | 6+++---
Msdk/src/asn1/mod.rs | 8+++++++-
Msdk/src/asn1/rfc3161.rs | 42++++++++++++++++++++++++------------------
Msdk/src/asn1/rfc3281.rs | 8++++----
Msdk/src/asn1/rfc4210.rs | 12++++++++----
Msdk/src/asn1/rfc5652.rs | 106+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
9 files changed, 117 insertions(+), 71 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: fail-fast: false matrix: os: [windows-latest, macos-latest, ubuntu-latest] - rust_version: [1.63.0, stable] + rust_version: [1.65.0, stable] steps: - name: Checkout repository diff --git a/README.md b/README.md @@ -25,7 +25,7 @@ We welcome contributions to this project. For information on contributing, prov ## Requirements -The SDK requires **Rust version 1.63.0** or newer. +The SDK requires **Rust version 1.65.0** or newer. ### Supported platforms diff --git a/make_test_images/Cargo.toml b/make_test_images/Cargo.toml @@ -4,7 +4,7 @@ version = "0.19.1" authors = ["Gavin Peacock <gpeacock@adobe.com>"] license = "MIT OR Apache-2.0" edition = "2018" -rust-version = "1.63.0" +rust-version = "1.65.0" [dependencies] anyhow = "1.0" diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml @@ -11,7 +11,7 @@ readme = "../README.md" keywords = ["xmp", "metadata"] categories = ["api-bindings"] edition = "2018" -rust-version = "1.63.0" +rust-version = "1.65.0" exclude = ["tests/fixtures"] [package.metadata.docs.rs] @@ -51,7 +51,7 @@ crate-type = ["lib"] async-trait = { version = "0.1.48"} atree = "0.5.2" base64 = "0.13.0" -bcder = "0.6.0" +bcder = "0.7.1" blake3 = "1.0.0" bytes = "1.1.0" byteorder = { version = "1.4.3", default-features = false } @@ -86,7 +86,7 @@ twoway = "0.2.1" url = "2.2.2" uuid = { version = "0.8.1", features = ["serde", "v4", "wasm-bindgen"] } x509-parser = "0.11.0" -x509-certificate = "0.12.0" +x509-certificate = "0.19.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] ureq = "2.4.0" diff --git a/sdk/src/asn1/mod.rs b/sdk/src/asn1/mod.rs @@ -4,7 +4,13 @@ /*! Holds Rust struct definitions for various ASN.1 primitives. */ -// https://github.com/indygreg/PyOxidizer/tree/main/cryptographic-message-syntax/src/asn1 +// This code is copied from a subset of version 0.22.0 of the +// cryptographic-message-syntax crate located at: +// https://github.com/indygreg/cryptography-rs/tree/main/cryptographic-message-syntax/src/asn1 + +// We can not incorporate the entire crate directly because other parts of the +// crate contain dependencies on blocking calls in reqwest. Those calls are not +// available in WASM environment. pub mod rfc3161; pub mod rfc3281; diff --git a/sdk/src/asn1/rfc3161.rs b/sdk/src/asn1/rfc3161.rs @@ -5,7 +5,7 @@ //! ASN.1 types defined by RFC 3161. use bcder::{ - decode::{Constructed, Malformed, Primitive, Source}, + decode::{Constructed, DecodeError, Primitive, Source}, encode::{self, PrimitiveContent, Values}, ConstOid, Integer, OctetString, Oid, Tag, }; @@ -51,7 +51,7 @@ pub struct TimeStampReq { } impl TimeStampReq { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_sequence(|cons| { let version = Integer::take_from(cons)?; let message_imprint = MessageImprint::take_from(cons)?; @@ -103,7 +103,7 @@ pub struct MessageImprint { } impl MessageImprint { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_sequence(|cons| { let hash_algorithm = AlgorithmIdentifier::take_from(cons)?; let hashed_message = OctetString::take_from(cons)?; @@ -136,7 +136,7 @@ pub struct TimeStampResp { } impl TimeStampResp { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_sequence(|cons| { let status = PkiStatusInfo::take_from(cons)?; let time_stamp_token = TimeStampToken::take_opt_from(cons)?; @@ -176,7 +176,7 @@ pub struct PkiStatusInfo { } impl PkiStatusInfo { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_sequence(|cons| { let status = PkiStatus::take_from(cons)?; let status_string = PkiFreeText::take_opt_from(cons)?; @@ -235,7 +235,7 @@ pub enum PkiStatus { } impl PkiStatus { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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::Granted), 1 => Ok(Self::GrantedWithMods), @@ -243,7 +243,7 @@ impl PkiStatus { 3 => Ok(Self::Waiting), 4 => Ok(Self::RevocationWarning), 5 => Ok(Self::RevocationNotification), - _ => Err(Malformed.into()), + _ => Err(cons.content_err("unknown PKIStatus value")), } } @@ -300,15 +300,19 @@ pub enum PkiFailureInfo { } impl PkiFailureInfo { - pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> { + pub fn take_opt_from<S: Source>( + cons: &mut Constructed<S>, + ) -> Result<Option<Self>, DecodeError<S::Error>> { cons.take_opt_primitive_if(Tag::INTEGER, Self::from_primitive) } - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_primitive_if(Tag::INTEGER, Self::from_primitive) } - pub fn from_primitive<S: Source>(prim: &mut Primitive<S>) -> Result<Self, S::Err> { + pub fn from_primitive<S: Source>( + prim: &mut Primitive<S>, + ) -> Result<Self, DecodeError<S::Error>> { match Integer::i8_from_primitive(prim)? { 0 => Ok(Self::BadAlg), 1 => Ok(Self::BadRequest), @@ -318,7 +322,7 @@ impl PkiFailureInfo { 16 => Ok(Self::UnacceptedExtension), 17 => Ok(Self::AddInfoNotAvailable), 25 => Ok(Self::SystemFailure), - _ => Err(Malformed.into()), + _ => Err(prim.content_err("Unknown PKIFailureInfo value")), } } @@ -385,7 +389,7 @@ pub struct TstInfo { } impl TstInfo { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_sequence(|cons| { let version = Integer::take_from(cons)?; let policy = TsaPolicyId::take_from(cons)?; @@ -452,17 +456,19 @@ pub struct Accuracy { } impl Accuracy { - pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> { + 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, S::Err> { + pub fn from_sequence<S: Source>( + cons: &mut Constructed<S>, + ) -> Result<Self, DecodeError<S::Error>> { let seconds = cons.take_opt_primitive_if(Tag::INTEGER, |prim| Integer::from_primitive(prim))?; - let millis = - cons.take_opt_primitive_if(Tag::CTX_0, |prim| Integer::from_primitive(prim))?; - let micros = - cons.take_opt_primitive_if(Tag::CTX_1, |prim| Integer::from_primitive(prim))?; + let millis = cons.take_opt_constructed_if(Tag::CTX_0, |cons| Integer::take_from(cons))?; + let micros = cons.take_opt_constructed_if(Tag::CTX_1, |cons| Integer::take_from(cons))?; Ok(Self { seconds, diff --git a/sdk/src/asn1/rfc3281.rs b/sdk/src/asn1/rfc3281.rs @@ -3,7 +3,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. use bcder::{ - decode::{Constructed, Source, Unimplemented}, + decode::{Constructed, DecodeError, Source}, BitString, Oid, }; use x509_certificate::{asn1time::*, rfc3280::*, rfc5280::*}; @@ -25,7 +25,7 @@ pub struct AttributeCertificate { } impl AttributeCertificate { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_sequence(|cons| { let ac_info = AttributeCertificateInfo::take_from(cons)?; let signature_algorithm = AlgorithmIdentifier::take_from(cons)?; @@ -69,8 +69,8 @@ pub struct AttributeCertificateInfo { } impl AttributeCertificateInfo { - pub fn take_from<S: Source>(_cons: &mut Constructed<S>) -> Result<Self, S::Err> { - Err(Unimplemented.into()) + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { + Err(cons.content_err("AttributeCertificateInfo parsing not implemented")) } } diff --git a/sdk/src/asn1/rfc4210.rs b/sdk/src/asn1/rfc4210.rs @@ -5,7 +5,7 @@ //! ASN.1 types defined by RFC 4210. use bcder::{ - decode::{Constructed, Source}, + decode::{Constructed, DecodeError, Source}, encode::{self, Values}, Tag, Utf8String, }; @@ -19,15 +19,19 @@ use bcder::{ pub struct PkiFreeText(Vec<Utf8String>); impl PkiFreeText { - pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> { + 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 take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_sequence(|cons| Self::from_sequence(cons)) } - pub fn from_sequence<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn from_sequence<S: Source>( + cons: &mut Constructed<S>, + ) -> Result<Self, DecodeError<S::Error>> { let mut res = vec![]; while let Some(s) = cons.take_opt_value_if(Tag::UTF8_STRING, |content| { diff --git a/sdk/src/asn1/rfc5652.rs b/sdk/src/asn1/rfc5652.rs @@ -19,7 +19,7 @@ use std::{ }; use bcder::{ - decode::{Constructed, Malformed, Source, Unimplemented}, + decode::{Constructed, DecodeError, Source}, encode, encode::{PrimitiveContent, Values}, BitString, Captured, ConstOid, Integer, Mode, OctetString, Oid, Tag, @@ -103,11 +103,15 @@ impl PartialEq for ContentInfo { impl Eq for ContentInfo {} impl ContentInfo { - pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> { + 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, S::Err> { + 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())?; @@ -154,23 +158,23 @@ pub struct SignedData { impl SignedData { /// Attempt to decode BER encoded bytes to a parsed data structure. - pub fn decode_ber(data: &[u8]) -> Result<Self, bcder::decode::Error> { + pub fn decode_ber(data: &[u8]) -> Result<Self, DecodeError<std::convert::Infallible>> { Constructed::decode(data, bcder::Mode::Ber, |cons| Self::decode(cons)) } - pub fn decode<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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(Malformed.into()); + 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, S::Err> { + 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)?; @@ -236,7 +240,7 @@ impl DerefMut for DigestAlgorithmIdentifiers { } impl DigestAlgorithmIdentifiers { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_set(|cons| { let mut identifiers = Vec::new(); @@ -278,7 +282,7 @@ impl DerefMut for SignerInfos { } impl SignerInfos { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { cons.take_set(|cons| { let mut infos = Vec::new(); @@ -326,7 +330,7 @@ impl Debug for EncapsulatedContentInfo { } impl EncapsulatedContentInfo { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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 = @@ -378,11 +382,15 @@ pub struct SignerInfo { } impl SignerInfo { - pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> { + 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, S::Err> { + 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)?; @@ -402,7 +410,8 @@ impl SignerInfo { Ok(( Constructed::decode(der.as_slice(), bcder::Mode::Der, |cons| { SignedAttributes::take_from_set(cons) - })?, + }) + .map_err(|e| e.convert())?, der_data, )) })?; @@ -581,7 +590,7 @@ pub enum SignerIdentifier { } impl SignerIdentifier { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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))? { @@ -635,11 +644,13 @@ impl DerefMut for SignedAttributes { } impl SignedAttributes { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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, S::Err> { + 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)? { @@ -652,12 +663,27 @@ impl SignedAttributes { /// Obtain an instance where the attributes are sorted according to DER /// rules. See the comment in [SignerInfo::signed_attributes_digested_content]. pub fn as_sorted(&self) -> Result<Self, std::io::Error> { - // The official rules say you sort by the first element in the container. - // That's an Oid, which implements comparisons. So our job is easy. - let mut res = self.0.clone(); - res.sort_by(|a, b| a.typ.as_ref().cmp(b.typ.as_ref())); + // All elements of the set have the same type. So sorting is based on encoded + // values, with shorter elements padded with 0s. Rust will sort a shorter value + // with a prefix match against a longer value as less than, so we can avoid the + // padding. + + let mut attributes = self + .0 + .iter() + .map(|x| { + let mut encoded = vec![]; + x.values.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(res)) + Ok(Self( + attributes.into_iter().map(|(_, x)| x).collect::<Vec<_>>(), + )) } fn encode_ref(&self) -> impl Values + '_ { @@ -729,11 +755,13 @@ impl DerefMut for UnsignedAttributes { } impl UnsignedAttributes { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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, S::Err> { + 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)? { @@ -1090,8 +1118,8 @@ pub type KeyDerivationAlgorithmIdentifier = AlgorithmIdentifier; pub struct RevocationInfoChoices(Vec<RevocationInfoChoice>); impl RevocationInfoChoices { - pub fn take_from<S: Source>(_cons: &mut Constructed<S>) -> Result<Self, S::Err> { - Err(Unimplemented.into()) + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { + Err(cons.content_err("RevocationInfoChoices parsing not implemented")) } } @@ -1142,12 +1170,14 @@ pub enum CertificateChoices { } 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()) + 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<(), S::Err> { - Err(Unimplemented.into()) + cons.take_opt_constructed_if(Tag::CTX_1, |cons| -> Result<(), DecodeError<S::Error>> { + Err(cons.content_err("AttributeCertificateV1 parsing not implemented")) })?; // TODO these first 2 need methods that parse an already entered SEQUENCE. @@ -1202,8 +1232,8 @@ pub struct OtherCertificateFormat { } impl OtherCertificateFormat { - pub fn take_from<S: Source>(_cons: &mut Constructed<S>) -> Result<Self, S::Err> { - Err(Unimplemented.into()) + pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> { + Err(cons.content_err("OtherCertificateFormat parsing not implemented")) } } @@ -1225,7 +1255,7 @@ impl DerefMut for CertificateSet { } impl CertificateSet { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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)? { @@ -1254,7 +1284,7 @@ pub struct IssuerAndSerialNumber { } impl IssuerAndSerialNumber { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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)?; @@ -1290,7 +1320,7 @@ pub enum CmsVersion { } impl CmsVersion { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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), @@ -1298,7 +1328,7 @@ impl CmsVersion { 3 => Ok(Self::V3), 4 => Ok(Self::V4), 5 => Ok(Self::V5), - _ => Err(Malformed.into()), + _ => Err(cons.content_err("unexpected CMSVersion")), } } @@ -1356,7 +1386,7 @@ pub enum Time { } impl Time { - pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> { + 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))? { @@ -1368,7 +1398,7 @@ impl Time { { Ok(Self::GeneralizedTime(generalized)) } else { - Err(Malformed.into()) + Err(cons.content_err("invalid Time value")) } } }