Changes

Jump to: navigation, search

NSS Shared DB

9,929 bytes added, 00:53, 5 February 2008
Database Upgrade
==== Database Upgrade ====
NSS has traditionally performed automatic updates when moving to new database formats. If NSS cannot find a database that matches it's current database type, it looks for older versions of it's database and automatically updates those versions to the new database version. In these cases database upgrade is automatic and mandatory for all applications.
In the shared database design, upgrade is no longer mandatory. Applications
may choose to continue to use the old DBM database, update to use the new shared database from old DBM databases, or update and merge old DBM database into a new location shared by multiple apps. There is still a desire for this update to be automatic, at least as far as the application user is concerned. The following describe how NSS deals with update in different applications , and what the different applications must do to get the correct update behavior.
To understand the issues of migration to the Shareable Database version of NSS from the traditional (legacy) versions, we group applications that use the new version of NSS into three 'modes' of operation, and into two types for a total of five valid combinations (Mode 1 B is not valid)..
Changes to aid in update
====== Type A: ====== Type A applications are new versions of applications that existed before NSS supported sharable databases. They have existing legacy NSS databases. The new versions of these applications have been upgraded to the new NSS that supports shareable databases. If they intend to share the contents of those old databases, they need to merge the old database contents into the new ones.
All Mode 1 applications are type A and need nssdbm3 at all times. Mode 2 and Mode 3 applications of Type A need nssdbm3 to upgrade from the old legacy DBM databases to the new shareable databases. Mode 3 Type A applications need libnssdbm3 to merge data from legacy DBM databases into shareable ones. Mode 2 and Mode 3 type A applications do not need nssdbm3 except for upgrading and merging data from old legacy databases.
====== Type B: ====== Type B applications are applications that never used any old version of NSS that supported only DBM databases. All NSS databases used by Type B applications are sharable databases. There are no legacy DBM databases for Type B applications. All Type B applications are either Mode 2 or Mode 3.
Type B applications do no database upgrades, and do not need nssdbm3.
 
=====How Applications Use Upgrade=====
 
Upgrade only applies to Mode 2 Type A apps (Mode 2A) and Mode 3 Type A apps. (Mode 3A).
NOTE: While database Upgrade may involve a merge (mode 3), database upgrade is not merging. See the section on how to manage merging databases.
====== Mode 1 ======
Mode 1 Applications can continue to call the traditional NSS_Initialize() function without changes. Mode 1 applications which need to guarantee that they open only old DBM databases should prepend the string "dbm:" to the directory path passed to NSS in the configdir parameter of NSS_Initialize().
====== Mode 2 2A ======Mode 2 2A Applications can also continue to call traditional NSS_Initialize() functions. The should, however, prepend the string "sql:" to the directory path passed to NSS in the configdir parameter. If the sql databases do not exist, NSS will automatically update any old DBM databases in the config directory to shared databases. Like the upgrade from cert7 to cert8, if the update does not work, the app will open and use the old DBM database. Upgrade will not happen if
# NSS is opened readOnly.
# NSS_Initialization fails.
Applications can avoid final case of failure by forcing the user to authenticate to softoken using PK11_Authenticate().
Sample code fragment.
====== Mode 3 ======
}
<pre>
 
==== Layering ====
 
In order to keep clean separation between the data and database operations, we will continue to maintain an layer between the actual data handling and interpretation and the database itself. The database code will not need to understand:
 
#What objects are actually stored in it.
#The types of the attributes.
#The meaning of the stored data.
 
Softoken (not the database adapter layer) will manage canonicalizing any CK_ULONGs, encrypting or decrypting private data blobs, checking integrity and deciding what attributes an object should have and setting the appropriate defaults if necessary.
 
Since softoken deals with PKCS #11 templates internally, its interface to the database will be in terms of those templates.
 
The database layer must be multi-thread safe. If the underlying database is not thread safe, sdb_ layer must implement the appropriate locking.
 
===== s_open =====
 
The database API consists of an initialization call, which returns an SDB data structure (defined below).
 
CK_RV
s_open(const char *directory, const char *certPrefix, const char *keyPrefix,
int cert_version, int key_version, int flags,
SDB **certdb, SDB **keydb, int *newInit)
 
The sdb_init function takes:
 
