hashicorp / vault

A tool for secrets management, encryption as a service, and privileged access management
https://www.vaultproject.io/
Other
30.05k stars 4.12k forks source link

PKI sign certificate with CSR gives "asn1: syntax error: sequence truncated" error #17918

Closed nlang closed 1 year ago

nlang commented 1 year ago

Describe the bug wIth a default configured PKI backend and generated CA, when trying to issue a certificate using a csr, vault produces the following error:

Request:
POST http://127.0.0.1:8200/v1/pki/sign/testrole
{
  "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIICwjCCAaoCAQAwfzELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEcMBoG\nA1UEBxMTTGF1ZiBhbiBkZXIgUGVnbml0ejEMMAoGA1UEChMDQUJMMRIwEAYDVQQL\nEwlDaGFyZ2Vib3gxHzAdBgNVBAMTFkNoYXJnZWJveCA4MDg4MjkxODYwNzMwggEi\nMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCanYTg5/A0ipDCjVQfBZxzjf2A\nM7Y6mtMA5xIHjJ3kI1a9uJ411FqLiXZjkHLVd9TOXOQQzzqUpjUPJqTVFlyBIhQK\n/8QAe3Eenz7pwgHVp6A/WMw7DAzTdQfSRLbPRoQkCDLxkesyXbkwXBB/J7Za5Kap\ngsFf/JxjZB9JyopiI9AvcM/N6fRbthSFpw+UQpANGjiM/MIHmVib570OTQnk46GY\nbvXt32tIkd1LthU++6EklxmowhyWOHfDXPWCl+qU7JpA+Y2WhYmtEbYbYwLqtERS\nJHmMWLK9y5APyCmomgVsyfWL6vZmEv1HUGH05ApH4HLJW8vIsOaDlv83qlanAgMB\nAAEwDQYJKoZIhvcNAQELBQADggEBADO64C03d/QlezT8XjhK3JwUHWKOB3YAhSvM\nCjs+a69G5l2IuT1Ni5jw36sXWWA0ZbQSwZO4wlIgOf62Uj/61pEfiTiX1fUiax5Y\nnVPe+wir9WU9QzWcTU7DM7W9mCpXVTzWeZl2OUQkEAgejCWJdSNXwEWuV8sqRqNI\nH6blkMyHZT38pzXB3KYNZ7l5XuNZ+SN72a9kTWRX6ePsTpTvOLv8bYqxe0PgQzVN\nyjUqV7dXPUCsyqqbkkwPZmKJOCyzthSrGK8+3j8ASVIE4ftkeaU3xglDwrx7ImZo\neG4KAfODvgVkg+6gqCmAdB75DXgXAkbeSxRxLZ3Ez8hIrkP64H0=\n-----END CERTIFICATE REQUEST-----"
}

Response:
400 Bad Request
{
    "errors": [
        "certificate request could not be parsed: asn1: syntax error: sequence truncated"
    ]
}

To Reproduce Steps to reproduce the behavior:

  1. Enable PKI, configure CA with default settings
  2. Create a role with the following settings:
    vault write pki/roles/testrole \
    allow_any_name=true \
    allow_localhost=false \
    allow_bare_domains=false \
    allow_subdomains=false \
    enforce_hostnames=false \
    allow_glob_domains=false \
    key_type="rsa" \
    require_cn=true \
    use_csr_common_name=true 
  3. Sign a certificate

Expected behavior A new certificate to be issued

Environment:

Vault server configuration file(s):

{
  "listener": [{
    "tcp": {
      "address": "0.0.0.0:8200",
      "tls_disable": 1
    }
  }],
  "storage": {
    "mysql": {
      "address": "172.17.0.2",
      "username": "",
      "password": "",
      "database": "VAULT_STORAGE",
      "table": "vault",
      "plaintext_connection_allowed": true
    }
  },
  "api_addr": "http://127.0.0.1:8200",
  "ui": true
}

Additional context The error does not occur with every CSR. But the CSR with which the error occurs is completely fine and can be used with openssl x509 -req ... command to get a certifcate without errors when using the same CA that vault uses.

