Subject: [pkix] id-pkix-ocsp-nocheck extension: NULL vs empty

From: "Manger, James H" <[email-masked]>
Date: Fri, 15 Jun 2012 13:56:09 +1000

I have noticed some strangely encoded id-pkix-ocsp-nocheck certificate extensions recently. I expected the content of the extension to be a DER-encoded NULL (05 00), inside the extnValue OCTET STRING (04 02 0500). Instead, extnValue was an empty OCTET STRING (04 00).

Is this encoding a bug?

My ASN.1 library and Java 1.6 fail with these responder certs. My guess is that major browsers and operating systems don't fail (otherwise the issue would have been fixed earlier).

I believe the offending certs are from Microsoft CA code. Does anyone have a Microsoft PKI contact to report this technical issue to?

The relevant bytes of the OCSP responder certificates are (DER-encoded Extension):

  30 0D
     06 09 2B0601050507300105
     04 00

In text, using <http://lapo.it/asn1js/>

 SEQUENCE(2 elem)
   OBJECT IDENTIFIER 1.3.6.1.5.5.7.48.1.5
   OCTET STRING (0 byte)

A StackOverflow question "Exception When Reading OCSP Signing Certs in Java" < http://stackoverflow.com/questions/1497594/exception-when-reading-ocsp-signing-certs-in-java> has a full certificate showing this problem.

[Java 1.6 fails to parse these certificates (keytool -printcert -v -file responder.cer), though I believe that is because of a bug handling zero-length octet strings that is not specific to the id-pkix-ocsp-nocheck extension. Java 7 seems to handle these certificates.]

The relevant text from RFC 2560 "PKIX OCSP" section 4.2.2.2.1 "Revocation Checking of an Authorized Responder" is:

   - A CA may specify that an OCSP client can trust a responder for the
   lifetime of the responder's certificate. The CA does so by including
   the extension id-pkix-ocsp-nocheck. This SHOULD be a non-critical
   extension. The value of the extension should be NULL. CAs issuing
   such a certificate should realized that a compromise of the
   responder's key, is as serious as the compromise of a CA key used to
   sign CRLs, at least for the validity period of this certificate. CA's
   may choose to issue this type of certificate with a very short
   lifetime and renew it frequently.

   id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 }

--
James Manger

---

From: Erwann Abalea <[email-masked]>
Date: Fri, 15 Jun 2012 18:48:48 +0200

Bonjour,

The relevant RFC2560 text does show "The value of the extension should be
NULL", and not "The value of the extension SHOULD be NULL". Note the
capitalization.
Also note that it's not written "The value of the extension MUST be NULL".

Therefore, the relying party needs to be able to handle an empty content,
or any other content.

The content is not important in fact, that's why browsers don't fail on it.
More, some of them don't care if this extension is present or not and
consider the certificate to be non-revoked, whatever its real state is.

2012/6/15 Manger, James H <[email-masked]>

> I have noticed some strangely encoded id-pkix-ocsp-nocheck certificate
> extensions recently. I expected the content of the extension to be a
> DER-encoded NULL (05 00), inside the extnValue OCTET STRING (04 02 0500).
> Instead, extnValue was an empty OCTET STRING (04 00).
>
>
-- 
Erwann.

---

From: "Manger, James H" <[email-masked]>
Date: Mon, 18 Jun 2012 09:28:19 +1000

>> I have noticed some strangely encoded id-pkix-ocsp-nocheck
>> certificate extensions recently. I expected the content of
>> the extension to be a DER-encoded NULL (05 00), inside the
>> extnValue OCTET STRING (04 02 0500). Instead, extnValue
>> was an empty OCTET STRING (04 00).

Erwann Abalea replied:
> The relevant RFC2560 text does show "The value of the extension
> should be NULL", and not "The value of the extension SHOULD be NULL".
> Note the capitalization. Also note that it's not written "The value
> of the extension MUST be NULL".
>
> Therefore, the relying party needs to be able to handle an empty
> content, or any other content.

I disagree, Erwann.

