summaryrefslogtreecommitdiff
path: root/security/nss
diff options
context:
space:
mode:
authorrrelyea%redhat.com <devnull@localhost>2007-06-13 00:24:57 +0000
committerrrelyea%redhat.com <devnull@localhost>2007-06-13 00:24:57 +0000
commitbc02abfdccbf6e07ce9036c85c3371c4bac5a5bc (patch)
tree58cb311a457ccceb1b291ada3cd9983b608c6e76 /security/nss
parent892018c57ede2a3b4d8d00a41fc583316a71d4e6 (diff)
downloadnss-hg-bc02abfdccbf6e07ce9036c85c3371c4bac5a5bc.tar.gz
Bug 217538 Add shared database to nss.
core Checking.
Diffstat (limited to 'security/nss')
-rw-r--r--security/nss/lib/softoken/config.mk2
-rw-r--r--security/nss/lib/softoken/fipstest.c5
-rw-r--r--security/nss/lib/softoken/fipstokn.c1
-rw-r--r--security/nss/lib/softoken/legacydb/Makefile80
-rw-r--r--security/nss/lib/softoken/legacydb/cdbhdl.h (renamed from security/nss/lib/softoken/cdbhdl.h)4
-rw-r--r--security/nss/lib/softoken/legacydb/config.mk102
-rw-r--r--security/nss/lib/softoken/legacydb/dbmshim.c (renamed from security/nss/lib/softoken/dbmshim.c)13
-rw-r--r--security/nss/lib/softoken/legacydb/keydb.c (renamed from security/nss/lib/softoken/keydb.c)1247
-rw-r--r--security/nss/lib/softoken/legacydb/keydbi.h (renamed from security/nss/lib/softoken/keydbi.h)0
-rw-r--r--security/nss/lib/softoken/legacydb/legacydb.def64
-rw-r--r--security/nss/lib/softoken/legacydb/lgattr.c1748
-rw-r--r--security/nss/lib/softoken/legacydb/lgcreate.c955
-rw-r--r--security/nss/lib/softoken/legacydb/lgdb.h197
-rw-r--r--security/nss/lib/softoken/legacydb/lgdestroy.c144
-rw-r--r--security/nss/lib/softoken/legacydb/lgfind.c941
-rw-r--r--security/nss/lib/softoken/legacydb/lginit.c (renamed from security/nss/lib/softoken/dbinit.c)572
-rw-r--r--security/nss/lib/softoken/legacydb/lgutil.c424
-rw-r--r--security/nss/lib/softoken/legacydb/lowcert.c (renamed from security/nss/lib/softoken/lowcert.c)246
-rw-r--r--security/nss/lib/softoken/legacydb/lowkey.c462
-rw-r--r--security/nss/lib/softoken/legacydb/lowkeyi.h198
-rw-r--r--security/nss/lib/softoken/legacydb/lowkeyti.h161
-rw-r--r--security/nss/lib/softoken/legacydb/manifest.mn68
-rw-r--r--security/nss/lib/softoken/legacydb/pcert.h (renamed from security/nss/lib/softoken/pcert.h)8
-rw-r--r--security/nss/lib/softoken/legacydb/pcertdb.c (renamed from security/nss/lib/softoken/pcertdb.c)184
-rw-r--r--security/nss/lib/softoken/legacydb/pcertt.h (renamed from security/nss/lib/softoken/pcertt.h)2
-rw-r--r--security/nss/lib/softoken/legacydb/pk11db.c (renamed from security/nss/lib/softoken/pk11db.c)271
-rw-r--r--security/nss/lib/softoken/lgglue.c341
-rw-r--r--security/nss/lib/softoken/lgglue.h92
-rw-r--r--security/nss/lib/softoken/lowkey.c34
-rw-r--r--security/nss/lib/softoken/lowkeyi.h166
-rw-r--r--security/nss/lib/softoken/lowkeyti.h36
-rw-r--r--security/nss/lib/softoken/manifest.mn23
-rw-r--r--security/nss/lib/softoken/pkcs11.c1809
-rw-r--r--security/nss/lib/softoken/pkcs11c.c4
-rw-r--r--security/nss/lib/softoken/pkcs11i.h54
-rw-r--r--security/nss/lib/softoken/pkcs11n.h143
-rw-r--r--security/nss/lib/softoken/pkcs11t.h10
-rw-r--r--security/nss/lib/softoken/pkcs11u.c1781
-rw-r--r--security/nss/lib/softoken/sdb.c1518
-rw-r--r--security/nss/lib/softoken/sdb.h115
-rw-r--r--security/nss/lib/softoken/sftkdb.c2738
-rw-r--r--security/nss/lib/softoken/sftkdb.h90
-rw-r--r--security/nss/lib/softoken/sftkdbt.h17
-rw-r--r--security/nss/lib/softoken/sftkpars.c616
-rw-r--r--security/nss/lib/softoken/sftkpars.h17
-rw-r--r--security/nss/lib/softoken/softoken.h4
46 files changed, 12670 insertions, 5037 deletions
diff --git a/security/nss/lib/softoken/config.mk b/security/nss/lib/softoken/config.mk
index bc48130aa..905ad5284 100644
--- a/security/nss/lib/softoken/config.mk
+++ b/security/nss/lib/softoken/config.mk
@@ -46,7 +46,7 @@ endif
EXTRA_LIBS += \
$(CRYPTOLIB) \
$(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
- $(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX) \
+ -lsqlite3 \
$(NULL)
# can't do this in manifest.mn because OS_TARGET isn't defined there.
diff --git a/security/nss/lib/softoken/fipstest.c b/security/nss/lib/softoken/fipstest.c
index 942bd4034..a3e6938f8 100644
--- a/security/nss/lib/softoken/fipstest.c
+++ b/security/nss/lib/softoken/fipstest.c
@@ -49,11 +49,6 @@
#ifdef NSS_ENABLE_ECC
#include "secdert.h" /* Required for ECDSA */
#include "ec.h" /* Required for ECDSA */
-extern SECStatus
-EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
-extern SECStatus
-EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
- const ECParams *srcParams);
#endif
diff --git a/security/nss/lib/softoken/fipstokn.c b/security/nss/lib/softoken/fipstokn.c
index 6cfcfcb05..3dd386b03 100644
--- a/security/nss/lib/softoken/fipstokn.c
+++ b/security/nss/lib/softoken/fipstokn.c
@@ -52,7 +52,6 @@
#include "seccomon.h"
#include "softoken.h"
#include "lowkeyi.h"
-#include "pcert.h"
#include "pkcs11.h"
#include "pkcs11i.h"
#include "prenv.h"
diff --git a/security/nss/lib/softoken/legacydb/Makefile b/security/nss/lib/softoken/legacydb/Makefile
new file mode 100644
index 000000000..a41aa72c6
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/Makefile
@@ -0,0 +1,80 @@
+#! gmake
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+export:: private_export
+
diff --git a/security/nss/lib/softoken/cdbhdl.h b/security/nss/lib/softoken/legacydb/cdbhdl.h
index 238a48669..aec617b73 100644
--- a/security/nss/lib/softoken/cdbhdl.h
+++ b/security/nss/lib/softoken/legacydb/cdbhdl.h
@@ -57,8 +57,6 @@ struct NSSLOWCERTCertDBHandleStr {
PRInt32 ref; /* reference count */
};
-#define nsslowcert_reference(x) (PR_AtomicIncrement(&(x)->ref) , (x))
-
#ifdef DBM_USING_NSPR
#define NO_RDONLY PR_RDONLY
#define NO_RDWR PR_RDWR
@@ -82,8 +80,6 @@ DB * rdbopen(const char *appName, const char *prefix,
DB *dbsopen (const char *dbname , int flags, int mode, DBTYPE type,
const void * appData);
SECStatus db_Copy(DB *dest,DB *src);
-int db_BeginTransaction(DB *db);
-int db_FinishTransaction(DB *db, PRBool abort);
int db_InitComplete(DB *db);
#endif
diff --git a/security/nss/lib/softoken/legacydb/config.mk b/security/nss/lib/softoken/legacydb/config.mk
new file mode 100644
index 000000000..815f25785
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/config.mk
@@ -0,0 +1,102 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
+CRYPTODIR=../freebl
+ifdef MOZILLA_SECURITY_BUILD
+ CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
+ CRYPTODIR=../crypto
+endif
+
+EXTRA_LIBS += \
+ $(CRYPTOLIB) \
+ $(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX)
+ $(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX) \
+ $(NULL)
+
+# can't do this in manifest.mn because OS_TARGET isn't defined there.
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+
+# don't want the 32 in the shared library name
+SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
+IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
+
+RES = $(OBJDIR)/$(LIBRARY_NAME).res
+RESNAME = $(LIBRARY_NAME).rc
+
+ifdef NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+else # ! NS_USE_GCC
+
+EXTRA_SHARED_LIBS += \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
+ $(NULL)
+endif # NS_USE_GCC
+
+else
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+EXTRA_SHARED_LIBS += \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+endif
+
+ifeq ($(OS_TARGET),SunOS)
+# The -R '$ORIGIN' linker option instructs this library to search for its
+# dependencies in the same directory where it resides.
+MKSHLIB += -R '$$ORIGIN'
+OS_LIBS += -lbsm
+endif
+
+ifeq ($(OS_TARGET),WINCE)
+DEFINES += -DDBM_USING_NSPR
+endif
+
+# indicates dependency on freebl static lib
+$(SHARED_LIBRARY): $(CRYPTOLIB)
diff --git a/security/nss/lib/softoken/dbmshim.c b/security/nss/lib/softoken/legacydb/dbmshim.c
index d429dae7c..9d512ac41 100644
--- a/security/nss/lib/softoken/dbmshim.c
+++ b/security/nss/lib/softoken/legacydb/dbmshim.c
@@ -41,20 +41,11 @@
*/
#include "mcom_db.h"
#include "secitem.h"
-#include "secder.h"
-#include "prprf.h"
-#include "cdbhdl.h"
-
-/* Call to SFTK_FreeSlot below */
-
-#include "pcertt.h"
-#include "secasn1.h"
-#include "secerr.h"
#include "nssb64.h"
#include "blapi.h"
-#include "sechash.h"
+#include "secerr.h"
-#include "pkcs11i.h"
+#include "lgdb.h"
/*
* Blob block:
diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/legacydb/keydb.c
index bfa99c256..a57c59fb9 100644
--- a/security/nss/lib/softoken/keydb.c
+++ b/security/nss/lib/softoken/legacydb/keydb.c
@@ -37,23 +37,18 @@
/* $Id$ */
#include "lowkeyi.h"
-#include "seccomon.h"
-#include "sechash.h"
-#include "secder.h"
#include "secasn1.h"
+#include "secder.h"
#include "secoid.h"
#include "blapi.h"
#include "secitem.h"
#include "pcert.h"
#include "mcom_db.h"
-#include "lowpbe.h"
#include "secerr.h"
-#include "cdbhdl.h"
#include "nsslocks.h"
#include "keydbi.h"
-#include "softoken.h"
-
+#include "lgdb.h"
/*
* Record keys for keydb
@@ -68,39 +63,6 @@
/* Size of the global salt for key database */
#define SALT_LENGTH 16
-const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
- { SEC_ASN1_SEQUENCE,
- 0, NULL, sizeof(NSSLOWKEYAttribute) },
- { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
- { SEC_ASN1_SET_OF, offsetof(NSSLOWKEYAttribute, attrValue),
- SEC_AnyTemplate },
- { 0 }
-};
-
-const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
- { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
-};
-/* ASN1 Templates for new decoder/encoder */
-const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
- { SEC_ASN1_SEQUENCE,
- 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
- { SEC_ASN1_INTEGER,
- offsetof(NSSLOWKEYPrivateKeyInfo,version) },
- { SEC_ASN1_INLINE,
- offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
- SECOID_AlgorithmIDTemplate },
- { SEC_ASN1_OCTET_STRING,
- offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
- offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
- nsslowkey_SetOfAttributeTemplate },
- { 0 }
-};
-
-const SEC_ASN1Template nsslowkey_PointerToPrivateKeyInfoTemplate[] = {
- { SEC_ASN1_POINTER, 0, nsslowkey_PrivateKeyInfoTemplate }
-};
-
const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(NSSLOWKEYEncryptedPrivateKeyInfo) },
@@ -118,26 +80,6 @@ const SEC_ASN1Template nsslowkey_PointerToEncryptedPrivateKeyInfoTemplate[] = {
/* ====== Default key databse encryption algorithm ====== */
-
-static SECOidTag defaultKeyDBAlg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
-
-/*
- * Default algorithm for encrypting data in the key database
- */
-SECOidTag
-nsslowkey_GetDefaultKeyDBAlg(void)
-{
- return(defaultKeyDBAlg);
-}
-
-void
-nsslowkey_SetDefaultKeyDBAlg(SECOidTag alg)
-{
- defaultKeyDBAlg = alg;
-
- return;
-}
-
static void
sec_destroy_dbkey(NSSLOWKEYDBKey *dbkey)
{
@@ -443,6 +385,7 @@ nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
return(SECSuccess);
}
+#ifdef notdef
typedef struct keyNode {
struct keyNode *next;
DBT key;
@@ -485,6 +428,7 @@ sec_add_key_to_list(DBT *key, DBT *data, void *arg)
return(SECSuccess);
}
+#endif
static SECItem *
decodeKeyDBGlobalSalt(DBT *saltData)
@@ -527,7 +471,7 @@ GetKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
}
static SECStatus
-StoreKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
+StoreKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle, SECItem *salt)
{
DBT saltKey;
DBT saltData;
@@ -536,8 +480,8 @@ StoreKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
saltKey.data = SALT_STRING;
saltKey.size = sizeof(SALT_STRING) - 1;
- saltData.data = (void *)handle->global_salt->data;
- saltData.size = handle->global_salt->len;
+ saltData.data = (void *)salt->data;
+ saltData.size = salt->len;
/* put global salt into the database now */
status = keydb_Put(handle, &saltKey, &saltData, 0);
@@ -580,18 +524,13 @@ makeGlobalSalt(NSSLOWKEYDBHandle *handle)
DBT saltData;
unsigned char saltbuf[16];
int status;
- SECStatus rv;
saltKey.data = SALT_STRING;
saltKey.size = sizeof(SALT_STRING) - 1;
saltData.data = (void *)saltbuf;
saltData.size = sizeof(saltbuf);
- rv = RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf));
- if ( rv != SECSuccess ) {
- sftk_fatalError = PR_TRUE;
- return(rv);
- }
+ RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf));
/* put global salt into the database now */
status = keydb_Put(handle, &saltKey, &saltData, 0);
@@ -603,24 +542,6 @@ makeGlobalSalt(NSSLOWKEYDBHandle *handle)
}
static SECStatus
-ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
- SECItem *oldpwitem, SECItem *newpwitem,
- SECOidTag new_algorithm);
-/*
- * Second pass of updating the key db. This time we have a password.
- */
-static SECStatus
-nsslowkey_UpdateKeyDBPass2(NSSLOWKEYDBHandle *handle, SECItem *pwitem)
-{
- SECStatus rv;
-
- rv = ChangeKeyDBPasswordAlg(handle, pwitem, pwitem,
- nsslowkey_GetDefaultKeyDBAlg());
-
- return(rv);
-}
-
-static SECStatus
encodePWCheckEntry(PLArenaPool *arena, SECItem *entry, SECOidTag alg,
SECItem *encCheck);
@@ -918,17 +839,10 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
return (status == RDB_RETRY) ? SECWouldBlock: SECFailure;
}
- rv = db_BeginTransaction(handle->db);
- if (rv != SECSuccess) {
- db_InitComplete(handle->db);
- return rv;
- }
-
/* force a transactional read, which will verify that one and only one
* process attempts the update. */
if (nsslowkey_version(handle) == NSSLOWKEY_DB_FILE_VERSION) {
/* someone else has already updated the database for us */
- db_FinishTransaction(handle->db, PR_FALSE);
db_InitComplete(handle->db);
return SECSuccess;
}
@@ -962,7 +876,6 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
/* copy the new DB from the old one */
db_Copy(handle->db, updatedb);
nsslowkey_CloseKeyDB(updateHandle);
- db_FinishTransaction(handle->db,PR_FALSE);
db_InitComplete(handle->db);
return SECSuccess;
}
@@ -1014,7 +927,6 @@ noupdate:
rv = SECSuccess;
loser:
- db_FinishTransaction(handle->db, rv != SECSuccess);
db_InitComplete(handle->db);
return rv;
}
@@ -1082,10 +994,6 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
handle = nsslowkey_NewHandle(NULL);
- if (!handle) {
- /* error code is set */
- return NULL;
- }
openflags = readOnly ? NO_RDONLY : NO_RDWR;
@@ -1181,7 +1089,7 @@ nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle)
* Delete a private key that was stored in the database
*/
SECStatus
-nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, SECItem *pubkey)
+nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, const SECItem *pubkey)
{
DBT namekey;
int ret;
@@ -1220,10 +1128,10 @@ nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
- SECItem *arg)
+ SDB *sdb)
{
return nsslowkey_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData,
- nickname, arg, nsslowkey_GetDefaultKeyDBAlg(),PR_FALSE);
+ nickname, sdb, PR_FALSE);
}
SECStatus
@@ -1231,10 +1139,10 @@ nsslowkey_UpdateNickname(NSSLOWKEYDBHandle *handle,
NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
- SECItem *arg)
+ SDB *sdb)
{
return nsslowkey_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData,
- nickname, arg, nsslowkey_GetDefaultKeyDBAlg(),PR_TRUE);
+ nickname, sdb, PR_TRUE);
}
/* see if the symetric CKA_ID already Exists.
@@ -1327,218 +1235,272 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer
return PR_TRUE;
}
-/*
- * check to see if the user has a password
- */
-SECStatus
-nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle)
+typedef struct NSSLowPasswordDataParamStr {
+ SECItem salt;
+ SECItem iter;
+} NSSLowPasswordDataParam;
+
+static const SEC_ASN1Template NSSLOWPasswordParamTemplate[] =
{
- DBT checkkey, checkdata;
- int ret;
+ {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLowPasswordDataParam) },
+ {SEC_ASN1_OCTET_STRING, offsetof(NSSLowPasswordDataParam, salt) },
+ {SEC_ASN1_INTEGER, offsetof(NSSLowPasswordDataParam, iter) },
+ {0}
+};
+struct LGEncryptedDataInfoStr {
+ SECAlgorithmID algorithm;
+ SECItem encryptedData;
+};
+typedef struct LGEncryptedDataInfoStr LGEncryptedDataInfo;
- if (handle == NULL) {
- return(SECFailure);
- }
+const SEC_ASN1Template lg_EncryptedDataInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(LGEncryptedDataInfo) },
+ { SEC_ASN1_INLINE,
+ offsetof(LGEncryptedDataInfo,algorithm),
+ SECOID_AlgorithmIDTemplate },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(LGEncryptedDataInfo,encryptedData) },
+ { 0 }
+};
+static const unsigned char def_iter_data[] = { SEC_ASN1_INTEGER, 0x01, 0x01 };
+static const SECItem def_iter = { siBuffer ,
+ (unsigned char *)def_iter_data,
+ sizeof(def_iter_data) };
- checkkey.data = KEYDB_PW_CHECK_STRING;
- checkkey.size = KEYDB_PW_CHECK_LEN;
-
- ret = keydb_Get(handle, &checkkey, &checkdata, 0 );
- if ( ret ) {
- /* see if this was an updated DB first */
- checkkey.data = KEYDB_FAKE_PW_CHECK_STRING;
- checkkey.size = KEYDB_FAKE_PW_CHECK_LEN;
- ret = keydb_Get(handle, &checkkey, &checkdata, 0 );
- if ( ret ) {
- return(SECFailure);
- }
- }
+static SECItem *
+nsslowkey_EncodePW(SECOidTag alg, const SECItem *salt, SECItem *data)
+{
+ NSSLowPasswordDataParam param;
+ LGEncryptedDataInfo edi;
+ PLArenaPool *arena;
+ unsigned char one = 1;
+ SECItem *epw = NULL;
+ SECItem *encParam;
+ SECStatus rv;
- return(SECSuccess);
-}
+ param.salt = *salt;
+ param.iter.data = &one;
+ param.iter.len = 1;
+ edi.encryptedData = *data;
-/*
- * Set up the password checker in the key database.
- * This is done by encrypting a known plaintext with the user's key.
- */
-SECStatus
-nsslowkey_SetKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem)
-{
- return nsslowkey_SetKeyDBPasswordAlg(handle, pwitem,
- nsslowkey_GetDefaultKeyDBAlg());
-}
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return NULL;
+ }
-static SECStatus
-HashPassword(unsigned char *hashresult, char *pw, SECItem *salt)
-{
- SHA1Context *cx;
- unsigned int outlen;
- cx = SHA1_NewContext();
- if ( cx == NULL ) {
- return(SECFailure);
+ encParam = SEC_ASN1EncodeItem(arena, NULL, &param,
+ NSSLOWPasswordParamTemplate);
+ if (encParam == NULL) {
+ goto loser;
}
-
- SHA1_Begin(cx);
- if ( ( salt != NULL ) && ( salt->data != NULL ) ) {
- SHA1_Update(cx, salt->data, salt->len);
+ rv = SECOID_SetAlgorithmID(arena, &edi.algorithm, alg, encParam);
+ if (rv != SECSuccess) {
+ goto loser;
}
-
- SHA1_Update(cx, (unsigned char *)pw, PORT_Strlen(pw));
- SHA1_End(cx, hashresult, &outlen, SHA1_LENGTH);
-
- SHA1_DestroyContext(cx, PR_TRUE);
-
- return(SECSuccess);
+ epw = SEC_ASN1EncodeItem(NULL, NULL, &edi, lg_EncryptedDataInfoTemplate);
+
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return epw;
}
-SECItem *
-nsslowkey_HashPassword(char *pw, SECItem *salt)
+static SECItem *
+nsslowkey_DecodePW(const SECItem *derData, SECOidTag *alg, SECItem *salt)
{
- SECItem *pwitem;
+ NSSLowPasswordDataParam param;
+ LGEncryptedDataInfo edi;
+ PLArenaPool *arena;
+ SECItem *pwe = NULL;
SECStatus rv;
-
- pwitem = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if ( pwitem == NULL ) {
- return(NULL);
+
+ salt->data = NULL;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return NULL;
}
- pwitem->len = SHA1_LENGTH;
- pwitem->data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH);
- if ( pwitem->data == NULL ) {
- PORT_Free(pwitem);
- return(NULL);
+
+ rv = SEC_QuickDERDecodeItem(arena, &edi, lg_EncryptedDataInfoTemplate,
+ derData);
+ if (rv != SECSuccess) {
+ goto loser;
}
- if ( pw ) {
- rv = HashPassword(pwitem->data, pw, salt);
- if ( rv != SECSuccess ) {
- SECITEM_ZfreeItem(pwitem, PR_TRUE);
- return(NULL);
- }
+ *alg = SECOID_GetAlgorithmTag(&edi.algorithm);
+ rv = SEC_QuickDERDecodeItem(arena, &param, NSSLOWPasswordParamTemplate,
+ &edi.algorithm.parameters);
+ if (rv != SECSuccess) {
+ goto loser;
}
-
- return(pwitem);
-}
-
-/* Derive the actual password value for the database from a pw string */
-SECItem *
-nsslowkey_DeriveKeyDBPassword(NSSLOWKEYDBHandle *keydb, char *pw)
-{
- PORT_Assert(keydb != NULL);
- PORT_Assert(pw != NULL);
- if (keydb == NULL || pw == NULL) return(NULL);
+ if (SECITEM_ItemsAreEqual(&param.iter, &def_iter) ) {
+ goto loser;
+ }
+ rv = SECITEM_CopyItem(NULL, salt, &param.salt);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ pwe = SECITEM_DupItem(&edi.encryptedData);
- return nsslowkey_HashPassword(pw, keydb->global_salt);
+loser:
+ if (!pwe && salt->data) {
+ PORT_Free(salt->data);
+ salt->data = NULL;
+ }
+ PORT_FreeArena(arena, PR_FALSE);
+ return pwe;
}
+
/*
- * Derive an RC4 key from a password key and a salt. This
- * was the method to used to encrypt keys in the version 2?
- * database
+ * check to see if the user has a password
*/
-SECItem *
-seckey_create_rc4_key(SECItem *pwitem, SECItem *salt)
+static SECStatus
+nsslowkey_GetPWCheckEntry(NSSLOWKEYDBHandle *handle,SDBPasswordEntry *entry)
{
- MD5Context *md5 = NULL;
- unsigned int part;
+ DBT checkkey; /*, checkdata; */
+ NSSLOWKEYDBKey *dbkey = NULL;
+ SECItem *global_salt = NULL;
+ SECItem *item = NULL;
+ SECItem entryData, oid;
SECStatus rv = SECFailure;
- SECItem *key = NULL;
+ SECOidTag algorithm;
- key = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if(key != NULL)
- {
- key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
- MD5_LENGTH);
- key->len = MD5_LENGTH;
- if(key->data != NULL)
- {
- md5 = MD5_NewContext();
- if ( md5 != NULL )
- {
- MD5_Begin(md5);
- MD5_Update(md5, salt->data, salt->len);
- MD5_Update(md5, pwitem->data, pwitem->len);
- MD5_End(md5, key->data, &part, MD5_LENGTH);
- MD5_DestroyContext(md5, PR_TRUE);
- rv = SECSuccess;
- }
- }
+ if (handle == NULL) {
+ /* PORT_SetError */
+ return(SECFailure);
+ }
+
+ global_salt = GetKeyDBGlobalSalt(handle);
+ if (!global_salt) {
+ return SECFailure;
+ }
+ if (global_salt->len > sizeof(entry->data)) {
+ /* PORT_SetError */
+ goto loser;
+ }
- if(rv != SECSuccess)
- {
- SECITEM_FreeItem(key, PR_TRUE);
- key = NULL;
- }
+ PORT_Memcpy(entry->data, global_salt->data, global_salt->len);
+ entry->salt.data = entry->data;
+ entry->salt.len = global_salt->len;
+ entry->value.data = &entry->data[entry->salt.len];
+
+ checkkey.data = KEYDB_PW_CHECK_STRING;
+ checkkey.size = KEYDB_PW_CHECK_LEN;
+ dbkey = get_dbkey(handle, &checkkey);
+ if (dbkey == NULL) {
+ /* handle 'FAKE' check here */
+ goto loser;
}
- return key;
+ oid.len = dbkey->derPK.data[0];
+ oid.data = &dbkey->derPK.data[1];
+
+ if (dbkey->derPK.len < (KEYDB_PW_CHECK_LEN + 1 +oid.len)) {
+ goto loser;
+ }
+ algorithm = SECOID_FindOIDTag(&oid);
+ entryData.len = dbkey->derPK.len - (oid.len+1);
+ entryData.data = &dbkey->derPK.data[oid.len+1];
+
+ item = nsslowkey_EncodePW(algorithm, &dbkey->salt, &entryData);
+ if (!item || (item->len + entry->salt.len) > sizeof(entry->data)) {
+ goto loser;
+ }
+ PORT_Memcpy(entry->value.data, item->data, item->len);
+ entry->value.len = item->len;
+ rv = SECSuccess;
+
+loser:
+ if (item) {
+ SECITEM_FreeItem(item, PR_TRUE);
+ }
+ if (dbkey) {
+ sec_destroy_dbkey(dbkey);
+ }
+ if (global_salt) {
+ SECITEM_FreeItem(global_salt,PR_TRUE);
+ }
+ return rv;
}
-SECItem *
-seckey_create_rc4_salt(void)
+/*
+ * check to see if the user has a password
+ */
+static SECStatus
+nsslowkey_PutPWCheckEntry(NSSLOWKEYDBHandle *handle,SDBPasswordEntry *entry)
{
- SECItem *salt = NULL;
+ DBT checkkey;
+ NSSLOWKEYDBKey *dbkey = NULL;
+ SECItem *item = NULL;
+ SECItem salt;
+ SECOidTag algid;
SECStatus rv = SECFailure;
+ PLArenaPool *arena;
- salt = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if(salt == NULL)
- return NULL;
+ if (handle == NULL) {
+ /* PORT_SetError */
+ return(SECFailure);
+ }
- salt->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
- SALT_LENGTH);
- if(salt->data != NULL)
- {
- salt->len = SALT_LENGTH;
- rv = RNG_GenerateGlobalRandomBytes(salt->data, salt->len);
- if(rv != SECSuccess)
- sftk_fatalError = PR_TRUE;
+ checkkey.data = KEYDB_PW_CHECK_STRING;
+ checkkey.size = KEYDB_PW_CHECK_LEN;
+
+ salt.data = NULL;
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return SECFailure;
}
-
- if(rv != SECSuccess)
- {
- SECITEM_FreeItem(salt, PR_TRUE);
- salt = NULL;
+
+ item = nsslowkey_DecodePW(&entry->value, &algid, &salt);
+ if (item == NULL) {
+ goto loser;
}
- return salt;
-}
+ dbkey = PORT_ArenaZNew(arena, NSSLOWKEYDBKey);
+ if (dbkey == NULL) {
+ goto loser;
+ }
-SECItem *
-seckey_rc4_decode(SECItem *key, SECItem *src)
-{
- SECItem *dest = NULL;
- RC4Context *ctxt = NULL;
- SECStatus rv = SECFailure;
+ dbkey->arena = arena;
- if((key == NULL) || (src == NULL))
- return NULL;
+ rv = SECITEM_CopyItem(arena, &dbkey->salt, &salt);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
- dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if(dest == NULL)
- return NULL;
+ rv = encodePWCheckEntry(arena, &dbkey->derPK, algid, item);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
- dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
- (src->len + 64)); /* TNH - padding? */
- if(dest->data != NULL)
- {
- ctxt = RC4_CreateContext(key->data, key->len);
- if(ctxt != NULL)
- {
- rv = RC4_Decrypt(ctxt, dest->data, &dest->len,
- src->len + 64, src->data, src->len);
- RC4_DestroyContext(ctxt, PR_TRUE);
- }
+ rv = put_dbkey(handle, &checkkey, dbkey, PR_TRUE);
+ if (rv != SECSuccess) {
+ goto loser;
}
- if(rv == SECFailure)
- if(dest != NULL)
- {
- SECITEM_FreeItem(dest, PR_TRUE);
- dest = NULL;
- }
+ if (handle->global_salt) {
+ SECITEM_FreeItem(handle->global_salt, PR_TRUE);
+ handle->global_salt = NULL;
+ }
+ rv = StoreKeyDBGlobalSalt(handle, &entry->salt);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ handle->global_salt = GetKeyDBGlobalSalt(handle);
- return dest;
+loser:
+ if (item) {
+ SECITEM_FreeItem(item, PR_TRUE);
+ }
+ if (arena) {
+ PORT_FreeArena(arena, PR_TRUE);
+ }
+ if (salt.data) {
+ PORT_Free(salt.data);
+ }
+ return rv;
}
-
#ifdef EC_DEBUG
#define SEC_PRINT(str1, str2, num, sitem) \
printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
@@ -1551,46 +1513,33 @@ seckey_rc4_decode(SECItem *key, SECItem *src)
#define SEC_PRINT(a, b, c, d)
#endif /* EC_DEBUG */
-/* TNH - keydb is unused */
-/* TNH - the pwitem should be the derived key for RC4 */
-NSSLOWKEYEncryptedPrivateKeyInfo *
-seckey_encrypt_private_key(
- NSSLOWKEYPrivateKey *pk, SECItem *pwitem, NSSLOWKEYDBHandle *keydb,
- SECOidTag algorithm, SECItem **salt)
+
+SECStatus
+seckey_encrypt_private_key( PLArenaPool *permarena, NSSLOWKEYPrivateKey *pk,
+ SDB *sdbpw, SECItem *result)
{
- NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL;
NSSLOWKEYPrivateKeyInfo *pki = NULL;
SECStatus rv = SECFailure;
- PLArenaPool *temparena = NULL, *permarena = NULL;
+ PLArenaPool *temparena = NULL;
SECItem *der_item = NULL;
- NSSPKCS5PBEParameter *param = NULL;
- SECItem *dummy = NULL, *dest = NULL;
- SECAlgorithmID *algid;
+ SECItem *cipherText = NULL;
+ SECItem *dummy = NULL;
#ifdef NSS_ENABLE_ECC
SECItem *fordebug = NULL;
int savelen;
- int i;
#endif
- *salt = NULL;
- permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
- if(permarena == NULL)
- return NULL;
-
temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if(temparena == NULL)
goto loser;
/* allocate structures */
- epki = (NSSLOWKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(permarena,
- sizeof(NSSLOWKEYEncryptedPrivateKeyInfo));
pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(temparena,
sizeof(NSSLOWKEYPrivateKeyInfo));
der_item = (SECItem *)PORT_ArenaZAlloc(temparena, sizeof(SECItem));
- if((epki == NULL) || (pki == NULL) || (der_item == NULL))
+ if((pki == NULL) || (der_item == NULL))
goto loser;
- epki->arena = permarena;
/* setup private key info */
dummy = SEC_ASN1EncodeInteger(temparena, &(pki->version),
@@ -1713,72 +1662,30 @@ seckey_encrypt_private_key(
goto loser;
}
- rv = SECFailure; /* assume failure */
- *salt = seckey_create_rc4_salt();
- if (*salt == NULL) {
- goto loser;
- }
-
- param = nsspkcs5_NewParam(algorithm,*salt,1);
- if (param == NULL) {
- goto loser;
- }
-
- dest = nsspkcs5_CipherData(param, pwitem, der_item, PR_TRUE, NULL);
- if (dest == NULL) {
- goto loser;
- }
-
- rv = SECITEM_CopyItem(permarena, &epki->encryptedData, dest);
+ rv = lg_util_encrypt(temparena, sdbpw, dummy, &cipherText);
if (rv != SECSuccess) {
goto loser;
}
- algid = nsspkcs5_CreateAlgorithmID(permarena, algorithm, param);
- if (algid == NULL) {
- rv = SECFailure;
- goto loser;
- }
-
- rv = SECOID_CopyAlgorithmID(permarena, &epki->algorithm, algid);
- SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+ rv = SECITEM_CopyItem ( permarena, result, cipherText);
loser:
- if(dest != NULL)
- SECITEM_FreeItem(dest, PR_TRUE);
-
- if(param != NULL)
- nsspkcs5_DestroyPBEParameter(param);
-
- /* let success fall through */
-
- if(rv == SECFailure)
- {
- PORT_FreeArena(permarena, PR_TRUE);
- epki = NULL;
- if(*salt != NULL)
- SECITEM_FreeItem(*salt, PR_TRUE);
- }
if(temparena != NULL)
PORT_FreeArena(temparena, PR_TRUE);
- return epki;
+ return rv;
}
static SECStatus
-seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem,
- NSSLOWKEYPrivateKey *pk, char *nickname, PRBool update,
- SECOidTag algorithm)
+seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SDB *sdbpw,
+ NSSLOWKEYPrivateKey *pk, char *nickname, PRBool update)
{
NSSLOWKEYDBKey *dbkey = NULL;
- NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL;
- PLArenaPool *arena = NULL;
- SECItem *dummy = NULL;
- SECItem *salt = NULL;
+ PLArenaPool *arena = NULL;
SECStatus rv = SECFailure;
- if((keydb == NULL) || (index == NULL) || (pwitem == NULL) ||
+ if((keydb == NULL) || (index == NULL) || (sdbpw == NULL) ||
(pk == NULL))
return SECFailure;
@@ -1792,31 +1699,16 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem,
dbkey->arena = arena;
dbkey->nickname = nickname;
- /* TNH - for RC4, the salt should be created here */
-
- epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm, &salt);
- if(epki == NULL)
+ rv = seckey_encrypt_private_key(arena, pk, sdbpw, &dbkey->derPK);
+ if(rv != SECSuccess)
goto loser;
- if(salt != NULL)
- {
- rv = SECITEM_CopyItem(arena, &(dbkey->salt), salt);
- SECITEM_ZfreeItem(salt, PR_TRUE);
- }
-
- dummy = SEC_ASN1EncodeItem(arena, &(dbkey->derPK), epki,
- nsslowkey_EncryptedPrivateKeyInfoTemplate);
- if(dummy == NULL)
- rv = SECFailure;
- else
- rv = put_dbkey(keydb, index, dbkey, update);
+ rv = put_dbkey(keydb, index, dbkey, update);
/* let success fall through */
loser:
if(arena != NULL)
- PORT_FreeArena(arena, PR_TRUE);
- if(epki != NULL)
- PORT_FreeArena(epki->arena, PR_TRUE);
+ PORT_FreeArena(arena, PR_TRUE);
return rv;
}
@@ -1830,8 +1722,7 @@ nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
- SECItem *pwitem,
- SECOidTag algorithm,
+ SDB *sdbpw,
PRBool update)
{
DBT namekey;
@@ -1847,30 +1738,26 @@ nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
namekey.size = pubKeyData->len;
/* encrypt the private key */
- rv = seckey_put_private_key(handle, &namekey, pwitem, privkey, nickname,
- update, algorithm);
+ rv = seckey_put_private_key(handle, &namekey, sdbpw, privkey, nickname,
+ update);
return(rv);
}
-NSSLOWKEYPrivateKey *
-seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki,
- SECItem *pwitem)
+static NSSLOWKEYPrivateKey *
+seckey_decrypt_private_key(SECItem*epki,
+ SDB *sdbpw)
{
NSSLOWKEYPrivateKey *pk = NULL;
NSSLOWKEYPrivateKeyInfo *pki = NULL;
SECStatus rv = SECFailure;
- SECOidTag algorithm;
PLArenaPool *temparena = NULL, *permarena = NULL;
- SECItem *salt = NULL, *dest = NULL, *key = NULL;
- NSSPKCS5PBEParameter *param;
+ SECItem *dest = NULL;
#ifdef NSS_ENABLE_ECC
- ECPrivateKey *ecpriv;
SECItem *fordebug = NULL;
- int i;
#endif
- if((epki == NULL) || (pwitem == NULL))
+ if((epki == NULL) || (sdbpw == NULL))
goto loser;
temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
@@ -1890,39 +1777,12 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki,
goto loser;
pk->arena = permarena;
-
- algorithm = SECOID_GetAlgorithmTag(&(epki->algorithm));
- switch(algorithm)
- {
- case SEC_OID_RC4:
- salt = SECITEM_DupItem(&epki->algorithm.parameters);
- if(salt != NULL)
- {
- key = seckey_create_rc4_key(pwitem, salt);
- if(key != NULL)
- {
- dest = seckey_rc4_decode(key, &epki->encryptedData);
- }
- }
- if(salt != NULL)
- SECITEM_ZfreeItem(salt, PR_TRUE);
- if(key != NULL)
- SECITEM_ZfreeItem(key, PR_TRUE);
- break;
- default:
- /* we depend on the fact that if this key was encoded with
- * DES, that the pw was also encoded with DES, so we don't have
- * to do the update here, the password code will handle it. */
- param = nsspkcs5_AlgidToParam(&epki->algorithm);
- if (param == NULL) {
- break;
- }
- dest = nsspkcs5_CipherData(param, pwitem, &epki->encryptedData,
- PR_FALSE, NULL);
- nsspkcs5_DestroyPBEParameter(param);
- break;
- }
+ rv = lg_util_decrypt(sdbpw, epki, &dest);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
if(dest != NULL)
{
SECItem newPrivateKey;
@@ -1998,32 +1858,13 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki,
goto loser;
/* Fill out the rest of EC params */
- rv = EC_FillParams(permarena, &pk->u.ec.ecParams.DEREncoding,
+ rv = LGEC_FillParams(permarena, &pk->u.ec.ecParams.DEREncoding,
&pk->u.ec.ecParams);
if (rv != SECSuccess)
goto loser;
- /*
- * NOTE: Encoding of the publicValue is optional
- * so we need to be able to regenerate the publicValue
- * from the base point and the private key.
- *
- * XXX This part of the code needs more testing.
- */
- if (pk->u.ec.publicValue.len == 0) {
- rv = EC_NewKeyFromSeed(&pk->u.ec.ecParams,
- &ecpriv, pk->u.ec.privateValue.data,
- pk->u.ec.privateValue.len);
- if (rv == SECSuccess) {
- SECITEM_CopyItem(permarena, &pk->u.ec.publicValue,
- &(ecpriv->publicValue));
- PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
- }
- } else {
- /* If publicValue was filled as part of DER decoding,
- * change length in bits to length in bytes.
- */
+ if (pk->u.ec.publicValue.len != 0) {
pk->u.ec.publicValue.len >>= 3;
}
@@ -2059,67 +1900,23 @@ loser:
}
static NSSLOWKEYPrivateKey *
-seckey_decode_encrypted_private_key(NSSLOWKEYDBKey *dbkey, SECItem *pwitem)
+seckey_decode_encrypted_private_key(NSSLOWKEYDBKey *dbkey, SDB *sdbpw)
{
- NSSLOWKEYPrivateKey *pk = NULL;
- NSSLOWKEYEncryptedPrivateKeyInfo *epki;
- PLArenaPool *temparena = NULL;
- SECStatus rv;
- SECOidTag algorithm;
-
- if( ( dbkey == NULL ) || ( pwitem == NULL ) ) {
+ if( ( dbkey == NULL ) || ( sdbpw == NULL ) ) {
return NULL;
}
- temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if(temparena == NULL) {
- return NULL;
- }
-
- epki = (NSSLOWKEYEncryptedPrivateKeyInfo *)
- PORT_ArenaZAlloc(temparena, sizeof(NSSLOWKEYEncryptedPrivateKeyInfo));
-
- if(epki == NULL) {
- goto loser;
- }
-
- rv = SEC_QuickDERDecodeItem(temparena, epki,
- nsslowkey_EncryptedPrivateKeyInfoTemplate,
- &(dbkey->derPK));
- if(rv != SECSuccess) {
- goto loser;
- }
-
- algorithm = SECOID_GetAlgorithmTag(&(epki->algorithm));
- switch(algorithm)
- {
- case SEC_OID_RC4:
- /* TNH - this code should derive the actual RC4 key from salt and
- pwitem */
- rv = SECITEM_CopyItem(temparena, &(epki->algorithm.parameters),
- &(dbkey->salt));
- break;
- default:
- break;
- }
-
- pk = seckey_decrypt_private_key(epki, pwitem);
-
- /* let success fall through */
-loser:
-
- PORT_FreeArena(temparena, PR_TRUE);
- return pk;
+ return seckey_decrypt_private_key(&(dbkey->derPK), sdbpw);
}
-NSSLOWKEYPrivateKey *
+static NSSLOWKEYPrivateKey *
seckey_get_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, char **nickname,
- SECItem *pwitem)
+ SDB *sdbpw)
{
NSSLOWKEYDBKey *dbkey = NULL;
NSSLOWKEYPrivateKey *pk = NULL;
- if( ( keydb == NULL ) || ( index == NULL ) || ( pwitem == NULL ) ) {
+ if( ( keydb == NULL ) || ( index == NULL ) || ( sdbpw == NULL ) ) {
return NULL;
}
@@ -2136,7 +1933,7 @@ seckey_get_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, char **nickname,
}
}
- pk = seckey_decode_encrypted_private_key(dbkey, pwitem);
+ pk = seckey_decode_encrypted_private_key(dbkey, sdbpw);
/* let success fall through */
loser:
@@ -2149,16 +1946,6 @@ loser:
}
/*
- * used by pkcs11 to import keys into it's object format... In the future
- * we really need a better way to tie in...
- */
-NSSLOWKEYPrivateKey *
-nsslowkey_DecryptKey(DBT *key, SECItem *pwitem,
- NSSLOWKEYDBHandle *handle) {
- return seckey_get_private_key(handle,key,NULL,pwitem);
-}
-
-/*
* Find a key in the database, indexed by its public key modulus
* This is used to find keys that have been stored before their
* certificate arrives. Once the certificate arrives the key
@@ -2167,7 +1954,7 @@ nsslowkey_DecryptKey(DBT *key, SECItem *pwitem,
*/
NSSLOWKEYPrivateKey *
nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
- SECItem *pwitem)
+ SDB *sdbpw)
{
DBT namekey;
NSSLOWKEYPrivateKey *pk = NULL;
@@ -2181,7 +1968,7 @@ nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
namekey.data = modulus->data;
namekey.size = modulus->len;
- pk = seckey_get_private_key(handle, &namekey, NULL, pwitem);
+ pk = seckey_get_private_key(handle, &namekey, NULL, sdbpw);
/* no need to free dbkey, since its on the stack, and the data it
* points to is owned by the database
@@ -2191,7 +1978,7 @@ nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
char *
nsslowkey_FindKeyNicknameByPublicKey(NSSLOWKEYDBHandle *handle,
- SECItem *modulus, SECItem *pwitem)
+ SECItem *modulus, SDB *sdbpw)
{
DBT namekey;
NSSLOWKEYPrivateKey *pk = NULL;
@@ -2206,7 +1993,7 @@ nsslowkey_FindKeyNicknameByPublicKey(NSSLOWKEYDBHandle *handle,
namekey.data = modulus->data;
namekey.size = modulus->len;
- pk = seckey_get_private_key(handle, &namekey, &nickname, pwitem);
+ pk = seckey_get_private_key(handle, &namekey, &nickname, sdbpw);
if (pk) {
nsslowkey_DestroyPrivateKey(pk);
}
@@ -2255,428 +2042,13 @@ encodePWCheckEntry(PLArenaPool *arena, SECItem *entry, SECOidTag alg,
loser:
return(SECFailure);
}
-
-/*
- * Set up the password checker in the key database.
- * This is done by encrypting a known plaintext with the user's key.
- */
-SECStatus
-nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
- SECItem *pwitem, SECOidTag algorithm)
-{
- DBT checkkey;
- NSSPKCS5PBEParameter *param = NULL;
- SECStatus rv = SECFailure;
- NSSLOWKEYDBKey *dbkey = NULL;
- PLArenaPool *arena;
- SECItem *salt = NULL;
- SECItem *dest = NULL, test_key;
-
- if (handle == NULL) {
- return(SECFailure);
- }
-
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if ( arena == NULL ) {
- rv = SECFailure;
- goto loser;
- }
-
- dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYDBKey));
- if ( dbkey == NULL ) {
- rv = SECFailure;
- goto loser;
- }
-
- dbkey->arena = arena;
-
- /* encrypt key */
- checkkey.data = test_key.data = (unsigned char *)KEYDB_PW_CHECK_STRING;
- checkkey.size = test_key.len = KEYDB_PW_CHECK_LEN;
-
- salt = seckey_create_rc4_salt();
- if(salt == NULL) {
- rv = SECFailure;
- goto loser;
- }
-
- param = nsspkcs5_NewParam(algorithm, salt, 1);
- if (param == NULL) {
- rv = SECFailure;
- goto loser;
- }
-
- dest = nsspkcs5_CipherData(param, pwitem, &test_key, PR_TRUE, NULL);
- if (dest == NULL)
- {
- rv = SECFailure;
- goto loser;
- }
-
- rv = SECITEM_CopyItem(arena, &dbkey->salt, salt);
- if (rv == SECFailure) {
- goto loser;
- }
-
- rv = encodePWCheckEntry(arena, &dbkey->derPK, algorithm, dest);
-
- if ( rv != SECSuccess ) {
- goto loser;
- }
-
- rv = put_dbkey(handle, &checkkey, dbkey, PR_TRUE);
-
- /* let success fall through */
-loser:
- if ( arena != NULL ) {
- PORT_FreeArena(arena, PR_TRUE);
- }
-
- if ( dest != NULL ) {
- SECITEM_ZfreeItem(dest, PR_TRUE);
- }
-
- if ( salt != NULL ) {
- SECITEM_ZfreeItem(salt, PR_TRUE);
- }
-
- if (param != NULL) {
- nsspkcs5_DestroyPBEParameter(param);
- }
-
- return(rv);
-}
-
-static SECStatus
-seckey_CheckKeyDB1Password(NSSLOWKEYDBHandle *handle, SECItem *pwitem)
-{
- SECStatus rv = SECFailure;
- keyList keylist;
- keyNode *node = NULL;
- NSSLOWKEYPrivateKey *privkey = NULL;
-
-
- /*
- * first find a key
- */
-
- /* traverse the database, collecting the keys of all records */
- keylist.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if ( keylist.arena == NULL )
- {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return(SECFailure);
- }
- keylist.head = NULL;
-
- /* TNH - TraverseKeys should not be public, since it exposes
- the underlying DBT data type. */
- rv = nsslowkey_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist);
- if ( rv != SECSuccess )
- goto done;
-
- /* just get the first key from the list */
- node = keylist.head;
-
- /* no private keys, accept any password */
- if (node == NULL) {
- rv = SECSuccess;
- goto done;
- }
- privkey = seckey_get_private_key(handle, &node->key, NULL, pwitem);
- if (privkey == NULL) {
- rv = SECFailure;
- goto done;
- }
-
- /* if we can decrypt the private key, then we had the correct password */
- rv = SECSuccess;
- nsslowkey_DestroyPrivateKey(privkey);
-
-done:
-
- /* free the arena */
- if ( keylist.arena ) {
- PORT_FreeArena(keylist.arena, PR_FALSE);
- }
-
- return(rv);
-}
-
-/*
- * check to see if the user has typed the right password
- */
-SECStatus
-nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem)
-{
- DBT checkkey;
- DBT checkdata;
- NSSPKCS5PBEParameter *param = NULL;
- SECStatus rv = SECFailure;
- NSSLOWKEYDBKey *dbkey = NULL;
- SECItem *key = NULL;
- SECItem *dest = NULL;
- SECOidTag algorithm;
- SECItem oid;
- SECItem encstring;
- PRBool update = PR_FALSE;
- int ret;
-
- if (handle == NULL) {
- goto loser;
- }
-
- checkkey.data = KEYDB_PW_CHECK_STRING;
- checkkey.size = KEYDB_PW_CHECK_LEN;
-
- dbkey = get_dbkey(handle, &checkkey);
-
- if ( dbkey == NULL ) {
- checkkey.data = KEYDB_FAKE_PW_CHECK_STRING;
- checkkey.size = KEYDB_FAKE_PW_CHECK_LEN;
- ret = keydb_Get(handle, &checkkey, &checkdata, 0 );
- if (ret) {
- goto loser;
- }
- /* if we have the fake PW_CHECK, then try to decode the key
- * rather than the pwcheck item.
- */
- rv = seckey_CheckKeyDB1Password(handle,pwitem);
- if (rv == SECSuccess) {
- /* OK we have enough to complete our conversion */
- nsslowkey_UpdateKeyDBPass2(handle,pwitem);
- }
- return rv;
- }
-
- /* build the oid item */
- oid.len = dbkey->derPK.data[0];
- oid.data = &dbkey->derPK.data[1];
-
- /* make sure entry is the correct length
- * since we are probably using a block cipher, the block will be
- * padded, so we may get a bit more than the exact size we need.
- */
- if ( dbkey->derPK.len < (KEYDB_PW_CHECK_LEN + 1 + oid.len ) ) {
- goto loser;
- }
-
- /* find the algorithm tag */
- algorithm = SECOID_FindOIDTag(&oid);
-
- /* make a secitem of the encrypted check string */
- encstring.len = dbkey->derPK.len - ( oid.len + 1 );
- encstring.data = &dbkey->derPK.data[oid.len+1];
- encstring.type = 0;
-
- switch(algorithm)
- {
- case SEC_OID_RC4:
- key = seckey_create_rc4_key(pwitem, &dbkey->salt);
- if(key != NULL) {
- dest = seckey_rc4_decode(key, &encstring);
- SECITEM_FreeItem(key, PR_TRUE);
- }
- break;
- default:
- param = nsspkcs5_NewParam(algorithm, &dbkey->salt, 1);
- if (param != NULL) {
- /* Decrypt - this function implements a workaround for
- * a previous coding error. It will decrypt values using
- * DES rather than 3DES, if the initial try at 3DES
- * decryption fails. In this case, the update flag is
- * set to TRUE. This indication is used later to force
- * an update of the database to "real" 3DES encryption.
- */
- dest = nsspkcs5_CipherData(param, pwitem,
- &encstring, PR_FALSE, &update);
- nsspkcs5_DestroyPBEParameter(param);
- }
- break;
- }
-
- if(dest == NULL) {
- goto loser;
- }
-
- if ((dest->len == KEYDB_PW_CHECK_LEN) &&
- (PORT_Memcmp(dest->data,
- KEYDB_PW_CHECK_STRING, KEYDB_PW_CHECK_LEN) == 0)) {
- rv = SECSuccess;
- /* we succeeded */
- if ( algorithm == SEC_OID_RC4 ) {
- /* partially updated database */
- nsslowkey_UpdateKeyDBPass2(handle, pwitem);
- }
- /* Force an update of the password to remove the incorrect DES
- * encryption (see the note above)
- */
- if (update &&
- (algorithm == SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC)) {
- /* data base was encoded with DES not triple des, fix it */
- nsslowkey_UpdateKeyDBPass2(handle,pwitem);
- }
- }
-
-loser:
- sec_destroy_dbkey(dbkey);
- if(dest != NULL) {
- SECITEM_ZfreeItem(dest, PR_TRUE);
- }
-
- return(rv);
-}
-
-/*
- * Change the database password and/or algorithm. This internal
- * routine does not check the old password. That must be done by
- * the caller.
- */
-static SECStatus
-ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
- SECItem *oldpwitem, SECItem *newpwitem,
- SECOidTag new_algorithm)
-{
- SECStatus rv;
- keyList keylist;
- keyNode *node = NULL;
- NSSLOWKEYPrivateKey *privkey = NULL;
- char *nickname;
- DBT newkey;
- int ret;
-
- /* traverse the database, collecting the keys of all records */
- keylist.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if ( keylist.arena == NULL )
- {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return(SECFailure);
- }
- keylist.head = NULL;
-
- rv = db_BeginTransaction(handle->db);
- if (rv != SECSuccess) {
- goto loser;
- }
-
- /* TNH - TraverseKeys should not be public, since it exposes
- the underlying DBT data type. */
- rv = nsslowkey_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist);
- if ( rv != SECSuccess )
- goto loser;
-
- /* walk the list, re-encrypting each entry */
- node = keylist.head;
- while ( node != NULL )
- {
- privkey = seckey_get_private_key(handle, &node->key, &nickname,
- oldpwitem);
-
- if (privkey == NULL) {
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- rv = SECFailure;
- goto loser;
- }
-
- /* delete the old record */
- ret = keydb_Del(handle, &node->key, 0);
- if ( ret ) {
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- rv = SECFailure;
- goto loser;
- }
-
- /* get the public key, which we use as the database index */
-
- switch (privkey->keyType) {
- case NSSLOWKEYRSAKey:
- newkey.data = privkey->u.rsa.modulus.data;
- newkey.size = privkey->u.rsa.modulus.len;
- break;
- case NSSLOWKEYDSAKey:
- newkey.data = privkey->u.dsa.publicValue.data;
- newkey.size = privkey->u.dsa.publicValue.len;
- break;
- case NSSLOWKEYDHKey:
- newkey.data = privkey->u.dh.publicValue.data;
- newkey.size = privkey->u.dh.publicValue.len;
- break;
-#ifdef NSS_ENABLE_ECC
- case NSSLOWKEYECKey:
- newkey.data = privkey->u.ec.publicValue.data;
- newkey.size = privkey->u.ec.publicValue.len;
- break;
-#endif /* NSS_ENABLE_ECC */
- default:
- /* should we continue here and loose the key? */
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- rv = SECFailure;
- goto loser;
- }
-
- rv = seckey_put_private_key(handle, &newkey, newpwitem, privkey,
- nickname, PR_TRUE, new_algorithm);
-
- if ( rv != SECSuccess )
- {
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- rv = SECFailure;
- goto loser;
- }
-
- /* next node */
- node = node->next;
- }
-
- rv = nsslowkey_SetKeyDBPasswordAlg(handle, newpwitem, new_algorithm);
-
-loser:
-
- db_FinishTransaction(handle->db,rv != SECSuccess);
-
- /* free the arena */
- if ( keylist.arena ) {
- PORT_FreeArena(keylist.arena, PR_FALSE);
- }
-
- return(rv);
-}
-
-/*
- * Re-encrypt the entire key database with a new password.
- * NOTE: The really should create a new database rather than doing it
- * in place in the original
- */
-SECStatus
-nsslowkey_ChangeKeyDBPassword(NSSLOWKEYDBHandle *handle,
- SECItem *oldpwitem, SECItem *newpwitem)
-{
- SECStatus rv;
-
- if (handle == NULL) {
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- rv = SECFailure;
- goto loser;
- }
-
- rv = nsslowkey_CheckKeyDBPassword(handle, oldpwitem);
- if ( rv != SECSuccess ) {
- return(SECFailure); /* return rv? */
- }
-
- rv = ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem,
- nsslowkey_GetDefaultKeyDBAlg());
-
-loser:
- return(rv);
-}
#define MAX_DB_SIZE 0xffff
/*
* Clear out all the keys in the existing database
*/
-SECStatus
+static SECStatus
nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
{
SECStatus rv;
@@ -2715,7 +2087,7 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
}
if (handle->global_salt) {
- rv = StoreKeyDBGlobalSalt(handle);
+ rv = StoreKeyDBGlobalSalt(handle, handle->global_salt);
} else {
rv = makeGlobalSalt(handle);
if ( rv == SECSuccess ) {
@@ -2841,3 +2213,58 @@ keydb_Close(NSSLOWKEYDBHandle *kdb)
return;
}
+/*
+ * SDB Entry Points for the Key DB
+ */
+
+CK_RV
+lg_GetPWEntry(SDB *sdb, SDBPasswordEntry *entry)
+{
+ NSSLOWKEYDBHandle *keydb;
+ SECStatus rv;
+
+ keydb = lg_getKeyDB(sdb);
+ if (keydb == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ rv = nsslowkey_GetPWCheckEntry(keydb, entry);
+ if (rv != SECSuccess) {
+ return CKR_GENERAL_ERROR;
+ }
+ return CKR_OK;
+}
+
+CK_RV
+lg_PutPWEntry(SDB *sdb, SDBPasswordEntry *entry)
+{
+ NSSLOWKEYDBHandle *keydb;
+ SECStatus rv;
+
+ keydb = lg_getKeyDB(sdb);
+ if (keydb == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ rv = nsslowkey_PutPWCheckEntry(keydb, entry);
+ if (rv != SECSuccess) {
+ return CKR_GENERAL_ERROR;
+ }
+ return CKR_OK;
+}
+
+CK_RV
+lg_Reset(SDB *sdb)
+{
+ NSSLOWKEYDBHandle *keydb;
+ SECStatus rv;
+
+ keydb = lg_getKeyDB(sdb);
+ if (keydb == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ rv = nsslowkey_ResetKeyDB(keydb);
+ if (rv != SECSuccess) {
+ return CKR_GENERAL_ERROR;
+ }
+ return CKR_OK;
+}
+
diff --git a/security/nss/lib/softoken/keydbi.h b/security/nss/lib/softoken/legacydb/keydbi.h
index f7f427266..f7f427266 100644
--- a/security/nss/lib/softoken/keydbi.h
+++ b/security/nss/lib/softoken/legacydb/keydbi.h
diff --git a/security/nss/lib/softoken/legacydb/legacydb.def b/security/nss/lib/softoken/legacydb/legacydb.def
new file mode 100644
index 000000000..3e3247099
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/legacydb.def
@@ -0,0 +1,64 @@
+;+#
+;+# ***** BEGIN LICENSE BLOCK *****
+;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+;+#
+;+# The contents of this file are subject to the Mozilla Public License Version
+;+# 1.1 (the "License"); you may not use this file except in compliance with
+;+# the License. You may obtain a copy of the License at
+;+# http://www.mozilla.org/MPL/
+;+#
+;+# Software distributed under the License is distributed on an "AS IS" basis,
+;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+;+# for the specific language governing rights and limitations under the
+;+# License.
+;+#
+;+# The Original Code is the Netscape security libraries.
+;+#
+;+# The Initial Developer of the Original Code is
+;+# Netscape Communications Corporation.
+;+# Portions created by the Initial Developer are Copyright (C) 2000
+;+# the Initial Developer. All Rights Reserved.
+;+#
+;+# Contributor(s):
+;+# Dr Stephen Henson <stephen.henson@gemplus.com>
+;+#
+;+# Alternatively, the contents of this file may be used under the terms of
+;+# either the GNU General Public License Version 2 or later (the "GPL"), or
+;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+;+# in which case the provisions of the GPL or the LGPL are applicable instead
+;+# of those above. If you wish to allow use of your version of this file only
+;+# under the terms of either the GPL or the LGPL, and not to allow others to
+;+# use your version of this file under the terms of the MPL, indicate your
+;+# decision by deleting the provisions above and replace them with the notice
+;+# and other provisions required by the GPL or the LGPL. If you do not delete
+;+# the provisions above, a recipient may use your version of this file under
+;+# the terms of any one of the MPL, the GPL or the LGPL.
+;+#
+;+# ***** END LICENSE BLOCK *****
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+LGDBM_3.12 { # NSS 3.12 release
+;+ global:
+LIBRARY lgdbm3 ;-
+EXPORTS ;-
+legacy_Open;
+legacy_Shutdown;
+legacy_ReadSecmodDB;
+legacy_ReleaseSecmodDBData;
+legacy_AddSecmodDB;
+legacy_DeleteSecmodDB;
+legacy_SetCryptFunctions;
+;+ local:
+;+ *;
+;+};
diff --git a/security/nss/lib/softoken/legacydb/lgattr.c b/security/nss/lib/softoken/legacydb/lgattr.c
new file mode 100644
index 000000000..428d2ae66
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lgattr.c
@@ -0,0 +1,1748 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * Internal PKCS #11 functions. Should only be called by pkcs11.c
+ */
+#include "pkcs11.h"
+#include "lgdb.h"
+
+#include "pcertt.h"
+#include "lowkeyi.h"
+#include "pcert.h"
+#include "blapi.h"
+#include "secerr.h"
+
+/*
+ * Cache the object we are working on during Set's and Get's
+ */
+typedef struct LGObjectCacheStr {
+ CK_OBJECT_CLASS objclass;
+ CK_OBJECT_HANDLE handle;
+ SDB *sdb;
+ void *objectInfo;
+ LGFreeFunc infoFree;
+ SECItem dbKey;
+} LGObjectCache;
+
+static const CK_OBJECT_HANDLE lg_classArray[] = {
+ 0, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY,
+ CKO_NETSCAPE_TRUST, CKO_NETSCAPE_CRL, CKO_NETSCAPE_SMIME,
+ CKO_CERTIFICATE };
+
+#define handleToClass(handle) \
+ lg_classArray[((handle & LG_TOKEN_TYPE_MASK))>>LG_TOKEN_TYPE_SHIFT]
+
+
+static void lg_DestroyObjectCache(LGObjectCache *obj);
+
+static LGObjectCache *
+lg_NewObjectCache(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE handle)
+{
+ LGObjectCache *obj = NULL;
+ SECStatus rv;
+
+ obj = PORT_New(LGObjectCache);
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ obj->objclass = handleToClass(handle);
+ obj->handle = handle;
+ obj->sdb = sdb;
+ obj->objectInfo = NULL;
+ obj->infoFree = NULL;
+ lg_DBLock(sdb);
+ if (dbKey == NULL) {
+ dbKey = lg_lookupTokenKeyByHandle(sdb,handle);
+ }
+ if (dbKey == NULL) {
+ lg_DBUnlock(sdb);
+ goto loser;
+ }
+ rv = SECITEM_CopyItem(NULL,&obj->dbKey,dbKey);
+ lg_DBUnlock(sdb);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ return obj;
+loser:
+ if (obj) {
+ (void) lg_DestroyObjectCache(obj);
+ }
+ return NULL;
+
+}
+
+/*
+ * free all the data associated with an object. Object reference count must
+ * be 'zero'.
+ */
+static void
+lg_DestroyObjectCache(LGObjectCache *obj)
+{
+ if (obj->dbKey.data) {
+ PORT_Free(obj->dbKey.data);
+ obj->dbKey.data = NULL;
+ }
+ if (obj->objectInfo) {
+ (*obj->infoFree)(obj->objectInfo);
+ obj->objectInfo = NULL;
+ obj->infoFree = NULL;
+ }
+ PORT_Free(obj);
+}
+/*
+ * ******************** Attribute Utilities *******************************
+ */
+
+static CK_RV
+lg_ULongAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type, CK_ULONG value)
+{
+ unsigned char *data;
+ int i;
+
+ if (attr->pValue == NULL) {
+ attr->ulValueLen = 4;
+ return CKR_OK;
+ }
+ if (attr->ulValueLen < 4) {
+ attr->ulValueLen = (CK_ULONG) -1;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ data = (unsigned char *)attr->pValue;
+ for (i=0; i < 4; i++) {
+ data[i] = (value >> ((3-i)*8)) & 0xff;
+ }
+ attr->ulValueLen = 4;
+ return CKR_OK;
+}
+
+static CK_RV
+lg_CopyAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type,
+ CK_VOID_PTR value, CK_ULONG len)
+{
+
+ if (attr->pValue == NULL) {
+ attr->ulValueLen = len;
+ return CKR_OK;
+ }
+ if (attr->ulValueLen < len) {
+ attr->ulValueLen = (CK_ULONG) -1;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ PORT_Memcpy(attr->pValue,value,len);
+ attr->ulValueLen = len;
+ return CKR_OK;
+}
+
+static CK_RV
+lg_CopyAttributeSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type,
+ void *value, CK_ULONG len)
+{
+ unsigned char * dval = (unsigned char *)value;
+ if (*dval == 0) {
+ dval++;
+ len--;
+ }
+ return lg_CopyAttribute(attribute,type,dval,len);
+}
+
+static CK_RV
+lg_CopyPrivAttribute(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type,
+ void *value, CK_ULONG len, SDB *sdbpw)
+{
+ SECItem plainText, *cipherText = NULL;
+ CK_RV crv = CKR_USER_NOT_LOGGED_IN;
+ SECStatus rv;
+
+ plainText.data = value;
+ plainText.len = len;
+ rv = lg_util_encrypt(NULL, sdbpw, &plainText, &cipherText);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ crv = lg_CopyAttribute(attribute,type,cipherText->data,cipherText->len);
+loser:
+ if (cipherText) {
+ SECITEM_FreeItem(cipherText,PR_TRUE);
+ }
+ return crv;
+}
+
+static CK_RV
+lg_CopyPrivAttrSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type,
+ void *value, CK_ULONG len, SDB *sdbpw)
+{
+ unsigned char * dval = (unsigned char *)value;
+
+ if (*dval == 0) {
+ dval++;
+ len--;
+ }
+ return lg_CopyPrivAttribute(attribute,type,dval,len,sdbpw);
+}
+
+static CK_RV
+lg_invalidAttribute(CK_ATTRIBUTE *attr)
+{
+ attr->ulValueLen = (CK_ULONG) -1;
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+}
+
+
+#define LG_DEF_ATTRIBUTE(value,len) \
+ { 0, value, len }
+
+#define LG_CLONE_ATTR(attribute, type, staticAttr) \
+ lg_CopyAttribute(attribute, type, staticAttr.pValue, staticAttr.ulValueLen)
+
+CK_BBOOL lg_staticTrueValue = CK_TRUE;
+CK_BBOOL lg_staticFalseValue = CK_FALSE;
+static const CK_ATTRIBUTE lg_StaticTrueAttr =
+ LG_DEF_ATTRIBUTE(&lg_staticTrueValue,sizeof(lg_staticTrueValue));
+static const CK_ATTRIBUTE lg_StaticFalseAttr =
+ LG_DEF_ATTRIBUTE(&lg_staticFalseValue,sizeof(lg_staticFalseValue));
+static const CK_ATTRIBUTE lg_StaticNullAttr = LG_DEF_ATTRIBUTE(NULL,0);
+char lg_StaticOneValue = 1;
+static const CK_ATTRIBUTE lg_StaticOneAttr =
+ LG_DEF_ATTRIBUTE(&lg_StaticOneValue,sizeof(lg_StaticOneValue));
+
+/*
+ * helper functions which get the database and call the underlying
+ * low level database function.
+ */
+static char *
+lg_FindKeyNicknameByPublicKey(SDB *sdb, SECItem *dbKey)
+{
+ NSSLOWKEYDBHandle *keyHandle;
+ char * label;
+
+ keyHandle = lg_getKeyDB(sdb);
+ if (!keyHandle) {
+ return NULL;
+ }
+
+ label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey,
+ sdb);
+ return label;
+}
+
+
+NSSLOWKEYPrivateKey *
+lg_FindKeyByPublicKey(SDB *sdb, SECItem *dbKey)
+{
+ NSSLOWKEYPrivateKey *privKey;
+ NSSLOWKEYDBHandle *keyHandle;
+
+ keyHandle = lg_getKeyDB(sdb);
+ if (keyHandle == NULL) {
+ return NULL;
+ }
+ privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, sdb);
+ if (privKey == NULL) {
+ return NULL;
+ }
+ return privKey;
+}
+
+static certDBEntrySMime *
+lg_getSMime(LGObjectCache *obj)
+{
+ certDBEntrySMime *entry;
+ NSSLOWCERTCertDBHandle *certHandle;
+
+ if (obj->objclass != CKO_NETSCAPE_SMIME) {
+ return NULL;
+ }
+ if (obj->objectInfo) {
+ return (certDBEntrySMime *)obj->objectInfo;
+ }
+
+ certHandle = lg_getCertDB(obj->sdb);
+ if (!certHandle) {
+ return NULL;
+ }
+ entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)obj->dbKey.data);
+ obj->objectInfo = (void *)entry;
+ obj->infoFree = (LGFreeFunc) nsslowcert_DestroyDBEntry;
+ return entry;
+}
+
+static certDBEntryRevocation *
+lg_getCrl(LGObjectCache *obj)
+{
+ certDBEntryRevocation *crl;
+ PRBool isKrl;
+ NSSLOWCERTCertDBHandle *certHandle;
+
+ if (obj->objclass != CKO_NETSCAPE_CRL) {
+ return NULL;
+ }
+ if (obj->objectInfo) {
+ return (certDBEntryRevocation *)obj->objectInfo;
+ }
+
+ isKrl = (PRBool) (obj->handle == LG_TOKEN_KRL_HANDLE);
+ certHandle = lg_getCertDB(obj->sdb);
+ if (!certHandle) {
+ return NULL;
+ }
+
+ crl = nsslowcert_FindCrlByKey(certHandle, &obj->dbKey, isKrl);
+ obj->objectInfo = (void *)crl;
+ obj->infoFree = (LGFreeFunc) nsslowcert_DestroyDBEntry;
+ return crl;
+}
+
+static NSSLOWCERTCertificate *
+lg_getCert(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle)
+{
+ NSSLOWCERTCertificate *cert;
+ CK_OBJECT_CLASS objClass = obj->objclass;
+
+ if ((objClass != CKO_CERTIFICATE) && (objClass != CKO_NETSCAPE_TRUST)) {
+ return NULL;
+ }
+ if (objClass == CKO_CERTIFICATE && obj->objectInfo) {
+ return (NSSLOWCERTCertificate *)obj->objectInfo;
+ }
+ cert = nsslowcert_FindCertByKey(certHandle, &obj->dbKey);
+ if (objClass == CKO_CERTIFICATE) {
+ obj->objectInfo = (void *)cert;
+ obj->infoFree = (LGFreeFunc) nsslowcert_DestroyCertificate ;
+ }
+ return cert;
+}
+
+static NSSLOWCERTTrust *
+lg_getTrust(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle)
+{
+ NSSLOWCERTTrust *trust;
+
+ if (obj->objclass != CKO_NETSCAPE_TRUST) {
+ return NULL;
+ }
+ if (obj->objectInfo) {
+ return (NSSLOWCERTTrust *)obj->objectInfo;
+ }
+ trust = nsslowcert_FindTrustByKey(certHandle, &obj->dbKey);
+ obj->objectInfo = (void *)trust;
+ obj->infoFree = (LGFreeFunc) nsslowcert_DestroyTrust ;
+ return trust;
+}
+
+static NSSLOWKEYPublicKey *
+lg_GetPublicKey(LGObjectCache *obj)
+{
+ NSSLOWKEYPublicKey *pubKey;
+ NSSLOWKEYPrivateKey *privKey;
+
+ if (obj->objclass != CKO_PUBLIC_KEY) {
+ return NULL;
+ }
+ if (obj->objectInfo) {
+ return (NSSLOWKEYPublicKey *)obj->objectInfo;
+ }
+ privKey = lg_FindKeyByPublicKey(obj->sdb, &obj->dbKey);
+ if (privKey == NULL) {
+ return NULL;
+ }
+ pubKey = nsslowkey_ConvertToPublicKey(privKey);
+ nsslowkey_DestroyPrivateKey(privKey);
+ obj->objectInfo = (void *) pubKey;
+ obj->infoFree = (LGFreeFunc) nsslowkey_DestroyPublicKey ;
+ return pubKey;
+}
+
+/*
+ * we need two versions of lg_GetPrivateKey. One version that takes the
+ * DB handle so we can pass the handle we have already acquired in,
+ * rather than going through the 'getKeyDB' code again,
+ * which may fail the second time and another which just aquires
+ * the key handle from the sdb (where we don't already have a key handle.
+ * This version does the former.
+ */
+static NSSLOWKEYPrivateKey *
+lg_GetPrivateKeyWithDB(LGObjectCache *obj, NSSLOWKEYDBHandle *keyHandle)
+{
+ NSSLOWKEYPrivateKey *privKey;
+
+ if ((obj->objclass != CKO_PRIVATE_KEY) &&
+ (obj->objclass != CKO_SECRET_KEY)) {
+ return NULL;
+ }
+ if (obj->objectInfo) {
+ return (NSSLOWKEYPrivateKey *)obj->objectInfo;
+ }
+ privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &obj->dbKey, obj->sdb);
+ if (privKey == NULL) {
+ return NULL;
+ }
+ obj->objectInfo = (void *) privKey;
+ obj->infoFree = (LGFreeFunc) nsslowkey_DestroyPrivateKey ;
+ return privKey;
+}
+
+/* this version does the latter */
+static NSSLOWKEYPrivateKey *
+lg_GetPrivateKey(LGObjectCache *obj)
+{
+ NSSLOWKEYDBHandle *keyHandle;
+ NSSLOWKEYPrivateKey *privKey;
+
+ keyHandle = lg_getKeyDB(obj->sdb);
+ if (!keyHandle) {
+ return NULL;
+ }
+ privKey = lg_GetPrivateKeyWithDB(obj, keyHandle);
+ return privKey;
+}
+
+/* lg_GetPubItem returns data associated with the public key.
+ * one only needs to free the public key. This comment is here
+ * because this sematic would be non-obvious otherwise. All callers
+ * should include this comment.
+ */
+static SECItem *
+lg_GetPubItem(NSSLOWKEYPublicKey *pubKey) {
+ SECItem *pubItem = NULL;
+ /* get value to compare from the cert's public key */
+ switch ( pubKey->keyType ) {
+ case NSSLOWKEYRSAKey:
+ pubItem = &pubKey->u.rsa.modulus;
+ break;
+ case NSSLOWKEYDSAKey:
+ pubItem = &pubKey->u.dsa.publicValue;
+ break;
+ case NSSLOWKEYDHKey:
+ pubItem = &pubKey->u.dh.publicValue;
+ break;
+#ifdef NSS_ENABLE_ECC
+ case NSSLOWKEYECKey:
+ pubItem = &pubKey->u.ec.publicValue;
+ break;
+#endif /* NSS_ENABLE_ECC */
+ default:
+ break;
+ }
+ return pubItem;
+}
+
+static const SEC_ASN1Template lg_SerialTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) },
+ { 0 }
+};
+
+static CK_RV
+lg_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_RSA;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return lg_ULongAttribute(attribute, type, keyType);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
+ return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
+ case CKA_DERIVE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_ENCRYPT:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_MODULUS:
+ return lg_CopyAttributeSigned(attribute,type,key->u.rsa.modulus.data,
+ key->u.rsa.modulus.len);
+ case CKA_PUBLIC_EXPONENT:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.rsa.publicExponent.data,
+ key->u.rsa.publicExponent.len);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_DSA;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return lg_ULongAttribute(attribute, type, keyType);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len);
+ return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
+ case CKA_DERIVE:
+ case CKA_ENCRYPT:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_VERIFY:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_VALUE:
+ return lg_CopyAttributeSigned(attribute,type,
+ key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len);
+ case CKA_PRIME:
+ return lg_CopyAttributeSigned(attribute,type,
+ key->u.dsa.params.prime.data,
+ key->u.dsa.params.prime.len);
+ case CKA_SUBPRIME:
+ return lg_CopyAttributeSigned(attribute,type,
+ key->u.dsa.params.subPrime.data,
+ key->u.dsa.params.subPrime.len);
+ case CKA_BASE:
+ return lg_CopyAttributeSigned(attribute,type,
+ key->u.dsa.params.base.data,
+ key->u.dsa.params.base.len);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_DH;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return lg_ULongAttribute(attribute, type, keyType);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
+ return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
+ case CKA_DERIVE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_ENCRYPT:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_VALUE:
+ return lg_CopyAttributeSigned(attribute,type,
+ key->u.dh.publicValue.data,
+ key->u.dh.publicValue.len);
+ case CKA_PRIME:
+ return lg_CopyAttributeSigned(attribute,type,key->u.dh.prime.data,
+ key->u.dh.prime.len);
+ case CKA_BASE:
+ return lg_CopyAttributeSigned(attribute,type,key->u.dh.base.data,
+ key->u.dh.base.len);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+#ifdef NSS_ENABLE_ECC
+static CK_RV
+lg_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_EC;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return lg_ULongAttribute(attribute, type, keyType);
+ case CKA_ID:
+ SHA1_HashBuf(hash, key->u.ec.publicValue.data,
+ key->u.ec.publicValue.len);
+ return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
+ case CKA_DERIVE:
+ case CKA_VERIFY:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_ENCRYPT:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_EC_PARAMS:
+ return lg_CopyAttributeSigned(attribute,type,
+ key->u.ec.ecParams.DEREncoding.data,
+ key->u.ec.ecParams.DEREncoding.len);
+ case CKA_EC_POINT:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.ec.publicValue.data,
+ key->u.ec.publicValue.len);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+#endif /* NSS_ENABLE_ECC */
+
+
+static CK_RV
+lg_FindPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ NSSLOWKEYPublicKey *key;
+ CK_RV crv;
+ char *label;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_NEVER_EXTRACTABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_MODIFIABLE:
+ case CKA_EXTRACTABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_LABEL:
+ label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
+ if (label == NULL) {
+ return LG_CLONE_ATTR(attribute,type,lg_StaticOneAttr);
+ }
+ crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));
+ PORT_Free(label);
+ return crv;
+ default:
+ break;
+ }
+
+ key = lg_GetPublicKey(obj);
+ if (key == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ switch (key->keyType) {
+ case NSSLOWKEYRSAKey:
+ return lg_FindRSAPublicKeyAttribute(key,type,attribute);
+ case NSSLOWKEYDSAKey:
+ return lg_FindDSAPublicKeyAttribute(key,type,attribute);
+ case NSSLOWKEYDHKey:
+ return lg_FindDHPublicKeyAttribute(key,type,attribute);
+#ifdef NSS_ENABLE_ECC
+ case NSSLOWKEYECKey:
+ return lg_FindECPublicKeyAttribute(key,type,attribute);
+#endif /* NSS_ENABLE_ECC */
+ default:
+ break;
+ }
+
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindSecretKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ NSSLOWKEYPrivateKey *key;
+ char *label;
+ unsigned char *keyString;
+ CK_RV crv;
+ int keyTypeLen;
+ CK_ULONG keyLen;
+ CK_KEY_TYPE keyType;
+ PRUint32 keyTypeStorage;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_EXTRACTABLE:
+ case CKA_DERIVE:
+ case CKA_ENCRYPT:
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_VERIFY:
+ case CKA_WRAP:
+ case CKA_UNWRAP:
+ case CKA_MODIFIABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_NEVER_EXTRACTABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_LABEL:
+ label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
+ if (label == NULL) {
+ return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
+ }
+ crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));
+ PORT_Free(label);
+ return crv;
+ case CKA_ID:
+ return lg_CopyAttribute(attribute,type,obj->dbKey.data,
+ obj->dbKey.len);
+ case CKA_KEY_TYPE:
+ case CKA_VALUE_LEN:
+ case CKA_VALUE:
+ break;
+ default:
+ return lg_invalidAttribute(attribute);
+ }
+
+ key = lg_GetPrivateKey(obj);
+ if (key == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+ switch (type) {
+ case CKA_KEY_TYPE:
+ /* handle legacy databases. In legacy databases key_type was stored
+ * in host order, with any leading zeros stripped off. Only key types
+ * under 0x1f (AES) were stored. We assume that any values which are
+ * either 1 byte long (big endian), or have byte[0] between 0 and
+ * 0x7f and bytes[1]-bytes[3] equal to '0' (little endian). All other
+ * values are assumed to be from the new database, which is always 4
+ * bytes in network order */
+ keyType=0;
+ keyString = key->u.rsa.coefficient.data;
+ keyTypeLen = key->u.rsa.coefficient.len;
+
+
+ /*
+ * Because of various endian and word lengths The database may have
+ * stored the keyType value in one of the following formats:
+ * (kt) <= 0x1f
+ * length data
+ * Big Endian, pre-3.9, all lengths: 1 (kt)
+ * Little Endian, pre-3.9, 32 bits: 4 (kt) 0 0 0
+ * Little Endian, pre-3.9, 64 bits: 8 (kt) 0 0 0 0 0 0 0
+ * All platforms, 3.9, 32 bits: 4 0 0 0 (kt)
+ * Big Endian, 3.9, 64 bits: 8 0 0 0 (kt) 0 0 0 0
+ * Little Endian, 3.9, 64 bits: 8 0 0 0 0 0 0 0 (kt)
+ * All platforms, >= 3.9.1, all lengths: 4 (a) k1 k2 k3
+ * where (a) is 0 or >= 0x80. currently (a) can only be 0.
+ */
+ /*
+ * this key was written on a 64 bit platform with a using NSS 3.9
+ * or earlier. Reduce the 64 bit possibilities above. When we are
+ * through, we will only have:
+ *
+ * Big Endian, pre-3.9, all lengths: 1 (kt)
+ * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0
+ * All platforms, 3.9, all lengths: 4 0 0 0 (kt)
+ * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3
+ */
+ if (keyTypeLen == 8) {
+ keyTypeStorage = *(PRUint32 *) keyString;
+ if (keyTypeStorage == 0) {
+ keyString += sizeof(PRUint32);
+ }
+ keyTypeLen = 4;
+ }
+ /*
+ * Now Handle:
+ *
+ * All platforms, 3.9, all lengths: 4 0 0 0 (kt)
+ * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3
+ *
+ * NOTE: if kt == 0 or ak1k2k3 == 0, the test fails and
+ * we handle it as:
+ *
+ * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0
+ */
+ if (keyTypeLen == sizeof(keyTypeStorage) &&
+ (((keyString[0] & 0x80) == 0x80) ||
+ !((keyString[1] == 0) && (keyString[2] == 0)
+ && (keyString[3] == 0))) ) {
+ PORT_Memcpy(&keyTypeStorage, keyString, sizeof(keyTypeStorage));
+ keyType = (CK_KEY_TYPE) PR_ntohl(keyTypeStorage);
+ } else {
+ /*
+ * Now Handle:
+ *
+ * Big Endian, pre-3.9, all lengths: 1 (kt)
+ * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0
+ * -- KeyType == 0 all other cases ---: 4 0 0 0 0
+ */
+ keyType = (CK_KEY_TYPE) keyString[0] ;
+ }
+ return lg_ULongAttribute(attribute, type, keyType);
+ case CKA_VALUE:
+ return lg_CopyPrivAttribute(attribute,type,key->u.rsa.privateExponent.data,
+ key->u.rsa.privateExponent.len, obj->sdb);
+ case CKA_VALUE_LEN:
+ keyLen=key->u.rsa.privateExponent.len;
+ return lg_ULongAttribute(attribute,type, keyLen);
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute, SDB *sdbpw)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_RSA;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return lg_ULongAttribute(attribute, type, keyType);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
+ return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
+ case CKA_DERIVE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return LG_CLONE_ATTR(attribute, type,lg_StaticTrueAttr);
+ case CKA_MODULUS:
+ return lg_CopyAttributeSigned(attribute,type,key->u.rsa.modulus.data,
+ key->u.rsa.modulus.len);
+ case CKA_PUBLIC_EXPONENT:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.rsa.publicExponent.data,
+ key->u.rsa.publicExponent.len);
+ case CKA_PRIVATE_EXPONENT:
+ return lg_CopyPrivAttrSigned(attribute,type,
+ key->u.rsa.privateExponent.data,
+ key->u.rsa.privateExponent.len, sdbpw);
+ case CKA_PRIME_1:
+ return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime1.data,
+ key->u.rsa.prime1.len, sdbpw);
+ case CKA_PRIME_2:
+ return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime2.data,
+ key->u.rsa.prime2.len, sdbpw);
+ case CKA_EXPONENT_1:
+ return lg_CopyPrivAttrSigned(attribute, type,
+ key->u.rsa.exponent1.data,
+ key->u.rsa.exponent1.len, sdbpw);
+ case CKA_EXPONENT_2:
+ return lg_CopyPrivAttrSigned(attribute, type,
+ key->u.rsa.exponent2.data,
+ key->u.rsa.exponent2.len, sdbpw);
+ case CKA_COEFFICIENT:
+ return lg_CopyPrivAttrSigned(attribute, type,
+ key->u.rsa.coefficient.data,
+ key->u.rsa.coefficient.len, sdbpw);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute, SDB *sdbpw)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_DSA;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return lg_ULongAttribute(attribute, type, keyType);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len);
+ return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
+ case CKA_DERIVE:
+ case CKA_DECRYPT:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_SIGN:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_VALUE:
+ return lg_CopyPrivAttrSigned(attribute, type,
+ key->u.dsa.privateValue.data,
+ key->u.dsa.privateValue.len, sdbpw);
+ case CKA_PRIME:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.dsa.params.prime.data,
+ key->u.dsa.params.prime.len);
+ case CKA_SUBPRIME:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.dsa.params.subPrime.data,
+ key->u.dsa.params.subPrime.len);
+ case CKA_BASE:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.dsa.params.base.data,
+ key->u.dsa.params.base.len);
+ case CKA_NETSCAPE_DB:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute, SDB *sdbpw)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_DH;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return lg_ULongAttribute(attribute, type, keyType);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
+ return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
+ case CKA_DERIVE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_VALUE:
+ return lg_CopyPrivAttrSigned(attribute, type,
+ key->u.dh.privateValue.data,
+ key->u.dh.privateValue.len, sdbpw);
+ case CKA_PRIME:
+ return lg_CopyAttributeSigned(attribute, type, key->u.dh.prime.data,
+ key->u.dh.prime.len);
+ case CKA_BASE:
+ return lg_CopyAttributeSigned(attribute, type, key->u.dh.base.data,
+ key->u.dh.base.len);
+ case CKA_NETSCAPE_DB:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.dh.publicValue.data,
+ key->u.dh.publicValue.len);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+#ifdef NSS_ENABLE_ECC
+static CK_RV
+lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute, SDB *sdbpw)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_EC;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return lg_ULongAttribute(attribute, type, keyType);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.ec.publicValue.data,key->u.ec.publicValue.len);
+ return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
+ case CKA_DERIVE:
+ case CKA_SIGN:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_DECRYPT:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_VALUE:
+ return lg_CopyPrivAttrSigned(attribute, type,
+ key->u.ec.privateValue.data,
+ key->u.ec.privateValue.len, sdbpw);
+ case CKA_EC_PARAMS:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.ec.ecParams.DEREncoding.data,
+ key->u.ec.ecParams.DEREncoding.len);
+ case CKA_NETSCAPE_DB:
+ return lg_CopyAttributeSigned(attribute, type,
+ key->u.ec.publicValue.data,
+ key->u.ec.publicValue.len);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+#endif /* NSS_ENABLE_ECC */
+
+static CK_RV
+lg_FindPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ NSSLOWKEYPrivateKey *key;
+ char *label;
+ CK_RV crv;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_EXTRACTABLE:
+ case CKA_MODIFIABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_NEVER_EXTRACTABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_SUBJECT:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
+ case CKA_LABEL:
+ label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
+ if (label == NULL) {
+ return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
+ }
+ crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));
+ PORT_Free(label);
+ return crv;
+ default:
+ break;
+ }
+ key = lg_GetPrivateKey(obj);
+ if (key == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+ switch (key->keyType) {
+ case NSSLOWKEYRSAKey:
+ return lg_FindRSAPrivateKeyAttribute(key,type,attribute,obj->sdb);
+ case NSSLOWKEYDSAKey:
+ return lg_FindDSAPrivateKeyAttribute(key,type,attribute,obj->sdb);
+ case NSSLOWKEYDHKey:
+ return lg_FindDHPrivateKeyAttribute(key,type,attribute,obj->sdb);
+#ifdef NSS_ENABLE_ECC
+ case NSSLOWKEYECKey:
+ return lg_FindECPrivateKeyAttribute(key,type,attribute,obj->sdb);
+#endif /* NSS_ENABLE_ECC */
+ default:
+ break;
+ }
+
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindSMIMEAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ certDBEntrySMime *entry;
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_MODIFIABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_NETSCAPE_EMAIL:
+ return lg_CopyAttribute(attribute,type,obj->dbKey.data,
+ obj->dbKey.len-1);
+ case CKA_NETSCAPE_SMIME_TIMESTAMP:
+ case CKA_SUBJECT:
+ case CKA_VALUE:
+ break;
+ default:
+ return lg_invalidAttribute(attribute);
+ }
+ entry = lg_getSMime(obj);
+ if (entry == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+ switch (type) {
+ case CKA_NETSCAPE_SMIME_TIMESTAMP:
+ return lg_CopyAttribute(attribute,type,entry->optionsDate.data,
+ entry->optionsDate.len);
+ case CKA_SUBJECT:
+ return lg_CopyAttribute(attribute,type,entry->subjectName.data,
+ entry->subjectName.len);
+ case CKA_VALUE:
+ return lg_CopyAttribute(attribute,type,entry->smimeOptions.data,
+ entry->smimeOptions.len);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindTrustAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ NSSLOWCERTTrust *trust;
+ NSSLOWCERTCertDBHandle *certHandle;
+ NSSLOWCERTCertificate *cert;
+ unsigned char hash[SHA1_LENGTH];
+ unsigned int trustFlags;
+ CK_RV crv;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_MODIFIABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_CERT_SHA1_HASH:
+ case CKA_CERT_MD5_HASH:
+ case CKA_TRUST_CLIENT_AUTH:
+ case CKA_TRUST_SERVER_AUTH:
+ case CKA_TRUST_EMAIL_PROTECTION:
+ case CKA_TRUST_CODE_SIGNING:
+ case CKA_TRUST_STEP_UP_APPROVED:
+ case CKA_ISSUER:
+ case CKA_SERIAL_NUMBER:
+ break;
+ default:
+ return lg_invalidAttribute(attribute);
+ }
+ certHandle = lg_getCertDB(obj->sdb);
+ if (!certHandle) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+ trust = lg_getTrust(obj, certHandle);
+ if (trust == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+ switch (type) {
+ case CKA_CERT_SHA1_HASH:
+ SHA1_HashBuf(hash,trust->derCert->data,trust->derCert->len);
+ return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
+ case CKA_CERT_MD5_HASH:
+ MD5_HashBuf(hash,trust->derCert->data,trust->derCert->len);
+ return lg_CopyAttribute(attribute, type, hash, MD5_LENGTH);
+ case CKA_TRUST_CLIENT_AUTH:
+ trustFlags = trust->trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ?
+ trust->trust->sslFlags | CERTDB_TRUSTED_CA : 0 ;
+ goto trust;
+ case CKA_TRUST_SERVER_AUTH:
+ trustFlags = trust->trust->sslFlags;
+ goto trust;
+ case CKA_TRUST_EMAIL_PROTECTION:
+ trustFlags = trust->trust->emailFlags;
+ goto trust;
+ case CKA_TRUST_CODE_SIGNING:
+ trustFlags = trust->trust->objectSigningFlags;
+trust:
+ if (trustFlags & CERTDB_TRUSTED_CA ) {
+ return lg_ULongAttribute(attribute, type,
+ CKT_NETSCAPE_TRUSTED_DELEGATOR);
+ }
+ if (trustFlags & CERTDB_TRUSTED) {
+ return lg_ULongAttribute(attribute, type, CKT_NETSCAPE_TRUSTED);
+ }
+ if (trustFlags & CERTDB_NOT_TRUSTED) {
+ return lg_ULongAttribute(attribute, type, CKT_NETSCAPE_UNTRUSTED);
+ }
+ if (trustFlags & CERTDB_TRUSTED_UNKNOWN) {
+ return lg_ULongAttribute(attribute, type,
+ CKT_NETSCAPE_TRUST_UNKNOWN);
+ }
+ if (trustFlags & CERTDB_VALID_CA) {
+ return lg_ULongAttribute(attribute, type,
+ CKT_NETSCAPE_VALID_DELEGATOR);
+ }
+ if (trustFlags & CERTDB_VALID_PEER) {
+ return lg_ULongAttribute(attribute, type, CKT_NETSCAPE_VALID);
+ }
+ return lg_ULongAttribute(attribute, type, CKT_NETSCAPE_MUST_VERIFY);
+ case CKA_TRUST_STEP_UP_APPROVED:
+ if (trust->trust->sslFlags & CERTDB_GOVT_APPROVED_CA) {
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ } else {
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ }
+ default:
+ break;
+ }
+
+
+ switch (type) {
+ case CKA_ISSUER:
+ cert = lg_getCert(obj, certHandle);
+ if (cert == NULL) break;
+ crv = lg_CopyAttribute(attribute,type,cert->derIssuer.data,
+ cert->derIssuer.len);
+ break;
+ case CKA_SERIAL_NUMBER:
+ cert = lg_getCert(obj, certHandle);
+ if (cert == NULL) break;
+ crv = lg_CopyAttribute(attribute,type,cert->derSN.data,
+ cert->derSN.len);
+ break;
+ default:
+ cert = NULL;
+ break;
+ }
+ if (cert) {
+ nsslowcert_DestroyCertificate(cert);
+ return crv;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindCrlAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ certDBEntryRevocation *crl;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_MODIFIABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_NETSCAPE_KRL:
+ return ((obj->handle == LG_TOKEN_KRL_HANDLE)
+ ? LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr)
+ : LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr));
+ case CKA_SUBJECT:
+ return lg_CopyAttribute(attribute,type,obj->dbKey.data,
+ obj->dbKey.len);
+ case CKA_NETSCAPE_URL:
+ case CKA_VALUE:
+ break;
+ default:
+ return lg_invalidAttribute(attribute);
+ }
+ crl = lg_getCrl(obj);
+ if (!crl) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+ switch (type) {
+ case CKA_NETSCAPE_URL:
+ if (crl->url == NULL) {
+ return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
+ }
+ return lg_CopyAttribute(attribute, type, crl->url,
+ PORT_Strlen(crl->url)+1);
+ case CKA_VALUE:
+ return lg_CopyAttribute(attribute, type, crl->derCrl.data,
+ crl->derCrl.len);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+static CK_RV
+lg_FindCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
+ CK_ATTRIBUTE *attribute)
+{
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertDBHandle *certHandle;
+ NSSLOWKEYPublicKey *pubKey;
+ unsigned char hash[SHA1_LENGTH];
+ SECItem *item;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
+ case CKA_MODIFIABLE:
+ return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
+ case CKA_CERTIFICATE_TYPE:
+ /* hardcoding X.509 into here */
+ return lg_ULongAttribute(attribute, type, CKC_X_509);
+ case CKA_VALUE:
+ case CKA_ID:
+ case CKA_LABEL:
+ case CKA_SUBJECT:
+ case CKA_ISSUER:
+ case CKA_SERIAL_NUMBER:
+ case CKA_NETSCAPE_EMAIL:
+ break;
+ default:
+ return lg_invalidAttribute(attribute);
+ }
+
+ certHandle = lg_getCertDB(obj->sdb);
+ if (certHandle == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ cert = lg_getCert(obj, certHandle);
+ if (cert == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+ switch (type) {
+ case CKA_VALUE:
+ return lg_CopyAttribute(attribute,type,cert->derCert.data,
+ cert->derCert.len);
+ case CKA_ID:
+ if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
+ ((cert->trust->emailFlags & CERTDB_USER) == 0) &&
+ ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
+ return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
+ }
+ pubKey = nsslowcert_ExtractPublicKey(cert);
+ if (pubKey == NULL) break;
+ item = lg_GetPubItem(pubKey);
+ if (item == NULL) {
+ nsslowkey_DestroyPublicKey(pubKey);
+ break;
+ }
+ SHA1_HashBuf(hash,item->data,item->len);
+ /* item is imbedded in pubKey, just free the key */
+ nsslowkey_DestroyPublicKey(pubKey);
+ return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
+ case CKA_LABEL:
+ return cert->nickname
+ ? lg_CopyAttribute(attribute, type, cert->nickname,
+ PORT_Strlen(cert->nickname))
+ : LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
+ case CKA_SUBJECT:
+ return lg_CopyAttribute(attribute,type,cert->derSubject.data,
+ cert->derSubject.len);
+ case CKA_ISSUER:
+ return lg_CopyAttribute(attribute,type,cert->derIssuer.data,
+ cert->derIssuer.len);
+ case CKA_SERIAL_NUMBER:
+ return lg_CopyAttribute(attribute,type,cert->derSN.data,
+ cert->derSN.len);
+ case CKA_NETSCAPE_EMAIL:
+ return (cert->emailAddr && cert->emailAddr[0])
+ ? lg_CopyAttribute(attribute, type, cert->emailAddr,
+ PORT_Strlen(cert->emailAddr))
+ : LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+CK_RV
+lg_GetSingleAttribute(LGObjectCache *obj, CK_ATTRIBUTE *attribute)
+{
+ /* handle the common ones */
+ CK_ATTRIBUTE_TYPE type = attribute->type;
+ switch (type) {
+ case CKA_CLASS:
+ return lg_ULongAttribute(attribute,type,obj->objclass);
+ case CKA_TOKEN:
+ return LG_CLONE_ATTR(attribute, type,lg_StaticTrueAttr);
+ case CKA_LABEL:
+ if ( (obj->objclass == CKO_CERTIFICATE)
+ || (obj->objclass == CKO_PRIVATE_KEY)
+ || (obj->objclass == CKO_PUBLIC_KEY)
+ || (obj->objclass == CKO_SECRET_KEY)) {
+ break;
+ }
+ return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
+ default:
+ break;
+ }
+ switch (obj->objclass) {
+ case CKO_CERTIFICATE:
+ return lg_FindCertAttribute(obj,type,attribute);
+ case CKO_NETSCAPE_CRL:
+ return lg_FindCrlAttribute(obj,type,attribute);
+ case CKO_NETSCAPE_TRUST:
+ return lg_FindTrustAttribute(obj,type,attribute);
+ case CKO_NETSCAPE_SMIME:
+ return lg_FindSMIMEAttribute(obj,type,attribute);
+ case CKO_PUBLIC_KEY:
+ return lg_FindPublicKeyAttribute(obj,type,attribute);
+ case CKO_PRIVATE_KEY:
+ return lg_FindPrivateKeyAttribute(obj,type,attribute);
+ case CKO_SECRET_KEY:
+ return lg_FindSecretKeyAttribute(obj,type,attribute);
+ default:
+ break;
+ }
+ return lg_invalidAttribute(attribute);
+}
+
+/*
+ * Fill in the attribute template based on the data in the database.
+ */
+CK_RV
+lg_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *templ,
+ CK_ULONG count)
+{
+ LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK);
+ CK_RV crv, crvCollect = CKR_OK;
+ int i;
+
+ if (obj == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ for (i=0; i < count; i++) {
+ crv = lg_GetSingleAttribute(obj, &templ[i]);
+ if (crvCollect == CKR_OK) crvCollect = crv;
+ }
+
+ lg_DestroyObjectCache(obj);
+ return crvCollect;
+}
+
+PRBool
+lg_cmpAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attribute)
+{
+ unsigned char buf[LG_BUF_SPACE];
+ CK_ATTRIBUTE testAttr;
+ unsigned char *tempBuf = NULL;
+ PRBool match = PR_TRUE;
+ CK_RV crv;
+
+ /* we're going to compare 'attribute' with the actual attribute from
+ * the object. We'll use the length of 'attribute' to decide how much
+ * space we need to read the test attribute. If 'attribute' doesn't give
+ * enough space, then we know the values don't match and that will
+ * show up as ckr != CKR_OK */
+ testAttr = *attribute;
+ testAttr.pValue = buf;
+
+ /* if we don't have enough space, malloc it */
+ if (attribute->ulValueLen > LG_BUF_SPACE) {
+ tempBuf = PORT_Alloc(attribute->ulValueLen);
+ if (!tempBuf) {
+ return PR_FALSE;
+ }
+ testAttr.pValue = tempBuf;
+ }
+
+ /* get the attribute */
+ crv = lg_GetSingleAttribute(obj, &testAttr);
+ /* if the attribute was read OK, compare it */
+ if ((crv != CKR_OK) || (attribute->ulValueLen != testAttr.ulValueLen) ||
+ (PORT_Memcmp(attribute->pValue,testAttr.pValue,testAttr.ulValueLen)!= 0)){
+ /* something didn't match, this isn't the object we are looking for */
+ match = PR_FALSE;
+ }
+ /* free the buffer we may have allocated */
+ if (tempBuf) {
+ PORT_Free(tempBuf);
+ }
+ return match;
+}
+
+PRBool
+lg_tokenMatch(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE class,
+ const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ PRBool match = PR_TRUE;
+ LGObjectCache *obj = lg_NewObjectCache(sdb, dbKey, class);
+ int i;
+
+ if (obj == NULL) {
+ return PR_FALSE;
+ }
+
+ for (i=0; i < count; i++) {
+ match = lg_cmpAttribute(obj, &templ[i]);
+ if (!match) {
+ break;
+ }
+ }
+
+ /* done looking, free up our cache */
+ lg_DestroyObjectCache(obj);
+
+ /* if we get through the whole list without finding a mismatched attribute,
+ * then this object fits the criteria we are matching */
+ return match;
+}
+
+static CK_RV
+lg_SetCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
+ const void *value, unsigned int len)
+{
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertDBHandle *certHandle;
+ char *nickname = NULL;
+ SECStatus rv;
+ CK_RV crv;
+
+ /* we can't change the EMAIL values, but let the
+ * upper layers feel better about the fact we tried to set these */
+ if (type == CKA_NETSCAPE_EMAIL) {
+ return CKR_OK;
+ }
+
+ certHandle = lg_getCertDB(obj->sdb);
+ if (certHandle == NULL) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ goto done;
+ }
+
+ if ((type != CKA_LABEL) && (type != CKA_ID)) {
+ crv = CKR_ATTRIBUTE_READ_ONLY;
+ goto done;
+ }
+
+ cert = lg_getCert(obj, certHandle);
+ if (cert == NULL) {
+ crv = CKR_OBJECT_HANDLE_INVALID;
+ goto done;
+ }
+
+ /* if the app is trying to set CKA_ID, it's probably because it just
+ * imported the key. Look to see if we need to set the CERTDB_USER bits.
+ */
+ if (type == CKA_ID) {
+ if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
+ ((cert->trust->emailFlags & CERTDB_USER) == 0) &&
+ ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
+ NSSLOWKEYDBHandle *keyHandle;
+
+ keyHandle = lg_getKeyDB(obj->sdb);
+ if (keyHandle) {
+ if (nsslowkey_KeyForCertExists(keyHandle, cert)) {
+ NSSLOWCERTCertTrust trust = *cert->trust;
+ trust.sslFlags |= CERTDB_USER;
+ trust.emailFlags |= CERTDB_USER;
+ trust.objectSigningFlags |= CERTDB_USER;
+ nsslowcert_ChangeCertTrust(certHandle,cert,&trust);
+ }
+ }
+ }
+ crv = CKR_OK;
+ goto done;
+ }
+
+ /* must be CKA_LABEL */
+ if (value != NULL) {
+ nickname = PORT_ZAlloc(len+1);
+ if (nickname == NULL) {
+ crv = CKR_HOST_MEMORY;
+ goto done;
+ }
+ PORT_Memcpy(nickname,value,len);
+ nickname[len] = 0;
+ }
+ rv = nsslowcert_AddPermNickname(certHandle, cert, nickname);
+ crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
+
+done:
+ if (nickname) {
+ PORT_Free(nickname);
+ }
+ return crv;
+}
+
+static CK_RV
+lg_SetPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
+ const void *value, unsigned int len,
+ PRBool *writePrivate)
+{
+ NSSLOWKEYPrivateKey *privKey;
+ NSSLOWKEYDBHandle *keyHandle;
+ char *nickname = NULL;
+ SECStatus rv;
+ CK_RV crv;
+
+ /* we can't change the ID and we don't store the subject, but let the
+ * upper layers feel better about the fact we tried to set these */
+ if ((type == CKA_ID) || (type == CKA_SUBJECT)) {
+ return CKR_OK;
+ }
+
+ keyHandle = lg_getKeyDB(obj->sdb);
+ if (keyHandle == NULL) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ goto done;
+ }
+
+ privKey = lg_GetPrivateKeyWithDB(obj, keyHandle);
+ if (privKey == NULL) {
+ crv = CKR_OBJECT_HANDLE_INVALID;
+ goto done;
+ }
+
+ crv = CKR_ATTRIBUTE_READ_ONLY;
+ switch(type) {
+ case CKA_LABEL:
+ if (value != NULL) {
+ nickname = PORT_ZAlloc(len+1);
+ if (nickname == NULL) {
+ crv = CKR_HOST_MEMORY;
+ goto done;
+ }
+ PORT_Memcpy(nickname,value,len);
+ nickname[len] = 0;
+ }
+ rv = nsslowkey_UpdateNickname(keyHandle, privKey, &obj->dbKey,
+ nickname, obj->sdb);
+ crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
+ break;
+ case CKA_VALUE:
+ case CKA_PRIVATE_EXPONENT:
+ case CKA_PRIME_1:
+ case CKA_PRIME_2:
+ case CKA_EXPONENT_1:
+ case CKA_EXPONENT_2:
+ case CKA_COEFFICIENT:
+ /* We aren't really changing these values, we are just triggering
+ * the database to update it's entry */
+ *writePrivate = 1;
+ crv = CKR_OK;
+ break;
+ default:
+ crv = CKR_ATTRIBUTE_READ_ONLY;
+ break;
+ }
+done:
+ if (nickname) {
+ PORT_Free(nickname);
+ }
+ return crv;
+}
+
+static CK_RV
+lg_SetTrustAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr)
+{
+ unsigned int flags;
+ CK_TRUST trust;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertDBHandle *certHandle;
+ NSSLOWCERTCertTrust dbTrust;
+ SECStatus rv;
+ CK_RV crv;
+
+ crv = lg_GetULongAttribute(attr->type, attr, 1, &trust);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+ flags = lg_MapTrust(trust, (PRBool) (attr->type == CKA_TRUST_SERVER_AUTH));
+
+ certHandle = lg_getCertDB(obj->sdb);
+
+ if (certHandle == NULL) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ goto done;
+ }
+
+ cert = lg_getCert(obj, certHandle);
+ if (cert == NULL) {
+ crv = CKR_OBJECT_HANDLE_INVALID;
+ goto done;
+ }
+ dbTrust = *cert->trust;
+
+ switch (attr->type) {
+ case CKA_TRUST_EMAIL_PROTECTION:
+ dbTrust.emailFlags = flags |
+ (cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS);
+ break;
+ case CKA_TRUST_CODE_SIGNING:
+ dbTrust.objectSigningFlags = flags |
+ (cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS);
+ break;
+ case CKA_TRUST_CLIENT_AUTH:
+ dbTrust.sslFlags = flags | (cert->trust->sslFlags &
+ (CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CA));
+ break;
+ case CKA_TRUST_SERVER_AUTH:
+ dbTrust.sslFlags = flags | (cert->trust->sslFlags &
+ (CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA));
+ break;
+ default:
+ crv = CKR_ATTRIBUTE_READ_ONLY;
+ goto done;
+ }
+
+ rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust);
+ crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
+done:
+ return crv;
+}
+
+static CK_RV
+lg_SetSingleAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr,
+ PRBool *writePrivate)
+{
+ CK_ATTRIBUTE attribLocal;
+ CK_RV crv;
+
+ /* Make sure the attribute exists first */
+ attribLocal.type = attr->type;
+ attribLocal.pValue = NULL;
+ attribLocal.ulValueLen = 0;
+ crv = lg_GetSingleAttribute(obj, &attribLocal);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+
+ /* if we are just setting it to the value we already have,
+ * allow it to happen. Let label setting go through so
+ * we have the opportunity to repair any database corruption. */
+ if (attr->type != CKA_LABEL) {
+ if (lg_cmpAttribute(obj,attr)) {
+ return CKR_OK;
+ }
+ }
+
+ crv = CKR_ATTRIBUTE_READ_ONLY;
+ switch (obj->objclass) {
+ case CKO_CERTIFICATE:
+ /* change NICKNAME, EMAIL, */
+ crv = lg_SetCertAttribute(obj,attr->type,
+ attr->pValue,attr->ulValueLen);
+ break;
+ case CKO_NETSCAPE_CRL:
+ /* change URL */
+ break;
+ case CKO_NETSCAPE_TRUST:
+ crv = lg_SetTrustAttribute(obj,attr);
+ break;
+ case CKO_PRIVATE_KEY:
+ case CKO_SECRET_KEY:
+ crv = lg_SetPrivateKeyAttribute(obj,attr->type,
+ attr->pValue,attr->ulValueLen, writePrivate);
+ break;
+ }
+ return crv;
+}
+
+/*
+ * Fill in the attribute template based on the data in the database.
+ */
+CK_RV
+lg_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle,
+ const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK);
+ CK_RV crv, crvCollect = CKR_OK;
+ PRBool writePrivate = PR_FALSE;
+ int i;
+
+ if (obj == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ for (i=0; i < count; i++) {
+ crv = lg_SetSingleAttribute(obj, &templ[i], &writePrivate);
+ if (crvCollect == CKR_OK) crvCollect = crv;
+ }
+
+ /* Write any collected changes out for private and secret keys.
+ * don't do the write for just the label */
+ if (writePrivate) {
+ NSSLOWKEYPrivateKey *privKey = lg_GetPrivateKey(obj);
+ SECStatus rv = SECFailure;
+ char * label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
+
+ if (privKey) {
+ rv = nsslowkey_StoreKeyByPublicKey(lg_getKeyDB(sdb), privKey,
+ &obj->dbKey, label, sdb );
+ }
+ if (rv != SECSuccess) {
+ crv = CKR_DEVICE_ERROR;
+ }
+ }
+
+ lg_DestroyObjectCache(obj);
+ return crvCollect;
+}
diff --git a/security/nss/lib/softoken/legacydb/lgcreate.c b/security/nss/lib/softoken/legacydb/lgcreate.c
new file mode 100644
index 000000000..c3ab0781d
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lgcreate.c
@@ -0,0 +1,955 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "secitem.h"
+#include "pkcs11.h"
+#include "lgdb.h"
+#include "pcert.h"
+#include "lowkeyi.h"
+#include "blapi.h"
+#include "secder.h"
+
+#include "keydbi.h"
+
+/*
+ * ******************** Object Creation Utilities ***************************
+ */
+
+/*
+ * check the consistancy and initialize a Certificate Object
+ */
+static CK_RV
+lg_createCertObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
+ const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ SECItem derCert;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertTrust *trust = NULL;
+ NSSLOWCERTCertTrust userTrust =
+ { CERTDB_USER, CERTDB_USER, CERTDB_USER };
+ NSSLOWCERTCertTrust defTrust =
+ { CERTDB_TRUSTED_UNKNOWN,
+ CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN };
+ char *label = NULL;
+ char *email = NULL;
+ SECStatus rv;
+ PRBool inDB = PR_TRUE;
+ NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
+ NSSLOWKEYDBHandle *keyHandle = NULL;
+ CK_CERTIFICATE_TYPE type;
+ const CK_ATTRIBUTE *attribute;
+
+ /* we can't store any certs private */
+ if (lg_isTrue(CKA_PRIVATE, templ, count)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ /* We only support X.509 Certs for now */
+ attribute = lg_FindAttribute(CKA_CERTIFICATE_TYPE, templ, count);
+ if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
+ type = *(CK_CERTIFICATE_TYPE *)attribute->pValue;
+
+ if (type != CKC_X_509) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ /* X.509 Certificate */
+
+
+ if (certHandle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ /* get the der cert */
+ attribute = lg_FindAttribute(CKA_VALUE, templ, count);
+ if (!attribute) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ derCert.type = 0;
+ derCert.data = (unsigned char *)attribute->pValue;
+ derCert.len = attribute->ulValueLen ;
+
+ label = lg_getString(CKA_LABEL, templ, count);
+
+ cert = nsslowcert_FindCertByDERCert(certHandle, &derCert);
+ if (cert == NULL) {
+ cert = nsslowcert_DecodeDERCertificate(&derCert, label);
+ inDB = PR_FALSE;
+ }
+ if (cert == NULL) {
+ if (label) PORT_Free(label);
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ keyHandle = lg_getKeyDB(sdb);
+ if (keyHandle) {
+ if (nsslowkey_KeyForCertExists(keyHandle,cert)) {
+ trust = &userTrust;
+ }
+ }
+
+ if (!inDB) {
+ if (!trust) trust = &defTrust;
+ rv = nsslowcert_AddPermCert(certHandle, cert, label, trust);
+ } else {
+ rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) :
+ SECSuccess;
+ }
+
+ if (label) PORT_Free(label);
+
+ if (rv != SECSuccess) {
+ nsslowcert_DestroyCertificate(cert);
+ return CKR_DEVICE_ERROR;
+ }
+
+ /*
+ * Add a NULL S/MIME profile if necessary.
+ */
+ email = lg_getString(CKA_NETSCAPE_EMAIL, templ, count);
+ if (email) {
+ certDBEntrySMime *entry;
+
+ entry = nsslowcert_ReadDBSMimeEntry(certHandle,email);
+ if (!entry) {
+ nsslowcert_SaveSMimeProfile(certHandle, email,
+ &cert->derSubject, NULL, NULL);
+ } else {
+ nsslowcert_DestroyDBEntry((certDBEntry *)entry);
+ }
+ PORT_Free(email);
+ }
+ *handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT);
+ nsslowcert_DestroyCertificate(cert);
+
+ return CKR_OK;
+}
+
+unsigned int
+lg_MapTrust(CK_TRUST trust, PRBool clientAuth)
+{
+ unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA :
+ CERTDB_TRUSTED_CA;
+ switch (trust) {
+ case CKT_NETSCAPE_TRUSTED:
+ return CERTDB_VALID_PEER|CERTDB_TRUSTED;
+ case CKT_NETSCAPE_TRUSTED_DELEGATOR:
+ return CERTDB_VALID_CA|trustCA;
+ case CKT_NETSCAPE_UNTRUSTED:
+ return CERTDB_NOT_TRUSTED;
+ case CKT_NETSCAPE_MUST_VERIFY:
+ return 0;
+ case CKT_NETSCAPE_VALID: /* implies must verify */
+ return CERTDB_VALID_PEER;
+ case CKT_NETSCAPE_VALID_DELEGATOR: /* implies must verify */
+ return CERTDB_VALID_CA;
+ default:
+ break;
+ }
+ return CERTDB_TRUSTED_UNKNOWN;
+}
+
+
+/*
+ * check the consistancy and initialize a Trust Object
+ */
+static CK_RV
+lg_createTrustObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
+ const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ const CK_ATTRIBUTE *issuer = NULL;
+ const CK_ATTRIBUTE *serial = NULL;
+ NSSLOWCERTCertificate *cert = NULL;
+ const CK_ATTRIBUTE *trust;
+ CK_TRUST sslTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
+ CK_TRUST clientTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
+ CK_TRUST emailTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
+ CK_TRUST signTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
+ CK_BBOOL stepUp;
+ NSSLOWCERTCertTrust dbTrust = { 0 };
+ SECStatus rv;
+ NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
+ NSSLOWCERTIssuerAndSN issuerSN;
+
+ /* we can't store any certs private */
+ if (lg_isTrue(CKA_PRIVATE, templ, count)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ if (certHandle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ issuer = lg_FindAttribute(CKA_ISSUER, templ, count);
+ serial = lg_FindAttribute(CKA_SERIAL_NUMBER, templ, count);
+
+ if (issuer && serial) {
+ issuerSN.derIssuer.data = (unsigned char *)issuer->pValue;
+ issuerSN.derIssuer.len = issuer->ulValueLen ;
+
+ issuerSN.serialNumber.data = (unsigned char *)serial->pValue;
+ issuerSN.serialNumber.len = serial->ulValueLen ;
+
+ cert = nsslowcert_FindCertByIssuerAndSN(certHandle,&issuerSN);
+ }
+
+ if (cert == NULL) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ lg_GetULongAttribute(CKA_TRUST_SERVER_AUTH, templ, count, &sslTrust);
+ lg_GetULongAttribute(CKA_TRUST_CLIENT_AUTH, templ, count, &clientTrust);
+ lg_GetULongAttribute(CKA_TRUST_EMAIL_PROTECTION, templ, count, &emailTrust);
+ lg_GetULongAttribute(CKA_TRUST_CODE_SIGNING, templ, count, &signTrust);
+ stepUp = CK_FALSE;
+ trust = lg_FindAttribute(CKA_TRUST_STEP_UP_APPROVED, templ, count);
+ if (trust) {
+ if (trust->ulValueLen == sizeof(CK_BBOOL)) {
+ stepUp = *(CK_BBOOL*)trust->pValue;
+ }
+ }
+
+ /* preserve certain old fields */
+ if (cert->trust) {
+ dbTrust.sslFlags = cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS;
+ dbTrust.emailFlags=
+ cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS;
+ dbTrust.objectSigningFlags =
+ cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS;
+ }
+
+ dbTrust.sslFlags |= lg_MapTrust(sslTrust,PR_FALSE);
+ dbTrust.sslFlags |= lg_MapTrust(clientTrust,PR_TRUE);
+ dbTrust.emailFlags |= lg_MapTrust(emailTrust,PR_FALSE);
+ dbTrust.objectSigningFlags |= lg_MapTrust(signTrust,PR_FALSE);
+ if (stepUp) {
+ dbTrust.sslFlags |= CERTDB_GOVT_APPROVED_CA;
+ }
+
+ rv = nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust);
+ *handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST);
+ nsslowcert_DestroyCertificate(cert);
+ if (rv != SECSuccess) {
+ return CKR_DEVICE_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+/*
+ * check the consistancy and initialize a Trust Object
+ */
+static CK_RV
+lg_createSMimeObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
+ const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ SECItem derSubj,rawProfile,rawTime,emailKey;
+ SECItem *pRawProfile = NULL;
+ SECItem *pRawTime = NULL;
+ char *email = NULL;
+ const CK_ATTRIBUTE *subject = NULL,
+ *profile = NULL,
+ *time = NULL;
+ SECStatus rv;
+ NSSLOWCERTCertDBHandle *certHandle;
+ CK_RV ck_rv = CKR_OK;
+
+ /* we can't store any certs private */
+ if (lg_isTrue(CKA_PRIVATE,templ,count)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ certHandle = lg_getCertDB(sdb);
+ if (certHandle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ /* lookup SUBJECT */
+ subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
+ PORT_Assert(subject);
+ if (!subject) {
+ ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ goto loser;
+ }
+
+ derSubj.data = (unsigned char *)subject->pValue;
+ derSubj.len = subject->ulValueLen ;
+ derSubj.type = 0;
+
+ /* lookup VALUE */
+ profile = lg_FindAttribute(CKA_VALUE,templ,count);
+ if (profile) {
+ rawProfile.data = (unsigned char *)profile->pValue;
+ rawProfile.len = profile->ulValueLen ;
+ rawProfile.type = siBuffer;
+ pRawProfile = &rawProfile;
+ }
+
+ /* lookup Time */
+ time = lg_FindAttribute(CKA_NETSCAPE_SMIME_TIMESTAMP,templ,count);
+ if (time) {
+ rawTime.data = (unsigned char *)time->pValue;
+ rawTime.len = time->ulValueLen ;
+ rawTime.type = siBuffer;
+ pRawTime = &rawTime;
+ }
+
+
+ email = lg_getString(CKA_NETSCAPE_EMAIL,templ,count);
+ if (!email) {
+ ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ goto loser;
+ }
+
+ /* Store S/MIME Profile by SUBJECT */
+ rv = nsslowcert_SaveSMimeProfile(certHandle, email, &derSubj,
+ pRawProfile,pRawTime);
+ if (rv != SECSuccess) {
+ ck_rv = CKR_DEVICE_ERROR;
+ goto loser;
+ }
+ emailKey.data = (unsigned char *)email;
+ emailKey.len = PORT_Strlen(email)+1;
+
+ *handle = lg_mkHandle(sdb, &emailKey, LG_TOKEN_TYPE_SMIME);
+
+loser:
+ if (email) PORT_Free(email);
+
+ return ck_rv;
+}
+
+/*
+ * check the consistancy and initialize a Trust Object
+ */
+static CK_RV
+lg_createCrlObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
+ const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ PRBool isKRL = PR_FALSE;
+ SECItem derSubj,derCrl;
+ char *url = NULL;
+ const CK_ATTRIBUTE *subject,*crl;
+ SECStatus rv;
+ NSSLOWCERTCertDBHandle *certHandle;
+
+ certHandle = lg_getCertDB(sdb);
+
+ /* we can't store any private crls */
+ if (lg_isTrue(CKA_PRIVATE,templ,count)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ if (certHandle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ /* lookup SUBJECT */
+ subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
+ if (!subject) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ derSubj.data = (unsigned char *)subject->pValue;
+ derSubj.len = subject->ulValueLen ;
+
+ /* lookup VALUE */
+ crl = lg_FindAttribute(CKA_VALUE,templ,count);
+ PORT_Assert(crl);
+ if (!crl) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ derCrl.data = (unsigned char *)crl->pValue;
+ derCrl.len = crl->ulValueLen ;
+
+ url = lg_getString(CKA_NETSCAPE_URL,templ,count);
+ isKRL = lg_isTrue(CKA_NETSCAPE_KRL,templ,count);
+
+ /* Store CRL by SUBJECT */
+ rv = nsslowcert_AddCrl(certHandle, &derCrl, &derSubj, url, isKRL);
+
+ if (url) {
+ PORT_Free(url);
+ }
+ if (rv != SECSuccess) {
+ return CKR_DEVICE_ERROR;
+ }
+
+ /* if we overwrote the existing CRL, poison the handle entry so we get
+ * a new object handle */
+ (void) lg_poisonHandle(sdb, &derSubj,
+ isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
+ *handle = lg_mkHandle(sdb, &derSubj,
+ isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
+
+ return CKR_OK;
+}
+
+/*
+ * check the consistancy and initialize a Public Key Object
+ */
+static CK_RV
+lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
+ CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE;
+ CK_RV crv;
+ NSSLOWKEYPrivateKey *priv;
+ SECItem pubKey;
+ NSSLOWKEYDBHandle *keyHandle = NULL;
+
+ switch (key_type) {
+ case CKK_RSA:
+ pubKeyAttr = CKA_MODULUS;
+ break;
+#ifdef NSS_ENABLE_ECC
+ case CKK_EC:
+ pubKeyAttr = CKA_EC_POINT;
+ break;
+#endif /* NSS_ENABLE_ECC */
+ case CKK_DSA:
+ case CKK_DH:
+ break;
+ default:
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+
+ crv = lg_Attribute2SSecItem(NULL,pubKeyAttr,templ,count,&pubKey);
+ if (crv != CKR_OK) return crv;
+
+ PORT_Assert(pubKey.data);
+ keyHandle = lg_getKeyDB(sdb);
+ if (keyHandle == NULL) {
+ PORT_Free(pubKey.data);
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ if (keyHandle->version != 3) {
+ unsigned char buf[SHA1_LENGTH];
+ SHA1_HashBuf(buf,pubKey.data,pubKey.len);
+ PORT_Memcpy(pubKey.data,buf,sizeof(buf));
+ pubKey.len = sizeof(buf);
+ }
+ /* make sure the associated private key already exists */
+ /* only works if we are logged in */
+ priv = nsslowkey_FindKeyByPublicKey(keyHandle, &pubKey, sdb /*password*/);
+ if (priv == NULL) {
+ PORT_Free(pubKey.data);
+ return crv;
+ }
+ nsslowkey_DestroyPrivateKey(priv);
+
+ *handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_PUB);
+ PORT_Free(pubKey.data);
+
+ return CKR_OK;
+}
+
+/* make a private key from a verified object */
+static NSSLOWKEYPrivateKey *
+lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
+ CK_KEY_TYPE key_type, CK_RV *crvp)
+{
+ NSSLOWKEYPrivateKey *privKey;
+ PLArenaPool *arena;
+ CK_RV crv = CKR_OK;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ *crvp = CKR_HOST_MEMORY;
+ return NULL;
+ }
+
+ privKey = (NSSLOWKEYPrivateKey *)
+ PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
+ if (privKey == NULL) {
+ PORT_FreeArena(arena,PR_FALSE);
+ *crvp = CKR_HOST_MEMORY;
+ return NULL;
+ }
+
+ /* in future this would be a switch on key_type */
+ privKey->arena = arena;
+ switch (key_type) {
+ case CKK_RSA:
+ privKey->keyType = NSSLOWKEYRSAKey;
+ crv=lg_Attribute2SSecItem(arena,CKA_MODULUS,templ,count,
+ &privKey->u.rsa.modulus);
+ if (crv != CKR_OK) break;
+ crv=lg_Attribute2SSecItem(arena,CKA_PUBLIC_EXPONENT,templ,count,
+ &privKey->u.rsa.publicExponent);
+ if (crv != CKR_OK) break;
+ crv=lg_PrivAttr2SSecItem(arena,CKA_PRIVATE_EXPONENT,templ,count,
+ &privKey->u.rsa.privateExponent, sdb);
+ if (crv != CKR_OK) break;
+ crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_1,templ,count,
+ &privKey->u.rsa.prime1, sdb);
+ if (crv != CKR_OK) break;
+ crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_2,templ,count,
+ &privKey->u.rsa.prime2, sdb);
+ if (crv != CKR_OK) break;
+ crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_1,templ,count,
+ &privKey->u.rsa.exponent1, sdb);
+ if (crv != CKR_OK) break;
+ crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_2,templ,count,
+ &privKey->u.rsa.exponent2, sdb);
+ if (crv != CKR_OK) break;
+ crv=lg_PrivAttr2SSecItem(arena,CKA_COEFFICIENT,templ,count,
+ &privKey->u.rsa.coefficient, sdb);
+ if (crv != CKR_OK) break;
+ rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
+ NSSLOWKEY_VERSION);
+ if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
+ break;
+
+ case CKK_DSA:
+ privKey->keyType = NSSLOWKEYDSAKey;
+ crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
+ &privKey->u.dsa.params.prime);
+ if (crv != CKR_OK) break;
+ crv = lg_Attribute2SSecItem(arena,CKA_SUBPRIME,templ,count,
+ &privKey->u.dsa.params.subPrime);
+ if (crv != CKR_OK) break;
+ crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
+ &privKey->u.dsa.params.base);
+ if (crv != CKR_OK) break;
+ crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
+ &privKey->u.dsa.privateValue, sdb);
+ if (crv != CKR_OK) break;
+ if (lg_hasAttribute(CKA_NETSCAPE_DB, templ,count)) {
+ crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
+ &privKey->u.dsa.publicValue);
+ /* privKey was zero'd so public value is already set to NULL, 0
+ * if we don't set it explicitly */
+ }
+ break;
+
+ case CKK_DH:
+ privKey->keyType = NSSLOWKEYDHKey;
+ crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
+ &privKey->u.dh.prime);
+ if (crv != CKR_OK) break;
+ crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
+ &privKey->u.dh.base);
+ if (crv != CKR_OK) break;
+ crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
+ &privKey->u.dh.privateValue, sdb);
+ if (crv != CKR_OK) break;
+ if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
+ crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
+ &privKey->u.dh.publicValue);
+ /* privKey was zero'd so public value is already set to NULL, 0
+ * if we don't set it explicitly */
+ }
+ break;
+
+#ifdef NSS_ENABLE_ECC
+ case CKK_EC:
+ privKey->keyType = NSSLOWKEYECKey;
+ crv = lg_Attribute2SSecItem(arena, CKA_EC_PARAMS,templ,count,
+ &privKey->u.ec.ecParams.DEREncoding);
+ if (crv != CKR_OK) break;
+
+ /* Fill out the rest of the ecParams structure
+ * based on the encoded params
+ */
+ if (LGEC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding,
+ &privKey->u.ec.ecParams) != SECSuccess) {
+ crv = CKR_DOMAIN_PARAMS_INVALID;
+ break;
+ }
+ crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
+ &privKey->u.ec.privateValue, sdb);
+ if (crv != CKR_OK) break;
+ if (lg_hasAttribute(CKA_NETSCAPE_DB,templ,count)) {
+ crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
+ &privKey->u.ec.publicValue);
+ if (crv != CKR_OK) break;
+ /* privKey was zero'd so public value is already set to NULL, 0
+ * if we don't set it explicitly */
+ }
+ rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version,
+ NSSLOWKEY_EC_PRIVATE_KEY_VERSION);
+ if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
+ break;
+#endif /* NSS_ENABLE_ECC */
+
+ default:
+ crv = CKR_KEY_TYPE_INCONSISTENT;
+ break;
+ }
+ *crvp = crv;
+ if (crv != CKR_OK) {
+ PORT_FreeArena(arena,PR_FALSE);
+ return NULL;
+ }
+ return privKey;
+}
+
+/*
+ * check the consistancy and initialize a Private Key Object
+ */
+static CK_RV
+lg_createPrivateKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
+ CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ NSSLOWKEYPrivateKey *privKey;
+ char *label;
+ SECStatus rv = SECSuccess;
+ CK_RV crv = CKR_DEVICE_ERROR;
+ SECItem pubKey;
+ NSSLOWKEYDBHandle *keyHandle = lg_getKeyDB(sdb);
+
+ if (keyHandle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ privKey=lg_mkPrivKey(sdb, templ,count,key_type,&crv);
+ if (privKey == NULL) return crv;
+ label = lg_getString(CKA_LABEL,templ,count);
+
+ crv = lg_Attribute2SSecItem(NULL,CKA_NETSCAPE_DB,templ,count,&pubKey);
+ if (crv != CKR_OK) {
+ crv = CKR_TEMPLATE_INCOMPLETE;
+ rv = SECFailure;
+ goto fail;
+ }
+#ifdef notdef
+ if (keyHandle->version != 3) {
+ unsigned char buf[SHA1_LENGTH];
+ SHA1_HashBuf(buf,pubKey.data,pubKey.len);
+ PORT_Memcpy(pubKey.data,buf,sizeof(buf));
+ pubKey.len = sizeof(buf);
+ }
+#endif
+ /* get the key type */
+ if (key_type == CKK_RSA) {
+ rv = RSA_PrivateKeyCheck(&privKey->u.rsa);
+ if (rv == SECFailure) {
+ goto fail;
+ }
+ }
+ rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey,
+ label, sdb /*->password*/);
+
+fail:
+ if (label) PORT_Free(label);
+ *handle = lg_mkHandle(sdb,&pubKey,LG_TOKEN_TYPE_PRIV);
+ if (pubKey.data) PORT_Free(pubKey.data);
+ nsslowkey_DestroyPrivateKey(privKey);
+ if (rv != SECSuccess) return crv;
+
+ return CKR_OK;
+}
+
+
+#define LG_KEY_MAX_RETRIES 10 /* don't hang if we are having problems with the rng */
+#define LG_KEY_ID_SIZE 18 /* don't use either SHA1 or MD5 sizes */
+/*
+ * Secret keys must have a CKA_ID value to be stored in the database. This code
+ * will generate one if there wasn't one already.
+ */
+static CK_RV
+lg_GenerateSecretCKA_ID(NSSLOWKEYDBHandle *handle, SECItem *id, char *label)
+{
+ unsigned int retries;
+ SECStatus rv = SECSuccess;
+ CK_RV crv = CKR_OK;
+
+ id->data = NULL;
+ if (label) {
+ id->data = (unsigned char *)PORT_Strdup(label);
+ if (id->data == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ id->len = PORT_Strlen(label)+1;
+ if (!nsslowkey_KeyForIDExists(handle,id)) {
+ return CKR_OK;
+ }
+ PORT_Free(id->data);
+ id->data = NULL;
+ id->len = 0;
+ }
+ id->data = (unsigned char *)PORT_Alloc(LG_KEY_ID_SIZE);
+ if (id->data == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ id->len = LG_KEY_ID_SIZE;
+
+ retries = 0;
+ do {
+ rv = RNG_GenerateGlobalRandomBytes(id->data,id->len);
+ } while (rv == SECSuccess && nsslowkey_KeyForIDExists(handle,id) &&
+ (++retries <= LG_KEY_MAX_RETRIES));
+
+ if ((rv != SECSuccess) || (retries > LG_KEY_MAX_RETRIES)) {
+ crv = CKR_DEVICE_ERROR; /* random number generator is bad */
+ PORT_Free(id->data);
+ id->data = NULL;
+ id->len = 0;
+ }
+ return crv;
+}
+
+
+static NSSLOWKEYPrivateKey *lg_mkSecretKeyRep(const CK_ATTRIBUTE *templ,
+ CK_ULONG count, CK_KEY_TYPE key_type,
+ SECItem *pubkey, SDB *sdbpw)
+{
+ NSSLOWKEYPrivateKey *privKey = 0;
+ PLArenaPool *arena = 0;
+ CK_KEY_TYPE keyType;
+ PRUint32 keyTypeStorage;
+ SECItem keyTypeItem;
+ CK_RV crv;
+ SECStatus rv;
+ static unsigned char derZero[1] = { 0 };
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
+
+ privKey = (NSSLOWKEYPrivateKey *)
+ PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
+ if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
+
+ privKey->arena = arena;
+
+ /* Secret keys are represented in the database as "fake" RSA keys.
+ * The RSA key is marked as a secret key representation by setting the
+ * public exponent field to 0, which is an invalid RSA exponent.
+ * The other fields are set as follows:
+ * modulus - CKA_ID value for the secret key
+ * private exponent - CKA_VALUE (the key itself)
+ * coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm
+ * is used for the key.
+ * all others - set to integer 0
+ */
+ privKey->keyType = NSSLOWKEYRSAKey;
+
+ /* The modulus is set to the key id of the symmetric key */
+ crv = lg_Attribute2SecItem(arena, CKA_ID, templ, count,
+ &privKey->u.rsa.modulus);
+ if (crv != CKR_OK) goto loser;
+
+ /* The public exponent is set to 0 length to indicate a special key */
+ privKey->u.rsa.publicExponent.len = sizeof derZero;
+ privKey->u.rsa.publicExponent.data = derZero;
+
+ /* The private exponent is the actual key value */
+ crv = lg_PrivAttr2SecItem(arena, CKA_VALUE, templ, count,
+ &privKey->u.rsa.privateExponent, sdbpw);
+ if (crv != CKR_OK) goto loser;
+
+ /* All other fields empty - needs testing */
+ privKey->u.rsa.prime1.len = sizeof derZero;
+ privKey->u.rsa.prime1.data = derZero;
+
+ privKey->u.rsa.prime2.len = sizeof derZero;
+ privKey->u.rsa.prime2.data = derZero;
+
+ privKey->u.rsa.exponent1.len = sizeof derZero;
+ privKey->u.rsa.exponent1.data = derZero;
+
+ privKey->u.rsa.exponent2.len = sizeof derZero;
+ privKey->u.rsa.exponent2.data = derZero;
+
+ /* Coeficient set to KEY_TYPE */
+ crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &keyType);
+ if (crv != CKR_OK) goto loser;
+ /* on 64 bit platforms, we still want to store 32 bits of keyType (This is
+ * safe since the PKCS #11 defines for all types are 32 bits or less). */
+ keyTypeStorage = (PRUint32) keyType;
+ keyTypeStorage = PR_htonl(keyTypeStorage);
+ keyTypeItem.data = (unsigned char *)&keyTypeStorage;
+ keyTypeItem.len = sizeof (keyTypeStorage);
+ rv = SECITEM_CopyItem(arena, &privKey->u.rsa.coefficient, &keyTypeItem);
+ if (rv != SECSuccess) {
+ crv = CKR_HOST_MEMORY;
+ goto loser;
+ }
+
+ /* Private key version field set normally for compatibility */
+ rv = DER_SetUInteger(privKey->arena,
+ &privKey->u.rsa.version, NSSLOWKEY_VERSION);
+ if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; }
+
+loser:
+ if (crv != CKR_OK) {
+ PORT_FreeArena(arena,PR_FALSE);
+ privKey = 0;
+ }
+
+ return privKey;
+}
+
+/*
+ * check the consistancy and initialize a Secret Key Object
+ */
+static CK_RV
+lg_createSecretKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
+ CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ CK_RV crv;
+ NSSLOWKEYPrivateKey *privKey = NULL;
+ NSSLOWKEYDBHandle *keyHandle = NULL;
+ SECItem pubKey;
+ char *label = NULL;
+ SECStatus rv = SECSuccess;
+
+ pubKey.data = 0;
+
+ /* If the object is a TOKEN object, store in the database */
+ keyHandle = lg_getKeyDB(sdb);
+
+ if (keyHandle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ label = lg_getString(CKA_LABEL,templ,count);
+
+ crv = lg_Attribute2SecItem(NULL,CKA_ID,templ,count,&pubKey);
+ /* Should this be ID? */
+ if (crv != CKR_OK) goto loser;
+
+ /* if we don't have an ID, generate one */
+ if (pubKey.len == 0) {
+ if (pubKey.data) {
+ PORT_Free(pubKey.data);
+ pubKey.data = NULL;
+ }
+ crv = lg_GenerateSecretCKA_ID(keyHandle, &pubKey, label);
+ if (crv != CKR_OK) goto loser;
+ }
+
+ privKey = lg_mkSecretKeyRep(templ, count, key_type, &pubKey, sdb);
+ if (privKey == NULL) {
+ crv = CKR_HOST_MEMORY;
+ goto loser;
+ }
+
+ rv = nsslowkey_StoreKeyByPublicKey(keyHandle,
+ privKey, &pubKey, label, sdb /*->password*/);
+ if (rv != SECSuccess) {
+ crv = CKR_DEVICE_ERROR;
+ goto loser;
+ }
+
+ *handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_KEY);
+
+loser:
+ if (label) PORT_Free(label);
+ if (privKey) nsslowkey_DestroyPrivateKey(privKey);
+ if (pubKey.data) PORT_Free(pubKey.data);
+
+ return crv;
+}
+
+/*
+ * check the consistancy and initialize a Key Object
+ */
+static CK_RV
+lg_createKeyObject(SDB *sdb, CK_OBJECT_CLASS objclass,
+ CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ CK_RV crv;
+ CK_KEY_TYPE key_type;
+
+ /* get the key type */
+ crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &key_type);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+
+ switch (objclass) {
+ case CKO_PUBLIC_KEY:
+ return lg_createPublicKeyObject(sdb,key_type,handle,templ,count);
+ case CKO_PRIVATE_KEY:
+ return lg_createPrivateKeyObject(sdb,key_type,handle,templ,count);
+ case CKO_SECRET_KEY:
+ return lg_createSecretKeyObject(sdb,key_type,handle,templ,count);
+ default:
+ break;
+ }
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+}
+
+/*
+ * Parse the template and create an object stored in the DB that reflects.
+ * the object specified in the database.
+ */
+CK_RV
+lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
+ const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ CK_RV crv;
+ CK_OBJECT_CLASS objclass;
+
+ /* get the object class */
+ crv = lg_GetULongAttribute(CKA_CLASS, templ, count, &objclass);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+
+ /* Now handle the specific object class.
+ */
+ switch (objclass) {
+ case CKO_CERTIFICATE:
+ crv = lg_createCertObject(sdb,handle,templ,count);
+ break;
+ case CKO_NETSCAPE_TRUST:
+ crv = lg_createTrustObject(sdb,handle,templ,count);
+ break;
+ case CKO_NETSCAPE_CRL:
+ crv = lg_createCrlObject(sdb,handle,templ,count);
+ break;
+ case CKO_NETSCAPE_SMIME:
+ crv = lg_createSMimeObject(sdb,handle,templ,count);
+ break;
+ case CKO_PRIVATE_KEY:
+ case CKO_PUBLIC_KEY:
+ case CKO_SECRET_KEY:
+ crv = lg_createKeyObject(sdb,objclass,handle,templ,count);
+ break;
+ default:
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ }
+
+ return crv;
+}
+
diff --git a/security/nss/lib/softoken/legacydb/lgdb.h b/security/nss/lib/softoken/legacydb/lgdb.h
new file mode 100644
index 000000000..1c5744571
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lgdb.h
@@ -0,0 +1,197 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * Internal data structures and functions used by pkcs11.c
+ */
+#ifndef _LGDB_H_
+#define _LGDB_H_ 1
+
+#include "nssilock.h"
+#include "seccomon.h"
+#include "secoidt.h"
+#include "lowkeyti.h"
+#include "pkcs11t.h"
+#include "sdb.h"
+#include "cdbhdl.h"
+
+
+#define MULTIACCESS "multiaccess:"
+
+
+/* machine dependent path stuff used by dbinit.c and pk11db.c */
+#ifdef macintosh
+#define PATH_SEPARATOR ":"
+#define SECMOD_DB "Security Modules"
+#define CERT_DB_FMT "%sCertificates%s"
+#define KEY_DB_FMT "%sKey Database%s"
+#else
+#define PATH_SEPARATOR "/"
+#define SECMOD_DB "secmod.db"
+#define CERT_DB_FMT "%scert%s.db"
+#define KEY_DB_FMT "%skey%s.db"
+#endif
+
+SEC_BEGIN_PROTOS
+
+
+/* internal utility functions used by pkcs11.c */
+extern const CK_ATTRIBUTE *lg_FindAttribute(CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count);
+extern CK_RV lg_Attribute2SecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count,
+ SECItem *item);
+extern CK_RV lg_Attribute2SSecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count,
+ SECItem *item);
+extern CK_RV lg_PrivAttr2SecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count,
+ SECItem *item, SDB *sdbpw);
+extern CK_RV lg_PrivAttr2SSecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count,
+ SECItem *item, SDB *sdbpw);
+extern CK_RV lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count,
+ CK_ULONG *out);
+extern PRBool lg_hasAttribute(CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count);
+extern PRBool lg_isTrue(CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count);
+extern PRBool lg_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass);
+extern char *lg_getString(CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count);
+extern unsigned int lg_MapTrust(CK_TRUST trust, PRBool clientAuth);
+
+/* clear out all the existing object ID to database key mappings.
+ * used to reinit a token */
+extern CK_RV SFTK_ClearTokenKeyHashTable(SDB *sdb);
+
+
+extern void lg_FreeSearch(SDBFind *search);
+
+NSSLOWCERTCertDBHandle *lg_getCertDB(SDB *sdb);
+NSSLOWKEYDBHandle *lg_getKeyDB(SDB *sdb);
+
+const char *lg_EvaluateConfigDir(const char *configdir, char **domain);
+
+
+/*
+ * object handle modifiers
+ */
+#define LG_TOKEN_MASK 0xc0000000L
+#define LG_TOKEN_TYPE_MASK 0x38000000L
+#define LG_TOKEN_TYPE_SHIFT 27
+/* keydb (high bit == 0) */
+#define LG_TOKEN_TYPE_PRIV 0x08000000L
+#define LG_TOKEN_TYPE_PUB 0x10000000L
+#define LG_TOKEN_TYPE_KEY 0x18000000L
+/* certdb (high bit == 1) */
+#define LG_TOKEN_TYPE_TRUST 0x20000000L
+#define LG_TOKEN_TYPE_CRL 0x28000000L
+#define LG_TOKEN_TYPE_SMIME 0x30000000L
+#define LG_TOKEN_TYPE_CERT 0x38000000L
+
+#define LG_TOKEN_KRL_HANDLE (LG_TOKEN_TYPE_CRL|1)
+
+#define LG_SEARCH_BLOCK_SIZE 10
+#define LG_BUF_SPACE 50
+#define LG_STRICT PR_FALSE
+
+/*
+ * token object utilities
+ */
+void lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle);
+PRBool lg_poisonHandle(SDB *sdb, SECItem *dbkey, CK_OBJECT_HANDLE handle);
+PRBool lg_tokenMatch(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE class,
+ const CK_ATTRIBUTE *templ, CK_ULONG count);
+const SECItem *lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle);
+CK_OBJECT_HANDLE lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class);
+SECStatus lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle);
+
+SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdbpw,
+ SECItem *plainText, SECItem **cipherText);
+SECStatus lg_util_decrypt(SDB *sdbpw,
+ SECItem *cipherText, SECItem **plainText);
+PLHashTable *lg_GetHashTable(SDB *sdb);
+void lg_DBLock(SDB *sdb);
+void lg_DBUnlock(SDB *sdb);
+
+typedef void (*LGFreeFunc)(void *);
+
+
+/*
+ * database functions
+ */
+
+/* lg_FindObjectsInit initializes a search for token and session objects
+ * that match a template. */
+CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
+ CK_ULONG ulCount, SDBFind **search);
+/* lg_FindObjects continues a search for token and session objects
+ * that match a template, obtaining additional object handles. */
+CK_RV lg_FindObjects(SDB *sdb, SDBFind *search,
+ CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
+ CK_ULONG *pulObjectCount);
+
+/* lg_FindObjectsFinal finishes a search for token and session objects. */
+CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search);
+
+/* lg_CreateObject parses the template and create an object stored in the
+ * DB that reflects the object specified in the template. */
+CK_RV lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
+ const CK_ATTRIBUTE *templ, CK_ULONG count);
+
+CK_RV lg_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
+ CK_ATTRIBUTE *template, CK_ULONG count);
+CK_RV lg_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
+ const CK_ATTRIBUTE *template, CK_ULONG count);
+CK_RV lg_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id);
+
+CK_RV lg_Close(SDB *sdb);
+CK_RV lg_Reset(SDB *sdb);
+
+/*
+ * The old database doesn't share and doesn't support
+ * transactions.
+ */
+CK_RV lg_Begin(SDB *sdb);
+CK_RV lg_Commit(SDB *sdb);
+CK_RV lg_Abort(SDB *sdb);
+CK_RV lg_GetPWEntry(SDB *sdb, SDBPasswordEntry *entry);
+CK_RV lg_PutPWEntry(SDB *sdb, SDBPasswordEntry *entry);
+
+SEC_END_PROTOS
+
+#endif /* _LGDB_H_ */
diff --git a/security/nss/lib/softoken/legacydb/lgdestroy.c b/security/nss/lib/softoken/legacydb/lgdestroy.c
new file mode 100644
index 000000000..37db2e50e
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lgdestroy.c
@@ -0,0 +1,144 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * Internal PKCS #11 functions. Should only be called by pkcs11.c
+ */
+#include "pkcs11.h"
+#include "lgdb.h"
+#include "pcert.h"
+#include "lowkeyi.h"
+
+/*
+ * remove an object.
+ */
+CK_RV
+lg_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
+{
+ CK_RV crv = CKR_OK;
+ SECStatus rv;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertTrust tmptrust;
+ PRBool isKrl;
+ NSSLOWKEYDBHandle *keyHandle;
+ NSSLOWCERTCertDBHandle *certHandle;
+ const SECItem *dbKey;
+
+ object_id &= ~LG_TOKEN_MASK;
+ dbKey = lg_lookupTokenKeyByHandle(sdb,object_id);
+ if (dbKey == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ /* remove the objects from the real data base */
+ switch (object_id & LG_TOKEN_TYPE_MASK) {
+ case LG_TOKEN_TYPE_PRIV:
+ case LG_TOKEN_TYPE_KEY:
+ /* KEYID is the public KEY for DSA and DH, and the MODULUS for
+ * RSA */
+ keyHandle = lg_getKeyDB(sdb);
+ if (!keyHandle) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ break;
+ }
+ rv = nsslowkey_DeleteKey(keyHandle, dbKey);
+ if (rv != SECSuccess) {
+ crv = CKR_DEVICE_ERROR;
+ }
+ break;
+ case LG_TOKEN_TYPE_PUB:
+ break; /* public keys only exist at the behest of the priv key */
+ case LG_TOKEN_TYPE_CERT:
+ certHandle = lg_getCertDB(sdb);
+ if (!certHandle) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ break;
+ }
+ cert = nsslowcert_FindCertByKey(certHandle,dbKey);
+ if (cert == NULL) {
+ crv = CKR_DEVICE_ERROR;
+ break;
+ }
+ rv = nsslowcert_DeletePermCertificate(cert);
+ if (rv != SECSuccess) {
+ crv = CKR_DEVICE_ERROR;
+ }
+ nsslowcert_DestroyCertificate(cert);
+ break;
+ case LG_TOKEN_TYPE_CRL:
+ certHandle = lg_getCertDB(sdb);
+ if (!certHandle) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ break;
+ }
+ isKrl = (PRBool) (object_id == LG_TOKEN_KRL_HANDLE);
+ rv = nsslowcert_DeletePermCRL(certHandle, dbKey, isKrl);
+ if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
+ break;
+ case LG_TOKEN_TYPE_TRUST:
+ certHandle = lg_getCertDB(sdb);
+ if (!certHandle) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ break;
+ }
+ cert = nsslowcert_FindCertByKey(certHandle, dbKey);
+ if (cert == NULL) {
+ crv = CKR_DEVICE_ERROR;
+ break;
+ }
+ tmptrust = *cert->trust;
+ tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS;
+ tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS;
+ tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS;
+ tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN;
+ tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN;
+ tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN;
+ rv = nsslowcert_ChangeCertTrust(certHandle, cert, &tmptrust);
+ if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
+ nsslowcert_DestroyCertificate(cert);
+ break;
+ default:
+ break;
+ }
+ lg_DBLock(sdb);
+ lg_deleteTokenKeyByHandle(sdb,object_id);
+ lg_DBUnlock(sdb);
+
+ return crv;
+}
+
+
+
diff --git a/security/nss/lib/softoken/legacydb/lgfind.c b/security/nss/lib/softoken/legacydb/lgfind.c
new file mode 100644
index 000000000..b7029c7d5
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lgfind.c
@@ -0,0 +1,941 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "secitem.h"
+#include "pkcs11.h"
+#include "lgdb.h"
+#include "lowkeyi.h"
+#include "pcert.h"
+#include "blapi.h"
+
+#include "keydbi.h"
+
+/*
+ * This code maps PKCS #11 Finds to legacy database searches. This code
+ * was orginally in pkcs11.c in previous versions of NSS.
+ */
+
+struct SDBFindStr {
+ CK_OBJECT_HANDLE *handles;
+ int size;
+ int index;
+ int array_size;
+};
+
+
+/*
+ * free a search structure
+ */
+void
+lg_FreeSearch(SDBFind *search)
+{
+ if (search->handles) {
+ PORT_Free(search->handles);
+ }
+ PORT_Free(search);
+}
+
+void
+lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle)
+{
+ if (search->handles == NULL) {
+ return;
+ }
+ if (search->size >= search->array_size) {
+ search->array_size += LG_SEARCH_BLOCK_SIZE;
+ search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
+ sizeof(CK_OBJECT_HANDLE)* search->array_size);
+ if (search->handles == NULL) {
+ return;
+ }
+ }
+ search->handles[search->size] = handle;
+ search->size++;
+}
+
+/*
+ * find any certs that may match the template and load them.
+ */
+#define LG_CERT 0x00000001
+#define LG_TRUST 0x00000002
+#define LG_CRL 0x00000004
+#define LG_SMIME 0x00000008
+#define LG_PRIVATE 0x00000010
+#define LG_PUBLIC 0x00000020
+#define LG_KEY 0x00000040
+
+/*
+ * structure to collect key handles.
+ */
+typedef struct lgEntryDataStr {
+ SDB *sdb;
+ SDBFind *searchHandles;
+ const CK_ATTRIBUTE *template;
+ CK_ULONG templ_count;
+} lgEntryData;
+
+
+static SECStatus
+lg_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
+{
+ lgEntryData *crlData;
+ CK_OBJECT_HANDLE class_handle;
+ SDB *sdb;
+
+ crlData = (lgEntryData *)arg;
+ sdb = crlData->sdb;
+
+ class_handle = (type == certDBEntryTypeRevocation) ? LG_TOKEN_TYPE_CRL :
+ LG_TOKEN_KRL_HANDLE;
+ if (lg_tokenMatch(sdb, key, class_handle,
+ crlData->template, crlData->templ_count)) {
+ lg_addHandle(crlData->searchHandles,
+ lg_mkHandle(sdb,key,class_handle));
+ }
+ return(SECSuccess);
+}
+
+static void
+lg_searchCrls(SDB *sdb, SECItem *derSubject, PRBool isKrl,
+ unsigned long classFlags, SDBFind *search,
+ const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
+{
+ NSSLOWCERTCertDBHandle *certHandle = NULL;
+
+ certHandle = lg_getCertDB(sdb);
+ if (certHandle == NULL) {
+ return;
+ }
+ if (derSubject->data != NULL) {
+ certDBEntryRevocation *crl =
+ nsslowcert_FindCrlByKey(certHandle, derSubject, isKrl);
+
+ if (crl != NULL) {
+ lg_addHandle(search, lg_mkHandle(sdb, derSubject,
+ isKrl ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL));
+ nsslowcert_DestroyDBEntry((certDBEntry *)crl);
+ }
+ } else {
+ lgEntryData crlData;
+
+ /* traverse */
+ crlData.sdb = sdb;
+ crlData.searchHandles = search;
+ crlData.template = pTemplate;
+ crlData.templ_count = ulCount;
+ nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation,
+ lg_crl_collect, (void *)&crlData);
+ nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation,
+ lg_crl_collect, (void *)&crlData);
+ }
+}
+
+/*
+ * structure to collect key handles.
+ */
+typedef struct lgKeyDataStr {
+ SDB *sdb;
+ NSSLOWKEYDBHandle *keyHandle;
+ SDBFind *searchHandles;
+ SECItem *id;
+ const CK_ATTRIBUTE *template;
+ CK_ULONG templ_count;
+ unsigned long classFlags;
+ PRBool strict;
+} lgKeyData;
+
+static PRBool
+isSecretKey(NSSLOWKEYPrivateKey *privKey)
+{
+ if (privKey->keyType == NSSLOWKEYRSAKey &&
+ privKey->u.rsa.publicExponent.len == 1 &&
+ privKey->u.rsa.publicExponent.data[0] == 0)
+ return PR_TRUE;
+
+ return PR_FALSE;
+}
+
+
+
+static SECStatus
+lg_key_collect(DBT *key, DBT *data, void *arg)
+{
+ lgKeyData *keyData;
+ NSSLOWKEYPrivateKey *privKey = NULL;
+ SECItem tmpDBKey;
+ SDB *sdb;
+ unsigned long classFlags;
+
+ keyData = (lgKeyData *)arg;
+ sdb = keyData->sdb;
+ classFlags = keyData->classFlags;
+
+ tmpDBKey.data = key->data;
+ tmpDBKey.len = key->size;
+ tmpDBKey.type = siBuffer;
+
+ PORT_Assert(keyData->keyHandle);
+ if (!keyData->strict && keyData->id) {
+ SECItem result;
+ PRBool haveMatch= PR_FALSE;
+ unsigned char hashKey[SHA1_LENGTH];
+ result.data = hashKey;
+ result.len = sizeof(hashKey);
+
+ if (keyData->id->len == 0) {
+ /* Make sure this isn't a LG_KEY */
+ privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle,
+ &tmpDBKey, keyData->sdb/*->password*/);
+ if (privKey) {
+ /* turn off the unneeded class flags */
+ classFlags &= isSecretKey(privKey) ? ~(LG_PRIVATE|LG_PUBLIC) :
+ ~LG_KEY;
+ haveMatch = (PRBool)
+ ((classFlags & (LG_KEY|LG_PRIVATE|LG_PUBLIC)) != 0);
+ nsslowkey_DestroyPrivateKey(privKey);
+ }
+ } else {
+ SHA1_HashBuf( hashKey, key->data, key->size ); /* match id */
+ haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
+ if (!haveMatch && ((unsigned char *)key->data)[0] == 0) {
+ /* This is a fix for backwards compatibility. The key
+ * database indexes private keys by the public key, and
+ * versions of NSS prior to 3.4 stored the public key as
+ * a signed integer. The public key is now treated as an
+ * unsigned integer, with no leading zero. In order to
+ * correctly compute the hash of an old key, it is necessary
+ * to fallback and detect the leading zero.
+ */
+ SHA1_HashBuf(hashKey,
+ (unsigned char *)key->data + 1, key->size - 1);
+ haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
+ }
+ }
+ if (haveMatch) {
+ if (classFlags & LG_PRIVATE) {
+ lg_addHandle(keyData->searchHandles,
+ lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
+ }
+ if (classFlags & LG_PUBLIC) {
+ lg_addHandle(keyData->searchHandles,
+ lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PUB));
+ }
+ if (classFlags & LG_KEY) {
+ lg_addHandle(keyData->searchHandles,
+ lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_KEY));
+ }
+ }
+ return SECSuccess;
+ }
+
+ privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey,
+ keyData->sdb/*->password*/);
+ if ( privKey == NULL ) {
+ goto loser;
+ }
+
+ if (isSecretKey(privKey)) {
+ if ((classFlags & LG_KEY) &&
+ lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY,
+ keyData->template, keyData->templ_count)) {
+ lg_addHandle(keyData->searchHandles,
+ lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY));
+ }
+ } else {
+ if ((classFlags & LG_PRIVATE) &&
+ lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV,
+ keyData->template, keyData->templ_count)) {
+ lg_addHandle(keyData->searchHandles,
+ lg_mkHandle(keyData->sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
+ }
+ if ((classFlags & LG_PUBLIC) &&
+ lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB,
+ keyData->template, keyData->templ_count)) {
+ lg_addHandle(keyData->searchHandles,
+ lg_mkHandle(keyData->sdb, &tmpDBKey,LG_TOKEN_TYPE_PUB));
+ }
+ }
+
+loser:
+ if ( privKey ) {
+ nsslowkey_DestroyPrivateKey(privKey);
+ }
+ return(SECSuccess);
+}
+
+static void
+lg_searchKeys(SDB *sdb, SECItem *key_id,
+ unsigned long classFlags, SDBFind *search, PRBool mustStrict,
+ const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
+{
+ NSSLOWKEYDBHandle *keyHandle = NULL;
+ NSSLOWKEYPrivateKey *privKey;
+ lgKeyData keyData;
+ PRBool found = PR_FALSE;
+
+ keyHandle = lg_getKeyDB(sdb);
+ if (keyHandle == NULL) {
+ return;
+ }
+
+ if (key_id->data) {
+ privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, sdb);
+ if (privKey) {
+ if ((classFlags & LG_KEY) && isSecretKey(privKey)) {
+ lg_addHandle(search,
+ lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_KEY));
+ found = PR_TRUE;
+ }
+ if ((classFlags & LG_PRIVATE) && !isSecretKey(privKey)) {
+ lg_addHandle(search,
+ lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PRIV));
+ found = PR_TRUE;
+ }
+ if ((classFlags & LG_PUBLIC) && !isSecretKey(privKey)) {
+ lg_addHandle(search,
+ lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PUB));
+ found = PR_TRUE;
+ }
+ nsslowkey_DestroyPrivateKey(privKey);
+ }
+ /* don't do the traversal if we have an up to date db */
+ if (keyHandle->version != 3) {
+ goto loser;
+ }
+ /* don't do the traversal if it can't possibly be the correct id */
+ /* all soft token id's are SHA1_HASH_LEN's */
+ if (key_id->len != SHA1_LENGTH) {
+ goto loser;
+ }
+ if (found) {
+ /* if we already found some keys, don't do the traversal */
+ goto loser;
+ }
+ }
+ keyData.sdb = sdb;
+ keyData.keyHandle = keyHandle;
+ keyData.searchHandles = search;
+ keyData.id = key_id;
+ keyData.template = pTemplate;
+ keyData.templ_count = ulCount;
+ keyData.classFlags = classFlags;
+ keyData.strict = mustStrict ? mustStrict : LG_STRICT;
+
+ nsslowkey_TraverseKeys(keyHandle, lg_key_collect, &keyData);
+
+loser:
+ return;
+}
+
+/*
+ * structure to collect certs into
+ */
+typedef struct lgCertDataStr {
+ SDB *sdb;
+ int cert_count;
+ int max_cert_count;
+ NSSLOWCERTCertificate **certs;
+ const CK_ATTRIBUTE *template;
+ CK_ULONG templ_count;
+ unsigned long classFlags;
+ PRBool strict;
+} lgCertData;
+
+/*
+ * collect all the certs from the traverse call.
+ */
+static SECStatus
+lg_cert_collect(NSSLOWCERTCertificate *cert,void *arg)
+{
+ lgCertData *cd = (lgCertData *)arg;
+
+ if (cert == NULL) {
+ return SECSuccess;
+ }
+
+ if (cd->certs == NULL) {
+ return SECFailure;
+ }
+
+ if (cd->strict) {
+ if ((cd->classFlags & LG_CERT) && !lg_tokenMatch(cd->sdb,
+ &cert->certKey, LG_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) {
+ return SECSuccess;
+ }
+ if ((cd->classFlags & LG_TRUST) && !lg_tokenMatch(cd->sdb,
+ &cert->certKey, LG_TOKEN_TYPE_TRUST,
+ cd->template, cd->templ_count)) {
+ return SECSuccess;
+ }
+ }
+
+ /* allocate more space if we need it. This should only happen in
+ * the general traversal case */
+ if (cd->cert_count >= cd->max_cert_count) {
+ int size;
+ cd->max_cert_count += LG_SEARCH_BLOCK_SIZE;
+ size = cd->max_cert_count * sizeof (NSSLOWCERTCertificate *);
+ cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs,size);
+ if (cd->certs == NULL) {
+ return SECFailure;
+ }
+ }
+
+ cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert);
+ return SECSuccess;
+}
+
+/* provide impedence matching ... */
+static SECStatus
+lg_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg)
+{
+ return lg_cert_collect(cert, arg);
+}
+
+static void
+lg_searchSingleCert(lgCertData *certData,NSSLOWCERTCertificate *cert)
+{
+ if (cert == NULL) {
+ return;
+ }
+ if (certData->strict &&
+ !lg_tokenMatch(certData->sdb, &cert->certKey, LG_TOKEN_TYPE_CERT,
+ certData->template,certData->templ_count)) {
+ nsslowcert_DestroyCertificate(cert);
+ return;
+ }
+ certData->certs = (NSSLOWCERTCertificate **)
+ PORT_Alloc(sizeof (NSSLOWCERTCertificate *));
+ if (certData->certs == NULL) {
+ nsslowcert_DestroyCertificate(cert);
+ return;
+ }
+ certData->certs[0] = cert;
+ certData->cert_count = 1;
+}
+
+static void
+lg_CertSetupData(lgCertData *certData,int count)
+{
+ certData->max_cert_count = count;
+
+ if (certData->max_cert_count <= 0) {
+ return;
+ }
+ certData->certs = (NSSLOWCERTCertificate **)
+ PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *));
+ return;
+}
+
+static void
+lg_searchCertsAndTrust(SDB *sdb, SECItem *derCert, SECItem *name,
+ SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN,
+ SECItem *email,
+ unsigned long classFlags, SDBFind *handles,
+ const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
+{
+ NSSLOWCERTCertDBHandle *certHandle = NULL;
+ lgCertData certData;
+ int i;
+
+ certHandle = lg_getCertDB(sdb);
+ if (certHandle == NULL) return;
+
+ certData.sdb = sdb;
+ certData.max_cert_count = 0;
+ certData.certs = NULL;
+ certData.cert_count = 0;
+ certData.template = pTemplate;
+ certData.templ_count = ulCount;
+ certData.classFlags = classFlags;
+ certData.strict = LG_STRICT;
+
+
+ /*
+ * Find the Cert.
+ */
+ if (derCert->data != NULL) {
+ NSSLOWCERTCertificate *cert =
+ nsslowcert_FindCertByDERCert(certHandle,derCert);
+ lg_searchSingleCert(&certData,cert);
+ } else if (name->data != NULL) {
+ char *tmp_name = (char*)PORT_Alloc(name->len+1);
+ int count;
+
+ if (tmp_name == NULL) {
+ return;
+ }
+ PORT_Memcpy(tmp_name,name->data,name->len);
+ tmp_name[name->len] = 0;
+
+ count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name);
+ lg_CertSetupData(&certData,count);
+ nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name,
+ lg_cert_collect, &certData);
+ PORT_Free(tmp_name);
+ } else if (derSubject->data != NULL) {
+ int count;
+
+ count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject);
+ lg_CertSetupData(&certData,count);
+ nsslowcert_TraversePermCertsForSubject(certHandle,derSubject,
+ lg_cert_collect, &certData);
+ } else if ((issuerSN->derIssuer.data != NULL) &&
+ (issuerSN->serialNumber.data != NULL)) {
+ if (classFlags & LG_CERT) {
+ NSSLOWCERTCertificate *cert =
+ nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN);
+
+ lg_searchSingleCert(&certData,cert);
+ }
+ if (classFlags & LG_TRUST) {
+ NSSLOWCERTTrust *trust =
+ nsslowcert_FindTrustByIssuerAndSN(certHandle, issuerSN);
+
+ if (trust) {
+ lg_addHandle(handles,
+ lg_mkHandle(sdb,&trust->dbKey,LG_TOKEN_TYPE_TRUST));
+ nsslowcert_DestroyTrust(trust);
+ }
+ }
+ } else if (email->data != NULL) {
+ char *tmp_name = (char*)PORT_Alloc(email->len+1);
+ certDBEntrySMime *entry = NULL;
+
+ if (tmp_name == NULL) {
+ return;
+ }
+ PORT_Memcpy(tmp_name,email->data,email->len);
+ tmp_name[email->len] = 0;
+
+ entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
+ if (entry) {
+ int count;
+ SECItem *subjectName = &entry->subjectName;
+
+ count = nsslowcert_NumPermCertsForSubject(certHandle, subjectName);
+ lg_CertSetupData(&certData,count);
+ nsslowcert_TraversePermCertsForSubject(certHandle, subjectName,
+ lg_cert_collect, &certData);
+
+ nsslowcert_DestroyDBEntry((certDBEntry *)entry);
+ }
+ PORT_Free(tmp_name);
+ } else {
+ /* we aren't filtering the certs, we are working on all, so turn
+ * on the strict filters. */
+ certData.strict = PR_TRUE;
+ lg_CertSetupData(&certData,LG_SEARCH_BLOCK_SIZE);
+ nsslowcert_TraversePermCerts(certHandle, lg_cert_collect2, &certData);
+ }
+
+ /*
+ * build the handles
+ */
+ for (i=0 ; i < certData.cert_count ; i++) {
+ NSSLOWCERTCertificate *cert = certData.certs[i];
+
+ /* if we filtered it would have been on the stuff above */
+ if (classFlags & LG_CERT) {
+ lg_addHandle(handles,
+ lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT));
+ }
+ if ((classFlags & LG_TRUST) && nsslowcert_hasTrust(cert->trust)) {
+ lg_addHandle(handles,
+ lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST));
+ }
+ nsslowcert_DestroyCertificate(cert);
+ }
+
+ if (certData.certs) PORT_Free(certData.certs);
+ return;
+}
+
+static SECStatus
+lg_smime_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
+{
+ lgEntryData *smimeData;
+ SDB *sdb;
+
+ smimeData = (lgEntryData *)arg;
+ sdb = smimeData->sdb;
+
+ if (lg_tokenMatch(sdb, key, LG_TOKEN_TYPE_SMIME,
+ smimeData->template, smimeData->templ_count)) {
+ lg_addHandle(smimeData->searchHandles,
+ lg_mkHandle(sdb,key,LG_TOKEN_TYPE_SMIME));
+ }
+ return(SECSuccess);
+}
+
+static void
+lg_searchSMime(SDB *sdb, SECItem *email, SDBFind *handles,
+ const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
+{
+ NSSLOWCERTCertDBHandle *certHandle = NULL;
+ certDBEntrySMime *entry;
+
+ certHandle = lg_getCertDB(sdb);
+ if (certHandle == NULL) return;
+
+ if (email->data != NULL) {
+ char *tmp_name = (char*)PORT_Alloc(email->len+1);
+
+ if (tmp_name == NULL) {
+ return;
+ }
+ PORT_Memcpy(tmp_name,email->data,email->len);
+ tmp_name[email->len] = 0;
+
+ entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
+ if (entry) {
+ SECItem emailKey;
+
+ emailKey.data = (unsigned char *)tmp_name;
+ emailKey.len = PORT_Strlen(tmp_name)+1;
+ emailKey.type = 0;
+ lg_addHandle(handles,
+ lg_mkHandle(sdb,&emailKey,LG_TOKEN_TYPE_SMIME));
+ nsslowcert_DestroyDBEntry((certDBEntry *)entry);
+ }
+ PORT_Free(tmp_name);
+ } else {
+ /* traverse */
+ lgEntryData smimeData;
+
+ /* traverse */
+ smimeData.sdb = sdb;
+ smimeData.searchHandles = handles;
+ smimeData.template = pTemplate;
+ smimeData.templ_count = ulCount;
+ nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeSMimeProfile,
+ lg_smime_collect, (void *)&smimeData);
+ }
+ return;
+}
+
+static CK_RV
+lg_searchTokenList(SDB *sdb, SDBFind *search,
+ const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
+{
+ int i;
+ PRBool isKrl = PR_FALSE;
+ SECItem derCert = { siBuffer, NULL, 0 };
+ SECItem derSubject = { siBuffer, NULL, 0 };
+ SECItem name = { siBuffer, NULL, 0 };
+ SECItem email = { siBuffer, NULL, 0 };
+ SECItem key_id = { siBuffer, NULL, 0 };
+ SECItem cert_sha1_hash = { siBuffer, NULL, 0 };
+ SECItem cert_md5_hash = { siBuffer, NULL, 0 };
+ NSSLOWCERTIssuerAndSN issuerSN = {
+ { siBuffer, NULL, 0 },
+ { siBuffer, NULL, 0 }
+ };
+ SECItem *copy = NULL;
+ CK_CERTIFICATE_TYPE certType;
+ CK_OBJECT_CLASS objectClass;
+ CK_RV crv;
+ unsigned long classFlags =
+ LG_CERT|LG_TRUST|LG_PRIVATE|LG_PUBLIC|LG_KEY|LG_SMIME|LG_CRL;
+
+ if (lg_getCertDB(sdb) == NULL) {
+ classFlags = LG_PRIVATE|LG_KEY;
+ } else {
+ classFlags = LG_CERT|LG_TRUST|LG_PUBLIC|LG_SMIME|LG_CRL;
+ }
+
+ /*
+ * look for things to search on token objects for. If the right options
+ * are specified, we can use them as direct indeces into the database
+ * (rather than using linear searches. We can also use the attributes to
+ * limit the kinds of objects we are searching for. Later we can use this
+ * array to filter the remaining objects more finely.
+ */
+ for (i=0 ;classFlags && i < (int)ulCount; i++) {
+
+ switch (pTemplate[i].type) {
+ case CKA_SUBJECT:
+ copy = &derSubject;
+ classFlags &= (LG_CERT|LG_PRIVATE|LG_PUBLIC|LG_SMIME|LG_CRL);
+ break;
+ case CKA_ISSUER:
+ copy = &issuerSN.derIssuer;
+ classFlags &= (LG_CERT|LG_TRUST);
+ break;
+ case CKA_SERIAL_NUMBER:
+ copy = &issuerSN.serialNumber;
+ classFlags &= (LG_CERT|LG_TRUST);
+ break;
+ case CKA_VALUE:
+ copy = &derCert;
+ classFlags &= (LG_CERT|LG_CRL|LG_SMIME);
+ break;
+ case CKA_LABEL:
+ copy = &name;
+ break;
+ case CKA_NETSCAPE_EMAIL:
+ copy = &email;
+ classFlags &= LG_SMIME|LG_CERT;
+ break;
+ case CKA_NETSCAPE_SMIME_TIMESTAMP:
+ classFlags &= LG_SMIME;
+ break;
+ case CKA_CLASS:
+ crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1, &objectClass);
+ if (crv != CKR_OK) {
+ classFlags = 0;
+ break;;
+ }
+ switch (objectClass) {
+ case CKO_CERTIFICATE:
+ classFlags &= LG_CERT;
+ break;
+ case CKO_NETSCAPE_TRUST:
+ classFlags &= LG_TRUST;
+ break;
+ case CKO_NETSCAPE_CRL:
+ classFlags &= LG_CRL;
+ break;
+ case CKO_NETSCAPE_SMIME:
+ classFlags &= LG_SMIME;
+ break;
+ case CKO_PRIVATE_KEY:
+ classFlags &= LG_PRIVATE;
+ break;
+ case CKO_PUBLIC_KEY:
+ classFlags &= LG_PUBLIC;
+ break;
+ case CKO_SECRET_KEY:
+ classFlags &= LG_KEY;
+ break;
+ default:
+ classFlags = 0;
+ break;
+ }
+ break;
+ case CKA_PRIVATE:
+ if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
+ classFlags = 0;
+ }
+ if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
+ classFlags &= (LG_PRIVATE|LG_KEY);
+ } else {
+ classFlags &= ~(LG_PRIVATE|LG_KEY);
+ }
+ break;
+ case CKA_SENSITIVE:
+ if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
+ classFlags = 0;
+ }
+ if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
+ classFlags &= (LG_PRIVATE|LG_KEY);
+ } else {
+ classFlags = 0;
+ }
+ break;
+ case CKA_TOKEN:
+ if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
+ classFlags = 0;
+ }
+ if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
+ classFlags = 0;
+ }
+ break;
+ case CKA_CERT_SHA1_HASH:
+ classFlags &= LG_TRUST;
+ copy = &cert_sha1_hash; break;
+ case CKA_CERT_MD5_HASH:
+ classFlags &= LG_TRUST;
+ copy = &cert_md5_hash; break;
+ case CKA_CERTIFICATE_TYPE:
+ crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1,&certType);
+ if (crv != CKR_OK) {
+ classFlags = 0;
+ }
+ classFlags &= LG_CERT;
+ if (certType != CKC_X_509) {
+ classFlags = 0;
+ }
+ break;
+ case CKA_ID:
+ copy = &key_id;
+ classFlags &= (LG_CERT|LG_PRIVATE|LG_KEY|LG_PUBLIC);
+ break;
+ case CKA_NETSCAPE_KRL:
+ if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
+ classFlags = 0;
+ }
+ classFlags &= LG_CRL;
+ isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE);
+ break;
+ case CKA_MODIFIABLE:
+ break;
+ case CKA_KEY_TYPE:
+ case CKA_DERIVE:
+ classFlags &= LG_PUBLIC|LG_PRIVATE|LG_KEY;
+ break;
+ case CKA_VERIFY_RECOVER:
+ classFlags &= LG_PUBLIC;
+ break;
+ case CKA_SIGN_RECOVER:
+ classFlags &= LG_PRIVATE;
+ break;
+ case CKA_ENCRYPT:
+ case CKA_VERIFY:
+ case CKA_WRAP:
+ classFlags &= LG_PUBLIC|LG_KEY;
+ break;
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_UNWRAP:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_EXTRACTABLE:
+ case CKA_NEVER_EXTRACTABLE:
+ classFlags &= LG_PRIVATE|LG_KEY;
+ break;
+ /* can't be a certificate if it doesn't match one of the above
+ * attributes */
+ default:
+ classFlags = 0;
+ break;
+ }
+ if (copy) {
+ copy->data = (unsigned char*)pTemplate[i].pValue;
+ copy->len = pTemplate[i].ulValueLen;
+ }
+ copy = NULL;
+ }
+
+ /* certs */
+ if (classFlags & (LG_CERT|LG_TRUST)) {
+ lg_searchCertsAndTrust(sdb,&derCert,&name,&derSubject,
+ &issuerSN, &email,classFlags,search,
+ pTemplate, ulCount);
+ }
+
+ /* keys */
+ if (classFlags & (LG_PRIVATE|LG_PUBLIC|LG_KEY)) {
+ PRBool mustStrict = ((classFlags & LG_KEY) != 0) && (name.len != 0);
+ lg_searchKeys(sdb, &key_id, classFlags, search,
+ mustStrict, pTemplate, ulCount);
+ }
+
+ /* crl's */
+ if (classFlags & LG_CRL) {
+ lg_searchCrls(sdb, &derSubject, isKrl, classFlags, search,
+ pTemplate, ulCount);
+ }
+ /* Add S/MIME entry stuff */
+ if (classFlags & LG_SMIME) {
+ lg_searchSMime(sdb, &email, search, pTemplate, ulCount);
+ }
+ return CKR_OK;
+}
+
+
+/* lg_FindObjectsInit initializes a search for token and session objects
+ * that match a template. */
+CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
+ CK_ULONG ulCount, SDBFind **retSearch)
+{
+ SDBFind *search;
+ CK_RV crv = CKR_OK;
+
+ *retSearch = NULL;
+
+ search = (SDBFind *)PORT_Alloc(sizeof(SDBFind));
+ if (search == NULL) {
+ crv = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ search->handles = (CK_OBJECT_HANDLE *)
+ PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * LG_SEARCH_BLOCK_SIZE);
+ if (search->handles == NULL) {
+ crv = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ search->index = 0;
+ search->size = 0;
+ search->array_size = LG_SEARCH_BLOCK_SIZE;
+ /* FIXME - do we still need to get Login state? */
+
+ crv = lg_searchTokenList(sdb, search, pTemplate, ulCount);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+
+ *retSearch = search;
+ return CKR_OK;
+
+loser:
+ if (search) {
+ lg_FreeSearch(search);
+ }
+ return crv;
+}
+
+
+/* lg_FindObjects continues a search for token and session objects
+ * that match a template, obtaining additional object handles. */
+CK_RV lg_FindObjects(SDB *sdb, SDBFind *search,
+ CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
+ CK_ULONG *pulObjectCount)
+{
+ int transfer;
+ int left;
+
+ *pulObjectCount = 0;
+ left = search->size - search->index;
+ transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount;
+ if (transfer > 0) {
+ PORT_Memcpy(phObject,&search->handles[search->index],
+ transfer*sizeof(CK_OBJECT_HANDLE_PTR));
+ } else {
+ *phObject = CK_INVALID_HANDLE;
+ }
+
+ search->index += transfer;
+ *pulObjectCount = transfer;
+ return CKR_OK;
+}
+
+/* lg_FindObjectsFinal finishes a search for token and session objects. */
+CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search)
+{
+
+ if (search != NULL) {
+ lg_FreeSearch(search);
+ }
+ return CKR_OK;
+}
diff --git a/security/nss/lib/softoken/dbinit.c b/security/nss/lib/softoken/legacydb/lginit.c
index 921af1568..ed5ec4a47 100644
--- a/security/nss/lib/softoken/dbinit.c
+++ b/security/nss/lib/softoken/legacydb/lginit.c
@@ -38,21 +38,20 @@
* ***** END LICENSE BLOCK ***** */
/* $Id$ */
-#include <ctype.h>
-#include "seccomon.h"
-#include "prinit.h"
-#include "prprf.h"
-#include "prmem.h"
-#include "pratom.h"
-#include "pcertt.h"
#include "lowkeyi.h"
#include "pcert.h"
-#include "cdbhdl.h"
#include "keydbi.h"
-#include "pkcs11i.h"
+#include "lgdb.h"
+
+typedef struct LGPrivateStr {
+ NSSLOWCERTCertDBHandle *certDB;
+ NSSLOWKEYDBHandle *keyDB;
+ PRLock *dbLock;
+ PLHashTable *hashTable;
+} LGPrivate;
static char *
-sftk_certdb_name_cb(void *arg, int dbVersion)
+lg_certdb_name_cb(void *arg, int dbVersion)
{
const char *configdir = (const char *)arg;
const char *dbver;
@@ -89,7 +88,7 @@ sftk_certdb_name_cb(void *arg, int dbVersion)
}
static char *
-sftk_keydb_name_cb(void *arg, int dbVersion)
+lg_keydb_name_cb(void *arg, int dbVersion)
{
const char *configdir = (const char *)arg;
const char *dbver;
@@ -121,7 +120,7 @@ sftk_keydb_name_cb(void *arg, int dbVersion)
}
const char *
-sftk_EvaluateConfigDir(const char *configdir,char **appName)
+lg_EvaluateConfigDir(const char *configdir,char **appName)
{
if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) {
char *cdir;
@@ -143,171 +142,9 @@ sftk_EvaluateConfigDir(const char *configdir,char **appName)
return configdir;
}
-static CK_RV
-sftk_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly,
- NSSLOWCERTCertDBHandle **certdbPtr)
-{
- NSSLOWCERTCertDBHandle *certdb = NULL;
- CK_RV crv = CKR_NETSCAPE_CERTDB_FAILED;
- SECStatus rv;
- char * name = NULL;
- char * appName = NULL;
-
- if (prefix == NULL) {
- prefix = "";
- }
-
- configdir = sftk_EvaluateConfigDir(configdir, &appName);
-
- name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
- if (name == NULL) goto loser;
-
- certdb = (NSSLOWCERTCertDBHandle*)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle));
- if (certdb == NULL)
- goto loser;
-
- certdb->ref = 1;
-/* fix when we get the DB in */
- rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix,
- sftk_certdb_name_cb, (void *)name, PR_FALSE);
- if (rv == SECSuccess) {
- crv = CKR_OK;
- *certdbPtr = certdb;
- certdb = NULL;
- }
-loser:
- if (certdb) PR_Free(certdb);
- if (name) PR_smprintf_free(name);
- if (appName) PORT_Free(appName);
- return crv;
-}
-
-static CK_RV
-sftk_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly,
- NSSLOWKEYDBHandle **keydbPtr)
-{
- NSSLOWKEYDBHandle *keydb;
- char * name = NULL;
- char * appName = NULL;
-
- if (prefix == NULL) {
- prefix = "";
- }
- configdir = sftk_EvaluateConfigDir(configdir, &appName);
-
- name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
- if (name == NULL)
- return CKR_HOST_MEMORY;
- keydb = nsslowkey_OpenKeyDB(readOnly, appName, prefix,
- sftk_keydb_name_cb, (void *)name);
- PR_smprintf_free(name);
- if (appName) PORT_Free(appName);
- if (keydb == NULL)
- return CKR_NETSCAPE_KEYDB_FAILED;
- *keydbPtr = keydb;
-
- return CKR_OK;
-}
-
-
-/*
- * OK there are now lots of options here, lets go through them all:
- *
- * configdir - base directory where all the cert, key, and module datbases live.
- * certPrefix - prefix added to the beginning of the cert database example: "
- * "https-server1-"
- * keyPrefix - prefix added to the beginning of the key database example: "
- * "https-server1-"
- * secmodName - name of the security module database (usually "secmod.db").
- * readOnly - Boolean: true if the databases are to be openned read only.
- * nocertdb - Don't open the cert DB and key DB's, just initialize the
- * Volatile certdb.
- * nomoddb - Don't open the security module DB, just initialize the
- * PKCS #11 module.
- * forceOpen - Continue to force initializations even if the databases cannot
- * be opened.
- */
-CK_RV
-sftk_DBInit(const char *configdir, const char *certPrefix,
- const char *keyPrefix, PRBool readOnly,
- PRBool noCertDB, PRBool noKeyDB, PRBool forceOpen,
- NSSLOWCERTCertDBHandle **certdbPtr, NSSLOWKEYDBHandle **keydbPtr)
-{
- CK_RV crv = CKR_OK;
-
-
- if (!noCertDB) {
- crv = sftk_OpenCertDB(configdir, certPrefix, readOnly, certdbPtr);
- if (crv != CKR_OK) {
- if (!forceOpen) goto loser;
- crv = CKR_OK;
- }
- }
- if (!noKeyDB) {
-
- crv = sftk_OpenKeyDB(configdir, keyPrefix, readOnly, keydbPtr);
- if (crv != CKR_OK) {
- if (!forceOpen) goto loser;
- crv = CKR_OK;
- }
- }
-
-
-loser:
- return crv;
-}
-
-NSSLOWCERTCertDBHandle *
-sftk_getCertDB(SFTKSlot *slot)
-{
- NSSLOWCERTCertDBHandle *certHandle;
-
- PZ_Lock(slot->slotLock);
- certHandle = slot->certDB;
- if (certHandle) {
- PR_AtomicIncrement(&certHandle->ref);
- }
- PZ_Unlock(slot->slotLock);
- return certHandle;
-}
-
-NSSLOWKEYDBHandle *
-sftk_getKeyDB(SFTKSlot *slot)
-{
- NSSLOWKEYDBHandle *keyHandle;
-
- PZ_Lock(slot->slotLock);
- keyHandle = slot->keyDB;
- if (keyHandle) {
- PR_AtomicIncrement(&keyHandle->ref);
- }
- PZ_Unlock(slot->slotLock);
- return keyHandle;
-}
-
-void
-sftk_freeCertDB(NSSLOWCERTCertDBHandle *certHandle)
-{
- PRInt32 ref = PR_AtomicDecrement(&certHandle->ref);
- if (ref == 0) {
- nsslowcert_ClosePermCertDB(certHandle);
- PORT_Free(certHandle);
- }
-}
-
-void
-sftk_freeKeyDB(NSSLOWKEYDBHandle *keyHandle)
-{
- PRInt32 ref = PR_AtomicDecrement(&keyHandle->ref);
- if (ref == 0) {
- nsslowkey_CloseKeyDB(keyHandle);
- }
-}
-
-
static int rdbmapflags(int flags);
-static rdbfunc sftk_rdbfunc = NULL;
-static rdbstatusfunc sftk_rdbstatusfunc = NULL;
+static rdbfunc lg_rdbfunc = NULL;
+static rdbstatusfunc lg_rdbstatusfunc = NULL;
/* NOTE: SHLIB_SUFFIX is defined on the command line */
#define RDBLIB SHLIB_PREFIX"rdb."SHLIB_SUFFIX
@@ -318,10 +155,10 @@ DB * rdbopen(const char *appName, const char *prefix,
PRLibrary *lib;
DB *db;
- if (sftk_rdbfunc) {
- db = (*sftk_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
- if (!db && status && sftk_rdbstatusfunc) {
- *status = (*sftk_rdbstatusfunc)();
+ if (lg_rdbfunc) {
+ db = (*lg_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
+ if (!db && status && lg_rdbstatusfunc) {
+ *status = (*lg_rdbstatusfunc)();
}
return db;
}
@@ -336,12 +173,12 @@ DB * rdbopen(const char *appName, const char *prefix,
}
/* get the entry points */
- sftk_rdbstatusfunc = (rdbstatusfunc) PR_FindFunctionSymbol(lib,"rdbstatus");
- sftk_rdbfunc = (rdbfunc) PR_FindFunctionSymbol(lib,"rdbopen");
- if (sftk_rdbfunc) {
- db = (*sftk_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
- if (!db && status && sftk_rdbstatusfunc) {
- *status = (*sftk_rdbstatusfunc)();
+ lg_rdbstatusfunc = (rdbstatusfunc) PR_FindSymbol(lib,"rdbstatus");
+ lg_rdbfunc = (rdbfunc) PR_FindSymbol(lib,"rdbopen");
+ if (lg_rdbfunc) {
+ db = (*lg_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
+ if (!db && status && lg_rdbstatusfunc) {
+ *status = (*lg_rdbstatusfunc)();
}
return db;
}
@@ -382,7 +219,6 @@ rdbmapflags(int flags) {
return 0;
}
-
PRBool
db_IsRDB(DB *db)
{
@@ -411,6 +247,71 @@ db_FinishTransaction(DB *db, PRBool abort)
return rdb->xactdone(db, abort);
}
+static DB *
+lg_getRawDB(SDB *sdb)
+{
+ NSSLOWCERTCertDBHandle *certDB;
+ NSSLOWKEYDBHandle *keyDB;
+
+ certDB = lg_getCertDB(sdb);
+ if (certDB) {
+ return certDB->permCertDB;
+ }
+ keyDB = lg_getKeyDB(sdb);
+ if (keyDB) {
+ return keyDB->db;
+ }
+ return NULL;
+}
+
+CK_RV
+lg_Begin(SDB *sdb)
+{
+ DB *db = lg_getRawDB(sdb);
+ int ret;
+
+ if (db == NULL) {
+ return CKR_GENERAL_ERROR; /* shouldn't happen */
+ }
+ ret = db_BeginTransaction(db);
+ if (ret != 0) {
+ return CKR_GENERAL_ERROR; /* could happen */
+ }
+ return CKR_OK;
+}
+
+CK_RV
+lg_Commit(SDB *sdb)
+{
+ DB *db = lg_getRawDB(sdb);
+ int ret;
+
+ if (db == NULL) {
+ return CKR_GENERAL_ERROR; /* shouldn't happen */
+ }
+ ret = db_FinishTransaction(db, PR_FALSE);
+ if (ret != 0) {
+ return CKR_GENERAL_ERROR; /* could happen */
+ }
+ return CKR_OK;
+}
+
+CK_RV
+lg_Abort(SDB *sdb)
+{
+ DB *db = lg_getRawDB(sdb);
+ int ret;
+
+ if (db == NULL) {
+ return CKR_GENERAL_ERROR; /* shouldn't happen */
+ }
+ ret = db_FinishTransaction(db, PR_TRUE);
+ if (ret != 0) {
+ return CKR_GENERAL_ERROR; /* could happen */
+ }
+ return CKR_OK;
+}
+
int
db_InitComplete(DB *db)
{
@@ -418,10 +319,10 @@ db_InitComplete(DB *db)
if (db->type != DB_RDB) {
return 0;
}
- /* we should have addes a version number to the RDBS structure. Since we
+ /* we should have added a version number to the RDBS structure. Since we
* didn't, we detect that we have and 'extended' structure if the rdbstatus
* func exists */
- if (!sftk_rdbstatusfunc) {
+ if (!lg_rdbstatusfunc) {
return 0;
}
@@ -448,3 +349,296 @@ db_Copy(DB *dest,DB *src)
return SECSuccess;
}
+
+static CK_RV
+lg_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly,
+ NSSLOWCERTCertDBHandle **certdbPtr)
+{
+ NSSLOWCERTCertDBHandle *certdb = NULL;
+ CK_RV crv = CKR_NETSCAPE_CERTDB_FAILED;
+ SECStatus rv;
+ char * name = NULL;
+ char * appName = NULL;
+
+ if (prefix == NULL) {
+ prefix = "";
+ }
+
+ configdir = lg_EvaluateConfigDir(configdir, &appName);
+
+ name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
+ if (name == NULL) goto loser;
+
+ certdb = (NSSLOWCERTCertDBHandle*)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle));
+ if (certdb == NULL)
+ goto loser;
+
+ certdb->ref = 1;
+/* fix when we get the DB in */
+ rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix,
+ lg_certdb_name_cb, (void *)name, PR_FALSE);
+ if (rv == SECSuccess) {
+ crv = CKR_OK;
+ *certdbPtr = certdb;
+ certdb = NULL;
+ }
+loser:
+ if (certdb) PR_Free(certdb);
+ if (name) PR_smprintf_free(name);
+ if (appName) PORT_Free(appName);
+ return crv;
+}
+
+static CK_RV
+lg_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly,
+ NSSLOWKEYDBHandle **keydbPtr)
+{
+ NSSLOWKEYDBHandle *keydb;
+ char * name = NULL;
+ char * appName = NULL;
+
+ if (prefix == NULL) {
+ prefix = "";
+ }
+ configdir = lg_EvaluateConfigDir(configdir, &appName);
+
+ name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
+ if (name == NULL)
+ return CKR_HOST_MEMORY;
+ keydb = nsslowkey_OpenKeyDB(readOnly, appName, prefix,
+ lg_keydb_name_cb, (void *)name);
+ PR_smprintf_free(name);
+ if (appName) PORT_Free(appName);
+ if (keydb == NULL)
+ return CKR_NETSCAPE_KEYDB_FAILED;
+ *keydbPtr = keydb;
+
+ return CKR_OK;
+}
+
+/*
+ * Accessors for the private parts of the sdb structure.
+ */
+void
+lg_DBLock(SDB *sdb)
+{
+ LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
+ PR_Lock(lgdb_p->dbLock);
+}
+
+void
+lg_DBUnlock(SDB *sdb)
+{
+ LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
+ PR_Unlock(lgdb_p->dbLock);
+}
+
+PLHashTable *
+lg_GetHashTable(SDB *sdb)
+{
+ LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
+ return lgdb_p->hashTable;
+}
+
+NSSLOWCERTCertDBHandle *
+lg_getCertDB(SDB *sdb)
+{
+ LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
+
+ return lgdb_p->certDB;
+}
+
+NSSLOWKEYDBHandle *
+lg_getKeyDB(SDB *sdb)
+{
+ LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
+
+ return lgdb_p->keyDB;
+}
+
+CK_RV
+lg_Close(SDB *sdb)
+{
+ LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
+ if (lgdb_p) {
+ if (lgdb_p->certDB) {
+ nsslowcert_ClosePermCertDB(lgdb_p->certDB);
+ } else if (lgdb_p->keyDB) {
+ nsslowkey_CloseKeyDB(lgdb_p->keyDB);
+ }
+ if (lgdb_p->dbLock) {
+ PR_DestroyLock(lgdb_p->dbLock);
+ }
+ if (lgdb_p->hashTable) {
+ PL_HashTableDestroy(lgdb_p->hashTable);
+ }
+ PORT_Free(lgdb_p);
+ }
+ PORT_Free(sdb);
+ return CKR_OK;
+}
+
+static PLHashNumber
+lg_HashNumber(const void *key)
+{
+ return (PLHashNumber) key;
+}
+
+
+/*
+ * helper function to wrap a NSSLOWCERTCertDBHandle or a NSSLOWKEYDBHandle
+ * with and sdb structure.
+ */
+CK_RV
+lg_init(SDB **pSdb, int flags, NSSLOWCERTCertDBHandle *certdbPtr,
+ NSSLOWKEYDBHandle *keydbPtr)
+{
+ SDB *sdb = NULL;
+ LGPrivate *lgdb_p = NULL;
+ CK_RV error = CKR_HOST_MEMORY;
+
+ *pSdb = NULL;
+ sdb = (SDB *) PORT_Alloc(sizeof(SDB));
+ if (sdb == NULL) {
+ goto loser;
+ }
+ lgdb_p = (LGPrivate *) PORT_Alloc(sizeof(LGPrivate));
+ if (lgdb_p == NULL) {
+ goto loser;
+ }
+ /* invariant fields */
+ lgdb_p->certDB = certdbPtr;
+ lgdb_p->keyDB = keydbPtr;
+ lgdb_p->dbLock = PR_NewLock();
+ if (lgdb_p->dbLock == NULL) {
+ goto loser;
+ }
+ lgdb_p->hashTable = PL_NewHashTable(64, lg_HashNumber, PL_CompareValues,
+ SECITEM_HashCompare, NULL, 0);
+ if (lgdb_p->hashTable == NULL) {
+ goto loser;
+ }
+
+ sdb->sdb_type = SDB_LEGACY;
+ sdb->sdb_flags = flags;
+ sdb->private = lgdb_p;
+ sdb->sdb_FindObjectsInit = lg_FindObjectsInit;
+ sdb->sdb_FindObjects = lg_FindObjects;
+ sdb->sdb_FindObjectsFinal = lg_FindObjectsFinal;
+ sdb->sdb_GetAttributeValue = lg_GetAttributeValue;
+ sdb->sdb_SetAttributeValue = lg_SetAttributeValue;
+ sdb->sdb_CreateObject = lg_CreateObject;
+ sdb->sdb_DestroyObject = lg_DestroyObject;
+ sdb->sdb_GetPWEntry = lg_GetPWEntry;
+ sdb->sdb_PutPWEntry = lg_PutPWEntry;
+ sdb->sdb_Begin = lg_Begin;
+ sdb->sdb_Commit = lg_Commit;
+ sdb->sdb_Abort = lg_Abort;
+ sdb->sdb_Close = lg_Reset;
+ sdb->sdb_Close = lg_Close;
+
+
+ *pSdb = sdb;
+ return CKR_OK;
+
+loser:
+ if (sdb) {
+ PORT_Free(sdb);
+ }
+ if (lgdb_p) {
+ if (lgdb_p->dbLock) {
+ PR_DestroyLock(lgdb_p->dbLock);
+ }
+ if (lgdb_p->hashTable) {
+ PL_HashTableDestroy(lgdb_p->hashTable);
+ }
+ PORT_Free(lgdb_p);
+ }
+ return error;
+
+}
+
+extern SECStatus secoid_Init(void); /* util *REALLY* needs
+ * to be a shared library */
+/*
+ * OK there are now lots of options here, lets go through them all:
+ *
+ * configdir - base directory where all the cert, key, and module datbases live.
+ * certPrefix - prefix added to the beginning of the cert database example: "
+ * "https-server1-"
+ * keyPrefix - prefix added to the beginning of the key database example: "
+ * "https-server1-"
+ * secmodName - name of the security module database (usually "secmod.db").
+ * readOnly - Boolean: true if the databases are to be openned read only.
+ * nocertdb - Don't open the cert DB and key DB's, just initialize the
+ * Volatile certdb.
+ * nomoddb - Don't open the security module DB, just initialize the
+ * PKCS #11 module.
+ * forceOpen - Continue to force initializations even if the databases cannot
+ * be opened.
+ */
+CK_RV
+legacy_Open(const char *configdir, const char *certPrefix,
+ const char *keyPrefix, int certVersion, int keyVersion,
+ int flags, SDB **certDB, SDB **keyDB)
+{
+ CK_RV crv = CKR_OK;
+ PRBool readOnly = (flags == SDB_RDONLY)? PR_TRUE: PR_FALSE;
+
+ secoid_Init();
+ nsslowcert_InitLocks();
+
+ if (keyDB) *keyDB = NULL;
+ if (certDB) *certDB = NULL;
+
+ if (certDB) {
+ NSSLOWCERTCertDBHandle *certdbPtr;
+
+ crv = lg_OpenCertDB(configdir, certPrefix, readOnly, &certdbPtr);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ crv = lg_init(certDB, flags, certdbPtr, NULL);
+ if (crv != CKR_OK) {
+ nsslowcert_ClosePermCertDB(certdbPtr);
+ goto loser;
+ }
+ }
+ if (keyDB) {
+ NSSLOWKEYDBHandle *keydbPtr;
+
+ crv = lg_OpenKeyDB(configdir, keyPrefix, readOnly, &keydbPtr);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ crv = lg_init(keyDB, flags, NULL, keydbPtr);
+ if (crv != CKR_OK) {
+ nsslowkey_CloseKeyDB(keydbPtr);
+ goto loser;
+ }
+ if (certDB && *certDB) {
+ LGPrivate *lgdb_p = (LGPrivate *)(*certDB)->private;
+ lgdb_p->keyDB = keydbPtr;
+ }
+ }
+
+loser:
+ if (crv != CKR_OK) {
+ if (keyDB && *keyDB) {
+ lg_Close(*keyDB);
+ *keyDB = NULL;
+ }
+ if (certDB && *certDB) {
+ lg_Close(*certDB);
+ *certDB = NULL;
+ }
+ }
+ return crv;
+}
+
+CK_RV
+legacy_Shutdown(void)
+{
+ nsslowcert_DestroyFreeLists();
+ nsslowcert_DestroyGlobalLocks();
+}
diff --git a/security/nss/lib/softoken/legacydb/lgutil.c b/security/nss/lib/softoken/legacydb/lgutil.c
new file mode 100644
index 000000000..3df08de09
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lgutil.c
@@ -0,0 +1,424 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "lgdb.h"
+#include "secerr.h"
+#include "lgglue.h"
+
+/*
+ * ******************** Attribute Utilities *******************************
+ */
+
+/*
+ * look up and attribute structure from a type and Object structure.
+ * The returned attribute is referenced and needs to be freed when
+ * it is no longer needed.
+ */
+const CK_ATTRIBUTE *
+lg_FindAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
+ CK_ULONG count )
+{
+ int i;
+
+ for (i=0; i < count; i++) {
+ if (templ[i].type == type) {
+ return &templ[i];
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ * return true if object has attribute
+ */
+PRBool
+lg_hasAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
+ CK_ULONG count )
+{
+ if (lg_FindAttribute(type, templ, count) == NULL) {
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+/*
+ * copy an attribute into a SECItem. Secitem is allocated in the specified
+ * arena.
+ */
+CK_RV
+lg_Attribute2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count,
+ SECItem *item)
+{
+ int len;
+ const CK_ATTRIBUTE *attribute;
+
+ attribute = lg_FindAttribute(type, templ, count);
+ if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
+ len = attribute->ulValueLen;
+
+ if (arena) {
+ item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
+ } else {
+ item->data = (unsigned char *) PORT_Alloc(len);
+ }
+ if (item->data == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ item->len = len;
+ PORT_Memcpy(item->data, attribute->pValue, len);
+ return CKR_OK;
+}
+
+
+/*
+ * copy an unsigned attribute into a SECItem. Secitem is allocated in
+ * the specified arena.
+ */
+CK_RV
+lg_Attribute2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count,
+ SECItem *item)
+{
+ const CK_ATTRIBUTE *attribute;
+ item->data = NULL;
+
+ attribute = lg_FindAttribute(type, templ, count);
+ if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
+
+ (void)SECITEM_AllocItem(arena, item, attribute->ulValueLen);
+ if (item->data == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ PORT_Memcpy(item->data, attribute->pValue, item->len);
+ return CKR_OK;
+}
+
+/*
+ * copy an unsigned attribute into a SECItem. Secitem is allocated in
+ * the specified arena.
+ */
+CK_RV
+lg_PrivAttr2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count,
+ SECItem *item, SDB *sdbpw)
+{
+ const CK_ATTRIBUTE *attribute;
+ SECItem epki, *dest = NULL;
+ SECStatus rv;
+
+ item->data = NULL;
+
+ attribute = lg_FindAttribute(type, templ, count);
+ if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
+
+ epki.data = attribute->pValue;
+ epki.len = attribute->ulValueLen;
+
+ rv = lg_util_decrypt(sdbpw, &epki, &dest);
+ if (rv != SECSuccess) {
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+ (void)SECITEM_AllocItem(arena, item, dest->len);
+ if (item->data == NULL) {
+ SECITEM_FreeItem(dest, PR_TRUE);
+ return CKR_HOST_MEMORY;
+ }
+
+ PORT_Memcpy(item->data, dest->data, item->len);
+ SECITEM_FreeItem(dest, PR_TRUE);
+ return CKR_OK;
+}
+
+CK_RV
+lg_PrivAttr2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
+ const CK_ATTRIBUTE *templ, CK_ULONG count,
+ SECItem *item, SDB *sdbpw)
+{
+ return lg_PrivAttr2SSecItem(arena, type, templ, count, item, sdbpw);
+}
+
+/*
+ * this is only valid for CK_BBOOL type attributes. Return the state
+ * of that attribute.
+ */
+PRBool
+lg_isTrue(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ const CK_ATTRIBUTE *attribute;
+ PRBool tok = PR_FALSE;
+
+ attribute=lg_FindAttribute(type, templ, count);
+ if (attribute == NULL) { return PR_FALSE; }
+ tok = (PRBool)(*(CK_BBOOL *)attribute->pValue);
+
+ return tok;
+}
+
+/*
+ * return a null terminated string from attribute 'type'. This string
+ * is allocated and needs to be freed with PORT_Free() When complete.
+ */
+char *
+lg_getString(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
+{
+ const CK_ATTRIBUTE *attribute;
+ char *label = NULL;
+
+ attribute = lg_FindAttribute(type, templ, count);
+ if (attribute == NULL) return NULL;
+
+ if (attribute->pValue != NULL) {
+ label = (char *) PORT_Alloc(attribute->ulValueLen+1);
+ if (label == NULL) {
+ return NULL;
+ }
+
+ PORT_Memcpy(label,attribute->pValue, attribute->ulValueLen);
+ label[attribute->ulValueLen] = 0;
+ }
+ return label;
+}
+
+CK_RV
+lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
+ CK_ULONG count, CK_ULONG *longData)
+{
+ const CK_ATTRIBUTE *attribute;
+ CK_ULONG value = 0;
+ const unsigned char *data;
+ int i;
+
+ attribute = lg_FindAttribute(type, templ, count);
+ if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
+
+ if (attribute->ulValueLen != sizeof(CK_ULONG)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ data = (const unsigned char *)attribute->pValue;
+ for (i=0; i < 4; i++) {
+ value |= (CK_ULONG)(data[i]) << ((3-i)*8);
+ }
+
+ *longData = value;
+ return CKR_OK;
+}
+
+/*
+ * ******************** Object Utilities *******************************
+ */
+
+SECStatus
+lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
+{
+ SECItem *item;
+ PRBool rem;
+ PLHashTable *hashTable= lg_GetHashTable(sdb);
+
+ item = (SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
+ rem = PL_HashTableRemove(hashTable,(void *)handle) ;
+ if (rem && item) {
+ SECITEM_FreeItem(item,PR_TRUE);
+ }
+ return rem ? SECSuccess : SECFailure;
+}
+
+/* must be called holding lg_DBLock(sdb) */
+static SECStatus
+lg_addTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle, SECItem *key)
+{
+ PLHashEntry *entry;
+ SECItem *item;
+ PLHashTable *hashTable= lg_GetHashTable(sdb);
+
+ item = SECITEM_DupItem(key);
+ if (item == NULL) {
+ return SECFailure;
+ }
+ entry = PL_HashTableAdd(hashTable,(void *)handle,item);
+ if (entry == NULL) {
+ SECITEM_FreeItem(item,PR_TRUE);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/* must be called holding lg_DBLock(sdb) */
+const SECItem *
+lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
+{
+ PLHashTable *hashTable= lg_GetHashTable(sdb);
+ return (const SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
+}
+
+
+static PRIntn
+lg_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
+{
+ SECItem *item = (SECItem *)entry->value;
+
+ SECITEM_FreeItem(item, PR_TRUE);
+ return HT_ENUMERATE_NEXT;
+}
+
+CK_RV
+LG_ClearTokenKeyHashTable(SDB *sdb)
+{
+ PLHashTable *hashTable;
+ lg_DBLock(sdb);
+ hashTable= lg_GetHashTable(sdb);
+ PL_HashTableEnumerateEntries(hashTable, lg_freeHashItem, NULL);
+ lg_DBLock(sdb);
+ return CKR_OK;
+}
+
+/*
+ * handle Token Object stuff
+ */
+static void
+lg_XORHash(unsigned char *key, unsigned char *dbkey, int len)
+{
+ int i;
+
+ PORT_Memset(key, 0, 4);
+
+ for (i=0; i < len-4; i += 4) {
+ key[0] ^= dbkey[i];
+ key[1] ^= dbkey[i+1];
+ key[2] ^= dbkey[i+2];
+ key[3] ^= dbkey[i+3];
+ }
+}
+
+/* Make a token handle for an object and record it so we can find it again */
+CK_OBJECT_HANDLE
+lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
+{
+ unsigned char hashBuf[4];
+ CK_OBJECT_HANDLE handle;
+ const SECItem *key;
+
+ handle = class;
+ /* there is only one KRL, use a fixed handle for it */
+ if (handle != LG_TOKEN_KRL_HANDLE) {
+ lg_XORHash(hashBuf,dbKey->data,dbKey->len);
+ handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
+ (hashBuf[2] << 8) | hashBuf[3];
+ handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
+ /* we have a CRL who's handle has randomly matched the reserved KRL
+ * handle, increment it */
+ if (handle == LG_TOKEN_KRL_HANDLE) {
+ handle++;
+ }
+ }
+
+ lg_DBLock(sdb);
+ while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
+ if (SECITEM_ItemsAreEqual(key,dbKey)) {
+ lg_DBUnlock(sdb);
+ return handle;
+ }
+ handle++;
+ }
+ lg_addTokenKeyByHandle(sdb,handle,dbKey);
+ lg_DBUnlock(sdb);
+ return handle;
+}
+
+PRBool
+lg_poisonHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
+{
+ unsigned char hashBuf[4];
+ CK_OBJECT_HANDLE handle;
+ const SECItem *key;
+
+ handle = class;
+ /* there is only one KRL, use a fixed handle for it */
+ if (handle != LG_TOKEN_KRL_HANDLE) {
+ lg_XORHash(hashBuf,dbKey->data,dbKey->len);
+ handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
+ (hashBuf[2] << 8) | hashBuf[3];
+ handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
+ /* we have a CRL who's handle has randomly matched the reserved KRL
+ * handle, increment it */
+ if (handle == LG_TOKEN_KRL_HANDLE) {
+ handle++;
+ }
+ }
+ lg_DBLock(sdb);
+ while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
+ if (SECITEM_ItemsAreEqual(key,dbKey)) {
+ key->data[0] ^= 0x80;
+ lg_DBUnlock(sdb);
+ return PR_TRUE;
+ }
+ handle++;
+ }
+ lg_DBUnlock(sdb);
+ return PR_FALSE;
+}
+
+static LGEncryptFunc lg_encrypt_stub = NULL;
+static LGDecryptFunc lg_decrypt_stub = NULL;
+
+void
+legacy_SetCryptFunctions(LGEncryptFunc enc, LGDecryptFunc dec)
+{
+ lg_encrypt_stub = enc;
+ lg_decrypt_stub = dec;
+}
+
+SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdb,
+ SECItem *plainText, SECItem **cipherText)
+{
+ if (lg_encrypt_stub == NULL) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ return (*lg_encrypt_stub)(arena, sdb, plainText, cipherText);
+}
+
+SECStatus lg_util_decrypt(SDB *sdb, SECItem *cipherText, SECItem **plainText)
+{
+ if (lg_decrypt_stub == NULL) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ return (*lg_decrypt_stub)(sdb, cipherText, plainText);
+}
+
+
diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/legacydb/lowcert.c
index 008687e52..6aa7e0960 100644
--- a/security/nss/lib/softoken/lowcert.c
+++ b/security/nss/lib/softoken/legacydb/lowcert.c
@@ -44,15 +44,11 @@
#include "seccomon.h"
#include "secder.h"
#include "nssilock.h"
-#include "prmon.h"
-#include "prtime.h"
#include "lowkeyi.h"
-#include "pcert.h"
#include "secasn1.h"
#include "secoid.h"
#include "secerr.h"
-#include "softoken.h"
-
+#include "pcert.h"
static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
@@ -112,26 +108,6 @@ prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
}
/*
- * Allow use of default cert database, so that apps(such as mozilla) don't
- * have to pass the handle all over the place.
- */
-static NSSLOWCERTCertDBHandle *default_pcert_db_handle = 0;
-
-void
-nsslowcert_SetDefaultCertDB(NSSLOWCERTCertDBHandle *handle)
-{
- default_pcert_db_handle = handle;
-
- return;
-}
-
-NSSLOWCERTCertDBHandle *
-nsslowcert_GetDefaultCertDB(void)
-{
- return(default_pcert_db_handle);
-}
-
-/*
* simple cert decoder to avoid the cost of asn1 engine
*/
static unsigned char *
@@ -211,7 +187,7 @@ nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
static int
nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
- SECItem *valid, SECItem *subjkey)
+ SECItem *valid, SECItem *subjkey, SECItem *extensions)
{
unsigned char *buf;
unsigned int buf_length;
@@ -269,10 +245,25 @@ nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
if (subjkey->data == NULL) return SECFailure;
buf_length -= (subjkey->data-buf) + subjkey->len;
buf = subjkey->data + subjkey->len;
+
+ extensions->data = NULL;
+ extensions->len = 0;
+ while (buf_length > 0) {
+ /* EXTENSIONS */
+ if (buf[0] == 0xa3) {
+ extensions->data = nsslowcert_dataStart(buf,buf_length,
+ &extensions->len, PR_FALSE, NULL);
+ break;
+ }
+ dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE,NULL);
+ if (dummy == NULL) return SECFailure;
+ buf_length -= (dummy - buf) + dummylen;
+ buf = dummy + dummylen;
+ }
return SECSuccess;
}
-SECStatus
+static SECStatus
nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
{
int rv;
@@ -412,6 +403,196 @@ loser:
}
+static char *
+nsslowcert_EmailName(SECItem *derDN, char *space, unsigned int len)
+{
+ unsigned char *buf;
+ unsigned int buf_length;
+
+ /* unwrap outer sequence */
+ buf=nsslowcert_dataStart(derDN->data,derDN->len,&buf_length,PR_FALSE,NULL);
+ if (buf == NULL) return NULL;
+
+ /* Walk each RDN */
+ while (buf_length > 0) {
+ unsigned char *rdn;
+ unsigned int rdn_length;
+
+ /* grab next rdn */
+ rdn=nsslowcert_dataStart(buf, buf_length, &rdn_length, PR_FALSE, NULL);
+ if (rdn == NULL) { return NULL; }
+ buf_length -= (rdn - buf) + rdn_length;
+ buf = rdn+rdn_length;
+
+ while (rdn_length > 0) {
+ unsigned char *ava;
+ unsigned int ava_length;
+ unsigned char *oid;
+ unsigned int oid_length;
+ unsigned char *name;
+ unsigned int name_length;
+ SECItem oidItem;
+ SECOidTag type;
+
+ /* unwrap the ava */
+ ava=nsslowcert_dataStart(rdn, rdn_length, &ava_length, PR_FALSE,
+ NULL);
+ if (ava == NULL) return NULL;
+ rdn_length -= (ava-rdn)+ava_length;
+ rdn = ava + ava_length;
+
+ oid=nsslowcert_dataStart(ava, ava_length, &oid_length, PR_FALSE,
+ NULL);
+ if (oid == NULL) { return NULL; }
+ ava_length -= (oid-ava)+oid_length;
+ ava = oid+oid_length;
+
+ name=nsslowcert_dataStart(ava, ava_length, &name_length, PR_FALSE,
+ NULL);
+ if (oid == NULL) { return NULL; }
+ ava_length -= (name-ava)+name_length;
+ ava = name+name_length;
+
+ oidItem.data = oid;
+ oidItem.len = oid_length;
+ type = SECOID_FindOIDTag(&oidItem);
+ if ((type == SEC_OID_PKCS9_EMAIL_ADDRESS) ||
+ (type == SEC_OID_RFC1274_MAIL)) {
+ /* Email is supposed to be IA5String, so no
+ * translation necessary */
+ char *emailAddr;
+ emailAddr = (char *)pkcs11_copyStaticData(name,name_length+1,
+ (unsigned char *)space,len);
+ if (emailAddr) {
+ emailAddr[name_length] = 0;
+ }
+ return emailAddr;
+ }
+ }
+ }
+ return NULL;
+}
+
+static char *
+nsslowcert_EmailAltName(NSSLOWCERTCertificate *cert, char *space,
+ unsigned int len)
+{
+ unsigned char *exts;
+ unsigned int exts_length;
+
+ /* unwrap the sequence */
+ exts = nsslowcert_dataStart(cert->extensions.data, cert->extensions.len,
+ &exts_length, PR_FALSE, NULL);
+ /* loop through extension */
+ while (exts && exts_length > 0) {
+ unsigned char * ext;
+ unsigned int ext_length;
+ unsigned char *oid;
+ unsigned int oid_length;
+ unsigned char *nameList;
+ unsigned int nameList_length;
+ SECItem oidItem;
+ SECOidTag type;
+
+ ext = nsslowcert_dataStart(exts, exts_length, &ext_length,
+ PR_FALSE, NULL);
+ if (ext == NULL) { break; }
+ exts_length -= (ext - exts) + ext_length;
+ exts = ext+ext_length;
+
+ oid=nsslowcert_dataStart(ext, ext_length, &oid_length, PR_FALSE, NULL);
+ if (oid == NULL) { break; }
+ ext_length -= (oid - ext) + oid_length;
+ ext = oid+oid_length;
+ oidItem.data = oid;
+ oidItem.len = oid_length;
+ type = SECOID_FindOIDTag(&oidItem);
+
+ /* get Alt Extension */
+ if (type != SEC_OID_X509_SUBJECT_ALT_NAME) {
+ continue;
+ }
+
+ /* skip passed the critical flag */
+ if (ext[0] == 0x01) { /* BOOLEAN */
+ unsigned char *dummy;
+ unsigned int dummy_length;
+ dummy = nsslowcert_dataStart(ext, ext_length, &dummy_length,
+ PR_FALSE, NULL);
+ if (dummy == NULL) { break; }
+ ext_length -= (dummy - ext) + dummy_length;
+ ext = dummy+dummy_length;
+ }
+
+
+ /* unwrap the name list */
+ nameList = nsslowcert_dataStart(ext, ext_length, &nameList_length,
+ PR_FALSE, NULL);
+ if (nameList == NULL) { break; }
+ ext_length -= (nameList - ext) + nameList_length;
+ ext = nameList+nameList_length;
+ nameList = nsslowcert_dataStart(nameList, nameList_length,
+ &nameList_length, PR_FALSE, NULL);
+ /* loop through the name list */
+ while (nameList && nameList_length > 0) {
+ unsigned char *thisName;
+ unsigned int thisName_length;
+
+ thisName = nsslowcert_dataStart(nameList, nameList_length,
+ &thisName_length, PR_FALSE, NULL);
+ if (thisName == NULL) { break; }
+ if (nameList[0] == 0xa2) { /* DNS Name */
+ SECItem dn;
+ char *emailAddr;
+
+ dn.data = thisName;
+ dn.len = thisName_length;
+ emailAddr = nsslowcert_EmailName(&dn, space, len);
+ if (emailAddr) {
+ return emailAddr;
+ }
+ }
+ if (nameList[0] == 0x81) { /* RFC 822name */
+ char *emailAddr;
+ emailAddr = (char *)pkcs11_copyStaticData(thisName,
+ thisName_length+1, (unsigned char *)space,len);
+ if (emailAddr) {
+ emailAddr[thisName_length] = 0;
+ }
+ return emailAddr;
+ }
+ nameList_length -= (thisName-nameList) + thisName_length;
+ nameList = thisName + thisName_length;
+ }
+ break;
+ }
+ return NULL;
+}
+
+static char *
+nsslowcert_GetCertificateEmailAddress(NSSLOWCERTCertificate *cert)
+{
+ char *emailAddr = NULL;
+ char *str;
+
+ emailAddr = nsslowcert_EmailName(&cert->derSubject,cert->emailAddrSpace,
+ sizeof(cert->emailAddrSpace));
+ /* couldn't find the email address in the DN, check the subject Alt name */
+ if (!emailAddr && cert->extensions.data) {
+ emailAddr = nsslowcert_EmailAltName(cert, cert->emailAddrSpace,
+ sizeof(cert->emailAddrSpace));
+ }
+
+
+ /* make it lower case */
+ str = emailAddr;
+ while ( str && *str ) {
+ *str = tolower( *str );
+ str++;
+ }
+ return emailAddr;
+
+}
/*
* take a DER certificate and decode it into a certificate structure
@@ -438,7 +619,7 @@ nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
/* decode the certificate info */
rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
&cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
- &cert->validity, &cert->derSubjKeyInfo);
+ &cert->validity, &cert->derSubjKeyInfo, &cert->extensions);
/* cert->subjectKeyID; x509v3 subject key identifier */
cert->subjectKeyID.data = NULL;
@@ -470,11 +651,11 @@ nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
if ( rv != SECSuccess ) {
goto loser;
}
+#endif
/* set the email address */
- cert->emailAddr = CERT_GetCertificateEmailAddress(cert);
+ cert->emailAddr = nsslowcert_GetCertificateEmailAddress(cert);
-#endif
cert->referenceCount = 1;
@@ -527,7 +708,8 @@ nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
- &certkey.derIssuer, &certkey.serialNumber, NULL, NULL, NULL, NULL);
+ &certkey.derIssuer, &certkey.serialNumber, NULL, NULL,
+ NULL, NULL, NULL);
if ( rv ) {
goto loser;
@@ -623,7 +805,7 @@ nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
/* Fill out the rest of the ecParams structure
* based on the encoded params
*/
- if (EC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
+ if (LGEC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
&pubk->u.ec.ecParams) != SECSuccess)
break;
diff --git a/security/nss/lib/softoken/legacydb/lowkey.c b/security/nss/lib/softoken/legacydb/lowkey.c
new file mode 100644
index 000000000..c9ed72e53
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lowkey.c
@@ -0,0 +1,462 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "lowkeyi.h"
+#include "secoid.h"
+#include "secitem.h"
+#include "secder.h"
+#include "secasn1.h"
+#include "secerr.h"
+
+static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWKEYAttribute) },
+ { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
+ { SEC_ASN1_SET_OF, offsetof(NSSLOWKEYAttribute, attrValue),
+ SEC_AnyTemplate },
+ { 0 }
+};
+
+static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
+};
+/* ASN1 Templates for new decoder/encoder */
+const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
+ { SEC_ASN1_INTEGER,
+ offsetof(NSSLOWKEYPrivateKeyInfo,version) },
+ { SEC_ASN1_INLINE,
+ offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
+ SECOID_AlgorithmIDTemplate },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+ offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
+ nsslowkey_SetOfAttributeTemplate },
+ { 0 }
+};
+
+const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
+ { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
+ { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
+ { SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
+ { 0, }
+};
+
+const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
+ { 0 }
+};
+
+
+const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
+ { 0, }
+};
+
+const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
+};
+
+const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) },
+ { 0, }
+};
+
+#ifdef NSS_ENABLE_ECC
+
+/* XXX This is just a placeholder for later when we support
+ * generic curves and need full-blown support for parsing EC
+ * parameters. For now, we only support named curves in which
+ * EC params are simply encoded as an object ID and we don't
+ * use nsslowkey_ECParamsTemplate.
+ */
+const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = {
+ { SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
+ { SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
+ { 0, }
+};
+
+
+/* NOTE: The SECG specification allows the private key structure
+ * to contain curve parameters but recommends that they be stored
+ * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
+ * instead.
+ */
+const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
+ /* XXX The following template works for now since we only
+ * support named curves for which the parameters are
+ * encoded as an object ID. When we support generic curves,
+ * we'll need to define nsslowkey_ECParamsTemplate
+ */
+#if 1
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+ offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID),
+ SEC_ObjectIDTemplate },
+#else
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+ offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams),
+ nsslowkey_ECParamsTemplate },
+#endif
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1,
+ offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
+ SEC_BitStringTemplate },
+ { 0, }
+};
+
+
+/*
+ * smaller version of EC_FillParams. In this code, we only need
+ * oid and DER data.
+ */
+SECStatus
+LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
+ ECParams *params)
+{
+ SECOidTag tag;
+ SECItem oid = { siBuffer, NULL, 0};
+
+#if EC_DEBUG
+ int i;
+
+ printf("Encoded params in EC_DecodeParams: ");
+ for (i = 0; i < encodedParams->len; i++) {
+ printf("%02x:", encodedParams->data[i]);
+ }
+ printf("\n");
+#endif
+
+ oid.len = encodedParams->len - 2;
+ oid.data = encodedParams->data + 2;
+ if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
+ ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+ return SECFailure;
+ }
+
+ params->arena = arena;
+
+ /* For named curves, fill out curveOID */
+ params->curveOID.len = oid.len;
+ params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
+ if (params->curveOID.data == NULL) {
+ return SECFailure;
+ }
+ memcpy(params->curveOID.data, oid.data, oid.len);
+
+ return SECSuccess;
+}
+
+/* Copy all of the fields from srcParams into dstParams
+ */
+SECStatus
+LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams)
+{
+ SECStatus rv = SECFailure;
+
+ dstParams->arena = arena;
+ rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding,
+ &srcParams->DEREncoding);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ rv =SECITEM_CopyItem(arena, &dstParams->curveOID,
+ &srcParams->curveOID);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ return SECSuccess;
+
+loser:
+ return SECFailure;
+}
+#endif /* NSS_ENABLE_ECC */
+/*
+ * See bugzilla bug 125359
+ * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
+ * all of the templates above that en/decode into integers must be converted
+ * from ASN.1's signed integer type. This is done by marking either the
+ * source or destination (encoding or decoding, respectively) type as
+ * siUnsignedInteger.
+ */
+
+void
+prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.rsa.modulus.type = siUnsignedInteger;
+ key->u.rsa.publicExponent.type = siUnsignedInteger;
+ key->u.rsa.privateExponent.type = siUnsignedInteger;
+ key->u.rsa.prime1.type = siUnsignedInteger;
+ key->u.rsa.prime2.type = siUnsignedInteger;
+ key->u.rsa.exponent1.type = siUnsignedInteger;
+ key->u.rsa.exponent2.type = siUnsignedInteger;
+ key->u.rsa.coefficient.type = siUnsignedInteger;
+}
+
+void
+prepare_low_pqg_params_for_asn1(PQGParams *params)
+{
+ params->prime.type = siUnsignedInteger;
+ params->subPrime.type = siUnsignedInteger;
+ params->base.type = siUnsignedInteger;
+}
+
+void
+prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.dsa.publicValue.type = siUnsignedInteger;
+ key->u.dsa.privateValue.type = siUnsignedInteger;
+ key->u.dsa.params.prime.type = siUnsignedInteger;
+ key->u.dsa.params.subPrime.type = siUnsignedInteger;
+ key->u.dsa.params.base.type = siUnsignedInteger;
+}
+
+void
+prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.dsa.privateValue.type = siUnsignedInteger;
+}
+
+void
+prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.dh.prime.type = siUnsignedInteger;
+ key->u.dh.base.type = siUnsignedInteger;
+ key->u.dh.publicValue.type = siUnsignedInteger;
+ key->u.dh.privateValue.type = siUnsignedInteger;
+}
+
+#ifdef NSS_ENABLE_ECC
+void
+prepare_low_ecparams_for_asn1(ECParams *params)
+{
+ params->DEREncoding.type = siUnsignedInteger;
+ params->curveOID.type = siUnsignedInteger;
+}
+
+void
+prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.ec.version.type = siUnsignedInteger;
+ key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
+ key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
+ key->u.ec.privateValue.type = siUnsignedInteger;
+ key->u.ec.publicValue.type = siUnsignedInteger;
+}
+#endif /* NSS_ENABLE_ECC */
+
+void
+nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
+{
+ if (privk && privk->arena) {
+ PORT_FreeArena(privk->arena, PR_TRUE);
+ }
+}
+
+void
+nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
+{
+ if (pubk && pubk->arena) {
+ PORT_FreeArena(pubk->arena, PR_FALSE);
+ }
+}
+unsigned
+nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
+{
+ unsigned char b0;
+
+ /* interpret modulus length as key strength... in
+ * fortezza that's the public key length */
+
+ switch (pubk->keyType) {
+ case NSSLOWKEYRSAKey:
+ b0 = pubk->u.rsa.modulus.data[0];
+ return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+unsigned
+nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
+{
+
+ unsigned char b0;
+
+ switch (privk->keyType) {
+ case NSSLOWKEYRSAKey:
+ b0 = privk->u.rsa.modulus.data[0];
+ return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+NSSLOWKEYPublicKey *
+nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
+{
+ NSSLOWKEYPublicKey *pubk;
+ PLArenaPool *arena;
+
+
+ arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ switch(privk->keyType) {
+ case NSSLOWKEYRSAKey:
+ case NSSLOWKEYNullKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof (NSSLOWKEYPublicKey));
+ if (pubk != NULL) {
+ SECStatus rv;
+
+ pubk->arena = arena;
+ pubk->keyType = privk->keyType;
+ if (privk->keyType == NSSLOWKEYNullKey) return pubk;
+ rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
+ &privk->u.rsa.modulus);
+ if (rv == SECSuccess) {
+ rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
+ &privk->u.rsa.publicExponent);
+ if (rv == SECSuccess)
+ return pubk;
+ }
+ } else {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ }
+ break;
+ case NSSLOWKEYDSAKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPublicKey));
+ if (pubk != NULL) {
+ SECStatus rv;
+
+ pubk->arena = arena;
+ pubk->keyType = privk->keyType;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
+ &privk->u.dsa.publicValue);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
+ &privk->u.dsa.params.prime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
+ &privk->u.dsa.params.subPrime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
+ &privk->u.dsa.params.base);
+ if (rv == SECSuccess) return pubk;
+ }
+ break;
+ case NSSLOWKEYDHKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPublicKey));
+ if (pubk != NULL) {
+ SECStatus rv;
+
+ pubk->arena = arena;
+ pubk->keyType = privk->keyType;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
+ &privk->u.dh.publicValue);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
+ &privk->u.dh.prime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
+ &privk->u.dh.base);
+ if (rv == SECSuccess) return pubk;
+ }
+ break;
+#ifdef NSS_ENABLE_ECC
+ case NSSLOWKEYECKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPublicKey));
+ if (pubk != NULL) {
+ SECStatus rv;
+
+ pubk->arena = arena;
+ pubk->keyType = privk->keyType;
+ rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
+ &privk->u.ec.publicValue);
+ if (rv != SECSuccess) break;
+ pubk->u.ec.ecParams.arena = arena;
+ /* Copy the rest of the params */
+ rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams),
+ &(privk->u.ec.ecParams));
+ if (rv == SECSuccess) return pubk;
+ }
+ break;
+#endif /* NSS_ENABLE_ECC */
+ /* No Fortezza in Low Key implementations (Fortezza keys aren't
+ * stored in our data base */
+ default:
+ break;
+ }
+
+ PORT_FreeArena (arena, PR_FALSE);
+ return NULL;
+}
+
diff --git a/security/nss/lib/softoken/legacydb/lowkeyi.h b/security/nss/lib/softoken/legacydb/lowkeyi.h
new file mode 100644
index 000000000..45359d4ef
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lowkeyi.h
@@ -0,0 +1,198 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/* $Id$ */
+
+#ifndef _LOWKEYI_H_
+#define _LOWKEYI_H_
+
+#include "prtypes.h"
+#include "seccomon.h"
+#include "secoidt.h"
+#include "pcertt.h"
+#include "lowkeyti.h"
+#include "sdb.h"
+
+SEC_BEGIN_PROTOS
+
+/*
+ * See bugzilla bug 125359
+ * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
+ * all of the templates above that en/decode into integers must be converted
+ * from ASN.1's signed integer type. This is done by marking either the
+ * source or destination (encoding or decoding, respectively) type as
+ * siUnsignedInteger.
+ */
+extern void prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
+extern void prepare_low_pqg_params_for_asn1(PQGParams *params);
+extern void prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
+extern void prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key);
+extern void prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
+#ifdef NSS_ENABLE_ECC
+extern void prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
+extern void prepare_low_ecparams_for_asn1(ECParams *params);
+#endif /* NSS_ENABLE_ECC */
+
+typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion);
+
+/*
+** Open a key database.
+*/
+extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDB(PRBool readOnly,
+ const char *domain,
+ const char *prefix,
+ NSSLOWKEYDBNameFunc namecb,
+ void *cbarg);
+
+/*
+** Close the specified key database.
+*/
+extern void nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle);
+
+/*
+ * Get the version number of the database
+ */
+extern int nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle);
+
+/*
+** Delete a key from the database
+*/
+extern SECStatus nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle,
+ const SECItem *pubkey);
+
+/*
+** Store a key in the database, indexed by its public key modulus.
+** "pk" is the private key to store
+** "f" is a the callback function for getting the password
+** "arg" is the argument for the callback
+*/
+extern SECStatus nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
+ NSSLOWKEYPrivateKey *pk,
+ SECItem *pubKeyData,
+ char *nickname,
+ SDB *sdb);
+
+/* does the key for this cert exist in the database filed by modulus */
+extern PRBool nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle,
+ NSSLOWCERTCertificate *cert);
+/* does a key with this ID already exist? */
+extern PRBool nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id);
+
+/*
+** Destroy a private key object.
+** "key" the object
+** "freeit" if PR_TRUE then free the object as well as its sub-objects
+*/
+extern void nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *key);
+
+/*
+** Destroy a public key object.
+** "key" the object
+** "freeit" if PR_TRUE then free the object as well as its sub-objects
+*/
+extern void nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *key);
+
+/*
+** Return the modulus length of "pubKey".
+*/
+extern unsigned int nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubKey);
+
+
+/*
+** Return the modulus length of "privKey".
+*/
+extern unsigned int nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privKey);
+
+
+/*
+** Convert a low private key "privateKey" into a public low key
+*/
+extern NSSLOWKEYPublicKey
+ *nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privateKey);
+
+
+SECStatus
+nsslowkey_UpdateNickname(NSSLOWKEYDBHandle *handle,
+ NSSLOWKEYPrivateKey *privkey,
+ SECItem *pubKeyData,
+ char *nickname,
+ SDB *sdb);
+
+/* Store key by modulus and specify an encryption algorithm to use.
+ * handle is the pointer to the key database,
+ * privkey is the private key to be stored,
+ * f and arg are the function and arguments to the callback
+ * to get a password,
+ * algorithm is the algorithm which the privKey is to be stored.
+ * A return of anything but SECSuccess indicates failure.
+ */
+extern SECStatus
+nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
+ NSSLOWKEYPrivateKey *privkey,
+ SECItem *pubKeyData,
+ char *nickname,
+ SDB *sdb,
+ PRBool update);
+
+/* Find key by modulus. This function is the inverse of store key
+ * by modulus. An attempt to locate the key with "modulus" is
+ * performed. If the key is found, the private key is returned,
+ * else NULL is returned.
+ * modulus is the modulus to locate
+ */
+extern NSSLOWKEYPrivateKey *
+nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
+ SDB *sdb);
+
+extern char *
+nsslowkey_FindKeyNicknameByPublicKey(NSSLOWKEYDBHandle *handle,
+ SECItem *modulus, SDB *sdb);
+
+#ifdef NSS_ENABLE_ECC
+/*
+ * smaller version of EC_FillParams. In this code, we only need
+ * oid and DER data.
+ */
+SECStatus LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
+ ECParams *params);
+
+/* Copy all of the fields from srcParams into dstParams */
+SECStatus LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams);
+#endif
+SEC_END_PROTOS
+
+#endif /* _LOWKEYI_H_ */
diff --git a/security/nss/lib/softoken/legacydb/lowkeyti.h b/security/nss/lib/softoken/legacydb/lowkeyti.h
new file mode 100644
index 000000000..57f8105e3
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lowkeyti.h
@@ -0,0 +1,161 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef _LOWKEYTI_H_
+#define _LOWKEYTI_H_ 1
+
+#include "blapit.h"
+#include "prtypes.h"
+#include "plarena.h"
+#include "secitem.h"
+#include "secasn1t.h"
+#include "secoidt.h"
+
+
+/*
+ * a key in/for the data base
+ */
+struct NSSLOWKEYDBKeyStr {
+ PLArenaPool *arena;
+ int version;
+ char *nickname;
+ SECItem salt;
+ SECItem derPK;
+};
+typedef struct NSSLOWKEYDBKeyStr NSSLOWKEYDBKey;
+
+typedef struct NSSLOWKEYDBHandleStr NSSLOWKEYDBHandle;
+
+#ifdef NSS_USE_KEY4_DB
+#define NSSLOWKEY_DB_FILE_VERSION 4
+#else
+#define NSSLOWKEY_DB_FILE_VERSION 3
+#endif
+
+#define NSSLOWKEY_VERSION 0 /* what we *create* */
+
+/*
+** Typedef for callback to get a password "key".
+*/
+extern const SEC_ASN1Template nsslowkey_PQGParamsTemplate[];
+extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[];
+extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[];
+extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[];
+extern const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[];
+extern const SEC_ASN1Template nsslowkey_DHPrivateKeyExportTemplate[];
+#ifdef NSS_ENABLE_ECC
+#define NSSLOWKEY_EC_PRIVATE_KEY_VERSION 1 /* as per SECG 1 C.4 */
+extern const SEC_ASN1Template nsslowkey_ECParamsTemplate[];
+extern const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[];
+#endif /* NSS_ENABLE_ECC */
+
+extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[];
+extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[];
+
+/*
+ * PKCS #8 attributes
+ */
+struct NSSLOWKEYAttributeStr {
+ SECItem attrType;
+ SECItem *attrValue;
+};
+typedef struct NSSLOWKEYAttributeStr NSSLOWKEYAttribute;
+
+/*
+** A PKCS#8 private key info object
+*/
+struct NSSLOWKEYPrivateKeyInfoStr {
+ PLArenaPool *arena;
+ SECItem version;
+ SECAlgorithmID algorithm;
+ SECItem privateKey;
+ NSSLOWKEYAttribute **attributes;
+};
+typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo;
+#define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */
+
+/*
+** A PKCS#8 private key info object
+*/
+struct NSSLOWKEYEncryptedPrivateKeyInfoStr {
+ PLArenaPool *arena;
+ SECAlgorithmID algorithm;
+ SECItem encryptedData;
+};
+typedef struct NSSLOWKEYEncryptedPrivateKeyInfoStr NSSLOWKEYEncryptedPrivateKeyInfo;
+
+
+typedef enum {
+ NSSLOWKEYNullKey = 0,
+ NSSLOWKEYRSAKey = 1,
+ NSSLOWKEYDSAKey = 2,
+ NSSLOWKEYDHKey = 4,
+ NSSLOWKEYECKey = 5
+} NSSLOWKEYType;
+
+/*
+** An RSA public key object.
+*/
+struct NSSLOWKEYPublicKeyStr {
+ PLArenaPool *arena;
+ NSSLOWKEYType keyType ;
+ union {
+ RSAPublicKey rsa;
+ DSAPublicKey dsa;
+ DHPublicKey dh;
+ ECPublicKey ec;
+ } u;
+};
+typedef struct NSSLOWKEYPublicKeyStr NSSLOWKEYPublicKey;
+
+/*
+** Low Level private key object
+** This is only used by the raw Crypto engines (crypto), keydb (keydb),
+** and PKCS #11. Everyone else uses the high level key structure.
+*/
+struct NSSLOWKEYPrivateKeyStr {
+ PLArenaPool *arena;
+ NSSLOWKEYType keyType;
+ union {
+ RSAPrivateKey rsa;
+ DSAPrivateKey dsa;
+ DHPrivateKey dh;
+ ECPrivateKey ec;
+ } u;
+};
+typedef struct NSSLOWKEYPrivateKeyStr NSSLOWKEYPrivateKey;
+
+#endif /* _LOWKEYTI_H_ */
diff --git a/security/nss/lib/softoken/legacydb/manifest.mn b/security/nss/lib/softoken/legacydb/manifest.mn
new file mode 100644
index 000000000..4c5fe7b95
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/manifest.mn
@@ -0,0 +1,68 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+CORE_DEPTH = ../../../..
+
+MODULE = nss
+
+REQUIRES = dbm
+
+LIBRARY_NAME = legacydb
+LIBRARY_VERSION = 3
+MAPFILE = $(OBJDIR)/legacydb.def
+
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
+
+
+CSRCS = \
+ dbmshim.c \
+ keydb.c \
+ lgattr.c \
+ lgcreate.c \
+ lgdestroy.c \
+ lgfind.c \
+ lginit.c \
+ lgutil.c \
+ lowcert.c \
+ lowkey.c \
+ pcertdb.c \
+ pk11db.c \
+ $(NULL)
+
+ifdef NSS_ENABLE_ECC
+DEFINES += -DNSS_ENABLE_ECC
+endif
+
diff --git a/security/nss/lib/softoken/pcert.h b/security/nss/lib/softoken/legacydb/pcert.h
index d4314f634..68956abd6 100644
--- a/security/nss/lib/softoken/pcert.h
+++ b/security/nss/lib/softoken/legacydb/pcert.h
@@ -85,7 +85,7 @@ nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle,
SECItem *crlKey, PRBool isKRL);
SECStatus
-nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle,SECItem *derName,
+nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle,const SECItem *derName,
PRBool isKRL);
SECStatus
nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl ,
@@ -110,7 +110,7 @@ void nsslowcert_DestroyTrust(NSSLOWCERTTrust *Trust);
* traversal.
*/
NSSLOWCERTCertificate *
-nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey);
+nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey);
/*
* Lookup trust for a certificate in the databases without locking
@@ -120,7 +120,7 @@ nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey);
* traversal.
*/
NSSLOWCERTTrust *
-nsslowcert_FindTrustByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey);
+nsslowcert_FindTrustByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey);
/*
** Generate a certificate key from the issuer and serialnumber, then look it
@@ -253,7 +253,7 @@ NSSLOWCERTCertificate *
nsslowcert_CreateCert(void);
certDBEntry *
-nsslowcert_DecodeAnyDBEntry(SECItem *dbData, SECItem *dbKey,
+nsslowcert_DecodeAnyDBEntry(SECItem *dbData, const SECItem *dbKey,
certDBEntryType entryType, void *pdata);
SEC_END_PROTOS
diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/legacydb/pcertdb.c
index a205ed71f..39c928f1e 100644
--- a/security/nss/lib/softoken/pcertdb.c
+++ b/security/nss/lib/softoken/legacydb/pcertdb.c
@@ -39,8 +39,6 @@
*
* $Id$
*/
-#include "prtime.h"
-
#include "lowkeyti.h"
#include "pcert.h"
#include "mcom_db.h"
@@ -48,19 +46,9 @@
#include "secitem.h"
#include "secder.h"
-/* Call to SFTK_FreeSlot below */
-
-#include "secasn1.h"
-#include "secerr.h"
-#include "nssilock.h"
-#include "prmon.h"
#include "nsslocks.h"
-#include "base64.h"
-#include "sechash.h"
-#include "plhash.h"
-
-#include "cdbhdl.h"
-#include "pkcs11i.h"
+#include "secerr.h"
+#include "lgdb.h"
/* forward declaration */
NSSLOWCERTCertificate *
@@ -198,7 +186,7 @@ nsslowcert_UnlockCertRefCount(NSSLOWCERTCertificate *cert)
* arg here so that it will be easy to make it per-cert in the future if
* that turns out to be necessary.
*/
-void
+static void
nsslowcert_LockCertTrust(NSSLOWCERTCertificate *cert)
{
PORT_Assert(certTrustLock != NULL);
@@ -210,7 +198,7 @@ nsslowcert_LockCertTrust(NSSLOWCERTCertificate *cert)
/*
* Free the cert trust lock
*/
-void
+static void
nsslowcert_UnlockCertTrust(NSSLOWCERTCertificate *cert)
{
PRStatus prstat;
@@ -677,7 +665,7 @@ loser:
* encode a database key for a cert record
*/
static SECStatus
-EncodeDBCertKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey)
+EncodeDBCertKey(const SECItem *certKey, PRArenaPool *arena, SECItem *dbkey)
{
unsigned int len = certKey->len + SEC_DB_KEY_HEADER_LEN;
if (arena) {
@@ -701,7 +689,7 @@ loser:
}
static SECStatus
-EncodeDBGenericKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey,
+EncodeDBGenericKey(const SECItem *certKey, PRArenaPool *arena, SECItem *dbkey,
certDBEntryType entryType)
{
/*
@@ -1090,7 +1078,7 @@ DestroyCertEntryFreeList(void)
* Read a certificate entry
*/
static certDBEntryCert *
-ReadDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
+ReadDBCertEntry(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey)
{
certDBEntryCert *entry;
SECItem dbkey;
@@ -1239,6 +1227,68 @@ loser:
return(SECFailure);
}
+/*
+ * Create a new certDBEntryRevocation from existing data
+ */
+static certDBEntryRevocation *
+NewDBCrlEntry(SECItem *derCrl, char * url, certDBEntryType crlType, int flags)
+{
+ certDBEntryRevocation *entry;
+ PRArenaPool *arena = NULL;
+ int nnlen;
+
+ arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE );
+
+ if ( !arena ) {
+ goto loser;
+ }
+
+ entry = PORT_ArenaZNew(arena, certDBEntryRevocation);
+ if ( entry == NULL ) {
+ goto loser;
+ }
+
+ /* fill in the dbRevolcation */
+ entry->common.arena = arena;
+ entry->common.type = crlType;
+ entry->common.version = CERT_DB_FILE_VERSION;
+ entry->common.flags = flags;
+
+
+ entry->derCrl.data = (unsigned char *)PORT_ArenaAlloc(arena, derCrl->len);
+ if ( !entry->derCrl.data ) {
+ goto loser;
+ }
+
+ if (url) {
+ nnlen = PORT_Strlen(url) + 1;
+ entry->url = (char *)PORT_ArenaAlloc(arena, nnlen);
+ if ( !entry->url ) {
+ goto loser;
+ }
+ PORT_Memcpy(entry->url, url, nnlen);
+ } else {
+ entry->url = NULL;
+ }
+
+
+ entry->derCrl.len = derCrl->len;
+ PORT_Memcpy(entry->derCrl.data, derCrl->data, derCrl->len);
+
+ return(entry);
+
+loser:
+
+ /* allocation error, free arena and return */
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return(0);
+}
+
+
static SECStatus
WriteDBCrlEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryRevocation *entry,
SECItem *crlKey )
@@ -1282,7 +1332,7 @@ loser:
* delete a crl entry
*/
static SECStatus
-DeleteDBCrlEntry(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey,
+DeleteDBCrlEntry(NSSLOWCERTCertDBHandle *handle, const SECItem *crlKey,
certDBEntryType crlType)
{
SECItem dbkey;
@@ -1696,7 +1746,7 @@ loser:
}
-SECStatus
+static SECStatus
EncodeDBSMimeEntry(certDBEntrySMime *entry, PRArenaPool *arena,
SECItem *dbitem)
{
@@ -2218,7 +2268,7 @@ loser:
static SECStatus
DecodeDBSubjectEntry(certDBEntrySubject *entry, SECItem *dbentry,
- SECItem *derSubject)
+ const SECItem *derSubject)
{
unsigned int ncerts;
PRArenaPool *arena;
@@ -3311,10 +3361,7 @@ AddCertToPermDB(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTCertificate *cert,
state = 2;
/* "Change" handles if necessary */
- if (cert->dbhandle) {
- sftk_freeCertDB(cert->dbhandle);
- }
- cert->dbhandle = nsslowcert_reference(handle);
+ cert->dbhandle = handle;
/* add to or create new subject entry */
if ( subjectEntry ) {
@@ -3977,12 +4024,6 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname,
return status == RDB_RETRY ? SECWouldBlock : SECFailure;
}
- rv = db_BeginTransaction(handle->permCertDB);
- if (rv != SECSuccess) {
- db_InitComplete(handle->permCertDB);
- return SECFailure;
- }
-
/* Verify version number; */
versionEntry = NewDBVersionEntry(0);
if ( versionEntry == NULL ) {
@@ -4020,7 +4061,6 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname,
loser:
- db_FinishTransaction(handle->permCertDB,rv != SECSuccess);
db_InitComplete(handle->permCertDB);
return rv;
}
@@ -4159,10 +4199,6 @@ nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert)
nsslowcert_LockDB(cert->dbhandle);
- rv = db_BeginTransaction(cert->dbhandle->permCertDB);
- if ( rv != SECSuccess ) {
- goto loser;
- }
/* delete the records from the permanent database */
rv = DeletePermCert(cert);
@@ -4170,9 +4206,6 @@ nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert)
DestroyDBEntry((certDBEntry *)cert->dbEntry);
cert->dbEntry = NULL;
cert->trust = NULL;
-
- db_FinishTransaction(cert->dbhandle->permCertDB,rv != SECSuccess);
-loser:
nsslowcert_UnlockDB(cert->dbhandle);
return(rv);
@@ -4243,7 +4276,7 @@ DecodeACert(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry)
goto loser;
}
- cert->dbhandle = nsslowcert_reference(handle);
+ cert->dbhandle = handle;
cert->dbEntry = entry;
cert->trust = &entry->trust;
@@ -4291,13 +4324,13 @@ DestroyTrustFreeList(void)
static NSSLOWCERTTrust *
DecodeTrustEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry,
- SECItem *dbKey)
+ const SECItem *dbKey)
{
NSSLOWCERTTrust *trust = CreateTrust();
if (trust == NULL) {
return trust;
}
- trust->dbhandle = nsslowcert_reference(handle);
+ trust->dbhandle = handle;
trust->dbEntry = entry;
trust->dbKey.data = pkcs11_copyStaticData(dbKey->data,dbKey->len,
trust->dbKeySpace, sizeof(trust->dbKeySpace));
@@ -4544,18 +4577,11 @@ nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *dbhandle,
NSSLOWCERTCertificate *cert, char *nickname, NSSLOWCERTCertTrust *trust)
{
SECStatus ret;
- SECStatus rv;
nsslowcert_LockDB(dbhandle);
- rv = db_BeginTransaction(dbhandle->permCertDB);
- if (rv != SECSuccess) {
- nsslowcert_UnlockDB(dbhandle);
- return SECFailure;
- }
ret = nsslowcert_UpdatePermCert(dbhandle, cert, nickname, trust);
- db_FinishTransaction(dbhandle->permCertDB, ret != SECSuccess);
nsslowcert_UnlockDB(dbhandle);
return(ret);
}
@@ -4609,7 +4635,7 @@ nsslowcert_setDBVerify(NSSLOWCERTCertDBHandle *handle, PRBool value)
* Lookup a certificate in the databases.
*/
static NSSLOWCERTCertificate *
-FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey, PRBool lockdb)
+FindCertByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey, PRBool lockdb)
{
NSSLOWCERTCertificate *cert = NULL;
certDBEntryCert *entry;
@@ -4648,7 +4674,7 @@ loser:
* Lookup a certificate in the databases.
*/
static NSSLOWCERTTrust *
-FindTrustByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey, PRBool lockdb)
+FindTrustByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey, PRBool lockdb)
{
NSSLOWCERTTrust *trust = NULL;
certDBEntryCert *entry;
@@ -4691,7 +4717,7 @@ loser:
* Lookup a certificate in the databases without locking
*/
NSSLOWCERTCertificate *
-nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
+nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey)
{
return(FindCertByKey(handle, certKey, PR_FALSE));
}
@@ -4700,7 +4726,7 @@ nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
* Lookup a trust object in the databases without locking
*/
NSSLOWCERTTrust *
-nsslowcert_FindTrustByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
+nsslowcert_FindTrustByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey)
{
return(FindTrustByKey(handle, certKey, PR_FALSE));
}
@@ -4931,9 +4957,6 @@ DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb)
*/
if ( lockdb && handle ) {
nsslowcert_LockDB(handle);
- /* keep a reference until we unlock, so handle won't disappear
- * before we are through with it */
- nsslowcert_reference(handle);
}
nsslowcert_LockCertRefCount(cert);
@@ -4949,6 +4972,7 @@ DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb)
}
pkcs11_freeNickname(cert->nickname,cert->nicknameSpace);
+ pkcs11_freeNickname(cert->emailAddr,cert->emailAddrSpace);
pkcs11_freeStaticData(cert->certKey.data,cert->certKeySpace);
cert->certKey.data = NULL;
cert->nickname = NULL;
@@ -4967,15 +4991,10 @@ DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb)
certListHead = cert;
}
nsslowcert_UnlockFreeList();
- if (handle) {
- sftk_freeCertDB(handle);
- }
-
cert = NULL;
}
if ( lockdb && handle ) {
nsslowcert_UnlockDB(handle);
- sftk_freeCertDB(handle);
}
}
@@ -5024,9 +5043,6 @@ nsslowcert_DestroyTrust(NSSLOWCERTTrust *trust)
if ( entry ) {
DestroyDBEntry((certDBEntry *)entry);
}
- if (trust->dbhandle) {
- sftk_freeCertDB(trust->dbhandle);
- }
pkcs11_freeStaticData(trust->dbKey.data,trust->dbKeySpace);
PORT_Memset(trust, 0, sizeof(*trust));
@@ -5109,23 +5125,22 @@ nsslowcert_UpdateCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl,
SECItem *crlKey, char *url, PRBool isKRL)
{
SECStatus rv = SECFailure;
- certDBEntryRevocation entry;
+ certDBEntryRevocation *entry = NULL;
certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation
: certDBEntryTypeRevocation;
DeleteDBCrlEntry(handle, crlKey, crlType);
/* Write the new entry into the data base */
- entry.common.arena = NULL;
- entry.common.type = crlType;
- entry.common.version = CERT_DB_FILE_VERSION;
- entry.common.flags = 0;
+ entry = NewDBCrlEntry(derCrl, url, crlType, 0);
+ if (entry == NULL) goto done;
- entry.derCrl.data = derCrl->data;
- entry.derCrl.len = derCrl->len;
- entry.url = url;
-
- rv = WriteDBCrlEntry(handle, &entry, crlKey);
+ rv = WriteDBCrlEntry(handle, entry, crlKey);
+ if (rv != SECSuccess) goto done;
+done:
+ if (entry) {
+ DestroyDBEntry((certDBEntry *)entry);
+ }
return rv;
}
@@ -5135,33 +5150,23 @@ nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl,
{
SECStatus rv;
- rv = db_BeginTransaction(handle->permCertDB);
- if (rv != SECSuccess) {
- return SECFailure;
- }
rv = nsslowcert_UpdateCrl(handle, derCrl, crlKey, url, isKRL);
- db_FinishTransaction(handle->permCertDB, rv != SECSuccess);
return rv;
}
SECStatus
-nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle, SECItem *derName,
+nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle, const SECItem *derName,
PRBool isKRL)
{
SECStatus rv;
certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation
: certDBEntryTypeRevocation;
- rv = db_BeginTransaction(handle->permCertDB);
- if (rv != SECSuccess) {
- return SECFailure;
- }
rv = DeleteDBCrlEntry(handle, derName, crlType);
if (rv != SECSuccess) goto done;
done:
- db_FinishTransaction(handle->permCertDB, rv != SECSuccess);
return rv;
}
@@ -5248,15 +5253,10 @@ nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr,
{
SECStatus rv = SECFailure;;
- rv = db_BeginTransaction(dbhandle->permCertDB);
- if (rv != SECSuccess) {
- return SECFailure;
- }
rv = nsslowcert_UpdateSMimeProfile(dbhandle, emailAddr,
derSubject, emailProfile, profileTime);
- db_FinishTransaction(dbhandle->permCertDB, rv != SECSuccess);
return(rv);
}
@@ -5288,7 +5288,7 @@ nsslowcert_DestroyGlobalLocks(void)
}
certDBEntry *
-nsslowcert_DecodeAnyDBEntry(SECItem *dbData, SECItem *dbKey,
+nsslowcert_DecodeAnyDBEntry(SECItem *dbData, const SECItem *dbKey,
certDBEntryType entryType, void *pdata)
{
PLArenaPool *arena = NULL;
diff --git a/security/nss/lib/softoken/pcertt.h b/security/nss/lib/softoken/legacydb/pcertt.h
index 848fe69e9..476a2d079 100644
--- a/security/nss/lib/softoken/pcertt.h
+++ b/security/nss/lib/softoken/legacydb/pcertt.h
@@ -146,6 +146,7 @@ struct NSSLOWCERTCertificateStr {
SECItem validity;
certDBEntryCert *dbEntry; /* database entry struct */
SECItem subjectKeyID; /* x509v3 subject key identifier */
+ SECItem extensions;
char *nickname;
char *emailAddr;
NSSLOWCERTCertTrust *trust;
@@ -156,6 +157,7 @@ struct NSSLOWCERTCertificateStr {
int referenceCount;
char nicknameSpace[200];
+ char emailAddrSpace[200];
unsigned char certKeySpace[512];
};
diff --git a/security/nss/lib/softoken/pk11db.c b/security/nss/lib/softoken/legacydb/pk11db.c
index 6bbe2ab4f..f85a0a6c3 100644
--- a/security/nss/lib/softoken/pk11db.c
+++ b/security/nss/lib/softoken/legacydb/pk11db.c
@@ -40,266 +40,12 @@
*/
#include "pk11pars.h"
-#include "pkcs11i.h"
+#include "lgdb.h"
#include "mcom_db.h"
-#include "cdbhdl.h"
#include "secerr.h"
#define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
-static void
-secmod_parseTokenFlags(char *tmp, sftk_token_parameters *parsed) {
- parsed->readOnly = secmod_argHasFlag("flags","readOnly",tmp);
- parsed->noCertDB = secmod_argHasFlag("flags","noCertDB",tmp);
- parsed->noKeyDB = secmod_argHasFlag("flags","noKeyDB",tmp);
- parsed->forceOpen = secmod_argHasFlag("flags","forceOpen",tmp);
- parsed->pwRequired = secmod_argHasFlag("flags","passwordRequired",tmp);
- parsed->optimizeSpace = secmod_argHasFlag("flags","optimizeSpace",tmp);
- return;
-}
-
-static void
-secmod_parseFlags(char *tmp, sftk_parameters *parsed) {
- parsed->noModDB = secmod_argHasFlag("flags","noModDB",tmp);
- parsed->readOnly = secmod_argHasFlag("flags","readOnly",tmp);
- /* keep legacy interface working */
- parsed->noCertDB = secmod_argHasFlag("flags","noCertDB",tmp);
- parsed->forceOpen = secmod_argHasFlag("flags","forceOpen",tmp);
- parsed->pwRequired = secmod_argHasFlag("flags","passwordRequired",tmp);
- parsed->optimizeSpace = secmod_argHasFlag("flags","optimizeSpace",tmp);
- return;
-}
-
-CK_RV
-secmod_parseTokenParameters(char *param, sftk_token_parameters *parsed)
-{
- int next;
- char *tmp = NULL;
- char *index;
- index = secmod_argStrip(param);
-
- while (*index) {
- SECMOD_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
- SECMOD_HANDLE_STRING_ARG(index,parsed->certPrefix,"certPrefix=",;)
- SECMOD_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyPrefix=",;)
- SECMOD_HANDLE_STRING_ARG(index,parsed->tokdes,"tokenDescription=",;)
- SECMOD_HANDLE_STRING_ARG(index,parsed->slotdes,"slotDescription=",;)
- SECMOD_HANDLE_STRING_ARG(index,tmp,"minPWLen=",
- if (tmp) { parsed->minPW=atoi(tmp); })
- SECMOD_HANDLE_STRING_ARG(index,tmp,"flags=",
- if (tmp) { secmod_parseTokenFlags(param,parsed); })
- SECMOD_HANDLE_FINAL_ARG(index)
- }
- if (tmp)
- PORT_Free(tmp);
- return CKR_OK;
-}
-
-static void
-secmod_parseTokens(char *tokenParams, sftk_parameters *parsed)
-{
- char *tokenIndex;
- sftk_token_parameters *tokens = NULL;
- int i=0,count = 0,next;
-
- if ((tokenParams == NULL) || (*tokenParams == 0)) return;
-
- /* first count the number of slots */
- for (tokenIndex = secmod_argStrip(tokenParams); *tokenIndex;
- tokenIndex = secmod_argStrip(secmod_argSkipParameter(tokenIndex))) {
- count++;
- }
-
- /* get the data structures */
- tokens = (sftk_token_parameters *)
- PORT_ZAlloc(count*sizeof(sftk_token_parameters));
- if (tokens == NULL) return;
-
- for (tokenIndex = secmod_argStrip(tokenParams), i = 0;
- *tokenIndex && i < count ; i++ ) {
- char *name;
- name = secmod_argGetName(tokenIndex,&next);
- tokenIndex += next;
-
- tokens[i].slotID = secmod_argDecodeNumber(name);
- tokens[i].readOnly = PR_FALSE;
- tokens[i].noCertDB = PR_FALSE;
- tokens[i].noKeyDB = PR_FALSE;
- if (!secmod_argIsBlank(*tokenIndex)) {
- char *args = secmod_argFetchValue(tokenIndex,&next);
- tokenIndex += next;
- if (args) {
- secmod_parseTokenParameters(args,&tokens[i]);
- PORT_Free(args);
- }
- }
- if (name) PORT_Free(name);
- tokenIndex = secmod_argStrip(tokenIndex);
- }
- parsed->token_count = i;
- parsed->tokens = tokens;
- return;
-}
-
-CK_RV
-secmod_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS)
-{
- int next;
- char *tmp = NULL;
- char *index;
- char *certPrefix = NULL, *keyPrefix = NULL;
- char *tokdes = NULL, *ptokdes = NULL;
- char *slotdes = NULL, *pslotdes = NULL;
- char *fslotdes = NULL, *fpslotdes = NULL;
- char *minPW = NULL;
- index = secmod_argStrip(param);
-
- PORT_Memset(parsed, 0, sizeof(sftk_parameters));
-
- while (*index) {
- SECMOD_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
- SECMOD_HANDLE_STRING_ARG(index,parsed->secmodName,"secmod=",;)
- SECMOD_HANDLE_STRING_ARG(index,parsed->man,"manufacturerID=",;)
- SECMOD_HANDLE_STRING_ARG(index,parsed->libdes,"libraryDescription=",;)
- /* constructed values, used so legacy interfaces still work */
- SECMOD_HANDLE_STRING_ARG(index,certPrefix,"certPrefix=",;)
- SECMOD_HANDLE_STRING_ARG(index,keyPrefix,"keyPrefix=",;)
- SECMOD_HANDLE_STRING_ARG(index,tokdes,"cryptoTokenDescription=",;)
- SECMOD_HANDLE_STRING_ARG(index,ptokdes,"dbTokenDescription=",;)
- SECMOD_HANDLE_STRING_ARG(index,slotdes,"cryptoSlotDescription=",;)
- SECMOD_HANDLE_STRING_ARG(index,pslotdes,"dbSlotDescription=",;)
- SECMOD_HANDLE_STRING_ARG(index,fslotdes,"FIPSSlotDescription=",;)
- SECMOD_HANDLE_STRING_ARG(index,fpslotdes,"FIPSTokenDescription=",;)
- SECMOD_HANDLE_STRING_ARG(index,minPW,"minPWLen=",;)
-
- SECMOD_HANDLE_STRING_ARG(index,tmp,"flags=",
- if (tmp) { secmod_parseFlags(param,parsed); })
- SECMOD_HANDLE_STRING_ARG(index,tmp,"tokens=",
- if (tmp) { secmod_parseTokens(tmp,parsed); })
- SECMOD_HANDLE_FINAL_ARG(index)
- }
- if (tmp)
- PORT_Free(tmp);
- if (parsed->tokens == NULL) {
- int count = isFIPS ? 1 : 2;
- int index = count-1;
- sftk_token_parameters *tokens = NULL;
-
- tokens = (sftk_token_parameters *)
- PORT_ZAlloc(count*sizeof(sftk_token_parameters));
- if (tokens == NULL) {
- goto loser;
- }
- parsed->tokens = tokens;
- parsed->token_count = count;
- tokens[index].slotID = isFIPS ? FIPS_SLOT_ID : PRIVATE_KEY_SLOT_ID;
- tokens[index].certPrefix = certPrefix;
- tokens[index].keyPrefix = keyPrefix;
- tokens[index].minPW = minPW ? atoi(minPW) : 0;
- tokens[index].readOnly = parsed->readOnly;
- tokens[index].noCertDB = parsed->noCertDB;
- tokens[index].noKeyDB = parsed->noCertDB;
- tokens[index].forceOpen = parsed->forceOpen;
- tokens[index].pwRequired = parsed->pwRequired;
- tokens[index].optimizeSpace = parsed->optimizeSpace;
- tokens[0].optimizeSpace = parsed->optimizeSpace;
- certPrefix = NULL;
- keyPrefix = NULL;
- if (isFIPS) {
- tokens[index].tokdes = fslotdes;
- tokens[index].slotdes = fpslotdes;
- fslotdes = NULL;
- fpslotdes = NULL;
- } else {
- tokens[index].tokdes = ptokdes;
- tokens[index].slotdes = pslotdes;
- tokens[0].slotID = NETSCAPE_SLOT_ID;
- tokens[0].tokdes = tokdes;
- tokens[0].slotdes = slotdes;
- tokens[0].noCertDB = PR_TRUE;
- tokens[0].noKeyDB = PR_TRUE;
- ptokdes = NULL;
- pslotdes = NULL;
- tokdes = NULL;
- slotdes = NULL;
- }
- }
-
-loser:
- FREE_CLEAR(certPrefix);
- FREE_CLEAR(keyPrefix);
- FREE_CLEAR(tokdes);
- FREE_CLEAR(ptokdes);
- FREE_CLEAR(slotdes);
- FREE_CLEAR(pslotdes);
- FREE_CLEAR(fslotdes);
- FREE_CLEAR(fpslotdes);
- FREE_CLEAR(minPW);
- return CKR_OK;
-}
-
-void
-secmod_freeParams(sftk_parameters *params)
-{
- int i;
-
- for (i=0; i < params->token_count; i++) {
- FREE_CLEAR(params->tokens[i].configdir);
- FREE_CLEAR(params->tokens[i].certPrefix);
- FREE_CLEAR(params->tokens[i].keyPrefix);
- FREE_CLEAR(params->tokens[i].tokdes);
- FREE_CLEAR(params->tokens[i].slotdes);
- }
-
- FREE_CLEAR(params->configdir);
- FREE_CLEAR(params->secmodName);
- FREE_CLEAR(params->man);
- FREE_CLEAR(params->libdes);
- FREE_CLEAR(params->tokens);
-}
-
-
-char *
-secmod_getSecmodName(char *param, char **appName, char **filename,PRBool *rw)
-{
- int next;
- char *configdir = NULL;
- char *secmodName = NULL;
- char *value = NULL;
- char *save_params = param;
- const char *lconfigdir = NULL;
- param = secmod_argStrip(param);
-
-
- while (*param) {
- SECMOD_HANDLE_STRING_ARG(param,configdir,"configDir=",;)
- SECMOD_HANDLE_STRING_ARG(param,secmodName,"secmod=",;)
- SECMOD_HANDLE_FINAL_ARG(param)
- }
-
- *rw = PR_TRUE;
- if (secmod_argHasFlag("flags","readOnly",save_params) ||
- secmod_argHasFlag("flags","noModDB",save_params)) *rw = PR_FALSE;
-
- if (!secmodName || *secmodName == '\0') {
- if (secmodName) PORT_Free(secmodName);
- secmodName = PORT_Strdup(SECMOD_DB);
- }
- *filename = secmodName;
-
- if (configdir) {
- lconfigdir = sftk_EvaluateConfigDir(configdir, appName);
- }
-
- if (lconfigdir) {
- value = PR_smprintf("%s" PATH_SEPARATOR "%s",lconfigdir,secmodName);
- } else {
- value = PR_smprintf("%s",secmodName);
- }
- if (configdir) PORT_Free(configdir);
- return value;
-}
-
/* Construct a database key for a given module */
static SECStatus secmod_MakeKey(DBT *key, char * module) {
int len = 0;
@@ -768,8 +514,6 @@ loser:
return NULL;
}
-
-
static DB *
secmod_OpenDB(const char *appName, const char *filename, const char *dbName,
PRBool readOnly, PRBool update)
@@ -862,13 +606,16 @@ secmod_addEscape(const char *string, char quote)
return newString;
}
+SECStatus legacy_AddSecmodDB(const char *appName, const char *filename,
+ const char *dbname, char *module, PRBool rw);
+
#define SECMOD_STEP 10
#define SFTK_DEFAULT_INTERNAL_INIT "library= name=\"NSS Internal PKCS #11 Module\" parameters=\"%s\" NSS=\"Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={%s askpw=any timeout=30})\""
/*
* Read all the existing modules in
*/
char **
-secmod_ReadPermDB(const char *appName, const char *filename,
+legacy_ReadSecmodDB(const char *appName, const char *filename,
const char *dbname, char *params, PRBool rw)
{
DBT key,data;
@@ -924,7 +671,7 @@ done:
if (pkcs11db) {
secmod_CloseDB(pkcs11db);
} else if (moduleList[0] && rw) {
- secmod_AddPermDB(appName,filename,dbname,moduleList[0], rw) ;
+ legacy_AddSecmodDB(appName,filename,dbname,moduleList[0], rw) ;
}
if (!moduleList[0]) {
PORT_Free(moduleList);
@@ -934,7 +681,7 @@ done:
}
SECStatus
-secmod_ReleasePermDBData(const char *appName, const char *filename,
+legacy_ReleaseSecmodDBData(const char *appName, const char *filename,
const char *dbname, char **moduleSpecList, PRBool rw)
{
if (moduleSpecList) {
@@ -951,7 +698,7 @@ secmod_ReleasePermDBData(const char *appName, const char *filename,
* Delete a module from the Data Base
*/
SECStatus
-secmod_DeletePermDB(const char *appName, const char *filename,
+legacy_DeleteSecmodDB(const char *appName, const char *filename,
const char *dbname, char *args, PRBool rw)
{
DBT key;
@@ -987,7 +734,7 @@ done:
* Add a module to the Data base
*/
SECStatus
-secmod_AddPermDB(const char *appName, const char *filename,
+legacy_AddSecmodDB(const char *appName, const char *filename,
const char *dbname, char *module, PRBool rw)
{
DBT key,data;
diff --git a/security/nss/lib/softoken/lgglue.c b/security/nss/lib/softoken/lgglue.c
new file mode 100644
index 000000000..a20a1804f
--- /dev/null
+++ b/security/nss/lib/softoken/lgglue.c
@@ -0,0 +1,341 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * The following code handles the storage of PKCS 11 modules used by the
+ * NSS. This file is written to abstract away how the modules are
+ * stored so we can deside that later.
+ */
+#include "sftkdb.h"
+#include "sdb.h"
+#include "prsystem.h"
+#include "prprf.h"
+#include "lgglue.h"
+#include "secerr.h"
+
+static LGOpenFunc legacy_glue_open = NULL;
+static LGReadSecmodFunc legacy_glue_readSecmod = NULL;
+static LGReleaseSecmodFunc legacy_glue_releaseSecmod = NULL;
+static LGDeleteSecmodFunc legacy_glue_deleteSecmod = NULL;
+static LGAddSecmodFunc legacy_glue_addSecmod = NULL;
+static LGShutdownFunc legacy_glue_shutdown = NULL;
+
+/*
+ * The following 3 functions duplicate the work done by bl_LoadLibrary.
+ * We should make bl_LoadLibrary a global and replace the call to
+ * sftkdb_LoadLibrary(const char *libname) with it.
+ */
+#ifdef XP_UNIX
+#include <unistd.h>
+#define LG_MAX_LINKS 20
+static char *
+sftkdb_resolvePath(const char *orig)
+{
+ int count = 0;
+ int len =0;
+ int ret = -1;
+ char *resolved = NULL;
+ char *source = NULL;
+
+ len = 1025; /* MAX PATH +1*/
+ if (strlen(orig)+1 > len) {
+ /* PATH TOO LONG */
+ return NULL;
+ }
+ resolved = PORT_Alloc(len);
+ if (!resolved) {
+ return NULL;
+ }
+ source = PORT_Alloc(len);
+ if (!source) {
+ goto loser;
+ }
+ PORT_Strcpy(source, orig);
+ /* Walk down all the links */
+ while ( count++ < LG_MAX_LINKS) {
+ char *tmp;
+ /* swap our previous sorce out with resolved */
+ /* read it */
+ ret = readlink(source, resolved, len-1);
+ if (ret < 0) {
+ break;
+ }
+ resolved[ret] = 0;
+ tmp = source; source = resolved; resolved = tmp;
+ }
+ if (count > 1) {
+ ret = 0;
+ }
+loser:
+ if (resolved) {
+ PORT_Free(resolved);
+ }
+ if (ret < 0) {
+ if (source) {
+ PORT_Free(source);
+ source = NULL;
+ }
+ }
+ return source;
+}
+
+#endif
+
+static PRLibrary *
+sftkdb_LoadFromPath(const char *path, const char *libname)
+{
+ char *c;
+ int pathLen, nameLen, fullPathLen;
+ char *fullPathName = NULL;
+ PRLibSpec libSpec;
+ PRLibrary *lib = NULL;
+
+
+ /* strip of our parent's library name */
+ c = strrchr(path, PR_GetDirectorySeparator());
+ if (!c) {
+ return NULL; /* invalid path */
+ }
+ pathLen = (c-path)+1;
+ nameLen = strlen(libname);
+ fullPathLen = pathLen + nameLen +1;
+ fullPathName = (char *)PORT_Alloc(fullPathLen);
+ if (fullPathName == NULL) {
+ return NULL; /* memory allocation error */
+ }
+ PORT_Memcpy(fullPathName, path, pathLen);
+ PORT_Memcpy(fullPathName+pathLen, libname, nameLen);
+ fullPathName[fullPathLen-1] = 0;
+
+ libSpec.type = PR_LibSpec_Pathname;
+ libSpec.value.pathname = fullPathName;
+ lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
+ PORT_Free(fullPathName);
+ return lib;
+}
+
+static PRLibrary *
+sftkdb_LoadLibrary(const char *libname)
+{
+ PRLibrary *lib = NULL;
+ PRFuncPtr fn_addr;
+ char *parentLibPath = NULL;
+
+ fn_addr = (PRFuncPtr) &sftkdb_LoadLibrary;
+ parentLibPath = PR_GetLibraryFilePathname(SOFTOKEN_LIB_NAME, fn_addr);
+
+ if (!parentLibPath) {
+ goto done;
+ }
+
+ lib = sftkdb_LoadFromPath(parentLibPath, libname);
+#ifdef XP_UNIX
+ /* handle symbolic link case */
+ if (!lib) {
+ char *trueParentLibPath = sftkdb_resolvePath(parentLibPath);
+ if (!trueParentLibPath) {
+ goto done;
+ }
+ lib = sftkdb_LoadFromPath(trueParentLibPath, libname);
+ PORT_Free(trueParentLibPath);
+ }
+#endif
+ PORT_Free(parentLibPath);
+
+done:
+ /* still couldn't load it, try the generic path */
+ if (!lib) {
+ PRLibSpec libSpec;
+ libSpec.type = PR_LibSpec_Pathname;
+ libSpec.value.pathname = libname;
+ lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
+ }
+ return lib;
+}
+
+static PRLibrary *legacy_glue_lib = NULL;
+static SECStatus
+sftkdbLoad_Legacy()
+{
+ PRLibrary *lib = NULL;
+ LGSetCryptFunc setCryptFunction = NULL;
+
+ if (legacy_glue_lib) {
+ return SECSuccess;
+ }
+
+ lib = sftkdb_LoadLibrary(SHLIB_PREFIX"legacydb"SHLIB_VERSION"."SHLIB_SUFFIX);
+ if (lib == NULL) {
+ return SECFailure;
+ }
+
+ legacy_glue_open = (LGOpenFunc)PR_FindFunctionSymbol(lib, "legacy_Open");
+ legacy_glue_readSecmod = (LGReadSecmodFunc) PR_FindFunctionSymbol(lib,
+ "legacy_ReadSecmodDB");
+ legacy_glue_releaseSecmod = (LGReleaseSecmodFunc) PR_FindFunctionSymbol(lib,
+ "legacy_ReleaseSecmodDBData");
+ legacy_glue_deleteSecmod = (LGDeleteSecmodFunc) PR_FindFunctionSymbol(lib,
+ "legacy_DeleteSecmodDB");
+ legacy_glue_addSecmod = (LGAddSecmodFunc)PR_FindFunctionSymbol(lib,
+ "legacy_AddSecmodDB");
+ legacy_glue_shutdown = (LGShutdownFunc) PR_FindFunctionSymbol(lib,
+ "legacy_Shutdown");
+ setCryptFunction = (LGSetCryptFunc) PR_FindFunctionSymbol(lib,
+ "legacy_SetCryptFunctions");
+
+ if (!legacy_glue_open || !legacy_glue_readSecmod ||
+ !legacy_glue_releaseSecmod || !legacy_glue_deleteSecmod ||
+ !legacy_glue_addSecmod || !setCryptFunction) {
+ PR_UnloadLibrary(lib);
+ return SECFailure;
+ }
+ setCryptFunction(sftkdb_encrypt_stub,sftkdb_decrypt_stub);
+ legacy_glue_lib = lib;
+ return SECSuccess;
+}
+
+CK_RV
+sftkdbCall_open(const char *dir, const char *certPrefix, const char *keyPrefix,
+ int certVersion, int keyVersion, int flags,
+ SDB **certDB, SDB **keyDB)
+{
+ SECStatus rv;
+
+ rv = sftkdbLoad_Legacy();
+ if (rv != SECSuccess) {
+ return CKR_GENERAL_ERROR;
+ }
+ if (!legacy_glue_open) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ return (*legacy_glue_open)(dir, certPrefix, keyPrefix,
+ certVersion, keyVersion,
+ flags, certDB, keyDB);
+}
+
+char **
+sftkdbCall_ReadSecmodDB(const char *appName, const char *filename,
+ const char *dbname, char *params, PRBool rw)
+{
+ SECStatus rv;
+
+ rv = sftkdbLoad_Legacy();
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+ if (!legacy_glue_readSecmod) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return NULL;
+ }
+ return (*legacy_glue_readSecmod)(appName, filename, dbname, params, rw);
+}
+
+SECStatus
+sftkdbCall_ReleaseSecmodDBData(const char *appName,
+ const char *filename, const char *dbname,
+ char **moduleSpecList, PRBool rw)
+{
+ SECStatus rv;
+
+ rv = sftkdbLoad_Legacy();
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ if (!legacy_glue_releaseSecmod) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ return (*legacy_glue_releaseSecmod)(appName, filename, dbname,
+ moduleSpecList, rw);
+}
+
+SECStatus
+sftkdbCall_DeleteSecmodDB(const char *appName,
+ const char *filename, const char *dbname,
+ char *args, PRBool rw)
+{
+ SECStatus rv;
+
+ rv = sftkdbLoad_Legacy();
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ if (!legacy_glue_deleteSecmod) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ return (*legacy_glue_deleteSecmod)(appName, filename, dbname, args, rw);
+}
+
+SECStatus
+sftkdbCall_AddSecmodDB(const char *appName,
+ const char *filename, const char *dbname,
+ char *module, PRBool rw)
+{
+ SECStatus rv;
+
+ rv = sftkdbLoad_Legacy();
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ if (!legacy_glue_addSecmod) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ return (*legacy_glue_addSecmod)(appName, filename, dbname, module, rw);
+}
+
+CK_RV
+sftkdbCall_Shutdown(void)
+{
+ CK_RV crv = CKR_OK;
+ if (legacy_glue_lib) {
+ return CKR_OK;
+ }
+ if (legacy_glue_shutdown) {
+ crv = (*legacy_glue_shutdown)();
+ }
+ PR_UnloadLibrary(legacy_glue_lib);
+ legacy_glue_lib = NULL;
+ legacy_glue_open = NULL;
+ legacy_glue_readSecmod = NULL;
+ legacy_glue_releaseSecmod = NULL;
+ legacy_glue_deleteSecmod = NULL;
+ legacy_glue_addSecmod = NULL;
+ return crv;
+}
+
+
diff --git a/security/nss/lib/softoken/lgglue.h b/security/nss/lib/softoken/lgglue.h
new file mode 100644
index 000000000..8ced909d3
--- /dev/null
+++ b/security/nss/lib/softoken/lgglue.h
@@ -0,0 +1,92 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * This code defines the glue layer between softoken and the legacy DB library
+ */
+#include "sdb.h"
+
+/*
+ * function prototypes for the callbacks into softoken from the legacyDB
+ */
+
+typedef SECStatus (*LGEncryptFunc)(PRArenaPool *arena, SDB *sdb,
+ SECItem *plainText, SECItem **cipherText);
+typedef SECStatus (*LGDecryptFunc)(SDB *sdb, SECItem *cipherText,
+ SECItem **plainText);
+
+/*
+ * function prototypes for the exported functions.
+ */
+typedef CK_RV (*LGOpenFunc) (const char *dir, const char *certPrefix,
+ const char *keyPrefix,
+ int certVersion, int keyVersion, int flags,
+ SDB **certDB, SDB **keyDB);
+typedef char ** (*LGReadSecmodFunc)(const char *appName,
+ const char *filename,
+ const char *dbname, char *params, PRBool rw);
+typedef SECStatus (*LGReleaseSecmodFunc)(const char *appName,
+ const char *filename,
+ const char *dbname, char **params, PRBool rw);
+typedef SECStatus (*LGDeleteSecmodFunc)(const char *appName,
+ const char *filename,
+ const char *dbname, char *params, PRBool rw);
+typedef SECStatus (*LGAddSecmodFunc)(const char *appName,
+ const char *filename,
+ const char *dbname, char *params, PRBool rw);
+typedef SECStatus (*LGShutdownFunc)(void);
+typedef void (*LGSetCryptFunc)(LGEncryptFunc, LGDecryptFunc);
+
+
+/*
+ * Softoken Glue Functions
+ */
+CK_RV sftkdbCall_open(const char *dir, const char *certPrefix,
+ const char *keyPrefix,
+ int certVersion, int keyVersion, int flags,
+ SDB **certDB, SDB **keyDB);
+char ** sftkdbCall_ReadSecmodDB(const char *appName, const char *filename,
+ const char *dbname, char *params, PRBool rw);
+SECStatus sftkdbCall_ReleaseSecmodDBData(const char *appName,
+ const char *filename, const char *dbname,
+ char **moduleSpecList, PRBool rw);
+SECStatus sftkdbCall_DeleteSecmodDB(const char *appName,
+ const char *filename, const char *dbname,
+ char *args, PRBool rw);
+SECStatus sftkdbCall_AddSecmodDB(const char *appName,
+ const char *filename, const char *dbname,
+ char *module, PRBool rw);
+CK_RV sftkdbCall_Shutdown(void);
+
diff --git a/security/nss/lib/softoken/lowkey.c b/security/nss/lib/softoken/lowkey.c
index 9c984b4d3..8772d024d 100644
--- a/security/nss/lib/softoken/lowkey.c
+++ b/security/nss/lib/softoken/lowkey.c
@@ -40,15 +40,41 @@
#include "secder.h"
#include "base64.h"
#include "secasn1.h"
-#include "pcert.h"
#include "secerr.h"
#ifdef NSS_ENABLE_ECC
-extern SECStatus EC_CopyParams(PRArenaPool *arena,
- ECParams *dstParams,
- const ECParams *srcParams);
+#include "softoken.h"
#endif
+const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWKEYAttribute) },
+ { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
+ { SEC_ASN1_SET_OF, offsetof(NSSLOWKEYAttribute, attrValue),
+ SEC_AnyTemplate },
+ { 0 }
+};
+
+const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
+};
+/* ASN1 Templates for new decoder/encoder */
+const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
+ { SEC_ASN1_INTEGER,
+ offsetof(NSSLOWKEYPrivateKeyInfo,version) },
+ { SEC_ASN1_INLINE,
+ offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
+ SECOID_AlgorithmIDTemplate },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+ offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
+ nsslowkey_SetOfAttributeTemplate },
+ { 0 }
+};
+
const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
{ SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
diff --git a/security/nss/lib/softoken/lowkeyi.h b/security/nss/lib/softoken/lowkeyi.h
index b32a0f0af..9c13bfa10 100644
--- a/security/nss/lib/softoken/lowkeyi.h
+++ b/security/nss/lib/softoken/lowkeyi.h
@@ -42,7 +42,6 @@
#include "prtypes.h"
#include "seccomon.h"
#include "secoidt.h"
-#include "pcertt.h"
#include "lowkeyti.h"
SEC_BEGIN_PROTOS
@@ -65,89 +64,6 @@ extern void prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_ecparams_for_asn1(ECParams *params);
#endif /* NSS_ENABLE_ECC */
-typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion);
-
-/*
-** Open a key database.
-*/
-extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDB(PRBool readOnly,
- const char *domain,
- const char *prefix,
- NSSLOWKEYDBNameFunc namecb,
- void *cbarg);
-
-
-/*
- * Clear out all the keys in the existing database
- */
-extern SECStatus nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle);
-
-/*
-** Close the specified key database.
-*/
-extern void nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle);
-
-/*
- * Get the version number of the database
- */
-extern int nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle);
-
-/*
-** Support a default key database.
-*/
-extern void nsslowkey_SetDefaultKeyDB(NSSLOWKEYDBHandle *handle);
-extern NSSLOWKEYDBHandle *nsslowkey_GetDefaultKeyDB(void);
-
-/* set the alg id of the key encryption algorithm */
-extern void nsslowkey_SetDefaultKeyDBAlg(SECOidTag alg);
-
-/*
- * given a password and salt, produce a hash of the password
- */
-extern SECItem *nsslowkey_HashPassword(char *pw, SECItem *salt);
-
-/*
- * Derive the actual password value for a key database from the
- * password string value. The derivation uses global salt value
- * stored in the key database.
- */
-extern SECItem *
-nsslowkey_DeriveKeyDBPassword(NSSLOWKEYDBHandle *handle, char *pw);
-
-/*
-** Delete a key from the database
-*/
-extern SECStatus nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle,
- SECItem *pubkey);
-
-/*
-** Store a key in the database, indexed by its public key modulus.
-** "pk" is the private key to store
-** "f" is a the callback function for getting the password
-** "arg" is the argument for the callback
-*/
-extern SECStatus nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
- NSSLOWKEYPrivateKey *pk,
- SECItem *pubKeyData,
- char *nickname,
- SECItem *arg);
-
-/* does the key for this cert exist in the database filed by modulus */
-extern PRBool nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle,
- NSSLOWCERTCertificate *cert);
-/* does a key with this ID already exist? */
-extern PRBool nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id);
-
-
-extern SECStatus nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle);
-extern SECStatus nsslowkey_SetKeyDBPassword(NSSLOWKEYDBHandle *handle,
- SECItem *pwitem);
-extern SECStatus nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle,
- SECItem *pwitem);
-extern SECStatus nsslowkey_ChangeKeyDBPassword(NSSLOWKEYDBHandle *handle,
- SECItem *oldpwitem,
- SECItem *newpwitem);
-
/*
** Destroy a private key object.
** "key" the object
@@ -180,88 +96,6 @@ extern unsigned int nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privKey);
extern NSSLOWKEYPublicKey
*nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privateKey);
-/*
- * Set the Key Database password.
- * handle is a handle to the key database
- * pwitem is the new password
- * algorithm is the algorithm by which the key database
- * password is to be encrypted.
- * On failure, SECFailure is returned, otherwise SECSuccess is
- * returned.
- */
-extern SECStatus
-nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
- SECItem *pwitem,
- SECOidTag algorithm);
-
-/* Check the key database password.
- * handle is a handle to the key database
- * pwitem is the suspect password
- * algorithm is the algorithm by which the key database
- * password is to be encrypted.
- * The password is checked against plaintext to see if it is the
- * actual password. If it is not, SECFailure is returned.
- */
-extern SECStatus
-nsslowkey_CheckKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
- SECItem *pwitem,
- SECOidTag algorithm);
-
-/* Change the key database password and/or algorithm by which
- * the password is stored with.
- * handle is a handle to the key database
- * old_pwitem is the current password
- * new_pwitem is the new password
- * old_algorithm is the algorithm by which the key database
- * password is currently encrypted.
- * new_algorithm is the algorithm with which the new password
- * is to be encrypted.
- * A return of anything but SECSuccess indicates failure.
- */
-extern SECStatus
-nsslowkey_ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
- SECItem *oldpwitem, SECItem *newpwitem,
- SECOidTag old_algorithm);
-
-SECStatus
-nsslowkey_UpdateNickname(NSSLOWKEYDBHandle *handle,
- NSSLOWKEYPrivateKey *privkey,
- SECItem *pubKeyData,
- char *nickname,
- SECItem *arg);
-
-/* Store key by modulus and specify an encryption algorithm to use.
- * handle is the pointer to the key database,
- * privkey is the private key to be stored,
- * f and arg are the function and arguments to the callback
- * to get a password,
- * algorithm is the algorithm which the privKey is to be stored.
- * A return of anything but SECSuccess indicates failure.
- */
-extern SECStatus
-nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
- NSSLOWKEYPrivateKey *privkey,
- SECItem *pubKeyData,
- char *nickname,
- SECItem *arg,
- SECOidTag algorithm,
- PRBool update);
-
-/* Find key by modulus. This function is the inverse of store key
- * by modulus. An attempt to locate the key with "modulus" is
- * performed. If the key is found, the private key is returned,
- * else NULL is returned.
- * modulus is the modulus to locate
- */
-extern NSSLOWKEYPrivateKey *
-nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
- SECItem *arg);
-
-extern char *
-nsslowkey_FindKeyNicknameByPublicKey(NSSLOWKEYDBHandle *handle,
- SECItem *modulus, SECItem *pwitem);
-
-
/* Make a copy of a low private key in it's own arena.
* a return of NULL indicates an error.
*/
diff --git a/security/nss/lib/softoken/lowkeyti.h b/security/nss/lib/softoken/lowkeyti.h
index 5423bdb7a..15bb9730a 100644
--- a/security/nss/lib/softoken/lowkeyti.h
+++ b/security/nss/lib/softoken/lowkeyti.h
@@ -43,31 +43,6 @@
#include "secitem.h"
#include "secasn1t.h"
#include "secoidt.h"
-/*#include "secmodt.h"
-#include "pkcs11t.h" */
-
-
-/*
- * a key in/for the data base
- */
-struct NSSLOWKEYDBKeyStr {
- PLArenaPool *arena;
- int version;
- char *nickname;
- SECItem salt;
- SECItem derPK;
-};
-typedef struct NSSLOWKEYDBKeyStr NSSLOWKEYDBKey;
-
-typedef struct NSSLOWKEYDBHandleStr NSSLOWKEYDBHandle;
-
-#ifdef NSS_USE_KEY4_DB
-#define NSSLOWKEY_DB_FILE_VERSION 4
-#else
-#define NSSLOWKEY_DB_FILE_VERSION 3
-#endif
-
-#define NSSLOWKEY_VERSION 0 /* what we *create* */
/*
** Typedef for callback to get a password "key".
@@ -109,17 +84,6 @@ struct NSSLOWKEYPrivateKeyInfoStr {
typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo;
#define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */
-/*
-** A PKCS#8 private key info object
-*/
-struct NSSLOWKEYEncryptedPrivateKeyInfoStr {
- PLArenaPool *arena;
- SECAlgorithmID algorithm;
- SECItem encryptedData;
-};
-typedef struct NSSLOWKEYEncryptedPrivateKeyInfoStr NSSLOWKEYEncryptedPrivateKeyInfo;
-
-
typedef enum {
NSSLOWKEYNullKey = 0,
NSSLOWKEYRSAKey = 1,
diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn
index 5df3a4517..a3d2f995f 100644
--- a/security/nss/lib/softoken/manifest.mn
+++ b/security/nss/lib/softoken/manifest.mn
@@ -37,6 +37,7 @@
CORE_DEPTH = ../../..
MODULE = nss
+DIRS = legacydb
REQUIRES = dbm
@@ -44,7 +45,7 @@ LIBRARY_NAME = softokn
LIBRARY_VERSION = 3
MAPFILE = $(OBJDIR)/softokn.def
-DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\" -DSHLIB_VERSION=\"$(LIBRARY_VERSION)\"
EXPORTS = \
@@ -54,37 +55,35 @@ EXPORTS = \
pkcs11t.h \
pkcs11n.h \
pkcs11u.h \
+ sdb.h \
+ sftkdbt.h \
$(NULL)
PRIVATE_EXPORTS = \
+ lgglue.h \
pk11pars.h \
pkcs11ni.h \
- lowkeyi.h \
- lowkeyti.h \
- pcertt.h \
softoken.h \
softoknt.h \
softkver.h \
$(NULL)
CSRCS = \
- dbinit.c \
- dbmshim.c \
ecdecode.c \
fipsaudt.c \
fipstest.c \
fipstokn.c \
- keydb.c \
- lowcert.c \
+ lgglue.c \
lowkey.c \
lowpbe.c \
padbuf.c \
- pcertdb.c \
- pk11db.c \
pkcs11.c \
pkcs11c.c \
pkcs11u.c \
rsawrapr.c \
+ sdb.c \
+ sftkdb.c \
+ sftkpars.c \
softkver.c \
tlsprf.c \
$(NULL)
@@ -93,3 +92,7 @@ ifdef NSS_ENABLE_ECC
DEFINES += -DNSS_ENABLE_ECC
endif
+ifdef SQLITE_UNSAFE_THREADS
+DEFINES += -DSQLITE_UNSAFE_THREADS
+endif
+
diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c
index eba10bf63..49e703ee1 100644
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -61,15 +61,14 @@
#include "blapi.h"
#include "secder.h"
#include "secport.h"
-#include "pcert.h"
#include "secrng.h"
+#include "nss.h"
+#include "prtypes.h"
+#include "nspr.h"
#include "softkver.h"
-#include "keydbi.h"
-
-#ifdef DEBUG
-#include "cdbhdl.h"
-#endif
+#include "sftkdb.h"
+#include "sftkpars.h"
/*
* ******************** Static data *******************************
@@ -86,7 +85,7 @@ static char libraryDescription_space[33];
* failure so that there are at most 60 login attempts per minute.
*/
static PRIntervalTime loginWaitTime;
-static PRUint32 minSessionObjectHandle = 1U;
+static PRUint32 minSessionObjectHandle = 1U;
#define __PASTE(x,y) x##y
@@ -353,12 +352,12 @@ static const struct mechanismList mechanisms[] = {
{CKM_AES_MAC_GENERAL, {16, 32, CKF_SN_VR}, PR_TRUE},
{CKM_AES_CBC_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
/* ------------------------- Camellia Operations --------------------- */
- {CKM_CAMELLIA_KEY_GEN, {16, 32, CKF_GENERATE}, PR_TRUE},
- {CKM_CAMELLIA_ECB, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAMELLIA_CBC, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAMELLIA_MAC, {16, 32, CKF_SN_VR}, PR_TRUE},
- {CKM_CAMELLIA_MAC_GENERAL, {16, 32, CKF_SN_VR}, PR_TRUE},
- {CKM_CAMELLIA_CBC_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
+ {CKM_CAMELLIA_KEY_GEN, {16, 32, CKF_GENERATE}, PR_TRUE},
+ {CKM_CAMELLIA_ECB, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
+ {CKM_CAMELLIA_CBC, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
+ {CKM_CAMELLIA_MAC, {16, 32, CKF_SN_VR}, PR_TRUE},
+ {CKM_CAMELLIA_MAC_GENERAL, {16, 32, CKF_SN_VR}, PR_TRUE},
+ {CKM_CAMELLIA_CBC_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
/* ------------------------- Hashing Operations ----------------------- */
{CKM_MD2, {0, 0, CKF_DIGEST}, PR_FALSE},
{CKM_MD2_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE},
@@ -538,22 +537,13 @@ sftk_configure(const char *man, const char *libdes)
* see if the key DB password is enabled
*/
static PRBool
-sftk_hasNullPassword(NSSLOWKEYDBHandle *keydb,SECItem **pwitem)
+sftk_hasNullPassword(SFTKDBHandle *keydb)
{
PRBool pwenabled;
-
+
pwenabled = PR_FALSE;
- *pwitem = NULL;
- if (nsslowkey_HasKeyDBPassword (keydb) == SECSuccess) {
- *pwitem = nsslowkey_HashPassword("", keydb->global_salt);
- if ( *pwitem ) {
- if (nsslowkey_CheckKeyDBPassword (keydb, *pwitem) == SECSuccess) {
- pwenabled = PR_TRUE;
- } else {
- SECITEM_ZfreeItem(*pwitem, PR_TRUE);
- *pwitem = NULL;
- }
- }
+ if (sftkdb_HasPasswordSet(keydb) == SECSuccess) {
+ return (sftkdb_CheckPassword(keydb, "") == SECSuccess);
}
return pwenabled;
@@ -661,124 +651,19 @@ sftk_handleCertObject(SFTKSession *session,SFTKObject *object)
if (sftk_isTrue(object,CKA_TOKEN)) {
SFTKSlot *slot = session->slot;
- SECItem derCert;
- NSSLOWCERTCertificate *cert;
- NSSLOWCERTCertTrust *trust = NULL;
- NSSLOWCERTCertTrust userTrust =
- { CERTDB_USER, CERTDB_USER, CERTDB_USER };
- NSSLOWCERTCertTrust defTrust =
- { CERTDB_TRUSTED_UNKNOWN,
- CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN };
- char *label = NULL;
- char *email = NULL;
- SECStatus rv;
- PRBool inDB = PR_TRUE;
- NSSLOWCERTCertDBHandle *certHandle = sftk_getCertDB(slot);
- NSSLOWKEYDBHandle *keyHandle = NULL;
+ SFTKDBHandle *certHandle = sftk_getCertDB(slot);
if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
- /* get the der cert */
- attribute = sftk_FindAttribute(object,CKA_VALUE);
- PORT_Assert(attribute);
- if (!attribute) {
- sftk_freeCertDB(certHandle);
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
-
- derCert.type = 0;
- derCert.data = (unsigned char *)attribute->attrib.pValue;
- derCert.len = attribute->attrib.ulValueLen ;
-
- label = sftk_getString(object,CKA_LABEL);
-
- cert = nsslowcert_FindCertByDERCert(certHandle, &derCert);
- if (cert == NULL) {
- cert = nsslowcert_DecodeDERCertificate(&derCert, label);
- inDB = PR_FALSE;
- }
- if (cert == NULL) {
- if (label) PORT_Free(label);
- sftk_FreeAttribute(attribute);
- sftk_freeCertDB(certHandle);
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
-
- keyHandle = sftk_getKeyDB(slot);
- if (keyHandle) {
- if (nsslowkey_KeyForCertExists(keyHandle,cert)) {
- trust = &userTrust;
- }
- sftk_freeKeyDB(keyHandle);
- }
-
- if (!inDB) {
- if (!trust) trust = &defTrust;
- rv = nsslowcert_AddPermCert(certHandle, cert, label, trust);
- } else {
- rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) :
- SECSuccess;
- }
-
- if (label) PORT_Free(label);
- sftk_FreeAttribute(attribute);
-
- if (rv != SECSuccess) {
- sftk_freeCertDB(certHandle);
- nsslowcert_DestroyCertificate(cert);
- return CKR_DEVICE_ERROR;
- }
-
- /*
- * Add a NULL S/MIME profile if necessary.
- */
- email = sftk_getString(object,CKA_NETSCAPE_EMAIL);
- if (email) {
- certDBEntrySMime *entry;
-
- entry = nsslowcert_ReadDBSMimeEntry(certHandle,email);
- if (!entry) {
- nsslowcert_SaveSMimeProfile(certHandle, email,
- &cert->derSubject, NULL, NULL);
- } else {
- nsslowcert_DestroyDBEntry((certDBEntry *)entry);
- }
- PORT_Free(email);
- }
- sftk_freeCertDB(certHandle);
- object->handle=sftk_mkHandle(slot,&cert->certKey,SFTK_TOKEN_TYPE_CERT);
- nsslowcert_DestroyCertificate(cert);
+ crv = sftkdb_write(certHandle, object, &object->handle);
+ sftk_freeDB(certHandle);
+ return crv;
}
return CKR_OK;
}
-
-unsigned int
-sftk_MapTrust(CK_TRUST trust, PRBool clientAuth)
-{
- unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA :
- CERTDB_TRUSTED_CA;
- switch (trust) {
- case CKT_NETSCAPE_TRUSTED:
- return CERTDB_VALID_PEER|CERTDB_TRUSTED;
- case CKT_NETSCAPE_TRUSTED_DELEGATOR:
- return CERTDB_VALID_CA|trustCA;
- case CKT_NETSCAPE_UNTRUSTED:
- return CERTDB_NOT_TRUSTED;
- case CKT_NETSCAPE_MUST_VERIFY:
- return 0;
- case CKT_NETSCAPE_VALID: /* implies must verify */
- return CERTDB_VALID_PEER;
- case CKT_NETSCAPE_VALID_DELEGATOR: /* implies must verify */
- return CERTDB_VALID_CA;
- default:
- break;
- }
- return CERTDB_TRUSTED_UNKNOWN;
-}
-
/*
* check the consistancy and initialize a Trust Object
@@ -786,8 +671,6 @@ sftk_MapTrust(CK_TRUST trust, PRBool clientAuth)
static CK_RV
sftk_handleTrustObject(SFTKSession *session,SFTKObject *object)
{
- NSSLOWCERTIssuerAndSN issuerSN;
-
/* we can't store any certs private */
if (sftk_isTrue(object,CKA_PRIVATE)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
@@ -809,109 +692,16 @@ sftk_handleTrustObject(SFTKSession *session,SFTKObject *object)
if (sftk_isTrue(object,CKA_TOKEN)) {
SFTKSlot *slot = session->slot;
- SFTKAttribute *issuer = NULL;
- SFTKAttribute *serial = NULL;
- NSSLOWCERTCertificate *cert = NULL;
- SFTKAttribute *trust;
- CK_TRUST sslTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
- CK_TRUST clientTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
- CK_TRUST emailTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
- CK_TRUST signTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
- CK_BBOOL stepUp;
- NSSLOWCERTCertTrust dbTrust = { 0 };
- SECStatus rv;
- NSSLOWCERTCertDBHandle *certHandle = sftk_getCertDB(slot);
+ SFTKDBHandle *certHandle = sftk_getCertDB(slot);
+ CK_RV crv;
if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
- issuer = sftk_FindAttribute(object,CKA_ISSUER);
- serial = sftk_FindAttribute(object,CKA_SERIAL_NUMBER);
-
- PORT_Assert(issuer && serial);
- if (issuer && serial) {
- issuerSN.derIssuer.data = (unsigned char *)issuer->attrib.pValue;
- issuerSN.derIssuer.len = issuer->attrib.ulValueLen ;
-
- issuerSN.serialNumber.data = (unsigned char *)serial->attrib.pValue;
- issuerSN.serialNumber.len = serial->attrib.ulValueLen ;
-
- cert = nsslowcert_FindCertByIssuerAndSN(certHandle,&issuerSN);
- }
- if (issuer) sftk_FreeAttribute(issuer);
- if (serial) sftk_FreeAttribute(serial);
-
- if (cert == NULL) {
- sftk_freeCertDB(certHandle);
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
-
- trust = sftk_FindAttribute(object,CKA_TRUST_SERVER_AUTH);
- if (trust) {
- if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) {
- PORT_Memcpy(&sslTrust,trust->attrib.pValue, sizeof(sslTrust));
- }
- sftk_FreeAttribute(trust);
- }
- trust = sftk_FindAttribute(object,CKA_TRUST_CLIENT_AUTH);
- if (trust) {
- if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) {
- PORT_Memcpy(&clientTrust,trust->attrib.pValue,
- sizeof(clientTrust));
- }
- sftk_FreeAttribute(trust);
- }
- trust = sftk_FindAttribute(object,CKA_TRUST_EMAIL_PROTECTION);
- if (trust) {
- if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) {
- PORT_Memcpy(&emailTrust,trust->attrib.pValue,
- sizeof(emailTrust));
- }
- sftk_FreeAttribute(trust);
- }
- trust = sftk_FindAttribute(object,CKA_TRUST_CODE_SIGNING);
- if (trust) {
- if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) {
- PORT_Memcpy(&signTrust,trust->attrib.pValue,
- sizeof(signTrust));
- }
- sftk_FreeAttribute(trust);
- }
- stepUp = CK_FALSE;
- trust = sftk_FindAttribute(object,CKA_TRUST_STEP_UP_APPROVED);
- if (trust) {
- if (trust->attrib.ulValueLen == sizeof(CK_BBOOL)) {
- stepUp = *(CK_BBOOL*)trust->attrib.pValue;
- }
- sftk_FreeAttribute(trust);
- }
-
- /* preserve certain old fields */
- if (cert->trust) {
- dbTrust.sslFlags =
- cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS;
- dbTrust.emailFlags=
- cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS;
- dbTrust.objectSigningFlags =
- cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS;
- }
-
- dbTrust.sslFlags |= sftk_MapTrust(sslTrust,PR_FALSE);
- dbTrust.sslFlags |= sftk_MapTrust(clientTrust,PR_TRUE);
- dbTrust.emailFlags |= sftk_MapTrust(emailTrust,PR_FALSE);
- dbTrust.objectSigningFlags |= sftk_MapTrust(signTrust,PR_FALSE);
- if (stepUp) {
- dbTrust.sslFlags |= CERTDB_GOVT_APPROVED_CA;
- }
-
- rv = nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust);
- object->handle=sftk_mkHandle(slot,&cert->certKey,SFTK_TOKEN_TYPE_TRUST);
- nsslowcert_DestroyCertificate(cert);
- sftk_freeCertDB(certHandle);
- if (rv != SECSuccess) {
- return CKR_DEVICE_ERROR;
- }
+ crv = sftkdb_write(certHandle, object, &object->handle);
+ sftk_freeDB(certHandle);
+ return crv;
}
return CKR_OK;
@@ -939,16 +729,8 @@ sftk_handleSMimeObject(SFTKSession *session,SFTKObject *object)
if (sftk_isTrue(object,CKA_TOKEN)) {
SFTKSlot *slot = session->slot;
- SECItem derSubj,rawProfile,rawTime,emailKey;
- SECItem *pRawProfile = NULL;
- SECItem *pRawTime = NULL;
- char *email = NULL;
- SFTKAttribute *subject = NULL,
- *profile = NULL,
- *time = NULL;
- SECStatus rv;
- NSSLOWCERTCertDBHandle *certHandle;
- CK_RV ck_rv = CKR_OK;
+ SFTKDBHandle *certHandle;
+ CK_RV crv;
PORT_Assert(slot);
if (slot == NULL) {
@@ -960,63 +742,9 @@ sftk_handleSMimeObject(SFTKSession *session,SFTKObject *object)
return CKR_TOKEN_WRITE_PROTECTED;
}
- /* lookup SUBJECT */
- subject = sftk_FindAttribute(object,CKA_SUBJECT);
- PORT_Assert(subject);
- if (!subject) {
- ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
- goto loser;
- }
-
- derSubj.data = (unsigned char *)subject->attrib.pValue;
- derSubj.len = subject->attrib.ulValueLen ;
- derSubj.type = 0;
-
- /* lookup VALUE */
- profile = sftk_FindAttribute(object,CKA_VALUE);
- if (profile) {
- rawProfile.data = (unsigned char *)profile->attrib.pValue;
- rawProfile.len = profile->attrib.ulValueLen ;
- rawProfile.type = siBuffer;
- pRawProfile = &rawProfile;
- }
-
- /* lookup Time */
- time = sftk_FindAttribute(object,CKA_NETSCAPE_SMIME_TIMESTAMP);
- if (time) {
- rawTime.data = (unsigned char *)time->attrib.pValue;
- rawTime.len = time->attrib.ulValueLen ;
- rawTime.type = siBuffer;
- pRawTime = &rawTime;
- }
-
-
- email = sftk_getString(object,CKA_NETSCAPE_EMAIL);
- if (!email) {
- ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
- goto loser;
- }
-
- /* Store CRL by SUBJECT */
- rv = nsslowcert_SaveSMimeProfile(certHandle, email, &derSubj,
- pRawProfile,pRawTime);
- if (rv != SECSuccess) {
- ck_rv = CKR_DEVICE_ERROR;
- goto loser;
- }
- emailKey.data = (unsigned char *)email;
- emailKey.len = PORT_Strlen(email)+1;
-
- object->handle = sftk_mkHandle(slot, &emailKey, SFTK_TOKEN_TYPE_SMIME);
-
-loser:
- sftk_freeCertDB(certHandle);
- if (subject) sftk_FreeAttribute(subject);
- if (profile) sftk_FreeAttribute(profile);
- if (time) sftk_FreeAttribute(time);
- if (email) PORT_Free(email);
-
- return ck_rv;
+ crv = sftkdb_write(certHandle, object, &object->handle);
+ sftk_freeDB(certHandle);
+ return crv;
}
return CKR_OK;
@@ -1044,61 +772,16 @@ sftk_handleCrlObject(SFTKSession *session,SFTKObject *object)
if (sftk_isTrue(object,CKA_TOKEN)) {
SFTKSlot *slot = session->slot;
- PRBool isKRL = PR_FALSE;
- SECItem derSubj,derCrl;
- char *url = NULL;
- SFTKAttribute *subject,*crl;
- SECStatus rv;
- NSSLOWCERTCertDBHandle *certHandle;
-
- PORT_Assert(slot);
- certHandle = sftk_getCertDB(slot);
+ SFTKDBHandle *certHandle = sftk_getCertDB(slot);
+ CK_RV crv;
if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
- /* lookup SUBJECT */
- subject = sftk_FindAttribute(object,CKA_SUBJECT);
- PORT_Assert(subject);
- if (!subject) {
- sftk_freeCertDB(certHandle);
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
-
- derSubj.data = (unsigned char *)subject->attrib.pValue;
- derSubj.len = subject->attrib.ulValueLen ;
-
- /* lookup VALUE */
- crl = sftk_FindAttribute(object,CKA_VALUE);
- PORT_Assert(crl);
- derCrl.data = (unsigned char *)crl->attrib.pValue;
- derCrl.len = crl->attrib.ulValueLen ;
-
-
- url = sftk_getString(object,CKA_NETSCAPE_URL);
- isKRL = sftk_isTrue(object,CKA_NETSCAPE_KRL);
-
- /* Store CRL by SUBJECT */
- rv = nsslowcert_AddCrl(certHandle, &derCrl, &derSubj, url, isKRL);
- sftk_freeCertDB(certHandle);
-
- if (url) {
- PORT_Free(url);
- }
- sftk_FreeAttribute(crl);
- if (rv != SECSuccess) {
- sftk_FreeAttribute(subject);
- return CKR_DEVICE_ERROR;
- }
-
- /* if we overwrote the existing CRL, poison the handle entry so we get
- * a new object handle */
- (void) sftk_poisonHandle(slot, &derSubj,
- isKRL ? SFTK_TOKEN_KRL_HANDLE : SFTK_TOKEN_TYPE_CRL);
- object->handle = sftk_mkHandle(slot, &derSubj,
- isKRL ? SFTK_TOKEN_KRL_HANDLE : SFTK_TOKEN_TYPE_CRL);
- sftk_FreeAttribute(subject);
+ crv = sftkdb_write(certHandle, object, &object->handle);
+ sftk_freeDB(certHandle);
+ return crv;
}
return CKR_OK;
@@ -1218,37 +901,15 @@ sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
if (sftk_isTrue(object,CKA_TOKEN)) {
SFTKSlot *slot = session->slot;
- NSSLOWKEYPrivateKey *priv;
- SECItem pubKey;
- NSSLOWKEYDBHandle *keyHandle = NULL;
-
- crv = sftk_Attribute2SSecItem(NULL,&pubKey,object,pubKeyAttr);
- if (crv != CKR_OK) return crv;
+ SFTKDBHandle *certHandle = sftk_getCertDB(slot);
- PORT_Assert(pubKey.data);
- keyHandle = sftk_getKeyDB(slot);
- if (keyHandle == NULL) {
- PORT_Free(pubKey.data);
+ if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
- if (keyHandle->version != 3) {
- unsigned char buf[SHA1_LENGTH];
- SHA1_HashBuf(buf,pubKey.data,pubKey.len);
- PORT_Memcpy(pubKey.data,buf,sizeof(buf));
- pubKey.len = sizeof(buf);
- }
- /* make sure the associated private key already exists */
- /* only works if we are logged in */
- priv = nsslowkey_FindKeyByPublicKey(keyHandle, &pubKey, slot->password);
- sftk_freeKeyDB(keyHandle);
- if (priv == NULL) {
- PORT_Free(pubKey.data);
- return crv;
- }
- nsslowkey_DestroyPrivateKey(priv);
- object->handle = sftk_mkHandle(slot, &pubKey, SFTK_TOKEN_TYPE_PUB);
- PORT_Free(pubKey.data);
+ crv = sftkdb_write(certHandle, object, &object->handle);
+ sftk_freeDB(certHandle);
+ return crv;
}
return CKR_OK;
@@ -1313,10 +974,6 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
if ( !sftk_hasAttribute(object, CKA_SUBPRIME)) {
return CKR_TEMPLATE_INCOMPLETE;
}
- if (sftk_isTrue(object,CKA_TOKEN) &&
- !sftk_hasAttribute(object, CKA_NETSCAPE_DB)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
sign = CK_TRUE;
/* fall through */
case CKK_DH:
@@ -1341,10 +998,6 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
if ( !sftk_hasAttribute(object, CKA_VALUE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
- if (sftk_isTrue(object,CKA_TOKEN) &&
- !sftk_hasAttribute(object, CKA_NETSCAPE_DB)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
encrypt = CK_FALSE;
sign = CK_TRUE;
recover = CK_FALSE;
@@ -1384,65 +1037,26 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
if (sftk_isTrue(object,CKA_TOKEN)) {
SFTKSlot *slot = session->slot;
- NSSLOWKEYPrivateKey *privKey;
- char *label;
- SECStatus rv = SECSuccess;
- CK_RV crv = CKR_DEVICE_ERROR;
- SECItem pubKey;
- NSSLOWKEYDBHandle *keyHandle = sftk_getKeyDB(slot);
+ SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
+ CK_RV crv;
if (keyHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
- privKey=sftk_mkPrivKey(object,key_type,&crv);
- if (privKey == NULL) return crv;
- label = sftk_getString(object,CKA_LABEL);
-
- crv = sftk_Attribute2SSecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
- if (crv != CKR_OK) {
- crv = CKR_TEMPLATE_INCOMPLETE;
- rv = SECFailure;
- goto fail;
- }
- if (keyHandle->version != 3) {
- unsigned char buf[SHA1_LENGTH];
- SHA1_HashBuf(buf,pubKey.data,pubKey.len);
- PORT_Memcpy(pubKey.data,buf,sizeof(buf));
- pubKey.len = sizeof(buf);
- }
-
- if (key_type == CKK_RSA) {
- rv = RSA_PrivateKeyCheck(&privKey->u.rsa);
- if (rv == SECFailure) {
- goto fail;
- }
- }
- rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey,
- label, slot->password);
-
-fail:
- sftk_freeKeyDB(keyHandle);
- if (label) PORT_Free(label);
- object->handle = sftk_mkHandle(slot,&pubKey,SFTK_TOKEN_TYPE_PRIV);
- if (pubKey.data) PORT_Free(pubKey.data);
- nsslowkey_DestroyPrivateKey(privKey);
- if (rv != SECSuccess) return crv;
+ crv = sftkdb_write(keyHandle, object, &object->handle);
+ sftk_freeDB(keyHandle);
+ return crv;
} else {
object->objectInfo = sftk_mkPrivKey(object,key_type,&crv);
if (object->objectInfo == NULL) return crv;
object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey;
- /* now NULL out the sensitive attributes */
- /* remove nulled out attributes for session objects. these only
- * applied to rsa private keys anyway (other private keys did not
- * get their attributes NULL'ed out */
}
return CKR_OK;
}
/* forward declare the DES formating function for handleSecretKey */
void sftk_FormatDESKey(unsigned char *key, int length);
-static NSSLOWKEYPrivateKey *sftk_mkSecretKeyRep(SFTKObject *object);
/* Validate secret key data, and set defaults */
static CK_RV
@@ -1535,57 +1149,6 @@ validateSecretKey(SFTKSession *session, SFTKObject *object,
return crv;
}
-#define SFTK_KEY_MAX_RETRIES 10 /* don't hang if we are having problems with the rng */
-#define SFTK_KEY_ID_SIZE 18 /* don't use either SHA1 or MD5 sizes */
-/*
- * Secret keys must have a CKA_ID value to be stored in the database. This code
- * will generate one if there wasn't one already.
- */
-static CK_RV
-sftk_GenerateSecretCKA_ID(NSSLOWKEYDBHandle *handle, SECItem *id, char *label)
-{
- unsigned int retries;
- SECStatus rv = SECSuccess;
- CK_RV crv = CKR_OK;
-
- id->data = NULL;
- if (label) {
- id->data = (unsigned char *)PORT_Strdup(label);
- if (id->data == NULL) {
- return CKR_HOST_MEMORY;
- }
- id->len = PORT_Strlen(label)+1;
- if (!nsslowkey_KeyForIDExists(handle,id)) {
- return CKR_OK;
- }
- PORT_Free(id->data);
- id->data = NULL;
- id->len = 0;
- }
- id->data = (unsigned char *)PORT_Alloc(SFTK_KEY_ID_SIZE);
- if (id->data == NULL) {
- return CKR_HOST_MEMORY;
- }
- id->len = SFTK_KEY_ID_SIZE;
-
- retries = 0;
- do {
- rv = RNG_GenerateGlobalRandomBytes(id->data,id->len);
- } while (rv == SECSuccess && nsslowkey_KeyForIDExists(handle,id) &&
- (++retries <= SFTK_KEY_MAX_RETRIES));
-
- if ((rv != SECSuccess) || (retries > SFTK_KEY_MAX_RETRIES)) {
- if (rv != SECSuccess) {
- sftk_fatalError = PR_TRUE;
- }
- crv = CKR_DEVICE_ERROR; /* random number generator is bad */
- PORT_Free(id->data);
- id->data = NULL;
- id->len = 0;
- }
- return crv;
-}
-
/*
* check the consistancy and initialize a Secret Key Object
*/
@@ -1594,12 +1157,6 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object,
CK_KEY_TYPE key_type, PRBool isFIPS)
{
CK_RV crv;
- NSSLOWKEYPrivateKey *privKey = NULL;
- NSSLOWKEYDBHandle *keyHandle = NULL;
- SECItem pubKey;
- char *label = NULL;
-
- pubKey.data = 0;
/* First validate and set defaults */
crv = validateSecretKey(session, object, key_type, isFIPS);
@@ -1608,53 +1165,19 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object,
/* If the object is a TOKEN object, store in the database */
if (sftk_isTrue(object,CKA_TOKEN)) {
SFTKSlot *slot = session->slot;
- SECStatus rv = SECSuccess;
- keyHandle = sftk_getKeyDB(slot);
+ SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
+ CK_RV crv;
if (keyHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
- label = sftk_getString(object,CKA_LABEL);
-
- crv = sftk_Attribute2SecItem(NULL, &pubKey, object, CKA_ID);
- /* Should this be ID? */
- if (crv != CKR_OK) goto loser;
-
- /* if we don't have an ID, generate one */
- if (pubKey.len == 0) {
- if (pubKey.data) {
- PORT_Free(pubKey.data);
- pubKey.data = NULL;
- }
- crv = sftk_GenerateSecretCKA_ID(keyHandle, &pubKey, label);
- if (crv != CKR_OK) goto loser;
-
- crv = sftk_forceAttribute(object, CKA_ID, pubKey.data, pubKey.len);
- if (crv != CKR_OK) goto loser;
- }
-
- privKey = sftk_mkSecretKeyRep(object);
- if (privKey == NULL) {
- crv = CKR_HOST_MEMORY;
- goto loser;
- }
-
- rv = nsslowkey_StoreKeyByPublicKey(keyHandle,
- privKey, &pubKey, label, slot->password);
- if (rv != SECSuccess) {
- crv = CKR_DEVICE_ERROR;
- goto loser;
- }
-
- object->handle = sftk_mkHandle(slot,&pubKey,SFTK_TOKEN_TYPE_KEY);
+ crv = sftkdb_write(keyHandle, object, &object->handle);
+ sftk_freeDB(keyHandle);
+ return crv;
}
loser:
- if (keyHandle) sftk_freeKeyDB(keyHandle);
- if (label) PORT_Free(label);
- if (privKey) nsslowkey_DestroyPrivateKey(privKey);
- if (pubKey.data) PORT_Free(pubKey.data);
return crv;
}
@@ -2071,7 +1594,7 @@ sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
CK_RV crv = CKR_OK;
SECStatus rv;
- PORT_Assert(!sftk_isToken(object->handle));
+ /*PORT_Assert(!sftk_isToken(object->handle)); */
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
*crvp = CKR_HOST_MEMORY;
@@ -2116,7 +1639,7 @@ sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
CKA_COEFFICIENT);
if (crv != CKR_OK) break;
rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
- NSSLOWKEY_VERSION);
+ NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
break;
@@ -2221,6 +1744,7 @@ sftk_GetPrivKey(SFTKObject *object,CK_KEY_TYPE key_type, CK_RV *crvp)
return (NSSLOWKEYPrivateKey *)object->objectInfo;
}
+#ifdef notdef
if (sftk_isToken(object->handle)) {
/* grab it from the data base */
SFTKTokenObject *to = sftk_narrowToTokenObject(object);
@@ -2231,6 +1755,9 @@ sftk_GetPrivKey(SFTKObject *object,CK_KEY_TYPE key_type, CK_RV *crvp)
} else {
priv = sftk_mkPrivKey(object, key_type, crvp);
}
+#else
+ priv = sftk_mkPrivKey(object, key_type, crvp);
+#endif
object->objectInfo = priv;
object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey;
return priv;
@@ -2296,104 +1823,6 @@ sftk_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type)
}
-/* make a fake private key representing a symmetric key */
-static NSSLOWKEYPrivateKey *
-sftk_mkSecretKeyRep(SFTKObject *object)
-{
- NSSLOWKEYPrivateKey *privKey = 0;
- PLArenaPool *arena = 0;
- CK_KEY_TYPE keyType;
- PRUint32 keyTypeStorage;
- SECItem keyTypeItem;
- CK_RV crv;
- SECStatus rv;
- static unsigned char derZero[1] = { 0 };
-
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
-
- privKey = (NSSLOWKEYPrivateKey *)
- PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
- if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
-
- privKey->arena = arena;
-
- /* Secret keys are represented in the database as "fake" RSA keys. The RSA key
- * is marked as a secret key representation by setting the public exponent field
- * to 0, which is an invalid RSA exponent. The other fields are set as follows:
- * modulus - CKA_ID value for the secret key
- * private exponent - CKA_VALUE (the key itself)
- * coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm
- * is used for the key.
- * all others - set to integer 0
- */
- privKey->keyType = NSSLOWKEYRSAKey;
-
- /* The modulus is set to the key id of the symmetric key */
- crv=sftk_Attribute2SecItem(arena,&privKey->u.rsa.modulus,object,CKA_ID);
- if (crv != CKR_OK) goto loser;
-
- /* The public exponent is set to 0 length to indicate a special key */
- privKey->u.rsa.publicExponent.len = sizeof derZero;
- privKey->u.rsa.publicExponent.data = derZero;
-
- /* The private exponent is the actual key value */
- crv=sftk_Attribute2SecItem(arena,&privKey->u.rsa.privateExponent,object,CKA_VALUE);
- if (crv != CKR_OK) goto loser;
-
- /* All other fields empty - needs testing */
- privKey->u.rsa.prime1.len = sizeof derZero;
- privKey->u.rsa.prime1.data = derZero;
-
- privKey->u.rsa.prime2.len = sizeof derZero;
- privKey->u.rsa.prime2.data = derZero;
-
- privKey->u.rsa.exponent1.len = sizeof derZero;
- privKey->u.rsa.exponent1.data = derZero;
-
- privKey->u.rsa.exponent2.len = sizeof derZero;
- privKey->u.rsa.exponent2.data = derZero;
-
- /* Coeficient set to KEY_TYPE */
- crv = sftk_GetULongAttribute(object, CKA_KEY_TYPE, &keyType);
- if (crv != CKR_OK) goto loser;
- /* on 64 bit platforms, we still want to store 32 bits of keyType (This is
- * safe since the PKCS #11 defines for all types are 32 bits or less). */
- keyTypeStorage = (PRUint32) keyType;
- keyTypeStorage = PR_htonl(keyTypeStorage);
- keyTypeItem.data = (unsigned char *)&keyTypeStorage;
- keyTypeItem.len = sizeof (keyTypeStorage);
- rv = SECITEM_CopyItem(arena, &privKey->u.rsa.coefficient, &keyTypeItem);
- if (rv != SECSuccess) {
- crv = CKR_HOST_MEMORY;
- goto loser;
- }
-
- /* Private key version field set normally for compatibility */
- rv = DER_SetUInteger(privKey->arena,
- &privKey->u.rsa.version, NSSLOWKEY_VERSION);
- if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; }
-
-loser:
- if (crv != CKR_OK) {
- PORT_FreeArena(arena,PR_FALSE);
- privKey = 0;
- }
-
- return privKey;
-}
-
-static PRBool
-isSecretKey(NSSLOWKEYPrivateKey *privKey)
-{
- if (privKey->keyType == NSSLOWKEYRSAKey &&
- privKey->u.rsa.publicExponent.len == 1 &&
- privKey->u.rsa.publicExponent.data[0] == 0)
- return PR_TRUE;
-
- return PR_FALSE;
-}
-
/**********************************************************************
*
* Start of PKCS 11 functions
@@ -2565,56 +1994,6 @@ sftk_RegisterSlot(SFTKSlot *slot, int moduleIndex)
return CKR_OK;
}
-typedef struct sftk_DBsStr {
- NSSLOWCERTCertDBHandle *certHandle;
- NSSLOWKEYDBHandle *keyHandle;
-} sftkDBs;
-
-static SECStatus
-sftk_set_user(NSSLOWCERTCertificate *cert, SECItem *dummy, void *arg)
-{
- sftkDBs *param = (sftkDBs *)arg;
- NSSLOWCERTCertTrust trust = *cert->trust;
-
- if (param->keyHandle &&
- nsslowkey_KeyForCertExists(param->keyHandle,cert)) {
- trust.sslFlags |= CERTDB_USER;
- trust.emailFlags |= CERTDB_USER;
- trust.objectSigningFlags |= CERTDB_USER;
- } else {
- trust.sslFlags &= ~CERTDB_USER;
- trust.emailFlags &= ~CERTDB_USER;
- trust.objectSigningFlags &= ~CERTDB_USER;
- }
-
- if (PORT_Memcmp(&trust,cert->trust, sizeof (trust)) != 0) {
- nsslowcert_ChangeCertTrust(param->certHandle, cert, &trust);
- }
-
- /* should check for email address and make sure we have an s/mime profile */
- return SECSuccess;
-}
-
-/*
- * this function fixes up old databases that may not have the CERTDB_USER
- * flags set correctly. it expects the owner already has references to
- * the cert and key handles.
- */
-static void
-sftk_DBVerify(NSSLOWCERTCertDBHandle *certHandle, NSSLOWKEYDBHandle *keyHandle)
-{
- /* walk through all the certs and check to see if there are any
- * user certs, and make sure there are s/mime profiles for all certs with
- * email addresses */
- sftkDBs param;
- param.certHandle = certHandle;
- param.keyHandle = keyHandle;
-
- nsslowcert_TraversePermCerts(certHandle, sftk_set_user, &param);
-
- return;
-}
-
/*
* ths function has all the common initialization that happens whenever we
@@ -2663,8 +2042,8 @@ SFTK_SlotReInit(SFTKSlot *slot,
sizeof(slot->tokDescription));
if ((!params->noCertDB) || (!params->noKeyDB)) {
- NSSLOWCERTCertDBHandle * certHandle = NULL;
- NSSLOWKEYDBHandle *keyHandle = NULL;
+ SFTKDBHandle * certHandle = NULL;
+ SFTKDBHandle *keyHandle = NULL;
crv = sftk_DBInit(params->configdir ? params->configdir : configdir,
params->certPrefix, params->keyPrefix, params->readOnly,
params->noCertDB, params->noKeyDB, params->forceOpen,
@@ -2673,16 +2052,13 @@ SFTK_SlotReInit(SFTKSlot *slot,
goto loser;
}
- if (nsslowcert_needDBVerify(certHandle)) {
- sftk_DBVerify(certHandle, keyHandle);
- }
slot->certDB = certHandle;
slot->keyDB = keyHandle;
}
if (needLogin) {
/* if the data base is initialized with a null password,remember that */
slot->needLogin =
- (PRBool)!sftk_hasNullPassword(slot->keyDB,&slot->password);
+ (PRBool)!sftk_hasNullPassword(slot->keyDB);
if ((params->minPW >= 0) && (params->minPW <= SFTK_MAX_PIN)) {
slot->minimumPinLen = params->minPW;
}
@@ -2794,16 +2170,21 @@ loser:
static CK_RV sft_CloseAllSession(SFTKSlot *slot)
{
- SECItem *pw = NULL;
SFTKSession *session;
unsigned int i;
+ SFTKDBHandle *handle;
+
/* first log out the card */
+ handle = sftk_getKeyDB(slot);
PZ_Lock(slot->slotLock);
- pw = slot->password;
slot->isLoggedIn = PR_FALSE;
- slot->password = NULL;
+ if (handle) {
+ sftkdb_ClearPassword(handle);
+ }
PZ_Unlock(slot->slotLock);
- if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
+ if (handle) {
+ sftk_freeDB(handle);
+ }
/* now close all the current sessions */
/* NOTE: If you try to open new sessions before NSC_CloseAllSessions
@@ -2852,8 +2233,8 @@ static CK_RV sft_CloseAllSession(SFTKSlot *slot)
static void
sftk_DBShutdown(SFTKSlot *slot)
{
- NSSLOWCERTCertDBHandle *certHandle;
- NSSLOWKEYDBHandle *keyHandle;
+ SFTKDBHandle *certHandle;
+ SFTKDBHandle *keyHandle;
PZ_Lock(slot->slotLock);
certHandle = slot->certDB;
slot->certDB = NULL;
@@ -2861,12 +2242,10 @@ sftk_DBShutdown(SFTKSlot *slot)
slot->keyDB = NULL;
PZ_Unlock(slot->slotLock);
if (certHandle) {
- PORT_Assert(certHandle->ref == 1 || slot->slotID > FIPS_SLOT_ID);
- sftk_freeCertDB(certHandle);
+ sftk_freeDB(certHandle);
}
if (keyHandle) {
- PORT_Assert(keyHandle->ref == 1 || slot->slotID > FIPS_SLOT_ID);
- sftk_freeKeyDB(keyHandle);
+ sftk_freeDB(keyHandle);
}
}
@@ -2961,26 +2340,27 @@ NSC_ModuleDBFunc(unsigned long function,char *parameters, void *args)
char *secmod = NULL;
char *appName = NULL;
char *filename = NULL;
+ SDBType dbType = SDB_LEGACY;
PRBool rw;
static char *success="Success";
char **rvstr = NULL;
- secmod = secmod_getSecmodName(parameters,&appName,&filename, &rw);
+ secmod = sftk_getSecmodName(parameters, &dbType, &appName,&filename, &rw);
switch (function) {
case SECMOD_MODULE_DB_FUNCTION_FIND:
- rvstr = secmod_ReadPermDB(appName,filename,secmod,(char *)parameters,rw);
+ rvstr = sftkdb_ReadSecmodDB(dbType,appName,filename,secmod,(char *)parameters,rw);
break;
case SECMOD_MODULE_DB_FUNCTION_ADD:
- rvstr = (secmod_AddPermDB(appName,filename,secmod,(char *)args,rw)
+ rvstr = (sftkdb_AddSecmodDB(dbType,appName,filename,secmod,(char *)args,rw)
== SECSuccess) ? &success: NULL;
break;
case SECMOD_MODULE_DB_FUNCTION_DEL:
- rvstr = (secmod_DeletePermDB(appName,filename,secmod,(char *)args,rw)
+ rvstr = (sftkdb_DeleteSecmodDB(dbType,appName,filename,secmod,(char *)args,rw)
== SECSuccess) ? &success: NULL;
break;
case SECMOD_MODULE_DB_FUNCTION_RELEASE:
- rvstr = (secmod_ReleasePermDBData(appName,filename,secmod,
+ rvstr = (sftkdb_ReleaseSecmodDBData(dbType, appName,filename,secmod,
(char **)args,rw) == SECSuccess) ? &success: NULL;
break;
}
@@ -3074,12 +2454,6 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
}
RNG_SystemInfoForRNG();
- rv = nsslowcert_InitLocks();
- if (rv != SECSuccess) {
- crv = CKR_DEVICE_ERROR;
- return crv;
- }
-
/* NOTE:
* we should be getting out mutexes from this list, not statically binding
@@ -3088,8 +2462,6 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
*/
/* initialize the key and cert db's */
- nsslowkey_SetDefaultKeyDBAlg
- (SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC);
if (init_args && (!(init_args->flags & CKF_OS_LOCKING_OK))) {
if (init_args->CreateMutex && init_args->DestroyMutex &&
init_args->LockMutex && init_args->UnlockMutex) {
@@ -3112,7 +2484,7 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
if ((init_args && init_args->LibraryParameters)) {
sftk_parameters paramStrings;
- crv = secmod_parseParameters
+ crv = sftk_parseParameters
((char *)init_args->LibraryParameters, &paramStrings, isFIPS);
if (crv != CKR_OK) {
return crv;
@@ -3145,7 +2517,7 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
}
}
loser:
- secmod_freeParams(&paramStrings);
+ sftk_freeParams(&paramStrings);
}
if (CKR_OK == crv) {
sftk_InitFreeLists();
@@ -3184,8 +2556,7 @@ CK_RV nsc_CommonFinalize (CK_VOID_PTR pReserved, PRBool isFIPS)
}
sftk_CleanupFreeLists();
- nsslowcert_DestroyFreeLists();
- nsslowcert_DestroyGlobalLocks();
+ sftkdb_Shutdown();
/* This function does not discard all our previously aquired entropy. */
RNG_RNGShutdown();
@@ -3286,21 +2657,12 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
* been changed underneath us.
*/
static PRBool
-sftk_checkNeedLogin(SFTKSlot *slot, NSSLOWKEYDBHandle *keyHandle)
+sftk_checkNeedLogin(SFTKSlot *slot, SFTKDBHandle *keyHandle)
{
- if (slot->password) {
- SECStatus rv;
- rv = nsslowkey_CheckKeyDBPassword(keyHandle,slot->password);
- if ( rv == SECSuccess) {
- return slot->needLogin;
- } else {
- SECITEM_FreeItem(slot->password, PR_TRUE);
- slot->password = NULL;
- slot->isLoggedIn = PR_FALSE;
- }
+ if (sftkdb_PWCached(keyHandle) == SECSuccess) {
+ return slot->needLogin;
}
- slot->needLogin =
- (PRBool)!sftk_hasNullPassword(keyHandle,&slot->password);
+ slot->needLogin = (PRBool)!sftk_hasNullPassword(keyHandle);
return (slot->needLogin);
}
@@ -3308,8 +2670,8 @@ sftk_checkNeedLogin(SFTKSlot *slot, NSSLOWKEYDBHandle *keyHandle)
* the system. */
CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
{
- SFTKSlot *slot;
- NSSLOWKEYDBHandle *handle;
+ SFTKSlot *slot;
+ SFTKDBHandle *handle;
if (!nsc_init && !nsf_init) return CKR_CRYPTOKI_NOT_INITIALIZED;
slot = sftk_SlotFromID(slotID, PR_FALSE);
@@ -3348,7 +2710,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
* (3) Finally we have an initialized password whicn is not NULL, and
* we will need to prompt for it.
*/
- if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) {
+ if (sftkdb_HasPasswordSet(handle) == SECFailure) {
pInfo->flags |= CKF_LOGIN_REQUIRED;
} else if (!sftk_checkNeedLogin(slot,handle)) {
pInfo->flags |= CKF_USER_PIN_INITIALIZED;
@@ -3361,9 +2723,14 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->ulFreePublicMemory = 1;
pInfo->ulTotalPrivateMemory = 1;
pInfo->ulFreePrivateMemory = 1;
+#ifdef SHDB_FIXME
pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION;
pInfo->hardwareVersion.minor = handle->version;
- sftk_freeKeyDB(handle);
+else
+ pInfo->hardwareVersion.major = 0;
+ pInfo->hardwareVersion.minor = 0;
+#endif
+ sftk_freeDB(handle);
}
/*
* CKF_LOGIN_REQUIRED CKF_USER_PIN_INITIALIZED how CKF_TOKEN_INITIALIZED
@@ -3468,31 +2835,12 @@ CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op)
return CKR_MECHANISM_INVALID;
}
-
-static SECStatus
-sftk_TurnOffUser(NSSLOWCERTCertificate *cert, SECItem *k, void *arg)
-{
- NSSLOWCERTCertTrust trust;
- SECStatus rv;
-
- rv = nsslowcert_GetCertTrust(cert,&trust);
- if (rv == SECSuccess && ((trust.emailFlags & CERTDB_USER) ||
- (trust.sslFlags & CERTDB_USER) ||
- (trust.objectSigningFlags & CERTDB_USER))) {
- trust.emailFlags &= ~CERTDB_USER;
- trust.sslFlags &= ~CERTDB_USER;
- trust.objectSigningFlags &= ~CERTDB_USER;
- nsslowcert_ChangeCertTrust(cert->dbhandle,cert,&trust);
- }
- return SECSuccess;
-}
-
/* NSC_InitToken initializes a token. */
CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
CK_ULONG ulPinLen,CK_CHAR_PTR pLabel) {
SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
- NSSLOWKEYDBHandle *handle;
- NSSLOWCERTCertDBHandle *certHandle;
+ SFTKDBHandle *handle;
+ SFTKDBHandle *certHandle;
SECStatus rv;
unsigned int i;
SFTKObject *object;
@@ -3534,8 +2882,8 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
return CKR_TOKEN_WRITE_PROTECTED;
}
- rv = nsslowkey_ResetKeyDB(handle);
- sftk_freeKeyDB(handle);
+ rv = sftkdb_ResetKeyDB(handle);
+ sftk_freeDB(handle);
if (rv != SECSuccess) {
return CKR_DEVICE_ERROR;
}
@@ -3544,8 +2892,7 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
certHandle = sftk_getCertDB(slot);
if (certHandle == NULL) return CKR_OK;
- nsslowcert_TraversePermCerts(certHandle,sftk_TurnOffUser, NULL);
- sftk_freeCertDB(certHandle);
+ sftk_freeDB(certHandle);
return CKR_OK; /*is this the right function for not implemented*/
}
@@ -3557,8 +2904,7 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
{
SFTKSession *sp = NULL;
SFTKSlot *slot;
- NSSLOWKEYDBHandle *handle = NULL;
- SECItem *newPin;
+ SFTKDBHandle *handle = NULL;
char newPinStr[SFTK_MAX_PIN+1];
SECStatus rv;
CK_RV crv = CKR_SESSION_HANDLE_INVALID;
@@ -3599,34 +2945,27 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
goto loser;
}
- if (nsslowkey_HasKeyDBPassword(handle) != SECFailure) {
+ if (sftkdb_HasPasswordSet(handle) != SECFailure) {
crv = CKR_DEVICE_ERROR;
goto loser;
}
/* convert to null terminated string */
- PORT_Memcpy(newPinStr,pPin,ulPinLen);
+ PORT_Memcpy(newPinStr, pPin, ulPinLen);
newPinStr[ulPinLen] = 0;
/* build the hashed pins which we pass around */
- newPin = nsslowkey_HashPassword(newPinStr,handle->global_salt);
- PORT_Memset(newPinStr,0,sizeof(newPinStr));
/* change the data base */
- rv = nsslowkey_SetKeyDBPassword(handle,newPin);
- sftk_freeKeyDB(handle);
+ rv = sftkdb_ChangePassword(handle, NULL, newPinStr);
+ sftk_freeDB(handle);
handle = NULL;
/* Now update our local copy of the pin */
if (rv == SECSuccess) {
- if (slot->password) {
- SECITEM_ZfreeItem(slot->password, PR_TRUE);
- }
- slot->password = newPin;
if (ulPinLen == 0) slot->needLogin = PR_FALSE;
return CKR_OK;
}
- SECITEM_ZfreeItem(newPin, PR_TRUE);
crv = CKR_PIN_INCORRECT;
loser:
@@ -3634,7 +2973,7 @@ loser:
sftk_FreeSession(sp);
}
if (handle) {
- sftk_freeKeyDB(handle);
+ sftk_freeDB(handle);
}
return crv;
}
@@ -3647,9 +2986,7 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
{
SFTKSession *sp = NULL;
SFTKSlot *slot;
- NSSLOWKEYDBHandle *handle = NULL;
- SECItem *newPin;
- SECItem *oldPin;
+ SFTKDBHandle *handle = NULL;
char newPinStr[SFTK_MAX_PIN+1],oldPinStr[SFTK_MAX_PIN+1];
SECStatus rv;
CK_RV crv = CKR_SESSION_HANDLE_INVALID;
@@ -3696,16 +3033,10 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
PORT_Memcpy(oldPinStr,pOldPin,ulOldLen);
oldPinStr[ulOldLen] = 0;
- /* build the hashed pins which we pass around */
- newPin = nsslowkey_HashPassword(newPinStr,handle->global_salt);
- oldPin = nsslowkey_HashPassword(oldPinStr,handle->global_salt);
- PORT_Memset(newPinStr,0,sizeof(newPinStr));
- PORT_Memset(oldPinStr,0,sizeof(oldPinStr));
-
/* change the data base password */
PR_Lock(slot->pwCheckLock);
- rv = nsslowkey_ChangeKeyDBPassword(handle,oldPin,newPin);
- sftk_freeKeyDB(handle);
+ rv = sftkdb_ChangePassword(handle, oldPinStr, newPinStr);
+ sftk_freeDB(handle);
handle = NULL;
if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) {
PR_Sleep(loginWaitTime);
@@ -3713,23 +3044,17 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
PR_Unlock(slot->pwCheckLock);
/* Now update our local copy of the pin */
- SECITEM_ZfreeItem(oldPin, PR_TRUE);
if (rv == SECSuccess) {
- if (slot->password) {
- SECITEM_ZfreeItem(slot->password, PR_TRUE);
- }
- slot->password = newPin;
slot->needLogin = (PRBool)(ulNewLen != 0);
return CKR_OK;
}
- SECITEM_ZfreeItem(newPin, PR_TRUE);
crv = CKR_PIN_INCORRECT;
loser:
if (sp) {
sftk_FreeSession(sp);
}
if (handle) {
- sftk_freeKeyDB(handle);
+ sftk_freeDB(handle);
}
return crv;
}
@@ -3791,7 +3116,6 @@ CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession)
{
SFTKSlot *slot;
SFTKSession *session;
- SECItem *pw = NULL;
PRBool sessionFound;
PZLock *lock;
@@ -3812,20 +3136,25 @@ CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession)
PZ_Unlock(lock);
if (sessionFound) {
+ SFTKDBHandle *handle;
+ handle = sftk_getKeyDB(slot);
PZ_Lock(slot->slotLock);
if (--slot->sessionCount == 0) {
- pw = slot->password;
slot->isLoggedIn = PR_FALSE;
- slot->password = NULL;
+ if (handle) {
+ sftkdb_ClearPassword(handle);
+ }
}
PZ_Unlock(slot->slotLock);
+ if (handle) {
+ sftk_freeDB(handle);
+ }
if (session->info.flags & CKF_RW_SESSION) {
PR_AtomicDecrement(&slot->rwSessionCount);
}
}
sftk_FreeSession(session);
- if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
return CKR_OK;
}
@@ -3863,11 +3192,10 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
{
SFTKSlot *slot;
SFTKSession *session;
- NSSLOWKEYDBHandle *handle;
+ SFTKDBHandle *handle;
CK_FLAGS sessionFlags;
SECStatus rv;
CK_RV crv;
- SECItem *pin;
char pinStr[SFTK_MAX_PIN+1];
@@ -3910,7 +3238,7 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
* password if and only if we haven't initialized the KEY DB yet.
* We only allow this on a RW session.
*/
- rv = nsslowkey_HasKeyDBPassword(handle);
+ rv = sftkdb_HasPasswordSet(handle);
if (rv == SECFailure) {
/* allow SSO's to log in only if there is not password on the
* key database */
@@ -3919,15 +3247,12 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
|| (slot->slotID == FIPS_SLOT_ID)) {
/* should this be a fixed password? */
if (ulPinLen == 0) {
- SECItem *pw;
+ sftkdb_ClearPassword(handle);
PZ_Lock(slot->slotLock);
- pw = slot->password;
- slot->password = NULL;
slot->isLoggedIn = PR_TRUE;
slot->ssoLoggedIn = (PRBool)(userType == CKU_SO);
PZ_Unlock(slot->slotLock);
sftk_update_all_states(slot);
- SECITEM_ZfreeItem(pw,PR_TRUE);
crv = CKR_OK;
goto done;
}
@@ -3946,39 +3271,28 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
/* build the hashed pins which we pass around */
- pin = nsslowkey_HashPassword(pinStr,handle->global_salt);
- if (pin == NULL) {
- crv = CKR_HOST_MEMORY;
- goto done;
- }
-
PR_Lock(slot->pwCheckLock);
- rv = nsslowkey_CheckKeyDBPassword(handle,pin);
- sftk_freeKeyDB(handle);
+ rv = sftkdb_CheckPassword(handle,pinStr);
+ sftk_freeDB(handle);
handle = NULL;
if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) {
PR_Sleep(loginWaitTime);
}
PR_Unlock(slot->pwCheckLock);
if (rv == SECSuccess) {
- SECItem *tmp;
PZ_Lock(slot->slotLock);
- tmp = slot->password;
slot->isLoggedIn = PR_TRUE;
- slot->password = pin;
PZ_Unlock(slot->slotLock);
- if (tmp) SECITEM_ZfreeItem(tmp, PR_TRUE);
/* update all sessions */
sftk_update_all_states(slot);
return CKR_OK;
}
- SECITEM_ZfreeItem(pin, PR_TRUE);
crv = CKR_PIN_INCORRECT;
done:
if (handle) {
- sftk_freeKeyDB(handle);
+ sftk_freeDB(handle);
}
return crv;
}
@@ -3988,7 +3302,7 @@ CK_RV NSC_Logout(CK_SESSION_HANDLE hSession)
{
SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
SFTKSession *session;
- SECItem *pw = NULL;
+ SFTKDBHandle *handle;
if (slot == NULL) {
return CKR_SESSION_HANDLE_INVALID;
@@ -4000,13 +3314,17 @@ CK_RV NSC_Logout(CK_SESSION_HANDLE hSession)
if (!slot->isLoggedIn) return CKR_USER_NOT_LOGGED_IN;
+ handle = sftk_getKeyDB(slot);
PZ_Lock(slot->slotLock);
- pw = slot->password;
slot->isLoggedIn = PR_FALSE;
slot->ssoLoggedIn = PR_FALSE;
- slot->password = NULL;
+ if (handle) {
+ sftkdb_ClearPassword(handle);
+ }
PZ_Unlock(slot->slotLock);
- if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
+ if (handle) {
+ sftk_freeDB(handle);
+ }
sftk_update_all_states(slot);
return CKR_OK;
@@ -4051,7 +3369,7 @@ static CK_RV sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
return CKR_TEMPLATE_INCOMPLETE;
}
paramString = (char *)attribute->attrib.pValue;
- crv = secmod_parseParameters(paramString, &paramStrings, isFIPS);
+ crv = sftk_parseParameters(paramString, &paramStrings, isFIPS);
if (crv != CKR_OK) {
goto loser;
}
@@ -4098,7 +3416,7 @@ static CK_RV sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
goto loser;
}
loser:
- secmod_freeParams(&paramStrings);
+ sftk_freeParams(&paramStrings);
sftk_FreeAttribute(attribute);
return crv;
@@ -4292,6 +3610,43 @@ CK_RV NSC_GetAttributeValue(CK_SESSION_HANDLE hSession,
return CKR_SESSION_HANDLE_INVALID;
}
+ /* short circuit everything for token objects */
+ if (sftk_isToken(hObject)) {
+ SFTKSlot *slot = sftk_SlotFromSession(session);
+ SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, hObject);
+ SFTKDBHandle *keydb = NULL;
+
+ if (dbHandle == NULL) {
+ sftk_FreeSession(session);
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ crv = sftkdb_GetAttributeValue(dbHandle, hObject, pTemplate, ulCount);
+
+ /* make sure we don't export any sensitive information */
+ keydb = sftk_getKeyDB(slot);
+ if (dbHandle == keydb) {
+ for (i=0; i < (int) ulCount; i++) {
+ if (sftk_isSensitive(pTemplate[i].type,CKO_PRIVATE_KEY)) {
+ crv = CKR_ATTRIBUTE_SENSITIVE;
+ if (pTemplate[i].pValue && (pTemplate[i].ulValueLen!= -1)){
+ PORT_Memset(pTemplate[i].pValue, 0,
+ pTemplate[i].ulValueLen);
+ }
+ pTemplate[i].ulValueLen = -1;
+ }
+ }
+ }
+
+ sftk_FreeSession(session);
+ sftk_freeDB(dbHandle);
+ if (keydb) {
+ sftk_freeDB(keydb);
+ }
+ return crv;
+ }
+
+ /* handle the session object */
object = sftk_ObjectFromHandle(hObject,session);
sftk_FreeSession(session);
if (object == NULL) {
@@ -4420,746 +3775,164 @@ CK_RV NSC_SetAttributeValue (CK_SESSION_HANDLE hSession,
return crv;
}
-/*
- * find any certs that may match the template and load them.
- */
-#define NSC_CERT 0x00000001
-#define NSC_TRUST 0x00000002
-#define NSC_CRL 0x00000004
-#define NSC_SMIME 0x00000008
-#define NSC_PRIVATE 0x00000010
-#define NSC_PUBLIC 0x00000020
-#define NSC_KEY 0x00000040
-
-/*
- * structure to collect key handles.
- */
-typedef struct sftkCrlDataStr {
- SFTKSlot *slot;
- SFTKSearchResults *searchHandles;
- CK_ATTRIBUTE *template;
- CK_ULONG templ_count;
-} sftkCrlData;
-
-
-static SECStatus
-sftk_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
-{
- sftkCrlData *crlData;
- CK_OBJECT_HANDLE class_handle;
- SFTKSlot *slot;
-
- crlData = (sftkCrlData *)arg;
- slot = crlData->slot;
-
- class_handle = (type == certDBEntryTypeRevocation) ? SFTK_TOKEN_TYPE_CRL :
- SFTK_TOKEN_KRL_HANDLE;
- if (sftk_tokenMatch(slot, key, class_handle,
- crlData->template, crlData->templ_count)) {
- sftk_addHandle(crlData->searchHandles,
- sftk_mkHandle(slot,key,class_handle));
- }
- return(SECSuccess);
-}
-
-static void
-sftk_searchCrls(SFTKSlot *slot, SECItem *derSubject, PRBool isKrl,
- unsigned long classFlags, SFTKSearchResults *search,
- CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
+static CK_RV
+sftk_expandSearchList(SFTKSearchResults *search, int count)
{
- NSSLOWCERTCertDBHandle *certHandle = NULL;
-
- certHandle = sftk_getCertDB(slot);
- if (certHandle == NULL) {
- return;
- }
- if (derSubject->data != NULL) {
- certDBEntryRevocation *crl =
- nsslowcert_FindCrlByKey(certHandle, derSubject, isKrl);
-
- if (crl != NULL) {
- sftk_addHandle(search, sftk_mkHandle(slot, derSubject,
- isKrl ? SFTK_TOKEN_KRL_HANDLE : SFTK_TOKEN_TYPE_CRL));
- nsslowcert_DestroyDBEntry((certDBEntry *)crl);
- }
- } else {
- sftkCrlData crlData;
-
- /* traverse */
- crlData.slot = slot;
- crlData.searchHandles = search;
- crlData.template = pTemplate;
- crlData.templ_count = ulCount;
- nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation,
- sftk_crl_collect, (void *)&crlData);
- nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation,
- sftk_crl_collect, (void *)&crlData);
- }
- sftk_freeCertDB(certHandle);
+ search->array_size += count;
+ search->handles = (CK_OBJECT_HANDLE *)PORT_Realloc(search->handles,
+ sizeof(CK_OBJECT_HANDLE)*search->array_size);
+ return search->handles ? CKR_OK : CKR_HOST_MEMORY;
}
-/*
- * structure to collect key handles.
- */
-typedef struct sftkKeyDataStr {
- SFTKSlot *slot;
- NSSLOWKEYDBHandle *keyHandle;
- SFTKSearchResults *searchHandles;
- SECItem *id;
- CK_ATTRIBUTE *template;
- CK_ULONG templ_count;
- unsigned long classFlags;
- PRBool isLoggedIn;
- PRBool strict;
-} sftkKeyData;
-
-static SECStatus
-sftk_key_collect(DBT *key, DBT *data, void *arg)
-{
- sftkKeyData *keyData;
- NSSLOWKEYPrivateKey *privKey = NULL;
- SECItem tmpDBKey;
- SFTKSlot *slot;
-
- keyData = (sftkKeyData *)arg;
- slot = keyData->slot;
-
- tmpDBKey.data = key->data;
- tmpDBKey.len = key->size;
- tmpDBKey.type = siBuffer;
-
- PORT_Assert(keyData->keyHandle);
- if (!keyData->strict && keyData->id) {
- SECItem result;
- PRBool haveMatch= PR_FALSE;
- unsigned char hashKey[SHA1_LENGTH];
- result.data = hashKey;
- result.len = sizeof(hashKey);
-
- if (keyData->id->len == 0) {
- /* Make sure this isn't a NSC_KEY */
- privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle,
- &tmpDBKey, keyData->slot->password);
- if (privKey) {
- haveMatch = isSecretKey(privKey) ?
- (PRBool)(keyData->classFlags & NSC_KEY) != 0:
- (PRBool)(keyData->classFlags &
- (NSC_PRIVATE|NSC_PUBLIC)) != 0;
- nsslowkey_DestroyPrivateKey(privKey);
- }
- } else {
- SHA1_HashBuf( hashKey, key->data, key->size ); /* match id */
- haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
- if (!haveMatch && ((unsigned char *)key->data)[0] == 0) {
- /* This is a fix for backwards compatibility. The key
- * database indexes private keys by the public key, and
- * versions of NSS prior to 3.4 stored the public key as
- * a signed integer. The public key is now treated as an
- * unsigned integer, with no leading zero. In order to
- * correctly compute the hash of an old key, it is necessary
- * to fallback and detect the leading zero.
- */
- SHA1_HashBuf(hashKey,
- (unsigned char *)key->data + 1, key->size - 1);
- haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
- }
- }
- if (haveMatch) {
- if (keyData->classFlags & NSC_PRIVATE) {
- sftk_addHandle(keyData->searchHandles,
- sftk_mkHandle(slot,&tmpDBKey,SFTK_TOKEN_TYPE_PRIV));
- }
- if (keyData->classFlags & NSC_PUBLIC) {
- sftk_addHandle(keyData->searchHandles,
- sftk_mkHandle(slot,&tmpDBKey,SFTK_TOKEN_TYPE_PUB));
- }
- if (keyData->classFlags & NSC_KEY) {
- sftk_addHandle(keyData->searchHandles,
- sftk_mkHandle(slot,&tmpDBKey,SFTK_TOKEN_TYPE_KEY));
- }
- }
- return SECSuccess;
- }
- privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey,
- keyData->slot->password);
- if ( privKey == NULL ) {
- goto loser;
- }
-
- if (isSecretKey(privKey)) {
- if ((keyData->classFlags & NSC_KEY) &&
- sftk_tokenMatch(keyData->slot, &tmpDBKey, SFTK_TOKEN_TYPE_KEY,
- keyData->template, keyData->templ_count)) {
- sftk_addHandle(keyData->searchHandles,
- sftk_mkHandle(keyData->slot, &tmpDBKey, SFTK_TOKEN_TYPE_KEY));
- }
- } else {
- if ((keyData->classFlags & NSC_PRIVATE) &&
- sftk_tokenMatch(keyData->slot, &tmpDBKey, SFTK_TOKEN_TYPE_PRIV,
- keyData->template, keyData->templ_count)) {
- sftk_addHandle(keyData->searchHandles,
- sftk_mkHandle(keyData->slot,&tmpDBKey,SFTK_TOKEN_TYPE_PRIV));
- }
- if ((keyData->classFlags & NSC_PUBLIC) &&
- sftk_tokenMatch(keyData->slot, &tmpDBKey, SFTK_TOKEN_TYPE_PUB,
- keyData->template, keyData->templ_count)) {
- sftk_addHandle(keyData->searchHandles,
- sftk_mkHandle(keyData->slot, &tmpDBKey,SFTK_TOKEN_TYPE_PUB));
- }
- }
-
-loser:
- if ( privKey ) {
- nsslowkey_DestroyPrivateKey(privKey);
- }
- return(SECSuccess);
-}
-
-static void
-sftk_searchKeys(SFTKSlot *slot, SECItem *key_id, PRBool isLoggedIn,
- unsigned long classFlags, SFTKSearchResults *search, PRBool mustStrict,
- CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
+static CK_RV
+sftk_searchDatabase(SFTKDBHandle *handle, SFTKSearchResults *search,
+ const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
{
- NSSLOWKEYDBHandle *keyHandle = NULL;
- NSSLOWKEYPrivateKey *privKey;
- sftkKeyData keyData;
- PRBool found = PR_FALSE;
+ CK_RV crv;
+ int objectListSize = search->array_size-search->size;
+ CK_OBJECT_HANDLE *array = &search->handles[search->size];
+ SDBFind *find;
+ CK_ULONG count;
- keyHandle = sftk_getKeyDB(slot);
- if (keyHandle == NULL) {
- return;
- }
+ crv = sftkdb_FindObjectsInit(handle, pTemplate, ulCount, &find);
+ if (crv != CKR_OK)
+ return crv;
+ do {
+ crv = sftkdb_FindObjects(handle, find, array, objectListSize, &count);
+ if ((crv != CKR_OK) || (count == 0))
+ break;
+ search->size += count;
+ objectListSize -= count;
+ if (objectListSize > 0)
+ break;
+ crv = sftk_expandSearchList(search,NSC_SEARCH_BLOCK_SIZE);
+ objectListSize = NSC_SEARCH_BLOCK_SIZE;
+ array = &search->handles[search->size];
+ } while (crv == CKR_OK);
+ sftkdb_FindObjectsFinal(handle, find);
- if (key_id->data) {
- privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, slot->password);
- if (privKey) {
- if ((classFlags & NSC_KEY) && isSecretKey(privKey)) {
- sftk_addHandle(search,
- sftk_mkHandle(slot,key_id,SFTK_TOKEN_TYPE_KEY));
- found = PR_TRUE;
- }
- if ((classFlags & NSC_PRIVATE) && !isSecretKey(privKey)) {
- sftk_addHandle(search,
- sftk_mkHandle(slot,key_id,SFTK_TOKEN_TYPE_PRIV));
- found = PR_TRUE;
- }
- if ((classFlags & NSC_PUBLIC) && !isSecretKey(privKey)) {
- sftk_addHandle(search,
- sftk_mkHandle(slot,key_id,SFTK_TOKEN_TYPE_PUB));
- found = PR_TRUE;
- }
- nsslowkey_DestroyPrivateKey(privKey);
- }
- /* don't do the traversal if we have an up to date db */
- if (keyHandle->version != 3) {
- goto loser;
- }
- /* don't do the traversal if it can't possibly be the correct id */
- /* all soft token id's are SHA1_HASH_LEN's */
- if (key_id->len != SHA1_LENGTH) {
- goto loser;
- }
- if (found) {
- /* if we already found some keys, don't do the traversal */
- goto loser;
- }
- }
- keyData.slot = slot;
- keyData.keyHandle = keyHandle;
- keyData.searchHandles = search;
- keyData.id = key_id;
- keyData.template = pTemplate;
- keyData.templ_count = ulCount;
- keyData.isLoggedIn = isLoggedIn;
- keyData.classFlags = classFlags;
- keyData.strict = mustStrict ? mustStrict : NSC_STRICT;
-
- nsslowkey_TraverseKeys(keyHandle, sftk_key_collect, &keyData);
-loser:
- sftk_freeKeyDB(keyHandle);
-
+ return crv;
}
-/*
- * structure to collect certs into
+/* softoken used to search the SMimeEntries automatically instead of
+ * doing this in pk11wrap. This code should really be up in
+ * pk11wrap so that it will work with other tokens other than softoken.
*/
-typedef struct sftkCertDataStr {
- SFTKSlot *slot;
- int cert_count;
- int max_cert_count;
- NSSLOWCERTCertificate **certs;
- CK_ATTRIBUTE *template;
- CK_ULONG templ_count;
- unsigned long classFlags;
- PRBool strict;
-} sftkCertData;
-
-/*
- * collect all the certs from the traverse call.
- */
-static SECStatus
-sftk_cert_collect(NSSLOWCERTCertificate *cert,void *arg)
+CK_RV
+sftk_emailhack(SFTKSlot *slot, SFTKDBHandle *handle,
+ SFTKSearchResults *search, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
{
- sftkCertData *cd = (sftkCertData *)arg;
+ PRBool isCert = PR_FALSE;
+ int emailIndex = -1;
+ int i;
+ SFTKSearchResults smime_search;
+ CK_ATTRIBUTE smime_template[2];
+ CK_OBJECT_CLASS smime_class = CKO_NETSCAPE_SMIME;
+ SFTKAttribute *attribute = NULL;
+ SFTKObject *object = NULL;
+ CK_RV crv = CKR_OK;
- if (cert == NULL) {
- return SECSuccess;
- }
- if (cd->certs == NULL) {
- return SECFailure;
- }
+ smime_search.handles = NULL; /* paranoia, some one is bound to add a goto
+ * loser before this gets initialized */
- if (cd->strict) {
- if ((cd->classFlags & NSC_CERT) && !sftk_tokenMatch(cd->slot,
- &cert->certKey, SFTK_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) {
- return SECSuccess;
- }
- if ((cd->classFlags & NSC_TRUST) && !sftk_tokenMatch(cd->slot,
- &cert->certKey, SFTK_TOKEN_TYPE_TRUST,
- cd->template, cd->templ_count)) {
- return SECSuccess;
+ /* see if we are looking for email certs */
+ for (i=0; i < ulCount; i++) {
+ if (pTemplate[i].type == CKA_CLASS) {
+ if ((pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS) ||
+ (*(CK_OBJECT_CLASS *)pTemplate[i].pValue) != CKO_CERTIFICATE)) {
+ /* not a cert, skip out */
+ break;
+ }
+ isCert = PR_TRUE;
+ } else if (pTemplate[i].type == CKA_NETSCAPE_EMAIL) {
+ emailIndex = i;
+
}
+ if (isCert && (emailIndex != -1)) break;
}
- /* allocate more space if we need it. This should only happen in
- * the general traversal case */
- if (cd->cert_count >= cd->max_cert_count) {
- int size;
- cd->max_cert_count += NSC_CERT_BLOCK_SIZE;
- size = cd->max_cert_count * sizeof (NSSLOWCERTCertificate *);
- cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs,size);
- if (cd->certs == NULL) {
- return SECFailure;
- }
+ if (!isCert || (emailIndex == -1)) {
+ return CKR_OK;
}
- cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert);
- return SECSuccess;
-}
-
-/* provide impedence matching ... */
-static SECStatus
-sftk_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg)
-{
- return sftk_cert_collect(cert, arg);
-}
+ /* we are doing a cert and email search, find the SMimeEntry */
+ smime_template[0].type = CKA_CLASS;
+ smime_template[0].pValue = &smime_class;
+ smime_template[0].ulValueLen = sizeof(smime_class);
+ smime_template[1] = pTemplate[emailIndex];
-static void
-sftk_searchSingleCert(sftkCertData *certData,NSSLOWCERTCertificate *cert)
-{
- if (cert == NULL) {
- return;
- }
- if (certData->strict &&
- !sftk_tokenMatch(certData->slot, &cert->certKey, SFTK_TOKEN_TYPE_CERT,
- certData->template,certData->templ_count)) {
- nsslowcert_DestroyCertificate(cert);
- return;
+ smime_search.handles = (CK_OBJECT_HANDLE *)
+ PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE);
+ if (smime_search.handles == NULL) {
+ crv = CKR_HOST_MEMORY;
+ goto loser;
}
- certData->certs = (NSSLOWCERTCertificate **)
- PORT_Alloc(sizeof (NSSLOWCERTCertificate *));
- if (certData->certs == NULL) {
- nsslowcert_DestroyCertificate(cert);
- return;
+ smime_search.index = 0;
+ smime_search.size = 0;
+ smime_search.array_size = NSC_SEARCH_BLOCK_SIZE;
+
+ crv = sftk_searchDatabase(handle, &smime_search, smime_template, 2);
+ if (crv != CKR_OK || smime_search.size == 0) {
+ goto loser;
}
- certData->certs[0] = cert;
- certData->cert_count = 1;
-}
-
-static void
-sftk_CertSetupData(sftkCertData *certData,int count)
-{
- certData->max_cert_count = count;
- if (certData->max_cert_count <= 0) {
- return;
+ /* get the SMime subject */
+ object = sftk_NewTokenObject(slot, NULL, smime_search.handles[0]);
+ if (object == NULL) {
+ crv = CKR_HOST_MEMORY; /* is there any other reason for this failure? */
+ goto loser;
+ }
+ attribute = sftk_FindAttribute(object,CKA_SUBJECT);
+ if (attribute == NULL) {
+ crv = CKR_ATTRIBUTE_TYPE_INVALID;
+ goto loser;
}
- certData->certs = (NSSLOWCERTCertificate **)
- PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *));
- return;
-}
-
-static void
-sftk_searchCertsAndTrust(SFTKSlot *slot, SECItem *derCert, SECItem *name,
- SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN,
- SECItem *email,
- unsigned long classFlags, SFTKSearchResults *handles,
- CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
-{
- NSSLOWCERTCertDBHandle *certHandle = NULL;
- sftkCertData certData;
- int i;
-
- certHandle = sftk_getCertDB(slot);
- if (certHandle == NULL) return;
-
- certData.slot = slot;
- certData.max_cert_count = 0;
- certData.certs = NULL;
- certData.cert_count = 0;
- certData.template = pTemplate;
- certData.templ_count = ulCount;
- certData.classFlags = classFlags;
- certData.strict = NSC_STRICT;
-
-
- /*
- * Find the Cert.
- */
- if (derCert->data != NULL) {
- NSSLOWCERTCertificate *cert =
- nsslowcert_FindCertByDERCert(certHandle,derCert);
- sftk_searchSingleCert(&certData,cert);
- } else if (name->data != NULL) {
- char *tmp_name = (char*)PORT_Alloc(name->len+1);
- int count;
-
- if (tmp_name == NULL) {
- return;
- }
- PORT_Memcpy(tmp_name,name->data,name->len);
- tmp_name[name->len] = 0;
-
- count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name);
- sftk_CertSetupData(&certData,count);
- nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name,
- sftk_cert_collect, &certData);
- PORT_Free(tmp_name);
- } else if (derSubject->data != NULL) {
- int count;
-
- count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject);
- sftk_CertSetupData(&certData,count);
- nsslowcert_TraversePermCertsForSubject(certHandle,derSubject,
- sftk_cert_collect, &certData);
- } else if ((issuerSN->derIssuer.data != NULL) &&
- (issuerSN->serialNumber.data != NULL)) {
- if (classFlags & NSC_CERT) {
- NSSLOWCERTCertificate *cert =
- nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN);
-
- sftk_searchSingleCert(&certData,cert);
- }
- if (classFlags & NSC_TRUST) {
- NSSLOWCERTTrust *trust =
- nsslowcert_FindTrustByIssuerAndSN(certHandle, issuerSN);
-
- if (trust) {
- sftk_addHandle(handles,
- sftk_mkHandle(slot,&trust->dbKey,SFTK_TOKEN_TYPE_TRUST));
- nsslowcert_DestroyTrust(trust);
- }
- }
- } else if (email->data != NULL) {
- char *tmp_name = (char*)PORT_Alloc(email->len+1);
- certDBEntrySMime *entry = NULL;
-
- if (tmp_name == NULL) {
- return;
- }
- PORT_Memcpy(tmp_name,email->data,email->len);
- tmp_name[email->len] = 0;
-
- entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
- if (entry) {
- int count;
- SECItem *subjectName = &entry->subjectName;
- count = nsslowcert_NumPermCertsForSubject(certHandle, subjectName);
- sftk_CertSetupData(&certData,count);
- nsslowcert_TraversePermCertsForSubject(certHandle, subjectName,
- sftk_cert_collect, &certData);
+ /* now find the certs with that subject */
+ pTemplate[emailIndex] = attribute->attrib;
+ /* now add the appropriate certs to the search list */
+ crv = sftk_searchDatabase(handle, search, pTemplate, ulCount);
+ pTemplate[emailIndex] = smime_template[1]; /* restore the user's template*/
- nsslowcert_DestroyDBEntry((certDBEntry *)entry);
- }
- PORT_Free(tmp_name);
- } else {
- /* we aren't filtering the certs, we are working on all, so turn
- * on the strict filters. */
- certData.strict = PR_TRUE;
- sftk_CertSetupData(&certData,NSC_CERT_BLOCK_SIZE);
- nsslowcert_TraversePermCerts(certHandle, sftk_cert_collect2, &certData);
+loser:
+ if (attribute) {
+ sftk_FreeAttribute(attribute);
}
- sftk_freeCertDB(certHandle);
-
- /*
- * build the handles
- */
- for (i=0 ; i < certData.cert_count ; i++) {
- NSSLOWCERTCertificate *cert = certData.certs[i];
-
- /* if we filtered it would have been on the stuff above */
- if (classFlags & NSC_CERT) {
- sftk_addHandle(handles,
- sftk_mkHandle(slot,&cert->certKey,SFTK_TOKEN_TYPE_CERT));
- }
- if ((classFlags & NSC_TRUST) && nsslowcert_hasTrust(cert->trust)) {
- sftk_addHandle(handles,
- sftk_mkHandle(slot,&cert->certKey,SFTK_TOKEN_TYPE_TRUST));
- }
- nsslowcert_DestroyCertificate(cert);
+ if (object) {
+ sftk_FreeObject(object);
}
-
- if (certData.certs) PORT_Free(certData.certs);
- return;
-}
-
-static void
-sftk_searchSMime(SFTKSlot *slot, SECItem *email, SFTKSearchResults *handles,
- CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
-{
- NSSLOWCERTCertDBHandle *certHandle = NULL;
- certDBEntrySMime *entry;
-
- certHandle = sftk_getCertDB(slot);
- if (certHandle == NULL) return;
-
- if (email->data != NULL) {
- char *tmp_name = (char*)PORT_Alloc(email->len+1);
-
- if (tmp_name == NULL) {
- sftk_freeCertDB(certHandle);
- return;
- }
- PORT_Memcpy(tmp_name,email->data,email->len);
- tmp_name[email->len] = 0;
-
- entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
- if (entry) {
- SECItem emailKey;
-
- emailKey.data = (unsigned char *)tmp_name;
- emailKey.len = PORT_Strlen(tmp_name)+1;
- emailKey.type = 0;
- sftk_addHandle(handles,
- sftk_mkHandle(slot,&emailKey,SFTK_TOKEN_TYPE_SMIME));
- nsslowcert_DestroyDBEntry((certDBEntry *)entry);
- }
- PORT_Free(tmp_name);
+ if (smime_search.handles) {
+ PORT_Free(smime_search.handles);
}
- sftk_freeCertDB(certHandle);
- return;
+
+ return crv;
}
+
static CK_RV
sftk_searchTokenList(SFTKSlot *slot, SFTKSearchResults *search,
- CK_ATTRIBUTE *pTemplate, CK_LONG ulCount,
- PRBool *tokenOnly, PRBool isLoggedIn)
+ CK_ATTRIBUTE *pTemplate, CK_LONG ulCount,
+ PRBool *tokenOnly, PRBool isLoggedIn)
{
- int i;
- PRBool isKrl = PR_FALSE;
- SECItem derCert = { siBuffer, NULL, 0 };
- SECItem derSubject = { siBuffer, NULL, 0 };
- SECItem name = { siBuffer, NULL, 0 };
- SECItem email = { siBuffer, NULL, 0 };
- SECItem key_id = { siBuffer, NULL, 0 };
- SECItem cert_sha1_hash = { siBuffer, NULL, 0 };
- SECItem cert_md5_hash = { siBuffer, NULL, 0 };
- NSSLOWCERTIssuerAndSN issuerSN = {
- { siBuffer, NULL, 0 },
- { siBuffer, NULL, 0 }
- };
- SECItem *copy = NULL;
- unsigned long classFlags =
- NSC_CERT|NSC_TRUST|NSC_PRIVATE|NSC_PUBLIC|NSC_KEY|NSC_SMIME|NSC_CRL;
-
- /* if we aren't logged in, don't look for private or secret keys */
- if (!isLoggedIn) {
- classFlags &= ~(NSC_PRIVATE|NSC_KEY);
- }
-
- /*
- * look for things to search on token objects for. If the right options
- * are specified, we can use them as direct indeces into the database
- * (rather than using linear searches. We can also use the attributes to
- * limit the kinds of objects we are searching for. Later we can use this
- * array to filter the remaining objects more finely.
- */
- for (i=0 ;classFlags && i < (int)ulCount; i++) {
-
- switch (pTemplate[i].type) {
- case CKA_SUBJECT:
- copy = &derSubject;
- classFlags &= (NSC_CERT|NSC_PRIVATE|NSC_PUBLIC|NSC_SMIME|NSC_CRL);
- break;
- case CKA_ISSUER:
- copy = &issuerSN.derIssuer;
- classFlags &= (NSC_CERT|NSC_TRUST);
- break;
- case CKA_SERIAL_NUMBER:
- copy = &issuerSN.serialNumber;
- classFlags &= (NSC_CERT|NSC_TRUST);
- break;
- case CKA_VALUE:
- copy = &derCert;
- classFlags &= (NSC_CERT|NSC_CRL|NSC_SMIME);
- break;
- case CKA_LABEL:
- copy = &name;
- break;
- case CKA_NETSCAPE_EMAIL:
- copy = &email;
- classFlags &= NSC_SMIME|NSC_CERT;
- break;
- case CKA_NETSCAPE_SMIME_TIMESTAMP:
- classFlags &= NSC_SMIME;
- break;
- case CKA_CLASS:
- if (pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS)) {
- classFlags = 0;
- break;;
- }
- switch (*((CK_OBJECT_CLASS *)pTemplate[i].pValue)) {
- case CKO_CERTIFICATE:
- classFlags &= NSC_CERT;
- break;
- case CKO_NETSCAPE_TRUST:
- classFlags &= NSC_TRUST;
- break;
- case CKO_NETSCAPE_CRL:
- classFlags &= NSC_CRL;
- break;
- case CKO_NETSCAPE_SMIME:
- classFlags &= NSC_SMIME;
- break;
- case CKO_PRIVATE_KEY:
- classFlags &= NSC_PRIVATE;
- break;
- case CKO_PUBLIC_KEY:
- classFlags &= NSC_PUBLIC;
- break;
- case CKO_SECRET_KEY:
- classFlags &= NSC_KEY;
- break;
- default:
- classFlags = 0;
- break;
- }
- break;
- case CKA_PRIVATE:
- if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
- classFlags = 0;
- }
- if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
- classFlags &= (NSC_PRIVATE|NSC_KEY);
- } else {
- classFlags &= ~(NSC_PRIVATE|NSC_KEY);
- }
- break;
- case CKA_SENSITIVE:
- if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
- classFlags = 0;
- }
- if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
- classFlags &= (NSC_PRIVATE|NSC_KEY);
- } else {
- classFlags = 0;
- }
- break;
- case CKA_TOKEN:
- if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
- classFlags = 0;
- }
- if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
- *tokenOnly = PR_TRUE;
- } else {
- classFlags = 0;
- }
- break;
- case CKA_CERT_SHA1_HASH:
- classFlags &= NSC_TRUST;
- copy = &cert_sha1_hash; break;
- case CKA_CERT_MD5_HASH:
- classFlags &= NSC_TRUST;
- copy = &cert_md5_hash; break;
- case CKA_CERTIFICATE_TYPE:
- if (pTemplate[i].ulValueLen != sizeof(CK_CERTIFICATE_TYPE)) {
- classFlags = 0;
- }
- classFlags &= NSC_CERT;
- if (*((CK_CERTIFICATE_TYPE *)pTemplate[i].pValue) != CKC_X_509) {
- classFlags = 0;
- }
- break;
- case CKA_ID:
- copy = &key_id;
- classFlags &= (NSC_CERT|NSC_PRIVATE|NSC_KEY|NSC_PUBLIC);
- break;
- case CKA_NETSCAPE_KRL:
- if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
- classFlags = 0;
- }
- classFlags &= NSC_CRL;
- isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE);
- break;
- case CKA_MODIFIABLE:
- break;
- case CKA_KEY_TYPE:
- case CKA_DERIVE:
- classFlags &= NSC_PUBLIC|NSC_PRIVATE|NSC_KEY;
- break;
- case CKA_VERIFY_RECOVER:
- classFlags &= NSC_PUBLIC;
- break;
- case CKA_SIGN_RECOVER:
- classFlags &= NSC_PRIVATE;
- break;
- case CKA_ENCRYPT:
- case CKA_VERIFY:
- case CKA_WRAP:
- classFlags &= NSC_PUBLIC|NSC_KEY;
- break;
- case CKA_DECRYPT:
- case CKA_SIGN:
- case CKA_UNWRAP:
- case CKA_ALWAYS_SENSITIVE:
- case CKA_EXTRACTABLE:
- case CKA_NEVER_EXTRACTABLE:
- classFlags &= NSC_PRIVATE|NSC_KEY;
- break;
- /* can't be a certificate if it doesn't match one of the above
- * attributes */
- default:
- classFlags = 0;
- break;
- }
- if (copy) {
- copy->data = (unsigned char*)pTemplate[i].pValue;
- copy->len = pTemplate[i].ulValueLen;
- }
- copy = NULL;
- }
-
-
- /* certs */
- if (classFlags & (NSC_CERT|NSC_TRUST)) {
- sftk_searchCertsAndTrust(slot,&derCert,&name,&derSubject,
- &issuerSN, &email,classFlags,search,
- pTemplate, ulCount);
- }
+ CK_RV crv;
+ CK_RV crv2;
+ SFTKDBHandle *certHandle = sftk_getCertDB(slot);
- /* keys */
- if (classFlags & (NSC_PRIVATE|NSC_PUBLIC|NSC_KEY)) {
- PRBool mustStrict = ((classFlags & NSC_KEY) != 0) && (name.len != 0);
- sftk_searchKeys(slot, &key_id, isLoggedIn, classFlags, search,
- mustStrict, pTemplate, ulCount);
- }
+ crv = sftk_searchDatabase(certHandle, search, pTemplate, ulCount);
+ crv2 = sftk_emailhack(slot, certHandle, search, pTemplate, ulCount);
+ if (crv == CKR_OK) crv2 = crv;
+ sftk_freeDB(certHandle);
- /* crl's */
- if (classFlags & NSC_CRL) {
- sftk_searchCrls(slot, &derSubject, isKrl, classFlags, search,
- pTemplate, ulCount);
- }
- /* Add S/MIME entry stuff */
- if (classFlags & NSC_SMIME) {
- sftk_searchSMime(slot, &email, search, pTemplate, ulCount);
+ if (crv == CKR_OK && isLoggedIn) {
+ SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
+ crv = sftk_searchDatabase(keyHandle, search, pTemplate, ulCount);
+ sftk_freeDB(keyHandle);
}
- return CKR_OK;
+ return crv;
}
-
/* NSC_FindObjectsInit initializes a search for token and session objects
* that match a template. */
@@ -5207,8 +3980,8 @@ CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession,
/* build list of found objects in the session */
if (!tokenOnly) {
crv = sftk_searchObjectList(search, slot->sessObjHashTable,
- slot->sessObjHashSize, slot->objectLock,
- pTemplate, ulCount, isLoggedIn);
+ slot->sessObjHashSize, slot->objectLock,
+ pTemplate, ulCount, isLoggedIn);
}
if (crv != CKR_OK) {
goto loser;
diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c
index cfd1e7cb0..df149a9ea 100644
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -59,7 +59,6 @@
#include "pkcs11.h"
#include "pkcs11i.h"
#include "lowkeyi.h"
-#include "pcert.h"
#include "sechash.h"
#include "secder.h"
#include "secdig.h"
@@ -71,7 +70,6 @@
#include "secasn1.h"
#include "secerr.h"
-#include "pcert.h"
#include "ssl3prot.h" /* for SSL3_RANDOM_LENGTH */
#include "prprf.h"
@@ -97,8 +95,6 @@ static void sftk_Null(void *data, PRBool freeit)
}
#ifdef NSS_ENABLE_ECC
-extern SECStatus EC_DecodeParams(const SECItem *encodedParams,
- ECParams **ecparams);
#ifdef EC_DEBUG
#define SEC_PRINT(str1, str2, num, sitem) \
printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h
index 8abc03ed8..71b0ccce3 100644
--- a/security/nss/lib/softoken/pkcs11i.h
+++ b/security/nss/lib/softoken/pkcs11i.h
@@ -44,7 +44,8 @@
#include "secoidt.h"
#include "lowkeyti.h"
#include "pkcs11t.h"
-#include "pcertt.h"
+
+#include "sftkdbt.h"
/*
@@ -348,7 +349,6 @@ struct SFTKSlotStr {
unsigned long sessionLockMask; /* invariant */
PZLock *objectLock; /* invariant */
PRLock *pwCheckLock; /* invariant */
- SECItem *password; /* variable - reset */
PRBool present; /* variable -set */
PRBool hasTokens; /* per load */
PRBool isLoggedIn; /* variable - reset */
@@ -357,8 +357,8 @@ struct SFTKSlotStr {
PRBool DB_loaded; /* per load */
PRBool readOnly; /* per load */
PRBool optimizeSpace; /* invariant */
- NSSLOWCERTCertDBHandle *certDB; /* per load */
- NSSLOWKEYDBHandle *keyDB; /* per load */
+ SFTKDBHandle *certDB; /* per load */
+ SFTKDBHandle *keyDB; /* per load */
int minimumPinLen; /* per load */
PRInt32 sessionIDCount; /* atomically incremented */
/* (preserved) */
@@ -367,7 +367,7 @@ struct SFTKSlotStr {
int sessionCount; /* variable - reset */
PRInt32 rwSessionCount; /* set by atomic operations */
/* (reset) */
- PRUint32 sessionObjectHandleCount; /* variable - preserved */
+ int sessionObjectHandleCount;/* variable - perserved */
int index; /* invariant */
PLHashTable *tokObjHashTable; /* invariant */
SFTKObject **sessObjHashTable; /* variable - reset */
@@ -650,53 +650,13 @@ extern void sftk_FormatDESKey(unsigned char *key, int length);
extern PRBool sftk_CheckDESKey(unsigned char *key);
extern PRBool sftk_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type);
-extern CK_RV secmod_parseParameters(char *param, sftk_parameters *parsed,
- PRBool isFIPS);
-extern void secmod_freeParams(sftk_parameters *params);
-extern char *secmod_getSecmodName(char *params, char **domain,
- char **filename, PRBool *rw);
-extern char ** secmod_ReadPermDB(const char *domain, const char *filename,
- const char *dbname, char *params, PRBool rw);
-extern SECStatus secmod_DeletePermDB(const char *domain, const char *filename,
- const char *dbname, char *args, PRBool rw);
-extern SECStatus secmod_AddPermDB(const char *domain, const char *filename,
- const char *dbname, char *module, PRBool rw);
-extern SECStatus secmod_ReleasePermDBData(const char *domain,
- const char *filename, const char *dbname, char **specList, PRBool rw);
/* mechanism allows this operation */
extern CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op);
-/*
- * OK there are now lots of options here, lets go through them all:
- *
- * configdir - base directory where all the cert, key, and module datbases live.
- * certPrefix - prefix added to the beginning of the cert database example: "
- * "https-server1-"
- * keyPrefix - prefix added to the beginning of the key database example: "
- * "https-server1-"
- * secmodName - name of the security module database (usually "secmod.db").
- * readOnly - Boolean: true if the databases are to be openned read only.
- * nocertdb - Don't open the cert DB and key DB's, just initialize the
- * Volatile certdb.
- * nomoddb - Don't open the security module DB, just initialize the
- * PKCS #11 module.
- * forceOpen - Continue to force initializations even if the databases cannot
- * be opened.
- */
-CK_RV sftk_DBInit(const char *configdir, const char *certPrefix,
- const char *keyPrefix, PRBool readOnly, PRBool noCertDB,
- PRBool noKeyDB, PRBool forceOpen,
- NSSLOWCERTCertDBHandle **certDB, NSSLOWKEYDBHandle **keyDB);
-NSSLOWCERTCertDBHandle *sftk_getCertDB(SFTKSlot *slot);
-NSSLOWKEYDBHandle *sftk_getKeyDB(SFTKSlot *slot);
-void sftk_freeCertDB(NSSLOWCERTCertDBHandle *certHandle);
-void sftk_freeKeyDB(NSSLOWKEYDBHandle *keyHandle);
/* helper function which calls nsslowkey_FindKeyByPublicKey after safely
* acquiring a reference to the keydb from the slot */
NSSLOWKEYPrivateKey *sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey);
-const char *sftk_EvaluateConfigDir(const char *configdir, char **domain);
-
/*
* narrow objects
*/
@@ -709,10 +669,6 @@ SFTKTokenObject * sftk_narrowToTokenObject(SFTKObject *);
void sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle);
PRBool sftk_poisonHandle(SFTKSlot *slot, SECItem *dbkey,
CK_OBJECT_HANDLE handle);
-PRBool sftk_tokenMatch(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class,
- CK_ATTRIBUTE_PTR theTemplate,int count);
-CK_OBJECT_HANDLE sftk_mkHandle(SFTKSlot *slot,
- SECItem *dbKey, CK_OBJECT_HANDLE class);
SFTKObject * sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey,
CK_OBJECT_HANDLE handle);
SFTKTokenObject *sftk_convertSessionToToken(SFTKObject *so);
diff --git a/security/nss/lib/softoken/pkcs11n.h b/security/nss/lib/softoken/pkcs11n.h
index b1dce6c12..6167c01b5 100644
--- a/security/nss/lib/softoken/pkcs11n.h
+++ b/security/nss/lib/softoken/pkcs11n.h
@@ -50,10 +50,10 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
*/
/*
- * NSSCK_VENDOR_NETSCAPE
+ * NSSCK_VENDOR_NSS
*
* Cryptoki reserves the high half of all the number spaces for
- * vendor-defined use. I'd like to keep all of our Netscape-
+ * vendor-defined use. I'd like to keep all of our NSS-
* specific values together, but not in the oh-so-obvious
* 0x80000001, 0x80000002, etc. area. So I've picked an offset,
* and constructed values for the beginnings of our spaces.
@@ -61,54 +61,56 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
* Note that some "historical" Netscape values don't fall within
* this range.
*/
-#define NSSCK_VENDOR_NETSCAPE 0x4E534350 /* NSCP */
+#define NSSCK_VENDOR_NSS 0x4E534350 /* NSCP */
/*
- * Netscape-defined object classes
+ * NSS-defined object classes
*
*/
-#define CKO_NETSCAPE (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
+#define CKO_NSS (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
+
+#define CKO_NSS_CRL (CKO_NSS + 1)
+#define CKO_NSS_SMIME (CKO_NSS + 2)
+#define CKO_NSS_TRUST (CKO_NSS + 3)
+#define CKO_NSS_BUILTIN_ROOT_LIST (CKO_NSS + 4)
+#define CKO_NSS_NEWSLOT (CKO_NSS + 5)
+#define CKO_NSS_DELSLOT (CKO_NSS + 6)
-#define CKO_NETSCAPE_CRL (CKO_NETSCAPE + 1)
-#define CKO_NETSCAPE_SMIME (CKO_NETSCAPE + 2)
-#define CKO_NETSCAPE_TRUST (CKO_NETSCAPE + 3)
-#define CKO_NETSCAPE_BUILTIN_ROOT_LIST (CKO_NETSCAPE + 4)
-#define CKO_NETSCAPE_NEWSLOT (CKO_NETSCAPE + 5)
-#define CKO_NETSCAPE_DELSLOT (CKO_NETSCAPE + 6)
/*
- * Netscape-defined key types
+ * NSS-defined key types
*
*/
-#define CKK_NETSCAPE (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
+#define CKK_NSS (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
-#define CKK_NETSCAPE_PKCS8 (CKK_NETSCAPE + 1)
+#define CKK_NSS_PKCS8 (CKK_NSS + 1)
/*
- * Netscape-defined certificate types
+ * NSS-defined certificate types
*
*/
-#define CKC_NETSCAPE (CKC_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
+#define CKC_NSS (CKC_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
/*
- * Netscape-defined object attributes
+ * NSS-defined object attributes
*
*/
-#define CKA_NETSCAPE (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
-
-#define CKA_NETSCAPE_URL (CKA_NETSCAPE + 1)
-#define CKA_NETSCAPE_EMAIL (CKA_NETSCAPE + 2)
-#define CKA_NETSCAPE_SMIME_INFO (CKA_NETSCAPE + 3)
-#define CKA_NETSCAPE_SMIME_TIMESTAMP (CKA_NETSCAPE + 4)
-#define CKA_NETSCAPE_PKCS8_SALT (CKA_NETSCAPE + 5)
-#define CKA_NETSCAPE_PASSWORD_CHECK (CKA_NETSCAPE + 6)
-#define CKA_NETSCAPE_EXPIRES (CKA_NETSCAPE + 7)
-#define CKA_NETSCAPE_KRL (CKA_NETSCAPE + 8)
-
-#define CKA_NETSCAPE_PQG_COUNTER (CKA_NETSCAPE + 20)
-#define CKA_NETSCAPE_PQG_SEED (CKA_NETSCAPE + 21)
-#define CKA_NETSCAPE_PQG_H (CKA_NETSCAPE + 22)
-#define CKA_NETSCAPE_PQG_SEED_BITS (CKA_NETSCAPE + 23)
-#define CKA_NETSCAPE_MODULE_SPEC (CKA_NETSCAPE + 24)
+#define CKA_NSS (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
+
+#define CKA_NSS_URL (CKA_NSS + 1)
+#define CKA_NSS_EMAIL (CKA_NSS + 2)
+#define CKA_NSS_SMIME_INFO (CKA_NSS + 3)
+#define CKA_NSS_SMIME_TIMESTAMP (CKA_NSS + 4)
+#define CKA_NSS_PKCS8_SALT (CKA_NSS + 5)
+#define CKA_NSS_PASSWORD_CHECK (CKA_NSS + 6)
+#define CKA_NSS_EXPIRES (CKA_NSS + 7)
+#define CKA_NSS_KRL (CKA_NSS + 8)
+
+#define CKA_NSS_PQG_COUNTER (CKA_NSS + 20)
+#define CKA_NSS_PQG_SEED (CKA_NSS + 21)
+#define CKA_NSS_PQG_H (CKA_NSS + 22)
+#define CKA_NSS_PQG_SEED_BITS (CKA_NSS + 23)
+#define CKA_NSS_MODULE_SPEC (CKA_NSS + 24)
+#define CKA_NSS_OVERRIDE_EXTENSIONS (CKA_NSS + 25)
/*
* Trust attributes:
@@ -117,7 +119,7 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
* put them all in one place.
*/
-#define CKA_TRUST (CKA_NETSCAPE + 0x2000)
+#define CKA_TRUST (CKA_NSS + 0x2000)
/* "Usage" key information */
#define CKA_TRUST_DIGITAL_SIGNATURE (CKA_TRUST + 1)
@@ -142,7 +144,7 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
#define CKA_CERT_SHA1_HASH (CKA_TRUST + 100)
#define CKA_CERT_MD5_HASH (CKA_TRUST + 101)
-/* Netscape trust stuff */
+/* NSS trust stuff */
/* XXX fgmr new ones here-- step-up, etc. */
/* HISTORICAL: define used to pass in the database key for DSA private keys */
@@ -150,13 +152,13 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
#define CKA_NETSCAPE_TRUST 0x80000001L
/*
- * Netscape-defined crypto mechanisms
+ * NSS-defined crypto mechanisms
*
*/
-#define CKM_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
+#define CKM_NSS (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
-#define CKM_NETSCAPE_AES_KEY_WRAP (CKM_NETSCAPE + 1)
-#define CKM_NETSCAPE_AES_KEY_WRAP_PAD (CKM_NETSCAPE + 2)
+#define CKM_NSS_AES_KEY_WRAP (CKM_NSS + 1)
+#define CKM_NSS_AES_KEY_WRAP_PAD (CKM_NSS + 2)
/*
* HISTORICAL:
@@ -178,13 +180,13 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
#define CKM_TLS_PRF_GENERAL 0x80000373L
/*
- * Netscape-defined return values
+ * NSS-defined return values
*
*/
-#define CKR_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
+#define CKR_NSS (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
-#define CKR_NETSCAPE_CERTDB_FAILED (CKR_NETSCAPE + 1)
-#define CKR_NETSCAPE_KEYDB_FAILED (CKR_NETSCAPE + 2)
+#define CKR_NSS_CERTDB_FAILED (CKR_NSS + 1)
+#define CKR_NSS_KEYDB_FAILED (CKR_NSS + 2)
/*
* Trust info
@@ -192,7 +194,7 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
* This isn't part of the Cryptoki standard (yet), so I'm putting
* all the definitions here. Some of this would move to nssckt.h
* if trust info were made part of the standard. In view of this
- * possibility, I'm putting my (Netscape) values in the netscape
+ * possibility, I'm putting my (NSS) values in the NSS
* vendor space, like everything else.
*/
@@ -201,22 +203,55 @@ typedef CK_ULONG CK_TRUST;
/* The following trust types are defined: */
#define CKT_VENDOR_DEFINED 0x80000000
-#define CKT_NETSCAPE (CKT_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
+#define CKT_NSS (CKT_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
/* If trust goes standard, these'll probably drop out of vendor space. */
-#define CKT_NETSCAPE_TRUSTED (CKT_NETSCAPE + 1)
-#define CKT_NETSCAPE_TRUSTED_DELEGATOR (CKT_NETSCAPE + 2)
-#define CKT_NETSCAPE_UNTRUSTED (CKT_NETSCAPE + 3)
-#define CKT_NETSCAPE_MUST_VERIFY (CKT_NETSCAPE + 4)
-#define CKT_NETSCAPE_TRUST_UNKNOWN (CKT_NETSCAPE + 5) /* default */
+#define CKT_NSS_TRUSTED (CKT_NSS + 1)
+#define CKT_NSS_TRUSTED_DELEGATOR (CKT_NSS + 2)
+#define CKT_NSS_UNTRUSTED (CKT_NSS + 3)
+#define CKT_NSS_MUST_VERIFY (CKT_NSS + 4)
+#define CKT_NSS_TRUST_UNKNOWN (CKT_NSS + 5) /* default */
/*
- * These may well remain Netscape-specific; I'm only using them
+ * These may well remain NSS-specific; I'm only using them
* to cache resolution data.
*/
-#define CKT_NETSCAPE_VALID (CKT_NETSCAPE + 10)
-#define CKT_NETSCAPE_VALID_DELEGATOR (CKT_NETSCAPE + 11)
-
+#define CKT_NSS_VALID (CKT_NSS + 10)
+#define CKT_NSS_VALID_DELEGATOR (CKT_NSS + 11)
+
+/* don't leave old programs in a lurch just yet, give them the old NETSCAPE
+ * synonym */
+#define CKO_NETSCAPE_CRL CKO_NSS_CRL
+#define CKO_NETSCAPE_SMIME CKO_NSS_SMIME
+#define CKO_NETSCAPE_TRUST CKO_NSS_TRUST
+#define CKO_NETSCAPE_BUILTIN_ROOT_LIST CKO_NSS_BUILTIN_ROOT_LIST
+#define CKO_NETSCAPE_NEWSLOT CKO_NSS_NEWSLOT
+#define CKO_NETSCAPE_DELSLOT CKO_NSS_DELSLOT
+#define CKK_NETSCAPE_PKCS8 CKK_NSS_PKCS8
+#define CKA_NETSCAPE_URL CKA_NSS_URL
+#define CKA_NETSCAPE_EMAIL CKA_NSS_EMAIL
+#define CKA_NETSCAPE_SMIME_INFO CKA_NSS_SMIME_INFO
+#define CKA_NETSCAPE_SMIME_TIMESTAMP CKA_NSS_SMIME_TIMESTAMP
+#define CKA_NETSCAPE_PKCS8_SALT CKA_NSS_PKCS8_SALT
+#define CKA_NETSCAPE_PASSWORD_CHECK CKA_NSS_PASSWORD_CHECK
+#define CKA_NETSCAPE_EXPIRES CKA_NSS_EXPIRES
+#define CKA_NETSCAPE_KRL CKA_NSS_KRL
+#define CKA_NETSCAPE_PQG_COUNTER CKA_NSS_PQG_COUNTER
+#define CKA_NETSCAPE_PQG_SEED CKA_NSS_PQG_SEED
+#define CKA_NETSCAPE_PQG_H CKA_NSS_PQG_H
+#define CKA_NETSCAPE_PQG_SEED_BITS CKA_NSS_PQG_SEED_BITS
+#define CKA_NETSCAPE_MODULE_SPEC CKA_NSS_MODULE_SPEC
+#define CKM_NETSCAPE_AES_KEY_WRAP CKM_NSS_AES_KEY_WRAP
+#define CKM_NETSCAPE_AES_KEY_WRAP_PAD CKM_NSS_AES_KEY_WRAP_PAD
+#define CKR_NETSCAPE_CERTDB_FAILED CKR_NSS_CERTDB_FAILED
+#define CKR_NETSCAPE_KEYDB_FAILED CKR_NSS_KEYDB_FAILED
+#define CKT_NETSCAPE_TRUSTED CKT_NSS_TRUSTED
+#define CKT_NETSCAPE_TRUSTED_DELEGATOR CKT_NSS_TRUSTED_DELEGATOR
+#define CKT_NETSCAPE_UNTRUSTED CKT_NSS_UNTRUSTED
+#define CKT_NETSCAPE_MUST_VERIFY CKT_NSS_MUST_VERIFY
+#define CKT_NETSCAPE_TRUST_UNKNOWN CKT_NSS_TRUST_UNKNOWN
+#define CKT_NETSCAPE_VALID CKT_NSS_VALID
+#define CKT_NETSCAPE_VALID_DELEGATOR CKT_NSS_VALID_DELEGATOR
/*
* These are not really PKCS #11 values specifically. They are the 'loadable'
diff --git a/security/nss/lib/softoken/pkcs11t.h b/security/nss/lib/softoken/pkcs11t.h
index 1eef6bf61..7f8009e40 100644
--- a/security/nss/lib/softoken/pkcs11t.h
+++ b/security/nss/lib/softoken/pkcs11t.h
@@ -912,12 +912,12 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_TWOFISH_CBC 0x00001093
/* Camellia is proposed for v2.20 Amendment 3 */
-#define CKM_CAMELLIA_KEY_GEN 0x00000550
-#define CKM_CAMELLIA_ECB 0x00000551
-#define CKM_CAMELLIA_CBC 0x00000552
-#define CKM_CAMELLIA_MAC 0x00000553
+#define CKM_CAMELLIA_KEY_GEN 0x00000550
+#define CKM_CAMELLIA_ECB 0x00000551
+#define CKM_CAMELLIA_CBC 0x00000552
+#define CKM_CAMELLIA_MAC 0x00000553
#define CKM_CAMELLIA_MAC_GENERAL 0x00000554
-#define CKM_CAMELLIA_CBC_PAD 0x00000555
+#define CKM_CAMELLIA_CBC_PAD 0x00000555
#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556
#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557
diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c
index a575bd13f..5e64cac95 100644
--- a/security/nss/lib/softoken/pkcs11u.c
+++ b/security/nss/lib/softoken/pkcs11u.c
@@ -39,13 +39,12 @@
*/
#include "pkcs11.h"
#include "pkcs11i.h"
-#include "pcertt.h"
#include "lowkeyi.h"
-#include "pcert.h"
#include "secasn1.h"
#include "blapi.h"
#include "secerr.h"
#include "prnetdb.h" /* for PR_ntohl */
+#include "sftkdb.h"
/*
* ******************** Attribute Utilities *******************************
@@ -107,59 +106,6 @@ sftk_NewAttribute(SFTKObject *object,
return attribute;
}
-static SFTKAttribute *
-sftk_NewTokenAttribute(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value,
- CK_ULONG len, PRBool copy)
-{
- SFTKAttribute *attribute;
-
- attribute = (SFTKAttribute*)PORT_Alloc(sizeof(SFTKAttribute));
-
- if (attribute == NULL) return NULL;
- attribute->attrib.type = type;
- attribute->handle = type;
- attribute->next = attribute->prev = NULL;
- attribute->freeAttr = PR_TRUE;
- attribute->freeData = PR_FALSE;
- attribute->attrib.type = type;
- if (!copy) {
- attribute->attrib.pValue = value;
- attribute->attrib.ulValueLen = len;
- return attribute;
- }
-
- if (value) {
- if (len <= ATTR_SPACE) {
- attribute->attrib.pValue = attribute->space;
- } else {
- attribute->attrib.pValue = PORT_Alloc(len);
- attribute->freeData = PR_TRUE;
- }
- if (attribute->attrib.pValue == NULL) {
- PORT_Free(attribute);
- return NULL;
- }
- PORT_Memcpy(attribute->attrib.pValue,value,len);
- attribute->attrib.ulValueLen = len;
- } else {
- attribute->attrib.pValue = NULL;
- attribute->attrib.ulValueLen = 0;
- }
- return attribute;
-}
-
-static SFTKAttribute *
-sftk_NewTokenAttributeSigned(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value,
- CK_ULONG len, PRBool copy)
-{
- unsigned char * dval = (unsigned char *)value;
- if (*dval == 0) {
- dval++;
- len--;
- }
- return sftk_NewTokenAttribute(type,dval,len,copy);
-}
-
/*
* Free up all the memory associated with an attribute. Reference count
* must be zero to call this.
@@ -191,1157 +137,60 @@ sftk_FreeAttribute(SFTKAttribute *attribute)
}
}
-#define SFTK_DEF_ATTRIBUTE(value,len) \
- { NULL, NULL, PR_FALSE, PR_FALSE, 0, { 0, value, len } }
-
-#define SFTK_CLONE_ATTR(type, staticAttr) \
- sftk_NewTokenAttribute( type, staticAttr.attrib.pValue, \
- staticAttr.attrib.ulValueLen, PR_FALSE)
-
-CK_BBOOL sftk_staticTrueValue = CK_TRUE;
-CK_BBOOL sftk_staticFalseValue = CK_FALSE;
-static const SFTKAttribute sftk_StaticTrueAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticTrueValue,sizeof(sftk_staticTrueValue));
-static const SFTKAttribute sftk_StaticFalseAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticFalseValue,sizeof(sftk_staticFalseValue));
-static const SFTKAttribute sftk_StaticNullAttr = SFTK_DEF_ATTRIBUTE(NULL,0);
-char sftk_StaticOneValue = 1;
-static const SFTKAttribute sftk_StaticOneAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_StaticOneValue,sizeof(sftk_StaticOneValue));
-
-CK_CERTIFICATE_TYPE sftk_staticX509Value = CKC_X_509;
-static const SFTKAttribute sftk_StaticX509Attr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticX509Value, sizeof(sftk_staticX509Value));
-CK_TRUST sftk_staticTrustedValue = CKT_NETSCAPE_TRUSTED;
-CK_TRUST sftk_staticTrustedDelegatorValue = CKT_NETSCAPE_TRUSTED_DELEGATOR;
-CK_TRUST sftk_staticValidDelegatorValue = CKT_NETSCAPE_VALID_DELEGATOR;
-CK_TRUST sftk_staticUnTrustedValue = CKT_NETSCAPE_UNTRUSTED;
-CK_TRUST sftk_staticTrustUnknownValue = CKT_NETSCAPE_TRUST_UNKNOWN;
-CK_TRUST sftk_staticValidPeerValue = CKT_NETSCAPE_VALID;
-CK_TRUST sftk_staticMustVerifyValue = CKT_NETSCAPE_MUST_VERIFY;
-static const SFTKAttribute sftk_StaticTrustedAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticTrustedValue,
- sizeof(sftk_staticTrustedValue));
-static const SFTKAttribute sftk_StaticTrustedDelegatorAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticTrustedDelegatorValue,
- sizeof(sftk_staticTrustedDelegatorValue));
-static const SFTKAttribute sftk_StaticValidDelegatorAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticValidDelegatorValue,
- sizeof(sftk_staticValidDelegatorValue));
-static const SFTKAttribute sftk_StaticUnTrustedAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticUnTrustedValue,
- sizeof(sftk_staticUnTrustedValue));
-static const SFTKAttribute sftk_StaticTrustUnknownAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticTrustUnknownValue,
- sizeof(sftk_staticTrustUnknownValue));
-static const SFTKAttribute sftk_StaticValidPeerAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticValidPeerValue,
- sizeof(sftk_staticValidPeerValue));
-static const SFTKAttribute sftk_StaticMustVerifyAttr =
- SFTK_DEF_ATTRIBUTE(&sftk_staticMustVerifyValue,
- sizeof(sftk_staticMustVerifyValue));
-
-/*
- * helper functions which get the database and call the underlying
- * low level database function.
- */
-static char *
-sftk_FindKeyNicknameByPublicKey(SFTKSlot *slot, SECItem *dbKey)
-{
- NSSLOWKEYDBHandle *keyHandle;
- char * label;
-
- keyHandle = sftk_getKeyDB(slot);
- if (!keyHandle) {
- return NULL;
- }
-
- label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey,
- slot->password);
- sftk_freeKeyDB(keyHandle);
- return label;
-}
-
-
-NSSLOWKEYPrivateKey *
-sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey)
-{
- NSSLOWKEYPrivateKey *privKey;
- NSSLOWKEYDBHandle *keyHandle;
-
- keyHandle = sftk_getKeyDB(slot);
- if (keyHandle == NULL) {
- return NULL;
- }
- privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, slot->password);
- sftk_freeKeyDB(keyHandle);
- if (privKey == NULL) {
- return NULL;
- }
- return privKey;
-}
-
-static certDBEntrySMime *
-sftk_getSMime(SFTKTokenObject *object)
-{
- certDBEntrySMime *entry;
- NSSLOWCERTCertDBHandle *certHandle;
-
- if (object->obj.objclass != CKO_NETSCAPE_SMIME) {
- return NULL;
- }
- if (object->obj.objectInfo) {
- return (certDBEntrySMime *)object->obj.objectInfo;
- }
-
- certHandle = sftk_getCertDB(object->obj.slot);
- if (!certHandle) {
- return NULL;
- }
- entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)object->dbKey.data);
- object->obj.objectInfo = (void *)entry;
- object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry;
- sftk_freeCertDB(certHandle);
- return entry;
-}
-
-static certDBEntryRevocation *
-sftk_getCrl(SFTKTokenObject *object)
-{
- certDBEntryRevocation *crl;
- PRBool isKrl;
- NSSLOWCERTCertDBHandle *certHandle;
-
- if (object->obj.objclass != CKO_NETSCAPE_CRL) {
- return NULL;
- }
- if (object->obj.objectInfo) {
- return (certDBEntryRevocation *)object->obj.objectInfo;
- }
-
- isKrl = (PRBool) (object->obj.handle == SFTK_TOKEN_KRL_HANDLE);
- certHandle = sftk_getCertDB(object->obj.slot);
- if (!certHandle) {
- return NULL;
- }
-
- crl = nsslowcert_FindCrlByKey(certHandle, &object->dbKey, isKrl);
- object->obj.objectInfo = (void *)crl;
- object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry;
- sftk_freeCertDB(certHandle);
- return crl;
-}
-
-static NSSLOWCERTCertificate *
-sftk_getCert(SFTKTokenObject *object, NSSLOWCERTCertDBHandle *certHandle)
-{
- NSSLOWCERTCertificate *cert;
- CK_OBJECT_CLASS objClass = object->obj.objclass;
-
- if ((objClass != CKO_CERTIFICATE) && (objClass != CKO_NETSCAPE_TRUST)) {
- return NULL;
- }
- if (objClass == CKO_CERTIFICATE && object->obj.objectInfo) {
- return (NSSLOWCERTCertificate *)object->obj.objectInfo;
- }
- cert = nsslowcert_FindCertByKey(certHandle, &object->dbKey);
- if (objClass == CKO_CERTIFICATE) {
- object->obj.objectInfo = (void *)cert;
- object->obj.infoFree = (SFTKFree) nsslowcert_DestroyCertificate ;
- }
- return cert;
-}
-
-static NSSLOWCERTTrust *
-sftk_getTrust(SFTKTokenObject *object)
-{
- NSSLOWCERTTrust *trust;
- NSSLOWCERTCertDBHandle *certHandle;
-
- if (object->obj.objclass != CKO_NETSCAPE_TRUST) {
- return NULL;
- }
- if (object->obj.objectInfo) {
- return (NSSLOWCERTTrust *)object->obj.objectInfo;
- }
- certHandle = sftk_getCertDB(object->obj.slot);
- if (!certHandle) {
- return NULL;
- }
- trust = nsslowcert_FindTrustByKey(certHandle, &object->dbKey);
- object->obj.objectInfo = (void *)trust;
- object->obj.infoFree = (SFTKFree) nsslowcert_DestroyTrust ;
- sftk_freeCertDB(certHandle);
- return trust;
-}
-
-static NSSLOWKEYPublicKey *
-sftk_GetPublicKey(SFTKTokenObject *object)
-{
- NSSLOWKEYPublicKey *pubKey;
- NSSLOWKEYPrivateKey *privKey;
-
- if (object->obj.objclass != CKO_PUBLIC_KEY) {
- return NULL;
- }
- if (object->obj.objectInfo) {
- return (NSSLOWKEYPublicKey *)object->obj.objectInfo;
- }
- privKey = sftk_FindKeyByPublicKey(object->obj.slot, &object->dbKey);
- if (privKey == NULL) {
- return NULL;
- }
- pubKey = nsslowkey_ConvertToPublicKey(privKey);
- nsslowkey_DestroyPrivateKey(privKey);
- object->obj.objectInfo = (void *) pubKey;
- object->obj.infoFree = (SFTKFree) nsslowkey_DestroyPublicKey ;
- return pubKey;
-}
-
-/*
- * we need two versions of sftk_GetPrivateKey. One version that takes the
- * DB handle so we can pass the handle we have already acquired in,
- * rather than going through the 'getKeyDB' code again,
- * which may fail the second time and another which just aquires
- * the key handle from the slot (where we don't already have a key handle.
- * This version does the former.
- */
-static NSSLOWKEYPrivateKey *
-sftk_GetPrivateKeyWithDB(SFTKTokenObject *object, NSSLOWKEYDBHandle *keyHandle)
-{
- NSSLOWKEYPrivateKey *privKey;
-
- if ((object->obj.objclass != CKO_PRIVATE_KEY) &&
- (object->obj.objclass != CKO_SECRET_KEY)) {
- return NULL;
- }
- if (object->obj.objectInfo) {
- return (NSSLOWKEYPrivateKey *)object->obj.objectInfo;
- }
- privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &object->dbKey,
- object->obj.slot->password);
- if (privKey == NULL) {
- return NULL;
- }
- object->obj.objectInfo = (void *) privKey;
- object->obj.infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey ;
- return privKey;
-}
-
-/* this version does the latter */
-static NSSLOWKEYPrivateKey *
-sftk_GetPrivateKey(SFTKTokenObject *object)
-{
- NSSLOWKEYDBHandle *keyHandle;
- NSSLOWKEYPrivateKey *privKey;
-
- keyHandle = sftk_getKeyDB(object->obj.slot);
- if (!keyHandle) {
- return NULL;
- }
- privKey = sftk_GetPrivateKeyWithDB(object, keyHandle);
- sftk_freeKeyDB(keyHandle);
- return privKey;
-}
-
-/* sftk_GetPubItem returns data associated with the public key.
- * one only needs to free the public key. This comment is here
- * because this sematic would be non-obvious otherwise. All callers
- * should include this comment.
- */
-static SECItem *
-sftk_GetPubItem(NSSLOWKEYPublicKey *pubKey) {
- SECItem *pubItem = NULL;
- /* get value to compare from the cert's public key */
- switch ( pubKey->keyType ) {
- case NSSLOWKEYRSAKey:
- pubItem = &pubKey->u.rsa.modulus;
- break;
- case NSSLOWKEYDSAKey:
- pubItem = &pubKey->u.dsa.publicValue;
- break;
- case NSSLOWKEYDHKey:
- pubItem = &pubKey->u.dh.publicValue;
- break;
-#ifdef NSS_ENABLE_ECC
- case NSSLOWKEYECKey:
- pubItem = &pubKey->u.ec.publicValue;
- break;
-#endif /* NSS_ENABLE_ECC */
- default:
- break;
- }
- return pubItem;
-}
-
-static const SEC_ASN1Template sftk_SerialTemplate[] = {
- { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) },
- { 0 }
-};
-
-static SFTKAttribute *
-sftk_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
-{
- unsigned char hash[SHA1_LENGTH];
- CK_KEY_TYPE keyType = CKK_RSA;
-
- switch (type) {
- case CKA_KEY_TYPE:
- return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
- case CKA_ID:
- SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
- return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
- case CKA_DERIVE:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_ENCRYPT:
- case CKA_VERIFY:
- case CKA_VERIFY_RECOVER:
- case CKA_WRAP:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_MODULUS:
- return sftk_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
- key->u.rsa.modulus.len, PR_FALSE);
- case CKA_PUBLIC_EXPONENT:
- return sftk_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
- key->u.rsa.publicExponent.len, PR_FALSE);
- default:
- break;
- }
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
-{
- unsigned char hash[SHA1_LENGTH];
- CK_KEY_TYPE keyType = CKK_DSA;
-
- switch (type) {
- case CKA_KEY_TYPE:
- return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
- case CKA_ID:
- SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
- key->u.dsa.publicValue.len);
- return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
- case CKA_DERIVE:
- case CKA_ENCRYPT:
- case CKA_VERIFY_RECOVER:
- case CKA_WRAP:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_VERIFY:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_VALUE:
- return sftk_NewTokenAttributeSigned(type,key->u.dsa.publicValue.data,
- key->u.dsa.publicValue.len, PR_FALSE);
- case CKA_PRIME:
- return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
- key->u.dsa.params.prime.len, PR_FALSE);
- case CKA_SUBPRIME:
- return sftk_NewTokenAttributeSigned(type,
- key->u.dsa.params.subPrime.data,
- key->u.dsa.params.subPrime.len, PR_FALSE);
- case CKA_BASE:
- return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
- key->u.dsa.params.base.len, PR_FALSE);
- default:
- break;
- }
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
-{
- unsigned char hash[SHA1_LENGTH];
- CK_KEY_TYPE keyType = CKK_DH;
-
- switch (type) {
- case CKA_KEY_TYPE:
- return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
- case CKA_ID:
- SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
- return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
- case CKA_DERIVE:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_ENCRYPT:
- case CKA_VERIFY:
- case CKA_VERIFY_RECOVER:
- case CKA_WRAP:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_VALUE:
- return sftk_NewTokenAttributeSigned(type,key->u.dh.publicValue.data,
- key->u.dh.publicValue.len, PR_FALSE);
- case CKA_PRIME:
- return sftk_NewTokenAttributeSigned(type,key->u.dh.prime.data,
- key->u.dh.prime.len, PR_FALSE);
- case CKA_BASE:
- return sftk_NewTokenAttributeSigned(type,key->u.dh.base.data,
- key->u.dh.base.len, PR_FALSE);
- default:
- break;
- }
- return NULL;
-}
-
-#ifdef NSS_ENABLE_ECC
-static SFTKAttribute *
-sftk_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
-{
- unsigned char hash[SHA1_LENGTH];
- CK_KEY_TYPE keyType = CKK_EC;
-
- switch (type) {
- case CKA_KEY_TYPE:
- return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
- case CKA_ID:
- SHA1_HashBuf(hash, key->u.ec.publicValue.data,
- key->u.ec.publicValue.len);
- return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
- case CKA_DERIVE:
- case CKA_VERIFY:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_ENCRYPT:
- case CKA_VERIFY_RECOVER:
- case CKA_WRAP:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_EC_PARAMS:
- /* XXX Why is the last arg PR_FALSE? */
- return sftk_NewTokenAttributeSigned(type,
- key->u.ec.ecParams.DEREncoding.data,
- key->u.ec.ecParams.DEREncoding.len,
- PR_FALSE);
- case CKA_EC_POINT:
- /* XXX Why is the last arg PR_FALSE? */
- return sftk_NewTokenAttributeSigned(type,key->u.ec.publicValue.data,
- key->u.ec.publicValue.len, PR_FALSE);
- default:
- break;
- }
- return NULL;
-}
-#endif /* NSS_ENABLE_ECC */
-
-
-static SFTKAttribute *
-sftk_FindPublicKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
-{
- NSSLOWKEYPublicKey *key;
- SFTKAttribute *att = NULL;
- char *label;
-
- switch (type) {
- case CKA_PRIVATE:
- case CKA_SENSITIVE:
- case CKA_ALWAYS_SENSITIVE:
- case CKA_NEVER_EXTRACTABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_MODIFIABLE:
- case CKA_EXTRACTABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_LABEL:
- label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
- &object->dbKey);
- if (label == NULL) {
- return SFTK_CLONE_ATTR(type,sftk_StaticOneAttr);
- }
- att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
- PORT_Free(label);
- return att;
- default:
- break;
- }
-
- key = sftk_GetPublicKey(object);
- if (key == NULL) {
- return NULL;
- }
-
- switch (key->keyType) {
- case NSSLOWKEYRSAKey:
- return sftk_FindRSAPublicKeyAttribute(key,type);
- case NSSLOWKEYDSAKey:
- return sftk_FindDSAPublicKeyAttribute(key,type);
- case NSSLOWKEYDHKey:
- return sftk_FindDHPublicKeyAttribute(key,type);
-#ifdef NSS_ENABLE_ECC
- case NSSLOWKEYECKey:
- return sftk_FindECPublicKeyAttribute(key,type);
-#endif /* NSS_ENABLE_ECC */
- default:
- break;
- }
-
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindSecretKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
-{
- NSSLOWKEYPrivateKey *key;
- char *label;
- unsigned char *keyString;
- SFTKAttribute *att;
- int keyTypeLen;
- CK_ULONG keyLen;
- CK_KEY_TYPE keyType;
- PRUint32 keyTypeStorage;
-
- switch (type) {
- case CKA_PRIVATE:
- case CKA_SENSITIVE:
- case CKA_ALWAYS_SENSITIVE:
- case CKA_EXTRACTABLE:
- case CKA_DERIVE:
- case CKA_ENCRYPT:
- case CKA_DECRYPT:
- case CKA_SIGN:
- case CKA_VERIFY:
- case CKA_WRAP:
- case CKA_UNWRAP:
- case CKA_MODIFIABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_NEVER_EXTRACTABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_LABEL:
- label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
- &object->dbKey);
- if (label == NULL) {
- return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
- }
- att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
- PORT_Free(label);
- return att;
- case CKA_KEY_TYPE:
- case CKA_VALUE_LEN:
- case CKA_VALUE:
- break;
- default:
- return NULL;
- }
-
- key = sftk_GetPrivateKey(object);
- if (key == NULL) {
- return NULL;
- }
- switch (type) {
- case CKA_KEY_TYPE:
- /* handle legacy databases. In legacy databases key_type was stored
- * in host order, with any leading zeros stripped off. Only key types
- * under 0x1f (AES) were stored. We assume that any values which are
- * either 1 byte long (big endian), or have byte[0] between 0 and
- * 0x7f and bytes[1]-bytes[3] equal to '0' (little endian). All other
- * values are assumed to be from the new database, which is always 4
- * bytes in network order */
- keyType=0;
- keyString = key->u.rsa.coefficient.data;
- keyTypeLen = key->u.rsa.coefficient.len;
-
-
- /*
- * Because of various endian and word lengths The database may have
- * stored the keyType value in one of the following formats:
- * (kt) <= 0x1f
- * length data
- * Big Endian, pre-3.9, all lengths: 1 (kt)
- * Little Endian, pre-3.9, 32 bits: 4 (kt) 0 0 0
- * Little Endian, pre-3.9, 64 bits: 8 (kt) 0 0 0 0 0 0 0
- * All platforms, 3.9, 32 bits: 4 0 0 0 (kt)
- * Big Endian, 3.9, 64 bits: 8 0 0 0 (kt) 0 0 0 0
- * Little Endian, 3.9, 64 bits: 8 0 0 0 0 0 0 0 (kt)
- * All platforms, >= 3.9.1, all lengths: 4 (a) k1 k2 k3
- * where (a) is 0 or >= 0x80. currently (a) can only be 0.
- */
- /*
- * this key was written on a 64 bit platform with a using NSS 3.9
- * or earlier. Reduce the 64 bit possibilities above. We were are
- * through, we will only have:
- *
- * Big Endian, pre-3.9, all lengths: 1 (kt)
- * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0
- * All platforms, 3.9, all lengths: 4 0 0 0 (kt)
- * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3
- */
- if (keyTypeLen == 8) {
- keyTypeStorage = *(PRUint32 *) keyString;
- if (keyTypeStorage == 0) {
- keyString += sizeof(PRUint32);
- }
- keyTypeLen = 4;
- }
- /*
- * Now Handle:
- *
- * All platforms, 3.9, all lengths: 4 0 0 0 (kt)
- * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3
- *
- * NOTE: if kt == 0 or ak1k2k3 == 0, the test fails and
- * we handle it as:
- *
- * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0
- */
- if (keyTypeLen == sizeof(keyTypeStorage) &&
- (((keyString[0] & 0x80) == 0x80) ||
- !((keyString[1] == 0) && (keyString[2] == 0)
- && (keyString[3] == 0))) ) {
- PORT_Memcpy(&keyTypeStorage, keyString, sizeof(keyTypeStorage));
- keyType = (CK_KEY_TYPE) PR_ntohl(keyTypeStorage);
- } else {
- /*
- * Now Handle:
- *
- * Big Endian, pre-3.9, all lengths: 1 (kt)
- * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0
- * -- KeyType == 0 all other cases ---: 4 0 0 0 0
- */
- keyType = (CK_KEY_TYPE) keyString[0] ;
- }
- return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType),PR_TRUE);
- case CKA_VALUE:
- return sftk_NewTokenAttribute(type,key->u.rsa.privateExponent.data,
- key->u.rsa.privateExponent.len, PR_FALSE);
- case CKA_VALUE_LEN:
- keyLen=key->u.rsa.privateExponent.len;
- return sftk_NewTokenAttribute(type, &keyLen, sizeof(CK_ULONG), PR_TRUE);
- }
-
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key,
- CK_ATTRIBUTE_TYPE type)
-{
- unsigned char hash[SHA1_LENGTH];
- CK_KEY_TYPE keyType = CKK_RSA;
-
- switch (type) {
- case CKA_KEY_TYPE:
- return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
- case CKA_ID:
- SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
- return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
- case CKA_DERIVE:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_DECRYPT:
- case CKA_SIGN:
- case CKA_SIGN_RECOVER:
- case CKA_UNWRAP:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_MODULUS:
- return sftk_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
- key->u.rsa.modulus.len, PR_FALSE);
- case CKA_PUBLIC_EXPONENT:
- return sftk_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
- key->u.rsa.publicExponent.len, PR_FALSE);
- case CKA_PRIVATE_EXPONENT:
- return sftk_NewTokenAttributeSigned(type,
- key->u.rsa.privateExponent.data,
- key->u.rsa.privateExponent.len, PR_FALSE);
- case CKA_PRIME_1:
- return sftk_NewTokenAttributeSigned(type, key->u.rsa.prime1.data,
- key->u.rsa.prime1.len, PR_FALSE);
- case CKA_PRIME_2:
- return sftk_NewTokenAttributeSigned(type, key->u.rsa.prime2.data,
- key->u.rsa.prime2.len, PR_FALSE);
- case CKA_EXPONENT_1:
- return sftk_NewTokenAttributeSigned(type, key->u.rsa.exponent1.data,
- key->u.rsa.exponent1.len, PR_FALSE);
- case CKA_EXPONENT_2:
- return sftk_NewTokenAttributeSigned(type, key->u.rsa.exponent2.data,
- key->u.rsa.exponent2.len, PR_FALSE);
- case CKA_COEFFICIENT:
- return sftk_NewTokenAttributeSigned(type, key->u.rsa.coefficient.data,
- key->u.rsa.coefficient.len, PR_FALSE);
- default:
- break;
- }
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key,
- CK_ATTRIBUTE_TYPE type)
-{
- unsigned char hash[SHA1_LENGTH];
- CK_KEY_TYPE keyType = CKK_DSA;
-
- switch (type) {
- case CKA_KEY_TYPE:
- return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
- case CKA_ID:
- SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
- key->u.dsa.publicValue.len);
- return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
- case CKA_DERIVE:
- case CKA_DECRYPT:
- case CKA_SIGN_RECOVER:
- case CKA_UNWRAP:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_SIGN:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_VALUE:
- return sftk_NewTokenAttributeSigned(type, key->u.dsa.privateValue.data,
- key->u.dsa.privateValue.len, PR_FALSE);
- case CKA_PRIME:
- return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
- key->u.dsa.params.prime.len, PR_FALSE);
- case CKA_SUBPRIME:
- return sftk_NewTokenAttributeSigned(type,
- key->u.dsa.params.subPrime.data,
- key->u.dsa.params.subPrime.len, PR_FALSE);
- case CKA_BASE:
- return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
- key->u.dsa.params.base.len, PR_FALSE);
- case CKA_NETSCAPE_DB:
- return sftk_NewTokenAttributeSigned(type,
- key->u.dsa.publicValue.data,
- key->u.dsa.publicValue.len,
- PR_FALSE);
- default:
- break;
- }
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type)
-{
- unsigned char hash[SHA1_LENGTH];
- CK_KEY_TYPE keyType = CKK_DH;
-
- switch (type) {
- case CKA_KEY_TYPE:
- return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
- case CKA_ID:
- SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
- return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
- case CKA_DERIVE:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_DECRYPT:
- case CKA_SIGN:
- case CKA_SIGN_RECOVER:
- case CKA_UNWRAP:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_VALUE:
- return sftk_NewTokenAttributeSigned(type,key->u.dh.privateValue.data,
- key->u.dh.privateValue.len, PR_FALSE);
- case CKA_PRIME:
- return sftk_NewTokenAttributeSigned(type,key->u.dh.prime.data,
- key->u.dh.prime.len, PR_FALSE);
- case CKA_BASE:
- return sftk_NewTokenAttributeSigned(type,key->u.dh.base.data,
- key->u.dh.base.len, PR_FALSE);
- case CKA_NETSCAPE_DB:
- return sftk_NewTokenAttributeSigned(type,
- key->u.dh.publicValue.data,
- key->u.dh.publicValue.len,
- PR_FALSE);
- default:
- break;
- }
- return NULL;
-}
-
-#ifdef NSS_ENABLE_ECC
-static SFTKAttribute *
-sftk_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type)
-{
- unsigned char hash[SHA1_LENGTH];
- CK_KEY_TYPE keyType = CKK_EC;
-
- switch (type) {
- case CKA_KEY_TYPE:
- return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
- case CKA_ID:
- SHA1_HashBuf(hash,key->u.ec.publicValue.data,key->u.ec.publicValue.len);
- return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
- case CKA_DERIVE:
- case CKA_SIGN:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_DECRYPT:
- case CKA_SIGN_RECOVER:
- case CKA_UNWRAP:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_VALUE:
- return sftk_NewTokenAttributeSigned(type, key->u.ec.privateValue.data,
- key->u.ec.privateValue.len, PR_FALSE);
- case CKA_EC_PARAMS:
- /* XXX Why is the last arg PR_FALSE? */
- return sftk_NewTokenAttributeSigned(type,
- key->u.ec.ecParams.DEREncoding.data,
- key->u.ec.ecParams.DEREncoding.len,
- PR_FALSE);
- case CKA_NETSCAPE_DB:
- return sftk_NewTokenAttributeSigned(type,
- key->u.ec.publicValue.data,
- key->u.ec.publicValue.len,
- PR_FALSE);
- default:
- break;
- }
- return NULL;
-}
-#endif /* NSS_ENABLE_ECC */
-
-static SFTKAttribute *
-sftk_FindPrivateKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
-{
- NSSLOWKEYPrivateKey *key;
- char *label;
- SFTKAttribute *att;
-
- switch (type) {
- case CKA_PRIVATE:
- case CKA_SENSITIVE:
- case CKA_ALWAYS_SENSITIVE:
- case CKA_EXTRACTABLE:
- case CKA_MODIFIABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_NEVER_EXTRACTABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_SUBJECT:
- return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
- case CKA_LABEL:
- label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
- &object->dbKey);
- if (label == NULL) {
- return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
- }
- att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
- PORT_Free(label);
- return att;
- default:
- break;
- }
- key = sftk_GetPrivateKey(object);
- if (key == NULL) {
- return NULL;
- }
- switch (key->keyType) {
- case NSSLOWKEYRSAKey:
- return sftk_FindRSAPrivateKeyAttribute(key,type);
- case NSSLOWKEYDSAKey:
- return sftk_FindDSAPrivateKeyAttribute(key,type);
- case NSSLOWKEYDHKey:
- return sftk_FindDHPrivateKeyAttribute(key,type);
-#ifdef NSS_ENABLE_ECC
- case NSSLOWKEYECKey:
- return sftk_FindECPrivateKeyAttribute(key,type);
-#endif /* NSS_ENABLE_ECC */
- default:
- break;
- }
-
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindSMIMEAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
-{
- certDBEntrySMime *entry;
- switch (type) {
- case CKA_PRIVATE:
- case CKA_MODIFIABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_NETSCAPE_EMAIL:
- return sftk_NewTokenAttribute(type,object->dbKey.data,
- object->dbKey.len-1, PR_FALSE);
- case CKA_NETSCAPE_SMIME_TIMESTAMP:
- case CKA_SUBJECT:
- case CKA_VALUE:
- break;
- default:
- return NULL;
- }
- entry = sftk_getSMime(object);
- if (entry == NULL) {
- return NULL;
- }
- switch (type) {
- case CKA_NETSCAPE_SMIME_TIMESTAMP:
- return sftk_NewTokenAttribute(type,entry->optionsDate.data,
- entry->optionsDate.len, PR_FALSE);
- case CKA_SUBJECT:
- return sftk_NewTokenAttribute(type,entry->subjectName.data,
- entry->subjectName.len, PR_FALSE);
- case CKA_VALUE:
- return sftk_NewTokenAttribute(type,entry->smimeOptions.data,
- entry->smimeOptions.len, PR_FALSE);
- default:
- break;
- }
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindTrustAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
-{
- NSSLOWCERTTrust *trust;
- unsigned char hash[SHA1_LENGTH];
- unsigned int trustFlags;
-
- switch (type) {
- case CKA_PRIVATE:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_MODIFIABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_CERT_SHA1_HASH:
- case CKA_CERT_MD5_HASH:
- case CKA_TRUST_CLIENT_AUTH:
- case CKA_TRUST_SERVER_AUTH:
- case CKA_TRUST_EMAIL_PROTECTION:
- case CKA_TRUST_CODE_SIGNING:
- case CKA_TRUST_STEP_UP_APPROVED:
- break;
- default:
- return NULL;
- }
- trust = sftk_getTrust(object);
- if (trust == NULL) {
- return NULL;
- }
- switch (type) {
- case CKA_CERT_SHA1_HASH:
- SHA1_HashBuf(hash,trust->derCert->data,trust->derCert->len);
- return sftk_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE);
- case CKA_CERT_MD5_HASH:
- MD5_HashBuf(hash,trust->derCert->data,trust->derCert->len);
- return sftk_NewTokenAttribute(type, hash, MD5_LENGTH, PR_TRUE);
- case CKA_TRUST_CLIENT_AUTH:
- trustFlags = trust->trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ?
- trust->trust->sslFlags | CERTDB_TRUSTED_CA : 0 ;
- goto trust;
- case CKA_TRUST_SERVER_AUTH:
- trustFlags = trust->trust->sslFlags;
- goto trust;
- case CKA_TRUST_EMAIL_PROTECTION:
- trustFlags = trust->trust->emailFlags;
- goto trust;
- case CKA_TRUST_CODE_SIGNING:
- trustFlags = trust->trust->objectSigningFlags;
-trust:
- if (trustFlags & CERTDB_TRUSTED_CA ) {
- return SFTK_CLONE_ATTR(type,sftk_StaticTrustedDelegatorAttr);
- }
- if (trustFlags & CERTDB_TRUSTED) {
- return SFTK_CLONE_ATTR(type,sftk_StaticTrustedAttr);
- }
- if (trustFlags & CERTDB_NOT_TRUSTED) {
- return SFTK_CLONE_ATTR(type,sftk_StaticUnTrustedAttr);
- }
- if (trustFlags & CERTDB_TRUSTED_UNKNOWN) {
- return SFTK_CLONE_ATTR(type,sftk_StaticTrustUnknownAttr);
- }
- if (trustFlags & CERTDB_VALID_CA) {
- return SFTK_CLONE_ATTR(type,sftk_StaticValidDelegatorAttr);
- }
- if (trustFlags & CERTDB_VALID_PEER) {
- return SFTK_CLONE_ATTR(type,sftk_StaticValidPeerAttr);
- }
- return SFTK_CLONE_ATTR(type,sftk_StaticMustVerifyAttr);
- case CKA_TRUST_STEP_UP_APPROVED:
- if (trust->trust->sslFlags & CERTDB_GOVT_APPROVED_CA) {
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- } else {
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- }
- default:
- break;
- }
-
-#ifdef notdef
- switch (type) {
- case CKA_ISSUER:
- cert = sftk_getCertObject(object);
- if (cert == NULL) break;
- attr = sftk_NewTokenAttribute(type,cert->derIssuer.data,
- cert->derIssuer.len, PR_FALSE);
-
- case CKA_SERIAL_NUMBER:
- cert = sftk_getCertObject(object);
- if (cert == NULL) break;
- item = SEC_ASN1EncodeItem(NULL,NULL,cert,sftk_SerialTemplate);
- if (item == NULL) break;
- attr = sftk_NewTokenAttribute(type, item->data, item->len, PR_TRUE);
- SECITEM_FreeItem(item,PR_TRUE);
- }
- if (cert) {
- NSSLOWCERTDestroyCertificate(cert);
- return attr;
- }
-#endif
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindCrlAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
+static SFTKAttribute *
+sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type)
{
- certDBEntryRevocation *crl;
+ SFTKAttribute *myattribute = NULL;
+ SFTKDBHandle *dbHandle = NULL;
+ CK_RV crv;
- switch (type) {
- case CKA_PRIVATE:
- case CKA_MODIFIABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_NETSCAPE_KRL:
- return ((object->obj.handle == SFTK_TOKEN_KRL_HANDLE)
- ? SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr)
- : SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr));
- case CKA_SUBJECT:
- return sftk_NewTokenAttribute(type,object->dbKey.data,
- object->dbKey.len, PR_FALSE);
- case CKA_NETSCAPE_URL:
- case CKA_VALUE:
- break;
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return NULL;
- }
- crl = sftk_getCrl(object);
- if (!crl) {
- return NULL;
- }
- switch (type) {
- case CKA_NETSCAPE_URL:
- if (crl->url == NULL) {
- return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
- }
- return sftk_NewTokenAttribute(type, crl->url,
- PORT_Strlen(crl->url)+1, PR_TRUE);
- case CKA_VALUE:
- return sftk_NewTokenAttribute(type, crl->derCrl.data,
- crl->derCrl.len, PR_FALSE);
- default:
- break;
+ myattribute = (SFTKAttribute*)PORT_Alloc(sizeof(SFTKAttribute));
+ if (myattribute == NULL) {
+ goto loser;
}
- return NULL;
-}
-static SFTKAttribute *
-sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
-{
- NSSLOWCERTCertificate *cert;
- NSSLOWCERTCertDBHandle *certHandle;
- NSSLOWKEYPublicKey *pubKey;
- unsigned char hash[SHA1_LENGTH];
- SECItem *item;
+ dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle);
- switch (type) {
- case CKA_PRIVATE:
- return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
- case CKA_MODIFIABLE:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_CERTIFICATE_TYPE:
- /* hardcoding X.509 into here */
- return SFTK_CLONE_ATTR(type,sftk_StaticX509Attr);
- case CKA_VALUE:
- case CKA_ID:
- case CKA_LABEL:
- case CKA_SUBJECT:
- case CKA_ISSUER:
- case CKA_SERIAL_NUMBER:
- case CKA_NETSCAPE_EMAIL:
- break;
- default:
- return NULL;
- }
+ myattribute->handle = type;
+ myattribute->attrib.type = type;
+ myattribute->attrib.pValue = myattribute->space;
+ myattribute->attrib.ulValueLen = ATTR_SPACE;
+ myattribute->next = myattribute->prev = NULL;
+ myattribute->freeAttr = PR_TRUE;
+ myattribute->freeData = PR_FALSE;
- certHandle = sftk_getCertDB(object->obj.slot);
- if (certHandle == NULL) {
- return NULL;
- }
+ crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
+ &myattribute->attrib, 1);
- cert = sftk_getCert(object, certHandle);
- sftk_freeCertDB(certHandle);
- if (cert == NULL) {
- return NULL;
- }
- switch (type) {
- case CKA_VALUE:
- return sftk_NewTokenAttribute(type,cert->derCert.data,
- cert->derCert.len,PR_FALSE);
- case CKA_ID:
- if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
- ((cert->trust->emailFlags & CERTDB_USER) == 0) &&
- ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
- return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
+ /* attribute is bigger than our attribute space buffer, malloc it */
+ if (crv == CKR_BUFFER_TOO_SMALL) {
+ myattribute->attrib.pValue = NULL;
+ crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
+ &myattribute->attrib, 1);
+ if (crv != CKR_OK) {
+ goto loser;
}
- pubKey = nsslowcert_ExtractPublicKey(cert);
- if (pubKey == NULL) break;
- item = sftk_GetPubItem(pubKey);
- if (item == NULL) {
- nsslowkey_DestroyPublicKey(pubKey);
- break;
+ myattribute->attrib.pValue = PORT_Alloc(myattribute->attrib.ulValueLen);
+ if (myattribute->attrib.pValue == NULL) {
+ crv = CKR_HOST_MEMORY;
+ goto loser;
}
- SHA1_HashBuf(hash,item->data,item->len);
- /* item is imbedded in pubKey, just free the key */
- nsslowkey_DestroyPublicKey(pubKey);
- return sftk_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE);
- case CKA_LABEL:
- return cert->nickname
- ? sftk_NewTokenAttribute(type, cert->nickname,
- PORT_Strlen(cert->nickname), PR_FALSE)
- : SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
- case CKA_SUBJECT:
- return sftk_NewTokenAttribute(type,cert->derSubject.data,
- cert->derSubject.len, PR_FALSE);
- case CKA_ISSUER:
- return sftk_NewTokenAttribute(type,cert->derIssuer.data,
- cert->derIssuer.len, PR_FALSE);
- case CKA_SERIAL_NUMBER:
- return sftk_NewTokenAttribute(type,cert->derSN.data,
- cert->derSN.len, PR_FALSE);
- case CKA_NETSCAPE_EMAIL:
- return (cert->emailAddr && cert->emailAddr[0])
- ? sftk_NewTokenAttribute(type, cert->emailAddr,
- PORT_Strlen(cert->emailAddr), PR_FALSE)
- : SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
- default:
- break;
+ myattribute->freeData = PR_TRUE;
+ crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
+ &myattribute->attrib, 1);
+ }
+loser:
+ if (dbHandle) {
+ sftk_freeDB(dbHandle);
}
- return NULL;
-}
-
-static SFTKAttribute *
-sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type)
-{
- /* handle the common ones */
- switch (type) {
- case CKA_CLASS:
- return sftk_NewTokenAttribute(type,&object->obj.objclass,
- sizeof(object->obj.objclass),PR_FALSE);
- case CKA_TOKEN:
- return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
- case CKA_LABEL:
- if ( (object->obj.objclass == CKO_CERTIFICATE)
- || (object->obj.objclass == CKO_PRIVATE_KEY)
- || (object->obj.objclass == CKO_PUBLIC_KEY)
- || (object->obj.objclass == CKO_SECRET_KEY)) {
- break;
+ if (crv != CKR_OK) {
+ if (myattribute) {
+ myattribute->attrib.ulValueLen = 0;
+ sftk_FreeAttribute(myattribute);
+ myattribute = NULL;
}
- return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
- default:
- break;
- }
- switch (object->obj.objclass) {
- case CKO_CERTIFICATE:
- return sftk_FindCertAttribute(object,type);
- case CKO_NETSCAPE_CRL:
- return sftk_FindCrlAttribute(object,type);
- case CKO_NETSCAPE_TRUST:
- return sftk_FindTrustAttribute(object,type);
- case CKO_NETSCAPE_SMIME:
- return sftk_FindSMIMEAttribute(object,type);
- case CKO_PUBLIC_KEY:
- return sftk_FindPublicKeyAttribute(object,type);
- case CKO_PRIVATE_KEY:
- return sftk_FindPrivateKeyAttribute(object,type);
- case CKO_SECRET_KEY:
- return sftk_FindSecretKeyAttribute(object,type);
- default:
- break;
}
- PORT_Assert(0);
- return NULL;
+ return myattribute;
}
/*
@@ -1434,9 +283,22 @@ sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
}
PRBool
-sftk_hasAttributeToken(SFTKTokenObject *object)
+sftk_hasAttributeToken(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
{
- return PR_FALSE;
+ CK_ATTRIBUTE template;
+ CK_RV crv;
+ SFTKDBHandle *dbHandle;
+
+ dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle);
+ template.type = type;
+ template.pValue = NULL;
+ template.ulValueLen = 0;
+
+ crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, &template, 1);
+ sftk_freeDB(dbHandle);
+
+ /* attribute is bigger than our attribute space buffer, malloc it */
+ return (crv == CKR_OK) ? PR_TRUE : PR_FALSE;
}
/*
@@ -1449,7 +311,7 @@ sftk_hasAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
if (sessObject == NULL) {
- return sftk_hasAttributeToken(sftk_narrowToTokenObject(object));
+ return sftk_hasAttributeToken(sftk_narrowToTokenObject(object), type);
}
PZ_Lock(sessObject->attributeLock);
@@ -1563,254 +425,35 @@ sftk_nullAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
sftk_FreeAttribute(attribute);
}
-static CK_RV
-sftk_SetCertAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
- void *value, unsigned int len)
-{
- NSSLOWCERTCertificate *cert;
- NSSLOWCERTCertDBHandle *certHandle;
- char *nickname = NULL;
- SECStatus rv;
- CK_RV crv;
-
- /* we can't change the EMAIL values, but let the
- * upper layers feel better about the fact we tried to set these */
- if (type == CKA_NETSCAPE_EMAIL) {
- return CKR_OK;
- }
-
- certHandle = sftk_getCertDB(to->obj.slot);
- if (certHandle == NULL) {
- crv = CKR_TOKEN_WRITE_PROTECTED;
- goto done;
- }
-
- if ((type != CKA_LABEL) && (type != CKA_ID)) {
- crv = CKR_ATTRIBUTE_READ_ONLY;
- goto done;
- }
-
- cert = sftk_getCert(to, certHandle);
- if (cert == NULL) {
- crv = CKR_OBJECT_HANDLE_INVALID;
- goto done;
- }
-
- /* if the app is trying to set CKA_ID, it's probably because it just
- * imported the key. Look to see if we need to set the CERTDB_USER bits.
- */
- if (type == CKA_ID) {
- if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
- ((cert->trust->emailFlags & CERTDB_USER) == 0) &&
- ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
- SFTKSlot *slot = to->obj.slot;
- NSSLOWKEYDBHandle *keyHandle;
-
- keyHandle = sftk_getKeyDB(slot);
- if (keyHandle) {
- if (nsslowkey_KeyForCertExists(keyHandle, cert)) {
- NSSLOWCERTCertTrust trust = *cert->trust;
- trust.sslFlags |= CERTDB_USER;
- trust.emailFlags |= CERTDB_USER;
- trust.objectSigningFlags |= CERTDB_USER;
- nsslowcert_ChangeCertTrust(certHandle,cert,&trust);
- }
- sftk_freeKeyDB(keyHandle);
- }
- }
- crv = CKR_OK;
- goto done;
- }
-
- /* must be CKA_LABEL */
- if (value != NULL) {
- nickname = PORT_ZAlloc(len+1);
- if (nickname == NULL) {
- crv = CKR_HOST_MEMORY;
- goto done;
- }
- PORT_Memcpy(nickname,value,len);
- nickname[len] = 0;
- }
- rv = nsslowcert_AddPermNickname(certHandle, cert, nickname);
- crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
-
-done:
- if (nickname) {
- PORT_Free(nickname);
- }
- if (certHandle) {
- sftk_freeCertDB(certHandle);
- }
- return crv;
-}
-
-static CK_RV
-sftk_SetPrivateKeyAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
- void *value, unsigned int len)
-{
- NSSLOWKEYPrivateKey *privKey;
- NSSLOWKEYDBHandle *keyHandle;
- char *nickname = NULL;
- SECStatus rv;
- CK_RV crv;
-
- /* we can't change the ID and we don't store the subject, but let the
- * upper layers feel better about the fact we tried to set these */
- if ((type == CKA_ID) || (type == CKA_SUBJECT)) {
- return CKR_OK;
- }
-
- keyHandle = sftk_getKeyDB(to->obj.slot);
- if (keyHandle == NULL) {
- crv = CKR_TOKEN_WRITE_PROTECTED;
- goto done;
- }
- if (type != CKA_LABEL) {
- crv = CKR_ATTRIBUTE_READ_ONLY;
- goto done;
- }
-
- privKey = sftk_GetPrivateKeyWithDB(to, keyHandle);
- if (privKey == NULL) {
- crv = CKR_OBJECT_HANDLE_INVALID;
- goto done;
- }
- if (value != NULL) {
- nickname = PORT_ZAlloc(len+1);
- if (nickname == NULL) {
- crv = CKR_HOST_MEMORY;
- goto done;
- }
- PORT_Memcpy(nickname,value,len);
- nickname[len] = 0;
- }
- rv = nsslowkey_UpdateNickname(keyHandle, privKey, &to->dbKey,
- nickname, to->obj.slot->password);
- crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
-done:
- if (nickname) {
- PORT_Free(nickname);
- }
- if (keyHandle) {
- sftk_freeKeyDB(keyHandle);
- }
- return crv;
-}
-
-static CK_RV
-sftk_SetTrustAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
- void *value, unsigned int len)
-{
- unsigned int flags;
- CK_TRUST trust;
- NSSLOWCERTCertificate *cert;
- NSSLOWCERTCertDBHandle *certHandle;
- NSSLOWCERTCertTrust dbTrust;
- SECStatus rv;
- CK_RV crv;
-
- if (len != sizeof (CK_TRUST)) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- trust = *(CK_TRUST *)value;
- flags = sftk_MapTrust(trust, (PRBool) (type == CKA_TRUST_SERVER_AUTH));
-
- certHandle = sftk_getCertDB(to->obj.slot);
-
- if (certHandle == NULL) {
- crv = CKR_TOKEN_WRITE_PROTECTED;
- goto done;
- }
-
- cert = sftk_getCert(to, certHandle);
- if (cert == NULL) {
- crv = CKR_OBJECT_HANDLE_INVALID;
- goto done;
- }
- dbTrust = *cert->trust;
-
- switch (type) {
- case CKA_TRUST_EMAIL_PROTECTION:
- dbTrust.emailFlags = flags |
- (cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS);
- break;
- case CKA_TRUST_CODE_SIGNING:
- dbTrust.objectSigningFlags = flags |
- (cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS);
- break;
- case CKA_TRUST_CLIENT_AUTH:
- dbTrust.sslFlags = flags | (cert->trust->sslFlags &
- (CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CA));
- break;
- case CKA_TRUST_SERVER_AUTH:
- dbTrust.sslFlags = flags | (cert->trust->sslFlags &
- (CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA));
- break;
- default:
- crv = CKR_ATTRIBUTE_READ_ONLY;
- goto done;
- }
-
- rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust);
- crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
-done:
- if (certHandle) {
- sftk_freeCertDB(certHandle);
- }
- return crv;
-}
static CK_RV
sftk_forceTokenAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type,
void *value, unsigned int len)
{
- SFTKAttribute *attribute;
+ CK_ATTRIBUTE attribute;
+ SFTKDBHandle *dbHandle = NULL;
SFTKTokenObject *to = sftk_narrowToTokenObject(object);
- CK_RV crv = CKR_ATTRIBUTE_READ_ONLY;
+ CK_RV crv;
PORT_Assert(to);
if (to == NULL) {
return CKR_DEVICE_ERROR;
}
- /* if we are just setting it to the value we already have,
- * allow it to happen. Let label setting go through so
- * we have the opportunity to repair any database corruption. */
- attribute=sftk_FindAttribute(object,type);
- PORT_Assert(attribute);
- if (!attribute) {
- return CKR_ATTRIBUTE_TYPE_INVALID;
+ dbHandle = sftk_getDBForTokenObject(object->slot, object->handle);
- }
- if ((type != CKA_LABEL) && (attribute->attrib.ulValueLen == len) &&
- PORT_Memcmp(attribute->attrib.pValue,value,len) == 0) {
- sftk_FreeAttribute(attribute);
- return CKR_OK;
- }
+ attribute.type = type;
+ attribute.pValue = value;
+ attribute.ulValueLen = len;
- switch (object->objclass) {
- case CKO_CERTIFICATE:
- /* change NICKNAME, EMAIL, */
- crv = sftk_SetCertAttribute(to,type,value,len);
- break;
- case CKO_NETSCAPE_CRL:
- /* change URL */
- break;
- case CKO_NETSCAPE_TRUST:
- crv = sftk_SetTrustAttribute(to,type,value,len);
- break;
- case CKO_PRIVATE_KEY:
- case CKO_SECRET_KEY:
- crv = sftk_SetPrivateKeyAttribute(to,type,value,len);
- break;
- }
- sftk_FreeAttribute(attribute);
+ crv = sftkdb_SetAttributeValue(dbHandle, object->handle,
+ &attribute, 1);
+ sftk_freeDB(dbHandle);
return crv;
}
/*
- * force an attribute to a spaecif value.
+ * force an attribute to a specifc value.
*/
CK_RV
sftk_forceAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, void *value,
@@ -2087,44 +730,6 @@ sftk_AddAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type,void *valPtr,
* ******************** Object Utilities *******************************
*/
-static SECStatus
-sftk_deleteTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
-{
- SECItem *item;
- PRBool rem;
-
- item = (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle);
- rem = PL_HashTableRemove(slot->tokObjHashTable,(void *)handle) ;
- if (rem && item) {
- SECITEM_FreeItem(item,PR_TRUE);
- }
- return rem ? SECSuccess : SECFailure;
-}
-
-/* must be called holding sftk_tokenKeyLock(slot) */
-static SECStatus
-sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key)
-{
- PLHashEntry *entry;
- SECItem *item;
-
- /* don't add a new handle in the middle of closing down a slot */
- if (!slot->present) {
- return SECFailure;
- }
-
- item = SECITEM_DupItem(key);
- if (item == NULL) {
- return SECFailure;
- }
- entry = PL_HashTableAdd(slot->tokObjHashTable,(void *)handle,item);
- if (entry == NULL) {
- SECITEM_FreeItem(item,PR_TRUE);
- return SECFailure;
- }
- return SECSuccess;
-}
-
/* must be called holding sftk_tokenKeyLock(slot) */
static SECItem *
sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
@@ -2213,7 +818,8 @@ sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list,
*/
PRBool optimizeSpace = isSessionObject &&
((SFTKSessionObject *)object)->optimizeSpace;
- if (!optimizeSpace && (list->count < MAX_OBJECT_LIST_SIZE)) {
+ if (object->refLock && !optimizeSpace
+ && (list->count < MAX_OBJECT_LIST_SIZE)) {
PZ_Lock(list->lock);
object->next = list->head;
list->head = object;
@@ -2226,8 +832,10 @@ sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list,
PZ_DestroyLock(so->attributeLock);
so->attributeLock = NULL;
}
- PZ_DestroyLock(object->refLock);
- object->refLock = NULL;
+ if (object->refLock) {
+ PZ_DestroyLock(object->refLock);
+ object->refLock = NULL;
+ }
PORT_Free(object);
}
@@ -2501,10 +1109,6 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
SFTKSessionObject *so = sftk_narrowToSessionObject(object);
SFTKTokenObject *to = sftk_narrowToTokenObject(object);
CK_RV crv = CKR_OK;
- SECStatus rv;
- NSSLOWCERTCertificate *cert;
- NSSLOWCERTCertTrust tmptrust;
- PRBool isKrl;
PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize);
/* Handle Token case */
@@ -2519,88 +1123,11 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
sftkqueue_clear_deleted_element(object);
sftk_FreeObject(object); /* reduce it's reference count */
} else {
- NSSLOWKEYDBHandle *keyHandle;
- NSSLOWCERTCertDBHandle *certHandle;
+ SFTKDBHandle *handle = sftk_getDBForTokenObject(slot, object->handle);
PORT_Assert(to);
- /* remove the objects from the real data base */
- switch (object->handle & SFTK_TOKEN_TYPE_MASK) {
- case SFTK_TOKEN_TYPE_PRIV:
- case SFTK_TOKEN_TYPE_KEY:
- /* KEYID is the public KEY for DSA and DH, and the MODULUS for
- * RSA */
- keyHandle = sftk_getKeyDB(slot);
- if (!keyHandle) {
- crv = CKR_TOKEN_WRITE_PROTECTED;
- break;
- }
- rv = nsslowkey_DeleteKey(keyHandle, &to->dbKey);
- sftk_freeKeyDB(keyHandle);
- if (rv != SECSuccess) {
- crv = CKR_DEVICE_ERROR;
- }
- break;
- case SFTK_TOKEN_TYPE_PUB:
- break; /* public keys only exist at the behest of the priv key */
- case SFTK_TOKEN_TYPE_CERT:
- certHandle = sftk_getCertDB(slot);
- if (!certHandle) {
- crv = CKR_TOKEN_WRITE_PROTECTED;
- break;
- }
- cert = nsslowcert_FindCertByKey(certHandle,&to->dbKey);
- sftk_freeCertDB(certHandle);
- if (cert == NULL) {
- crv = CKR_DEVICE_ERROR;
- break;
- }
- rv = nsslowcert_DeletePermCertificate(cert);
- if (rv != SECSuccess) {
- crv = CKR_DEVICE_ERROR;
- }
- nsslowcert_DestroyCertificate(cert);
- break;
- case SFTK_TOKEN_TYPE_CRL:
- certHandle = sftk_getCertDB(slot);
- if (!certHandle) {
- crv = CKR_TOKEN_WRITE_PROTECTED;
- break;
- }
- isKrl = (PRBool) (object->handle == SFTK_TOKEN_KRL_HANDLE);
- rv = nsslowcert_DeletePermCRL(certHandle, &to->dbKey, isKrl);
- sftk_freeCertDB(certHandle);
- if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
- break;
- case SFTK_TOKEN_TYPE_TRUST:
- certHandle = sftk_getCertDB(slot);
- if (!certHandle) {
- crv = CKR_TOKEN_WRITE_PROTECTED;
- break;
- }
- cert = nsslowcert_FindCertByKey(certHandle, &to->dbKey);
- if (cert == NULL) {
- sftk_freeCertDB(certHandle);
- crv = CKR_DEVICE_ERROR;
- break;
- }
- tmptrust = *cert->trust;
- tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS;
- tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS;
- tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS;
- tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN;
- tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN;
- tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN;
- rv = nsslowcert_ChangeCertTrust(certHandle, cert, &tmptrust);
- sftk_freeCertDB(certHandle);
- if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
- nsslowcert_DestroyCertificate(cert);
- break;
- default:
- break;
- }
- sftk_tokenKeyLock(object->slot);
- sftk_deleteTokenKeyByHandle(object->slot,object->handle);
- sftk_tokenKeyUnlock(object->slot);
+ crv = sftkdb_DestroyObject(handle, object->handle);
+ sftk_freeDB(handle);
}
return crv;
}
@@ -3265,93 +1792,6 @@ sftk_FreeSession(SFTKSession *session)
if (destroy) sftk_DestroySession(session);
}
-/*
- * handle Token Object stuff
- */
-static void
-sftk_XORHash(unsigned char *key, unsigned char *dbkey, int len)
-{
- int i;
-
- PORT_Memset(key, 0, 4);
-
- for (i=0; i < len-4; i += 4) {
- key[0] ^= dbkey[i];
- key[1] ^= dbkey[i+1];
- key[2] ^= dbkey[i+2];
- key[3] ^= dbkey[i+3];
- }
-}
-
-/* Make a token handle for an object and record it so we can find it again */
-CK_OBJECT_HANDLE
-sftk_mkHandle(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class)
-{
- unsigned char hashBuf[4];
- CK_OBJECT_HANDLE handle;
- SECItem *key;
-
- handle = class;
- /* there is only one KRL, use a fixed handle for it */
- if (handle != SFTK_TOKEN_KRL_HANDLE) {
- sftk_XORHash(hashBuf,dbKey->data,dbKey->len);
- handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
- (hashBuf[2] << 8) | hashBuf[3];
- handle = SFTK_TOKEN_MAGIC | class |
- (handle & ~(SFTK_TOKEN_TYPE_MASK|SFTK_TOKEN_MASK));
- /* we have a CRL who's handle has randomly matched the reserved KRL
- * handle, increment it */
- if (handle == SFTK_TOKEN_KRL_HANDLE) {
- handle++;
- }
- }
-
- sftk_tokenKeyLock(slot);
- while ((key = sftk_lookupTokenKeyByHandle(slot,handle)) != NULL) {
- if (SECITEM_ItemsAreEqual(key,dbKey)) {
- sftk_tokenKeyUnlock(slot);
- return handle;
- }
- handle++;
- }
- sftk_addTokenKeyByHandle(slot,handle,dbKey);
- sftk_tokenKeyUnlock(slot);
- return handle;
-}
-
-PRBool
-sftk_poisonHandle(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class)
-{
- unsigned char hashBuf[4];
- CK_OBJECT_HANDLE handle;
- SECItem *key;
-
- handle = class;
- /* there is only one KRL, use a fixed handle for it */
- if (handle != SFTK_TOKEN_KRL_HANDLE) {
- sftk_XORHash(hashBuf,dbKey->data,dbKey->len);
- handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
- (hashBuf[2] << 8) | hashBuf[3];
- handle = SFTK_TOKEN_MAGIC | class |
- (handle & ~(SFTK_TOKEN_TYPE_MASK|SFTK_TOKEN_MASK));
- /* we have a CRL who's handle has randomly matched the reserved KRL
- * handle, increment it */
- if (handle == SFTK_TOKEN_KRL_HANDLE) {
- handle++;
- }
- }
- sftk_tokenKeyLock(slot);
- while ((key = sftk_lookupTokenKeyByHandle(slot,handle)) != NULL) {
- if (SECITEM_ItemsAreEqual(key,dbKey)) {
- key->data[0] ^= 0x80;
- sftk_tokenKeyUnlock(slot);
- return PR_TRUE;
- }
- handle++;
- }
- sftk_tokenKeyUnlock(slot);
- return PR_FALSE;
-}
void
sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle)
@@ -3371,13 +1811,22 @@ sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle)
search->size++;
}
-static const CK_OBJECT_HANDLE sftk_classArray[] = {
- 0, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY,
- CKO_NETSCAPE_TRUST, CKO_NETSCAPE_CRL, CKO_NETSCAPE_SMIME,
- CKO_CERTIFICATE };
+static CK_RV
+handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle,
+ CK_OBJECT_CLASS *objClass)
+{
+ SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, handle);
+ CK_ATTRIBUTE objClassTemplate;
+ CK_RV crv;
-#define handleToClass(handle) \
- sftk_classArray[((handle & SFTK_TOKEN_TYPE_MASK))>>28]
+ *objClass = CKO_DATA;
+ objClassTemplate.type = CKA_CLASS;
+ objClassTemplate.pValue = objClass;
+ objClassTemplate.ulValueLen = sizeof(*objClass);
+ crv = sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1);
+ sftk_freeDB(dbHandle);
+ return crv;
+}
SFTKObject *
sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
@@ -3385,7 +1834,7 @@ sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
SFTKObject *object = NULL;
SFTKTokenObject *tokObject = NULL;
PRBool hasLocks = PR_FALSE;
- SECStatus rv;
+ CK_RV crv;
object = sftk_GetObjectFromList(&hasLocks, PR_FALSE, &tokenObjectList, 0,
PR_FALSE);
@@ -3394,26 +1843,16 @@ sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
}
tokObject = (SFTKTokenObject *) object;
- object->objclass = handleToClass(handle);
object->handle = handle;
+ /* every object must have a class, if we can't get it, the object
+ * doesn't exist */
+ crv = handleToClass(slot, handle, &object->objclass);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
object->slot = slot;
object->objectInfo = NULL;
object->infoFree = NULL;
- if (dbKey == NULL) {
- sftk_tokenKeyLock(slot);
- dbKey = sftk_lookupTokenKeyByHandle(slot,handle);
- if (dbKey == NULL) {
- sftk_tokenKeyUnlock(slot);
- goto loser;
- }
- rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
- sftk_tokenKeyUnlock(slot);
- } else {
- rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
- }
- if (rv != SECSuccess) {
- goto loser;
- }
if (!hasLocks) {
object->refLock = PZ_NewLock(nssILockRefLock);
}
@@ -3431,23 +1870,6 @@ loser:
}
-PRBool
-sftk_tokenMatch(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class,
- CK_ATTRIBUTE_PTR theTemplate,int count)
-{
- SFTKObject *object;
- PRBool ret;
-
- object = sftk_NewTokenObject(slot,dbKey,SFTK_TOKEN_MASK|class);
- if (object == NULL) {
- return PR_FALSE;
- }
-
- ret = sftk_objectMatch(object,theTemplate,count);
- sftk_FreeObject(object);
- return ret;
-}
-
SFTKTokenObject *
sftk_convertSessionToToken(SFTKObject *obj)
{
@@ -3474,7 +1896,6 @@ sftk_convertSessionToToken(SFTKObject *obj)
}
return to;
-
}
SFTKSessionObject *
diff --git a/security/nss/lib/softoken/sdb.c b/security/nss/lib/softoken/sdb.c
new file mode 100644
index 000000000..2642a991d
--- /dev/null
+++ b/security/nss/lib/softoken/sdb.c
@@ -0,0 +1,1518 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Red Hat, Inc.
+ *
+ * The Initial Developer of the Original Code is
+ * Red Hat, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert Relyea (rrelyea@redhat.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * This file implements PKCS 11 on top of our existing security modules
+ *
+ * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
+ * This implementation has two slots:
+ * slot 1 is our generic crypto support. It does not require login.
+ * It supports Public Key ops, and all they bulk ciphers and hashes.
+ * It can also support Private Key ops for imported Private keys. It does
+ * not have any token storage.
+ * slot 2 is our private key support. It requires a login before use. It
+ * can store Private Keys and Certs as token objects. Currently only private
+ * keys and their associated Certificates are saved on the token.
+ *
+ * In this implementation, session objects are only visible to the session
+ * that created or generated them.
+ */
+
+#include "sdb.h"
+#include "pkcs11t.h"
+#include "seccomon.h"
+#include <sqlite3.h>
+#include "prthread.h"
+#include "prio.h"
+#include "stdio.h"
+
+#include "prlock.h"
+
+#ifdef SQLITE_UNSAFE_THREADS
+/*
+ * SQLite can be compiled to be thread safe or not.
+ * turn on SQLITE_UNSAFE_THREADS if the OS does not support
+ * a thread safe version of sqlite.
+ */
+static PRLock *sqlite_lock = NULL;
+
+#define LOCK_SQLITE() PR_Lock(sqlite_lock);
+#define UNLOCK_SQLITE() PR_Unlock(sqlite_lock);
+#else
+#define LOCK_SQLITE()
+#define UNLOCK_SQLITE()
+#endif
+
+typedef enum {
+ SDB_CERT = 1,
+ SDB_KEY = 2
+} sdbDataType;
+
+struct SDBPrivateStr {
+ char *sqlDBName; /* invarient, path to this database */
+ sqlite3 *sqlXactDB; /* protected by lock, current transaction db*/
+ PRThread *sqlXactThread; /* protected by lock,
+ * current transaiction thred*/
+ sdbDataType type; /* invariant, database type */
+ char *table; /* invariant, SQL table which contains the db */
+ PRLock *lock; /* invariant, lock to protect sqlXact* fields*/
+};
+
+typedef struct SDBPrivateStr SDBPrivate;
+
+/*
+ * known attributes
+ */
+static const CK_ATTRIBUTE_TYPE known_attributes[] = {
+ CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION,
+ CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER,
+ CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED,
+ CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL,
+ CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY,
+ CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE,
+ CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER,
+ CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE,
+ CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT,
+ CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT,
+ CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS,
+ CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE,
+ CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE,
+ CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS,
+ CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_TEMPLATE,
+ CKA_UNWRAP_TEMPLATE, CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT,
+ CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y, CKA_RESOLUTION, CKA_CHAR_ROWS,
+ CKA_CHAR_COLUMNS, CKA_COLOR, CKA_BITS_PER_PIXEL, CKA_CHAR_SETS,
+ CKA_ENCODING_METHODS, CKA_MIME_TYPES, CKA_MECHANISM_TYPE,
+ CKA_REQUIRED_CMS_ATTRIBUTES, CKA_DEFAULT_CMS_ATTRIBUTES,
+ CKA_SUPPORTED_CMS_ATTRIBUTES, CKA_NETSCAPE_URL, CKA_NETSCAPE_EMAIL,
+ CKA_NETSCAPE_SMIME_INFO, CKA_NETSCAPE_SMIME_TIMESTAMP,
+ CKA_NETSCAPE_PKCS8_SALT, CKA_NETSCAPE_PASSWORD_CHECK, CKA_NETSCAPE_EXPIRES,
+ CKA_NETSCAPE_KRL, CKA_NETSCAPE_PQG_COUNTER, CKA_NETSCAPE_PQG_SEED,
+ CKA_NETSCAPE_PQG_H, CKA_NETSCAPE_PQG_SEED_BITS, CKA_NETSCAPE_MODULE_SPEC,
+ CKA_TRUST_DIGITAL_SIGNATURE, CKA_TRUST_NON_REPUDIATION,
+ CKA_TRUST_KEY_ENCIPHERMENT, CKA_TRUST_DATA_ENCIPHERMENT,
+ CKA_TRUST_KEY_AGREEMENT, CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN,
+ CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING,
+ CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM,
+ CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING,
+ CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
+ CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS
+};
+
+static int known_attributes_size= sizeof(known_attributes)/
+ sizeof(known_attributes[0]);
+
+/* Magic for an explicit NULL. NOTE: ideally this should be
+ * out of band data. Since it's not completely out of band, pick
+ * a value that has no meaning to any existing PKCS #11 attributes.
+ * This value is 1) not a valid string (imbedded '\0'). 2) not a U_LONG
+ * or a normal key (too short). 3) not a bool (too long). 4) not an RSA
+ * public exponent (too many bits).
+ */
+const unsigned char SQLITE_EXPLICIT_NULL[] = { 0xa5, 0x0, 0x5a };
+#define SQLITE_EXPLICIT_NULL_LEN 3
+
+/*
+ * determine when we've completed our tasks
+ */
+#define MAX_RETRIES 10
+static int
+sdb_done(int err, int *count)
+{
+ /* allow as many rows as the database wants to give */
+ if (err == SQLITE_ROW) {
+ *count = 0;
+ return 0;
+ }
+ if (err != SQLITE_BUSY) {
+ return 1;
+ }
+ /* err == SQLITE_BUSY, Dont' retry forever in this case */
+ if (++(*count) >= MAX_RETRIES) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Map SQL_LITE errors to PKCS #11 errors as best we can.
+ */
+static int
+sdb_mapSQLError(sdbDataType type, int sqlerr)
+{
+ switch (sqlerr) {
+ /* good matches */
+ case SQLITE_OK:
+ case SQLITE_DONE:
+ return CKR_OK;
+ case SQLITE_NOMEM:
+ return CKR_HOST_MEMORY;
+ case SQLITE_READONLY:
+ return CKR_TOKEN_WRITE_PROTECTED;
+ /* close matches */
+ case SQLITE_AUTH:
+ case SQLITE_PERM:
+ /*return CKR_USER_NOT_LOGGED_IN; */
+ case SQLITE_CANTOPEN:
+ case SQLITE_NOTFOUND:
+ /* NSS distiguishes between failure to open the cert and the key db */
+ return type == SDB_CERT ?
+ CKR_NETSCAPE_CERTDB_FAILED : CKR_NETSCAPE_KEYDB_FAILED;
+ case SQLITE_IOERR:
+ return CKR_DEVICE_ERROR;
+ default:
+ break;
+ }
+ return CKR_GENERAL_ERROR;
+}
+
+/*
+ * sqlite3 cannot share handles across threads, in general.
+ * PKCS #11 modules can be called thread, so we need to constantly open and
+ * close the sqlite database.
+ *
+ * The one exception is transactions. When we are in a transaction, we must
+ * use the same database pointer for that entire transation. In this case
+ * we save the transaction database and use it for all accesses on the
+ * transaction thread. Other threads still get their own database.
+ *
+ * There can only be once active transaction on the database at a time.
+ */
+static CK_RV
+sdb_openDBLocal(SDBPrivate *sdb_p, sqlite3 **sqlDB)
+{
+#ifdef SQLITE_THREAD_SHARE_DB
+ *sqlDB = sdb_p->sqlXactDB;
+ return CKR_OK;
+#else
+
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+
+ char *dbname = sdb_p->sqlDBName;
+ sdbDataType type = sdb_p->type;
+
+ *sqlDB = NULL;
+
+ PR_Lock(sdb_p->lock);
+
+ /* We're in a transaction, use the transaction DB */
+ if ((sdb_p->sqlXactDB) && (sdb_p->sqlXactThread == PR_GetCurrentThread())) {
+ *sqlDB =sdb_p->sqlXactDB;
+ /* only one thread can get here, safe to unlock */
+ PR_Unlock(sdb_p->lock);
+ return CKR_OK;
+ }
+
+ /* we're and independent operation, get our own db handle */
+ PR_Unlock(sdb_p->lock);
+
+ sqlerr = sqlite3_open(dbname, sqlDB);
+ if (sqlerr != SQLITE_OK) {
+ error = sdb_mapSQLError(type, sqlerr);
+ goto loser;
+ }
+
+ sqlerr = sqlite3_busy_timeout(*sqlDB, 1000);
+ if (sqlerr != CKR_OK) {
+ error = sdb_mapSQLError(type, sqlerr);
+ goto loser;
+ }
+ return error;
+
+loser:
+ if (*sqlDB) {
+ sqlite3_close(*sqlDB);
+ *sqlDB = NULL;
+ }
+ return error;
+#endif
+}
+
+/* down with the local database, free it if we allocated it, otherwise
+ * free unlock our use the the transaction database */
+static CK_RV
+sdb_closeDBLocal(SDBPrivate *sdb_p, sqlite3 *sqlDB)
+{
+#ifndef SQLITE_THREAD_SHARE_DB
+ if (sdb_p->sqlXactDB != sqlDB) {
+ sqlite3_close(sqlDB);
+ }
+#endif
+ return CKR_OK;
+}
+
+struct SDBFindStr {
+ sqlite3 *sqlDB;
+ sqlite3_stmt *findstmt;
+};
+
+
+#define FIND_OBJECTS_CMD "SELECT ALL * FROM %s WHERE %s;"
+#define FIND_OBJECTS_ALL_CMD "SELECT ALL * FROM %s;"
+CK_RV
+sdb_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *template, CK_ULONG count,
+ SDBFind **find)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = NULL;
+ char *newStr, *findStr = NULL;
+ sqlite3_stmt *findstmt = NULL;
+ char *join="";
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+ int i;
+
+ LOCK_SQLITE()
+ *find = NULL;
+ error = sdb_openDBLocal(sdb_p, &sqlDB);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+
+ findStr = sqlite3_mprintf("");
+ for (i=0; findStr && i < count; i++) {
+ newStr = sqlite3_mprintf("%s%sa%x=$DATA%d", findStr, join,
+ template[i].type, i);
+ join=" AND ";
+ sqlite3_free(findStr);
+ findStr = newStr;
+ }
+
+ if (findStr == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+
+ if (count == 0) {
+ newStr = sqlite3_mprintf(FIND_OBJECTS_ALL_CMD, sdb_p->table);
+ } else {
+ newStr = sqlite3_mprintf(FIND_OBJECTS_CMD, sdb_p->table, findStr);
+ }
+ sqlite3_free(findStr);
+ if (newStr == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ sqlerr = sqlite3_prepare(sqlDB, newStr, -1, &findstmt, NULL);
+ sqlite3_free(newStr);
+ for (i=0; sqlerr == SQLITE_OK && i < count; i++) {
+ sqlerr = sqlite3_bind_blob(findstmt, i+1, template[i].pValue,
+ template[i].ulValueLen, SQLITE_TRANSIENT);
+ }
+ if (sqlerr == SQLITE_OK) {
+ *find = PORT_New(SDBFind);
+ if (*find == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ (*find)->findstmt = findstmt;
+ (*find)->sqlDB = sqlDB;
+ UNLOCK_SQLITE()
+ return CKR_OK;
+ }
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+
+loser:
+ if (findstmt) {
+ sqlite3_finalize(findstmt);
+ }
+ if (sqlDB) {
+ sdb_closeDBLocal(sdb_p, sqlDB) ;
+ }
+ UNLOCK_SQLITE()
+ return error;
+}
+
+
+CK_RV
+sdb_FindObjects(SDB *sdb, SDBFind *sdbFind, CK_OBJECT_HANDLE *object,
+ CK_ULONG arraySize, CK_ULONG *count)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3_stmt *stmt = sdbFind->findstmt;
+ int sqlerr = SQLITE_OK;
+ int retry = 0;
+
+ *count = 0;
+
+ if (arraySize == 0) {
+ return CKR_OK;
+ }
+ LOCK_SQLITE()
+
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(5);
+ }
+ if (sqlerr == SQLITE_ROW) {
+ /* only care about the id */
+ *object++= sqlite3_column_int(stmt, 0);
+ arraySize--;
+ (*count)++;
+ }
+ } while (!sdb_done(sqlerr,&retry) && (arraySize > 0));
+
+ /* we only have some of the objects, there is probably more,
+ * set the sqlerr to an OK value so we return CKR_OK */
+ if (sqlerr == SQLITE_ROW && arraySize == 0) {
+ sqlerr = SQLITE_DONE;
+ }
+ UNLOCK_SQLITE()
+
+ return sdb_mapSQLError(sdb_p->type, sqlerr);
+}
+
+CK_RV
+sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3_stmt *stmt = sdbFind->findstmt;
+ sqlite3 *sqlDB = sdbFind->sqlDB;
+ int sqlerr = SQLITE_OK;
+
+ LOCK_SQLITE()
+ if (stmt) {
+ sqlite3_reset(stmt);
+ sqlerr = sqlite3_finalize(stmt);
+ }
+ if (sqlDB) {
+ sdb_closeDBLocal(sdb_p, sqlDB) ;
+ }
+ PORT_Free(sdbFind);
+
+ UNLOCK_SQLITE()
+ return sdb_mapSQLError(sdb_p->type, sqlerr);
+}
+
+#define GET_ATTRIBUTE_CMD "SELECT ALL %s FROM %s WHERE id=$ID;"
+CK_RV
+sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
+ CK_ATTRIBUTE *template, CK_ULONG count)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *getStr = NULL;
+ char *newStr = NULL;
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+ int found = 0;
+ int retry = 0;
+ int i;
+
+ getStr = sqlite3_mprintf("");
+ for (i=0; getStr && i < count; i++) {
+ if (i==0) {
+ newStr = sqlite3_mprintf("a%x", template[i].type);
+ } else {
+ newStr = sqlite3_mprintf("%s, a%x", getStr, template[i].type);
+ }
+ sqlite3_free(getStr);
+ getStr = newStr;
+ }
+
+ if (getStr == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+
+ newStr = sqlite3_mprintf(GET_ATTRIBUTE_CMD, getStr, sdb_p->table);
+ sqlite3_free(getStr);
+ getStr = NULL;
+ if (newStr == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ /* open a new db if necessary */
+ error = sdb_openDBLocal(sdb_p,&sqlDB);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+ sqlerr = sqlite3_prepare(sqlDB, newStr, -1, &stmt, NULL);
+ if (sqlerr != SQLITE_OK) { goto loser; }
+ sqlerr = sqlite3_bind_int(stmt, 1, object_id);
+ if (sqlerr != SQLITE_OK) { goto loser; }
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(5);
+ }
+ if (sqlerr == SQLITE_ROW) {
+ for (i=0; i < count; i++) {
+ int column = i;
+ int blobSize;
+ const char *blobData;
+
+ blobSize = sqlite3_column_bytes(stmt, column);
+ blobData = sqlite3_column_blob(stmt, column);
+ if (blobData == NULL) {
+ template[i].ulValueLen = -1;
+ error = CKR_ATTRIBUTE_TYPE_INVALID;
+ continue;
+ }
+ /* If the blob equals our explicit NULL value, then the
+ * attribute is a NULL. */
+ if ((blobSize == SQLITE_EXPLICIT_NULL_LEN) &&
+ (PORT_Memcmp(blobData, SQLITE_EXPLICIT_NULL,
+ SQLITE_EXPLICIT_NULL_LEN) == 0)) {
+ blobSize = 0;
+ }
+ if (template[i].pValue) {
+ if (template[i].ulValueLen < blobSize) {
+ template[i].ulValueLen = -1;
+ error = CKR_BUFFER_TOO_SMALL;
+ continue;
+ }
+ PORT_Memcpy(template[i].pValue, blobData, blobSize);
+ }
+ template[i].ulValueLen = blobSize;
+ }
+ found = 1;
+ }
+ } while (!sdb_done(sqlerr,&retry));
+
+loser:
+ /* fix up the error if necessary */
+ if (error == CKR_OK) {
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+ if (!found && error == CKR_OK) {
+ error = CKR_OBJECT_HANDLE_INVALID;
+ }
+ }
+ if (newStr) {
+ sqlite3_free(newStr);
+ }
+
+ if (stmt) {
+ sqlite3_reset(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+ /* if we had to open a new database, free it now */
+ if (sqlDB) {
+ sdb_closeDBLocal(sdb_p, sqlDB) ;
+ }
+ return error;
+}
+
+CK_RV
+sdb_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
+ CK_ATTRIBUTE *template, CK_ULONG count)
+{
+ CK_RV crv;
+
+ if (count == 0) {
+ return CKR_OK;
+ }
+
+ LOCK_SQLITE()
+ crv = sdb_GetAttributeValueNoLock(sdb, object_id, template, count);
+ UNLOCK_SQLITE()
+ return crv;
+}
+
+#define SET_ATTRIBUTE_CMD "UPDATE %s SET %s WHERE id=$ID;"
+CK_RV
+sdb_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
+ const CK_ATTRIBUTE *template, CK_ULONG count)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *setStr = NULL;
+ char *newStr = NULL;
+ int sqlerr = SQLITE_OK;
+ int retry = 0;
+ CK_RV error = CKR_OK;
+ int i;
+
+ if (sdb->sdb_flags == SDB_RDONLY) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ if (count == 0) {
+ return CKR_OK;
+ }
+
+ LOCK_SQLITE()
+ setStr = sqlite3_mprintf("");
+ for (i=0; setStr && i < count; i++) {
+ if (i==0) {
+ sqlite3_free(setStr);
+ setStr = sqlite3_mprintf("a%x=$VALUE%d",
+ template[i].type, i);
+ continue;
+ }
+ newStr = sqlite3_mprintf("%s,a%x=$VALUE%d", setStr,
+ template[i].type, i);
+ sqlite3_free(setStr);
+ setStr = newStr;
+ }
+ newStr = NULL;
+
+ if (setStr == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ newStr = sqlite3_mprintf(SET_ATTRIBUTE_CMD, sdb_p->table, setStr);
+ sqlite3_free(setStr);
+ if (newStr == NULL) {
+ UNLOCK_SQLITE()
+ return CKR_HOST_MEMORY;
+ }
+ error = sdb_openDBLocal(sdb_p, &sqlDB);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+ sqlerr = sqlite3_prepare(sqlDB, newStr, -1, &stmt, NULL);
+ if (sqlerr != SQLITE_OK) goto loser;
+ for (i=0; i < count; i++) {
+ if (template[i].ulValueLen != 0) {
+ sqlerr = sqlite3_bind_blob(stmt, i+1, template[i].pValue,
+ template[i].ulValueLen, SQLITE_STATIC);
+ } else {
+ sqlerr = sqlite3_bind_blob(stmt, i+2, SQLITE_EXPLICIT_NULL,
+ SQLITE_EXPLICIT_NULL_LEN, SQLITE_STATIC);
+ }
+ if (sqlerr != SQLITE_OK) goto loser;
+ }
+ sqlerr = sqlite3_bind_int(stmt, i+1, object_id);
+ if (sqlerr != SQLITE_OK) goto loser;
+
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(5);
+ }
+ } while (!sdb_done(sqlerr,&retry));
+
+loser:
+ if (newStr) {
+ sqlite3_free(newStr);
+ }
+ if (error == CKR_OK) {
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+ }
+
+ if (stmt) {
+ sqlite3_reset(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+ if (sqlDB) {
+ sdb_closeDBLocal(sdb_p, sqlDB) ;
+ }
+
+ UNLOCK_SQLITE()
+ return error;
+}
+
+/*
+ * check to see if a candidate object handle already exists.
+ */
+static PRBool
+sdb_objectExists(SDB *sdb, CK_OBJECT_HANDLE candidate)
+{
+ CK_RV crv;
+ CK_ATTRIBUTE template = { CKA_LABEL, NULL, 0 };
+
+ crv = sdb_GetAttributeValueNoLock(sdb,candidate,&template, 1);
+ if (crv == CKR_OBJECT_HANDLE_INVALID) {
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+/*
+ * if we're here, we are in a transaction, so it's safe
+ * to examine the current state of the database
+ */
+static CK_OBJECT_HANDLE
+sdb_getObjectId(SDB *sdb)
+{
+ CK_OBJECT_HANDLE candidate;
+ static CK_OBJECT_HANDLE next_obj = CK_INVALID_HANDLE;
+ int count;
+ /*
+ * get an initial object handle to use
+ */
+ if (next_obj == CK_INVALID_HANDLE) {
+ PRTime time;
+ time = PR_Now();
+
+ next_obj = (CK_OBJECT_HANDLE)(time & 0x3fffffffL);
+ }
+ candidate = next_obj++;
+ /* detect that we've looped through all the handles... */
+ for (count = 0; count < 0x40000000; count++, candidate = next_obj++) {
+ /* mask off excess bits */
+ candidate &= 0x3fffffff;
+ /* if we hit zero, go to the next entry */
+ if (candidate == CK_INVALID_HANDLE) {
+ continue;
+ }
+ /* make sure we aren't already using */
+ if (!sdb_objectExists(sdb, candidate)) {
+ /* this one is free */
+ return candidate;
+ }
+ }
+
+ /* no handle is free, fail */
+ return CK_INVALID_HANDLE;
+}
+
+#define CREATE_CMD "INSERT INTO %s (id%s) VALUES($ID%s);"
+CK_RV
+sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
+ const CK_ATTRIBUTE *template, CK_ULONG count)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *columnStr = NULL;
+ char *valueStr = NULL;
+ char *newStr = NULL;
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+ CK_OBJECT_HANDLE this_object;
+ int retry = 0;
+ int i;
+
+ if (sdb->sdb_flags == SDB_RDONLY) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ LOCK_SQLITE()
+ if ((*object_id != CK_INVALID_HANDLE) &&
+ !sdb_objectExists(sdb, *object_id)) {
+ this_object = *object_id;
+ } else {
+ this_object = sdb_getObjectId(sdb);
+ }
+ if (this_object == CK_INVALID_HANDLE) {
+ UNLOCK_SQLITE();
+ return CKR_HOST_MEMORY;
+ }
+ columnStr = sqlite3_mprintf("");
+ valueStr = sqlite3_mprintf("");
+ *object_id = this_object;
+ for (i=0; columnStr && valueStr && i < count; i++) {
+ newStr = sqlite3_mprintf("%s,a%x", columnStr, template[i].type);
+ sqlite3_free(columnStr);
+ columnStr = newStr;
+ newStr = sqlite3_mprintf("%s,$VALUE%d", valueStr, i);
+ sqlite3_free(valueStr);
+ valueStr = newStr;
+ }
+ newStr = NULL;
+ if ((columnStr == NULL) || (valueStr == NULL)) {
+ if (columnStr) {
+ sqlite3_free(columnStr);
+ }
+ if (valueStr) {
+ sqlite3_free(valueStr);
+ }
+ UNLOCK_SQLITE()
+ return CKR_HOST_MEMORY;
+ }
+ newStr = sqlite3_mprintf(CREATE_CMD, sdb_p->table, columnStr, valueStr);
+ sqlite3_free(columnStr);
+ sqlite3_free(valueStr);
+ error = sdb_openDBLocal(sdb_p, &sqlDB);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+ sqlerr = sqlite3_prepare(sqlDB, newStr, -1, &stmt, NULL);
+ if (sqlerr != SQLITE_OK) goto loser;
+ sqlerr = sqlite3_bind_int(stmt, 1, *object_id);
+ if (sqlerr != SQLITE_OK) goto loser;
+ for (i=0; i < count; i++) {
+ if (template[i].ulValueLen) {
+ sqlerr = sqlite3_bind_blob(stmt, i+2, template[i].pValue,
+ template[i].ulValueLen, SQLITE_STATIC);
+ } else {
+ sqlerr = sqlite3_bind_blob(stmt, i+2, SQLITE_EXPLICIT_NULL,
+ SQLITE_EXPLICIT_NULL_LEN, SQLITE_STATIC);
+ }
+ if (sqlerr != SQLITE_OK) goto loser;
+ }
+
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(5);
+ }
+ } while (!sdb_done(sqlerr,&retry));
+
+loser:
+ if (newStr) {
+ sqlite3_free(newStr);
+ }
+ if (error == CKR_OK) {
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+ }
+
+ if (stmt) {
+ sqlite3_reset(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+ if (sqlDB) {
+ sdb_closeDBLocal(sdb_p, sqlDB) ;
+ }
+ UNLOCK_SQLITE()
+
+ return error;
+}
+
+#define DESTROY_CMD "DELETE FROM %s WHERE (id=$ID);"
+CK_RV
+sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *newStr = NULL;
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+ int retry = 0;
+
+ if (sdb->sdb_flags == SDB_RDONLY) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ LOCK_SQLITE()
+ error = sdb_openDBLocal(sdb_p, &sqlDB);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+ newStr = sqlite3_mprintf(DESTROY_CMD, sdb_p->table);
+ if (newStr == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ sqlerr =sqlite3_prepare(sqlDB, newStr, -1, &stmt, NULL);
+ sqlite3_free(newStr);
+ if (sqlerr != SQLITE_OK) goto loser;
+ sqlerr =sqlite3_bind_int(stmt, 1, object_id);
+ if (sqlerr != SQLITE_OK) goto loser;
+
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(5);
+ }
+ } while (!sdb_done(sqlerr,&retry));
+
+loser:
+ if (error == CKR_OK) {
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+ }
+
+ if (stmt) {
+ sqlite3_reset(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+ if (sqlDB) {
+ sdb_closeDBLocal(sdb_p, sqlDB) ;
+ }
+
+ UNLOCK_SQLITE()
+ return error;
+}
+
+#define BEGIN_CMD "BEGIN IMMEDIATE TRANSACTION;"
+/*
+ * start a transaction.
+ *
+ * We need to open a new database, then store that new database into
+ * the private data structure. We open the database first, then use locks
+ * to protect storing the data to prevent deadlocks.
+ */
+CK_RV
+sdb_Begin(SDB *sdb)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = NULL;
+ sqlite3_stmt *stmt = NULL;
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+ int retry = 0;
+
+
+ if (sdb->sdb_flags == SDB_RDONLY) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+
+ LOCK_SQLITE()
+#ifdef SQLITE_THREAD_SHARE_DB
+ sqlDB = sdb_p->sqlXactDB;
+#else
+ /* get a new version that we will use for the entire transaction */
+ sqlerr = sqlite3_open(sdb_p->sqlDBName, &sqlDB);
+ if (sqlerr != SQLITE_OK) {
+ goto loser;
+ }
+#endif
+
+ sqlerr = sqlite3_busy_timeout(sqlDB, 1000);
+ if (sqlerr != CKR_OK) {
+ goto loser;
+ }
+
+ sqlerr =sqlite3_prepare(sqlDB, BEGIN_CMD, -1, &stmt, NULL);
+
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(5);
+ }
+ } while (!sdb_done(sqlerr,&retry));
+
+ if (stmt) {
+ sqlite3_reset(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+loser:
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+
+#ifndef SQLITE_THREAD_SHARE_DB
+ /* we are starting a new transaction,
+ * and if we succeeded, then save this database for the rest of
+ * our transaction */
+ if (error == CKR_OK) {
+ /* we hold a 'BEGIN TRANSACTION' and a sdb_p->lock. At this point
+ * sdb_p->sqlXactDB MUST be null */
+ PR_Lock(sdb_p->lock);
+ PORT_Assert(sdb_p->sqlXactDB == NULL);
+ sdb_p->sqlXactDB = sqlDB;
+ sdb_p->sqlXactThread = PR_GetCurrentThread();
+ PR_Unlock(sdb_p->lock);
+ } else {
+ /* we failed to start our transaction,
+ * free any databases we openned. */
+ if (sqlDB) {
+ sqlite3_close(sqlDB);
+ }
+ }
+#endif
+
+ UNLOCK_SQLITE()
+ return error;
+}
+
+/*
+ * Complete a transaction. Basically undo everything we did in begin.
+ * There are 2 flavors Abort and Commit. Basically the only differerence between
+ * these 2 are what the database will show. (no change in to former, change in
+ * the latter).
+ */
+static CK_RV
+sdb_complete(SDB *sdb, const char *cmd)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = NULL;
+ sqlite3_stmt *stmt = NULL;
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+ int retry = 0;
+
+
+ if (sdb->sdb_flags == SDB_RDONLY) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+
+#ifndef SQLITE_THREAD_SHARE_DB
+ /* We must have a transation database, or we shouldn't have arrived here */
+ PR_Lock(sdb_p->lock);
+ PORT_Assert(sdb_p->sqlXactDB);
+ if (sdb_p->sqlXactDB == NULL) {
+ PR_Unlock(sdb_p->lock);
+ return CKR_GENERAL_ERROR; /* shouldn't happen */
+ }
+ PORT_Assert( sdb_p->sqlXactThread == PR_GetCurrentThread());
+ if ( sdb_p->sqlXactThread != PR_GetCurrentThread()) {
+ PR_Unlock(sdb_p->lock);
+ return CKR_GENERAL_ERROR; /* shouldn't happen */
+ }
+ sqlDB = sdb_p->sqlXactDB;
+ sdb_p->sqlXactDB = NULL; /* no one else can get to this DB,
+ * safe to unlock */
+ sdb_p->sqlXactThread = NULL;
+ PR_Unlock(sdb_p->lock);
+#else
+ sqlDB = sdb_p->sqlXactDB;
+#endif
+
+ sqlerr =sqlite3_prepare(sqlDB, cmd, -1, &stmt, NULL);
+
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(5);
+ }
+ } while (!sdb_done(sqlerr,&retry));
+
+ /* Pending BEGIN TRANSACTIONS Can move forward at this point. */
+
+ if (stmt) {
+ sqlite3_reset(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+
+#ifndef SQLITE_THREAD_SHARE_DB
+ /* We just finished a transaction.
+ * Free the database, and remove it from the list */
+ sqlite3_close(sqlDB);
+#endif
+
+ return error;
+}
+
+#define COMMIT_CMD "COMMIT TRANSACTION;"
+CK_RV
+sdb_Commit(SDB *sdb)
+{
+ CK_RV crv;
+ LOCK_SQLITE()
+ crv = sdb_complete(sdb,COMMIT_CMD);
+ UNLOCK_SQLITE()
+ return crv;
+}
+
+#define ROLLBACK_CMD "ROLLBACK TRANSACTION;"
+CK_RV
+sdb_Abort(SDB *sdb)
+{
+ CK_RV crv;
+ LOCK_SQLITE()
+ crv = sdb_complete(sdb,ROLLBACK_CMD);
+ UNLOCK_SQLITE()
+ return crv;
+}
+
+#define GET_PW_CMD "SELECT ALL * FROM password WHERE id='password';"
+CK_RV
+sdb_GetPWEntry(SDB *sdb, SDBPasswordEntry *entry)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = sdb_p->sqlXactDB;
+ sqlite3_stmt *stmt = NULL;
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+ int found = 0;
+ int retry = 0;
+
+ /* only Key databases have password entries */
+ if (sdb_p->type != SDB_KEY) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ LOCK_SQLITE()
+ error = sdb_openDBLocal(sdb_p, &sqlDB);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+
+ sqlerr = sqlite3_prepare(sqlDB, GET_PW_CMD, -1, &stmt, NULL);
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(5);
+ }
+ if (sqlerr == SQLITE_ROW) {
+ const char *blobData;
+ entry->salt.data = entry->data;
+ entry->salt.len = sqlite3_column_bytes(stmt, 1);
+ if (entry->salt.len > sizeof(entry->data)) {
+ error = CKR_BUFFER_TOO_SMALL;
+ continue;
+ }
+ blobData = sqlite3_column_blob(stmt, 1);
+ PORT_Memcpy(entry->salt.data,blobData, entry->salt.len);
+ entry->value.data = &entry->data[entry->salt.len];
+ entry->value.len = sqlite3_column_bytes(stmt, 2);
+ if ((entry->value.len+entry->salt.len) > sizeof(entry->data)) {
+ error = CKR_BUFFER_TOO_SMALL;
+ continue;
+ }
+ blobData = sqlite3_column_blob(stmt, 2);
+ PORT_Memcpy(entry->value.data,blobData, entry->value.len);
+ found = 1;
+ }
+ } while (!sdb_done(sqlerr,&retry));
+
+loser:
+ /* fix up the error if necessary */
+ if (error == CKR_OK) {
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+ if (!found && error == CKR_OK) {
+ error = CKR_OBJECT_HANDLE_INVALID;
+ }
+ }
+
+ if (stmt) {
+ sqlite3_reset(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+ if (sqlDB) {
+ sdb_closeDBLocal(sdb_p, sqlDB) ;
+ }
+ UNLOCK_SQLITE()
+
+ return error;
+}
+
+static int tableExists(sqlite3 *sqlDB, const char *tableName);
+#define PW_CREATE_TABLE_CMD \
+ "CREATE TABLE password (id PRIMARY KEY UNIQUE ON CONFLICT REPLACE, salt, value);"
+#define PW_CREATE_CMD \
+ "INSERT INTO password (id,salt,value) VALUES('password',$SALT,$VALUE);"
+CK_RV
+sdb_PutPWEntry(SDB *sdb, SDBPasswordEntry *entry)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = sdb_p->sqlXactDB;
+ sqlite3_stmt *stmt = NULL;
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+ int retry = 0;
+
+ /* only Key databases have password entries */
+ if (sdb_p->type != SDB_KEY) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ LOCK_SQLITE()
+ error = sdb_openDBLocal(sdb_p, &sqlDB);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+
+ if (!tableExists(sqlDB, "password")) {
+ sqlerr = sqlite3_exec(sqlDB, PW_CREATE_TABLE_CMD, NULL, 0, NULL);
+ if (sqlerr != SQLITE_OK) goto loser;
+ }
+ sqlerr = sqlite3_prepare(sqlDB, PW_CREATE_CMD, -1, &stmt, NULL);
+ if (sqlerr != SQLITE_OK) goto loser;
+ sqlerr = sqlite3_bind_blob(stmt, 1, entry->salt.data,
+ entry->salt.len, SQLITE_STATIC);
+ if (sqlerr != SQLITE_OK) goto loser;
+ sqlerr = sqlite3_bind_blob(stmt, 2, entry->value.data,
+ entry->value.len, SQLITE_STATIC);
+ if (sqlerr != SQLITE_OK) goto loser;
+
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(5);
+ }
+ } while (!sdb_done(sqlerr,&retry));
+
+loser:
+ /* fix up the error if necessary */
+ if (error == CKR_OK) {
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+ }
+
+ if (stmt) {
+ sqlite3_reset(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+ if (sqlDB) {
+ sdb_closeDBLocal(sdb_p, sqlDB) ;
+ }
+ UNLOCK_SQLITE()
+
+ return error;
+}
+
+#define RESET_CMD "DROP TABLE IF EXISTS %s;"
+CK_RV
+sdb_Reset(SDB *sdb)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ sqlite3 *sqlDB = NULL;
+ char *newStr;
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+
+ /* only Key databases can be reset */
+ if (sdb_p->type != SDB_KEY) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ LOCK_SQLITE()
+ error = sdb_openDBLocal(sdb_p, &sqlDB);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+
+ /* delete the key table */
+ newStr = sqlite3_mprintf(RESET_CMD, sdb_p->table);
+ if (newStr == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
+ sqlite3_free(newStr);
+
+ if (sqlerr != SQLITE_OK) goto loser;
+
+ /* delete the password entry table */
+ sqlerr = sqlite3_exec(sqlDB, "DROP TABLE IF EXISTS password;",
+ NULL, 0, NULL);
+
+loser:
+ /* fix up the error if necessary */
+ if (error == CKR_OK) {
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+ }
+
+ if (sqlDB) {
+ sdb_closeDBLocal(sdb_p, sqlDB) ;
+ }
+
+ UNLOCK_SQLITE()
+ return error;
+}
+
+
+CK_RV
+sdb_Close(SDB *sdb)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ int sqlerr = SQLITE_OK;
+ sdbDataType type = sdb_p->type;
+
+ /* sqlerr = sqlite3_close(sqlDB); */
+ PORT_Free(sdb_p->sqlDBName);
+ free(sdb_p);
+ free(sdb);
+ return sdb_mapSQLError(type, sqlerr);
+}
+
+
+/*
+ * functions to support open
+ */
+
+#define CHECK_TABLE_CMD "SELECT ALL * FROM %s LIMIT 0;"
+/* return 1 if sqlDB contains table 'tableName */
+static int tableExists(sqlite3 *sqlDB, const char *tableName)
+{
+ char * cmd = sqlite3_mprintf(CHECK_TABLE_CMD, tableName);
+ int sqlerr = SQLITE_OK;
+
+ if (cmd == NULL) {
+ return 0;
+ }
+
+ sqlerr = sqlite3_exec(sqlDB, cmd, NULL, 0, 0);
+ sqlite3_free(cmd);
+
+ return (sqlerr == SQLITE_OK) ? 1 : 0;
+}
+
+/*
+ * initialize a single database
+ */
+#define INIT_CMD \
+ "CREATE TABLE %s (id PRIMARY KEY UNIQUE ON CONFLICT ABORT%s)"
+#define ALTER_CMD \
+ "ALTER TABLE %s ADD COLUMN a%x"
+
+
+CK_RV
+sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
+ int *newInit, int flags, SDB **pSdb)
+{
+ int i;
+ char *initStr = NULL;
+ char *newStr;
+ int inTransaction = 0;
+ SDB *sdb = NULL;
+ SDBPrivate *sdb_p = NULL;
+ sqlite3 *sqlDB = NULL;
+ int sqlerr = SQLITE_OK;
+ CK_RV error = CKR_OK;
+
+ *pSdb = NULL;
+ *inUpdate = 0;
+
+ /* sqlite3 doesn't have a flag to specify that we want to
+ * open the database read only. If the db doesn't exist,
+ * sqlite3 will always create it.
+ */
+ LOCK_SQLITE();
+ if ((flags == SDB_RDONLY) && PR_Access(dbname, PR_ACCESS_EXISTS)) {
+ error = sdb_mapSQLError(type, SQLITE_CANTOPEN);
+ goto loser;
+ }
+ sqlerr = sqlite3_open(dbname, &sqlDB);
+ if (sqlerr != SQLITE_OK) {
+ error = sdb_mapSQLError(type, sqlerr);
+ goto loser;
+ }
+
+ sqlerr = sqlite3_busy_timeout(sqlDB, 1000);
+ if (sqlerr != CKR_OK) {
+ error = sdb_mapSQLError(type, sqlerr);
+ goto loser;
+ }
+
+ if (flags != SDB_RDONLY) {
+ sqlerr = sqlite3_exec(sqlDB, BEGIN_CMD, NULL, 0, NULL);
+ if (sqlerr != SQLITE_OK) {
+ error = sdb_mapSQLError(type, sqlerr);
+ goto loser;
+ }
+ inTransaction = 1;
+ }
+ if (!tableExists(sqlDB,table)) {
+ *newInit = 1;
+ if (flags != SDB_CREATE) {
+ error = sdb_mapSQLError(type, SQLITE_CANTOPEN);
+ goto loser;
+ }
+ initStr = sqlite3_mprintf("");
+ for (i=0; initStr && i < known_attributes_size; i++) {
+ newStr = sqlite3_mprintf("%s, a%x",initStr, known_attributes[i]);
+ sqlite3_free(initStr);
+ initStr = newStr;
+ }
+ if (initStr == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ newStr = sqlite3_mprintf(INIT_CMD, table, initStr);
+ sqlite3_free(initStr);
+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
+ sqlite3_free(newStr);
+ if (sqlerr != SQLITE_OK) {
+ error = sdb_mapSQLError(type, sqlerr);
+ goto loser;
+ }
+ } else {
+ /* if the nssInit table exists, then someone else is initing the
+ * nss database. We don't want to complete the open until the init
+ * is completed. */
+ if (tableExists(sqlDB,"nssInUpdate")) {
+ *inUpdate = 1;
+ }
+ }
+ sdb = (SDB *) malloc(sizeof(SDB));
+ sdb_p = (SDBPrivate *) malloc(sizeof(SDBPrivate));
+ /* invariant fields */
+ sdb_p->sqlDBName = PORT_Strdup(dbname);
+ sdb_p->type = type;
+ sdb_p->table = table;
+ sdb_p->lock = PR_NewLock();
+ /* these fields are protected by the lock */
+ sdb_p->sqlXactDB = NULL;
+ sdb_p->sqlXactThread = NULL;
+ sdb->private = sdb_p;
+ sdb->sdb_type = SDB_SQL;
+ sdb->sdb_flags = flags;
+ sdb->sdb_FindObjectsInit = sdb_FindObjectsInit;
+ sdb->sdb_FindObjects = sdb_FindObjects;
+ sdb->sdb_FindObjectsFinal = sdb_FindObjectsFinal;
+ sdb->sdb_GetAttributeValue = sdb_GetAttributeValue;
+ sdb->sdb_SetAttributeValue = sdb_SetAttributeValue;
+ sdb->sdb_CreateObject = sdb_CreateObject;
+ sdb->sdb_DestroyObject = sdb_DestroyObject;
+ sdb->sdb_GetPWEntry = sdb_GetPWEntry;
+ sdb->sdb_PutPWEntry = sdb_PutPWEntry;
+ sdb->sdb_Begin = sdb_Begin;
+ sdb->sdb_Commit = sdb_Commit;
+ sdb->sdb_Abort = sdb_Abort;
+ sdb->sdb_Close = sdb_Close;
+
+ if (inTransaction) {
+ sqlerr = sqlite3_exec(sqlDB, COMMIT_CMD, NULL, 0, NULL);
+ if (sqlerr != SQLITE_OK) {
+ error = sdb_mapSQLError(sdb_p->type, sqlerr);
+ goto loser;
+ }
+ inTransaction = 0;
+ }
+ if (*inUpdate) {
+ while (tableExists(sqlDB,"nssInit")) {
+ PR_Sleep(5);
+ }
+ }
+#ifdef SQLITE_THREAD_SHARE_DB
+ sdb_p->sqlXactDB = sqlDB;
+#else
+ /* sqlite3 cannot share sqlDB references across threads, open the
+ * db only when we need to read or update it (sigh) */
+ sqlite3_close(sqlDB);
+#endif
+
+ *pSdb = sdb;
+ UNLOCK_SQLITE();
+ return CKR_OK;
+
+loser:
+ /* lots of stuff to do */
+ if (inTransaction) {
+ sqlite3_exec(sqlDB, ROLLBACK_CMD, NULL, 0, NULL);
+ }
+ if (sdb) {
+ free(sdb);
+ }
+ if (sdb_p) {
+ free(sdb_p);
+ }
+ if (sqlDB) {
+ sqlite3_close(sqlDB);
+ }
+ UNLOCK_SQLITE();
+ return error;
+
+}
+
+static char *sdb_BuildFileName(const char * directory,
+ const char *prefix, const char *type,
+ int version, int flags)
+{
+ char *dbname = NULL;
+ /* build the full dbname */
+ dbname = sqlite3_mprintf("%s/%s%s%d.db",directory, prefix, type, version);
+ return dbname;
+}
+
+/* sdbopen */
+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)
+{
+ char *cert = sdb_BuildFileName(directory, certPrefix,
+ "cert", cert_version, flags);
+ char *key = sdb_BuildFileName(directory, keyPrefix,
+ "key", key_version, flags);
+ CK_RV error = CKR_OK;
+ int inUpdate;
+
+ *certdb = NULL;
+ *keydb = NULL;
+ *newInit = 0;
+
+#ifdef SQLITE_UNSAFE_THREADS
+ if (sqlite_lock == NULL) {
+ sqlite_lock = PR_NewLock();
+ if (sqlite_lock == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ }
+#endif
+
+ /*
+ * open the cert data base
+ */
+ if (certdb) {
+ /* initialize Certificate database */
+ error = sdb_init(cert, "nssPublic", SDB_CERT, &inUpdate,
+ newInit, flags, certdb);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+ }
+
+ /*
+ * open the key data base:
+ * NOTE:is we want to implement a single database, we open
+ * the same database file as the certificate here.
+ *
+ * cert an key db's have different tables, so they will not
+ * conflict.
+ */
+ if (keydb) {
+ /* initialize the Key database */
+ error = sdb_init(key, "nssPrivate", SDB_KEY, &inUpdate,
+ newInit, flags, keydb);
+ if (error != CKR_OK) {
+ goto loser;
+ }
+ }
+
+
+loser:
+ if (cert) {
+ sqlite3_free(cert);
+ }
+ if (key) {
+ sqlite3_free(key);
+ }
+
+ if (error != CKR_OK) {
+ /* currently redundant, but could be necessary if more code is added
+ * just before loser */
+ if (keydb && *keydb) {
+ sdb_Close(*keydb);
+ }
+ if (certdb && *certdb) {
+ sdb_Close(*certdb);
+ }
+ }
+
+ return error;
+}
+
+CK_RV
+s_shutdown()
+{
+#ifdef SQLITE_UNSAFE_THREADS
+ if (sqlite_lock) {
+ PR_DestroyLock(sqlite_lock);
+ sqlite_lock = NULL;
+ }
+#endif
+ return CKR_OK;
+}
diff --git a/security/nss/lib/softoken/sdb.h b/security/nss/lib/softoken/sdb.h
new file mode 100644
index 000000000..818bc4bf1
--- /dev/null
+++ b/security/nss/lib/softoken/sdb.h
@@ -0,0 +1,115 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Red Hat, Inc.
+ *
+ * The Initial Developer of the Original Code is
+ * Red Hat, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert Relyea (rrelyea@redhat.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * This file implements PKCS 11 on top of our existing security modules
+ *
+ * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
+ * This implementation has two slots:
+ * slot 1 is our generic crypto support. It does not require login.
+ * It supports Public Key ops, and all they bulk ciphers and hashes.
+ * It can also support Private Key ops for imported Private keys. It does
+ * not have any token storage.
+ * slot 2 is our private key support. It requires a login before use. It
+ * can store Private Keys and Certs as token objects. Currently only private
+ * keys and their associated Certificates are saved on the token.
+ *
+ * In this implementation, session objects are only visible to the session
+ * that created or generated them.
+ */
+
+/*
+ * the following data structures should be moved to a 'rdb.h'.
+ */
+
+#ifndef _SDB_H
+#define _SDB_H 1
+#include "pkcs11t.h"
+#include "secitem.h"
+#include "sftkdbt.h"
+#include <sqlite3.h>
+
+#define STATIC_CMD_SIZE 2048
+
+typedef struct SDBFindStr SDBFind;
+typedef struct SDBStr SDB;
+typedef struct SDBPasswordEntryStr SDBPasswordEntry;
+
+struct SDBStr {
+ void *private;
+ int version;
+ SDBType sdb_type;
+ int sdb_flags;
+ void *app_private;
+ CK_RV (*sdb_FindObjectsInit)(SDB *sdb, const CK_ATTRIBUTE *template,
+ CK_ULONG count, SDBFind **find);
+ CK_RV (*sdb_FindObjects)(SDB *sdb, SDBFind *find, CK_OBJECT_HANDLE *ids,
+ CK_ULONG arraySize, CK_ULONG *count);
+ CK_RV (*sdb_FindObjectsFinal)(SDB *sdb, SDBFind *find);
+ CK_RV (*sdb_GetAttributeValue)(SDB *sdb, CK_OBJECT_HANDLE object,
+ CK_ATTRIBUTE *template, CK_ULONG count);
+ CK_RV (*sdb_SetAttributeValue)(SDB *sdb, CK_OBJECT_HANDLE object,
+ const CK_ATTRIBUTE *template, CK_ULONG count);
+ CK_RV (*sdb_CreateObject)(SDB *sdb, CK_OBJECT_HANDLE *object,
+ const CK_ATTRIBUTE *template, CK_ULONG 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);
+};
+
+struct SDBPasswordEntryStr {
+ SECItem salt;
+ SECItem value;
+ unsigned char data[128];
+};
+
+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);
+CK_RV s_shutdown();
+
+/* flags */
+#define SDB_RDONLY 1
+#define SDB_RDWR 2
+#define SDB_CREATE 4
+
+#endif
diff --git a/security/nss/lib/softoken/sftkdb.c b/security/nss/lib/softoken/sftkdb.c
new file mode 100644
index 000000000..6f126f9f5
--- /dev/null
+++ b/security/nss/lib/softoken/sftkdb.c
@@ -0,0 +1,2738 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * The following code handles the storage of PKCS 11 modules used by the
+ * NSS. For the rest of NSS, only one kind of database handle exists:
+ *
+ * SFTKDBHandle
+ *
+ * There is one SFTKDBHandle for the each key database and one for each cert
+ * database. These databases are opened as associated pairs, one pair per
+ * slot. SFTKDBHandles are reference counted objects.
+ *
+ * Each SFTKDBHandle points to a low level database handle (SDB). This handle
+ * represents the underlying physical database. These objects are not
+ * reference counted, an are 'owned' by their respective SFTKDBHandles.
+ *
+ *
+ */
+#include "sftkdb.h"
+#include "pkcs11t.h"
+#include "pkcs11i.h"
+#include "sdb.h"
+#include "prprf.h"
+#include "secmodt.h"
+#include "sftkpars.h"
+#include "pratom.h"
+#include "blapi.h"
+#include "secoid.h"
+#include "sechash.h"
+#include "lowpbe.h"
+#include "secdert.h"
+#include "prsystem.h"
+#include "lgglue.h"
+
+/*
+ * private defines
+ */
+struct SFTKDBHandleStr {
+ SDB *db;
+ PRInt32 ref;
+ CK_OBJECT_HANDLE type;
+ SECItem passwordKey;
+ SECItem *newKey;
+ PZLock *passwordLock;
+ SFTKDBHandle *peerDB;
+ SDB *update;
+};
+
+#define SFTK_KEYDB_TYPE 0x40000000
+#define SFTK_CERTDB_TYPE 0x00000000
+#define SFTK_OBJ_TYPE_MASK 0xc0000000
+#define SFTK_OBJ_ID_MASK (~SFTK_OBJ_TYPE_MASK)
+#define SFTK_TOKEN_TYPE 0x80000000
+
+static SECStatus sftkdb_decrypt(SECItem *passKey, SECItem *cipherText,
+ SECItem **plainText);
+static SECStatus sftkdb_encrypt(PLArenaPool *arena, SECItem *passKey,
+ SECItem *plainText, SECItem **cipherText);
+
+
+/*
+ * We want all databases to have the same binary representation independent of
+ * endianness or length of the host architecture. In general PKCS #11 attributes
+ * are endian/length independent except those attributes that pass CK_ULONG.
+ *
+ * The following functions fixes up the CK_ULONG type attributes so that the data
+ * base sees a machine independent view. CK_ULONGs are stored as 4 byte network
+ * byte order values (big endian).
+ */
+#define DB_ULONG_SIZE 4
+#define BBP 8
+
+static PRBool
+sftkdb_isULONG(CK_ATTRIBUTE_TYPE type)
+{
+ switch(type) {
+ case CKA_CLASS:
+ case CKA_CERTIFICATE_TYPE:
+ case CKA_CERTIFICATE_CATEGORY:
+ case CKA_KEY_TYPE:
+ case CKA_JAVA_MIDP_SECURITY_DOMAIN:
+
+ case CKA_TRUST_DIGITAL_SIGNATURE:
+ case CKA_TRUST_NON_REPUDIATION:
+ case CKA_TRUST_KEY_ENCIPHERMENT:
+ case CKA_TRUST_DATA_ENCIPHERMENT:
+ case CKA_TRUST_KEY_AGREEMENT:
+ case CKA_TRUST_KEY_CERT_SIGN:
+ case CKA_TRUST_CRL_SIGN:
+
+ case CKA_TRUST_SERVER_AUTH:
+ case CKA_TRUST_CLIENT_AUTH:
+ case CKA_TRUST_CODE_SIGNING:
+ case CKA_TRUST_EMAIL_PROTECTION:
+ case CKA_TRUST_IPSEC_END_SYSTEM:
+ case CKA_TRUST_IPSEC_TUNNEL:
+ case CKA_TRUST_IPSEC_USER:
+ case CKA_TRUST_TIME_STAMPING:
+ case CKA_TRUST_STEP_UP_APPROVED:
+ return PR_TRUE;
+ default:
+ break;
+ }
+ return PR_FALSE;
+
+}
+
+/* are the attributes private? */
+static PRBool
+sftkdb_isPrivate(CK_ATTRIBUTE_TYPE type)
+{
+ switch(type) {
+ case CKA_VALUE:
+ case CKA_PRIVATE_EXPONENT:
+ case CKA_PRIME_1:
+ case CKA_PRIME_2:
+ case CKA_EXPONENT_1:
+ case CKA_EXPONENT_2:
+ case CKA_COEFFICIENT:
+ return PR_TRUE;
+ default:
+ break;
+ }
+ return PR_FALSE;
+}
+
+/*
+ * fix up the input templates. Our fixed up ints are stored in data and must
+ * be freed by the caller. The new template must also be freed. If there are no
+ * CK_ULONG attributes, the orignal template is passed in as is.
+ */
+static CK_ATTRIBUTE *
+sftkdb_fixupTemplateIn(const CK_ATTRIBUTE *template, int count,
+ unsigned char **dataOut)
+{
+ int i,j;
+ int ulongCount = 0;
+ unsigned char *data;
+ CK_ATTRIBUTE *ntemplate;
+
+ *dataOut = NULL;
+
+ /* first count the number of CK_ULONG attributes */
+ for (i=0; i < count; i++) {
+ /* Don't 'fixup' NULL values */
+ if (!template[i].pValue) {
+ continue;
+ }
+ if (template[i].ulValueLen == sizeof (CK_ULONG)) {
+ if ( sftkdb_isULONG(template[i].type)) {
+ ulongCount++;
+ }
+ }
+ }
+ /* no attributes to fixup, just call on through */
+ if (ulongCount == 0) {
+ return (CK_ATTRIBUTE *)template;
+ }
+
+ /* allocate space for new ULONGS */
+ data = (unsigned char *)PORT_Alloc(DB_ULONG_SIZE*ulongCount);
+ if (!data) {
+ return NULL;
+ }
+
+ /* allocate new template */
+ ntemplate = PORT_NewArray(CK_ATTRIBUTE,count);
+ if (!ntemplate) {
+ PORT_Free(data);
+ return NULL;
+ }
+ *dataOut = data;
+ /* copy the old template, fixup the actual ulongs */
+ for (i=0; i < count; i++) {
+ ntemplate[i] = template[i];
+ /* Don't 'fixup' NULL values */
+ if (!template[i].pValue) {
+ continue;
+ }
+ if (template[i].ulValueLen == sizeof (CK_ULONG)) {
+ if ( sftkdb_isULONG(template[i].type) ) {
+ CK_ULONG value = *(CK_ULONG *) template[i].pValue;
+ for (j=0; j < DB_ULONG_SIZE; j++) {
+ data[j] = (value >> (DB_ULONG_SIZE-1-j)*BBP) & 0xff;
+ }
+ ntemplate[i].pValue = data;
+ ntemplate[i].ulValueLen = DB_ULONG_SIZE;
+ data += DB_ULONG_SIZE;
+ }
+ }
+ }
+ return ntemplate;
+}
+
+
+
+/*
+ * fix up returned data. NOTE: sftkdb_fixupTemplateIn has already allocated
+ * separate data sections for the database ULONG values.
+ */
+static CK_RV
+sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_ATTRIBUTE *ntemplate,
+ int count, SFTKDBHandle *handle)
+{
+ int i,j;
+ CK_RV crv = CKR_OK;
+
+ for (i=0; i < count; i++) {
+ CK_ULONG length = template[i].ulValueLen;
+ template[i].ulValueLen = ntemplate[i].ulValueLen;
+ /* fixup ulongs */
+ if (ntemplate[i].ulValueLen == DB_ULONG_SIZE) {
+ if (sftkdb_isULONG(template[i].type)) {
+ if (template[i].pValue) {
+ CK_ULONG value = 0;
+ unsigned char *data;
+
+ data = (unsigned char *)ntemplate[i].pValue;
+ for (j=0; j < DB_ULONG_SIZE; j++) {
+ value |= (((CK_ULONG)data[j]) << (DB_ULONG_SIZE-1-j)*BBP);
+ }
+ if (length < sizeof(CK_ULONG)) {
+ template[i].ulValueLen = -1;
+ crv = CKR_BUFFER_TOO_SMALL;
+ continue;
+ }
+ PORT_Memcpy(template[i].pValue,&value,sizeof(CK_ULONG));
+ }
+ template[i].ulValueLen = sizeof(CK_ULONG);
+ }
+ }
+ /* fixup private attributes */
+ if ((handle != NULL) && (handle->type == SFTK_KEYDB_TYPE) &&
+ (template[i].pValue != NULL) && (template[i].ulValueLen != -1)
+ && sftkdb_isPrivate(ntemplate[i].type)) {
+ /* we have a private attribute */
+ /* This code depends on the fact that the cipherText is bigger
+ * than the plain text */
+ SECItem cipherText;
+ SECItem *plainText;
+ SECStatus rv;
+
+ cipherText.data = ntemplate[i].pValue;
+ cipherText.len = ntemplate[i].ulValueLen;
+ PZ_Lock(handle->passwordLock);
+ if (handle->passwordKey.data == NULL) {
+ PZ_Unlock(handle->passwordLock);
+ template[i].ulValueLen = -1;
+ crv = CKR_USER_NOT_LOGGED_IN;
+ continue;
+ }
+ rv = sftkdb_decrypt(&handle->passwordKey, &cipherText, &plainText);
+ PZ_Unlock(handle->passwordLock);
+ if (rv != SECSuccess) {
+ PORT_Memset(template[i].pValue, 0, template[i].ulValueLen);
+ template[i].ulValueLen = -1;
+ crv = CKR_GENERAL_ERROR;
+ continue;
+ }
+ PORT_Assert(template[i].ulValueLen >= plainText->len);
+ if (template[i].ulValueLen < plainText->len) {
+ SECITEM_FreeItem(plainText,PR_TRUE);
+ PORT_Memset(template[i].pValue, 0, template[i].ulValueLen);
+ template[i].ulValueLen = -1;
+ crv = CKR_GENERAL_ERROR;
+ continue;
+ }
+
+ /* copy the plain text back into the template */
+ PORT_Memcpy(template[i].pValue, plainText->data, plainText->len);
+ template[i].ulValueLen = plainText->len;
+ SECITEM_FreeItem(plainText,PR_TRUE);
+ }
+ }
+ return crv;
+}
+
+static CK_RV
+sftkdb_CreateObject(SFTKDBHandle *handle, SDB *db, CK_OBJECT_HANDLE *objectID,
+ CK_ATTRIBUTE *template, CK_ULONG count)
+{
+ PRBool inTransaction = PR_FALSE;
+ CK_RV crv;
+
+ crv = (*db->sdb_Begin)(db);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ inTransaction = PR_TRUE;
+ crv = (*db->sdb_CreateObject)(db, objectID, template, count);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ crv = (*db->sdb_Commit)(db);
+ inTransaction = PR_FALSE;
+
+loser:
+ if (inTransaction) {
+ (*handle->db->sdb_Abort)(handle->db);
+ /* It is trivial to show the following code cannot
+ * happen unless something is horribly wrong with our compilier or
+ * hardware */
+ PORT_Assert(crv != CKR_OK);
+ if (crv == CKR_OK) crv = CKR_GENERAL_ERROR;
+ }
+ return crv;
+}
+
+CK_ATTRIBUTE *
+sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object,
+ SFTKDBHandle *handle,CK_ULONG *pcount,
+ CK_RV *crv)
+{
+ int count;
+ CK_ATTRIBUTE *template;
+ int i, templateIndex;
+ SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
+
+ *crv = CKR_OK;
+
+ if (sessObject == NULL) {
+ *crv = CKR_GENERAL_ERROR; /* internal programming error */
+ return NULL;
+ }
+
+ PZ_Lock(sessObject->attributeLock);
+ count = 0;
+ for (i=0; i < sessObject->hashSize; i++) {
+ SFTKAttribute *attr;
+ for (attr=sessObject->head[i]; attr; attr=attr->next) {
+ count++;
+ }
+ }
+ template = PORT_ArenaNewArray(arena, CK_ATTRIBUTE, count);
+ if (template == NULL) {
+ PZ_Unlock(sessObject->attributeLock);
+ *crv = CKR_HOST_MEMORY;
+ return NULL;
+ }
+ templateIndex = 0;
+ for (i=0; i < sessObject->hashSize; i++) {
+ SFTKAttribute *attr;
+ for (attr=sessObject->head[i]; attr; attr=attr->next) {
+ CK_ATTRIBUTE *tp = &template[templateIndex++];
+ /* copy the attribute */
+ *tp = attr->attrib;
+
+ /* fixup ULONG s */
+ if ((tp->ulValueLen == sizeof (CK_ULONG)) &&
+ (sftkdb_isULONG(tp->type)) ) {
+ CK_ULONG value = *(CK_ULONG *) tp->pValue;
+ unsigned char *data;
+ int j;
+
+ tp->pValue = PORT_ArenaAlloc(arena, DB_ULONG_SIZE);
+ data = (unsigned char *)tp->pValue;
+ if (data == NULL) {
+ *crv = CKR_HOST_MEMORY;
+ break;
+ }
+ for (j=0; j < DB_ULONG_SIZE; j++) {
+ data[j] = (value >> (DB_ULONG_SIZE-1-j)*BBP) & 0xff;
+ }
+ tp->ulValueLen = DB_ULONG_SIZE;
+ }
+
+ /* encrypt private attributes */
+ if ((handle != NULL) && (handle->type == SFTK_KEYDB_TYPE) &&
+ sftkdb_isPrivate(tp->type)) {
+
+ /* we have a private attribute */
+ SECItem *cipherText;
+ SECItem plainText;
+ SECStatus rv;
+
+ plainText.data = tp->pValue;
+ plainText.len = tp->ulValueLen;
+ PZ_Lock(handle->passwordLock);
+ if (handle->passwordKey.data == NULL) {
+ PZ_Unlock(handle->passwordLock);
+ *crv = CKR_USER_NOT_LOGGED_IN;
+ break;
+ }
+ rv = sftkdb_encrypt(arena, &handle->passwordKey, &plainText,
+ &cipherText);
+ PZ_Unlock(handle->passwordLock);
+ if (rv == SECSuccess) {
+ tp->pValue = cipherText->data;
+ tp->ulValueLen = cipherText->len;
+ } else {
+ *crv = CKR_GENERAL_ERROR; /* better error code here? */
+ break;
+ }
+ PORT_Memset(plainText.data, 0, plainText.len);
+ }
+ }
+ }
+ PORT_Assert(templateIndex <= count);
+ PZ_Unlock(sessObject->attributeLock);
+
+ if (*crv != CKR_OK) {
+ return NULL;
+ }
+ if (pcount) {
+ *pcount = count;
+ }
+ return template;
+
+}
+
+#define GET_SDB(handle) ((handle)->update ? (handle)->update : (handle)->db)
+
+CK_RV
+sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
+ CK_OBJECT_HANDLE *objectID)
+{
+ CK_ATTRIBUTE *template;
+ PLArenaPool *arena;
+ CK_ULONG count;
+ CK_RV crv;
+ SDB *db;
+
+ *objectID = CK_INVALID_HANDLE;
+
+ if (handle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ db = GET_SDB(handle);
+
+ arena = PORT_NewArena(256);
+ if (arena == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+
+ template = sftk_ExtractTemplate(arena, object, handle, &count, &crv);
+ if (!template) {
+ goto loser;
+ }
+
+ crv = sftkdb_CreateObject(handle, db, objectID, template, count);
+
+loser:
+ if (arena) {
+ PORT_FreeArena(arena,PR_FALSE);
+ }
+ if (crv == CKR_OK) {
+ *objectID |= (handle->type | SFTK_TOKEN_TYPE);
+ }
+ return crv;
+}
+
+
+
+
+CK_RV
+sftkdb_FindObjectsInit(SFTKDBHandle *handle, const CK_ATTRIBUTE *template,
+ CK_ULONG count, SDBFind **find)
+{
+ unsigned char *data = NULL;
+ CK_ATTRIBUTE *ntemplate = NULL;
+ CK_RV crv;
+ SDB *db;
+
+ if (handle == NULL) {
+ return CKR_OK;
+ }
+ db = GET_SDB(handle);
+
+ if (count != 0) {
+ ntemplate = sftkdb_fixupTemplateIn(template, count, &data);
+ if (ntemplate == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ }
+
+ crv = (*db->sdb_FindObjectsInit)(db, ntemplate,
+ count, find);
+ if (data) {
+ PORT_Free(ntemplate);
+ PORT_Free(data);
+ }
+ return crv;
+}
+
+CK_RV
+sftkdb_FindObjects(SFTKDBHandle *handle, SDBFind *find,
+ CK_OBJECT_HANDLE *ids, int arraySize, CK_ULONG *count)
+{
+ CK_RV crv;
+ SDB *db;
+
+ if (handle == NULL) {
+ *count = 0;
+ return CKR_OK;
+ }
+ db = GET_SDB(handle);
+
+ crv = (*db->sdb_FindObjects)(db, find, ids,
+ arraySize, count);
+ if (crv == CKR_OK) {
+ int i;
+ for (i=0; i < *count; i++) {
+ ids[i] |= (handle->type | SFTK_TOKEN_TYPE);
+ }
+ }
+ return crv;
+}
+
+CK_RV sftkdb_FindObjectsFinal(SFTKDBHandle *handle, SDBFind *find)
+{
+ SDB *db;
+ if (handle == NULL) {
+ return CKR_OK;
+ }
+ db = GET_SDB(handle);
+ return (*db->sdb_FindObjectsFinal)(db, find);
+}
+
+CK_RV
+sftkdb_GetAttributeValue(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id,
+ CK_ATTRIBUTE *template, CK_ULONG count)
+{
+ CK_RV crv,crv2;
+ CK_ATTRIBUTE *ntemplate;
+ unsigned char *data = NULL;
+ SDB *db;
+ int i;
+
+ if (handle == NULL) {
+ return CKR_GENERAL_ERROR;
+ }
+
+ /* short circuit common attributes */
+ if (count == 1 &&
+ (template[0].type == CKA_TOKEN ||
+ template[0].type == CKA_PRIVATE ||
+ template[0].type == CKA_SENSITIVE)) {
+ CK_BBOOL boolVal = CK_TRUE;
+
+ if (template[0].pValue == NULL) {
+ template[0].ulValueLen = sizeof(CK_BBOOL);
+ return CKR_OK;
+ }
+ if (template[0].ulValueLen < sizeof(CK_BBOOL)) {
+ template[0].ulValueLen = -1;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ if ((template[0].type == CKA_PRIVATE) &&
+ (handle->type != SFTK_KEYDB_TYPE)) {
+ boolVal = CK_FALSE;
+ }
+ if ((template[0].type == CKA_SENSITIVE) &&
+ (handle->type != SFTK_KEYDB_TYPE)) {
+ boolVal = CK_FALSE;
+ }
+ *(CK_BBOOL *)template[0].pValue = boolVal;
+ template[0].ulValueLen = sizeof(CK_BBOOL);
+ return CKR_OK;
+ }
+
+ db = GET_SDB(handle);
+ /* nothing to do */
+ if (count == 0) {
+ return CKR_OK;
+ }
+ ntemplate = sftkdb_fixupTemplateIn(template, count, &data);
+ if (ntemplate == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ object_id &= SFTK_OBJ_ID_MASK;
+ crv = (*db->sdb_GetAttributeValue)(db, object_id,
+ ntemplate, count);
+ crv2 = sftkdb_fixupTemplateOut(template, ntemplate, count, handle);
+ if (crv == CKR_OK) crv = crv2;
+ if (data) {
+ PORT_Free(ntemplate);
+ PORT_Free(data);
+ }
+ return crv;
+
+}
+
+CK_RV
+sftkdb_SetAttributeValue(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id,
+ const CK_ATTRIBUTE *template, CK_ULONG count)
+{
+ CK_RV crv = CKR_OK;
+ CK_ATTRIBUTE *ntemplate;
+ unsigned char *data = NULL;
+ SDB *db;
+
+ if (handle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ db = GET_SDB(handle);
+ /* nothing to do */
+ if (count == 0) {
+ return CKR_OK;
+ }
+ ntemplate = sftkdb_fixupTemplateIn(template, count, &data);
+ if (ntemplate == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ object_id &= SFTK_OBJ_ID_MASK;
+ crv = (*db->sdb_Begin)(db);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ crv = (*db->sdb_SetAttributeValue)(db, object_id,
+ ntemplate, count);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ crv = (*db->sdb_Commit)(db);
+loser:
+ if (crv != CKR_OK) {
+ (*db->sdb_Abort)(db);
+ }
+ if (data) {
+ PORT_Free(ntemplate);
+ PORT_Free(data);
+ }
+ return crv;
+}
+
+CK_RV
+sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id)
+{
+ CK_RV crv = CKR_OK;
+ SDB *db;
+
+ if (handle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ db = GET_SDB(handle);
+ object_id &= SFTK_OBJ_ID_MASK;
+ crv = (*db->sdb_Begin)(db);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ crv = (*db->sdb_DestroyObject)(db, object_id);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ crv = (*db->sdb_Commit)(db);
+loser:
+ if (crv != CKR_OK) {
+ (*db->sdb_Abort)(db);
+ }
+ return crv;
+}
+
+CK_RV
+sftkdb_CloseDB(SFTKDBHandle *handle)
+{
+ if (handle == NULL) {
+ return CKR_OK;
+ }
+ if (handle->update) {
+ (*handle->update->sdb_Close)(handle->update);
+ }
+ if (handle->db) {
+ (*handle->db->sdb_Close)(handle->db);
+ }
+ PORT_Free(handle);
+ return CKR_OK;
+}
+
+/*
+ * reset a database to it's uninitialized state.
+ */
+static CK_RV
+sftkdb_ResetDB(SFTKDBHandle *handle)
+{
+ CK_RV crv = CKR_OK;
+ SDB *db;
+ if (handle == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ db = GET_SDB(handle);
+ crv = (*db->sdb_Begin)(db);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ crv = (*db->sdb_Reset)(db);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ crv = (*db->sdb_Commit)(db);
+loser:
+ if (crv != CKR_OK) {
+ (*db->sdb_Abort)(db);
+ }
+ return crv;
+}
+
+
+CK_RV
+sftkdb_Begin(SFTKDBHandle *handle)
+{
+ CK_RV crv = CKR_OK;
+ SDB *db;
+
+ if (handle == NULL) {
+ return CKR_OK;
+ }
+ db = GET_SDB(handle);
+ if (db) {
+ crv = (*db->sdb_Begin)(db);
+ }
+ return crv;
+}
+
+CK_RV
+sftkdb_Commit(SFTKDBHandle *handle)
+{
+ CK_RV crv = CKR_OK;
+ SDB *db;
+
+ if (handle == NULL) {
+ return CKR_OK;
+ }
+ db = GET_SDB(handle);
+ if (db) {
+ (*db->sdb_Commit)(db);
+ }
+ return crv;
+}
+
+CK_RV
+sftkdb_Abort(SFTKDBHandle *handle)
+{
+ CK_RV crv = CKR_OK;
+ SDB *db;
+
+ if (handle == NULL) {
+ return CKR_OK;
+ }
+ db = GET_SDB(handle);
+ if (db) {
+ crv = (db->sdb_Abort)(db);
+ }
+ return crv;
+}
+
+
+/****************************************************************
+ *
+ * Secmod database.
+ *
+ * The new secmod database is simply a text file with each of the module
+ * entries. in the following form:
+ *
+ * #
+ * # This is a comment The next line is the library to load
+ * library=libmypkcs11.so
+ * name="My PKCS#11 module"
+ * params="my library's param string"
+ * nss="NSS parameters"
+ * other="parameters for other libraries and applications"
+ *
+ * library=libmynextpk11.so
+ * name="My other PKCS#11 module"
+ */
+
+static char *
+sftkdb_quote(const char *string, char quote)
+{
+ char *newString = 0;
+ int escapes = 0, size = 0;
+ const char *src;
+ char *dest;
+
+ size=2;
+ for (src=string; *src ; src++) {
+ if ((*src == quote) || (*src == '\\')) escapes++;
+ size++;
+ }
+
+ dest = newString = PORT_ZAlloc(escapes+size+1);
+ if (newString == NULL) {
+ return NULL;
+ }
+
+ *dest++=quote;
+ for (src=string; *src; src++,dest++) {
+ if ((*src == '\\') || (*src == quote)) {
+ *dest++ = '\\';
+ }
+ *dest = *src;
+ }
+ *dest=quote;
+
+ return newString;
+}
+
+/*
+ * Smart string cat functions. Automatically manage the memory.
+ * The first parameter is the source string. If it's null, we
+ * allocate memory for it. If it's not, we reallocate memory
+ * so the the concanenated string fits.
+ */
+static char *
+sftkdb_DupnCat(char *baseString, const char *str, int str_len)
+{
+ int len = (baseString ? PORT_Strlen(baseString) : 0) + 1;
+ char *newString;
+
+ len += str_len;
+ newString = (char *) PORT_Realloc(baseString,len);
+ if (newString == NULL) {
+ PORT_Free(baseString);
+ return NULL;
+ }
+ if (baseString == NULL) *newString = 0;
+ return PORT_Strncat(newString,str, str_len);
+}
+
+/* Same as sftkdb_DupnCat except it concatenates the full string, not a
+ * partial one */
+static char *
+sftkdb_DupCat(char *baseString, const char *str)
+{
+ return sftkdb_DupnCat(baseString, str, PORT_Strlen(str));
+}
+
+/* function to free up all the memory associated with a null terminated
+ * array of module specs */
+static SECStatus
+sftkdb_releaseSpecList(char **moduleSpecList)
+{
+ if (moduleSpecList) {
+ char **index;
+ for(index = moduleSpecList; *index; index++) {
+ PORT_Free(*index);
+ }
+ PORT_Free(moduleSpecList);
+ }
+ return SECSuccess;
+}
+
+#define SECMOD_STEP 10
+static SECStatus
+sftkdb_growList(char ***pModuleList, int *useCount, int last)
+{
+ char **newModuleList;
+
+ *useCount += SECMOD_STEP;
+ newModuleList = (char **)PORT_Realloc(*pModuleList,
+ *useCount*sizeof(char *));
+ if (newModuleList == NULL) {
+ return SECFailure;
+ }
+ PORT_Memset(&newModuleList[last],0, sizeof(char *)*SECMOD_STEP);
+ *pModuleList = newModuleList;
+ return SECSuccess;
+}
+
+static
+char *sftk_getOldSecmodName(const char *dbname,const char *filename)
+{
+ char *file = NULL;
+ char *dirPath = PORT_Strdup(dbname);
+ char *sep;
+
+ sep = PORT_Strrchr(dirPath,*PATH_SEPARATOR);
+#ifdef WINDOWS
+ if (!sep) {
+ sep = PORT_Strrchr(dirPath,'/');
+ }
+#endif
+ if (sep) {
+ *(sep)=0;
+ }
+ file= PR_smprintf("%s"PATH_SEPARATOR"%s", dirPath, filename);
+ PORT_Free(dirPath);
+ return file;
+}
+
+#define MAX_LINE_LENGTH 2048
+#define SFTK_DEFAULT_INTERNAL_INIT1 "library= name=\"NSS Internal PKCS #11 Module\" parameters="
+#define SFTK_DEFAULT_INTERNAL_INIT2 " NSS=\"Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={"
+#define SFTK_DEFAULT_INTERNAL_INIT3 " askpw=any timeout=30})\""
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+/*
+ * Read all the existing modules in out of the file.
+ */
+char **
+sftkdb_ReadSecmodDB(SDBType dbType, const char *appName,
+ const char *filename, const char *dbname,
+ char *params, PRBool rw)
+{
+ FILE *fd = NULL;
+ char **moduleList = NULL;
+ int moduleCount = 1;
+ int useCount = SECMOD_STEP;
+ char line[MAX_LINE_LENGTH];
+ PRBool internal = PR_FALSE;
+ PRBool skipParams = PR_FALSE;
+ char *moduleString = NULL;
+ char *paramsValue=NULL;
+ PRBool failed = PR_TRUE;
+
+ if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
+ return sftkdbCall_ReadSecmodDB(appName, filename, dbname, params, rw);
+ }
+
+ moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
+ if (moduleList == NULL) return NULL;
+
+ /* do we really want to use streams here */
+ fd = fopen(dbname, "r");
+ if (fd == NULL) goto done;
+
+ /*
+ * the following loop takes line separated config lines and colapses
+ * the lines to a single string, escaping and quoting as necessary.
+ */
+ /* loop state variables */
+ moduleString = NULL; /* current concatenated string */
+ internal = PR_FALSE; /* is this an internal module */
+ skipParams = PR_FALSE; /* did we find an override parameter block*/
+ paramsValue = NULL; /* the current parameter block value */
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ int len = PORT_Strlen(line);
+
+ /* remove the ending newline */
+ if (len && line[len-1] == '\n') {
+ len--;
+ line[len] = 0;
+ }
+ if (*line == '#') {
+ continue;
+ }
+ if (*line != 0) {
+ /*
+ * The PKCS #11 group standard assumes blocks of strings
+ * separated by new lines, clumped by new lines. Internally
+ * we take strings separated by spaces, so we may need to escape
+ * certain spaces.
+ */
+ char *value = PORT_Strchr(line,'=');
+
+ /* there is no value, write out the stanza as is */
+ if (value == NULL || value[1] == 0) {
+ if (moduleString) {
+ moduleString = sftkdb_DupnCat(moduleString," ", 1);
+ if (moduleString == NULL) goto loser;
+ }
+ moduleString = sftkdb_DupCat(moduleString, line);
+ if (moduleString == NULL) goto loser;
+ /* value is already quoted, just write it out */
+ } else if (value[1] == '"') {
+ if (moduleString) {
+ moduleString = sftkdb_DupnCat(moduleString," ", 1);
+ if (moduleString == NULL) goto loser;
+ }
+ moduleString = sftkdb_DupCat(moduleString, line);
+ if (moduleString == NULL) goto loser;
+ /* we have an override parameter section, remember that
+ * we found this (see following comment about why this
+ * is necessary). */
+ if (PORT_Strncasecmp(line, "parameters", 10) == 0) {
+ skipParams = PR_TRUE;
+ }
+ /*
+ * The internal token always overrides it's parameter block
+ * from the passed in parameters, so wait until then end
+ * before we include the parameter block in case we need to
+ * override it. NOTE: if the parameter block is quoted with ("),
+ * this override does not happen. This allows you to override
+ * the application's parameter configuration.
+ *
+ * parameter block state is controlled by the following variables:
+ * skipParams - Bool : set to true of we have an override param
+ * block (all other blocks, either implicit or explicit are
+ * ignored).
+ * paramsValue - char * : pointer to the current param block. In
+ * the absence of overrides, paramsValue is set to the first
+ * parameter block we find. All subsequent blocks are ignored.
+ * When we find an internal token, the application passed
+ * parameters take precident.
+ */
+ } else if (PORT_Strncasecmp(line, "parameters", 10) == 0) {
+ /* already have parameters */
+ if (paramsValue) {
+ continue;
+ }
+ paramsValue = sftkdb_quote(&value[1], '"');
+ if (paramsValue == NULL) goto loser;
+ continue;
+ } else {
+ /* may need to quote */
+ char *newLine;
+ if (moduleString) {
+ moduleString = sftkdb_DupnCat(moduleString," ", 1);
+ if (moduleString == NULL) goto loser;
+ }
+ moduleString = sftkdb_DupnCat(moduleString,line,value-line+1);
+ if (moduleString == NULL) goto loser;
+ newLine = sftkdb_quote(&value[1],'"');
+ if (newLine == NULL) goto loser;
+ moduleString = sftkdb_DupCat(moduleString,newLine);
+ PORT_Free(newLine);
+ if (moduleString == NULL) goto loser;
+ }
+
+ /* check to see if it's internal? */
+ if (PORT_Strncasecmp(line, "NSS=", 4) == 0) {
+ /* This should be case insensitive! reviewers make
+ * me fix it if it's not */
+ if (PORT_Strstr(line,"internal")) {
+ internal = PR_TRUE;
+ /* override the parameters */
+ if (paramsValue) {
+ PORT_Free(paramsValue);
+ }
+ paramsValue = sftkdb_quote(params, '"');
+ }
+ }
+ continue;
+ }
+ if ((moduleString == NULL) || (*moduleString == 0)) {
+ continue;
+ }
+
+ /*
+ * if we are here, we have found a complete stanza. Now write out
+ * any param section we may have found.
+ */
+ if (paramsValue) {
+ /* we had an override */
+ if (!skipParams) {
+ moduleString = sftkdb_DupnCat(moduleString," parameters=", 12);
+ if (moduleString == NULL) goto loser;
+ moduleString = sftkdb_DupCat(moduleString, paramsValue);
+ if (moduleString == NULL) goto loser;
+ }
+ PORT_Free(paramsValue);
+ paramsValue = NULL;
+ }
+
+ if ((moduleCount+1) >= useCount) {
+ SECStatus rv;
+ rv = sftkdb_growList(&moduleList, &useCount, moduleCount+1);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+
+ if (internal) {
+ moduleList[0] = moduleString;
+ } else {
+ moduleList[moduleCount] = moduleString;
+ moduleCount++;
+ }
+ moduleString = NULL;
+ internal = PR_FALSE;
+ skipParams = PR_FALSE;
+ }
+
+ if (moduleString) {
+ PORT_Free(moduleString);
+ moduleString = NULL;
+ }
+done:
+ /* if we couldn't open a pkcs11 database, look for the old one */
+ if (fd == NULL) {
+ char *olddbname = sftk_getOldSecmodName(dbname,filename);
+ PRStatus status;
+ char **oldModuleList;
+ int i;
+
+ /* couldn't get the old name */
+ if (!olddbname) {
+ goto bail;
+ }
+
+ /* old one doesn't exist */
+ status = PR_Access(olddbname, PR_ACCESS_EXISTS);
+ if (status != PR_SUCCESS) {
+ goto bail;
+ }
+
+ oldModuleList = sftkdbCall_ReadSecmodDB(appName, filename,
+ olddbname, params, rw);
+ /* old one had no modules */
+ if (!oldModuleList) {
+ goto bail;
+ }
+
+ /* count the modules */
+ for (i=0; oldModuleList[i]; i++) { }
+
+ /* grow the moduleList if necessary */
+ if (i >= useCount) {
+ SECStatus rv;
+ rv = sftkdb_growList(&moduleList,&useCount,moduleCount+1);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+
+ /* write each module out, and copy it */
+ for (i=0; oldModuleList[i]; i++) {
+ if (rw) {
+ sftkdb_AddSecmodDB(dbType,appName,filename,dbname,
+ oldModuleList[i],rw);
+ }
+ if (moduleList[i]) {
+ PORT_Free(moduleList[i]);
+ }
+ moduleList[i] = PORT_Strdup(oldModuleList[i]);
+ }
+
+ /* done with the old module list */
+ sftkdbCall_ReleaseSecmodDBData(appName, filename, olddbname,
+ oldModuleList, rw);
+ }
+bail:
+
+ if (!moduleList[0]) {
+ char * newParams;
+ moduleString = PORT_Strdup(SFTK_DEFAULT_INTERNAL_INIT1);
+ newParams = sftkdb_quote(params,'"');
+ if (newParams == NULL) goto loser;
+ moduleString = sftkdb_DupCat(moduleString, newParams);
+ PORT_Free(newParams);
+ if (moduleString == NULL) goto loser;
+ moduleString = sftkdb_DupCat(moduleString, SFTK_DEFAULT_INTERNAL_INIT2);
+ if (moduleString == NULL) goto loser;
+ moduleString = sftkdb_DupCat(moduleString, SECMOD_SLOT_FLAGS);
+ if (moduleString == NULL) goto loser;
+ moduleString = sftkdb_DupCat(moduleString, SFTK_DEFAULT_INTERNAL_INIT3);
+ if (moduleString == NULL) goto loser;
+ moduleList[0] = moduleString;
+ moduleString = NULL;
+ }
+ failed = PR_FALSE;
+
+loser:
+ /*
+ * cleanup
+ */
+ /* deal with trust cert db here */
+ if (moduleString) {
+ PORT_Free(moduleString);
+ moduleString = NULL;
+ }
+ if (paramsValue) {
+ PORT_Free(paramsValue);
+ paramsValue = NULL;
+ }
+ if (failed || (moduleList[0] == NULL)) {
+ /* This is wrong! FIXME */
+ sftkdb_releaseSpecList(moduleList);
+ moduleList = NULL;
+ failed = PR_TRUE;
+ }
+ if (fd != NULL) {
+ fclose(fd);
+ } else if (!failed && rw) {
+ /* update our internal module */
+ sftkdb_AddSecmodDB(dbType,appName,filename,dbname,moduleList[0],rw);
+ }
+ return moduleList;
+}
+
+SECStatus
+sftkdb_ReleaseSecmodDBData(SDBType dbType, const char *appName,
+ const char *filename, const char *dbname,
+ char **moduleSpecList, PRBool rw)
+{
+ if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
+ return sftkdbCall_ReleaseSecmodDBData(appName, filename, dbname,
+ moduleSpecList, rw);
+ }
+ if (moduleSpecList) {
+ sftkdb_releaseSpecList(moduleSpecList);
+ }
+ return SECSuccess;
+}
+
+
+/*
+ * Delete a module from the Data Base
+ */
+SECStatus
+sftkdb_DeleteSecmodDB(SDBType dbType, const char *appName,
+ const char *filename, const char *dbname,
+ char *args, PRBool rw)
+{
+ /* SHDB_FIXME implement */
+ FILE *fd = NULL;
+ FILE *fd2 = NULL;
+ char line[MAX_LINE_LENGTH];
+ char *dbname2 = NULL;
+ char *block = NULL;
+ char *name = NULL;
+ char *lib = NULL;
+ int name_len, lib_len;
+ PRBool skip = PR_FALSE;
+ PRBool found = PR_FALSE;
+
+ if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
+ return sftkdbCall_DeleteSecmodDB(appName, filename, dbname, args, rw);
+ }
+
+ if (!rw) {
+ return SECFailure;
+ }
+
+ dbname2 = strdup(dbname);
+ if (dbname2 == NULL) goto loser;
+ dbname2[strlen(dbname)-1]++;
+
+ /* do we really want to use streams here */
+ fd = fopen(dbname, "r");
+ if (fd == NULL) goto loser;
+ fd2 = fopen(dbname2, "w+");
+ if (fd2 == NULL) goto loser;
+
+ name = sftk_argGetParamValue("name",args);
+ if (name) {
+ name_len = PORT_Strlen(name);
+ }
+ lib = sftk_argGetParamValue("library",args);
+ if (lib) {
+ lib_len = PORT_Strlen(lib);
+ }
+
+
+ /*
+ * the following loop takes line separated config files and colapses
+ * the lines to a single string, escaping and quoting as necessary.
+ */
+ /* loop state variables */
+ block = NULL;
+ skip = PR_FALSE;
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ /* If we are processing a block (we haven't hit a blank line yet */
+ if (*line != '\n') {
+ /* skip means we are in the middle of a block we are deleting */
+ if (skip) {
+ continue;
+ }
+ /* if we haven't found the block yet, check to see if this block
+ * matches our requirements */
+ if (!found && ((name && (PORT_Strncasecmp(line,"name=",5) == 0) &&
+ (PORT_Strncmp(line+5,name,name_len) == 0)) ||
+ (lib && (PORT_Strncasecmp(line,"library=",8) == 0) &&
+ (PORT_Strncmp(line+8,lib,lib_len) == 0)))) {
+
+ /* yup, we don't need to save any more data, */
+ PORT_Free(block);
+ block=NULL;
+ /* we don't need to collect more of this block */
+ skip = PR_TRUE;
+ /* we don't need to continue searching for the block */
+ found =PR_TRUE;
+ continue;
+ }
+ /* not our match, continue to collect data in this block */
+ block = sftkdb_DupCat(block,line);
+ continue;
+ }
+ /* we've collected a block of data that wasn't the module we were
+ * looking for, write it out */
+ if (block) {
+ fwrite(block, PORT_Strlen(block), 1, fd2);
+ PORT_Free(block);
+ block = NULL;
+ }
+ /* If we didn't just delete the this block, keep the blank line */
+ if (!skip) {
+ fputs(line,fd2);
+ }
+ /* we are definately not in a deleted block anymore */
+ skip = PR_FALSE;
+ }
+ fclose(fd);
+ fclose(fd2);
+ /* rename dbname2 to dbname */
+ if (found) {
+ PR_Delete(dbname);
+ PR_Rename(dbname2,dbname);
+ }
+ PORT_Free(dbname2);
+ return SECSuccess;
+
+loser:
+ if (fd != NULL) {
+ fclose(fd);
+ }
+ if (fd2 != NULL) {
+ fclose(fd2);
+ }
+ if (dbname2) {
+ PR_Delete(dbname2);
+ PORT_Free(dbname2);
+ }
+ return SECFailure;
+}
+
+/*
+ * Add a module to the Data base
+ */
+SECStatus
+sftkdb_AddSecmodDB(SDBType dbType, const char *appName,
+ const char *filename, const char *dbname,
+ char *module, PRBool rw)
+{
+ FILE *fd = NULL;
+ char *block = NULL;
+ PRBool libFound = PR_FALSE;
+
+ if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
+ return sftkdbCall_AddSecmodDB(appName, filename, dbname, module, rw);
+ }
+
+ /* can't write to a read only module */
+ if (!rw) {
+ return SECFailure;
+ }
+
+ /* remove the previous version if it exists */
+ (void) sftkdb_DeleteSecmodDB(dbType, appName, filename, dbname, module, rw);
+
+ /* do we really want to use streams here */
+ fd = fopen(dbname, "a+");
+ if (fd == NULL) {
+ return SECFailure;
+ }
+ module = sftk_argStrip(module);
+ while (*module) {
+ int count;
+ char *keyEnd = PORT_Strchr(module,'=');
+ char *value;
+
+ if (PORT_Strncmp(module, "library=", 8) == 0) {
+ libFound=PR_TRUE;
+ }
+ if (keyEnd == NULL) {
+ block = sftkdb_DupCat(block, module);
+ break;
+ }
+ value = sftk_argFetchValue(&keyEnd[1], &count);
+ block = sftkdb_DupnCat(block, module, keyEnd-module+1);
+ if (block == NULL) { goto loser; }
+ if (value) {
+ block = sftkdb_DupCat(block, sftk_argStrip(value));
+ PORT_Free(value);
+ }
+ if (block == NULL) { goto loser; }
+ block = sftkdb_DupnCat(block, "\n", 1);
+ module = keyEnd + 1 + count;
+ module = sftk_argStrip(module);
+ }
+ if (block) {
+ if (!libFound) {
+ fprintf(fd,"library=\n");
+ }
+ fwrite(block, PORT_Strlen(block), 1, fd);
+ fprintf(fd,"\n");
+ PORT_Free(block);
+ block = NULL;
+ }
+ fclose(fd);
+ return SECSuccess;
+
+loser:
+ PORT_Free(block);
+ fclose(fd);
+ return SECFailure;
+}
+
+/******************************************************************
+ *
+ * Key DB password handling functions
+ *
+ * These functions manage the key db password (set, reset, initialize, use).
+ *
+ * The key is managed on 'this side' of the database. All private data is
+ * encrypted before it is sent to the database itself. Besides PBE's, the
+ * database management code can also mix in various fixed keys so the data
+ * in the database is no longer considered 'plain text'.
+ */
+
+
+/* take string password and turn it into a key. The key is dependent
+ * on a global salt entry acquired from the database. This salted
+ * value will be based to a pkcs5 pbe function before it is used
+ * in an actual encryption */
+static SECStatus
+sftkdb_passwordToKey(SFTKDBHandle *keydb, SDBPasswordEntry *entry,
+ const char *pw, SECItem *key)
+{
+ SHA1Context *cx = NULL;
+ SECStatus rv = SECFailure;
+
+ key->data = PORT_Alloc(SHA1_LENGTH);
+ if (key->data == NULL) {
+ goto loser;
+ }
+ key->len = SHA1_LENGTH;
+
+ cx = SHA1_NewContext();
+ if ( cx == NULL) {
+ goto loser;
+ }
+ SHA1_Begin(cx);
+ if (entry && entry->salt.data ) {
+ SHA1_Update(cx, entry->salt.data, entry->salt.len);
+ }
+ SHA1_Update(cx, (unsigned char *)pw, PORT_Strlen(pw));
+ SHA1_End(cx, key->data, &key->len, key->len);
+ rv = SECSuccess;
+
+loser:
+ if (cx) {
+ SHA1_DestroyContext(cx, PR_TRUE);
+ }
+ if (rv != SECSuccess) {
+ if (key->data != NULL) {
+ PORT_ZFree(key->data,key->len);
+ }
+ key->data = NULL;
+ }
+ return rv;
+}
+
+/*
+ * Cipher text stored in the database contains 3 elements:
+ * 1) an identifier describing the encryption algorithm.
+ * 2) an entry specific salt value.
+ * 3) the encrypted value.
+ *
+ * The following data structure represents the encrypted data in a decoded
+ * (but still encrypted) form.
+ */
+typedef struct sftkCipherValueStr sftkCipherValue;
+struct sftkCipherValueStr {
+ PLArenaPool *arena;
+ SECOidTag alg;
+ NSSPKCS5PBEParameter *param;
+ SECItem salt;
+ SECItem value;
+};
+
+#define SFTK_CIPHERTEXT_VERSION 3
+
+struct SFTKDBEncryptedDataInfoStr {
+ SECAlgorithmID algorithm;
+ SECItem encryptedData;
+};
+typedef struct SFTKDBEncryptedDataInfoStr SFTKDBEncryptedDataInfo;
+
+const SEC_ASN1Template sftkdb_EncryptedDataInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(SFTKDBEncryptedDataInfo) },
+ { SEC_ASN1_INLINE,
+ offsetof(SFTKDBEncryptedDataInfo,algorithm),
+ SECOID_AlgorithmIDTemplate },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(SFTKDBEncryptedDataInfo,encryptedData) },
+ { 0 }
+};
+
+/*
+ * This parses the cipherText into cipher value. NOTE: cipherValue will point
+ * to data in cipherText, if cipherText is freed, cipherValue will be invalid.
+ *
+ * Use existing NSS data record: (sizes and offsets in bytes)
+ *
+ * offset size label Description
+ * 0 1 version Data base version number must be 3
+ * 1 1 slen Length of Salt
+ * 2 1 nlen Length of optional nickname
+ * 3 slen sdata Salt data
+ * 3+slen nlen ndata Optional nickname data
+ * 3+nlen+slen 1 olen Length of algorithm OID
+ * 4+nlen+slen olen odata Algorithm OID data.
+ * 4+nlen+slen+
+ * olen rest vdata Encrypted data.
+ *
+ * rest is the rest of the block passed into us.
+ */
+static SECStatus
+sftkdb_decodeCipherText(SECItem *cipherText, sftkCipherValue *cipherValue)
+{
+ PLArenaPool *arena = NULL;
+ SFTKDBEncryptedDataInfo edi;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return SECFailure;
+ }
+ cipherValue->arena = NULL;
+ cipherValue->param = NULL;
+
+ rv = SEC_QuickDERDecodeItem(arena, &edi, sftkdb_EncryptedDataInfoTemplate,
+ cipherText);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ cipherValue->alg = SECOID_GetAlgorithmTag(&edi.algorithm);
+ cipherValue->param = nsspkcs5_AlgidToParam(&edi.algorithm);
+ if (cipherValue->param == NULL) {
+ goto loser;
+ }
+ cipherValue->value = edi.encryptedData;
+ cipherValue->arena = arena;
+
+ return SECSuccess;
+loser:
+ if (cipherValue->param) {
+ nsspkcs5_DestroyPBEParameter(cipherValue->param);
+ cipherValue->param = NULL;
+ }
+ if (arena) {
+ PORT_FreeArena(arena,PR_FALSE);
+ }
+ return SECFailure;
+}
+
+
+
+/*
+ * unlike decode, Encode actually allocates a SECItem the caller must free
+ * The caller can pass an optional arena to to indicate where to place
+ * the resultant cipherText.
+ */
+static SECStatus
+sftkdb_encodeCipherText(PLArenaPool *arena, sftkCipherValue *cipherValue,
+ SECItem **cipherText)
+{
+ SFTKDBEncryptedDataInfo edi;
+ SECAlgorithmID *algid;
+ SECStatus rv;
+ PLArenaPool *localArena = NULL;
+
+
+ localArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (localArena == NULL) {
+ return SECFailure;
+ }
+
+ algid = nsspkcs5_CreateAlgorithmID(localArena, cipherValue->alg,
+ cipherValue->param);
+ if (algid == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+ rv = SECOID_CopyAlgorithmID(localArena, &edi.algorithm, algid);
+ SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ edi.encryptedData = cipherValue->value;
+
+ *cipherText = SEC_ASN1EncodeItem(arena, NULL, &edi,
+ sftkdb_EncryptedDataInfoTemplate);
+ if (*cipherText == NULL) {
+ rv = SECFailure;
+ }
+
+loser:
+ if (localArena) {
+ PORT_FreeArena(localArena,PR_FALSE);
+ }
+
+ return rv;
+}
+
+
+/*
+ * Use our key to decode a cipherText block from the database.
+ *
+ * plain text is allocated by nsspkcs5_CipherData and must be freed
+ * with SECITEM_FreeItem by the caller.
+ */
+static SECStatus
+sftkdb_decrypt(SECItem *passKey, SECItem *cipherText, SECItem **plain)
+{
+ SECStatus rv;
+ sftkCipherValue cipherValue;
+
+ /* First get the cipher type */
+ rv = sftkdb_decodeCipherText(cipherText, &cipherValue);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ *plain = nsspkcs5_CipherData(cipherValue.param, passKey, &cipherValue.value,
+ PR_FALSE, NULL);
+ if (*plain == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+loser:
+ if (cipherValue.param) {
+ nsspkcs5_DestroyPBEParameter(cipherValue.param);
+ }
+ if (cipherValue.arena) {
+ PORT_FreeArena(cipherValue.arena,PR_FALSE);
+ }
+ return rv;
+}
+
+#define SALT_LENGTH 20
+
+/*
+ * encrypt a block. This function returned the encrypted ciphertext which
+ * the caller must free. If the caller provides an arena, cipherText will
+ * be allocated out of that arena. This also generated the per entry
+ * salt automatically.
+ */
+static SECStatus
+sftkdb_encrypt(PLArenaPool *arena, SECItem *passKey, SECItem *plainText,
+ SECItem **cipherText)
+{
+ SECStatus rv;
+ sftkCipherValue cipherValue;
+ SECItem *cipher = NULL;
+ NSSPKCS5PBEParameter *param = NULL;
+ unsigned char saltData[SALT_LENGTH];
+
+ cipherValue.alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
+ cipherValue.salt.len = SALT_LENGTH;
+ cipherValue.salt.data = saltData;
+ RNG_GenerateGlobalRandomBytes(saltData,SALT_LENGTH);
+
+ param = nsspkcs5_NewParam(cipherValue.alg, &cipherValue.salt, 1);
+ if (param == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+ cipher = nsspkcs5_CipherData(param, passKey, plainText, PR_TRUE, NULL);
+ if (cipher == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+ cipherValue.value = *cipher;
+ cipherValue.param = param;
+
+ rv = sftkdb_encodeCipherText(arena, &cipherValue, cipherText);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+loser:
+ if (cipher) {
+ SECITEM_FreeItem(cipher, PR_FALSE);
+ }
+ if (param) {
+ nsspkcs5_DestroyPBEParameter(param);
+ }
+ return rv;
+}
+
+
+/*
+ * stub files for legacy db's to be able to encrypt and decrypt
+ * various keys and attributes.
+ */
+SECStatus
+sftkdb_encrypt_stub(PRArenaPool *arena, SDB *sdb, SECItem *plainText,
+ SECItem **cipherText)
+{
+ SFTKDBHandle *handle = sdb->app_private;
+ SECStatus rv;
+
+ if (handle == NULL) {
+ return SECFailure;
+ }
+
+ /* if we aren't th handle, try the other handle */
+ if (handle->type != SFTK_KEYDB_TYPE) {
+ handle = handle->peerDB;
+ }
+
+ /* not a key handle */
+ if (handle == NULL || handle->passwordLock == NULL) {
+ return SECFailure;
+ }
+
+ PZ_Lock(handle->passwordLock);
+ if (handle->passwordKey.data == NULL) {
+ PZ_Unlock(handle->passwordLock);
+ /* PORT_SetError */
+ return SECFailure;
+ }
+
+ rv = sftkdb_encrypt(arena,
+ handle->newKey?handle->newKey:&handle->passwordKey,
+ plainText, cipherText);
+ PZ_Unlock(handle->passwordLock);
+
+ return rv;
+}
+
+/*
+ * stub files for legacy db's to be able to encrypt and decrypt
+ * various keys and attributes.
+ */
+SECStatus
+sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText)
+{
+ SFTKDBHandle *handle = sdb->app_private;
+ SECStatus rv;
+
+ if (handle == NULL) {
+ return SECFailure;
+ }
+
+ /* if we aren't th handle, try the other handle */
+ if (handle->type != SFTK_KEYDB_TYPE) {
+ handle = handle->peerDB;
+ }
+
+ /* not a key handle */
+ if (handle == NULL || handle->passwordLock == NULL) {
+ return SECFailure;
+ }
+
+ PZ_Lock(handle->passwordLock);
+ if (handle->passwordKey.data == NULL) {
+ PZ_Unlock(handle->passwordLock);
+ /* PORT_SetError */
+ return SECFailure;
+ }
+ rv = sftkdb_decrypt(&handle->passwordKey, cipherText, plainText);
+ PZ_Unlock(handle->passwordLock);
+
+ return rv;
+}
+
+/*
+ * safely swith the passed in key for the one caches in the keydb handle
+ *
+ * A key attached to the handle tells us the the token is logged in.
+ * We can used the key attached to the handle in sftkdb_encrypt
+ * and sftkdb_decrypt calls.
+ */
+static void
+sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey)
+{
+ unsigned char *data;
+ int len;
+
+ if (keydb->passwordLock == NULL) {
+ PORT_Assert(keydb->type != SFTK_KEYDB_TYPE);
+ return;
+ }
+
+ /* an atomic pointer set would be nice */
+ PZ_Lock(keydb->passwordLock);
+ data = keydb->passwordKey.data;
+ len = keydb->passwordKey.len;
+ keydb->passwordKey.data = passKey->data;
+ keydb->passwordKey.len = passKey->len;
+ passKey->data = data;
+ passKey->len = len;
+ PZ_Unlock(keydb->passwordLock);
+}
+
+/*
+ * known attributes
+ */
+static const CK_ATTRIBUTE_TYPE known_attributes[] = {
+ CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION,
+ CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER,
+ CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED,
+ CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL,
+ CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY,
+ CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE,
+ CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER,
+ CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE,
+ CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT,
+ CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT,
+ CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS,
+ CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE,
+ CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE,
+ CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS,
+ CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_TEMPLATE,
+ CKA_UNWRAP_TEMPLATE, CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT,
+ CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y, CKA_RESOLUTION, CKA_CHAR_ROWS,
+ CKA_CHAR_COLUMNS, CKA_COLOR, CKA_BITS_PER_PIXEL, CKA_CHAR_SETS,
+ CKA_ENCODING_METHODS, CKA_MIME_TYPES, CKA_MECHANISM_TYPE,
+ CKA_REQUIRED_CMS_ATTRIBUTES, CKA_DEFAULT_CMS_ATTRIBUTES,
+ CKA_SUPPORTED_CMS_ATTRIBUTES, CKA_NETSCAPE_URL, CKA_NETSCAPE_EMAIL,
+ CKA_NETSCAPE_SMIME_INFO, CKA_NETSCAPE_SMIME_TIMESTAMP,
+ CKA_NETSCAPE_PKCS8_SALT, CKA_NETSCAPE_PASSWORD_CHECK, CKA_NETSCAPE_EXPIRES,
+ CKA_NETSCAPE_KRL, CKA_NETSCAPE_PQG_COUNTER, CKA_NETSCAPE_PQG_SEED,
+ CKA_NETSCAPE_PQG_H, CKA_NETSCAPE_PQG_SEED_BITS, CKA_NETSCAPE_MODULE_SPEC,
+ CKA_TRUST_DIGITAL_SIGNATURE, CKA_TRUST_NON_REPUDIATION,
+ CKA_TRUST_KEY_ENCIPHERMENT, CKA_TRUST_DATA_ENCIPHERMENT,
+ CKA_TRUST_KEY_AGREEMENT, CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN,
+ CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING,
+ CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM,
+ CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING,
+ CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
+ CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS
+};
+
+static int known_attributes_size= sizeof(known_attributes)/
+ sizeof(known_attributes[0]);
+
+static CK_RV
+sftkdb_GetObjectTemplate(SDB *source, CK_OBJECT_HANDLE id,
+ CK_ATTRIBUTE *ptemplate, CK_ULONG *max)
+{
+ int i,j;
+ CK_RV crv;
+
+ if (*max < known_attributes_size) {
+ *max = known_attributes_size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ for (i=0; i < known_attributes_size; i++) {
+ ptemplate[i].type = known_attributes[i];
+ ptemplate[i].pValue = NULL;
+ ptemplate[i].ulValueLen = 0;
+ }
+
+ crv = (*source->sdb_GetAttributeValue)(source, id,
+ ptemplate, known_attributes_size);
+
+ if ((crv != CKR_OK) && (crv != CKR_ATTRIBUTE_TYPE_INVALID)) {
+ return crv;
+ }
+
+ for (i=0, j=0; i < known_attributes_size; i++, j++) {
+ while (i < known_attributes_size && (ptemplate[i].ulValueLen == -1)) {
+ i++;
+ }
+ if (i >= known_attributes_size) {
+ break;
+ }
+ /* cheap optimization */
+ if (i == j) {
+ continue;
+ }
+ ptemplate[j] = ptemplate[i];
+ }
+ *max = j;
+ return CKR_OK;
+}
+
+#ifdef notdef
+static void
+dump_attribute(CK_ATTRIBUTE *attr)
+{
+ unsigned char *buf = attr->pValue;
+ int count,i;
+
+ printf("%08x: (%d) ",attr->type, attr->ulValueLen);
+ count = attr->ulValueLen;
+ if (count > 10) count = 10;
+ for (i=0; i < count; i++) {
+ printf("%02x",buf[i]);
+ }
+ printf("\n");
+}
+#endif
+
+
+#define MAX_ATTRIBUTES 500
+static CK_RV
+sftkdb_copyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id, SECItem *key)
+{
+ CK_ATTRIBUTE template[MAX_ATTRIBUTES];
+ CK_ATTRIBUTE *ptemplate;
+ CK_ULONG max_attributes = MAX_ATTRIBUTES;
+ SDB *source = handle->update;
+ SDB *target = handle->db;
+ int i;
+ CK_RV crv;
+
+ ptemplate = &template[0];
+ id &= SFTK_OBJ_ID_MASK;
+ crv = sftkdb_GetObjectTemplate(source, id, ptemplate, &max_attributes);
+ if (crv == CKR_BUFFER_TOO_SMALL) {
+ ptemplate = PORT_NewArray(CK_ATTRIBUTE, max_attributes);
+ if (ptemplate == NULL) {
+ crv = CKR_HOST_MEMORY;
+ } else {
+ crv = sftkdb_GetObjectTemplate(source, id,
+ ptemplate, &max_attributes);
+ }
+ }
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+
+ for (i=0; i < max_attributes; i++) {
+ ptemplate[i].pValue = PORT_Alloc(ptemplate[i].ulValueLen);
+ if (ptemplate[i].pValue == NULL) {
+ crv = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ }
+ crv = (*source->sdb_GetAttributeValue)(source, id,
+ ptemplate, max_attributes);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+
+ crv = sftkdb_CreateObject(handle, target, &id, ptemplate, max_attributes);
+ if (ptemplate && ptemplate != template) {
+ PORT_Free(ptemplate);
+ }
+
+loser:
+ if (ptemplate) {
+ for (i=0; i < max_attributes; i++) {
+ if (ptemplate[i].pValue) {
+ PORT_Memset(ptemplate[i].pValue, 0, ptemplate[i].ulValueLen);
+ PORT_Free(ptemplate[i].pValue);
+ }
+ }
+ if (ptemplate != template) {
+ PORT_Free(ptemplate);
+ }
+ }
+ return crv;
+}
+
+
+#define MAX_IDS 10
+/*
+ * update a new database from an old one, now that we have the key
+ */
+static CK_RV
+sftkdb_update(SFTKDBHandle *handle, SECItem *key)
+{
+ SDBFind *find = NULL;
+ CK_ULONG idCount = MAX_IDS;
+ CK_OBJECT_HANDLE ids[MAX_IDS];
+ CK_RV crv, crv2;
+ PRBool inTransaction = PR_FALSE;
+ int i;
+
+ if (handle == NULL) {
+ return CKR_OK;
+ }
+ if (handle->update == NULL) {
+ return CKR_OK;
+ }
+
+ /* find all the objects */
+ crv = sftkdb_FindObjectsInit(handle, NULL, 0, &find);
+
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ while ((crv == CKR_OK) && (idCount == MAX_IDS)) {
+ crv = sftkdb_FindObjects(handle, find, ids, MAX_IDS, &idCount);
+ for (i=0; (crv == CKR_OK) && (i < idCount); i++) {
+ crv = sftkdb_copyObject(handle, ids[i], key);
+ }
+ }
+ crv2 = sftkdb_FindObjectsFinal(handle, find);
+ if (crv == CKR_OK) crv = crv2;
+
+loser:
+ /* update Meta data - even if we didn't update objects */
+ if (handle->type == SFTK_KEYDB_TYPE) {
+ SDBPasswordEntry entry;
+ crv = (*handle->db->sdb_Begin)(handle->db);
+ if (crv != CKR_OK) {
+ goto loser2;
+ }
+ inTransaction = PR_TRUE;
+ crv = (*handle->update->sdb_GetPWEntry)(handle->update, & entry);
+ if (crv != CKR_OK) {
+ goto loser2;
+ }
+ crv = (*handle->db->sdb_PutPWEntry)(handle->db, &entry);
+ if (crv != CKR_OK) {
+ goto loser2;
+ }
+ crv = (*handle->db->sdb_Commit)(handle->db);
+ inTransaction = PR_FALSE;
+ }
+loser2:
+ if (inTransaction) {
+ (*handle->db->sdb_Abort)(handle->db);
+ }
+ if (handle->update) {
+ (*handle->update->sdb_Close)(handle->update);
+ handle->update = NULL;
+ }
+ return crv;
+}
+
+/*
+ * return success if we have a valid password entry.
+ * This is will show up outside of PKCS #11 as CKF_USER_PIN_INIT
+ * in the token flags.
+ */
+SECStatus
+sftkdb_HasPasswordSet(SFTKDBHandle *keydb)
+{
+ SDBPasswordEntry entry;
+ CK_RV crv;
+ SDB *db;
+
+ if (keydb == NULL) {
+ return SECFailure;
+ }
+
+ db = GET_SDB(keydb);
+ if (db == NULL) {
+ return SECFailure;
+ }
+
+ crv = (*db->sdb_GetPWEntry)(db, &entry);
+ return (crv == CKR_OK) ? SECSuccess : SECFailure;
+}
+
+#define SFTK_PW_CHECK_STRING "password-check"
+#define SFTK_PW_CHECK_LEN 14
+
+/*
+ * check if the supplied password is valid
+ */
+SECStatus
+sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw)
+{
+ SECStatus rv;
+ SDBPasswordEntry entry;
+ SECItem key;
+ SECItem *result = NULL;
+ SDB *db;
+ CK_RV crv;
+
+ if (keydb == NULL) {
+ return SECFailure;
+ }
+
+ db = GET_SDB(keydb);
+ if (db == NULL) {
+ return SECFailure;
+ }
+
+ key.data = NULL;
+ key.len = 0;
+
+ if (pw == NULL) pw="";
+
+ /* get the entry from the database */
+ crv = (*db->sdb_GetPWEntry)(db, &entry);
+ if (crv != CKR_OK) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ /* get our intermediate key based on the entry salt value */
+ rv = sftkdb_passwordToKey(keydb, &entry, pw, &key);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ /* decrypt the entry value */
+ rv = sftkdb_decrypt(&key, &entry.value, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ /* if it's what we expect, update our key in the database handle and
+ * return Success */
+ if ((result->len == SFTK_PW_CHECK_LEN) &&
+ PORT_Memcmp(result->data, SFTK_PW_CHECK_STRING, SFTK_PW_CHECK_LEN) == 0){
+ /* load the keys, so the keydb can parse it's key set */
+ sftkdb_switchKeys(keydb, &key);
+ if (keydb->update) {
+ /* update the peer certdb if it exists */
+ if (keydb->peerDB) {
+ sftkdb_update(keydb->peerDB, &key);
+ }
+ sftkdb_update(keydb, &key);
+ }
+ } else {
+ rv = SECFailure;
+ /*PORT_SetError( bad password); */
+ }
+
+loser:
+ if (key.data) {
+ PORT_ZFree(key.data,key.len);
+ }
+ if (result) {
+ SECITEM_FreeItem(result,PR_TRUE);
+ }
+ return rv;
+}
+
+/*
+ * return Success if the there is a cached password key.
+ */
+SECStatus
+sftkdb_PWCached(SFTKDBHandle *keydb)
+{
+ return keydb->passwordKey.data ? SECSuccess : SECFailure;
+}
+
+static SECStatus
+sftk_convertPrivateAttributes(SFTKDBHandle *keydb, CK_OBJECT_HANDLE id,
+ SECItem *newKey)
+{
+ CK_RV crv = CKR_OK;
+ CK_RV crv2;
+ CK_ATTRIBUTE *first, *last;
+ CK_ATTRIBUTE privAttrs[] = {
+ {CKA_VALUE, NULL, 0},
+ {CKA_PRIVATE_EXPONENT, NULL, 0},
+ {CKA_PRIME_1, NULL, 0},
+ {CKA_PRIME_2, NULL, 0},
+ {CKA_EXPONENT_1, NULL, 0},
+ {CKA_EXPONENT_2, NULL, 0},
+ {CKA_COEFFICIENT, NULL, 0} };
+ CK_ULONG privAttrCount = sizeof(privAttrs)/sizeof(CK_ATTRIBUTE);
+ PLArenaPool *arena = NULL;
+ int i, count;
+
+
+ /* get a new arena to simplify cleanup */
+ arena = PORT_NewArena(1024);
+ if (!arena) {
+ return SECFailure;
+ }
+
+ /*
+ * STEP 1. Read the old attributes in the clear.
+ */
+
+ /* Get the attribute sizes.
+ * ignore the error code, we will have unknown attributes here */
+ crv2 = sftkdb_GetAttributeValue(keydb, id, privAttrs, privAttrCount);
+
+ /*
+ * find the valid block of attributes and fill allocate space for
+ * their data */
+ first = last = NULL;
+ for (i=0; i < privAttrCount; i++) {
+ /* find the block of attributes that are appropriate for this
+ * objects. There should only be once contiguous block, if not
+ * there's an error.
+ *
+ * find the first and last good entry.
+ */
+ if ((privAttrs[i].ulValueLen == -1) || (privAttrs[i].ulValueLen == 0)){
+ if (!first) continue;
+ if (!last) {
+ /* previous entry was last good entry */
+ last= &privAttrs[i-1];
+ }
+ continue;
+ }
+ if (!first) {
+ first = &privAttrs[i];
+ }
+ if (last) {
+ /* OOPS, we've found another good entry beyond the end of the
+ * last good entry, we need to fail here. */
+ crv = CKR_GENERAL_ERROR;
+ break;
+ }
+ privAttrs[i].pValue = PORT_ArenaAlloc(arena,privAttrs[i].ulValueLen);
+ if (privAttrs[i].pValue == NULL) {
+ crv = CKR_HOST_MEMORY;
+ break;
+ }
+ }
+ if (first == NULL) {
+ /* no valid entries found, return error based on crv2 */
+ /* set error */
+ goto loser;
+ }
+ if (last == NULL) {
+ last = &privAttrs[privAttrCount-1];
+ }
+ if (crv != CKR_OK) {
+ /* set error */
+ goto loser;
+ }
+ /* read the attributes */
+ count = (last-first)+1;
+ crv = sftkdb_GetAttributeValue(keydb, id, first, count);
+ if (crv != CKR_OK) {
+ /* set error */
+ goto loser;
+ }
+
+
+ /*
+ * STEP 2: read the encrypt the attributes with the new key.
+ */
+ for (i=0; i < count; i++) {
+ SECItem plainText;
+ SECItem *result;
+ SECStatus rv;
+
+ plainText.data = first[i].pValue;
+ plainText.len = first[i].ulValueLen;
+ rv = sftkdb_encrypt(arena, newKey, &plainText, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ first[i].pValue = result->data;
+ first[i].ulValueLen = result->len;
+ /* clear our sensitive data out */
+ PORT_Memset(plainText.data, 0, plainText.len);
+ }
+
+
+ /*
+ * STEP 3: write the newly encrypted attributes out directly
+ */
+ id &= SFTK_OBJ_ID_MASK;
+ keydb->newKey = newKey;
+ crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, id, first, count);
+ keydb->newKey = NULL;
+ if (crv != CKR_OK) {
+ /* set error */
+ goto loser;
+ }
+
+ /* free up our mess */
+ /* NOTE: at this point we know we've cleared out any unencrypted data */
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECSuccess;
+
+loser:
+ /* there may be unencrypted data, clear it out down */
+ PORT_FreeArena(arena, PR_TRUE);
+ return SECFailure;
+}
+
+
+/*
+ * must be called with the old key active.
+ */
+SECStatus
+sftkdb_convertPrivateObjects(SFTKDBHandle *keydb, SECItem *newKey)
+{
+ SDBFind *find = NULL;
+ CK_ULONG idCount = MAX_IDS;
+ CK_OBJECT_HANDLE ids[MAX_IDS];
+ CK_RV crv, crv2;
+ int i;
+
+ /* find all the private objects */
+ crv = sftkdb_FindObjectsInit(keydb, NULL, 0, &find);
+
+ if (crv != CKR_OK) {
+ /* set error */
+ return SECFailure;
+ }
+ while ((crv == CKR_OK) && (idCount == MAX_IDS)) {
+ crv = sftkdb_FindObjects(keydb, find, ids, MAX_IDS, &idCount);
+ for (i=0; (crv == CKR_OK) && (i < idCount); i++) {
+ SECStatus rv;
+ rv = sftk_convertPrivateAttributes(keydb, ids[i], newKey);
+ if (rv != SECSuccess) {
+ crv = CKR_GENERAL_ERROR;
+ /* error should be already set here */
+ }
+ }
+ }
+ crv2 = sftkdb_FindObjectsFinal(keydb, find);
+ if (crv == CKR_OK) crv = crv2;
+ if (crv != CKR_OK) {
+ /* set error */
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+
+/*
+ * change the database password.
+ */
+SECStatus
+sftkdb_ChangePassword(SFTKDBHandle *keydb, char *oldPin, char *newPin)
+{
+ SECStatus rv = SECSuccess;
+ SECItem plainText;
+ SECItem newKey;
+ SECItem *result = NULL;
+ SDBPasswordEntry entry;
+ CK_RV crv;
+ SDB *db;
+
+ if (keydb == NULL) {
+ return SECFailure;
+ }
+
+ db = GET_SDB(keydb);
+ if (db == NULL) {
+ return SECFailure;
+ }
+
+ newKey.data = NULL;
+
+ /* make sure we have a valid old pin */
+ crv = (*keydb->db->sdb_Begin)(keydb->db);
+ if (crv != CKR_OK) {
+ rv = SECFailure;
+ goto loser;
+ }
+ crv = (*db->sdb_GetPWEntry)(db, &entry);
+ if (crv == CKR_OK) {
+ rv = sftkdb_CheckPassword(keydb, oldPin);
+ if (rv == SECFailure) {
+ goto loser;
+ }
+ } else {
+ entry.salt.data = entry.data;
+ entry.salt.len = SALT_LENGTH;
+ RNG_GenerateGlobalRandomBytes(entry.data,entry.salt.len);
+ }
+
+ rv = sftkdb_passwordToKey(keydb, &entry, newPin, &newKey);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+
+ /*
+ * convert encrypted entries here.
+ */
+ rv = sftkdb_convertPrivateObjects(keydb, &newKey);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+
+ plainText.data = (unsigned char *)SFTK_PW_CHECK_STRING;
+ plainText.len = SFTK_PW_CHECK_LEN;
+
+ rv = sftkdb_encrypt(NULL, &newKey, &plainText, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ entry.value.data = result->data;
+ entry.value.len = result->len;
+ crv = (*keydb->db->sdb_PutPWEntry)(keydb->db, &entry);
+ if (crv != CKR_OK) {
+ rv = SECFailure;
+ goto loser;
+ }
+ crv = (*keydb->db->sdb_Commit)(keydb->db);
+ if (crv != CKR_OK) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ keydb->newKey = NULL;
+
+ sftkdb_switchKeys(keydb, &newKey);
+
+loser:
+ if (newKey.data) {
+ PORT_ZFree(newKey.data,newKey.len);
+ }
+ if (result) {
+ SECITEM_FreeItem(result, PR_FALSE);
+ }
+ if (rv != SECSuccess) {
+ (*keydb->db->sdb_Abort)(keydb->db);
+ }
+
+ return rv;
+}
+
+/*
+ * loose our cached password
+ */
+SECStatus
+sftkdb_ClearPassword(SFTKDBHandle *keydb)
+{
+ SECItem oldKey;
+ oldKey.data = NULL;
+ oldKey.len = 0;
+ sftkdb_switchKeys(keydb, &oldKey);
+ if (oldKey.data) {
+ PORT_ZFree(oldKey.data, oldKey.len);
+ }
+ return SECSuccess;
+}
+
+/******************************************************************
+ * DB handle managing functions.
+ *
+ * These functions are called by softoken to initialize, acquire,
+ * and release database handles.
+ */
+
+/* release a database handle */
+void
+sftk_freeDB(SFTKDBHandle *handle)
+{
+ PRInt32 ref;
+
+ if (!handle) return;
+ ref = PR_AtomicDecrement(&handle->ref);
+ if (ref == 0) {
+ sftkdb_CloseDB(handle);
+ }
+ return;
+}
+
+
+/*
+ * acquire a database handle for a certificate db
+ * (database for public objects)
+ */
+SFTKDBHandle *
+sftk_getCertDB(SFTKSlot *slot)
+{
+ SFTKDBHandle *dbHandle;
+
+ PZ_Lock(slot->slotLock);
+ dbHandle = slot->certDB;
+ if (dbHandle) {
+ PR_AtomicIncrement(&dbHandle->ref);
+ }
+ PZ_Unlock(slot->slotLock);
+ return dbHandle;
+}
+
+/*
+ * acquire a database handle for a key database
+ * (database for private objects)
+ */
+SFTKDBHandle *
+sftk_getKeyDB(SFTKSlot *slot)
+{
+ SFTKDBHandle *dbHandle;
+
+ PZ_Lock(slot->slotLock);
+ dbHandle = slot->keyDB;
+ if (dbHandle) {
+ PR_AtomicIncrement(&dbHandle->ref);
+ }
+ PZ_Unlock(slot->slotLock);
+ return dbHandle;
+}
+
+/*
+ * acquire the database for a specific object. NOTE: objectID must point
+ * to a Token object!
+ */
+SFTKDBHandle *
+sftk_getDBForTokenObject(SFTKSlot *slot, CK_OBJECT_HANDLE objectID)
+{
+ SFTKDBHandle *dbHandle;
+
+ PZ_Lock(slot->slotLock);
+ dbHandle = objectID & SFTK_KEYDB_TYPE ? slot->keyDB : slot->certDB;
+ if (dbHandle) {
+ PR_AtomicIncrement(&dbHandle->ref);
+ }
+ PZ_Unlock(slot->slotLock);
+ return dbHandle;
+}
+
+/*
+ * initialize a new database handle
+ */
+static SFTKDBHandle *
+sftk_NewDBHandle(SDB *sdb, int type)
+{
+ SFTKDBHandle *handle = PORT_New(SFTKDBHandle);
+ handle->ref = 1;
+ handle->db = sdb;
+ handle->update = NULL;
+ handle->peerDB = NULL;
+ handle->newKey = NULL;
+ handle->type = type;
+ handle->passwordKey.data = NULL;
+ handle->passwordKey.len = 0;
+ handle->passwordLock = NULL;
+ if (type == SFTK_KEYDB_TYPE) {
+ handle->passwordLock = PZ_NewLock();
+ }
+ sdb->app_private = handle;
+ return handle;
+}
+
+/*
+ * reset the key database to it's uninitialized state. This call
+ * will clear all the key entried.
+ */
+SECStatus
+sftkdb_ResetKeyDB(SFTKDBHandle *handle)
+{
+ CK_RV crv;
+
+ /* only rest the key db */
+ if (handle->type != SFTK_KEYDB_TYPE) {
+ return SECFailure;
+ }
+ crv = sftkdb_ResetDB(handle);
+ if (crv != CKR_OK) {
+ /* set error */
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+static PRBool
+sftk_oldVersionExists(const char *dir, int version)
+{
+ int i;
+ PRStatus exists = PR_FAILURE;
+ char *file = NULL;
+
+ for (i=version; i > 1 ; i--) {
+ file = PR_smprintf("%s%d.db",dir,i);
+ if (file == NULL) {
+ continue;
+ }
+ exists = PR_Access(file, PR_ACCESS_EXISTS);
+ PR_smprintf_free(file);
+ if (exists == PR_SUCCESS) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+static PRBool
+sftk_hasLegacyDB(const char *confdir, const char *certPrefix,
+ const char *keyPrefix, int certVersion, int keyVersion)
+{
+ char *dir;
+ PRBool exists;
+
+ dir= PR_smprintf("%s/%scert", confdir, certPrefix);
+ if (dir == NULL) {
+ return PR_FALSE;
+ }
+
+ exists = sftk_oldVersionExists(dir, certVersion);
+ PR_smprintf_free(dir);
+ if (exists) {
+ return PR_TRUE;
+ }
+
+ dir= PR_smprintf("%s/%skey", confdir, keyPrefix);
+ if (dir == NULL) {
+ return PR_FALSE;
+ }
+
+ exists = sftk_oldVersionExists(dir, keyVersion);
+ PR_smprintf_free(dir);
+ return exists;
+}
+
+/*
+ * initialize certificate and key database handles as a pair.
+ *
+ * This function figures out what type of database we are opening and
+ * calls the appropriate low level function to open the database.
+ * It also figures out whether or not to setup up automatic update.
+ */
+CK_RV
+sftk_DBInit(const char *configdir, const char *certPrefix,
+ const char *keyPrefix, PRBool readOnly, PRBool noCertDB,
+ PRBool noKeyDB, PRBool forceOpen,
+ SFTKDBHandle **certDB, SFTKDBHandle **keyDB)
+{
+ const char *confdir;
+ SDBType dbType;
+ char *appName = NULL;
+ SDB *keySDB, *certSDB;
+ CK_RV crv = CKR_OK;
+ int flags = SDB_RDONLY;
+ PRBool newInit = PR_FALSE;
+ PRBool needUpdate = PR_FALSE;
+
+ if (!readOnly) {
+ flags = SDB_CREATE;
+ }
+
+ *certDB = NULL;
+ *keyDB = NULL;
+
+ if (noKeyDB && noCertDB) {
+ return CKR_OK;
+ }
+ confdir = sftk_EvaluateConfigDir(configdir, &dbType, &appName);
+
+ /*
+ * now initialize the appropriate database
+ */
+ switch (dbType) {
+ case SDB_LEGACY:
+ crv = sftkdbCall_open(confdir, certPrefix, keyPrefix, 8, 3, flags,
+ noCertDB? NULL : &certSDB, noKeyDB ? NULL: &keySDB);
+ break;
+ case SDB_MULTIACCESS:
+ crv = sftkdbCall_open(configdir, certPrefix, keyPrefix, 8, 3, flags,
+ noCertDB? NULL : &certSDB, noKeyDB ? NULL: &keySDB);
+ break;
+ case SDB_SQL:
+ case SDB_EXTERN: /* SHOULD open a loadable db */
+ crv = s_open(confdir, certPrefix, keyPrefix, 9, 4, flags,
+ noCertDB? NULL : &certSDB, noKeyDB ? NULL : &keySDB, &newInit);
+
+ /*
+ * if we failed to open the DB's read only, use the old ones if
+ * the exists.
+ */
+ if (crv != CKR_OK && (flags == SDB_RDONLY)) {
+ if (sftk_hasLegacyDB(confdir, certPrefix, keyPrefix, 8, 3)) {
+ /* we have legacy databases, if we failed to open the new format
+ * DB's read only, just use the legacy ones */
+ crv = sftkdbCall_open(confdir, certPrefix,
+ keyPrefix, 8, 3, flags, noCertDB? NULL : &certSDB,
+ noKeyDB ? NULL : &keySDB);
+ }
+ } else if (newInit && crv == CKR_OK) {
+ /* if the new format DB was also a newly created DB, and we
+ * succeeded, then need to update that new database with data
+ * from the existing legacy DB */
+ if (sftk_hasLegacyDB(confdir, certPrefix, keyPrefix, 8, 3)) {
+ needUpdate = 1;
+ }
+ }
+ break;
+ default:
+ crv = CKR_GENERAL_ERROR; /* can't happen, EvaluationConfigDir MUST
+ * return one of the types we already
+ * specified. */
+ }
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ if (!noCertDB) {
+ *certDB = sftk_NewDBHandle(certSDB, SFTK_CERTDB_TYPE);
+ } else {
+ *certDB = NULL;
+ }
+ if (!noKeyDB) {
+ *keyDB = sftk_NewDBHandle(keySDB, SFTK_KEYDB_TYPE);
+ } else {
+ *keyDB = NULL;
+ }
+
+ /* link them together */
+ if (*certDB) {
+ (*certDB)->peerDB = *keyDB;
+ }
+ if (*keyDB) {
+ (*keyDB)->peerDB = *certDB;
+ }
+
+ if (needUpdate) {
+ SDB *updateCert = NULL;
+ SDB *updateKey = NULL;
+ CK_RV crv2;
+
+ crv2 = sftkdbCall_open(confdir, certPrefix, keyPrefix, 8, 3, flags,
+ noCertDB ? NULL : &updateCert, noKeyDB ? NULL : &updateKey);
+ if (crv2 == CKR_OK) {
+ if (*certDB) {
+ (*certDB)->update = updateCert;
+ updateCert->app_private = (*certDB);
+ }
+ if (*keyDB) {
+ (*keyDB)->update = updateKey;
+ updateKey->app_private = (*keyDB);
+ } else {
+ /* we don't have a key DB, update the certificate DB now */
+ sftkdb_update(*certDB, NULL);
+ }
+ }
+ }
+loser:
+ if (appName) {
+ PORT_Free(appName);
+ }
+ return forceOpen ? CKR_OK : crv;
+}
+
+CK_RV
+sftkdb_Shutdown(void)
+{
+ s_shutdown();
+ sftkdbCall_Shutdown();
+ return CKR_OK;
+}
+
diff --git a/security/nss/lib/softoken/sftkdb.h b/security/nss/lib/softoken/sftkdb.h
new file mode 100644
index 000000000..0491c3e68
--- /dev/null
+++ b/security/nss/lib/softoken/sftkdb.h
@@ -0,0 +1,90 @@
+/*
+ * license
+ */
+
+#include "sftkdbt.h"
+#include "sdb.h"
+#include "pkcs11i.h"
+#include "pkcs11t.h"
+
+/* raw database stuff */
+CK_RV sftkdb_write(SFTKDBHandle *handle, SFTKObject *,CK_OBJECT_HANDLE *);
+CK_RV sftkdb_FindObjectsInit(SFTKDBHandle *sdb, const CK_ATTRIBUTE *template,
+ CK_ULONG count, SDBFind **find);
+CK_RV sftkdb_FindObjects(SFTKDBHandle *sdb, SDBFind *find,
+ CK_OBJECT_HANDLE *ids, int arraySize, CK_ULONG *count);
+CK_RV sftkdb_FindObjectsFinal(SFTKDBHandle *sdb, SDBFind *find);
+CK_RV sftkdb_GetAttributeValue(SFTKDBHandle *handle,
+ CK_OBJECT_HANDLE object_id, CK_ATTRIBUTE *template, CK_ULONG count);
+CK_RV sftkdb_SetAttributeValue(SFTKDBHandle *handle,
+ CK_OBJECT_HANDLE object_id, const CK_ATTRIBUTE *template,
+ CK_ULONG count);
+CK_RV sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id);
+CK_RV sftkdb_closeDB(SFTKDBHandle *handle);
+
+
+/* secmod.db functions */
+char ** sftkdb_ReadSecmodDB(SDBType dbType, const char *appName,
+ const char *filename, const char *dbname,
+ char *params, PRBool rw);
+SECStatus sftkdb_ReleaseSecmodDBData(SDBType dbType, const char *appName,
+ const char *filename, const char *dbname,
+ char **moduleSpecList, PRBool rw);
+SECStatus sftkdb_DeleteSecmodDB(SDBType dbType, const char *appName,
+ const char *filename, const char *dbname,
+ char *args, PRBool rw);
+SECStatus sftkdb_AddSecmodDB(SDBType dbType, const char *appName,
+ const char *filename, const char *dbname,
+ char *module, PRBool rw);
+
+/* keydb functions */
+
+SECStatus sftkdb_PWIsInitialized(SFTKDBHandle *keydb);
+SECStatus sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw);
+SECStatus sftkdb_PWCached(SFTKDBHandle *keydb);
+SECStatus sftkdb_HasPasswordSet(SFTKDBHandle *keydb);
+SECStatus sftkdb_ResetKeyDB(SFTKDBHandle *keydb);
+SECStatus sftkdb_ChangePassword(SFTKDBHandle *keydb, char *oldPin, char *newPin);
+SECStatus sftkdb_ClearPassword(SFTKDBHandle *keydb);
+
+/* Utility functions */
+/*
+ * OK there are now lots of options here, lets go through them all:
+ *
+ * configdir - base directory where all the cert, key, and module datbases live.
+ * certPrefix - prefix added to the beginning of the cert database example: "
+ * "https-server1-"
+ * keyPrefix - prefix added to the beginning of the key database example: "
+ * "https-server1-"
+ * secmodName - name of the security module database (usually "secmod.db").
+ * readOnly - Boolean: true if the databases are to be openned read only.
+ * nocertdb - Don't open the cert DB and key DB's, just initialize the
+ * Volatile certdb.
+ * nomoddb - Don't open the security module DB, just initialize the
+ * PKCS #11 module.
+ * forceOpen - Continue to force initializations even if the databases cannot
+ * be opened.
+ */
+CK_RV sftk_DBInit(const char *configdir, const char *certPrefix,
+ const char *keyPrefix, PRBool readOnly, PRBool noCertDB,
+ PRBool noKeyDB, PRBool forceOpen,
+ SFTKDBHandle **certDB, SFTKDBHandle **keyDB);
+CK_RV sftkdb_Shutdown(void);
+
+SFTKDBHandle *sftk_getCertDB(SFTKSlot *slot);
+SFTKDBHandle *sftk_getKeyDB(SFTKSlot *slot);
+SFTKDBHandle *sftk_getDBForTokenObject(SFTKSlot *slot,
+ CK_OBJECT_HANDLE objectID);
+void sftk_freeDB(SFTKDBHandle *certHandle);
+
+/*
+ * for lgglue, stubs to encrypt and decrypt password entries
+ */
+SECStatus sftkdb_encrypt_stub(PRArenaPool *arena, SDB *sdb, SECItem *plainText,
+ SECItem **cipherText);
+SECStatus sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText,
+ SECItem **plainText);
+
+
+
+
diff --git a/security/nss/lib/softoken/sftkdbt.h b/security/nss/lib/softoken/sftkdbt.h
new file mode 100644
index 000000000..f9d7c9eaa
--- /dev/null
+++ b/security/nss/lib/softoken/sftkdbt.h
@@ -0,0 +1,17 @@
+/*
+ * license
+ */
+
+
+#ifndef SFTKDBT_H
+#define SFTKDBT_H 1
+typedef struct SFTKDBHandleStr SFTKDBHandle;
+
+typedef enum {
+ SDB_SQL,
+ SDB_EXTERN,
+ SDB_LEGACY,
+ SDB_MULTIACCESS
+} SDBType;
+
+#endif
diff --git a/security/nss/lib/softoken/sftkpars.c b/security/nss/lib/softoken/sftkpars.c
new file mode 100644
index 000000000..96189937e
--- /dev/null
+++ b/security/nss/lib/softoken/sftkpars.c
@@ -0,0 +1,616 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * The following code handles the storage of PKCS 11 modules used by the
+ * NSS. This file is written to abstract away how the modules are
+ * stored so we can deside that later.
+ */
+#include "sftkpars.h"
+#include "pkcs11i.h"
+#include "sdb.h"
+#include "prprf.h"
+#include "prenv.h"
+
+/*
+ * this file contains routines for parsing PKCS #11 module spec
+ * strings.
+ */
+
+#define SFTK_HANDLE_STRING_ARG(param,target,value,command) \
+ if (PORT_Strncasecmp(param,value,sizeof(value)-1) == 0) { \
+ param += sizeof(value)-1; \
+ target = sftk_argFetchValue(param,&next); \
+ param += next; \
+ command ;\
+ } else
+
+#define SFTK_HANDLE_FINAL_ARG(param) \
+ { param = sftk_argSkipParameter(param); } param = sftk_argStrip(param);
+
+static PRBool sftk_argGetPair(char c) {
+ switch (c) {
+ case '\'': return c;
+ case '\"': return c;
+ case '<': return '>';
+ case '{': return '}';
+ case '[': return ']';
+ case '(': return ')';
+ default: break;
+ }
+ return ' ';
+}
+
+static PRBool sftk_argIsBlank(char c) {
+ return isspace(c);
+}
+
+static PRBool sftk_argIsEscape(char c) {
+ return c == '\\';
+}
+
+static PRBool sftk_argIsQuote(char c) {
+ switch (c) {
+ case '\'':
+ case '\"':
+ case '<':
+ case '{': /* } end curly to keep vi bracket matching working */
+ case '(': /* ) */
+ case '[': /* ] */ return PR_TRUE;
+ default: break;
+ }
+ return PR_FALSE;
+}
+
+char *sftk_argStrip(char *c) {
+ while (*c && sftk_argIsBlank(*c)) c++;
+ return c;
+}
+
+static char *
+sftk_argFindEnd(char *string) {
+ char endChar = ' ';
+ PRBool lastEscape = PR_FALSE;
+
+ if (sftk_argIsQuote(*string)) {
+ endChar = sftk_argGetPair(*string);
+ string++;
+ }
+
+ for (;*string; string++) {
+ if (lastEscape) {
+ lastEscape = PR_FALSE;
+ continue;
+ }
+ if (sftk_argIsEscape(*string) && !lastEscape) {
+ lastEscape = PR_TRUE;
+ continue;
+ }
+ if ((endChar == ' ') && sftk_argIsBlank(*string)) break;
+ if (*string == endChar) {
+ break;
+ }
+ }
+
+ return string;
+}
+
+char *
+sftk_argFetchValue(char *string, int *pcount)
+{
+ char *end = sftk_argFindEnd(string);
+ char *retString, *copyString;
+ PRBool lastEscape = PR_FALSE;
+ int len;
+
+ len = end - string;
+ if (len == 0) {
+ *pcount = 0;
+ return NULL;
+ }
+
+ copyString = retString = (char *)PORT_Alloc(len+1);
+
+ if (*end) len++;
+ *pcount = len;
+ if (retString == NULL) return NULL;
+
+
+ if (sftk_argIsQuote(*string)) string++;
+ for (; string < end; string++) {
+ if (sftk_argIsEscape(*string) && !lastEscape) {
+ lastEscape = PR_TRUE;
+ continue;
+ }
+ lastEscape = PR_FALSE;
+ *copyString++ = *string;
+ }
+ *copyString = 0;
+ return retString;
+}
+
+static char *
+sftk_argSkipParameter(char *string)
+{
+ char *end;
+ /* look for the end of the <name>= */
+ for (;*string; string++) {
+ if (*string == '=') { string++; break; }
+ if (sftk_argIsBlank(*string)) return(string);
+ }
+
+ end = sftk_argFindEnd(string);
+ if (*end) end++;
+ return end;
+}
+
+char *
+sftk_argGetParamValue(char *paramName,char *parameters)
+{
+ char searchValue[256];
+ int paramLen = strlen(paramName);
+ char *returnValue = NULL;
+ int next;
+
+ if ((parameters == NULL) || (*parameters == 0)) return NULL;
+
+ PORT_Assert(paramLen+2 < sizeof(searchValue));
+
+ PORT_Strcpy(searchValue,paramName);
+ PORT_Strcat(searchValue,"=");
+ while (*parameters) {
+ if (PORT_Strncasecmp(parameters,searchValue,paramLen+1) == 0) {
+ parameters += paramLen+1;
+ returnValue = sftk_argFetchValue(parameters,&next);
+ break;
+ } else {
+ parameters = sftk_argSkipParameter(parameters);
+ }
+ parameters = sftk_argStrip(parameters);
+ }
+ return returnValue;
+}
+
+static char *
+sftk_argNextFlag(char *flags)
+{
+ for (; *flags ; flags++) {
+ if (*flags == ',') {
+ flags++;
+ break;
+ }
+ }
+ return flags;
+}
+
+static PRBool
+sftk_argHasFlag(char *label, char *flag, char *parameters)
+{
+ char *flags,*index;
+ int len = strlen(flag);
+ PRBool found = PR_FALSE;
+
+ flags = sftk_argGetParamValue(label,parameters);
+ if (flags == NULL) return PR_FALSE;
+
+ for (index=flags; *index; index=sftk_argNextFlag(index)) {
+ if (PORT_Strncasecmp(index,flag,len) == 0) {
+ found=PR_TRUE;
+ break;
+ }
+ }
+ PORT_Free(flags);
+ return found;
+}
+
+/*
+ * decode a number. handle octal (leading '0'), hex (leading '0x') or decimal
+ */
+static long
+sftk_argDecodeNumber(char *num)
+{
+ int radix = 10;
+ unsigned long value = 0;
+ long retValue = 0;
+ int sign = 1;
+ int digit;
+
+ if (num == NULL) return retValue;
+
+ num = sftk_argStrip(num);
+
+ if (*num == '-') {
+ sign = -1;
+ num++;
+ }
+
+ if (*num == '0') {
+ radix = 8;
+ num++;
+ if ((*num == 'x') || (*num == 'X')) {
+ radix = 16;
+ num++;
+ }
+ }
+
+
+ for ( ;*num; num++ ) {
+ if (isdigit(*num)) {
+ digit = *num - '0';
+ } else if ((*num >= 'a') && (*num <= 'f')) {
+ digit = *num - 'a' + 10;
+ } else if ((*num >= 'A') && (*num <= 'F')) {
+ digit = *num - 'A' + 10;
+ } else {
+ break;
+ }
+ if (digit >= radix) break;
+ value = value*radix + digit;
+ }
+
+ retValue = ((int) value) * sign;
+ return retValue;
+}
+
+static char *
+sftk_argGetName(char *inString, int *next)
+{
+ char *name=NULL;
+ char *string;
+ int len;
+
+ /* look for the end of the <name>= */
+ for (string = inString;*string; string++) {
+ if (*string == '=') { break; }
+ if (sftk_argIsBlank(*string)) break;
+ }
+
+ len = string - inString;
+
+ *next = len;
+ if (*string == '=') (*next) += 1;
+ if (len > 0) {
+ name = PORT_Alloc(len+1);
+ PORT_Strncpy(name,inString,len);
+ name[len] = 0;
+ }
+ return name;
+}
+
+#define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
+
+static void
+sftk_parseTokenFlags(char *tmp, sftk_token_parameters *parsed) {
+ parsed->readOnly = sftk_argHasFlag("flags","readOnly",tmp);
+ parsed->noCertDB = sftk_argHasFlag("flags","noCertDB",tmp);
+ parsed->noKeyDB = sftk_argHasFlag("flags","noKeyDB",tmp);
+ parsed->forceOpen = sftk_argHasFlag("flags","forceOpen",tmp);
+ parsed->pwRequired = sftk_argHasFlag("flags","passwordRequired",tmp);
+ parsed->optimizeSpace = sftk_argHasFlag("flags","optimizeSpace",tmp);
+ return;
+}
+
+static void
+sftk_parseFlags(char *tmp, sftk_parameters *parsed) {
+ parsed->noModDB = sftk_argHasFlag("flags","noModDB",tmp);
+ parsed->readOnly = sftk_argHasFlag("flags","readOnly",tmp);
+ /* keep legacy interface working */
+ parsed->noCertDB = sftk_argHasFlag("flags","noCertDB",tmp);
+ parsed->forceOpen = sftk_argHasFlag("flags","forceOpen",tmp);
+ parsed->pwRequired = sftk_argHasFlag("flags","passwordRequired",tmp);
+ parsed->optimizeSpace = sftk_argHasFlag("flags","optimizeSpace",tmp);
+ return;
+}
+
+static CK_RV
+sftk_parseTokenParameters(char *param, sftk_token_parameters *parsed)
+{
+ int next;
+ char *tmp;
+ char *index;
+ index = sftk_argStrip(param);
+
+ while (*index) {
+ SFTK_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
+ SFTK_HANDLE_STRING_ARG(index,parsed->certPrefix,"certPrefix=",;)
+ SFTK_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyPrefix=",;)
+ SFTK_HANDLE_STRING_ARG(index,parsed->tokdes,"tokenDescription=",;)
+ SFTK_HANDLE_STRING_ARG(index,parsed->slotdes,"slotDescription=",;)
+ SFTK_HANDLE_STRING_ARG(index,tmp,"minPWLen=",
+ if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); })
+ SFTK_HANDLE_STRING_ARG(index,tmp,"flags=",
+ if(tmp) { sftk_parseTokenFlags(param,parsed); PORT_Free(tmp); })
+ SFTK_HANDLE_FINAL_ARG(index)
+ }
+ return CKR_OK;
+}
+
+static void
+sftk_parseTokens(char *tokenParams, sftk_parameters *parsed)
+{
+ char *tokenIndex;
+ sftk_token_parameters *tokens = NULL;
+ int i=0,count = 0,next;
+
+ if ((tokenParams == NULL) || (*tokenParams == 0)) return;
+
+ /* first count the number of slots */
+ for (tokenIndex = sftk_argStrip(tokenParams); *tokenIndex;
+ tokenIndex = sftk_argStrip(sftk_argSkipParameter(tokenIndex))) {
+ count++;
+ }
+
+ /* get the data structures */
+ tokens = (sftk_token_parameters *)
+ PORT_ZAlloc(count*sizeof(sftk_token_parameters));
+ if (tokens == NULL) return;
+
+ for (tokenIndex = sftk_argStrip(tokenParams), i = 0;
+ *tokenIndex && i < count ; i++ ) {
+ char *name;
+ name = sftk_argGetName(tokenIndex,&next);
+ tokenIndex += next;
+
+ tokens[i].slotID = sftk_argDecodeNumber(name);
+ tokens[i].readOnly = PR_FALSE;
+ tokens[i].noCertDB = PR_FALSE;
+ tokens[i].noKeyDB = PR_FALSE;
+ if (!sftk_argIsBlank(*tokenIndex)) {
+ char *args = sftk_argFetchValue(tokenIndex,&next);
+ tokenIndex += next;
+ if (args) {
+ sftk_parseTokenParameters(args,&tokens[i]);
+ PORT_Free(args);
+ }
+ }
+ if (name) PORT_Free(name);
+ tokenIndex = sftk_argStrip(tokenIndex);
+ }
+ parsed->token_count = i;
+ parsed->tokens = tokens;
+ return;
+}
+
+CK_RV
+sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS)
+{
+ int next;
+ char *tmp;
+ char *index;
+ char *certPrefix = NULL, *keyPrefix = NULL;
+ char *tokdes = NULL, *ptokdes = NULL;
+ char *slotdes = NULL, *pslotdes = NULL;
+ char *fslotdes = NULL, *fpslotdes = NULL;
+ char *minPW = NULL;
+ index = sftk_argStrip(param);
+
+ PORT_Memset(parsed, 0, sizeof(sftk_parameters));
+
+ while (*index) {
+ SFTK_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
+ SFTK_HANDLE_STRING_ARG(index,parsed->secmodName,"secmod=",;)
+ SFTK_HANDLE_STRING_ARG(index,parsed->man,"manufacturerID=",;)
+ SFTK_HANDLE_STRING_ARG(index,parsed->libdes,"libraryDescription=",;)
+ /* constructed values, used so legacy interfaces still work */
+ SFTK_HANDLE_STRING_ARG(index,certPrefix,"certPrefix=",;)
+ SFTK_HANDLE_STRING_ARG(index,keyPrefix,"keyPrefix=",;)
+ SFTK_HANDLE_STRING_ARG(index,tokdes,"cryptoTokenDescription=",;)
+ SFTK_HANDLE_STRING_ARG(index,ptokdes,"dbTokenDescription=",;)
+ SFTK_HANDLE_STRING_ARG(index,slotdes,"cryptoSlotDescription=",;)
+ SFTK_HANDLE_STRING_ARG(index,pslotdes,"dbSlotDescription=",;)
+ SFTK_HANDLE_STRING_ARG(index,fslotdes,"FIPSSlotDescription=",;)
+ SFTK_HANDLE_STRING_ARG(index,fpslotdes,"FIPSTokenDescription=",;)
+ SFTK_HANDLE_STRING_ARG(index,minPW,"minPWLen=",;)
+
+ SFTK_HANDLE_STRING_ARG(index,tmp,"flags=",
+ if(tmp) { sftk_parseFlags(param,parsed); PORT_Free(tmp); })
+ SFTK_HANDLE_STRING_ARG(index,tmp,"tokens=",
+ if(tmp) { sftk_parseTokens(tmp,parsed); PORT_Free(tmp); })
+ SFTK_HANDLE_FINAL_ARG(index)
+ }
+ if (parsed->tokens == NULL) {
+ int count = isFIPS ? 1 : 2;
+ int index = count-1;
+ sftk_token_parameters *tokens = NULL;
+
+ tokens = (sftk_token_parameters *)
+ PORT_ZAlloc(count*sizeof(sftk_token_parameters));
+ if (tokens == NULL) {
+ goto loser;
+ }
+ parsed->tokens = tokens;
+ parsed->token_count = count;
+ tokens[index].slotID = isFIPS ? FIPS_SLOT_ID : PRIVATE_KEY_SLOT_ID;
+ tokens[index].certPrefix = certPrefix;
+ tokens[index].keyPrefix = keyPrefix;
+ tokens[index].minPW = minPW ? atoi(minPW) : 0;
+ tokens[index].readOnly = parsed->readOnly;
+ tokens[index].noCertDB = parsed->noCertDB;
+ tokens[index].noKeyDB = parsed->noCertDB;
+ tokens[index].forceOpen = parsed->forceOpen;
+ tokens[index].pwRequired = parsed->pwRequired;
+ tokens[index].optimizeSpace = parsed->optimizeSpace;
+ tokens[0].optimizeSpace = parsed->optimizeSpace;
+ certPrefix = NULL;
+ keyPrefix = NULL;
+ if (isFIPS) {
+ tokens[index].tokdes = fslotdes;
+ tokens[index].slotdes = fpslotdes;
+ fslotdes = NULL;
+ fpslotdes = NULL;
+ } else {
+ tokens[index].tokdes = ptokdes;
+ tokens[index].slotdes = pslotdes;
+ tokens[0].slotID = NETSCAPE_SLOT_ID;
+ tokens[0].tokdes = tokdes;
+ tokens[0].slotdes = slotdes;
+ tokens[0].noCertDB = PR_TRUE;
+ tokens[0].noKeyDB = PR_TRUE;
+ ptokdes = NULL;
+ pslotdes = NULL;
+ tokdes = NULL;
+ slotdes = NULL;
+ }
+ }
+
+loser:
+ FREE_CLEAR(certPrefix);
+ FREE_CLEAR(keyPrefix);
+ FREE_CLEAR(tokdes);
+ FREE_CLEAR(ptokdes);
+ FREE_CLEAR(slotdes);
+ FREE_CLEAR(pslotdes);
+ FREE_CLEAR(fslotdes);
+ FREE_CLEAR(fpslotdes);
+ FREE_CLEAR(minPW);
+ return CKR_OK;
+}
+
+void
+sftk_freeParams(sftk_parameters *params)
+{
+ int i;
+
+ for (i=0; i < params->token_count; i++) {
+ FREE_CLEAR(params->tokens[i].configdir);
+ FREE_CLEAR(params->tokens[i].certPrefix);
+ FREE_CLEAR(params->tokens[i].keyPrefix);
+ FREE_CLEAR(params->tokens[i].tokdes);
+ FREE_CLEAR(params->tokens[i].slotdes);
+ }
+
+ FREE_CLEAR(params->configdir);
+ FREE_CLEAR(params->secmodName);
+ FREE_CLEAR(params->man);
+ FREE_CLEAR(params->libdes);
+ FREE_CLEAR(params->tokens);
+}
+
+#define SQLDB "sql:"
+#define EXTERNDB "extern:"
+#define LEGACY "dbm:"
+const char *
+sftk_EvaluateConfigDir(const char *configdir, SDBType *dbType, char **appName)
+{
+ *appName = NULL;
+ *dbType = SDB_LEGACY;
+ if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) {
+ char *cdir;
+ *dbType = SDB_MULTIACCESS;
+
+ *appName = PORT_Strdup(configdir+sizeof(MULTIACCESS)-1);
+ if (*appName == NULL) {
+ return configdir;
+ }
+ cdir = *appName;
+ while (*cdir && *cdir != ':') {
+ cdir++;
+ }
+ if (*cdir == ':') {
+ *cdir = 0;
+ cdir++;
+ }
+ configdir = cdir;
+ } else if (PORT_Strncmp(configdir, SQLDB, sizeof(SQLDB)-1) == 0) {
+ *dbType = SDB_SQL;
+ configdir = configdir + sizeof(SQLDB) -1;
+ } else if (PORT_Strncmp(configdir, EXTERNDB, sizeof(EXTERNDB)-1) == 0) {
+ *dbType = SDB_EXTERN;
+ configdir = configdir + sizeof(EXTERNDB) -1;
+ } else if (PORT_Strncmp(configdir, LEGACY, sizeof(LEGACY)-1) == 0) {
+ *dbType = SDB_LEGACY;
+ configdir = configdir + sizeof(LEGACY) -1;
+ } else {
+ /* look up the default from the environment */
+ char *defaultType = PR_GetEnv("NSS_DEFAULT_DB_TYPE");
+ if (defaultType == NULL) {
+ /* none specified, go with the legacy */
+ return configdir;
+ }
+ if (PORT_Strncmp(defaultType, SQLDB, sizeof(SQLDB)-2) == 0) {
+ *dbType = SDB_SQL;
+ } else if (PORT_Strncmp(defaultType,EXTERNDB,sizeof(EXTERNDB)-2)==0) {
+ *dbType = SDB_EXTERN;
+ } else if (PORT_Strncmp(defaultType, LEGACY, sizeof(LEGACY)-2) == 0) {
+ *dbType = SDB_LEGACY;
+ }
+ }
+ return configdir;
+}
+
+char *
+sftk_getSecmodName(char *param, SDBType *dbType, char **appName,
+ char **filename, PRBool *rw)
+{
+ int next;
+ char *configdir = NULL;
+ char *secmodName = NULL;
+ char *value = NULL;
+ char *save_params = param;
+ const char *lconfigdir;
+ param = sftk_argStrip(param);
+
+
+ while (*param) {
+ SFTK_HANDLE_STRING_ARG(param,configdir,"configDir=",;)
+ SFTK_HANDLE_STRING_ARG(param,secmodName,"secmod=",;)
+ SFTK_HANDLE_FINAL_ARG(param)
+ }
+
+ *rw = PR_TRUE;
+ if (sftk_argHasFlag("flags","readOnly",save_params) ||
+ sftk_argHasFlag("flags","noModDB",save_params)) *rw = PR_FALSE;
+
+ if (!secmodName || *secmodName == '\0') {
+ if (secmodName) PORT_Free(secmodName);
+ secmodName = PORT_Strdup(SECMOD_DB);
+ }
+
+ *filename = secmodName;
+ lconfigdir = sftk_EvaluateConfigDir(configdir, dbType, appName);
+
+ /* only use the renamed secmod for legacy databases */
+ if ((*dbType != SDB_LEGACY) && (*dbType != SDB_MULTIACCESS)) {
+ secmodName="pkcs11.txt";
+ }
+
+ if (lconfigdir) {
+ value = PR_smprintf("%s" PATH_SEPARATOR "%s",lconfigdir,secmodName);
+ } else {
+ value = PR_smprintf("%s",secmodName);
+ }
+ if (configdir) PORT_Free(configdir);
+ return value;
+}
diff --git a/security/nss/lib/softoken/sftkpars.h b/security/nss/lib/softoken/sftkpars.h
new file mode 100644
index 000000000..beb9edf97
--- /dev/null
+++ b/security/nss/lib/softoken/sftkpars.h
@@ -0,0 +1,17 @@
+/*
+ * license
+ */
+#include "pkcs11i.h"
+#include "sftkdbt.h"
+
+/* parsing functions */
+char * sftk_argFetchValue(char *string, int *pcount);
+char * sftk_getSecmodName(char *param, SDBType *dbType, char **appName, char **filename,PRBool *rw);
+char *sftk_argStrip(char *c);
+CK_RV sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS);
+void sftk_freeParams(sftk_parameters *params);
+const char *sftk_EvaluateConfigDir(const char *configdir, SDBType *dbType, char **app);
+char * sftk_argGetParamValue(char *paramName,char *parameters);
+
+
+
diff --git a/security/nss/lib/softoken/softoken.h b/security/nss/lib/softoken/softoken.h
index ed9108dcc..6078c40b2 100644
--- a/security/nss/lib/softoken/softoken.h
+++ b/security/nss/lib/softoken/softoken.h
@@ -147,6 +147,10 @@ SECStatus RSA_DecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
*/
extern SECStatus EC_FillParams(PRArenaPool *arena,
const SECItem *encodedParams, ECParams *params);
+extern SECStatus EC_DecodeParams(const SECItem *encodedParams,
+ ECParams **ecparams);
+extern SECStatus EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams);
#endif