#223 Certmonger creates CSRs with invalid DER syntax for X509v3 extensions with critical=FALSE
Closed: fixed 7 months ago by rcritten. Opened 7 months ago by cheimes.

Certmonger's template for X509v3 extensions is wrong and generate invalid DER for extensions with critical=FALSE. Since FALSE is the default value, a standard conform CSR or cert must not encode the critical flag.

$ openssl asn1parse -inform PEM -in freeipa.csr
...
  421:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Alternative Name
  426:d=7  hl=2 l=   1 prim: BOOLEAN           :0
  429:d=7  hl=3 l= 135 prim: OCTET STRING      [HEX DUMP]:...

The line BOOLEAN 0 should not be present.

/* RFC 5280, 4.1 */
const SEC_ASN1Template
cm_certext_cert_extension_template[] = {
        {
        .kind = SEC_ASN1_SEQUENCE,
        .offset = 0,
        .sub = NULL,
        .size = sizeof(CERTCertExtension),
        },
        {
        .kind = SEC_ASN1_OBJECT_ID,
        .offset = offsetof(CERTCertExtension, id),
        .sub = NULL,
        .size = sizeof(SECItem),
        },
        {
        .kind = SEC_ASN1_BOOLEAN,
        .offset = offsetof(CERTCertExtension, critical),
        .sub = NULL,
        .size = sizeof(SECItem),
        },
        {
        .kind = SEC_ASN1_OCTET_STRING,
        .offset = offsetof(CERTCertExtension, value),
        .sub = NULL,
        .size = sizeof(SECItem),
        },
        {0, 0, NULL, 0},
};

The correct kind for the critical extension is SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN.


You can't encode values that match the default?

It's probably a one-liner I just don't understand the reasoning for the strictness.

According to ITU X.690 standard 202102:

11 Restrictions on BER employed by both CER and DER

11.5 Set and sequence components with default value

The encoding of a set value or sequence value shall not include an encoding for any component value which is equal to its default value.

Python asn1crypto doesn't load the invalid request either:

