20260711 完善资源证书基础profile校验
This commit is contained in:
@@ -3,7 +3,8 @@ use crate::data_model::crl::{CrlDecodeError, CrlVerifyError, RpkixCrl};
|
||||
use crate::data_model::oid::OID_KEY_USAGE_RAW;
|
||||
use crate::data_model::rc::{
|
||||
AsIdentifierChoice, AsResourceSet, IpAddressChoice, IpResourceSet, ResourceCertKind,
|
||||
ResourceCertificate, ResourceCertificateDecodeError,
|
||||
ResourceCertificate, ResourceCertificateDecodeError, ResourceCertificateProfileError,
|
||||
ResourceCertificateRole,
|
||||
};
|
||||
use crate::policy::ResourceValidationMode;
|
||||
use x509_parser::prelude::{FromDer, X509Certificate};
|
||||
@@ -108,6 +109,12 @@ pub enum CaPathError {
|
||||
#[error("issuer CA certificate decode failed: {0} (RFC 6487 §4; RFC 5280 §4.1)")]
|
||||
IssuerDecode(ResourceCertificateDecodeError),
|
||||
|
||||
#[error("child CA certificate profile validation failed: {0} (RFC 6487 §4.8)")]
|
||||
ChildProfile(ResourceCertificateProfileError),
|
||||
|
||||
#[error("issuer CA certificate profile validation failed: {0} (RFC 6487 §4.8)")]
|
||||
IssuerProfile(ResourceCertificateProfileError),
|
||||
|
||||
#[error("issuer CRL decode failed: {0} (RFC 6487 §5; RFC 9829 §3.1; RFC 5280 §5.1)")]
|
||||
CrlDecode(#[from] CrlDecodeError),
|
||||
|
||||
@@ -244,12 +251,18 @@ pub fn validate_subordinate_ca_cert_with_resource_validation_mode(
|
||||
if child_ca.kind != ResourceCertKind::Ca {
|
||||
return Err(CaPathError::ChildNotCa);
|
||||
}
|
||||
child_ca
|
||||
.validate_rfc6487_profile(ResourceCertificateRole::Ca)
|
||||
.map_err(CaPathError::ChildProfile)?;
|
||||
|
||||
let issuer_ca =
|
||||
ResourceCertificate::decode_der(issuer_ca_der).map_err(CaPathError::IssuerDecode)?;
|
||||
if issuer_ca.kind != ResourceCertKind::Ca {
|
||||
return Err(CaPathError::IssuerNotCa);
|
||||
}
|
||||
issuer_ca
|
||||
.validate_rfc6487_profile(ResourceCertificateRole::Ca)
|
||||
.map_err(CaPathError::IssuerProfile)?;
|
||||
let issuer_spki = parse_subject_pki_from_der(&issuer_ca.tbs.subject_public_key_info)?;
|
||||
|
||||
if !x509_names_equivalent(&child_ca.tbs.issuer_name, &issuer_ca.tbs.subject_name) {
|
||||
@@ -379,6 +392,12 @@ pub fn validate_subordinate_ca_cert_with_prevalidated_issuer_and_resources(
|
||||
if issuer_ca.kind != ResourceCertKind::Ca {
|
||||
return Err(CaPathError::IssuerNotCa);
|
||||
}
|
||||
child_ca
|
||||
.validate_rfc6487_profile(ResourceCertificateRole::Ca)
|
||||
.map_err(CaPathError::ChildProfile)?;
|
||||
issuer_ca
|
||||
.validate_rfc6487_profile(ResourceCertificateRole::Ca)
|
||||
.map_err(CaPathError::IssuerProfile)?;
|
||||
|
||||
if !x509_names_equivalent(&child_ca.tbs.issuer_name, &issuer_ca.tbs.subject_name) {
|
||||
return Err(CaPathError::IssuerSubjectMismatch {
|
||||
@@ -1375,12 +1394,14 @@ fn bytes_leq(a: &[u8], b: &[u8]) -> bool {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::data_model::common::X509NameDer;
|
||||
use crate::data_model::oid::OID_CP_IPADDR_ASNUMBER;
|
||||
use crate::data_model::rc::{
|
||||
Afi, AsIdOrRange, AsIdentifierChoice, AsResourceSet, IpAddressChoice, IpAddressFamily,
|
||||
IpAddressOrRange, IpPrefix, IpResourceSet,
|
||||
};
|
||||
use crate::data_model::rc::{
|
||||
RcExtensions, ResourceCertKind, ResourceCertificate, RpkixTbsCertificate,
|
||||
BasicConstraintsProfile, CertificatePoliciesProfile, RcExtensions, ResourceCertKind,
|
||||
ResourceCertificate, RpkixTbsCertificate,
|
||||
};
|
||||
use der_parser::num_bigint::BigUint;
|
||||
use std::process::Command;
|
||||
@@ -1410,12 +1431,27 @@ mod tests {
|
||||
subject_public_key_info: Vec::new(),
|
||||
extensions: RcExtensions {
|
||||
basic_constraints_ca: kind == ResourceCertKind::Ca,
|
||||
basic_constraints: (kind == ResourceCertKind::Ca).then_some(
|
||||
BasicConstraintsProfile {
|
||||
ca: true,
|
||||
critical: true,
|
||||
path_len_constraint: None,
|
||||
},
|
||||
),
|
||||
subject_key_identifier: ski,
|
||||
authority_key_identifier: aki,
|
||||
crl_distribution_points_uris: crldp,
|
||||
ca_issuers_uris: aia,
|
||||
subject_info_access: None,
|
||||
certificate_policies_oid: None,
|
||||
certificate_policies_oid: (kind == ResourceCertKind::Ca)
|
||||
.then_some(OID_CP_IPADDR_ASNUMBER.to_string()),
|
||||
certificate_policies: (kind == ResourceCertKind::Ca).then_some(
|
||||
CertificatePoliciesProfile {
|
||||
policy_oid: OID_CP_IPADDR_ASNUMBER.to_string(),
|
||||
qualifier_oids: Vec::new(),
|
||||
},
|
||||
),
|
||||
extension_oids: Vec::new(),
|
||||
ip_resources: None,
|
||||
as_resources: None,
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::data_model::common::BigUnsigned;
|
||||
use crate::data_model::crl::{CrlDecodeError, CrlVerifyError, RpkixCrl};
|
||||
use crate::data_model::rc::{
|
||||
ResourceCertKind, ResourceCertificate, ResourceCertificateDecodeError,
|
||||
ResourceCertificateProfileError, ResourceCertificateRole,
|
||||
};
|
||||
use crate::data_model::signed_object::{EeKeyUsageSummary, ResourceEeCertificate};
|
||||
use ring::signature;
|
||||
@@ -34,6 +35,9 @@ pub enum CertPathError {
|
||||
)]
|
||||
IssuerNotCa,
|
||||
|
||||
#[error("issuer CA certificate profile validation failed: {0} (RFC 6487 §4.8)")]
|
||||
IssuerProfile(ResourceCertificateProfileError),
|
||||
|
||||
#[error("EE certificate must be an EE resource certificate (RFC 6487 §4)")]
|
||||
EeNotEe,
|
||||
|
||||
@@ -128,6 +132,9 @@ pub fn validate_ee_cert_path(
|
||||
if issuer_ca.kind != ResourceCertKind::Ca {
|
||||
return Err(CertPathError::IssuerNotCa);
|
||||
}
|
||||
issuer_ca
|
||||
.validate_rfc6487_profile(ResourceCertificateRole::Ca)
|
||||
.map_err(CertPathError::IssuerProfile)?;
|
||||
let issuer_spki = parse_subject_pki_from_der(&issuer_ca.tbs.subject_public_key_info)?;
|
||||
|
||||
if !x509_names_equivalent(&ee.tbs.issuer_name, &issuer_ca.tbs.subject_name) {
|
||||
@@ -311,6 +318,9 @@ fn validate_ee_cert_path_bindings_and_status(
|
||||
if issuer_ca.kind != ResourceCertKind::Ca {
|
||||
return Err(CertPathError::IssuerNotCa);
|
||||
}
|
||||
issuer_ca
|
||||
.validate_rfc6487_profile(ResourceCertificateRole::Ca)
|
||||
.map_err(CertPathError::IssuerProfile)?;
|
||||
|
||||
if !x509_names_equivalent(&ee.tbs.issuer_name, &issuer_ca.tbs.subject_name) {
|
||||
return Err(CertPathError::IssuerSubjectMismatch {
|
||||
@@ -515,8 +525,10 @@ fn is_serial_revoked_by_crl(ee: &ResourceCertificate, crl: &RpkixCrl) -> bool {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::data_model::common::X509NameDer;
|
||||
use crate::data_model::oid::OID_CP_IPADDR_ASNUMBER;
|
||||
use crate::data_model::rc::{
|
||||
RcExtensions, ResourceCertKind, ResourceCertificate, RpkixTbsCertificate,
|
||||
BasicConstraintsProfile, CertificatePoliciesProfile, RcExtensions, ResourceCertKind,
|
||||
ResourceCertificate, RpkixTbsCertificate,
|
||||
};
|
||||
use der_parser::num_bigint::BigUint;
|
||||
|
||||
@@ -545,12 +557,27 @@ mod tests {
|
||||
subject_public_key_info: Vec::new(),
|
||||
extensions: RcExtensions {
|
||||
basic_constraints_ca: kind == ResourceCertKind::Ca,
|
||||
basic_constraints: (kind == ResourceCertKind::Ca).then_some(
|
||||
BasicConstraintsProfile {
|
||||
ca: true,
|
||||
critical: true,
|
||||
path_len_constraint: None,
|
||||
},
|
||||
),
|
||||
subject_key_identifier: ski,
|
||||
authority_key_identifier: aki,
|
||||
crl_distribution_points_uris: crldp,
|
||||
ca_issuers_uris: aia,
|
||||
subject_info_access: None,
|
||||
certificate_policies_oid: None,
|
||||
certificate_policies_oid: (kind == ResourceCertKind::Ca)
|
||||
.then_some(OID_CP_IPADDR_ASNUMBER.to_string()),
|
||||
certificate_policies: (kind == ResourceCertKind::Ca).then_some(
|
||||
CertificatePoliciesProfile {
|
||||
policy_oid: OID_CP_IPADDR_ASNUMBER.to_string(),
|
||||
qualifier_oids: Vec::new(),
|
||||
},
|
||||
),
|
||||
extension_oids: Vec::new(),
|
||||
ip_resources: None,
|
||||
as_resources: None,
|
||||
},
|
||||
|
||||
@@ -2316,8 +2316,18 @@ fn discover_children_from_fresh_snapshot_with_audit_cached_with_issuer_der<
|
||||
let issuer_ca_decode_error: Option<String>;
|
||||
let issuer_ca = match crate::data_model::rc::ResourceCertificate::decode_der(issuer_ca_der) {
|
||||
Ok(v) => {
|
||||
issuer_ca_decode_error = None;
|
||||
Some(v)
|
||||
match v.validate_rfc6487_profile(crate::data_model::rc::ResourceCertificateRole::Ca) {
|
||||
Ok(()) => {
|
||||
issuer_ca_decode_error = None;
|
||||
Some(v)
|
||||
}
|
||||
Err(e) => {
|
||||
issuer_ca_decode_error = Some(format!(
|
||||
"issuer CA profile validation failed: {e} (RFC 6487 §4.8)"
|
||||
));
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
issuer_ca_decode_error = Some(format!(
|
||||
|
||||
Reference in New Issue
Block a user