* directory full path to where the database lives.
* certPrefix a prefix string to add in front of the key and cert db (if keyPrefix is null), null means add no prefix.
* keyPrefix a prefix string to add in front of the key db. Null means use the same prefix as the cert db.
* cert_version current version is the current database version
* key_version is the current key database version
* flags are:
** FORCE
** READONLY
** READ/WRITE/CREATE
* certdb is the returned cert SDB structure
* keydb is the returned key SDB structure
* newInit returns 1 of s_open created new instances of cert and key (used for update).
 
The returned SDB structure has the following format:
 
typedef struct SDBStr SDB;
 
struct SDBStr {
void *private;
void *sdb_app_private;
int sdb_type;
int sdb_flags;
int sdb_version;
CK_RV (*sdb_FindObjectsInit)(SDB *sdb, const CK_ATTRIBUTE *template,
int count, SDBFind **find);
CK_RV (*sdb_FindObjects)(SDB *sdb, SDBFind *find, CK_OBJECT_HANDLE *ids,
int arraySize, int *count);
CK_RV (*sdb_FindObjectsFinal)(SDB *sdb, SDBFind *find);
CK_RV (*sdb_GetAttributeValue)(SDB *sdb, CK_OBJECT_HANDLE object,
CK_ATTRIBUTE *template, int count);
CK_RV (*sdb_SetAttributeValue)(SDB *sdb, CK_OBJECT_HANDLE object,
const CK_ATTRIBUTE *template, int count);
CK_RV (*sdb_CreateObject)(SDB *sdb, CK_OBJECT_HANDLE *object,
const CK_ATTRIBUTE *template, int count);
CK_RV (*sdb_DestroyObject)(SDB *sdb, CK_OBJECT_HANDLE object);
CK_RV (*sdb_GetPWEntry)(SDB *sdb, SDBPasswordEntry *entry);
CK_RV (*sdb_PutPWEntry)(SDB *sdb, SDBPasswordEntry *entry);
CK_RV (*sdb_Begin)(SDB *sdb);
CK_RV (*sdb_Commit)(SDB *sdb);
CK_RV (*sdb_Abort)(SDB *sdb);
CK_RV (*sdb_Reset)(SDB *sdb);
CK_RV (*sdb_Close)(SDB *sdb);
};
 
where:
 
* private is a pointer to opaque private data specific to the Shared DB implementation.
* sdb_type is the type of database (key [aka private] or cert [aka public]).
* sdb_flags specifies how the database was opened (ReadOnly, Create, etc).
* sdb_version specifies the version of the underlying sdb structure. This allows us to handle future expansion of the sdb data structure safely.
* The rest are function pointers to database primitives described next.
 
===== sdb_FindObjectsInit =====
 
CK_RV (*sdb_FindObjectsInit)(SDB *sdb, const CK_ATTRIBUTE *template,
int count, SDBFind **find);
 
This function is the equivalent of PKCS #11 C_FindObjectsInit(). It returns a SDBFind context with is opaque to the caller. The caller must call sdb_FindObjectsFinal with this context if sdb_FindobjectsInit succeeds.
 
===== sdb_FindObjects =====
 
CK_RV (*sdb_FindObjects)(SDB *sdb, SDBFind *find, CK_OBJECT_HANDLE *ids,
int arraySize, int *count);
 
This function is the equivalent of PKCS #11 C_FindObjects(). It takes a SDBFind
context returned by sdb_FindObjectsInit. This function has the same semantics as C_FindObjects with respect to handling how many objects are returned in a single call.
 
===== sdb_FindObjectsFinal =====
 
CK_RV (*sdb_FindObjectsFinal)(SDB *sdb, SDBFind *find);
 
This function is the equivalent of PKCS #11 C_FindObjectsFinal(). It frees any resources associated with SDBFIND.
 
===== sdb_GetAttributeValue =====
 
CK_RV (*sdb_GetAttributeValue)(SDB *sdb, CK_OBJECT_HANDLE object,
CK_ATTRIBUTE *template, int count);
 
This function is the equivalent of PKCS #11 C_GetAttributeValue(). It has the
same memory allocation and error code semantics of the PKCS #11 call.
The attributes passed to sdb_GetAttributeValues are already transformed from
their native representations in the following ways:
 
# CKU_LONG values are stored as 32-bit values in network byte order.
# Private attributes will be encrypted.
 
===== sdb_SetAttributeValue =====
 
CK_RV (*sdb_SetAttributeValue)(SDB *sdb, CK_OBJECT_HANDLE object,
const CK_ATTRIBUTE *template, int count);
 
This function is the equivalent of PKCS #11 C_SetAttributeValue().
The attributes returned to sdb_SetAttributeValues are transformed from
their native representations in the following ways:
 