The extnValue field is clearly specified to hold the encoding of
an ASN.1 type in the value of the OCTET STRING. A empty string is
not a encoding of any ASN.1 type so these certificates are wrong.

X.509 says:
  Extension ::= SEQUENCE { 
    extnId  EXTENSION.&id ({ExtensionSet}), 
    critical  BOOLEAN DEFAULT FALSE, 
    extnValue OCTET STRING 
          -- contains a DER encoding of a value of type &ExtnType
          -- for the extension object identified by extnId -- }

RFC5280 says something similar:
    extnValue   OCTET STRING
          -- contains the DER encoding of an ASN.1 value
          -- corresponding to the extension type identified
          -- by extnID

Earlier versions didn't have a comment in the ASN.1 but were
clear enough in the text. RFC2459 says:
   Each extension includes an OID and an ASN.1 structure.  When an
   extension appears in a certificate, the OID appears as the field
   extnID and the corresponding ASN.1 encoded structure is the value of
   the octet string extnValue.

RFC2560 "OCSP" was a bit sloppy because it specified the
OID (id-pkix-ocsp-nocheck) and ASN.1 structure (NULL), but didn't
include the ASN.1 for an EXTENSION object class item.
It should have included the following:

  ocspNoCheck EXTENSION ::= {
    SYNTAX         NULL
    IDENTIFIED BY  id-pkix-ocsp-nocheck }

Perhaps RFC2560bis can add that for completeness.

--
James Manger

---

From: Erwann Abalea <[email-masked]>
Date: Mon, 18 Jun 2012 17:42:14 +0200

Bonjour,

2012/6/18 Manger, James H <[email-masked]>

> not a encoding of any ASN.1 type so these certificates are wrong.

Empty elements are frequently encoded in DER, think of OPTIONAL (or
DEFAULT) elements. The encoding result doesn't contain them, that's all. In
a sense, an empty element gets encoded into 0 octets. That's mandatory for
elements whose value is equal to the specified DEFAULT value.

X.509 edition 2008/11 says:
Extension ::= SEQUENCE {
  extnId EXTENSION.&id ({ExtensionSet}),
  critical BOOLEAN DEFAULT FALSE,
  extnValue OCTET STRING
  (CONTAINING EXTENSION.&ExtnType({ExtensionSet}{@extnId})
  ENCODED BY der)}

This is more or less the same as what you wrote (found in the 2005
edition), I won't argue on the phrasing.

The extension value is first encoded in DER, and the result is then
enclosed inside an OCTET STRING. If the DER encoding results in no output
bytes, then the OCTET STRING enclosing it will have a zero length.

Anyway, I got a hard time trying to read X.680 to X.683 to find an answer
to the following question. Can I define my own extension like this:

myStupidExample EXTENSION ::= {
  SYNTAX INTEGER DEFAULT 0  -- note the "DEFAULT 0"
  IDENTIFIED BY id-myarc-mystupidextension }

The EXTENSION class is defined below:
EXTENSION ::= CLASS {
  &id OBJECT IDENTIFIER UNIQUE,
  &ExtnType }
WITH SYNTAX {
  SYNTAX &ExtnType
  IDENTIFIED BY &id }

My understanding of X.68x is that the optionality specifier has to be
included in the EXTENSION (by specifying "&ExtnType OPTIONAL" in the CLASS
group, for example) and cannot be added to an object using the EXTENSION
abstract class. Which of course would have the effect to render your
observed extension invalid.

Well. X.68x is much harder to read than X.509 and its companions together,
so you may be finally right.
The (good?) news is that nobody cares about the content of this extension.

-- 
Erwann.

---

From: Steven Legg <[email-masked]>
Date: Tue, 19 Jun 2012 09:56:22 +1000

Hi Erwann,

