NSS Shared DB
Applications have been chaffing at the restrictions of the current NSS database for quite some time now. In 2001 we built some tools to work around those restrictions so certain applications could share the database if they supplied their own shared database implementation, and configured NSS to use that implementation. Today we have a process level, ACID, open source, and widely available database called SQLite. In addition, there is a strong desire to make NSS the system security service for Linux. I am proposing how we could leverage this database to give all of our applications Shared Database access.
Where we are today
At initialization time, NSS currently takes an argument which points to some directory the application uses to store it's private configuration data. NSS uses 3 libdbm files in that directory:
- cert8.db - stores publicly accessible objects (certs, crls, smime records).
- key3.db - stores the private keys.
- secmod.db - stores the pkcs #11 module configuration.
In addition:
- NSS may also use a directory called cert8.dir to store very large blobs (typically large CRLs).
- NSS may read from from previous certificate database and build a new cert8.db it it doesn't exist.
These files are all accessed through the softoken, making libsoftokn3.so the only NSS library that needs to link with libdbm.
If the directory argument passed to NSS starts with the string 'multiaccess:', NSS does not use it as a directory path. Instead, NSS parses the string out as follows:
multiaccess:appName[:directory]
Where:
multicaccess is a keyword.
appName is a unique string for each group of applications which share the database.
directory is an optional parameter pointing to an NSS non-shared database which NSS will use to update the shared database from on loading.
NSS will find librdb.so (rdb.dll on windows) in it's patch and load it. This shared library is expected to implement a small superset of the standard libdbm interface. The main entry point is rdbopen, which will pass the appName, database name, and open flags. The rdb shared library will pick a location or method to store the database (it may not necessarily be a file), then handle the raw db records form NSS. The library does not do any formatting of the data.
What we want to do
We want to move key3 and cert8 into a new SQL databases called key4.db and cert9.db. This database will store the PKCS #11 objects currently stored in cert8 and key3. The schema for the database will be simple. Each row will represent an object. The row schema will contain the the Object ID and the list of known Attribute Types. Newer versions of NSS may add new attribute types on the fly as necessary. The Attribute values will be stored as binary blobs. Attributes that represent CK_ULONG values will be stored in network byte order. All other objects, byte order is already specified by PKCS #11. Private attributes will be encrypted with a pkcs5 PBE in the same way private and secret keys are encrypted today. Optionally the databases could be combined into a single database, cert9.db.
In order to maintain binary compatibility, I propose extending the keyword usage in NSS as follows:
multiaccess:appName[:directory] works as it does today, including using the cert8/key3 record version.
dbm:directory opens an existing non-shared libdbm version 8 database.
sql:directory1[:directory2] opens a shared database, cert9.db (& key4.db) in directory1 if cert9.db does exist. If the database does not exist, then directory2 is searched for a libdbm cert8.db and key3.db. If directory2 is not supplied, directory1 is searched.
extern:directory open a sql-like database by loading an external module, a. la. rdb and multiaccess:. This option would not be implemented in the initial release, but the extern: keyword would be reserved for future use.
Plain directory spec. For binary compatibility, we can treat the plain directory spec as the same as dbm:directory. In this case applications will not need to change for this release of NSS. (particularly unfriendly applications that want to tweak with the actual database file). Alternatively, we could treat it as sql:directory. In this case existing applications will get the benefits of shared databases immediately, though we risk breaking those aforementioned applications.
When accessing the dbm: and multiaccess: directories, external shared library will be loaded with knows how to handle these legacy databases. This allows us to move much of the current mapping code into this shared library.
Secmod.db
In the dbm: and multiaccess: cases, there will be no changes to secmod.db.
In the sql: case, a new flat text file of the format specified in the PKCS #11 working group, but not yet included in any spec. This file will be opened, locked, used, then closed (much like the current secmod.db). The file will live in the same directory as cert9.db/key4.db.
Rational:
- dbm: - current semantic. Some applications may want to preserve it. It at least gives us the ability to manage old databases with the new version of NSS.
- sql: - this is the semantic that many servers, or applications with special requirements as far as keeping their key material separate. It is quite likely
User App Initialization and System App Initialization
In order for applications to control sharing of keys and certificates, they will need to agree to 'rondevue' to the same directory. In addition, common user apps will want to share a common view of system wide root certificate lists and PKCS #11 modules. Rather than surfacing that view down into the PKCS #11 module (which is effectively is what is happening with the current rdb module), NSS will supply new NSS initialization wrappers which will automatically open the current system's view of where user and system keys and certs should be.
Other issues
Question, should we 'mark' old cert8/key3 databases as having been used to upgrade the shared database? The issue here is applications that were once separated, but now combined. It would be nice if the keys and certs in each of these databases were properly merged into the overall shared database.