Patrick,

Cesard, Patrick O. wrote:

Thanks.

I assume I don't need to first import the CRL in the NSS cert DB before
using the CERT_DecodeDERCRLWithFlags function; all I need to provide are the
CRL raw bytes (e.g., read from a file), correct?
If you just want to decode it, you can simply read the CRL from a file and decode it, without importing it to the database or to any other token.

Also, it looks like I need to use the CERT_CompleteCRLDecodeEntries function
to actually get to the list of revoked certs.
This function was added because partial CRL decoding was introduced in NSS 3.6 . The partial decoding is present because many applications don't look at need at the entries, but they need to verify if they have a valid CRL in a short amount of time. This is the case for example in the browser, before importing a CRL and prompting the user to do the import or not. When using partial decoding, the CRL is fully decoded except for the entries. This makes the decoding a very short fixed-time operation regardless of the size of the CRL, thanks to the new QuickDER decoder.

To do a partial decoding, use CERT_DecodeDERCrlWithFlags with a flag of CRL_DECODE_SKIP_ENTRIES . This will decode everything but the entries. If you then want to decode the entries, you can call CERT_CompleteCRLDecodeEntries.

Otherwise, if you pass CRL_DECODE_DEFAULT_OPTIONS in the decode flags (which is zero), then a full decoding will be performed, including the entries. You can call CERT_CompleteCRLDecodeEntries if you wish in that case, but it won't have any effect since the entries are already decoded.

If I did first import the CRL in the NSS cert DB (e.g., using crlutil), how
much of a performance hit would I take when reading the CRL back out for
parsing, versus decoding CRL straight from a file? I assume the crlutil tool
uses your improved CRL decoding function when importing.
Yes, crlutil in NSS 3.6 uses the new optimized functions.

Where does NSS do the actual checking of a CRL for the revocation status of
a particular certificate?
The functions to call are CERT_VerifyCertificate and CERT_VerifyCertificateNow . Both are new in NSS 3.6 and should be used in place of the obsolete CERT_VerifyCert and CERT_VerifyCertNow calls (which are still supported).
All four of these functions will automatically search all PKCS#11 modules for a CRL applicable to a certificate, and, if one is found, will check the cert's serial against it. If the cert cannot be verified due to revocation, the function will fail and you can check the error using PR_GetError(). The error will be SEC_ERROR_REVOKED_CERTIFICATE .

The actual revocation check is performed in certdb/crl.c in a function called CERT_CheckCRL, which is not currently a public function and is only called from the certificate verification functions I mentioned in the previous paragraph.

As you can see, the 4 certificate verification functions do not let you pass a pointer to a CERTSignedCrl object. They currently only use the CRLs found in PKCS#11 tokens.

This means that if you want to do a certificate verification against the CRL, then the CRL should be imported to a PKCS#11 token.

While it is possible for you to write a simple revocation checking function that would take a newly-decoded CERTSignedCrl*, I recommend that you don't try.

The reason is that I added a CRL cache in NSS 3.6, which is going to be more efficient than any simple verification function you could write.

The CRL cache ensures that the CRL only gets fetched from the PKCS#11 token and decoded once - the first time you verify a a certificate from a given issuer. After that, the decoded version of the CRL is cached in memory, and you can verify more certificates without the CRL ever having to be decoded again. As long as the CRL is stored in a token, this will all happen transparently during the certificate verification, without your higher-level code having to know anything about CRLs.

The cache also goes one step further in optimizing the performance of revocation checking. In previous versions of NSS, the CRL was only represented as an array of CRL entries - each consisting of a serial number, revocation date, and optional reason code. This meant that a linear search was required through the array to verify a certificate. For a good certificate, which serial number didn't appear on the CRL, the entire array needed to be traversed. On the benchmark CRL we used containing 1.2 million serial numbers, this full traversal could take a full second of peaking the CPU on the 440 MHz machine.

