增加RC数据结构和资源集合数据结构 (#1)
Co-authored-by: xiuting.xu <xiutingxt.xu@gmail.com> Reviewed-on: #1 Reviewed-by: yuyr <yuyr@zgclab.edu.cn> Co-authored-by: xuxt <xuxt@zgclab.edu.cn> Co-committed-by: xuxt <xuxt@zgclab.edu.cn>
This commit was merged in pull request #1.
This commit is contained in:
@@ -1,2 +1,6 @@
|
||||
pub mod crl;
|
||||
|
||||
mod rc;
|
||||
mod tal;
|
||||
mod ta;
|
||||
mod resources;
|
||||
mod oids;
|
||||
|
||||
13
src/data_model/oids.rs
Normal file
13
src/data_model/oids.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
pub const OID_BASIC_CONSTRAINTS: &str = "2.5.29.19";
|
||||
pub const OID_SUBJECT_KEY_IDENTIFIER: &str = "2.5.29.14";
|
||||
pub const OID_AUTHORITY_KEY_IDENTIFIER: &str = "2.5.29.35";
|
||||
pub const OID_KEY_USAGE: &str = "2.5.29.15";
|
||||
pub const OID_EXTENDED_KEY_USAGE: &str = "2.5.29.37";
|
||||
pub const OID_CRL_DISTRIBUTION_POINTS: &str = "2.5.29.31";
|
||||
pub const OID_AUTHORITY_INFO_ACCESS: &str = "1.3.6.1.5.5.7.1.1";
|
||||
pub const OID_ACCESS_DESCRIPTION: &str = "1.3.6.1.5.5.7.48";
|
||||
pub const OID_AD_CA_ISSUERS: &str = "1.3.6.1.5.5.7.48.2";
|
||||
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_CERTIFICATE_POLICIES: &str = "2.5.29.32";
|
||||
pub const OID_SHA256_WITH_RSA_ENCRYPTION: &str = "1.2.840.113549.1.1.11";
|
||||
519
src/data_model/rc.rs
Normal file
519
src/data_model/rc.rs
Normal file
@@ -0,0 +1,519 @@
|
||||
use der_parser::asn1_rs::Tag;
|
||||
use der_parser::num_bigint::BigUint;
|
||||
use url::Url;
|
||||
use time::OffsetDateTime;
|
||||
use x509_parser::x509::AlgorithmIdentifier;
|
||||
use x509_parser::prelude::{Validity, KeyUsage, X509Certificate, FromDer,
|
||||
X509Version, X509Extension, ParsedExtension,
|
||||
CRLDistributionPoints, DistributionPointName, GeneralName};
|
||||
use crate::data_model::crl::CrlDecodeError;
|
||||
use crate::data_model::resources::ip_resources::IPAddrBlocks;
|
||||
use crate::data_model::resources::as_resources::ASIdentifiers;
|
||||
use crate::data_model::oids;
|
||||
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct SubjectPublicKeyInfo {
|
||||
pub algorithm_oid: String,
|
||||
pub subject_public_key: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct AccessDescription {
|
||||
pub access_method_oid: String,
|
||||
pub access_location: Url,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PolicyInformation {
|
||||
pub policy_oid: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RcExtension {
|
||||
pub basic_constraints: bool,
|
||||
pub subject_key_identifier: u8,
|
||||
pub authority_key_identifier: u8,
|
||||
pub key_usage: KeyUsage,
|
||||
pub extended_key_usage_oid: u8,
|
||||
pub crl_distribution_points: Vec<Url>,
|
||||
pub authority_info_access: Vec<AccessDescription>,
|
||||
pub subject_info_access: Vec<AccessDescription>,
|
||||
pub certificate_policies: Vec<PolicyInformation>,
|
||||
pub ip_resource: IPAddrBlocks,
|
||||
pub as_resource: ASIdentifiers,
|
||||
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ResourceCert {
|
||||
/// 证书原始DER内容
|
||||
pub cert_der: Vec<u8>,
|
||||
|
||||
/// 基本证书信息
|
||||
pub version: u32,
|
||||
pub serial_number: BigUint,
|
||||
pub signature_algorithm_oid: String,
|
||||
pub issuer_dn: String,
|
||||
pub subject_dn: String,
|
||||
pub validity: Validity,
|
||||
pub subject_public_key_info: SubjectPublicKeyInfo,
|
||||
pub extensions: RcExtension,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ResourceCertError {
|
||||
#[error("X.509 parse resource cert error: {0}")]
|
||||
ParseCert(String),
|
||||
|
||||
#[error("trailing bytes after CRL DER: {0} bytes")]
|
||||
TrailingBytes(usize),
|
||||
|
||||
#[error("invalid version {0}")]
|
||||
InvalidVersion(u32),
|
||||
|
||||
#[error("signatureAlgorithm does not match tbsCertificate.signature")]
|
||||
SignatureAlgorithmMismatch,
|
||||
|
||||
#[error("unsupported signature algorithm")]
|
||||
UnsupportedSignatureAlgorithm,
|
||||
|
||||
#[error("invalid Cert signature algorithm parameters")]
|
||||
InvalidSignatureParameters,
|
||||
|
||||
#[error("invalid Cert validity range")]
|
||||
InvalidValidityRange,
|
||||
|
||||
#[error("Cert not yet valid")]
|
||||
NotYetValid,
|
||||
|
||||
#[error("expired")]
|
||||
Expired,
|
||||
|
||||
#[error("Critical error, {0} should be {1}")]
|
||||
CriticalError(String, String),
|
||||
|
||||
#[error("Duplicate Extension: {0}")]
|
||||
DuplicateExtension(String),
|
||||
|
||||
#[error("AKI missing keyIdentifier")]
|
||||
AkiMissingKeyIdentifier,
|
||||
|
||||
#[error("Unexpected parameter: {0}")]
|
||||
UnexceptedParameter(String),
|
||||
|
||||
#[error("Missing parameter: {0}")]
|
||||
MissingParameter(String),
|
||||
|
||||
#[error("CRL DP invalid distributionPointName: {0}")]
|
||||
CrlDpInvalidDistributionPointName(String),
|
||||
|
||||
#[error("CRL DP unexpected distributionPointType: {0}")]
|
||||
CrlDpUnexpectedDistributionPointType(String),
|
||||
|
||||
#[error("invalid URI: {0}")]
|
||||
InvalidUri(String),
|
||||
|
||||
#[error("Unsupported General Name in {0}")]
|
||||
UnsupportedGeneralName(String),
|
||||
|
||||
#[error("Unsupported CRL Distribution Point")]
|
||||
UnsupportedCrlDistributionPoint,
|
||||
|
||||
#[error("Invalid Access Location Type")]
|
||||
InvalidAccessLocationType,
|
||||
|
||||
#[error("Empty AuthorityInfoAccess!")]
|
||||
EmptyAuthorityInfoAccess,
|
||||
|
||||
}
|
||||
|
||||
// impl ResourceCert{
|
||||
// pub fn from_der(cert_der: &[u8]) -> Result<Self, ResourceCertError> {
|
||||
// let (rem, x509_rc) = X509Certificate::from_der(cert_der)
|
||||
// .map_err(|e| ResourceCertError::ParseCert(e.to_string()))?;
|
||||
//
|
||||
// if !rem.is_empty() {
|
||||
// return Err(ResourceCertError::TrailingBytes(rem.len()));
|
||||
// }
|
||||
//
|
||||
// // 校验
|
||||
// parse_and_validate_cert(x509_rc)
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// fn parse_and_validate_cert(x509_rc: X509Certificate) -> Result<ResourceCert, ResourceCertError> {
|
||||
// ///逐个校验RC的内容, 如果有任何一个校验失败, 则返回错误
|
||||
//
|
||||
// // 1. 版本号必须是V3
|
||||
// let version = match x509_rc.version() {
|
||||
// X509Version::V3 => X509Version::V3,
|
||||
// v => {
|
||||
// return Err(ResourceCertError::InvalidVersion(v.0));
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// // 2.校验签名算法
|
||||
// // 2.1. 校验外层的签名算法与里层的一致
|
||||
// let outer = &x509_rc.signature_algorithm;
|
||||
// let inner = &x509_rc.tbs_certificate.signature;
|
||||
//
|
||||
// if outer.algorithm != inner.algorithm || outer.parameters != inner.parameters {
|
||||
// return Err(ResourceCertError::SignatureAlgorithmMismatch);
|
||||
// }
|
||||
// //2.2 RPKI的签名算法必须是rsaWithSHA256
|
||||
// let signature_algorithm = &x509_rc.signature_algorithm;
|
||||
// if signature_algorithm.algorithm.to_id_string() != oids::OID_SHA256_WITH_RSA_ENCRYPTION {
|
||||
// return Err(ResourceCertError::UnsupportedSignatureAlgorithm);
|
||||
// }
|
||||
// validate_sig_params(signature_algorithm)?;
|
||||
//
|
||||
// // 3. 校验Validity
|
||||
// let validity = x509_rc.validity();
|
||||
// validate_validity(validity, OffsetDateTime::now_utc())?;
|
||||
//
|
||||
// // 4. SubjectPublicKeyInfo
|
||||
// let subject_public_key_info = x509_rc.tbs_certificate.subject_pki;
|
||||
//
|
||||
// let extensions = parse_and_validate_extensions(x509_rc.extensions())?;
|
||||
//
|
||||
// Ok(ResourceCert {
|
||||
// cert_der: x509_rc.to_der().to_vec(),
|
||||
// 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 {
|
||||
// // algorithm_oid: x509_rc.tbs_certificate.subject_pki.algorithm.algorithm.to_id_string(),
|
||||
// // subject_public_key: x509_rc.tbs_certificate.subject_pki.subject_public_key.unused_bits,
|
||||
// },
|
||||
// extensions,
|
||||
// })
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// fn validate_sig_params(sig: &AlgorithmIdentifier<'_>) -> Result<(), CrlDecodeError> {
|
||||
// match sig.parameters.as_ref() {
|
||||
// None => Ok(()),
|
||||
// Some(p) if p.tag() == Tag::Null => Ok(()),
|
||||
// Some(_p) => Err(CrlDecodeError::InvalidSignatureAlgorithmParameters),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn validate_validity(
|
||||
// validity: &Validity,
|
||||
// now: OffsetDateTime,
|
||||
// ) -> Result<(), ResourceCertError> {
|
||||
// let not_before = validity.not_before.to_datetime();
|
||||
// let not_after = validity.not_after.to_datetime();
|
||||
//
|
||||
// if not_after < not_before {
|
||||
// return Err(ResourceCertError::InvalidValidityRange);
|
||||
// }
|
||||
//
|
||||
// if now < not_before {
|
||||
// return Err(ResourceCertError::NotYetValid);
|
||||
// }
|
||||
//
|
||||
// if now > not_after {
|
||||
// return Err(ResourceCertError::Expired);
|
||||
// }
|
||||
//
|
||||
// Ok(())
|
||||
// }
|
||||
//
|
||||
//
|
||||
// pub fn parse_and_validate_extensions(
|
||||
// exts: &[X509Extension<'_>],
|
||||
// ) -> Result<RcExtension, ResourceCertError> {
|
||||
// let mut basic_constraints = None;
|
||||
// let mut ip_addr_blocks = None;
|
||||
// let mut as_identifiers = None;
|
||||
// let mut ski = None;
|
||||
// let mut aki = None;
|
||||
// let mut crl_dp = None;
|
||||
// let mut aia = None;
|
||||
// let mut sia = None;
|
||||
// let mut key_usage = None;
|
||||
// let mut extended_key_usage = None;
|
||||
// let mut certificate_policies = None;
|
||||
//
|
||||
// for ext in exts {
|
||||
// let oid = ext.oid.to_id_string();
|
||||
// let critical = ext.critical;
|
||||
// match oid.as_str() {
|
||||
// oids::OID_BASIC_CONSTRAINTS => {
|
||||
// if basic_constraints.is_some() {
|
||||
// return Err(ResourceCertError::DuplicateExtension("basicConstraints".into()));
|
||||
// }
|
||||
// if !critical {
|
||||
// return Err(ResourceCertError::CriticalError("basicConstraints".into(), "critical".into()));
|
||||
// }
|
||||
// let bc = parse_basic_constraints(ext)?;
|
||||
// basic_constraints = Some(bc);
|
||||
// }
|
||||
// oids::OID_SUBJECT_KEY_IDENTIFIER => {
|
||||
// if ski.is_some() {
|
||||
// return Err(ResourceCertError::DuplicateExtension("subjectKeyIdentifier".into()));
|
||||
// }
|
||||
// if critical {
|
||||
// return Err(ResourceCertError::CriticalError("subjectKeyIdentifier".into(), "non-critical".into()));
|
||||
// }
|
||||
// let s = parse_subject_key_identifier(ext)?;
|
||||
// ski = Some(s);
|
||||
// }
|
||||
// oids::OID_AUTHORITY_KEY_IDENTIFIER => {
|
||||
// if aki.is_some() {
|
||||
// return Err(ResourceCertError::DuplicateExtension("authorityKeyIdentifier".into()));
|
||||
// }
|
||||
// if critical {
|
||||
// return Err(ResourceCertError::CriticalError("authorityKeyIdentifier".into(), "non-critical".into()));
|
||||
// }
|
||||
// let a = parse_authority_key_identifier(ext)?;
|
||||
// aki = Some(a);
|
||||
// }
|
||||
// oids::OID_KEY_USAGE => {
|
||||
// if key_usage.is_some() {
|
||||
// return Err(ResourceCertError::DuplicateExtension("keyUsage".into()));
|
||||
// }
|
||||
// if !critical {
|
||||
// return Err(ResourceCertError::CriticalError("keyUsage".into(), "critical".into()));
|
||||
// }
|
||||
// let ku = parse_key_usage(ext)?;
|
||||
// key_usage = Some(ku);
|
||||
// }
|
||||
// oids::OID_EXTENDED_KEY_USAGE => {
|
||||
// if extended_key_usage.is_some() {
|
||||
// return Err(ResourceCertError::DuplicateExtension("extendedKeyUsage".into()));
|
||||
// }
|
||||
// if critical {
|
||||
// return Err(ResourceCertError::CriticalError("extendedKeyUsage".into(), "non-critical".into()));
|
||||
// }
|
||||
// let eku = oids::OID_EXTENDED_KEY_USAGE;
|
||||
// }
|
||||
// oids::OID_CRL_DISTRIBUTION_POINTS => {
|
||||
// if crl_dp.is_some() {
|
||||
// return Err(ResourceCertError::DuplicateExtension("crlDistributionPoints".into()));
|
||||
// }
|
||||
// if critical {
|
||||
// return Err(ResourceCertError::CriticalError("crlDistributionPoints".into(), "non-critical".into()));
|
||||
// }
|
||||
// let cdp = parse_crl_distribution_points(ext)?;
|
||||
// crl_dp = Some(cdp);
|
||||
// }
|
||||
// oids::OID_AUTHORITY_INFO_ACCESS => {
|
||||
// if aia.is_some() {
|
||||
// return Err(ResourceCertError::DuplicateExtension("authorityInfoAccess".into()));
|
||||
// }
|
||||
// if critical {
|
||||
// return Err(ResourceCertError::CriticalError("authorityInfoAccess".into(), "non-critical".into()));
|
||||
// }
|
||||
// let p_aia = parse_authority_info_access(ext)?;
|
||||
// aia = Some(p_aia);
|
||||
// }
|
||||
// oids::OID_SUBJECT_INFO_ACCESS => {
|
||||
// if sia.is_some() {
|
||||
// return Err(ResourceCertError::DuplicateExtension("subjectInfoAccess".into()));
|
||||
// }
|
||||
// if critical {
|
||||
// return Err(ResourceCertError::CriticalError("subjectInfoAccess".into(), "non-critical".into()));
|
||||
// }
|
||||
// let p_sia = parse_subject_info_access(ext)?;
|
||||
// sia = Some(p_sia);
|
||||
// }
|
||||
// oids::OID_CERTIFICATE_POLICIES => {
|
||||
// if certificate_policies.is_some() {
|
||||
// return Err(ResourceCertError::DuplicateExtension("certificatePolicies".into()));
|
||||
// }
|
||||
// if !critical {
|
||||
// return Err(ResourceCertError::CriticalError("certificatePolicies".into(), "critical".into()));
|
||||
// }
|
||||
// let p_cp = parse_certificate_policies(ext)?;
|
||||
// certificate_policies = Some(p_cp);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
// Ok(RcExtension {
|
||||
// basic_constraints,
|
||||
// ip_addr_blocks,
|
||||
// as_identifiers,
|
||||
// subject_key_id: ski,
|
||||
// authority_key_id: aki,
|
||||
// crl_distribution_points: crl_dp,
|
||||
// authority_info_access: aia,
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// 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_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()));
|
||||
// };
|
||||
// Ok(s.0.to_vec())
|
||||
// }
|
||||
//
|
||||
// fn parse_authority_key_identifier(ext: &X509Extension<'_>) -> Result<Vec<u8>, ResourceCertError> {
|
||||
// let ParsedExtension::AuthorityKeyIdentifier(aki) = ext.parsed_extension() else {
|
||||
// return Err(ResourceCertError::ParseCert("authorityKeyIdentifier parse failed".into()));
|
||||
// };
|
||||
// let key_id = aki
|
||||
// .key_identifier
|
||||
// .as_ref()
|
||||
// .ok_or(ResourceCertError::MissingParameter("key_identifier".into()))?;
|
||||
//
|
||||
// if aki.authority_cert_issuer.is_some() {
|
||||
// return Err(ResourceCertError::UnexceptedParameter("authority_cert_issuer".into()));
|
||||
// }
|
||||
// if aki.authority_cert_serial.is_some() {
|
||||
// return Err(ResourceCertError::UnexceptedParameter("authority_cert_serial".into()));
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Ok(key_id.0.to_vec())
|
||||
// }
|
||||
//
|
||||
// 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()));
|
||||
// };
|
||||
// Ok(ku.clone())
|
||||
// }
|
||||
//
|
||||
// fn parse_crl_distribution_points(ext: &X509Extension<'_>) -> Result<Vec<Url>, ResourceCertError> {
|
||||
// let ParsedExtension::CRLDistributionPoints(cdp) = ext.parsed_extension() else {
|
||||
// return Err(ResourceCertError::ParseCert("crlDistributionPoints parse failed".into()));
|
||||
// };
|
||||
// let mut urls = Vec::new();
|
||||
// for point in cdp.points.iter() {
|
||||
// if point.reasons.is_some() {
|
||||
// return Err(ResourceCertError::UnexceptedParameter("reasons".into()));
|
||||
// }
|
||||
// if point.crl_issuer.is_some() {
|
||||
// return Err(ResourceCertError::UnexceptedParameter("crl_issuer".into()));
|
||||
// }
|
||||
//
|
||||
// let dp_name = point.distribution_point.as_ref()
|
||||
// .ok_or(ResourceCertError::MissingParameter("distribution_point".into()))?;
|
||||
// match dp_name {
|
||||
// DistributionPointName::FullName(names) => {
|
||||
// for name in names {
|
||||
// match name {
|
||||
// GeneralName::URI(uri) => {
|
||||
// let url = Url::parse(uri)
|
||||
// .map_err(|_| ResourceCertError::InvalidUri(uri.to_string()))?;
|
||||
// urls.push(url);
|
||||
// }
|
||||
// _ => {
|
||||
// return Err(ResourceCertError::UnsupportedGeneralName("distribution_point".into()));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// DistributionPointName::NameRelativeToCRLIssuer(_) => {
|
||||
// return Err(ResourceCertError::UnsupportedCrlDistributionPoint);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if urls.is_empty() {
|
||||
// return Err(ResourceCertError::MissingParameter("distribution_point".into()));
|
||||
// }
|
||||
// Ok(urls)
|
||||
// }
|
||||
//
|
||||
// fn parse_authority_info_access(
|
||||
// ext: &X509Extension<'_>,
|
||||
// ) -> Result<Vec<AccessDescription>, ResourceCertError> {
|
||||
// let ParsedExtension::AuthorityInfoAccess(aia) = ext.parsed_extension() else {
|
||||
// return Err(ResourceCertError::ParseCert(
|
||||
// "authorityInfoAccess parse failed".into(),
|
||||
// ));
|
||||
// };
|
||||
//
|
||||
// let mut access_descriptions = Vec::new();
|
||||
//
|
||||
// for access in &aia.accessdescs {
|
||||
// let access_method_oid = access.access_method.to_id_string();
|
||||
//
|
||||
// let uri = match &access.access_location {
|
||||
// GeneralName::URI(uri) => uri,
|
||||
// _ => {
|
||||
// return Err(ResourceCertError::InvalidAccessLocationType);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// let url = Url::parse(uri)
|
||||
// .map_err(|_| ResourceCertError::InvalidUri(uri.to_string()))?;
|
||||
//
|
||||
// access_descriptions.push(AccessDescription {
|
||||
// access_method_oid,
|
||||
// access_location: url,
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// if access_descriptions.is_empty() {
|
||||
// return Err(ResourceCertError::EmptyAuthorityInfoAccess);
|
||||
// }
|
||||
//
|
||||
// Ok(access_descriptions)
|
||||
// }
|
||||
//
|
||||
// fn parse_subject_info_access(ext: &X509Extension<'_>) -> Result<Vec<AccessDescription>, ResourceCertError> {
|
||||
// let ParsedExtension::SubjectInfoAccess(sia) = ext.parsed_extension() else {
|
||||
// return Err(ResourceCertError::ParseCert(
|
||||
// "subjectInfoAccess parse failed".into(),
|
||||
// ));
|
||||
// };
|
||||
// let mut access_descriptions = Vec::new();
|
||||
//
|
||||
// for access in &sia.accessdescs {
|
||||
// let access_method_oid = access.access_method.to_id_string();
|
||||
//
|
||||
// // accessLocation: MUST be URI in RPKI
|
||||
// let uri = match &access.access_location {
|
||||
// GeneralName::URI(uri) => uri,
|
||||
// _ => {
|
||||
// return Err(ResourceCertError::InvalidAccessLocationType);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// let url = Url::parse(uri)
|
||||
// .map_err(|_| ResourceCertError::InvalidUri(uri.to_string()))?;
|
||||
//
|
||||
// access_descriptions.push(AccessDescription {
|
||||
// access_method_oid,
|
||||
// access_location: url,
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// if access_descriptions.is_empty() {
|
||||
// return Err(ResourceCertError::EmptyAuthorityInfoAccess);
|
||||
// }
|
||||
//
|
||||
// Ok(access_descriptions)
|
||||
// }
|
||||
//
|
||||
// fn parse_certificate_policies(ext: &X509Extension<'_>) -> Result<Vec<PolicyInformation>, ResourceCertError> {
|
||||
// let ParsedExtension::CertificatePolicies(cp) = ext.parsed_extension() else {
|
||||
// return Err(ResourceCertError::ParseCert(
|
||||
// "certificatePolicies parse failed".into(),
|
||||
// ));
|
||||
// };
|
||||
// let mut policies = Vec::new();
|
||||
//
|
||||
// }
|
||||
90
src/data_model/resources/as_resources.rs
Normal file
90
src/data_model/resources/as_resources.rs
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ASIdentifiers {
|
||||
pub asn: Vec<ASIdentifierChoice>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ASN
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ASIdentifierChoice {
|
||||
Inherit,
|
||||
ASIDsOrRanges(Vec<ASIDOrRange>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ASIDOrRange {
|
||||
Id(Asn),
|
||||
AsRange(ASRange),
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ASRange {
|
||||
pub min: Asn,
|
||||
pub max: Asn,
|
||||
}
|
||||
|
||||
impl ASRange {
|
||||
/// Creates a new AS number range from the smallest and largest number.
|
||||
pub fn new(min: Asn, max: Asn) -> Self {
|
||||
ASRange { min, max }
|
||||
}
|
||||
|
||||
/// Returns an AS block covering all ASNs.
|
||||
pub fn all() -> ASRange {
|
||||
ASRange::new(Asn::MIN, Asn::MAX)
|
||||
}
|
||||
|
||||
/// Returns the smallest AS number that is part of this range.
|
||||
pub fn min(self) -> Asn {
|
||||
self.min
|
||||
}
|
||||
|
||||
/// Returns the largest AS number that is still part of this range.
|
||||
pub fn max(self) -> Asn {
|
||||
self.max
|
||||
}
|
||||
|
||||
/// Returns the number of ASNs covered by this value.
|
||||
pub fn asn_count(self) -> u32 {
|
||||
u32::from(self.max) - u32::from(self.min) + 1
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Asn(u32);
|
||||
|
||||
impl Asn {
|
||||
pub const MIN: Asn = Asn(u32::MIN);
|
||||
pub const MAX: Asn = Asn(u32::MAX);
|
||||
|
||||
/// Creates an AS number from a `u32`.
|
||||
pub fn from_u32(value: u32) -> Self {
|
||||
Asn(value)
|
||||
}
|
||||
|
||||
/// Converts an AS number into a `u32`.
|
||||
pub fn into_u32(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Converts an AS number into a network-order byte array.
|
||||
pub fn to_raw(self) -> [u8; 4] {
|
||||
self.0.to_be_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Asn {
|
||||
fn from(id: u32) -> Self {
|
||||
Asn(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Asn> for u32 {
|
||||
fn from(id: Asn) -> Self {
|
||||
id.0
|
||||
}
|
||||
}
|
||||
46
src/data_model/resources/ip_resources.rs
Normal file
46
src/data_model/resources/ip_resources.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct IPAddrBlocks {
|
||||
ips: Vec<IPAddressFamily>
|
||||
}
|
||||
|
||||
|
||||
// IP Address Family
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct IPAddressFamily {
|
||||
pub address_family: Afi,
|
||||
pub ip_address_choice: IPAddressChoice,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Afi {
|
||||
Ipv4,
|
||||
Ipv6,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum IPAddressChoice {
|
||||
Inherit,
|
||||
AddressOrRange(Vec<IPAddressOrRange>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum IPAddressOrRange {
|
||||
AddressPrefix(IPAddressPrefix),
|
||||
AddressRange(IPAddressRange),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct IPAddressPrefix {
|
||||
pub address: IPAddress,
|
||||
pub prefix_length: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct IPAddressRange {
|
||||
pub min: IPAddress,
|
||||
pub max: IPAddress,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct IPAddress(u128);
|
||||
3
src/data_model/resources/mod.rs
Normal file
3
src/data_model/resources/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub(crate) mod ip_resources;
|
||||
pub(crate) mod as_resources;
|
||||
pub mod resource;
|
||||
10
src/data_model/resources/resource.rs
Normal file
10
src/data_model/resources/resource.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use crate::data_model::resources::as_resources::ASIdentifiers;
|
||||
use crate::data_model::resources::ip_resources::IPAddrBlocks;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ResourceSet {
|
||||
ip_addr_blocks: IPAddrBlocks,
|
||||
as_identifiers: ASIdentifiers,
|
||||
}
|
||||
|
||||
|
||||
27
src/data_model/ta.rs
Normal file
27
src/data_model/ta.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use url::Url;
|
||||
use x509_parser::prelude::*;
|
||||
|
||||
use crate::data_model::resources::resource::ResourceSet;
|
||||
|
||||
//
|
||||
// #[derive(Debug, Clone)]
|
||||
// pub struct TrustAnchorCert {
|
||||
// /// 信任锚证书名称
|
||||
// pub name: String,
|
||||
//
|
||||
// /// 证书原始DER内容
|
||||
// pub cert_der: Vec<u8>,
|
||||
//
|
||||
// /// 证书
|
||||
// pub cert: X509Certificate<'static>,
|
||||
//
|
||||
// /// 资源集合
|
||||
// pub resources: ResourceSet,
|
||||
//
|
||||
// ///发布点
|
||||
// pub publication_point: Url,
|
||||
// }
|
||||
//
|
||||
// impl TrustAnchorCert {
|
||||
//
|
||||
// }
|
||||
18
src/data_model/tal.rs
Normal file
18
src/data_model/tal.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
/// TAL Model
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Tal {
|
||||
/// Optional human-readable comments
|
||||
pub comments: Vec<String>,
|
||||
|
||||
/// Ordered list of URIs pointing to the TA certificate
|
||||
pub uris: Vec<TalUri>,
|
||||
|
||||
/// SubjectPublicKeyInfo DER
|
||||
pub spki_der: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TalUri {
|
||||
Rsync(String),
|
||||
Https(String),
|
||||
}
|
||||
Reference in New Issue
Block a user