# CKU_LONG values returned 32-bit values in network byte order.
# Private attributes returned encrypted.
 
===== sdb_CreateObject =====
 
CK_RV (*sdb_CreateObject)(SDB *sdb, CK_OBJECT_HANDLE *object,
const CK_ATTRIBUTE *template, int count);
 
This function is the equivalent of PKCS #11 C_CreateObject(). The value of 'object' is chosen by the implementer of sdb_CreateObject. This value must be unique for this sdb instance. It should be no more than 30 bits long.
 
===== sdb_DestroyObject =====
 
CK_RV (*sdb_DestroyObject)(SDB *sdb, CK_OBJECT_HANDLE object);
 
This function is the equivalent of PKCS #11 C_Destroy object(). It removed the object from the database.
 
===== sdb_GetPWEntry =====
 
CK_RV (*sdb_GetPWEntry)(SDB *sdb, SDBPasswordEntry *entry);
 
Get the password entry. This only applies to the private database.
 
===== sdb_PutPWEntry =====
 
CK_RV (*sdb_PutPWEntry)(SDB *sdb, SDBPasswordEntry *entry);
 
Write the password entry. This only applies to the private database.
Writing a password entry will overwrite the old entry.
 
===== sdb_Begin =====
 
CK_RV (*sdb_Begin)(SDB *sdb);
 
Begin a transaction. Any write to the database (sdb_CreateObject, sdb_DestroyObject, sdb_SetAttributeValue) must be accomplished while holding
a transaction. Transactions are completed by calling sdb_Commit to commit the change, or sdb_Abort to discard the change. More than one write operation may be made while holding a transaction. Aborting the transaction will discard all writes made while in the transaction.
 
===== sdb_Commit =====
 
CK_RV (*sdb_Commit)(SDB *sdb);
 
Commit a transaction. Any write to the database (sdb_CreateObject, sdb_DestroyObject, sdb_SetAttributeValue) must be accomplished while holding
a transaction. Transactions are completed by calling sdb_Commit to commit the change, or sdb_Abort to discard the change. More than one write operation may be made while holding a transaction.
 
===== sdb_Abort =====
 
CK_RV (*sdb_Abort)(SDB *sdb);
 
Abort a transaction. Any write to the database (sdb_CreateObject, sdb_DestroyObject, sdb_SetAttributeValue) must be accomplished while holding
a transaction. Transactions are completed by calling sdb_Commit to commit the change, or sdb_Abort to discard the change. More than one write operation may be made while holding a transaction. Aborting the transaction will discard all writes made while in the transaction.
 
===== sdb_Close =====
 
CK_RV (*sdb_Close)(SDB *sdb);
 
Close the SDB and free up any resources associated with it.
 
===== sdb_Reset =====
 
CK_RV (*sdb_Reset)(SDB *sdb);
 
Reset zeros out the key database and resets the password.
 
==== legacy DB support ====
 
The old dbm code can be supported with the above SDB structure with the following exceptions:
 
# The old db code cannot be extensible (can't dynamically handle new types).
# A private interface may be needed to unwrap the private keys, or provide a handle to the password so the keys can be presented in the attribute format.
 
This code would live in its own shared library, called lgdbm (with the appropriate platform semantics, lgdbm.dll on windows, liblgdbm.so on unix, etc). Most of the low level cert, CRL, key handling, and translation to PKCS #11 objects and attributes that was part of softoken will moved to this legacy shared library. When access to old databased are needed, the lgdbm shared library will be loaded, and the following symbols will be dynamically found:
* legacy_Open - This has the same signature as s_open and returns SDB handles for the legacy database.
* legacy_ReadSecmodDB, legacy_ReleaseSecmodDBData, legacy_DeleteSecmodDB, legacy_AddSecmodDB - These functions provide access to the old secmod databases.
* legacy_Shutdown - This is called when NSS is through with all database support (that is when softoken shuts down).
* legacy_SetCryptFunctions - This is used to set some callbacks that the legacy db can call to decrypt and encrypt password protected records (pkcs8 formatted keys, etc.). This allows the legacy database to translate it's database records to the new format without getting direct access to the keys.
 
NSS will automaticall load the legacy database support under the following conditions:
 
# The application requests that the old databases be loaded (either implicitly or explicitly).
# The application request that new databases are loaded, but the new databases do not exist and the old databases do.
 
[[Category:NSS]]
==== Layering ====
439
edits

Navigation menu