To resolve this performance problem, the CRL cache provides an additional hash table which allows a fixed-time lookup of the serial number in the CRL, whether the cert is revoked or not.

I have measured that once the CRL is decoded and in the cache, a full certificate revocation check can happen in about 50 microseconds on the aforementioned 440 MHz system - or about 17 microseconds on the 2.2 GHz Xeon CPU system I'm using to type this.

To be able to take advantage of the performance improvements from the CRL cache, you need to use the NSS certificate verification functions mentioned above, and the CRL must be present in a PKCS#11 token.

It should be noted that the official PKCS#11 specification doesn't currently include CRLs. We (Netscape) defined extensions to support this. Only the NSS certificate database (softoken) and some other internal Netscape proprietary PKCS#11 modules currently support these PKCS#11 CRL extensions. So at this time, your only option is to import your CRL to the database. The crlutil tool will allow you to do that.

You can then start your NSS application against that database containing the CRL, and simply call the certificate verification functions. The CRL check will be automatically performed. The first time you verify a certificate from your CA, NSS will transparently read the CRL from the database, decode it, and put it in the cache along with the hash table. So your first verification will take a long time. Subsequent certificate verifications however will be very short. The 50 microseconds revocation check time is actually negligible compared to the rest of the certificate verification. With a cerificate containing a 1024 bit RSA key, the signature verification will take over 500 microseconds. With a 2048 bit key it will be much longer. So basically the CRL check will be invisible overhead after your first verification.
Note that in versions of NSS before 3.6 that didn't have the CRL cache, the CRL was pulled from the tokens, decoded, and freed, for every certificate verification. Needless to say, the performance with that method was not impressive and this is why the CRL cache was added.


-- POC


-----Original Message-----
From: Julien Pierre [mailto:jpierre@;com.netscape.netscape.com]
Sent: Tuesday, October 29, 2002 5:51 PM
To: [EMAIL PROTECTED]
Subject: Re: CRL parsing, in C


Patrick,

POC wrote:


>Does mozilla have a API I could use to parse through a CRL? I'm
>currently using Sun's CertificateFactory and calling the generateCRL()
>method but I find it very slow when dealing with large CRLs > 1
>MB...Moreover if I build a list of such CRL objects, my JVM runs out
>of memory!
>
>I'm ready to try a C API..
>
>I looked at the NSS command crlutil, but that tool is geared around
>the CRL being first imported in the NSS cert DB.
>
>-- POC


The recently-released NSS 3.6 contains improved CRL decoding.
The function you want to look at is called CERT_DecodeDERCRLWithFlags .

One of its current limitations is that it can only deal with full CRLs.
Delta CRLs, or CRLs containing issuing distribution point extensions, or
freshest CRL extensions, currently cannot be decoded with this API. It
is likely that this extra functionality will only become available in
NSS 4.0. The additional work is not scheduled for the next version of
NSS, which is NSS 3.7 .

If it is acceptable to you to decode only full CRLs, then the C API
should meet your performance need. To give you an idea of how fast the
decoding the NSS CRL decoding API has become in NSS 3.6, it is now
capable of decoding a 26 MB CRL containing 1.2 million revoked
certificate entries in under 8 seconds on a low-end 440 MHz Ultrasparc
II machine. This is about 6 times as fast as in previous versions of
NSS. It also needs about 1/4 as much RAM as before to do the decoding -
which is still an additional 35 MB of memory, on top of the 26 MB DER
source CRL. Both improvements are the result of a new ASN.1 DER decoder
I wrote for NSS 3.6, called the "QuickDER" decoder (see
SEC_QuickDERDecodeItem if you are interested). Documentation on that new
decoder - as well as on the old, less efficient SEC_ASN1DecodeItem -
will be written in upcoming months. But you don't need to use the
ASN.1/DER decoder directly to decode a CRL. The cert.h header file
should contain sufficient documentation on how to call
CERT_DecodeDERCRLWithFlags .



Reply via email to