Unfortunately, the error does not help to figure out what is really going on. As the CSR can be used with openssl to issue a certificate I consider this a bug. If nevertheless this is not considered a bug, any help would be greatly appreciated to resolve the issue.

cipherboy commented 1 year ago

Hi @nlang

Your CSR is malformed...

If you look at your ASN.1:

image

The outer SEQUENCE has the right number of elements, but the first inner SEQUENCE has 3 elements, but needs 4:

image

This follows here: https://www.rfc-editor.org/rfc/rfc2986#section-4.1 -- notice how there's 4 elements in the CertificationRequestInfo element, none of which are marked optional.

P.S. https://lapo.it/asn1js/ is a useful site for debugging ASN.1 blobs -- I find it is more clear than openssl asn1parse, which works offline but lacks the helpful highlighting in the hexdump &c.

nlang commented 1 year ago

Thanks @cipherboy, we'll have to take a look on our CSR generation then.

cipherboy commented 1 year ago

Yeah, I'm rather curious to hear how this CSR was generated :-)

Unless you're doing manual construction somehow, most ecosystems I know of (OpenSSL, NSS, Golang, and perhaps BouncyCastle) will generate CSRs correctly... I think the exception to the latter ecosystem (JSS, BouncyCastle, JDK) is if you're using the raw ASN construction directly, versus a higher-level interface over CSR. I suppose that holds for Golang or OpenSSL as well... But 90% of people probably just use openssl req ...

nlang commented 1 year ago

The CSR is generated on a embedded device with limited resources. I had a chat with the developers, and as far as I understood they construct the CSR themselves because BouncyCastle would not fit on the device and they have no tools for it in their Java Version which apparently is 1.7.

cipherboy commented 1 year ago

Does sun.security.pkcs.PKCS10 work on this embedded device? My Java is admittedly rusty (I think JDK7 exposes everything but maybe JDK9+ put it into a module and hid it).

But that is interesting, note the javadoc:

 * The ASN.1 syntax for a Certification Request is:
 * <pre>
 * CertificationRequest ::= SEQUENCE {
 *    certificationRequestInfo CertificationRequestInfo,
 *    signatureAlgorithm       SignatureAlgorithmIdentifier,
 *    signature                Signature
 *  }
 *
 * SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
 * Signature ::= BIT STRING
 *
 * CertificationRequestInfo ::= SEQUENCE {
 *    version                 Version,
 *    subject                 Name,
 *    subjectPublicKeyInfo    SubjectPublicKeyInfo,
 *    attributes [0] IMPLICIT Attributes
 * }
 * Attributes ::= SET OF Attribute
 * </pre>

Here, in the JDK it mentions that the attribute is IMPLICIT, but RFC 2986 doesn't make it IMPLICIT... (PKCS10 Version 1.7)...

It looks like the older RFC 2314 PKCS10 version 1.5 makes it IMPLICIT. This is likely why OpenSSL parses it.

I'll try filing a Go issue about this -- may I use your CSR above, or would you prefer to provide another CSR with just a example.com CN?

(Our CSR parser is from Go's crypto/x509).

nlang commented 1 year ago

Hi @cipherboy, thanks for the input. I forwarded it to the developers. Of course you can use the CSR for filing the issue. By the way, we also use "node-forge" (a native javascript crypto lib) and it also parses the CSR without complaining. Thanks for your support!

cipherboy commented 1 year ago

@nlang Aha, I reviewed my ASN.1 terminology in preparing to file the Go issue: IMPLICIT doesn't mean OPTIONAL, but instead has to do with the type tagging (taking the value [0]) on the CertificationRequestInfo's SEQUENCE member. See e.g., 2.3 Implicitly and explicitly tagged types of https://luca.ntop.org/Teaching/Appunti/asn1.html.

I believe, if you're getting a CSR without this attribute, its just poorly constructed, unless you've got an even earlier reference to PKCS10 prior to RFC 2314 where it is both IMPLICIT and OPTIONAL.

I'll still file this as a Go issue, but while OpenSSL and node-forge parse it, I'm less optimistic (about Go accepting this for fix).