1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is Red Hat, Inc.
16 * The Initial Developer of the Original Code is
18 * Portions created by the Initial Developer are Copyright (C) 2005
19 * the Initial Developer. All Rights Reserved.
22 * Robert Relyea (rrelyea@redhat.com)
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * This file implements PKCS 11 on top of our existing security modules
40 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
41 * This implementation has two slots:
42 * slot 1 is our generic crypto support. It does not require login.
43 * It supports Public Key ops, and all they bulk ciphers and hashes.
44 * It can also support Private Key ops for imported Private keys. It does
45 * not have any token storage.
46 * slot 2 is our private key support. It requires a login before use. It
47 * can store Private Keys and Certs as token objects. Currently only private
48 * keys and their associated Certificates are saved on the token.
50 * In this implementation, session objects are only visible to the session
51 * that created or generated them.
64 #ifdef SQLITE_UNSAFE_THREADS
66 * SQLite can be compiled to be thread safe or not.
67 * turn on SQLITE_UNSAFE_THREADS if the OS does not support
68 * a thread safe version of sqlite.
70 static PRLock
*sqlite_lock
= NULL
;
72 #define LOCK_SQLITE() PR_Lock(sqlite_lock);
73 #define UNLOCK_SQLITE() PR_Unlock(sqlite_lock);
76 #define UNLOCK_SQLITE()
84 struct SDBPrivateStr
{
85 char *sqlDBName
; /* invarient, path to this database */
86 sqlite3
*sqlXactDB
; /* protected by lock, current transaction db*/
87 PRThread
*sqlXactThread
; /* protected by lock,
88 * current transaiction thred*/
89 sdbDataType type
; /* invariant, database type */
90 char *table
; /* invariant, SQL table which contains the db */
91 PRLock
*lock
; /* invariant, lock to protect sqlXact* fields*/
94 typedef struct SDBPrivateStr SDBPrivate
;
99 static const CK_ATTRIBUTE_TYPE known_attributes
[] = {
100 CKA_CLASS
, CKA_TOKEN
, CKA_PRIVATE
, CKA_LABEL
, CKA_APPLICATION
,
101 CKA_VALUE
, CKA_OBJECT_ID
, CKA_CERTIFICATE_TYPE
, CKA_ISSUER
,
102 CKA_SERIAL_NUMBER
, CKA_AC_ISSUER
, CKA_OWNER
, CKA_ATTR_TYPES
, CKA_TRUSTED
,
103 CKA_CERTIFICATE_CATEGORY
, CKA_JAVA_MIDP_SECURITY_DOMAIN
, CKA_URL
,
104 CKA_HASH_OF_SUBJECT_PUBLIC_KEY
, CKA_HASH_OF_ISSUER_PUBLIC_KEY
,
105 CKA_CHECK_VALUE
, CKA_KEY_TYPE
, CKA_SUBJECT
, CKA_ID
, CKA_SENSITIVE
,
106 CKA_ENCRYPT
, CKA_DECRYPT
, CKA_WRAP
, CKA_UNWRAP
, CKA_SIGN
, CKA_SIGN_RECOVER
,
107 CKA_VERIFY
, CKA_VERIFY_RECOVER
, CKA_DERIVE
, CKA_START_DATE
, CKA_END_DATE
,
108 CKA_MODULUS
, CKA_MODULUS_BITS
, CKA_PUBLIC_EXPONENT
, CKA_PRIVATE_EXPONENT
,
109 CKA_PRIME_1
, CKA_PRIME_2
, CKA_EXPONENT_1
, CKA_EXPONENT_2
, CKA_COEFFICIENT
,
110 CKA_PRIME
, CKA_SUBPRIME
, CKA_BASE
, CKA_PRIME_BITS
,
111 CKA_SUB_PRIME_BITS
, CKA_VALUE_BITS
, CKA_VALUE_LEN
, CKA_EXTRACTABLE
,
112 CKA_LOCAL
, CKA_NEVER_EXTRACTABLE
, CKA_ALWAYS_SENSITIVE
,
113 CKA_KEY_GEN_MECHANISM
, CKA_MODIFIABLE
, CKA_EC_PARAMS
,
114 CKA_EC_POINT
, CKA_SECONDARY_AUTH
, CKA_AUTH_PIN_FLAGS
,
115 CKA_ALWAYS_AUTHENTICATE
, CKA_WRAP_WITH_TRUSTED
, CKA_WRAP_TEMPLATE
,
116 CKA_UNWRAP_TEMPLATE
, CKA_HW_FEATURE_TYPE
, CKA_RESET_ON_INIT
,
117 CKA_HAS_RESET
, CKA_PIXEL_X
, CKA_PIXEL_Y
, CKA_RESOLUTION
, CKA_CHAR_ROWS
,
118 CKA_CHAR_COLUMNS
, CKA_COLOR
, CKA_BITS_PER_PIXEL
, CKA_CHAR_SETS
,
119 CKA_ENCODING_METHODS
, CKA_MIME_TYPES
, CKA_MECHANISM_TYPE
,
120 CKA_REQUIRED_CMS_ATTRIBUTES
, CKA_DEFAULT_CMS_ATTRIBUTES
,
121 CKA_SUPPORTED_CMS_ATTRIBUTES
, CKA_NETSCAPE_URL
, CKA_NETSCAPE_EMAIL
,
122 CKA_NETSCAPE_SMIME_INFO
, CKA_NETSCAPE_SMIME_TIMESTAMP
,
123 CKA_NETSCAPE_PKCS8_SALT
, CKA_NETSCAPE_PASSWORD_CHECK
, CKA_NETSCAPE_EXPIRES
,
124 CKA_NETSCAPE_KRL
, CKA_NETSCAPE_PQG_COUNTER
, CKA_NETSCAPE_PQG_SEED
,
125 CKA_NETSCAPE_PQG_H
, CKA_NETSCAPE_PQG_SEED_BITS
, CKA_NETSCAPE_MODULE_SPEC
,
126 CKA_TRUST_DIGITAL_SIGNATURE
, CKA_TRUST_NON_REPUDIATION
,
127 CKA_TRUST_KEY_ENCIPHERMENT
, CKA_TRUST_DATA_ENCIPHERMENT
,
128 CKA_TRUST_KEY_AGREEMENT
, CKA_TRUST_KEY_CERT_SIGN
, CKA_TRUST_CRL_SIGN
,
129 CKA_TRUST_SERVER_AUTH
, CKA_TRUST_CLIENT_AUTH
, CKA_TRUST_CODE_SIGNING
,
130 CKA_TRUST_EMAIL_PROTECTION
, CKA_TRUST_IPSEC_END_SYSTEM
,
131 CKA_TRUST_IPSEC_TUNNEL
, CKA_TRUST_IPSEC_USER
, CKA_TRUST_TIME_STAMPING
,
132 CKA_TRUST_STEP_UP_APPROVED
, CKA_CERT_SHA1_HASH
, CKA_CERT_MD5_HASH
,
133 CKA_NETSCAPE_DB
, CKA_NETSCAPE_TRUST
, CKA_NSS_OVERRIDE_EXTENSIONS
136 static int known_attributes_size
= sizeof(known_attributes
)/
137 sizeof(known_attributes
[0]);
139 /* Magic for an explicit NULL. NOTE: ideally this should be
140 * out of band data. Since it's not completely out of band, pick
141 * a value that has no meaning to any existing PKCS #11 attributes.
142 * This value is 1) not a valid string (imbedded '\0'). 2) not a U_LONG
143 * or a normal key (too short). 3) not a bool (too long). 4) not an RSA
144 * public exponent (too many bits).
146 const unsigned char SQLITE_EXPLICIT_NULL
[] = { 0xa5, 0x0, 0x5a };
147 #define SQLITE_EXPLICIT_NULL_LEN 3
150 * determine when we've completed our tasks
152 #define MAX_RETRIES 10
154 sdb_done(int err
, int *count
)
156 /* allow as many rows as the database wants to give */
157 if (err
== SQLITE_ROW
) {
161 if (err
!= SQLITE_BUSY
) {
164 /* err == SQLITE_BUSY, Dont' retry forever in this case */
165 if (++(*count
) >= MAX_RETRIES
) {
172 * Map SQL_LITE errors to PKCS #11 errors as best we can.
175 sdb_mapSQLError(sdbDataType type
, int sqlerr
)
183 return CKR_HOST_MEMORY
;
184 case SQLITE_READONLY
:
185 return CKR_TOKEN_WRITE_PROTECTED
;
189 /*return CKR_USER_NOT_LOGGED_IN; */
190 case SQLITE_CANTOPEN
:
191 case SQLITE_NOTFOUND
:
192 /* NSS distiguishes between failure to open the cert and the key db */
193 return type
== SDB_CERT
?
194 CKR_NETSCAPE_CERTDB_FAILED
: CKR_NETSCAPE_KEYDB_FAILED
;
196 return CKR_DEVICE_ERROR
;
200 return CKR_GENERAL_ERROR
;
204 * sqlite3 cannot share handles across threads, in general.
205 * PKCS #11 modules can be called thread, so we need to constantly open and
206 * close the sqlite database.
208 * The one exception is transactions. When we are in a transaction, we must
209 * use the same database pointer for that entire transation. In this case
210 * we save the transaction database and use it for all accesses on the
211 * transaction thread. Other threads still get their own database.
213 * There can only be once active transaction on the database at a time.
216 sdb_openDBLocal(SDBPrivate
*sdb_p
, sqlite3
**sqlDB
)
218 #ifdef SQLITE_THREAD_SHARE_DB
219 *sqlDB
= sdb_p
->sqlXactDB
;
223 int sqlerr
= SQLITE_OK
;
224 CK_RV error
= CKR_OK
;
226 char *dbname
= sdb_p
->sqlDBName
;
227 sdbDataType type
= sdb_p
->type
;
231 PR_Lock(sdb_p
->lock
);
233 /* We're in a transaction, use the transaction DB */
234 if ((sdb_p
->sqlXactDB
) && (sdb_p
->sqlXactThread
== PR_GetCurrentThread())) {
235 *sqlDB
=sdb_p
->sqlXactDB
;
236 /* only one thread can get here, safe to unlock */
237 PR_Unlock(sdb_p
->lock
);
241 /* we're and independent operation, get our own db handle */
242 PR_Unlock(sdb_p
->lock
);
244 sqlerr
= sqlite3_open(dbname
, sqlDB
);
245 if (sqlerr
!= SQLITE_OK
) {
246 error
= sdb_mapSQLError(type
, sqlerr
);
250 sqlerr
= sqlite3_busy_timeout(*sqlDB
, 1000);
251 if (sqlerr
!= CKR_OK
) {
252 error
= sdb_mapSQLError(type
, sqlerr
);
259 sqlite3_close(*sqlDB
);
266 /* down with the local database, free it if we allocated it, otherwise
267 * free unlock our use the the transaction database */
269 sdb_closeDBLocal(SDBPrivate
*sdb_p
, sqlite3
*sqlDB
)
271 #ifndef SQLITE_THREAD_SHARE_DB
272 if (sdb_p
->sqlXactDB
!= sqlDB
) {
273 sqlite3_close(sqlDB
);
281 sqlite3_stmt
*findstmt
;
285 #define FIND_OBJECTS_CMD "SELECT ALL * FROM %s WHERE %s;"
286 #define FIND_OBJECTS_ALL_CMD "SELECT ALL * FROM %s;"
288 sdb_FindObjectsInit(SDB
*sdb
, const CK_ATTRIBUTE
*template, CK_ULONG count
,
291 SDBPrivate
*sdb_p
= sdb
->private;
292 sqlite3
*sqlDB
= NULL
;
293 char *newStr
, *findStr
= NULL
;
294 sqlite3_stmt
*findstmt
= NULL
;
296 int sqlerr
= SQLITE_OK
;
297 CK_RV error
= CKR_OK
;
302 error
= sdb_openDBLocal(sdb_p
, &sqlDB
);
303 if (error
!= CKR_OK
) {
307 findStr
= sqlite3_mprintf("");
308 for (i
=0; findStr
&& i
< count
; i
++) {
309 newStr
= sqlite3_mprintf("%s%sa%x=$DATA%d", findStr
, join
,
310 template[i
].type
, i
);
312 sqlite3_free(findStr
);
316 if (findStr
== NULL
) {
317 error
= CKR_HOST_MEMORY
;
322 newStr
= sqlite3_mprintf(FIND_OBJECTS_ALL_CMD
, sdb_p
->table
);
324 newStr
= sqlite3_mprintf(FIND_OBJECTS_CMD
, sdb_p
->table
, findStr
);
326 sqlite3_free(findStr
);
327 if (newStr
== NULL
) {
328 error
= CKR_HOST_MEMORY
;
331 sqlerr
= sqlite3_prepare(sqlDB
, newStr
, -1, &findstmt
, NULL
);
332 sqlite3_free(newStr
);
333 for (i
=0; sqlerr
== SQLITE_OK
&& i
< count
; i
++) {
334 sqlerr
= sqlite3_bind_blob(findstmt
, i
+1, template[i
].pValue
,
335 template[i
].ulValueLen
, SQLITE_TRANSIENT
);
337 if (sqlerr
== SQLITE_OK
) {
338 *find
= PORT_New(SDBFind
);
340 error
= CKR_HOST_MEMORY
;
343 (*find
)->findstmt
= findstmt
;
344 (*find
)->sqlDB
= sqlDB
;
348 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
352 sqlite3_finalize(findstmt
);
355 sdb_closeDBLocal(sdb_p
, sqlDB
) ;
363 sdb_FindObjects(SDB
*sdb
, SDBFind
*sdbFind
, CK_OBJECT_HANDLE
*object
,
364 CK_ULONG arraySize
, CK_ULONG
*count
)
366 SDBPrivate
*sdb_p
= sdb
->private;
367 sqlite3_stmt
*stmt
= sdbFind
->findstmt
;
368 int sqlerr
= SQLITE_OK
;
373 if (arraySize
== 0) {
379 sqlerr
= sqlite3_step(stmt
);
380 if (sqlerr
== SQLITE_BUSY
) {
383 if (sqlerr
== SQLITE_ROW
) {
384 /* only care about the id */
385 *object
++= sqlite3_column_int(stmt
, 0);
389 } while (!sdb_done(sqlerr
,&retry
) && (arraySize
> 0));
391 /* we only have some of the objects, there is probably more,
392 * set the sqlerr to an OK value so we return CKR_OK */
393 if (sqlerr
== SQLITE_ROW
&& arraySize
== 0) {
394 sqlerr
= SQLITE_DONE
;
398 return sdb_mapSQLError(sdb_p
->type
, sqlerr
);
402 sdb_FindObjectsFinal(SDB
*sdb
, SDBFind
*sdbFind
)
404 SDBPrivate
*sdb_p
= sdb
->private;
405 sqlite3_stmt
*stmt
= sdbFind
->findstmt
;
406 sqlite3
*sqlDB
= sdbFind
->sqlDB
;
407 int sqlerr
= SQLITE_OK
;
412 sqlerr
= sqlite3_finalize(stmt
);
415 sdb_closeDBLocal(sdb_p
, sqlDB
) ;
420 return sdb_mapSQLError(sdb_p
->type
, sqlerr
);
423 #define GET_ATTRIBUTE_CMD "SELECT ALL %s FROM %s WHERE id=$ID;"
425 sdb_GetAttributeValueNoLock(SDB
*sdb
, CK_OBJECT_HANDLE object_id
,
426 CK_ATTRIBUTE
*template, CK_ULONG count
)
428 SDBPrivate
*sdb_p
= sdb
->private;
429 sqlite3
*sqlDB
= NULL
;
430 sqlite3_stmt
*stmt
= NULL
;
433 int sqlerr
= SQLITE_OK
;
434 CK_RV error
= CKR_OK
;
439 getStr
= sqlite3_mprintf("");
440 for (i
=0; getStr
&& i
< count
; i
++) {
442 newStr
= sqlite3_mprintf("a%x", template[i
].type
);
444 newStr
= sqlite3_mprintf("%s, a%x", getStr
, template[i
].type
);
446 sqlite3_free(getStr
);
450 if (getStr
== NULL
) {
451 error
= CKR_HOST_MEMORY
;
455 newStr
= sqlite3_mprintf(GET_ATTRIBUTE_CMD
, getStr
, sdb_p
->table
);
456 sqlite3_free(getStr
);
458 if (newStr
== NULL
) {
459 error
= CKR_HOST_MEMORY
;
462 /* open a new db if necessary */
463 error
= sdb_openDBLocal(sdb_p
,&sqlDB
);
464 if (error
!= CKR_OK
) {
467 sqlerr
= sqlite3_prepare(sqlDB
, newStr
, -1, &stmt
, NULL
);
468 if (sqlerr
!= SQLITE_OK
) { goto loser
; }
469 sqlerr
= sqlite3_bind_int(stmt
, 1, object_id
);
470 if (sqlerr
!= SQLITE_OK
) { goto loser
; }
472 sqlerr
= sqlite3_step(stmt
);
473 if (sqlerr
== SQLITE_BUSY
) {
476 if (sqlerr
== SQLITE_ROW
) {
477 for (i
=0; i
< count
; i
++) {
480 const char *blobData
;
482 blobSize
= sqlite3_column_bytes(stmt
, column
);
483 blobData
= sqlite3_column_blob(stmt
, column
);
484 if (blobData
== NULL
) {
485 template[i
].ulValueLen
= -1;
486 error
= CKR_ATTRIBUTE_TYPE_INVALID
;
489 /* If the blob equals our explicit NULL value, then the
490 * attribute is a NULL. */
491 if ((blobSize
== SQLITE_EXPLICIT_NULL_LEN
) &&
492 (PORT_Memcmp(blobData
, SQLITE_EXPLICIT_NULL
,
493 SQLITE_EXPLICIT_NULL_LEN
) == 0)) {
496 if (template[i
].pValue
) {
497 if (template[i
].ulValueLen
< blobSize
) {
498 template[i
].ulValueLen
= -1;
499 error
= CKR_BUFFER_TOO_SMALL
;
502 PORT_Memcpy(template[i
].pValue
, blobData
, blobSize
);
504 template[i
].ulValueLen
= blobSize
;
508 } while (!sdb_done(sqlerr
,&retry
));
511 /* fix up the error if necessary */
512 if (error
== CKR_OK
) {
513 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
514 if (!found
&& error
== CKR_OK
) {
515 error
= CKR_OBJECT_HANDLE_INVALID
;
519 sqlite3_free(newStr
);
524 sqlite3_finalize(stmt
);
527 /* if we had to open a new database, free it now */
529 sdb_closeDBLocal(sdb_p
, sqlDB
) ;
535 sdb_GetAttributeValue(SDB
*sdb
, CK_OBJECT_HANDLE object_id
,
536 CK_ATTRIBUTE
*template, CK_ULONG count
)
545 crv
= sdb_GetAttributeValueNoLock(sdb
, object_id
, template, count
);
550 #define SET_ATTRIBUTE_CMD "UPDATE %s SET %s WHERE id=$ID;"
552 sdb_SetAttributeValue(SDB
*sdb
, CK_OBJECT_HANDLE object_id
,
553 const CK_ATTRIBUTE
*template, CK_ULONG count
)
555 SDBPrivate
*sdb_p
= sdb
->private;
556 sqlite3
*sqlDB
= NULL
;
557 sqlite3_stmt
*stmt
= NULL
;
560 int sqlerr
= SQLITE_OK
;
562 CK_RV error
= CKR_OK
;
565 if (sdb
->sdb_flags
== SDB_RDONLY
) {
566 return CKR_TOKEN_WRITE_PROTECTED
;
574 setStr
= sqlite3_mprintf("");
575 for (i
=0; setStr
&& i
< count
; i
++) {
577 sqlite3_free(setStr
);
578 setStr
= sqlite3_mprintf("a%x=$VALUE%d",
579 template[i
].type
, i
);
582 newStr
= sqlite3_mprintf("%s,a%x=$VALUE%d", setStr
,
583 template[i
].type
, i
);
584 sqlite3_free(setStr
);
589 if (setStr
== NULL
) {
590 return CKR_HOST_MEMORY
;
592 newStr
= sqlite3_mprintf(SET_ATTRIBUTE_CMD
, sdb_p
->table
, setStr
);
593 sqlite3_free(setStr
);
594 if (newStr
== NULL
) {
596 return CKR_HOST_MEMORY
;
598 error
= sdb_openDBLocal(sdb_p
, &sqlDB
);
599 if (error
!= CKR_OK
) {
602 sqlerr
= sqlite3_prepare(sqlDB
, newStr
, -1, &stmt
, NULL
);
603 if (sqlerr
!= SQLITE_OK
) goto loser
;
604 for (i
=0; i
< count
; i
++) {
605 if (template[i
].ulValueLen
!= 0) {
606 sqlerr
= sqlite3_bind_blob(stmt
, i
+1, template[i
].pValue
,
607 template[i
].ulValueLen
, SQLITE_STATIC
);
609 sqlerr
= sqlite3_bind_blob(stmt
, i
+2, SQLITE_EXPLICIT_NULL
,
610 SQLITE_EXPLICIT_NULL_LEN
, SQLITE_STATIC
);
612 if (sqlerr
!= SQLITE_OK
) goto loser
;
614 sqlerr
= sqlite3_bind_int(stmt
, i
+1, object_id
);
615 if (sqlerr
!= SQLITE_OK
) goto loser
;
618 sqlerr
= sqlite3_step(stmt
);
619 if (sqlerr
== SQLITE_BUSY
) {
622 } while (!sdb_done(sqlerr
,&retry
));
626 sqlite3_free(newStr
);
628 if (error
== CKR_OK
) {
629 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
634 sqlite3_finalize(stmt
);
638 sdb_closeDBLocal(sdb_p
, sqlDB
) ;
646 * check to see if a candidate object handle already exists.
649 sdb_objectExists(SDB
*sdb
, CK_OBJECT_HANDLE candidate
)
652 CK_ATTRIBUTE
template = { CKA_LABEL
, NULL
, 0 };
654 crv
= sdb_GetAttributeValueNoLock(sdb
,candidate
,&template, 1);
655 if (crv
== CKR_OBJECT_HANDLE_INVALID
) {
662 * if we're here, we are in a transaction, so it's safe
663 * to examine the current state of the database
665 static CK_OBJECT_HANDLE
666 sdb_getObjectId(SDB
*sdb
)
668 CK_OBJECT_HANDLE candidate
;
669 static CK_OBJECT_HANDLE next_obj
= CK_INVALID_HANDLE
;
672 * get an initial object handle to use
674 if (next_obj
== CK_INVALID_HANDLE
) {
678 next_obj
= (CK_OBJECT_HANDLE
)(time
& 0x3fffffffL
);
680 candidate
= next_obj
++;
681 /* detect that we've looped through all the handles... */
682 for (count
= 0; count
< 0x40000000; count
++, candidate
= next_obj
++) {
683 /* mask off excess bits */
684 candidate
&= 0x3fffffff;
685 /* if we hit zero, go to the next entry */
686 if (candidate
== CK_INVALID_HANDLE
) {
689 /* make sure we aren't already using */
690 if (!sdb_objectExists(sdb
, candidate
)) {
691 /* this one is free */
696 /* no handle is free, fail */
697 return CK_INVALID_HANDLE
;
700 #define CREATE_CMD "INSERT INTO %s (id%s) VALUES($ID%s);"
702 sdb_CreateObject(SDB
*sdb
, CK_OBJECT_HANDLE
*object_id
,
703 const CK_ATTRIBUTE
*template, CK_ULONG count
)
705 SDBPrivate
*sdb_p
= sdb
->private;
706 sqlite3
*sqlDB
= NULL
;
707 sqlite3_stmt
*stmt
= NULL
;
708 char *columnStr
= NULL
;
709 char *valueStr
= NULL
;
711 int sqlerr
= SQLITE_OK
;
712 CK_RV error
= CKR_OK
;
713 CK_OBJECT_HANDLE this_object
;
717 if (sdb
->sdb_flags
== SDB_RDONLY
) {
718 return CKR_TOKEN_WRITE_PROTECTED
;
722 if ((*object_id
!= CK_INVALID_HANDLE
) &&
723 !sdb_objectExists(sdb
, *object_id
)) {
724 this_object
= *object_id
;
726 this_object
= sdb_getObjectId(sdb
);
728 if (this_object
== CK_INVALID_HANDLE
) {
730 return CKR_HOST_MEMORY
;
732 columnStr
= sqlite3_mprintf("");
733 valueStr
= sqlite3_mprintf("");
734 *object_id
= this_object
;
735 for (i
=0; columnStr
&& valueStr
&& i
< count
; i
++) {
736 newStr
= sqlite3_mprintf("%s,a%x", columnStr
, template[i
].type
);
737 sqlite3_free(columnStr
);
739 newStr
= sqlite3_mprintf("%s,$VALUE%d", valueStr
, i
);
740 sqlite3_free(valueStr
);
744 if ((columnStr
== NULL
) || (valueStr
== NULL
)) {
746 sqlite3_free(columnStr
);
749 sqlite3_free(valueStr
);
752 return CKR_HOST_MEMORY
;
754 newStr
= sqlite3_mprintf(CREATE_CMD
, sdb_p
->table
, columnStr
, valueStr
);
755 sqlite3_free(columnStr
);
756 sqlite3_free(valueStr
);
757 error
= sdb_openDBLocal(sdb_p
, &sqlDB
);
758 if (error
!= CKR_OK
) {
761 sqlerr
= sqlite3_prepare(sqlDB
, newStr
, -1, &stmt
, NULL
);
762 if (sqlerr
!= SQLITE_OK
) goto loser
;
763 sqlerr
= sqlite3_bind_int(stmt
, 1, *object_id
);
764 if (sqlerr
!= SQLITE_OK
) goto loser
;
765 for (i
=0; i
< count
; i
++) {
766 if (template[i
].ulValueLen
) {
767 sqlerr
= sqlite3_bind_blob(stmt
, i
+2, template[i
].pValue
,
768 template[i
].ulValueLen
, SQLITE_STATIC
);
770 sqlerr
= sqlite3_bind_blob(stmt
, i
+2, SQLITE_EXPLICIT_NULL
,
771 SQLITE_EXPLICIT_NULL_LEN
, SQLITE_STATIC
);
773 if (sqlerr
!= SQLITE_OK
) goto loser
;
777 sqlerr
= sqlite3_step(stmt
);
778 if (sqlerr
== SQLITE_BUSY
) {
781 } while (!sdb_done(sqlerr
,&retry
));
785 sqlite3_free(newStr
);
787 if (error
== CKR_OK
) {
788 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
793 sqlite3_finalize(stmt
);
797 sdb_closeDBLocal(sdb_p
, sqlDB
) ;
804 #define DESTROY_CMD "DELETE FROM %s WHERE (id=$ID);"
806 sdb_DestroyObject(SDB
*sdb
, CK_OBJECT_HANDLE object_id
)
808 SDBPrivate
*sdb_p
= sdb
->private;
809 sqlite3
*sqlDB
= NULL
;
810 sqlite3_stmt
*stmt
= NULL
;
812 int sqlerr
= SQLITE_OK
;
813 CK_RV error
= CKR_OK
;
816 if (sdb
->sdb_flags
== SDB_RDONLY
) {
817 return CKR_TOKEN_WRITE_PROTECTED
;
821 error
= sdb_openDBLocal(sdb_p
, &sqlDB
);
822 if (error
!= CKR_OK
) {
825 newStr
= sqlite3_mprintf(DESTROY_CMD
, sdb_p
->table
);
826 if (newStr
== NULL
) {
827 error
= CKR_HOST_MEMORY
;
830 sqlerr
=sqlite3_prepare(sqlDB
, newStr
, -1, &stmt
, NULL
);
831 sqlite3_free(newStr
);
832 if (sqlerr
!= SQLITE_OK
) goto loser
;
833 sqlerr
=sqlite3_bind_int(stmt
, 1, object_id
);
834 if (sqlerr
!= SQLITE_OK
) goto loser
;
837 sqlerr
= sqlite3_step(stmt
);
838 if (sqlerr
== SQLITE_BUSY
) {
841 } while (!sdb_done(sqlerr
,&retry
));
844 if (error
== CKR_OK
) {
845 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
850 sqlite3_finalize(stmt
);
854 sdb_closeDBLocal(sdb_p
, sqlDB
) ;
861 #define BEGIN_CMD "BEGIN IMMEDIATE TRANSACTION;"
863 * start a transaction.
865 * We need to open a new database, then store that new database into
866 * the private data structure. We open the database first, then use locks
867 * to protect storing the data to prevent deadlocks.
872 SDBPrivate
*sdb_p
= sdb
->private;
873 sqlite3
*sqlDB
= NULL
;
874 sqlite3_stmt
*stmt
= NULL
;
875 int sqlerr
= SQLITE_OK
;
876 CK_RV error
= CKR_OK
;
880 if (sdb
->sdb_flags
== SDB_RDONLY
) {
881 return CKR_TOKEN_WRITE_PROTECTED
;
886 #ifdef SQLITE_THREAD_SHARE_DB
887 sqlDB
= sdb_p
->sqlXactDB
;
889 /* get a new version that we will use for the entire transaction */
890 sqlerr
= sqlite3_open(sdb_p
->sqlDBName
, &sqlDB
);
891 if (sqlerr
!= SQLITE_OK
) {
896 sqlerr
= sqlite3_busy_timeout(sqlDB
, 1000);
897 if (sqlerr
!= CKR_OK
) {
901 sqlerr
=sqlite3_prepare(sqlDB
, BEGIN_CMD
, -1, &stmt
, NULL
);
904 sqlerr
= sqlite3_step(stmt
);
905 if (sqlerr
== SQLITE_BUSY
) {
908 } while (!sdb_done(sqlerr
,&retry
));
912 sqlite3_finalize(stmt
);
916 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
918 #ifndef SQLITE_THREAD_SHARE_DB
919 /* we are starting a new transaction,
920 * and if we succeeded, then save this database for the rest of
922 if (error
== CKR_OK
) {
923 /* we hold a 'BEGIN TRANSACTION' and a sdb_p->lock. At this point
924 * sdb_p->sqlXactDB MUST be null */
925 PR_Lock(sdb_p
->lock
);
926 PORT_Assert(sdb_p
->sqlXactDB
== NULL
);
927 sdb_p
->sqlXactDB
= sqlDB
;
928 sdb_p
->sqlXactThread
= PR_GetCurrentThread();
929 PR_Unlock(sdb_p
->lock
);
931 /* we failed to start our transaction,
932 * free any databases we openned. */
934 sqlite3_close(sqlDB
);
944 * Complete a transaction. Basically undo everything we did in begin.
945 * There are 2 flavors Abort and Commit. Basically the only differerence between
946 * these 2 are what the database will show. (no change in to former, change in
950 sdb_complete(SDB
*sdb
, const char *cmd
)
952 SDBPrivate
*sdb_p
= sdb
->private;
953 sqlite3
*sqlDB
= NULL
;
954 sqlite3_stmt
*stmt
= NULL
;
955 int sqlerr
= SQLITE_OK
;
956 CK_RV error
= CKR_OK
;
960 if (sdb
->sdb_flags
== SDB_RDONLY
) {
961 return CKR_TOKEN_WRITE_PROTECTED
;
965 #ifndef SQLITE_THREAD_SHARE_DB
966 /* We must have a transation database, or we shouldn't have arrived here */
967 PR_Lock(sdb_p
->lock
);
968 PORT_Assert(sdb_p
->sqlXactDB
);
969 if (sdb_p
->sqlXactDB
== NULL
) {
970 PR_Unlock(sdb_p
->lock
);
971 return CKR_GENERAL_ERROR
; /* shouldn't happen */
973 PORT_Assert( sdb_p
->sqlXactThread
== PR_GetCurrentThread());
974 if ( sdb_p
->sqlXactThread
!= PR_GetCurrentThread()) {
975 PR_Unlock(sdb_p
->lock
);
976 return CKR_GENERAL_ERROR
; /* shouldn't happen */
978 sqlDB
= sdb_p
->sqlXactDB
;
979 sdb_p
->sqlXactDB
= NULL
; /* no one else can get to this DB,
981 sdb_p
->sqlXactThread
= NULL
;
982 PR_Unlock(sdb_p
->lock
);
984 sqlDB
= sdb_p
->sqlXactDB
;
987 sqlerr
=sqlite3_prepare(sqlDB
, cmd
, -1, &stmt
, NULL
);
990 sqlerr
= sqlite3_step(stmt
);
991 if (sqlerr
== SQLITE_BUSY
) {
994 } while (!sdb_done(sqlerr
,&retry
));
996 /* Pending BEGIN TRANSACTIONS Can move forward at this point. */
1000 sqlite3_finalize(stmt
);
1003 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
1005 #ifndef SQLITE_THREAD_SHARE_DB
1006 /* We just finished a transaction.
1007 * Free the database, and remove it from the list */
1008 sqlite3_close(sqlDB
);
1014 #define COMMIT_CMD "COMMIT TRANSACTION;"
1016 sdb_Commit(SDB
*sdb
)
1020 crv
= sdb_complete(sdb
,COMMIT_CMD
);
1025 #define ROLLBACK_CMD "ROLLBACK TRANSACTION;"
1031 crv
= sdb_complete(sdb
,ROLLBACK_CMD
);
1036 #define GET_PW_CMD "SELECT ALL * FROM password WHERE id='password';"
1038 sdb_GetPWEntry(SDB
*sdb
, SDBPasswordEntry
*entry
)
1040 SDBPrivate
*sdb_p
= sdb
->private;
1041 sqlite3
*sqlDB
= sdb_p
->sqlXactDB
;
1042 sqlite3_stmt
*stmt
= NULL
;
1043 int sqlerr
= SQLITE_OK
;
1044 CK_RV error
= CKR_OK
;
1048 /* only Key databases have password entries */
1049 if (sdb_p
->type
!= SDB_KEY
) {
1050 return CKR_OBJECT_HANDLE_INVALID
;
1054 error
= sdb_openDBLocal(sdb_p
, &sqlDB
);
1055 if (error
!= CKR_OK
) {
1059 sqlerr
= sqlite3_prepare(sqlDB
, GET_PW_CMD
, -1, &stmt
, NULL
);
1061 sqlerr
= sqlite3_step(stmt
);
1062 if (sqlerr
== SQLITE_BUSY
) {
1065 if (sqlerr
== SQLITE_ROW
) {
1066 const char *blobData
;
1067 entry
->salt
.data
= entry
->data
;
1068 entry
->salt
.len
= sqlite3_column_bytes(stmt
, 1);
1069 if (entry
->salt
.len
> sizeof(entry
->data
)) {
1070 error
= CKR_BUFFER_TOO_SMALL
;
1073 blobData
= sqlite3_column_blob(stmt
, 1);
1074 PORT_Memcpy(entry
->salt
.data
,blobData
, entry
->salt
.len
);
1075 entry
->value
.data
= &entry
->data
[entry
->salt
.len
];
1076 entry
->value
.len
= sqlite3_column_bytes(stmt
, 2);
1077 if ((entry
->value
.len
+entry
->salt
.len
) > sizeof(entry
->data
)) {
1078 error
= CKR_BUFFER_TOO_SMALL
;
1081 blobData
= sqlite3_column_blob(stmt
, 2);
1082 PORT_Memcpy(entry
->value
.data
,blobData
, entry
->value
.len
);
1085 } while (!sdb_done(sqlerr
,&retry
));
1088 /* fix up the error if necessary */
1089 if (error
== CKR_OK
) {
1090 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
1091 if (!found
&& error
== CKR_OK
) {
1092 error
= CKR_OBJECT_HANDLE_INVALID
;
1097 sqlite3_reset(stmt
);
1098 sqlite3_finalize(stmt
);
1102 sdb_closeDBLocal(sdb_p
, sqlDB
) ;
1109 static int tableExists(sqlite3
*sqlDB
, const char *tableName
);
1110 #define PW_CREATE_TABLE_CMD \
1111 "CREATE TABLE password (id PRIMARY KEY UNIQUE ON CONFLICT REPLACE, salt, value);"
1112 #define PW_CREATE_CMD \
1113 "INSERT INTO password (id,salt,value) VALUES('password',$SALT,$VALUE);"
1115 sdb_PutPWEntry(SDB
*sdb
, SDBPasswordEntry
*entry
)
1117 SDBPrivate
*sdb_p
= sdb
->private;
1118 sqlite3
*sqlDB
= sdb_p
->sqlXactDB
;
1119 sqlite3_stmt
*stmt
= NULL
;
1120 int sqlerr
= SQLITE_OK
;
1121 CK_RV error
= CKR_OK
;
1124 /* only Key databases have password entries */
1125 if (sdb_p
->type
!= SDB_KEY
) {
1126 return CKR_OBJECT_HANDLE_INVALID
;
1130 error
= sdb_openDBLocal(sdb_p
, &sqlDB
);
1131 if (error
!= CKR_OK
) {
1135 if (!tableExists(sqlDB
, "password")) {
1136 sqlerr
= sqlite3_exec(sqlDB
, PW_CREATE_TABLE_CMD
, NULL
, 0, NULL
);
1137 if (sqlerr
!= SQLITE_OK
) goto loser
;
1139 sqlerr
= sqlite3_prepare(sqlDB
, PW_CREATE_CMD
, -1, &stmt
, NULL
);
1140 if (sqlerr
!= SQLITE_OK
) goto loser
;
1141 sqlerr
= sqlite3_bind_blob(stmt
, 1, entry
->salt
.data
,
1142 entry
->salt
.len
, SQLITE_STATIC
);
1143 if (sqlerr
!= SQLITE_OK
) goto loser
;
1144 sqlerr
= sqlite3_bind_blob(stmt
, 2, entry
->value
.data
,
1145 entry
->value
.len
, SQLITE_STATIC
);
1146 if (sqlerr
!= SQLITE_OK
) goto loser
;
1149 sqlerr
= sqlite3_step(stmt
);
1150 if (sqlerr
== SQLITE_BUSY
) {
1153 } while (!sdb_done(sqlerr
,&retry
));
1156 /* fix up the error if necessary */
1157 if (error
== CKR_OK
) {
1158 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
1162 sqlite3_reset(stmt
);
1163 sqlite3_finalize(stmt
);
1167 sdb_closeDBLocal(sdb_p
, sqlDB
) ;
1174 #define RESET_CMD "DROP TABLE IF EXISTS %s;"
1178 SDBPrivate
*sdb_p
= sdb
->private;
1179 sqlite3
*sqlDB
= NULL
;
1181 int sqlerr
= SQLITE_OK
;
1182 CK_RV error
= CKR_OK
;
1184 /* only Key databases can be reset */
1185 if (sdb_p
->type
!= SDB_KEY
) {
1186 return CKR_OBJECT_HANDLE_INVALID
;
1190 error
= sdb_openDBLocal(sdb_p
, &sqlDB
);
1191 if (error
!= CKR_OK
) {
1195 /* delete the key table */
1196 newStr
= sqlite3_mprintf(RESET_CMD
, sdb_p
->table
);
1197 if (newStr
== NULL
) {
1198 error
= CKR_HOST_MEMORY
;
1201 sqlerr
= sqlite3_exec(sqlDB
, newStr
, NULL
, 0, NULL
);
1202 sqlite3_free(newStr
);
1204 if (sqlerr
!= SQLITE_OK
) goto loser
;
1206 /* delete the password entry table */
1207 sqlerr
= sqlite3_exec(sqlDB
, "DROP TABLE IF EXISTS password;",
1211 /* fix up the error if necessary */
1212 if (error
== CKR_OK
) {
1213 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
1217 sdb_closeDBLocal(sdb_p
, sqlDB
) ;
1228 SDBPrivate
*sdb_p
= sdb
->private;
1229 int sqlerr
= SQLITE_OK
;
1230 sdbDataType type
= sdb_p
->type
;
1232 /* sqlerr = sqlite3_close(sqlDB); */
1233 PORT_Free(sdb_p
->sqlDBName
);
1236 return sdb_mapSQLError(type
, sqlerr
);
1241 * functions to support open
1244 #define CHECK_TABLE_CMD "SELECT ALL * FROM %s LIMIT 0;"
1245 /* return 1 if sqlDB contains table 'tableName */
1246 static int tableExists(sqlite3
*sqlDB
, const char *tableName
)
1248 char * cmd
= sqlite3_mprintf(CHECK_TABLE_CMD
, tableName
);
1249 int sqlerr
= SQLITE_OK
;
1255 sqlerr
= sqlite3_exec(sqlDB
, cmd
, NULL
, 0, 0);
1258 return (sqlerr
== SQLITE_OK
) ? 1 : 0;
1262 * initialize a single database
1265 "CREATE TABLE %s (id PRIMARY KEY UNIQUE ON CONFLICT ABORT%s)"
1267 "ALTER TABLE %s ADD COLUMN a%x"
1271 sdb_init(char *dbname
, char *table
, sdbDataType type
, int *inUpdate
,
1272 int *newInit
, int flags
, SDB
**pSdb
)
1275 char *initStr
= NULL
;
1277 int inTransaction
= 0;
1279 SDBPrivate
*sdb_p
= NULL
;
1280 sqlite3
*sqlDB
= NULL
;
1281 int sqlerr
= SQLITE_OK
;
1282 CK_RV error
= CKR_OK
;
1287 /* sqlite3 doesn't have a flag to specify that we want to
1288 * open the database read only. If the db doesn't exist,
1289 * sqlite3 will always create it.
1292 if ((flags
== SDB_RDONLY
) && PR_Access(dbname
, PR_ACCESS_EXISTS
)) {
1293 error
= sdb_mapSQLError(type
, SQLITE_CANTOPEN
);
1296 sqlerr
= sqlite3_open(dbname
, &sqlDB
);
1297 if (sqlerr
!= SQLITE_OK
) {
1298 error
= sdb_mapSQLError(type
, sqlerr
);
1302 sqlerr
= sqlite3_busy_timeout(sqlDB
, 1000);
1303 if (sqlerr
!= CKR_OK
) {
1304 error
= sdb_mapSQLError(type
, sqlerr
);
1308 if (flags
!= SDB_RDONLY
) {
1309 sqlerr
= sqlite3_exec(sqlDB
, BEGIN_CMD
, NULL
, 0, NULL
);
1310 if (sqlerr
!= SQLITE_OK
) {
1311 error
= sdb_mapSQLError(type
, sqlerr
);
1316 if (!tableExists(sqlDB
,table
)) {
1318 if (flags
!= SDB_CREATE
) {
1319 error
= sdb_mapSQLError(type
, SQLITE_CANTOPEN
);
1322 initStr
= sqlite3_mprintf("");
1323 for (i
=0; initStr
&& i
< known_attributes_size
; i
++) {
1324 newStr
= sqlite3_mprintf("%s, a%x",initStr
, known_attributes
[i
]);
1325 sqlite3_free(initStr
);
1328 if (initStr
== NULL
) {
1329 error
= CKR_HOST_MEMORY
;
1332 newStr
= sqlite3_mprintf(INIT_CMD
, table
, initStr
);
1333 sqlite3_free(initStr
);
1334 sqlerr
= sqlite3_exec(sqlDB
, newStr
, NULL
, 0, NULL
);
1335 sqlite3_free(newStr
);
1336 if (sqlerr
!= SQLITE_OK
) {
1337 error
= sdb_mapSQLError(type
, sqlerr
);
1341 /* if the nssInit table exists, then someone else is initing the
1342 * nss database. We don't want to complete the open until the init
1344 if (tableExists(sqlDB
,"nssInUpdate")) {
1348 sdb
= (SDB
*) malloc(sizeof(SDB
));
1349 sdb_p
= (SDBPrivate
*) malloc(sizeof(SDBPrivate
));
1350 /* invariant fields */
1351 sdb_p
->sqlDBName
= PORT_Strdup(dbname
);
1353 sdb_p
->table
= table
;
1354 sdb_p
->lock
= PR_NewLock();
1355 /* these fields are protected by the lock */
1356 sdb_p
->sqlXactDB
= NULL
;
1357 sdb_p
->sqlXactThread
= NULL
;
1358 sdb
->private = sdb_p
;
1359 sdb
->sdb_type
= SDB_SQL
;
1360 sdb
->sdb_flags
= flags
;
1361 sdb
->sdb_FindObjectsInit
= sdb_FindObjectsInit
;
1362 sdb
->sdb_FindObjects
= sdb_FindObjects
;
1363 sdb
->sdb_FindObjectsFinal
= sdb_FindObjectsFinal
;
1364 sdb
->sdb_GetAttributeValue
= sdb_GetAttributeValue
;
1365 sdb
->sdb_SetAttributeValue
= sdb_SetAttributeValue
;
1366 sdb
->sdb_CreateObject
= sdb_CreateObject
;
1367 sdb
->sdb_DestroyObject
= sdb_DestroyObject
;
1368 sdb
->sdb_GetPWEntry
= sdb_GetPWEntry
;
1369 sdb
->sdb_PutPWEntry
= sdb_PutPWEntry
;
1370 sdb
->sdb_Begin
= sdb_Begin
;
1371 sdb
->sdb_Commit
= sdb_Commit
;
1372 sdb
->sdb_Abort
= sdb_Abort
;
1373 sdb
->sdb_Close
= sdb_Close
;
1375 if (inTransaction
) {
1376 sqlerr
= sqlite3_exec(sqlDB
, COMMIT_CMD
, NULL
, 0, NULL
);
1377 if (sqlerr
!= SQLITE_OK
) {
1378 error
= sdb_mapSQLError(sdb_p
->type
, sqlerr
);
1384 while (tableExists(sqlDB
,"nssInit")) {
1388 #ifdef SQLITE_THREAD_SHARE_DB
1389 sdb_p
->sqlXactDB
= sqlDB
;
1391 /* sqlite3 cannot share sqlDB references across threads, open the
1392 * db only when we need to read or update it (sigh) */
1393 sqlite3_close(sqlDB
);
1401 /* lots of stuff to do */
1402 if (inTransaction
) {
1403 sqlite3_exec(sqlDB
, ROLLBACK_CMD
, NULL
, 0, NULL
);
1412 sqlite3_close(sqlDB
);
1419 static char *sdb_BuildFileName(const char * directory
,
1420 const char *prefix
, const char *type
,
1421 int version
, int flags
)
1423 char *dbname
= NULL
;
1424 /* build the full dbname */
1425 dbname
= sqlite3_mprintf("%s/%s%s%d.db",directory
, prefix
, type
, version
);
1431 s_open(const char *directory
, const char *certPrefix
, const char *keyPrefix
,
1432 int cert_version
, int key_version
, int flags
,
1433 SDB
**certdb
, SDB
**keydb
, int *newInit
)
1435 char *cert
= sdb_BuildFileName(directory
, certPrefix
,
1436 "cert", cert_version
, flags
);
1437 char *key
= sdb_BuildFileName(directory
, keyPrefix
,
1438 "key", key_version
, flags
);
1439 CK_RV error
= CKR_OK
;
1446 #ifdef SQLITE_UNSAFE_THREADS
1447 if (sqlite_lock
== NULL
) {
1448 sqlite_lock
= PR_NewLock();
1449 if (sqlite_lock
== NULL
) {
1450 error
= CKR_HOST_MEMORY
;
1457 * open the cert data base
1460 /* initialize Certificate database */
1461 error
= sdb_init(cert
, "nssPublic", SDB_CERT
, &inUpdate
,
1462 newInit
, flags
, certdb
);
1463 if (error
!= CKR_OK
) {
1469 * open the key data base:
1470 * NOTE:is we want to implement a single database, we open
1471 * the same database file as the certificate here.
1473 * cert an key db's have different tables, so they will not
1477 /* initialize the Key database */
1478 error
= sdb_init(key
, "nssPrivate", SDB_KEY
, &inUpdate
,
1479 newInit
, flags
, keydb
);
1480 if (error
!= CKR_OK
) {
1494 if (error
!= CKR_OK
) {
1495 /* currently redundant, but could be necessary if more code is added
1496 * just before loser */
1497 if (keydb
&& *keydb
) {
1500 if (certdb
&& *certdb
) {
1511 #ifdef SQLITE_UNSAFE_THREADS
1513 PR_DestroyLock(sqlite_lock
);