As discussed in our monday meeting, the NIST tests use the following policy for
1) if a CRL for an issuer is not present, this is considered an error (cert
By contrast, NSS until now has considered this case a success. The reasoning is
that we use the CRL revocation if available, but if not, we function, in order
to be user-friendly.
Note that if however NSS detects that any attempt was made to use a CRL, such as
a CRL is present, but corrupt, it considers it a failure.
There may be some hints we can take from the leaf cert or CA cert through the
distribution point extension to find out if the CA even issues a CRL at all, and
only fail if it does, rather than for all CAs for which don't have CRLs.
Either way, I don't think this setting would have any actual real-world
application since pretty much nothing on the public Internet would work unless
you had CRLs for all CAs in all cert chains. It is probably only suitable for
NIST tests, and maybe for some closed PKI environments, and I'm somewhat
skeptical of the practicality of it even in that case.
2) if a CRL has a nextUpdate that is before the date against which a certificate
is being verified, this is considered an error.
There is nothing in RFCs that says revocation information ever expires.
Nextupdate is only information that the CA should make new revocation
In most cases it is better to use the CRL information than not use it at all.
But some users, such as NIST, want to consider that a failure case (revoked cert).
This bug is an RFE to add functions allowing NSS applications to function with
According to Lord, the original request from the DoD was that the application
should be able to control how long the CRL will continue to be considered
unexpired after the nextUpdate time passes. Originally, NSS treated that
amount as zero, and that is the amount that NIST wants to see. Today NSS
treats that amount as infinite. Neither fixed value seems to satisfy the
original request. I would suggest that, rather than a "NIST MODE" for CRL
expiration, we add a function that allows the application to set the
amount of time.
My guess is that this will be a global value, but maybe that's not right.
It's not clear to what other object we would attach this value.
We can debate whether the default should be zero, or infinite.
1) About the first part of this problem, the missing CRL case :
If we are going to have a policy where NSS can return a "missing CRL" error,
then we must make sure that we have the appropriate CRL.
The current policy can be summarized as :
We check the cert against the latest available and valid CRL. If no CRL is
available, we pass. If a CRL is available, but invalid, we fail.
However, when we do have a valid CRL, we don't try to ensure that it is the
appropriate CRL to use, other than the fact that it is the CRL for the correct
issuer. The whole problem comes from the fact that we allow verifications at
dates other than now, which really isn't specified by the RFCs.
When verifying at a date in the past, there are cases where the latest CRL may
not be appropriate to use, and we should instead return missing CRL if we are
going to apply our policy correctly.
cert A is issued at t1=1/1/2003, expires at t2=12/31/2003
- today is 2/18/2004
We verify the signature on an old e-mail dated t3=11/10/2003
We have the current CRL dated 2/18/2004
The CRL is not guaranteed to carry status for cert A on it, because that cert
has expired. The CRL may optionally have it, but it is to the discretion of the
CA and to my knowledge there isn't a CRL extension allowing us to find out how
far back the CRL goes if it carries expired certs (maybe that's something to
propose to PKIX ?). In the absence of such extension, we must assume the worst -
that the current CRL does not carry status for cert A because it's expired, and
therefore this is equivalent to a missing CRL case.
I think this policy *may* be usable in some closed environments for SSL, since
it is real-time and presumably we wouldn't be doing checks in the past in our
applications during server auth or client auth, assuming properly configured
clocks. We still however need to have a way to make sure a CRL exists. It's not
clear that the CDP extension does the job. I need to dig that up.
I don't think this policy will work for S/MIME at all though, at least not in
the current state of the softoken storing a single CRL per issuer - see bug
217392 about that. If we were able to store multiple CRLs, then the policy could
be implemented to check revocation status against all the different available
CRLs, including for certs that would have dropped out in the newest CRLs.
Today the only way to accomplish that would be to add separate revocation
tokens, since each token can store one CRL per issuer. But you would need one
token per CRL so it wouldn't be practical.
For this reason, I'm marking this bug dependent on 217392 . This is basically
going to require cert9.db .
2) Performing this check about nextUpdate not being expired really only makes
sense if you are verifying certs at the current date. We do have a function
called CERT_VerifyCertificateNow() . Instead of just calling PR_Now() and
passing it to CERT_VerifyCertificate(), this function could propagate a policy
argument (check CRL expiration) to its callees . This could be implemented in a
very straightforward manner (I know I have said that before, and not come up
with the patch yet, but there were other issues, read below).
Again the problem comes from the fact that we allow verifying certs at a date in
the past (S/MIME case typically), and it's not clear which CRL you need to use
for that, as it's not defined in RFCs.
If you take the example used above for the 1st part, by using the latest CRL,
you have no guarantee that are you checking the particular cert's status, since
it most likely has dropped off the CRL. So this test is actually
counterproductive in this case : we would actually want to use an older CRL - in
fact, we want the newest available CRL issued before the cert's expiration date,
not the newest CRL with nextUpdate in the future.
To be able to do that, we would want to improve the CRL cache to cache multiple
full CRL objects at different dates, rather than picking a single one CRL,
caching it, and doing all lookups from that one until a new one becomes
available. This shouldn't be too major of a change. We already keep a copy of
the DER for all relevant CRLs for an issuer in the cache, we just don't fully
decode and cache them currently if we determine they aren't the one we want to use.
Julien and I have had a discussion which is copied below this intro.
I have also posted a note to the S/MIME WG list today (Mar 8, 2004) related to
item 1) below.
Two issues are discussed: 1) the selection of what CRL is valid to use, and 2)
the validity period of CRLs (the DoD question).
For 1) I believe that trying to use “old” CRLs, although laudable in its desire
to permit the validation of old messages, is neither desirable nor a good idea
since it leads to a security vulnerability. I believe that CERT (rfc2632bis-05)
section 4.1 and rfc3280 sections 3.3 and 6.3.3 want only the “latest” crl to be
used – and “latest” must be judged based on the receiver’s sense of time, not
the signing time provided in the message (as may be the case in the current
Mozilla implementation). That is “current time” in these documents does NOT
mean “signing time”. Furthermore, no revocation check is possible for expired
certificates, and thus revocation checking should not be attempted for expired
certificates (and expiry too must be judged based on the receiver’s time, NOT
the signing time!). So I argue that only the “latest” crl should be retained
and thus only one crl is required per distribution point.
For 2) A problem also arises since the CRL does not specify its validity period,
only its “thisUpdate” and OPTIONALLY “nextUpdate”. There are extensive
discussions in the PKIX WG list on this.
Microsoft Knowledge base article 313281 says:
"The cached CRL will still be valid until it expires (by default, a
CRL's validity period extends 10 percent past the publication period)."
(I presume this is MS’s answer to the DoD question!)
Which sounds reasonable provided nextUpdate is specified. If nextUpdate is
unspecified presumably the CA has decided that a “best effort” CRL check is ok
(or the validity period is configured in some other way, possibly as a local or
certificate security policy parameter). If unknown, maybe the latest CRL is
acceptable, BUT hopefully implementers will indicate this to the user in some
way. For example displaying:
“Revocation Status : OK. Effective Date <March 5, 2004 12:12:49 PM>
Next Update <Unspecified>”
(In Outlook 2002 on XP a similar message is displayed for CRLs with nextUpdate
specified, and “Unspecified” above is replaced with the nextUpdate date/time.)
I ran a few quick tests with Outlook 2002 on XP to see what MS does.
1. I re-verified an old signed message but only providing an “old”, but
newer-than-signing-time, CRL (CRL thisUpdate after signing time, nextUpdate more
than one CRL issue period older than current receiver time, signing certificate
>> MS generates a Warning (as I hoped):
“The CRL needed to verify the signing certificate
is either unavailable or it has expired”.
So it appears that MS will not try to use an old CRL even if it was issued after
the signing time in the message.
2. I repeated above but making an up-to-date CRL available.
>> MS accepts signature without errors or warnings as expected. By opening
security properties there is an explicit Revocation Status message with
effective and next update dates and times provided (nice).
3. I re-verified an old signed message which used a certificate which is now
expired (but was signed when it was valid).
>> MS generates a big warning and appears not to bother with a crl check.
This is what I expected; my only problem is that MS seems to have varying levels
of Warnings; Warning for #3 is big and red (with an extra dialog box); while
warning for #1 is almost a minimal caution (and not visible unless you open the
security properties page).
Cheers, (below is the long winded discussion!)
TC> Tony’s original comment
JP> Julien’s reply to Tony’s original comment
TC>> Tony’s reply to the reply.
TC>The NIST/DoD requirements are similar to those which I have encountered
TC>here in Canada. There are actually two aspects to the problem: 1)
TC>selection of CRL to use and 2) validity period of CRLs. I will attempt
TC>to discuss them both below:
TC>A problem arises since the originator's signing time is not trusted.
TC>An attack is for a forger to set their local clock back to a time prior
TC>to the revocation, sign the message and enclose a then-current (old)
TC>CRL in the message. If the signing time is used to select the CRL the
TC>forger could succeed (the forger might mount a DOS attack to prevent
TC>the receiver getting a more recent CRL). A comment regarding this
TC>security vulnerability was posted by Sean Turner in the S/MIME WG list
TC>a few days ago (Mar 2, 2004, his comment #6).
JP>FYI, Mozilla Mail does not actually accept CRLs through S/MIME messages
JP>(there's a bug if you search bugzilla), so it is not subject to this
JP>On the other hand, by default, no revocation is performed (OCSP is
JP>turned off, and only local CRLs are looked up). I need to get back on
JP>the IETF mailing lists
TC>> I consider receiving CRL’s in messages of minor value anyway in S/MIME
TC>> since CRLs age so quickly compared to the lifetime of messages.
TC>This means that we MUST always select and use the most recent CRL, and
TC>it MUST not be "too old" compared with the receiver's local time sense.
TC>So there should only be one CRL per CRL distribution point and it is
TC>the "current" one (or correspondingly, the current OCSP interrogation).
TC>The current one is the one with the latest "thisUpdate" attribute
TC>value. Keeping old CRL's is unnecessary (and undesirable).
JP>That's quite a jump to conclusion there. I would say to work around that
JP>particular attack adequately, we need a trusted time source, not to
JP>enforce using the latest CRL.
TC>> Trusted time source (or trusted third party archive) would be
TC>> great but I don’t want that to be mandatory
TC>> for basic non-repudiation. I think the INTENT of revocation
TC>> using CRLs was to use the current one.
JP>Signatures in S/MIME messages in Mozilla are verified against the time
JP>in the message, not against the current time. If only the latest CRL is
TC>> I think this is a big problem.
JP>used, then old S/MIME messages - those signed with certs which are
JP>expired at the current time (but valid at the time of the message), and
JP>therefore no longer required to be listed on the latest CRL - can never
JP>be checked for revocation. Checking an old cert against the latest CRL
JP>won't help at all. For that reason, it is desirable to keep around old CRLs.
JP>The only way you can be guaranteed that you have performed *some* sort
JP>of revocation check for the cert is if you have a CRL with a thisUpdate
JP>that falls within the validity period of the cert (and, if the cert is
JP>expired, as close to its notAfter date as possible). *if* the particular
JP>serial number of the expired cert you are checking is on the latest CRL,
JP>then that's also a valid revocation check. But if it's not listed, that
JP>doesn't tell you anything. The cert may indeed have been revoked in the
JP>past, and then removed from the latest CRL because it is expired.
TC>> I believe expired certs must immediately cause an error. The
TC>> forger is not limited to attacking only during the cert validity
TC>> period. For compromises after cert expiry, the CA will not
TC>> process the revocation. So using the signing time to select the CRL
TC>> will allow a forger to succeed (even if the rightful owner knows
TC>> about it) if it is mounted after cert expiry.
JP>Unfortunately, RFCs don't cover verification at dates in the past, only
JP>at current time. But in those cases, and especially for expired certs,
JP>the latest CRL is not the one to use. For all certs that are currently
JP>valid, I agree that the latest CRL is the one to check against.
TC>There is of course a problem with determining how old "too old" is,
TC>since the CRL does not say (its unfortunate that the X.509 designers
TC>did not include notBefore and notAfter attributes). There is
TC>"thisUpdate" and optionally "nextUpdate", but "nextUpdate" is only an
TC>indicator of when the next regularly scheduled CRL will be issued.
TC>Since it will take time to get the next one, "too old" is presumably
TC>some value greater than "nextUpdate" (provided "nextUpdate" is even
JP>There are 3 cases :
JP>1) CRL has nextUpdate and currentTime <= nextUpdate
JP>The application should accept this CRL as the latest CRL.
JP>2) CRL has nextUpdate and currentTime TC> nextUpdate
JP>This CRLis not the latest. If the latest CRL is needed, then the
JP>application should attempt to fetch a newer one.
TC>> yes I agree; although since CA’s can publish a CRL at any time
TC>> some applications might choose to always try for a new CRL.
TC>> But rfc3280 does not require this.
TC>> Obviously this would lead to extra overheads so if this is made
TC>> available it should be capable of being disabled. BUT the case
TC>> where nextUpdate is not provided may require a CRL or OCSP check
JP>3) CRL has no nextUpdate
JP>In this case there is no indication whatsoever of whether the CRL is
JP>current. For all you know the CA could issue one CRL every 5 years, so
JP>maybe a CRL with thisUpdate 4 years ago is current.
JP>In this case, it is a matter of application policy to determine if it
JP>wants to accept it as the latest CRL. As currently setup, NSS will use
JP>such CRL no matter how old, as long as it is the most recent that it's
JP>got locally stored. Of course, if it did not use it, in the current mode
JP>of operation, no error would be produced - just no revocation check
JP>would be performed at all - since there is no "missing CRL" error.
TC>> I think if rfc3280 6.3.3 (a) (1) (ii) fails, you should drop to the
TC>> end of the steps and return the cert_status UNDETERMINED. I.e.
TC>> do not use old CRLs.
TC>The other issue is that you may get a new CRL even before "nextUpdate"
TC>(the CA may "push" a CRL earlier if it wishes).
JP>Yes, that's possible. But if you obtain such a CRL, you could easily
JP>determine that it is the latest CRL by doing a thisUpdate comparison
JP>between any multiple CRLs you have previously fetched. nextUpdate would
JP>have no relevance.
TC>So the ideal is to ALWAYS do a CRL or
TC>OCSP enquiry every time, even if you have a cached CRL which appears
TC>not "too old". (X.509 says: "The next revocation list could be issued
TC>before the indicated date, but it will not be issued any later than the
TC>indicated time.") This appears to be how the latest version of MS
TC>Outlook and CAPI works, they request a CRL each time (I THINK!).
TC>> NO I was wrong. If the current CRL nextUpdate is after current
TC>> time it seems to use the cached value.
JP>Currently, Mozilla does not ever request any CRLs during the cert
JP>processing. It only *checks* certs against locally stored CRLs, of which
JP>there can only be one per issuer. There is indeed a hole here that needs
JP>to be plugged in Mozilla about automatically requesting CRLs, but that's
JP>separate from bug 233806 . I believe it has been filed, but I'm not sure
JP>what the bug ID is.
TC>> I think this could be ok. It does not seem to be mandatory to always
TC>> try for a new CRL if nextUpdate is greater than current time.
JP>If that's really the way MS Outlook and CAPI works, then I would say
JP>it's bad, because it would unnecessarily overload the network in most
JP>cases, fetching the CRL each time which has not been updated. But it's
JP>possible they don't have any local storage/cache for CRLs or OCSP at
JP>all, so they have no other choice but to fetch every time. I really
JP>don't know about Outlook or CAPI. Either way, I would not consider that
TC>> Yes, sorry, I was wrong, they seem only to get CRL’s when they try
TC>> a validation and current time is after nextUpdate time.
TC>So the question about how long after "nextUpdate" should the CRL be
TC>considered too old is a good one.
JP>I would qualify this statement .
JP>So the question about how long after "nextUpdate" should the CRL be
JP>considered too old /to be the latest CRL /is a good one.
JP>The distinction is important, as I have shown above there are cases
JP>where the latest CRL is inappropriate
TC>Zero obviously will not work, so some non-zero value
TC>needs to be securely set. If "nextUpdate" is not present the problem
TC>is worse since now we need to set an offset from "thisUpdate". I have
TC>seen systems which issue CRLs every four hours and will say they are
TC>too old if they are five hours old. Presumably some systems will issue
TC>CRLs less frequently, so if issued every week one might set one week
TC>plus one day as being too old. But this will vary. Hopefully
TC>implementers will provide some secure means to set the value.
TC>> The PKIX WG list seems to imply that some CA’s may publish in advance
TC>> of nextUpdate time, setting back by the margin of time needed.
TC>> That way when the client reaches its own sense of nextUpdate time,
TC>> it will always succeed in getting a new CRL. I don’t know if any
TC>> CAs are actually doing that.
JP>In the past, I created such configuration settings at the application
JP>level (in AOL's version of Netscape Enterprise Server 6.1). The check
JP>for CRL "age" occurred at the time of the CRL download though, not at
JP>the time of the certificate verification against that CRL.
TC>For client processing I think the situation can be simplified to the
TC>1. If the certificate is expired, no CRL (or OCSP) check need be done
TC>- it would be useless anyway since the CA does not guarantee keeping
JP>That's fine in the context of verifying server certs during SSL
JP>connections, where server certs are always verified against the current
JP>That's also fine in the context of S/MIME messages used in real-time,
JP>such as in AOL's Instant Messenger when using secure mode. That's not
JP>acceptable for non-real time S/MIME e-mail messages, which
JP>signatures are already in the past when they are received.
JP>Say you read an S/MIME signed e-mail on monday evening, dated 6pm that
JP>day, and written by a colleague. His cert is valid, the signature is
JP>valid, you have the latest CRL and the cert is not revoked. The message
JP>shows as valid in your e-mail client. But it's time to go home so you
JP>put the e-mail aside to read the next morning.
JP>You may come in tuesday at 9am and reopen the same message. Your
JP>colleague's certificate just expired this morning at 8am. Should your
JP>mail client flag that message as invalid due to the cert being expired
JP>at the time it's being read, as opposed to the time it's been written ?
JP>Currently, the answer in Mozilla mail is no. The signature is checked
JP>against the message's date, so the message will still show as valid. If you
JP>want a different policy for this case, then you should file an
JP>enhancement request against PSM (S/MIME component), which would
JP>basically be a preference setting to "verify all e-mail messages at the
JP>current time" if you don't trust the time in the message (and I
JP>understand your concern, since the e-mail timestamps aren't secure).
TC>> This would be very nice, but I think the security penalty is too big.
JP>Let's go back to the revocation checking. I have already discussed at
JP>length how NSS checks signatures in real-time (which would be done if
JP>you had this new e-mail setting to always verify at the current time),
JP>so I won't do it again. In this case, the real-time revocation check
JP>would fail, because real-time revocation information for the certificate
JP>is unavailable (CRL and OCSP are no longer required to give status for
JP>However, a retroactive revocation check may pass. And this is where the
JP>waters get murky :
JP>Some non real-time revocation information may be available. For instance
JP>: the user could have an older locally stored CRL (or locally cached
JP>OCSP response, if NSS supported it) with a thisUpdate before the cert's
JP>notAfter, ie. a CRL that is supposed to list the cert that signed the
JP>message if it has been revoked. This is then subdivided into two cases :
JP>a) the locally available CRL has a thisUpdate before the S/MIME
JP>message's date (fetched before the user left his desk, the day before) ; or
JP>b) the locally available CRL has a thisUpdate after the S/MIME message's
JP>date (perhaps the user left his desk after 6pm, obtained the CRL for
JP>some reason such as the Mozilla periodic CRL auto-update, but didn't
JP>check his e-mail at that time)
JP>It's not clear whether either CRL is acceptable for this retroactive
JP>revocation check, as the RFCs certainly don't discuss it. I would tend
TC>> I think the bottom line is that key support vanishes at the end
TC>> of the cert validity period and thereafter the certificate has
TC>> marginal status. If status is to continue, you need to
TC>> submit the message (prior to cert expiry) to a trusted time stamp
TC>> server or trusted archive or something.
JP>to say that the b) case gives me a higher level of confidence than a),
JP>but the only way I would be 100% confident the cert was never revoked is
JP>if the thisUpdate of the CRL was equal to the notAfter of the cert
JP>(which is very unlikely to be the case).
JP>Currently, when performing the retroactive revocation check however, NSS
JP>uses the one and only locally available CRL, which is the one with the
JP>most current thisUpdate. It therefore may have a thisUpdate past the
JP>notAfter of the cert, and would therefore not be guaranteed to list the
TC>This situation should result in a warning to the user to this effect,
TC>potentially with the note that revocation checking is not possible in
TC>this situation (there may be additional reasons to warn the user, e.g.
TC>use of certificates beyond expiry may violate security policy).
JP>But the cert may not have been used beyond expiry at the time the
JP>message was written. It's just getting verified after expiry. I'm not
JP>aware of a programmatic way to check the security policy and enforce
JP>this. It would be appropriate to warn the user if there was one.
TC> Any attempt to
TC>backtrack in time to get an old CRL, etc. inherently implies we trust
TC>the signing time - which we cannot.
JP>Trusting the time should be an application setting, given that I haven't
JP>seen deployed secure time checking for e-mail and not trusting the time
JP>will just result in lots of e-mail messages not verifying and puzzled
JP>users, not necessarily for good reasons. There are other ways to check
JP>for the client to check time, which don't necessarily involve PKI at
JP>all. Eg. the mail client can be configured to filter e-mails with a date
JP>in the future or in the past with a certain offset, relative to the time
JP>they are downloaded (unfortunately, I don't believe Mozilla has a way of
JP>doing this, but it seems to be a much easier solution to the problem
JP>with far less infrastructure changes, even though I agree it is less
JP>That said, if you can point out some specs & actual deployments of
JP>secure timestamping for e-mail, it would definitely be a good thing to
JP>add to NSS / Mozilla Mail to plug this hole.
TC>2. If the certificate is not expired, and a cRLDistributionPoints
TC>extension is present in the certificate, the most recent and not "too
TC>old" CRL is used or an OCSP server (as specified in the cert) accessed.
TC>There are three outcomes: 1) cannot find current-CRL/OCSP (cannot do
TC>what is specified in the cert or CRL too old); 2) status revoked; and
TC>status not-revoked. The first outcome should be a warning ("unable to
TC>obtain revocation status"), the second a broken pen ("certificate/key
TC>revoked"), the third potentially an unbroken pen.
JP>It would indeed be valuable to have this info is current CRL/OCSP info
JP>is unavailable, but the warning should probably be a setting rather than
TC>3. The definition of "too old" must be configurable either as an
TC>offset from "nextUpdate", if present, or "thisUpdate" if the
TC>"nextUpdate" attribute is not present in the CRL.
TC>> could also be certificate security policy certificate entry.
JP>While these settings may be desirable, it seems to me they would vary
JP>for each CA, since they can have very different cert and CRL issuing
This is a RFE that will most likely result in new APIs. Targetting for 3.10 .
Retargetting for 3.12 .
Retargetting for 3.12 .
libpkix APIs will allow the NIST policy to be set.
We should also make sure that we can configure these settings via public NSS
APIs once libpkix is integrated.
Removing pkix from whiteboard.
This bug is not specifically about libpkix.
It may be implemented as an enhancement to libpkix.
This bug requests that NIST's CRL policy be implemented/supported.
bug 390502 complains that libPKIX *ALWAYS* enforces NIST's CRL policy.
So, is this bug effectively fixed by libPKIX?
I would say yes. The remaining part is have the switch to turn it off, which is bug 390502 .