Skip to content

Commit 48040c8

Browse files
authored
cmpv2: build OobCertHash from a certificate (#1766)
* cmpv2: build `OobCertHash` from a certificate * crmf: make `CertId` not profile specific * x509-cert: provide hash method to certificate
1 parent 5f63cc0 commit 48040c8

6 files changed

Lines changed: 72 additions & 6 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmpv2/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ der = { version = "0.8.0-rc.0", features = ["alloc", "derive", "flagset", "oid"]
2121
spki = { version = "0.8.0-rc.0" }
2222
x509-cert = { version = "=0.3.0-pre.0", default-features = false }
2323

24+
digest = { version = "0.11.0-pre.10", optional = true, default-features = false }
25+
2426
[dev-dependencies]
2527
const-oid = { version = "0.10.0-rc.0", features = ["db"] }
2628
hex-literal = "0.4"
@@ -30,6 +32,7 @@ alloc = ["der/alloc"]
3032
std = ["der/std", "spki/std"]
3133

3234
pem = ["alloc", "der/pem"]
35+
digest = ["dep:digest", "x509-cert/digest"]
3336

3437
[package.metadata.docs.rs]
3538
all-features = true

cmpv2/src/oob.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ use der::asn1::BitString;
55

66
use crmf::controls::CertId;
77
use spki::AlgorithmIdentifierOwned;
8+
use x509_cert::certificate::{Profile, Rfc5280};
9+
10+
#[cfg(feature = "digest")]
11+
use {
12+
der::{asn1::Null, oid::AssociatedOid},
13+
x509_cert::{certificate::CertificateInner, ext::pkix::name::GeneralName},
14+
};
815

916
use crate::header::CmpCertificate;
1017

@@ -31,7 +38,7 @@ pub type OobCert = CmpCertificate;
3138
/// [RFC 4210 Section 5.2.5]: https://www.rfc-editor.org/rfc/rfc4210#section-5.2.5
3239
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
3340
#[allow(missing_docs)]
34-
pub struct OobCertHash {
41+
pub struct OobCertHash<P: Profile = Rfc5280> {
3542
#[asn1(
3643
context_specific = "0",
3744
tag_mode = "EXPLICIT",
@@ -45,6 +52,30 @@ pub struct OobCertHash {
4552
constructed = "true",
4653
optional = "true"
4754
)]
48-
pub cert_id: Option<CertId>,
55+
pub cert_id: Option<CertId<P>>,
4956
pub hash_val: BitString,
5057
}
58+
59+
#[cfg(feature = "digest")]
60+
impl<P> OobCertHash<P>
61+
where
62+
P: Profile,
63+
{
64+
/// Create an [`OobCertHash`] from a given certificate
65+
pub fn from_certificate<D>(cert: &CertificateInner<P>) -> der::Result<Self>
66+
where
67+
D: digest::Digest + AssociatedOid,
68+
{
69+
Ok(Self {
70+
hash_alg: Some(AlgorithmIdentifierOwned {
71+
oid: D::OID,
72+
parameters: Some(Null.into()),
73+
}),
74+
cert_id: Some(CertId {
75+
issuer: GeneralName::DirectoryName(cert.tbs_certificate().issuer().clone()),
76+
serial_number: cert.tbs_certificate().serial_number().clone(),
77+
}),
78+
hash_val: BitString::from_bytes(&cert.hash::<D>()?)?,
79+
})
80+
}
81+
}

crmf/src/controls.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ use cms::enveloped_data::EnvelopedData;
99
use spki::{AlgorithmIdentifierOwned, SubjectPublicKeyInfoOwned};
1010
use x509_cert::attr::AttributeTypeAndValue;
1111
use x509_cert::ext::pkix::name::GeneralName;
12-
use x509_cert::serial_number::SerialNumber;
12+
use x509_cert::{
13+
certificate::{Profile, Rfc5280},
14+
serial_number::SerialNumber,
15+
};
1316

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

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

252255
/// The `ProtocolEncrKey` control is defined in [RFC 4211 Section 6.6].

x509-cert/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ spki = { version = "0.8.0-rc.0", features = ["alloc"] }
2222

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

4546
arbitrary = ["dep:arbitrary", "std", "der/arbitrary", "spki/arbitrary"]
4647
builder = ["std", "sha1/default", "signature"]
48+
digest = ["dep:digest", "spki/digest"]
4749
hazmat = []
4850
pem = ["der/pem", "spki/pem"]
4951
sct = ["dep:tls_codec"]

x509-cert/src/certificate.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ use der::{
1313
pem::{self, PemLabel},
1414
};
1515

16+
#[cfg(feature = "digest")]
17+
use {
18+
der::Encode,
19+
digest::{Digest, Output},
20+
spki::DigestWriter,
21+
};
22+
1623
use crate::time::Time;
1724

1825
/// [`Profile`] allows the consumer of this crate to customize the behavior when parsing
@@ -420,3 +427,21 @@ impl<P: Profile> CertificateInner<P> {
420427
Ok(certs)
421428
}
422429
}
430+
431+
#[cfg(feature = "digest")]
432+
impl<P> CertificateInner<P>
433+
where
434+
P: Profile,
435+
{
436+
/// Return the hash of the DER serialization of this cetificate
437+
pub fn hash<D>(&self) -> der::Result<Output<D>>
438+
where
439+
D: Digest,
440+
{
441+
let mut digest = D::new();
442+
443+
self.encode(&mut DigestWriter(&mut digest))?;
444+
445+
Ok(digest.finalize())
446+
}
447+
}

0 commit comments

Comments
 (0)