diff --git a/rcgen/src/key_pair.rs b/rcgen/src/key_pair.rs index 6f5e7728..d500f524 100644 --- a/rcgen/src/key_pair.rs +++ b/rcgen/src/key_pair.rs @@ -252,6 +252,12 @@ impl KeyPair { } else 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 { #[cfg(feature = "aws_lc_rs")] if alg == &PKCS_ECDSA_P521_SHA512 { @@ -367,6 +373,12 @@ impl KeyPair { } else if alg == &PKCS_RSA_PSS_SHA256 { let rsakp = rsa_key_pair_from(&serialized_der)._err()?; KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256) + } else if alg == &PKCS_RSA_PSS_SHA384 { + let rsakp = rsa_key_pair_from(&serialized_der)._err()?; + KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA384) + } else if alg == &PKCS_RSA_PSS_SHA512 { + let rsakp = rsa_key_pair_from(&serialized_der)._err()?; + KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA512) } else { panic!("Unknown SignatureAlgorithm specified!"); }; diff --git a/rcgen/src/oid.rs b/rcgen/src/oid.rs index a757559c..1d75d7b8 100644 --- a/rcgen/src/oid.rs +++ b/rcgen/src/oid.rs @@ -28,8 +28,14 @@ pub(crate) const EC_SECP_521_R1: &[u64] = &[1, 3, 132, 0, 35]; /// 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]; -/// 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]; +/// id-RSASSA-PSS in [RFC 4055](https://www.rfc-editor.org/rfc/rfc4055#section-6) with sha256WithRSAEncryption +pub(crate) const RSASSA_PSS_SHA256: &[u64] = &[1, 2, 840, 113549, 1, 1, 11]; + +/// id-RSASSA-PSS in [RFC 4055](https://www.rfc-editor.org/rfc/rfc4055#section-6) with sha384WithRSAEncryption +pub(crate) const RSASSA_PSS_SHA384: &[u64] = &[1, 2, 840, 113549, 1, 1, 12]; + +/// id-RSASSA-PSS in [RFC 4055](https://www.rfc-editor.org/rfc/rfc4055#section-6) with sha512WithRSAEncryption +pub(crate) const RSASSA_PSS_SHA512: &[u64] = &[1, 2, 840, 113549, 1, 1, 13]; /// id-ce-keyUsage in [RFC 5280](https://tools.ietf.org/html/rfc5280#appendix-A.2) pub(crate) const KEY_USAGE: &[u64] = &[2, 5, 29, 15]; diff --git a/rcgen/src/sign_algo.rs b/rcgen/src/sign_algo.rs index 5d7052ae..f3632640 100644 --- a/rcgen/src/sign_algo.rs +++ b/rcgen/src/sign_algo.rs @@ -49,6 +49,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 { @@ -88,7 +92,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")] @@ -145,24 +151,66 @@ 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 { + /// + /// Note: `*ring*` does not support this signature algorithm, and so it can not be used with the `crypto` feature + /// of `rcgen` when verifying signatures using the `ring` backend. + 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], + oids_sign_alg: &[&RSASSA_PSS_SHA256], #[cfg(feature = "crypto")] sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA256), - oid_components: RSASSA_PSS, //&[1, 2, 840, 113549, 1, 1, 13], + oid_components: RSASSA_PSS_SHA256, //&[1, 2, 840, 113549, 1, 1, 11], // rSASSA-PSS-SHA256-Params in RFC 4055 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, + // It's conventional to use a salt length equal to the size of the hash algorithm's digest + // (32 bytes for the 256 bit digest produced by SHA256). + 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) + /// + /// Note: `*ring*` does not support this signature algorithm, and so it can not be used with the `crypto` feature + /// of `rcgen` when verifying signatures using the `ring` backend. + 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_SHA384], + #[cfg(feature = "crypto")] + sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA384), + oid_components: RSASSA_PSS_SHA384, //&[1, 2, 840, 113549, 1, 1, 12], + // rSASSA-PSS-SHA384-Params in RFC 4055 + params: SignatureAlgorithmParams::RsaPss { + // id-sha384 in https://datatracker.ietf.org/doc/html/rfc4055#section-2.1 + hash_algorithm: &[2, 16, 840, 1, 101, 3, 4, 2, 2], + // It's conventional to use a salt length equal to the size of the hash algorithm's digest + // (48 bytes for the 384 bit digest produced by SHA384). + 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) + /// + /// Note: `*ring*` does not support this signature algorithm, and so it can not be used with the `crypto` feature + /// of `rcgen` when verifying signatures using the `ring` backend. + 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_SHA512], + #[cfg(feature = "crypto")] + sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA512), + oid_components: RSASSA_PSS_SHA512, //&[1, 2, 840, 113549, 1, 1, 13], + // rSASSA-PSS-SHA512-Params in RFC 4055 + params: SignatureAlgorithmParams::RsaPss { + // id-sha512 in https://datatracker.ietf.org/doc/html/rfc4055#section-2.1 + hash_algorithm: &[2, 16, 840, 1, 101, 3, 4, 2, 3], + // It's conventional to use a salt length equal to the size of the hash algorithm's digest + // (64 bytes for the 512 bit digest produced by SHA512). + salt_length: 64, }, }; diff --git a/rcgen/tests/openssl.rs b/rcgen/tests/openssl.rs index 478f565e..968e11ae 100644 --- a/rcgen/tests/openssl.rs +++ b/rcgen/tests/openssl.rs @@ -288,23 +288,21 @@ fn test_openssl_rsa_combinations_given() { &rcgen::PKCS_RSA_SHA256, &rcgen::PKCS_RSA_SHA384, &rcgen::PKCS_RSA_SHA512, - //&rcgen::PKCS_RSA_PSS_SHA256, + #[cfg(feature = "aws_lc_rs")] + &rcgen::PKCS_RSA_PSS_SHA256, + // #[cfg(feature = "aws_lc_rs")] + // &rcgen::PKCS_RSA_PSS_SHA384, + // #[cfg(feature = "aws_lc_rs")] + // &rcgen::PKCS_RSA_PSS_SHA512, ]; - for (i, alg) in alg_list.iter().enumerate() { + for (_i, alg) in alg_list.iter().enumerate() { let (params, _) = util::default_params(); let key_pair = KeyPair::from_pkcs8_pem_and_sign_algo(util::RSA_TEST_KEY_PAIR_PEM, alg).unwrap(); let cert = params.self_signed(&key_pair).unwrap(); - // Now verify the certificate. - if i >= 4 { - verify_cert(&cert, &key_pair); - verify_csr(&cert, &key_pair); - } else { - // The PSS key types are not fully supported. - // An attempt to use them gives a handshake error. - verify_cert_basic(&cert); - } + verify_cert(&cert, &key_pair); + verify_csr(&cert, &key_pair); } } diff --git a/rcgen/tests/webpki.rs b/rcgen/tests/webpki.rs index 8f076952..7e4a0d75 100644 --- a/rcgen/tests/webpki.rs +++ b/rcgen/tests/webpki.rs @@ -245,6 +245,8 @@ fn test_webpki_rsa_combinations_given() { &signature::RSA_PKCS1_SHA512, ), //(&rcgen::PKCS_RSA_PSS_SHA256, &webpki::RSA_PSS_2048_8192_SHA256_LEGACY_KEY, &signature::RSA_PSS_SHA256), + //(&rcgen::PKCS_RSA_PSS_SHA384, &webpki::RSA_PSS_2048_8192_SHA384_LEGACY_KEY, &signature::RSA_PSS_SHA384), + //(&rcgen::PKCS_RSA_PSS_SHA384, &webpki::RSA_PSS_2048_8192_SHA512_LEGACY_KEY, &signature::RSA_PSS_SHA512), ]; for c in configs { let (params, _) = util::default_params();