From b1b3196fbc896aff0d52c07883ee6b4b408a9aef Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 11 Sep 2024 15:04:29 +0700 Subject: [PATCH 01/19] fix: remove PEN supported --- .../src/attributes/attribute.rs | 18 +-- .../src/extensions/extension/mod.rs | 22 ++-- rust/c509-certificate/src/oid.rs | 118 +++--------------- 3 files changed, 39 insertions(+), 119 deletions(-) diff --git a/rust/c509-certificate/src/attributes/attribute.rs b/rust/c509-certificate/src/attributes/attribute.rs index 1aa99740a91..950ca001b37 100644 --- a/rust/c509-certificate/src/attributes/attribute.rs +++ b/rust/c509-certificate/src/attributes/attribute.rs @@ -58,7 +58,7 @@ impl Attribute { /// Set whether `Attribute` can be PEN encoded. pub(crate) fn set_pen_supported(self) -> Self { Self { - registered_oid: self.registered_oid.pen_encoded(), + registered_oid: self.registered_oid, multi_value: self.multi_value, value: self.value, } @@ -82,7 +82,9 @@ struct Helper { impl<'de> Deserialize<'de> for Attribute { fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> { + where + D: Deserializer<'de>, + { let helper = Helper::deserialize(deserializer)?; let oid = Oid::from_str(&helper.oid).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?; @@ -96,7 +98,9 @@ impl<'de> Deserialize<'de> for Attribute { impl Serialize for Attribute { fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer { + where + S: serde::Serializer, + { let helper = Helper { oid: self.registered_oid.get_c509_oid().get_oid().to_string(), value: self.value.clone(), @@ -207,11 +211,9 @@ impl Decode<'_, ()> for AttributeValue { match d.datatype()? { minicbor::data::Type::String => Ok(AttributeValue::Text(d.str()?.to_string())), minicbor::data::Type::Bytes => Ok(AttributeValue::Bytes(d.bytes()?.to_vec())), - _ => { - Err(minicbor::decode::Error::message( - "Invalid AttributeValue, value should be either String or Bytes", - )) - }, + _ => Err(minicbor::decode::Error::message( + "Invalid AttributeValue, value should be either String or Bytes", + )), } } } diff --git a/rust/c509-certificate/src/extensions/extension/mod.rs b/rust/c509-certificate/src/extensions/extension/mod.rs index b2b82e54926..899b6d5c2a5 100644 --- a/rust/c509-certificate/src/extensions/extension/mod.rs +++ b/rust/c509-certificate/src/extensions/extension/mod.rs @@ -29,8 +29,7 @@ impl Extension { #[must_use] pub fn new(oid: Oid<'static>, value: ExtensionValue, critical: bool) -> Self { Self { - registered_oid: C509oidRegistered::new(oid, EXTENSIONS_LOOKUP.get_int_to_oid_table()) - .pen_encoded(), + registered_oid: C509oidRegistered::new(oid, EXTENSIONS_LOOKUP.get_int_to_oid_table()), critical, value, } @@ -68,7 +67,9 @@ struct Helper { impl<'de> Deserialize<'de> for Extension { fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> { + where + D: Deserializer<'de>, + { let helper = Helper::deserialize(deserializer)?; let oid = Oid::from_str(&helper.oid).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?; @@ -79,7 +80,9 @@ impl<'de> Deserialize<'de> for Extension { impl Serialize for Extension { fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer { + where + S: serde::Serializer, + { let helper = Helper { oid: self.registered_oid.get_c509_oid().get_oid().to_string(), value: self.value.clone(), @@ -228,7 +231,8 @@ impl Encode<()> for ExtensionValue { } impl Decode<'_, C> for ExtensionValue -where C: ExtensionValueTypeTrait + Debug +where + C: ExtensionValueTypeTrait + Debug, { fn decode(d: &mut Decoder<'_>, ctx: &mut C) -> Result { match ctx.get_type() { @@ -244,11 +248,9 @@ where C: ExtensionValueTypeTrait + Debug let value = AlternativeName::decode(d, &mut ())?; Ok(ExtensionValue::AlternativeName(value)) }, - ExtensionValueType::Unsupported => { - Err(minicbor::decode::Error::message( - "Cannot decode Unsupported extension value", - )) - }, + ExtensionValueType::Unsupported => Err(minicbor::decode::Error::message( + "Cannot decode Unsupported extension value", + )), } } } diff --git a/rust/c509-certificate/src/oid.rs b/rust/c509-certificate/src/oid.rs index 2a8ed92fd9f..5f487d10efe 100644 --- a/rust/c509-certificate/src/oid.rs +++ b/rust/c509-certificate/src/oid.rs @@ -7,19 +7,12 @@ use std::str::FromStr; use anyhow::Result; -use asn1_rs::oid; -use minicbor::{data::Tag, decode, encode::Write, Decode, Decoder, Encode, Encoder}; +use minicbor::{decode, encode::Write, Decode, Decoder, Encode, Encoder}; use oid_registry::Oid; use serde::{Deserialize, Deserializer, Serialize}; use crate::tables::IntegerToOidTable; -/// IANA Private Enterprise Number (PEN) OID prefix. -const PEN_PREFIX: Oid<'static> = oid!(1.3.6 .1 .4 .1); - -/// Tag number representing IANA Private Enterprise Number (PEN) OID. -const OID_PEN_TAG: u64 = 112; - /// A strut of C509 OID with Registered Integer. #[derive(Debug, Clone, PartialEq)] pub struct C509oidRegistered { @@ -38,13 +31,6 @@ impl C509oidRegistered { } } - /// Is PEN Encoding supported for this OID. - /// Depends on each registration table. - pub(crate) fn pen_encoded(mut self) -> Self { - self.oid.pen_supported = true; - self - } - /// Get the `C509oid`. #[must_use] pub fn get_c509_oid(&self) -> C509oid { @@ -61,12 +47,7 @@ impl C509oidRegistered { /// A struct represent an instance of `C509oid`. #[derive(Debug, PartialEq, Clone, Eq, Hash)] -pub struct C509oid { - /// The OID. - oid: Oid<'static>, - /// The flag to indicate whether PEN encoding is supported. - pen_supported: bool, -} +pub struct C509oid(Oid<'static>); /// A helper struct for deserialize and serialize `C509oid`. #[derive(Debug, Deserialize, Serialize)] @@ -77,7 +58,9 @@ struct Helper { impl<'de> Deserialize<'de> for C509oid { fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> { + where + D: Deserializer<'de>, + { let helper = Helper::deserialize(deserializer)?; let oid = Oid::from_str(&helper.oid).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?; @@ -87,9 +70,11 @@ impl<'de> Deserialize<'de> for C509oid { impl Serialize for C509oid { fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer { + where + S: serde::Serializer, + { let helper = Helper { - oid: self.oid.to_string(), + oid: self.0.to_string(), }; helper.serialize(serializer) } @@ -100,30 +85,19 @@ impl C509oid { /// Default value of PEN flag is false #[must_use] pub fn new(oid: Oid<'static>) -> Self { - Self { - oid, - pen_supported: false, - } - } - - /// Is PEN Encoding supported for this OID - pub(crate) fn pen_encoded(mut self) -> Self { - self.pen_supported = true; - self + Self(oid) } /// Get the underlying OID of the `C509oid` #[must_use] pub fn get_oid(self) -> Oid<'static> { - self.oid.clone() + self.0 } } impl Encode<()> for C509oid { /// Encode an OID - /// If `pen_supported` flag is set, and OID start with a valid `PEN_PREFIX`, - /// it is encoded as PEN (Private Enterprise Number) - /// else encode as an unwrapped OID (~oid) - as bytes string without tag. + /// Encode as an unwrapped OID (~oid) - as bytes string without tag. /// /// # Returns /// @@ -132,66 +106,21 @@ impl Encode<()> for C509oid { fn encode( &self, e: &mut Encoder, _ctx: &mut (), ) -> Result<(), minicbor::encode::Error> { - // Check if PEN encoding is supported and the OID starts with the PEN prefix. - if self.pen_supported && self.oid.starts_with(&PEN_PREFIX) { - // Set the CBOR tag. - e.tag(Tag::new(OID_PEN_TAG))?; - // Convert OID originally store as [u8] to [u64] - // This process is necessary to get the correct OID - // For example given - 1.3.6 .1 .4 .1.4.999 - // This OID will be stored as [u8] - [43, 6, 1, 4, 1, 4, 135, 103] - // The first 2 integer has a special encoding formula where, - // values is computed using X * 40 + Y (See RFC9090 for more info) - // The number 999 exceed the 225 limit (max of u8), so it will be encoded as 2 bytes - let raw_oid: Vec = - self.oid - .iter() - .map(Iterator::collect) - .ok_or(minicbor::encode::Error::message( - "Failed to collect OID components from iterator", - ))?; - let raw_pen_prefix: Vec = PEN_PREFIX.iter().map(Iterator::collect).ok_or( - minicbor::encode::Error::message("Failed to collect OID components from iterator"), - )?; - // relative_oid is OID that follows PEN_PREFIX (relative to PEN_PREFIX) - // Use the [u64] PEN prefix length to extract the relative OID - let oid_slice = - raw_oid - .get(raw_pen_prefix.len()..) - .ok_or(minicbor::encode::Error::message( - "Failed to get a OID slice", - ))?; - let relative_oid = Oid::from_relative(oid_slice) - .map_err(|_| minicbor::encode::Error::message("Failed to get a relative OID"))?; - return e.bytes(relative_oid.as_bytes())?.ok(); - } - let oid_bytes = self.oid.as_bytes(); - e.bytes(oid_bytes)?.ok() + let oid_bytes = self.0.as_bytes(); + e.bytes(oid_bytes)?; + Ok(()) } } impl Decode<'_, ()> for C509oid { /// Decode an OID - /// If the data to be decoded is a `Tag`, and the tag is an `OID_PEN_TAG`, - /// then decode the OID as Private Enterprise Number (PEN) OID. - /// else decode the OID as unwrapped OID (~oid) - as bytes string without tag. + /// Decode the OID as unwrapped OID (~oid) - as bytes string without tag. /// # Returns /// /// A C509oid instance. /// If the decoding fails, it will return an error. fn decode(d: &mut Decoder, _ctx: &mut ()) -> Result { - if (minicbor::data::Type::Tag == d.datatype()?) && (Tag::new(OID_PEN_TAG) == d.tag()?) { - let oid_bytes = d.bytes()?; - // raw_oid contains the whole OID which stored in bytes - let mut raw_oid = Vec::new(); - raw_oid.extend_from_slice(PEN_PREFIX.as_bytes()); - raw_oid.extend_from_slice(oid_bytes); - // Convert the raw_oid to Oid - let oid = Oid::new(raw_oid.into()); - return Ok(C509oid::new(oid).pen_encoded()); - } - // Not a PEN Relative OID, so treat as a normal OID let oid_bytes = d.bytes()?; let oid = Oid::new(oid_bytes.to_owned().into()); Ok(C509oid::new(oid)) @@ -204,6 +133,7 @@ impl Decode<'_, ()> for C509oid { mod test_c509_oid { use super::*; + use asn1_rs::oid; // Test reference 3.1. Encoding of the SHA-256 OID // https://datatracker.ietf.org/doc/rfc9090/ @@ -221,20 +151,6 @@ mod test_c509_oid { assert_eq!(decoded_oid, oid); } - #[test] - fn encode_decode_pen() { - let mut buffer = Vec::new(); - let mut encoder = Encoder::new(&mut buffer); - let oid = C509oid::new(oid!(1.3.6 .1 .4 .1 .1 .1 .29)).pen_encoded(); - oid.encode(&mut encoder, &mut ()) - .expect("Failed to encode OID"); - assert_eq!(hex::encode(buffer.clone()), "d8704301011d"); - - let mut decoder = Decoder::new(&buffer); - let decoded_oid = C509oid::decode(&mut decoder, &mut ()).expect("Failed to decode OID"); - assert_eq!(decoded_oid, oid); - } - #[test] fn partial_equal() { let oid1 = C509oid::new(oid_registry::OID_HASH_SHA1); From 8a045e4973d0b2bec26fe777e2f8bd942eddb76d Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 11 Sep 2024 15:43:55 +0700 Subject: [PATCH 02/19] fix(rust/c509-certificate): time --- rust/c509-certificate/examples/cli/main.rs | 39 ++++++++++++++-------- rust/c509-certificate/src/time.rs | 22 ++++++------ 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/rust/c509-certificate/examples/cli/main.rs b/rust/c509-certificate/examples/cli/main.rs index 816446f487e..3289356cbba 100644 --- a/rust/c509-certificate/examples/cli/main.rs +++ b/rust/c509-certificate/examples/cli/main.rs @@ -159,7 +159,12 @@ fn generate( // Parse validity dates or use defaults // Now for not_before date - let not_before = parse_or_default_date(c509_json.validity_not_before, Utc::now().timestamp())?; + let now_timestamp: u64 = Utc::now() + .timestamp() + .try_into() + .expect("Timestamp cannot be converted to u64"); + + let not_before = parse_or_default_date(c509_json.validity_not_before, now_timestamp)?; // Default as expire date for not_after // Expire date = 9999-12-31T23:59:59+00:00 as mention in the C509 document let not_after = parse_or_default_date( @@ -249,14 +254,16 @@ fn get_key_type(key_type: &Option) -> anyhow::Result<(Oid<'static>, Opti } } -/// Parse date string to i64. -fn parse_or_default_date(date_option: Option, default: i64) -> Result { +/// Parse date string to u64. +fn parse_or_default_date(date_option: Option, default: u64) -> Result { match date_option { - Some(date) => { - DateTime::parse_from_rfc3339(&date) - .map(|dt| dt.timestamp()) - .map_err(|e| anyhow::anyhow!(format!("Failed to parse date {date}: {e}",))) - }, + Some(date) => DateTime::parse_from_rfc3339(&date) + .map(|dt| { + dt.timestamp() + .try_into() + .map_err(|_| anyhow::anyhow!("Timestamp is invalid")) + })? + .map_err(|e| anyhow::anyhow!(format!("Failed to parse date {date}: {e}",))), None => Ok(default), } } @@ -295,8 +302,8 @@ fn decode(file: &PathBuf, output: Option) -> anyhow::Result<()> { certificate_type: Some(tbs_cert.get_c509_certificate_type()), serial_number: Some(tbs_cert.get_certificate_serial_number().clone()), issuer: Some(extract_relative_distinguished_name(tbs_cert.get_issuer())?), - validity_not_before: Some(time_to_string(tbs_cert.get_validity_not_before().to_i64())?), - validity_not_after: Some(time_to_string(tbs_cert.get_validity_not_after().to_i64())?), + validity_not_before: Some(time_to_string(tbs_cert.get_validity_not_before().to_u64())?), + validity_not_after: Some(time_to_string(tbs_cert.get_validity_not_after().to_u64())?), subject: extract_relative_distinguished_name(tbs_cert.get_subject())?, subject_public_key_algorithm: Some(tbs_cert.get_subject_public_key_algorithm().clone()), // Return a hex formation of the public key @@ -325,9 +332,15 @@ fn extract_relative_distinguished_name(name: &Name) -> anyhow::Result anyhow::Result { - let datetime = - DateTime::from_timestamp(time, 0).ok_or_else(|| anyhow::anyhow!("Invalid timestamp"))?; +fn time_to_string(time: u64) -> anyhow::Result { + // Attempt to convert the timestamp and handle errors if they occur + let timestamp: i64 = time + .try_into() + .map_err(|e| anyhow::anyhow!("Failed to convert time: {:?}", e))?; + + // Convert the timestamp to a DateTime and handle any potential errors + let datetime = DateTime::from_timestamp(timestamp, 0) + .ok_or_else(|| anyhow::anyhow!("Invalid timestamp"))?; Ok(datetime.to_rfc3339()) } diff --git a/rust/c509-certificate/src/time.rs b/rust/c509-certificate/src/time.rs index 48c370f22e6..ade7a5a11e4 100644 --- a/rust/c509-certificate/src/time.rs +++ b/rust/c509-certificate/src/time.rs @@ -4,22 +4,24 @@ use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder}; use serde::{Deserialize, Serialize}; /// A struct representing a time where it accept seconds since the Unix epoch. +/// Doesn't support dates before the Unix epoch (January 1, 1970, 00:00:00 UTC) +/// so unsigned integer is used. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct Time(i64); +pub struct Time(u64); /// No expiration date in seconds since the Unix epoch. -const NO_EXP_DATE: i64 = 253_402_300_799; +const NO_EXP_DATE: u64 = 253_402_300_799; impl Time { /// Create a new instance of `Time`. #[must_use] - pub fn new(time: i64) -> Self { + pub fn new(time: u64) -> Self { Self(time) } - /// Get the time in i64. + /// Get the time in u64. #[must_use] - pub fn to_i64(&self) -> i64 { + pub fn to_u64(&self) -> u64 { self.0 } } @@ -31,7 +33,7 @@ impl Encode<()> for Time { if self.0 == NO_EXP_DATE { e.null()?; } else { - e.i64(self.0)?; + e.u64(self.0)?; } Ok(()) } @@ -41,14 +43,10 @@ impl Decode<'_, ()> for Time { fn decode(d: &mut Decoder<'_>, _ctx: &mut ()) -> Result { match d.datatype()? { minicbor::data::Type::U8 - | minicbor::data::Type::I8 | minicbor::data::Type::U16 - | minicbor::data::Type::I16 | minicbor::data::Type::U32 - | minicbor::data::Type::I32 - | minicbor::data::Type::U64 - | minicbor::data::Type::I64 => { - let time = d.i64()?; + | minicbor::data::Type::U64 => { + let time = d.u64()?; Ok(Time::new(time)) }, minicbor::data::Type::Null => { From 4b73607dd85b0a2623e892e41c45f471a0028da8 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 11 Sep 2024 15:49:51 +0700 Subject: [PATCH 03/19] fix(rust/c509-certificate): handle if issuer not set, set to subject --- rust/c509-certificate/examples/cli/main.rs | 2 +- rust/c509-certificate/src/tbs_cert.rs | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/rust/c509-certificate/examples/cli/main.rs b/rust/c509-certificate/examples/cli/main.rs index 3289356cbba..a67cab3f88f 100644 --- a/rust/c509-certificate/examples/cli/main.rs +++ b/rust/c509-certificate/examples/cli/main.rs @@ -180,7 +180,7 @@ fn generate( let tbs = TbsCert::new( c509_json.certificate_type.unwrap_or(SELF_SIGNED_INT), serial_number, - Name::new(NameValue::RelativeDistinguishedName(issuer)), + Some(Name::new(NameValue::RelativeDistinguishedName(issuer))), Time::new(not_before), Time::new(not_after), Name::new(NameValue::RelativeDistinguishedName(c509_json.subject)), diff --git a/rust/c509-certificate/src/tbs_cert.rs b/rust/c509-certificate/src/tbs_cert.rs index c9f4b555856..f27f5e2a28e 100644 --- a/rust/c509-certificate/src/tbs_cert.rs +++ b/rust/c509-certificate/src/tbs_cert.rs @@ -36,18 +36,19 @@ pub struct TbsCert { impl TbsCert { /// Create a new instance of TBS Certificate. + /// If issuer is not provided, it will use the subject as the issuer. #[must_use] #[allow(clippy::too_many_arguments)] pub fn new( - c509_certificate_type: u8, certificate_serial_number: UnwrappedBigUint, issuer: Name, - validity_not_before: Time, validity_not_after: Time, subject: Name, + c509_certificate_type: u8, certificate_serial_number: UnwrappedBigUint, + issuer: Option, validity_not_before: Time, validity_not_after: Time, subject: Name, subject_public_key_algorithm: SubjectPubKeyAlgorithm, subject_public_key: Vec, extensions: Extensions, issuer_signature_algorithm: IssuerSignatureAlgorithm, ) -> Self { Self { c509_certificate_type, certificate_serial_number, - issuer, + issuer: issuer.unwrap_or_else(|| subject.clone()), validity_not_before, validity_not_after, subject, @@ -141,7 +142,7 @@ impl Decode<'_, ()> for TbsCert { fn decode(d: &mut Decoder<'_>, ctx: &mut ()) -> Result { let cert_type = d.u8()?; let serial_number = UnwrappedBigUint::decode(d, ctx)?; - let issuer = Name::decode(d, ctx)?; + let issuer = Some(Name::decode(d, ctx)?); let not_before = Time::decode(d, ctx)?; let not_after = Time::decode(d, ctx)?; let subject = Name::decode(d, ctx)?; @@ -264,7 +265,7 @@ pub(crate) mod test_tbs_cert { TbsCert::new( 1, UnwrappedBigUint::new(128_269), - name_cn_text().0, + Some(name_cn_text().0), Time::new(1_672_531_200), Time::new(1_767_225_600), name_cn_eui_mac().0, @@ -419,9 +420,10 @@ pub(crate) mod test_tbs_cert { true, )); let mut gns = GeneralNames::new(); - let hw = OtherNameHardwareModuleName::new(oid!(1.3.6 .1 .4 .1 .6175 .10 .1), vec![ - 0x01, 0x02, 0x03, 0x04, - ]); + let hw = OtherNameHardwareModuleName::new( + oid!(1.3.6 .1 .4 .1 .6175 .10 .1), + vec![0x01, 0x02, 0x03, 0x04], + ); gns.add_gn(GeneralName::new( GeneralNameTypeRegistry::OtherNameHardwareModuleName, GeneralNameValue::OtherNameHWModuleName(hw), @@ -441,7 +443,7 @@ pub(crate) mod test_tbs_cert { let tbs_cert = TbsCert::new( 1, UnwrappedBigUint::new(9_112_578_475_118_446_130), - names().0, + Some(names().0), Time::new(1_548_934_156), Time::new(253_402_300_799), subject(), From 3e70fc0a98a8a2fd43f2becc4c7988f573ec3bb5 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 11 Sep 2024 19:21:47 +0700 Subject: [PATCH 04/19] fix(rust/c509-certificate): remove rdn --- rust/c509-certificate/examples/cli/main.rs | 24 +-- .../src/attributes/attribute.rs | 9 - rust/c509-certificate/src/attributes/mod.rs | 9 +- rust/c509-certificate/src/name/mod.rs | 132 +++++++------- rust/c509-certificate/src/name/rdn.rs | 171 ------------------ rust/c509-certificate/src/tbs_cert.rs | 22 ++- 6 files changed, 94 insertions(+), 273 deletions(-) delete mode 100644 rust/c509-certificate/src/name/rdn.rs diff --git a/rust/c509-certificate/examples/cli/main.rs b/rust/c509-certificate/examples/cli/main.rs index a67cab3f88f..5b176be9817 100644 --- a/rust/c509-certificate/examples/cli/main.rs +++ b/rust/c509-certificate/examples/cli/main.rs @@ -8,10 +8,11 @@ use std::{ use asn1_rs::{oid, Oid}; use c509_certificate::{ + attributes::Attributes, big_uint::UnwrappedBigUint, extensions::Extensions, issuer_sig_algo::IssuerSignatureAlgorithm, - name::{rdn::RelativeDistinguishedName, Name, NameValue}, + name::{Name, NameValue}, signing::{PrivateKey, PublicKey}, subject_pub_key_algo::SubjectPubKeyAlgorithm, tbs_cert::TbsCert, @@ -104,7 +105,7 @@ struct C509Json { serial_number: Option, /// Optional issuer of the certificate, /// if not provided, issuer is the same as subject. - issuer: Option, + issuer: Option, /// Optional validity not before date, /// if not provided, set to current time. validity_not_before: Option, @@ -112,7 +113,7 @@ struct C509Json { /// if not provided, set to no expire date 9999-12-31T23:59:59+00:00. validity_not_after: Option, /// Relative distinguished name of the subject. - subject: RelativeDistinguishedName, + subject: Attributes, /// Optional subject public key algorithm of the certificate, /// if not provided, set to Ed25519. subject_public_key_algorithm: Option, @@ -180,10 +181,10 @@ fn generate( let tbs = TbsCert::new( c509_json.certificate_type.unwrap_or(SELF_SIGNED_INT), serial_number, - Some(Name::new(NameValue::RelativeDistinguishedName(issuer))), + Some(Name::new(NameValue::Attributes(issuer))), Time::new(not_before), Time::new(not_after), - Name::new(NameValue::RelativeDistinguishedName(c509_json.subject)), + Name::new(NameValue::Attributes(c509_json.subject)), c509_json .subject_public_key_algorithm .unwrap_or(SubjectPubKeyAlgorithm::new(key_type.0.clone(), key_type.1)), @@ -218,9 +219,8 @@ fn write_to_output_file(output: PathBuf, data: &[u8]) -> anyhow::Result<()> { /// If self-signed is true, issuer is the same as subject. /// Otherwise, issuer must be present. fn determine_issuer( - self_signed: bool, issuer: Option, - subject: RelativeDistinguishedName, -) -> anyhow::Result { + self_signed: bool, issuer: Option, subject: Attributes, +) -> anyhow::Result { if self_signed { Ok(subject) } else { @@ -323,11 +323,11 @@ fn decode(file: &PathBuf, output: Option) -> anyhow::Result<()> { Ok(()) } -/// Extract a `RelativeDistinguishedName` from a `Name`. -fn extract_relative_distinguished_name(name: &Name) -> anyhow::Result { +/// Extract a `Attributes` from a `Name`. +fn extract_relative_distinguished_name(name: &Name) -> anyhow::Result { match name.get_value() { - NameValue::RelativeDistinguishedName(rdn) => Ok(rdn.clone()), - _ => Err(anyhow::anyhow!("Expected RelativeDistinguishedName")), + NameValue::Attributes(attrs) => Ok(attrs.clone()), + _ => Err(anyhow::anyhow!("Expected Attributes")), } } diff --git a/rust/c509-certificate/src/attributes/attribute.rs b/rust/c509-certificate/src/attributes/attribute.rs index 950ca001b37..5a0e59b9d56 100644 --- a/rust/c509-certificate/src/attributes/attribute.rs +++ b/rust/c509-certificate/src/attributes/attribute.rs @@ -55,15 +55,6 @@ impl Attribute { &self.value } - /// Set whether `Attribute` can be PEN encoded. - pub(crate) fn set_pen_supported(self) -> Self { - Self { - registered_oid: self.registered_oid, - multi_value: self.multi_value, - value: self.value, - } - } - /// Set whether `Attribute` can have multiple value. pub(crate) fn set_multi_value(mut self) -> Self { self.multi_value = true; diff --git a/rust/c509-certificate/src/attributes/mod.rs b/rust/c509-certificate/src/attributes/mod.rs index b188558e18a..928e70cd3b3 100644 --- a/rust/c509-certificate/src/attributes/mod.rs +++ b/rust/c509-certificate/src/attributes/mod.rs @@ -15,12 +15,13 @@ use attribute::Attribute; use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder}; +use serde::{Deserialize, Serialize}; pub mod attribute; mod data; /// A struct of C509 `Attributes` containing a vector of `Attribute`. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Attributes(Vec); impl Default for Attributes { @@ -36,6 +37,12 @@ impl Attributes { Self(Vec::new()) } + /// Get the attributes. + #[must_use] + pub fn attributes(&self) -> &[Attribute] { + &self.0 + } + /// Add an `Attribute` to the `Attributes`. /// and set `Attribute` value to support multiple value. pub fn add_attr(&mut self, attribute: Attribute) { diff --git a/rust/c509-certificate/src/name/mod.rs b/rust/c509-certificate/src/name/mod.rs index c4144390775..4ddc2be7a28 100644 --- a/rust/c509-certificate/src/name/mod.rs +++ b/rust/c509-certificate/src/name/mod.rs @@ -4,26 +4,23 @@ //! are UTF-8 encoded and all attributeType should be non-negative. //! //! ```cddl -//! Name = [ * RelativeDistinguishedName ] / text / bytes -//! RelativeDistinguishedName = Attribute / [ 2* Attribute ] +//! Name = [ * Attributes ] / text / bytes //! Attribute = ( attributeType: int, attributeValue: text ) // //! ( attributeType: ~oid, attributeValue: bytes ) // -//! ( attributeType: pen, attributeValue: bytes ) //! ``` //! //! For more information about Name, //! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) -// cspell: words rdns - -pub mod rdn; use asn1_rs::{oid, Oid}; use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder}; -use rdn::RelativeDistinguishedName; use regex::Regex; use serde::{Deserialize, Serialize}; -use crate::attributes::attribute::{Attribute, AttributeValue}; +use crate::attributes::{ + attribute::{Attribute, AttributeValue}, + Attributes, +}; /// OID of `CommonName` attribute. const COMMON_NAME_OID: Oid<'static> = oid!(2.5.4 .3); @@ -77,8 +74,8 @@ impl Decode<'_, ()> for Name { #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub enum NameValue { - /// A relative distinguished name. - RelativeDistinguishedName(RelativeDistinguishedName), + /// Attributes. + Attributes(Attributes), /// A text. Text(String), /// bytes. @@ -90,13 +87,16 @@ impl Encode<()> for NameValue { &self, e: &mut Encoder, ctx: &mut (), ) -> Result<(), minicbor::encode::Error> { match self { - NameValue::RelativeDistinguishedName(rdn) => { - let attr = rdn.get_attributes(); - let attr_first = attr.first().ok_or(minicbor::encode::Error::message( - "Cannot get the first Attribute", - ))?; + NameValue::Attributes(attrs) => { + let attr_first = + attrs + .attributes() + .first() + .ok_or(minicbor::encode::Error::message( + "Cannot get the first Attribute", + ))?; // If Name contains a single Attribute of type CommonName - if attr.len() == 1 + if attrs.attributes().len() == 1 && attr_first.get_registered_oid().get_c509_oid().get_oid() == COMMON_NAME_OID { // Get the value of the attribute @@ -110,7 +110,7 @@ impl Encode<()> for NameValue { encode_cn_value(e, cn_value)?; } else { - rdn.encode(e, ctx)?; + attrs.encode(e, ctx)?; } }, NameValue::Text(text) => { @@ -127,19 +127,13 @@ impl Encode<()> for NameValue { impl Decode<'_, ()> for NameValue { fn decode(d: &mut Decoder<'_>, ctx: &mut ()) -> Result { match d.datatype()? { - minicbor::data::Type::Array => { - Ok(NameValue::RelativeDistinguishedName( - RelativeDistinguishedName::decode(d, ctx)?, - )) - }, + minicbor::data::Type::Array => Ok(NameValue::Attributes(Attributes::decode(d, ctx)?)), // If Name is a text string, the attribute is a CommonName - minicbor::data::Type::String => Ok(create_rdn_with_cn_attr(d.str()?.to_string())), + minicbor::data::Type::String => Ok(create_attributes_with_cn(d.str()?.to_string())), minicbor::data::Type::Bytes => decode_bytes(d), - _ => { - Err(minicbor::decode::Error::message( - "Name must be an array, text or bytes", - )) - }, + _ => Err(minicbor::decode::Error::message( + "Name must be an array, text or bytes", + )), } } } @@ -235,7 +229,7 @@ fn decode_hex_cn_bytes(bytes: &[u8]) -> Result Result { let text = formatted_eui_bytes(bytes.get(1..).ok_or( minicbor::decode::Error::message("Failed to get EUI-64 bytes index"), )?); - Ok(create_rdn_with_cn_attr(text)) - }, - _ => { - Err(minicbor::decode::Error::message( - "EUI-64 or MAC address must be 7 or 9 bytes", - )) + Ok(create_attributes_with_cn(text)) }, + _ => Err(minicbor::decode::Error::message( + "EUI-64 or MAC address must be 7 or 9 bytes", + )), } } -/// Create a relative distinguished name with attribute common name from string. -fn create_rdn_with_cn_attr(text: String) -> NameValue { +/// Create a attributes with attribute common name from string. +fn create_attributes_with_cn(text: String) -> NameValue { let mut attr = Attribute::new(COMMON_NAME_OID); attr.add_value(AttributeValue::Text(text)); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr); - NameValue::RelativeDistinguishedName(rdn) + let mut attrs = Attributes::new(); + attrs.add_attr(attr); + NameValue::Attributes(attrs) } // ------------------Test---------------------- @@ -291,11 +283,11 @@ pub(crate) mod test_name { pub(crate) fn name_cn_text() -> (Name, String) { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("RFC test CA".to_string())); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr); + let mut attrs = Attributes::new(); + attrs.add_attr(attr); ( - Name::new(NameValue::RelativeDistinguishedName(rdn)), + Name::new(NameValue::Attributes(attrs)), // "RFC test CA" Text string: 6b5246432074657374204341 "6b5246432074657374204341".to_string(), ) @@ -324,10 +316,10 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("000123abcd".to_string())); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr); + let mut attrs = Attributes::new(); + attrs.add_attr(attr); - let name = Name::new(NameValue::RelativeDistinguishedName(rdn)); + let name = Name::new(NameValue::Attributes(attrs)); name.encode(&mut encoder, &mut ()) .expect("Failed to encode Name"); @@ -348,10 +340,10 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("000123ABCD".to_string())); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr); + let mut attrs = Attributes::new(); + attrs.add_attr(attr); - let name = Name::new(NameValue::RelativeDistinguishedName(rdn)); + let name = Name::new(NameValue::Attributes(attrs)); name.encode(&mut encoder, &mut ()) .expect("Failed to encode Name"); @@ -369,11 +361,11 @@ pub(crate) mod test_name { pub(crate) fn name_cn_eui_mac() -> (Name, String) { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("01-23-45-FF-FE-67-89-AB".to_string())); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr); + let mut attrs = Attributes::new(); + attrs.add_attr(attr); ( - Name::new(NameValue::RelativeDistinguishedName(rdn)), + Name::new(NameValue::Attributes(attrs)), // Bytes of length 7: 0x47 // "01-23-45-FF-FE-67-89-AB" special encode: 0x010123456789AB "47010123456789ab".to_string(), @@ -403,9 +395,9 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("01-23-45-ff-fe-67-89-AB".to_string())); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr); - let name = Name::new(NameValue::RelativeDistinguishedName(rdn)); + let mut attrs = Attributes::new(); + attrs.add_attr(attr); + let name = Name::new(NameValue::Attributes(attrs)); name.encode(&mut encoder, &mut ()) .expect("Failed to encode Name"); @@ -429,10 +421,10 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("01-23-45-67-89-AB-00-01".to_string())); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr); + let mut attrs = Attributes::new(); + attrs.add_attr(attr); - let name = Name::new(NameValue::RelativeDistinguishedName(rdn)); + let name = Name::new(NameValue::Attributes(attrs)); name.encode(&mut encoder, &mut ()) .expect("Failed to encode Name"); @@ -451,10 +443,10 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("01-23-45-67-89-ab-00-01".to_string())); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr); + let mut attrs = Attributes::new(); + attrs.add_attr(attr); - let name = Name::new(NameValue::RelativeDistinguishedName(rdn)); + let name = Name::new(NameValue::Attributes(attrs)); name.encode(&mut encoder, &mut ()) .expect("Failed to encode Name"); @@ -486,15 +478,15 @@ pub(crate) mod test_name { let mut attr5 = Attribute::new(oid!(2.5.4 .3)); attr5.add_value(AttributeValue::Text("802.1AR CA".to_string())); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr1); - rdn.add_attr(attr2); - rdn.add_attr(attr3); - rdn.add_attr(attr4); - rdn.add_attr(attr5); + let mut attrs = Attributes::new(); + attrs.add_attr(attr1); + attrs.add_attr(attr2); + attrs.add_attr(attr3); + attrs.add_attr(attr4); + attrs.add_attr(attr5); ( - Name::new(NameValue::RelativeDistinguishedName(rdn)), + Name::new(NameValue::Attributes(attrs)), // Array of 10 items [4, "US", 6, "CA", 8, "Example Inc", 9, "certification", 1, "802.1AR CA"] : 0x8a // attr1: 0x04625553 // attr2: 0x06624341 @@ -505,7 +497,7 @@ pub(crate) mod test_name { ) } #[test] - fn encode_decode_type_name_rdns() { + fn encode_decode_type_name_attrs() { let mut buffer = Vec::new(); let mut encoder = Encoder::new(&mut buffer); diff --git a/rust/c509-certificate/src/name/rdn.rs b/rust/c509-certificate/src/name/rdn.rs deleted file mode 100644 index 13f5eb12f09..00000000000 --- a/rust/c509-certificate/src/name/rdn.rs +++ /dev/null @@ -1,171 +0,0 @@ -//! C509 Relative Distinguished Name -//! -//! For more information about `RelativeDistinguishedName`, -//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) - -// cspell: words rdns - -use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder}; -use serde::{Deserialize, Serialize}; - -use crate::attributes::attribute::Attribute; - -/// A struct represents a Relative Distinguished Name containing vector of `Attribute`. -/// -/// ```cddl -/// RelativeDistinguishedName = Attribute / [ 2* Attribute ] -/// ``` -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct RelativeDistinguishedName(Vec); - -impl Default for RelativeDistinguishedName { - fn default() -> Self { - Self::new() - } -} - -impl RelativeDistinguishedName { - /// Create a new instance of `RelativeDistinguishedName` as empty vector. - #[must_use] - pub fn new() -> Self { - Self(Vec::new()) - } - - /// Add an `Attribute` to the `RelativeDistinguishedName`. - pub fn add_attr(&mut self, attribute: Attribute) { - // RelativeDistinguishedName support pen encoding - self.0.push(attribute.set_pen_supported()); - } - - /// Get the a vector of `Attribute`. - pub(crate) fn get_attributes(&self) -> &Vec { - &self.0 - } -} - -impl Encode<()> for RelativeDistinguishedName { - // ```cddl - // RelativeDistinguishedName = Attribute / [ 2* Attribute ] - // ``` - fn encode( - &self, e: &mut Encoder, ctx: &mut (), - ) -> Result<(), minicbor::encode::Error> { - // Should contain >= 1 attribute - if self.0.is_empty() { - return Err(minicbor::encode::Error::message( - "RelativeDistinguishedName should not be empty", - )); - } - - if self.0.len() == 1 { - self.0.first().encode(e, ctx)?; - } else { - // The attribute type should be included in array too - e.array(self.0.len() as u64 * 2)?; - for attr in &self.0 { - attr.encode(e, ctx)?; - } - } - Ok(()) - } -} - -impl Decode<'_, ()> for RelativeDistinguishedName { - fn decode(d: &mut Decoder<'_>, ctx: &mut ()) -> Result { - let mut rdn = RelativeDistinguishedName::new(); - - match d.datatype()? { - minicbor::data::Type::Array => { - let len = d.array()?.ok_or(minicbor::decode::Error::message( - "Failed to get array length for relative distinguished name", - ))?; - // Should contain >= 1 attribute - if len == 0 { - return Err(minicbor::decode::Error::message( - "RelativeDistinguishedName should not be empty", - )); - } - // The attribute type is included in an array, so divide by 2 - for _ in 0..len / 2 { - rdn.add_attr(Attribute::decode(d, ctx)?); - } - }, - _ => rdn.add_attr(Attribute::decode(d, ctx)?), - } - Ok(rdn) - } -} - -// -------------------Test---------------------- - -#[cfg(test)] -mod test_relative_distinguished_name { - - use asn1_rs::oid; - - use super::*; - use crate::attributes::attribute::AttributeValue; - - #[test] - fn encode_decode_rdn() { - let mut buffer = Vec::new(); - let mut encoder = Encoder::new(&mut buffer); - - let mut attr = Attribute::new(oid!(1.2.840 .113549 .1 .9 .1)); - attr.add_value(AttributeValue::Text("example@example.com".to_string())); - - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr); - rdn.encode(&mut encoder, &mut ()) - .expect("Failed to encode RDN"); - // Email Address: 0x00 - // "example@example.como": 736578616d706c65406578616d706c652e636f6d - assert_eq!( - hex::encode(buffer.clone()), - "00736578616d706c65406578616d706c652e636f6d" - ); - - let mut decoder = Decoder::new(&buffer); - let rdn_decoded = RelativeDistinguishedName::decode(&mut decoder, &mut ()) - .expect("Failed to decode RelativeDistinguishedName"); - assert_eq!(rdn_decoded, rdn); - } - - #[test] - fn encode_decode_rdns() { - let mut buffer = Vec::new(); - let mut encoder = Encoder::new(&mut buffer); - - let mut attr1 = Attribute::new(oid!(1.2.840 .113549 .1 .9 .1)); - attr1.add_value(AttributeValue::Text("example@example.com".to_string())); - let mut attr2 = Attribute::new(oid!(2.5.4 .3)); - attr2.add_value(AttributeValue::Text("example".to_string())); - - let mut rdns = RelativeDistinguishedName::new(); - rdns.add_attr(attr1); - rdns.add_attr(attr2); - - rdns.encode(&mut encoder, &mut ()) - .expect("Failed to encode RDN"); - // Array of 2 attributes: 0x84 - // Email Address example@example.com: 0x00736578616d706c65406578616d706c652e636f6d - // Common Name example: 0x01676578616d706c65 - assert_eq!( - hex::encode(buffer.clone()), - "8400736578616d706c65406578616d706c652e636f6d01676578616d706c65" - ); - let mut decoder = Decoder::new(&buffer); - let rdn_decoded = RelativeDistinguishedName::decode(&mut decoder, &mut ()) - .expect("Failed to decode RelativeDistinguishedName"); - assert_eq!(rdn_decoded, rdns); - } - - #[test] - fn empty_rdn() { - let mut buffer = Vec::new(); - let mut encoder = Encoder::new(&mut buffer); - let rdn = RelativeDistinguishedName::new(); - rdn.encode(&mut encoder, &mut ()) - .expect_err("Failed to encode RDN"); - } -} diff --git a/rust/c509-certificate/src/tbs_cert.rs b/rust/c509-certificate/src/tbs_cert.rs index f27f5e2a28e..926e009989b 100644 --- a/rust/c509-certificate/src/tbs_cert.rs +++ b/rust/c509-certificate/src/tbs_cert.rs @@ -182,7 +182,10 @@ pub(crate) mod test_tbs_cert { use super::*; use crate::{ - attributes::attribute::{Attribute, AttributeValue}, + attributes::{ + attribute::{Attribute, AttributeValue}, + Attributes, + }, extensions::{ alt_name::{AlternativeName, GeneralNamesOrText}, extension::{Extension, ExtensionValue}, @@ -193,7 +196,6 @@ pub(crate) mod test_tbs_cert { GeneralNames, }, name::{ - rdn::RelativeDistinguishedName, test_name::{name_cn_eui_mac, name_cn_text, names}, NameValue, }, @@ -385,15 +387,15 @@ pub(crate) mod test_tbs_cert { let mut attr6 = Attribute::new(oid!(2.5.4 .5)); attr6.add_value(AttributeValue::Text("Wt1234".to_string())); - let mut rdn = RelativeDistinguishedName::new(); - rdn.add_attr(attr1); - rdn.add_attr(attr2); - rdn.add_attr(attr3); - rdn.add_attr(attr4); - rdn.add_attr(attr5); - rdn.add_attr(attr6); + let mut attrs = Attributes::new(); + attrs.add_attr(attr1); + attrs.add_attr(attr2); + attrs.add_attr(attr3); + attrs.add_attr(attr4); + attrs.add_attr(attr5); + attrs.add_attr(attr6); - Name::new(NameValue::RelativeDistinguishedName(rdn)) + Name::new(NameValue::Attributes(attrs)) } fn extensions() -> Extensions { From afe628dd5c2737440f9ff91acf2fcd81c9881480 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 11 Sep 2024 19:23:21 +0700 Subject: [PATCH 05/19] fix(rust/c509-certificate): change certificate version number --- rust/c509-certificate/examples/cli/data/cert_sample_1.json | 2 +- rust/c509-certificate/examples/cli/main.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/c509-certificate/examples/cli/data/cert_sample_1.json b/rust/c509-certificate/examples/cli/data/cert_sample_1.json index ca41ddabfab..fffa5003085 100644 --- a/rust/c509-certificate/examples/cli/data/cert_sample_1.json +++ b/rust/c509-certificate/examples/cli/data/cert_sample_1.json @@ -1,6 +1,6 @@ { "self_signed": true, - "c509_certificate_type": 0, + "c509_certificate_type": 2, "certificate_serial_number": 128269, "issuer": [ { diff --git a/rust/c509-certificate/examples/cli/main.rs b/rust/c509-certificate/examples/cli/main.rs index 5b176be9817..01d61984c73 100644 --- a/rust/c509-certificate/examples/cli/main.rs +++ b/rust/c509-certificate/examples/cli/main.rs @@ -134,9 +134,9 @@ struct C509Json { const ED25519: (Oid, Option) = (oid!(1.3.101 .112), None); /// Integer indicate that certificate is self-signed. -/// 0 for Natively Signed C509 Certificate following X.509 v3 -/// 1 for CBOR re-encoding of X.509 v3 Certificate -const SELF_SIGNED_INT: u8 = 0; +/// 2 for Natively Signed C509 Certificate following X.509 v3 +/// 3 for CBOR re-encoding of X.509 v3 Certificate +const SELF_SIGNED_INT: u8 = 2; // -------------------generate----------------------- From 0e30d15669c7b932b8d9122b98301bef217409d1 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Wed, 11 Sep 2024 19:24:25 +0700 Subject: [PATCH 06/19] fix(rust/c509-certificate): rearrange tbscertificate --- .../examples/cli/data/cert_sample_1.json | 4 +-- rust/c509-certificate/examples/cli/main.rs | 32 +++++++++--------- rust/c509-certificate/src/tbs_cert.rs | 33 ++++++++++--------- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/rust/c509-certificate/examples/cli/data/cert_sample_1.json b/rust/c509-certificate/examples/cli/data/cert_sample_1.json index fffa5003085..f7ed50eb45d 100644 --- a/rust/c509-certificate/examples/cli/data/cert_sample_1.json +++ b/rust/c509-certificate/examples/cli/data/cert_sample_1.json @@ -2,6 +2,7 @@ "self_signed": true, "c509_certificate_type": 2, "certificate_serial_number": 128269, + "issuer_signature_algorithm": null, "issuer": [ { "oid": "2.5.4.3", @@ -24,6 +25,5 @@ "value": { "int": 1 }, "critical": false } - ], - "issuer_signature_algorithm": null + ] } diff --git a/rust/c509-certificate/examples/cli/main.rs b/rust/c509-certificate/examples/cli/main.rs index 01d61984c73..738d19ca17b 100644 --- a/rust/c509-certificate/examples/cli/main.rs +++ b/rust/c509-certificate/examples/cli/main.rs @@ -103,6 +103,9 @@ struct C509Json { /// Optional serial number of the certificate, /// if not provided, a random number will be generated. serial_number: Option, + /// Optional issuer signature algorithm of the certificate, + /// if not provided, set to Ed25519. + issuer_signature_algorithm: Option, /// Optional issuer of the certificate, /// if not provided, issuer is the same as subject. issuer: Option, @@ -122,9 +125,6 @@ struct C509Json { subject_public_key: String, /// Extensions of the certificate. extensions: Extensions, - /// Optional issuer signature algorithm of the certificate, - /// if not provided, set to Ed25519. - issuer_signature_algorithm: Option, /// Optional issuer signature value of the certificate. #[serde(skip_deserializing)] issuer_signature_value: Option>, @@ -181,18 +181,18 @@ fn generate( let tbs = TbsCert::new( c509_json.certificate_type.unwrap_or(SELF_SIGNED_INT), serial_number, + c509_json + .issuer_signature_algorithm + .unwrap_or(IssuerSignatureAlgorithm::new(key_type.0.clone(), ED25519.1)), Some(Name::new(NameValue::Attributes(issuer))), Time::new(not_before), Time::new(not_after), Name::new(NameValue::Attributes(c509_json.subject)), c509_json .subject_public_key_algorithm - .unwrap_or(SubjectPubKeyAlgorithm::new(key_type.0.clone(), key_type.1)), + .unwrap_or(SubjectPubKeyAlgorithm::new(key_type.0, key_type.1)), public_key.to_bytes(), c509_json.extensions.clone(), - c509_json - .issuer_signature_algorithm - .unwrap_or(IssuerSignatureAlgorithm::new(key_type.0, ED25519.1)), ); let cert = c509_certificate::generate(&tbs, private_key)?; @@ -257,13 +257,15 @@ fn get_key_type(key_type: &Option) -> anyhow::Result<(Oid<'static>, Opti /// Parse date string to u64. fn parse_or_default_date(date_option: Option, default: u64) -> Result { match date_option { - Some(date) => DateTime::parse_from_rfc3339(&date) - .map(|dt| { - dt.timestamp() - .try_into() - .map_err(|_| anyhow::anyhow!("Timestamp is invalid")) - })? - .map_err(|e| anyhow::anyhow!(format!("Failed to parse date {date}: {e}",))), + Some(date) => { + DateTime::parse_from_rfc3339(&date) + .map(|dt| { + dt.timestamp() + .try_into() + .map_err(|_| anyhow::anyhow!("Timestamp is invalid")) + })? + .map_err(|e| anyhow::anyhow!(format!("Failed to parse date {date}: {e}",))) + }, None => Ok(default), } } @@ -301,6 +303,7 @@ fn decode(file: &PathBuf, output: Option) -> anyhow::Result<()> { self_signed: is_self_signed, certificate_type: Some(tbs_cert.get_c509_certificate_type()), serial_number: Some(tbs_cert.get_certificate_serial_number().clone()), + issuer_signature_algorithm: Some(tbs_cert.get_issuer_signature_algorithm().clone()), issuer: Some(extract_relative_distinguished_name(tbs_cert.get_issuer())?), validity_not_before: Some(time_to_string(tbs_cert.get_validity_not_before().to_u64())?), validity_not_after: Some(time_to_string(tbs_cert.get_validity_not_after().to_u64())?), @@ -309,7 +312,6 @@ fn decode(file: &PathBuf, output: Option) -> anyhow::Result<()> { // Return a hex formation of the public key subject_public_key: tbs_cert.get_subject_public_key().encode_hex(), extensions: tbs_cert.get_extensions().clone(), - issuer_signature_algorithm: Some(tbs_cert.get_issuer_signature_algorithm().clone()), issuer_signature_value: c509.get_issuer_signature_value().clone(), }; diff --git a/rust/c509-certificate/src/tbs_cert.rs b/rust/c509-certificate/src/tbs_cert.rs index 926e009989b..d67089a4b6e 100644 --- a/rust/c509-certificate/src/tbs_cert.rs +++ b/rust/c509-certificate/src/tbs_cert.rs @@ -16,6 +16,8 @@ pub struct TbsCert { c509_certificate_type: u8, /// Serial number of the certificate. certificate_serial_number: UnwrappedBigUint, + /// Issuer Signature Algorithm + issuer_signature_algorithm: IssuerSignatureAlgorithm, /// Issuer issuer: Name, /// Validity not before. @@ -30,8 +32,6 @@ pub struct TbsCert { subject_public_key: Vec, /// Extensions extensions: Extensions, - /// Issuer Signature Algorithm - issuer_signature_algorithm: IssuerSignatureAlgorithm, } impl TbsCert { @@ -41,13 +41,15 @@ impl TbsCert { #[allow(clippy::too_many_arguments)] pub fn new( c509_certificate_type: u8, certificate_serial_number: UnwrappedBigUint, - issuer: Option, validity_not_before: Time, validity_not_after: Time, subject: Name, + issuer_signature_algorithm: IssuerSignatureAlgorithm, issuer: Option, + validity_not_before: Time, validity_not_after: Time, subject: Name, subject_public_key_algorithm: SubjectPubKeyAlgorithm, subject_public_key: Vec, - extensions: Extensions, issuer_signature_algorithm: IssuerSignatureAlgorithm, + extensions: Extensions, ) -> Self { Self { c509_certificate_type, certificate_serial_number, + issuer_signature_algorithm, issuer: issuer.unwrap_or_else(|| subject.clone()), validity_not_before, validity_not_after, @@ -55,7 +57,6 @@ impl TbsCert { subject_public_key_algorithm, subject_public_key, extensions, - issuer_signature_algorithm, } } @@ -71,6 +72,12 @@ impl TbsCert { &self.certificate_serial_number } + /// Get the issuer signature algorithm. + #[must_use] + pub fn get_issuer_signature_algorithm(&self) -> &IssuerSignatureAlgorithm { + &self.issuer_signature_algorithm + } + /// Get the issuer. #[must_use] pub fn get_issuer(&self) -> &Name { @@ -112,12 +119,6 @@ impl TbsCert { pub fn get_extensions(&self) -> &Extensions { &self.extensions } - - /// Get the issuer signature algorithm. - #[must_use] - pub fn get_issuer_signature_algorithm(&self) -> &IssuerSignatureAlgorithm { - &self.issuer_signature_algorithm - } } impl Encode<()> for TbsCert { @@ -126,6 +127,7 @@ impl Encode<()> for TbsCert { ) -> Result<(), minicbor::encode::Error> { e.u8(self.c509_certificate_type)?; self.certificate_serial_number.encode(e, ctx)?; + self.issuer_signature_algorithm.encode(e, ctx)?; self.issuer.encode(e, ctx)?; self.validity_not_before.encode(e, ctx)?; self.validity_not_after.encode(e, ctx)?; @@ -133,7 +135,6 @@ impl Encode<()> for TbsCert { self.subject_public_key_algorithm.encode(e, ctx)?; e.bytes(&self.subject_public_key)?; self.extensions.encode(e, ctx)?; - self.issuer_signature_algorithm.encode(e, ctx)?; Ok(()) } } @@ -142,6 +143,7 @@ impl Decode<'_, ()> for TbsCert { fn decode(d: &mut Decoder<'_>, ctx: &mut ()) -> Result { let cert_type = d.u8()?; let serial_number = UnwrappedBigUint::decode(d, ctx)?; + let issuer_signature_algorithm = IssuerSignatureAlgorithm::decode(d, ctx)?; let issuer = Some(Name::decode(d, ctx)?); let not_before = Time::decode(d, ctx)?; let not_after = Time::decode(d, ctx)?; @@ -149,11 +151,11 @@ impl Decode<'_, ()> for TbsCert { let subject_public_key_algorithm = SubjectPubKeyAlgorithm::decode(d, ctx)?; let subject_public_key = d.bytes()?; let extensions = Extensions::decode(d, ctx)?; - let issuer_signature_algorithm = IssuerSignatureAlgorithm::decode(d, ctx)?; Ok(TbsCert::new( cert_type, serial_number, + issuer_signature_algorithm, issuer, not_before, not_after, @@ -161,7 +163,6 @@ impl Decode<'_, ()> for TbsCert { subject_public_key_algorithm, subject_public_key.to_vec(), extensions, - issuer_signature_algorithm, )) } } @@ -267,6 +268,7 @@ pub(crate) mod test_tbs_cert { TbsCert::new( 1, UnwrappedBigUint::new(128_269), + IssuerSignatureAlgorithm::new(oid!(1.2.840 .10045 .4 .3 .2), None), Some(name_cn_text().0), Time::new(1_672_531_200), Time::new(1_767_225_600), @@ -274,7 +276,6 @@ pub(crate) mod test_tbs_cert { SubjectPubKeyAlgorithm::new(oid!(1.2.840 .10045 .2 .1), None), PUBKEY.to_vec(), extensions(), - IssuerSignatureAlgorithm::new(oid!(1.2.840 .10045 .4 .3 .2), None), ) } @@ -445,6 +446,7 @@ pub(crate) mod test_tbs_cert { let tbs_cert = TbsCert::new( 1, UnwrappedBigUint::new(9_112_578_475_118_446_130), + IssuerSignatureAlgorithm::new(oid!(1.2.840 .10045 .4 .3 .2), None), Some(names().0), Time::new(1_548_934_156), Time::new(253_402_300_799), @@ -452,7 +454,6 @@ pub(crate) mod test_tbs_cert { SubjectPubKeyAlgorithm::new(oid!(1.2.840 .10045 .2 .1), None), PUBKEY.to_vec(), extensions(), - IssuerSignatureAlgorithm::new(oid!(1.2.840 .10045 .4 .3 .2), None), ); let mut buffer = Vec::new(); From 069640b493716388b28cd0f81877ab41b210ee91 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Thu, 12 Sep 2024 10:30:33 +0700 Subject: [PATCH 07/19] fix(rust/c509-certificate): update docs --- .../c509-cert-plutus-restricted.cddl | 39 +++++++------------ rust/c509-certificate/examples/cli/main.rs | 8 ++-- rust/c509-certificate/examples/web/index.js | 8 ++-- .../src/algorithm_identifier.rs | 2 +- .../src/attributes/attribute.rs | 5 +-- rust/c509-certificate/src/attributes/data.rs | 2 +- rust/c509-certificate/src/attributes/mod.rs | 14 ++++--- rust/c509-certificate/src/big_uint.rs | 4 +- .../src/extensions/extension/data.rs | 2 +- rust/c509-certificate/src/extensions/mod.rs | 11 ++---- .../src/general_names/data.rs | 2 +- .../src/general_names/general_name.rs | 2 +- .../c509-certificate/src/general_names/mod.rs | 2 +- .../src/issuer_sig_algo/data.rs | 2 +- rust/c509-certificate/src/lib.rs | 2 +- rust/c509-certificate/src/name/mod.rs | 8 ++-- .../src/subject_pub_key_algo/data.rs | 2 +- rust/c509-certificate/src/tbs_cert.rs | 4 +- rust/c509-certificate/src/time.rs | 2 +- 19 files changed, 53 insertions(+), 68 deletions(-) diff --git a/docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl b/docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl index 4967ed331e1..6247eaa0892 100644 --- a/docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl +++ b/docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl @@ -1,5 +1,5 @@ ; This c509 Certificate format is based upon: -; https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/ +; https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ ; And is restricted/customized to better enable compatibility with Plutus scripts ; that would consume them, without loosing necessary features of x509 ; Not all x509 features are supported and some fields have different semantics to improve @@ -11,42 +11,32 @@ C509CertificatePlutusRestrictedSubset = [ TBSCertificate, issuerSignatureValue: ; The elements of the following group are used in a CBOR Sequence: TBSCertificate = ( - c509CertificateType: &c509CertificateTypeValues, ; Always 0 + c509CertificateType: int, ; Always 2 as natively signed C509 certificate following X.509 v3 certificateSerialNumber: CertificateSerialNumber, ; Can be ignored/set to 0 or used as intended. - issuer: Name, ; This could be an on-chain reference to the issuer cert, what would be the best way? Transaction hash/cert hash? - validityNotBefore: Time, ; c509 uses UTC - validityNotAfter: Time, ; c509 uses UTC + issuerSignatureAlgorithm: AlgorithmIdentifier, ; Must be int(12) = Ed25519 + issuer: Name / null, ; If set to null, use the `subject`. This could be an on-chain reference to + the issuer cert, what would be the best way? Transaction hash/cert hash? + validityNotBefore: ~time, ; UTC + validityNotAfter: ~time / null, ; UTC subject: Name, ; Reference to on-chain keys related to this certificate subjectPublicKeyAlgorithm: AlgorithmIdentifier, ; Must be int(12) = Ed25519 - subjectPublicKey: subjectPublicKey, ; Ed25519 public key - extensions: Extensions, ; No extensions are currently supported must be set to [] - issuerSignatureAlgorithm: AlgorithmIdentifier, ; Must be int(12) = Ed25519 -) - -; 0 = Native CBOR Certificate type -; 1 = reencoded-der-cert - Not supported in this restricted version of the format. -c509CertificateTypeValues = ( native-cbor: 0, - ; reencoded-der: 1 ; Not supported in this restricted encoding format + subjectPublicKey: any, ; Ed25519 public key + extensions: Extensions, ; Currently support extensions with basic CBOR types and Alternative Name ) -CertificateSerialNumber = biguint - -Name = [ * RelativeDistinguishedName ] - / text - / bytes +CertificateSerialNumber = ~biguint -RelativeDistinguishedName = Attribute / [ 2* Attribute ] +Name = [ * Attribute ] / text / bytes Attribute = ( ( attributeType: int, attributeValue: text ) // ( attributeType: oid, attributeValue: bytes ) - // ( attributeType: pen, attributeValue: bytes ) // CardanoPublicKey ) subjectPublicKey = bytes .size (32..32); Ed25519 public key stored in bytes, adjust size of this if other key types are supported. -; This is a completely custom Attribute for the RelativeDistinguishedName which is only for use with Plutus scripts. +; This is a completely custom Attribute, which is only for use with Plutus scripts. ; attributeType = The type of Cardano key we associate with this certificate. ; proof = Does the transaction require proof that the key is owned by the transaction signer? ; attributeValue = The Cardano public key hash of the attribute type @@ -61,14 +51,12 @@ cardanoKeyTypes = ( ccHotVerificationKeyHash: 4, ) -; Plutus will need to convert the Unix epoch timestamp to the nearest slot number +; For `~time` Plutus will need to convert the Unix epoch timestamp to the nearest slot number ; validityNotBefore rounds up to the next Slot after that time. ; validityNotAfter rounds down to the next Slot before that time. -Time = ( ~time / null ) ed25519Signature = bstr .size 64; Ed25519 signature must be tagged to identify their type. - ; Currently ONLY AlgorithmIdentifier int(12) - Ed25519 is supported. ; oid and [ algorithm: oid, parameters: bytes ] are not supported by Plutus. AlgorithmIdentifier = (int @@ -82,5 +70,4 @@ Extensions = [ * Extension ] / int Extension = ( ( extensionID: int, extensionValue: any ) // ( extensionID: ~oid, ? critical: true, extensionValue: bytes ) - // ( extensionID: pen, ? critical: true, extensionValue: bytes ) ) diff --git a/rust/c509-certificate/examples/cli/main.rs b/rust/c509-certificate/examples/cli/main.rs index 738d19ca17b..6297b14348e 100644 --- a/rust/c509-certificate/examples/cli/main.rs +++ b/rust/c509-certificate/examples/cli/main.rs @@ -115,7 +115,7 @@ struct C509Json { /// Optional validity not after date, /// if not provided, set to no expire date 9999-12-31T23:59:59+00:00. validity_not_after: Option, - /// Relative distinguished name of the subject. + /// Attributes of the subject. subject: Attributes, /// Optional subject public key algorithm of the certificate, /// if not provided, set to Ed25519. @@ -304,10 +304,10 @@ fn decode(file: &PathBuf, output: Option) -> anyhow::Result<()> { certificate_type: Some(tbs_cert.get_c509_certificate_type()), serial_number: Some(tbs_cert.get_certificate_serial_number().clone()), issuer_signature_algorithm: Some(tbs_cert.get_issuer_signature_algorithm().clone()), - issuer: Some(extract_relative_distinguished_name(tbs_cert.get_issuer())?), + issuer: Some(extract_attributes(tbs_cert.get_issuer())?), validity_not_before: Some(time_to_string(tbs_cert.get_validity_not_before().to_u64())?), validity_not_after: Some(time_to_string(tbs_cert.get_validity_not_after().to_u64())?), - subject: extract_relative_distinguished_name(tbs_cert.get_subject())?, + subject: extract_attributes(tbs_cert.get_subject())?, subject_public_key_algorithm: Some(tbs_cert.get_subject_public_key_algorithm().clone()), // Return a hex formation of the public key subject_public_key: tbs_cert.get_subject_public_key().encode_hex(), @@ -326,7 +326,7 @@ fn decode(file: &PathBuf, output: Option) -> anyhow::Result<()> { } /// Extract a `Attributes` from a `Name`. -fn extract_relative_distinguished_name(name: &Name) -> anyhow::Result { +fn extract_attributes(name: &Name) -> anyhow::Result { match name.get_value() { NameValue::Attributes(attrs) => Ok(attrs.clone()), _ => Err(anyhow::anyhow!("Expected Attributes")), diff --git a/rust/c509-certificate/examples/web/index.js b/rust/c509-certificate/examples/web/index.js index dd37a6f83f1..a2bdca0cadf 100644 --- a/rust/c509-certificate/examples/web/index.js +++ b/rust/c509-certificate/examples/web/index.js @@ -1,11 +1,11 @@ // Testing the wasm binding JS functions. import init, { - generate, - verify, decode, - PublicKey, + generate, PrivateKey, + PublicKey, + verify, } from "../../pkg/c509_certificate.js"; const pem_sk = ` @@ -24,7 +24,7 @@ const tbs = { c509_certificate_type: 0, certificate_serial_number: 1000000n, issuer: { - relative_distinguished_name: [ + attributes: [ { oid: "2.5.4.3", value: [{ text: "RFC test CA" }], diff --git a/rust/c509-certificate/src/algorithm_identifier.rs b/rust/c509-certificate/src/algorithm_identifier.rs index 89bca4b118d..285878c975d 100644 --- a/rust/c509-certificate/src/algorithm_identifier.rs +++ b/rust/c509-certificate/src/algorithm_identifier.rs @@ -11,7 +11,7 @@ //! not implemented yet. //! //! For more information about `AlgorithmIdentifier`, -//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) use asn1_rs::Oid; use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder}; diff --git a/rust/c509-certificate/src/attributes/attribute.rs b/rust/c509-certificate/src/attributes/attribute.rs index 5a0e59b9d56..4567bfcaab0 100644 --- a/rust/c509-certificate/src/attributes/attribute.rs +++ b/rust/c509-certificate/src/attributes/attribute.rs @@ -2,12 +2,11 @@ //! //! ```cddl //! Attribute = ( attributeType: int, attributeValue: text ) // -//! ( attributeType: ~oid, attributeValue: bytes ) // -//! ( attributeType: pen, attributeValue: bytes ) +//! ( attributeType: ~oid, attributeValue: bytes ) // //! ``` //! //! For more information about Attribute, -//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) use std::str::FromStr; diff --git a/rust/c509-certificate/src/attributes/data.rs b/rust/c509-certificate/src/attributes/data.rs index b89fb429cb4..0ae826a3453 100644 --- a/rust/c509-certificate/src/attributes/data.rs +++ b/rust/c509-certificate/src/attributes/data.rs @@ -1,5 +1,5 @@ //! Attribute data provides a necessary information for encoding and decoding of C509 -//! Attribute. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! Attribute. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) //! Section 9.3 C509 Attributes Registry for more information. use anyhow::Error; diff --git a/rust/c509-certificate/src/attributes/mod.rs b/rust/c509-certificate/src/attributes/mod.rs index 928e70cd3b3..ead810ec22e 100644 --- a/rust/c509-certificate/src/attributes/mod.rs +++ b/rust/c509-certificate/src/attributes/mod.rs @@ -2,7 +2,7 @@ //! //! ```cddl //! Attributes = ( attributeType: int, attributeValue: [+text] ) // -//! ( attributeType: ~oid, attributeValue: [+bytes] ) +//! ( attributeType: ~oid, attributeValue: [+bytes] ) //! ``` //! //! Use case: @@ -11,7 +11,7 @@ //! ``` //! //! For more information about `Attributes`, -//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) use attribute::Attribute; use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder}; @@ -59,7 +59,8 @@ impl Encode<()> for Attributes { "Attributes should not be empty", )); } - e.array(self.0.len() as u64)?; + // The attribute type should be included in array too + e.array(self.0.len() as u64 * 2)?; for attribute in &self.0 { attribute.encode(e, ctx)?; } @@ -78,7 +79,8 @@ impl Decode<'_, ()> for Attributes { let mut attributes = Attributes::new(); - for _ in 0..len { + // The attribute type is included in an array, so divide by 2 + for _ in 0..len / 2 { let attribute = Attribute::decode(d, &mut ())?; attributes.add_attr(attribute); } @@ -108,13 +110,13 @@ mod test_attributes { attributes .encode(&mut encoder, &mut ()) .expect("Failed to encode Attributes"); - // 1 Attribute value (array len 1): 0x81 + // 1 Attribute (array len 2 (attribute type + value)): 0x82 // Email Address: 0x00 // Attribute value (array len 2): 0x82 // example@example.com: 0x736578616d706c65406578616d706c652e636f6d assert_eq!( hex::encode(buffer.clone()), - "810082736578616d706c65406578616d706c652e636f6d736578616d706c65406578616d706c652e636f6d" + "820082736578616d706c65406578616d706c652e636f6d736578616d706c65406578616d706c652e636f6d" ); let mut decoder = Decoder::new(&buffer); diff --git a/rust/c509-certificate/src/big_uint.rs b/rust/c509-certificate/src/big_uint.rs index a28e93305d8..ca87c056173 100644 --- a/rust/c509-certificate/src/big_uint.rs +++ b/rust/c509-certificate/src/big_uint.rs @@ -54,7 +54,7 @@ mod test_big_uint { use super::*; - // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/ + // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ // A.1. Example RFC 7925 profiled X.509 Certificate #[test] fn test_encode_decode() { @@ -74,7 +74,7 @@ mod test_big_uint { assert_eq!(decoded_b_uint, b_uint); } - // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/ + // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ // A.2. Example IEEE 802.1AR profiled X.509 Certificate #[test] fn test_encode_decode_2() { diff --git a/rust/c509-certificate/src/extensions/extension/data.rs b/rust/c509-certificate/src/extensions/extension/data.rs index 9bf2b5a8fc8..09980dd4448 100644 --- a/rust/c509-certificate/src/extensions/extension/data.rs +++ b/rust/c509-certificate/src/extensions/extension/data.rs @@ -1,5 +1,5 @@ //! Extension data provides a necessary information for encoding and decoding of C509 -//! Extension. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! Extension. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) //! Section 9.4 C509 Extensions Registry for more information. // cspell: words Evt diff --git a/rust/c509-certificate/src/extensions/mod.rs b/rust/c509-certificate/src/extensions/mod.rs index 1288f9e642b..f5788ee2443 100644 --- a/rust/c509-certificate/src/extensions/mod.rs +++ b/rust/c509-certificate/src/extensions/mod.rs @@ -1,21 +1,18 @@ //! C509 Extension as a part of `TBSCertificate` used in C509 Certificate. //! //! Extension fallback of C509 OID extension -//! Given OID if not found in the registered OID table, it will be encoded as a PEN OID. -//! If the OID is not a PEN OID, it will be encoded as an unwrapped OID. +//! Given OID if not found in the registered OID table, it will be encoded as an unwrapped OID. //! //! ```cddl //! Extensions and Extension can be encoded as the following: //! Extensions = [ * Extension ] / int //! Extension = ( extensionID: int, extensionValue: any ) // -//! ( extensionID: ~oid, ? critical: true, -//! extensionValue: bytes ) // -//! ( extensionID: pen, ? critical: true, -//! extensionValue: bytes ) +//! ( extensionID: ~oid, ? critical: true, +//! extensionValue: bytes ) // //! ``` //! //! For more information about Extensions, -//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) pub mod alt_name; pub mod extension; diff --git a/rust/c509-certificate/src/general_names/data.rs b/rust/c509-certificate/src/general_names/data.rs index 71ff7649492..993d031ecf2 100644 --- a/rust/c509-certificate/src/general_names/data.rs +++ b/rust/c509-certificate/src/general_names/data.rs @@ -1,5 +1,5 @@ //! General Name data provides a necessary information for encoding and decoding of C509 -//! General Name. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! General Name. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) //! Section 9.9 C509 General Names Registry for more information. // cspell: words Gntr Gnvt diff --git a/rust/c509-certificate/src/general_names/general_name.rs b/rust/c509-certificate/src/general_names/general_name.rs index 0549f37bb4c..e7d400b9ac9 100644 --- a/rust/c509-certificate/src/general_names/general_name.rs +++ b/rust/c509-certificate/src/general_names/general_name.rs @@ -1,7 +1,7 @@ //! C509 General Name //! //! For more information about `GeneralName`, -//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) use std::fmt::Debug; diff --git a/rust/c509-certificate/src/general_names/mod.rs b/rust/c509-certificate/src/general_names/mod.rs index 1998733be30..3e0867c33d2 100644 --- a/rust/c509-certificate/src/general_names/mod.rs +++ b/rust/c509-certificate/src/general_names/mod.rs @@ -1,7 +1,7 @@ //! C509 General Names //! //! For more information about `GeneralNames`, -//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) mod data; pub mod general_name; diff --git a/rust/c509-certificate/src/issuer_sig_algo/data.rs b/rust/c509-certificate/src/issuer_sig_algo/data.rs index 1d0e77bf392..c052c7e438b 100644 --- a/rust/c509-certificate/src/issuer_sig_algo/data.rs +++ b/rust/c509-certificate/src/issuer_sig_algo/data.rs @@ -1,5 +1,5 @@ //! Signature algorithm data provides a necessary information for encoding and decoding of -//! C509 `issuerSignatureAlgorithm`. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! C509 `issuerSignatureAlgorithm`. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) //! Section 9.10 C509 Signature Algorithms Registry for more information. // cspell: words RSASSA XMSS diff --git a/rust/c509-certificate/src/lib.rs b/rust/c509-certificate/src/lib.rs index ae223655b93..a2ca40d225a 100644 --- a/rust/c509-certificate/src/lib.rs +++ b/rust/c509-certificate/src/lib.rs @@ -33,7 +33,7 @@ //! * issuerSignatureAlgorithm: The algorithm used to sign the certificate (must be the //! algorithm uses to create `IssuerSignatureValue`). //! -//! Please refer to the [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) for more information. +//! Please refer to the [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) for more information. use anyhow::anyhow; use c509::C509; diff --git a/rust/c509-certificate/src/name/mod.rs b/rust/c509-certificate/src/name/mod.rs index 4ddc2be7a28..1bf2b13c262 100644 --- a/rust/c509-certificate/src/name/mod.rs +++ b/rust/c509-certificate/src/name/mod.rs @@ -10,7 +10,7 @@ //! ``` //! //! For more information about Name, -//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) use asn1_rs::{oid, Oid}; use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder}; @@ -278,7 +278,7 @@ pub(crate) mod test_name { use super::*; use crate::attributes::attribute::Attribute; - // Test data from https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/ + // Test data from https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ // A.1.1. Example C509 Certificate Encoding pub(crate) fn name_cn_text() -> (Name, String) { let mut attr = Attribute::new(oid!(2.5.4 .3)); @@ -356,7 +356,7 @@ pub(crate) mod test_name { assert_eq!(name_decoded, name); } - // Test data from https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/ + // Test data from https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ // A.1. Example RFC 7925 profiled X.509 Certificate pub(crate) fn name_cn_eui_mac() -> (Name, String) { let mut attr = Attribute::new(oid!(2.5.4 .3)); @@ -463,7 +463,7 @@ pub(crate) mod test_name { assert_eq!(name_decoded, name); } - // Test data from https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/ + // Test data from https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ // A.2. Example IEEE 802.1AR profiled X.509 Certificate // Issuer: C=US, ST=CA, O=Example Inc, OU=certification, CN=802.1AR CA pub(crate) fn names() -> (Name, String) { diff --git a/rust/c509-certificate/src/subject_pub_key_algo/data.rs b/rust/c509-certificate/src/subject_pub_key_algo/data.rs index bb37a2d4bf5..0a29de39f48 100644 --- a/rust/c509-certificate/src/subject_pub_key_algo/data.rs +++ b/rust/c509-certificate/src/subject_pub_key_algo/data.rs @@ -1,5 +1,5 @@ //! Public key algorithm data provides a necessary information for encoding and decoding -//! of C509 `subjectPublicKeyAlgorithm`. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/) +//! of C509 `subjectPublicKeyAlgorithm`. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) //! Section 9.11 C509 Public Key Algorithms Registry for more information. // cspell: words Weierstraß secp XMSS brainpool diff --git a/rust/c509-certificate/src/tbs_cert.rs b/rust/c509-certificate/src/tbs_cert.rs index d67089a4b6e..87ae6eb8b4b 100644 --- a/rust/c509-certificate/src/tbs_cert.rs +++ b/rust/c509-certificate/src/tbs_cert.rs @@ -205,7 +205,7 @@ pub(crate) mod test_tbs_cert { // Mnemonic: match mad promote group rival case const PUBKEY: [u8; 8] = [0x88, 0xD0, 0xB6, 0xB0, 0xB3, 0x7B, 0xAA, 0x46]; - // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/ + // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ // A.1. Example RFC 7925 profiled X.509 Certificate // // @@ -311,7 +311,7 @@ pub(crate) mod test_tbs_cert { assert_eq!(decoded_tbs, tbs_cert); } - // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/ + // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ // A.2. Example IEEE 802.1AR profiled X.509 Certificate // // Certificate: diff --git a/rust/c509-certificate/src/time.rs b/rust/c509-certificate/src/time.rs index ade7a5a11e4..9e1811c0657 100644 --- a/rust/c509-certificate/src/time.rs +++ b/rust/c509-certificate/src/time.rs @@ -79,7 +79,7 @@ mod test_time { assert_eq!(decoded_time, time); } - // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/ + // Test reference https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ // A.1. Example RFC 7925 profiled X.509 Certificate #[test] fn test_encode_decode() { From b2d22c834c8d52bf62277ce7a497cd8a8ff7b045 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Thu, 12 Sep 2024 10:32:53 +0700 Subject: [PATCH 08/19] fix(rust/c509-certificate): format + err handling --- rust/c509-certificate/examples/cli/main.rs | 2 +- .../src/attributes/attribute.rs | 16 +++++++--------- .../src/extensions/extension/mod.rs | 19 ++++++++----------- rust/c509-certificate/src/extensions/mod.rs | 3 ++- rust/c509-certificate/src/name/mod.rs | 17 +++++++++++------ rust/c509-certificate/src/oid.rs | 11 ++++------- rust/c509-certificate/src/tbs_cert.rs | 8 ++++---- rust/c509-certificate/src/time.rs | 2 +- 8 files changed, 38 insertions(+), 40 deletions(-) diff --git a/rust/c509-certificate/examples/cli/main.rs b/rust/c509-certificate/examples/cli/main.rs index 6297b14348e..e7c662de28e 100644 --- a/rust/c509-certificate/examples/cli/main.rs +++ b/rust/c509-certificate/examples/cli/main.rs @@ -163,7 +163,7 @@ fn generate( let now_timestamp: u64 = Utc::now() .timestamp() .try_into() - .expect("Timestamp cannot be converted to u64"); + .map_err(|_| anyhow::anyhow!("Current timestamp is invalid"))?; let not_before = parse_or_default_date(c509_json.validity_not_before, now_timestamp)?; // Default as expire date for not_after diff --git a/rust/c509-certificate/src/attributes/attribute.rs b/rust/c509-certificate/src/attributes/attribute.rs index 4567bfcaab0..ce5e0b74881 100644 --- a/rust/c509-certificate/src/attributes/attribute.rs +++ b/rust/c509-certificate/src/attributes/attribute.rs @@ -72,9 +72,7 @@ struct Helper { impl<'de> Deserialize<'de> for Attribute { fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { + where D: Deserializer<'de> { let helper = Helper::deserialize(deserializer)?; let oid = Oid::from_str(&helper.oid).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?; @@ -88,9 +86,7 @@ impl<'de> Deserialize<'de> for Attribute { impl Serialize for Attribute { fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { + where S: serde::Serializer { let helper = Helper { oid: self.registered_oid.get_c509_oid().get_oid().to_string(), value: self.value.clone(), @@ -201,9 +197,11 @@ impl Decode<'_, ()> for AttributeValue { match d.datatype()? { minicbor::data::Type::String => Ok(AttributeValue::Text(d.str()?.to_string())), minicbor::data::Type::Bytes => Ok(AttributeValue::Bytes(d.bytes()?.to_vec())), - _ => Err(minicbor::decode::Error::message( - "Invalid AttributeValue, value should be either String or Bytes", - )), + _ => { + Err(minicbor::decode::Error::message( + "Invalid AttributeValue, value should be either String or Bytes", + )) + }, } } } diff --git a/rust/c509-certificate/src/extensions/extension/mod.rs b/rust/c509-certificate/src/extensions/extension/mod.rs index 899b6d5c2a5..095ed9c56d5 100644 --- a/rust/c509-certificate/src/extensions/extension/mod.rs +++ b/rust/c509-certificate/src/extensions/extension/mod.rs @@ -67,9 +67,7 @@ struct Helper { impl<'de> Deserialize<'de> for Extension { fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { + where D: Deserializer<'de> { let helper = Helper::deserialize(deserializer)?; let oid = Oid::from_str(&helper.oid).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?; @@ -80,9 +78,7 @@ impl<'de> Deserialize<'de> for Extension { impl Serialize for Extension { fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { + where S: serde::Serializer { let helper = Helper { oid: self.registered_oid.get_c509_oid().get_oid().to_string(), value: self.value.clone(), @@ -231,8 +227,7 @@ impl Encode<()> for ExtensionValue { } impl Decode<'_, C> for ExtensionValue -where - C: ExtensionValueTypeTrait + Debug, +where C: ExtensionValueTypeTrait + Debug { fn decode(d: &mut Decoder<'_>, ctx: &mut C) -> Result { match ctx.get_type() { @@ -248,9 +243,11 @@ where let value = AlternativeName::decode(d, &mut ())?; Ok(ExtensionValue::AlternativeName(value)) }, - ExtensionValueType::Unsupported => Err(minicbor::decode::Error::message( - "Cannot decode Unsupported extension value", - )), + ExtensionValueType::Unsupported => { + Err(minicbor::decode::Error::message( + "Cannot decode Unsupported extension value", + )) + }, } } } diff --git a/rust/c509-certificate/src/extensions/mod.rs b/rust/c509-certificate/src/extensions/mod.rs index f5788ee2443..51784aaedc4 100644 --- a/rust/c509-certificate/src/extensions/mod.rs +++ b/rust/c509-certificate/src/extensions/mod.rs @@ -1,7 +1,8 @@ //! C509 Extension as a part of `TBSCertificate` used in C509 Certificate. //! //! Extension fallback of C509 OID extension -//! Given OID if not found in the registered OID table, it will be encoded as an unwrapped OID. +//! Given OID if not found in the registered OID table, it will be encoded as an unwrapped +//! OID. //! //! ```cddl //! Extensions and Extension can be encoded as the following: diff --git a/rust/c509-certificate/src/name/mod.rs b/rust/c509-certificate/src/name/mod.rs index 1bf2b13c262..6d11d114771 100644 --- a/rust/c509-certificate/src/name/mod.rs +++ b/rust/c509-certificate/src/name/mod.rs @@ -131,9 +131,11 @@ impl Decode<'_, ()> for NameValue { // If Name is a text string, the attribute is a CommonName minicbor::data::Type::String => Ok(create_attributes_with_cn(d.str()?.to_string())), minicbor::data::Type::Bytes => decode_bytes(d), - _ => Err(minicbor::decode::Error::message( - "Name must be an array, text or bytes", - )), + _ => { + Err(minicbor::decode::Error::message( + "Name must be an array, text or bytes", + )) + }, } } } @@ -256,9 +258,11 @@ fn decode_eui_cn_bytes(bytes: &[u8]) -> Result Err(minicbor::decode::Error::message( - "EUI-64 or MAC address must be 7 or 9 bytes", - )), + _ => { + Err(minicbor::decode::Error::message( + "EUI-64 or MAC address must be 7 or 9 bytes", + )) + }, } } @@ -466,6 +470,7 @@ pub(crate) mod test_name { // Test data from https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ // A.2. Example IEEE 802.1AR profiled X.509 Certificate // Issuer: C=US, ST=CA, O=Example Inc, OU=certification, CN=802.1AR CA + #[allow(clippy::similar_names)] pub(crate) fn names() -> (Name, String) { let mut attr1 = Attribute::new(oid!(2.5.4 .6)); attr1.add_value(AttributeValue::Text("US".to_string())); diff --git a/rust/c509-certificate/src/oid.rs b/rust/c509-certificate/src/oid.rs index 5f487d10efe..2db0b90a3c7 100644 --- a/rust/c509-certificate/src/oid.rs +++ b/rust/c509-certificate/src/oid.rs @@ -58,9 +58,7 @@ struct Helper { impl<'de> Deserialize<'de> for C509oid { fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { + where D: Deserializer<'de> { let helper = Helper::deserialize(deserializer)?; let oid = Oid::from_str(&helper.oid).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?; @@ -70,9 +68,7 @@ impl<'de> Deserialize<'de> for C509oid { impl Serialize for C509oid { fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { + where S: serde::Serializer { let helper = Helper { oid: self.0.to_string(), }; @@ -132,9 +128,10 @@ impl Decode<'_, ()> for C509oid { #[cfg(test)] mod test_c509_oid { - use super::*; use asn1_rs::oid; + use super::*; + // Test reference 3.1. Encoding of the SHA-256 OID // https://datatracker.ietf.org/doc/rfc9090/ #[test] diff --git a/rust/c509-certificate/src/tbs_cert.rs b/rust/c509-certificate/src/tbs_cert.rs index 87ae6eb8b4b..f347159040e 100644 --- a/rust/c509-certificate/src/tbs_cert.rs +++ b/rust/c509-certificate/src/tbs_cert.rs @@ -371,6 +371,7 @@ pub(crate) mod test_tbs_cert { // 83 2A 4D 33 6A 08 AD 67 DF 20 F1 50 64 21 18 8A 0A DE 6D 34 92 36 #[test] + #[allow(clippy::similar_names)] fn tbs_cert2() { // ---------helper---------- // C=US, ST=CA, L=LA, O=example Inc, OU=IoT/serialNumber=Wt1234 @@ -423,10 +424,9 @@ pub(crate) mod test_tbs_cert { true, )); let mut gns = GeneralNames::new(); - let hw = OtherNameHardwareModuleName::new( - oid!(1.3.6 .1 .4 .1 .6175 .10 .1), - vec![0x01, 0x02, 0x03, 0x04], - ); + let hw = OtherNameHardwareModuleName::new(oid!(1.3.6 .1 .4 .1 .6175 .10 .1), vec![ + 0x01, 0x02, 0x03, 0x04, + ]); gns.add_gn(GeneralName::new( GeneralNameTypeRegistry::OtherNameHardwareModuleName, GeneralNameValue::OtherNameHWModuleName(hw), diff --git a/rust/c509-certificate/src/time.rs b/rust/c509-certificate/src/time.rs index 9e1811c0657..1244473ffa2 100644 --- a/rust/c509-certificate/src/time.rs +++ b/rust/c509-certificate/src/time.rs @@ -4,7 +4,7 @@ use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder}; use serde::{Deserialize, Serialize}; /// A struct representing a time where it accept seconds since the Unix epoch. -/// Doesn't support dates before the Unix epoch (January 1, 1970, 00:00:00 UTC) +/// Doesn't support dates before the Unix epoch (January 1, 1970, 00:00:00 UTC) /// so unsigned integer is used. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct Time(u64); From c50834af3bfa0b90824552a29db938951a39e020 Mon Sep 17 00:00:00 2001 From: bkioshn <35752733+bkioshn@users.noreply.github.com> Date: Tue, 17 Sep 2024 15:42:38 +0700 Subject: [PATCH 09/19] fix(rust/c509-certificate): Rename functions + add necessary functions (#26) * fix: naming + add neccesary function * fix(rust/c509-certificate): cleanup * fix(rust/c509-certificate): cleanup --------- Co-authored-by: Steven Johnson --- rust/c509-certificate/examples/cli/main.rs | 32 +++++++------ .../src/algorithm_identifier.rs | 23 +++++---- .../src/attributes/attribute.rs | 27 ++++++----- rust/c509-certificate/src/attributes/mod.rs | 18 +++---- rust/c509-certificate/src/big_uint.rs | 12 +++++ rust/c509-certificate/src/c509.rs | 4 +- .../src/extensions/alt_name.rs | 16 +++---- .../src/extensions/extension/mod.rs | 21 ++++---- rust/c509-certificate/src/extensions/mod.rs | 46 ++++++++---------- .../src/general_names/general_name.rs | 4 +- .../c509-certificate/src/general_names/mod.rs | 38 +++++++-------- .../src/general_names/other_name_hw_module.rs | 14 +++++- .../src/issuer_sig_algo/mod.rs | 25 +++++++--- rust/c509-certificate/src/lib.rs | 4 +- rust/c509-certificate/src/name/mod.rs | 32 ++++++------- rust/c509-certificate/src/oid.rs | 39 ++++++++------- .../src/subject_pub_key_algo/mod.rs | 24 +++++++--- rust/c509-certificate/src/tbs_cert.rs | 48 +++++++++++-------- rust/c509-certificate/src/time.rs | 16 ++++++- 19 files changed, 256 insertions(+), 187 deletions(-) diff --git a/rust/c509-certificate/examples/cli/main.rs b/rust/c509-certificate/examples/cli/main.rs index e7c662de28e..9ef57c157f6 100644 --- a/rust/c509-certificate/examples/cli/main.rs +++ b/rust/c509-certificate/examples/cli/main.rs @@ -297,22 +297,26 @@ fn decode(file: &PathBuf, output: Option) -> anyhow::Result<()> { let mut d = minicbor::Decoder::new(&cert); let c509 = c509_certificate::c509::C509::decode(&mut d, &mut ())?; - let tbs_cert = c509.get_tbs_cert(); - let is_self_signed = tbs_cert.get_c509_certificate_type() == SELF_SIGNED_INT; + let tbs_cert = c509.tbs_cert(); + let is_self_signed = tbs_cert.c509_certificate_type() == SELF_SIGNED_INT; let c509_json = C509Json { self_signed: is_self_signed, - certificate_type: Some(tbs_cert.get_c509_certificate_type()), - serial_number: Some(tbs_cert.get_certificate_serial_number().clone()), - issuer_signature_algorithm: Some(tbs_cert.get_issuer_signature_algorithm().clone()), - issuer: Some(extract_attributes(tbs_cert.get_issuer())?), - validity_not_before: Some(time_to_string(tbs_cert.get_validity_not_before().to_u64())?), - validity_not_after: Some(time_to_string(tbs_cert.get_validity_not_after().to_u64())?), - subject: extract_attributes(tbs_cert.get_subject())?, - subject_public_key_algorithm: Some(tbs_cert.get_subject_public_key_algorithm().clone()), + certificate_type: Some(tbs_cert.c509_certificate_type()), + serial_number: Some(tbs_cert.certificate_serial_number().clone()), + issuer_signature_algorithm: Some(tbs_cert.issuer_signature_algorithm().clone()), + issuer: Some(extract_attributes(tbs_cert.issuer())?), + validity_not_before: Some(time_to_string( + tbs_cert.validity_not_before().clone().into(), + )?), + validity_not_after: Some(time_to_string( + tbs_cert.validity_not_after().clone().into(), + )?), + subject: extract_attributes(tbs_cert.subject())?, + subject_public_key_algorithm: Some(tbs_cert.subject_public_key_algorithm().clone()), // Return a hex formation of the public key - subject_public_key: tbs_cert.get_subject_public_key().encode_hex(), - extensions: tbs_cert.get_extensions().clone(), - issuer_signature_value: c509.get_issuer_signature_value().clone(), + subject_public_key: tbs_cert.subject_public_key().encode_hex(), + extensions: tbs_cert.extensions().clone(), + issuer_signature_value: c509.issuer_signature_value().clone(), }; let data = serde_json::to_string(&c509_json)?; @@ -327,7 +331,7 @@ fn decode(file: &PathBuf, output: Option) -> anyhow::Result<()> { /// Extract a `Attributes` from a `Name`. fn extract_attributes(name: &Name) -> anyhow::Result { - match name.get_value() { + match name.value() { NameValue::Attributes(attrs) => Ok(attrs.clone()), _ => Err(anyhow::anyhow!("Expected Attributes")), } diff --git a/rust/c509-certificate/src/algorithm_identifier.rs b/rust/c509-certificate/src/algorithm_identifier.rs index 285878c975d..d6a3e1e1ccb 100644 --- a/rust/c509-certificate/src/algorithm_identifier.rs +++ b/rust/c509-certificate/src/algorithm_identifier.rs @@ -23,7 +23,7 @@ use crate::oid::C509oid; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct AlgorithmIdentifier { /// A `C509oid` - oid: C509oid, + c509_oid: C509oid, /// An optional parameter string param: Option, } @@ -33,18 +33,20 @@ impl AlgorithmIdentifier { #[must_use] pub fn new(oid: Oid<'static>, param: Option) -> Self { Self { - oid: C509oid::new(oid), + c509_oid: C509oid::new(oid), param, } } /// Get the OID. - pub(crate) fn get_oid(&self) -> Oid<'static> { - self.oid.clone().get_oid() + #[must_use] + pub fn oid(&self) -> &Oid<'static> { + self.c509_oid.oid() } /// Get the parameter. - pub(crate) fn get_param(&self) -> &Option { + #[must_use] + pub fn param(&self) -> &Option { &self.param } } @@ -57,12 +59,12 @@ impl Encode<()> for AlgorithmIdentifier { // [ algorithm: ~oid, parameters: bytes ] Some(p) => { e.array(2)?; - self.oid.encode(e, ctx)?; + self.c509_oid.encode(e, ctx)?; e.bytes(p.as_bytes())?; }, // ~oid None => { - self.oid.encode(e, ctx)?; + self.c509_oid.encode(e, ctx)?; }, } Ok(()) @@ -82,11 +84,14 @@ impl Decode<'_, ()> for AlgorithmIdentifier { let c509_oid = C509oid::decode(d, ctx)?; let param = String::from_utf8(d.bytes()?.to_vec()).map_err(minicbor::decode::Error::message)?; - Ok(AlgorithmIdentifier::new(c509_oid.get_oid(), Some(param))) + Ok(AlgorithmIdentifier::new( + c509_oid.oid().clone(), + Some(param), + )) // ~oid } else { let oid = C509oid::decode(d, ctx)?; - Ok(AlgorithmIdentifier::new(oid.get_oid(), None)) + Ok(AlgorithmIdentifier::new(oid.oid().clone(), None)) } } } diff --git a/rust/c509-certificate/src/attributes/attribute.rs b/rust/c509-certificate/src/attributes/attribute.rs index ce5e0b74881..b1da9793cc6 100644 --- a/rust/c509-certificate/src/attributes/attribute.rs +++ b/rust/c509-certificate/src/attributes/attribute.rs @@ -39,19 +39,20 @@ impl Attribute { } } - /// Add a value to `Attribute`. - pub fn add_value(&mut self, value: AttributeValue) { - self.value.push(value); + /// Get the value of `Attribute`. + #[must_use] + pub fn value(&self) -> &[AttributeValue] { + &self.value } /// Get the registered OID of `Attribute`. - pub(crate) fn get_registered_oid(&self) -> &C509oidRegistered { + pub(crate) fn registered_oid(&self) -> &C509oidRegistered { &self.registered_oid } - /// Get the value of `Attribute`. - pub(crate) fn get_value(&self) -> &Vec { - &self.value + /// Add a value to `Attribute`. + pub fn add_value(&mut self, value: AttributeValue) { + self.value.push(value); } /// Set whether `Attribute` can have multiple value. @@ -88,7 +89,7 @@ impl Serialize for Attribute { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { let helper = Helper { - oid: self.registered_oid.get_c509_oid().get_oid().to_string(), + oid: self.registered_oid().c509_oid().oid().to_string(), value: self.value.clone(), }; helper.serialize(serializer) @@ -102,14 +103,14 @@ impl Encode<()> for Attribute { // Encode CBOR int if available if let Some(&oid) = self .registered_oid - .get_table() + .table() .get_map() - .get_by_right(&self.registered_oid.get_c509_oid().get_oid()) + .get_by_right(self.registered_oid().c509_oid().oid()) { e.i16(oid)?; } else { - // Encode unwrapped CBOR OID or CBOR PEN - self.registered_oid.get_c509_oid().encode(e, ctx)?; + // Encode unwrapped CBOR OID + self.registered_oid().c509_oid().encode(e, ctx)?; } // Check if the attribute value is empty @@ -141,7 +142,7 @@ impl Decode<'_, ()> for Attribute { } else { // Handle unwrapped CBOR OID or CBOR PEN let c509_oid: C509oid = d.decode()?; - Attribute::new(c509_oid.get_oid()) + Attribute::new(c509_oid.oid().clone()) }; // Handle attribute value diff --git a/rust/c509-certificate/src/attributes/mod.rs b/rust/c509-certificate/src/attributes/mod.rs index ead810ec22e..898c3233408 100644 --- a/rust/c509-certificate/src/attributes/mod.rs +++ b/rust/c509-certificate/src/attributes/mod.rs @@ -24,12 +24,6 @@ mod data; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Attributes(Vec); -impl Default for Attributes { - fn default() -> Self { - Self::new() - } -} - impl Attributes { /// Create a new instance of `Attributes` as empty vector. #[must_use] @@ -45,11 +39,17 @@ impl Attributes { /// Add an `Attribute` to the `Attributes`. /// and set `Attribute` value to support multiple value. - pub fn add_attr(&mut self, attribute: Attribute) { + pub fn add_attribute(&mut self, attribute: Attribute) { self.0.push(attribute.set_multi_value()); } } +impl Default for Attributes { + fn default() -> Self { + Self::new() + } +} + impl Encode<()> for Attributes { fn encode( &self, e: &mut Encoder, ctx: &mut (), @@ -82,7 +82,7 @@ impl Decode<'_, ()> for Attributes { // The attribute type is included in an array, so divide by 2 for _ in 0..len / 2 { let attribute = Attribute::decode(d, &mut ())?; - attributes.add_attr(attribute); + attributes.add_attribute(attribute); } Ok(attributes) @@ -106,7 +106,7 @@ mod test_attributes { attr.add_value(AttributeValue::Text("example@example.com".to_string())); attr.add_value(AttributeValue::Text("example@example.com".to_string())); let mut attributes = Attributes::new(); - attributes.add_attr(attr); + attributes.add_attribute(attr); attributes .encode(&mut encoder, &mut ()) .expect("Failed to encode Attributes"); diff --git a/rust/c509-certificate/src/big_uint.rs b/rust/c509-certificate/src/big_uint.rs index ca87c056173..722965ae08c 100644 --- a/rust/c509-certificate/src/big_uint.rs +++ b/rust/c509-certificate/src/big_uint.rs @@ -21,6 +21,18 @@ impl UnwrappedBigUint { } } +impl From for UnwrappedBigUint { + fn from(value: u64) -> Self { + UnwrappedBigUint::new(value) + } +} + +impl From for u64 { + fn from(unwrapped_big_uint: UnwrappedBigUint) -> Self { + unwrapped_big_uint.0 + } +} + impl Encode<()> for UnwrappedBigUint { fn encode( &self, e: &mut Encoder, _ctx: &mut (), diff --git a/rust/c509-certificate/src/c509.rs b/rust/c509-certificate/src/c509.rs index 75cc23bfa9f..8c2543d907d 100644 --- a/rust/c509-certificate/src/c509.rs +++ b/rust/c509-certificate/src/c509.rs @@ -26,13 +26,13 @@ impl C509 { /// Get the `TBSCertificate` of the C509 Certificate. #[must_use] - pub fn get_tbs_cert(&self) -> &TbsCert { + pub fn tbs_cert(&self) -> &TbsCert { &self.tbs_cert } /// Get the `IssuerSignatureValue` of the C509 Certificate. #[must_use] - pub fn get_issuer_signature_value(&self) -> &Option> { + pub fn issuer_signature_value(&self) -> &Option> { &self.issuer_signature_value } } diff --git a/rust/c509-certificate/src/extensions/alt_name.rs b/rust/c509-certificate/src/extensions/alt_name.rs index f5448ff032d..9681fec63df 100644 --- a/rust/c509-certificate/src/extensions/alt_name.rs +++ b/rust/c509-certificate/src/extensions/alt_name.rs @@ -21,9 +21,9 @@ impl AlternativeName { Self(value) } - /// Get the inner of Alternative Name. + /// Get the general name which can be general names or text. #[must_use] - pub fn get_inner(&self) -> &GeneralNamesOrText { + pub fn general_name(&self) -> &GeneralNamesOrText { &self.0 } } @@ -61,12 +61,12 @@ impl Encode<()> for GeneralNamesOrText { match self { GeneralNamesOrText::GeneralNames(gns) => { let gn = gns - .get_inner() + .general_names() .first() .ok_or(minicbor::encode::Error::message("GeneralNames is empty"))?; // Check whether there is only 1 item in the array which is a DNSName - if gns.get_inner().len() == 1 && gn.get_gn_type().is_dns_name() { - gn.get_gn_value().encode(e, ctx)?; + if gns.general_names().len() == 1 && gn.gn_type().is_dns_name() { + gn.gn_value().encode(e, ctx)?; } else { gns.encode(e, ctx)?; } @@ -89,7 +89,7 @@ impl Decode<'_, ()> for GeneralNamesOrText { GeneralNameValue::Text(d.str()?.to_string()), ); let mut gns = GeneralNames::new(); - gns.add_gn(gn_dns); + gns.add_general_name(gn_dns); Ok(GeneralNamesOrText::GeneralNames(gns)) }, minicbor::data::Type::Array => { @@ -120,7 +120,7 @@ mod test_alt_name { let mut buffer = Vec::new(); let mut encoder = Encoder::new(&mut buffer); let mut gns = GeneralNames::new(); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::DNSName, GeneralNameValue::Text("example.com".to_string()), )); @@ -151,7 +151,7 @@ mod test_alt_name { // If only text, it should be GeneralNames with only 1 DNSName let mut gns = GeneralNames::new(); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::DNSName, GeneralNameValue::Text("example.com".to_string()), )); diff --git a/rust/c509-certificate/src/extensions/extension/mod.rs b/rust/c509-certificate/src/extensions/extension/mod.rs index 095ed9c56d5..3c261af0002 100644 --- a/rust/c509-certificate/src/extensions/extension/mod.rs +++ b/rust/c509-certificate/src/extensions/extension/mod.rs @@ -37,19 +37,19 @@ impl Extension { /// Get the value of the `Extension` in `ExtensionValue`. #[must_use] - pub fn get_value(&self) -> &ExtensionValue { + pub fn value(&self) -> &ExtensionValue { &self.value } /// Get the critical flag of the `Extension`. #[must_use] - pub fn get_critical(&self) -> bool { + pub fn critical(&self) -> bool { self.critical } /// Get the registered OID of the `Extension`. #[must_use] - pub fn get_registered_oid(&self) -> &C509oidRegistered { + pub(crate) fn registered_oid(&self) -> &C509oidRegistered { &self.registered_oid } } @@ -80,7 +80,7 @@ impl Serialize for Extension { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { let helper = Helper { - oid: self.registered_oid.get_c509_oid().get_oid().to_string(), + oid: self.registered_oid.c509_oid().oid().to_string(), value: self.value.clone(), critical: self.critical, }; @@ -92,16 +92,15 @@ impl Encode<()> for Extension { // Extension can be encoded as: // - (extensionID: int, extensionValue: any) // - (extensionID: ~oid, ? critical: true, extensionValue: bytes) - // - (extensionID: pen, ? critical: true, extensionValue: bytes) fn encode( &self, e: &mut Encoder, ctx: &mut (), ) -> Result<(), minicbor::encode::Error> { // Handle CBOR int based on OID mapping if let Some(&mapped_oid) = self .registered_oid - .get_table() + .table() .get_map() - .get_by_right(&self.registered_oid.get_c509_oid().get_oid()) + .get_by_right(self.registered_oid.c509_oid().oid()) { // Determine encoded OID value based on critical flag let encoded_oid = if self.critical { @@ -111,8 +110,8 @@ impl Encode<()> for Extension { }; e.i16(encoded_oid)?; } else { - // Handle unwrapped CBOR OID or CBOR PEN - self.registered_oid.get_c509_oid().encode(e, ctx)?; + // Handle unwrapped CBOR OID + self.registered_oid.c509_oid().encode(e, ctx)?; if self.critical { e.bool(self.critical)?; } @@ -150,7 +149,7 @@ impl Decode<'_, ()> for Extension { )) }, _ => { - // Handle unwrapped CBOR OID or CBOR PEN + // Handle unwrapped CBOR OID let c509_oid = C509oid::decode(d, ctx)?; // Critical flag is optional, so if exist, this mean we have to decode it let critical = if d.datatype()? == minicbor::data::Type::Bool { @@ -163,7 +162,7 @@ impl Decode<'_, ()> for Extension { let extension_value = ExtensionValue::Bytes(d.bytes()?.to_vec()); Ok(Extension::new( - c509_oid.get_oid(), + c509_oid.oid().clone(), extension_value, critical, )) diff --git a/rust/c509-certificate/src/extensions/mod.rs b/rust/c509-certificate/src/extensions/mod.rs index 51784aaedc4..f97268496d4 100644 --- a/rust/c509-certificate/src/extensions/mod.rs +++ b/rust/c509-certificate/src/extensions/mod.rs @@ -32,12 +32,6 @@ static KEY_USAGE_OID: Oid<'static> = oid!(2.5.29 .15); #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct Extensions(Vec); -impl Default for Extensions { - fn default() -> Self { - Self::new() - } -} - impl Extensions { /// Create a new instance of `Extensions` as empty vector. #[must_use] @@ -45,15 +39,21 @@ impl Extensions { Self(Vec::new()) } + /// Get the inner vector of `Extensions`. + #[must_use] + pub fn extensions(&self) -> &[Extension] { + &self.0 + } + /// Add an `Extension` to the `Extensions`. - pub fn add_ext(&mut self, extension: Extension) { + pub fn add_extension(&mut self, extension: Extension) { self.0.push(extension); } +} - /// Get the inner vector of `Extensions`. - #[must_use] - pub fn get_inner(&self) -> &Vec { - &self.0 +impl Default for Extensions { + fn default() -> Self { + Self::new() } } @@ -64,16 +64,10 @@ impl Encode<()> for Extensions { // If there is only one extension and it is KeyUsage, encode as int // encoding as absolute value of the second int and the sign of the first int if let Some(extension) = self.0.first() { - if self.0.len() == 1 - && extension.get_registered_oid().get_c509_oid().get_oid() == KEY_USAGE_OID - { - match extension.get_value() { + if self.0.len() == 1 && extension.registered_oid().c509_oid().oid() == &KEY_USAGE_OID { + match extension.value() { ExtensionValue::Int(value) => { - let ku_value = if extension.get_critical() { - -value - } else { - *value - }; + let ku_value = if extension.critical() { -value } else { *value }; e.i64(ku_value)?; return Ok(()); }, @@ -106,7 +100,7 @@ impl Decode<'_, ()> for Extensions { let extension_value = ExtensionValue::Int(value); let mut extensions = Extensions::new(); - extensions.add_ext(Extension::new( + extensions.add_extension(Extension::new( KEY_USAGE_OID.clone(), extension_value, critical, @@ -120,7 +114,7 @@ impl Decode<'_, ()> for Extensions { let mut extensions = Extensions::new(); for _ in 0..len { let extension = Extension::decode(d, &mut ())?; - extensions.add_ext(extension); + extensions.add_extension(extension); } Ok(extensions) @@ -139,7 +133,7 @@ mod test_extensions { let mut encoder = Encoder::new(&mut buffer); let mut exts = Extensions::new(); - exts.add_ext(Extension::new( + exts.add_extension(Extension::new( oid!(2.5.29 .15), ExtensionValue::Int(2), false, @@ -162,7 +156,7 @@ mod test_extensions { let mut encoder = Encoder::new(&mut buffer); let mut exts = Extensions::new(); - exts.add_ext(Extension::new( + exts.add_extension(Extension::new( oid!(2.5.29 .15), ExtensionValue::Int(2), true, @@ -185,13 +179,13 @@ mod test_extensions { let mut encoder = Encoder::new(&mut buffer); let mut exts = Extensions::new(); - exts.add_ext(Extension::new( + exts.add_extension(Extension::new( oid!(2.5.29 .15), ExtensionValue::Int(2), false, )); - exts.add_ext(Extension::new( + exts.add_extension(Extension::new( oid!(2.5.29 .14), ExtensionValue::Bytes([1, 2, 3, 4].to_vec()), false, diff --git a/rust/c509-certificate/src/general_names/general_name.rs b/rust/c509-certificate/src/general_names/general_name.rs index e7d400b9ac9..6a15e2ebd70 100644 --- a/rust/c509-certificate/src/general_names/general_name.rs +++ b/rust/c509-certificate/src/general_names/general_name.rs @@ -37,13 +37,13 @@ impl GeneralName { /// Get the `GeneralName` type. #[must_use] - pub fn get_gn_type(&self) -> &GeneralNameTypeRegistry { + pub fn gn_type(&self) -> &GeneralNameTypeRegistry { &self.gn_type } /// Get the value of the `GeneralName` in `GeneralNameValue`. #[must_use] - pub fn get_gn_value(&self) -> &GeneralNameValue { + pub fn gn_value(&self) -> &GeneralNameValue { &self.value } } diff --git a/rust/c509-certificate/src/general_names/mod.rs b/rust/c509-certificate/src/general_names/mod.rs index 3e0867c33d2..d46413ea52e 100644 --- a/rust/c509-certificate/src/general_names/mod.rs +++ b/rust/c509-certificate/src/general_names/mod.rs @@ -18,12 +18,6 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct GeneralNames(Vec); -impl Default for GeneralNames { - fn default() -> Self { - Self::new() - } -} - impl GeneralNames { /// Create a new instance of `GeneralNames` as empty vector. #[must_use] @@ -31,15 +25,21 @@ impl GeneralNames { Self(Vec::new()) } + /// Get the inner of `GeneralName`. + #[must_use] + pub fn general_names(&self) -> &[GeneralName] { + &self.0 + } + /// Add a new `GeneralName` to the `GeneralNames`. - pub fn add_gn(&mut self, gn: GeneralName) { + pub fn add_general_name(&mut self, gn: GeneralName) { self.0.push(gn); } +} - /// Get the inner of `GeneralName`. - #[must_use] - pub fn get_inner(&self) -> &Vec { - &self.0 +impl Default for GeneralNames { + fn default() -> Self { + Self::new() } } @@ -68,7 +68,7 @@ impl Decode<'_, ()> for GeneralNames { ))?; let mut gn = GeneralNames::new(); for _ in 0..len / 2 { - gn.add_gn(GeneralName::decode(d, ctx)?); + gn.add_general_name(GeneralName::decode(d, ctx)?); } Ok(gn) } @@ -94,22 +94,22 @@ mod test_general_names { let mut encoder = Encoder::new(&mut buffer); let mut gns = GeneralNames::new(); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::DNSName, GeneralNameValue::Text("example.com".to_string()), )); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::OtherNameHardwareModuleName, GeneralNameValue::OtherNameHWModuleName(OtherNameHardwareModuleName::new( oid!(2.16.840 .1 .101 .3 .4 .2 .1), vec![0x01, 0x02, 0x03, 0x04], )), )); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::IPAddress, GeneralNameValue::Bytes(Ipv4Addr::new(192, 168, 1, 1).octets().to_vec()), )); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::RegisteredID, GeneralNameValue::Oid(C509oid::new(oid!(2.16.840 .1 .101 .3 .4 .2 .1))), )); @@ -130,15 +130,15 @@ mod test_general_names { let mut encoder = Encoder::new(&mut buffer); let mut gns = GeneralNames::new(); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::DNSName, GeneralNameValue::Text("example.com".to_string()), )); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::DNSName, GeneralNameValue::Text("example.com".to_string()), )); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::DNSName, GeneralNameValue::Text("example.com".to_string()), )); diff --git a/rust/c509-certificate/src/general_names/other_name_hw_module.rs b/rust/c509-certificate/src/general_names/other_name_hw_module.rs index b57697ce79a..9e6ba200005 100644 --- a/rust/c509-certificate/src/general_names/other_name_hw_module.rs +++ b/rust/c509-certificate/src/general_names/other_name_hw_module.rs @@ -29,6 +29,18 @@ impl OtherNameHardwareModuleName { hw_serial_num, } } + + /// Get the c509 OID hardware type. + #[must_use] + pub fn hw_type(&self) -> &C509oid { + &self.hw_type + } + + /// Get the hardware serial number. + #[must_use] + pub fn hw_serial_num(&self) -> &[u8] { + &self.hw_serial_num + } } impl Encode<()> for OtherNameHardwareModuleName { @@ -48,7 +60,7 @@ impl<'a> Decode<'a, ()> for OtherNameHardwareModuleName { let hw_type = C509oid::decode(d, ctx)?; let hw_serial_num = d.bytes()?.to_vec(); Ok(OtherNameHardwareModuleName::new( - hw_type.get_oid(), + hw_type.oid().clone(), hw_serial_num, )) } diff --git a/rust/c509-certificate/src/issuer_sig_algo/mod.rs b/rust/c509-certificate/src/issuer_sig_algo/mod.rs index ff63acae59a..db15c1f6884 100644 --- a/rust/c509-certificate/src/issuer_sig_algo/mod.rs +++ b/rust/c509-certificate/src/issuer_sig_algo/mod.rs @@ -37,7 +37,20 @@ impl IssuerSignatureAlgorithm { algo_identifier: AlgorithmIdentifier::new(oid, param), } } + + /// Get the algorithm identifier. + #[must_use] + pub fn algo_identifier(&self) -> &AlgorithmIdentifier { + &self.algo_identifier + } + + /// Get the registered OID. + #[allow(dead_code)] + pub(crate) fn registered_oid(&self) -> &C509oidRegistered { + &self.registered_oid + } } + /// Helper struct for deserialize and serialize `IssuerSignatureAlgorithm`. #[derive(Debug, Deserialize, Serialize)] struct Helper { @@ -62,8 +75,8 @@ impl Serialize for IssuerSignatureAlgorithm { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { let helper = Helper { - oid: self.registered_oid.get_c509_oid().get_oid().to_string(), - param: self.algo_identifier.get_param().clone(), + oid: self.registered_oid.c509_oid().oid().to_string(), + param: self.algo_identifier.param().clone(), }; helper.serialize(serializer) } @@ -75,9 +88,9 @@ impl Encode<()> for IssuerSignatureAlgorithm { ) -> Result<(), minicbor::encode::Error> { if let Some(&i) = self .registered_oid - .get_table() + .table() .get_map() - .get_by_right(&self.registered_oid.get_c509_oid().get_oid()) + .get_by_right(self.registered_oid.c509_oid().oid()) { e.i16(i)?; } else { @@ -99,8 +112,8 @@ impl Decode<'_, ()> for IssuerSignatureAlgorithm { _ => { let algo_identifier = AlgorithmIdentifier::decode(d, ctx)?; Ok(IssuerSignatureAlgorithm::new( - algo_identifier.get_oid(), - algo_identifier.get_param().clone(), + algo_identifier.oid().clone(), + algo_identifier.param().clone(), )) }, } diff --git a/rust/c509-certificate/src/lib.rs b/rust/c509-certificate/src/lib.rs index a2ca40d225a..808de48c1dd 100644 --- a/rust/c509-certificate/src/lib.rs +++ b/rust/c509-certificate/src/lib.rs @@ -104,8 +104,8 @@ pub fn verify(c509: &[u8], public_key: &PublicKey) -> anyhow::Result<()> { let c509 = C509::decode(&mut d, &mut ())?; let mut encoded_tbs = Vec::new(); let mut encoder = minicbor::Encoder::new(&mut encoded_tbs); - c509.get_tbs_cert().encode(&mut encoder, &mut ())?; - let issuer_sig = c509.get_issuer_signature_value().clone().ok_or(anyhow!( + c509.tbs_cert().encode(&mut encoder, &mut ())?; + let issuer_sig = c509.issuer_signature_value().clone().ok_or(anyhow!( "Signature verification failed, No issuer signature" ))?; public_key.verify(&encoded_tbs, &issuer_sig) diff --git a/rust/c509-certificate/src/name/mod.rs b/rust/c509-certificate/src/name/mod.rs index 6d11d114771..75c04bc0692 100644 --- a/rust/c509-certificate/src/name/mod.rs +++ b/rust/c509-certificate/src/name/mod.rs @@ -48,7 +48,7 @@ impl Name { /// Get the value of the `Name`. #[must_use] - pub fn get_value(&self) -> &NameValue { + pub fn value(&self) -> &NameValue { &self.0 } } @@ -97,12 +97,12 @@ impl Encode<()> for NameValue { ))?; // If Name contains a single Attribute of type CommonName if attrs.attributes().len() == 1 - && attr_first.get_registered_oid().get_c509_oid().get_oid() == COMMON_NAME_OID + && attr_first.registered_oid().c509_oid().oid() == &COMMON_NAME_OID { // Get the value of the attribute let cn_value = attr_first - .get_value() + .value() .first() .ok_or(minicbor::encode::Error::message( "Cannot get the first Attribute value", @@ -271,7 +271,7 @@ fn create_attributes_with_cn(text: String) -> NameValue { let mut attr = Attribute::new(COMMON_NAME_OID); attr.add_value(AttributeValue::Text(text)); let mut attrs = Attributes::new(); - attrs.add_attr(attr); + attrs.add_attribute(attr); NameValue::Attributes(attrs) } @@ -288,7 +288,7 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("RFC test CA".to_string())); let mut attrs = Attributes::new(); - attrs.add_attr(attr); + attrs.add_attribute(attr); ( Name::new(NameValue::Attributes(attrs)), @@ -321,7 +321,7 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("000123abcd".to_string())); let mut attrs = Attributes::new(); - attrs.add_attr(attr); + attrs.add_attribute(attr); let name = Name::new(NameValue::Attributes(attrs)); name.encode(&mut encoder, &mut ()) @@ -345,7 +345,7 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("000123ABCD".to_string())); let mut attrs = Attributes::new(); - attrs.add_attr(attr); + attrs.add_attribute(attr); let name = Name::new(NameValue::Attributes(attrs)); name.encode(&mut encoder, &mut ()) @@ -366,7 +366,7 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("01-23-45-FF-FE-67-89-AB".to_string())); let mut attrs = Attributes::new(); - attrs.add_attr(attr); + attrs.add_attribute(attr); ( Name::new(NameValue::Attributes(attrs)), @@ -400,7 +400,7 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("01-23-45-ff-fe-67-89-AB".to_string())); let mut attrs = Attributes::new(); - attrs.add_attr(attr); + attrs.add_attribute(attr); let name = Name::new(NameValue::Attributes(attrs)); name.encode(&mut encoder, &mut ()) @@ -426,7 +426,7 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("01-23-45-67-89-AB-00-01".to_string())); let mut attrs = Attributes::new(); - attrs.add_attr(attr); + attrs.add_attribute(attr); let name = Name::new(NameValue::Attributes(attrs)); @@ -448,7 +448,7 @@ pub(crate) mod test_name { let mut attr = Attribute::new(oid!(2.5.4 .3)); attr.add_value(AttributeValue::Text("01-23-45-67-89-ab-00-01".to_string())); let mut attrs = Attributes::new(); - attrs.add_attr(attr); + attrs.add_attribute(attr); let name = Name::new(NameValue::Attributes(attrs)); @@ -484,11 +484,11 @@ pub(crate) mod test_name { attr5.add_value(AttributeValue::Text("802.1AR CA".to_string())); let mut attrs = Attributes::new(); - attrs.add_attr(attr1); - attrs.add_attr(attr2); - attrs.add_attr(attr3); - attrs.add_attr(attr4); - attrs.add_attr(attr5); + attrs.add_attribute(attr1); + attrs.add_attribute(attr2); + attrs.add_attribute(attr3); + attrs.add_attribute(attr4); + attrs.add_attribute(attr5); ( Name::new(NameValue::Attributes(attrs)), diff --git a/rust/c509-certificate/src/oid.rs b/rust/c509-certificate/src/oid.rs index 2db0b90a3c7..6148dcfb43c 100644 --- a/rust/c509-certificate/src/oid.rs +++ b/rust/c509-certificate/src/oid.rs @@ -17,7 +17,7 @@ use crate::tables::IntegerToOidTable; #[derive(Debug, Clone, PartialEq)] pub struct C509oidRegistered { /// The `C509oid`. - oid: C509oid, + c509_oid: C509oid, /// The registration table. registration_table: &'static IntegerToOidTable, } @@ -26,19 +26,19 @@ impl C509oidRegistered { /// Create a new instance of `C509oidRegistered`. pub(crate) fn new(oid: Oid<'static>, table: &'static IntegerToOidTable) -> Self { Self { - oid: C509oid::new(oid), + c509_oid: C509oid::new(oid), registration_table: table, } } /// Get the `C509oid`. #[must_use] - pub fn get_c509_oid(&self) -> C509oid { - self.oid.clone() + pub fn c509_oid(&self) -> &C509oid { + &self.c509_oid } /// Get the registration table. - pub(crate) fn get_table(&self) -> &'static IntegerToOidTable { + pub(crate) fn table(&self) -> &'static IntegerToOidTable { self.registration_table } } @@ -56,6 +56,20 @@ struct Helper { oid: String, } +impl C509oid { + /// Create an new instance of `C509oid`. + #[must_use] + pub fn new(oid: Oid<'static>) -> Self { + Self(oid) + } + + /// Get the underlying OID of the `C509oid` + #[must_use] + pub fn oid(&self) -> &Oid<'static> { + &self.0 + } +} + impl<'de> Deserialize<'de> for C509oid { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { @@ -76,21 +90,6 @@ impl Serialize for C509oid { } } -impl C509oid { - /// Create an new instance of `C509oid`. - /// Default value of PEN flag is false - #[must_use] - pub fn new(oid: Oid<'static>) -> Self { - Self(oid) - } - - /// Get the underlying OID of the `C509oid` - #[must_use] - pub fn get_oid(self) -> Oid<'static> { - self.0 - } -} - impl Encode<()> for C509oid { /// Encode an OID /// Encode as an unwrapped OID (~oid) - as bytes string without tag. diff --git a/rust/c509-certificate/src/subject_pub_key_algo/mod.rs b/rust/c509-certificate/src/subject_pub_key_algo/mod.rs index 014ad6e6cc7..bd59a9b6112 100644 --- a/rust/c509-certificate/src/subject_pub_key_algo/mod.rs +++ b/rust/c509-certificate/src/subject_pub_key_algo/mod.rs @@ -39,6 +39,18 @@ impl SubjectPubKeyAlgorithm { algo_identifier: AlgorithmIdentifier::new(oid, param), } } + + /// Get the algorithm identifier. + #[must_use] + pub fn algo_identifier(&self) -> &AlgorithmIdentifier { + &self.algo_identifier + } + + /// Get the registered OID. + #[allow(dead_code)] + pub(crate) fn registered_oid(&self) -> &C509oidRegistered { + &self.registered_oid + } } /// Helper struct for deserialize and serialize `SubjectPubKeyAlgorithm`. @@ -65,8 +77,8 @@ impl Serialize for SubjectPubKeyAlgorithm { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { let helper = Helper { - oid: self.registered_oid.get_c509_oid().get_oid().to_string(), - param: self.algo_identifier.get_param().clone(), + oid: self.registered_oid.c509_oid().oid().to_string(), + param: self.algo_identifier.param().clone(), }; helper.serialize(serializer) } @@ -78,9 +90,9 @@ impl Encode<()> for SubjectPubKeyAlgorithm { ) -> Result<(), minicbor::encode::Error> { if let Some(&i) = self .registered_oid - .get_table() + .table() .get_map() - .get_by_right(&self.registered_oid.get_c509_oid().get_oid()) + .get_by_right(self.registered_oid.c509_oid().oid()) { e.i16(i)?; } else { @@ -100,8 +112,8 @@ impl Decode<'_, ()> for SubjectPubKeyAlgorithm { } else { let algo_identifier = AlgorithmIdentifier::decode(d, ctx)?; Ok(SubjectPubKeyAlgorithm::new( - algo_identifier.get_oid(), - algo_identifier.get_param().clone(), + algo_identifier.oid().clone(), + algo_identifier.param().clone(), )) } } diff --git a/rust/c509-certificate/src/tbs_cert.rs b/rust/c509-certificate/src/tbs_cert.rs index f347159040e..e0e10551ebf 100644 --- a/rust/c509-certificate/src/tbs_cert.rs +++ b/rust/c509-certificate/src/tbs_cert.rs @@ -62,13 +62,13 @@ impl TbsCert { /// Get the certificate type. #[must_use] - pub fn get_c509_certificate_type(&self) -> u8 { + pub fn c509_certificate_type(&self) -> u8 { self.c509_certificate_type } /// Get the certificate serial number. #[must_use] - pub fn get_certificate_serial_number(&self) -> &UnwrappedBigUint { + pub fn certificate_serial_number(&self) -> &UnwrappedBigUint { &self.certificate_serial_number } @@ -80,45 +80,51 @@ impl TbsCert { /// Get the issuer. #[must_use] - pub fn get_issuer(&self) -> &Name { + pub fn issuer(&self) -> &Name { &self.issuer } /// Get the validity not before. #[must_use] - pub fn get_validity_not_before(&self) -> &Time { + pub fn validity_not_before(&self) -> &Time { &self.validity_not_before } /// Get the validity not after. #[must_use] - pub fn get_validity_not_after(&self) -> &Time { + pub fn validity_not_after(&self) -> &Time { &self.validity_not_after } /// Get the subject. #[must_use] - pub fn get_subject(&self) -> &Name { + pub fn subject(&self) -> &Name { &self.subject } /// Get the subject public key algorithm. #[must_use] - pub fn get_subject_public_key_algorithm(&self) -> &SubjectPubKeyAlgorithm { + pub fn subject_public_key_algorithm(&self) -> &SubjectPubKeyAlgorithm { &self.subject_public_key_algorithm } /// Get the subject public key. #[must_use] - pub fn get_subject_public_key(&self) -> &[u8] { + pub fn subject_public_key(&self) -> &[u8] { &self.subject_public_key } /// Get the extensions. #[must_use] - pub fn get_extensions(&self) -> &Extensions { + pub fn extensions(&self) -> &Extensions { &self.extensions } + + /// Get the issuer signature algorithm. + #[must_use] + pub fn issuer_signature_algorithm(&self) -> &IssuerSignatureAlgorithm { + &self.issuer_signature_algorithm + } } impl Encode<()> for TbsCert { @@ -257,7 +263,7 @@ pub(crate) mod test_tbs_cert { pub(crate) fn tbs() -> TbsCert { fn extensions() -> Extensions { let mut exts = Extensions::new(); - exts.add_ext(Extension::new( + exts.add_extension(Extension::new( oid!(2.5.29 .15), ExtensionValue::Int(1), false, @@ -390,24 +396,24 @@ pub(crate) mod test_tbs_cert { attr6.add_value(AttributeValue::Text("Wt1234".to_string())); let mut attrs = Attributes::new(); - attrs.add_attr(attr1); - attrs.add_attr(attr2); - attrs.add_attr(attr3); - attrs.add_attr(attr4); - attrs.add_attr(attr5); - attrs.add_attr(attr6); + attrs.add_attribute(attr1); + attrs.add_attribute(attr2); + attrs.add_attribute(attr3); + attrs.add_attribute(attr4); + attrs.add_attribute(attr5); + attrs.add_attribute(attr6); Name::new(NameValue::Attributes(attrs)) } fn extensions() -> Extensions { let mut exts = Extensions::new(); - exts.add_ext(Extension::new( + exts.add_extension(Extension::new( oid!(2.5.29 .19), ExtensionValue::Int(-2), false, )); - exts.add_ext(Extension::new( + exts.add_extension(Extension::new( oid!(2.5.29 .14), ExtensionValue::Bytes( [ @@ -418,7 +424,7 @@ pub(crate) mod test_tbs_cert { ), false, )); - exts.add_ext(Extension::new( + exts.add_extension(Extension::new( oid!(2.5.29 .15), ExtensionValue::Int(5), true, @@ -427,12 +433,12 @@ pub(crate) mod test_tbs_cert { let hw = OtherNameHardwareModuleName::new(oid!(1.3.6 .1 .4 .1 .6175 .10 .1), vec![ 0x01, 0x02, 0x03, 0x04, ]); - gns.add_gn(GeneralName::new( + gns.add_general_name(GeneralName::new( GeneralNameTypeRegistry::OtherNameHardwareModuleName, GeneralNameValue::OtherNameHWModuleName(hw), )); - exts.add_ext(Extension::new( + exts.add_extension(Extension::new( oid!(2.5.29 .17), ExtensionValue::AlternativeName(AlternativeName::new( GeneralNamesOrText::GeneralNames(gns), diff --git a/rust/c509-certificate/src/time.rs b/rust/c509-certificate/src/time.rs index 1244473ffa2..6fb9b0896ee 100644 --- a/rust/c509-certificate/src/time.rs +++ b/rust/c509-certificate/src/time.rs @@ -19,13 +19,25 @@ impl Time { Self(time) } - /// Get the time in u64. + /// Get the u64 of `Time`. #[must_use] - pub fn to_u64(&self) -> u64 { + pub fn time(&self) -> u64 { self.0 } } +impl From for Time { + fn from(value: u64) -> Self { + Time::new(value) + } +} + +impl From