As discussed in our monday meeting, the NIST tests use the following policy for CRLs : 1) if a CRL for an issuer is not present, this is considered an error (cert revoked). 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 information available. 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 those policies.
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. Examples : 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 unexpired). >> 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!) Tony >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>. 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>particular vulnerability. 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 TC>present). 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 TC>> always. 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 JP>behavior desirable. 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>following: 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 TC>revocation info. 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>time. 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>that cert). 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 JP>cert. 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>secure). 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 JP>unconditional. 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 JP>periods .
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.
Julien, 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 .