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 34b581f61848ade0280736382bd2ca6459251b29
parent 737a804e410b0e588d3c1d191b0fbd65490f43c3
Author: Eric Scouten <scouten@adobe.com>
Date:   Tue, 11 Apr 2023 15:19:42 -0400

Upgrade x509-parser to 0.15.0 (#229)


Diffstat:
Msdk/Cargo.toml | 3++-
Msdk/src/cose_validator.rs | 96+++++++++++++++++++++++++++++++++++++++----------------------------------------
2 files changed, 49 insertions(+), 50 deletions(-)

diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml @@ -48,6 +48,7 @@ name = "custom_assertion" crate-type = ["lib"] [dependencies] +asn1-rs = "0.5.2" async-trait = { version = "0.1.48"} atree = "0.5.2" base64 = "0.13.0" @@ -85,7 +86,7 @@ treeline = "0.1.0" twoway = "0.2.2" url = "2.2.2" uuid = { version = "0.8.1", features = ["serde", "v4", "wasm-bindgen"] } -x509-parser = "0.11.0" +x509-parser = "0.15.0" x509-certificate = "0.19.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/sdk/src/cose_validator.rs b/sdk/src/cose_validator.rs @@ -11,6 +11,7 @@ // specific language governing permissions and limitations under // each license. +use asn1_rs::{Any, Class, Header, Tag}; use ciborium::value::Value; use conv::*; use coset::{sig_structure_data, Label, TaggedCborSerializable}; @@ -127,12 +128,10 @@ fn check_cert( if let Some(tst_info) = _tst_info_opt { // was there a time stamp associtation with this signature, is verify against that time let signing_time = gt_to_datetime(tst_info.gen_time.clone()); - if !signcert - .validity() - .is_valid_at(x509_parser::time::ASN1Time::from_timestamp( - signing_time.timestamp(), - )) - { + if !signcert.validity().is_valid_at( + x509_parser::time::ASN1Time::from_timestamp(signing_time.timestamp()) + .map_err(|_| Error::CoseInvalidCert)?, + ) { let log_item = log_item!("Cose_Sign1", "certificate expired", "check_cert_alg") .error(Error::CoseCertExpiration) .validation_status(validation_status::SIGNING_CREDENTIAL_EXPIRED); @@ -148,10 +147,9 @@ fn check_cert( .approx_as::<i64>() .map_err(|_e| Error::BadParam("system time invalid".to_string()))?; - if !signcert - .validity() - .is_valid_at(x509_parser::time::ASN1Time::from_timestamp(now)) - { + if !signcert.validity().is_valid_at( + x509_parser::time::ASN1Time::from_timestamp(now).map_err(|_| Error::CoseInvalidCert)?, + ) { let log_item = log_item!("Cose_Sign1", "certificate expired", "check_cert_alg") .error(Error::CoseCertExpiration) .validation_status(validation_status::SIGNING_CREDENTIAL_EXPIRED); @@ -193,46 +191,45 @@ fn check_cert( let seq = parameters .as_sequence() .map_err(|_err| Error::CoseInvalidCert)?; - if seq.len() < 3 { - let log_item = log_item!( - "Cose_Sign1", - "certificate incorrect rsapss algorithm", - "check_cert_alg" - ) - .error(Error::CoseInvalidCert) - .validation_status(validation_status::SIGNING_CREDENTIAL_INVALID); - validation_log.log_silent(log_item); - return Err(Error::CoseInvalidCert); - } + let (_i, (ha_alg, mgf_ai)) = seq + .parse(|i| { + let (i, h) = Header::from_der(i)?; + if h.class() != Class::ContextSpecific || h.tag() != Tag(0) { + return Err(nom::Err::Error(asn1_rs::Error::BerValueError)); + } - // get hash algorithm - let (_b, ha_alg) = AlgorithmIdentifier::from_der( - seq[0] - .content - .as_slice() - .map_err(|_err| Error::CoseInvalidCert)?, - ) - .map_err(|_err| Error::CoseInvalidCert)?; + let (i, ha_alg) = AlgorithmIdentifier::from_der(i) + .map_err(|_| nom::Err::Error(asn1_rs::Error::BerValueError))?; - let (_b, mgf_ai) = AlgorithmIdentifier::from_der( - seq[1] - .content - .as_slice() - .map_err(|_err| Error::CoseInvalidCert)?, - ) - .map_err(|_err| Error::CoseInvalidCert)?; + let (i, h) = Header::from_der(i)?; + if h.class() != Class::ContextSpecific || h.tag() != Tag(1) { + return Err(nom::Err::Error(asn1_rs::Error::BerValueError)); + } + + let (i, mgf_ai) = AlgorithmIdentifier::from_der(i) + .map_err(|_| nom::Err::Error(asn1_rs::Error::BerValueError))?; + + // Ignore anything that follows these two parameters. + + Ok((i, (ha_alg, mgf_ai))) + }) + .map_err(|_| Error::CoseInvalidCert)?; let mgf_ai_parameters = mgf_ai.parameters.ok_or(Error::CoseInvalidCert)?; - let s = mgf_ai_parameters + let mgf_ai_parameters = mgf_ai_parameters .as_sequence() - .map_err(|_err| Error::CoseInvalidCert)?; - let t0 = &s[0]; - //let _t1 = &s[1]; - let mfg_ai_params_algorithm = t0.as_oid_val().map_err(|_err| Error::CoseInvalidCert)?; + .map_err(|_| Error::CoseInvalidCert)?; + + let (_i, mgf_ai_params_algorithm) = + Any::from_der(&mgf_ai_parameters.content).map_err(|_| Error::CoseInvalidCert)?; + + let mgf_ai_params_algorithm = mgf_ai_params_algorithm + .as_oid() + .map_err(|_| Error::CoseInvalidCert)?; // must be the same - if ha_alg.algorithm != mfg_ai_params_algorithm { + if ha_alg.algorithm != mgf_ai_params_algorithm { let log_item = log_item!( "Cose_Sign1", "certificate algorithm error", @@ -281,9 +278,7 @@ fn check_cert( if skpi_alg.algorithm == EC_PUBLICKEY_OID { if let Some(parameters) = &skpi_alg.parameters { - let named_curve_oid = parameters - .as_oid_val() - .map_err(|_err| Error::CoseInvalidCert)?; + let named_curve_oid = parameters.as_oid().map_err(|_err| Error::CoseInvalidCert)?; // must be one of these named curves if !(named_curve_oid == PRIME256V1_OID @@ -308,7 +303,7 @@ fn check_cert( // check modulus minimum length (for RSA & PSS algorithms) if skpi_alg.algorithm == RSA_OID || skpi_alg.algorithm == RSASSA_PSS_OID { - let (_, skpi_ber) = parse_ber_sequence(pk.subject_public_key.data) + let (_, skpi_ber) = parse_ber_sequence(&pk.subject_public_key.data) .map_err(|_err| Error::CoseInvalidCert)?; let seq = skpi_ber @@ -318,7 +313,7 @@ fn check_cert( return Err(Error::CoseInvalidCert); } - let modulus = seq[0].as_bigint().ok_or(Error::CoseInvalidCert)?; + let modulus = seq[0].as_bigint().map_err(|_| Error::CoseInvalidCert)?; if modulus.bits() < 2048 { let log_item = log_item!( @@ -357,8 +352,11 @@ fn check_cert( let mut ski_good = false; let mut key_usage_good = false; let mut handled_all_critical = true; - let extended_key_usage_good = match tbscert.extended_key_usage() { - Some((_critical, eku)) => { + let extended_key_usage_good = match tbscert + .extended_key_usage() + .map_err(|_| Error::CoseInvalidCert)? + { + Some(BasicExtension { value: eku, .. }) => { if eku.any { let log_item = log_item!( "Cose_Sign1",