Bug 45708 - CRL verification fails if CA have distinct AKID for CRL and client certificates
Summary: CRL verification fails if CA have distinct AKID for CRL and client certificates
Status: RESOLVED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_ssl (show other bugs)
Version: 2.2-HEAD
Hardware: All All
: P2 normal with 18 votes (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords: FixedInTrunk
: 45683 (view as bug list)
Depends on:
Blocks:
 
Reported: 2008-08-28 15:11 UTC by Nicob
Modified: 2012-02-26 16:49 UTC (History)
6 users (show)



Attachments
patch for mod_ssl in order to support more than one crl issued by different CAs with the same subject (11.54 KB, patch)
2011-10-10 08:02 UTC, sektor
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Nicob 2008-08-28 15:11:03 UTC
I'm actually trying to setup a SSL reverse-proxy based on Apache 2.x / mod_ssl and it seems there's a bug in the verification of the CRL.

If a CA changes its keys before expiration, the CRL is now signed by the new key and include certificates issued by both the new and old keys. However, mod_ssl will refuse to work if the AKID (authority key identifier) of the proposed client certificate doesn't match the issuer of the CRL.

Browsing Apache archives, I found that somebody posted a patch covering this need (http://marc.info/?l=apache-httpd-dev&m=120350484626015), but the code haven't been merged. I tested it and it works perfectly well.

Does this patch seems OK to you ? If yes, is it possible to include it ?
Comment 1 Markus Wernig 2008-11-17 04:38:45 UTC
Confirm + additional info:
- Bug bites as whenever there are 2 or more CRLs to check with the same subject hash (as given by openssl crl -in file.crl -noout -hash), independent of lifetime, keyid etc.
- Bug depends on order of CRLs checked. If a client certificate is checked against a CRL that apache determined applicable for it (most likely by using the above hash mechanism and looking up accordingly-named files in SSLCARevocationPath), and if there are more such files, there are two possibilities:
a) The first file checked is by chance the one signed by the CA key that also signed the client cert: all OK, verification succeeds
b) The first file checked is by chance signed by another key of the same CA ("same CA" meaning "same subject hash"): mod_ssl seems to compare the issuing key identifier (AKID) of client certificate and CRL, and if they don't match, reports the following errors:
[warn] Invalid signature on CRL
[error] Certificate Verification: Error (8): CRL signature failure.

This behaviour seems broken. Apparently, mod_ssl relies on the hash value only for determining which CRL file to use. This is not enough. In addition, it should compare the AKID of the client cert and the CRL and only use the CRL if they match. Thus, it could skip the "wrong" ones until the "correct" one (ie.: correct hash AND correkt AKID) is found. In case the information is not present in either one, mod_ssl should probably try to calculate the hash of the signing certificate's public key.

The "first match wins" algorithm is breaking a lot of CRL checking schemes at the moment, since nobody is able to check CRLs for CAs in process of renewing (rekeying) their CAs, which is a process to be expected about every 5 years in the case of average issuing CAs. With a list of (currently) around 120 CAs in the NSS CA store, this will lead to one of them being rolled over every 2 weeks approximately (24 per year for 5 years), creating a failure situation. The only remedy at the moment is to disable CRL checking for those CAs altogether - which is most likely not what is inteded.
Actually, I'm pretty confident that next to nobody is able to use CRL checking coherently because of this.

Please consider changing the CRL matching algorithm in mod_ssl.
Comment 2 Markus Wernig 2008-11-17 04:49:53 UTC
*** Bug 45683 has been marked as a duplicate of this bug. ***
Comment 3 Pavel Janík 2009-01-22 14:09:36 UTC
raising priority.

Comment 4 Franck Leroy 2010-01-11 08:00:10 UTC
UP
not yet solved ? 
CA rekeying fails with mod_ssl, should use AKI instead of Subjects...
Comment 5 pierregeek 2010-01-15 06:17:48 UTC
UP.

It's not possible to have two CRL with the same hash.

