Closed Bug 232693 Opened 21 years ago Closed 21 years ago

CERT_DecodeGeneralName fails if generalName is DN

Categories

(NSS :: Libraries, defect, P2)

Sun
Solaris
defect

Tracking

(Not tracked)

RESOLVED INVALID

People

(Reporter: yassir.elley, Assigned: nelson)

Details

Attachments

(1 file)

User-Agent:       
Build Identifier: Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.2.1) Gecko/20030711

Here is the relevant fragment from genname.c 
        ...
        rv = SEC_ASN1DecodeItem(arena, genName, template, encodedName);
        if (rv != SECSuccess) 
                goto loser;
        if (genNameType == certDirectoryName) {
                rv = SEC_ASN1DecodeItem(arena, &(genName->name.directoryName), 
                                        CERT_NameTemplate, 
                                        &(genName->derDirectoryName));
        ...

If I call CERT_DecodeGeneralName with an encodedName whose type is 
"certDirectoryName", there are two calls to SEC_ASN1DecodeItem. The first
call uses a CERT_DirectoryNameTemplate in this case, and it returns 
SECSuccess. The second call uses the CERT_NameTemplate and returns 
SECFailure, causing the function to return NULL.

On both NSS 3.3 and NSS 3.9, I have found this to be a problem.

More details:

When CERT_DecodeGeneralName calls SEC_ASN1DecodeItem with
a CERT_DirectoryNameTemplate, the encoded name that is passed in is:

                [4] {
                  SET OF {
                    SEQUENCE {
                      OBJECT IDENTIFIER countryName (2 5 4 6)
                      PrintableString 'us'
                      }
                    }
                  } ...

Then, when CERT_DecodeGeneralName subsequently calls SEC_ASN1DecodeItem 
with a CERT_NameTemplate, the encoded name that is passed in is:

                  SET OF {
                    SEQUENCE {
                      OBJECT IDENTIFIER countryName (2 5 4 6)
                      PrintableString 'us'
                      }
                    }
                  } 

Here, the decoder expects a tag_number of SEQUENCE_OF but finds the tag_number
of SET_OF, and therefore fails.