>>> csr = b"MIIDqzCCApMCAQAwLzERMA8GA1UEChMISVBBLlRFU1QxGjAYBgNVBAMTEXJlcGxpY2ExLmlwYS50ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5TzQZpKgWu4v4LmX44xRCgA2DcvY4D7Lw/Zyr3uch54gvAUWi2oi/PYVixJQNVHfZIckgrPRO+gtMaFsXuIHgWHjy2TdFNOV5Uav3W07fl28nngmAWd8Sq4W+i7vnBMp62sztE0nomTUe/52D+V3pggCzqVlvFvAg8IqxyavDQ974I13V2SuvJVJ7EnlaCnNZPRXL1ICnszKfIhoLWH8cbBaxHCjZkHEInu87qb9OHNpevrz5OJMX2HG14Ic15I52l0YVTBQQr1AQFGDNpSqt+NeoCSiY9F7nhEXdkgvhk3rMV2nk2XJut9YIsEJYo4SK0pBTxdSUYHsyZqrP/cdFwIDAQABoIIBNTAlBgkqhkiG9w0BCRQxGB4WAFMAZQByAHYAZQByAC0AQwBlAHIAdDCCAQoGCSqGSIb3DQEJDjGB/DCB+TCBkgYDVR0RAQEABIGHMIGEghFyZXBsaWNhMS5pcGEudGVzdKAvBgorBgEEAYI3FAIDoCEMH2xkYXAvcmVwbGljYTEuaXBhLnRlc3RASVBBLlRFU1SgPgYGKwYBBQICoDQwMqAKGwhJUEEuVEVTVKEkMCKgAwIBAaEbMBkbBGxkYXAbEXJlcGxpY2ExLmlwYS50ZXN0MAwGA1UdEwEB/wQCMAAwIAYDVR0OAQEABBYEFPtLvk2RcgKwKfIo0Cp8Pvp7Xu3wMDIGCSsGAQQBgjcUAgEBAAQiHiAAYwBhAEkAUABBAHMAZQByAHYAaQBjAGUAQwBlAHIAdDANBgkqhkiG9w0BAQsFAAOCAQEA1jEX9uXSAvDjP6ZRxT5Wo2DWy4yqJx5+tO21jrpRgCKuowUhwyzEFiA/WDQ/vy9XGqvcRaRpkdbwrcmefvUCgprOBeNjR1F2aKTHngaH4WbWd4BI0lR0Z1WZuvL2fRGDvOCQAGNVyGvtxV+15olWq7386fEe3PAHF9osXpcH97KifL1+eG2Vkaqo4yylUGme/Rin4vGzxkjGYE+O/ugxtgil5VPs0nrJx0bFWaMLK9yErv9O1V3JSKoLn+yAKxrYQuMBl1nqpAj9P4NWdFsGl3Ubpn4vwitwaq9pkEu0K1Z+CP5FXOyFsgEGKncL4gub8IQC720B25A8YowGTk3BNw=="
>>> der = base64.b64decode(csr)
>>> import asn1crypto.csr
>>> r = asn1crypto.csr.CertificationRequest.load(der)
>>> r.native
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4060, in native
    raise e
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4055, in native
    self._native[name] = child.native
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4060, in native
    raise e
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4055, in native
    self._native[name] = child.native
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4531, in native
    raise e
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4527, in native
    self._native = [child.native for child in self]
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4527, in <listcomp>
    self._native = [child.native for child in self]
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4060, in native
    raise e
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4055, in native
    self._native[name] = child.native
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 911, in native
    return self._parsed[0].native
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4044, in native
    self._parse_children(recurse=True)
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4740, in _parse_children
    raise e
  File "/usr/lib/python3.9/site-packages/asn1crypto/core.py", line 4669, in _parse_children
    raise ValueError(unwrap(
ValueError: Data for field 0 (universal class, primitive method, tag 30) does not match any of the field definitions
    while parsing asn1crypto.core.Set
    while parsing asn1crypto.csr.CRIAttribute
    while parsing asn1crypto.csr.CRIAttributes
    while parsing asn1crypto.csr.CertificationRequestInfo
    while parsing asn1crypto.csr.CertificationRequest

pyasn1 is more forgiving:

>>> from pyasn1.codec.der.decoder import decode as der_decoder
>>> from pyasn1_modules.rfc2314 import CertificationRequest
>>> print(der_decoder(der, rfc2314.CertificationRequest())[0].prettyPrint())
CertificationRequest:
 certificationRequestInfo=CertificationRequestInfo:
  version=0
  subject=Name:
   =RDNSequence:
    RelativeDistinguishedName:
     AttributeTypeAndValue:
      type=2.5.4.10
      value=0x13084950412e54455354
    RelativeDistinguishedName:
     AttributeTypeAndValue:
      type=2.5.4.3
      value=0x13117265706c696361312e6970612e74657374


  subjectPublicKeyInfo=SubjectPublicKeyInfo:
   algorithm=AlgorithmIdentifier:
    algorithm=1.2.840.113549.1.1.1
    parameters=0x0500

   subjectPublicKey=31795268810366627125475313886103102199764218411405668827835783669710603685491359325453053380514453239071455249063417922456515252011418810761469161478180532526544979485304779183014800264848703333493660324757380223479070913340634375662178089314656087904012385741946286314889429352770941321502891866138242642943685501777990037507087577558875127582390935514726341132162180802073094308309707739455314398750760534060373174794287282043915000601126982875940738215591207576299077039489824751852616725040262537669726612369009494074208916397741576157159488279796958471171086170618832296895360025465253787362003389186496006462013881656299561703639268046296645633

  attributes=Attributes:
   Attribute:
    type=1.2.840.113549.1.9.20
    vals=SetOf:
     0x1e16005300650072007600650072002d0043006500720074
   Attribute:
    type=1.2.840.113549.1.9.14
    vals=SetOf:
     0x3081f93081920603551d1101010004818730818482117265706c696361312e6970612e74657374a02f060a2b060104018237140203a0210c1f6c6461702f7265706c696361312e6970612e74657374404950412e54455354a03e06062b0601050202a0343032a00a1b084950412e54455354a1243022a003020101a11b30191b046c6461701b117265706c696361312e6970612e74657374300c0603551d130101ff0402300030200603551d0e01010004160414fb4bbe4d917202b029f228d02a7c3efa7b5eedf0303206092b060104018237140201010004221e200063006100490050004100730065007200760069006300650043006500720074


 signatureAlgorithm=SignatureAlgorithmIdentifier:
  algorithm=1.2.840.113549.1.1.11
  parameters=0x0500

 signature=27039206224655485060916927450244981705686275703614023231340583854229401453411395198878641554068088900619312400249340343240570901024628342186254782681237053799123042444071619134445002618359500100990709248730133274062231030037049221292768213035638387082993787541107261624863385408733162997871481695244822589287548853150605111183007945786021035617693452892836532286876126767601182821660874025579271693574475799529554042718683325403019455636413445944301327620379921971635649216741845160711231735876178808340290551468936814984099995402040151103604145541838395379026283045884042414746025999614637763351046547785739668406583

Metadata Update from @rcritten:
- Issue close_status updated to: fixed
- Issue status updated to: Closed (was: Open)

7 months ago

While working on the rawhide build I found that the csrgen tests are failing. It's because OpenSSL 3.0.0 change some of the output and the tests are doing direct string compares.

I'll open a new PR with a fixup.

Login to comment on this ticket.

Metadata
Related Pull Requests
  • #226 Merged 7 months ago
  • #224 Merged 7 months ago