Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose PKCS_RSA_PSS_SHA256 for CSR generation #272

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions rcgen/src/key_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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!");
};
Expand Down
10 changes: 8 additions & 2 deletions rcgen/src/oid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
68 changes: 58 additions & 10 deletions rcgen/src/sign_algo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add the _SHA384 and _SHA512 variants as well for parity with PKCS_RSA_XXX?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// 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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might merit a comment here that's its conventional to use a salt length equal to the size of the hash algorithm's digest (in this case, 32 bytes for the 256 bit digest produced by SHA256).

I don't think this is a requirement with any backing in specification text so it seems overly aggressive for OpenSSL to be rejecting other salt lengths, but I also don't see any reason to avoid doing what seems to be most conventional.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

},
};

/// 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,
},
};

Expand Down
20 changes: 9 additions & 11 deletions rcgen/tests/openssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
2 changes: 2 additions & 0 deletions rcgen/tests/webpki.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading