手动执行全量同步
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::data_model::oid::OID_CT_ASPA;
|
||||
use crate::data_model::common::{DerReader, der_take_tlv};
|
||||
use crate::data_model::oid::OID_CT_ASPA;
|
||||
use crate::data_model::rc::ResourceCertificate;
|
||||
use crate::data_model::signed_object::{
|
||||
RpkiSignedObject, RpkiSignedObjectParsed, SignedObjectParseError, SignedObjectValidateError,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use x509_parser::asn1_rs::Tag;
|
||||
use x509_parser::x509::AlgorithmIdentifier;
|
||||
use x509_parser::prelude::FromDer;
|
||||
use x509_parser::x509::AlgorithmIdentifier;
|
||||
|
||||
pub type UtcTime = time::OffsetDateTime;
|
||||
|
||||
@@ -169,7 +169,10 @@ impl<'a> DerReader<'a> {
|
||||
}
|
||||
|
||||
pub(crate) fn peek_tag(&self) -> Result<u8, String> {
|
||||
self.buf.first().copied().ok_or_else(|| "truncated DER".into())
|
||||
self.buf
|
||||
.first()
|
||||
.copied()
|
||||
.ok_or_else(|| "truncated DER".into())
|
||||
}
|
||||
|
||||
pub(crate) fn take_any(&mut self) -> Result<(u8, &'a [u8]), String> {
|
||||
@@ -223,7 +226,10 @@ impl<'a> DerReader<'a> {
|
||||
der_uint_from_bytes(v)
|
||||
}
|
||||
|
||||
pub(crate) fn take_explicit(&mut self, expected_outer_tag: u8) -> Result<(u8, &'a [u8]), String> {
|
||||
pub(crate) fn take_explicit(
|
||||
&mut self,
|
||||
expected_outer_tag: u8,
|
||||
) -> Result<(u8, &'a [u8]), String> {
|
||||
let inner_der = self.take_tag(expected_outer_tag)?;
|
||||
let (tag, value, rem) = der_take_tlv(inner_der)?;
|
||||
if !rem.is_empty() {
|
||||
|
||||
@@ -433,10 +433,7 @@ fn algorithm_identifier_value(ai: &AlgorithmIdentifier<'_>) -> AlgorithmIdentifi
|
||||
} else {
|
||||
ai.algorithm.to_id_string()
|
||||
};
|
||||
AlgorithmIdentifierValue {
|
||||
oid,
|
||||
parameters,
|
||||
}
|
||||
AlgorithmIdentifierValue { oid, parameters }
|
||||
}
|
||||
|
||||
fn parse_extensions_parse(exts: &[X509Extension<'_>]) -> Result<Vec<CrlExtensionParsed>, String> {
|
||||
@@ -444,15 +441,15 @@ fn parse_extensions_parse(exts: &[X509Extension<'_>]) -> Result<Vec<CrlExtension
|
||||
for ext in exts {
|
||||
let oid = ext.oid.as_bytes();
|
||||
if oid == OID_AUTHORITY_KEY_IDENTIFIER_RAW {
|
||||
let ParsedExtension::AuthorityKeyIdentifier(aki) = ext.parsed_extension() else {
|
||||
return Err("AKI extension parse failed".to_string());
|
||||
};
|
||||
out.push(CrlExtensionParsed::AuthorityKeyIdentifier {
|
||||
key_identifier: aki.key_identifier.as_ref().map(|k| k.0.to_vec()),
|
||||
has_other_fields: aki.authority_cert_issuer.is_some()
|
||||
|| aki.authority_cert_serial.is_some(),
|
||||
critical: ext.critical,
|
||||
});
|
||||
let ParsedExtension::AuthorityKeyIdentifier(aki) = ext.parsed_extension() else {
|
||||
return Err("AKI extension parse failed".to_string());
|
||||
};
|
||||
out.push(CrlExtensionParsed::AuthorityKeyIdentifier {
|
||||
key_identifier: aki.key_identifier.as_ref().map(|k| k.0.to_vec()),
|
||||
has_other_fields: aki.authority_cert_issuer.is_some()
|
||||
|| aki.authority_cert_serial.is_some(),
|
||||
critical: ext.critical,
|
||||
});
|
||||
} else if oid == OID_CRL_NUMBER_RAW {
|
||||
match ext.parsed_extension() {
|
||||
ParsedExtension::CRLNumber(n) => out.push(CrlExtensionParsed::CrlNumber {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::data_model::common::{BigUnsigned, UtcTime};
|
||||
use crate::data_model::common::der_take_tlv;
|
||||
use crate::data_model::common::{BigUnsigned, UtcTime};
|
||||
use crate::data_model::oid::{OID_CT_RPKI_MANIFEST, OID_SHA256};
|
||||
use crate::data_model::rc::ResourceCertificate;
|
||||
use crate::data_model::signed_object::{
|
||||
@@ -248,8 +248,7 @@ impl ManifestObject {
|
||||
impl ManifestEContent {
|
||||
/// Parse step of scheme A (`parse → validate → verify`).
|
||||
pub fn parse_der(der: &[u8]) -> Result<ManifestEContentParsed, ManifestParseError> {
|
||||
let (_tag, _value, rem) =
|
||||
der_take_tlv(der).map_err(|e| ManifestParseError::Parse(e))?;
|
||||
let (_tag, _value, rem) = der_take_tlv(der).map_err(|e| ManifestParseError::Parse(e))?;
|
||||
if !rem.is_empty() {
|
||||
return Err(ManifestParseError::TrailingBytes(rem.len()));
|
||||
}
|
||||
@@ -412,8 +411,8 @@ fn decode_manifest_econtent_fast(der: &[u8]) -> Result<ManifestEContent, Manifes
|
||||
));
|
||||
}
|
||||
|
||||
let seq_len = der_count_elements(seq_content)
|
||||
.map_err(|e| ManifestProfileError::ProfileDecode(e))?;
|
||||
let seq_len =
|
||||
der_count_elements(seq_content).map_err(|e| ManifestProfileError::ProfileDecode(e))?;
|
||||
if seq_len != 5 && seq_len != 6 {
|
||||
return Err(ManifestProfileError::InvalidManifestSequenceLen(seq_len));
|
||||
}
|
||||
@@ -587,15 +586,17 @@ fn parse_file_list_sha256_fast(content: &[u8]) -> Result<Vec<FileAndHash>, Manif
|
||||
let mut cur = content;
|
||||
let mut out: Vec<FileAndHash> = Vec::with_capacity(est);
|
||||
while !cur.is_empty() {
|
||||
let (tag, value, rem) = der_take_tlv(cur)
|
||||
.map_err(|e| ManifestProfileError::ProfileDecode(format!("fileList entry decode error: {e}")))?;
|
||||
let (tag, value, rem) = der_take_tlv(cur).map_err(|e| {
|
||||
ManifestProfileError::ProfileDecode(format!("fileList entry decode error: {e}"))
|
||||
})?;
|
||||
cur = rem;
|
||||
if tag != 0x30 {
|
||||
return Err(ManifestProfileError::InvalidFileAndHash);
|
||||
}
|
||||
let mut entry = value;
|
||||
let (fn_tag, fn_value, entry_rem) = der_take_tlv(entry)
|
||||
.map_err(|e| ManifestProfileError::ProfileDecode(format!("fileList fileName decode error: {e}")))?;
|
||||
let (fn_tag, fn_value, entry_rem) = der_take_tlv(entry).map_err(|e| {
|
||||
ManifestProfileError::ProfileDecode(format!("fileList fileName decode error: {e}"))
|
||||
})?;
|
||||
entry = entry_rem;
|
||||
if fn_tag != 0x16 {
|
||||
return Err(ManifestProfileError::InvalidFileAndHash);
|
||||
@@ -702,7 +703,9 @@ fn parse_generalized_time_bytes(bytes: &[u8]) -> Result<UtcTime, String> {
|
||||
return Err("GeneralizedTime must end with 'Z'".into());
|
||||
}
|
||||
let core = &s[..s.len() - 1];
|
||||
let (main, frac) = core.split_once('.').map_or((core, None), |(a, b)| (a, Some(b)));
|
||||
let (main, frac) = core
|
||||
.split_once('.')
|
||||
.map_or((core, None), |(a, b)| (a, Some(b)));
|
||||
if main.len() != 14 || !main.bytes().all(|b| b.is_ascii_digit()) {
|
||||
return Err("GeneralizedTime must be YYYYMMDDHHMMSS[.fff]Z".into());
|
||||
}
|
||||
@@ -731,9 +734,14 @@ fn parse_generalized_time_bytes(bytes: &[u8]) -> Result<UtcTime, String> {
|
||||
0
|
||||
};
|
||||
|
||||
let date = time::Date::from_calendar_date(year, time::Month::try_from(month).map_err(|_| "bad month")?, day)
|
||||
.map_err(|e| e.to_string())?;
|
||||
let t = time::Time::from_hms_nano(hour, minute, second, nanosecond).map_err(|e| e.to_string())?;
|
||||
let date = time::Date::from_calendar_date(
|
||||
year,
|
||||
time::Month::try_from(month).map_err(|_| "bad month")?,
|
||||
day,
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
let t =
|
||||
time::Time::from_hms_nano(hour, minute, second, nanosecond).map_err(|e| e.to_string())?;
|
||||
Ok(date.with_time(t).assume_utc())
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,9 @@ pub const OID_SUBJECT_KEY_IDENTIFIER: &str = "2.5.29.14";
|
||||
pub const OID_SUBJECT_KEY_IDENTIFIER_RAW: &[u8] = &asn1_rs::oid!(raw 2.5.29.14);
|
||||
|
||||
pub const OID_CT_RPKI_MANIFEST: &str = "1.2.840.113549.1.9.16.1.26";
|
||||
pub const OID_CT_RPKI_MANIFEST_RAW: &[u8] =
|
||||
&asn1_rs::oid!(raw 1.2.840.113549.1.9.16.1.26);
|
||||
pub const OID_CT_RPKI_MANIFEST_RAW: &[u8] = &asn1_rs::oid!(raw 1.2.840.113549.1.9.16.1.26);
|
||||
pub const OID_CT_ROUTE_ORIGIN_AUTHZ: &str = "1.2.840.113549.1.9.16.1.24";
|
||||
pub const OID_CT_ROUTE_ORIGIN_AUTHZ_RAW: &[u8] =
|
||||
&asn1_rs::oid!(raw 1.2.840.113549.1.9.16.1.24);
|
||||
pub const OID_CT_ROUTE_ORIGIN_AUTHZ_RAW: &[u8] = &asn1_rs::oid!(raw 1.2.840.113549.1.9.16.1.24);
|
||||
pub const OID_CT_ASPA: &str = "1.2.840.113549.1.9.16.1.49";
|
||||
pub const OID_CT_ASPA_RAW: &[u8] = &asn1_rs::oid!(raw 1.2.840.113549.1.9.16.1.49);
|
||||
|
||||
|
||||
@@ -648,10 +648,7 @@ impl RcExtensionsParsed {
|
||||
let subject_key_identifier = match subject_key_identifier.len() {
|
||||
0 => None,
|
||||
1 => {
|
||||
let (ski, critical) = subject_key_identifier
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("len==1");
|
||||
let (ski, critical) = subject_key_identifier.into_iter().next().expect("len==1");
|
||||
if critical {
|
||||
return Err(ResourceCertificateProfileError::SkiCriticality);
|
||||
}
|
||||
@@ -673,10 +670,7 @@ impl RcExtensionsParsed {
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let (aki, critical) = authority_key_identifier
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("len==1");
|
||||
let (aki, critical) = authority_key_identifier.into_iter().next().expect("len==1");
|
||||
if critical {
|
||||
return Err(ResourceCertificateProfileError::AkiCriticality);
|
||||
}
|
||||
@@ -716,10 +710,7 @@ impl RcExtensionsParsed {
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let (crldp, critical) = crl_distribution_points
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("len==1");
|
||||
let (crldp, critical) = crl_distribution_points.into_iter().next().expect("len==1");
|
||||
if critical {
|
||||
return Err(ResourceCertificateProfileError::CrlDistributionPointsCriticality);
|
||||
}
|
||||
@@ -795,7 +786,11 @@ impl RcExtensionsParsed {
|
||||
ResourceCertificateProfileError::AuthorityInfoAccessMissingCaIssuers,
|
||||
);
|
||||
}
|
||||
if !aia.ca_issuers_uris.iter().any(|u| u.starts_with("rsync://")) {
|
||||
if !aia
|
||||
.ca_issuers_uris
|
||||
.iter()
|
||||
.any(|u| u.starts_with("rsync://"))
|
||||
{
|
||||
return Err(ResourceCertificateProfileError::AuthorityInfoAccessNoRsync);
|
||||
}
|
||||
Some(aia.ca_issuers_uris)
|
||||
@@ -932,10 +927,7 @@ fn algorithm_identifier_value(
|
||||
} else {
|
||||
ai.algorithm.to_id_string()
|
||||
};
|
||||
AlgorithmIdentifierValue {
|
||||
oid,
|
||||
parameters,
|
||||
}
|
||||
AlgorithmIdentifierValue { oid, parameters }
|
||||
}
|
||||
|
||||
fn parse_extensions_parse(
|
||||
@@ -955,78 +947,78 @@ fn parse_extensions_parse(
|
||||
for ext in exts {
|
||||
let oid = ext.oid.as_bytes();
|
||||
if oid == OID_BASIC_CONSTRAINTS_RAW {
|
||||
let ParsedExtension::BasicConstraints(bc) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"basicConstraints parse failed".into(),
|
||||
));
|
||||
};
|
||||
basic_constraints_ca.push(bc.ca);
|
||||
} else if oid == OID_SUBJECT_KEY_IDENTIFIER_RAW {
|
||||
let ParsedExtension::SubjectKeyIdentifier(s) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"subjectKeyIdentifier parse failed".into(),
|
||||
));
|
||||
};
|
||||
ski.push((s.0.to_vec(), ext.critical));
|
||||
} else if oid == OID_AUTHORITY_KEY_IDENTIFIER_RAW {
|
||||
let ParsedExtension::AuthorityKeyIdentifier(a) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"authorityKeyIdentifier parse failed".into(),
|
||||
));
|
||||
};
|
||||
aki.push((
|
||||
AuthorityKeyIdentifierParsed {
|
||||
key_identifier: a.key_identifier.as_ref().map(|k| k.0.to_vec()),
|
||||
has_authority_cert_issuer: a.authority_cert_issuer.is_some(),
|
||||
has_authority_cert_serial: a.authority_cert_serial.is_some(),
|
||||
},
|
||||
ext.critical,
|
||||
let ParsedExtension::BasicConstraints(bc) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"basicConstraints parse failed".into(),
|
||||
));
|
||||
};
|
||||
basic_constraints_ca.push(bc.ca);
|
||||
} else if oid == OID_SUBJECT_KEY_IDENTIFIER_RAW {
|
||||
let ParsedExtension::SubjectKeyIdentifier(s) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"subjectKeyIdentifier parse failed".into(),
|
||||
));
|
||||
};
|
||||
ski.push((s.0.to_vec(), ext.critical));
|
||||
} else if oid == OID_AUTHORITY_KEY_IDENTIFIER_RAW {
|
||||
let ParsedExtension::AuthorityKeyIdentifier(a) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"authorityKeyIdentifier parse failed".into(),
|
||||
));
|
||||
};
|
||||
aki.push((
|
||||
AuthorityKeyIdentifierParsed {
|
||||
key_identifier: a.key_identifier.as_ref().map(|k| k.0.to_vec()),
|
||||
has_authority_cert_issuer: a.authority_cert_issuer.is_some(),
|
||||
has_authority_cert_serial: a.authority_cert_serial.is_some(),
|
||||
},
|
||||
ext.critical,
|
||||
));
|
||||
} else if oid == OID_CRL_DISTRIBUTION_POINTS_RAW {
|
||||
let ParsedExtension::CRLDistributionPoints(p) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"cRLDistributionPoints parse failed".into(),
|
||||
));
|
||||
};
|
||||
crldp.push((parse_crldp_parse(p)?, ext.critical));
|
||||
let ParsedExtension::CRLDistributionPoints(p) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"cRLDistributionPoints parse failed".into(),
|
||||
));
|
||||
};
|
||||
crldp.push((parse_crldp_parse(p)?, ext.critical));
|
||||
} else if oid == OID_AUTHORITY_INFO_ACCESS_RAW {
|
||||
let ParsedExtension::AuthorityInfoAccess(p) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"authorityInfoAccess parse failed".into(),
|
||||
));
|
||||
};
|
||||
aia.push((parse_aia_parse(p.accessdescs.as_slice())?, ext.critical));
|
||||
let ParsedExtension::AuthorityInfoAccess(p) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"authorityInfoAccess parse failed".into(),
|
||||
));
|
||||
};
|
||||
aia.push((parse_aia_parse(p.accessdescs.as_slice())?, ext.critical));
|
||||
} else if oid == OID_SUBJECT_INFO_ACCESS_RAW {
|
||||
let ParsedExtension::SubjectInfoAccess(s) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"subjectInfoAccess parse failed".into(),
|
||||
));
|
||||
};
|
||||
sia.push((parse_sia_parse(s.accessdescs.as_slice())?, ext.critical));
|
||||
let ParsedExtension::SubjectInfoAccess(s) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"subjectInfoAccess parse failed".into(),
|
||||
));
|
||||
};
|
||||
sia.push((parse_sia_parse(s.accessdescs.as_slice())?, ext.critical));
|
||||
} else if oid == OID_CERTIFICATE_POLICIES_RAW {
|
||||
let ParsedExtension::CertificatePolicies(cp) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"certificatePolicies parse failed".into(),
|
||||
));
|
||||
};
|
||||
let mut oids: Vec<String> = Vec::with_capacity(cp.len());
|
||||
for p in cp.iter() {
|
||||
let b = p.policy_id.as_bytes();
|
||||
if b == OID_CP_IPADDR_ASNUMBER_RAW {
|
||||
oids.push(OID_CP_IPADDR_ASNUMBER.to_string());
|
||||
} else {
|
||||
oids.push(p.policy_id.to_id_string());
|
||||
}
|
||||
let ParsedExtension::CertificatePolicies(cp) = ext.parsed_extension() else {
|
||||
return Err(ResourceCertificateParseError::Parse(
|
||||
"certificatePolicies parse failed".into(),
|
||||
));
|
||||
};
|
||||
let mut oids: Vec<String> = Vec::with_capacity(cp.len());
|
||||
for p in cp.iter() {
|
||||
let b = p.policy_id.as_bytes();
|
||||
if b == OID_CP_IPADDR_ASNUMBER_RAW {
|
||||
oids.push(OID_CP_IPADDR_ASNUMBER.to_string());
|
||||
} else {
|
||||
oids.push(p.policy_id.to_id_string());
|
||||
}
|
||||
cert_policies.push((oids, ext.critical));
|
||||
}
|
||||
cert_policies.push((oids, ext.critical));
|
||||
} else if oid == OID_IP_ADDR_BLOCKS_RAW {
|
||||
let parsed = IpResourceSet::decode_extn_value(ext.value)
|
||||
.map_err(|_e| ResourceCertificateParseError::InvalidIpResourcesEncoding)?;
|
||||
ip_resources.push((parsed, ext.critical));
|
||||
let parsed = IpResourceSet::decode_extn_value(ext.value)
|
||||
.map_err(|_e| ResourceCertificateParseError::InvalidIpResourcesEncoding)?;
|
||||
ip_resources.push((parsed, ext.critical));
|
||||
} else if oid == OID_AUTONOMOUS_SYS_IDS_RAW {
|
||||
let parsed = AsResourceSet::decode_extn_value(ext.value)
|
||||
.map_err(|_e| ResourceCertificateParseError::InvalidAsResourcesEncoding)?;
|
||||
as_resources.push((parsed, ext.critical));
|
||||
let parsed = AsResourceSet::decode_extn_value(ext.value)
|
||||
.map_err(|_e| ResourceCertificateParseError::InvalidAsResourcesEncoding)?;
|
||||
as_resources.push((parsed, ext.critical));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::data_model::oid::OID_CT_ROUTE_ORIGIN_AUTHZ;
|
||||
use crate::data_model::common::{DerReader, der_take_tlv};
|
||||
use crate::data_model::oid::OID_CT_ROUTE_ORIGIN_AUTHZ;
|
||||
use crate::data_model::rc::{Afi as RcAfi, IpPrefix as RcIpPrefix, ResourceCertificate};
|
||||
use crate::data_model::signed_object::{
|
||||
RpkiSignedObject, RpkiSignedObjectParsed, SignedObjectParseError, SignedObjectValidateError,
|
||||
@@ -397,15 +397,18 @@ impl RoaEContentParsed {
|
||||
return Err(RoaProfileError::AsIdOutOfRange(as_id_u64));
|
||||
}
|
||||
let as_id = as_id_u64 as u32;
|
||||
let ip_addr_blocks = parse_ip_addr_blocks_cursor(seq.take_sequence().map_err(|e| {
|
||||
RoaProfileError::ProfileDecode(format!("ipAddrBlocks: {e}"))
|
||||
})?)?;
|
||||
let ip_addr_blocks = parse_ip_addr_blocks_cursor(
|
||||
seq.take_sequence()
|
||||
.map_err(|e| RoaProfileError::ProfileDecode(format!("ipAddrBlocks: {e}")))?,
|
||||
)?;
|
||||
|
||||
if !seq.is_empty() {
|
||||
// Extra elements beyond the expected 2..3.
|
||||
let extra =
|
||||
count_elements(seq).map_err(|e| RoaProfileError::ProfileDecode(e.to_string()))?;
|
||||
return Err(RoaProfileError::InvalidAttestationSequenceLen(elem_count + extra));
|
||||
return Err(RoaProfileError::InvalidAttestationSequenceLen(
|
||||
elem_count + extra,
|
||||
));
|
||||
}
|
||||
|
||||
let mut out = RoaEContent {
|
||||
@@ -517,11 +520,13 @@ fn parse_roa_ip_address_cursor(
|
||||
let v = seq
|
||||
.take_uint_u64()
|
||||
.map_err(|e| RoaProfileError::ProfileDecode(e.to_string()))?;
|
||||
let max_len: u16 = v.try_into().map_err(|_e| RoaProfileError::InvalidMaxLength {
|
||||
afi,
|
||||
prefix_len: prefix.prefix_len,
|
||||
max_len: u16::MAX,
|
||||
})?;
|
||||
let max_len: u16 = v
|
||||
.try_into()
|
||||
.map_err(|_e| RoaProfileError::InvalidMaxLength {
|
||||
afi,
|
||||
prefix_len: prefix.prefix_len,
|
||||
max_len: u16::MAX,
|
||||
})?;
|
||||
Some(max_len)
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use crate::data_model::common::{der_take_tlv, Asn1TimeEncoding, Asn1TimeUtc, DerReader};
|
||||
use crate::data_model::common::{Asn1TimeEncoding, Asn1TimeUtc, DerReader, der_take_tlv};
|
||||
use crate::data_model::oid::{
|
||||
OID_AD_SIGNED_OBJECT, OID_CMS_ATTR_CONTENT_TYPE, OID_CMS_ATTR_MESSAGE_DIGEST,
|
||||
OID_CMS_ATTR_CONTENT_TYPE_RAW, OID_CMS_ATTR_MESSAGE_DIGEST_RAW, OID_CMS_ATTR_SIGNING_TIME,
|
||||
OID_CMS_ATTR_SIGNING_TIME_RAW, OID_CT_ASPA, OID_CT_ASPA_RAW, OID_CT_RPKI_MANIFEST,
|
||||
OID_CT_RPKI_MANIFEST_RAW, OID_CT_ROUTE_ORIGIN_AUTHZ, OID_CT_ROUTE_ORIGIN_AUTHZ_RAW,
|
||||
OID_AD_SIGNED_OBJECT, OID_CMS_ATTR_CONTENT_TYPE, OID_CMS_ATTR_CONTENT_TYPE_RAW,
|
||||
OID_CMS_ATTR_MESSAGE_DIGEST, OID_CMS_ATTR_MESSAGE_DIGEST_RAW, OID_CMS_ATTR_SIGNING_TIME,
|
||||
OID_CMS_ATTR_SIGNING_TIME_RAW, OID_CT_ASPA, OID_CT_ASPA_RAW, OID_CT_ROUTE_ORIGIN_AUTHZ,
|
||||
OID_CT_ROUTE_ORIGIN_AUTHZ_RAW, OID_CT_RPKI_MANIFEST, OID_CT_RPKI_MANIFEST_RAW,
|
||||
OID_RSA_ENCRYPTION, OID_RSA_ENCRYPTION_RAW, OID_SHA256, OID_SHA256_RAW,
|
||||
OID_SHA256_WITH_RSA_ENCRYPTION, OID_SHA256_WITH_RSA_ENCRYPTION_RAW, OID_SIGNED_DATA,
|
||||
OID_SIGNED_DATA_RAW, OID_SUBJECT_INFO_ACCESS,
|
||||
@@ -429,7 +429,9 @@ fn parse_signed_data_from_contentinfo_cursor(
|
||||
parse_signed_data_cursor(signed_data_seq)
|
||||
}
|
||||
|
||||
fn parse_signed_data_cursor(mut seq: DerReader<'_>) -> Result<SignedDataParsed, SignedObjectParseError> {
|
||||
fn parse_signed_data_cursor(
|
||||
mut seq: DerReader<'_>,
|
||||
) -> Result<SignedDataParsed, SignedObjectParseError> {
|
||||
let version = seq
|
||||
.take_uint_u64()
|
||||
.map_err(|e| SignedObjectParseError::Parse(e.to_string()))?;
|
||||
@@ -496,8 +498,8 @@ fn parse_signed_data_cursor(mut seq: DerReader<'_>) -> Result<SignedDataParsed,
|
||||
}
|
||||
}
|
||||
|
||||
let signer_infos =
|
||||
signer_infos.ok_or_else(|| SignedObjectParseError::Parse("SignedData.signerInfos missing".into()))?;
|
||||
let signer_infos = signer_infos
|
||||
.ok_or_else(|| SignedObjectParseError::Parse("SignedData.signerInfos missing".into()))?;
|
||||
|
||||
Ok(SignedDataParsed {
|
||||
version,
|
||||
@@ -524,7 +526,9 @@ fn parse_encapsulated_content_info_cursor(
|
||||
None
|
||||
} else {
|
||||
let inner_der = seq.take_explicit_der(0xA0).map_err(|_e| {
|
||||
SignedObjectParseError::Parse("EncapsulatedContentInfo.eContent must be [0] EXPLICIT".into())
|
||||
SignedObjectParseError::Parse(
|
||||
"EncapsulatedContentInfo.eContent must be [0] EXPLICIT".into(),
|
||||
)
|
||||
})?;
|
||||
let mut inner = DerReader::new(inner_der);
|
||||
let octets = inner
|
||||
@@ -561,7 +565,9 @@ fn split_der_objects(mut input: &[u8]) -> Result<Vec<Vec<u8>>, SignedObjectParse
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn parse_signer_infos_set_cursor(set_bytes: &[u8]) -> Result<Vec<SignerInfoParsed>, SignedObjectParseError> {
|
||||
fn parse_signer_infos_set_cursor(
|
||||
set_bytes: &[u8],
|
||||
) -> Result<Vec<SignerInfoParsed>, SignedObjectParseError> {
|
||||
let mut set = DerReader::new(set_bytes);
|
||||
let mut out: Vec<SignerInfoParsed> = Vec::new();
|
||||
while !set.is_empty() {
|
||||
@@ -624,7 +630,9 @@ fn validate_ee_certificate(der: &[u8]) -> Result<ResourceEeCertificate, SignedOb
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_signer_info_cursor(mut seq: DerReader<'_>) -> Result<SignerInfoParsed, SignedObjectParseError> {
|
||||
fn parse_signer_info_cursor(
|
||||
mut seq: DerReader<'_>,
|
||||
) -> Result<SignerInfoParsed, SignedObjectParseError> {
|
||||
let version = seq
|
||||
.take_uint_u64()
|
||||
.map_err(|e| SignedObjectParseError::Parse(e.to_string()))?;
|
||||
@@ -880,10 +888,9 @@ fn parse_signed_attrs_implicit(
|
||||
}
|
||||
};
|
||||
if count != 1 {
|
||||
return Err(SignedObjectValidateError::InvalidSignedAttributeValuesCount {
|
||||
oid,
|
||||
count,
|
||||
});
|
||||
return Err(
|
||||
SignedObjectValidateError::InvalidSignedAttributeValuesCount { oid, count },
|
||||
);
|
||||
}
|
||||
|
||||
// Re-parse the sole value.
|
||||
@@ -938,7 +945,10 @@ fn parse_signed_attrs_implicit(
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_signing_time_value_tlv(tag: u8, value: &[u8]) -> Result<Asn1TimeUtc, SignedObjectValidateError> {
|
||||
fn parse_signing_time_value_tlv(
|
||||
tag: u8,
|
||||
value: &[u8],
|
||||
) -> Result<Asn1TimeUtc, SignedObjectValidateError> {
|
||||
match tag {
|
||||
0x17 => Ok(Asn1TimeUtc {
|
||||
utc: parse_utctime(value)?,
|
||||
@@ -1070,7 +1080,8 @@ fn parse_algorithm_identifier_cursor(
|
||||
}
|
||||
|
||||
fn parse_utctime(value: &[u8]) -> Result<time::OffsetDateTime, SignedObjectValidateError> {
|
||||
let s = std::str::from_utf8(value).map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let s = std::str::from_utf8(value)
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
if !s.ends_with('Z') {
|
||||
return Err(SignedObjectValidateError::InvalidSigningTimeValue);
|
||||
}
|
||||
@@ -1081,25 +1092,41 @@ fn parse_utctime(value: &[u8]) -> Result<time::OffsetDateTime, SignedObjectValid
|
||||
if !digits.as_bytes().iter().all(|b| b.is_ascii_digit()) {
|
||||
return Err(SignedObjectValidateError::InvalidSigningTimeValue);
|
||||
}
|
||||
let yy: i32 = digits[0..2].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let yy: i32 = digits[0..2]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let year = if yy <= 49 { 2000 + yy } else { 1900 + yy };
|
||||
let mon: u8 = digits[2..4].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let day: u8 = digits[4..6].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let hour: u8 = digits[6..8].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let min: u8 = digits[8..10].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let mon: u8 = digits[2..4]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let day: u8 = digits[4..6]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let hour: u8 = digits[6..8]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let min: u8 = digits[8..10]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let sec: u8 = if digits.len() == 12 {
|
||||
digits[10..12].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?
|
||||
digits[10..12]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let month = time::Month::try_from(mon).map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let date = time::Date::from_calendar_date(year, month, day).map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let time = time::Time::from_hms(hour, min, sec).map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let month = time::Month::try_from(mon)
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let date = time::Date::from_calendar_date(year, month, day)
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let time = time::Time::from_hms(hour, min, sec)
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
Ok(time::OffsetDateTime::new_utc(date, time))
|
||||
}
|
||||
|
||||
fn parse_generalized_time(value: &[u8]) -> Result<time::OffsetDateTime, SignedObjectValidateError> {
|
||||
let s = std::str::from_utf8(value).map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let s = std::str::from_utf8(value)
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
if !s.ends_with('Z') {
|
||||
return Err(SignedObjectValidateError::InvalidSigningTimeValue);
|
||||
}
|
||||
@@ -1110,19 +1137,34 @@ fn parse_generalized_time(value: &[u8]) -> Result<time::OffsetDateTime, SignedOb
|
||||
if !digits.as_bytes().iter().all(|b| b.is_ascii_digit()) {
|
||||
return Err(SignedObjectValidateError::InvalidSigningTimeValue);
|
||||
}
|
||||
let year: i32 = digits[0..4].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let mon: u8 = digits[4..6].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let day: u8 = digits[6..8].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let hour: u8 = digits[8..10].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let min: u8 = digits[10..12].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let year: i32 = digits[0..4]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let mon: u8 = digits[4..6]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let day: u8 = digits[6..8]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let hour: u8 = digits[8..10]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let min: u8 = digits[10..12]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let sec: u8 = if digits.len() == 14 {
|
||||
digits[12..14].parse().map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?
|
||||
digits[12..14]
|
||||
.parse()
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let month = time::Month::try_from(mon).map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let date = time::Date::from_calendar_date(year, month, day).map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let time = time::Time::from_hms(hour, min, sec).map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let month = time::Month::try_from(mon)
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let date = time::Date::from_calendar_date(year, month, day)
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
let time = time::Time::from_hms(hour, min, sec)
|
||||
.map_err(|_| SignedObjectValidateError::InvalidSigningTimeValue)?;
|
||||
Ok(time::OffsetDateTime::new_utc(date, time))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user