Skip to content

Commit

Permalink
Add KeyUsagePurpose support to CSR from DER; add CSR test
Browse files Browse the repository at this point in the history
  • Loading branch information
lvkv authored and djc committed Aug 23, 2024
1 parent 40974f1 commit 964f9c6
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
7 changes: 7 additions & 0 deletions rcgen/src/csr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ impl CertificateSigningRequestParams {
/// [`rustls_pemfile::csr()`]: https://docs.rs/rustls-pemfile/latest/rustls_pemfile/fn.csr.html
#[cfg(feature = "x509-parser")]
pub fn from_der(csr: &CertificateSigningRequestDer<'_>) -> Result<Self, Error> {
use crate::KeyUsagePurpose;
use x509_parser::prelude::FromDer;

let csr = x509_parser::certification_request::X509CertificationRequest::from_der(csr)
.map_err(|_| Error::CouldNotParseCertificationRequest)?
.1;
Expand All @@ -117,6 +119,11 @@ impl CertificateSigningRequestParams {
if let Some(extensions) = csr.requested_extensions() {
for ext in extensions {
match ext {
x509_parser::extensions::ParsedExtension::KeyUsage(key_usage) => {
// This x509 parser stores flags in reversed bit BIT STRING order
params.key_usages =
KeyUsagePurpose::from_u16(key_usage.flags.reverse_bits());
},
x509_parser::extensions::ParsedExtension::SubjectAlternativeName(san) => {
for name in &san.general_names {
params
Expand Down
30 changes: 29 additions & 1 deletion rcgen/tests/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ mod test_parse_other_name_alt_name {

#[cfg(feature = "x509-parser")]
mod test_csr {
use rcgen::{CertificateParams, CertificateSigningRequestParams, KeyPair};
use rcgen::{CertificateParams, CertificateSigningRequestParams, KeyPair, KeyUsagePurpose};

#[test]
fn test_csr_roundtrip() {
Expand All @@ -375,4 +375,32 @@ mod test_csr {
// Ensure algorithms match.
assert_eq!(key_pair.algorithm(), csrp.public_key.algorithm());
}

#[test]
fn test_nontrivial_csr_roundtrip() {
let key_pair = KeyPair::generate().unwrap();

// We should be able to serialize a CSR, and then parse the CSR.
let mut params = CertificateParams::default();
params.key_usages = vec![
KeyUsagePurpose::DigitalSignature,
KeyUsagePurpose::ContentCommitment,
KeyUsagePurpose::KeyEncipherment,
KeyUsagePurpose::DataEncipherment,
KeyUsagePurpose::KeyAgreement,
KeyUsagePurpose::KeyCertSign,
KeyUsagePurpose::CrlSign,
// It doesn't make sense to have both encipher and decipher only
// So we'll take this opportunity to test omitting a key usage
// KeyUsagePurpose::EncipherOnly,
KeyUsagePurpose::DecipherOnly,
];
let csr = params.serialize_request(&key_pair).unwrap();
let csrp = CertificateSigningRequestParams::from_der(csr.der()).unwrap();

// Ensure algorithms match.
assert_eq!(key_pair.algorithm(), csrp.public_key.algorithm());
// Ensure key usages match.
assert_eq!(csrp.params.key_usages, params.key_usages);
}
}

0 comments on commit 964f9c6

Please sign in to comment.