From 3ad14586eacda572763b339fdbc0d7c106c70845 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 6 Sep 2024 12:19:32 -0600 Subject: [PATCH 1/7] [WIP] x509-cert: make fields of certificate structs private This allows them to maintain invariants. Adds read-only accessor methods in place of public fields. --- x509-cert/src/certificate.rs | 74 +++++++++++++++++++++++++----- x509-cert/tests/certificate.rs | 50 ++++++++++---------- x509-cert/tests/pkix_extensions.rs | 54 +++++++++++----------- 3 files changed, 115 insertions(+), 63 deletions(-) diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index d435789a7..488fd5df1 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -1,6 +1,6 @@ //! Certificate types -use crate::{name::Name, serial_number::SerialNumber, time::Validity}; +use crate::{ext, name::Name, serial_number::SerialNumber, time::Validity}; use alloc::vec::Vec; use const_oid::AssociatedOid; use core::{cmp::Ordering, fmt::Debug}; @@ -143,26 +143,78 @@ pub struct TbsCertificateInner { /// require later versions. Care should be taken in order to ensure /// standards compliance. #[asn1(context_specific = "0", default = "Default::default")] - pub version: Version, + pub(crate) version: Version, - pub serial_number: SerialNumber

, - pub signature: AlgorithmIdentifierOwned, - pub issuer: Name, - pub validity: Validity

, - pub subject: Name, - pub subject_public_key_info: SubjectPublicKeyInfoOwned, + pub(crate) serial_number: SerialNumber

, + pub(crate) signature: AlgorithmIdentifierOwned, + pub(crate) issuer: Name, + pub(crate) validity: Validity

, + pub(crate) subject: Name, + pub(crate) subject_public_key_info: SubjectPublicKeyInfoOwned, #[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")] - pub issuer_unique_id: Option, + pub(crate) issuer_unique_id: Option, #[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")] - pub subject_unique_id: Option, + pub(crate) subject_unique_id: Option, #[asn1(context_specific = "3", tag_mode = "EXPLICIT", optional = "true")] - pub extensions: Option, + pub(crate) extensions: Option, } impl TbsCertificateInner

{ + /// Version of this certificate. + pub fn version(&self) -> Version { + self.version + } + + /// Serial number of this certificate. + pub fn serial_number(&self) -> &SerialNumber

{ + &self.serial_number + } + + /// Signature algorithm identifier. + pub fn signature(&self) -> &AlgorithmIdentifierOwned { + &self.signature + } + + /// Certificate issuer. + pub fn issuer(&self) -> &Name { + &self.issuer + } + + /// Validity period for this certificate. + pub fn validity(&self) -> &Validity

{ + &self.validity + } + + /// Subject of this certificate. + pub fn subject(&self) -> &Name { + &self.subject + } + + /// Subject Public Key Info (SPKI): public key information about this certificate including + /// algorithm identifier and key data. + pub fn subject_public_key_info(&self) -> &SubjectPublicKeyInfoOwned { + &self.subject_public_key_info + } + + /// Issuer unique ID. + pub fn issuer_unique_id(&self) -> &Option { + &self.issuer_unique_id + } + + /// Subject unique ID. + pub fn subject_unique_id(&self) -> &Option { + &self.subject_unique_id + } + + /// Certificate extensions. + pub fn extensions(&self) -> &ext::Extensions { + static EMPTY_EXTENSIONS: ext::Extensions = Vec::new(); + self.extensions.as_ref().unwrap_or(&EMPTY_EXTENSIONS) + } + /// Decodes a single extension /// /// Returns `Ok(None)` if the extension is not present. diff --git a/x509-cert/tests/certificate.rs b/x509-cert/tests/certificate.rs index 3984f9f03..ebcbc197d 100644 --- a/x509-cert/tests/certificate.rs +++ b/x509-cert/tests/certificate.rs @@ -137,22 +137,22 @@ fn reencode_cert() { // TODO - defer decode then re-encode version field - let encoded_serial = parsed_tbs.serial_number.to_der().unwrap(); + let encoded_serial = parsed_tbs.serial_number().to_der().unwrap(); assert_eq!(parsed_coverage_tbs.serial_number, encoded_serial); - let encoded_signature = parsed_tbs.signature.to_der().unwrap(); + let encoded_signature = parsed_tbs.signature().to_der().unwrap(); assert_eq!(parsed_coverage_tbs.signature, encoded_signature); - let encoded_issuer = parsed_tbs.issuer.to_der().unwrap(); + let encoded_issuer = parsed_tbs.issuer().to_der().unwrap(); assert_eq!(parsed_coverage_tbs.issuer, encoded_issuer); - let encoded_validity = parsed_tbs.validity.to_der().unwrap(); + let encoded_validity = parsed_tbs.validity().to_der().unwrap(); assert_eq!(parsed_coverage_tbs.validity, encoded_validity); - let encoded_subject = parsed_tbs.subject.to_der().unwrap(); + let encoded_subject = parsed_tbs.subject().to_der().unwrap(); assert_eq!(parsed_coverage_tbs.subject, encoded_subject); - let encoded_subject_public_key_info = parsed_tbs.subject_public_key_info.to_der().unwrap(); + let encoded_subject_public_key_info = parsed_tbs.subject_public_key_info().to_der().unwrap(); assert_eq!( parsed_coverage_tbs.subject_public_key_info, encoded_subject_public_key_info @@ -160,7 +160,7 @@ fn reencode_cert() { // TODO - either encode as context specific or decode to sequence. for know lop off context // specific tag and length - let encoded_extensions = parsed_tbs.extensions.to_der().unwrap(); + let encoded_extensions = parsed_tbs.extensions().to_der().unwrap(); assert_eq!(&parsed_coverage_tbs.extensions[4..], encoded_extensions); } @@ -199,7 +199,7 @@ fn decode_cert() { let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); println!("{:?}", cert); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); for (ext, (oid, crit)) in exts.iter().zip(EXTENSIONS) { assert_eq!(ext.extn_id.to_string(), *oid); assert_eq!(ext.critical, *crit); @@ -208,22 +208,22 @@ fn decode_cert() { let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - assert_eq!(cert.tbs_certificate.version, Version::V3); + assert_eq!(cert.tbs_certificate.version(), Version::V3); let target_serial: [u8; 16] = [ 0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x49, 0xCF, 0x70, 0x66, 0x4D, 0x00, 0x00, 0x00, 0x02, ]; assert_eq!( - cert.tbs_certificate.serial_number, - SerialNumber::new(&target_serial).unwrap() + cert.tbs_certificate.serial_number(), + &SerialNumber::new(&target_serial).unwrap() ); assert_eq!( - cert.tbs_certificate.signature.oid.to_string(), + cert.tbs_certificate.signature().oid.to_string(), "1.2.840.113549.1.1.11" ); assert_eq!( cert.tbs_certificate - .signature + .signature() .parameters .as_ref() .unwrap() @@ -232,14 +232,14 @@ fn decode_cert() { ); assert!(cert .tbs_certificate - .signature + .signature() .parameters .as_ref() .unwrap() .is_null()); let mut counter = 0; - let i = cert.tbs_certificate.issuer.0.iter(); + let i = cert.tbs_certificate.issuer().0.iter(); for rdn in i { let i1 = rdn.0.iter(); for atav in i1 { @@ -278,7 +278,7 @@ fn decode_cert() { assert_eq!( cert.tbs_certificate - .validity + .validity() .not_before .to_unix_duration() .as_secs(), @@ -286,7 +286,7 @@ fn decode_cert() { ); assert_eq!( cert.tbs_certificate - .validity + .validity() .not_after .to_unix_duration() .as_secs(), @@ -294,7 +294,7 @@ fn decode_cert() { ); counter = 0; - let i = cert.tbs_certificate.subject.0.iter(); + let i = cert.tbs_certificate.subject().0.iter(); for rdn in i { let i1 = rdn.0.iter(); for atav in i1 { @@ -338,7 +338,7 @@ fn decode_cert() { assert_eq!( cert.tbs_certificate - .subject_public_key_info + .subject_public_key_info() .algorithm .oid .to_string(), @@ -346,7 +346,7 @@ fn decode_cert() { ); assert_eq!( cert.tbs_certificate - .subject_public_key_info + .subject_public_key_info() .algorithm .parameters .as_ref() @@ -356,7 +356,7 @@ fn decode_cert() { ); assert!(cert .tbs_certificate - .subject_public_key_info + .subject_public_key_info() .algorithm .parameters .as_ref() @@ -365,7 +365,7 @@ fn decode_cert() { // TODO - parse and compare public key - let exts = cert.tbs_certificate.extensions.as_ref().unwrap(); + let exts = cert.tbs_certificate.extensions(); for (ext, (oid, crit)) in exts.iter().zip(EXTENSIONS) { assert_eq!(ext.extn_id.to_string(), *oid); assert_eq!(ext.critical, *crit); @@ -408,7 +408,7 @@ fn decode_cert_negative_serial_number() { let cert = Certificate::from_der(der_encoded_cert).unwrap(); assert_eq!( - cert.tbs_certificate.serial_number.as_bytes(), + cert.tbs_certificate.serial_number().as_bytes(), // INTEGER (125 bit) -2.370157924795571e+37 &[238, 43, 61, 235, 212, 33, 222, 20, 168, 98, 172, 4, 243, 221, 196, 1] ); @@ -429,13 +429,13 @@ fn decode_cert_overlength_serial_number() { let cert = CertificateInner::::from_pem(pem_encoded_cert).unwrap(); assert_eq!( - cert.tbs_certificate.serial_number.as_bytes(), + cert.tbs_certificate.serial_number().as_bytes(), &[ 0, 132, 206, 11, 246, 160, 254, 130, 78, 229, 229, 6, 202, 168, 157, 120, 198, 21, 1, 98, 87, 113 ] ); - assert_eq!(cert.tbs_certificate.serial_number.as_bytes().len(), 22); + assert_eq!(cert.tbs_certificate.serial_number().as_bytes().len(), 22); let reencoded = cert.to_pem(LineEnding::LF).unwrap(); assert_eq!(pem_encoded_cert, reencoded.as_bytes()); diff --git a/x509-cert/tests/pkix_extensions.rs b/x509-cert/tests/pkix_extensions.rs index 9d9973a0a..cd9e28ada 100644 --- a/x509-cert/tests/pkix_extensions.rs +++ b/x509-cert/tests/pkix_extensions.rs @@ -14,7 +14,7 @@ use x509_cert::{serial_number::SerialNumber, Certificate, Version}; use const_oid::db::rfc5280::*; use const_oid::db::rfc5912::ID_CE_CERTIFICATE_POLICIES; -fn spin_over_exts(exts: Extensions) { +fn spin_over_exts(exts: &Extensions) { for ext in exts { match ext.extn_id { SubjectDirectoryAttributes::OID => { @@ -211,7 +211,7 @@ fn decode_cert() { include_bytes!("examples/026EDA6FA1EDFA8C253936C75B5EEBD954BFF452.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); for (i, ext) in exts.iter().enumerate() { match i { 0 => { @@ -551,19 +551,19 @@ fn decode_cert() { let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - assert_eq!(cert.tbs_certificate.version, Version::V3); + assert_eq!(cert.tbs_certificate.version(), Version::V3); let target_serial: [u8; 1] = [2]; assert_eq!( - cert.tbs_certificate.serial_number, - SerialNumber::new(&target_serial).unwrap() + cert.tbs_certificate.serial_number(), + &SerialNumber::new(&target_serial).unwrap() ); assert_eq!( - cert.tbs_certificate.signature.oid.to_string(), + cert.tbs_certificate.signature().oid.to_string(), "1.2.840.113549.1.1.11" ); assert_eq!( cert.tbs_certificate - .signature + .signature() .parameters .as_ref() .unwrap() @@ -572,7 +572,7 @@ fn decode_cert() { ); assert_eq!( cert.tbs_certificate - .signature + .signature() .parameters .as_ref() .unwrap() @@ -581,7 +581,7 @@ fn decode_cert() { ); let mut counter = 0; - let i = cert.tbs_certificate.issuer.0.iter(); + let i = cert.tbs_certificate.issuer().0.iter(); for rdn in i { let i1 = rdn.0.iter(); for atav in i1 { @@ -616,7 +616,7 @@ fn decode_cert() { assert_eq!( cert.tbs_certificate - .validity + .validity() .not_before .to_unix_duration() .as_secs(), @@ -624,7 +624,7 @@ fn decode_cert() { ); assert_eq!( cert.tbs_certificate - .validity + .validity() .not_after .to_unix_duration() .as_secs(), @@ -632,7 +632,7 @@ fn decode_cert() { ); counter = 0; - let i = cert.tbs_certificate.subject.0.iter(); + let i = cert.tbs_certificate.subject().0.iter(); for rdn in i { let i1 = rdn.0.iter(); for atav in i1 { @@ -667,7 +667,7 @@ fn decode_cert() { assert_eq!( cert.tbs_certificate - .subject_public_key_info + .subject_public_key_info() .algorithm .oid .to_string(), @@ -675,7 +675,7 @@ fn decode_cert() { ); assert_eq!( cert.tbs_certificate - .subject_public_key_info + .subject_public_key_info() .algorithm .parameters .as_ref() @@ -685,7 +685,7 @@ fn decode_cert() { ); assert_eq!( cert.tbs_certificate - .subject_public_key_info + .subject_public_key_info() .algorithm .parameters .as_ref() @@ -697,7 +697,7 @@ fn decode_cert() { // TODO - parse and compare public key counter = 0; - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); let i = exts.iter(); for ext in i { if 0 == counter { @@ -765,49 +765,49 @@ fn decode_cert() { let der_encoded_cert = include_bytes!("examples/0954e2343dd5efe0a7f0967d69caf33e5f893720.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert adds extended key usage and name constraints vs above samples let der_encoded_cert = include_bytes!("examples/0fcc78fbbca9f32b08b19b032b84f2c86a128f35.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert adds logotype (which is unrecognized) vs above samples let der_encoded_cert = include_bytes!("examples/15b05c4865410c6b3ff76a4e8f3d87276756bd0c.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert features an EC key unlike the above samples let der_encoded_cert = include_bytes!("examples/16ee54e48c76eaa1052e09010d8faefee95e5ebb.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert adds issuer alt name vs above samples let der_encoded_cert = include_bytes!("examples/342cd9d3062da48c346965297f081ebc2ef68fdc.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert adds policy constraints vs above samples let der_encoded_cert = include_bytes!("examples/2049a5b28f104b2c6e1a08546f9cfc0353d6fd30.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert adds subject alt name vs above samples let der_encoded_cert = include_bytes!("examples/21723e7a0fb61a0bd4a29879b82a02b2fb4ad096.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert adds subject directory attributes vs above samples @@ -815,7 +815,7 @@ fn decode_cert() { include_bytes!("examples/085B1E2F40254F9C7A2387BE9FF4EC116C326E10.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert adds private key usage period (and an unprocessed Entrust extension) vs above samples @@ -823,7 +823,7 @@ fn decode_cert() { include_bytes!("examples/554D5FF11DA613A155584D8D4AA07F67724D8077.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert adds OCSP no check vs above samples @@ -831,7 +831,7 @@ fn decode_cert() { include_bytes!("examples/28879DABB0FD11618FB74E47BE049D2933866D53.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); // This cert adds PIV NACI indicator vs above samples @@ -839,7 +839,7 @@ fn decode_cert() { include_bytes!("examples/288C8BCFEE6B89D110DAE2C9873897BF7FF53382.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions.unwrap(); + let exts = cert.tbs_certificate.extensions(); spin_over_exts(exts); } From 5df77ad99068f25c952ed1429a7c10329ea739c8 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 6 Sep 2024 12:31:31 -0600 Subject: [PATCH 2/7] x509-ocsp: updates for x509-cert changes --- x509-ocsp/src/cert_id.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x509-ocsp/src/cert_id.rs b/x509-ocsp/src/cert_id.rs index 8fa036e2b..20ec831a4 100644 --- a/x509-ocsp/src/cert_id.rs +++ b/x509-ocsp/src/cert_id.rs @@ -66,13 +66,13 @@ mod builder { parameters: Some(Null.into()), }, issuer_name_hash: OctetString::new( - D::digest(issuer.tbs_certificate.subject.to_der()?).to_vec(), + D::digest(issuer.tbs_certificate.subject().to_der()?).to_vec(), )?, issuer_key_hash: OctetString::new( D::digest( issuer .tbs_certificate - .subject_public_key_info + .subject_public_key_info() .subject_public_key .raw_bytes(), ) @@ -93,7 +93,7 @@ mod builder { where D: Digest + AssociatedOid, { - Self::from_issuer::(issuer, cert.tbs_certificate.serial_number.clone()) + Self::from_issuer::(issuer, cert.tbs_certificate.serial_number().clone()) } } } From 28328f1a04b3c6e41ed351af48b31b314443bee2 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 6 Sep 2024 13:44:12 -0600 Subject: [PATCH 3/7] cmpv2,cms,x509-ocsp: fixes for x509-cert API changes --- cmpv2/tests/cert_req.rs | 2 +- cmpv2/tests/init_req.rs | 4 +++- cmpv2/tests/p10cr_req.rs | 2 +- cms/tests/enveloped_data.rs | 22 ++++++++++++++-------- x509-ocsp/src/builder/response.rs | 2 +- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/cmpv2/tests/cert_req.rs b/cmpv2/tests/cert_req.rs index 1dc38ad2f..4cbcb0ab3 100644 --- a/cmpv2/tests/cert_req.rs +++ b/cmpv2/tests/cert_req.rs @@ -127,7 +127,7 @@ fn cr_rsp_message_test() { let server_cert = Certificate::from_der(enc_server_cert).unwrap(); let header = &message.header; match &header.sender { - GeneralName::DirectoryName(name) => assert_eq!(server_cert.tbs_certificate.subject, *name), + GeneralName::DirectoryName(name) => assert_eq!(server_cert.tbs_certificate.subject(), name), _ => panic!(), } match &header.recipient { diff --git a/cmpv2/tests/init_req.rs b/cmpv2/tests/init_req.rs index 3a9d0a98c..adfa0e671 100644 --- a/cmpv2/tests/init_req.rs +++ b/cmpv2/tests/init_req.rs @@ -234,7 +234,9 @@ fn ir_rsp_message_test() { let server_cert = Certificate::from_der(enc_server_cert).unwrap(); let header = &message.header; match &header.sender { - GeneralName::DirectoryName(name) => assert_eq!(server_cert.tbs_certificate.subject, *name), + GeneralName::DirectoryName(name) => { + assert_eq!(server_cert.tbs_certificate.subject(), name) + } _ => panic!(), } match &header.recipient { diff --git a/cmpv2/tests/p10cr_req.rs b/cmpv2/tests/p10cr_req.rs index 0af25935c..93fcfa20d 100644 --- a/cmpv2/tests/p10cr_req.rs +++ b/cmpv2/tests/p10cr_req.rs @@ -58,7 +58,7 @@ fn p10cr_req_message_test() { match &message.body { PkiBody::P10cr(p10crs) => { assert_eq!( - ee_cert.tbs_certificate.subject.to_string(), + ee_cert.tbs_certificate.subject().to_string(), p10crs.info.subject.to_string() ); } diff --git a/cms/tests/enveloped_data.rs b/cms/tests/enveloped_data.rs index 13744995c..8549a4bfc 100644 --- a/cms/tests/enveloped_data.rs +++ b/cms/tests/enveloped_data.rs @@ -49,8 +49,8 @@ fn reencode_enveloped_data_ktri_test() { ); match &ktri.rid { RecipientIdentifier::IssuerAndSerialNumber(iasn) => { - assert_eq!(cert.tbs_certificate.issuer, iasn.issuer); - assert_eq!(cert.tbs_certificate.serial_number, iasn.serial_number); + assert_eq!(cert.tbs_certificate.issuer(), &iasn.issuer); + assert_eq!(cert.tbs_certificate.serial_number(), &iasn.serial_number); } _ => panic!(), } @@ -146,8 +146,8 @@ fn reencode_enveloped_data_kari_test() { for rk in &kari.recipient_enc_keys { match &rk.rid { KeyAgreeRecipientIdentifier::IssuerAndSerialNumber(iasn) => { - assert_eq!(cert.tbs_certificate.issuer, iasn.issuer); - assert_eq!(cert.tbs_certificate.serial_number, iasn.serial_number); + assert_eq!(cert.tbs_certificate.issuer(), &iasn.issuer); + assert_eq!(cert.tbs_certificate.serial_number(), &iasn.serial_number); } _ => panic!(), } @@ -375,8 +375,11 @@ fn reencode_enveloped_data_multi_test() { ); match &ktri.rid { RecipientIdentifier::IssuerAndSerialNumber(iasn) => { - assert_eq!(rsa_cert.tbs_certificate.issuer, iasn.issuer); - assert_eq!(rsa_cert.tbs_certificate.serial_number, iasn.serial_number); + assert_eq!(rsa_cert.tbs_certificate.issuer(), &iasn.issuer); + assert_eq!( + rsa_cert.tbs_certificate.serial_number(), + &iasn.serial_number + ); } _ => panic!(), } @@ -415,8 +418,11 @@ fn reencode_enveloped_data_multi_test() { for rk in &kari.recipient_enc_keys { match &rk.rid { KeyAgreeRecipientIdentifier::IssuerAndSerialNumber(iasn) => { - assert_eq!(ec_cert.tbs_certificate.issuer, iasn.issuer); - assert_eq!(ec_cert.tbs_certificate.serial_number, iasn.serial_number); + assert_eq!(ec_cert.tbs_certificate.issuer(), &iasn.issuer); + assert_eq!( + ec_cert.tbs_certificate.serial_number(), + &iasn.serial_number + ); } _ => panic!(), } diff --git a/x509-ocsp/src/builder/response.rs b/x509-ocsp/src/builder/response.rs index d77349d8d..2dcef3feb 100644 --- a/x509-ocsp/src/builder/response.rs +++ b/x509-ocsp/src/builder/response.rs @@ -40,7 +40,7 @@ use x509_cert::{ /// let req = OcspRequest::from_der(OCSP_REQ_DER).unwrap(); /// let ca = Certificate::from_der(CA_DER).unwrap(); /// -/// let mut builder = OcspResponseBuilder::new(ca.tbs_certificate.subject.clone()) +/// let mut builder = OcspResponseBuilder::new(ca.tbs_certificate.subject().clone()) /// .with_single_response( /// SingleResponse::new( /// req.tbs_request.request_list[0].req_cert.clone(), From c78759f92fe07b9f156417fff01831bdc1f080d8 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 7 Sep 2024 13:00:12 -0600 Subject: [PATCH 4/7] x509-cert: make CertificateInner fields private; add accessor methods --- cmpv2/tests/cert_req.rs | 4 +- cmpv2/tests/init_req.rs | 2 +- cmpv2/tests/p10cr_req.rs | 2 +- cms/tests/builder.rs | 2 +- cms/tests/enveloped_data.rs | 16 +++---- x509-cert/src/certificate.rs | 24 +++++++++-- x509-cert/tests/certificate.rs | 46 ++++++++++---------- x509-cert/tests/pkix_extensions.rs | 67 +++++++++++++++++------------- x509-ocsp/src/cert_id.rs | 6 +-- 9 files changed, 102 insertions(+), 67 deletions(-) diff --git a/cmpv2/tests/cert_req.rs b/cmpv2/tests/cert_req.rs index 4cbcb0ab3..322e8aa52 100644 --- a/cmpv2/tests/cert_req.rs +++ b/cmpv2/tests/cert_req.rs @@ -127,7 +127,9 @@ fn cr_rsp_message_test() { let server_cert = Certificate::from_der(enc_server_cert).unwrap(); let header = &message.header; match &header.sender { - GeneralName::DirectoryName(name) => assert_eq!(server_cert.tbs_certificate.subject(), name), + GeneralName::DirectoryName(name) => { + assert_eq!(server_cert.tbs_certificate().subject(), name) + } _ => panic!(), } match &header.recipient { diff --git a/cmpv2/tests/init_req.rs b/cmpv2/tests/init_req.rs index adfa0e671..a3e5d866a 100644 --- a/cmpv2/tests/init_req.rs +++ b/cmpv2/tests/init_req.rs @@ -235,7 +235,7 @@ fn ir_rsp_message_test() { let header = &message.header; match &header.sender { GeneralName::DirectoryName(name) => { - assert_eq!(server_cert.tbs_certificate.subject(), name) + assert_eq!(server_cert.tbs_certificate().subject(), name) } _ => panic!(), } diff --git a/cmpv2/tests/p10cr_req.rs b/cmpv2/tests/p10cr_req.rs index 93fcfa20d..d771c5940 100644 --- a/cmpv2/tests/p10cr_req.rs +++ b/cmpv2/tests/p10cr_req.rs @@ -58,7 +58,7 @@ fn p10cr_req_message_test() { match &message.body { PkiBody::P10cr(p10crs) => { assert_eq!( - ee_cert.tbs_certificate.subject().to_string(), + ee_cert.tbs_certificate().subject().to_string(), p10crs.info.subject.to_string() ); } diff --git a/cms/tests/builder.rs b/cms/tests/builder.rs index a3fa2322b..990c9398e 100644 --- a/cms/tests/builder.rs +++ b/cms/tests/builder.rs @@ -522,7 +522,7 @@ fn test_degenerate_certificates_only_cms() { }; let original_cert = x509_cert::Certificate::from_pem(cert_buf).unwrap(); - assert_eq!(original_cert.signature, extracted_cert.signature) + assert_eq!(original_cert.signature(), extracted_cert.signature()) } #[test] diff --git a/cms/tests/enveloped_data.rs b/cms/tests/enveloped_data.rs index 8549a4bfc..a89400ddd 100644 --- a/cms/tests/enveloped_data.rs +++ b/cms/tests/enveloped_data.rs @@ -49,8 +49,8 @@ fn reencode_enveloped_data_ktri_test() { ); match &ktri.rid { RecipientIdentifier::IssuerAndSerialNumber(iasn) => { - assert_eq!(cert.tbs_certificate.issuer(), &iasn.issuer); - assert_eq!(cert.tbs_certificate.serial_number(), &iasn.serial_number); + assert_eq!(cert.tbs_certificate().issuer(), &iasn.issuer); + assert_eq!(cert.tbs_certificate().serial_number(), &iasn.serial_number); } _ => panic!(), } @@ -146,8 +146,8 @@ fn reencode_enveloped_data_kari_test() { for rk in &kari.recipient_enc_keys { match &rk.rid { KeyAgreeRecipientIdentifier::IssuerAndSerialNumber(iasn) => { - assert_eq!(cert.tbs_certificate.issuer(), &iasn.issuer); - assert_eq!(cert.tbs_certificate.serial_number(), &iasn.serial_number); + assert_eq!(cert.tbs_certificate().issuer(), &iasn.issuer); + assert_eq!(cert.tbs_certificate().serial_number(), &iasn.serial_number); } _ => panic!(), } @@ -375,9 +375,9 @@ fn reencode_enveloped_data_multi_test() { ); match &ktri.rid { RecipientIdentifier::IssuerAndSerialNumber(iasn) => { - assert_eq!(rsa_cert.tbs_certificate.issuer(), &iasn.issuer); + assert_eq!(rsa_cert.tbs_certificate().issuer(), &iasn.issuer); assert_eq!( - rsa_cert.tbs_certificate.serial_number(), + rsa_cert.tbs_certificate().serial_number(), &iasn.serial_number ); } @@ -418,9 +418,9 @@ fn reencode_enveloped_data_multi_test() { for rk in &kari.recipient_enc_keys { match &rk.rid { KeyAgreeRecipientIdentifier::IssuerAndSerialNumber(iasn) => { - assert_eq!(ec_cert.tbs_certificate.issuer(), &iasn.issuer); + assert_eq!(ec_cert.tbs_certificate().issuer(), &iasn.issuer); assert_eq!( - ec_cert.tbs_certificate.serial_number(), + ec_cert.tbs_certificate().serial_number(), &iasn.serial_number ); } diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index 488fd5df1..0c69baf48 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -310,9 +310,27 @@ pub type Certificate = CertificateInner; #[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct CertificateInner { - pub tbs_certificate: TbsCertificateInner

, - pub signature_algorithm: AlgorithmIdentifierOwned, - pub signature: BitString, + pub(crate) tbs_certificate: TbsCertificateInner

, + pub(crate) signature_algorithm: AlgorithmIdentifierOwned, + pub(crate) signature: BitString, +} + +impl CertificateInner