Incidentally, CERT_DerNameToAscii() also calls SEC_ASN1DecodeItem with a
CERT_NameTemplate and succeeds. The encoded name that is passed in is:


                SEQUENCE OF {
                  SET OF {
                    SEQUENCE {
                      OBJECT IDENTIFIER countryName (2 5 4 6)
                      PrintableString 'us'
                      }
                    }

Clearly, the CERT_NameTemplate is expecting to start with SEQUENCE_OF,
but that is not what it receives in CERT_DecodeGeneralName.

Reproducible: Always
Steps to Reproduce:
1.Create a certificate with a subjectAlternativeName of type "certDirectoryName" 
2.Read in the cert file and decode the DER bytes into a CERTCertificate
3.Call CERT_GetCertificateNames on the CERTCertificate


Actual Results:  
CERT_GetCertificateNames returns NULL.

Expected Results:  
CERT_GetCertificateNames should have returned a CERTGeneralName with
type = certDirectoryName, and with the name.directoryName field filled
with a CERTName representing the DN.
Here is the certificate I used to reproduce this bug.
Status: UNCONFIRMED → NEW
Ever confirmed: true
Taking
Assignee: wchang0222 → MisterSSL
Nominating for 3.9.1 since this affects a customer.
Status: NEW → ASSIGNED
Priority: -- → P2
Target Milestone: --- → 3.9.1
The Alt name in the cert attached to this bug contains a GeneralName that 
is encoded as an implicitly tagged SEQUENCE of RelativeDistinguishedName.  
That is, the context-dependent tag [4] takes the place of the SEQUENCE OF tag.  
But that is not how NSS expects the GeneralName to be encoded.

RFC 3280 and X.509v3 define the subject alt name and issuer alt name as 
shown below.  See http://www.rfc-editor.org/rfc/rfc3280.txt and
http://www.itu.int/ITU-T/asn1/database/itu-t/x/x509/1997/CertificateExtensions.html
(page numbers from RFC 3280):

[pages 34-35]

   SubjectAltName ::= GeneralNames  

   IssuerAltName ::= GeneralNames

   GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName

   GeneralName ::= CHOICE {
        otherName                       [0]     OtherName,
        rfc822Name                      [1]     IA5String,
        dNSName                         [2]     IA5String,
        x400Address                     [3]     ORAddress,
        directoryName                   [4]     Name,
        ediPartyName                    [5]     EDIPartyName,
        uniformResourceIdentifier       [6]     IA5String,
        iPAddress                       [7]     OCTET STRING,
        registeredID                    [8]     OBJECT IDENTIFIER }

[page 18]

   Name ::= CHOICE { rdnSequence RDNSequence }   

   RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

   RelativeDistinguishedName ::=
     SET OF AttributeTypeAndValue

   AttributeTypeAndValue ::= SEQUENCE {
     type     AttributeType,
     value    AttributeValue }

   AttributeType ::= OBJECT IDENTIFIER

   AttributeValue ::= ANY DEFINED BY AttributeType


In that definition, the directoryName component of GeneralName is an 
implicitly tagged Name.  A Name is a CHOICE that includes an RDNSequence; 
that is, a Name is a *CHOICE* that includes a SEQUENCE OF 
RelativeDistinguishedName (which I will call "RDN" for short).  
A name is not merely a SEQUENCE OF RDN, but rather is a CHOICE.

Personally, an implicitly tagged CHOICE strikes me as a flawed ASN.1 
definition.  If there are multiple alternatives within the CHOIcE,
and the implicit tag replaces any/all of them, how does a decoder know 
which of the alternative values within the CHOICE to choose?

There seem to be two ways around this issue:

1. Implement it as if directoryName was defined within GeneralName as

        directoryName                  [4]     RDNSequence, -- no choice

2. Implement it as if directoryName was defined within GeneralName as

        directoryName             [4] EXPLICIT Name,    -- explicitly tagged

The original authors of NSS's GeneralName encoder and decoder chose 
the second of those alternatives.  The creators of the cert in the 
attachment above chose the first of those alternatives.  

I do not know what the right solution is at this time, and will investigate
futher.  I do know that changing NSS to use the first alternative above 
will be a non-trivial task, unfortunately.
Google showed me this web page, which addresses this subject directly:
http://www.imc.org/ietf-pkix/old-archive-97/msg00625.html

In it, the author writes:

> The IMPLICIT rule does not apply to CHOICE and ANY. So you are right in 
> your assomption: i.e. you have to encode CHOICE item tags.

I also found this interesting piece of open source from apple, which is 
clearly based on NSS.  It reimplements the general Name parsing code,
and uses the same technique as NSS, treating directory namd as expicitly
tagged.

http://www.opensource.apple.com/darwinsource/10.3/SecurityNssAsn1-11/nssDER/Source/nameTemplates.cpp

This "PKIX 1" ASN.1 definition of GeneralName explicitly declares all types 
of GeneralName except Name as IMPLICIT, implying that Name is EXPLICIT.
(View the source of this page.  It's a plain text page sent as type TEXT/HTML.)

http://www.trl.ibm.com/projects/xml/xss4j/data/asn1/grammars/x509.asn

In this next page, at lines 1542-1543, both X400Address and directoryName
are declared EXPLICIT.

http://www.cl.cam.ac.uk/Research/Security/resources/SET/SetCertificateExtensions.html

After reading all these interpretations, I conclude that NSS's interpetation 
and implementation is correct, and that the cert attached to this bug is
incorrectly encoded.  

In fact, the ONLY document I found that agreed with the view that Name should
be implicitly tagged was a JavaDoc page.  

http://www.semoa.org/docs/api/codec/x509/GeneralName.html


So, I am marking this bug report Resolved/INVALID
Status: ASSIGNED → RESOLVED
Closed: 21 years ago
Resolution: --- → INVALID
Version: unspecified → 3.9
Yet another page that declares 
   directoryName [4] EXPLICIT Name

http://www.oss.com/asn1/setoss1.asn

However, feel free to reopen this bug if you can cite an authoritative
ISO or IETF source saying that a directoryName MUST be encoded implicitly.
NIST has a test suite of certs and CRLs that are used for extensive validity
testing of cert path validation.  You may read about it here:

http://csrc.nist.gov/pki/testing/x509paths.html

That page also contains a link to download the zip file that contains all
the test certificates.

This test suite contains numerous certs that contain subjectAltNames with
directoryNames in them.  An examination of some of those certs, such as 
certs in the files named 
InvalidDNnameConstraintsTest3EE.crt
ValidDNnameConstraintsTest4EE.crt
ValidDNnameConstraintsTest5EE.crt
shows that all the GeneralNames that contain directoryNames have used
EXPLICIT encoding of the Name in the directory name.  I consider these
examples to authoritatively show the correct encoding of a DN GeneralName.

By the way, NSS passes the tests that use these certs, so I believe NSS
is parsing these correctly.
OK, I agree that my certificate was encoded incorrectly.
I'll have to look into my encoding software. Sorry.

BTW, I found the reference explaining this somewhat peculiar case.

RFC 3280 makes a normative reference to X.690 (for DER).
X.690 makes a normative reference to X.680 (for ASN.1).

X.680 states (in Section 30.6) that explicit tagging
should be used if the tagged type is of either of three forms:
	a) <tag> EXPLICIT <type>
	b) <tag> <type> where the modules default is EXPLICIT_TAGS or empty
	c) <tag> <type> where the modules default is IMPLICIT_TAGS, but 
	   the type is an untagged choice

Our situation is covered by form (c), and should therefore be
handled with explicit tagging, as the NSS code correctly does.
OS: SunOS → Solaris
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: