Skip to content

Commit 345ac96

Browse files
authored
x509-cert: don't bind builder with signer early (#1161)
* x509-cert: don't bind builder with signer early This is mostly a draft after discussion in #1160 Signed-off-by: Arthur Gautier <baloo@superbaloo.net> * cms: pull builder changes Signed-off-by: Arthur Gautier <baloo@superbaloo.net> --------- Signed-off-by: Arthur Gautier <baloo@superbaloo.net>
1 parent c410c4b commit 345ac96

File tree

4 files changed

+177
-143
lines changed

4 files changed

+177
-143
lines changed

cms/src/builder.rs

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ use rsa::Pkcs1v15Encrypt;
3535
use sha2::digest;
3636
use signature::digest::DynDigest;
3737
use signature::{Keypair, Signer};
38-
use spki::{AlgorithmIdentifierOwned, DynSignatureAlgorithmIdentifier, SignatureBitStringEncoding};
38+
use spki::{
39+
AlgorithmIdentifierOwned, DynSignatureAlgorithmIdentifier, EncodePublicKey,
40+
SignatureBitStringEncoding,
41+
};
3942
use std::time::SystemTime;
4043
use std::vec;
4144
use x509_cert::attr::{Attribute, AttributeValue, Attributes};
42-
use x509_cert::builder::Builder;
45+
use x509_cert::builder::{self, Builder};
4346
use zeroize::Zeroize;
4447

4548
/// Error type
@@ -96,8 +99,7 @@ type Result<T> = core::result::Result<T, Error>;
9699
/// - calculate the signature
97100
/// - set the signing time attribute
98101
/// - create a `SignerInfo` object
99-
pub struct SignerInfoBuilder<'s, S> {
100-
signer: &'s S,
102+
pub struct SignerInfoBuilder<'s> {
101103
sid: SignerIdentifier,
102104
digest_algorithm: AlgorithmIdentifierOwned,
103105
signed_attributes: Option<Vec<Attribute>>,
@@ -106,24 +108,19 @@ pub struct SignerInfoBuilder<'s, S> {
106108
external_message_digest: Option<&'s [u8]>,
107109
}
108110

