![]() |
Content Version Numbers in the Certificate DatabaseNewsgroup: netscape.public.mozilla.cryptoTechnical contact: Frederick Roeber Yell at the manager: Bob Lord NSS has traditionally contained a set of pre-trusted root certificates provided by a few root certificate authorities. These authorities and the basic trust information can be seen in the Communicator Security Advisor (click on the lock), under "Certificates / Signers." Some companies consider their certificates "proprietary software," so we had to sanitize out their roots and replace them with a couple sample certificates to illustrate how the code works. See the file lib/cert/certinit.c. In the original codebase, all certificate and trust information is kept in the certificate database (e.g., "cert7.db"). The physical format of this database is described here. Upon NSS initialization, this database would be created or updated with the built-in information. (This information proved much more dynamic than originally expected; in the future, we wish to move this basic trust info to one or more specific "data-only" PKCS#11 modules: see the code in lib/ckfw/builtins/). The code that creates or updates the database is in lib/cert/certinit.c. Specifically, "CERT_InitCertDB" creates a new database, and "CERT_AddNewCerts" updates the database when a new version of the client is run with an old database. The certificates are stored in base64 form in static char arrays. The array "initialcerts" provides instructions on updating a database.
This is an array of structures with the following format:
typedef struct {The cert field points to the base64-encoded cert. The nickname contains the text name that appears in the security advisor. The trust field contains the basic trust bits for the three subjects of SSL, S/MIME, and object signing. Usually three flags have to be set: CERTDB_VALID_CA, CERTDB_TRUSTED_CA, and CERTDB_NS_TRUSTED_CA. (These flags are defined in lib/cert/certdb.h). The update version is the content version number at which this entry appeared. The code's version is CERT_DB_CONTENT_VERSION in certdb.h. The op is the update operation to perform, usually certUpdateAdd or certUpdateAddTrust. Finally, the trustDelta field is used for some update operations. When the database is being updated, CERT_AddNewCerts loops through the initialcerts array. Any entry with an updateVersion greater than the ContentVersion field in the database is acted upon. The certUpdateOp operations are:
ExampleAs an example, let us suppose that the first version of the NSS code contained two root CA certificates from Example.com: one for server certs, and one for individual certs. Originally, they wanted the first to be trusted for SSL server authentication, and the second for s/mime and object signing. The first version of the code would look like this:In certdb.h: #define CERT_DB_CONTENT_VERSION 1In certinit.c: static char example_com_server_ca[] = "....";Then let us suppose that Example.com received export approval to issue step-up server certs, and they also decided that they'd prefer to have a third root specifically for object signing. The next version of the code might look like this: In certdb.h: #define CERT_DB_CONTENT_VERSION 2In certinit.c: static char example_com_server_ca[] = "...."; One dimensionalThis scheme -- which admittedly grew over time -- worked when there was a one-dimensional sequence of the Netscape client products. Unfortunately, this scheme is not going to work if NSS is used in multiple divergent clients. In particular, we're afraid someone will write a program based on NSS, add their own root cert to their code (incrementing the database content version number) and release that program. Anyone else who makes a program with a similarly-numbered change (including future versions of Netscape, iPlanet, or mozilla.org programs) would find that their root trust information would not update properly. The only way this would work is if we all coordinated database content version numbers, which I don't think will be workable, especially in the long run.Going forwardLuckily, we had already been planning on moving to a better system. We would like to move all sources of data -- the local database, ldap servers, these builtins, etc. -- to "data-only" PKCS#11 modules. This is in fact why we wrote the "Cryptoki Framework" in lib/ckfw. Different products could release small modules with their own trusted roots, and users could install any number of these from various sources.We have defined a PKCS#11 "trust object" definition. The
current code does not yet make use of "trust objects," but adding
that soon will allow the code to use these external data modules even before
the databases are replaced.
|
|
|
Copyright © 1998-2000 The Mozilla Organization.
Last modified February 11, 2000. |
|