Skip to content

cmpv2: build OobCertHash from a certificate #1766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions cmpv2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ der = { version = "0.8.0-rc.0", features = ["alloc", "derive", "flagset", "oid"]
spki = { version = "0.8.0-rc.0" }
x509-cert = { version = "=0.3.0-pre.0", default-features = false }

digest = { version = "0.11.0-pre.10", optional = true, default-features = false }

[dev-dependencies]
const-oid = { version = "0.10.0-rc.0", features = ["db"] }
hex-literal = "0.4"
Expand All @@ -30,6 +32,7 @@ alloc = ["der/alloc"]
std = ["der/std", "spki/std"]

pem = ["alloc", "der/pem"]
digest = ["dep:digest", "x509-cert/digest"]

[package.metadata.docs.rs]
all-features = true
Expand Down
35 changes: 33 additions & 2 deletions cmpv2/src/oob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ use der::asn1::BitString;

use crmf::controls::CertId;
use spki::AlgorithmIdentifierOwned;
use x509_cert::certificate::{Profile, Rfc5280};

#[cfg(feature = "digest")]
use {
der::{asn1::Null, oid::AssociatedOid},
x509_cert::{certificate::CertificateInner, ext::pkix::name::GeneralName},
};

use crate::header::CmpCertificate;

Expand All @@ -31,7 +38,7 @@ pub type OobCert = CmpCertificate;
/// [RFC 4210 Section 5.2.5]: https://www.rfc-editor.org/rfc/rfc4210#section-5.2.5
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
pub struct OobCertHash {
pub struct OobCertHash<P: Profile = Rfc5280> {
#[asn1(
context_specific = "0",
tag_mode = "EXPLICIT",
Expand All @@ -45,6 +52,30 @@ pub struct OobCertHash {
constructed = "true",
optional = "true"
)]
pub cert_id: Option<CertId>,
pub cert_id: Option<CertId<P>>,
pub hash_val: BitString,
}

#[cfg(feature = "digest")]
impl<P> OobCertHash<P>
where
P: Profile,
{
/// Create an [`OobCertHash`] from a given certificate
pub fn from_certificate<D>(cert: &CertificateInner<P>) -> der::Result<Self>
where
D: digest::Digest + AssociatedOid,
{
Ok(Self {
hash_alg: Some(AlgorithmIdentifierOwned {
oid: D::OID,
parameters: Some(Null.into()),
}),
cert_id: Some(CertId {
issuer: GeneralName::DirectoryName(cert.tbs_certificate().issuer().clone()),
serial_number: cert.tbs_certificate().serial_number().clone(),
}),
hash_val: BitString::from_bytes(&cert.hash::<D>()?)?,
})
}
}
11 changes: 7 additions & 4 deletions crmf/src/controls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use cms::enveloped_data::EnvelopedData;
use spki::{AlgorithmIdentifierOwned, SubjectPublicKeyInfoOwned};
use x509_cert::attr::AttributeTypeAndValue;
use x509_cert::ext::pkix::name::GeneralName;
use x509_cert::serial_number::SerialNumber;
use x509_cert::{
certificate::{Profile, Rfc5280},
serial_number::SerialNumber,
};

/// The `Controls` type is defined in [RFC 4211 Section 6].
///
Expand Down Expand Up @@ -231,7 +234,7 @@ pub type KeyGenParameters = OctetString;
/// ```
///
/// [RFC 4211 Section 6.5]: https://www.rfc-editor.org/rfc/rfc4211#section-6.5
pub type OldCertId = CertId;
pub type OldCertId<P> = CertId<P>;

/// The `CertId` control is defined in [RFC 4211 Section 6.5].
///
Expand All @@ -244,9 +247,9 @@ pub type OldCertId = CertId;
/// [RFC 4211 Section 6.5]: https://www.rfc-editor.org/rfc/rfc4211#section-6.5
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
pub struct CertId {
pub struct CertId<P: Profile = Rfc5280> {
pub issuer: GeneralName,
pub serial_number: SerialNumber,
pub serial_number: SerialNumber<P>,
}

/// The `ProtocolEncrKey` control is defined in [RFC 4211 Section 6.6].
Expand Down
2 changes: 2 additions & 0 deletions x509-cert/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ spki = { version = "0.8.0-rc.0", features = ["alloc"] }

# optional dependencies
arbitrary = { version = "1.4", features = ["derive"], optional = true }
digest = { version = "0.11.0-pre.10", optional = true, default-features = false }
sha1 = { version = "0.11.0-pre.5", optional = true }
signature = { version = "=2.3.0-pre.6", features = ["rand_core"], optional = true }
tls_codec = { version = "0.4.0", default-features = false, features = ["derive"], optional = true }
Expand All @@ -44,6 +45,7 @@ std = ["der/std", "spki/std", "tls_codec?/std"]

arbitrary = ["dep:arbitrary", "std", "der/arbitrary", "spki/arbitrary"]
builder = ["std", "sha1/default", "signature"]
digest = ["dep:digest", "spki/digest"]
hazmat = []
pem = ["der/pem", "spki/pem"]
sct = ["dep:tls_codec"]
Expand Down
25 changes: 25 additions & 0 deletions x509-cert/src/certificate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ use der::{
pem::{self, PemLabel},
};

#[cfg(feature = "digest")]
use {
der::Encode,
digest::{Digest, Output},
spki::DigestWriter,
};

use crate::time::Time;

/// [`Profile`] allows the consumer of this crate to customize the behavior when parsing
Expand Down Expand Up @@ -420,3 +427,21 @@ impl<P: Profile> CertificateInner<P> {
Ok(certs)
}
}

#[cfg(feature = "digest")]
impl<P> CertificateInner<P>
where
P: Profile,
{
/// Return the hash of the DER serialization of this cetificate
pub fn hash<D>(&self) -> der::Result<Output<D>>
where
D: Digest,
{
let mut digest = D::new();

self.encode(&mut DigestWriter(&mut digest))?;

Ok(digest.finalize())
}
}