Thank's
Comment 6 apache 2010-01-28 15:18:39 UTC
A patch was already proposed 2 years ago :
http://marc.info/?l=apache-httpd-dev&m=120350484626015&w=2
Comment 7 Erwann Abalea 2010-07-06 14:02:08 UTC
(In reply to comment #4)
> UP
> not yet solved ? 
> CA rekeying fails with mod_ssl, should use AKI instead of Subjects...

No. AKI is not the good way to go.
A certificate signed by an CA (with KeyID K1) will be revoked by the renewed CA, with a changed key (with KeyID K2). In that case, AKIs will be different. The only thing in common will be the IssuerName of both the user certificate and CRL. They must match in order to be considered issued by the same CA (for X.509, a CA is only a name, not a key).

The patch I provided 2 years ago solves this, and also some specific case where a CA has one key to sign certificates, and another one to sign CRLs. In that case, AKIs will also be different.
Comment 8 Erwann Abalea 2010-07-06 14:10:32 UTC
(In reply to comment #2)
> *** Bug 45683 has been marked as a duplicate of this bug. ***

This is technically not really a duplicate of this bug. In this bug (#45863), the described situation doesn't conform to the X.509 standard if the 2 CRLs cover the whole set of certificates (i.e. if they're not partitioned, which actual mod_ssl code doesn't deal with).

The proposed patch will solve their error, by masking it, which is sub-optimal. It's OK if the 2 CRLs are "full ones" (not partitioned), and if they contain the same revocation information (i.e. the exact same list of revoked certificates).
If this is not the case, then this CA doesn't do its job correctly, which is not Apache/mod_ssl's fault.
Comment 9 sektor 2011-10-10 08:02:55 UTC
Created attachment 27749 [details]
patch for mod_ssl in order to support more than one crl issued by different CAs with the same subject
Comment 10 sektor 2011-10-10 08:05:35 UTC
Comment on attachment 27749 [details]
patch for mod_ssl in order to support more than one crl issued by different CAs with the same subject

In my company we have a root certification authority with a subCA.
The PKI is based on Microsoft infrastructure (Certificate Service,
Active Directory, etc).
Last month, we have renewed (with new key pair) the subCA since in
6 months it will expire and now  we have to manage two different
CRLs: the first one is issued by the old subCA and the second is
issued by the new subCA. Of course, the subject of the subCA is not
changed.
When we revoke a certificate issued by the old subCA the first CRL is
updated and when we revoke a certificate issued by the new subCA the
related CRL is updated.
I don’t know if it is the right behavior but it sounds reasonable,
however it is the only behavior possible for the Microsoft services.

We have a lot of certificates issued with a high turnover (many
revocations) so it is important for us to check both the CRLs.
For this reason we have developed a patch starting from the patch
provided by Erwann that unfortunately does not fit with our scenario.

For that I described before, the usage of authority key identifier and
subject key identifier, during the CRL verification process, can be
helpful.

So, the idea behind the patch is this:
1. Get authority key identifier (akid) from the current certificate
2. Get subject key identifier (skid) from the current certificate
3. For the CRL verification (first step), look for the CRL with the
   CRL issuer equal to certificate subject and CRL akid equal to
   certificate skid
4. For the revocation check (second step), look for the CRL with the
   CRL issuer equal to certificate issuer and CRL akid equal to
   certificate akid
Comment 11 Erwann Abalea 2011-10-10 09:10:35 UTC
(In reply to comment #10)
> Comment on attachment 27749 [details]
> patch for mod_ssl in order to support more than one crl issued by different CAs
> with the same subject

If the subject is the same, then it's the same CA. A CA can have several certificates, separated by roles, or generation (renewed), but together they form only one CA, not several.

Please read X.509 (which can be freely downloaded). A CA is not a certificate, or a key, it's a *name*.

> In my company we have a root certification authority with a subCA.
> The PKI is based on Microsoft infrastructure (Certificate Service,
> Active Directory, etc).
> Last month, we have renewed (with new key pair) the subCA since in
> 6 months it will expire and now  we have to manage two different
> CRLs: the first one is issued by the old subCA and the second is
> issued by the new subCA. Of course, the subject of the subCA is not
> changed.
> When we revoke a certificate issued by the old subCA the first CRL is
> updated and when we revoke a certificate issued by the new subCA the
> related CRL is updated.
> I don’t know if it is the right behavior but it sounds reasonable,
> however it is the only behavior possible for the Microsoft services.

This is not conformant to X.509. The fact that this is the only possible behaviour from the Microsoft PKI doesn't make it valid.
In the absence of any critical extension in a CRL stating that this CRL is a partitioned one (the wording used in X.509 is "full scope" CRL), then this CRL provides a revocation status for *all the certificates signed by the issuer*. The AKI extension in the CRL is only a helper to find the correct key to validate the CRL' signature, it's *not* a CRL differenciator.

[...]
> For that I described before, the usage of authority key identifier and
> subject key identifier, during the CRL verification process, can be
> helpful.
> 
> So, the idea behind the patch is this:
> 1. Get authority key identifier (akid) from the current certificate
> 2. Get subject key identifier (skid) from the current certificate

So SKID is the key identifier of the end-user certificate, right?

> 3. For the CRL verification (first step), look for the CRL with the
>    CRL issuer equal to certificate subject and CRL akid equal to
>    certificate skid

So you're trying to find a CRL emitted by the issuer, but signed by the end-user key? That's wrong.

> 4. For the revocation check (second step), look for the CRL with the
>    CRL issuer equal to certificate issuer and CRL akid equal to
>    certificate akid

This algorithm won't validate X.509 compliant PKIs, with renewed CAs (read  rekeyed if you want).
Comment 12 sektor 2011-10-10 10:26:31 UTC
(In reply to comment #11)
> [...]
> 
> This is not conformant to X.509. The fact that this is the only possible
> behaviour from the Microsoft PKI doesn't make it valid.
> In the absence of any critical extension in a CRL stating that this CRL is a
> partitioned one (the wording used in X.509 is "full scope" CRL), then this CRL
> provides a revocation status for *all the certificates signed by the issuer*.
> The AKI extension in the CRL is only a helper to find the correct key to
> validate the CRL' signature, it's *not* a CRL differenciator.
>

Ok, let's say the scope of the old CRL is "all the certificates issued before xxx" and the scope of the new CRL is "all the certificates issued after xxx".
 
> [...]
> > For that I described before, the usage of authority key identifier and
> > subject key identifier, during the CRL verification process, can be
> > helpful.
> > 
> > So, the idea behind the patch is this:
> > 1. Get authority key identifier (akid) from the current certificate
> > 2. Get subject key identifier (skid) from the current certificate
> 
> So SKID is the key identifier of the end-user certificate, right?

No, SKID is the key identifier of the current certificate during the loop of the chain verification, so it can be a CA or a subCA or an end-user certificate.

> 
> > 3. For the CRL verification (first step), look for the CRL with the
> >    CRL issuer equal to certificate subject and CRL akid equal to
> >    certificate skid
> 
> So you're trying to find a CRL emitted by the issuer, but signed by the
> end-user key? That's wrong.
> 

No, the CRL verification process in mod_ssl is described in the ssl_callback_SSLVerify_CRL function.
We try to check the signature of a CRL in each step when we find a CRL
through the _subject_ name of the current certificate and the skid (we use also the skid because we can have more than one CRL).


> > 4. For the revocation check (second step), look for the CRL with the
> >    CRL issuer equal to certificate issuer and CRL akid equal to
> >    certificate akid
> 
> This algorithm won't validate X.509 compliant PKIs, with renewed CAs (read 
> rekeyed if you want).

I think the specification regarding CRL is too generic: to implement a general CRL verification system is rather difficult.
For example, my patch solves the problem for scoped CRL based on the time, your patch solves the problem for "full scope" CRL, but a lot of cases remain uncovered.
Comment 13 Erwann Abalea 2011-10-10 12:59:22 UTC
(In reply to comment #12)
> (In reply to comment #11)
> > [...]
> > 
> > This is not conformant to X.509. The fact that this is the only possible
> > behaviour from the Microsoft PKI doesn't make it valid.
> > In the absence of any critical extension in a CRL stating that this CRL is a
> > partitioned one (the wording used in X.509 is "full scope" CRL), then this CRL
> > provides a revocation status for *all the certificates signed by the issuer*.
> > The AKI extension in the CRL is only a helper to find the correct key to
> > validate the CRL' signature, it's *not* a CRL differenciator.
> 
> Ok, let's say the scope of the old CRL is "all the certificates issued before
> xxx" and the scope of the new CRL is "all the certificates issued after xxx".

I understand what you want. But you need to express it with a critical extension. Please read X.509 recommendation, chapter 8.5.2.5 (CRL scope extension). The need here is to avoid a CRL substitution attack.

> > [...]
> > > For that I described before, the usage of authority key identifier and
> > > subject key identifier, during the CRL verification process, can be
> > > helpful.
> > > 
> > > So, the idea behind the patch is this:
> > > 1. Get authority key identifier (akid) from the current certificate
> > > 2. Get subject key identifier (skid) from the current certificate
> > 
> > So SKID is the key identifier of the end-user certificate, right?
> 
> No, SKID is the key identifier of the current certificate during the loop of
> the chain verification, so it can be a CA or a subCA or an end-user
> certificate.

Ok. I worked on it some time ago, and forgot about the 2 steps method.

> > > 3. For the CRL verification (first step), look for the CRL with the
> > >    CRL issuer equal to certificate subject and CRL akid equal to
> > >    certificate skid
> > 
> > So you're trying to find a CRL emitted by the issuer, but signed by the
> > end-user key? That's wrong.
> 
> No, the CRL verification process in mod_ssl is described in the
> ssl_callback_SSLVerify_CRL function.
> We try to check the signature of a CRL in each step when we find a CRL
> through the _subject_ name of the current certificate and the skid (we use also
> the skid because we can have more than one CRL).

The original process is already flawed, as it permits a CA to revoke itself. This is not permitted as per X.509.
Your modification requires the CA to use the same key to sign the CRL as the one used to sign the certificate, which is not the case with roles separation: 1 certificate to sign certificates, 1 certificate to sign CRLs.

> > > 4. For the revocation check (second step), look for the CRL with the
> > >    CRL issuer equal to certificate issuer and CRL akid equal to
> > >    certificate akid
> > 
> > This algorithm won't validate X.509 compliant PKIs, with renewed CAs (read 
> > rekeyed if you want).
> 
> I think the specification regarding CRL is too generic: to implement a general
> CRL verification system is rather difficult.

The algorithm is well described in the X.509 recommendation, and is normative. mod_ssl already deviates from this algorithm. Your modification enhances this distance.

If your Microsoft PKI really does it like you described, then file a bug to them, they're clearly doing it wrong.

In the meantime, mod_ssl CRL verification needs to be radically changed, it doesn't check critical extensions, it doesn't follow the normative algorithm, it can't pass the NIST's PKITS. What should be done is to use internal OpenSSL CRL validation mechanism, which is correct.
Comment 14 Kaspar Brand 2011-10-11 05:12:31 UTC
(In reply to comment #13)
> In the meantime, mod_ssl CRL verification needs to be radically changed, it
> doesn't check critical extensions, it doesn't follow the normative algorithm,
> it can't pass the NIST's PKITS. What should be done is to use internal OpenSSL
> CRL validation mechanism, which is correct.

That's what has been done in r1165056 recently, so I'm tempted to add the FixedInTrunk keyword to this bug.

It will first appear in 2.3.15-beta (to be released later this month, hopefully); tests with a current checkout of trunk are very welcome, of course. For best results, mod_ssl should be compiled against OpenSSL 1.0.0e or later, since a considerable number of CRL processing enhancements are only available in 1.0.0.

(In reply to comment #0)
> Browsing Apache archives, I found that somebody posted a patch covering this
> need (http://marc.info/?l=apache-httpd-dev&m=120350484626015), but the code
> haven't been merged. I tested it and it works perfectly well.

For the records: in Apache's own list archive, it's
http://mail-archives.apache.org/mod_mbox/httpd-dev/200802.mbox/%3C20080220105329.GE24122@keynectis.com%3E
Comment 15 Erwann Abalea 2011-10-11 10:37:38 UTC
(In reply to comment #14)
> (In reply to comment #13)
> > In the meantime, mod_ssl CRL verification needs to be radically changed, it
> > doesn't check critical extensions, it doesn't follow the normative algorithm,
> > it can't pass the NIST's PKITS. What should be done is to use internal OpenSSL
> > CRL validation mechanism, which is correct.
> 
> That's what has been done in r1165056 recently, so I'm tempted to add the
> FixedInTrunk keyword to this bug.

Nice information. I'm browsing the SVN tree to look at the changes. I'm glad someone took the time for this.

> It will first appear in 2.3.15-beta (to be released later this month,
> hopefully); tests with a current checkout of trunk are very welcome, of course.

I'll do some tests, with role separated CAs, and rekeyed CAs.

> (In reply to comment #0)
> > Browsing Apache archives, I found that somebody posted a patch covering this
> > need (http://marc.info/?l=apache-httpd-dev&m=120350484626015), but the code
> > haven't been merged. I tested it and it works perfectly well.
> 
> For the records: in Apache's own list archive, it's
> http://mail-archives.apache.org/mod_mbox/httpd-dev/200802.mbox/%3C20080220105329.GE24122@keynectis.com%3E

I did receive some useful comments on this patch, but I don't remember who wrote them (cold got me). Basically, it was about using OpenSSL's own CRL validation code instead of mod_ssl legacy one, which does a really bad job.
Comment 16 sektor 2011-10-17 15:51:08 UTC
I tested the trunk version against my scenario:
- 1 CA with two different key pairs due the renewal,
- 2 CRLs issued by the same CA but signed with the two different keys,
- no critical extensions in the CRLs in order to define the scope,
- certificates issued by CA and signed with the CA old key are revoked using the CRL signed by the CA old key,
- certificates issued by CA and signed with the CA new key are revoked using the CRL signed by the CA new key.

Everything works fine:
- valid certificates issued by the CA using CA old key pass the validation
- valid certificates issued by the CA using CA new key pass the validation
- revoked certificates issued by the CA using CA old key and listed in the relative CRL do not pass the validation
- revoked certificates issued by the CA using CA new key and listed in the relative CRL do not pass the validation

Works for me.
Comment 17 Kaspar Brand 2011-11-20 10:53:58 UTC
Thanks for your testing. Adding the FixedInTrunk keyword, therefore.

Note that 2.3.15-beta has been released in the meantime (http://httpd.apache.org/download.cgi#apache23), so for those who want to do additional tests, there's no longer a need to check out things from svn.
Comment 18 Stefan Fritsch 2012-02-26 16:49:10 UTC
2.4.1 is released, closing