aboutsummaryrefslogtreecommitdiff
path: root/src/ext/pkix
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/pkix')
-rw-r--r--src/ext/pkix/access.rs18
-rw-r--r--src/ext/pkix/authkeyid.rs24
-rw-r--r--src/ext/pkix/certpolicy.rs43
-rw-r--r--src/ext/pkix/constraints/basic.rs25
-rw-r--r--src/ext/pkix/constraints/name.rs16
-rw-r--r--src/ext/pkix/constraints/policy.rs2
-rw-r--r--src/ext/pkix/crl.rs36
-rw-r--r--src/ext/pkix/crl/dp.rs16
-rw-r--r--src/ext/pkix/keyusage.rs119
-rw-r--r--src/ext/pkix/name/dirstr.rs11
-rw-r--r--src/ext/pkix/name/dp.rs6
-rw-r--r--src/ext/pkix/name/ediparty.rs6
-rw-r--r--src/ext/pkix/name/general.rs66
-rw-r--r--src/ext/pkix/name/other.rs12
-rw-r--r--src/ext/pkix/policymap.rs1
15 files changed, 309 insertions, 92 deletions
diff --git a/src/ext/pkix/access.rs b/src/ext/pkix/access.rs
index 0390235..4d2d9db 100644
--- a/src/ext/pkix/access.rs
+++ b/src/ext/pkix/access.rs
@@ -16,13 +16,14 @@ use der::{asn1::ObjectIdentifier, Sequence, ValueOrd};
///
/// [RFC 5280 Section 4.2.2.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.1
#[derive(Clone, Debug, Default, PartialEq, Eq)]
-pub struct AuthorityInfoAccessSyntax<'a>(pub Vec<AccessDescription<'a>>);
+pub struct AuthorityInfoAccessSyntax(pub Vec<AccessDescription>);
-impl<'a> AssociatedOid for AuthorityInfoAccessSyntax<'a> {
+impl AssociatedOid for AuthorityInfoAccessSyntax {
const OID: ObjectIdentifier = ID_PE_AUTHORITY_INFO_ACCESS;
}
-impl_newtype!(AuthorityInfoAccessSyntax<'a>, Vec<AccessDescription<'a>>);
+impl_newtype!(AuthorityInfoAccessSyntax, Vec<AccessDescription>);
+impl_extension!(AuthorityInfoAccessSyntax, critical = false);
/// SubjectInfoAccessSyntax as defined in [RFC 5280 Section 4.2.2.2].
///
@@ -32,13 +33,14 @@ impl_newtype!(AuthorityInfoAccessSyntax<'a>, Vec<AccessDescription<'a>>);
///
/// [RFC 5280 Section 4.2.2.2]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.2
#[derive(Clone, Debug, Default, PartialEq, Eq)]
-pub struct SubjectInfoAccessSyntax<'a>(pub Vec<AccessDescription<'a>>);
+pub struct SubjectInfoAccessSyntax(pub Vec<AccessDescription>);
-impl<'a> AssociatedOid for SubjectInfoAccessSyntax<'a> {
+impl AssociatedOid for SubjectInfoAccessSyntax {
const OID: ObjectIdentifier = ID_PE_SUBJECT_INFO_ACCESS;
}
-impl_newtype!(SubjectInfoAccessSyntax<'a>, Vec<AccessDescription<'a>>);
+impl_newtype!(SubjectInfoAccessSyntax, Vec<AccessDescription>);
+impl_extension!(SubjectInfoAccessSyntax, critical = false);
/// AccessDescription as defined in [RFC 5280 Section 4.2.2.1].
///
@@ -52,7 +54,7 @@ impl_newtype!(SubjectInfoAccessSyntax<'a>, Vec<AccessDescription<'a>>);
/// [RFC 5280 Section 4.2.2.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.1
#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
-pub struct AccessDescription<'a> {
+pub struct AccessDescription {
pub access_method: ObjectIdentifier,
- pub access_location: GeneralName<'a>,
+ pub access_location: GeneralName,
}
diff --git a/src/ext/pkix/authkeyid.rs b/src/ext/pkix/authkeyid.rs
index e7644f5..60b61e5 100644
--- a/src/ext/pkix/authkeyid.rs
+++ b/src/ext/pkix/authkeyid.rs
@@ -1,8 +1,9 @@
use super::name::GeneralNames;
+use crate::serial_number::SerialNumber;
use const_oid::db::rfc5280::ID_CE_AUTHORITY_KEY_IDENTIFIER;
use const_oid::{AssociatedOid, ObjectIdentifier};
-use der::asn1::{OctetStringRef, UIntRef};
+use der::asn1::OctetString;
use der::Sequence;
/// AuthorityKeyIdentifier as defined in [RFC 5280 Section 4.2.1.1].
@@ -18,19 +19,28 @@ use der::Sequence;
/// ```
///
/// [RFC 5280 Section 4.2.1.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.1
-#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
+#[derive(Clone, Debug, Eq, PartialEq, Sequence, Default)]
#[allow(missing_docs)]
-pub struct AuthorityKeyIdentifier<'a> {
+pub struct AuthorityKeyIdentifier {
#[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")]
- pub key_identifier: Option<OctetStringRef<'a>>,
+ pub key_identifier: Option<OctetString>,
#[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")]
- pub authority_cert_issuer: Option<GeneralNames<'a>>,
+ pub authority_cert_issuer: Option<GeneralNames>,
#[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")]
- pub authority_cert_serial_number: Option<UIntRef<'a>>,
+ pub authority_cert_serial_number: Option<SerialNumber>,
}
-impl<'a> AssociatedOid for AuthorityKeyIdentifier<'a> {
+impl AssociatedOid for AuthorityKeyIdentifier {
const OID: ObjectIdentifier = ID_CE_AUTHORITY_KEY_IDENTIFIER;
}
+
+impl_extension!(AuthorityKeyIdentifier, critical = false);
+impl_key_identifier!(
+ AuthorityKeyIdentifier,
+ (|result: &[u8]| Ok(Self {
+ key_identifier: Some(OctetString::new(result)?),
+ ..Default::default()
+ }))
+);
diff --git a/src/ext/pkix/certpolicy.rs b/src/ext/pkix/certpolicy.rs
index bb2211f..85820c1 100644
--- a/src/ext/pkix/certpolicy.rs
+++ b/src/ext/pkix/certpolicy.rs
@@ -1,11 +1,11 @@
//! PKIX Certificate Policies extension
-use alloc::vec::Vec;
+use alloc::{string::String, vec::Vec};
use const_oid::db::rfc5912::ID_CE_CERTIFICATE_POLICIES;
use const_oid::AssociatedOid;
-use der::asn1::{GeneralizedTime, Ia5StringRef, ObjectIdentifier, UIntRef, Utf8StringRef};
-use der::{AnyRef, Choice, Sequence, ValueOrd};
+use der::asn1::{GeneralizedTime, Ia5String, ObjectIdentifier, Uint};
+use der::{Any, Choice, Sequence, ValueOrd};
/// CertificatePolicies as defined in [RFC 5280 Section 4.2.1.4].
///
@@ -14,14 +14,19 @@ use der::{AnyRef, Choice, Sequence, ValueOrd};
/// ```
///
/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
+// If this extension is
+// critical, the path validation software MUST be able to interpret this
+// extension (including the optional qualifier), or MUST reject the
+// certificate.
#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct CertificatePolicies<'a>(pub Vec<PolicyInformation<'a>>);
+pub struct CertificatePolicies(pub Vec<PolicyInformation>);
-impl<'a> AssociatedOid for CertificatePolicies<'a> {
+impl AssociatedOid for CertificatePolicies {
const OID: ObjectIdentifier = ID_CE_CERTIFICATE_POLICIES;
}
-impl_newtype!(CertificatePolicies<'a>, Vec<PolicyInformation<'a>>);
+impl_newtype!(CertificatePolicies, Vec<PolicyInformation>);
+impl_extension!(CertificatePolicies);
/// PolicyInformation as defined in [RFC 5280 Section 4.2.1.4].
///
@@ -37,9 +42,9 @@ impl_newtype!(CertificatePolicies<'a>, Vec<PolicyInformation<'a>>);
/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
-pub struct PolicyInformation<'a> {
+pub struct PolicyInformation {
pub policy_identifier: ObjectIdentifier,
- pub policy_qualifiers: Option<Vec<PolicyQualifierInfo<'a>>>,
+ pub policy_qualifiers: Option<Vec<PolicyQualifierInfo>>,
}
/// PolicyQualifierInfo as defined in [RFC 5280 Section 4.2.1.4].
@@ -54,9 +59,9 @@ pub struct PolicyInformation<'a> {
/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
-pub struct PolicyQualifierInfo<'a> {
+pub struct PolicyQualifierInfo {
pub policy_qualifier_id: ObjectIdentifier,
- pub qualifier: Option<AnyRef<'a>>,
+ pub qualifier: Option<Any>,
}
/// CpsUri as defined in [RFC 5280 Section 4.2.1.4].
@@ -66,7 +71,7 @@ pub struct PolicyQualifierInfo<'a> {
/// ```
///
/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
-pub type CpsUri<'a> = Ia5StringRef<'a>;
+pub type CpsUri = Ia5String;
/// UserNotice as defined in [RFC 5280 Section 4.2.1.4].
///
@@ -80,9 +85,9 @@ pub type CpsUri<'a> = Ia5StringRef<'a>;
/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
-pub struct UserNotice<'a> {
+pub struct UserNotice {
pub notice_ref: Option<GeneralizedTime>,
- pub explicit_text: Option<DisplayText<'a>>,
+ pub explicit_text: Option<DisplayText>,
}
/// NoticeReference as defined in [RFC 5280 Section 4.2.1.4].
@@ -96,9 +101,9 @@ pub struct UserNotice<'a> {
/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
-pub struct NoticeReference<'a> {
- pub organization: DisplayText<'a>,
- pub notice_numbers: Option<Vec<UIntRef<'a>>>,
+pub struct NoticeReference {
+ pub organization: DisplayText,
+ pub notice_numbers: Option<Vec<Uint>>,
}
/// DisplayText as defined in [RFC 5280 Section 4.2.1.4].
@@ -117,10 +122,10 @@ pub struct NoticeReference<'a> {
/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
#[derive(Choice, Clone, Debug, Eq, PartialEq)]
#[allow(missing_docs)]
-pub enum DisplayText<'a> {
+pub enum DisplayText {
#[asn1(type = "IA5String")]
- Ia5String(Ia5StringRef<'a>),
+ Ia5String(Ia5String),
#[asn1(type = "UTF8String")]
- Utf8String(Utf8StringRef<'a>),
+ Utf8String(String),
}
diff --git a/src/ext/pkix/constraints/basic.rs b/src/ext/pkix/constraints/basic.rs
index 5972cc8..c50d8e8 100644
--- a/src/ext/pkix/constraints/basic.rs
+++ b/src/ext/pkix/constraints/basic.rs
@@ -22,3 +22,28 @@ pub struct BasicConstraints {
impl AssociatedOid for BasicConstraints {
const OID: ObjectIdentifier = ID_CE_BASIC_CONSTRAINTS;
}
+
+impl crate::ext::AsExtension for BasicConstraints {
+ fn critical(
+ &self,
+ _subject: &crate::name::Name,
+ _extensions: &[crate::ext::Extension],
+ ) -> bool {
+ // https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9
+ // Conforming CAs MUST include this extension in all CA certificates
+ // that contain public keys used to validate digital signatures on
+ // certificates and MUST mark the extension as critical in such
+ // certificates. This extension MAY appear as a critical or non-
+ // critical extension in CA certificates that contain public keys used
+ // exclusively for purposes other than validating digital signatures on
+ // certificates. Such CA certificates include ones that contain public
+ // keys used exclusively for validating digital signatures on CRLs and
+ // ones that contain key management public keys used with certificate
+ // enrollment protocols. This extension MAY appear as a critical or
+ // non-critical extension in end entity certificates.
+
+ // NOTE(baloo): from the spec, it doesn't appear to hurt if we force the extension
+ // to be critical.
+ true
+ }
+}
diff --git a/src/ext/pkix/constraints/name.rs b/src/ext/pkix/constraints/name.rs
index 658f1e2..c05d005 100644
--- a/src/ext/pkix/constraints/name.rs
+++ b/src/ext/pkix/constraints/name.rs
@@ -19,18 +19,20 @@ use super::super::name::GeneralName;
/// [RFC 5280 Section 4.2.1.10]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
-pub struct NameConstraints<'a> {
+pub struct NameConstraints {
#[asn1(context_specific = "0", optional = "true", tag_mode = "IMPLICIT")]
- pub permitted_subtrees: Option<GeneralSubtrees<'a>>,
+ pub permitted_subtrees: Option<GeneralSubtrees>,
#[asn1(context_specific = "1", optional = "true", tag_mode = "IMPLICIT")]
- pub excluded_subtrees: Option<GeneralSubtrees<'a>>,
+ pub excluded_subtrees: Option<GeneralSubtrees>,
}
-impl<'a> AssociatedOid for NameConstraints<'a> {
+impl AssociatedOid for NameConstraints {
const OID: ObjectIdentifier = ID_CE_NAME_CONSTRAINTS;
}
+impl_extension!(NameConstraints, critical = true);
+
/// GeneralSubtrees as defined in [RFC 5280 Section 4.2.1.10].
///
/// ```text
@@ -38,7 +40,7 @@ impl<'a> AssociatedOid for NameConstraints<'a> {
/// ```
///
/// [RFC 5280 Section 4.2.1.10]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10
-pub type GeneralSubtrees<'a> = Vec<GeneralSubtree<'a>>;
+pub type GeneralSubtrees = Vec<GeneralSubtree>;
/// GeneralSubtree as defined in [RFC 5280 Section 4.2.1.10].
///
@@ -53,8 +55,8 @@ pub type GeneralSubtrees<'a> = Vec<GeneralSubtree<'a>>;
/// [RFC 5280 Section 4.2.1.10]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
-pub struct GeneralSubtree<'a> {
- pub base: GeneralName<'a>,
+pub struct GeneralSubtree {
+ pub base: GeneralName,
#[asn1(
context_specific = "0",
diff --git a/src/ext/pkix/constraints/policy.rs b/src/ext/pkix/constraints/policy.rs
index dcb1a8c..c409737 100644
--- a/src/ext/pkix/constraints/policy.rs
+++ b/src/ext/pkix/constraints/policy.rs
@@ -24,3 +24,5 @@ pub struct PolicyConstraints {
impl AssociatedOid for PolicyConstraints {
const OID: ObjectIdentifier = ID_CE_POLICY_CONSTRAINTS;
}
+
+impl_extension!(PolicyConstraints, critical = true);
diff --git a/src/ext/pkix/crl.rs b/src/ext/pkix/crl.rs
index d65b837..f3e9397 100644
--- a/src/ext/pkix/crl.rs
+++ b/src/ext/pkix/crl.rs
@@ -11,7 +11,7 @@ pub use dp::IssuingDistributionPoint;
use alloc::vec::Vec;
-use der::{asn1::UIntRef, Enumerated};
+use der::{asn1::Uint, Enumerated};
/// CrlNumber as defined in [RFC 5280 Section 5.2.3].
///
@@ -20,14 +20,15 @@ use der::{asn1::UIntRef, Enumerated};
/// ```
///
/// [RFC 5280 Section 5.2.3]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.3
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct CrlNumber<'a>(pub UIntRef<'a>);
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct CrlNumber(pub Uint);
-impl<'a> AssociatedOid for CrlNumber<'a> {
+impl AssociatedOid for CrlNumber {
const OID: ObjectIdentifier = ID_CE_CRL_NUMBER;
}
-impl_newtype!(CrlNumber<'a>, UIntRef<'a>);
+impl_newtype!(CrlNumber, Uint);
+impl_extension!(CrlNumber, critical = false);
/// BaseCRLNumber as defined in [RFC 5280 Section 5.2.4].
///
@@ -36,14 +37,15 @@ impl_newtype!(CrlNumber<'a>, UIntRef<'a>);
/// ```
///
/// [RFC 5280 Section 5.2.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.4
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct BaseCrlNumber<'a>(pub UIntRef<'a>);
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct BaseCrlNumber(pub Uint);
-impl<'a> AssociatedOid for BaseCrlNumber<'a> {
+impl AssociatedOid for BaseCrlNumber {
const OID: ObjectIdentifier = ID_CE_DELTA_CRL_INDICATOR;
}
-impl_newtype!(BaseCrlNumber<'a>, UIntRef<'a>);
+impl_newtype!(BaseCrlNumber, Uint);
+impl_extension!(BaseCrlNumber, critical = true);
/// CrlDistributionPoints as defined in [RFC 5280 Section 4.2.1.13].
///
@@ -53,13 +55,14 @@ impl_newtype!(BaseCrlNumber<'a>, UIntRef<'a>);
///
/// [RFC 5280 Section 4.2.1.13]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13
#[derive(Clone, Debug, Default, PartialEq, Eq)]
-pub struct CrlDistributionPoints<'a>(pub Vec<dp::DistributionPoint<'a>>);
+pub struct CrlDistributionPoints(pub Vec<dp::DistributionPoint>);
-impl<'a> AssociatedOid for CrlDistributionPoints<'a> {
+impl AssociatedOid for CrlDistributionPoints {
const OID: ObjectIdentifier = ID_CE_CRL_DISTRIBUTION_POINTS;
}
-impl_newtype!(CrlDistributionPoints<'a>, Vec<dp::DistributionPoint<'a>>);
+impl_newtype!(CrlDistributionPoints, Vec<dp::DistributionPoint>);
+impl_extension!(CrlDistributionPoints, critical = false);
/// FreshestCrl as defined in [RFC 5280 Section 5.2.6].
///
@@ -69,13 +72,14 @@ impl_newtype!(CrlDistributionPoints<'a>, Vec<dp::DistributionPoint<'a>>);
///
/// [RFC 5280 Section 5.2.6]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.6
#[derive(Clone, Debug, Default, PartialEq, Eq)]
-pub struct FreshestCrl<'a>(pub Vec<dp::DistributionPoint<'a>>);
+pub struct FreshestCrl(pub Vec<dp::DistributionPoint>);
-impl<'a> AssociatedOid for FreshestCrl<'a> {
+impl AssociatedOid for FreshestCrl {
const OID: ObjectIdentifier = ID_CE_FRESHEST_CRL;
}
-impl_newtype!(FreshestCrl<'a>, Vec<dp::DistributionPoint<'a>>);
+impl_newtype!(FreshestCrl, Vec<dp::DistributionPoint>);
+impl_extension!(FreshestCrl, critical = false);
/// CRLReason as defined in [RFC 5280 Section 5.3.1].
///
@@ -114,3 +118,5 @@ pub enum CrlReason {
impl AssociatedOid for CrlReason {
const OID: ObjectIdentifier = ID_CE_CRL_REASONS;
}
+
+impl_extension!(CrlReason, critical = false);
diff --git a/src/ext/pkix/crl/dp.rs b/src/ext/pkix/crl/dp.rs
index f7d1ab7..7acd2c9 100644
--- a/src/ext/pkix/crl/dp.rs
+++ b/src/ext/pkix/crl/dp.rs
@@ -1,8 +1,8 @@
//! PKIX distribution point types
use const_oid::{db::rfc5280::ID_PE_SUBJECT_INFO_ACCESS, AssociatedOid, ObjectIdentifier};
+use der::flagset::{flags, FlagSet};
use der::{Sequence, ValueOrd};
-use flagset::{flags, FlagSet};
use crate::ext::pkix::name::{DistributionPointName, GeneralNames};
@@ -24,9 +24,9 @@ use crate::ext::pkix::name::{DistributionPointName, GeneralNames};
/// [RFC 5280 Section 5.2.5]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.5
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
-pub struct IssuingDistributionPoint<'a> {
+pub struct IssuingDistributionPoint {
#[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")]
- pub distribution_point: Option<DistributionPointName<'a>>,
+ pub distribution_point: Option<DistributionPointName>,
#[asn1(
context_specific = "1",
@@ -60,10 +60,12 @@ pub struct IssuingDistributionPoint<'a> {
pub only_contains_attribute_certs: bool,
}
-impl<'a> AssociatedOid for IssuingDistributionPoint<'a> {
+impl AssociatedOid for IssuingDistributionPoint {
const OID: ObjectIdentifier = ID_PE_SUBJECT_INFO_ACCESS;
}
+impl_extension!(IssuingDistributionPoint, critical = true);
+
/// DistributionPoint as defined in [RFC 5280 Section 4.2.1.13].
///
/// ```text
@@ -76,15 +78,15 @@ impl<'a> AssociatedOid for IssuingDistributionPoint<'a> {
/// [RFC 5280 Section 4.2.1.13]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13
#[derive(Clone, Debug, PartialEq, Eq, Sequence, ValueOrd)]
#[allow(missing_docs)]
-pub struct DistributionPoint<'a> {
+pub struct DistributionPoint {
#[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")]
- pub distribution_point: Option<DistributionPointName<'a>>,
+ pub distribution_point: Option<DistributionPointName>,
#[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")]
pub reasons: Option<ReasonFlags>,
#[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")]
- pub crl_issuer: Option<GeneralNames<'a>>,
+ pub crl_issuer: Option<GeneralNames>,
}
/// ReasonFlags as defined in [RFC 5280 Section 4.2.1.13].
diff --git a/src/ext/pkix/keyusage.rs b/src/ext/pkix/keyusage.rs
index cd051fe..833db69 100644
--- a/src/ext/pkix/keyusage.rs
+++ b/src/ext/pkix/keyusage.rs
@@ -1,12 +1,12 @@
use alloc::vec::Vec;
use const_oid::db::rfc5280::{
- ID_CE_EXT_KEY_USAGE, ID_CE_KEY_USAGE, ID_CE_PRIVATE_KEY_USAGE_PERIOD,
+ ANY_EXTENDED_KEY_USAGE, ID_CE_EXT_KEY_USAGE, ID_CE_KEY_USAGE, ID_CE_PRIVATE_KEY_USAGE_PERIOD,
};
use const_oid::AssociatedOid;
use der::asn1::{GeneralizedTime, ObjectIdentifier};
+use der::flagset::{flags, FlagSet};
use der::Sequence;
-use flagset::{flags, FlagSet};
flags! {
/// Key usage flags as defined in [RFC 5280 Section 4.2.1.3].
@@ -52,6 +52,66 @@ impl AssociatedOid for KeyUsage {
}
impl_newtype!(KeyUsage, FlagSet<KeyUsages>);
+impl_extension!(KeyUsage, critical = true);
+
+impl KeyUsage {
+ /// The subject public key is used for verifying digital signatures
+ pub fn digital_signature(&self) -> bool {
+ self.0.contains(KeyUsages::DigitalSignature)
+ }
+
+ /// When the subject public key is used to verify digital signatures,
+ /// it is asserted as non-repudiation.
+ pub fn non_repudiation(&self) -> bool {
+ self.0.contains(KeyUsages::NonRepudiation)
+ }
+
+ /// The subject public key is used for enciphering private or
+ /// secret keys, i.e., for key transport.
+ pub fn key_encipherment(&self) -> bool {
+ self.0.contains(KeyUsages::KeyEncipherment)
+ }
+
+ /// The subject public key is used for directly enciphering
+ /// raw user data without the use of an intermediate symmetric cipher.
+ pub fn data_encipherment(&self) -> bool {
+ self.0.contains(KeyUsages::DataEncipherment)
+ }
+
+ /// The subject public key is used for key agreement
+ pub fn key_agreement(&self) -> bool {
+ self.0.contains(KeyUsages::KeyAgreement)
+ }
+
+ /// The subject public key is used for enciphering private or
+ /// secret keys, i.e., for key transport.
+ pub fn key_cert_sign(&self) -> bool {
+ self.0.contains(KeyUsages::KeyCertSign)
+ }
+
+ /// The subject public key is used for verifying signatures
+ /// on certificate revocation lists (e.g., CRLs, delta CRLs,
+ /// or ARLs).
+ pub fn crl_sign(&self) -> bool {
+ self.0.contains(KeyUsages::CRLSign)
+ }
+
+ /// The meaning of the `encipher_only` is undefined when `key_agreement`
+ /// returns false. When `encipher_only` returns true and
+ /// `key_agreement` also returns true, the subject public key may be
+ /// used only for enciphering data while performing key agreement.
+ pub fn encipher_only(&self) -> bool {
+ self.0.contains(KeyUsages::EncipherOnly)
+ }
+
+ /// The meaning of the `decipher_only` is undefined when `key_agreement`
+ /// returns false. When `encipher_only` returns true and
+ /// `key_agreement` also returns true, the subject public key may be
+ /// used only for deciphering data while performing key agreement.
+ pub fn decipher_only(&self) -> bool {
+ self.0.contains(KeyUsages::DecipherOnly)
+ }
+}
/// ExtKeyUsageSyntax as defined in [RFC 5280 Section 4.2.1.12].
///
@@ -78,6 +138,30 @@ impl AssociatedOid for ExtendedKeyUsage {
impl_newtype!(ExtendedKeyUsage, Vec<ObjectIdentifier>);
+impl crate::ext::AsExtension for ExtendedKeyUsage {
+ fn critical(
+ &self,
+ _subject: &crate::name::Name,
+ _extensions: &[crate::ext::Extension],
+ ) -> bool {
+ // https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12
+ // This extension MAY, at the option of the certificate issuer, be
+ // either critical or non-critical.
+ //
+ // If a CA includes extended key usages to satisfy such applications,
+ // but does not wish to restrict usages of the key, the CA can include
+ // the special KeyPurposeId anyExtendedKeyUsage in addition to the
+ // particular key purposes required by the applications. Conforming CAs
+ // SHOULD NOT mark this extension as critical if the anyExtendedKeyUsage
+ // KeyPurposeId is present. Applications that require the presence of a
+ // particular purpose MAY reject certificates that include the
+ // anyExtendedKeyUsage OID but not the particular OID expected for the
+ // application.
+
+ !self.0.iter().any(|el| *el == ANY_EXTENDED_KEY_USAGE)
+ }
+}
+
/// PrivateKeyUsagePeriod as defined in [RFC 3280 Section 4.2.1.4].
///
/// RFC 5280 states "use of this ISO standard extension is neither deprecated nor recommended for use in the Internet PKI."
@@ -103,3 +187,34 @@ pub struct PrivateKeyUsagePeriod {
impl AssociatedOid for PrivateKeyUsagePeriod {
const OID: ObjectIdentifier = ID_CE_PRIVATE_KEY_USAGE_PERIOD;
}
+
+impl_extension!(PrivateKeyUsagePeriod, critical = false);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn digital_signature_contains_digital_signature() {
+ let key_usage = KeyUsage(KeyUsages::DigitalSignature.into());
+ assert!(key_usage.digital_signature());
+ }
+
+ #[test]
+ fn all_contains_digital_signature() {
+ let key_usage = KeyUsage(FlagSet::full());
+ assert!(key_usage.digital_signature());
+ }
+
+ #[test]
+ fn key_encipherment_not_contains_digital_signature() {
+ let key_usage = KeyUsage(KeyUsages::KeyEncipherment.into());
+ assert!(!key_usage.digital_signature());
+ }
+
+ #[test]
+ fn empty_not_contains_digital_signature() {
+ let key_usage = KeyUsage(None.into());
+ assert!(!key_usage.digital_signature());
+ }
+}
diff --git a/src/ext/pkix/name/dirstr.rs b/src/ext/pkix/name/dirstr.rs
index 2aaa732..a6a0117 100644
--- a/src/ext/pkix/name/dirstr.rs
+++ b/src/ext/pkix/name/dirstr.rs
@@ -1,4 +1,5 @@
-use der::asn1::{PrintableStringRef, TeletexStringRef, Utf8StringRef};
+use alloc::string::String;
+use der::asn1::{PrintableString, TeletexString};
use der::{Choice, ValueOrd};
/// DirectoryString as defined in [RFC 5280 Section 4.2.1.4].
@@ -40,13 +41,13 @@ use der::{Choice, ValueOrd};
/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
#[derive(Clone, Debug, Eq, PartialEq, Choice, ValueOrd)]
#[allow(missing_docs)]
-pub enum DirectoryString<'a> {
+pub enum DirectoryString {
#[asn1(type = "PrintableString")]
- PrintableString(PrintableStringRef<'a>),
+ PrintableString(PrintableString),
#[asn1(type = "TeletexString")]
- TeletexString(TeletexStringRef<'a>),
+ TeletexString(TeletexString),
#[asn1(type = "UTF8String")]
- Utf8String(Utf8StringRef<'a>),
+ Utf8String(String),
}
diff --git a/src/ext/pkix/name/dp.rs b/src/ext/pkix/name/dp.rs
index e895f88..0965564 100644
--- a/src/ext/pkix/name/dp.rs
+++ b/src/ext/pkix/name/dp.rs
@@ -15,10 +15,10 @@ use der::{Choice, ValueOrd};
/// [RFC 5280 Section 4.2.1.13]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13
#[derive(Clone, Debug, Eq, PartialEq, Choice, ValueOrd)]
#[allow(missing_docs)]
-pub enum DistributionPointName<'a> {
+pub enum DistributionPointName {
#[asn1(context_specific = "0", tag_mode = "IMPLICIT", constructed = "true")]
- FullName(GeneralNames<'a>),
+ FullName(GeneralNames),
#[asn1(context_specific = "1", tag_mode = "IMPLICIT", constructed = "true")]
- NameRelativeToCRLIssuer(RelativeDistinguishedName<'a>),
+ NameRelativeToCRLIssuer(RelativeDistinguishedName),
}
diff --git a/src/ext/pkix/name/ediparty.rs b/src/ext/pkix/name/ediparty.rs
index 94af09b..9d10040 100644
--- a/src/ext/pkix/name/ediparty.rs
+++ b/src/ext/pkix/name/ediparty.rs
@@ -27,10 +27,10 @@ use super::DirectoryString;
/// [RFC 5280 Section 4.2.1.6]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6
#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
-pub struct EdiPartyName<'a> {
+pub struct EdiPartyName {
#[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")]
- pub name_assigner: Option<DirectoryString<'a>>,
+ pub name_assigner: Option<DirectoryString>,
#[asn1(context_specific = "1", tag_mode = "EXPLICIT")]
- pub party_name: DirectoryString<'a>,
+ pub party_name: DirectoryString,
}
diff --git a/src/ext/pkix/name/general.rs b/src/ext/pkix/name/general.rs
index f6861d4..bd0fa7e 100644
--- a/src/ext/pkix/name/general.rs
+++ b/src/ext/pkix/name/general.rs
@@ -3,7 +3,7 @@
use super::{EdiPartyName, OtherName};
use crate::name::Name;
-use der::asn1::{Ia5StringRef, ObjectIdentifier, OctetStringRef};
+use der::asn1::{Ia5String, ObjectIdentifier, OctetString};
use der::{Choice, ValueOrd};
/// GeneralNames as defined in [RFC 5280 Section 4.2.1.6].
@@ -13,7 +13,7 @@ use der::{Choice, ValueOrd};
/// ```
///
/// [RFC 5280 Section 4.2.1.6]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6
-pub type GeneralNames<'a> = alloc::vec::Vec<GeneralName<'a>>;
+pub type GeneralNames = alloc::vec::Vec<GeneralName>;
/// GeneralName as defined in [RFC 5280 Section 4.2.1.6].
///
@@ -36,28 +36,74 @@ pub type GeneralNames<'a> = alloc::vec::Vec<GeneralName<'a>>;
/// [RFC 5280 Section 4.2.1.6]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6
#[derive(Clone, Debug, Eq, PartialEq, Choice, ValueOrd)]
#[allow(missing_docs)]
-pub enum GeneralName<'a> {
+pub enum GeneralName {
#[asn1(context_specific = "0", tag_mode = "IMPLICIT", constructed = "true")]
- OtherName(OtherName<'a>),
+ OtherName(OtherName),
#[asn1(context_specific = "1", tag_mode = "IMPLICIT")]
- Rfc822Name(Ia5StringRef<'a>),
+ Rfc822Name(Ia5String),
#[asn1(context_specific = "2", tag_mode = "IMPLICIT")]
- DnsName(Ia5StringRef<'a>),
+ DnsName(Ia5String),
#[asn1(context_specific = "4", tag_mode = "EXPLICIT", constructed = "true")]
- DirectoryName(Name<'a>),
+ DirectoryName(Name),
#[asn1(context_specific = "5", tag_mode = "IMPLICIT", constructed = "true")]
- EdiPartyName(EdiPartyName<'a>),
+ EdiPartyName(EdiPartyName),
#[asn1(context_specific = "6", tag_mode = "IMPLICIT")]
- UniformResourceIdentifier(Ia5StringRef<'a>),
+ UniformResourceIdentifier(Ia5String),
#[asn1(context_specific = "7", tag_mode = "IMPLICIT")]
- IpAddress(OctetStringRef<'a>),
+ IpAddress(OctetString),
#[asn1(context_specific = "8", tag_mode = "IMPLICIT")]
RegisteredId(ObjectIdentifier),
}
+
+#[cfg(feature = "std")]
+impl From<std::net::IpAddr> for GeneralName {
+ fn from(ip: std::net::IpAddr) -> Self {
+ // Safety: this is unfailable here, OctetString will issue an error if you go
+ // over 256MiB, here the buffer is at most 16 bytes (ipv6). The two `expect`s
+ // below are safe.
+ let buf = match ip {
+ std::net::IpAddr::V4(v) => {
+ let value = v.octets();
+ OctetString::new(&value[..])
+ .expect("OctetString is not expected to fail with a 4 bytes long buffer")
+ }
+ std::net::IpAddr::V6(v) => {
+ let value = v.octets();
+ OctetString::new(&value[..])
+ .expect("OctetString is not expected to fail with a 16 bytes long buffer")
+ }
+ };
+
+ GeneralName::IpAddress(buf)
+ }
+}
+
+#[cfg(all(feature = "std", test))]
+mod tests {
+ use super::*;
+ use der::Encode;
+
+ #[test]
+ fn test_convert() {
+ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+
+ let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
+ let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+
+ assert_eq!(
+ GeneralName::from(localhost_v4).to_der().unwrap(),
+ &[135, 4, 127, 0, 0, 1][..]
+ );
+ assert_eq!(
+ GeneralName::from(localhost_v6).to_der().unwrap(),
+ &[135, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1][..]
+ );
+ }
+}
diff --git a/src/ext/pkix/name/other.rs b/src/ext/pkix/name/other.rs
index a33601c..26b93bc 100644
--- a/src/ext/pkix/name/other.rs
+++ b/src/ext/pkix/name/other.rs
@@ -1,4 +1,4 @@
-use der::{asn1::ObjectIdentifier, AnyRef, Sequence, ValueOrd};
+use der::{asn1::ObjectIdentifier, Any, Sequence, ValueOrd};
/// OtherName as defined in [RFC 5280 Section 4.2.1.6].
///
@@ -12,26 +12,26 @@ use der::{asn1::ObjectIdentifier, AnyRef, Sequence, ValueOrd};
/// [RFC 5280 Section 4.2.1.6]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6
#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
-pub struct OtherName<'a> {
+pub struct OtherName {
pub type_id: ObjectIdentifier,
#[asn1(context_specific = "0", tag_mode = "EXPLICIT")]
- pub value: AnyRef<'a>,
+ pub value: Any,
}
#[test]
#[cfg(test)]
fn test() {
use alloc::string::ToString;
- use der::{Decode, Encode};
+ use der::{asn1::Utf8StringRef, Decode, Encode};
use hex_literal::hex;
let input = hex!("3021060A2B060104018237140203A0130C1155706E5F323134393530313330406D696C");
let decoded = OtherName::from_der(&input).unwrap();
- let onval = decoded.value.utf8_string().unwrap();
+ let onval = Utf8StringRef::try_from(&decoded.value).unwrap();
assert_eq!(onval.to_string(), "Upn_214950130@mil");
- let encoded = decoded.to_vec().unwrap();
+ let encoded = decoded.to_der().unwrap();
assert_eq!(&input[..], &encoded);
}
diff --git a/src/ext/pkix/policymap.rs b/src/ext/pkix/policymap.rs
index e6b55ba..1997f54 100644
--- a/src/ext/pkix/policymap.rs
+++ b/src/ext/pkix/policymap.rs
@@ -20,6 +20,7 @@ impl AssociatedOid for PolicyMappings {
}
impl_newtype!(PolicyMappings, Vec<PolicyMapping>);
+impl_extension!(PolicyMappings, critical = true);
/// PolicyMapping as defined in [RFC 5280 Section 4.2.1.5].
///