Skip to content

Commit 16abda1

Browse files
committed
Support RSA PKCS#1 signatures with absent parameters
RFC4055 says on sha256WithRSAEncryption and company: > When any of these four object identifiers appears within an > AlgorithmIdentifier, the parameters MUST be NULL. Implementations > MUST accept the parameters being absent as well as present. The latter clause is implemented in this commit. The algorithm identifiers live here rather than pki-types, as they _must not_ be used to originate new certificates. Putting them in pki-types would mean they appear in a public API, whereas here they are kept private and restricted to verifying existing signatures.
1 parent 0ac75b1 commit 16abda1

11 files changed

Lines changed: 172 additions & 2 deletions

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ include = [
3434
"src/cert.rs",
3535
"src/crl/mod.rs",
3636
"src/crl/types.rs",
37+
"src/data/",
3738
"src/der.rs",
3839
"src/end_entity.rs",
3940
"src/error.rs",

src/aws_lc_rs_algs.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,66 @@ pub static RSA_PKCS1_2048_8192_SHA512: &dyn SignatureVerificationAlgorithm = &Aw
124124
verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
125125
};
126126

127+
/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits,
128+
/// with illegally absent AlgorithmIdentifier parameters.
129+
///
130+
/// RFC4055 says on sha256WithRSAEncryption and company:
131+
///
132+
/// > When any of these four object identifiers appears within an
133+
/// > AlgorithmIdentifier, the parameters MUST be NULL. Implementations
134+
/// > MUST accept the parameters being absent as well as present.
135+
///
136+
/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA256`] covers
137+
/// the present case.
138+
pub static RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
139+
&AwsLcRsAlgorithm {
140+
public_key_alg_id: alg_id::RSA_ENCRYPTION,
141+
signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
142+
"data/alg-rsa-pkcs1-sha256-absent-params.der"
143+
)),
144+
verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
145+
};
146+
147+
/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits,
148+
/// with illegally absent AlgorithmIdentifier parameters.
149+
///
150+
/// RFC4055 says on sha256WithRSAEncryption and company:
151+
///
152+
/// > When any of these four object identifiers appears within an
153+
/// > AlgorithmIdentifier, the parameters MUST be NULL. Implementations
154+
/// > MUST accept the parameters being absent as well as present.
155+
///
156+
/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA384`] covers
157+
/// the present case.
158+
pub static RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
159+
&AwsLcRsAlgorithm {
160+
public_key_alg_id: alg_id::RSA_ENCRYPTION,
161+
signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
162+
"data/alg-rsa-pkcs1-sha384-absent-params.der"
163+
)),
164+
verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
165+
};
166+
167+
/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits,
168+
/// with illegally absent AlgorithmIdentifier parameters.
169+
///
170+
/// RFC4055 says on sha256WithRSAEncryption and company:
171+
///
172+
/// > When any of these four object identifiers appears within an
173+
/// > AlgorithmIdentifier, the parameters MUST be NULL. Implementations
174+
/// > MUST accept the parameters being absent as well as present.
175+
///
176+
/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA512`] covers
177+
/// the present case.
178+
pub static RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
179+
&AwsLcRsAlgorithm {
180+
public_key_alg_id: alg_id::RSA_ENCRYPTION,
181+
signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
182+
"data/alg-rsa-pkcs1-sha512-absent-params.der"
183+
)),
184+
verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
185+
};
186+
127187
/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 3072-8192 bits.
128188
pub static RSA_PKCS1_3072_8192_SHA384: &dyn SignatureVerificationAlgorithm = &AwsLcRsAlgorithm {
129189
public_key_alg_id: alg_id::RSA_ENCRYPTION,

src/data/alg-rsa-pkcs1-sha256-absent-params.der

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
 *�H��

src/data/alg-rsa-pkcs1-sha384-absent-params.der

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
 *�H��

src/data/alg-rsa-pkcs1-sha512-absent-params.der

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
 *�H��

src/lib.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ pub mod ring {
9797

9898
#[cfg(feature = "alloc")]
9999
pub use super::ring_algs::{
100-
RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_2048_8192_SHA384, RSA_PKCS1_2048_8192_SHA512,
100+
RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS,
101+
RSA_PKCS1_2048_8192_SHA384, RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS,
102+
RSA_PKCS1_2048_8192_SHA512, RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS,
101103
RSA_PKCS1_3072_8192_SHA384, RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
102104
RSA_PSS_2048_8192_SHA384_LEGACY_KEY, RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
103105
};
@@ -109,7 +111,9 @@ pub mod aws_lc_rs {
109111
pub use super::aws_lc_rs_algs::{
110112
ECDSA_P256_SHA256, ECDSA_P256_SHA384, ECDSA_P384_SHA256, ECDSA_P384_SHA384,
111113
ECDSA_P521_SHA256, ECDSA_P521_SHA384, ECDSA_P521_SHA512, ED25519,
112-
RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_2048_8192_SHA384, RSA_PKCS1_2048_8192_SHA512,
114+
RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS,
115+
RSA_PKCS1_2048_8192_SHA384, RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS,
116+
RSA_PKCS1_2048_8192_SHA512, RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS,
113117
RSA_PKCS1_3072_8192_SHA384, RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
114118
RSA_PSS_2048_8192_SHA384_LEGACY_KEY, RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
115119
};
@@ -136,6 +140,12 @@ pub static ALL_VERIFICATION_ALGS: &[&dyn pki_types::SignatureVerificationAlgorit
136140
#[cfg(all(feature = "ring", feature = "alloc"))]
137141
ring::RSA_PKCS1_2048_8192_SHA512,
138142
#[cfg(all(feature = "ring", feature = "alloc"))]
143+
ring::RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS,
144+
#[cfg(all(feature = "ring", feature = "alloc"))]
145+
ring::RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS,
146+
#[cfg(all(feature = "ring", feature = "alloc"))]
147+
ring::RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS,
148+
#[cfg(all(feature = "ring", feature = "alloc"))]
139149
ring::RSA_PKCS1_3072_8192_SHA384,
140150
#[cfg(all(feature = "ring", feature = "alloc"))]
141151
ring::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
@@ -166,6 +176,12 @@ pub static ALL_VERIFICATION_ALGS: &[&dyn pki_types::SignatureVerificationAlgorit
166176
#[cfg(feature = "aws-lc-rs")]
167177
aws_lc_rs::RSA_PKCS1_2048_8192_SHA512,
168178
#[cfg(feature = "aws-lc-rs")]
179+
aws_lc_rs::RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS,
180+
#[cfg(feature = "aws-lc-rs")]
181+
aws_lc_rs::RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS,
182+
#[cfg(feature = "aws-lc-rs")]
183+
aws_lc_rs::RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS,
184+
#[cfg(feature = "aws-lc-rs")]
169185
aws_lc_rs::RSA_PKCS1_3072_8192_SHA384,
170186
#[cfg(feature = "aws-lc-rs")]
171187
aws_lc_rs::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,

src/ring_algs.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,69 @@ pub static RSA_PKCS1_2048_8192_SHA512: &dyn SignatureVerificationAlgorithm = &Ri
9696
verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
9797
};
9898

99+
/// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits,
100+
/// with illegally absent AlgorithmIdentifier parameters.
101+
///
102+
/// RFC4055 says on sha256WithRSAEncryption and company:
103+
///
104+
/// > When any of these four object identifiers appears within an
105+
/// > AlgorithmIdentifier, the parameters MUST be NULL. Implementations
106+
/// > MUST accept the parameters being absent as well as present.
107+
///
108+
/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA256`] covers
109+
/// the present case.
110+
#[cfg(feature = "alloc")]
111+
pub static RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
112+
&RingAlgorithm {
113+
public_key_alg_id: alg_id::RSA_ENCRYPTION,
114+
signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
115+
"data/alg-rsa-pkcs1-sha256-absent-params.der"
116+
)),
117+
verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
118+
};
119+
120+
/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits,
121+
/// with illegally absent AlgorithmIdentifier parameters.
122+
///
123+
/// RFC4055 says on sha256WithRSAEncryption and company:
124+
///
125+
/// > When any of these four object identifiers appears within an
126+
/// > AlgorithmIdentifier, the parameters MUST be NULL. Implementations
127+
/// > MUST accept the parameters being absent as well as present.
128+
///
129+
/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA384`] covers
130+
/// the present case.
131+
#[cfg(feature = "alloc")]
132+
pub static RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
133+
&RingAlgorithm {
134+
public_key_alg_id: alg_id::RSA_ENCRYPTION,
135+
signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
136+
"data/alg-rsa-pkcs1-sha384-absent-params.der"
137+
)),
138+
verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
139+
};
140+
141+
/// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits,
142+
/// with illegally absent AlgorithmIdentifier parameters.
143+
///
144+
/// RFC4055 says on sha256WithRSAEncryption and company:
145+
///
146+
/// > When any of these four object identifiers appears within an
147+
/// > AlgorithmIdentifier, the parameters MUST be NULL. Implementations
148+
/// > MUST accept the parameters being absent as well as present.
149+
///
150+
/// This algorithm covers the absent case, [`RSA_PKCS1_2048_8192_SHA512`] covers
151+
/// the present case.
152+
#[cfg(feature = "alloc")]
153+
pub static RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS: &dyn SignatureVerificationAlgorithm =
154+
&RingAlgorithm {
155+
public_key_alg_id: alg_id::RSA_ENCRYPTION,
156+
signature_alg_id: alg_id::AlgorithmIdentifier::from_slice(include_bytes!(
157+
"data/alg-rsa-pkcs1-sha512-absent-params.der"
158+
)),
159+
verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
160+
};
161+
99162
/// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 3072-8192 bits.
100163
#[cfg(feature = "alloc")]
101164
pub static RSA_PKCS1_3072_8192_SHA384: &dyn SignatureVerificationAlgorithm = &RingAlgorithm {

tests/integration.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,33 @@ fn netflix() {
4848
);
4949
}
5050

51+
/// See also https://github.com/rustls/rustls/issues/2448
52+
#[test]
53+
fn sanofi_rsa_signature_with_absent_algorithm_params() {
54+
let ee: &[u8] = include_bytes!("sanofi/ee.der");
55+
let inter = CertificateDer::from(&include_bytes!("sanofi/inter.der")[..]);
56+
let ca = CertificateDer::from(&include_bytes!("sanofi/ca.der")[..]);
57+
58+
let anchors = [anchor_from_trusted_cert(&ca).unwrap()];
59+
60+
let time = UnixTime::since_unix_epoch(Duration::from_secs(1_746_549_566)); // 2025-05-06T17:39:26Z
61+
62+
let ee = CertificateDer::from(ee);
63+
let cert = webpki::EndEntityCert::try_from(&ee).unwrap();
64+
assert!(
65+
cert.verify_for_usage(
66+
webpki::ALL_VERIFICATION_ALGS,
67+
&anchors,
68+
&[inter],
69+
time,
70+
KeyUsage::server_auth(),
71+
None,
72+
None,
73+
)
74+
.is_ok()
75+
);
76+
}
77+
5178
/* This is notable because it is a popular use of IP address subjectAltNames. */
5279
#[cfg(feature = "alloc")]
5380
#[test]

tests/sanofi/ca.der

1.33 KB
Binary file not shown.

tests/sanofi/ee.der

1.44 KB
Binary file not shown.

0 commit comments

Comments
 (0)