109-
impl<'s, S> SignerInfoBuilder<'s, S>
110-
where
111-
S: Keypair + DynSignatureAlgorithmIdentifier,
112-
{
111+
impl<'s> SignerInfoBuilder<'s> {
113112
/// Create a new `SignerInfoBuilder`. This is used for adding `SignerInfo`s to `SignedData`
114113
/// structures.
115114
/// The content to be signed can be stored externally. In this case `eContent` in
116115
/// `encapsulated_content_info` must be `None` and the message digest must be passed with
117116
/// `external_message_digest`. `digest_algorithm` must match the used digest algorithm.
118117
pub fn new(
119-
signer: &'s S,
120118
sid: SignerIdentifier,
121119
digest_algorithm: AlgorithmIdentifierOwned,
122120
encapsulated_content_info: &'s EncapsulatedContentInfo,
123121
external_message_digest: Option<&'s [u8]>,
124122
) -> Result<Self> {
125123
Ok(SignerInfoBuilder {
126-
signer,
127124
sid,
128125
digest_algorithm,
129126
signed_attributes: None,
@@ -167,28 +164,24 @@ where
167164
}
168165
}
169166

170-
impl<'s, S> Builder for SignerInfoBuilder<'s, S>
171-
where
172-
S: Keypair + DynSignatureAlgorithmIdentifier,
173-
{
174-
type Signer = S;
167+
impl<'s> Builder for SignerInfoBuilder<'s> {
175168
type Output = SignerInfo;
176169

177-
fn signer(&self) -> &Self::Signer {
178-
self.signer
179-
}
180-
181170
/// Calculate the data to be signed
182171
/// [RFC 5652 § 5.4](https://datatracker.ietf.org/doc/html/rfc5652#section-5.4)
183172
/// If an `external_message_digest` is passed in, it is assumed, that we are signing external
184173
/// content (see RFC 5652 § 5.2). In this case, the `eContent` in `EncapsulatedContentInfo`
185174
/// must be `None`.
186-
fn finalize(&mut self) -> der::Result<Vec<u8>> {
175+
fn finalize<S>(&mut self, _signer: &S) -> builder::Result<Vec<u8>>
176+
where
177+
S: Keypair + DynSignatureAlgorithmIdentifier,
178+
S::VerifyingKey: EncodePublicKey,
179+
{
187180
let message_digest = match self.external_message_digest {
188181
Some(external_content_digest) => {
189182
if self.encapsulated_content_info.econtent.is_some() {
190183
// Encapsulated content must be empty, if external digest is given.
191-
return Err(der::Error::from(ErrorKind::Failed));
184+
return Err(der::Error::from(ErrorKind::Failed).into());
192185
}
193186
Some(external_content_digest.to_vec())
194187
}
@@ -201,7 +194,7 @@ where
201194
Some(content) => {
202195
let mut hasher = get_hasher(&self.digest_algorithm).ok_or_else(|| {
203196
// Unsupported hash algorithm: {}, &self.digest_algorithm.oid.to_string()
204-
der::Error::from(ErrorKind::Failed)
197+
x509_cert::builder::Error::from(der::Error::from(ErrorKind::Failed))
205198
})?;
206199
// Only the octets comprising the value of the eContent
207200
// OCTET STRING are input to the message digest algorithm, not the tag
@@ -245,7 +238,7 @@ where
245238
// Check against `eContentType`
246239
if signed_attributes_content_type.oid != econtent_type {
247240
// Mismatch between content types: encapsulated content info <-> signed attributes.
248-
return Err(der::Error::from(ErrorKind::Failed));
241+
return Err(der::Error::from(ErrorKind::Failed).into());
249242
}
250243
} else {
251244
signed_attributes.push(
@@ -264,10 +257,11 @@ where
264257
Ok(signed_attributes_der)
265258
}
266259

267-
fn assemble(
268-
self,
269-
signature: BitString,
270-
) -> core::result::Result<Self::Output, x509_cert::builder::Error> {
260+
fn assemble<S>(self, signature: BitString, signer: &S) -> builder::Result<Self::Output>
261+
where
262+
S: Keypair + DynSignatureAlgorithmIdentifier,
263+
S::VerifyingKey: EncodePublicKey,
264+
{
271265
let signed_attrs = self.signed_attributes.as_ref().map(|signed_attributes| {
272266
SignedAttributes::try_from(signed_attributes.to_owned()).unwrap()
273267
});
@@ -281,7 +275,7 @@ where
281275
let signature_value =
282276
SignatureValue::new(signature.raw_bytes()).map_err(x509_cert::builder::Error::from)?;
283277

284-
let signature_algorithm = self.signer.signature_algorithm_identifier()?;
278+
let signature_algorithm = signer.signature_algorithm_identifier()?;
285279

286280
Ok(SignerInfo {
287281
version: self.version(),
@@ -379,15 +373,17 @@ impl<'s> SignedDataBuilder<'s> {
379373
/// must not be changed after the first signer info was added.
380374
pub fn add_signer_info<S, Signature>(
381375
&mut self,
382-
signer_info_builder: SignerInfoBuilder<'_, S>,
376+
signer_info_builder: SignerInfoBuilder<'_>,
377+
signer: &S,
383378
) -> Result<&mut Self>
384379
where
385380
S: Keypair + DynSignatureAlgorithmIdentifier,
386381
S: Signer<Signature>,
382+
S::VerifyingKey: EncodePublicKey,
387383
Signature: SignatureBitStringEncoding,
388384
{
389385
let signer_info = signer_info_builder
390-
.build::<Signature>()
386+
.build::<S, Signature>(signer)
391387
.map_err(|_| der::Error::from(ErrorKind::Failed))?;
392388
self.signer_infos.push(signer_info);
393389

cms/tests/builder.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ fn test_build_signed_data() {
104104
};
105105
let external_message_digest = None;
106106
let signer_info_builder_1 = SignerInfoBuilder::new(
107-
&signer,
108107
signer_identifier(1),
109108
digest_algorithm.clone(),
110109
&content,
@@ -119,7 +118,6 @@ fn test_build_signed_data() {
119118
};
120119
let external_message_digest_2 = None;
121120
let signer_info_builder_2 = SignerInfoBuilder::new(
122-
&signer_2,
123121
signer_identifier(1),
124122
digest_algorithm_2.clone(),
125123
&content,
@@ -137,10 +135,14 @@ fn test_build_signed_data() {
137135
.expect("could not add a digest algorithm")
138136
.add_certificate(CertificateChoices::Certificate(certificate))
139137
.expect("error adding certificate")
140-
.add_signer_info::<SigningKey<Sha256>, rsa::pkcs1v15::Signature>(signer_info_builder_1)
138+
.add_signer_info::<SigningKey<Sha256>, rsa::pkcs1v15::Signature>(
139+
signer_info_builder_1,
140+
&signer,
141+
)
141142
.expect("error adding RSA signer info")
142143
.add_signer_info::<ecdsa::SigningKey<NistP256>, p256::ecdsa::DerSignature>(
143144
signer_info_builder_2,
145+
&signer_2,
144146
)
145147
.expect("error adding P256 signer info")
146148
.build()
@@ -324,7 +326,6 @@ fn test_build_pkcs7_scep_pkcsreq() {
324326
parameters: None,
325327
};
326328
let mut signer_info_builder = SignerInfoBuilder::new(
327-
&signer,
328329
signer_identifier(1),
329330
digest_algorithm.clone(),
330331
&content,
@@ -380,7 +381,10 @@ fn test_build_pkcs7_scep_pkcsreq() {
380381
.unwrap()
381382
.add_certificate(CertificateChoices::Certificate(certificate))
382383
.unwrap()
383-
.add_signer_info::<SigningKey<Sha256>, rsa::pkcs1v15::Signature>(signer_info_builder)
384+
.add_signer_info::<SigningKey<Sha256>, rsa::pkcs1v15::Signature>(
385+
signer_info_builder,
386+
&signer,
387+
)
384388
.unwrap()
385389
.build()
386390
.unwrap();

0 commit comments

Comments
 (0)