{ + /// Get the [`TbsCertificateInner`] (i.e. the part the signature is computed over). + pub fn tbs_certificate(&self) -> &TbsCertificateInner

{ + &self.tbs_certificate + } + + /// Signature algorithm. + pub fn signature_algorithm(&self) -> &AlgorithmIdentifierOwned { + &self.signature_algorithm + } + + /// Signature over the certificate using the algorithm identified in + /// [`CertificateInner::signature_algorithm`]. + pub fn signature(&self) -> &BitString { + &self.signature + } } #[cfg(feature = "pem")] diff --git a/x509-cert/tests/certificate.rs b/x509-cert/tests/certificate.rs index ebcbc197d..182abdae4 100644 --- a/x509-cert/tests/certificate.rs +++ b/x509-cert/tests/certificate.rs @@ -199,7 +199,7 @@ fn decode_cert() { let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); println!("{:?}", cert); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); for (ext, (oid, crit)) in exts.iter().zip(EXTENSIONS) { assert_eq!(ext.extn_id.to_string(), *oid); assert_eq!(ext.critical, *crit); @@ -208,21 +208,21 @@ fn decode_cert() { let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - assert_eq!(cert.tbs_certificate.version(), Version::V3); + assert_eq!(cert.tbs_certificate().version(), Version::V3); let target_serial: [u8; 16] = [ 0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x49, 0xCF, 0x70, 0x66, 0x4D, 0x00, 0x00, 0x00, 0x02, ]; assert_eq!( - cert.tbs_certificate.serial_number(), + cert.tbs_certificate().serial_number(), &SerialNumber::new(&target_serial).unwrap() ); assert_eq!( - cert.tbs_certificate.signature().oid.to_string(), + cert.tbs_certificate().signature().oid.to_string(), "1.2.840.113549.1.1.11" ); assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .signature() .parameters .as_ref() @@ -231,7 +231,7 @@ fn decode_cert() { Tag::Null ); assert!(cert - .tbs_certificate + .tbs_certificate() .signature() .parameters .as_ref() @@ -239,7 +239,7 @@ fn decode_cert() { .is_null()); let mut counter = 0; - let i = cert.tbs_certificate.issuer().0.iter(); + let i = cert.tbs_certificate().issuer().0.iter(); for rdn in i { let i1 = rdn.0.iter(); for atav in i1 { @@ -277,7 +277,7 @@ fn decode_cert() { } assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .validity() .not_before .to_unix_duration() @@ -285,7 +285,7 @@ fn decode_cert() { 1416524490 ); assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .validity() .not_after .to_unix_duration() @@ -294,7 +294,7 @@ fn decode_cert() { ); counter = 0; - let i = cert.tbs_certificate.subject().0.iter(); + let i = cert.tbs_certificate().subject().0.iter(); for rdn in i { let i1 = rdn.0.iter(); for atav in i1 { @@ -337,7 +337,7 @@ fn decode_cert() { } assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .subject_public_key_info() .algorithm .oid @@ -345,7 +345,7 @@ fn decode_cert() { "1.2.840.113549.1.1.1" ); assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .subject_public_key_info() .algorithm .parameters @@ -355,7 +355,7 @@ fn decode_cert() { Tag::Null ); assert!(cert - .tbs_certificate + .tbs_certificate() .subject_public_key_info() .algorithm .parameters @@ -365,22 +365,26 @@ fn decode_cert() { // TODO - parse and compare public key - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); for (ext, (oid, crit)) in exts.iter().zip(EXTENSIONS) { assert_eq!(ext.extn_id.to_string(), *oid); assert_eq!(ext.critical, *crit); } assert_eq!( - cert.signature_algorithm.oid.to_string(), + cert.signature_algorithm().oid.to_string(), "1.2.840.113549.1.1.11" ); assert_eq!( - cert.signature_algorithm.parameters.as_ref().unwrap().tag(), + cert.signature_algorithm() + .parameters + .as_ref() + .unwrap() + .tag(), Tag::Null ); assert!(cert - .signature_algorithm + .signature_algorithm() .parameters .as_ref() .unwrap() @@ -388,7 +392,7 @@ fn decode_cert() { assert_eq!( &hex!("2A892F357BF3EF19E1211986106803FA18E66237802F1B1B0C6756CE678DB01D72CD0A4EB7171C2CDDF110ACD38AA65C35699E869C219AD7550AA4F287BB784F72EF8C9EA0E3DD103EFE5BF182EA36FFBCB45AAE65840263680534789C4F3215AF5454AD48CBC4B7A881E0135401A0BD5A849C11101DD1C66178E762C00DF59DD50F8DE9ED46FC6A0D742AE5697D87DD08DAC5291A75FB13C82FF2865C9E36799EA726137E1814E6A878C9532E8FC3D0A2A942D1CCC668FFCEAC255E6002FDE5ACDF2CE47556BB141C3A797A4BFDB673F6F1C229D7914FFEEF1505EE36F8038137D1B8F90106994BAB3E6FF0F60360A2E32F7A30B7ECEC1502DF3CC725BD6E436BA8F96A1847C9CEBB3F5A5906472292501D59BE1A98475BB1F30B677FAA8A45E351640C85B1B22661D33BD23EC6C0CA33DDD79E1120C7FC869EC4D0175ADB4A258AEAC5E8D2F0F578B8BF4B2C5DCC3269768AAA5B9E26D0592C5BB09C702C72E0A60F66D3EEB2B4983279634D59B0A2011B0E26AE796CC95D3243DF49615434E5CC06C374C3F936C005D360CAE6101F3AE7E97E29A157F5020770D4648D7877EBF8248CF3F3E68F9957A36F92D50616F2C60D3842327EF9BC0312CFF03A48C78E97254C2ADEADCA05069168443D833831FF66295A2EED685F164F1DBE01F8C897E1F63D42851682CBEE7B5A64D7BA2923D33644DBF1F7B3EDCE996F9928F043"), - cert.signature.raw_bytes() + cert.signature().raw_bytes() ); #[cfg(feature = "pem")] @@ -408,7 +412,7 @@ fn decode_cert_negative_serial_number() { let cert = Certificate::from_der(der_encoded_cert).unwrap(); assert_eq!( - cert.tbs_certificate.serial_number().as_bytes(), + cert.tbs_certificate().serial_number().as_bytes(), // INTEGER (125 bit) -2.370157924795571e+37 &[238, 43, 61, 235, 212, 33, 222, 20, 168, 98, 172, 4, 243, 221, 196, 1] ); @@ -429,13 +433,13 @@ fn decode_cert_overlength_serial_number() { let cert = CertificateInner::::from_pem(pem_encoded_cert).unwrap(); assert_eq!( - cert.tbs_certificate.serial_number().as_bytes(), + cert.tbs_certificate().serial_number().as_bytes(), &[ 0, 132, 206, 11, 246, 160, 254, 130, 78, 229, 229, 6, 202, 168, 157, 120, 198, 21, 1, 98, 87, 113 ] ); - assert_eq!(cert.tbs_certificate.serial_number().as_bytes().len(), 22); + assert_eq!(cert.tbs_certificate().serial_number().as_bytes().len(), 22); let reencoded = cert.to_pem(LineEnding::LF).unwrap(); assert_eq!(pem_encoded_cert, reencoded.as_bytes()); diff --git a/x509-cert/tests/pkix_extensions.rs b/x509-cert/tests/pkix_extensions.rs index cd9e28ada..64e710852 100644 --- a/x509-cert/tests/pkix_extensions.rs +++ b/x509-cert/tests/pkix_extensions.rs @@ -211,7 +211,7 @@ fn decode_cert() { include_bytes!("examples/026EDA6FA1EDFA8C253936C75B5EEBD954BFF452.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); for (i, ext) in exts.iter().enumerate() { match i { 0 => { @@ -551,18 +551,18 @@ fn decode_cert() { let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - assert_eq!(cert.tbs_certificate.version(), Version::V3); + assert_eq!(cert.tbs_certificate().version(), Version::V3); let target_serial: [u8; 1] = [2]; assert_eq!( - cert.tbs_certificate.serial_number(), + cert.tbs_certificate().serial_number(), &SerialNumber::new(&target_serial).unwrap() ); assert_eq!( - cert.tbs_certificate.signature().oid.to_string(), + cert.tbs_certificate().signature().oid.to_string(), "1.2.840.113549.1.1.11" ); assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .signature() .parameters .as_ref() @@ -571,7 +571,7 @@ fn decode_cert() { Tag::Null ); assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .signature() .parameters .as_ref() @@ -581,7 +581,7 @@ fn decode_cert() { ); let mut counter = 0; - let i = cert.tbs_certificate.issuer().0.iter(); + let i = cert.tbs_certificate().issuer().0.iter(); for rdn in i { let i1 = rdn.0.iter(); for atav in i1 { @@ -615,7 +615,7 @@ fn decode_cert() { } assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .validity() .not_before .to_unix_duration() @@ -623,7 +623,7 @@ fn decode_cert() { 1262334600 ); assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .validity() .not_after .to_unix_duration() @@ -632,7 +632,7 @@ fn decode_cert() { ); counter = 0; - let i = cert.tbs_certificate.subject().0.iter(); + let i = cert.tbs_certificate().subject().0.iter(); for rdn in i { let i1 = rdn.0.iter(); for atav in i1 { @@ -666,7 +666,7 @@ fn decode_cert() { } assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .subject_public_key_info() .algorithm .oid @@ -674,7 +674,7 @@ fn decode_cert() { "1.2.840.113549.1.1.1" ); assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .subject_public_key_info() .algorithm .parameters @@ -684,7 +684,7 @@ fn decode_cert() { Tag::Null ); assert_eq!( - cert.tbs_certificate + cert.tbs_certificate() .subject_public_key_info() .algorithm .parameters @@ -697,7 +697,7 @@ fn decode_cert() { // TODO - parse and compare public key counter = 0; - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); let i = exts.iter(); for ext in i { if 0 == counter { @@ -750,14 +750,25 @@ fn decode_cert() { counter += 1; } assert_eq!( - cert.signature_algorithm.oid.to_string(), + cert.signature_algorithm().oid.to_string(), "1.2.840.113549.1.1.11" ); assert_eq!( - cert.signature_algorithm.parameters.as_ref().unwrap().tag(), + cert.signature_algorithm() + .parameters + .as_ref() + .unwrap() + .tag(), Tag::Null ); - assert_eq!(cert.signature_algorithm.parameters.unwrap().is_null(), true); + assert_eq!( + cert.signature_algorithm() + .parameters + .as_ref() + .unwrap() + .is_null(), + true + ); // TODO - parse and compare signature value @@ -765,49 +776,49 @@ fn decode_cert() { let der_encoded_cert = include_bytes!("examples/0954e2343dd5efe0a7f0967d69caf33e5f893720.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert adds extended key usage and name constraints vs above samples let der_encoded_cert = include_bytes!("examples/0fcc78fbbca9f32b08b19b032b84f2c86a128f35.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert adds logotype (which is unrecognized) vs above samples let der_encoded_cert = include_bytes!("examples/15b05c4865410c6b3ff76a4e8f3d87276756bd0c.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert features an EC key unlike the above samples let der_encoded_cert = include_bytes!("examples/16ee54e48c76eaa1052e09010d8faefee95e5ebb.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert adds issuer alt name vs above samples let der_encoded_cert = include_bytes!("examples/342cd9d3062da48c346965297f081ebc2ef68fdc.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert adds policy constraints vs above samples let der_encoded_cert = include_bytes!("examples/2049a5b28f104b2c6e1a08546f9cfc0353d6fd30.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert adds subject alt name vs above samples let der_encoded_cert = include_bytes!("examples/21723e7a0fb61a0bd4a29879b82a02b2fb4ad096.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert adds subject directory attributes vs above samples @@ -815,7 +826,7 @@ fn decode_cert() { include_bytes!("examples/085B1E2F40254F9C7A2387BE9FF4EC116C326E10.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert adds private key usage period (and an unprocessed Entrust extension) vs above samples @@ -823,7 +834,7 @@ fn decode_cert() { include_bytes!("examples/554D5FF11DA613A155584D8D4AA07F67724D8077.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert adds OCSP no check vs above samples @@ -831,7 +842,7 @@ fn decode_cert() { include_bytes!("examples/28879DABB0FD11618FB74E47BE049D2933866D53.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); // This cert adds PIV NACI indicator vs above samples @@ -839,7 +850,7 @@ fn decode_cert() { include_bytes!("examples/288C8BCFEE6B89D110DAE2C9873897BF7FF53382.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate.extensions(); + let exts = cert.tbs_certificate().extensions(); spin_over_exts(exts); } diff --git a/x509-ocsp/src/cert_id.rs b/x509-ocsp/src/cert_id.rs index 20ec831a4..fcc153c4c 100644 --- a/x509-ocsp/src/cert_id.rs +++ b/x509-ocsp/src/cert_id.rs @@ -66,12 +66,12 @@ mod builder { parameters: Some(Null.into()), }, issuer_name_hash: OctetString::new( - D::digest(issuer.tbs_certificate.subject().to_der()?).to_vec(), + D::digest(issuer.tbs_certificate().subject().to_der()?).to_vec(), )?, issuer_key_hash: OctetString::new( D::digest( issuer - .tbs_certificate + .tbs_certificate() .subject_public_key_info() .subject_public_key .raw_bytes(), @@ -93,7 +93,7 @@ mod builder { where D: Digest + AssociatedOid, { - Self::from_issuer::(issuer, cert.tbs_certificate.serial_number().clone()) + Self::from_issuer::(issuer, cert.tbs_certificate().serial_number().clone()) } } } From 3da9f15cbf659054ee3490c146f064dc10befd0c Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 7 Sep 2024 13:05:18 -0600 Subject: [PATCH 5/7] Have `TbsCertificateInner::extensions` return `Option<&ext::Extensions>` --- x509-cert/src/certificate.rs | 5 ++--- x509-cert/tests/certificate.rs | 6 +++--- x509-cert/tests/pkix_extensions.rs | 26 +++++++++++++------------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index 0c69baf48..21c836618 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -210,9 +210,8 @@ impl TbsCertificateInner

{ } /// Certificate extensions. - pub fn extensions(&self) -> &ext::Extensions { - static EMPTY_EXTENSIONS: ext::Extensions = Vec::new(); - self.extensions.as_ref().unwrap_or(&EMPTY_EXTENSIONS) + pub fn extensions(&self) -> Option<&ext::Extensions> { + self.extensions.as_ref() } /// Decodes a single extension diff --git a/x509-cert/tests/certificate.rs b/x509-cert/tests/certificate.rs index 182abdae4..230620e11 100644 --- a/x509-cert/tests/certificate.rs +++ b/x509-cert/tests/certificate.rs @@ -160,7 +160,7 @@ fn reencode_cert() { // TODO - either encode as context specific or decode to sequence. for know lop off context // specific tag and length - let encoded_extensions = parsed_tbs.extensions().to_der().unwrap(); + let encoded_extensions = parsed_tbs.extensions().unwrap().to_der().unwrap(); assert_eq!(&parsed_coverage_tbs.extensions[4..], encoded_extensions); } @@ -199,7 +199,7 @@ fn decode_cert() { let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); println!("{:?}", cert); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); for (ext, (oid, crit)) in exts.iter().zip(EXTENSIONS) { assert_eq!(ext.extn_id.to_string(), *oid); assert_eq!(ext.critical, *crit); @@ -365,7 +365,7 @@ fn decode_cert() { // TODO - parse and compare public key - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); for (ext, (oid, crit)) in exts.iter().zip(EXTENSIONS) { assert_eq!(ext.extn_id.to_string(), *oid); assert_eq!(ext.critical, *crit); diff --git a/x509-cert/tests/pkix_extensions.rs b/x509-cert/tests/pkix_extensions.rs index 64e710852..1560a893d 100644 --- a/x509-cert/tests/pkix_extensions.rs +++ b/x509-cert/tests/pkix_extensions.rs @@ -211,7 +211,7 @@ fn decode_cert() { include_bytes!("examples/026EDA6FA1EDFA8C253936C75B5EEBD954BFF452.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); for (i, ext) in exts.iter().enumerate() { match i { 0 => { @@ -697,7 +697,7 @@ fn decode_cert() { // TODO - parse and compare public key counter = 0; - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); let i = exts.iter(); for ext in i { if 0 == counter { @@ -776,49 +776,49 @@ fn decode_cert() { let der_encoded_cert = include_bytes!("examples/0954e2343dd5efe0a7f0967d69caf33e5f893720.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert adds extended key usage and name constraints vs above samples let der_encoded_cert = include_bytes!("examples/0fcc78fbbca9f32b08b19b032b84f2c86a128f35.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert adds logotype (which is unrecognized) vs above samples let der_encoded_cert = include_bytes!("examples/15b05c4865410c6b3ff76a4e8f3d87276756bd0c.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert features an EC key unlike the above samples let der_encoded_cert = include_bytes!("examples/16ee54e48c76eaa1052e09010d8faefee95e5ebb.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert adds issuer alt name vs above samples let der_encoded_cert = include_bytes!("examples/342cd9d3062da48c346965297f081ebc2ef68fdc.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert adds policy constraints vs above samples let der_encoded_cert = include_bytes!("examples/2049a5b28f104b2c6e1a08546f9cfc0353d6fd30.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert adds subject alt name vs above samples let der_encoded_cert = include_bytes!("examples/21723e7a0fb61a0bd4a29879b82a02b2fb4ad096.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert adds subject directory attributes vs above samples @@ -826,7 +826,7 @@ fn decode_cert() { include_bytes!("examples/085B1E2F40254F9C7A2387BE9FF4EC116C326E10.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert adds private key usage period (and an unprocessed Entrust extension) vs above samples @@ -834,7 +834,7 @@ fn decode_cert() { include_bytes!("examples/554D5FF11DA613A155584D8D4AA07F67724D8077.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert adds OCSP no check vs above samples @@ -842,7 +842,7 @@ fn decode_cert() { include_bytes!("examples/28879DABB0FD11618FB74E47BE049D2933866D53.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); // This cert adds PIV NACI indicator vs above samples @@ -850,7 +850,7 @@ fn decode_cert() { include_bytes!("examples/288C8BCFEE6B89D110DAE2C9873897BF7FF53382.fake.der"); let result = Certificate::from_der(der_encoded_cert); let cert: Certificate = result.unwrap(); - let exts = cert.tbs_certificate().extensions(); + let exts = cert.tbs_certificate().extensions().unwrap(); spin_over_exts(exts); } From 379c28dc6df2d69ce81a03ca483b66b11ff67c48 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 7 Sep 2024 13:09:43 -0600 Subject: [PATCH 6/7] x509-cert: fix rustdoc --- x509-cert/src/certificate.rs | 4 ++-- x509-ocsp/src/builder/response.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index 21c836618..bd3eb46e5 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -228,7 +228,7 @@ impl TbsCertificateInner

{ /// use x509_cert::{der::DecodePem, ext::pkix::BasicConstraints, Certificate}; /// let certificate = Certificate::from_pem(CERT_PEM.as_bytes()).expect("parse certificate"); /// - /// let (critical, constraints) = certificate.tbs_certificate.get_extension::() + /// let (critical, constraints) = certificate.tbs_certificate().get_extension::() /// .expect("Failed to parse extension") /// .expect("Basic constraints expected"); /// # let _ = constraints; @@ -264,7 +264,7 @@ impl TbsCertificateInner

{ /// use x509_cert::{der::DecodePem, ext::pkix::BasicConstraints, Certificate}; /// let certificate = Certificate::from_pem(CERT_PEM.as_bytes()).expect("parse certificate"); /// - /// let mut extensions_found = certificate.tbs_certificate.filter_extensions::(); + /// let mut extensions_found = certificate.tbs_certificate().filter_extensions::(); /// while let Some(Ok((critical, extension))) = extensions_found.next() { /// println!("Found (critical={critical}): {extension:?}"); /// } diff --git a/x509-ocsp/src/builder/response.rs b/x509-ocsp/src/builder/response.rs index 2dcef3feb..c283251d5 100644 --- a/x509-ocsp/src/builder/response.rs +++ b/x509-ocsp/src/builder/response.rs @@ -40,7 +40,7 @@ use x509_cert::{ /// let req = OcspRequest::from_der(OCSP_REQ_DER).unwrap(); /// let ca = Certificate::from_der(CA_DER).unwrap(); /// -/// let mut builder = OcspResponseBuilder::new(ca.tbs_certificate.subject().clone()) +/// let mut builder = OcspResponseBuilder::new(ca.tbs_certificate().subject().clone()) /// .with_single_response( /// SingleResponse::new( /// req.tbs_request.request_list[0].req_cert.clone(), From 53c16e6ad13740a9b4f0ee72551c88719288e25f Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 8 Sep 2024 12:08:23 -0600 Subject: [PATCH 7/7] rustdoc improvements --- x509-cert/src/certificate.rs | 46 ++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index bd3eb46e5..5a1702ca6 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -136,7 +136,7 @@ pub type TbsCertificate = TbsCertificateInner; #[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct TbsCertificateInner { - /// The certificate version + /// The certificate version. /// /// Note that this value defaults to Version 1 per the RFC. However, /// fields such as `issuer_unique_id`, `subject_unique_id` and `extensions` @@ -163,32 +163,40 @@ pub struct TbsCertificateInner { } impl TbsCertificateInner

{ - /// Version of this certificate. + /// [`Version`] of this certificate (v1/v2/v3). pub fn version(&self) -> Version { self.version } /// Serial number of this certificate. + /// + /// X.509 serial numbers are used to uniquely identify certificates issued by a given + /// Certificate Authority (CA) identified in the `issuer` field. pub fn serial_number(&self) -> &SerialNumber

{ &self.serial_number } - /// Signature algorithm identifier. + /// Identifies the signature algorithm that this `TBSCertificate` should be signed with. + /// + /// In a signed certificate, matches [`CertificateInner::signature_algorithm`]. pub fn signature(&self) -> &AlgorithmIdentifierOwned { &self.signature } - /// Certificate issuer. + /// Certificate issuer: [`Name`] of the Certificate Authority (CA) which issued this + /// certificate. pub fn issuer(&self) -> &Name { &self.issuer } - /// Validity period for this certificate. + /// Validity period for this certificate: time range in which a certificate is considered valid, + /// after which it expires. pub fn validity(&self) -> &Validity

{ &self.validity } - /// Subject of this certificate. + /// Subject of this certificate: entity that the certificate is intended to represent or + /// authenticate, e.g. an individual, a device, or an organization. pub fn subject(&self) -> &Name { &self.subject } @@ -199,26 +207,38 @@ impl TbsCertificateInner

{ &self.subject_public_key_info } - /// Issuer unique ID. + /// Issuer unique ID: unique identifier representing the issuing CA, as defined by the + /// issuing CA. + /// + /// (NOTE: added in X.509 v2) pub fn issuer_unique_id(&self) -> &Option { &self.issuer_unique_id } - /// Subject unique ID. + /// Subject unique ID: unique identifier representing the certificate subject, as defined by the + /// issuing CA. + /// + /// (NOTE: added in X.509 v2) pub fn subject_unique_id(&self) -> &Option { &self.subject_unique_id } /// Certificate extensions. + /// + /// Additional fields in a digital certificate that provide extra information beyond the + /// standard fields. These extensions enhance the functionality and flexibility of certificates, + /// allowing them to convey more specific details about the certificate's usage and constraints. + /// + /// (NOTE: added in X.509 v3) pub fn extensions(&self) -> Option<&ext::Extensions> { self.extensions.as_ref() } - /// Decodes a single extension + /// Decodes a single extension. /// /// Returns `Ok(None)` if the extension is not present. /// - /// Otherwise returns the extension, and indicates if the extension was marked critical in the + /// Otherwise, returns the extension, and indicates if the extension was marked critical in the /// boolean. /// /// ``` @@ -320,13 +340,13 @@ impl CertificateInner

{ &self.tbs_certificate } - /// Signature algorithm. + /// Signature algorithm used to sign the serialization of [`CertificateInner::tbs_certificate`]. pub fn signature_algorithm(&self) -> &AlgorithmIdentifierOwned { &self.signature_algorithm } - /// Signature over the certificate using the algorithm identified in - /// [`CertificateInner::signature_algorithm`]. + /// Signature over the DER serialization of [`CertificateInner::tbs_certificate`] using the + /// algorithm identified in [`CertificateInner::signature_algorithm`]. pub fn signature(&self) -> &BitString { &self.signature }