RC证书解析部分代码
This commit is contained in:
parent
421847d329
commit
da14f26acb
@ -10,3 +10,6 @@ thiserror = "2.0.18"
|
|||||||
time = "0.3.45"
|
time = "0.3.45"
|
||||||
x509-parser = { version = "0.18.0", features = ["verify"] }
|
x509-parser = { version = "0.18.0", features = ["verify"] }
|
||||||
url = "2.5.8"
|
url = "2.5.8"
|
||||||
|
asn1-rs = "0.7.1"
|
||||||
|
asn1-rs-derive = "0.6.0"
|
||||||
|
asn1 = "0.23.0"
|
||||||
|
|||||||
@ -11,3 +11,6 @@ pub const OID_AD_OCSP: &str = "1.3.6.1.5.5.7.48.1";
|
|||||||
pub const OID_SUBJECT_INFO_ACCESS: &str = "1.3.6.1.5.5.7.1.11";
|
pub const OID_SUBJECT_INFO_ACCESS: &str = "1.3.6.1.5.5.7.1.11";
|
||||||
pub const OID_CERTIFICATE_POLICIES: &str = "2.5.29.32";
|
pub const OID_CERTIFICATE_POLICIES: &str = "2.5.29.32";
|
||||||
pub const OID_SHA256_WITH_RSA_ENCRYPTION: &str = "1.2.840.113549.1.1.11";
|
pub const OID_SHA256_WITH_RSA_ENCRYPTION: &str = "1.2.840.113549.1.1.11";
|
||||||
|
pub const OID_IP_ADDRESS_BLOCKS: &str = "1.3.6.1.5.5.7.1.7";
|
||||||
|
pub const OID_AS_IDENTIFIERS: &str = "1.3.6.1.5.5.7.1.8";
|
||||||
|
pub const OID_RPKI_CP: &str = "1.3.6.1.5.5.7.14.2";
|
||||||
@ -1,13 +1,17 @@
|
|||||||
|
use asn1::{parse, BitString};
|
||||||
use der_parser::asn1_rs::Tag;
|
use der_parser::asn1_rs::Tag;
|
||||||
use der_parser::num_bigint::BigUint;
|
use der_parser::num_bigint::BigUint;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
use url::quirks::password;
|
||||||
use x509_parser::x509::AlgorithmIdentifier;
|
use x509_parser::x509::AlgorithmIdentifier;
|
||||||
use x509_parser::prelude::{Validity, KeyUsage, X509Certificate, FromDer,
|
use x509_parser::prelude::{Validity, KeyUsage, X509Certificate, FromDer,
|
||||||
X509Version, X509Extension, ParsedExtension,
|
X509Version, X509Extension, ParsedExtension,
|
||||||
CRLDistributionPoints, DistributionPointName, GeneralName};
|
DistributionPointName, GeneralName};
|
||||||
use crate::data_model::crl::CrlDecodeError;
|
use crate::data_model::crl::CrlDecodeError;
|
||||||
use crate::data_model::resources::ip_resources::IPAddrBlocks;
|
use crate::data_model::resources::ip_resources::{Afi, IPAddrBlocks, IPAddress, IPAddressChoice,
|
||||||
|
IPAddressOrRange, IPAddressPrefix, IPAddressRange,
|
||||||
|
IPAddressFamily};
|
||||||
use crate::data_model::resources::as_resources::ASIdentifiers;
|
use crate::data_model::resources::as_resources::ASIdentifiers;
|
||||||
use crate::data_model::oids;
|
use crate::data_model::oids;
|
||||||
|
|
||||||
@ -127,393 +131,510 @@ pub enum ResourceCertError {
|
|||||||
#[error("Empty AuthorityInfoAccess!")]
|
#[error("Empty AuthorityInfoAccess!")]
|
||||||
EmptyAuthorityInfoAccess,
|
EmptyAuthorityInfoAccess,
|
||||||
|
|
||||||
|
#[error("Certificate Policies must exists one policy")]
|
||||||
|
CertificatePoliciesTooMany,
|
||||||
|
|
||||||
|
#[error("Certificate Policies invalid")]
|
||||||
|
CertificatePoliciesInvalid,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl ResourceCert{
|
impl ResourceCert{
|
||||||
// pub fn from_der(cert_der: &[u8]) -> Result<Self, ResourceCertError> {
|
pub fn from_der(cert_der: &[u8]) -> Result<Self, ResourceCertError> {
|
||||||
// let (rem, x509_rc) = X509Certificate::from_der(cert_der)
|
let (rem, x509_rc) = X509Certificate::from_der(cert_der)
|
||||||
// .map_err(|e| ResourceCertError::ParseCert(e.to_string()))?;
|
.map_err(|e| ResourceCertError::ParseCert(e.to_string()))?;
|
||||||
//
|
|
||||||
// if !rem.is_empty() {
|
if !rem.is_empty() {
|
||||||
// return Err(ResourceCertError::TrailingBytes(rem.len()));
|
return Err(ResourceCertError::TrailingBytes(rem.len()));
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// // 校验
|
// 校验
|
||||||
// parse_and_validate_cert(x509_rc)
|
parse_and_validate_cert(x509_rc)
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// fn parse_and_validate_cert(x509_rc: X509Certificate) -> Result<ResourceCert, ResourceCertError> {
|
fn parse_and_validate_cert(x509_rc: X509Certificate) -> Result<ResourceCert, ResourceCertError> {
|
||||||
// ///逐个校验RC的内容, 如果有任何一个校验失败, 则返回错误
|
///逐个校验RC的内容, 如果有任何一个校验失败, 则返回错误
|
||||||
//
|
|
||||||
// // 1. 版本号必须是V3
|
// 1. 版本号必须是V3
|
||||||
// let version = match x509_rc.version() {
|
let version = match x509_rc.version() {
|
||||||
// X509Version::V3 => X509Version::V3,
|
X509Version::V3 => X509Version::V3,
|
||||||
// v => {
|
v => {
|
||||||
// return Err(ResourceCertError::InvalidVersion(v.0));
|
return Err(ResourceCertError::InvalidVersion(v.0));
|
||||||
// }
|
}
|
||||||
// };
|
};
|
||||||
//
|
|
||||||
// // 2.校验签名算法
|
// 2.校验签名算法
|
||||||
// // 2.1. 校验外层的签名算法与里层的一致
|
// 2.1. 校验外层的签名算法与里层的一致
|
||||||
// let outer = &x509_rc.signature_algorithm;
|
let outer = &x509_rc.signature_algorithm;
|
||||||
// let inner = &x509_rc.tbs_certificate.signature;
|
let inner = &x509_rc.tbs_certificate.signature;
|
||||||
//
|
|
||||||
// if outer.algorithm != inner.algorithm || outer.parameters != inner.parameters {
|
if outer.algorithm != inner.algorithm || outer.parameters != inner.parameters {
|
||||||
// return Err(ResourceCertError::SignatureAlgorithmMismatch);
|
return Err(ResourceCertError::SignatureAlgorithmMismatch);
|
||||||
// }
|
}
|
||||||
// //2.2 RPKI的签名算法必须是rsaWithSHA256
|
//2.2 RPKI的签名算法必须是rsaWithSHA256
|
||||||
// let signature_algorithm = &x509_rc.signature_algorithm;
|
let signature_algorithm = &x509_rc.signature_algorithm;
|
||||||
// if signature_algorithm.algorithm.to_id_string() != oids::OID_SHA256_WITH_RSA_ENCRYPTION {
|
if signature_algorithm.algorithm.to_id_string() != oids::OID_SHA256_WITH_RSA_ENCRYPTION {
|
||||||
// return Err(ResourceCertError::UnsupportedSignatureAlgorithm);
|
return Err(ResourceCertError::UnsupportedSignatureAlgorithm);
|
||||||
// }
|
}
|
||||||
// validate_sig_params(signature_algorithm)?;
|
validate_sig_params(signature_algorithm)?;
|
||||||
//
|
|
||||||
// // 3. 校验Validity
|
// 3. 校验Validity
|
||||||
// let validity = x509_rc.validity();
|
let validity = x509_rc.validity();
|
||||||
// validate_validity(validity, OffsetDateTime::now_utc())?;
|
validate_validity(validity, OffsetDateTime::now_utc())?;
|
||||||
//
|
|
||||||
// // 4. SubjectPublicKeyInfo
|
// 4. SubjectPublicKeyInfo
|
||||||
// let subject_public_key_info = x509_rc.tbs_certificate.subject_pki;
|
let subject_public_key_info = x509_rc.tbs_certificate.subject_pki;
|
||||||
//
|
|
||||||
// let extensions = parse_and_validate_extensions(x509_rc.extensions())?;
|
let extensions = parse_and_validate_extensions(x509_rc.extensions())?;
|
||||||
//
|
|
||||||
// Ok(ResourceCert {
|
// TODO
|
||||||
// cert_der: x509_rc.to_der().to_vec(),
|
Ok(ResourceCert {
|
||||||
// version: version.0,
|
|
||||||
// serial_number: x509_rc.serial(),
|
})
|
||||||
// signature_algorithm_oid: signature_algorithm.algorithm.to_id_string(),
|
|
||||||
// issuer_dn: x509_rc.issuer().to_string(),
|
|
||||||
// subject_dn: x509_rc.subject().to_string(),
|
}
|
||||||
// validity,
|
|
||||||
// subject_public_key_info: SubjectPublicKeyInfo {
|
fn validate_sig_params(sig: &AlgorithmIdentifier<'_>) -> Result<(), CrlDecodeError> {
|
||||||
// // algorithm_oid: x509_rc.tbs_certificate.subject_pki.algorithm.algorithm.to_id_string(),
|
match sig.parameters.as_ref() {
|
||||||
// // subject_public_key: x509_rc.tbs_certificate.subject_pki.subject_public_key.unused_bits,
|
None => Ok(()),
|
||||||
// },
|
Some(p) if p.tag() == Tag::Null => Ok(()),
|
||||||
// extensions,
|
Some(_p) => Err(CrlDecodeError::InvalidSignatureAlgorithmParameters),
|
||||||
// })
|
}
|
||||||
//
|
}
|
||||||
//
|
|
||||||
// }
|
fn validate_validity(
|
||||||
//
|
validity: &Validity,
|
||||||
// fn validate_sig_params(sig: &AlgorithmIdentifier<'_>) -> Result<(), CrlDecodeError> {
|
now: OffsetDateTime,
|
||||||
// match sig.parameters.as_ref() {
|
) -> Result<(), ResourceCertError> {
|
||||||
// None => Ok(()),
|
let not_before = validity.not_before.to_datetime();
|
||||||
// Some(p) if p.tag() == Tag::Null => Ok(()),
|
let not_after = validity.not_after.to_datetime();
|
||||||
// Some(_p) => Err(CrlDecodeError::InvalidSignatureAlgorithmParameters),
|
|
||||||
// }
|
if not_after < not_before {
|
||||||
// }
|
return Err(ResourceCertError::InvalidValidityRange);
|
||||||
//
|
}
|
||||||
// fn validate_validity(
|
|
||||||
// validity: &Validity,
|
if now < not_before {
|
||||||
// now: OffsetDateTime,
|
return Err(ResourceCertError::NotYetValid);
|
||||||
// ) -> Result<(), ResourceCertError> {
|
}
|
||||||
// let not_before = validity.not_before.to_datetime();
|
|
||||||
// let not_after = validity.not_after.to_datetime();
|
if now > not_after {
|
||||||
//
|
return Err(ResourceCertError::Expired);
|
||||||
// if not_after < not_before {
|
}
|
||||||
// return Err(ResourceCertError::InvalidValidityRange);
|
|
||||||
// }
|
Ok(())
|
||||||
//
|
}
|
||||||
// if now < not_before {
|
|
||||||
// return Err(ResourceCertError::NotYetValid);
|
|
||||||
// }
|
pub fn parse_and_validate_extensions(
|
||||||
//
|
exts: &[X509Extension<'_>],
|
||||||
// if now > not_after {
|
) -> Result<RcExtension, ResourceCertError> {
|
||||||
// return Err(ResourceCertError::Expired);
|
let mut basic_constraints = None;
|
||||||
// }
|
let mut ip_addr_blocks = None;
|
||||||
//
|
let mut as_identifiers = None;
|
||||||
// Ok(())
|
let mut ski = None;
|
||||||
// }
|
let mut aki = None;
|
||||||
//
|
let mut crl_dp = None;
|
||||||
//
|
let mut aia = None;
|
||||||
// pub fn parse_and_validate_extensions(
|
let mut sia = None;
|
||||||
// exts: &[X509Extension<'_>],
|
let mut key_usage = None;
|
||||||
// ) -> Result<RcExtension, ResourceCertError> {
|
let mut extended_key_usage = None;
|
||||||
// let mut basic_constraints = None;
|
let mut certificate_policies = None;
|
||||||
// let mut ip_addr_blocks = None;
|
|
||||||
// let mut as_identifiers = None;
|
for ext in exts {
|
||||||
// let mut ski = None;
|
let oid = ext.oid.to_id_string();
|
||||||
// let mut aki = None;
|
let critical = ext.critical;
|
||||||
// let mut crl_dp = None;
|
match oid.as_str() {
|
||||||
// let mut aia = None;
|
oids::OID_BASIC_CONSTRAINTS => {
|
||||||
// let mut sia = None;
|
if basic_constraints.is_some() {
|
||||||
// let mut key_usage = None;
|
return Err(ResourceCertError::DuplicateExtension("basicConstraints".into()));
|
||||||
// let mut extended_key_usage = None;
|
}
|
||||||
// let mut certificate_policies = None;
|
if !critical {
|
||||||
//
|
return Err(ResourceCertError::CriticalError("basicConstraints".into(), "critical".into()));
|
||||||
// for ext in exts {
|
}
|
||||||
// let oid = ext.oid.to_id_string();
|
let bc = parse_basic_constraints(ext)?;
|
||||||
// let critical = ext.critical;
|
basic_constraints = Some(bc);
|
||||||
// match oid.as_str() {
|
}
|
||||||
// oids::OID_BASIC_CONSTRAINTS => {
|
oids::OID_SUBJECT_KEY_IDENTIFIER => {
|
||||||
// if basic_constraints.is_some() {
|
if ski.is_some() {
|
||||||
// return Err(ResourceCertError::DuplicateExtension("basicConstraints".into()));
|
return Err(ResourceCertError::DuplicateExtension("subjectKeyIdentifier".into()));
|
||||||
// }
|
}
|
||||||
// if !critical {
|
if critical {
|
||||||
// return Err(ResourceCertError::CriticalError("basicConstraints".into(), "critical".into()));
|
return Err(ResourceCertError::CriticalError("subjectKeyIdentifier".into(), "non-critical".into()));
|
||||||
// }
|
}
|
||||||
// let bc = parse_basic_constraints(ext)?;
|
let s = parse_subject_key_identifier(ext)?;
|
||||||
// basic_constraints = Some(bc);
|
ski = Some(s);
|
||||||
// }
|
}
|
||||||
// oids::OID_SUBJECT_KEY_IDENTIFIER => {
|
oids::OID_AUTHORITY_KEY_IDENTIFIER => {
|
||||||
// if ski.is_some() {
|
if aki.is_some() {
|
||||||
// return Err(ResourceCertError::DuplicateExtension("subjectKeyIdentifier".into()));
|
return Err(ResourceCertError::DuplicateExtension("authorityKeyIdentifier".into()));
|
||||||
// }
|
}
|
||||||
// if critical {
|
if critical {
|
||||||
// return Err(ResourceCertError::CriticalError("subjectKeyIdentifier".into(), "non-critical".into()));
|
return Err(ResourceCertError::CriticalError("authorityKeyIdentifier".into(), "non-critical".into()));
|
||||||
// }
|
}
|
||||||
// let s = parse_subject_key_identifier(ext)?;
|
let a = parse_authority_key_identifier(ext)?;
|
||||||
// ski = Some(s);
|
aki = Some(a);
|
||||||
// }
|
}
|
||||||
// oids::OID_AUTHORITY_KEY_IDENTIFIER => {
|
oids::OID_KEY_USAGE => {
|
||||||
// if aki.is_some() {
|
if key_usage.is_some() {
|
||||||
// return Err(ResourceCertError::DuplicateExtension("authorityKeyIdentifier".into()));
|
return Err(ResourceCertError::DuplicateExtension("keyUsage".into()));
|
||||||
// }
|
}
|
||||||
// if critical {
|
if !critical {
|
||||||
// return Err(ResourceCertError::CriticalError("authorityKeyIdentifier".into(), "non-critical".into()));
|
return Err(ResourceCertError::CriticalError("keyUsage".into(), "critical".into()));
|
||||||
// }
|
}
|
||||||
// let a = parse_authority_key_identifier(ext)?;
|
let ku = parse_key_usage(ext)?;
|
||||||
// aki = Some(a);
|
key_usage = Some(ku);
|
||||||
// }
|
}
|
||||||
// oids::OID_KEY_USAGE => {
|
oids::OID_EXTENDED_KEY_USAGE => {
|
||||||
// if key_usage.is_some() {
|
if extended_key_usage.is_some() {
|
||||||
// return Err(ResourceCertError::DuplicateExtension("keyUsage".into()));
|
return Err(ResourceCertError::DuplicateExtension("extendedKeyUsage".into()));
|
||||||
// }
|
}
|
||||||
// if !critical {
|
if critical {
|
||||||
// return Err(ResourceCertError::CriticalError("keyUsage".into(), "critical".into()));
|
return Err(ResourceCertError::CriticalError("extendedKeyUsage".into(), "non-critical".into()));
|
||||||
// }
|
}
|
||||||
// let ku = parse_key_usage(ext)?;
|
let eku = oids::OID_EXTENDED_KEY_USAGE;
|
||||||
// key_usage = Some(ku);
|
}
|
||||||
// }
|
oids::OID_CRL_DISTRIBUTION_POINTS => {
|
||||||
// oids::OID_EXTENDED_KEY_USAGE => {
|
if crl_dp.is_some() {
|
||||||
// if extended_key_usage.is_some() {
|
return Err(ResourceCertError::DuplicateExtension("crlDistributionPoints".into()));
|
||||||
// return Err(ResourceCertError::DuplicateExtension("extendedKeyUsage".into()));
|
}
|
||||||
// }
|
if critical {
|
||||||
// if critical {
|
return Err(ResourceCertError::CriticalError("crlDistributionPoints".into(), "non-critical".into()));
|
||||||
// return Err(ResourceCertError::CriticalError("extendedKeyUsage".into(), "non-critical".into()));
|
}
|
||||||
// }
|
let cdp = parse_crl_distribution_points(ext)?;
|
||||||
// let eku = oids::OID_EXTENDED_KEY_USAGE;
|
crl_dp = Some(cdp);
|
||||||
// }
|
}
|
||||||
// oids::OID_CRL_DISTRIBUTION_POINTS => {
|
oids::OID_AUTHORITY_INFO_ACCESS => {
|
||||||
// if crl_dp.is_some() {
|
if aia.is_some() {
|
||||||
// return Err(ResourceCertError::DuplicateExtension("crlDistributionPoints".into()));
|
return Err(ResourceCertError::DuplicateExtension("authorityInfoAccess".into()));
|
||||||
// }
|
}
|
||||||
// if critical {
|
if critical {
|
||||||
// return Err(ResourceCertError::CriticalError("crlDistributionPoints".into(), "non-critical".into()));
|
return Err(ResourceCertError::CriticalError("authorityInfoAccess".into(), "non-critical".into()));
|
||||||
// }
|
}
|
||||||
// let cdp = parse_crl_distribution_points(ext)?;
|
let p_aia = parse_authority_info_access(ext)?;
|
||||||
// crl_dp = Some(cdp);
|
aia = Some(p_aia);
|
||||||
// }
|
}
|
||||||
// oids::OID_AUTHORITY_INFO_ACCESS => {
|
oids::OID_SUBJECT_INFO_ACCESS => {
|
||||||
// if aia.is_some() {
|
if sia.is_some() {
|
||||||
// return Err(ResourceCertError::DuplicateExtension("authorityInfoAccess".into()));
|
return Err(ResourceCertError::DuplicateExtension("subjectInfoAccess".into()));
|
||||||
// }
|
}
|
||||||
// if critical {
|
if critical {
|
||||||
// return Err(ResourceCertError::CriticalError("authorityInfoAccess".into(), "non-critical".into()));
|
return Err(ResourceCertError::CriticalError("subjectInfoAccess".into(), "non-critical".into()));
|
||||||
// }
|
}
|
||||||
// let p_aia = parse_authority_info_access(ext)?;
|
let p_sia = parse_subject_info_access(ext)?;
|
||||||
// aia = Some(p_aia);
|
sia = Some(p_sia);
|
||||||
// }
|
}
|
||||||
// oids::OID_SUBJECT_INFO_ACCESS => {
|
oids::OID_CERTIFICATE_POLICIES => {
|
||||||
// if sia.is_some() {
|
if certificate_policies.is_some() {
|
||||||
// return Err(ResourceCertError::DuplicateExtension("subjectInfoAccess".into()));
|
return Err(ResourceCertError::DuplicateExtension("certificatePolicies".into()));
|
||||||
// }
|
}
|
||||||
// if critical {
|
if !critical {
|
||||||
// return Err(ResourceCertError::CriticalError("subjectInfoAccess".into(), "non-critical".into()));
|
return Err(ResourceCertError::CriticalError("certificatePolicies".into(), "critical".into()));
|
||||||
// }
|
}
|
||||||
// let p_sia = parse_subject_info_access(ext)?;
|
let p_cp = parse_certificate_policies(ext)?;
|
||||||
// sia = Some(p_sia);
|
certificate_policies = Some(p_cp);
|
||||||
// }
|
}
|
||||||
// oids::OID_CERTIFICATE_POLICIES => {
|
oids::OID_IP_ADDRESS_BLOCKS => {
|
||||||
// if certificate_policies.is_some() {
|
if ip_addr_blocks.is_some() {
|
||||||
// return Err(ResourceCertError::DuplicateExtension("certificatePolicies".into()));
|
return Err(ResourceCertError::DuplicateExtension("ipAddressBlocks".into()));
|
||||||
// }
|
}
|
||||||
// if !critical {
|
if !critical {
|
||||||
// return Err(ResourceCertError::CriticalError("certificatePolicies".into(), "critical".into()));
|
return Err(ResourceCertError::CriticalError("ipAddressBlocks".into(), "critical".into()));
|
||||||
// }
|
}
|
||||||
// let p_cp = parse_certificate_policies(ext)?;
|
let p_ip = parse_ip_address_blocks(ext)?;
|
||||||
// certificate_policies = Some(p_cp);
|
ip_addr_blocks = Some(p_ip);
|
||||||
// }
|
}
|
||||||
// }
|
oids::OID_AS_IDENTIFIERS => {
|
||||||
//
|
if as_identifiers.is_some() {
|
||||||
//
|
return Err(ResourceCertError::DuplicateExtension("asIdentifiers".into()));
|
||||||
// }
|
}
|
||||||
// Ok(RcExtension {
|
if !critical {
|
||||||
// basic_constraints,
|
return Err(ResourceCertError::CriticalError("asIdentifiers".into(), "critical".into()));
|
||||||
// ip_addr_blocks,
|
}
|
||||||
// as_identifiers,
|
let p_as = parse_as_identifiers(ext)?;
|
||||||
// subject_key_id: ski,
|
as_identifiers = Some(p_as);
|
||||||
// authority_key_id: aki,
|
}
|
||||||
// crl_distribution_points: crl_dp,
|
}
|
||||||
// authority_info_access: aia,
|
}
|
||||||
// })
|
|
||||||
// }
|
// TODO:
|
||||||
//
|
Ok(RcExtension {
|
||||||
// fn parse_basic_constraints(ext: &X509Extension<'_>) -> Result<bool, ResourceCertError> {
|
|
||||||
// let ParsedExtension::BasicConstraints(bc) = ext.parsed_extension() else {
|
}
|
||||||
// return Err(ResourceCertError::ParseCert("basicConstraints parse failed".into()));
|
}
|
||||||
// };
|
|
||||||
// Ok(bc.ca)
|
fn parse_basic_constraints(ext: &X509Extension<'_>) -> Result<bool, ResourceCertError> {
|
||||||
// }
|
let ParsedExtension::BasicConstraints(bc) = ext.parsed_extension() else {
|
||||||
//
|
return Err(ResourceCertError::ParseCert("basicConstraints parse failed".into()));
|
||||||
// fn parse_subject_key_identifier(ext: &X509Extension<'_>) -> Result<Vec<u8>, ResourceCertError> {
|
};
|
||||||
// let ParsedExtension::SubjectKeyIdentifier(s) = ext.parsed_extension() else {
|
Ok(bc.ca)
|
||||||
// return Err(ResourceCertError::ParseCert("subjectKeyIdentifier parse failed".into()));
|
}
|
||||||
// };
|
|
||||||
// Ok(s.0.to_vec())
|
fn parse_subject_key_identifier(ext: &X509Extension<'_>) -> Result<Vec<u8>, ResourceCertError> {
|
||||||
// }
|
let ParsedExtension::SubjectKeyIdentifier(s) = ext.parsed_extension() else {
|
||||||
//
|
return Err(ResourceCertError::ParseCert("subjectKeyIdentifier parse failed".into()));
|
||||||
// fn parse_authority_key_identifier(ext: &X509Extension<'_>) -> Result<Vec<u8>, ResourceCertError> {
|
};
|
||||||
// let ParsedExtension::AuthorityKeyIdentifier(aki) = ext.parsed_extension() else {
|
Ok(s.0.to_vec())
|
||||||
// return Err(ResourceCertError::ParseCert("authorityKeyIdentifier parse failed".into()));
|
}
|
||||||
// };
|
|
||||||
// let key_id = aki
|
fn parse_authority_key_identifier(ext: &X509Extension<'_>) -> Result<Vec<u8>, ResourceCertError> {
|
||||||
// .key_identifier
|
let ParsedExtension::AuthorityKeyIdentifier(aki) = ext.parsed_extension() else {
|
||||||
// .as_ref()
|
return Err(ResourceCertError::ParseCert("authorityKeyIdentifier parse failed".into()));
|
||||||
// .ok_or(ResourceCertError::MissingParameter("key_identifier".into()))?;
|
};
|
||||||
//
|
let key_id = aki
|
||||||
// if aki.authority_cert_issuer.is_some() {
|
.key_identifier
|
||||||
// return Err(ResourceCertError::UnexceptedParameter("authority_cert_issuer".into()));
|
.as_ref()
|
||||||
// }
|
.ok_or(ResourceCertError::MissingParameter("key_identifier".into()))?;
|
||||||
// if aki.authority_cert_serial.is_some() {
|
|
||||||
// return Err(ResourceCertError::UnexceptedParameter("authority_cert_serial".into()));
|
if aki.authority_cert_issuer.is_some() {
|
||||||
// }
|
return Err(ResourceCertError::UnexceptedParameter("authority_cert_issuer".into()));
|
||||||
//
|
}
|
||||||
//
|
if aki.authority_cert_serial.is_some() {
|
||||||
// Ok(key_id.0.to_vec())
|
return Err(ResourceCertError::UnexceptedParameter("authority_cert_serial".into()));
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// fn parse_key_usage(ext: &X509Extension<'_>) -> Result<KeyUsage, ResourceCertError> {
|
|
||||||
// let ParsedExtension::KeyUsage(ku) = ext.parsed_extension() else {
|
Ok(key_id.0.to_vec())
|
||||||
// return Err(ResourceCertError::ParseCert("keyUsage parse failed".into()));
|
}
|
||||||
// };
|
|
||||||
// Ok(ku.clone())
|
fn parse_key_usage(ext: &X509Extension<'_>) -> Result<KeyUsage, ResourceCertError> {
|
||||||
// }
|
let ParsedExtension::KeyUsage(ku) = ext.parsed_extension() else {
|
||||||
//
|
return Err(ResourceCertError::ParseCert("keyUsage parse failed".into()));
|
||||||
// fn parse_crl_distribution_points(ext: &X509Extension<'_>) -> Result<Vec<Url>, ResourceCertError> {
|
};
|
||||||
// let ParsedExtension::CRLDistributionPoints(cdp) = ext.parsed_extension() else {
|
Ok(ku.clone())
|
||||||
// return Err(ResourceCertError::ParseCert("crlDistributionPoints parse failed".into()));
|
}
|
||||||
// };
|
|
||||||
// let mut urls = Vec::new();
|
fn parse_crl_distribution_points(ext: &X509Extension<'_>) -> Result<Vec<Url>, ResourceCertError> {
|
||||||
// for point in cdp.points.iter() {
|
let ParsedExtension::CRLDistributionPoints(cdp) = ext.parsed_extension() else {
|
||||||
// if point.reasons.is_some() {
|
return Err(ResourceCertError::ParseCert("crlDistributionPoints parse failed".into()));
|
||||||
// return Err(ResourceCertError::UnexceptedParameter("reasons".into()));
|
};
|
||||||
// }
|
let mut urls = Vec::new();
|
||||||
// if point.crl_issuer.is_some() {
|
for point in cdp.points.iter() {
|
||||||
// return Err(ResourceCertError::UnexceptedParameter("crl_issuer".into()));
|
if point.reasons.is_some() {
|
||||||
// }
|
return Err(ResourceCertError::UnexceptedParameter("reasons".into()));
|
||||||
//
|
}
|
||||||
// let dp_name = point.distribution_point.as_ref()
|
if point.crl_issuer.is_some() {
|
||||||
// .ok_or(ResourceCertError::MissingParameter("distribution_point".into()))?;
|
return Err(ResourceCertError::UnexceptedParameter("crl_issuer".into()));
|
||||||
// match dp_name {
|
}
|
||||||
// DistributionPointName::FullName(names) => {
|
|
||||||
// for name in names {
|
let dp_name = point.distribution_point.as_ref()
|
||||||
// match name {
|
.ok_or(ResourceCertError::MissingParameter("distribution_point".into()))?;
|
||||||
// GeneralName::URI(uri) => {
|
match dp_name {
|
||||||
// let url = Url::parse(uri)
|
DistributionPointName::FullName(names) => {
|
||||||
// .map_err(|_| ResourceCertError::InvalidUri(uri.to_string()))?;
|
for name in names {
|
||||||
// urls.push(url);
|
match name {
|
||||||
// }
|
GeneralName::URI(uri) => {
|
||||||
// _ => {
|
let url = Url::parse(uri)
|
||||||
// return Err(ResourceCertError::UnsupportedGeneralName("distribution_point".into()));
|
.map_err(|_| ResourceCertError::InvalidUri(uri.to_string()))?;
|
||||||
// }
|
urls.push(url);
|
||||||
// }
|
}
|
||||||
// }
|
_ => {
|
||||||
//
|
return Err(ResourceCertError::UnsupportedGeneralName("distribution_point".into()));
|
||||||
// }
|
}
|
||||||
// DistributionPointName::NameRelativeToCRLIssuer(_) => {
|
}
|
||||||
// return Err(ResourceCertError::UnsupportedCrlDistributionPoint);
|
}
|
||||||
// }
|
|
||||||
// }
|
}
|
||||||
// }
|
DistributionPointName::NameRelativeToCRLIssuer(_) => {
|
||||||
// if urls.is_empty() {
|
return Err(ResourceCertError::UnsupportedCrlDistributionPoint);
|
||||||
// return Err(ResourceCertError::MissingParameter("distribution_point".into()));
|
}
|
||||||
// }
|
}
|
||||||
// Ok(urls)
|
}
|
||||||
// }
|
if urls.is_empty() {
|
||||||
//
|
return Err(ResourceCertError::MissingParameter("distribution_point".into()));
|
||||||
// fn parse_authority_info_access(
|
}
|
||||||
// ext: &X509Extension<'_>,
|
Ok(urls)
|
||||||
// ) -> Result<Vec<AccessDescription>, ResourceCertError> {
|
}
|
||||||
// let ParsedExtension::AuthorityInfoAccess(aia) = ext.parsed_extension() else {
|
|
||||||
// return Err(ResourceCertError::ParseCert(
|
fn parse_authority_info_access(
|
||||||
// "authorityInfoAccess parse failed".into(),
|
ext: &X509Extension<'_>,
|
||||||
// ));
|
) -> Result<Vec<AccessDescription>, ResourceCertError> {
|
||||||
// };
|
let ParsedExtension::AuthorityInfoAccess(aia) = ext.parsed_extension() else {
|
||||||
//
|
return Err(ResourceCertError::ParseCert(
|
||||||
// let mut access_descriptions = Vec::new();
|
"authorityInfoAccess parse failed".into(),
|
||||||
//
|
));
|
||||||
// for access in &aia.accessdescs {
|
};
|
||||||
// let access_method_oid = access.access_method.to_id_string();
|
|
||||||
//
|
let mut access_descriptions = Vec::new();
|
||||||
// let uri = match &access.access_location {
|
|
||||||
// GeneralName::URI(uri) => uri,
|
for access in &aia.accessdescs {
|
||||||
// _ => {
|
let access_method_oid = access.access_method.to_id_string();
|
||||||
// return Err(ResourceCertError::InvalidAccessLocationType);
|
|
||||||
// }
|
let uri = match &access.access_location {
|
||||||
// };
|
GeneralName::URI(uri) => uri,
|
||||||
//
|
_ => {
|
||||||
// let url = Url::parse(uri)
|
return Err(ResourceCertError::InvalidAccessLocationType);
|
||||||
// .map_err(|_| ResourceCertError::InvalidUri(uri.to_string()))?;
|
}
|
||||||
//
|
};
|
||||||
// access_descriptions.push(AccessDescription {
|
|
||||||
// access_method_oid,
|
let url = Url::parse(uri)
|
||||||
// access_location: url,
|
.map_err(|_| ResourceCertError::InvalidUri(uri.to_string()))?;
|
||||||
// });
|
|
||||||
// }
|
access_descriptions.push(AccessDescription {
|
||||||
//
|
access_method_oid,
|
||||||
// if access_descriptions.is_empty() {
|
access_location: url,
|
||||||
// return Err(ResourceCertError::EmptyAuthorityInfoAccess);
|
});
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// Ok(access_descriptions)
|
if access_descriptions.is_empty() {
|
||||||
// }
|
return Err(ResourceCertError::EmptyAuthorityInfoAccess);
|
||||||
//
|
}
|
||||||
// fn parse_subject_info_access(ext: &X509Extension<'_>) -> Result<Vec<AccessDescription>, ResourceCertError> {
|
|
||||||
// let ParsedExtension::SubjectInfoAccess(sia) = ext.parsed_extension() else {
|
Ok(access_descriptions)
|
||||||
// return Err(ResourceCertError::ParseCert(
|
}
|
||||||
// "subjectInfoAccess parse failed".into(),
|
|
||||||
// ));
|
fn parse_subject_info_access(ext: &X509Extension<'_>) -> Result<Vec<AccessDescription>, ResourceCertError> {
|
||||||
// };
|
let ParsedExtension::SubjectInfoAccess(sia) = ext.parsed_extension() else {
|
||||||
// let mut access_descriptions = Vec::new();
|
return Err(ResourceCertError::ParseCert(
|
||||||
//
|
"subjectInfoAccess parse failed".into(),
|
||||||
// for access in &sia.accessdescs {
|
));
|
||||||
// let access_method_oid = access.access_method.to_id_string();
|
};
|
||||||
//
|
let mut access_descriptions = Vec::new();
|
||||||
// // accessLocation: MUST be URI in RPKI
|
|
||||||
// let uri = match &access.access_location {
|
for access in &sia.accessdescs {
|
||||||
// GeneralName::URI(uri) => uri,
|
let access_method_oid = access.access_method.to_id_string();
|
||||||
// _ => {
|
|
||||||
// return Err(ResourceCertError::InvalidAccessLocationType);
|
// accessLocation: MUST be URI in RPKI
|
||||||
// }
|
let uri = match &access.access_location {
|
||||||
// };
|
GeneralName::URI(uri) => uri,
|
||||||
//
|
_ => {
|
||||||
// let url = Url::parse(uri)
|
return Err(ResourceCertError::InvalidAccessLocationType);
|
||||||
// .map_err(|_| ResourceCertError::InvalidUri(uri.to_string()))?;
|
}
|
||||||
//
|
};
|
||||||
// access_descriptions.push(AccessDescription {
|
|
||||||
// access_method_oid,
|
let url = Url::parse(uri)
|
||||||
// access_location: url,
|
.map_err(|_| ResourceCertError::InvalidUri(uri.to_string()))?;
|
||||||
// });
|
|
||||||
// }
|
access_descriptions.push(AccessDescription {
|
||||||
//
|
access_method_oid,
|
||||||
// if access_descriptions.is_empty() {
|
access_location: url,
|
||||||
// return Err(ResourceCertError::EmptyAuthorityInfoAccess);
|
});
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// Ok(access_descriptions)
|
if access_descriptions.is_empty() {
|
||||||
// }
|
return Err(ResourceCertError::EmptyAuthorityInfoAccess);
|
||||||
//
|
}
|
||||||
// fn parse_certificate_policies(ext: &X509Extension<'_>) -> Result<Vec<PolicyInformation>, ResourceCertError> {
|
|
||||||
// let ParsedExtension::CertificatePolicies(cp) = ext.parsed_extension() else {
|
Ok(access_descriptions)
|
||||||
// return Err(ResourceCertError::ParseCert(
|
}
|
||||||
// "certificatePolicies parse failed".into(),
|
|
||||||
// ));
|
fn parse_certificate_policies(ext: &X509Extension<'_>) -> Result<Vec<PolicyInformation>, ResourceCertError> {
|
||||||
// };
|
let ParsedExtension::CertificatePolicies(cp) = ext.parsed_extension() else {
|
||||||
// let mut policies = Vec::new();
|
return Err(ResourceCertError::ParseCert(
|
||||||
//
|
"certificatePolicies parse failed".into(),
|
||||||
// }
|
));
|
||||||
|
};
|
||||||
|
let mut policies = Vec::new();
|
||||||
|
if cp.len() > 1 {
|
||||||
|
return Err(ResourceCertError::CertificatePoliciesTooMany);
|
||||||
|
}
|
||||||
|
let policy_info = cp.first().unwrap();
|
||||||
|
let policy_id = policy_info.policy_id.to_id_string();
|
||||||
|
if policy_id != oids::OID_RPKI_CP {
|
||||||
|
return Err(ResourceCertError::CertificatePoliciesInvalid);
|
||||||
|
}
|
||||||
|
let policy_info = PolicyInformation{
|
||||||
|
policy_oid: policy_id,
|
||||||
|
};
|
||||||
|
policies.push(policy_info);
|
||||||
|
Ok(policies)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bitstring_to_ip(b: &BitString, afi: &Afi) -> Result<IPAddress, ResourceCertError> {
|
||||||
|
let bytes = b.as_bytes();
|
||||||
|
let ip = match afi {
|
||||||
|
Afi::Ipv4 => {
|
||||||
|
if bytes.len() != 4 { return Err(ResourceCertError::ParseCert("IPv4 length mismatch".into())); }
|
||||||
|
u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as u128
|
||||||
|
},
|
||||||
|
Afi::Ipv6 => {
|
||||||
|
if bytes.len() != 16 { return Err(ResourceCertError::ParseCert("IPv6 length mismatch".into())); }
|
||||||
|
u128::from_be_bytes([
|
||||||
|
bytes[0], bytes[1], bytes[2], bytes[3],
|
||||||
|
bytes[4], bytes[5], bytes[6], bytes[7],
|
||||||
|
bytes[8], bytes[9], bytes[10], bytes[11],
|
||||||
|
bytes[12], bytes[13], bytes[14], bytes[15],
|
||||||
|
])
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Ok(IPAddress(ip))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ip_address_blocks(ext: &X509Extension<'_>) -> Result<IPAddrBlocks, ResourceCertError> {
|
||||||
|
|
||||||
|
let ip_blocks_der = ext.value;
|
||||||
|
|
||||||
|
let ips = parse(ip_blocks_der, |p| {
|
||||||
|
// 顶层 SEQUENCE OF IPAddressFamily
|
||||||
|
let mut ip_families = Vec::new();
|
||||||
|
p.read_sequence_of(|p2| {
|
||||||
|
// 每个 IPAddressFamily 是 SEQUENCE { addressFamily OCTET STRING, ipAddressChoice }
|
||||||
|
p2.read_sequence(|p3| {
|
||||||
|
let address_family_bytes = p3.read_element::<&[u8]>()?;
|
||||||
|
let afi = match address_family_bytes {
|
||||||
|
[0,1] => Afi::Ipv4,
|
||||||
|
[0,2] => Afi::Ipv6,
|
||||||
|
_ => return Err(asn1::ParseError::new(asn1::ParseErrorKind::InvalidValue)),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 解析 IPAddressChoice
|
||||||
|
let ip_address_choice = {
|
||||||
|
let peek_tag = p3.peek_tag()?;
|
||||||
|
match peek_tag.tag_number() {
|
||||||
|
5 => IPAddressChoice::Inherit, // NULL
|
||||||
|
16 => { // SEQUENCE OF IPAddressOrRange
|
||||||
|
let ranges = p3.read_sequence_of(|p4| {
|
||||||
|
// 解析 IPAddressOrRange CHOICE
|
||||||
|
let peek = p4.peek_tag()?.tag_number();
|
||||||
|
if peek == 16 { // SEQUENCE -> AddressPrefix
|
||||||
|
let (addr_bytes, prefix_len): (&[u8], u8) = p4.read_sequence(|p5| {
|
||||||
|
let addr = p5.read_element::<BitString>()?.as_bytes();
|
||||||
|
let prefix_len = addr.len() as u8 * 8; // 简化:用字节长度推前缀
|
||||||
|
Ok((addr, prefix_len))
|
||||||
|
})?;
|
||||||
|
Ok(IPAddressOrRange::AddressPrefix(IPAddressPrefix{
|
||||||
|
address: bitstring_to_ip(addr_bytes, &afi)?,
|
||||||
|
prefix_length: prefix_len,
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
// AddressRange
|
||||||
|
let (min_bytes, max_bytes) = p4.read_sequence(|p5| {
|
||||||
|
let min = p5.read_element::<BitString>()?.as_bytes();
|
||||||
|
let max = p5.read_element::<BitString>()?.as_bytes();
|
||||||
|
Ok((min, max))
|
||||||
|
})?;
|
||||||
|
Ok(IPAddressOrRange::AddressRange(IPAddressRange{
|
||||||
|
min: bitstring_to_ip(min_bytes, &afi)?,
|
||||||
|
max: bitstring_to_ip(max_bytes, &afi)?,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
IPAddressChoice::AddressOrRange(ranges)
|
||||||
|
}
|
||||||
|
_ => return Err(asn1::ParseError::new(asn1::ParseErrorKind::InvalidValue)),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ip_families.push(IPAddressFamily {
|
||||||
|
address_family: afi,
|
||||||
|
ip_address_choice,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
Ok(IPAddrBlocks { ips: ip_families })
|
||||||
|
}).map_err(|_| ResourceCertError::ParseCert("Failed to parse IPAddrBlocks DER".into()))?;
|
||||||
|
|
||||||
|
Ok(ips)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_as_identifiers(ext: &X509Extension<'_>) -> Result<Vec<AsIdentifier>, ResourceCertError> {
|
||||||
|
let as_identifiers_der = ext.value;
|
||||||
|
// TODO: 解析 ASIdentifiers DER
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct IPAddrBlocks {
|
pub struct IPAddrBlocks {
|
||||||
ips: Vec<IPAddressFamily>
|
pub ips: Vec<IPAddressFamily>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -43,4 +43,5 @@ pub struct IPAddressRange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
pub struct IPAddress(u128);
|
pub struct IPAddress(u128);
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
pub(crate) mod ip_resources;
|
pub(crate) mod ip_resources;
|
||||||
pub(crate) mod as_resources;
|
pub(crate) mod as_resources;
|
||||||
pub mod resource;
|
pub mod resource;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user