Subject: [IPsec] Matching of IKE ID on certificate subject and RDN ordering

From: Paul Wouters <[email-masked]>
Date: Thu, 7 May 2020 19:11:25 -0400 (EDT)

Recently I had an interesting issue come up. I needed to generate a
certificate with a specific OU= content that our openssl/python
code couldn't do, and I switched to nss's cert-util to generate
a cert of sets for a test.

Then I noticed something strange. Let's say you have the following
DN specified for certificate generation:

 	C=CZ, ST=Moravia, L=Brno, O=Test Example, OU="Global, Support, Services", CN=server

For openssl, when checking the subject of the cert, it matches in this
order. but when I generated the same certificate with nss cert-util
and re-read it back in openssl, it showed me:

 	CN=server, OU="Global, Support, Services", O=Test Example, L=Brno, ST=Moravia, C=CZ

Note that C= and CN= are swapped. These are differences in the binary data, not the presentation.

When reading https://tools.ietf.org/html/rfc5280#section-7.1 we see:

    Two distinguished names DN1 and DN2 match if they
    have the same number of RDNs, for each RDN in DN1 there is a matching
    RDN in DN2, and the matching RDNs appear in the same order in both
    DNs.

So technically, when we expect one, receiving the other order would be
wrong. So should we really do matching based on the same order of RDNs.
What do other implementations do?

Now, I guess I can weasel myself out of here, by claiming that we are
not comparing two certificates. We just get one via CERT payload and
validate it, and _then_ compare its DN against our IKE ID (which is a
DN, sorta kinda). So perhaps I can say the IKE ID can take RDN's in
any order. As we are dealing with (private) CA's, we can probably be
ensured it would not create two certs that only differ in RDN ordering.

Interested in hearing what others think,

Paul

---

From: Tobias Brunner <[email-masked]>
Date: Fri, 8 May 2020 10:05:33 +0200

Hi Paul,

> Note that C= and CN= are swapped. These are differences in the binary data, not the presentation.

That's because, according to the documentation and examples, NSS
certutil follows RFC 1485 when it comes to string representations of
DNs, which states:

  The name is presented/input in a little-endian order (most significant
  component last).

The latest RFC that replaced it, RFC 4514, states it this way, which is
a bit clearer:

  Otherwise, the output consists of the string encodings of each
  RelativeDistinguishedName in the RDNSequence ..., starting with the
  last element of the sequence and moving backwards toward the first.

Why the last RDN first?  Could be to see the CN immediately, which
usually identifies the actual entity.

What you see in OpenSSL is the physical representation in the ASN.1
encoding of the certificate, i.e. the RDNs in their actual order in the
RDNSequence.  We follow the same principle in strongSwan when logging
and parsing DNs.

> What do other implementations do?

In strongSwan we have an option (charon.rdn_matching) that allows
changing how DNs in certificates are matched against configured IKE
identities.  It defaults to 'strict', which results in what RFC 5280
describes, i.e. all RDNs have to match in the same order (wildcards to
ignore the values of RDNs are always allowed).  With 'reordered', all
RDNs have to be there, but their order doesn't matter.  Finally, with
'relaxed', the certificate's DN may additionally contain RNDs that are
not configured, which are then treated like wildcards.  For example,
with 'relaxed' you could configure

  CN=server

which would be the same as configuring

  C=*, ST=*, L=*, O=*, OU=*, CN=server

which matched both certificates with 'relaxed' and 'reordered' but only
one with 'strict'.

Using 'reordered' and 'relaxed' causes some overhead (memory and
runtime) so 'strict' continues to be the default.

Regards,
Tobias

---

From: Tero Kivinen <[email-masked]>
Date: Sun, 10 May 2020 15:02:44 +0300

> Note that C= and CN= are swapped. These are differences in the binary data, not the presentation.

Most likely another assumes bitwise DN order, and other used LDAP DN
order. Another is most significant part first, another is least
significant part first. I.e., I assume you made certificate
incorrectly when you switched to new tool, as you assumed it takes DN
in same order than openssl tools took it.

Most of the tools just take the DN you give to them and do not look at
the order of C, ST, L, etc parts, but just encode the sequence in the
order you gave them in. But some tools assume you give the DN in LDAP
order which is reversed order from what you have in the actual binary
DER, so they reverse the list before doing this encoding.

>From RFC4514:
----------------------------------------------------------------------
2.1.  Converting the RDNSequence

   If the RDNSequence is an empty sequence, the result is the empty or
   zero-length string.

   Otherwise, the output consists of the string encodings of each
   RelativeDistinguishedName in the RDNSequence (according to Section
   2.2), starting with the last element of the sequence and moving
   backwards toward the first.
----------------------------------------------------------------------

If you look at the
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_certutil
page you notice that examples do have DN in reverse order, i.e. CN
first etc, while openssl takes them in other order. So it clearly
assumes you give the DN in ldap order, not in the most significant
part first order.

BTW, If I remember right the reason for LDAP to use the least
significant part first order was that it allowed searching the
database using partial searches like "CN=kivinen" without the need to
fill in the OU, O, C etc parts and search could then simply assume
default values for those omitted parts. Or something like that.

> What do other implementations do?

You MUST match them in order. If the order is wrong then the DNs do
not match.

Note, that there can be multiple OU fields in the same certificate and
the order of those must be preserved, and also those are reversed
depending on the string format used, so you cannot just take the
attributes and sort them in some order, you must know which order is
supposed to be used and use that.

I.e., if you have

C=FI, O=example Corp, OU=Development, OU=Support, CN=server

and

C=FI, O=example Corp, OU=Support, OU=Development, CN=server

then they are two different sub devisions inside the same
organization, and you must be able to limit developments version
control server so that only support people of the development division
can access it and the global support devision do not have any access
to it.... Same goes with other things for example for DC attributes.

And when you reverse those for least significant part first order, you
do reverse the order of OU fields too.

> ensured it would not create two certs that only differ in RDN ordering.

It is better to properly make the certificates so that the most
significant part of the DN is first in sequence (i.e., C first inside
ASN.1 sequence) and make sure you give then DN in the order that will
result in that to the tool you are using. 

If you ever use any string representation for the DN you must clarify
in your documentation which format you use, i.e., whether you use most
significant part first, or least siginifanct part first. And when you
encode and print them you always consistently do the encoding and
printing in same order. And do matching using binary representation in
the order they are in the DER sequence.
-- 
[email-masked]