From 22d140e6dbb05dcb324d77fccc42861306236b4c Mon Sep 17 00:00:00 2001 From: Mason Date: Thu, 12 Mar 2026 12:52:13 -0500 Subject: [PATCH 1/6] Added support for RSASSA-PSS padding --- rcgen/src/sign_algo.rs | 50 +++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/rcgen/src/sign_algo.rs b/rcgen/src/sign_algo.rs index 9e6916cb..07ccc777 100644 --- a/rcgen/src/sign_algo.rs +++ b/rcgen/src/sign_algo.rs @@ -56,6 +56,10 @@ impl fmt::Debug for SignatureAlgorithm { write!(f, "PKCS_RSA_SHA512") } else if self == &PKCS_RSA_PSS_SHA256 { write!(f, "PKCS_RSA_PSS_SHA256") + } else if self == &PKCS_RSA_PSS_SHA384 { + write!(f, "PKCS_RSA_PSS_SHA384") + } else if self == &PKCS_RSA_PSS_SHA512 { + write!(f, "PKCS_RSA_PSS_SHA512") } else if self == &PKCS_ECDSA_P256_SHA256 { write!(f, "PKCS_ECDSA_P256_SHA256") } else if self == &PKCS_ECDSA_P384_SHA384 { @@ -103,7 +107,9 @@ impl SignatureAlgorithm { &PKCS_RSA_SHA256, &PKCS_RSA_SHA384, &PKCS_RSA_SHA512, - //&PKCS_RSA_PSS_SHA256, + &PKCS_RSA_PSS_SHA256, + &PKCS_RSA_PSS_SHA384, + &PKCS_RSA_PSS_SHA512, &PKCS_ECDSA_P256_SHA256, &PKCS_ECDSA_P384_SHA384, #[cfg(feature = "aws_lc_rs")] @@ -163,13 +169,8 @@ pub(crate) mod algo { params: SignatureAlgorithmParams::Null, }; - // TODO: not really sure whether the certs we generate actually work. - // Both openssl and webpki reject them. It *might* be possible that openssl - // accepts the certificate if the key is a proper RSA-PSS key, but ring doesn't - // support those: https://github.com/briansmith/ring/issues/1353 - // /// RSA signing with PKCS#1 2.1 RSASSA-PSS padding and SHA-256 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) - pub(crate) static PKCS_RSA_PSS_SHA256: SignatureAlgorithm = SignatureAlgorithm { + pub static PKCS_RSA_PSS_SHA256: SignatureAlgorithm = SignatureAlgorithm { // We could also use RSA_ENCRYPTION here, but it's recommended // to use ID-RSASSA-PSS if possible. oids_sign_alg: &[RSASSA_PSS], @@ -180,7 +181,40 @@ pub(crate) mod algo { params: SignatureAlgorithmParams::RsaPss { // id-sha256 in https://datatracker.ietf.org/doc/html/rfc4055#section-2.1 hash_algorithm: &[2, 16, 840, 1, 101, 3, 4, 2, 1], - salt_length: 20, + // Salt length = hash octets (RFC 4055, pg. 9) + salt_length: 32, + }, + }; + + /// RSA signing with PKCS#1 2.1 RSASSA-PSS padding and SHA-384 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) + pub static PKCS_RSA_PSS_SHA384: SignatureAlgorithm = SignatureAlgorithm { + // We could also use RSA_ENCRYPTION here, but it's recommended + // to use ID-RSASSA-PSS if possible. + oids_sign_alg: &[RSASSA_PSS], + #[cfg(feature = "crypto")] + sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA384), + oid_components: RSASSA_PSS, //&[1, 2, 840, 113549, 1, 1, 13], + params: SignatureAlgorithmParams::RsaPss { + // id-sha256 in https://datatracker.ietf.org/doc/html/rfc4055#section-2.1 + hash_algorithm: &[2, 16, 840, 1, 101, 3, 4, 2, 2], + // Salt length = hash octets (RFC 4055, pg. 9) + salt_length: 48, + }, + }; + + /// RSA signing with PKCS#1 2.1 RSASSA-PSS padding and SHA-512 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) + pub static PKCS_RSA_PSS_SHA512: SignatureAlgorithm = SignatureAlgorithm { + // We could also use RSA_ENCRYPTION here, but it's recommended + // to use ID-RSASSA-PSS if possible. + oids_sign_alg: &[RSASSA_PSS], + #[cfg(feature = "crypto")] + sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA512), + oid_components: RSASSA_PSS, //&[1, 2, 840, 113549, 1, 1, 13], + params: SignatureAlgorithmParams::RsaPss { + // id-sha256 in https://datatracker.ietf.org/doc/html/rfc4055#section-2.1 + hash_algorithm: &[2, 16, 840, 1, 101, 3, 4, 2, 3], + // Salt length = hash octets (RFC 4055, pg. 9) + salt_length: 64, }, }; From 2b35c1117f23fb19d23854f1b7f21f175e4cd706 Mon Sep 17 00:00:00 2001 From: Mason Date: Thu, 12 Mar 2026 15:41:56 -0500 Subject: [PATCH 2/6] Fix --- rcgen/src/key_pair.rs | 14 ++++++++++---- rcgen/src/oid.rs | 1 + rcgen/src/sign_algo.rs | 40 +++++++++++++++++++++++++++++----------- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/rcgen/src/key_pair.rs b/rcgen/src/key_pair.rs index 102cd4df..e81066eb 100644 --- a/rcgen/src/key_pair.rs +++ b/rcgen/src/key_pair.rs @@ -259,12 +259,18 @@ impl KeyPair { } else if alg == &PKCS_RSA_SHA512 { let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?; KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512) - } else if alg == &PKCS_RSA_PSS_SHA256 { - let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?; - KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256) } else { #[cfg(feature = "aws_lc_rs")] - if alg == &PKCS_ECDSA_P521_SHA256 { + if alg == &PKCS_RSA_PSS_SHA256 { + let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?; + KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256) + } else if alg == &PKCS_RSA_PSS_SHA384 { + let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?; + KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA384) + } else if alg == &PKCS_RSA_PSS_SHA512 { + let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?; + KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA512) + } else if alg == &PKCS_ECDSA_P521_SHA256 { KeyPairKind::Ec(ecdsa_from_pkcs8( &signature::ECDSA_P521_SHA256_ASN1_SIGNING, &serialized_der, diff --git a/rcgen/src/oid.rs b/rcgen/src/oid.rs index 3b1c0eb9..ee35b257 100644 --- a/rcgen/src/oid.rs +++ b/rcgen/src/oid.rs @@ -35,6 +35,7 @@ pub(crate) const ML_DSA_87: &[u64] = &[2, 16, 840, 1, 101, 3, 4, 3, 19]; /// rsaEncryption in [RFC 4055](https://www.rfc-editor.org/rfc/rfc4055#section-6) pub(crate) const RSA_ENCRYPTION: &[u64] = &[1, 2, 840, 113549, 1, 1, 1]; +#[cfg(feature = "aws_lc_rs")] /// id-RSASSA-PSS in [RFC 4055](https://www.rfc-editor.org/rfc/rfc4055#section-6) pub(crate) const RSASSA_PSS: &[u64] = &[1, 2, 840, 113549, 1, 1, 10]; diff --git a/rcgen/src/sign_algo.rs b/rcgen/src/sign_algo.rs index 07ccc777..6fe3c3a0 100644 --- a/rcgen/src/sign_algo.rs +++ b/rcgen/src/sign_algo.rs @@ -29,6 +29,7 @@ pub(crate) enum SignatureAlgorithmParams { /// Write null parameters Null, /// RSASSA-PSS-params as per RFC 4055 + #[allow(unused)] // RsaPss only used by feature `aws_lc_rs` RsaPss { hash_algorithm: &'static [u64], salt_length: u64, @@ -54,12 +55,6 @@ impl fmt::Debug for SignatureAlgorithm { write!(f, "PKCS_RSA_SHA384") } else if self == &PKCS_RSA_SHA512 { write!(f, "PKCS_RSA_SHA512") - } else if self == &PKCS_RSA_PSS_SHA256 { - write!(f, "PKCS_RSA_PSS_SHA256") - } else if self == &PKCS_RSA_PSS_SHA384 { - write!(f, "PKCS_RSA_PSS_SHA384") - } else if self == &PKCS_RSA_PSS_SHA512 { - write!(f, "PKCS_RSA_PSS_SHA512") } else if self == &PKCS_ECDSA_P256_SHA256 { write!(f, "PKCS_ECDSA_P256_SHA256") } else if self == &PKCS_ECDSA_P384_SHA384 { @@ -67,6 +62,18 @@ impl fmt::Debug for SignatureAlgorithm { } else if self == &PKCS_ED25519 { write!(f, "PKCS_ED25519") } else { + #[cfg(feature = "aws_lc_rs")] + if self == &PKCS_RSA_PSS_SHA256 { + return write!(f, "PKCS_RSA_PSS_SHA256"); + } + #[cfg(feature = "aws_lc_rs")] + if self == &PKCS_RSA_PSS_SHA384 { + return write!(f, "PKCS_RSA_PSS_SHA384"); + } + #[cfg(feature = "aws_lc_rs")] + if self == &PKCS_RSA_PSS_SHA512 { + return write!(f, "PKCS_RSA_PSS_SHA512"); + } #[cfg(feature = "aws_lc_rs")] if self == &PKCS_ECDSA_P521_SHA256 { return write!(f, "PKCS_ECDSA_P521_SHA256"); @@ -87,7 +94,15 @@ impl fmt::Debug for SignatureAlgorithm { impl PartialEq for SignatureAlgorithm { fn eq(&self, other: &Self) -> bool { - (self.oids_sign_alg, self.oid_components) == (other.oids_sign_alg, other.oid_components) + // RSA-PSS algs all have the same OID with different `params` fields + if let SignatureAlgorithmParams::RsaPss{hash_algorithm: selfhash, ..} = self.params { + if let SignatureAlgorithmParams::RsaPss{hash_algorithm: otherhash, ..} = other.params { + return (self.oids_sign_alg, self.oid_components, selfhash) == + (other.oids_sign_alg, other.oid_components, otherhash) + } + } + (self.oids_sign_alg, self.oid_components) == + (other.oids_sign_alg, other.oid_components) } } @@ -107,8 +122,11 @@ impl SignatureAlgorithm { &PKCS_RSA_SHA256, &PKCS_RSA_SHA384, &PKCS_RSA_SHA512, + #[cfg(feature = "aws_lc_rs")] &PKCS_RSA_PSS_SHA256, + #[cfg(feature = "aws_lc_rs")] &PKCS_RSA_PSS_SHA384, + #[cfg(feature = "aws_lc_rs")] &PKCS_RSA_PSS_SHA512, &PKCS_ECDSA_P256_SHA256, &PKCS_ECDSA_P384_SHA384, @@ -169,6 +187,7 @@ pub(crate) mod algo { params: SignatureAlgorithmParams::Null, }; + #[cfg(feature = "aws_lc_rs")] /// RSA signing with PKCS#1 2.1 RSASSA-PSS padding and SHA-256 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) pub static PKCS_RSA_PSS_SHA256: SignatureAlgorithm = SignatureAlgorithm { // We could also use RSA_ENCRYPTION here, but it's recommended @@ -176,6 +195,7 @@ pub(crate) mod algo { oids_sign_alg: &[RSASSA_PSS], #[cfg(feature = "crypto")] sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA256), + // rSASSA-PSS-SHA256-Identifier oid_components: RSASSA_PSS, //&[1, 2, 840, 113549, 1, 1, 13], // rSASSA-PSS-SHA256-Params in RFC 4055 params: SignatureAlgorithmParams::RsaPss { @@ -186,10 +206,9 @@ pub(crate) mod algo { }, }; + #[cfg(feature = "aws_lc_rs")] /// RSA signing with PKCS#1 2.1 RSASSA-PSS padding and SHA-384 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) pub static PKCS_RSA_PSS_SHA384: SignatureAlgorithm = SignatureAlgorithm { - // We could also use RSA_ENCRYPTION here, but it's recommended - // to use ID-RSASSA-PSS if possible. oids_sign_alg: &[RSASSA_PSS], #[cfg(feature = "crypto")] sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA384), @@ -202,10 +221,9 @@ pub(crate) mod algo { }, }; + #[cfg(feature = "aws_lc_rs")] /// RSA signing with PKCS#1 2.1 RSASSA-PSS padding and SHA-512 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) pub static PKCS_RSA_PSS_SHA512: SignatureAlgorithm = SignatureAlgorithm { - // We could also use RSA_ENCRYPTION here, but it's recommended - // to use ID-RSASSA-PSS if possible. oids_sign_alg: &[RSASSA_PSS], #[cfg(feature = "crypto")] sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA512), From 9dbb03ca388808935e6e521722d5bd03f5f30c11 Mon Sep 17 00:00:00 2001 From: Mason Date: Thu, 12 Mar 2026 16:19:40 -0500 Subject: [PATCH 3/6] Formatting --- rcgen/src/sign_algo.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/rcgen/src/sign_algo.rs b/rcgen/src/sign_algo.rs index 6fe3c3a0..103a4dd9 100644 --- a/rcgen/src/sign_algo.rs +++ b/rcgen/src/sign_algo.rs @@ -95,14 +95,20 @@ impl fmt::Debug for SignatureAlgorithm { impl PartialEq for SignatureAlgorithm { fn eq(&self, other: &Self) -> bool { // RSA-PSS algs all have the same OID with different `params` fields - if let SignatureAlgorithmParams::RsaPss{hash_algorithm: selfhash, ..} = self.params { - if let SignatureAlgorithmParams::RsaPss{hash_algorithm: otherhash, ..} = other.params { - return (self.oids_sign_alg, self.oid_components, selfhash) == - (other.oids_sign_alg, other.oid_components, otherhash) - } + if let SignatureAlgorithmParams::RsaPss { + hash_algorithm: selfhash, + .. + } = self.params + { + if let SignatureAlgorithmParams::RsaPss { + hash_algorithm: otherhash, + .. + } = other.params + { + return (self.oids_sign_alg, self.oid_components, selfhash) + == (other.oids_sign_alg, other.oid_components, otherhash); } - (self.oids_sign_alg, self.oid_components) == - (other.oids_sign_alg, other.oid_components) + (self.oids_sign_alg, self.oid_components) == (other.oids_sign_alg, other.oid_components) } } From 5715f7d47f671434dc4b12c4688ee6e4d09fcf27 Mon Sep 17 00:00:00 2001 From: Mason Date: Thu, 12 Mar 2026 16:23:31 -0500 Subject: [PATCH 4/6] Formatting 2 --- rcgen/src/sign_algo.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rcgen/src/sign_algo.rs b/rcgen/src/sign_algo.rs index 103a4dd9..e4582e88 100644 --- a/rcgen/src/sign_algo.rs +++ b/rcgen/src/sign_algo.rs @@ -107,6 +107,7 @@ impl PartialEq for SignatureAlgorithm { { return (self.oids_sign_alg, self.oid_components, selfhash) == (other.oids_sign_alg, other.oid_components, otherhash); + } } (self.oids_sign_alg, self.oid_components) == (other.oids_sign_alg, other.oid_components) } From 1ea1fce999aed1d83db867b438789bbc1df9d74e Mon Sep 17 00:00:00 2001 From: Mason Date: Fri, 13 Mar 2026 15:19:26 -0500 Subject: [PATCH 5/6] OpenSSL tests --- verify-tests/tests/openssl.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/verify-tests/tests/openssl.rs b/verify-tests/tests/openssl.rs index a99cad49..975cf86e 100644 --- a/verify-tests/tests/openssl.rs +++ b/verify-tests/tests/openssl.rs @@ -187,6 +187,39 @@ fn test_request() { verify_csr(¶ms, &key_pair); } +#[test] +fn test_openssl_rsa_pss_sha256() { + let (params, _) = util::default_params(); + let key_pair = KeyPair::generate_for(&rcgen::PKCS_RSA_PSS_SHA256).unwrap(); + let cert = params.self_signed(&key_pair).unwrap(); + + // Now verify the certificate. + verify_cert(&cert, &key_pair); + verify_csr(¶ms, &key_pair); +} + +#[test] +fn test_openssl_rsa_pss_sha384() { + let (params, _) = util::default_params(); + let key_pair = KeyPair::generate_for(&rcgen::PKCS_RSA_PSS_SHA384).unwrap(); + let cert = params.self_signed(&key_pair).unwrap(); + + // Now verify the certificate. + verify_cert(&cert, &key_pair); + verify_csr(¶ms, &key_pair); +} + +#[test] +fn test_openssl_rsa_pss_sha512() { + let (params, _) = util::default_params(); + let key_pair = KeyPair::generate_for(&rcgen::PKCS_RSA_PSS_SHA512).unwrap(); + let cert = params.self_signed(&key_pair).unwrap(); + + // Now verify the certificate. + verify_cert(&cert, &key_pair); + verify_csr(¶ms, &key_pair); +} + #[test] fn test_openssl_256() { let (params, _) = util::default_params(); From fdf0b04532449aeabc1901e4c7b9398afb3fe252 Mon Sep 17 00:00:00 2001 From: Mason Date: Fri, 13 Mar 2026 15:30:24 -0500 Subject: [PATCH 6/6] Feature-gated tests --- verify-tests/tests/openssl.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/verify-tests/tests/openssl.rs b/verify-tests/tests/openssl.rs index 975cf86e..1f030d52 100644 --- a/verify-tests/tests/openssl.rs +++ b/verify-tests/tests/openssl.rs @@ -187,6 +187,7 @@ fn test_request() { verify_csr(¶ms, &key_pair); } +#[cfg(feature = "aws_lc_rs")] #[test] fn test_openssl_rsa_pss_sha256() { let (params, _) = util::default_params(); @@ -198,6 +199,7 @@ fn test_openssl_rsa_pss_sha256() { verify_csr(¶ms, &key_pair); } +#[cfg(feature = "aws_lc_rs")] #[test] fn test_openssl_rsa_pss_sha384() { let (params, _) = util::default_params(); @@ -209,6 +211,7 @@ fn test_openssl_rsa_pss_sha384() { verify_csr(¶ms, &key_pair); } +#[cfg(feature = "aws_lc_rs")] #[test] fn test_openssl_rsa_pss_sha512() { let (params, _) = util::default_params();