On 19/06/2012 1:42 AM, Erwann Abalea wrote:
> Bonjour,
>
> 2012/6/18 Manger, James H <[email-masked] <mailto:[email-masked]>>
>
>     2012/6/15 Manger, James H <[email-masked] <mailto:[email-masked]>>
> Empty elements are frequently encoded in DER, think of OPTIONAL (or DEFAULT) elements. The encoding result
> doesn't contain them, that's all. In a sense, an empty element gets encoded into 0 octets. That's mandatory
> for elements whose value is equal to the specified DEFAULT value.

The content of the extnValue is in no way an OPTIONAL or DEFAULT component,
so it has to be the encoding of some ASN.1 value.

> This is more or less the same as what you wrote (found in the 2005 edition), I won't argue on the phrasing.
>
> The extension value is first encoded in DER, and the result is then enclosed inside an OCTET STRING. If the
> DER encoding results in no output bytes, then the OCTET STRING enclosing it will have a zero length.

There is no circumstance in which the mandatory DER encoding of an
ASN.1 value is a zero length sequence of octets, even though the
encodings of parts of that value may be omitted.

>
> Anyway, I got a hard time trying to read X.680 to X.683 to find an answer to the following question. Can I
> define my own extension like this:
>

The above is not syntactically correct, nor is there a syntactically
correct way of achieving your intent.

> My understanding of X.68x is that the optionality specifier has to be included in the EXTENSION (by
> specifying "&ExtnType OPTIONAL" in the CLASS group, for example) and cannot be added to an object using the
> EXTENSION abstract class.

That is correct. The CLASS definition is analogous to a type and the myStupidExample
information object is analogous to a value. Values don't have optionality specifiers.
Furthermore, if the ExtnType were defined to be DEFAULT, then the default would be
an ASN.1 type rather than a value.

 > Which of course would have the effect to render your observed extension invalid.
>
> Well. X.68x is much harder to read than X.509 and its companions together, so you may be finally right.

James was right from the beginning :-).

> The (good?) news is that nobody cares about the content of this extension.

People like James and myself who use ASN.1 tools to automate the processing
of ASN.1 types and values care. When people with hand-crafted encoders and
decoders break the rules it spells pain for us because we have to convince
our tools to behave in a non-conformant way, or work around them somehow.

Regards,
Steven

>
> --
> Erwann.
>
>
> _______________________________________________
> pkix mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/pkix

---

From: Erwann Abalea <[email-masked]>
Date: Tue, 19 Jun 2012 17:04:20 +0200

Bonjour Peter,

2012/6/19 Peter Gutmann <[email-masked]>

> Erwann Abalea <[email-masked]> writes:
>
> DEFAULT)
> >elements. The encoding result doesn't contain them, that's all. In a
> sense,
> >an empty element gets encoded into 0 octets. That's mandatory for elements
> >whose value is equal to the specified DEFAULT value.
>
> There's no indication in the OCSP spec that the value of noCheck is
> OPTIONAL
> or DEFAULT,

That's the second part of my reply, trying to understand ASN.1 grammar
rules. This is what I understood, and Steven confirmed it.
OCSP couldn't have defined the value as OPTIONAL. The EXTENSION class
hasn't defined ExtnType as OPTIONAL, so it's not (and whence, the value of
the extension can't be empty).

I was clearly wrong in saying that an empty OCTET STRING content is valid.
I admit it.

> and the fact that the NULL is given as a should rather than a
> SHOULD is almost certainly a typo.  If it's to be interpreted only as a
> MAY as
> you suggested in a previous post then that means you could put absolutely
> anything in there, including the ever-popular MPEG of a cat.  I doubt
> that's
> what the authors of the RFC had in mind.

There's a typo ("should" instead of "SHOULD"), but more, there's no ASN.1
definition of the extension.
As pointer by James, things would be much more clear if this was present:

That way, the value MUST be a NULL (instead of SHOULD), and it is clear
that it's an extension. OCSP responders with id-pkix-ocsp-nocheck as an EKU
exist. In the wild.

> This is clearly a bug in Microsoft's
> implementation, and it's only persisted because most other implementations
> seem to ignore what the find there.
>

Right. Most implementations don't use a validating ASN.1 parser either.

-- 
Erwann.