From 51221b2c48cd04fa6e31099d949f5d7bd564984d Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 2 Oct 2021 21:52:54 +0800 Subject: [PATCH] support legacy PEM headers for certificate and CSR (#6356) --- docs/development/test-vectors.rst | 5 +++ src/rust/src/x509.rs | 8 +++-- tests/x509/test_x509.py | 16 +++++++++ .../x509/cryptography.io.old_header.pem | 33 +++++++++++++++++++ .../x509/requests/ec_sha256_old_header.pem | 10 ++++++ 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 vectors/cryptography_vectors/x509/cryptography.io.old_header.pem create mode 100644 vectors/cryptography_vectors/x509/requests/ec_sha256_old_header.pem diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index d8249926f..2fd3470f3 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -202,6 +202,9 @@ X.509 tree. * ``cryptography.io.pem`` - A leaf certificate issued by RapidSSL for the cryptography website. +* ``cryptography.io.old_header.pem`` - A leaf certificate issued by RapidSSL + for the cryptography website. This certificate uses the ``X509 CERTIFICATE`` + legacy PEM header format. * ``rapidssl_sha256_ca_g3.pem`` - The intermediate CA that issued the ``cryptography.io.pem`` certificate. * ``cryptography.io.precert.pem`` - A pre-certificate with the CT poison @@ -450,6 +453,8 @@ Custom X.509 Request Vectors using 2048 bit RSA and SHA256 generated using OpenSSL. * ``ec_sha256.pem`` and ``ec_sha256.der`` - Contain a certificate request using EC (``secp384r1``) and SHA256 generated using OpenSSL. +* ``ec_sha256_old_header.pem`` - Identical to ``ec_sha256.pem``, but uses + the ``-----BEGIN NEW CERTIFICATE REQUEST-----`` legacy PEM header format. * ``san_rsa_sha1.pem`` and ``san_rsa_sha1.der`` - Contain a certificate request using RSA and SHA1 with a subject alternative name extension generated using OpenSSL. diff --git a/src/rust/src/x509.rs b/src/rust/src/x509.rs index 1cbbce94b..605e12814 100644 --- a/src/rust/src/x509.rs +++ b/src/rust/src/x509.rs @@ -392,7 +392,9 @@ fn cert_version(py: pyo3::Python<'_>, version: u8) -> Result<&pyo3::PyAny, PyAsn #[pyo3::prelude::pyfunction] fn load_pem_x509_certificate(py: pyo3::Python<'_>, data: &[u8]) -> PyAsn1Result { let parsed = pem::parse(data)?; - if parsed.tag != "CERTIFICATE" { + // We support both PEM header strings that OpenSSL does + // https://github.com/openssl/openssl/blob/5e2d22d53ed322a7124e26a4fbd116a8210eb77a/include/openssl/pem.h#L32-L33 + if parsed.tag != "CERTIFICATE" && parsed.tag != "X509 CERTIFICATE" { return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( "Valid PEM but no BEGIN CERTIFICATE/END CERTIFICATE delimiters. Are you sure this is a certificate?" ))); @@ -671,7 +673,9 @@ impl CertificateSigningRequest { #[pyo3::prelude::pyfunction] fn load_pem_x509_csr(py: pyo3::Python<'_>, data: &[u8]) -> PyAsn1Result { let parsed = pem::parse(data)?; - if parsed.tag != "CERTIFICATE REQUEST" { + // We support both PEM header strings that OpenSSL does + // https://github.com/openssl/openssl/blob/5e2d22d53ed322a7124e26a4fbd116a8210eb77a/include/openssl/pem.h#L35-L36 + if parsed.tag != "CERTIFICATE REQUEST" && parsed.tag != "NEW CERTIFICATE REQUEST" { // TODO: The old errors had the following URL: // See https://cryptography.io/en/latest/faq.html#why-can-t-i-import-my-pem-file for more details. return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 4241d1b9d..d872316e4 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -686,6 +686,14 @@ class TestRSACertificate(object): cert.signature_algorithm_oid == SignatureAlgorithmOID.RSA_WITH_SHA1 ) + def test_load_legacy_pem_header(self, backend): + cert = _load_cert( + os.path.join("x509", "cryptography.io.old_header.pem"), + x509.load_pem_x509_certificate, + backend, + ) + assert isinstance(cert, x509.Certificate) + def test_negative_serial_number(self, backend): with pytest.raises(ValueError, match="TbsCertificate::serial"): _load_cert( @@ -1301,6 +1309,14 @@ class TestRSACertificateRequest(object): assert isinstance(extensions, x509.Extensions) assert list(extensions) == [] + def test_load_legacy_pem_header(self, backend): + cert = _load_cert( + os.path.join("x509", "requests", "ec_sha256_old_header.pem"), + x509.load_pem_x509_csr, + backend, + ) + assert isinstance(cert, x509.CertificateSigningRequest) + def test_invalid_pem(self, backend): with pytest.raises(ValueError, match="Unable to load"): x509.load_pem_x509_csr(b"notacsr", backend) diff --git a/vectors/cryptography_vectors/x509/cryptography.io.old_header.pem b/vectors/cryptography_vectors/x509/cryptography.io.old_header.pem new file mode 100644 index 000000000..84470d96b --- /dev/null +++ b/vectors/cryptography_vectors/x509/cryptography.io.old_header.pem @@ -0,0 +1,33 @@ +-----BEGIN X509 CERTIFICATE----- +MIIFvTCCBKWgAwIBAgICPyAwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UEBhMCVVMx +FjAUBgNVBAoTDUdlb1RydXN0IEluYy4xIDAeBgNVBAMTF1JhcGlkU1NMIFNIQTI1 +NiBDQSAtIEczMB4XDTE0MTAxNTEyMDkzMloXDTE4MTExNjAxMTUwM1owgZcxEzAR +BgNVBAsTCkdUNDg3NDI5NjUxMTAvBgNVBAsTKFNlZSB3d3cucmFwaWRzc2wuY29t +L3Jlc291cmNlcy9jcHMgKGMpMTQxLzAtBgNVBAsTJkRvbWFpbiBDb250cm9sIFZh +bGlkYXRlZCAtIFJhcGlkU1NMKFIpMRwwGgYDVQQDExN3d3cuY3J5cHRvZ3JhcGh5 +LmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAom/FebKJIot7Sp3s +itG1sicpe3thCssjI+g1JDAS7I3GLVNmbms1DOdIIqwf01gZkzzXBN2+9sOnyRaR +PPfCe1jTr3dk2y6rPE559vPa1nZQkhlzlhMhlPyjaT+S7g4Tio4qV2sCBZU01DZJ +CaksfohN+5BNVWoJzTbOcrHOEJ+M8B484KlBCiSxqf9cyNQKru4W3bHaCVNVJ8eu +6i6KyhzLa0L7yK3LXwwXVs583C0/vwFhccGWsFODqD/9xHUzsBIshE8HKjdjDi7Y +3BFQzVUQFjBB50NSZfAA/jcdt1blxJouc7z9T8Oklh+V5DDBowgAsrT4b6Z2Fq6/ +r7D1GqivLK/ypUQmxq2WXWAUBb/Q6xHgxASxI4Br+CByIUQJsm8L2jzc7k+mF4hW +ltAIUkbo8fGiVnat0505YJgxWEDKOLc4Gda6d/7GVd5AvKrz242bUqeaWo6e4MTx +diku2Ma3rhdcr044Qvfh9hGyjqNjvhWY/I+VRWgihU7JrYvgwFdJqsQ5eiKT4OHi +gsejvWwkZzDtiQ+aQTrzM1FsY2swJBJsLSX4ofohlVRlIJCn/ME+XErj553431Lu +YQ5SzMd3nXzN78Vj6qzTfMUUY72UoT1/AcFiUMobgIqrrmwuNxfrkbVE2b6Bga74 +FsJX63prvrJ41kuHK/16RQBM7fcCAwEAAaOCAWAwggFcMB8GA1UdIwQYMBaAFMOc +8/zTRgg0u85Gf6B8W/PiCMtZMFcGCCsGAQUFBwEBBEswSTAfBggrBgEFBQcwAYYT +aHR0cDovL2d2LnN5bWNkLmNvbTAmBggrBgEFBQcwAoYaaHR0cDovL2d2LnN5bWNi +LmNvbS9ndi5jcnQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB +BggrBgEFBQcDAjAvBgNVHREEKDAmghN3d3cuY3J5cHRvZ3JhcGh5Lmlvgg9jcnlw +dG9ncmFwaHkuaW8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2d2LnN5bWNiLmNv +bS9ndi5jcmwwDAYDVR0TAQH/BAIwADBFBgNVHSAEPjA8MDoGCmCGSAGG+EUBBzYw +LDAqBggrBgEFBQcCARYeaHR0cHM6Ly93d3cucmFwaWRzc2wuY29tL2xlZ2FsMA0G +CSqGSIb3DQEBCwUAA4IBAQAzIYO2jx7h17FBT74tJ2zbV9OKqGb7QF8y3wUtP4xc +dH80vprI/Cfji8s86kr77aAvAqjDjaVjHn7UzebhSUivvRPmfzRgyWBacomnXTSt +Xlt2dp2nDQuwGyK2vB7dMfKnQAkxwq1sYUXznB8i0IhhCAoXp01QGPKq51YoIlnF +7DRMk6iEaL1SJbkIrLsCQyZFDf0xtfW9DqXugMMLoxeCsBhZJQzNyS2ryirrv9LH +aK3+6IZjrcyy9bkpz/gzJucyhU+75c4My/mnRCrtItRbCQuiI5pd5poDowm+HH9i +GVI9+0lAFwxOUnOnwsoI40iOoxjLMGB+CgFLKCGUcWxP +-----END X509 CERTIFICATE----- diff --git a/vectors/cryptography_vectors/x509/requests/ec_sha256_old_header.pem b/vectors/cryptography_vectors/x509/requests/ec_sha256_old_header.pem new file mode 100644 index 000000000..f9c932180 --- /dev/null +++ b/vectors/cryptography_vectors/x509/requests/ec_sha256_old_header.pem @@ -0,0 +1,10 @@ +-----BEGIN NEW CERTIFICATE REQUEST----- +MIIBTzCB1gIBADBXMRgwFgYDVQQDDA9jcnlwdG9ncmFwaHkuaW8xDTALBgNVBAoM +BFB5Q0ExCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGQXVz +dGluMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3hm1FMCzw66bOY6j4mtegWvc+RAs +rY8S/gL55MkkhySzkpftdYLgTYsypVEDjQkIaAOm0/uRoaEWfsAhWLAO+tOck5ZG +L6zP8P+vcVWBKQnTcmvVn94AHP9LubL1r4y6oAAwCgYIKoZIzj0EAwIDaAAwZQIw +LBqffejBeHMy0jB6iGtHalnxcrmw4lAmLzI4sbRe4RK7brNbD7VqEjuSlushLf/D +AjEAlM9EDJXFKCfVVq5tdlAOMAglXUfCn37ngu11WOUb/XaqRd9tmZ7VxGM0f+I4 +LRdR +-----END NEW CERTIFICATE REQUEST----- -- 2.33.0