summaryrefslogtreecommitdiff
path: root/security/nss/lib/softoken
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2001-11-08 00:15:51 +0000
committerrelyea%netscape.com <devnull@localhost>2001-11-08 00:15:51 +0000
commit395e319de1892e3454b66fc50206c7b027cb2904 (patch)
tree3a66fcd2ba3a244541ad877193503639f5a17d7e /security/nss/lib/softoken
parentcf02e5e9a3d60bd18873d065dd9c2dc0714776c7 (diff)
downloadnss-hg-395e319de1892e3454b66fc50206c7b027cb2904.tar.gz
Land BOB_WORK_BRANCH unto the tip.
remove lots of depricated files. move some files to appropriate directories (pcertdb *_rand associated headers to soft token, for instance) rename several stan files which had the same name as other nss files. remove depricated functions.
Diffstat (limited to 'security/nss/lib/softoken')
-rw-r--r--security/nss/lib/softoken/alghmac.c22
-rw-r--r--security/nss/lib/softoken/alghmac.h4
-rw-r--r--security/nss/lib/softoken/cdbhdl.h (renamed from security/nss/lib/softoken/keytboth.h)49
-rw-r--r--security/nss/lib/softoken/config.mk81
-rw-r--r--security/nss/lib/softoken/dbinit.c141
-rw-r--r--security/nss/lib/softoken/fipstest.c18
-rw-r--r--security/nss/lib/softoken/fipstokn.c75
-rw-r--r--security/nss/lib/softoken/keydb.c1094
-rw-r--r--security/nss/lib/softoken/keydbi.h (renamed from security/nss/lib/softoken/private.h)14
-rw-r--r--security/nss/lib/softoken/keydbt.h88
-rw-r--r--security/nss/lib/softoken/lowcert.c525
-rw-r--r--security/nss/lib/softoken/lowkey.c108
-rw-r--r--security/nss/lib/softoken/lowkeyi.h (renamed from security/nss/lib/softoken/keylow.h)98
-rw-r--r--security/nss/lib/softoken/lowkeyti.h138
-rw-r--r--security/nss/lib/softoken/lowpbe.c1184
-rw-r--r--security/nss/lib/softoken/lowpbe.h132
-rw-r--r--security/nss/lib/softoken/mac_rand.c315
-rw-r--r--security/nss/lib/softoken/manifest.mn31
-rw-r--r--security/nss/lib/softoken/os2_rand.c329
-rw-r--r--security/nss/lib/softoken/pcert.h147
-rw-r--r--security/nss/lib/softoken/pcertdb.c4410
-rw-r--r--security/nss/lib/softoken/pcertt.h433
-rw-r--r--security/nss/lib/softoken/pk11db.c190
-rw-r--r--security/nss/lib/softoken/pk11pars.h4
-rw-r--r--security/nss/lib/softoken/pkcs11.c3194
-rw-r--r--security/nss/lib/softoken/pkcs11.h13
-rw-r--r--security/nss/lib/softoken/pkcs11c.c808
-rw-r--r--security/nss/lib/softoken/pkcs11f.h9
-rw-r--r--security/nss/lib/softoken/pkcs11i.h206
-rw-r--r--security/nss/lib/softoken/pkcs11t.h336
-rw-r--r--security/nss/lib/softoken/pkcs11u.c1697
-rw-r--r--security/nss/lib/softoken/rsawrapr.c288
-rw-r--r--security/nss/lib/softoken/secpkcs5.c1849
-rw-r--r--security/nss/lib/softoken/secpkcs5.h185
-rw-r--r--security/nss/lib/softoken/softoken.h23
-rw-r--r--security/nss/lib/softoken/softokn.def57
-rw-r--r--security/nss/lib/softoken/softokn.rc98
-rw-r--r--security/nss/lib/softoken/sysrand.c (renamed from security/nss/lib/softoken/keytlow.h)55
-rw-r--r--security/nss/lib/softoken/unix_rand.c891
-rw-r--r--security/nss/lib/softoken/win_rand.c415
40 files changed, 13687 insertions, 6067 deletions
diff --git a/security/nss/lib/softoken/alghmac.c b/security/nss/lib/softoken/alghmac.c
index aef81a76b..60abd73d0 100644
--- a/security/nss/lib/softoken/alghmac.c
+++ b/security/nss/lib/softoken/alghmac.c
@@ -31,10 +31,10 @@
* GPL.
*/
-#include "alghmac.h"
#include "sechash.h"
-#include "secoid.h"
#include "secport.h"
+#include "alghmac.h"
+/*#include "secoid.h"*/
#define HMAC_PAD_SIZE 64
@@ -57,8 +57,7 @@ HMAC_Destroy(HMACContext *cx)
}
HMACContext *
-HMAC_Create(SECOidTag hash_alg,
- const unsigned char *secret,
+HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret,
unsigned int secret_len)
{
HMACContext *cx;
@@ -68,20 +67,7 @@ HMAC_Create(SECOidTag hash_alg,
cx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext));
if (cx == NULL)
return NULL;
-
- switch (hash_alg) {
- case SEC_OID_MD5:
- cx->hashobj = &SECRawHashObjects[HASH_AlgMD5];
- break;
- case SEC_OID_MD2:
- cx->hashobj = &SECRawHashObjects[HASH_AlgMD2];
- break;
- case SEC_OID_SHA1:
- cx->hashobj = &SECRawHashObjects[HASH_AlgSHA1];
- break;
- default:
- goto loser;
- }
+ cx->hashobj = hash_obj;
cx->hash = cx->hashobj->create();
if (cx->hash == NULL)
diff --git a/security/nss/lib/softoken/alghmac.h b/security/nss/lib/softoken/alghmac.h
index 10d598267..3cb1a74dc 100644
--- a/security/nss/lib/softoken/alghmac.h
+++ b/security/nss/lib/softoken/alghmac.h
@@ -34,8 +34,6 @@
#ifndef _ALGHMAC_H_
#define _ALGHMAC_H_
-#include "secoid.h"
-
typedef struct HMACContextStr HMACContext;
SEC_BEGIN_PROTOS
@@ -53,7 +51,7 @@ HMAC_Destroy(HMACContext *cx);
* NULL is returned if an error occurs or the secret is > 64 bytes.
*/
extern HMACContext *
-HMAC_Create(SECOidTag hash_alg, const unsigned char *secret,
+HMAC_Create(const SECHashObject *hashObj, const unsigned char *secret,
unsigned int secret_len);
/* reset HMAC for a fresh round */
diff --git a/security/nss/lib/softoken/keytboth.h b/security/nss/lib/softoken/cdbhdl.h
index 0e4816cb6..b606e9876 100644
--- a/security/nss/lib/softoken/keytboth.h
+++ b/security/nss/lib/softoken/cdbhdl.h
@@ -30,42 +30,25 @@
* may use your version of this file under either the MPL or the
* GPL.
*/
-#ifndef _KEYTBOTH_H_
-#define _KEYTBOTH_H_ 1
-
-#include "blapit.h"
-#include "secoidt.h"
-
/*
-** Attributes
-*/
-struct SECKEYAttributeStr {
- SECItem attrType;
- SECItem **attrValue;
-};
-typedef struct SECKEYAttributeStr SECKEYAttribute;
+ * cdbhdl.h - certificate database handle
+ * private to the certdb module
+ *
+ * $Id$
+ */
+#ifndef _CDBHDL_H_
+#define _CDBHDL_H_
-/*
-** A PKCS#8 private key info object
-*/
-struct PrivateKeyInfoStr {
- PLArenaPool *arena;
- SECItem version;
- SECAlgorithmID algorithm;
- SECItem privateKey;
- SECKEYAttribute **attributes;
-};
-typedef struct PrivateKeyInfoStr PrivateKeyInfo;
-#define SEC_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */
+#include "nspr.h"
+#include "mcom_db.h"
+#include "pcertt.h"
/*
-** A PKCS#8 private key info object
-*/
-struct EncryptedPrivateKeyInfoStr {
- PLArenaPool *arena;
- SECAlgorithmID algorithm;
- SECItem encryptedData;
+ * Handle structure for open certificate databases
+ */
+struct NSSLOWCERTCertDBHandleStr {
+ DB *permCertDB;
+ PZMonitor *dbMon;
};
-typedef struct EncryptedPrivateKeyInfoStr EncryptedPrivateKeyInfo;
-#endif /* _KEYT_H_ */
+#endif
diff --git a/security/nss/lib/softoken/config.mk b/security/nss/lib/softoken/config.mk
index 0a00dc61e..702802b8c 100644
--- a/security/nss/lib/softoken/config.mk
+++ b/security/nss/lib/softoken/config.mk
@@ -36,8 +36,81 @@
# are specifed as dependencies within rules.mk.
#
-TARGETS = $(LIBRARY)
-SHARED_LIBRARY =
-IMPORT_LIBRARY =
-PROGRAM =
+#TARGETS = $(LIBRARY)
+#SHARED_LIBRARY =
+#IMPORT_LIBRARY =
+#PROGRAM =
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+ifeq ($(OS_ARCH), WINNT)
+
+# don't want the 32 in the shared library name
+SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).dll
+IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).lib
+
+RES = $(OBJDIR)/$(LIBRARY_NAME).res
+RESNAME = $(LIBRARY_NAME).rc
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+CRYPTOLIB=$(DIST)/lib/freebl.lib
+CRYPTODIR=../freebl
+ifdef MOZILLA_SECURITY_BUILD
+ CRYPTOLIB=$(DIST)/lib/crypto.lib
+ CRYPTODIR=../crypto
+endif
+
+EXTRA_SHARED_LIBRARY_LIBS += \
+ $(CRYPTOLIB) \
+ $(DIST)/lib/secutil.lib \
+ $(NULL)
+
+EXTRA_LIBS += \
+ $(DIST)/lib/dbm.lib \
+ $(NULL)
+
+ifdef MOZILLA_BSAFE_BUILD
+ EXTRA_LIBS+=$(DIST)/lib/bsafe$(BSAFEVER).lib
+endif
+
+EXTRA_SHARED_LIBS += \
+ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \
+ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \
+ $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \
+ $(NULL)
+else
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+CRYPTOLIB=$(DIST)/lib/libfreebl.$(LIB_SUFFIX)
+CRYPTODIR=../freebl
+ifdef MOZILLA_SECURITY_BUILD
+ CRYPTOLIB=$(DIST)/lib/libcrypto.$(LIB_SUFFIX)
+ CRYPTODIR=../crypto
+endif
+EXTRA_LIBS += \
+ $(CRYPTOLIB) \
+ $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \
+ $(DIST)/lib/libdbm.$(LIB_SUFFIX) \
+ $(NULL)
+ifdef MOZILLA_BSAFE_BUILD
+ EXTRA_LIBS+=$(DIST)/lib/libbsafe.$(LIB_SUFFIX)
+endif
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib/ \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+endif
+
+ifeq ($(OS_ARCH),SunOS)
+ifndef USE_64
+ifeq ($(CPU_ARCH),sparc)
+# The -R '$ORIGIN' linker option instructs libnss3.so to search for its
+# dependencies (libfreebl_*.so) in the same directory where it resides.
+MKSHLIB += -R '$$ORIGIN'
+endif
+endif
+endif
diff --git a/security/nss/lib/softoken/dbinit.c b/security/nss/lib/softoken/dbinit.c
index f31eb514b..bae037a4a 100644
--- a/security/nss/lib/softoken/dbinit.c
+++ b/security/nss/lib/softoken/dbinit.c
@@ -40,22 +40,15 @@
#include "prinit.h"
#include "prprf.h"
#include "prmem.h"
-#include "cert.h"
-#include "keylow.h"
-#include "keydbt.h"
-#include "ssl.h"
-#include "sslproto.h"
-#include "secmod.h"
-#include "secmodi.h"
-#include "secoid.h"
-#include "nss.h"
+#include "pcertt.h"
+#include "lowkeyi.h"
+#include "pcert.h"
+/*#include "secmodi.h" */
#include "secrng.h"
#include "cdbhdl.h"
-#include "pk11func.h"
+/*#include "pk11func.h" */
#include "pkcs11i.h"
-static char *secmodname = NULL;
-
static char *
pk11_certdb_name_cb(void *arg, int dbVersion)
{
@@ -109,77 +102,61 @@ pk11_keydb_name_cb(void *arg, int dbVersion)
#define CKR_KEYDB_FAILED CKR_DEVICE_ERROR
static CK_RV
-pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly)
+pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly,
+ NSSLOWCERTCertDBHandle **certdbPtr)
{
- CERTCertDBHandle *certdb;
- CK_RV crv = CKR_OK;
+ NSSLOWCERTCertDBHandle *certdb;
+ CK_RV crv = CKR_CERTDB_FAILED;
SECStatus rv;
char * name = NULL;
- certdb = CERT_GetDefaultCertDB();
- if (certdb)
- return CKR_OK; /* idempotency */
+ if (prefix == NULL) {
+ prefix = "";
+ }
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
if (name == NULL) goto loser;
- certdb = (CERTCertDBHandle*)PORT_ZAlloc(sizeof(CERTCertDBHandle));
+ certdb = (NSSLOWCERTCertDBHandle*)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle));
if (certdb == NULL)
goto loser;
/* fix when we get the DB in */
- rv = CERT_OpenCertDB(certdb, readOnly, pk11_certdb_name_cb, (void *)name);
- if (rv == SECSuccess)
- CERT_SetDefaultCertDB(certdb);
- else {
- PR_Free(certdb);
-loser:
- crv = CKR_CERTDB_FAILED;
+ rv = nsslowcert_OpenCertDB(certdb, readOnly,
+ pk11_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) PORT_Free(name);
return crv;
}
static CK_RV
-pk11_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly)
+pk11_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly,
+ NSSLOWKEYDBHandle **keydbPtr)
{
- SECKEYKeyDBHandle *keydb;
+ NSSLOWKEYDBHandle *keydb;
char * name = NULL;
- keydb = SECKEY_GetDefaultKeyDB();
- if (keydb)
- return SECSuccess;
+ if (prefix == NULL) {
+ prefix = "";
+ }
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
if (name == NULL)
return SECFailure;
- keydb = SECKEY_OpenKeyDB(readOnly, pk11_keydb_name_cb, (void *)name);
+ keydb = nsslowkey_OpenKeyDB(readOnly, pk11_keydb_name_cb, (void *)name);
+ PORT_Free(name);
if (keydb == NULL)
return CKR_KEYDB_FAILED;
- SECKEY_SetDefaultKeyDB(keydb);
- PORT_Free(name);
+ *keydbPtr = keydb;
return CKR_OK;
}
-static CERTCertDBHandle certhandle = { 0 };
-
-static PRBool isInitialized = PR_FALSE;
-
-static CK_RV
-pk11_OpenVolatileCertDB() {
- SECStatus rv = SECSuccess;
- /* now we want to verify the signature */
- /* Initialize the cert code */
- rv = CERT_OpenVolatileCertDB(&certhandle);
- if (rv != SECSuccess) {
- return CKR_DEVICE_ERROR;
- }
- CERT_SetDefaultCertDB(&certhandle);
- return CKR_OK;
-}
-
-/* forward declare so that a failure in the init case can shutdown */
-void pk11_Shutdown(void);
/*
* OK there are now lots of options here, lets go through them all:
@@ -200,71 +177,53 @@ void pk11_Shutdown(void);
*/
CK_RV
pk11_DBInit(const char *configdir, const char *certPrefix,
- const char *keyPrefix,
- const char *secmodName, PRBool readOnly, PRBool noCertDB,
- PRBool noModDB, PRBool forceOpen)
+ const char *keyPrefix, PRBool readOnly,
+ PRBool noCertDB, PRBool noKeyDB, PRBool forceOpen,
+ NSSLOWCERTCertDBHandle **certdbPtr, NSSLOWKEYDBHandle **keydbPtr)
{
- SECStatus rv = SECFailure;
CK_RV crv = CKR_OK;
- if( isInitialized ) {
- return CKR_OK;
- }
-
- rv = RNG_RNGInit(); /* initialize random number generator */
- if (rv != SECSuccess) {
- crv = CKR_DEVICE_ERROR;
- goto loser;
- }
- RNG_SystemInfoForRNG();
- if (noCertDB) {
- crv = pk11_OpenVolatileCertDB();
- if (crv != CKR_OK) {
- goto loser;
- }
- } else {
- crv = pk11_OpenCertDB(configdir, certPrefix, readOnly);
+ if (!noCertDB) {
+ crv = pk11_OpenCertDB(configdir, certPrefix, readOnly, certdbPtr);
if (crv != CKR_OK) {
if (!forceOpen) goto loser;
- crv = pk11_OpenVolatileCertDB();
- if (crv != CKR_OK) {
- goto loser;
- }
+ crv = CKR_OK;
}
+ }
+ if (!noKeyDB) {
- crv = pk11_OpenKeyDB(configdir, keyPrefix, readOnly);
+ crv = pk11_OpenKeyDB(configdir, keyPrefix, readOnly, keydbPtr);
if (crv != CKR_OK) {
if (!forceOpen) goto loser;
+ crv = CKR_OK;
}
}
- isInitialized = PR_TRUE;
loser:
- if (crv != CKR_OK) {
- pk11_Shutdown();
- }
return crv;
}
+#ifdef notdef
void
pk11_Shutdown(void)
{
- CERTCertDBHandle *certHandle;
- SECKEYKeyDBHandle *keyHandle;
+ NSSLOWCERTCertDBHandle *certHandle;
+ NSSLOWKEYDBHandle *keyHandle;
PR_FREEIF(secmodname);
- certHandle = CERT_GetDefaultCertDB();
+ certHandle = nsslowcert_GetDefaultCertDB();
if (certHandle)
- CERT_ClosePermCertDB(certHandle);
- CERT_SetDefaultCertDB(NULL);
+ nsslowcert_ClosePermCertDB(certHandle);
+ nsslowcert_SetDefaultCertDB(NULL);
- keyHandle = SECKEY_GetDefaultKeyDB();
+ keyHandle = nsslowkey_GetDefaultKeyDB();
if (keyHandle)
- SECKEY_CloseKeyDB(keyHandle);
- SECKEY_SetDefaultKeyDB(NULL);
+ nsslowkey_CloseKeyDB(keyHandle);
+ nsslowkey_SetDefaultKeyDB(NULL);
isInitialized = PR_FALSE;
}
+#endif
diff --git a/security/nss/lib/softoken/fipstest.c b/security/nss/lib/softoken/fipstest.c
index f11448356..15e490090 100644
--- a/security/nss/lib/softoken/fipstest.c
+++ b/security/nss/lib/softoken/fipstest.c
@@ -39,7 +39,7 @@
/* DES-CBC, DES3-ECB, DES3-CBC, RSA */
/* and DSA. */
#include "seccomon.h" /* Required for RSA and DSA. */
-#include "keylow.h" /* Required for RSA and DSA. */
+#include "lowkeyi.h" /* Required for RSA and DSA. */
#include "pkcs11.h" /* Required for PKCS #11. */
#include "secerr.h"
@@ -792,13 +792,13 @@ pk11_fips_RSA_PowerUpSelfTest( void )
PLArenaPool * rsa_public_arena;
PLArenaPool * rsa_private_arena;
#endif
- SECKEYLowPublicKey * rsa_public_key;
- SECKEYLowPrivateKey * rsa_private_key;
+ NSSLOWKEYPublicKey * rsa_public_key;
+ NSSLOWKEYPrivateKey * rsa_private_key;
unsigned int rsa_bytes_signed;
SECStatus rsa_status;
- SECKEYLowPublicKey low_public_key = { NULL, lowRSAKey, };
- SECKEYLowPrivateKey low_private_key = { NULL, lowRSAKey, };
+ NSSLOWKEYPublicKey low_public_key = { NULL, NSSLOWKEYRSAKey, };
+ NSSLOWKEYPrivateKey low_private_key = { NULL, NSSLOWKEYRSAKey, };
PRUint8 rsa_computed_ciphertext[FIPS_RSA_ENCRYPT_LENGTH];
PRUint8 rsa_computed_plaintext[FIPS_RSA_DECRYPT_LENGTH];
PRUint8 rsa_computed_signature[FIPS_RSA_SIGNATURE_LENGTH];
@@ -894,16 +894,16 @@ pk11_fips_RSA_PowerUpSelfTest( void )
goto rsa_loser;
/* Dispose of all RSA key material. */
- SECKEY_LowDestroyPublicKey( rsa_public_key );
- SECKEY_LowDestroyPrivateKey( rsa_private_key );
+ nsslowkey_DestroyPublicKey( rsa_public_key );
+ nsslowkey_DestroyPrivateKey( rsa_private_key );
return( CKR_OK );
rsa_loser:
- SECKEY_LowDestroyPublicKey( rsa_public_key );
- SECKEY_LowDestroyPrivateKey( rsa_private_key );
+ nsslowkey_DestroyPublicKey( rsa_public_key );
+ nsslowkey_DestroyPrivateKey( rsa_private_key );
return( CKR_DEVICE_ERROR );
}
diff --git a/security/nss/lib/softoken/fipstokn.c b/security/nss/lib/softoken/fipstokn.c
index e72a9965a..b547a93e4 100644
--- a/security/nss/lib/softoken/fipstokn.c
+++ b/security/nss/lib/softoken/fipstokn.c
@@ -48,32 +48,11 @@
*/
#include "seccomon.h"
#include "softoken.h"
-#include "key.h"
+#include "lowkeyi.h"
+#include "pcert.h"
#include "pkcs11.h"
#include "pkcs11i.h"
-/* The next two strings must be exactly 64 characters long, with the
- first 32 characters meaningful */
-static char *slotDescription =
- "Netscape Internal FIPS-140-1 Cryptographic Services ";
-static char *privSlotDescription =
- "Netscape FIPS-140-1 User Private Key Services ";
-
-
-/*
- * Configuration utils
- */
-void
-PK11_ConfigureFIPS(char *slotdes, char *pslotdes)
-{
- if (slotdes && (PORT_Strlen(slotdes) == 65)) {
- slotDescription = slotdes;
- }
- if (pslotdes && (PORT_Strlen(pslotdes) == 65)) {
- privSlotDescription = pslotdes;
- }
- return;
-}
/*
* ******************** Password Utilities *******************************
@@ -170,30 +149,22 @@ CK_RV FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) {
/* FC_Initialize initializes the PKCS #11 library. */
CK_RV FC_Initialize(CK_VOID_PTR pReserved) {
- CK_RV rv;
- static PRBool init= PR_FALSE;
-
-
- rv = PK11_LowInitialize(pReserved);
+ CK_RV crv;
- if (rv == CKR_OK && !init) {
- init = PR_TRUE;
- rv = PK11_SlotInit(FIPS_SLOT_ID,PR_TRUE);
- /* fall through to check below */
- }
+ crv = nsc_CommonInitialize(pReserved, PR_TRUE);
/* not an 'else' rv can be set by either PK11_LowInit or PK11_SlotInit*/
- if (rv != CKR_OK) {
+ if (crv != CKR_OK) {
fatalError = PR_TRUE;
- return rv;
+ return crv;
}
fatalError = PR_FALSE; /* any error has been reset */
- rv = pk11_fipsPowerUpSelfTest();
- if (rv != CKR_OK) {
+ crv = pk11_fipsPowerUpSelfTest();
+ if (crv != CKR_OK) {
fatalError = PR_TRUE;
- return rv;
+ return crv;
}
return CKR_OK;
@@ -214,11 +185,7 @@ CK_RV FC_GetInfo(CK_INFO_PTR pInfo) {
/* FC_GetSlotList obtains a list of slots in the system. */
CK_RV FC_GetSlotList(CK_BBOOL tokenPresent,
CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
- *pulCount = 1;
- if (pSlotList != NULL) {
- pSlotList[0] = FIPS_SLOT_ID;
- }
- return CKR_OK;
+ return NSC_GetSlotList(tokenPresent,pSlotList,pulCount);
}
/* FC_GetSlotInfo obtains information about a particular slot in the system. */
@@ -226,16 +193,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CK_RV crv;
- if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID;
-
- /* Use NETSCAPE_SLOT_ID as a basis so that we get Library version number,
- * not key_DB version number */
- crv = NSC_GetSlotInfo(NETSCAPE_SLOT_ID,pInfo);
+ crv = NSC_GetSlotInfo(slotID,pInfo);
if (crv != CKR_OK) {
return crv;
}
- PORT_Memcpy(pInfo->slotDescription,slotDescription,64);
return CKR_OK;
}
@@ -244,13 +206,8 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CK_RV FC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) {
CK_RV crv;
- if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID;
-
- /* use PRIVATE_KEY_SLOT_ID so we get the correct
- Authentication information */
- crv = NSC_GetTokenInfo(PRIVATE_KEY_SLOT_ID,pInfo);
+ crv = NSC_GetTokenInfo(slotID,pInfo);
pInfo->flags |= CKF_RNG | CKF_LOGIN_REQUIRED;
- /* yes virginia, FIPS can do random number generation:) */
return crv;
}
@@ -261,9 +218,9 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CK_RV FC_GetMechanismList(CK_SLOT_ID slotID,
CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pusCount) {
PK11_FIPSFATALCHECK();
- if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID;
+ if (slotID == FIPS_SLOT_ID) slotID = NETSCAPE_SLOT_ID;
/* FIPS Slot supports all functions */
- return NSC_GetMechanismList(NETSCAPE_SLOT_ID,pMechanismList,pusCount);
+ return NSC_GetMechanismList(slotID,pMechanismList,pusCount);
}
@@ -272,9 +229,9 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CK_RV FC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo) {
PK11_FIPSFATALCHECK();
- if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID;
+ if (slotID == FIPS_SLOT_ID) slotID = NETSCAPE_SLOT_ID;
/* FIPS Slot supports all functions */
- return NSC_GetMechanismInfo(NETSCAPE_SLOT_ID,type,pInfo);
+ return NSC_GetMechanismInfo(slotID,type,pInfo);
}
diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c
index f13ca5374..cc00014f7 100644
--- a/security/nss/lib/softoken/keydb.c
+++ b/security/nss/lib/softoken/keydb.c
@@ -35,9 +35,7 @@
* $Id$
*/
-#include "keylow.h"
-#include "keydbt.h"
-#include "keytboth.h"
+#include "lowkeyi.h"
#include "seccomon.h"
#include "sechash.h"
#include "secder.h"
@@ -45,12 +43,12 @@
#include "secoid.h"
#include "blapi.h"
#include "secitem.h"
-#include "cert.h"
+#include "pcert.h"
#include "mcom_db.h"
-#include "secpkcs5.h"
+#include "lowpbe.h"
#include "secerr.h"
-#include "private.h"
+#include "keydbi.h"
/*
* Record keys for keydb
@@ -66,55 +64,36 @@
#define SALT_LENGTH 16
/* ASN1 Templates for new decoder/encoder */
-/*
- * Attribute value for PKCS8 entries (static?)
- */
-const SEC_ASN1Template SECKEY_AttributeTemplate[] = {
- { SEC_ASN1_SEQUENCE,
- 0, NULL, sizeof(SECKEYAttribute) },
- { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) },
- { SEC_ASN1_SET_OF, offsetof(SECKEYAttribute, attrValue),
- SEC_AnyTemplate },
- { 0 }
-};
-
-const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = {
- { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate },
-};
-
-const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = {
+const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
- 0, NULL, sizeof(PrivateKeyInfo) },
+ 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
{ SEC_ASN1_INTEGER,
- offsetof(PrivateKeyInfo,version) },
+ offsetof(NSSLOWKEYPrivateKeyInfo,version) },
{ SEC_ASN1_INLINE,
- offsetof(PrivateKeyInfo,algorithm),
+ offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
SECOID_AlgorithmIDTemplate },
{ SEC_ASN1_OCTET_STRING,
- offsetof(PrivateKeyInfo,privateKey) },
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
- offsetof(PrivateKeyInfo,attributes),
- SECKEY_SetOfAttributeTemplate },
+ offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
{ 0 }
};
-const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = {
- { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate }
+const SEC_ASN1Template nsslowkey_PointerToPrivateKeyInfoTemplate[] = {
+ { SEC_ASN1_POINTER, 0, nsslowkey_PrivateKeyInfoTemplate }
};
-const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = {
+const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
- 0, NULL, sizeof(EncryptedPrivateKeyInfo) },
+ 0, NULL, sizeof(NSSLOWKEYEncryptedPrivateKeyInfo) },
{ SEC_ASN1_INLINE,
- offsetof(EncryptedPrivateKeyInfo,algorithm),
+ offsetof(NSSLOWKEYEncryptedPrivateKeyInfo,algorithm),
SECOID_AlgorithmIDTemplate },
{ SEC_ASN1_OCTET_STRING,
- offsetof(EncryptedPrivateKeyInfo,encryptedData) },
+ offsetof(NSSLOWKEYEncryptedPrivateKeyInfo,encryptedData) },
{ 0 }
};
-const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = {
- { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate }
+const SEC_ASN1Template nsslowkey_PointerToEncryptedPrivateKeyInfoTemplate[] = {
+ { SEC_ASN1_POINTER, 0, nsslowkey_EncryptedPrivateKeyInfoTemplate }
};
@@ -126,13 +105,13 @@ static SECOidTag defaultKeyDBAlg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_C
* Default algorithm for encrypting data in the key database
*/
SECOidTag
-SECKEY_GetDefaultKeyDBAlg(void)
+nsslowkey_GetDefaultKeyDBAlg(void)
{
return(defaultKeyDBAlg);
}
void
-SECKEY_SetDefaultKeyDBAlg(SECOidTag alg)
+nsslowkey_SetDefaultKeyDBAlg(SECOidTag alg)
{
defaultKeyDBAlg = alg;
@@ -140,7 +119,7 @@ SECKEY_SetDefaultKeyDBAlg(SECOidTag alg)
}
static void
-sec_destroy_dbkey(SECKEYDBKey *dbkey)
+sec_destroy_dbkey(NSSLOWKEYDBKey *dbkey)
{
if ( dbkey && dbkey->arena ) {
PORT_FreeArena(dbkey->arena, PR_FALSE);
@@ -170,7 +149,7 @@ free_dbt(DBT *dbt)
* ... encrypted-key-data
*/
static DBT *
-encode_dbkey(SECKEYDBKey *dbkey)
+encode_dbkey(NSSLOWKEYDBKey *dbkey)
{
DBT *bufitem = NULL;
unsigned char *buf;
@@ -202,7 +181,7 @@ encode_dbkey(SECKEYDBKey *dbkey)
buf = (unsigned char *)bufitem->data;
/* set version number */
- buf[0] = PRIVATE_KEY_DB_FILE_VERSION;
+ buf[0] = NSSLOWKEY_DB_FILE_VERSION;
/* set length of salt */
PORT_Assert(dbkey->salt.len < 256);
@@ -232,10 +211,10 @@ loser:
return(NULL);
}
-static SECKEYDBKey *
+static NSSLOWKEYDBKey *
decode_dbkey(DBT *bufitem, int expectedVersion)
{
- SECKEYDBKey *dbkey;
+ NSSLOWKEYDBKey *dbkey;
PLArenaPool *arena = NULL;
unsigned char *buf;
int version;
@@ -256,7 +235,7 @@ decode_dbkey(DBT *bufitem, int expectedVersion)
goto loser;
}
- dbkey = (SECKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYDBKey));
+ dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYDBKey));
if ( dbkey == NULL ) {
goto loser;
}
@@ -274,7 +253,7 @@ decode_dbkey(DBT *bufitem, int expectedVersion)
saltoff = 2;
keyoff = 2 + dbkey->salt.len;
- if ( expectedVersion == PRIVATE_KEY_DB_FILE_VERSION ) {
+ if ( expectedVersion == NSSLOWKEY_DB_FILE_VERSION ) {
nnlen = buf[2];
if ( nnlen ) {
dbkey->nickname = (char *)PORT_ArenaZAlloc(arena, nnlen + 1);
@@ -307,10 +286,10 @@ loser:
return(NULL);
}
-static SECKEYDBKey *
-get_dbkey(SECKEYKeyDBHandle *handle, DBT *index)
+static NSSLOWKEYDBKey *
+get_dbkey(NSSLOWKEYDBHandle *handle, DBT *index)
{
- SECKEYDBKey *dbkey;
+ NSSLOWKEYDBKey *dbkey;
DBT entry;
int ret;
@@ -323,13 +302,13 @@ get_dbkey(SECKEYKeyDBHandle *handle, DBT *index)
/* set up dbkey struct */
- dbkey = decode_dbkey(&entry, PRIVATE_KEY_DB_FILE_VERSION);
+ dbkey = decode_dbkey(&entry, NSSLOWKEY_DB_FILE_VERSION);
return(dbkey);
}
static SECStatus
-put_dbkey(SECKEYKeyDBHandle *handle, DBT *index, SECKEYDBKey *dbkey, PRBool update)
+put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool update)
{
DBT *keydata = NULL;
int status;
@@ -369,7 +348,7 @@ loser:
}
SECStatus
-SECKEY_TraverseKeys(SECKEYKeyDBHandle *handle,
+nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
SECStatus (* keyfunc)(DBT *k, DBT *d, void *pdata),
void *udata )
{
@@ -480,7 +459,7 @@ decodeKeyDBGlobalSalt(DBT *saltData)
}
static SECItem *
-GetKeyDBGlobalSalt(SECKEYKeyDBHandle *handle)
+GetKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
{
DBT saltKey;
DBT saltData;
@@ -498,14 +477,14 @@ GetKeyDBGlobalSalt(SECKEYKeyDBHandle *handle)
}
static SECStatus
-makeGlobalVersion(SECKEYKeyDBHandle *handle)
+makeGlobalVersion(NSSLOWKEYDBHandle *handle)
{
unsigned char version;
DBT versionData;
DBT versionKey;
int status;
- version = PRIVATE_KEY_DB_FILE_VERSION;
+ version = NSSLOWKEY_DB_FILE_VERSION;
versionData.data = &version;
versionData.size = 1;
versionKey.data = VERSION_STRING;
@@ -522,7 +501,7 @@ makeGlobalVersion(SECKEYKeyDBHandle *handle)
static SECStatus
-makeGlobalSalt(SECKEYKeyDBHandle *handle)
+makeGlobalSalt(NSSLOWKEYDBHandle *handle)
{
DBT saltKey;
DBT saltData;
@@ -551,17 +530,241 @@ keyDBFilenameCallback(void *arg, int dbVersion)
return(PORT_Strdup((char *)arg));
}
-SECKEYKeyDBHandle *
-SECKEY_OpenKeyDBFilename(char *dbname, PRBool readOnly)
+NSSLOWKEYDBHandle *
+nsslowkey_OpenKeyDBFilename(char *dbname, PRBool readOnly)
{
- return(SECKEY_OpenKeyDB(readOnly, keyDBFilenameCallback,
+ return(nsslowkey_OpenKeyDB(readOnly, keyDBFilenameCallback,
(void *)dbname));
}
-SECKEYKeyDBHandle *
-SECKEY_OpenKeyDB(PRBool readOnly, SECKEYDBNameFunc namecb, void *cbarg)
+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);
+/*
+ * currently updates key database from v2 to v3
+ */
+static SECStatus
+nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
+{
+ SECStatus rv;
+ DBT versionKey;
+ DBT versionData;
+ DBT checkKey;
+ DBT checkData;
+ DBT saltKey;
+ DBT saltData;
+ DBT key;
+ DBT data;
+ SECItem *rc4key = NULL;
+ NSSLOWKEYDBKey *dbkey = NULL;
+ SECItem *oldSalt = NULL;
+ int ret;
+ SECItem checkitem;
+
+ if ( handle->updatedb == NULL ) {
+ return(SECSuccess);
+ }
+
+ /*
+ * check the version record
+ */
+ versionKey.data = VERSION_STRING;
+ versionKey.size = sizeof(VERSION_STRING)-1;
+
+ ret = (* handle->updatedb->get)(handle->updatedb, &versionKey,
+ &versionData, 0 );
+
+ if (ret) {
+ /* no version record, so old db never used */
+ goto done;
+ }
+
+ if ( ( versionData.size != 1 ) ||
+ ( *((unsigned char *)versionData.data) != 2 ) ) {
+ /* corrupt or wrong version number so don't update */
+ goto done;
+ }
+
+ saltKey.data = SALT_STRING;
+ saltKey.size = sizeof(SALT_STRING) - 1;
+
+ ret = (* handle->updatedb->get)(handle->updatedb, &saltKey, &saltData, 0);
+ if ( ret ) {
+ /* no salt in old db, so it is corrupted */
+ goto done;
+ }
+
+ oldSalt = decodeKeyDBGlobalSalt(&saltData);
+ if ( oldSalt == NULL ) {
+ /* bad salt in old db, so it is corrupted */
+ goto done;
+ }
+
+ /*
+ * look for a pw check entry
+ */
+ checkKey.data = KEYDB_PW_CHECK_STRING;
+ checkKey.size = KEYDB_PW_CHECK_LEN;
+
+ ret = (* handle->updatedb->get)(handle->updatedb, &checkKey,
+ &checkData, 0 );
+ if (ret) {
+ /*
+ * if we have a key, but no KEYDB_PW_CHECK_STRING, then this must
+ * be an old server database, and it does have a password associated
+ * with it. Put a fake entry in so we can identify this db when we do
+ * get the password for it.
+ */
+ if (seckey_HasAServerKey(handle->updatedb)) {
+ DBT fcheckKey;
+ DBT fcheckData;
+
+ /*
+ * include a fake string
+ */
+ fcheckKey.data = KEYDB_FAKE_PW_CHECK_STRING;
+ fcheckKey.size = KEYDB_FAKE_PW_CHECK_LEN;
+ fcheckData.data = "1";
+ fcheckData.size = 1;
+ /* put global salt into the new database now */
+ ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0);
+ if ( ret ) {
+ goto done;
+ }
+ ret = (* handle->db->put)( handle->db, &fcheckKey, &fcheckData, 0);
+ if ( ret ) {
+ goto done;
+ }
+ } else {
+ goto done;
+ }
+ } else {
+ /* put global salt into the new database now */
+ ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0);
+ if ( ret ) {
+ goto done;
+ }
+
+ dbkey = decode_dbkey(&checkData, 2);
+ if ( dbkey == NULL ) {
+ goto done;
+ }
+ checkitem = dbkey->derPK;
+ dbkey->derPK.data = NULL;
+
+ /* format the new pw check entry */
+ rv = encodePWCheckEntry(NULL, &dbkey->derPK, SEC_OID_RC4, &checkitem);
+ if ( rv != SECSuccess ) {
+ goto done;
+ }
+
+ rv = put_dbkey(handle, &checkKey, dbkey, PR_TRUE);
+ if ( rv != SECSuccess ) {
+ goto done;
+ }
+
+ /* free the dbkey */
+ sec_destroy_dbkey(dbkey);
+ dbkey = NULL;
+ }
+
+
+ /* now traverse the database */
+ ret = (* handle->updatedb->seq)(handle->updatedb, &key, &data, R_FIRST);
+ if ( ret ) {
+ goto done;
+ }
+
+ do {
+ /* skip version record */
+ if ( data.size > 1 ) {
+ /* skip salt */
+ if ( key.size == ( sizeof(SALT_STRING) - 1 ) ) {
+ if ( PORT_Memcmp(key.data, SALT_STRING, key.size) == 0 ) {
+ continue;
+ }
+ }
+ /* skip pw check entry */
+ if ( key.size == checkKey.size ) {
+ if ( PORT_Memcmp(key.data, checkKey.data, key.size) == 0 ) {
+ continue;
+ }
+ }
+
+ /* keys stored by nickname will have 0 as the last byte of the
+ * db key. Other keys must be stored by modulus. We will not
+ * update those because they are left over from a keygen that
+ * never resulted in a cert.
+ */
+ if ( ((unsigned char *)key.data)[key.size-1] != 0 ) {
+ continue;
+ }
+
+ dbkey = decode_dbkey(&data, 2);
+ if ( dbkey == NULL ) {
+ continue;
+ }
+
+ /* This puts the key into the new database with the same
+ * index (nickname) that it had before. The second pass
+ * of the update will have the password. It will decrypt
+ * and re-encrypt the entries using a new algorithm.
+ */
+ dbkey->nickname = (char *)key.data;
+ rv = put_dbkey(handle, &key, dbkey, PR_FALSE);
+ dbkey->nickname = NULL;
+
+ sec_destroy_dbkey(dbkey);
+ }
+ } while ( (* handle->updatedb->seq)(handle->updatedb, &key, &data,
+ R_NEXT) == 0 );
+
+ dbkey = NULL;
+
+done:
+ /* sync the database */
+ ret = (* handle->db->sync)(handle->db, 0);
+
+ (* handle->updatedb->close)(handle->updatedb);
+ handle->updatedb = NULL;
+
+ if ( rc4key ) {
+ SECITEM_FreeItem(rc4key, PR_TRUE);
+ }
+
+ if ( oldSalt ) {
+ SECITEM_FreeItem(oldSalt, PR_TRUE);
+ }
+
+ if ( dbkey ) {
+ sec_destroy_dbkey(dbkey);
+ }
+
+ return(SECSuccess);
+}
+
+NSSLOWKEYDBHandle *
+nsslowkey_OpenKeyDB(PRBool readOnly, NSSLOWKEYDBNameFunc namecb, void *cbarg)
{
- SECKEYKeyDBHandle *handle;
+ NSSLOWKEYDBHandle *handle;
DBT versionKey;
DBT versionData;
int ret;
@@ -570,7 +773,7 @@ SECKEY_OpenKeyDB(PRBool readOnly, SECKEYDBNameFunc namecb, void *cbarg)
char *dbname = NULL;
PRBool updated = PR_FALSE;
- handle = (SECKEYKeyDBHandle *)PORT_ZAlloc (sizeof(SECKEYKeyDBHandle));
+ handle = (NSSLOWKEYDBHandle *)PORT_ZAlloc (sizeof(NSSLOWKEYDBHandle));
if (handle == NULL) {
PORT_SetError (SEC_ERROR_NO_MEMORY);
return NULL;
@@ -585,7 +788,7 @@ SECKEY_OpenKeyDB(PRBool readOnly, SECKEYDBNameFunc namecb, void *cbarg)
openflags = O_RDWR;
}
- dbname = (*namecb)(cbarg, PRIVATE_KEY_DB_FILE_VERSION);
+ dbname = (*namecb)(cbarg, NSSLOWKEY_DB_FILE_VERSION);
if ( dbname == NULL ) {
goto loser;
}
@@ -616,7 +819,7 @@ SECKEY_OpenKeyDB(PRBool readOnly, SECKEYDBNameFunc namecb, void *cbarg)
handle->version = *( (unsigned char *)versionData.data);
- if (handle->version != PRIVATE_KEY_DB_FILE_VERSION ) {
+ if (handle->version != NSSLOWKEY_DB_FILE_VERSION ) {
/* bogus version number record, reset the database */
(* handle->db->close)( handle->db );
handle->db = NULL;
@@ -666,7 +869,7 @@ newdb:
* have a password, then this will fail and we will do the
* update later
*/
- rv = SECKEY_UpdateKeyDBPass1(handle);
+ rv = nsslowkey_UpdateKeyDBPass1(handle);
if ( rv == SECSuccess ) {
updated = PR_TRUE;
}
@@ -716,11 +919,11 @@ loser:
* Close the database
*/
void
-SECKEY_CloseKeyDB(SECKEYKeyDBHandle *handle)
+nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle)
{
if (handle != NULL) {
- if (handle == SECKEY_GetDefaultKeyDB()) {
- SECKEY_SetDefaultKeyDB(NULL);
+ if (handle == nsslowkey_GetDefaultKeyDB()) {
+ nsslowkey_SetDefaultKeyDB(NULL);
}
if (handle->db != NULL) {
(* handle->db->close)(handle->db);
@@ -732,7 +935,7 @@ SECKEY_CloseKeyDB(SECKEYKeyDBHandle *handle)
/* Get the key database version */
int
-SECKEY_GetKeyDBVersion(SECKEYKeyDBHandle *handle)
+nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle)
{
PORT_Assert(handle != NULL);
@@ -744,16 +947,16 @@ SECKEY_GetKeyDBVersion(SECKEYKeyDBHandle *handle)
* not have to pass the handle all over the place.
*/
-static SECKEYKeyDBHandle *sec_default_key_db = NULL;
+static NSSLOWKEYDBHandle *sec_default_key_db = NULL;
void
-SECKEY_SetDefaultKeyDB(SECKEYKeyDBHandle *handle)
+nsslowkey_SetDefaultKeyDB(NSSLOWKEYDBHandle *handle)
{
sec_default_key_db = handle;
}
-SECKEYKeyDBHandle *
-SECKEY_GetDefaultKeyDB(void)
+NSSLOWKEYDBHandle *
+nsslowkey_GetDefaultKeyDB(void)
{
return sec_default_key_db;
}
@@ -762,7 +965,7 @@ SECKEY_GetDefaultKeyDB(void)
* Delete a private key that was stored in the database
*/
SECStatus
-SECKEY_DeleteKey(SECKEYKeyDBHandle *handle, SECItem *pubkey)
+nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, SECItem *pubkey)
{
DBT namekey;
int ret;
@@ -797,112 +1000,66 @@ SECKEY_DeleteKey(SECKEYKeyDBHandle *handle, SECItem *pubkey)
* Store a key in the database, indexed by its public key modulus.(value!)
*/
SECStatus
-SECKEY_StoreKeyByPublicKey(SECKEYKeyDBHandle *handle,
- SECKEYLowPrivateKey *privkey,
+nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
+ NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
- SECKEYLowGetPasswordKey f, void *arg)
+ SECItem *arg)
{
- return SECKEY_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData, nickname,
- f, arg, SECKEY_GetDefaultKeyDBAlg());
+ return nsslowkey_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData,
+ nickname, arg, nsslowkey_GetDefaultKeyDBAlg());
}
/* see if the public key for this cert is in the database filed
* by modulus
*/
-SECStatus
-SECKEY_KeyForCertExists(SECKEYKeyDBHandle *handle, CERTCertificate *cert)
+PRBool
+nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cert)
{
- SECKEYPublicKey *pubkey = NULL;
+ NSSLOWKEYPublicKey *pubkey = NULL;
DBT namekey;
DBT dummy;
int status;
/* get cert's public key */
- pubkey = CERT_ExtractPublicKey(cert);
+ pubkey = nsslowcert_ExtractPublicKey(cert);
if ( pubkey == NULL ) {
- return SECFailure;
+ return PR_FALSE;
}
- /* TNH - make key from SECKEYPublicKey */
+ /* TNH - make key from NSSLOWKEYPublicKey */
switch (pubkey->keyType) {
- case rsaKey:
+ case NSSLOWKEYRSAKey:
namekey.data = pubkey->u.rsa.modulus.data;
namekey.size = pubkey->u.rsa.modulus.len;
break;
- case dsaKey:
+ case NSSLOWKEYDSAKey:
namekey.data = pubkey->u.dsa.publicValue.data;
namekey.size = pubkey->u.dsa.publicValue.len;
break;
- case dhKey:
+ case NSSLOWKEYDHKey:
namekey.data = pubkey->u.dh.publicValue.data;
namekey.size = pubkey->u.dh.publicValue.len;
break;
default:
/* XXX We don't do Fortezza or DH yet. */
- return SECFailure;
+ return PR_FALSE;
}
status = (* handle->db->get)(handle->db, &namekey, &dummy, 0);
- SECKEY_DestroyPublicKey(pubkey);
+ nsslowkey_DestroyPublicKey(pubkey);
if ( status ) {
- /* TNH - should this really set an error? */
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- return SECFailure;
+ return PR_FALSE;
}
- return SECSuccess;
-}
-
-/*
- * find the private key for a cert
- */
-SECKEYLowPrivateKey *
-SECKEY_FindKeyByCert(SECKEYKeyDBHandle *handle, CERTCertificate *cert,
- SECKEYLowGetPasswordKey f, void *arg)
-{
- SECKEYPublicKey *pubkey = NULL;
- SECItem *keyItem = NULL;
- SECKEYLowPrivateKey *privKey = NULL;
-
- /* get cert's public key */
- pubkey = CERT_ExtractPublicKey(cert);
- if ( !pubkey ) {
- goto loser;
- }
-
- /* TNH - make record key from SECKEYPublicKey (again) */
- switch (pubkey->keyType) {
- case rsaKey:
- keyItem = &pubkey->u.rsa.modulus;
- break;
- case dsaKey:
- keyItem = &pubkey->u.dsa.publicValue;
- break;
- case dhKey:
- keyItem = &pubkey->u.dh.publicValue;
- break;
- /* fortezza an NULL keys are not stored in the data base */
- case keaKey:
- case fortezzaKey:
- case nullKey:
- goto loser;
- }
- PORT_Assert( keyItem != NULL );
-
- privKey = SECKEY_FindKeyByPublicKey(handle, keyItem, f, arg);
-
- /* success falls through */
-loser:
- SECKEY_DestroyPublicKey(pubkey);
- return(privKey);
+ return PR_TRUE;
}
/*
* check to see if the user has a password
*/
SECStatus
-SECKEY_HasKeyDBPassword(SECKEYKeyDBHandle *handle)
+nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle)
{
DBT checkkey, checkdata;
int ret;
@@ -933,23 +1090,10 @@ SECKEY_HasKeyDBPassword(SECKEYKeyDBHandle *handle)
* This is done by encrypting a known plaintext with the user's key.
*/
SECStatus
-SECKEY_SetKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem)
-{
- return SECKEY_SetKeyDBPasswordAlg(handle, pwitem,
- SECKEY_GetDefaultKeyDBAlg());
-}
-
-/*
- * Re-encrypt the entire key database with a new password.
- * NOTE: This really should create a new database rather than doing it
- * in place in the original
- */
-SECStatus
-SECKEY_ChangeKeyDBPassword(SECKEYKeyDBHandle *handle,
- SECItem *oldpwitem, SECItem *newpwitem)
+nsslowkey_SetKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem)
{
- return SECKEY_ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem,
- SECKEY_GetDefaultKeyDBAlg());
+ return nsslowkey_SetKeyDBPasswordAlg(handle, pwitem,
+ nsslowkey_GetDefaultKeyDBAlg());
}
static SECStatus
@@ -976,7 +1120,7 @@ HashPassword(unsigned char *hashresult, char *pw, SECItem *salt)
}
SECItem *
-SECKEY_HashPassword(char *pw, SECItem *salt)
+nsslowkey_HashPassword(char *pw, SECItem *salt)
{
SECItem *pwitem;
SECStatus rv;
@@ -1004,13 +1148,13 @@ SECKEY_HashPassword(char *pw, SECItem *salt)
/* Derive the actual password value for the database from a pw string */
SECItem *
-SECKEY_DeriveKeyDBPassword(SECKEYKeyDBHandle *keydb, char *pw)
+nsslowkey_DeriveKeyDBPassword(NSSLOWKEYDBHandle *keydb, char *pw)
{
PORT_Assert(keydb != NULL);
PORT_Assert(pw != NULL);
if (keydb == NULL || pw == NULL) return(NULL);
- return SECKEY_HashPassword(pw, keydb->global_salt);
+ return nsslowkey_HashPassword(pw, keydb->global_salt);
}
#if 0
@@ -1019,11 +1163,11 @@ SECKEY_DeriveKeyDBPassword(SECKEYKeyDBHandle *keydb, char *pw)
* is encrypted.
*/
SECOidTag
-seckey_get_private_key_algorithm(SECKEYKeyDBHandle *keydb, DBT *index)
+seckey_get_private_key_algorithm(NSSLOWKEYDBHandle *keydb, DBT *index)
{
- SECKEYDBKey *dbkey = NULL;
+ NSSLOWKEYDBKey *dbkey = NULL;
SECOidTag algorithm = SEC_OID_UNKNOWN;
- EncryptedPrivateKeyInfo *epki = NULL;
+ NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL;
PLArenaPool *poolp = NULL;
SECStatus rv;
@@ -1035,12 +1179,12 @@ seckey_get_private_key_algorithm(SECKEYKeyDBHandle *keydb, DBT *index)
if(dbkey == NULL)
return (SECOidTag)SECFailure;
- epki = (EncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp,
- sizeof(EncryptedPrivateKeyInfo));
+ epki = (NSSLOWKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp,
+ sizeof(NSSLOWKEYEncryptedPrivateKeyInfo));
if(epki == NULL)
goto loser;
rv = SEC_ASN1DecodeItem(poolp, epki,
- SECKEY_EncryptedPrivateKeyInfoTemplate, &dbkey->derPK);
+ nsslowkey_EncryptedPrivateKeyInfoTemplate, &dbkey->derPK);
if(rv == SECFailure)
goto loser;
@@ -1129,7 +1273,7 @@ seckey_create_rc4_salt(void)
}
SECItem *
-seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt)
+seckey_rc4_decode(SECItem *key, SECItem *src)
{
SECItem *dest = NULL;
RC4Context *ctxt = NULL;
@@ -1149,11 +1293,7 @@ seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt)
ctxt = RC4_CreateContext(key->data, key->len);
if(ctxt != NULL)
{
- if(encrypt == PR_TRUE)
- rv = RC4_Encrypt(ctxt, dest->data, &dest->len,
- src->len + 64, src->data, src->len);
- else
- rv = RC4_Decrypt(ctxt, dest->data, &dest->len,
+ rv = RC4_Decrypt(ctxt, dest->data, &dest->len,
src->len + 64, src->data, src->len);
RC4_DestroyContext(ctxt, PR_TRUE);
}
@@ -1171,19 +1311,21 @@ seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt)
/* TNH - keydb is unused */
/* TNH - the pwitem should be the derived key for RC4 */
-EncryptedPrivateKeyInfo *
+NSSLOWKEYEncryptedPrivateKeyInfo *
seckey_encrypt_private_key(
- SECKEYLowPrivateKey *pk, SECItem *pwitem, SECKEYKeyDBHandle *keydb,
- SECOidTag algorithm)
+ NSSLOWKEYPrivateKey *pk, SECItem *pwitem, NSSLOWKEYDBHandle *keydb,
+ SECOidTag algorithm, SECItem **salt)
{
- EncryptedPrivateKeyInfo *epki = NULL;
- PrivateKeyInfo *pki = NULL;
+ NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL;
+ NSSLOWKEYPrivateKeyInfo *pki = NULL;
SECStatus rv = SECFailure;
- SECAlgorithmID *algid = NULL;
PLArenaPool *temparena = NULL, *permarena = NULL;
- SECItem *key = NULL, *salt = NULL, *der_item = NULL;
+ SECItem *der_item = NULL;
+ NSSPKCS5PBEParameter *param;
SECItem *dummy = NULL, *dest = NULL;
+ SECAlgorithmID *algid;
+ *salt = NULL;
permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if(permarena == NULL)
return NULL;
@@ -1193,10 +1335,10 @@ seckey_encrypt_private_key(
goto loser;
/* allocate structures */
- epki = (EncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(permarena,
- sizeof(EncryptedPrivateKeyInfo));
- pki = (PrivateKeyInfo *)PORT_ArenaZAlloc(temparena,
- sizeof(PrivateKeyInfo));
+ 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))
goto loser;
@@ -1205,15 +1347,15 @@ seckey_encrypt_private_key(
/* setup private key info */
dummy = SEC_ASN1EncodeInteger(temparena, &(pki->version),
- SEC_PRIVATE_KEY_INFO_VERSION);
+ NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
if(dummy == NULL)
goto loser;
/* Encode the key, and set the algorithm (with params) */
switch (pk->keyType) {
- case lowRSAKey:
+ case NSSLOWKEYRSAKey:
dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
- SECKEY_LowRSAPrivateKeyTemplate);
+ nsslowkey_RSAPrivateKeyTemplate);
if (dummy == NULL) {
rv = SECFailure;
goto loser;
@@ -1226,16 +1368,16 @@ seckey_encrypt_private_key(
}
break;
- case lowDSAKey:
+ case NSSLOWKEYDSAKey:
dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
- SECKEY_LowDSAPrivateKeyTemplate);
+ nsslowkey_DSAPrivateKeyTemplate);
if (dummy == NULL) {
rv = SECFailure;
goto loser;
}
dummy = SEC_ASN1EncodeItem(temparena, NULL, &pk->u.dsa.params,
- SECKEY_LowPQGParamsTemplate);
+ nsslowkey_PQGParamsTemplate);
if (dummy == NULL) {
rv = SECFailure;
goto loser;
@@ -1248,9 +1390,9 @@ seckey_encrypt_private_key(
}
break;
- case lowDHKey:
+ case NSSLOWKEYDHKey:
dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
- SECKEY_LowDHPrivateKeyTemplate);
+ nsslowkey_DHPrivateKeyTemplate);
if (dummy == NULL) {
rv = SECFailure;
goto loser;
@@ -1270,85 +1412,72 @@ seckey_encrypt_private_key(
/* setup encrypted private key info */
dummy = SEC_ASN1EncodeItem(temparena, der_item, pki,
- SECKEY_PrivateKeyInfoTemplate);
+ nsslowkey_PrivateKeyInfoTemplate);
if(dummy == NULL) {
rv = SECFailure;
goto loser;
}
rv = SECFailure; /* assume failure */
- switch(algorithm)
- {
- case SEC_OID_RC4:
- salt = seckey_create_rc4_salt();
- if(salt != NULL)
- {
- key = seckey_create_rc4_key(pwitem, salt);
- if(key != NULL)
- {
- dest = seckey_rc4_cipher(key, der_item, PR_TRUE);
- if(dest != NULL)
- {
- rv = SECITEM_CopyItem(permarena, &epki->encryptedData,
- dest);
- if(rv == SECSuccess)
- rv = SECOID_SetAlgorithmID(permarena,
- &epki->algorithm, SEC_OID_RC4, salt);
- }
- }
- }
- if(dest != NULL)
- SECITEM_FreeItem(dest, PR_TRUE);
- if(key != NULL)
- SECITEM_ZfreeItem(key, PR_TRUE);
- break;
- default:
- algid = SEC_PKCS5CreateAlgorithmID(algorithm, NULL, 1);
- if(algid != NULL)
- {
- dest = SEC_PKCS5CipherData(algid, pwitem,
- der_item, PR_TRUE, NULL);
- if(dest != NULL)
- {
- rv = SECITEM_CopyItem(permarena, &epki->encryptedData,
- dest);
- if(rv == SECSuccess)
- rv = SECOID_CopyAlgorithmID(permarena,
- &epki->algorithm, algid);
- }
- }
- if(dest != NULL)
- SECITEM_FreeItem(dest, PR_TRUE);
- if(algid != NULL)
- SECOID_DestroyAlgorithmID(algid, PR_TRUE);
- break;
+ *salt = seckey_create_rc4_salt();
+ if (*salt == NULL) {
+ goto loser;
}
- /* let success fall through */
+ 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);
+ 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);
+
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;
+ epki = NULL;
+ if(*salt != NULL)
+ SECITEM_FreeItem(*salt, PR_TRUE);
}
if(temparena != NULL)
PORT_FreeArena(temparena, PR_TRUE);
-
- if(salt != NULL)
- SECITEM_FreeItem(salt, PR_TRUE);
return epki;
}
-SECStatus
-seckey_put_private_key(SECKEYKeyDBHandle *keydb, DBT *index, SECItem *pwitem,
- SECKEYLowPrivateKey *pk, char *nickname, PRBool update,
+static SECStatus
+seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem,
+ NSSLOWKEYPrivateKey *pk, char *nickname, PRBool update,
SECOidTag algorithm)
{
- SECKEYDBKey *dbkey = NULL;
- EncryptedPrivateKeyInfo *epki = NULL;
+ NSSLOWKEYDBKey *dbkey = NULL;
+ NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL;
PLArenaPool *temparena = NULL, *permarena = NULL;
SECItem *dummy = NULL;
SECItem *salt = NULL;
@@ -1362,7 +1491,7 @@ seckey_put_private_key(SECKEYKeyDBHandle *keydb, DBT *index, SECItem *pwitem,
if(permarena == NULL)
return SECFailure;
- dbkey = (SECKEYDBKey *)PORT_ArenaZAlloc(permarena, sizeof(SECKEYDBKey));
+ dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(permarena, sizeof(NSSLOWKEYDBKey));
if(dbkey == NULL)
goto loser;
dbkey->arena = permarena;
@@ -1370,33 +1499,19 @@ seckey_put_private_key(SECKEYKeyDBHandle *keydb, DBT *index, SECItem *pwitem,
/* TNH - for RC4, the salt should be created here */
- epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm);
+ epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm, &salt);
if(epki == NULL)
goto loser;
temparena = epki->arena;
- /* extract salt for db key */
- switch(algorithm)
+ if(salt != NULL)
{
- case SEC_OID_RC4:
- rv = SECITEM_CopyItem(permarena, &(dbkey->salt),
- &(epki->algorithm.parameters));
- epki->algorithm.parameters.len = 0;
- epki->algorithm.parameters.data = NULL;
- break;
- default:
- /* TNH - this should not be necessary */
- salt = SEC_PKCS5GetSalt(&epki->algorithm);
- if(salt != NULL)
- {
- rv = SECITEM_CopyItem(permarena, &(dbkey->salt), salt);
- SECITEM_ZfreeItem(salt, PR_TRUE);
- }
- break;
+ rv = SECITEM_CopyItem(permarena, &(dbkey->salt), salt);
+ SECITEM_ZfreeItem(salt, PR_TRUE);
}
dummy = SEC_ASN1EncodeItem(permarena, &(dbkey->derPK), epki,
- SECKEY_EncryptedPrivateKeyInfoTemplate);
+ nsslowkey_EncryptedPrivateKeyInfoTemplate);
if(dummy == NULL)
rv = SECFailure;
else
@@ -1418,15 +1533,14 @@ loser:
* Note that the nickname is optional. It was only used by keyutil.
*/
SECStatus
-SECKEY_StoreKeyByPublicKeyAlg(SECKEYKeyDBHandle *handle,
- SECKEYLowPrivateKey *privkey,
+nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
+ NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
- SECKEYLowGetPasswordKey f, void *arg,
+ SECItem *pwitem,
SECOidTag algorithm)
{
DBT namekey;
- SECItem *pwitem = NULL;
SECStatus rv;
if (handle == NULL) {
@@ -1438,29 +1552,24 @@ SECKEY_StoreKeyByPublicKeyAlg(SECKEYKeyDBHandle *handle,
namekey.data = pubKeyData->data;
namekey.size = pubKeyData->len;
- pwitem = (*f )(arg, handle);
- if ( pwitem == NULL ) {
- return(SECFailure);
- }
-
/* encrypt the private key */
rv = seckey_put_private_key(handle, &namekey, pwitem, privkey, nickname,
PR_FALSE, algorithm);
- SECITEM_ZfreeItem(pwitem, PR_TRUE);
return(rv);
}
-SECKEYLowPrivateKey *
-seckey_decrypt_private_key(EncryptedPrivateKeyInfo *epki,
+NSSLOWKEYPrivateKey *
+seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki,
SECItem *pwitem)
{
- SECKEYLowPrivateKey *pk = NULL;
- PrivateKeyInfo *pki = NULL;
+ 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;
if((epki == NULL) || (pwitem == NULL))
goto loser;
@@ -1471,12 +1580,12 @@ seckey_decrypt_private_key(EncryptedPrivateKeyInfo *epki,
goto loser;
/* allocate temporary items */
- pki = (PrivateKeyInfo *)PORT_ArenaZAlloc(temparena,
- sizeof(PrivateKeyInfo));
+ pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(temparena,
+ sizeof(NSSLOWKEYPrivateKeyInfo));
/* allocate permanent arena items */
- pk = (SECKEYLowPrivateKey *)PORT_ArenaZAlloc(permarena,
- sizeof(SECKEYLowPrivateKey));
+ pk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(permarena,
+ sizeof(NSSLOWKEYPrivateKey));
if((pk == NULL) || (pki == NULL))
goto loser;
@@ -1493,8 +1602,7 @@ seckey_decrypt_private_key(EncryptedPrivateKeyInfo *epki,
key = seckey_create_rc4_key(pwitem, salt);
if(key != NULL)
{
- dest = seckey_rc4_cipher(key, &epki->encryptedData,
- PR_FALSE);
+ dest = seckey_rc4_decode(key, &epki->encryptedData);
}
}
if(salt != NULL)
@@ -1506,40 +1614,45 @@ seckey_decrypt_private_key(EncryptedPrivateKeyInfo *epki,
/* 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. */
- dest = SEC_PKCS5CipherData(&epki->algorithm, pwitem,
- &epki->encryptedData, PR_FALSE, NULL);
+ param = nsspkcs5_AlgidToParam(&epki->algorithm);
+ if (param == NULL) {
+ break;
+ }
+ dest = nsspkcs5_CipherData(param, pwitem, &epki->encryptedData,
+ PR_FALSE, NULL);
+ nsspkcs5_DestroyPBEParameter(param);
break;
}
if(dest != NULL)
{
rv = SEC_ASN1DecodeItem(temparena, pki,
- SECKEY_PrivateKeyInfoTemplate, dest);
+ nsslowkey_PrivateKeyInfoTemplate, dest);
if(rv == SECSuccess)
{
switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
case SEC_OID_X500_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_ENCRYPTION:
- pk->keyType = lowRSAKey;
+ pk->keyType = NSSLOWKEYRSAKey;
rv = SEC_ASN1DecodeItem(permarena, pk,
- SECKEY_LowRSAPrivateKeyTemplate,
+ nsslowkey_RSAPrivateKeyTemplate,
&pki->privateKey);
break;
case SEC_OID_ANSIX9_DSA_SIGNATURE:
- pk->keyType = lowDSAKey;
+ pk->keyType = NSSLOWKEYDSAKey;
rv = SEC_ASN1DecodeItem(permarena, pk,
- SECKEY_LowDSAPrivateKeyTemplate,
+ nsslowkey_DSAPrivateKeyTemplate,
&pki->privateKey);
if (rv != SECSuccess)
goto loser;
rv = SEC_ASN1DecodeItem(permarena, &pk->u.dsa.params,
- SECKEY_LowPQGParamsTemplate,
+ nsslowkey_PQGParamsTemplate,
&pki->algorithm.parameters);
break;
case SEC_OID_X942_DIFFIE_HELMAN_KEY:
- pk->keyType = lowDHKey;
+ pk->keyType = NSSLOWKEYDHKey;
rv = SEC_ASN1DecodeItem(permarena, pk,
- SECKEY_LowDHPrivateKeyTemplate,
+ nsslowkey_DHPrivateKeyTemplate,
&pki->privateKey);
break;
default:
@@ -1571,11 +1684,11 @@ loser:
return pk;
}
-static SECKEYLowPrivateKey *
-seckey_decode_encrypted_private_key(SECKEYDBKey *dbkey, SECItem *pwitem)
+static NSSLOWKEYPrivateKey *
+seckey_decode_encrypted_private_key(NSSLOWKEYDBKey *dbkey, SECItem *pwitem)
{
- SECKEYLowPrivateKey *pk = NULL;
- EncryptedPrivateKeyInfo *epki;
+ NSSLOWKEYPrivateKey *pk = NULL;
+ NSSLOWKEYEncryptedPrivateKeyInfo *epki;
PLArenaPool *temparena = NULL;
SECStatus rv;
SECOidTag algorithm;
@@ -1589,15 +1702,15 @@ seckey_decode_encrypted_private_key(SECKEYDBKey *dbkey, SECItem *pwitem)
return NULL;
}
- epki = (EncryptedPrivateKeyInfo *)
- PORT_ArenaZAlloc(temparena, sizeof(EncryptedPrivateKeyInfo));
+ epki = (NSSLOWKEYEncryptedPrivateKeyInfo *)
+ PORT_ArenaZAlloc(temparena, sizeof(NSSLOWKEYEncryptedPrivateKeyInfo));
if(epki == NULL) {
goto loser;
}
rv = SEC_ASN1DecodeItem(temparena, epki,
- SECKEY_EncryptedPrivateKeyInfoTemplate,
+ nsslowkey_EncryptedPrivateKeyInfoTemplate,
&(dbkey->derPK));
if(rv != SECSuccess) {
goto loser;
@@ -1625,12 +1738,12 @@ loser:
return pk;
}
-SECKEYLowPrivateKey *
-seckey_get_private_key(SECKEYKeyDBHandle *keydb, DBT *index, char **nickname,
+NSSLOWKEYPrivateKey *
+seckey_get_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, char **nickname,
SECItem *pwitem)
{
- SECKEYDBKey *dbkey = NULL;
- SECKEYLowPrivateKey *pk = NULL;
+ NSSLOWKEYDBKey *dbkey = NULL;
+ NSSLOWKEYPrivateKey *pk = NULL;
if( ( keydb == NULL ) || ( index == NULL ) || ( pwitem == NULL ) ) {
return NULL;
@@ -1665,9 +1778,9 @@ loser:
* used by pkcs11 to import keys into it's object format... In the future
* we really need a better way to tie in...
*/
-SECKEYLowPrivateKey *
-SECKEY_DecryptKey(DBT *key, SECItem *pwitem,
- SECKEYKeyDBHandle *handle) {
+NSSLOWKEYPrivateKey *
+nsslowkey_DecryptKey(DBT *key, SECItem *pwitem,
+ NSSLOWKEYDBHandle *handle) {
return seckey_get_private_key(handle,key,NULL,pwitem);
}
@@ -1678,13 +1791,12 @@ SECKEY_DecryptKey(DBT *key, SECItem *pwitem,
* is looked up by the public modulus in the certificate, and the
* re-stored by its nickname.
*/
-SECKEYLowPrivateKey *
-SECKEY_FindKeyByPublicKey(SECKEYKeyDBHandle *handle, SECItem *modulus,
- SECKEYLowGetPasswordKey f, void *arg)
+NSSLOWKEYPrivateKey *
+nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
+ SECItem *pwitem)
{
DBT namekey;
- SECKEYLowPrivateKey *pk = NULL;
- SECItem *pwitem = NULL;
+ NSSLOWKEYPrivateKey *pk = NULL;
if (handle == NULL) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
@@ -1695,13 +1807,7 @@ SECKEY_FindKeyByPublicKey(SECKEYKeyDBHandle *handle, SECItem *modulus,
namekey.data = modulus->data;
namekey.size = modulus->len;
- pwitem = (*f )(arg, handle);
- if ( pwitem == NULL ) {
- return(NULL);
- }
-
pk = seckey_get_private_key(handle, &namekey, NULL, pwitem);
- SECITEM_ZfreeItem(pwitem, PR_TRUE);
/* no need to free dbkey, since its on the stack, and the data it
* points to is owned by the database
@@ -1754,15 +1860,15 @@ loser:
* This is done by encrypting a known plaintext with the user's key.
*/
SECStatus
-SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
+nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
SECItem *pwitem, SECOidTag algorithm)
{
DBT checkkey;
- SECAlgorithmID *algid = NULL;
+ NSSPKCS5PBEParameter *param = NULL;
SECStatus rv = SECFailure;
- SECKEYDBKey *dbkey = NULL;
+ NSSLOWKEYDBKey *dbkey = NULL;
PLArenaPool *arena;
- SECItem *key = NULL, *salt = NULL;
+ SECItem *salt = NULL;
SECItem *dest = NULL, test_key;
if (handle == NULL) {
@@ -1775,7 +1881,7 @@ SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
goto loser;
}
- dbkey = (SECKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYDBKey));
+ dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYDBKey));
if ( dbkey == NULL ) {
rv = SECFailure;
goto loser;
@@ -1793,40 +1899,31 @@ SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
goto loser;
}
- switch(algorithm)
- {
- case SEC_OID_RC4:
- key = seckey_create_rc4_key(pwitem, salt);
- if(key != NULL)
- {
- dest = seckey_rc4_cipher(key, &test_key, PR_TRUE);
- SECITEM_FreeItem(key, PR_TRUE);
- }
- break;
- default:
- algid = SEC_PKCS5CreateAlgorithmID(algorithm, salt, 1);
- if(algid != NULL)
- dest = SEC_PKCS5CipherData(algid, pwitem, &test_key,
- PR_TRUE, NULL);
- break;
+ param = nsspkcs5_NewParam(algorithm, salt, 1);
+ if (param == NULL) {
+ rv = SECFailure;
+ goto loser;
}
- if(dest != NULL)
+ dest = nsspkcs5_CipherData(param, pwitem, &test_key, PR_TRUE, NULL);
+ if (dest == NULL)
{
- rv = SECITEM_CopyItem(arena, &dbkey->salt, salt);
- if(rv == SECFailure)
- goto loser;
+ 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 = encodePWCheckEntry(arena, &dbkey->derPK, algorithm, dest);
- rv = put_dbkey(handle, &checkkey, dbkey, PR_TRUE);
- } else {
- rv = SECFailure;
+ if ( rv != SECSuccess ) {
+ goto loser;
}
+
+ rv = put_dbkey(handle, &checkkey, dbkey, PR_TRUE);
/* let success fall through */
loser:
@@ -1841,6 +1938,10 @@ loser:
if ( salt != NULL ) {
SECITEM_ZfreeItem(salt, PR_TRUE);
}
+
+ if (param != NULL) {
+ nsspkcs5_DestroyPBEParameter(param);
+ }
return(rv);
}
@@ -1896,12 +1997,12 @@ seckey_HasAServerKey(DB *db)
}
static SECStatus
-seckey_CheckKeyDB1Password(SECKEYKeyDBHandle *handle, SECItem *pwitem)
+seckey_CheckKeyDB1Password(NSSLOWKEYDBHandle *handle, SECItem *pwitem)
{
SECStatus rv = SECFailure;
keyList keylist;
keyNode *node = NULL;
- SECKEYLowPrivateKey *privkey = NULL;
+ NSSLOWKEYPrivateKey *privkey = NULL;
/*
@@ -1919,7 +2020,7 @@ seckey_CheckKeyDB1Password(SECKEYKeyDBHandle *handle, SECItem *pwitem)
/* TNH - TraverseKeys should not be public, since it exposes
the underlying DBT data type. */
- rv = SECKEY_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist);
+ rv = nsslowkey_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist);
if ( rv != SECSuccess )
goto done;
@@ -1939,7 +2040,7 @@ seckey_CheckKeyDB1Password(SECKEYKeyDBHandle *handle, SECItem *pwitem)
/* if we can decrypt the private key, then we had the correct password */
rv = SECSuccess;
- SECKEY_LowDestroyPrivateKey(privkey);
+ nsslowkey_DestroyPrivateKey(privkey);
done:
@@ -1955,13 +2056,13 @@ done:
* check to see if the user has typed the right password
*/
SECStatus
-SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem)
+nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem)
{
DBT checkkey;
DBT checkdata;
- SECAlgorithmID *algid = NULL;
+ NSSPKCS5PBEParameter *param = NULL;
SECStatus rv = SECFailure;
- SECKEYDBKey *dbkey = NULL;
+ NSSLOWKEYDBKey *dbkey = NULL;
SECItem *key = NULL;
SECItem *dest = NULL;
SECOidTag algorithm;
@@ -1993,7 +2094,7 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem)
rv = seckey_CheckKeyDB1Password(handle,pwitem);
if (rv == SECSuccess) {
/* OK we have enough to complete our conversion */
- SECKEY_UpdateKeyDBPass2(handle,pwitem);
+ nsslowkey_UpdateKeyDBPass2(handle,pwitem);
}
return rv;
}
@@ -2022,14 +2123,13 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem)
case SEC_OID_RC4:
key = seckey_create_rc4_key(pwitem, &dbkey->salt);
if(key != NULL) {
- dest = seckey_rc4_cipher(key, &encstring, PR_FALSE);
+ dest = seckey_rc4_decode(key, &encstring);
SECITEM_FreeItem(key, PR_TRUE);
}
break;
default:
- algid = SEC_PKCS5CreateAlgorithmID(algorithm,
- &dbkey->salt, 1);
- if(algid != NULL) {
+ 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
@@ -2037,9 +2137,9 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem)
* set to TRUE. This indication is used later to force
* an update of the database to "real" 3DES encryption.
*/
- dest = SEC_PKCS5CipherData(algid, pwitem,
+ dest = nsspkcs5_CipherData(param, pwitem,
&encstring, PR_FALSE, &update);
- SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+ nsspkcs5_DestroyPBEParameter(param);
}
break;
}
@@ -2055,7 +2155,7 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem)
/* we succeeded */
if ( algorithm == SEC_OID_RC4 ) {
/* partially updated database */
- SECKEY_UpdateKeyDBPass2(handle, pwitem);
+ nsslowkey_UpdateKeyDBPass2(handle, pwitem);
}
/* Force an update of the password to remove the incorrect DES
* encryption (see the note above)
@@ -2063,7 +2163,7 @@ SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem)
if (update &&
(algorithm == SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC)) {
/* data base was encoded with DES not triple des, fix it */
- SECKEY_UpdateKeyDBPass2(handle,pwitem);
+ nsslowkey_UpdateKeyDBPass2(handle,pwitem);
}
}
@@ -2082,14 +2182,14 @@ loser:
* the caller.
*/
static SECStatus
-ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
+ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
SECItem *oldpwitem, SECItem *newpwitem,
SECOidTag new_algorithm)
{
SECStatus rv;
keyList keylist;
keyNode *node = NULL;
- SECKEYLowPrivateKey *privkey = NULL;
+ NSSLOWKEYPrivateKey *privkey = NULL;
char *nickname;
DBT newkey;
int ret;
@@ -2105,7 +2205,7 @@ ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
/* TNH - TraverseKeys should not be public, since it exposes
the underlying DBT data type. */
- rv = SECKEY_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist);
+ rv = nsslowkey_TraverseKeys(handle, sec_add_key_to_list, (void *)&keylist);
if ( rv != SECSuccess )
goto loser;
@@ -2133,20 +2233,19 @@ ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
/* get the public key, which we use as the database index */
switch (privkey->keyType) {
- case lowRSAKey:
+ case NSSLOWKEYRSAKey:
newkey.data = privkey->u.rsa.modulus.data;
newkey.size = privkey->u.rsa.modulus.len;
break;
- case lowDSAKey:
+ case NSSLOWKEYDSAKey:
newkey.data = privkey->u.dsa.publicValue.data;
newkey.size = privkey->u.dsa.publicValue.len;
break;
- case lowDHKey:
+ case NSSLOWKEYDHKey:
newkey.data = privkey->u.dh.publicValue.data;
newkey.size = privkey->u.dh.publicValue.len;
break;
default:
- /* XXX We don't do Fortezza. */
return SECFailure;
}
@@ -2164,7 +2263,7 @@ ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
node = node->next;
}
- rv = SECKEY_SetKeyDBPasswordAlg(handle, newpwitem, new_algorithm);
+ rv = nsslowkey_SetKeyDBPasswordAlg(handle, newpwitem, new_algorithm);
loser:
@@ -2182,9 +2281,8 @@ loser:
* in place in the original
*/
SECStatus
-SECKEY_ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
- SECItem *oldpwitem, SECItem *newpwitem,
- SECOidTag new_algorithm)
+nsslowkey_ChangeKeyDBPassword(NSSLOWKEYDBHandle *handle,
+ SECItem *oldpwitem, SECItem *newpwitem)
{
SECStatus rv;
@@ -2194,240 +2292,25 @@ SECKEY_ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
goto loser;
}
- rv = SECKEY_CheckKeyDBPassword(handle, oldpwitem);
+ rv = nsslowkey_CheckKeyDBPassword(handle, oldpwitem);
if ( rv != SECSuccess ) {
return(SECFailure); /* return rv? */
}
- rv = ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem, new_algorithm);
+ rv = ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem,
+ nsslowkey_GetDefaultKeyDBAlg());
loser:
return(rv);
}
-/*
- * Second pass of updating the key db. This time we have a password.
- */
-SECStatus
-SECKEY_UpdateKeyDBPass2(SECKEYKeyDBHandle *handle, SECItem *pwitem)
-{
- SECStatus rv;
-
- rv = ChangeKeyDBPasswordAlg(handle, pwitem, pwitem,
- SECKEY_GetDefaultKeyDBAlg());
-
- return(rv);
-}
-
-/*
- * currently updates key database from v2 to v3
- */
-SECStatus
-SECKEY_UpdateKeyDBPass1(SECKEYKeyDBHandle *handle)
-{
- SECStatus rv;
- DBT versionKey;
- DBT versionData;
- DBT checkKey;
- DBT checkData;
- DBT saltKey;
- DBT saltData;
- DBT key;
- DBT data;
- SECItem *rc4key = NULL;
- SECKEYDBKey *dbkey = NULL;
- SECItem *oldSalt = NULL;
- int ret;
- SECItem checkitem;
-
- if ( handle->updatedb == NULL ) {
- return(SECSuccess);
- }
-
- /*
- * check the version record
- */
- versionKey.data = VERSION_STRING;
- versionKey.size = sizeof(VERSION_STRING)-1;
-
- ret = (* handle->updatedb->get)(handle->updatedb, &versionKey,
- &versionData, 0 );
-
- if (ret) {
- /* no version record, so old db never used */
- goto done;
- }
-
- if ( ( versionData.size != 1 ) ||
- ( *((unsigned char *)versionData.data) != 2 ) ) {
- /* corrupt or wrong version number so don't update */
- goto done;
- }
-
- saltKey.data = SALT_STRING;
- saltKey.size = sizeof(SALT_STRING) - 1;
-
- ret = (* handle->updatedb->get)(handle->updatedb, &saltKey, &saltData, 0);
- if ( ret ) {
- /* no salt in old db, so it is corrupted */
- goto done;
- }
-
- oldSalt = decodeKeyDBGlobalSalt(&saltData);
- if ( oldSalt == NULL ) {
- /* bad salt in old db, so it is corrupted */
- goto done;
- }
-
- /*
- * look for a pw check entry
- */
- checkKey.data = KEYDB_PW_CHECK_STRING;
- checkKey.size = KEYDB_PW_CHECK_LEN;
-
- ret = (* handle->updatedb->get)(handle->updatedb, &checkKey,
- &checkData, 0 );
- if (ret) {
- /*
- * if we have a key, but no KEYDB_PW_CHECK_STRING, then this must
- * be an old server database, and it does have a password associated
- * with it. Put a fake entry in so we can identify this db when we do
- * get the password for it.
- */
- if (seckey_HasAServerKey(handle->updatedb)) {
- DBT fcheckKey;
- DBT fcheckData;
-
- /*
- * include a fake string
- */
- fcheckKey.data = KEYDB_FAKE_PW_CHECK_STRING;
- fcheckKey.size = KEYDB_FAKE_PW_CHECK_LEN;
- fcheckData.data = "1";
- fcheckData.size = 1;
- /* put global salt into the new database now */
- ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0);
- if ( ret ) {
- goto done;
- }
- ret = (* handle->db->put)( handle->db, &fcheckKey, &fcheckData, 0);
- if ( ret ) {
- goto done;
- }
- } else {
- goto done;
- }
- } else {
- /* put global salt into the new database now */
- ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0);
- if ( ret ) {
- goto done;
- }
-
- dbkey = decode_dbkey(&checkData, 2);
- if ( dbkey == NULL ) {
- goto done;
- }
- checkitem = dbkey->derPK;
- dbkey->derPK.data = NULL;
-
- /* format the new pw check entry */
- rv = encodePWCheckEntry(NULL, &dbkey->derPK, SEC_OID_RC4, &checkitem);
- if ( rv != SECSuccess ) {
- goto done;
- }
-
- rv = put_dbkey(handle, &checkKey, dbkey, PR_TRUE);
- if ( rv != SECSuccess ) {
- goto done;
- }
-
- /* free the dbkey */
- sec_destroy_dbkey(dbkey);
- dbkey = NULL;
- }
-
-
- /* now traverse the database */
- ret = (* handle->updatedb->seq)(handle->updatedb, &key, &data, R_FIRST);
- if ( ret ) {
- goto done;
- }
-
- do {
- /* skip version record */
- if ( data.size > 1 ) {
- /* skip salt */
- if ( key.size == ( sizeof(SALT_STRING) - 1 ) ) {
- if ( PORT_Memcmp(key.data, SALT_STRING, key.size) == 0 ) {
- continue;
- }
- }
- /* skip pw check entry */
- if ( key.size == checkKey.size ) {
- if ( PORT_Memcmp(key.data, checkKey.data, key.size) == 0 ) {
- continue;
- }
- }
-
- /* keys stored by nickname will have 0 as the last byte of the
- * db key. Other keys must be stored by modulus. We will not
- * update those because they are left over from a keygen that
- * never resulted in a cert.
- */
- if ( ((unsigned char *)key.data)[key.size-1] != 0 ) {
- continue;
- }
-
- dbkey = decode_dbkey(&data, 2);
- if ( dbkey == NULL ) {
- continue;
- }
-
- /* This puts the key into the new database with the same
- * index (nickname) that it had before. The second pass
- * of the update will have the password. It will decrypt
- * and re-encrypt the entries using a new algorithm.
- */
- dbkey->nickname = (char *)key.data;
- rv = put_dbkey(handle, &key, dbkey, PR_FALSE);
- dbkey->nickname = NULL;
-
- sec_destroy_dbkey(dbkey);
- }
- } while ( (* handle->updatedb->seq)(handle->updatedb, &key, &data,
- R_NEXT) == 0 );
-
- dbkey = NULL;
-
-done:
- /* sync the database */
- ret = (* handle->db->sync)(handle->db, 0);
-
- (* handle->updatedb->close)(handle->updatedb);
- handle->updatedb = NULL;
-
- if ( rc4key ) {
- SECITEM_FreeItem(rc4key, PR_TRUE);
- }
-
- if ( oldSalt ) {
- SECITEM_FreeItem(oldSalt, PR_TRUE);
- }
-
- if ( dbkey ) {
- sec_destroy_dbkey(dbkey);
- }
-
- return(SECSuccess);
-}
#define MAX_DB_SIZE 0xffff
/*
* Clear out all the keys in the existing database
*/
SECStatus
-SECKEY_ResetKeyDB(SECKEYKeyDBHandle *handle)
+nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
{
SECStatus rv;
int ret;
@@ -2478,12 +2361,3 @@ done:
return (errors == 0 ? SECSuccess : SECFailure);
}
-
-/* These functions simply return the address of the above-declared templates.
-** This is necessary for Windows DLLs. Sigh.
-*/
-SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate)
-SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate)
-SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate)
-SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate)
-
diff --git a/security/nss/lib/softoken/private.h b/security/nss/lib/softoken/keydbi.h
index 0125c7e7b..28eb962ad 100644
--- a/security/nss/lib/softoken/private.h
+++ b/security/nss/lib/softoken/keydbi.h
@@ -35,8 +35,8 @@
* $Id$
*/
-#ifndef _PRIVATE_H_
-#define _PRIVATE_H_
+#ifndef _KEYDBI_H_
+#define _KEYDBI_H_
#include "nspr.h"
#include "seccomon.h"
@@ -45,7 +45,7 @@
/*
* Handle structure for open key databases
*/
-struct SECKEYKeyDBHandleStr {
+struct NSSLOWKEYDBHandleStr {
DB *db;
DB *updatedb; /* used when updating an old version */
SECItem *global_salt; /* password hashing salt for this db */
@@ -60,7 +60,7 @@ struct SECKEYKeyDBHandleStr {
** "data" is the key data
** "pdata" is the user's data
*/
-typedef SECStatus (* SECKEYTraverseKeysFunc)(DBT *key, DBT *data, void *pdata);
+typedef SECStatus (* NSSLOWKEYTraverseKeysFunc)(DBT *key, DBT *data, void *pdata);
SEC_BEGIN_PROTOS
@@ -71,10 +71,10 @@ SEC_BEGIN_PROTOS
** "f" is the user function to call for each key
** "udata" is the user's data, which is passed through to "f"
*/
-extern SECStatus SECKEY_TraverseKeys(SECKEYKeyDBHandle *handle,
- SECKEYTraverseKeysFunc f,
+extern SECStatus NSSLOWKEY_TraverseKeys(NSSLOWKEYDBHandle *handle,
+ NSSLOWKEYTraverseKeysFunc f,
void *udata);
SEC_END_PROTOS
-#endif /* _PRIVATE_H_ */
+#endif /* _KEYDBI_H_ */
diff --git a/security/nss/lib/softoken/keydbt.h b/security/nss/lib/softoken/keydbt.h
deleted file mode 100644
index 5cb574b47..000000000
--- a/security/nss/lib/softoken/keydbt.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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 Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- *
- * keydbt.h - private data structures for the private key library
- *
- * $Id$
- */
-
-#ifndef _KEYDBT_H_
-#define _KEYDBT_H_
-
-#include "prtypes.h"
-#include "plarena.h"
-#include "secitem.h"
-#include "secasn1t.h"
-#include "secmodt.h"
-#include "pkcs11t.h"
-
-
-/*
- * a key in/for the data base
- */
-struct SECKEYDBKeyStr {
- PLArenaPool *arena;
- int version;
- char *nickname;
- SECItem salt;
- SECItem derPK;
-};
-typedef struct SECKEYDBKeyStr SECKEYDBKey;
-
-typedef struct SECKEYKeyDBHandleStr SECKEYKeyDBHandle;
-
-#define PRIVATE_KEY_DB_FILE_VERSION 3
-
-#define SEC_PRIVATE_KEY_VERSION 0 /* what we *create* */
-
-/*
-** Typedef for callback to get a password "key".
-*/
-typedef SECItem * (* SECKEYLowGetPasswordKey)(void *arg,
- SECKEYKeyDBHandle *handle);
-
-extern const SEC_ASN1Template SECKEY_LowPQGParamsTemplate[];
-extern const SEC_ASN1Template SECKEY_LowRSAPrivateKeyTemplate[];
-extern const SEC_ASN1Template SECKEY_LowDSAPrivateKeyTemplate[];
-extern const SEC_ASN1Template SECKEY_LowDSAPrivateKeyExportTemplate[];
-extern const SEC_ASN1Template SECKEY_LowDHPrivateKeyTemplate[];
-extern const SEC_ASN1Template SECKEY_LowDHPrivateKeyExportTemplate[];
-
-extern const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[];
-extern const SEC_ASN1Template SECKEY_AttributeTemplate[];
-
-/* These functions simply return the address of the above-declared templates.
-** This is necessary for Windows DLLs. Sigh.
-*/
-extern SEC_ASN1TemplateChooser NSS_Get_SECKEY_EncryptedPrivateKeyInfoTemplate;
-
-#endif /* _KEYDBT_H_ */
diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c
new file mode 100644
index 000000000..0cea4e396
--- /dev/null
+++ b/security/nss/lib/softoken/lowcert.c
@@ -0,0 +1,525 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Certificate handling code
+ *
+ * $Id$
+ */
+
+#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"
+
+/* should have been in a 'util' header */
+extern const SEC_ASN1Template CERT_ValidityTemplate[];
+
+static const SEC_ASN1Template nsslowcert_CertKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWCERTCertKey) },
+ { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_CONTEXT_SPECIFIC | 0, 0, SEC_SkipTemplate }, /* version */
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertKey,serialNumber) },
+ { SEC_ASN1_SKIP }, /* signature algorithm */
+ { SEC_ASN1_ANY, offsetof(NSSLOWCERTCertKey,derIssuer) },
+ { SEC_ASN1_SKIP_REST },
+ { 0 }
+};
+
+const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
+ { SEC_ASN1_INLINE, offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm),
+ SECOID_AlgorithmIDTemplate },
+ { SEC_ASN1_BIT_STRING,
+ offsetof(NSSLOWCERTSubjectPublicKeyInfo,subjectPublicKey), },
+ { 0, }
+};
+
+const SEC_ASN1Template nsslowcert_CertificateTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWCERTCertificate) },
+ { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_CONTEXT_SPECIFIC | 0, 0, SEC_SkipTemplate }, /* version */
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) },
+ { SEC_ASN1_SKIP }, /* Signature algorithm */
+ { SEC_ASN1_ANY, offsetof(NSSLOWCERTCertificate,derIssuer) },
+ { SEC_ASN1_INLINE,
+ offsetof(NSSLOWCERTCertificate,validity),
+ CERT_ValidityTemplate },
+ { SEC_ASN1_ANY, offsetof(NSSLOWCERTCertificate,derSubject) },
+ { SEC_ASN1_INLINE,
+ offsetof(NSSLOWCERTCertificate,subjectPublicKeyInfo),
+ nsslowcert_SubjectPublicKeyInfoTemplate },
+ { SEC_ASN1_SKIP_REST },
+ { 0 }
+};
+const SEC_ASN1Template nsslowcert_SignedCertificateTemplate[] =
+{
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTCertificate) },
+ { SEC_ASN1_INLINE, 0, nsslowcert_CertificateTemplate },
+ { SEC_ASN1_SKIP_REST },
+ { 0 }
+};
+const SEC_ASN1Template nsslowcert_SignedDataTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSignedData) },
+ { SEC_ASN1_ANY, offsetof(NSSLOWCERTSignedData,data), },
+ { SEC_ASN1_SKIP_REST },
+ { 0, }
+};
+const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.modulus), },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.publicExponent), },
+ { 0, }
+};
+const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), },
+ { 0, }
+};
+const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), },
+ { 0, }
+};
+
+
+static PZLock *pcertRefCountLock = NULL;
+
+/*
+ * Acquire the cert reference count lock
+ * There is currently one global lock for all certs, but I'm putting a 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
+nsslowcert_LockCertRefCount(NSSLOWCERTCertificate *cert)
+{
+ if ( pcertRefCountLock == NULL ) {
+ nss_InitLock(&pcertRefCountLock, nssILockRefLock);
+ PORT_Assert(pcertRefCountLock != NULL);
+ }
+
+ PZ_Lock(pcertRefCountLock);
+ return;
+}
+
+/*
+ * Free the cert reference count lock
+ */
+void
+nsslowcert_UnlockCertRefCount(NSSLOWCERTCertificate *cert)
+{
+ PRStatus prstat;
+
+ PORT_Assert(pcertRefCountLock != NULL);
+
+ prstat = PZ_Unlock(pcertRefCountLock);
+
+ PORT_Assert(prstat == PR_SUCCESS);
+
+ return;
+}
+
+
+NSSLOWCERTCertificate *
+nsslowcert_DupCertificate(NSSLOWCERTCertificate *c)
+{
+ if (c) {
+ nsslowcert_LockCertRefCount(c);
+ ++c->referenceCount;
+ nsslowcert_UnlockCertRefCount(c);
+ }
+ return c;
+}
+
+/*
+ * 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);
+}
+
+
+SECStatus
+nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
+{
+ int rv;
+
+ /* convert DER not-before time */
+ rv = DER_UTCTimeToTime(notBefore, &c->validity.notBefore);
+ if (rv) {
+ return(SECFailure);
+ }
+
+ /* convert DER not-after time */
+ rv = DER_UTCTimeToTime(notAfter, &c->validity.notAfter);
+ if (rv) {
+ return(SECFailure);
+ }
+
+ return(SECSuccess);
+}
+
+/*
+ * is certa newer than certb? If one is expired, pick the other one.
+ */
+PRBool
+nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
+{
+ PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
+ SECStatus rv;
+ PRBool newerbefore, newerafter;
+
+ rv = nsslowcert_GetCertTimes(certa, &notBeforeA, &notAfterA);
+ if ( rv != SECSuccess ) {
+ return(PR_FALSE);
+ }
+
+ rv = nsslowcert_GetCertTimes(certb, &notBeforeB, &notAfterB);
+ if ( rv != SECSuccess ) {
+ return(PR_TRUE);
+ }
+
+ newerbefore = PR_FALSE;
+ if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
+ newerbefore = PR_TRUE;
+ }
+
+ newerafter = PR_FALSE;
+ if ( LL_CMP(notAfterA, >, notAfterB) ) {
+ newerafter = PR_TRUE;
+ }
+
+ if ( newerbefore && newerafter ) {
+ return(PR_TRUE);
+ }
+
+ if ( ( !newerbefore ) && ( !newerafter ) ) {
+ return(PR_FALSE);
+ }
+
+ /* get current UTC time */
+ now = PR_Now();
+
+ if ( newerbefore ) {
+ /* cert A was issued after cert B, but expires sooner */
+ /* if A is expired, then pick B */
+ if ( LL_CMP(notAfterA, <, now ) ) {
+ return(PR_FALSE);
+ }
+ return(PR_TRUE);
+ } else {
+ /* cert B was issued after cert A, but expires sooner */
+ /* if B is expired, then pick A */
+ if ( LL_CMP(notAfterB, <, now ) ) {
+ return(PR_TRUE);
+ }
+ return(PR_FALSE);
+ }
+}
+
+#define SOFT_DEFAULT_CHUNKSIZE 2048
+
+/*
+ * take a DER certificate and decode it into a certificate structure
+ */
+NSSLOWCERTCertificate *
+nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER,
+ char *nickname)
+{
+ NSSLOWCERTCertificate *cert;
+ PRArenaPool *arena;
+ void *data;
+ int rv;
+ int len;
+
+ /* make a new arena */
+ arena = PORT_NewArena(SOFT_DEFAULT_CHUNKSIZE);
+
+ if ( !arena ) {
+ return 0;
+ }
+
+ /* allocate the certificate structure */
+ cert = (NSSLOWCERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWCERTCertificate));
+
+ if ( !cert ) {
+ goto loser;
+ }
+
+ cert->arena = arena;
+
+ if ( copyDER ) {
+ /* copy the DER data for the cert into this arena */
+ data = (void *)PORT_ArenaAlloc(arena, derSignedCert->len);
+ if ( !data ) {
+ goto loser;
+ }
+ cert->derCert.data = (unsigned char *)data;
+ cert->derCert.len = derSignedCert->len;
+ PORT_Memcpy(data, derSignedCert->data, derSignedCert->len);
+ } else {
+ /* point to passed in DER data */
+ cert->derCert = *derSignedCert;
+ }
+
+ /* decode the certificate info */
+ rv = SEC_ASN1DecodeItem(arena, cert, nsslowcert_SignedCertificateTemplate,
+ &cert->derCert);
+
+ /* cert->subjectKeyID; x509v3 subject key identifier */
+ cert->dbEntry = NULL;
+ cert ->trust = NULL;
+
+#ifdef notdef
+ /* these fields are used by client GUI code to keep track of ssl sockets
+ * that are blocked waiting on GUI feedback related to this cert.
+ * XXX - these should be moved into some sort of application specific
+ * data structure. They are only used by the browser right now.
+ */
+ struct SECSocketNode *socketlist;
+ int socketcount;
+ struct SECSocketNode *authsocketlist;
+ int authsocketcount;
+
+ /* This is PKCS #11 stuff. */
+ PK11SlotInfo *slot; /*if this cert came of a token, which is it*/
+ CK_OBJECT_HANDLE pkcs11ID; /*and which object on that token is it */
+ PRBool ownSlot; /*true if the cert owns the slot reference */
+#endif
+
+ /* generate and save the database key for the cert */
+ rv = nsslowcert_KeyFromDERCert(arena, &cert->derCert, &cert->certKey);
+ if ( rv ) {
+ goto loser;
+ }
+
+ /* set the nickname */
+ if ( nickname == NULL ) {
+ cert->nickname = NULL;
+ } else {
+ /* copy and install the nickname */
+ len = PORT_Strlen(nickname) + 1;
+ cert->nickname = (char*)PORT_ArenaAlloc(arena, len);
+ if ( cert->nickname == NULL ) {
+ goto loser;
+ }
+
+ PORT_Memcpy(cert->nickname, nickname, len);
+ }
+
+#ifdef FIXME
+ /* initialize the subjectKeyID */
+ rv = cert_GetKeyID(cert);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* set the email address */
+ cert->emailAddr = CERT_GetCertificateEmailAddress(cert);
+
+#endif
+
+ cert->referenceCount = 1;
+
+ return(cert);
+
+loser:
+
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(0);
+}
+
+char *
+nsslowcert_FixupEmailAddr(char *emailAddr)
+{
+ char *retaddr;
+ char *str;
+
+ if ( emailAddr == NULL ) {
+ return(NULL);
+ }
+
+ /* copy the string */
+ str = retaddr = PORT_Strdup(emailAddr);
+ if ( str == NULL ) {
+ return(NULL);
+ }
+
+ /* make it lower case */
+ while ( *str ) {
+ *str = tolower( *str );
+ str++;
+ }
+
+ return(retaddr);
+}
+
+static SECStatus
+nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn,
+ SECItem *key)
+{
+ key->len = sn->len + issuer->len;
+
+ key->data = (unsigned char*)PORT_ArenaAlloc(arena, key->len);
+ if ( !key->data ) {
+ goto loser;
+ }
+
+ /* copy the serialNumber */
+ PORT_Memcpy(key->data, sn->data, sn->len);
+
+ /* copy the issuer */
+ PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+
+
+/*
+ * Generate a database key, based on serial number and issuer, from a
+ * DER certificate.
+ */
+SECStatus
+nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
+{
+ int rv;
+ NSSLOWCERTSignedData sd;
+ NSSLOWCERTCertKey certkey;
+
+ PORT_Memset(&sd, 0, sizeof(NSSLOWCERTSignedData));
+ PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
+
+ rv = SEC_ASN1DecodeItem(arena, &sd, nsslowcert_SignedDataTemplate, derCert);
+
+ if ( rv ) {
+ goto loser;
+ }
+
+ PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
+ rv = SEC_ASN1DecodeItem(arena, &certkey,
+ nsslowcert_CertKeyTemplate, &sd.data);
+
+ if ( rv ) {
+ goto loser;
+ }
+
+ return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
+ &certkey.serialNumber, key));
+loser:
+ return(SECFailure);
+}
+
+NSSLOWKEYPublicKey *
+nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
+{
+ NSSLOWCERTSubjectPublicKeyInfo *spki = &cert->subjectPublicKeyInfo;
+ NSSLOWKEYPublicKey *pubk;
+ SECItem os;
+ SECStatus rv;
+ PRArenaPool *arena;
+ SECOidTag tag;
+
+ arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL)
+ return NULL;
+
+ pubk = (NSSLOWKEYPublicKey *)
+ PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPublicKey));
+ if (pubk == NULL) {
+ PORT_FreeArena (arena, PR_FALSE);
+ return NULL;
+ }
+
+ pubk->arena = arena;
+
+ /* Convert bit string length from bits to bytes */
+ os = spki->subjectPublicKey;
+ DER_ConvertBitString (&os);
+
+ tag = SECOID_GetAlgorithmTag(&spki->algorithm);
+ switch ( tag ) {
+ case SEC_OID_X500_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ pubk->keyType = NSSLOWKEYRSAKey;
+ rv = SEC_ASN1DecodeItem(arena, pubk,
+ nsslowcert_RSAPublicKeyTemplate, &os);
+ if (rv == SECSuccess)
+ return pubk;
+ break;
+ case SEC_OID_ANSIX9_DSA_SIGNATURE:
+ pubk->keyType = NSSLOWKEYDSAKey;
+ rv = SEC_ASN1DecodeItem(arena, pubk,
+ nsslowcert_DSAPublicKeyTemplate, &os);
+ if (rv == SECSuccess) return pubk;
+ break;
+ case SEC_OID_X942_DIFFIE_HELMAN_KEY:
+ pubk->keyType = NSSLOWKEYDHKey;
+ rv = SEC_ASN1DecodeItem(arena, pubk,
+ nsslowcert_DHPublicKeyTemplate, &os);
+ if (rv == SECSuccess) return pubk;
+ break;
+ default:
+ rv = SECFailure;
+ break;
+ }
+
+ nsslowkey_DestroyPublicKey (pubk);
+ return NULL;
+}
+
diff --git a/security/nss/lib/softoken/lowkey.c b/security/nss/lib/softoken/lowkey.c
index fafbf361e..3d7cfa94a 100644
--- a/security/nss/lib/softoken/lowkey.c
+++ b/security/nss/lib/softoken/lowkey.c
@@ -30,17 +30,17 @@
* may use your version of this file under either the MPL or the
* GPL.
*/
-#include "keylow.h"
+#include "lowkeyi.h"
#include "secoid.h"
#include "secitem.h"
#include "secder.h"
#include "base64.h"
#include "secasn1.h"
-#include "cert.h"
+#include "pcert.h"
#include "secerr.h"
-const SEC_ASN1Template SECKEY_LowPQGParamsTemplate[] = {
+const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
{ SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
{ SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
@@ -48,43 +48,43 @@ const SEC_ASN1Template SECKEY_LowPQGParamsTemplate[] = {
{ 0, }
};
-const SEC_ASN1Template SECKEY_LowRSAPrivateKeyTemplate[] = {
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKey) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.version) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.modulus) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.publicExponent) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.privateExponent) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.prime1) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.prime2) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.exponent1) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.exponent2) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.rsa.coefficient) },
+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 SECKEY_LowDSAPrivateKeyTemplate[] = {
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYLowPrivateKey) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dsa.publicValue) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dsa.privateValue) },
+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 SECKEY_LowDSAPrivateKeyExportTemplate[] = {
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dsa.privateValue) },
+const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
};
-const SEC_ASN1Template SECKEY_LowDHPrivateKeyTemplate[] = {
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYLowPrivateKey) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dh.publicValue) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dh.privateValue) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dh.base) },
- { SEC_ASN1_INTEGER, offsetof(SECKEYLowPrivateKey,u.dh.prime) },
+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, }
};
void
-SECKEY_LowDestroyPrivateKey(SECKEYLowPrivateKey *privk)
+nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
{
if (privk && privk->arena) {
PORT_FreeArena(privk->arena, PR_TRUE);
@@ -92,14 +92,14 @@ SECKEY_LowDestroyPrivateKey(SECKEYLowPrivateKey *privk)
}
void
-SECKEY_LowDestroyPublicKey(SECKEYLowPublicKey *pubk)
+nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
{
if (pubk && pubk->arena) {
PORT_FreeArena(pubk->arena, PR_FALSE);
}
}
unsigned
-SECKEY_LowPublicModulusLen(SECKEYLowPublicKey *pubk)
+nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
{
unsigned char b0;
@@ -107,7 +107,7 @@ SECKEY_LowPublicModulusLen(SECKEYLowPublicKey *pubk)
* fortezza that's the public key length */
switch (pubk->keyType) {
- case lowRSAKey:
+ case NSSLOWKEYRSAKey:
b0 = pubk->u.rsa.modulus.data[0];
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
default:
@@ -117,13 +117,13 @@ SECKEY_LowPublicModulusLen(SECKEYLowPublicKey *pubk)
}
unsigned
-SECKEY_LowPrivateModulusLen(SECKEYLowPrivateKey *privk)
+nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
{
unsigned char b0;
switch (privk->keyType) {
- case lowRSAKey:
+ case NSSLOWKEYRSAKey:
b0 = privk->u.rsa.modulus.data[0];
return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
default:
@@ -132,10 +132,10 @@ SECKEY_LowPrivateModulusLen(SECKEYLowPrivateKey *privk)
return 0;
}
-SECKEYLowPublicKey *
-SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk)
+NSSLOWKEYPublicKey *
+nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
{
- SECKEYLowPublicKey *pubk;
+ NSSLOWKEYPublicKey *pubk;
PLArenaPool *arena;
@@ -146,16 +146,16 @@ SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk)
}
switch(privk->keyType) {
- case lowRSAKey:
- case nullKey:
- pubk = (SECKEYLowPublicKey *)PORT_ArenaZAlloc(arena,
- sizeof (SECKEYLowPublicKey));
+ 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 == nullKey) return pubk;
+ if (privk->keyType == NSSLOWKEYNullKey) return pubk;
rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
&privk->u.rsa.modulus);
if (rv == SECSuccess) {
@@ -164,14 +164,14 @@ SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk)
if (rv == SECSuccess)
return pubk;
}
- SECKEY_LowDestroyPublicKey (pubk);
+ nsslowkey_DestroyPublicKey (pubk);
} else {
PORT_SetError (SEC_ERROR_NO_MEMORY);
}
break;
- case lowDSAKey:
- pubk = (SECKEYLowPublicKey *)PORT_ArenaZAlloc(arena,
- sizeof(SECKEYLowPublicKey));
+ case NSSLOWKEYDSAKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
@@ -191,9 +191,9 @@ SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk)
if (rv == SECSuccess) return pubk;
}
break;
- case lowDHKey:
- pubk = (SECKEYLowPublicKey *)PORT_ArenaZAlloc(arena,
- sizeof(SECKEYLowPublicKey));
+ case NSSLOWKEYDHKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
@@ -220,10 +220,10 @@ SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privk)
return NULL;
}
-SECKEYLowPrivateKey *
-SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey)
+NSSLOWKEYPrivateKey *
+nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey)
{
- SECKEYLowPrivateKey *returnKey = NULL;
+ NSSLOWKEYPrivateKey *returnKey = NULL;
SECStatus rv = SECFailure;
PLArenaPool *poolp;
@@ -236,7 +236,7 @@ SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey)
return NULL;
}
- returnKey = (SECKEYLowPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(SECKEYLowPrivateKey));
+ returnKey = (NSSLOWKEYPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey));
if(!returnKey) {
rv = SECFailure;
goto loser;
@@ -246,7 +246,7 @@ SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey)
returnKey->arena = poolp;
switch(privKey->keyType) {
- case lowRSAKey:
+ case NSSLOWKEYRSAKey:
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus),
&(privKey->u.rsa.modulus));
if(rv != SECSuccess) break;
@@ -275,7 +275,7 @@ SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey)
&(privKey->u.rsa.coefficient));
if(rv != SECSuccess) break;
break;
- case lowDSAKey:
+ case NSSLOWKEYDSAKey:
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue),
&(privKey->u.dsa.publicValue));
if(rv != SECSuccess) break;
@@ -293,7 +293,7 @@ SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey)
&(privKey->u.dsa.params.base));
if(rv != SECSuccess) break;
break;
- case lowDHKey:
+ case NSSLOWKEYDHKey:
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue),
&(privKey->u.dh.publicValue));
if(rv != SECSuccess) break;
diff --git a/security/nss/lib/softoken/keylow.h b/security/nss/lib/softoken/lowkeyi.h
index 3c7679b3a..0a58b1fa3 100644
--- a/security/nss/lib/softoken/keylow.h
+++ b/security/nss/lib/softoken/lowkeyi.h
@@ -35,65 +35,64 @@
* $Id$
*/
-#ifndef _KEYLOW_H_
-#define _KEYLOW_H_
+#ifndef _LOWKEYI_H_
+#define _LOWKEYI_H_
#include "prtypes.h"
#include "seccomon.h"
-#include "keydbt.h"
#include "secoidt.h"
-#include "certt.h"
-#include "keytlow.h"
+#include "pcertt.h"
+#include "lowkeyti.h"
SEC_BEGIN_PROTOS
-typedef char * (* SECKEYDBNameFunc)(void *arg, int dbVersion);
+typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion);
/*
** Open a key database.
*/
-extern SECKEYKeyDBHandle *SECKEY_OpenKeyDB(PRBool readOnly,
- SECKEYDBNameFunc namecb,
+extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDB(PRBool readOnly,
+ NSSLOWKEYDBNameFunc namecb,
void *cbarg);
-extern SECKEYKeyDBHandle *SECKEY_OpenKeyDBFilename(char *filename,
+extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDBFilename(char *filename,
PRBool readOnly);
/*
** Update the database
*/
-extern SECStatus SECKEY_UpdateKeyDBPass1(SECKEYKeyDBHandle *handle);
-extern SECStatus SECKEY_UpdateKeyDBPass2(SECKEYKeyDBHandle *handle,
+extern SECStatus nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle);
+extern SECStatus nsslowkey_UpdateKeyDBPass2(NSSLOWKEYDBHandle *handle,
SECItem *pwitem);
/*
* Clear out all the keys in the existing database
*/
-extern SECStatus SECKEY_ResetKeyDB(SECKEYKeyDBHandle *handle);
+extern SECStatus nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle);
/*
** Close the specified key database.
*/
-extern void SECKEY_CloseKeyDB(SECKEYKeyDBHandle *handle);
+extern void nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle);
/*
* Get the version number of the database
*/
-extern int SECKEY_GetKeyDBVersion(SECKEYKeyDBHandle *handle);
+extern int nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle);
/*
** Support a default key database.
*/
-extern void SECKEY_SetDefaultKeyDB(SECKEYKeyDBHandle *handle);
-extern SECKEYKeyDBHandle *SECKEY_GetDefaultKeyDB(void);
+extern void nsslowkey_SetDefaultKeyDB(NSSLOWKEYDBHandle *handle);
+extern NSSLOWKEYDBHandle *nsslowkey_GetDefaultKeyDB(void);
/* set the alg id of the key encryption algorithm */
-extern void SECKEY_SetDefaultKeyDBAlg(SECOidTag alg);
+extern void nsslowkey_SetDefaultKeyDBAlg(SECOidTag alg);
/*
* given a password and salt, produce a hash of the password
*/
-extern SECItem *SECKEY_HashPassword(char *pw, SECItem *salt);
+extern SECItem *nsslowkey_HashPassword(char *pw, SECItem *salt);
/*
* Derive the actual password value for a key database from the
@@ -101,12 +100,12 @@ extern SECItem *SECKEY_HashPassword(char *pw, SECItem *salt);
* stored in the key database.
*/
extern SECItem *
-SECKEY_DeriveKeyDBPassword(SECKEYKeyDBHandle *handle, char *pw);
+nsslowkey_DeriveKeyDBPassword(NSSLOWKEYDBHandle *handle, char *pw);
/*
** Delete a key from the database
*/
-extern SECStatus SECKEY_DeleteKey(SECKEYKeyDBHandle *handle,
+extern SECStatus nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle,
SECItem *pubkey);
/*
@@ -115,27 +114,22 @@ extern SECStatus SECKEY_DeleteKey(SECKEYKeyDBHandle *handle,
** "f" is a the callback function for getting the password
** "arg" is the argument for the callback
*/
-extern SECStatus SECKEY_StoreKeyByPublicKey(SECKEYKeyDBHandle *handle,
- SECKEYLowPrivateKey *pk,
+extern SECStatus nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
+ NSSLOWKEYPrivateKey *pk,
SECItem *pubKeyData,
char *nickname,
- SECKEYLowGetPasswordKey f,
- void *arg);
+ SECItem *arg);
/* does the key for this cert exist in the database filed by modulus */
-extern SECStatus SECKEY_KeyForCertExists(SECKEYKeyDBHandle *handle,
- CERTCertificate *cert);
+extern PRBool nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle,
+ NSSLOWCERTCertificate *cert);
-SECKEYLowPrivateKey *
-SECKEY_FindKeyByCert(SECKEYKeyDBHandle *handle, CERTCertificate *cert,
- SECKEYLowGetPasswordKey f, void *arg);
-
-extern SECStatus SECKEY_HasKeyDBPassword(SECKEYKeyDBHandle *handle);
-extern SECStatus SECKEY_SetKeyDBPassword(SECKEYKeyDBHandle *handle,
+extern SECStatus nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle);
+extern SECStatus nsslowkey_SetKeyDBPassword(NSSLOWKEYDBHandle *handle,
SECItem *pwitem);
-extern SECStatus SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle,
+extern SECStatus nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle,
SECItem *pwitem);
-extern SECStatus SECKEY_ChangeKeyDBPassword(SECKEYKeyDBHandle *handle,
+extern SECStatus nsslowkey_ChangeKeyDBPassword(NSSLOWKEYDBHandle *handle,
SECItem *oldpwitem,
SECItem *newpwitem);
@@ -144,32 +138,32 @@ extern SECStatus SECKEY_ChangeKeyDBPassword(SECKEYKeyDBHandle *handle,
** "key" the object
** "freeit" if PR_TRUE then free the object as well as its sub-objects
*/
-extern void SECKEY_LowDestroyPrivateKey(SECKEYLowPrivateKey *key);
+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 SECKEY_LowDestroyPublicKey(SECKEYLowPublicKey *key);
+extern void nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *key);
/*
** Return the modulus length of "pubKey".
*/
-extern unsigned int SECKEY_LowPublicModulusLen(SECKEYLowPublicKey *pubKey);
+extern unsigned int nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubKey);
/*
** Return the modulus length of "privKey".
*/
-extern unsigned int SECKEY_LowPrivateModulusLen(SECKEYLowPrivateKey *privKey);
+extern unsigned int nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privKey);
/*
** Convert a low private key "privateKey" into a public low key
*/
-extern SECKEYLowPublicKey
- *SECKEY_LowConvertToPublicKey(SECKEYLowPrivateKey *privateKey);
+extern NSSLOWKEYPublicKey
+ *nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privateKey);
/*
* Set the Key Database password.
@@ -181,7 +175,7 @@ extern SECKEYLowPublicKey
* returned.
*/
extern SECStatus
-SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
+nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
SECItem *pwitem,
SECOidTag algorithm);
@@ -194,7 +188,7 @@ SECKEY_SetKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
* actual password. If it is not, SECFailure is returned.
*/
extern SECStatus
-SECKEY_CheckKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
+nsslowkey_CheckKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
SECItem *pwitem,
SECOidTag algorithm);
@@ -210,7 +204,7 @@ SECKEY_CheckKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
* A return of anything but SECSuccess indicates failure.
*/
extern SECStatus
-SECKEY_ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
+nsslowkey_ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
SECItem *oldpwitem, SECItem *newpwitem,
SECOidTag old_algorithm);
@@ -223,11 +217,11 @@ SECKEY_ChangeKeyDBPasswordAlg(SECKEYKeyDBHandle *handle,
* A return of anything but SECSuccess indicates failure.
*/
extern SECStatus
-SECKEY_StoreKeyByPublicKeyAlg(SECKEYKeyDBHandle *handle,
- SECKEYLowPrivateKey *privkey,
+nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
+ NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
- SECKEYLowGetPasswordKey f, void *arg,
+ SECItem *arg,
SECOidTag algorithm);
/* Find key by modulus. This function is the inverse of store key
@@ -236,17 +230,17 @@ SECKEY_StoreKeyByPublicKeyAlg(SECKEYKeyDBHandle *handle,
* else NULL is returned.
* modulus is the modulus to locate
*/
-extern SECKEYLowPrivateKey *
-SECKEY_FindKeyByPublicKey(SECKEYKeyDBHandle *handle, SECItem *modulus,
- SECKEYLowGetPasswordKey f, void *arg);
+extern NSSLOWKEYPrivateKey *
+nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
+ SECItem *arg);
/* Make a copy of a low private key in it's own arena.
* a return of NULL indicates an error.
*/
-extern SECKEYLowPrivateKey *
-SECKEY_CopyLowPrivateKey(SECKEYLowPrivateKey *privKey);
+extern NSSLOWKEYPrivateKey *
+nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey);
SEC_END_PROTOS
-#endif /* _KEYLOW_H_ */
+#endif /* _LOWKEYI_H_ */
diff --git a/security/nss/lib/softoken/lowkeyti.h b/security/nss/lib/softoken/lowkeyti.h
new file mode 100644
index 000000000..b8941bb0d
--- /dev/null
+++ b/security/nss/lib/softoken/lowkeyti.h
@@ -0,0 +1,138 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#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"
+/*#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;
+
+#define NSSLOWKEY_DB_FILE_VERSION 3
+
+#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[];
+
+extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[];
+extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[];
+
+
+/*
+** A PKCS#8 private key info object
+*/
+struct NSSLOWKEYPrivateKeyInfoStr {
+ PLArenaPool *arena;
+ SECItem version;
+ SECAlgorithmID algorithm;
+ SECItem privateKey;
+};
+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
+} NSSLOWKEYType;
+
+/*
+** An RSA public key object.
+*/
+struct NSSLOWKEYPublicKeyStr {
+ PLArenaPool *arena;
+ NSSLOWKEYType keyType ;
+ union {
+ RSAPublicKey rsa;
+ DSAPublicKey dsa;
+ DHPublicKey dh;
+ } 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;
+ } u;
+};
+typedef struct NSSLOWKEYPrivateKeyStr NSSLOWKEYPrivateKey;
+
+#endif /* _LOWKEYTI_H_ */
diff --git a/security/nss/lib/softoken/lowpbe.c b/security/nss/lib/softoken/lowpbe.c
new file mode 100644
index 000000000..cac83b90c
--- /dev/null
+++ b/security/nss/lib/softoken/lowpbe.c
@@ -0,0 +1,1184 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "plarena.h"
+
+#include "seccomon.h"
+#include "secitem.h"
+#include "secport.h"
+#include "hasht.h"
+#include "pkcs11t.h"
+#include "blapi.h"
+#include "hasht.h"
+#include "secasn1.h"
+#include "secder.h"
+#include "lowpbe.h"
+#include "secoid.h"
+#include "alghmac.h"
+#include "softoken.h"
+#include "secerr.h"
+
+/* template for PKCS 5 PBE Parameter. This template has been expanded
+ * based upon the additions in PKCS 12. This should eventually be moved
+ * if RSA updates PKCS 5.
+ */
+static const SEC_ASN1Template NSSPKCS5PBEParameterTemplate[] =
+{
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSPKCS5PBEParameter) },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(NSSPKCS5PBEParameter, salt) },
+ { SEC_ASN1_INTEGER,
+ offsetof(NSSPKCS5PBEParameter, iteration) },
+ { 0 }
+};
+
+static const SEC_ASN1Template NSSPKCS5PKCS12V2PBEParameterTemplate[] =
+{
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) },
+ { SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) },
+ { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) },
+ { 0 }
+};
+
+SECStatus
+nsspkcs5_HashBuf(const SECHashObject *hashObj, unsigned char *dest,
+ unsigned char *src, int len)
+{
+ void *ctx;
+ unsigned int retLen;
+
+ ctx = hashObj->create();
+ if(ctx == NULL) {
+ return SECFailure;
+ }
+ hashObj->begin(ctx);
+ hashObj->update(ctx, src, len);
+ hashObj->end(ctx, dest, &retLen, hashObj->length);
+ hashObj->destroy(ctx, PR_TRUE);
+ return SECSuccess;
+}
+
+/* generate bits using any hash
+ */
+static SECItem *
+nsspkcs5_PBKDF1(const SECHashObject *hashObj, SECItem *salt, SECItem *pwd,
+ int iter, PRBool faulty3DES)
+{
+ SECItem *hash = NULL, *pre_hash = NULL;
+ SECStatus rv = SECFailure;
+
+ if((salt == NULL) || (pwd == NULL) || (iter < 0)) {
+ return NULL;
+ }
+
+ hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+
+ if((hash != NULL) && (pre_hash != NULL)) {
+ int i, ph_len;
+
+ ph_len = hashObj->length;
+ if((salt->len + pwd->len) > hashObj->length) {
+ ph_len = salt->len + pwd->len;
+ }
+
+ rv = SECFailure;
+
+ /* allocate buffers */
+ hash->data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH);
+ hash->len = hashObj->length;
+ pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len);
+
+ /* in pbeSHA1TripleDESCBC there was an allocation error that made
+ * it into the caller. We do not want to propagate those errors
+ * further, so we are doing it correctly, but reading the old method.
+ */
+ if (faulty3DES) {
+ pre_hash->len = ph_len;
+ } else {
+ pre_hash->len = salt->len + pwd->len;
+ }
+
+ /* preform hash */
+ if ((hash->data != NULL) && (pre_hash->data != NULL)) {
+ rv = SECSuccess;
+ /* check for 0 length password */
+ if(pwd->len > 0) {
+ PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
+ }
+ if(salt->len > 0) {
+ PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len);
+ }
+ for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) {
+ rv = nsspkcs5_HashBuf(hashObj, hash->data,
+ pre_hash->data, pre_hash->len);
+ if(rv != SECFailure) {
+ pre_hash->len = hashObj->length;
+ PORT_Memcpy(pre_hash->data, hash->data, hashObj->length);
+ }
+ }
+ }
+ }
+
+ if(pre_hash != NULL) {
+ SECITEM_FreeItem(pre_hash, PR_TRUE);
+ }
+
+ if((rv != SECSuccess) && (hash != NULL)) {
+ SECITEM_FreeItem(hash, PR_TRUE);
+ hash = NULL;
+ }
+
+ return hash;
+}
+
+/* this bit generation routine is described in PKCS 12 and the proposed
+ * extensions to PKCS 5. an initial hash is generated following the
+ * instructions laid out in PKCS 5. If the number of bits generated is
+ * insufficient, then the method discussed in the proposed extensions to
+ * PKCS 5 in PKCS 12 are used. This extension makes use of the HMAC
+ * function. And the P_Hash function from the TLS standard.
+ */
+static SECItem *
+nsspkcs5_PFXPBE(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param,
+ SECItem *init_hash, unsigned int bytes_needed)
+{
+ SECItem *ret_bits = NULL;
+ int hash_size = 0;
+ unsigned int i;
+ unsigned int hash_iter;
+ unsigned int dig_len;
+ SECStatus rv = SECFailure;
+ unsigned char *state = NULL;
+ unsigned int state_len;
+ HMACContext *cx = NULL;
+
+ hash_size = hashObj->length;
+ hash_iter = (bytes_needed + (unsigned int)hash_size - 1) / hash_size;
+
+ /* allocate return buffer */
+ ret_bits = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ if(ret_bits == NULL)
+ return NULL;
+ ret_bits->data = (unsigned char *)PORT_ZAlloc((hash_iter * hash_size) + 1);
+ ret_bits->len = (hash_iter * hash_size);
+ if(ret_bits->data == NULL) {
+ PORT_Free(ret_bits);
+ return NULL;
+ }
+
+ /* allocate intermediate hash buffer. 8 is for the 8 bytes of
+ * data which are added based on iteration number
+ */
+
+ if ((unsigned int)hash_size > pbe_param->salt.len) {
+ state_len = hash_size;
+ } else {
+ state_len = pbe_param->salt.len;
+ }
+ state = (unsigned char *)PORT_ZAlloc(state_len);
+ if(state == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+ if(pbe_param->salt.len > 0) {
+ PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len);
+ }
+
+ cx = HMAC_Create(hashObj, init_hash->data, init_hash->len);
+ if (cx == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ for(i = 0; i < hash_iter; i++) {
+
+ /* generate output bits */
+ HMAC_Begin(cx);
+ HMAC_Update(cx, state, state_len);
+ HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len);
+ rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size),
+ &dig_len, hash_size);
+ if (rv != SECSuccess)
+ goto loser;
+ PORT_Assert((unsigned int)hash_size == dig_len);
+
+ /* generate new state */
+ HMAC_Begin(cx);
+ HMAC_Update(cx, state, state_len);
+ rv = HMAC_Finish(cx, state, &state_len, state_len);
+ if (rv != SECSuccess)
+ goto loser;
+ PORT_Assert(state_len == dig_len);
+ }
+
+loser:
+ if (state != NULL)
+ PORT_ZFree(state, state_len);
+ HMAC_Destroy(cx);
+
+ if(rv != SECSuccess) {
+ SECITEM_ZfreeItem(ret_bits, PR_TRUE);
+ ret_bits = NULL;
+ }
+
+ return ret_bits;
+}
+
+/* generate bits for the key and iv determination. if enough bits
+ * are not generated using PKCS 5, then we need to generate more bits
+ * based on the extension proposed in PKCS 12
+ */
+static SECItem *
+nsspkcs5_PBKDF1Extended(const SECHashObject *hashObj,
+ NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, PRBool faulty3DES)
+{
+ SECItem * hash = NULL;
+ SECItem * newHash = NULL;
+ int bytes_needed;
+ int bytes_available;
+
+ bytes_needed = pbe_param->ivLen + pbe_param->keyLen;
+ bytes_available = hashObj->length;
+
+ hash = nsspkcs5_PBKDF1(hashObj, &pbe_param->salt, pwitem,
+ pbe_param->iter, faulty3DES);
+
+ if(hash == NULL) {
+ return NULL;
+ }
+
+ if(bytes_needed <= bytes_available) {
+ return hash;
+ }
+
+ newHash = nsspkcs5_PFXPBE(hashObj, pbe_param, hash, bytes_needed);
+ if (hash != newHash)
+ SECITEM_FreeItem(hash, PR_TRUE);
+ return newHash;
+}
+
+#ifdef PBKDF2
+
+/*
+ * PBDKDF2 is PKCS #5 v2.0 it's currently not used by NSS
+ */
+/*
+ * We This is safe because hLen for all our
+ * HMAC algorithms are multiples of 4.
+ */
+static void
+xorbytes(unsigned char *dest, unsigned char *src, int len)
+{
+#ifdef PARANOIA
+ while (len--) {
+ *dest = *dest ^ *src;
+ dest++;
+ src++;
+ }
+#else
+ PRUInt32 dest32 = (PRUInt32 *)dest;
+ PRUInt32 src32 = (PRUInt32 *)dest;
+ while (len -= sizeof(PRUInt32)) {
+ *dest32 = *dest32 ^ *src32;
+ dest++;
+ src++;
+ }
+#endif
+}
+
+static SECStatus
+nsspkcs5_PBKFD2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt,
+ int iterations, unsigned int i, unsigned char *T)
+{
+ int j;
+ HMACContext *cx = NULL;
+ unsigned int hLen = hashObject->length
+ SECStatus rv = SECFailure;
+ unsigned char *last = NULL;
+ int lastLength = salt->len + 4;
+
+ cx=HMAC_Create(hashobj,pwitem->data,pwitem->len);
+ if (cx == NULL) {
+ goto loser;
+ }
+ PORT_Memset(T,0,hLen);
+ realLastLength= MAX(lastLength,hLen);
+ last = PORT_Alloc(realLastLength);
+ if (last == NULL) {
+ goto loser;
+ }
+ PORT_Memcpy(last,salt.data,salt.len);
+ last[salt->len ] = (i >> 24) & 0xff;
+ last[salt->len+1] = (i >> 16) & 0xff;
+ last[salt->len+2] = (i >> 8) & 0xff;
+ last[salt->len+3] = i & 0xff;
+
+ /* NOTE: we need at least one iteration to return success! */
+ for (j=0; j < interations; j++) {
+ rv =HMAC_Begin(cx);
+ if (rv !=SECSuccess) {
+ break;
+ }
+ HMAC_Update(cx,last,lastLength);
+ rv =HMAC_Finish(cx,last,&lastLength,hLen);
+ if (rv !=SECSuccess) {
+ break;
+ }
+ do_xor(T,last,hLen);
+ }
+loser:
+ if (cx) {
+ HMAC_DestroyContext(cx);
+ }
+ if (last) {
+ PORT_ZFree(last,reaLastLength);
+ }
+ return rv;
+}
+
+static SECItem *
+nsspkcs5_PBKFD2(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param,
+ SECItem *pwitem)
+{
+ unsigned int dkLen = bytesNeeded;
+ unsigned int hLen = hashObject->length
+ unsigned int l = (dkLen+hLen-1) / hLen;
+ unsigned char *rp;
+ SECItem *result;
+ SECItem *salt = pbe_param->salt;
+ int interations = pbe_param->iter;
+ int bytesNeeded = pbe_param->keyLen;
+
+ result = SECITEM_AllocItem(NULL,NULL,l*hLen);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ T = PORT_Alloc(hLen);
+ if (T == NULL) {
+ goto loser;
+ }
+
+ for (i=0,rp=results->data; i < l ; i++, rp +=hLen) {
+ rv = nsspkcs5_PBKFD2_F(hashobj,pwitem,salt,iterations,i,T);
+ if (rv != SECSuccess) {
+ break;
+ }
+ PORT_Memcpy(rp,T,hLen);
+ }
+
+loser:
+ if (T) {
+ PORT_ZFree(T);
+ }
+ if (rv != SECSuccess) {
+ SECITEM_FreeITEM(result,PR_TRUE);
+ result = NULL;
+ } else {
+ result->len = dkLen;
+ }
+
+ return result;
+}
+#endif
+
+#define HMAC_BUFFER 64
+#define ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
+/*
+ * This is the extended PBE function defined by the final PKCS #12 spec.
+ */
+static SECItem *
+nsspkcs5_PKCS12PBE(const SECHashObject *hashObject,
+ NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
+ PBEBitGenID bitGenPurpose, unsigned int bytesNeeded)
+{
+ PRArenaPool *arena = NULL;
+ unsigned int SLen,PLen;
+ unsigned int hashLength = hashObject->length;
+ unsigned char *S, *P;
+ SECItem *A = NULL, B, D, I;
+ SECItem *salt = &pbe_param->salt;
+ unsigned int c,i = 0;
+ unsigned int hashLen, iter;
+ unsigned char *iterBuf;
+ void *hash = NULL;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if(!arena) {
+ return NULL;
+ }
+
+ /* how many hash object lengths are needed */
+ c = (bytesNeeded + (hashLength-1))/hashLength;
+
+ /* initialize our buffers */
+ D.len = HMAC_BUFFER;
+ /* B and D are the same length, use one alloc go get both */
+ D.data = (unsigned char*)PORT_ArenaZAlloc(arena, D.len*2);
+ B.len = D.len;
+ B.data = D.data + D.len;
+
+ /* if all goes well, A will be returned, so don't use our temp arena */
+ A = SECITEM_AllocItem(NULL,NULL,c*hashLength);
+ if (A == NULL) {
+ goto loser;
+ }
+
+ SLen = ROUNDUP(salt->len,HMAC_BUFFER);
+ PLen = ROUNDUP(pwitem->len,HMAC_BUFFER);
+ I.len = SLen+PLen;
+ I.data = (unsigned char*)PORT_ArenaZAlloc(arena, I.len);
+ if (I.data == NULL) {
+ goto loser;
+ }
+
+ /* S & P are only used to initialize I */
+ S = I.data;
+ P = S + SLen;
+
+ PORT_Memset(D.data, (char)bitGenPurpose, D.len);
+ if (SLen) {
+ PORT_Memcpy(S, salt->data, salt->len);
+ if (salt->len != SLen) {
+ PORT_Memcpy(S+salt->len, salt->data, SLen-(salt->len));
+ }
+ }
+ if (PLen) {
+ PORT_Memcpy(P, salt->data, salt->len);
+ if (salt->len != PLen) {
+ PORT_Memcpy(P+salt->len, salt->data, PLen-salt->len);
+ }
+ }
+
+ iterBuf = (unsigned char*)PORT_ArenaZAlloc(arena,hashLength);
+ if (iterBuf == NULL) {
+ goto loser;
+ }
+
+ hash = hashObject->create();
+ if(!hash) {
+ goto loser;
+ }
+ /* calculate the PBE now */
+ for(i = 0; i < c; i++) {
+ int Bidx; /* must be signed or the for loop won't terminate */
+ unsigned int k, j;
+ unsigned char *Ai = A->data+i*hashLength;
+
+
+ for(iter = 0; iter < pbe_param->iter; iter++) {
+ hashObject->begin(hash);
+
+ if (iter) {
+ hashObject->update(hash, iterBuf, hashLen);
+ } else {
+ hashObject->update(hash, D.data, D.len);
+ hashObject->update(hash, I.data, I.len);
+ }
+
+ hashObject->end(hash, iterBuf, &hashLen, hashObject->length);
+ if(hashLen != hashObject->length) {
+ break;
+ }
+ }
+
+ PORT_Memcpy(Ai, iterBuf, hashLength);
+ for (Bidx = 0; Bidx < B.len; B.len += hashLength) {
+ PORT_Memcpy(B.data +Bidx, iterBuf,
+ (((Bidx + hashLength) > B.len) ? (B.len - Bidx) :
+ hashLength));
+ }
+
+ k = I.len/B.len;
+ for(j = 0; j < k; j++) {
+ unsigned int q, carryBit;
+ unsigned char *Ij = I.data + j*B.len;
+
+ /* (Ij = Ij+B+1) */
+ for (Bidx = (B.len-1), q=1, carryBit=0; Bidx >= 0; Bidx--,q=0) {
+ q += (unsigned int)Ij[Bidx];
+ q += (unsigned int)B.data[Bidx];
+ q += carryBit;
+
+ carryBit = (q > 0xff);
+ Ij[Bidx] = (unsigned char)(q & 0xff);
+ }
+ }
+ }
+loser:
+ if (hash) {
+ hashObject->destroy(hash, PR_TRUE);
+ }
+ if(arena) {
+ PORT_FreeArena(arena, PR_TRUE);
+ }
+
+ /* if i != c, then we didn't complete the loop above and must of failed
+ * somwhere along the way */
+ if (i != c) {
+ SECITEM_ZfreeItem(A,PR_TRUE);
+ A = NULL;
+ } else {
+ A->len = bytesNeeded;
+ }
+
+ return A;
+}
+
+/*
+ * generate key as per PKCS 5
+ */
+SECItem *
+nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
+ SECItem *iv, PRBool faulty3DES)
+{
+ SECItem *hash = NULL, *key = NULL;
+ const SECHashObject *hashObj;
+ PRBool getIV = PR_FALSE;
+
+ if((pbe_param == NULL) || (pwitem == NULL)) {
+ return NULL;
+ }
+
+ key = SECITEM_AllocItem(NULL,NULL,pbe_param->keyLen);
+ if (key == NULL) {
+ return NULL;
+ }
+
+ if ((pbe_param->ivLen) && (iv->data == NULL)) {
+ getIV = PR_TRUE;
+ iv->data = (unsigned char *)PORT_Alloc(pbe_param->ivLen);
+ if (iv->data == NULL) {
+ goto loser;
+ }
+ iv->len = pbe_param->ivLen;
+ }
+
+ hashObj = &SECRawHashObjects[pbe_param->hashType];
+ switch (pbe_param->pbeType) {
+ case NSSPKCS5_PBKDF1:
+ hash = nsspkcs5_PBKDF1Extended(hashObj,pbe_param,pwitem,faulty3DES);
+ if (hash == NULL) {
+ goto loser;
+ }
+ PORT_Assert(hash->len >= key->len+iv->len);
+ if (getIV) {
+ PORT_Memcpy(iv->data, hash->data+(hash->len - iv->len),iv->len);
+ }
+ break;
+#ifdef PBKDF2
+ case NSSPKCS5_PBKDF2:
+ hash = nsspkcs5_PBKDF2(hashObj,pbe_param,pwitem);
+ PORT_Assert(!getIV);
+ break;
+#endif
+ case NSSPKCS5_PKCS12_V2:
+ if (getIV) {
+ hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem,
+ pbeBitGenCipherIV,iv->len);
+ if (hash == NULL) {
+ goto loser;
+ }
+ PORT_Memcpy(iv->data,hash->data,iv->len);
+ SECITEM_ZfreeItem(hash,PR_TRUE);
+ hash = NULL;
+ }
+ hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem,
+ pbe_param->keyID,key->len);
+ default:
+ break;
+ }
+
+ if (hash == NULL) {
+ goto loser;
+ }
+
+ if (pbe_param->is2KeyDES) {
+ PORT_Memcpy(key->data, hash->data, (key->len * 2) / 3);
+ PORT_Memcpy(&(key->data[(key->len * 2) / 3]), key->data,
+ key->len / 3);
+ } else {
+ PORT_Memcpy(key->data, hash->data, key->len);
+ }
+
+ SECITEM_FreeItem(hash, PR_TRUE);
+ return key;
+
+loser:
+ if (getIV && iv->data) {
+ PORT_ZFree(iv->data,iv->len);
+ iv->data = NULL;
+ }
+
+ SECITEM_ZfreeItem(key, PR_TRUE);
+ return NULL;
+}
+
+static SECStatus
+nsspkcs5_FillInParam(SECOidTag algorithm, NSSPKCS5PBEParameter *pbe_param)
+{
+ PRBool skipType = PR_FALSE;
+
+ pbe_param->keyLen = 5;
+ pbe_param->ivLen = 8;
+ pbe_param->hashType = HASH_AlgSHA1;
+ pbe_param->pbeType = NSSPKCS5_PBKDF1;
+ pbe_param->encAlg = SEC_OID_RC2_CBC;
+ pbe_param->is2KeyDES = PR_FALSE;
+ switch(algorithm) {
+ /* DES3 Algorithms */
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
+ pbe_param->is2KeyDES = PR_TRUE;
+ /* fall through */
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
+ pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
+ /* fall through */
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
+ pbe_param->keyLen = 24;
+ pbe_param->encAlg = SEC_OID_DES_EDE3_CBC;
+ break;
+
+ /* DES Algorithms */
+ case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
+ pbe_param->hashType = HASH_AlgMD2;
+ goto finish_des;
+ case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
+ pbe_param->hashType = HASH_AlgMD5;
+ /* fall through */
+ case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
+finish_des:
+ pbe_param->keyLen = 8;
+ pbe_param->encAlg = SEC_OID_DES_CBC;
+ break;
+
+ /* RC2 Algorithms */
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
+ pbe_param->keyLen = 16;
+ /* fall through */
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
+ pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
+ break;
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
+ pbe_param->keyLen = 16;
+ /* fall through */
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
+ break;
+
+ /* RC4 algorithms */
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
+ skipType = PR_TRUE;
+ /* fall through */
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
+ pbe_param->keyLen = 16;
+ /* fall through */
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
+ if (!skipType) {
+ pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
+ }
+ /* fall through */
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
+ pbe_param->ivLen = 0;
+ pbe_param->encAlg = SEC_OID_RC4;
+ break;
+ default:
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+/* decode the algid and generate a PKCS 5 parameter from it
+ */
+NSSPKCS5PBEParameter *
+nsspkcs5_NewParam(SECOidTag alg, SECItem *salt, int iterator)
+{
+ PRArenaPool *arena = NULL;
+ NSSPKCS5PBEParameter *pbe_param = NULL;
+ SECStatus rv = SECFailure;
+
+ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (arena == NULL)
+ return NULL;
+
+ /* allocate memory for the parameter */
+ pbe_param = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSPKCS5PBEParameter));
+
+ if (pbe_param == NULL) {
+ goto loser;
+ }
+
+ pbe_param->poolp = arena;
+
+ rv = nsspkcs5_FillInParam(alg, pbe_param);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ pbe_param->iter = iterator;
+ if (salt) {
+ rv = SECITEM_CopyItem(arena,&pbe_param->salt,salt);
+ }
+
+ /* default key gen */
+ pbe_param->keyID = pbeBitGenCipherKey;
+
+loser:
+ if (rv != SECSuccess) {
+ PORT_FreeArena(arena, PR_TRUE);
+ pbe_param = NULL;
+ }
+
+ return pbe_param;
+}
+
+/* decode the algid and generate a PKCS 5 parameter from it
+ */
+NSSPKCS5PBEParameter *
+nsspkcs5_AlgidToParam(SECAlgorithmID *algid)
+{
+ NSSPKCS5PBEParameter *pbe_param = NULL;
+ SECOidTag algorithm;
+ SECStatus rv = SECFailure;
+
+ if (algid == NULL) {
+ return NULL;
+ }
+
+ algorithm = SECOID_GetAlgorithmTag(algid);
+ if (algorithm == SEC_OID_UNKNOWN) {
+ goto loser;
+ }
+
+ pbe_param = nsspkcs5_NewParam(algorithm, NULL, 1);
+ if (pbe_param == NULL) {
+ goto loser;
+ }
+
+ /* decode parameter */
+ rv = SECFailure;
+ switch (pbe_param->pbeType) {
+ case NSSPKCS5_PBKDF1:
+ rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
+ NSSPKCS5PBEParameterTemplate, &algid->parameters);
+ break;
+ case NSSPKCS5_PKCS12_V2:
+ rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
+ NSSPKCS5PKCS12V2PBEParameterTemplate, &algid->parameters);
+ break;
+ case NSSPKCS5_PBKDF2:
+ break;
+ }
+
+loser:
+ if (rv == SECSuccess) {
+ pbe_param->iter = DER_GetInteger(&pbe_param->iteration);
+ } else {
+ nsspkcs5_DestroyPBEParameter(pbe_param);
+ pbe_param = NULL;
+ }
+
+ return pbe_param;
+}
+
+/* destroy a pbe parameter. it assumes that the parameter was
+ * generated using the appropriate create function and therefor
+ * contains an arena pool.
+ */
+void
+nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param)
+{
+ if (pbe_param != NULL) {
+ PORT_FreeArena(pbe_param->poolp, PR_TRUE);
+ }
+}
+
+
+/* crypto routines */
+/* perform DES encryption and decryption. these routines are called
+ * by nsspkcs5_CipherData. In the case of an error, NULL is returned.
+ */
+static SECItem *
+sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
+ PRBool encrypt)
+{
+ SECItem *dest;
+ SECItem *dup_src;
+ SECStatus rv = SECFailure;
+ int pad;
+
+ if((src == NULL) || (key == NULL) || (iv == NULL))
+ return NULL;
+
+ dup_src = SECITEM_DupItem(src);
+ if(dup_src == NULL) {
+ return NULL;
+ }
+
+ if(encrypt != PR_FALSE) {
+ void *dummy;
+
+ dummy = DES_PadBuffer(NULL, dup_src->data,
+ dup_src->len, &dup_src->len);
+ if(dummy == NULL) {
+ SECITEM_FreeItem(dup_src, PR_TRUE);
+ return NULL;
+ }
+ dup_src->data = (unsigned char*)dummy;
+ }
+
+ dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ if(dest != NULL) {
+ /* allocate with over flow */
+ dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
+ if(dest->data != NULL) {
+ DESContext *ctxt;
+ ctxt = DES_CreateContext(key->data, iv->data,
+ (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC),
+ encrypt);
+
+ if(ctxt != NULL) {
+ rv = ((encrypt != PR_TRUE) ? DES_Decrypt : DES_Encrypt)(
+ ctxt, dest->data, &dest->len,
+ dup_src->len + 64, dup_src->data, dup_src->len);
+
+ /* remove padding -- assumes 64 bit blocks */
+ if((encrypt == PR_FALSE) && (rv == SECSuccess)) {
+ pad = dest->data[dest->len-1];
+ if((pad > 0) && (pad <= 8)) {
+ if(dest->data[dest->len-pad] != pad) {
+ rv = SECFailure;
+ PORT_SetError(SEC_ERROR_BAD_PASSWORD);
+ } else {
+ dest->len -= pad;
+ }
+ } else {
+ rv = SECFailure;
+ PORT_SetError(SEC_ERROR_BAD_PASSWORD);
+ }
+ }
+ DES_DestroyContext(ctxt, PR_TRUE);
+ }
+ }
+ }
+
+ if(rv == SECFailure) {
+ if(dest != NULL) {
+ SECITEM_FreeItem(dest, PR_TRUE);
+ }
+ dest = NULL;
+ }
+
+ if(dup_src != NULL) {
+ SECITEM_FreeItem(dup_src, PR_TRUE);
+ }
+
+ return dest;
+}
+
+/* perform rc2 encryption/decryption if an error occurs, NULL is returned
+ */
+static SECItem *
+sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy,
+ PRBool encrypt)
+{
+ SECItem *dest;
+ SECItem *dup_src;
+ SECStatus rv = SECFailure;
+ int pad;
+
+ if((src == NULL) || (key == NULL) || (iv == NULL)) {
+ return NULL;
+ }
+
+ dup_src = SECITEM_DupItem(src);
+ if(dup_src == NULL) {
+ return NULL;
+ }
+
+ if(encrypt != PR_FALSE) {
+ void *dummy;
+
+ dummy = DES_PadBuffer(NULL, dup_src->data,
+ dup_src->len, &dup_src->len);
+ if(dummy == NULL) {
+ SECITEM_FreeItem(dup_src, PR_TRUE);
+ return NULL;
+ }
+ dup_src->data = (unsigned char*)dummy;
+ }
+
+ dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ if(dest != NULL) {
+ dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
+ if(dest->data != NULL) {
+ RC2Context *ctxt;
+
+ ctxt = RC2_CreateContext(key->data, key->len, iv->data,
+ NSS_RC2_CBC, key->len);
+
+ if(ctxt != NULL) {
+ rv = ((encrypt != PR_TRUE) ? RC2_Decrypt : RC2_Encrypt)(
+ ctxt, dest->data, &dest->len,
+ dup_src->len + 64, dup_src->data, dup_src->len);
+
+ /* assumes 8 byte blocks -- remove padding */
+ if((rv == SECSuccess) && (encrypt != PR_TRUE)) {
+ pad = dest->data[dest->len-1];
+ if((pad > 0) && (pad <= 8)) {
+ if(dest->data[dest->len-pad] != pad) {
+ PORT_SetError(SEC_ERROR_BAD_PASSWORD);
+ rv = SECFailure;
+ } else {
+ dest->len -= pad;
+ }
+ } else {
+ PORT_SetError(SEC_ERROR_BAD_PASSWORD);
+ rv = SECFailure;
+ }
+ }
+
+ }
+ }
+ }
+
+ if((rv != SECSuccess) && (dest != NULL)) {
+ SECITEM_FreeItem(dest, PR_TRUE);
+ dest = NULL;
+ }
+
+ if(dup_src != NULL) {
+ SECITEM_FreeItem(dup_src, PR_TRUE);
+ }
+
+ return dest;
+}
+
+/* perform rc4 encryption and decryption */
+static SECItem *
+sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op,
+ PRBool encrypt)
+{
+ SECItem *dest;
+ SECStatus rv = SECFailure;
+
+ if((src == NULL) || (key == NULL) || (iv == NULL)) {
+ return NULL;
+ }
+
+ dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ if(dest != NULL) {
+ dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
+ (src->len + 64));
+ if(dest->data != NULL) {
+ RC4Context *ctxt;
+
+ ctxt = RC4_CreateContext(key->data, key->len);
+ if(ctxt) {
+ rv = ((encrypt != PR_FALSE) ? RC4_Decrypt : RC4_Encrypt)(
+ ctxt, dest->data, &dest->len,
+ src->len + 64, src->data, src->len);
+ RC4_DestroyContext(ctxt, PR_TRUE);
+ }
+ }
+ }
+
+ if((rv != SECSuccess) && (dest)) {
+ SECITEM_FreeItem(dest, PR_TRUE);
+ dest = NULL;
+ }
+
+ return dest;
+}
+/* function pointer template for crypto functions */
+typedef SECItem *(* pkcs5_crypto_func)(SECItem *key, SECItem *iv,
+ SECItem *src, PRBool op1, PRBool op2);
+
+/* performs the cipher operation on the src and returns the result.
+ * if an error occurs, NULL is returned.
+ *
+ * a null length password is allowed. this corresponds to encrypting
+ * the data with ust the salt.
+ */
+/* change this to use PKCS 11? */
+SECItem *
+nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
+ SECItem *src, PRBool encrypt, PRBool *update)
+{
+ SECItem *key = NULL, iv;
+ SECItem *dest = NULL;
+ PRBool tripleDES = PR_TRUE;
+ pkcs5_crypto_func cryptof;
+
+ iv.data = NULL;
+
+ if (update) {
+ *update = PR_FALSE;
+ }
+
+ if ((pwitem == NULL) || (src == NULL)) {
+ return NULL;
+ }
+
+ /* get key, and iv */
+ key = nsspkcs5_ComputeKeyAndIV(pbe_param, pwitem, &iv, PR_FALSE);
+ if(key == NULL) {
+ return NULL;
+ }
+
+ switch(pbe_param->encAlg) {
+ case SEC_OID_DES_EDE3_CBC:
+ cryptof = sec_pkcs5_des;
+ tripleDES = PR_TRUE;
+ break;
+ case SEC_OID_DES_CBC:
+ cryptof = sec_pkcs5_des;
+ tripleDES = PR_FALSE;
+ break;
+ case SEC_OID_RC2_CBC:
+ cryptof = sec_pkcs5_rc2;
+ break;
+ case SEC_OID_RC4:
+ cryptof = sec_pkcs5_rc4;
+ break;
+ default:
+ cryptof = NULL;
+ break;
+ }
+
+ if (cryptof == NULL) {
+ goto loser;
+ }
+
+ dest = (*cryptof)(key, &iv, src, tripleDES, encrypt);
+ /*
+ * it's possible for some keys and keydb's to claim to
+ * be triple des when they're really des. In this case
+ * we simply try des. If des works we set the update flag
+ * so the key db knows it needs to update all it's entries.
+ * The case can only happen on decrypted of a
+ * SEC_OID_DES_EDE3_CBD.
+ */
+ if ((dest == NULL) && (encrypt == PR_FALSE) &&
+ (pbe_param->encAlg == SEC_OID_DES_EDE3_CBC)) {
+ dest = (*cryptof)(key, &iv, src, PR_FALSE, encrypt);
+ if (update && (dest != NULL)) *update = PR_TRUE;
+ }
+
+loser:
+ if (key != NULL) {
+ SECITEM_ZfreeItem(key, PR_TRUE);
+ }
+ if (iv.data != NULL) {
+ SECITEM_ZfreeItem(&iv, PR_FALSE);
+ }
+
+ return dest;
+}
+
+/* creates a algorithm ID containing the PBE algorithm and appropriate
+ * parameters. the required parameter is the algorithm. if salt is
+ * not specified, it is generated randomly. if IV is specified, it overrides
+ * the PKCS 5 generation of the IV.
+ *
+ * the returned SECAlgorithmID should be destroyed using
+ * SECOID_DestroyAlgorithmID
+ */
+SECAlgorithmID *
+nsspkcs5_CreateAlgorithmID(PRArenaPool *arena, SECOidTag algorithm,
+ NSSPKCS5PBEParameter *pbe_param)
+{
+ SECAlgorithmID *algid, *ret_algid;
+ SECItem der_param;
+ SECStatus rv = SECFailure;
+ void *dummy = NULL;
+
+ if (arena == NULL) {
+ return NULL;
+ }
+
+ der_param.data = NULL;
+ der_param.len = 0;
+
+ /* generate the algorithm id */
+ algid = (SECAlgorithmID *)PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID));
+ if (algid == NULL) {
+ goto loser;
+ }
+
+ if (pbe_param->iteration.data == NULL) {
+ dummy = SEC_ASN1EncodeInteger(pbe_param->poolp,&pbe_param->iteration,
+ pbe_param->iter);
+ if (dummy == NULL) {
+ goto loser;
+ }
+ }
+ switch (pbe_param->pbeType) {
+ case NSSPKCS5_PBKDF1:
+ dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
+ NSSPKCS5PBEParameterTemplate);
+ break;
+ case NSSPKCS5_PKCS12_V2:
+ dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
+ NSSPKCS5PKCS12V2PBEParameterTemplate);
+ break;
+ default:
+ break;
+ }
+
+ if (dummy == NULL) {
+ goto loser;
+ }
+
+ rv = SECOID_SetAlgorithmID(arena, algid, algorithm, &der_param);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
+ if (ret_algid == NULL) {
+ goto loser;
+ }
+
+ rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
+ if (rv != SECSuccess) {
+ SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
+ ret_algid = NULL;
+ }
+
+loser:
+
+ return ret_algid;
+}
diff --git a/security/nss/lib/softoken/lowpbe.h b/security/nss/lib/softoken/lowpbe.h
new file mode 100644
index 000000000..8ddee11a6
--- /dev/null
+++ b/security/nss/lib/softoken/lowpbe.h
@@ -0,0 +1,132 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef _SECPKCS5_H_
+#define _SECPKCS5_H_
+
+#include "plarena.h"
+#include "secitem.h"
+#include "seccomon.h"
+#include "secoidt.h"
+#include "hasht.h"
+
+typedef SECItem * (* SEC_PKCS5GetPBEPassword)(void *arg);
+
+/* used for V2 PKCS 12 Draft Spec */
+typedef enum {
+ pbeBitGenIDNull = 0,
+ pbeBitGenCipherKey = 0x01,
+ pbeBitGenCipherIV = 0x02,
+ pbeBitGenIntegrityKey = 0x03
+} PBEBitGenID;
+
+typedef enum {
+ NSSPKCS5_PBKDF1 = 0,
+ NSSPKCS5_PBKDF2 = 1,
+ NSSPKCS5_PKCS12_V2 = 2
+} NSSPKCS5PBEType;
+
+typedef struct NSSPKCS5PBEParameterStr NSSPKCS5PBEParameter;
+
+struct NSSPKCS5PBEParameterStr {
+ PRArenaPool *poolp;
+ SECItem salt; /* octet string */
+ SECItem iteration; /* integer */
+
+ /* used locally */
+ int iter;
+ int keyLen;
+ int ivLen;
+ HASH_HashType hashType;
+ NSSPKCS5PBEType pbeType;
+ PBEBitGenID keyID;
+ SECOidTag encAlg;
+ PRBool is2KeyDES;
+};
+
+
+SEC_BEGIN_PROTOS
+/* Create a PKCS5 Algorithm ID
+ * The algorithm ID is set up using the PKCS #5 parameter structure
+ * algorithm is the PBE algorithm ID for the desired algorithm
+ * pbe is a pbe param block with all the info needed to create the
+ * algorithm id.
+ * If an error occurs or the algorithm specified is not supported
+ * or is not a password based encryption algorithm, NULL is returned.
+ * Otherwise, a pointer to the algorithm id is returned.
+ */
+extern SECAlgorithmID *
+nsspkcs5_CreateAlgorithmID(PRArenaPool *arena, SECOidTag algorithm,
+ NSSPKCS5PBEParameter *pbe);
+
+/*
+ * Convert an Algorithm ID to a PBE Param.
+ * NOTE: this does not suppport PKCS 5 v2 because it's only used for the
+ * keyDB which only support PKCS 5 v1, PFX, and PKCS 12.
+ */
+NSSPKCS5PBEParameter *
+nsspkcs5_AlgidToParam(SECAlgorithmID *algid);
+
+/*
+ * Convert an Algorithm ID to a PBE Param.
+ * NOTE: this does not suppport PKCS 5 v2 because it's only used for the
+ * keyDB which only support PKCS 5 v1, PFX, and PKCS 12.
+ */
+NSSPKCS5PBEParameter *
+nsspkcs5_NewParam(SECOidTag alg, SECItem *salt, int iterator);
+
+
+/* Encrypt/Decrypt data using password based encryption.
+ * algid is the PBE algorithm identifier,
+ * pwitem is the password,
+ * src is the source for encryption/decryption,
+ * encrypt is PR_TRUE for encryption, PR_FALSE for decryption.
+ * The key and iv are generated based upon PKCS #5 then the src
+ * is either encrypted or decrypted. If an error occurs, NULL
+ * is returned, otherwise the ciphered contents is returned.
+ */
+extern SECItem *
+nsspkcs5_CipherData(NSSPKCS5PBEParameter *, SECItem *pwitem,
+ SECItem *src, PRBool encrypt, PRBool *update);
+
+extern SECItem *
+nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *, SECItem *pwitem,
+ SECItem *iv, PRBool faulty3DES);
+
+/* Destroys PBE parameter */
+extern void
+nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *param);
+
+SEC_END_PROTOS
+
+#endif
diff --git a/security/nss/lib/softoken/mac_rand.c b/security/nss/lib/softoken/mac_rand.c
new file mode 100644
index 000000000..6198f3407
--- /dev/null
+++ b/security/nss/lib/softoken/mac_rand.c
@@ -0,0 +1,315 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifdef notdef
+#include "xp_core.h"
+#include "xp_file.h"
+#endif
+#include "secrng.h"
+#include "mcom_db.h"
+#ifdef XP_MAC
+#include <Events.h>
+#include <OSUtils.h>
+#include <QDOffscreen.h>
+#include <PPCToolbox.h>
+#include <Processes.h>
+#include <LowMem.h>
+#include <Scrap.h>
+
+/* Static prototypes */
+static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen);
+void FE_ReadScreen();
+
+static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen)
+{
+ union endianness {
+ int32 i;
+ char c[4];
+ } u;
+
+ if (srclen <= dstlen) {
+ memcpy(dst, src, srclen);
+ return srclen;
+ }
+ u.i = 0x01020304;
+ if (u.c[0] == 0x01) {
+ /* big-endian case */
+ memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
+ } else {
+ /* little-endian case */
+ memcpy(dst, src, dstlen);
+ }
+ return dstlen;
+}
+
+size_t RNG_GetNoise(void *buf, size_t maxbytes)
+{
+ UnsignedWide microTickCount;
+ Microseconds(&microTickCount);
+ return CopyLowBits(buf, maxbytes, &microTickCount, sizeof(microTickCount));
+}
+
+void RNG_FileForRNG(char *filename)
+{
+ unsigned char buffer[BUFSIZ];
+ size_t bytes;
+#ifdef notdef /*sigh*/
+ XP_File file;
+ unsigned long totalFileBytes = 0;
+
+ if (filename == NULL) /* For now, read in global history if filename is null */
+ file = XP_FileOpen(NULL, xpGlobalHistory,XP_FILE_READ_BIN);
+ else
+ file = XP_FileOpen(NULL, xpURL,XP_FILE_READ_BIN);
+ if (file != NULL) {
+ for (;;) {
+ bytes = XP_FileRead(buffer, sizeof(buffer), file);
+ if (bytes == 0) break;
+ RNG_RandomUpdate( buffer, bytes);
+ totalFileBytes += bytes;
+ if (totalFileBytes > 100*1024) break; /* No more than 100 K */
+ }
+ XP_FileClose(file);
+ }
+#endif
+ /*
+ * Pass yet another snapshot of our highest resolution clock into
+ * the hash function.
+ */
+ bytes = RNG_GetNoise(buffer, sizeof(buffer));
+ RNG_RandomUpdate(buffer, sizeof(buffer));
+}
+
+void RNG_SystemInfoForRNG()
+{
+/* Time */
+ {
+ unsigned long sec;
+ size_t bytes;
+ GetDateTime(&sec); /* Current time since 1970 */
+ RNG_RandomUpdate( &sec, sizeof(sec));
+ bytes = RNG_GetNoise(&sec, sizeof(sec));
+ RNG_RandomUpdate(&sec, bytes);
+ }
+/* User specific variables */
+ {
+ MachineLocation loc;
+ ReadLocation(&loc);
+ RNG_RandomUpdate( &loc, sizeof(loc));
+ }
+#if !TARGET_CARBON
+/* User name */
+ {
+ unsigned long userRef;
+ Str32 userName;
+ GetDefaultUser(&userRef, userName);
+ RNG_RandomUpdate( &userRef, sizeof(userRef));
+ RNG_RandomUpdate( userName, sizeof(userName));
+ }
+#endif
+/* Mouse location */
+ {
+ Point mouseLoc;
+ GetMouse(&mouseLoc);
+ RNG_RandomUpdate( &mouseLoc, sizeof(mouseLoc));
+ }
+/* Keyboard time threshold */
+ {
+ SInt16 keyTresh = LMGetKeyThresh();
+ RNG_RandomUpdate( &keyTresh, sizeof(keyTresh));
+ }
+/* Last key pressed */
+ {
+ SInt8 keyLast;
+ keyLast = LMGetKbdLast();
+ RNG_RandomUpdate( &keyLast, sizeof(keyLast));
+ }
+/* Volume */
+ {
+ UInt8 volume = LMGetSdVolume();
+ RNG_RandomUpdate( &volume, sizeof(volume));
+ }
+#if !TARGET_CARBON
+/* Current directory */
+ {
+ SInt32 dir = LMGetCurDirStore();
+ RNG_RandomUpdate( &dir, sizeof(dir));
+ }
+#endif
+/* Process information about all the processes in the machine */
+ {
+ ProcessSerialNumber process;
+ ProcessInfoRec pi;
+
+ process.highLongOfPSN = process.lowLongOfPSN = kNoProcess;
+
+ while (GetNextProcess(&process) == noErr)
+ {
+ FSSpec fileSpec;
+ pi.processInfoLength = sizeof(ProcessInfoRec);
+ pi.processName = NULL;
+ pi.processAppSpec = &fileSpec;
+ GetProcessInformation(&process, &pi);
+ RNG_RandomUpdate( &pi, sizeof(pi));
+ RNG_RandomUpdate( &fileSpec, sizeof(fileSpec));
+ }
+ }
+
+#if !TARGET_CARBON
+/* Heap */
+ {
+ THz zone = LMGetTheZone();
+ RNG_RandomUpdate( &zone, sizeof(zone));
+ }
+#endif
+
+/* Screen */
+ {
+ GDHandle h = GetMainDevice(); /* GDHandle is **GDevice */
+ RNG_RandomUpdate( *h, sizeof(GDevice));
+ }
+
+#if !TARGET_CARBON
+/* Scrap size */
+ {
+ SInt32 scrapSize = LMGetScrapSize();
+ RNG_RandomUpdate( &scrapSize, sizeof(scrapSize));
+ }
+/* Scrap count */
+ {
+ SInt16 scrapCount = LMGetScrapCount();
+ RNG_RandomUpdate( &scrapCount, sizeof(scrapCount));
+ }
+#else
+ {
+ ScrapRef scrap;
+ if (GetCurrentScrap(&scrap) == noErr) {
+ UInt32 flavorCount;
+ if (GetScrapFlavorCount(scrap, &flavorCount) == noErr) {
+ ScrapFlavorInfo* flavorInfo = (ScrapFlavorInfo*) malloc(flavorCount * sizeof(ScrapFlavorInfo));
+ if (flavorInfo != NULL) {
+ if (GetScrapFlavorInfoList(scrap, &flavorCount, flavorInfo) == noErr) {
+ UInt32 i;
+ RNG_RandomUpdate(&flavorCount, sizeof(flavorCount));
+ for (i = 0; i < flavorCount; ++i) {
+ Size flavorSize;
+ if (GetScrapFlavorSize(scrap, flavorInfo[i].flavorType, &flavorSize) == noErr)
+ RNG_RandomUpdate(&flavorSize, sizeof(flavorSize));
+ }
+ }
+ free(flavorInfo);
+ }
+ }
+ }
+ }
+#endif
+/* File stuff, last modified, etc. */
+ {
+ HParamBlockRec pb;
+ GetVolParmsInfoBuffer volInfo;
+ pb.ioParam.ioVRefNum = 0;
+ pb.ioParam.ioNamePtr = nil;
+ pb.ioParam.ioBuffer = (Ptr) &volInfo;
+ pb.ioParam.ioReqCount = sizeof(volInfo);
+ PBHGetVolParmsSync(&pb);
+ RNG_RandomUpdate( &volInfo, sizeof(volInfo));
+ }
+#if !TARGET_CARBON
+/* Event queue */
+ {
+ EvQElPtr eventQ;
+ for (eventQ = (EvQElPtr) LMGetEventQueue()->qHead;
+ eventQ;
+ eventQ = (EvQElPtr)eventQ->qLink)
+ RNG_RandomUpdate( &eventQ->evtQWhat, sizeof(EventRecord));
+ }
+#endif
+ FE_ReadScreen();
+ RNG_FileForRNG(NULL);
+}
+
+void FE_ReadScreen()
+{
+ UInt16 coords[4];
+ PixMapHandle pmap;
+ GDHandle gh;
+ UInt16 screenHeight;
+ UInt16 screenWidth; /* just what they say */
+ UInt32 bytesToRead; /* number of bytes we're giving */
+ UInt32 offset; /* offset into the graphics buffer */
+ UInt16 rowBytes;
+ UInt32 rowsToRead;
+ float bytesPerPixel; /* dependent on buffer depth */
+ Ptr p; /* temporary */
+ UInt16 x, y, w, h;
+
+ gh = LMGetMainDevice();
+ if ( !gh )
+ return;
+ pmap = (**gh).gdPMap;
+ if ( !pmap )
+ return;
+
+ RNG_GenerateGlobalRandomBytes( coords, sizeof( coords ) );
+
+ /* make x and y inside the screen rect */
+ screenHeight = (**pmap).bounds.bottom - (**pmap).bounds.top;
+ screenWidth = (**pmap).bounds.right - (**pmap).bounds.left;
+ x = coords[0] % screenWidth;
+ y = coords[1] % screenHeight;
+ w = ( coords[2] & 0x7F ) | 0x40; /* Make sure that w is in the range 64..128 */
+ h = ( coords[3] & 0x7F ) | 0x40; /* same for h */
+
+ bytesPerPixel = (**pmap).pixelSize / 8;
+ rowBytes = (**pmap).rowBytes & 0x7FFF;
+
+ /* starting address */
+ offset = ( rowBytes * y ) + (UInt32)( (float)x * bytesPerPixel );
+
+ /* don't read past the end of the pixmap's rowbytes */
+ bytesToRead = MIN( (UInt32)( w * bytesPerPixel ),
+ (UInt32)( rowBytes - ( x * bytesPerPixel ) ) );
+
+ /* don't read past the end of the graphics device pixmap */
+ rowsToRead = MIN( h,
+ ( screenHeight - y ) );
+
+ p = GetPixBaseAddr( pmap ) + offset;
+
+ while ( rowsToRead-- )
+ {
+ RNG_RandomUpdate( p, bytesToRead );
+ p += rowBytes;
+ }
+}
+#endif
diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn
index c889a90c4..9d06365bb 100644
--- a/security/nss/lib/softoken/manifest.mn
+++ b/security/nss/lib/softoken/manifest.mn
@@ -36,39 +36,42 @@ MODULE = security
REQUIRES = dbm
-LIBRARY_NAME = softoken
+LIBRARY_NAME = softokn
+LIBRARY_VERSION = 3
+MAPFILE = $(OBJDIR)/softokn.def
EXPORTS = \
- secpkcs5.h \
pkcs11.h \
pkcs11f.h \
pkcs11p.h \
pkcs11t.h \
+ pkcs11n.h \
pkcs11u.h \
$(NULL)
PRIVATE_EXPORTS = \
alghmac.h \
- pkcs11i.h \
pk11pars.h \
+ pkcs11i.h \
$(NULL)
CSRCS = \
alghmac.c \
- rsawrapr.c \
- pkcs11.c \
- pkcs11c.c \
- pkcs11u.c \
- secpkcs5.c \
+ dbinit.c \
+ fipstest.c \
+ fipstokn.c \
keydb.c \
+ lowcert.c \
lowkey.c \
+ lowpbe.c \
padbuf.c \
- fipstest.c \
- fipstokn.c \
- rawhash.c \
- dbinit.c \
+ pcertdb.c \
pk11db.c \
+ pkcs11.c \
+ pkcs11c.c \
+ pkcs11u.c \
+ rawhash.c \
+ rsawrapr.c \
+ sysrand.c \
$(NULL)
-
-
diff --git a/security/nss/lib/softoken/os2_rand.c b/security/nss/lib/softoken/os2_rand.c
new file mode 100644
index 000000000..b1dbba805
--- /dev/null
+++ b/security/nss/lib/softoken/os2_rand.c
@@ -0,0 +1,329 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+#include <secrng.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+static BOOL clockTickTime(unsigned long *phigh, unsigned long *plow)
+{
+ APIRET rc = NO_ERROR;
+ QWORD qword = {0,0};
+
+ rc = DosTmrQueryTime(&qword);
+ if (rc != NO_ERROR)
+ return FALSE;
+
+ *phigh = qword.ulHi;
+ *plow = qword.ulLo;
+
+ return TRUE;
+}
+
+size_t RNG_GetNoise(void *buf, size_t maxbuf)
+{
+ unsigned long high = 0;
+ unsigned long low = 0;
+ clock_t val = 0;
+ int n = 0;
+ int nBytes = 0;
+ time_t sTime;
+
+ if (maxbuf <= 0)
+ return 0;
+
+ clockTickTime(&high, &low);
+
+ /* get the maximally changing bits first */
+ nBytes = sizeof(low) > maxbuf ? maxbuf : sizeof(low);
+ memcpy(buf, &low, nBytes);
+ n += nBytes;
+ maxbuf -= nBytes;
+
+ if (maxbuf <= 0)
+ return n;
+
+ nBytes = sizeof(high) > maxbuf ? maxbuf : sizeof(high);
+ memcpy(((char *)buf) + n, &high, nBytes);
+ n += nBytes;
+ maxbuf -= nBytes;
+
+ if (maxbuf <= 0)
+ return n;
+
+ /* get the number of milliseconds that have elapsed since application started */
+ val = clock();
+
+ nBytes = sizeof(val) > maxbuf ? maxbuf : sizeof(val);
+ memcpy(((char *)buf) + n, &val, nBytes);
+ n += nBytes;
+ maxbuf -= nBytes;
+
+ if (maxbuf <= 0)
+ return n;
+
+ /* get the time in seconds since midnight Jan 1, 1970 */
+ time(&sTime);
+ nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
+ memcpy(((char *)buf) + n, &sTime, nBytes);
+ n += nBytes;
+
+ return n;
+}
+
+static BOOL
+EnumSystemFiles(void (*func)(char *))
+{
+ APIRET rc;
+ ULONG sysInfo = 0;
+ char bootLetter[2];
+ char sysDir[_MAX_PATH] = "";
+ char filename[_MAX_PATH];
+ HDIR hdir = HDIR_CREATE;
+ ULONG numFiles = 1;
+ FILEFINDBUF3 fileBuf = {0};
+ ULONG buflen = sizeof(FILEFINDBUF3);
+
+ if (DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&sysInfo,
+ sizeof(ULONG)) == NO_ERROR)
+ {
+ bootLetter[0] = sysInfo + 'A' -1;
+ strcpy(sysDir, bootLetter);
+ strcpy(sysDir+1, ":\\OS2\\");
+
+ strcpy( filename, sysDir );
+ strcat( filename, "*.*" );
+ }
+
+ rc =DosFindFirst( filename, &hdir, FILE_NORMAL, &fileBuf, buflen,
+ &numFiles, FIL_STANDARD );
+ if( rc == NO_ERROR )
+ {
+ do {
+ // pass the full pathname to the callback
+ sprintf( filename, "%s\\%s", sysDir, fileBuf.achName );
+ (*func)(filename);
+
+ numFiles = 1;
+ rc = DosFindNext( hdir, &fileBuf, buflen, &numFiles );
+ if( rc != NO_ERROR && rc != ERROR_NO_MORE_FILES )
+ printf( "DosFindNext errod code = %d\n", rc );
+ } while ( rc == NO_ERROR );
+
+ rc = DosFindClose(hdir);
+ if( rc != NO_ERROR )
+ printf( "DosFindClose error code = %d", rc );
+ }
+ else
+ printf( "DosFindFirst error code = %d", rc );
+
+ return TRUE;
+}
+
+static int dwNumFiles, dwReadEvery;
+
+static void
+CountFiles(char *file)
+{
+ dwNumFiles++;
+}
+
+static void
+ReadFiles(char *file)
+{
+ if ((dwNumFiles % dwReadEvery) == 0)
+ RNG_FileForRNG(file);
+
+ dwNumFiles++;
+}
+
+static void
+ReadSystemFiles()
+{
+ // first count the number of files
+ dwNumFiles = 0;
+ if (!EnumSystemFiles(CountFiles))
+ return;
+
+ RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles));
+
+ // now read 10 files
+ if (dwNumFiles == 0)
+ return;
+
+ dwReadEvery = dwNumFiles / 10;
+ if (dwReadEvery == 0)
+ dwReadEvery = 1; // less than 10 files
+
+ dwNumFiles = 0;
+ EnumSystemFiles(ReadFiles);
+}
+
+void RNG_SystemInfoForRNG(void)
+{
+ unsigned long *plong = 0;
+ PTIB ptib;
+ PPIB ppib;
+ APIRET rc = NO_ERROR;
+ DATETIME dt;
+ COUNTRYCODE cc = {0};
+ COUNTRYINFO ci = {0};
+ unsigned long actual = 0;
+ char path[_MAX_PATH]="";
+ char fullpath[_MAX_PATH]="";
+ unsigned long pathlength = sizeof(path);
+ FSALLOCATE fsallocate;
+ FILESTATUS3 fstatus;
+ unsigned long defaultdrive = 0;
+ unsigned long logicaldrives = 0;
+ unsigned long sysInfo[QSV_MAX] = {0};
+ char buffer[20];
+ int nBytes = 0;
+
+ nBytes = RNG_GetNoise(buffer, sizeof(buffer));
+ RNG_RandomUpdate(buffer, nBytes);
+
+ /* allocate memory and use address and memory */
+ plong = (unsigned long *)malloc(sizeof(*plong));
+ RNG_RandomUpdate(&plong, sizeof(plong));
+ RNG_RandomUpdate(plong, sizeof(*plong));
+ free(plong);
+
+ /* process info */
+ rc = DosGetInfoBlocks(&ptib, &ppib);
+ if (rc == NO_ERROR)
+ {
+ RNG_RandomUpdate(ptib, sizeof(*ptib));
+ RNG_RandomUpdate(ppib, sizeof(*ppib));
+ }
+
+ /* time */
+ rc = DosGetDateTime(&dt);
+ if (rc == NO_ERROR)
+ {
+ RNG_RandomUpdate(&dt, sizeof(dt));
+ }
+
+ /* country */
+ rc = DosQueryCtryInfo(sizeof(ci), &cc, &ci, &actual);
+ if (rc == NO_ERROR)
+ {
+ RNG_RandomUpdate(&cc, sizeof(cc));
+ RNG_RandomUpdate(&ci, sizeof(ci));
+ RNG_RandomUpdate(&actual, sizeof(actual));
+ }
+
+ /* current directory */
+ rc = DosQueryCurrentDir(0, path, &pathlength);
+ strcat(fullpath, "\\");
+ strcat(fullpath, path);
+ if (rc == NO_ERROR)
+ {
+ RNG_RandomUpdate(fullpath, strlen(fullpath));
+ // path info
+ rc = DosQueryPathInfo(fullpath, FIL_STANDARD, &fstatus, sizeof(fstatus));
+ if (rc == NO_ERROR)
+ {
+ RNG_RandomUpdate(&fstatus, sizeof(fstatus));
+ }
+ }
+
+ /* file system info */
+ rc = DosQueryFSInfo(0, FSIL_ALLOC, &fsallocate, sizeof(fsallocate));
+ if (rc == NO_ERROR)
+ {
+ RNG_RandomUpdate(&fsallocate, sizeof(fsallocate));
+ }
+
+ /* drive info */
+ rc = DosQueryCurrentDisk(&defaultdrive, &logicaldrives);
+ if (rc == NO_ERROR)
+ {
+ RNG_RandomUpdate(&defaultdrive, sizeof(defaultdrive));
+ RNG_RandomUpdate(&logicaldrives, sizeof(logicaldrives));
+ }
+
+ /* system info */
+ rc = DosQuerySysInfo(1L, QSV_MAX, (PVOID)&sysInfo, sizeof(ULONG)*QSV_MAX);
+ if (rc == NO_ERROR)
+ {
+ RNG_RandomUpdate(&sysInfo, sizeof(sysInfo));
+ }
+
+ // now let's do some files
+ ReadSystemFiles();
+
+ /* more noise */
+ nBytes = RNG_GetNoise(buffer, sizeof(buffer));
+ RNG_RandomUpdate(buffer, nBytes);
+}
+
+void RNG_FileForRNG(char *filename)
+{
+ struct stat stat_buf;
+ unsigned char buffer[1024];
+ FILE *file = 0;
+ int nBytes = 0;
+ static int totalFileBytes = 0;
+
+ if (stat((char *)filename, &stat_buf) < 0)
+ return;
+
+ RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf));
+
+ file = fopen((char *)filename, "r");
+ if (file != NULL)
+ {
+ for (;;)
+ {
+ size_t bytes = fread(buffer, 1, sizeof(buffer), file);
+
+ if (bytes == 0)
+ break;
+
+ RNG_RandomUpdate(buffer, bytes);
+ totalFileBytes += bytes;
+ if (totalFileBytes > 250000)
+ break;
+ }
+ fclose(file);
+ }
+
+ nBytes = RNG_GetNoise(buffer, 20);
+ RNG_RandomUpdate(buffer, nBytes);
+}
diff --git a/security/nss/lib/softoken/pcert.h b/security/nss/lib/softoken/pcert.h
new file mode 100644
index 000000000..51a969f1a
--- /dev/null
+++ b/security/nss/lib/softoken/pcert.h
@@ -0,0 +1,147 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef _PCERTDB_H_
+#define _PCERTDB_H_
+
+#include "plarena.h"
+#include "prlong.h"
+#include "pcertt.h"
+
+SEC_BEGIN_PROTOS
+
+/*
+** Add a DER encoded certificate to the permanent database.
+** "derCert" is the DER encoded certificate.
+** "nickname" is the nickname to use for the cert
+** "trust" is the trust parameters for the cert
+*/
+SECStatus nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *handle,
+ NSSLOWCERTCertificate *cert,
+ char *nickname, NSSLOWCERTCertTrust *trust);
+
+SECStatus nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert);
+
+typedef SECStatus (PR_CALLBACK * PermCertCallback)(NSSLOWCERTCertificate *cert,
+ SECItem *k, void *pdata);
+/*
+** Traverse the entire permanent database, and pass the certs off to a
+** user supplied function.
+** "certfunc" is the user function to call for each certificate
+** "udata" is the user's data, which is passed through to "certfunc"
+*/
+SECStatus
+nsslowcert_TraversePermCerts(NSSLOWCERTCertDBHandle *handle,
+ PermCertCallback certfunc,
+ void *udata );
+
+PRBool
+nsslowcert_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle);
+
+SECItem *
+nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey,
+ char **urlp, PRBool isKRL);
+
+SECStatus
+nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle,SECItem *derName,
+ PRBool isKRL);
+SECStatus
+nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl ,
+ SECItem *derKey, char *url, PRBool isKRL);
+
+NSSLOWCERTCertDBHandle *nsslowcert_GetDefaultCertDB();
+NSSLOWKEYPublicKey *nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *);
+
+NSSLOWCERTCertificate *
+nsslowcert_NewTempCertificate(NSSLOWCERTCertDBHandle *handle, SECItem *derCert,
+ char *nickname, PRBool isperm, PRBool copyDER);
+NSSLOWCERTCertificate *
+nsslowcert_DupCertificate(NSSLOWCERTCertificate *cert);
+void nsslowcert_DestroyCertificate(NSSLOWCERTCertificate *cert);
+
+/*
+ * Lookup a certificate in the databases without locking
+ * "certKey" is the database key to look for
+ *
+ * XXX - this should be internal, but pkcs 11 needs to call it during a
+ * traversal.
+ */
+NSSLOWCERTCertificate *
+nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey);
+
+/*
+** Generate a certificate key from the issuer and serialnumber, then look it
+** up in the database. Return the cert if found.
+** "issuerAndSN" is the issuer and serial number to look for
+*/
+extern NSSLOWCERTCertificate *
+nsslowcert_FindCertByIssuerAndSN (NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN);
+
+/*
+** Find a certificate in the database by a DER encoded certificate
+** "derCert" is the DER encoded certificate
+*/
+extern NSSLOWCERTCertificate *
+nsslowcert_FindCertByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCert);
+
+/* convert an email address to lower case */
+char *nsslowcert_FixupEmailAddr(char *emailAddr);
+
+/*
+** Decode a DER encoded certificate into an NSSLOWCERTCertificate structure
+** "derSignedCert" is the DER encoded signed certificate
+** "copyDER" is true if the DER should be copied, false if the
+** existing copy should be referenced
+** "nickname" is the nickname to use in the database. If it is NULL
+** then a temporary nickname is generated.
+*/
+extern NSSLOWCERTCertificate *
+nsslowcert_DecodeDERCertificate (SECItem *derSignedCert, PRBool copyDER, char *nickname);
+
+SECStatus
+nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key);
+
+certDBEntrySMime *
+nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *certHandle,
+ char *emailAddr);
+void
+nsslowcert_DestroyDBEntry(certDBEntry *entry);
+
+SECStatus
+nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
+ NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile);
+
+
+SEC_END_PROTOS
+
+ #endif /* _PCERTDB_H_ */
diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c
new file mode 100644
index 000000000..e23752990
--- /dev/null
+++ b/security/nss/lib/softoken/pcertdb.c
@@ -0,0 +1,4410 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Permanent Certificate database handling code
+ *
+ * $Id$
+ */
+#include "prtime.h"
+
+#include "lowkeyti.h"
+#include "pcert.h"
+#include "mcom_db.h"
+#include "pcert.h"
+#include "secitem.h"
+#include "secder.h"
+
+/* Call to PK11_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"
+
+/* forward declaration */
+NSSLOWCERTCertificate *
+nsslowcert_FindCertByDERCertNoLocking(NSSLOWCERTCertDBHandle *handle, SECItem *derCert);
+
+/*
+ * the following functions are wrappers for the db library that implement
+ * a global lock to make the database thread safe.
+ */
+static PZLock *dbLock = NULL;
+
+void
+certdb_InitDBLock(NSSLOWCERTCertDBHandle *handle)
+{
+ if (dbLock == NULL) {
+ nss_InitLock(&dbLock, nssILockCertDB);
+ PORT_Assert(dbLock != NULL);
+ }
+
+ return;
+}
+
+/*
+ * Acquire the global lock on the cert database.
+ * This lock is currently used for the following operations:
+ * adding or deleting a cert to either the temp or perm databases
+ * converting a temp to perm or perm to temp
+ * changing(maybe just adding????) the trust of a cert
+ * chaning the DB status checking Configuration
+ */
+static void
+nsslowcert_LockDB(NSSLOWCERTCertDBHandle *handle)
+{
+ PZ_EnterMonitor(handle->dbMon);
+ return;
+}
+
+/*
+ * Free the global cert database lock.
+ */
+static void
+nsslowcert_UnlockDB(NSSLOWCERTCertDBHandle *handle)
+{
+ PRStatus prstat;
+
+ prstat = PZ_ExitMonitor(handle->dbMon);
+
+ PORT_Assert(prstat == PR_SUCCESS);
+
+ return;
+}
+
+static PZLock *certRefCountLock = NULL;
+
+/*
+ * Acquire the cert reference count lock
+ * There is currently one global lock for all certs, but I'm putting a cert
+ * arg here so that it will be easy to make it per-cert in the future if
+ * that turns out to be necessary.
+ */
+static void
+nsslowcert_LockCertRefCount(NSSLOWCERTCertificate *cert)
+{
+ if ( certRefCountLock == NULL ) {
+ nss_InitLock(&certRefCountLock, nssILockRefLock);
+ PORT_Assert(certRefCountLock != NULL);
+ }
+
+ PZ_Lock(certRefCountLock);
+ return;
+}
+
+/*
+ * Free the cert reference count lock
+ */
+static void
+nsslowcert_UnlockCertRefCount(NSSLOWCERTCertificate *cert)
+{
+ PRStatus prstat;
+
+ PORT_Assert(certRefCountLock != NULL);
+
+ prstat = PZ_Unlock(certRefCountLock);
+
+ PORT_Assert(prstat == PR_SUCCESS);
+
+ return;
+}
+
+static PZLock *certTrustLock = NULL;
+
+/*
+ * Acquire the cert trust lock
+ * There is currently one global lock for all certs, but I'm putting a 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
+nsslowcert_LockCertTrust(NSSLOWCERTCertificate *cert)
+{
+ if ( certTrustLock == NULL ) {
+ nss_InitLock(&certTrustLock, nssILockCertDB);
+ PORT_Assert(certTrustLock != NULL);
+ }
+
+ PZ_Lock(certTrustLock);
+ return;
+}
+
+/*
+ * Free the cert trust lock
+ */
+void
+nsslowcert_UnlockCertTrust(NSSLOWCERTCertificate *cert)
+{
+ PRStatus prstat;
+
+ PORT_Assert(certTrustLock != NULL);
+
+ prstat = PZ_Unlock(certTrustLock);
+
+ PORT_Assert(prstat == PR_SUCCESS);
+
+ return;
+}
+
+
+static int
+certdb_Get(DB *db, DBT *key, DBT *data, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret;
+
+ PORT_Assert(dbLock != NULL);
+ PZ_Lock(dbLock);
+
+ ret = (* db->get)(db, key, data, flags);
+
+ prstat = PZ_Unlock(dbLock);
+
+ return(ret);
+}
+
+static int
+certdb_Put(DB *db, DBT *key, DBT *data, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret;
+
+ PORT_Assert(dbLock != NULL);
+ PZ_Lock(dbLock);
+
+ ret = (* db->put)(db, key, data, flags);
+
+ prstat = PZ_Unlock(dbLock);
+
+ return(ret);
+}
+
+static int
+certdb_Sync(DB *db, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret;
+
+ PORT_Assert(dbLock != NULL);
+ PZ_Lock(dbLock);
+
+ ret = (* db->sync)(db, flags);
+
+ prstat = PZ_Unlock(dbLock);
+
+ return(ret);
+}
+
+static int
+certdb_Del(DB *db, DBT *key, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret;
+
+ PORT_Assert(dbLock != NULL);
+ PZ_Lock(dbLock);
+
+ ret = (* db->del)(db, key, flags);
+
+ prstat = PZ_Unlock(dbLock);
+
+ return(ret);
+}
+
+static int
+certdb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret;
+
+ PORT_Assert(dbLock != NULL);
+ PZ_Lock(dbLock);
+
+ ret = (* db->seq)(db, key, data, flags);
+
+ prstat = PZ_Unlock(dbLock);
+
+ return(ret);
+}
+
+static void
+certdb_Close(DB *db)
+{
+ PRStatus prstat;
+
+ PORT_Assert(dbLock != NULL);
+ PZ_Lock(dbLock);
+
+ (* db->close)(db);
+
+ prstat = PZ_Unlock(dbLock);
+
+ return;
+}
+
+/* forward references */
+static void nsslowcert_DestroyCertificateNoLocking(NSSLOWCERTCertificate *cert);
+
+static SECStatus
+DeleteDBEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryType type, SECItem *dbkey)
+{
+ DBT key;
+ int ret;
+
+ /* init the database key */
+ key.data = dbkey->data;
+ key.size = dbkey->len;
+
+ dbkey->data[0] = (unsigned char)type;
+
+ /* delete entry from database */
+ ret = certdb_Del(handle->permCertDB, &key, 0 );
+ if ( ret != 0 ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ ret = certdb_Sync(handle->permCertDB, 0);
+ if ( ret ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+static SECStatus
+ReadDBEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCommon *entry,
+ SECItem *dbkey, SECItem *dbentry, PRArenaPool *arena)
+{
+ DBT data, key;
+ int ret;
+ unsigned char *buf;
+
+ /* init the database key */
+ key.data = dbkey->data;
+ key.size = dbkey->len;
+
+ dbkey->data[0] = (unsigned char)entry->type;
+
+ /* read entry from database */
+ ret = certdb_Get(handle->permCertDB, &key, &data, 0 );
+ if ( ret != 0 ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ /* validate the entry */
+ if ( data.size < SEC_DB_ENTRY_HEADER_LEN ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+ buf = (unsigned char *)data.data;
+ if ( buf[0] != (unsigned char)CERT_DB_FILE_VERSION ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+ if ( buf[1] != (unsigned char)entry->type ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ /* copy out header information */
+ entry->version = (unsigned int)buf[0];
+ entry->type = (certDBEntryType)buf[1];
+ entry->flags = (unsigned int)buf[2];
+
+ /* format body of entry for return to caller */
+ dbentry->len = data.size - SEC_DB_ENTRY_HEADER_LEN;
+ if ( dbentry->len ) {
+ dbentry->data = (unsigned char *)PORT_ArenaAlloc(arena, dbentry->len);
+ if ( dbentry->data == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ PORT_Memcpy(dbentry->data, &buf[SEC_DB_ENTRY_HEADER_LEN],
+ dbentry->len);
+ } else {
+ dbentry->data = NULL;
+ }
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/**
+ ** Implement low level database access
+ **/
+static SECStatus
+WriteDBEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCommon *entry,
+ SECItem *dbkey, SECItem *dbentry)
+{
+ int ret;
+ DBT data, key;
+ unsigned char *buf;
+
+ data.data = dbentry->data;
+ data.size = dbentry->len;
+
+ buf = (unsigned char*)data.data;
+
+ buf[0] = (unsigned char)entry->version;
+ buf[1] = (unsigned char)entry->type;
+ buf[2] = (unsigned char)entry->flags;
+
+ key.data = dbkey->data;
+ key.size = dbkey->len;
+
+ dbkey->data[0] = (unsigned char)entry->type;
+
+ /* put the record into the database now */
+ ret = certdb_Put(handle->permCertDB, &key, &data, 0);
+
+ if ( ret != 0 ) {
+ goto loser;
+ }
+
+ ret = certdb_Sync( handle->permCertDB, 0 );
+
+ if ( ret ) {
+ goto loser;
+ }
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * encode a database cert record
+ */
+static SECStatus
+EncodeDBCertEntry(certDBEntryCert *entry, PRArenaPool *arena, SECItem *dbitem)
+{
+ unsigned int nnlen;
+ unsigned char *buf;
+ char *nn;
+ char zbuf = 0;
+
+ if ( entry->nickname ) {
+ nn = entry->nickname;
+ } else {
+ nn = &zbuf;
+ }
+ nnlen = PORT_Strlen(nn) + 1;
+
+ /* allocate space for encoded database record, including space
+ * for low level header
+ */
+ dbitem->len = entry->derCert.len + nnlen + DB_CERT_ENTRY_HEADER_LEN +
+ SEC_DB_ENTRY_HEADER_LEN;
+
+ dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len);
+ if ( dbitem->data == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ /* fill in database record */
+ buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
+
+ buf[0] = ( entry->trust.sslFlags >> 8 ) & 0xff;
+ buf[1] = entry->trust.sslFlags & 0xff;
+ buf[2] = ( entry->trust.emailFlags >> 8 ) & 0xff;
+ buf[3] = entry->trust.emailFlags & 0xff;
+ buf[4] = ( entry->trust.objectSigningFlags >> 8 ) & 0xff;
+ buf[5] = entry->trust.objectSigningFlags & 0xff;
+ buf[6] = ( entry->derCert.len >> 8 ) & 0xff;
+ buf[7] = entry->derCert.len & 0xff;
+ buf[8] = ( nnlen >> 8 ) & 0xff;
+ buf[9] = nnlen & 0xff;
+
+ PORT_Memcpy(&buf[DB_CERT_ENTRY_HEADER_LEN], entry->derCert.data,
+ entry->derCert.len);
+
+ PORT_Memcpy(&buf[DB_CERT_ENTRY_HEADER_LEN + entry->derCert.len],
+ nn, nnlen);
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * encode a database key for a cert record
+ */
+static SECStatus
+EncodeDBCertKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey)
+{
+ dbkey->len = certKey->len + SEC_DB_KEY_HEADER_LEN;
+ dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
+ if ( dbkey->data == NULL ) {
+ goto loser;
+ }
+ PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN],
+ certKey->data, certKey->len);
+ dbkey->data[0] = certDBEntryTypeCert;
+
+ return(SECSuccess);
+loser:
+ return(SECFailure);
+}
+
+static SECStatus
+EncodeDBGenericKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey,
+ certDBEntryType entryType)
+{
+ /*
+ * we only allow _one_ KRL key!
+ */
+ if (entryType == certDBEntryTypeKeyRevocation) {
+ dbkey->len = SEC_DB_KEY_HEADER_LEN;
+ dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
+ if ( dbkey->data == NULL ) {
+ goto loser;
+ }
+ dbkey->data[0] = (unsigned char) entryType;
+ return(SECSuccess);
+ }
+
+
+ dbkey->len = certKey->len + SEC_DB_KEY_HEADER_LEN;
+ dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
+ if ( dbkey->data == NULL ) {
+ goto loser;
+ }
+ PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN],
+ certKey->data, certKey->len);
+ dbkey->data[0] = (unsigned char) entryType;
+
+ return(SECSuccess);
+loser:
+ return(SECFailure);
+}
+
+static SECStatus
+DecodeDBCertEntry(certDBEntryCert *entry, SECItem *dbentry)
+{
+ unsigned int nnlen;
+ int headerlen;
+ int lenoff;
+
+ /* allow updates of old versions of the database */
+ switch ( entry->common.version ) {
+ case 5:
+ headerlen = DB_CERT_V5_ENTRY_HEADER_LEN;
+ lenoff = 3;
+ break;
+ case 6:
+ /* should not get here */
+ PORT_Assert(0);
+ headerlen = DB_CERT_V6_ENTRY_HEADER_LEN;
+ lenoff = 3;
+ break;
+ case 7:
+ headerlen = DB_CERT_ENTRY_HEADER_LEN;
+ lenoff = 6;
+ break;
+ default:
+ /* better not get here */
+ PORT_Assert(0);
+ headerlen = DB_CERT_V5_ENTRY_HEADER_LEN;
+ lenoff = 3;
+ break;
+ }
+
+ /* is record long enough for header? */
+ if ( dbentry->len < headerlen ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ /* is database entry correct length? */
+ entry->derCert.len = ( ( dbentry->data[lenoff] << 8 ) |
+ dbentry->data[lenoff+1] );
+ nnlen = ( ( dbentry->data[lenoff+2] << 8 ) | dbentry->data[lenoff+3] );
+ if ( ( entry->derCert.len + nnlen + headerlen )
+ != dbentry->len) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ /* copy the dercert */
+ entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(entry->common.arena,
+ entry->derCert.len);
+ if ( entry->derCert.data == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->derCert.data, &dbentry->data[headerlen],
+ entry->derCert.len);
+
+ /* copy the nickname */
+ if ( nnlen > 1 ) {
+ entry->nickname = (char *)PORT_ArenaAlloc(entry->common.arena, nnlen);
+ if ( entry->nickname == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->nickname,
+ &dbentry->data[headerlen +
+ entry->derCert.len],
+ nnlen);
+ } else {
+ entry->nickname = NULL;
+ }
+
+ if ( entry->common.version < 7 ) {
+ /* allow updates of v5 db */
+ entry->trust.sslFlags = dbentry->data[0];
+ entry->trust.emailFlags = dbentry->data[1];
+ entry->trust.objectSigningFlags = dbentry->data[2];
+ } else {
+ entry->trust.sslFlags = ( dbentry->data[0] << 8 ) | dbentry->data[1];
+ entry->trust.emailFlags = ( dbentry->data[2] << 8 ) | dbentry->data[3];
+ entry->trust.objectSigningFlags =
+ ( dbentry->data[4] << 8 ) | dbentry->data[5];
+ }
+
+ return(SECSuccess);
+loser:
+ return(SECFailure);
+}
+
+
+/*
+ * Create a new certDBEntryCert from existing data
+ */
+static certDBEntryCert *
+NewDBCertEntry(SECItem *derCert, char *nickname,
+ NSSLOWCERTCertTrust *trust, int flags)
+{
+ certDBEntryCert *entry;
+ PRArenaPool *arena = NULL;
+ int nnlen;
+
+ arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE );
+
+ if ( !arena ) {
+ goto loser;
+ }
+
+ entry = (certDBEntryCert *)PORT_ArenaZAlloc(arena, sizeof(certDBEntryCert));
+
+ if ( entry == NULL ) {
+ goto loser;
+ }
+
+ /* fill in the dbCert */
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeCert;
+ entry->common.version = CERT_DB_FILE_VERSION;
+ entry->common.flags = flags;
+
+ if ( trust ) {
+ entry->trust = *trust;
+ }
+
+ entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(arena, derCert->len);
+ if ( !entry->derCert.data ) {
+ goto loser;
+ }
+ entry->derCert.len = derCert->len;
+ PORT_Memcpy(entry->derCert.data, derCert->data, derCert->len);
+
+ nnlen = ( nickname ? strlen(nickname) + 1 : 0 );
+
+ if ( nnlen ) {
+ entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen);
+ if ( !entry->nickname ) {
+ goto loser;
+ }
+ PORT_Memcpy(entry->nickname, nickname, nnlen);
+
+ } else {
+ entry->nickname = 0;
+ }
+
+ return(entry);
+
+loser:
+
+ /* allocation error, free arena and return */
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return(0);
+}
+
+/*
+ * Decode a version 4 DBCert from the byte stream database format
+ * and construct a current database entry struct
+ */
+static certDBEntryCert *
+DecodeV4DBCertEntry(unsigned char *buf, int len)
+{
+ certDBEntryCert *entry;
+ int certlen;
+ int nnlen;
+ PRArenaPool *arena;
+
+ /* make sure length is at least long enough for the header */
+ if ( len < DBCERT_V4_HEADER_LEN ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ return(0);
+ }
+
+ /* get other lengths */
+ certlen = buf[3] << 8 | buf[4];
+ nnlen = buf[5] << 8 | buf[6];
+
+ /* make sure DB entry is the right size */
+ if ( ( certlen + nnlen + DBCERT_V4_HEADER_LEN ) != len ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ return(0);
+ }
+
+ /* allocate arena */
+ arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE );
+
+ if ( !arena ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return(0);
+ }
+
+ /* allocate structure and members */
+ entry = (certDBEntryCert *) PORT_ArenaAlloc(arena, sizeof(certDBEntryCert));
+
+ if ( !entry ) {
+ goto loser;
+ }
+
+ entry->derCert.data = (unsigned char *)PORT_ArenaAlloc(arena, certlen);
+ if ( !entry->derCert.data ) {
+ goto loser;
+ }
+ entry->derCert.len = certlen;
+
+ if ( nnlen ) {
+ entry->nickname = (char *) PORT_ArenaAlloc(arena, nnlen);
+ if ( !entry->nickname ) {
+ goto loser;
+ }
+ } else {
+ entry->nickname = 0;
+ }
+
+ entry->common.arena = arena;
+ entry->common.version = CERT_DB_FILE_VERSION;
+ entry->common.type = certDBEntryTypeCert;
+ entry->common.flags = 0;
+ entry->trust.sslFlags = buf[0];
+ entry->trust.emailFlags = buf[1];
+ entry->trust.objectSigningFlags = buf[2];
+
+ PORT_Memcpy(entry->derCert.data, &buf[DBCERT_V4_HEADER_LEN], certlen);
+ PORT_Memcpy(entry->nickname, &buf[DBCERT_V4_HEADER_LEN + certlen], nnlen);
+
+ if (PORT_Strcmp(entry->nickname,"Server-Cert") == 0) {
+ entry->trust.sslFlags |= CERTDB_USER;
+ }
+
+ return(entry);
+
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return(0);
+}
+
+/*
+ * Encode a Certificate database entry into byte stream suitable for
+ * the database
+ */
+static SECStatus
+WriteDBCertEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry)
+{
+ SECItem dbitem, dbkey;
+ PRArenaPool *tmparena = NULL;
+ SECItem tmpitem;
+ SECStatus rv;
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBCertEntry(entry, tmparena, &dbitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* get the database key and format it */
+ rv = nsslowcert_KeyFromDERCert(tmparena, &entry->derCert, &tmpitem);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ rv = EncodeDBCertKey(&tmpitem, tmparena, &dbkey);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ /* now write it to the database */
+ rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ return(SECFailure);
+}
+
+
+/*
+ * delete a certificate entry
+ */
+static SECStatus
+DeleteDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
+{
+ SECItem dbkey;
+ PRArenaPool *arena = NULL;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBCertKey(certKey, arena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = DeleteDBEntry(handle, certDBEntryTypeCert, &dbkey);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(SECFailure);
+}
+
+/*
+ * Read a certificate entry
+ */
+static certDBEntryCert *
+ReadDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
+{
+ PRArenaPool *arena = NULL;
+ PRArenaPool *tmparena = NULL;
+ certDBEntryCert *entry;
+ SECItem dbkey;
+ SECItem dbentry;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntryCert *)PORT_ArenaAlloc(arena, sizeof(certDBEntryCert));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeCert;
+
+ rv = EncodeDBCertKey(certKey, tmparena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ rv = DecodeDBCertEntry(entry, &dbentry);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(entry);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+/*
+ * encode a database cert record
+ */
+static SECStatus
+EncodeDBCrlEntry(certDBEntryRevocation *entry, PRArenaPool *arena, SECItem *dbitem)
+{
+ unsigned int nnlen = 0;
+ unsigned char *buf;
+
+ if (entry->url) {
+ nnlen = PORT_Strlen(entry->url) + 1;
+ }
+
+ /* allocate space for encoded database record, including space
+ * for low level header
+ */
+ dbitem->len = entry->derCrl.len + nnlen
+ + SEC_DB_ENTRY_HEADER_LEN + DB_CRL_ENTRY_HEADER_LEN;
+
+ dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len);
+ if ( dbitem->data == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ /* fill in database record */
+ buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
+
+ buf[0] = ( entry->derCrl.len >> 8 ) & 0xff;
+ buf[1] = entry->derCrl.len & 0xff;
+ buf[2] = ( nnlen >> 8 ) & 0xff;
+ buf[3] = nnlen & 0xff;
+
+ PORT_Memcpy(&buf[DB_CRL_ENTRY_HEADER_LEN], entry->derCrl.data,
+ entry->derCrl.len);
+
+ if (nnlen != 0) {
+ PORT_Memcpy(&buf[DB_CRL_ENTRY_HEADER_LEN + entry->derCrl.len],
+ entry->url, nnlen);
+ }
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+static SECStatus
+DecodeDBCrlEntry(certDBEntryRevocation *entry, SECItem *dbentry)
+{
+ unsigned int nnlen;
+
+ /* is record long enough for header? */
+ if ( dbentry->len < DB_CRL_ENTRY_HEADER_LEN ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ /* is database entry correct length? */
+ entry->derCrl.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] );
+ nnlen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] );
+ if ( ( entry->derCrl.len + nnlen + DB_CRL_ENTRY_HEADER_LEN )
+ != dbentry->len) {
+ /* CRL entry is greater than 64 K. Hack to make this continue to work */
+ if (dbentry->len >= (0xffff - DB_CRL_ENTRY_HEADER_LEN) - nnlen) {
+ entry->derCrl.len =
+ (dbentry->len - DB_CRL_ENTRY_HEADER_LEN) - nnlen;
+ } else {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+ }
+
+ /* copy the dercert */
+ entry->derCrl.data = (unsigned char *)PORT_ArenaAlloc(entry->common.arena,
+ entry->derCrl.len);
+ if ( entry->derCrl.data == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->derCrl.data, &dbentry->data[DB_CRL_ENTRY_HEADER_LEN],
+ entry->derCrl.len);
+
+ /* copy the url */
+ entry->url = NULL;
+ if (nnlen != 0) {
+ entry->url = (char *)PORT_ArenaAlloc(entry->common.arena, nnlen);
+ if ( entry->url == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->url,
+ &dbentry->data[DB_CRL_ENTRY_HEADER_LEN + entry->derCrl.len],
+ nnlen);
+ }
+
+ return(SECSuccess);
+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 = (certDBEntryRevocation*)
+ PORT_ArenaZAlloc(arena, sizeof(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 )
+{
+ SECItem dbkey;
+ PRArenaPool *tmparena = NULL;
+ SECItem encodedEntry;
+ SECStatus rv;
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBCrlEntry(entry, tmparena, &encodedEntry);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ rv = EncodeDBGenericKey(crlKey, tmparena, &dbkey, entry->common.type);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ /* now write it to the database */
+ rv = WriteDBEntry(handle, &entry->common, &dbkey, &encodedEntry);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ return(SECFailure);
+}
+/*
+ * delete a crl entry
+ */
+static SECStatus
+DeleteDBCrlEntry(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey,
+ certDBEntryType crlType)
+{
+ SECItem dbkey;
+ PRArenaPool *arena = NULL;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBGenericKey(crlKey, arena, &dbkey, crlType);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = DeleteDBEntry(handle, crlType, &dbkey);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(SECFailure);
+}
+
+/*
+ * Read a certificate entry
+ */
+static certDBEntryRevocation *
+ReadDBCrlEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey,
+ certDBEntryType crlType)
+{
+ PRArenaPool *arena = NULL;
+ PRArenaPool *tmparena = NULL;
+ certDBEntryRevocation *entry;
+ SECItem dbkey;
+ SECItem dbentry;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntryRevocation *)
+ PORT_ArenaAlloc(arena, sizeof(certDBEntryRevocation));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ entry->common.arena = arena;
+ entry->common.type = crlType;
+
+ rv = EncodeDBGenericKey(certKey, tmparena, &dbkey, crlType);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ rv = DecodeDBCrlEntry(entry, &dbentry);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(entry);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+/*
+ * destroy a database entry
+ */
+static void
+DestroyDBEntry(certDBEntry *entry)
+{
+ PRArenaPool *arena = entry->common.arena;
+
+ /* Zero out the entry struct, so that any further attempts to use it
+ * will cause an exception (e.g. null pointer reference). */
+ PORT_Memset(&entry->common, 0, sizeof entry->common);
+ PORT_FreeArena(arena, PR_FALSE);
+
+ return;
+}
+
+void
+nsslowcert_DestroyDBEntry(certDBEntry *entry)
+{
+ DestroyDBEntry(entry);
+ return;
+}
+
+/*
+ * Encode a database nickname record
+ */
+static SECStatus
+EncodeDBNicknameEntry(certDBEntryNickname *entry, PRArenaPool *arena,
+ SECItem *dbitem)
+{
+ unsigned char *buf;
+
+ /* allocate space for encoded database record, including space
+ * for low level header
+ */
+ dbitem->len = entry->subjectName.len + DB_NICKNAME_ENTRY_HEADER_LEN +
+ SEC_DB_ENTRY_HEADER_LEN;
+
+ dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len);
+ if ( dbitem->data == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ /* fill in database record */
+ buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
+
+ buf[0] = ( entry->subjectName.len >> 8 ) & 0xff;
+ buf[1] = entry->subjectName.len & 0xff;
+
+ PORT_Memcpy(&buf[DB_NICKNAME_ENTRY_HEADER_LEN], entry->subjectName.data,
+ entry->subjectName.len);
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * Encode a database key for a nickname record
+ */
+static SECStatus
+EncodeDBNicknameKey(char *nickname, PRArenaPool *arena,
+ SECItem *dbkey)
+{
+ unsigned int nnlen;
+
+ nnlen = PORT_Strlen(nickname) + 1; /* includes null */
+
+ /* now get the database key and format it */
+ dbkey->len = nnlen + SEC_DB_KEY_HEADER_LEN;
+ dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
+ if ( dbkey->data == NULL ) {
+ goto loser;
+ }
+ PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], nickname, nnlen);
+ dbkey->data[0] = certDBEntryTypeNickname;
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+static SECStatus
+DecodeDBNicknameEntry(certDBEntryNickname *entry, SECItem *dbentry,
+ char *nickname)
+{
+ /* is record long enough for header? */
+ if ( dbentry->len < DB_NICKNAME_ENTRY_HEADER_LEN ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ /* is database entry correct length? */
+ entry->subjectName.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] );
+ if (( entry->subjectName.len + DB_NICKNAME_ENTRY_HEADER_LEN ) !=
+ dbentry->len ){
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ /* copy the certkey */
+ entry->subjectName.data =
+ (unsigned char *)PORT_ArenaAlloc(entry->common.arena,
+ entry->subjectName.len);
+ if ( entry->subjectName.data == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->subjectName.data,
+ &dbentry->data[DB_NICKNAME_ENTRY_HEADER_LEN],
+ entry->subjectName.len);
+
+ entry->nickname = (char *)PORT_ArenaAlloc(entry->common.arena,
+ PORT_Strlen(nickname)+1);
+ if ( entry->nickname ) {
+ PORT_Strcpy(entry->nickname, nickname);
+ }
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * create a new nickname entry
+ */
+static certDBEntryNickname *
+NewDBNicknameEntry(char *nickname, SECItem *subjectName, unsigned int flags)
+{
+ PRArenaPool *arena = NULL;
+ certDBEntryNickname *entry;
+ int nnlen;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntryNickname *)PORT_ArenaAlloc(arena,
+ sizeof(certDBEntryNickname));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ /* init common fields */
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeNickname;
+ entry->common.version = CERT_DB_FILE_VERSION;
+ entry->common.flags = flags;
+
+ /* copy the nickname */
+ nnlen = PORT_Strlen(nickname) + 1;
+
+ entry->nickname = (char*)PORT_ArenaAlloc(arena, nnlen);
+ if ( entry->nickname == NULL ) {
+ goto loser;
+ }
+
+ PORT_Memcpy(entry->nickname, nickname, nnlen);
+
+ rv = SECITEM_CopyItem(arena, &entry->subjectName, subjectName);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ return(entry);
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+/*
+ * delete a nickname entry
+ */
+static SECStatus
+DeleteDBNicknameEntry(NSSLOWCERTCertDBHandle *handle, char *nickname)
+{
+ PRArenaPool *arena = NULL;
+ SECStatus rv;
+ SECItem dbkey;
+
+ if ( nickname == NULL ) {
+ return(SECSuccess);
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBNicknameKey(nickname, arena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = DeleteDBEntry(handle, certDBEntryTypeNickname, &dbkey);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(SECFailure);
+}
+
+/*
+ * Read a nickname entry
+ */
+static certDBEntryNickname *
+ReadDBNicknameEntry(NSSLOWCERTCertDBHandle *handle, char *nickname)
+{
+ PRArenaPool *arena = NULL;
+ PRArenaPool *tmparena = NULL;
+ certDBEntryNickname *entry;
+ SECItem dbkey;
+ SECItem dbentry;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntryNickname *)PORT_ArenaAlloc(arena,
+ sizeof(certDBEntryNickname));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeNickname;
+
+ rv = EncodeDBNicknameKey(nickname, tmparena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ /* is record long enough for header? */
+ if ( dbentry.len < DB_NICKNAME_ENTRY_HEADER_LEN ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ rv = DecodeDBNicknameEntry(entry, &dbentry, nickname);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(entry);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+/*
+ * Encode a nickname entry into byte stream suitable for
+ * the database
+ */
+static SECStatus
+WriteDBNicknameEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryNickname *entry)
+{
+ SECItem dbitem, dbkey;
+ PRArenaPool *tmparena = NULL;
+ SECStatus rv;
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBNicknameEntry(entry, tmparena, &dbitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = EncodeDBNicknameKey(entry->nickname, tmparena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* now write it to the database */
+ rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ return(SECFailure);
+
+}
+
+SECStatus
+EncodeDBSMimeEntry(certDBEntrySMime *entry, PRArenaPool *arena,
+ SECItem *dbitem)
+{
+ unsigned char *buf;
+
+ /* allocate space for encoded database record, including space
+ * for low level header
+ */
+ dbitem->len = entry->subjectName.len + entry->smimeOptions.len +
+ entry->optionsDate.len +
+ DB_SMIME_ENTRY_HEADER_LEN + SEC_DB_ENTRY_HEADER_LEN;
+
+ dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len);
+ if ( dbitem->data == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ /* fill in database record */
+ buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
+
+ buf[0] = ( entry->subjectName.len >> 8 ) & 0xff;
+ buf[1] = entry->subjectName.len & 0xff;
+ buf[2] = ( entry->smimeOptions.len >> 8 ) & 0xff;
+ buf[3] = entry->smimeOptions.len & 0xff;
+ buf[4] = ( entry->optionsDate.len >> 8 ) & 0xff;
+ buf[5] = entry->optionsDate.len & 0xff;
+
+ /* if no smime options, then there should not be an options date either */
+ PORT_Assert( ! ( ( entry->smimeOptions.len == 0 ) &&
+ ( entry->optionsDate.len != 0 ) ) );
+
+ PORT_Memcpy(&buf[DB_SMIME_ENTRY_HEADER_LEN], entry->subjectName.data,
+ entry->subjectName.len);
+ if ( entry->smimeOptions.len ) {
+ PORT_Memcpy(&buf[DB_SMIME_ENTRY_HEADER_LEN+entry->subjectName.len],
+ entry->smimeOptions.data,
+ entry->smimeOptions.len);
+ PORT_Memcpy(&buf[DB_SMIME_ENTRY_HEADER_LEN + entry->subjectName.len +
+ entry->smimeOptions.len],
+ entry->optionsDate.data,
+ entry->optionsDate.len);
+ }
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * Encode a database key for a SMIME record
+ */
+static SECStatus
+EncodeDBSMimeKey(char *emailAddr, PRArenaPool *arena,
+ SECItem *dbkey)
+{
+ unsigned int addrlen;
+
+ addrlen = PORT_Strlen(emailAddr) + 1; /* includes null */
+
+ /* now get the database key and format it */
+ dbkey->len = addrlen + SEC_DB_KEY_HEADER_LEN;
+ dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
+ if ( dbkey->data == NULL ) {
+ goto loser;
+ }
+ PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], emailAddr, addrlen);
+ dbkey->data[0] = certDBEntryTypeSMimeProfile;
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * Decode a database SMIME record
+ */
+static SECStatus
+DecodeDBSMimeEntry(certDBEntrySMime *entry, SECItem *dbentry, char *emailAddr)
+{
+ /* is record long enough for header? */
+ if ( dbentry->len < DB_SMIME_ENTRY_HEADER_LEN ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ /* is database entry correct length? */
+ entry->subjectName.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] );
+ entry->smimeOptions.len = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] );
+ entry->optionsDate.len = ( ( dbentry->data[4] << 8 ) | dbentry->data[5] );
+ if (( entry->subjectName.len + entry->smimeOptions.len +
+ entry->optionsDate.len + DB_SMIME_ENTRY_HEADER_LEN ) != dbentry->len){
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ /* copy the subject name */
+ entry->subjectName.data =
+ (unsigned char *)PORT_ArenaAlloc(entry->common.arena,
+ entry->subjectName.len);
+ if ( entry->subjectName.data == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->subjectName.data,
+ &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN],
+ entry->subjectName.len);
+
+ /* copy the smime options */
+ if ( entry->smimeOptions.len ) {
+ entry->smimeOptions.data =
+ (unsigned char *)PORT_ArenaAlloc(entry->common.arena,
+ entry->smimeOptions.len);
+ if ( entry->smimeOptions.data == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->smimeOptions.data,
+ &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN +
+ entry->subjectName.len],
+ entry->smimeOptions.len);
+ }
+ if ( entry->optionsDate.len ) {
+ entry->optionsDate.data =
+ (unsigned char *)PORT_ArenaAlloc(entry->common.arena,
+ entry->optionsDate.len);
+ if ( entry->optionsDate.data == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->optionsDate.data,
+ &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN +
+ entry->subjectName.len +
+ entry->smimeOptions.len],
+ entry->optionsDate.len);
+ }
+
+ /* both options and options date must either exist or not exist */
+ if ( ( ( entry->optionsDate.len == 0 ) ||
+ ( entry->smimeOptions.len == 0 ) ) &&
+ entry->smimeOptions.len != entry->optionsDate.len ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ entry->emailAddr = (char *)PORT_Alloc(PORT_Strlen(emailAddr)+1);
+ if ( entry->emailAddr ) {
+ PORT_Strcpy(entry->emailAddr, emailAddr);
+ }
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * create a new SMIME entry
+ */
+static certDBEntrySMime *
+NewDBSMimeEntry(char *emailAddr, SECItem *subjectName, SECItem *smimeOptions,
+ SECItem *optionsDate, unsigned int flags)
+{
+ PRArenaPool *arena = NULL;
+ certDBEntrySMime *entry;
+ int addrlen;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntrySMime *)PORT_ArenaAlloc(arena,
+ sizeof(certDBEntrySMime));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ /* init common fields */
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeSMimeProfile;
+ entry->common.version = CERT_DB_FILE_VERSION;
+ entry->common.flags = flags;
+
+ /* copy the email addr */
+ addrlen = PORT_Strlen(emailAddr) + 1;
+
+ entry->emailAddr = (char*)PORT_ArenaAlloc(arena, addrlen);
+ if ( entry->emailAddr == NULL ) {
+ goto loser;
+ }
+
+ PORT_Memcpy(entry->emailAddr, emailAddr, addrlen);
+
+ /* copy the subject name */
+ rv = SECITEM_CopyItem(arena, &entry->subjectName, subjectName);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* copy the smime options */
+ if ( smimeOptions ) {
+ rv = SECITEM_CopyItem(arena, &entry->smimeOptions, smimeOptions);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ } else {
+ PORT_Assert(optionsDate == NULL);
+ entry->smimeOptions.data = NULL;
+ entry->smimeOptions.len = 0;
+ }
+
+ /* copy the options date */
+ if ( optionsDate ) {
+ rv = SECITEM_CopyItem(arena, &entry->optionsDate, optionsDate);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ } else {
+ PORT_Assert(smimeOptions == NULL);
+ entry->optionsDate.data = NULL;
+ entry->optionsDate.len = 0;
+ }
+
+ return(entry);
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+/*
+ * delete a SMIME entry
+ */
+static SECStatus
+DeleteDBSMimeEntry(NSSLOWCERTCertDBHandle *handle, char *emailAddr)
+{
+ PRArenaPool *arena = NULL;
+ SECStatus rv;
+ SECItem dbkey;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBSMimeKey(emailAddr, arena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = DeleteDBEntry(handle, certDBEntryTypeSMimeProfile, &dbkey);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(SECFailure);
+}
+
+/*
+ * Read a SMIME entry
+ */
+certDBEntrySMime *
+nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *handle, char *emailAddr)
+{
+ PRArenaPool *arena = NULL;
+ PRArenaPool *tmparena = NULL;
+ certDBEntrySMime *entry;
+ SECItem dbkey;
+ SECItem dbentry;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntrySMime *)PORT_ArenaAlloc(arena,
+ sizeof(certDBEntrySMime));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeSMimeProfile;
+
+ rv = EncodeDBSMimeKey(emailAddr, tmparena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ /* is record long enough for header? */
+ if ( dbentry.len < DB_SMIME_ENTRY_HEADER_LEN ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ rv = DecodeDBSMimeEntry(entry, &dbentry, emailAddr);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(entry);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+/*
+ * Encode a SMIME entry into byte stream suitable for
+ * the database
+ */
+static SECStatus
+WriteDBSMimeEntry(NSSLOWCERTCertDBHandle *handle, certDBEntrySMime *entry)
+{
+ SECItem dbitem, dbkey;
+ PRArenaPool *tmparena = NULL;
+ SECStatus rv;
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBSMimeEntry(entry, tmparena, &dbitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = EncodeDBSMimeKey(entry->emailAddr, tmparena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* now write it to the database */
+ rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ return(SECFailure);
+
+}
+
+/*
+ * Encode a database subject record
+ */
+static SECStatus
+EncodeDBSubjectEntry(certDBEntrySubject *entry, PRArenaPool *arena,
+ SECItem *dbitem)
+{
+ unsigned char *buf;
+ int len;
+ unsigned int ncerts;
+ unsigned int i;
+ unsigned char *tmpbuf;
+ unsigned int nnlen = 0;
+ unsigned int eaddrlen = 0;
+ int keyidoff;
+ SECItem *certKeys;
+ SECItem *keyIDs;
+
+ if ( entry->nickname ) {
+ nnlen = PORT_Strlen(entry->nickname) + 1;
+ }
+ if ( entry->emailAddr ) {
+ eaddrlen = PORT_Strlen(entry->emailAddr) + 1;
+ }
+
+ ncerts = entry->ncerts;
+
+ /* compute the length of the entry */
+ keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen;
+ len = keyidoff + 4 * ncerts;
+ for ( i = 0; i < ncerts; i++ ) {
+ len += entry->certKeys[i].len;
+ len += entry->keyIDs[i].len;
+ }
+
+ /* allocate space for encoded database record, including space
+ * for low level header
+ */
+ dbitem->len = len + SEC_DB_ENTRY_HEADER_LEN;
+
+ dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len);
+ if ( dbitem->data == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ /* fill in database record */
+ buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
+
+ buf[0] = ( ncerts >> 8 ) & 0xff;
+ buf[1] = ncerts & 0xff;
+ buf[2] = ( nnlen >> 8 ) & 0xff;
+ buf[3] = nnlen & 0xff;
+ buf[4] = ( eaddrlen >> 8 ) & 0xff;
+ buf[5] = eaddrlen & 0xff;
+
+ PORT_Memcpy(&buf[DB_SUBJECT_ENTRY_HEADER_LEN], entry->nickname, nnlen);
+ PORT_Memcpy(&buf[DB_SUBJECT_ENTRY_HEADER_LEN+nnlen], entry->emailAddr,
+ eaddrlen);
+
+ for ( i = 0; i < ncerts; i++ ) {
+
+ certKeys = entry->certKeys;
+ keyIDs = entry->keyIDs;
+
+ buf[keyidoff+i*2] = ( certKeys[i].len >> 8 ) & 0xff;
+ buf[keyidoff+1+i*2] = certKeys[i].len & 0xff;
+ buf[keyidoff+ncerts*2+i*2] = ( keyIDs[i].len >> 8 ) & 0xff;
+ buf[keyidoff+1+ncerts*2+i*2] = keyIDs[i].len & 0xff;
+ }
+
+ /* temp pointer used to stuff certkeys and keyids into the buffer */
+ tmpbuf = &buf[keyidoff+ncerts*4];
+
+ for ( i = 0; i < ncerts; i++ ) {
+ certKeys = entry->certKeys;
+ PORT_Memcpy(tmpbuf, certKeys[i].data, certKeys[i].len);
+ tmpbuf = tmpbuf + certKeys[i].len;
+ }
+
+ for ( i = 0; i < ncerts; i++ ) {
+ keyIDs = entry->keyIDs;
+ PORT_Memcpy(tmpbuf, keyIDs[i].data, keyIDs[i].len);
+ tmpbuf = tmpbuf + keyIDs[i].len;
+ }
+
+ PORT_Assert(tmpbuf == &buf[len]);
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * Encode a database key for a subject record
+ */
+static SECStatus
+EncodeDBSubjectKey(SECItem *derSubject, PRArenaPool *arena,
+ SECItem *dbkey)
+{
+ dbkey->len = derSubject->len + SEC_DB_KEY_HEADER_LEN;
+ dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
+ if ( dbkey->data == NULL ) {
+ goto loser;
+ }
+ PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], derSubject->data,
+ derSubject->len);
+ dbkey->data[0] = certDBEntryTypeSubject;
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+static SECStatus
+DecodeDBSubjectEntry(certDBEntrySubject *entry, SECItem *dbentry,
+ SECItem *derSubject)
+{
+ unsigned int ncerts;
+ PRArenaPool *arena;
+ unsigned int len, itemlen;
+ unsigned char *tmpbuf;
+ unsigned int i;
+ SECStatus rv;
+ unsigned int keyidoff;
+ unsigned int nnlen, eaddrlen;
+
+ arena = entry->common.arena;
+
+ rv = SECITEM_CopyItem(arena, &entry->derSubject, derSubject);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* is record long enough for header? */
+ if ( dbentry->len < DB_SUBJECT_ENTRY_HEADER_LEN ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ entry->ncerts = ncerts = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] );
+ nnlen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] );
+ eaddrlen = ( ( dbentry->data[4] << 8 ) | dbentry->data[5] );
+ if ( dbentry->len < ( ncerts * 4 + DB_SUBJECT_ENTRY_HEADER_LEN +
+ nnlen + eaddrlen) ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ entry->certKeys = (SECItem *)PORT_ArenaAlloc(arena,
+ sizeof(SECItem) * ncerts);
+ entry->keyIDs = (SECItem *)PORT_ArenaAlloc(arena,
+ sizeof(SECItem) * ncerts);
+
+ if ( ( entry->certKeys == NULL ) || ( entry->keyIDs == NULL ) ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ if ( nnlen > 1 ) { /* null terminator is stored */
+ entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen);
+ if ( entry->nickname == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->nickname,
+ &dbentry->data[DB_SUBJECT_ENTRY_HEADER_LEN],
+ nnlen);
+ } else {
+ entry->nickname = NULL;
+ }
+
+ if ( eaddrlen > 1 ) { /* null terminator is stored */
+ entry->emailAddr = (char *)PORT_ArenaAlloc(arena, eaddrlen);
+ if ( entry->emailAddr == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->emailAddr,
+ &dbentry->data[DB_SUBJECT_ENTRY_HEADER_LEN+nnlen],
+ eaddrlen);
+ } else {
+ entry->emailAddr = NULL;
+ }
+
+ /* collect the lengths of the certKeys and keyIDs, and total the
+ * overall length.
+ */
+ keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen;
+ len = keyidoff + 4 * ncerts;
+
+ tmpbuf = &dbentry->data[0];
+
+ for ( i = 0; i < ncerts; i++ ) {
+
+ itemlen = ( tmpbuf[keyidoff + 2*i] << 8 ) | tmpbuf[keyidoff + 1 + 2*i] ;
+ len += itemlen;
+ entry->certKeys[i].len = itemlen;
+
+ itemlen = ( tmpbuf[keyidoff + 2*ncerts + 2*i] << 8 ) |
+ tmpbuf[keyidoff + 1 + 2*ncerts + 2*i] ;
+ len += itemlen;
+ entry->keyIDs[i].len = itemlen;
+ }
+
+ /* is database entry correct length? */
+ if ( len != dbentry->len ){
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+
+ tmpbuf = &tmpbuf[keyidoff + 4*ncerts];
+ for ( i = 0; i < ncerts; i++ ) {
+ entry->certKeys[i].data =
+ (unsigned char *)PORT_ArenaAlloc(arena, entry->certKeys[i].len);
+ if ( entry->certKeys[i].data == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->certKeys[i].data, tmpbuf, entry->certKeys[i].len);
+ tmpbuf = &tmpbuf[entry->certKeys[i].len];
+ }
+
+ for ( i = 0; i < ncerts; i++ ) {
+ entry->keyIDs[i].data =
+ (unsigned char *)PORT_ArenaAlloc(arena, entry->keyIDs[i].len);
+ if ( entry->keyIDs[i].data == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ PORT_Memcpy(entry->keyIDs[i].data, tmpbuf, entry->keyIDs[i].len);
+ tmpbuf = &tmpbuf[entry->keyIDs[i].len];
+ }
+
+ PORT_Assert(tmpbuf == &dbentry->data[dbentry->len]);
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * create a new subject entry with a single cert
+ */
+static certDBEntrySubject *
+NewDBSubjectEntry(SECItem *derSubject, SECItem *certKey,
+ SECItem *keyID, char *nickname, char *emailAddr,
+ unsigned int flags)
+{
+ PRArenaPool *arena = NULL;
+ certDBEntrySubject *entry;
+ SECStatus rv;
+ unsigned int nnlen;
+ unsigned int eaddrlen;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntrySubject *)PORT_ArenaAlloc(arena,
+ sizeof(certDBEntrySubject));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ /* init common fields */
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeSubject;
+ entry->common.version = CERT_DB_FILE_VERSION;
+ entry->common.flags = flags;
+
+ /* copy the subject */
+ rv = SECITEM_CopyItem(arena, &entry->derSubject, derSubject);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ entry->ncerts = 1;
+ /* copy nickname */
+ if ( nickname && ( *nickname != '\0' ) ) {
+ nnlen = PORT_Strlen(nickname) + 1;
+ entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen);
+ if ( entry->nickname == NULL ) {
+ goto loser;
+ }
+
+ PORT_Memcpy(entry->nickname, nickname, nnlen);
+ } else {
+ entry->nickname = NULL;
+ }
+
+ /* copy email addr */
+ if ( emailAddr && ( *emailAddr != '\0' ) ) {
+ emailAddr = nsslowcert_FixupEmailAddr(emailAddr);
+ if ( emailAddr == NULL ) {
+ entry->emailAddr = NULL;
+ goto loser;
+ }
+
+ eaddrlen = PORT_Strlen(emailAddr) + 1;
+ entry->emailAddr = (char *)PORT_ArenaAlloc(arena, eaddrlen);
+ if ( entry->emailAddr == NULL ) {
+ PORT_Free(emailAddr);
+ goto loser;
+ }
+
+ PORT_Memcpy(entry->emailAddr, emailAddr, eaddrlen);
+ PORT_Free(emailAddr);
+ } else {
+ entry->emailAddr = NULL;
+ }
+
+ /* allocate space for certKeys and keyIDs */
+ entry->certKeys = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));
+ entry->keyIDs = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));
+ if ( ( entry->certKeys == NULL ) || ( entry->keyIDs == NULL ) ) {
+ goto loser;
+ }
+
+ /* copy the certKey and keyID */
+ rv = SECITEM_CopyItem(arena, &entry->certKeys[0], certKey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ rv = SECITEM_CopyItem(arena, &entry->keyIDs[0], keyID);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ return(entry);
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+/*
+ * delete a subject entry
+ */
+static SECStatus
+DeleteDBSubjectEntry(NSSLOWCERTCertDBHandle *handle, SECItem *derSubject)
+{
+ SECItem dbkey;
+ PRArenaPool *arena = NULL;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBSubjectKey(derSubject, arena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = DeleteDBEntry(handle, certDBEntryTypeSubject, &dbkey);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(SECFailure);
+}
+
+/*
+ * Read the subject entry
+ */
+static certDBEntrySubject *
+ReadDBSubjectEntry(NSSLOWCERTCertDBHandle *handle, SECItem *derSubject)
+{
+ PRArenaPool *arena = NULL;
+ PRArenaPool *tmparena = NULL;
+ certDBEntrySubject *entry;
+ SECItem dbkey;
+ SECItem dbentry;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntrySubject *)PORT_ArenaAlloc(arena,
+ sizeof(certDBEntrySubject));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeSubject;
+
+ rv = EncodeDBSubjectKey(derSubject, tmparena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ rv = DecodeDBSubjectEntry(entry, &dbentry, derSubject);
+ if ( rv == SECFailure ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(entry);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+/*
+ * Encode a subject name entry into byte stream suitable for
+ * the database
+ */
+static SECStatus
+WriteDBSubjectEntry(NSSLOWCERTCertDBHandle *handle, certDBEntrySubject *entry)
+{
+ SECItem dbitem, dbkey;
+ PRArenaPool *tmparena = NULL;
+ SECStatus rv;
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBSubjectEntry(entry, tmparena, &dbitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = EncodeDBSubjectKey(&entry->derSubject, tmparena, &dbkey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* now write it to the database */
+ rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ return(SECFailure);
+
+}
+
+static SECStatus
+UpdateSubjectWithEmailAddr(NSSLOWCERTCertDBHandle *dbhandle,
+ SECItem *derSubject, char *emailAddr)
+{
+ PRBool save = PR_FALSE, delold = PR_FALSE;
+ certDBEntrySubject *entry;
+ SECStatus rv;
+
+ if (emailAddr) {
+ emailAddr = nsslowcert_FixupEmailAddr(emailAddr);
+ if (emailAddr == NULL) {
+ return SECFailure;
+ }
+ }
+
+ entry = ReadDBSubjectEntry(dbhandle,derSubject);
+
+ if ( entry->emailAddr ) {
+ if ( (emailAddr == NULL) ||
+ (PORT_Strcmp(entry->emailAddr, emailAddr) != 0) ) {
+ save = PR_TRUE;
+ delold = PR_TRUE;
+ }
+ } else if (emailAddr) {
+ save = PR_TRUE;
+ }
+
+ if ( delold ) {
+ /* delete the old smime entry, because this cert now has a new
+ * smime entry pointing to it
+ */
+ PORT_Assert(save);
+ PORT_Assert(entry->emailAddr != NULL);
+ DeleteDBSMimeEntry(dbhandle, entry->emailAddr);
+ }
+
+ if ( save ) {
+ unsigned int len;
+
+ PORT_Assert(entry != NULL);
+ if (emailAddr) {
+ len = PORT_Strlen(emailAddr) + 1;
+ entry->emailAddr = (char *)PORT_ArenaAlloc(entry->common.arena, len);
+ if ( entry->emailAddr == NULL ) {
+ goto loser;
+ }
+ PORT_Memcpy(entry->emailAddr, emailAddr, len);
+ } else {
+ entry->emailAddr = NULL;
+ }
+
+ /* delete the subject entry */
+ DeleteDBSubjectEntry(dbhandle, derSubject);
+
+ /* write the new one */
+ rv = WriteDBSubjectEntry(dbhandle, entry);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ }
+
+ if (emailAddr) PORT_Free(emailAddr);
+ return(SECSuccess);
+
+loser:
+ if (emailAddr) PORT_Free(emailAddr);
+ return(SECFailure);
+}
+
+/*
+ * writes a nickname to an existing subject entry that does not currently
+ * have one
+ */
+static SECStatus
+AddNicknameToSubject(NSSLOWCERTCertDBHandle *dbhandle,
+ NSSLOWCERTCertificate *cert, char *nickname)
+{
+ certDBEntrySubject *entry;
+ SECStatus rv;
+
+ if ( nickname == NULL ) {
+ return(SECFailure);
+ }
+
+ entry = ReadDBSubjectEntry(dbhandle,&cert->derSubject);
+ PORT_Assert(entry != NULL);
+ if ( entry == NULL ) {
+ goto loser;
+ }
+
+ PORT_Assert(entry->nickname == NULL);
+ if ( entry->nickname != NULL ) {
+ goto loser;
+ }
+
+ entry->nickname = (nickname) ?
+ PORT_ArenaStrdup(entry->common.arena, nickname) : NULL;
+
+ if ( entry->nickname == NULL ) {
+ goto loser;
+ }
+
+ /* delete the subject entry */
+ DeleteDBSubjectEntry(dbhandle, &cert->derSubject);
+
+ /* write the new one */
+ rv = WriteDBSubjectEntry(dbhandle, entry);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * create a new version entry
+ */
+static certDBEntryVersion *
+NewDBVersionEntry(unsigned int flags)
+{
+ PRArenaPool *arena = NULL;
+ certDBEntryVersion *entry;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntryVersion *)PORT_ArenaAlloc(arena,
+ sizeof(certDBEntryVersion));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeVersion;
+ entry->common.version = CERT_DB_FILE_VERSION;
+ entry->common.flags = flags;
+
+ return(entry);
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+/*
+ * Read the version entry
+ */
+static certDBEntryVersion *
+ReadDBVersionEntry(NSSLOWCERTCertDBHandle *handle)
+{
+ PRArenaPool *arena = NULL;
+ PRArenaPool *tmparena = NULL;
+ certDBEntryVersion *entry;
+ SECItem dbkey;
+ SECItem dbentry;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ entry = (certDBEntryVersion *)PORT_ArenaAlloc(arena,
+ sizeof(certDBEntryVersion));
+ if ( entry == NULL ) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+ entry->common.arena = arena;
+ entry->common.type = certDBEntryTypeVersion;
+
+ /* now get the database key and format it */
+ dbkey.len = SEC_DB_VERSION_KEY_LEN + SEC_DB_KEY_HEADER_LEN;
+ dbkey.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbkey.len);
+ if ( dbkey.data == NULL ) {
+ goto loser;
+ }
+ PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_VERSION_KEY,
+ SEC_DB_VERSION_KEY_LEN);
+
+ ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena);
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(entry);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+
+/*
+ * Encode a version entry into byte stream suitable for
+ * the database
+ */
+static SECStatus
+WriteDBVersionEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryVersion *entry)
+{
+ SECItem dbitem, dbkey;
+ PRArenaPool *tmparena = NULL;
+ SECStatus rv;
+
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( tmparena == NULL ) {
+ goto loser;
+ }
+
+ /* allocate space for encoded database record, including space
+ * for low level header
+ */
+ dbitem.len = SEC_DB_ENTRY_HEADER_LEN;
+
+ dbitem.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbitem.len);
+ if ( dbitem.data == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ /* now get the database key and format it */
+ dbkey.len = SEC_DB_VERSION_KEY_LEN + SEC_DB_KEY_HEADER_LEN;
+ dbkey.data = (unsigned char *)PORT_ArenaAlloc(tmparena, dbkey.len);
+ if ( dbkey.data == NULL ) {
+ goto loser;
+ }
+ PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_VERSION_KEY,
+ SEC_DB_VERSION_KEY_LEN);
+
+ /* now write it to the database */
+ rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return(SECSuccess);
+
+loser:
+ if ( tmparena ) {
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ return(SECFailure);
+}
+
+/*
+ * cert is no longer a perm cert, but will remain a temp cert
+ */
+static SECStatus
+RemovePermSubjectNode(NSSLOWCERTCertificate *cert)
+{
+ certDBEntrySubject *entry;
+ unsigned int i;
+ SECStatus rv;
+
+ entry = ReadDBSubjectEntry(cert->dbhandle,&cert->derSubject);
+ PORT_Assert(entry);
+ if ( entry == NULL ) {
+ return(SECFailure);
+ }
+
+ PORT_Assert(entry->ncerts);
+ rv = SECFailure;
+
+ if ( entry->ncerts > 1 ) {
+ for ( i = 0; i < entry->ncerts; i++ ) {
+ if ( SECITEM_CompareItem(&entry->certKeys[i], &cert->certKey) ==
+ SECEqual ) {
+ /* copy rest of list forward one entry */
+ for ( i = i + 1; i < entry->ncerts; i++ ) {
+ entry->certKeys[i-1] = entry->certKeys[i];
+ entry->keyIDs[i-1] = entry->keyIDs[i];
+ }
+ entry->ncerts--;
+ DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject);
+ rv = WriteDBSubjectEntry(cert->dbhandle, entry);
+ break;
+ }
+ }
+ } else {
+ /* no entries left, delete the perm entry in the DB */
+ if ( entry->emailAddr ) {
+ /* if the subject had an email record, then delete it too */
+ DeleteDBSMimeEntry(cert->dbhandle, entry->emailAddr);
+ }
+
+ DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject);
+ }
+ DestroyDBEntry((certDBEntry *)entry);
+
+ return(rv);
+}
+
+/*
+ * add a cert to the perm subject list
+ */
+static SECStatus
+AddPermSubjectNode(certDBEntrySubject *entry, NSSLOWCERTCertificate *cert,
+ char *nickname)
+{
+ SECItem *newCertKeys, *newKeyIDs;
+ int i;
+ SECStatus rv;
+ NSSLOWCERTCertificate *cmpcert;
+ unsigned int nnlen;
+ int ncerts;
+
+
+ PORT_Assert(entry);
+ ncerts = entry->ncerts;
+
+ if ( nickname && entry->nickname ) {
+ /* nicknames must be the same */
+ PORT_Assert(PORT_Strcmp(nickname, entry->nickname) == 0);
+ }
+
+ if ( ( entry->nickname == NULL ) && ( nickname != NULL ) ) {
+ /* copy nickname into the entry */
+ nnlen = PORT_Strlen(nickname) + 1;
+ entry->nickname = (char *)PORT_ArenaAlloc(entry->common.arena,nnlen);
+ if ( entry->nickname == NULL ) {
+ return(SECFailure);
+ }
+ PORT_Memcpy(entry->nickname, nickname, nnlen);
+ }
+
+ /* a DB entry already exists, so add this cert */
+ newCertKeys = (SECItem *)PORT_ArenaAlloc(entry->common.arena,
+ sizeof(SECItem) * ( ncerts + 1 ) );
+ newKeyIDs = (SECItem *)PORT_ArenaAlloc(entry->common.arena,
+ sizeof(SECItem) * ( ncerts + 1 ) );
+
+ if ( ( newCertKeys == NULL ) || ( newKeyIDs == NULL ) ) {
+ return(SECFailure);
+ }
+
+ for ( i = 0; i < ncerts; i++ ) {
+ cmpcert = nsslowcert_FindCertByKey(cert->dbhandle,
+ &entry->certKeys[i]);
+ PORT_Assert(cmpcert);
+ if ( nsslowcert_IsNewer(cert, cmpcert) ) {
+ /* insert before cmpcert */
+ rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[i],
+ &cert->certKey);
+ if ( rv != SECSuccess ) {
+ return(SECFailure);
+ }
+ rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[i],
+ &cert->subjectKeyID);
+ if ( rv != SECSuccess ) {
+ return(SECFailure);
+ }
+ /* copy the rest of the entry */
+ for ( ; i < ncerts; i++ ) {
+ newCertKeys[i+1] = entry->certKeys[i];
+ newKeyIDs[i+1] = entry->keyIDs[i];
+ }
+
+ /* update certKeys and keyIDs */
+ entry->certKeys = newCertKeys;
+ entry->keyIDs = newKeyIDs;
+
+ /* increment count */
+ entry->ncerts++;
+ break;
+ }
+ /* copy this cert entry */
+ newCertKeys[i] = entry->certKeys[i];
+ newKeyIDs[i] = entry->keyIDs[i];
+ }
+
+ if ( entry->ncerts == ncerts ) {
+ /* insert new one at end */
+ rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[ncerts],
+ &cert->certKey);
+ if ( rv != SECSuccess ) {
+ return(SECFailure);
+ }
+ rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[ncerts],
+ &cert->subjectKeyID);
+ if ( rv != SECSuccess ) {
+ return(SECFailure);
+ }
+
+ /* update certKeys and keyIDs */
+ entry->certKeys = newCertKeys;
+ entry->keyIDs = newKeyIDs;
+
+ /* increment count */
+ entry->ncerts++;
+ }
+ DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject);
+ rv = WriteDBSubjectEntry(cert->dbhandle, entry);
+ return(rv);
+}
+
+
+SECStatus
+nsslowcert_TraversePermCertsForSubject(NSSLOWCERTCertDBHandle *handle,
+ SECItem *derSubject,
+ NSSLOWCERTCertCallback cb, void *cbarg)
+{
+ certDBEntrySubject *entry;
+ int i;
+ NSSLOWCERTCertificate *cert;
+ SECStatus rv = SECSuccess;
+
+ entry = ReadDBSubjectEntry(handle, derSubject);
+
+ if ( entry == NULL ) {
+ return(SECFailure);
+ }
+
+ for( i = 0; i < entry->ncerts; i++ ) {
+ cert = nsslowcert_FindCertByKey(handle, &entry->certKeys[i]);
+ rv = (* cb)(cert, cbarg);
+ nsslowcert_DestroyCertificate(cert);
+ if ( rv == SECFailure ) {
+ break;
+ }
+ }
+
+ DestroyDBEntry((certDBEntry *)entry);
+
+ return(rv);
+}
+
+int
+nsslowcert_NumPermCertsForSubject(NSSLOWCERTCertDBHandle *handle, SECItem *derSubject)
+{
+ certDBEntrySubject *entry;
+ int ret;
+
+ entry = ReadDBSubjectEntry(handle, derSubject);
+
+ if ( entry == NULL ) {
+ return(SECFailure);
+ }
+
+ ret = entry->ncerts;
+
+ DestroyDBEntry((certDBEntry *)entry);
+
+ return(ret);
+}
+
+SECStatus
+nsslowcert_TraversePermCertsForNickname(NSSLOWCERTCertDBHandle *handle, char *nickname,
+ NSSLOWCERTCertCallback cb, void *cbarg)
+{
+ certDBEntryNickname *nnentry = NULL;
+ certDBEntrySMime *smentry = NULL;
+ SECStatus rv;
+ SECItem *derSubject = NULL;
+
+ nnentry = ReadDBNicknameEntry(handle, nickname);
+ if ( nnentry ) {
+ derSubject = &nnentry->subjectName;
+ } else {
+ smentry = nsslowcert_ReadDBSMimeEntry(handle, nickname);
+ if ( smentry ) {
+ derSubject = &smentry->subjectName;
+ }
+ }
+
+ if ( derSubject ) {
+ rv = nsslowcert_TraversePermCertsForSubject(handle, derSubject,
+ cb, cbarg);
+ } else {
+ rv = SECFailure;
+ }
+
+ if ( nnentry ) {
+ DestroyDBEntry((certDBEntry *)nnentry);
+ }
+ if ( smentry ) {
+ DestroyDBEntry((certDBEntry *)smentry);
+ }
+
+ return(rv);
+}
+
+
+int
+nsslowcert_NumPermCertsForNickname(NSSLOWCERTCertDBHandle *handle, char *nickname)
+{
+ certDBEntryNickname *entry;
+ int ret;
+
+ entry = ReadDBNicknameEntry(handle, nickname);
+
+ if ( entry ) {
+ ret = nsslowcert_NumPermCertsForSubject(handle, &entry->subjectName);
+ DestroyDBEntry((certDBEntry *)entry);
+ } else {
+ ret = 0;
+ }
+ return(ret);
+}
+
+/*
+ * add a nickname to a cert that doesn't have one
+ */
+static SECStatus
+AddNicknameToPermCert(NSSLOWCERTCertDBHandle *dbhandle,
+ NSSLOWCERTCertificate *cert, char *nickname)
+{
+ certDBEntryCert *entry;
+ int rv;
+
+ entry = cert->dbEntry;
+ PORT_Assert(entry != NULL);
+ if ( entry == NULL ) {
+ goto loser;
+ }
+
+ entry->nickname = PORT_ArenaStrdup(entry->common.arena, nickname);
+
+ rv = WriteDBCertEntry(dbhandle, entry);
+ if ( rv ) {
+ goto loser;
+ }
+
+ cert->nickname = PORT_ArenaStrdup(cert->arena, nickname);
+ return(SECSuccess);
+
+loser:
+ return(SECFailure);
+}
+
+/*
+ * add a nickname to a cert that is already in the perm database, but doesn't
+ * have one yet (it is probably an e-mail cert).
+ */
+SECStatus
+nsslowcert_AddPermNickname(NSSLOWCERTCertDBHandle *dbhandle,
+ NSSLOWCERTCertificate *cert, char *nickname)
+{
+ SECStatus rv = SECFailure;
+ certDBEntrySubject *entry = NULL;
+
+ nsslowcert_LockDB(dbhandle);
+
+ PORT_Assert(cert->nickname == NULL);
+
+ if ( cert->nickname != NULL ) {
+ rv = SECSuccess;
+ goto loser;
+ }
+
+ entry = ReadDBSubjectEntry(dbhandle, &cert->derSubject);
+ if (entry == NULL) goto loser;
+
+ if ( entry->nickname == NULL ) {
+ /* no nickname for subject */
+ rv = AddNicknameToSubject(dbhandle, cert, nickname);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ rv = AddNicknameToPermCert(dbhandle, cert, nickname);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ } else {
+ /* subject already has a nickname */
+ rv = AddNicknameToPermCert(dbhandle, cert, entry->nickname);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ }
+ rv = SECSuccess;
+
+loser:
+ if (entry) {
+ DestroyDBEntry((certDBEntry *)entry);
+ }
+ nsslowcert_UnlockDB(dbhandle);
+ return(rv);
+}
+
+static certDBEntryCert *
+AddCertToPermDB(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTCertificate *cert,
+ char *nickname, NSSLOWCERTCertTrust *trust)
+{
+ certDBEntryCert *certEntry = NULL;
+ certDBEntryNickname *nicknameEntry = NULL;
+ certDBEntrySubject *subjectEntry = NULL;
+ int state = 0;
+ SECStatus rv;
+ PRBool donnentry = PR_FALSE;
+
+ if ( nickname ) {
+ donnentry = PR_TRUE;
+ }
+
+ subjectEntry = ReadDBSubjectEntry(handle, &cert->derSubject);
+
+ if ( subjectEntry ) {
+ donnentry = PR_FALSE;
+ nickname = subjectEntry->nickname;
+ }
+
+ certEntry = NewDBCertEntry(&cert->derCert, nickname, trust, 0);
+ if ( certEntry == NULL ) {
+ goto loser;
+ }
+
+ if ( donnentry ) {
+ nicknameEntry = NewDBNicknameEntry(nickname, &cert->derSubject, 0);
+ if ( nicknameEntry == NULL ) {
+ goto loser;
+ }
+ }
+
+ rv = WriteDBCertEntry(handle, certEntry);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ state = 1;
+
+ if ( nicknameEntry ) {
+ rv = WriteDBNicknameEntry(handle, nicknameEntry);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ }
+
+ state = 2;
+
+ /* add to or create new subject entry */
+ if ( subjectEntry ) {
+ /* REWRITE BASED ON SUBJECT ENTRY */
+ rv = AddPermSubjectNode(subjectEntry, cert, nickname);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ } else {
+ /* make a new subject entry - this case is only used when updating
+ * an old version of the database. This is OK because the oldnickname
+ * db format didn't allow multiple certs with the same subject.
+ */
+ /* where does subjectKeyID and certKey come from? */
+ subjectEntry = NewDBSubjectEntry(&cert->derSubject, &cert->certKey,
+ &cert->subjectKeyID, nickname,
+ NULL, 0);
+ if ( subjectEntry == NULL ) {
+ goto loser;
+ }
+ rv = WriteDBSubjectEntry(handle, subjectEntry);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ }
+
+ state = 3;
+
+ if ( nicknameEntry ) {
+ DestroyDBEntry((certDBEntry *)nicknameEntry);
+ }
+
+ if ( subjectEntry ) {
+ DestroyDBEntry((certDBEntry *)subjectEntry);
+ }
+
+ return(certEntry);
+
+loser:
+ /* don't leave partial entry in the database */
+ if ( state > 0 ) {
+ rv = DeleteDBCertEntry(handle, &cert->certKey);
+ }
+ if ( ( state > 1 ) && donnentry ) {
+ rv = DeleteDBNicknameEntry(handle, nickname);
+ }
+ if ( state > 2 ) {
+ rv = DeleteDBSubjectEntry(handle, &cert->derSubject);
+ }
+ if ( certEntry ) {
+ DestroyDBEntry((certDBEntry *)certEntry);
+ }
+ if ( nicknameEntry ) {
+ DestroyDBEntry((certDBEntry *)nicknameEntry);
+ }
+ if ( subjectEntry ) {
+ DestroyDBEntry((certDBEntry *)subjectEntry);
+ }
+
+ return(NULL);
+}
+
+/*
+ * NOTE - Version 6 DB did not go out to the real world in a release,
+ * so we can remove this function in a later release.
+ */
+static SECStatus
+UpdateV6DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb)
+{
+ int ret;
+ DBT key, data;
+ unsigned char *buf, *tmpbuf = NULL;
+ certDBEntryType type;
+ certDBEntryNickname *nnEntry = NULL;
+ certDBEntrySubject *subjectEntry = NULL;
+ certDBEntrySMime *emailEntry = NULL;
+ char *nickname;
+ char *emailAddr;
+ SECStatus rv;
+
+ /*
+ * Sequence through the old database and copy all of the entries
+ * to the new database. Subject name entries will have the new
+ * fields inserted into them (with zero length).
+ */
+ ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST);
+ if ( ret ) {
+ return(SECFailure);
+ }
+
+ do {
+ buf = (unsigned char *)data.data;
+
+ if ( data.size >= 3 ) {
+ if ( buf[0] == 6 ) { /* version number */
+ type = (certDBEntryType)buf[1];
+ if ( type == certDBEntryTypeSubject ) {
+ /* expando subjecto entrieo */
+ tmpbuf = (unsigned char *)PORT_Alloc(data.size + 4);
+ if ( tmpbuf ) {
+ /* copy header stuff */
+ PORT_Memcpy(tmpbuf, buf, SEC_DB_ENTRY_HEADER_LEN + 2);
+ /* insert 4 more bytes of zero'd header */
+ PORT_Memset(&tmpbuf[SEC_DB_ENTRY_HEADER_LEN + 2],
+ 0, 4);
+ /* copy rest of the data */
+ PORT_Memcpy(&tmpbuf[SEC_DB_ENTRY_HEADER_LEN + 6],
+ &buf[SEC_DB_ENTRY_HEADER_LEN + 2],
+ data.size - (SEC_DB_ENTRY_HEADER_LEN + 2));
+
+ data.data = (void *)tmpbuf;
+ data.size += 4;
+ buf = tmpbuf;
+ }
+ } else if ( type == certDBEntryTypeCert ) {
+ /* expando certo entrieo */
+ tmpbuf = (unsigned char *)PORT_Alloc(data.size + 3);
+ if ( tmpbuf ) {
+ /* copy header stuff */
+ PORT_Memcpy(tmpbuf, buf, SEC_DB_ENTRY_HEADER_LEN);
+
+ /* copy trust flage, setting msb's to 0 */
+ tmpbuf[SEC_DB_ENTRY_HEADER_LEN] = 0;
+ tmpbuf[SEC_DB_ENTRY_HEADER_LEN+1] =
+ buf[SEC_DB_ENTRY_HEADER_LEN];
+ tmpbuf[SEC_DB_ENTRY_HEADER_LEN+2] = 0;
+ tmpbuf[SEC_DB_ENTRY_HEADER_LEN+3] =
+ buf[SEC_DB_ENTRY_HEADER_LEN+1];
+ tmpbuf[SEC_DB_ENTRY_HEADER_LEN+4] = 0;
+ tmpbuf[SEC_DB_ENTRY_HEADER_LEN+5] =
+ buf[SEC_DB_ENTRY_HEADER_LEN+2];
+
+ /* copy rest of the data */
+ PORT_Memcpy(&tmpbuf[SEC_DB_ENTRY_HEADER_LEN + 6],
+ &buf[SEC_DB_ENTRY_HEADER_LEN + 3],
+ data.size - (SEC_DB_ENTRY_HEADER_LEN + 3));
+
+ data.data = (void *)tmpbuf;
+ data.size += 3;
+ buf = tmpbuf;
+ }
+
+ }
+
+ /* update the record version number */
+ buf[0] = CERT_DB_FILE_VERSION;
+
+ /* copy to the new database */
+ ret = certdb_Put(handle->permCertDB, &key, &data, 0);
+ if ( tmpbuf ) {
+ PORT_Free(tmpbuf);
+ tmpbuf = NULL;
+ }
+ }
+ }
+ } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 );
+
+ ret = certdb_Sync(handle->permCertDB, 0);
+
+ ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST);
+ if ( ret ) {
+ return(SECFailure);
+ }
+
+ do {
+ buf = (unsigned char *)data.data;
+
+ if ( data.size >= 3 ) {
+ if ( buf[0] == CERT_DB_FILE_VERSION ) { /* version number */
+ type = (certDBEntryType)buf[1];
+ if ( type == certDBEntryTypeNickname ) {
+ nickname = &((char *)key.data)[1];
+
+ /* get the matching nickname entry in the new DB */
+ nnEntry = ReadDBNicknameEntry(handle, nickname);
+ if ( nnEntry == NULL ) {
+ goto endloop;
+ }
+
+ /* find the subject entry pointed to by nickname */
+ subjectEntry = ReadDBSubjectEntry(handle,
+ &nnEntry->subjectName);
+ if ( subjectEntry == NULL ) {
+ goto endloop;
+ }
+
+ subjectEntry->nickname =
+ (char *)PORT_ArenaAlloc(subjectEntry->common.arena,
+ key.size - 1);
+ if ( subjectEntry->nickname ) {
+ PORT_Memcpy(subjectEntry->nickname, nickname,
+ key.size - 1);
+ rv = WriteDBSubjectEntry(handle, subjectEntry);
+ }
+ } else if ( type == certDBEntryTypeSMimeProfile ) {
+ emailAddr = &((char *)key.data)[1];
+
+ /* get the matching smime entry in the new DB */
+ emailEntry = nsslowcert_ReadDBSMimeEntry(handle, emailAddr);
+ if ( emailEntry == NULL ) {
+ goto endloop;
+ }
+
+ /* find the subject entry pointed to by nickname */
+ subjectEntry = ReadDBSubjectEntry(handle,
+ &emailEntry->subjectName);
+ if ( subjectEntry == NULL ) {
+ goto endloop;
+ }
+
+ subjectEntry->nickname =
+ (char *)PORT_ArenaAlloc(subjectEntry->common.arena,
+ key.size - 1);
+ if ( subjectEntry->emailAddr ) {
+ PORT_Memcpy(subjectEntry->emailAddr, emailAddr,
+ key.size - 1);
+ rv = WriteDBSubjectEntry(handle, subjectEntry);
+ }
+ }
+
+endloop:
+ if ( subjectEntry ) {
+ DestroyDBEntry((certDBEntry *)subjectEntry);
+ subjectEntry = NULL;
+ }
+ if ( nnEntry ) {
+ DestroyDBEntry((certDBEntry *)nnEntry);
+ nnEntry = NULL;
+ }
+ if ( emailEntry ) {
+ DestroyDBEntry((certDBEntry *)emailEntry);
+ emailEntry = NULL;
+ }
+ }
+ }
+ } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 );
+
+ ret = certdb_Sync(handle->permCertDB, 0);
+
+ (* updatedb->close)(updatedb);
+ return(SECSuccess);
+}
+
+
+static SECStatus
+updateV5Callback(NSSLOWCERTCertificate *cert, SECItem *k, void *pdata)
+{
+ NSSLOWCERTCertDBHandle *handle;
+ certDBEntryCert *entry;
+ NSSLOWCERTCertTrust *trust;
+
+ handle = (NSSLOWCERTCertDBHandle *)pdata;
+ trust = &cert->dbEntry->trust;
+
+ /* SSL user certs can be used for email if they have an email addr */
+ if ( cert->emailAddr && ( trust->sslFlags & CERTDB_USER ) &&
+ ( trust->emailFlags == 0 ) ) {
+ trust->emailFlags = CERTDB_USER;
+ }
+ /* servers didn't set the user flags on the server cert.. */
+ if (PORT_Strcmp(cert->dbEntry->nickname,"Server-Cert") == 0) {
+ trust->sslFlags |= CERTDB_USER;
+ }
+
+ entry = AddCertToPermDB(handle, cert, cert->dbEntry->nickname,
+ &cert->dbEntry->trust);
+ if ( entry ) {
+ DestroyDBEntry((certDBEntry *)entry);
+ }
+
+ return(SECSuccess);
+}
+
+static SECStatus
+UpdateV5DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb)
+{
+ NSSLOWCERTCertDBHandle updatehandle;
+ SECStatus rv;
+
+ updatehandle.permCertDB = updatedb;
+ updatehandle.dbMon = PZ_NewMonitor(nssILockCertDB);
+
+ rv = nsslowcert_TraversePermCerts(&updatehandle, updateV5Callback,
+ (void *)handle);
+
+ PZ_DestroyMonitor(updatehandle.dbMon);
+
+ (* updatedb->close)(updatedb);
+ return(SECSuccess);
+}
+
+static PRBool
+isV4DB(DB *db) {
+ DBT key,data;
+ int ret;
+
+ key.data = "Version";
+ key.size = 7;
+
+ ret = (*db->get)(db, &key, &data, 0);
+ if (ret) {
+ return PR_FALSE;
+ }
+
+ if ((data.size == 1) && (*(unsigned char *)data.data <= 4)) {
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+static SECStatus
+UpdateV4DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb)
+{
+ DBT key, data;
+ certDBEntryCert *entry, *entry2;
+ SECItem derSubject;
+ int ret;
+ PRArenaPool *arena = NULL;
+ NSSLOWCERTCertificate *cert;
+
+ ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST);
+
+ if ( ret ) {
+ return(SECFailure);
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return(SECFailure);
+ }
+
+ do {
+ if ( data.size != 1 ) { /* skip version number */
+
+ /* decode the old DB entry */
+ entry = (certDBEntryCert *)DecodeV4DBCertEntry((unsigned char*)data.data, data.size);
+ derSubject.data = NULL;
+
+ if ( entry ) {
+ cert = nsslowcert_DecodeDERCertificate(&entry->derCert, PR_TRUE,
+ entry->nickname);
+
+ if ( cert != NULL ) {
+ /* add to new database */
+ entry2 = AddCertToPermDB(handle, cert, entry->nickname,
+ &entry->trust);
+
+ nsslowcert_DestroyCertificate(cert);
+ if ( entry2 ) {
+ DestroyDBEntry((certDBEntry *)entry2);
+ }
+ }
+ DestroyDBEntry((certDBEntry *)entry);
+ }
+ }
+ } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 );
+
+ PORT_FreeArena(arena, PR_FALSE);
+ (* updatedb->close)(updatedb);
+ return(SECSuccess);
+}
+
+
+/*
+ * return true if a database key conflict exists
+ */
+PRBool
+nsslowcert_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle)
+{
+ SECStatus rv;
+ DBT tmpdata;
+ DBT namekey;
+ int ret;
+ SECItem keyitem;
+ PRArenaPool *arena = NULL;
+ SECItem derKey;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ goto loser;
+ }
+
+ /* get the db key of the cert */
+ rv = nsslowcert_KeyFromDERCert(arena, derCert, &derKey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ rv = EncodeDBCertKey(&derKey, arena, &keyitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ namekey.data = keyitem.data;
+ namekey.size = keyitem.len;
+
+ ret = certdb_Get(handle->permCertDB, &namekey, &tmpdata, 0);
+ if ( ret == 0 ) {
+ goto loser;
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+
+ return(PR_FALSE);
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(PR_TRUE);
+}
+
+/*
+ * return true if a nickname conflict exists
+ * NOTE: caller must have already made sure that this exact cert
+ * doesn't exist in the DB
+ */
+static PRBool
+nsslowcert_CertNicknameConflict(char *nickname, SECItem *derSubject,
+ NSSLOWCERTCertDBHandle *handle)
+{
+ PRBool rv;
+ certDBEntryNickname *entry;
+
+ if ( nickname == NULL ) {
+ return(PR_FALSE);
+ }
+
+ entry = ReadDBNicknameEntry(handle, nickname);
+
+ if ( entry == NULL ) {
+ /* no entry for this nickname, so no conflict */
+ return(PR_FALSE);
+ }
+
+ rv = PR_TRUE;
+ if ( SECITEM_CompareItem(derSubject, &entry->subjectName) == SECEqual ) {
+ /* if subject names are the same, then no conflict */
+ rv = PR_FALSE;
+ }
+
+ DestroyDBEntry((certDBEntry *)entry);
+ return(rv);
+}
+
+/*
+ * Open the certificate database and index databases. Create them if
+ * they are not there or bad.
+ */
+static SECStatus
+nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
+ NSSLOWCERTDBNameFunc namecb, void *cbarg)
+{
+ SECStatus rv;
+ int openflags;
+ certDBEntryVersion *versionEntry = NULL;
+ DB *updatedb = NULL;
+ char *tmpname;
+ char *certdbname;
+ PRBool updated = PR_FALSE;
+ PRBool forceUpdate = PR_FALSE;
+
+ certdbname = (* namecb)(cbarg, CERT_DB_FILE_VERSION);
+ if ( certdbname == NULL ) {
+ return(SECFailure);
+ }
+
+ if ( readOnly ) {
+ openflags = O_RDONLY;
+ } else {
+ openflags = O_RDWR;
+ }
+
+ /*
+ * first open the permanent file based database.
+ */
+ handle->permCertDB = dbopen( certdbname, openflags, 0600, DB_HASH, 0 );
+
+ /* check for correct version number */
+ if ( handle->permCertDB ) {
+ versionEntry = ReadDBVersionEntry(handle);
+
+ if ( versionEntry == NULL ) {
+ /* no version number */
+ certdb_Close(handle->permCertDB);
+ handle->permCertDB = 0;
+ } else if ( versionEntry->common.version != CERT_DB_FILE_VERSION ) {
+ /* wrong version number, can't update in place */
+ DestroyDBEntry((certDBEntry *)versionEntry);
+ PORT_Free(certdbname);
+ return(SECFailure);
+ } else {
+ DestroyDBEntry((certDBEntry *)versionEntry);
+ versionEntry = NULL;
+ }
+ }
+
+
+ /* if first open fails, try to create a new DB */
+ if ( handle->permCertDB == NULL ) {
+
+ /* don't create if readonly */
+ if ( readOnly ) {
+ goto loser;
+ }
+
+ handle->permCertDB = dbopen(certdbname,
+ O_RDWR | O_CREAT | O_TRUNC,
+ 0600, DB_HASH, 0);
+
+ /* if create fails then we lose */
+ if ( handle->permCertDB == 0 ) {
+ goto loser;
+ }
+
+ versionEntry = NewDBVersionEntry(0);
+ if ( versionEntry == NULL ) {
+ goto loser;
+ }
+
+ rv = WriteDBVersionEntry(handle, versionEntry);
+
+ DestroyDBEntry((certDBEntry *)versionEntry);
+
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* try to upgrade old db here */
+ tmpname = (* namecb)(cbarg, 6); /* get v6 db name */
+ if ( tmpname ) {
+ updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 );
+ PORT_Free(tmpname);
+ if ( updatedb ) {
+ rv = UpdateV6DB(handle, updatedb);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ updated = PR_TRUE;
+ } else { /* no v6 db, so try v5 db */
+ tmpname = (* namecb)(cbarg, 5); /* get v5 db name */
+ if ( tmpname ) {
+ updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 );
+ PORT_Free(tmpname);
+ if ( updatedb ) {
+ rv = UpdateV5DB(handle, updatedb);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ updated = PR_TRUE;
+ } else { /* no v5 db, so try v4 db */
+ /* try to upgrade v4 db */
+ tmpname = (* namecb)(cbarg, 4); /* get v4 db name */
+ if ( tmpname ) {
+ updatedb = dbopen( tmpname, O_RDONLY, 0600,
+ DB_HASH, 0 );
+ PORT_Free(tmpname);
+ if ( updatedb ) {
+ /* NES has v5 db's with v4 db names! */
+ if (isV4DB(updatedb)) {
+ rv = UpdateV4DB(handle, updatedb);
+ } else {
+ rv = UpdateV5DB(handle, updatedb);
+ }
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ forceUpdate = PR_TRUE;
+ updated = PR_TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Root certs are no longer automatically added to the DB. They
+ * come from and external PKCS #11 file.
+ */
+ }
+
+ PORT_Free(certdbname);
+
+ return (SECSuccess);
+
+loser:
+
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+
+ if ( handle->permCertDB ) {
+ certdb_Close(handle->permCertDB);
+ handle->permCertDB = 0;
+ }
+
+ PORT_Free(certdbname);
+
+ return(SECFailure);
+}
+
+/*
+ * delete all DB records associated with a particular certificate
+ */
+static SECStatus
+DeletePermCert(NSSLOWCERTCertificate *cert)
+{
+ SECStatus rv;
+ SECStatus ret;
+
+ ret = SECSuccess;
+
+ rv = DeleteDBCertEntry(cert->dbhandle, &cert->certKey);
+ if ( rv != SECSuccess ) {
+ ret = SECFailure;
+ }
+
+ if ( cert->nickname ) {
+ rv = DeleteDBNicknameEntry(cert->dbhandle, cert->nickname);
+ if ( rv != SECSuccess ) {
+ ret = SECFailure;
+ }
+ }
+
+ rv = RemovePermSubjectNode(cert);
+
+ return(ret);
+}
+
+/*
+ * Delete a certificate from the permanent database.
+ */
+SECStatus
+nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert)
+{
+ SECStatus rv;
+
+ nsslowcert_LockDB(cert->dbhandle);
+ /* delete the records from the permanent database */
+ rv = DeletePermCert(cert);
+
+ /* get rid of dbcert and stuff pointing to it */
+ DestroyDBEntry((certDBEntry *)cert->dbEntry);
+ cert->dbEntry = NULL;
+ cert->trust = NULL;
+
+ nsslowcert_UnlockDB(cert->dbhandle);
+ return(rv);
+}
+
+/*
+ * Traverse all of the entries in the database of a particular type
+ * call the given function for each one.
+ */
+SECStatus
+nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle,
+ certDBEntryType type,
+ SECStatus (* callback)(SECItem *data, SECItem *key,
+ certDBEntryType type, void *pdata),
+ void *udata )
+{
+ DBT data;
+ DBT key;
+ SECStatus rv;
+ int ret;
+ SECItem dataitem;
+ SECItem keyitem;
+ unsigned char *buf;
+ unsigned char *keybuf;
+
+ ret = certdb_Seq(handle->permCertDB, &key, &data, R_FIRST);
+
+ if ( ret ) {
+ return(SECFailure);
+ }
+
+ do {
+ buf = (unsigned char *)data.data;
+
+ if ( buf[1] == (unsigned char)type ) {
+ dataitem.len = data.size;
+ dataitem.data = buf;
+ dataitem.type = siBuffer;
+ keyitem.len = key.size - SEC_DB_KEY_HEADER_LEN;
+ keybuf = (unsigned char *)key.data;
+ keyitem.data = &keybuf[SEC_DB_KEY_HEADER_LEN];
+ keyitem.type = siBuffer;
+
+ rv = (* callback)(&dataitem, &keyitem, type, udata);
+ if ( rv != SECSuccess ) {
+ return(rv);
+ }
+ }
+ } while ( certdb_Seq(handle->permCertDB, &key, &data, R_NEXT) == 0 );
+
+ return(SECSuccess);
+}
+/*
+ * Decode a certificate and enter it into the temporary certificate database.
+ * Deal with nicknames correctly
+ *
+ * This is the private entry point.
+ */
+static NSSLOWCERTCertificate *
+DecodeACert(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry)
+{
+ NSSLOWCERTCertificate *cert = NULL;
+
+ cert = nsslowcert_DecodeDERCertificate(&entry->derCert, PR_TRUE,
+ entry->nickname );
+
+ if ( cert == NULL ) {
+ goto loser;
+ }
+
+ cert->dbhandle = handle;
+ cert->dbEntry = entry;
+ cert->trust = &entry->trust;
+
+ return(cert);
+
+loser:
+ return(0);
+}
+
+typedef struct {
+ PermCertCallback certfunc;
+ NSSLOWCERTCertDBHandle *handle;
+ void *data;
+} PermCertCallbackState;
+
+/*
+ * traversal callback to decode certs and call callers callback
+ */
+static SECStatus
+certcallback(SECItem *dbdata, SECItem *dbkey, certDBEntryType type, void *data)
+{
+ PermCertCallbackState *mystate;
+ SECStatus rv;
+ certDBEntryCert *entry;
+ SECItem entryitem;
+ NSSLOWCERTCertificate *cert;
+ PRArenaPool *arena = NULL;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ goto loser;
+ }
+
+ entry = (certDBEntryCert *)PORT_ArenaAlloc(arena, sizeof(certDBEntryCert));
+ mystate = (PermCertCallbackState *)data;
+ entry->common.version = (unsigned int)dbdata->data[0];
+ entry->common.type = (certDBEntryType)dbdata->data[1];
+ entry->common.flags = (unsigned int)dbdata->data[2];
+ entry->common.arena = arena;
+
+ entryitem.len = dbdata->len - SEC_DB_ENTRY_HEADER_LEN;
+ entryitem.data = &dbdata->data[SEC_DB_ENTRY_HEADER_LEN];
+
+ rv = DecodeDBCertEntry(entry, &entryitem);
+ if (rv != SECSuccess ) {
+ goto loser;
+ }
+ entry->derCert.type = siBuffer;
+
+ /* note: Entry is 'inheritted'. */
+ cert = DecodeACert(mystate->handle, entry);
+
+ rv = (* mystate->certfunc)(cert, dbkey, mystate->data);
+
+ /* arena stored in entry destroyed by nsslowcert_DestroyCertificate */
+ nsslowcert_DestroyCertificateNoLocking(cert);
+
+ return(rv);
+
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ return(SECFailure);
+}
+
+/*
+ * Traverse all of the certificates in the permanent database and
+ * call the given function for each one; expect the caller to have lock.
+ */
+static SECStatus
+TraversePermCertsNoLocking(NSSLOWCERTCertDBHandle *handle,
+ SECStatus (* certfunc)(NSSLOWCERTCertificate *cert,
+ SECItem *k,
+ void *pdata),
+ void *udata )
+{
+ SECStatus rv;
+ PermCertCallbackState mystate;
+
+ mystate.certfunc = certfunc;
+ mystate.handle = handle;
+ mystate.data = udata;
+ rv = nsslowcert_TraverseDBEntries(handle, certDBEntryTypeCert, certcallback,
+ (void *)&mystate);
+
+ return(rv);
+}
+
+/*
+ * Traverse all of the certificates in the permanent database and
+ * call the given function for each one.
+ */
+SECStatus
+nsslowcert_TraversePermCerts(NSSLOWCERTCertDBHandle *handle,
+ SECStatus (* certfunc)(NSSLOWCERTCertificate *cert, SECItem *k,
+ void *pdata),
+ void *udata )
+{
+ SECStatus rv;
+
+ nsslowcert_LockDB(handle);
+ rv = TraversePermCertsNoLocking(handle, certfunc, udata);
+ nsslowcert_UnlockDB(handle);
+
+ return(rv);
+}
+
+
+
+/*
+ * Close the database
+ */
+void
+__nsslowcert_ClosePermCertDB(NSSLOWCERTCertDBHandle *handle)
+{
+ if ( handle ) {
+ if ( handle->permCertDB ) {
+ certdb_Close( handle->permCertDB );
+ handle->permCertDB = 0;
+ }
+ }
+ return;
+}
+
+void
+nsslowcert_ClosePermCertDB(NSSLOWCERTCertDBHandle *handle)
+{
+ __nsslowcert_ClosePermCertDB(handle);
+}
+
+/*
+ * Get the trust attributes from a certificate
+ */
+SECStatus
+nsslowcert_GetCertTrust(NSSLOWCERTCertificate *cert, NSSLOWCERTCertTrust *trust)
+{
+ SECStatus rv;
+
+ nsslowcert_LockCertTrust(cert);
+
+ if ( cert->trust == NULL ) {
+ rv = SECFailure;
+ } else {
+ *trust = *cert->trust;
+ rv = SECSuccess;
+ }
+
+ nsslowcert_UnlockCertTrust(cert);
+ return(rv);
+}
+
+/*
+ * Change the trust attributes of a certificate and make them permanent
+ * in the database.
+ */
+SECStatus
+nsslowcert_ChangeCertTrust(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTCertificate *cert,
+ NSSLOWCERTCertTrust *trust)
+{
+ certDBEntryCert *entry;
+ int rv;
+ SECStatus ret;
+
+ nsslowcert_LockDB(handle);
+ nsslowcert_LockCertTrust(cert);
+ /* only set the trust on permanent certs */
+ if ( cert->trust == NULL ) {
+ ret = SECFailure;
+ goto done;
+ }
+
+ *cert->trust = *trust;
+ if ( cert->dbEntry == NULL ) {
+ ret = SECSuccess; /* not in permanent database */
+ goto done;
+ }
+
+ entry = cert->dbEntry;
+ entry->trust = *trust;
+
+ rv = WriteDBCertEntry(handle, entry);
+ if ( rv ) {
+ ret = SECFailure;
+ goto done;
+ }
+
+ ret = SECSuccess;
+
+done:
+ nsslowcert_UnlockCertTrust(cert);
+ nsslowcert_UnlockDB(handle);
+ return(ret);
+}
+
+
+SECStatus
+nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *dbhandle,
+ NSSLOWCERTCertificate *cert, char *nickname, NSSLOWCERTCertTrust *trust)
+{
+ char *oldnn;
+ certDBEntryCert *entry;
+ PRBool conflict;
+ SECStatus ret;
+
+ nsslowcert_LockDB(dbhandle);
+
+ PORT_Assert(!cert->dbEntry);
+
+ /* don't add a conflicting nickname */
+ conflict = nsslowcert_CertNicknameConflict(nickname, &cert->derSubject,
+ dbhandle);
+ if ( conflict ) {
+ ret = SECFailure;
+ goto done;
+ }
+
+ /* save old nickname so that we can delete it */
+ oldnn = cert->nickname;
+
+ entry = AddCertToPermDB(dbhandle, cert, nickname, trust);
+
+ if ( entry == NULL ) {
+ ret = SECFailure;
+ goto done;
+ }
+
+ cert->nickname = (entry->nickname) ? PORT_ArenaStrdup(cert->arena,entry->nickname) : NULL;
+ cert->trust = &entry->trust;
+ cert->dbEntry = entry;
+
+ ret = SECSuccess;
+done:
+ nsslowcert_UnlockDB(dbhandle);
+ return(ret);
+}
+
+/*
+ * Open the certificate database and index databases. Create them if
+ * they are not there or bad.
+ */
+SECStatus
+nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
+ NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile)
+{
+ int rv;
+
+ certdb_InitDBLock(handle);
+
+ handle->dbMon = PZ_NewMonitor(nssILockCertDB);
+ PORT_Assert(handle->dbMon != NULL);
+
+ rv = nsslowcert_OpenPermCertDB(handle, readOnly, namecb, cbarg);
+ if ( rv ) {
+ goto loser;
+ }
+
+ return (SECSuccess);
+
+loser:
+
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ return(SECFailure);
+}
+
+
+/*
+ * Lookup a certificate in the databases.
+ */
+static NSSLOWCERTCertificate *
+FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey, PRBool lockdb)
+{
+ SECItem keyitem;
+ DBT key;
+ SECStatus rv;
+ NSSLOWCERTCertificate *cert = NULL;
+ PRArenaPool *arena = NULL;
+ certDBEntryCert *entry;
+ PRBool locked = PR_FALSE;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBCertKey(certKey, arena, &keyitem);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ key.data = keyitem.data;
+ key.size = keyitem.len;
+
+ if ( lockdb ) {
+ locked = PR_TRUE;
+ nsslowcert_LockDB(handle);
+ }
+
+ /* find in perm database */
+ entry = ReadDBCertEntry(handle, certKey);
+
+ if ( entry == NULL ) {
+ goto loser;
+ }
+
+ /* inherit entry */
+ cert = DecodeACert(handle, entry);
+
+loser:
+ if ( locked ) {
+ nsslowcert_UnlockDB(handle);
+ }
+
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(cert);
+}
+
+/*
+ * Lookup a certificate in the databases without locking
+ */
+NSSLOWCERTCertificate *
+nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
+{
+ return(FindCertByKey(handle, certKey, PR_FALSE));
+}
+
+/*
+ * Generate a key from an issuerAndSerialNumber, and find the
+ * associated cert in the database.
+ */
+NSSLOWCERTCertificate *
+nsslowcert_FindCertByIssuerAndSN(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN)
+{
+ SECItem certKey;
+ NSSLOWCERTCertificate *cert;
+
+ certKey.len = issuerAndSN->serialNumber.len + issuerAndSN->derIssuer.len;
+ certKey.data = (unsigned char*)PORT_Alloc(certKey.len);
+
+ if ( certKey.data == NULL ) {
+ return(0);
+ }
+
+ /* copy the serialNumber */
+ PORT_Memcpy(certKey.data, issuerAndSN->serialNumber.data,
+ issuerAndSN->serialNumber.len);
+
+ /* copy the issuer */
+ PORT_Memcpy( &certKey.data[issuerAndSN->serialNumber.len],
+ issuerAndSN->derIssuer.data, issuerAndSN->derIssuer.len);
+
+ cert = nsslowcert_FindCertByKey(handle, &certKey);
+
+ PORT_Free(certKey.data);
+
+ return(cert);
+}
+
+/*
+ * look for the given DER certificate in the database
+ */
+NSSLOWCERTCertificate *
+nsslowcert_FindCertByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCert)
+{
+ PRArenaPool *arena;
+ SECItem certKey;
+ SECStatus rv;
+ NSSLOWCERTCertificate *cert = NULL;
+
+ /* create a scratch arena */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ return(NULL);
+ }
+
+ /* extract the database key from the cert */
+ rv = nsslowcert_KeyFromDERCert(arena, derCert, &certKey);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* find the certificate */
+ cert = nsslowcert_FindCertByKey(handle, &certKey);
+
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return(cert);
+}
+
+static void
+DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb)
+{
+ int refCount;
+ NSSLOWCERTCertDBHandle *handle;
+
+ if ( cert ) {
+
+ handle = cert->dbhandle;
+
+ /*
+ * handle may be NULL, for example if the cert was created with
+ * nsslowcert_DecodeDERCertificate.
+ */
+ if ( lockdb && handle ) {
+ nsslowcert_LockDB(handle);
+ }
+
+ nsslowcert_LockCertRefCount(cert);
+ PORT_Assert(cert->referenceCount > 0);
+ refCount = --cert->referenceCount;
+ nsslowcert_UnlockCertRefCount(cert);
+
+ if ( ( refCount == 0 ) ) {
+ certDBEntryCert *entry = cert->dbEntry;
+ PRArenaPool * arena = cert->arena;
+
+ if ( entry ) {
+ DestroyDBEntry((certDBEntry *)entry);
+ }
+
+ /* zero cert before freeing. Any stale references to this cert
+ * after this point will probably cause an exception. */
+ PORT_Memset(cert, 0, sizeof *cert);
+
+ cert = NULL;
+
+ /* free the arena that contains the cert. */
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ if ( lockdb && handle ) {
+ nsslowcert_UnlockDB(handle);
+ }
+ }
+
+ return;
+}
+
+void
+nsslowcert_DestroyCertificate(NSSLOWCERTCertificate *cert)
+{
+ DestroyCertificate(cert, PR_TRUE);
+ return;
+}
+
+static void
+nsslowcert_DestroyCertificateNoLocking(NSSLOWCERTCertificate *cert)
+{
+ DestroyCertificate(cert, PR_FALSE);
+ return;
+}
+
+/*
+ * Lookup a CRL in the databases. We mirror the same fast caching data base
+ * caching stuff used by certificates....?
+ */
+SECItem *
+nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey,
+ char **url, PRBool isKRL)
+{
+ SECItem keyitem;
+ DBT key;
+ SECStatus rv;
+ SECItem *crl = NULL;
+ PRArenaPool *arena = NULL;
+ certDBEntryRevocation *entry;
+ certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation
+ : certDBEntryTypeRevocation;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( arena == NULL ) {
+ goto loser;
+ }
+
+ rv = EncodeDBGenericKey(crlKey, arena, &keyitem, crlType);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ key.data = keyitem.data;
+ key.size = keyitem.len;
+
+ /* find in perm database */
+ entry = ReadDBCrlEntry(handle, crlKey, crlType);
+
+ if ( entry == NULL ) {
+ goto loser;
+ }
+
+ if (entry->url) {
+ *url = PORT_Strdup(entry->url);
+ }
+ crl = SECITEM_DupItem(&entry->derCrl);
+
+loser:
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ if (entry) {
+ DestroyDBEntry((certDBEntry *)entry);
+ }
+
+ return(crl);
+}
+
+/*
+ * replace the existing URL in the data base with a new one
+ */
+SECStatus
+nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl,
+ SECItem *crlKey, char *url, PRBool isKRL)
+{
+ SECStatus rv = SECFailure;
+ certDBEntryRevocation *entry = NULL;
+ certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation
+ : certDBEntryTypeRevocation;
+ DeleteDBCrlEntry(handle, crlKey, crlType);
+
+ /* Write the new entry into the data base */
+ entry = NewDBCrlEntry(derCrl, url, crlType, 0);
+ if (entry == NULL) goto done;
+
+ rv = WriteDBCrlEntry(handle, entry, crlKey);
+ if (rv != SECSuccess) goto done;
+
+done:
+ if (entry) {
+ DestroyDBEntry((certDBEntry *)entry);
+ }
+ return rv;
+}
+
+SECStatus
+nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle, SECItem *derName,
+ PRBool isKRL)
+{
+ SECStatus rv;
+ certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation
+ : certDBEntryTypeRevocation;
+
+ rv = DeleteDBCrlEntry(handle, derName, crlType);
+ if (rv != SECSuccess) goto done;
+
+done:
+ return rv;
+}
+
+
+PRBool
+nsslowcert_hasTrust(NSSLOWCERTCertificate *cert)
+{
+ NSSLOWCERTCertTrust *trust;
+
+ if (cert->trust == NULL) {
+ return PR_FALSE;
+ }
+ trust = cert->trust;
+ return !((trust->sslFlags & CERTDB_TRUSTED_UNKNOWN) &&
+ (trust->emailFlags & CERTDB_TRUSTED_UNKNOWN) &&
+ (trust->objectSigningFlags & CERTDB_TRUSTED_UNKNOWN));
+}
+
+/*
+ * This function has the logic that decides if another person's cert and
+ * email profile from an S/MIME message should be saved. It can deal with
+ * the case when there is no profile.
+ */
+SECStatus
+nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr,
+ SECItem *derSubject, SECItem *emailProfile, SECItem *profileTime)
+{
+ certDBEntrySMime *entry = NULL;
+ SECStatus rv = SECFailure;;
+
+ /* find our existing entry */
+ entry = nsslowcert_ReadDBSMimeEntry(dbhandle, emailAddr);
+
+ if ( entry ) {
+ /* keep our old db entry consistant for old applications. */
+ if (!SECITEM_ItemsAreEqual(derSubject, &entry->subjectName)) {
+ UpdateSubjectWithEmailAddr(dbhandle, &entry->subjectName, NULL);
+ }
+ DestroyDBEntry((certDBEntry *)entry);
+ entry = NULL;
+ }
+
+ /* now save the entry */
+ entry = NewDBSMimeEntry(emailAddr, derSubject, emailProfile,
+ profileTime, 0);
+ if ( entry == NULL ) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ nsslowcert_LockDB(dbhandle);
+
+ rv = DeleteDBSMimeEntry(dbhandle, emailAddr);
+ /* if delete fails, try to write new entry anyway... */
+
+ /* link subject entry back here */
+ rv = UpdateSubjectWithEmailAddr(dbhandle, derSubject, emailAddr);
+ if ( rv != SECSuccess ) {
+ nsslowcert_UnlockDB(dbhandle);
+ goto loser;
+ }
+
+ rv = WriteDBSMimeEntry(dbhandle, entry);
+ if ( rv != SECSuccess ) {
+ nsslowcert_UnlockDB(dbhandle);
+ goto loser;
+ }
+
+ nsslowcert_UnlockDB(dbhandle);
+
+ rv = SECSuccess;
+
+loser:
+ if ( entry ) {
+ DestroyDBEntry((certDBEntry *)entry);
+ }
+ return(rv);
+}
diff --git a/security/nss/lib/softoken/pcertt.h b/security/nss/lib/softoken/pcertt.h
new file mode 100644
index 000000000..808f95fe1
--- /dev/null
+++ b/security/nss/lib/softoken/pcertt.h
@@ -0,0 +1,433 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+/*
+ * certt.h - public data structures for the certificate library
+ *
+ * $Id$
+ */
+#ifndef _PCERTT_H_
+#define _PCERTT_H_
+
+#include "prclist.h"
+#include "pkcs11t.h"
+#include "seccomon.h"
+#include "secoidt.h"
+#include "plarena.h"
+#include "prcvar.h"
+#include "nssilock.h"
+#include "prio.h"
+#include "prmon.h"
+
+
+/* Non-opaque objects */
+typedef struct NSSLOWCERTCertDBHandleStr NSSLOWCERTCertDBHandle;
+typedef struct NSSLOWCERTCertKeyStr NSSLOWCERTCertKey;
+
+typedef struct NSSLOWCERTCertTrustStr NSSLOWCERTCertTrust;
+typedef struct NSSLOWCERTCertificateStr NSSLOWCERTCertificate;
+typedef struct NSSLOWCERTCertificateListStr NSSLOWCERTCertificateList;
+typedef struct NSSLOWCERTIssuerAndSNStr NSSLOWCERTIssuerAndSN;
+typedef struct NSSLOWCERTSignedDataStr NSSLOWCERTSignedData;
+typedef struct NSSLOWCERTSubjectPublicKeyInfoStr NSSLOWCERTSubjectPublicKeyInfo;
+typedef struct NSSLOWCERTValidityStr NSSLOWCERTValidity;
+
+/*
+** An X.509 validity object
+*/
+struct NSSLOWCERTValidityStr {
+ PRArenaPool *arena;
+ SECItem notBefore;
+ SECItem notAfter;
+};
+
+/*
+ * A serial number and issuer name, which is used as a database key
+ */
+struct NSSLOWCERTCertKeyStr {
+ SECItem serialNumber;
+ SECItem derIssuer;
+};
+
+/*
+** A signed data object. Used to implement the "signed" macro used
+** in the X.500 specs.
+*/
+struct NSSLOWCERTSignedDataStr {
+ SECItem data;
+ SECAlgorithmID signatureAlgorithm;
+ SECItem signature;
+};
+
+/*
+** An X.509 subject-public-key-info object
+*/
+struct NSSLOWCERTSubjectPublicKeyInfoStr {
+ PRArenaPool *arena;
+ SECAlgorithmID algorithm;
+ SECItem subjectPublicKey;
+};
+
+typedef struct _certDBEntryCert certDBEntryCert;
+typedef struct _certDBEntryRevocation certDBEntryRevocation;
+
+struct NSSLOWCERTCertTrustStr {
+ unsigned int sslFlags;
+ unsigned int emailFlags;
+ unsigned int objectSigningFlags;
+};
+
+/*
+** An X.509 certificate object (the unsigned form)
+*/
+struct NSSLOWCERTCertificateStr {
+ /* the arena is used to allocate any data structures that have the same
+ * lifetime as the cert. This is all stuff that hangs off of the cert
+ * structure, and is all freed at the same time. I is used when the
+ * cert is decoded, destroyed, and at some times when it changes
+ * state
+ */
+ PRArenaPool *arena;
+ NSSLOWCERTCertDBHandle *dbhandle;
+
+ SECItem derCert; /* original DER for the cert */
+ SECItem derIssuer; /* DER for issuer name */
+ SECItem serialNumber;
+ SECItem derSubject; /* DER for subject name */
+ NSSLOWCERTSubjectPublicKeyInfo subjectPublicKeyInfo;
+ SECItem certKey; /* database key for this cert */
+ NSSLOWCERTValidity validity;
+ certDBEntryCert *dbEntry; /* database entry struct */
+ SECItem subjectKeyID; /* x509v3 subject key identifier */
+ char *nickname;
+ char *emailAddr;
+ NSSLOWCERTCertTrust *trust;
+
+ /* the reference count is modified whenever someone looks up, dups
+ * or destroys a certificate
+ */
+ int referenceCount;
+};
+#define SEC_CERTIFICATE_VERSION_1 0 /* default created */
+#define SEC_CERTIFICATE_VERSION_2 1 /* v2 */
+#define SEC_CERTIFICATE_VERSION_3 2 /* v3 extensions */
+
+#define SEC_CRL_VERSION_1 0 /* default */
+#define SEC_CRL_VERSION_2 1 /* v2 extensions */
+
+struct NSSLOWCERTIssuerAndSNStr {
+ SECItem derIssuer;
+ SECItem serialNumber;
+};
+
+typedef SECStatus (* NSSLOWCERTCertCallback)(NSSLOWCERTCertificate *cert, void *arg);
+
+/* This is the typedef for the callback passed to nsslowcert_OpenCertDB() */
+/* callback to return database name based on version number */
+typedef char * (*NSSLOWCERTDBNameFunc)(void *arg, int dbVersion);
+
+/* XXX Lisa thinks the template declarations belong in cert.h, not here? */
+
+#include "secasn1t.h" /* way down here because I expect template stuff to
+ * move out of here anyway */
+
+SEC_BEGIN_PROTOS
+
+extern const SEC_ASN1Template nsslowcert_CertificateTemplate[];
+extern const SEC_ASN1Template SEC_SignedCertificateTemplate[];
+extern const SEC_ASN1Template nsslowcert_SignedDataTemplate[];
+extern const SEC_ASN1Template NSSLOWKEY_PublicKeyTemplate[];
+extern const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[];
+extern const SEC_ASN1Template nsslowcert_ValidityTemplate[];
+
+SEC_END_PROTOS
+
+/*
+ * Certificate Database related definitions and data structures
+ */
+
+/* version number of certificate database */
+#define CERT_DB_FILE_VERSION 7
+#ifdef USE_NS_ROOTS
+#define CERT_DB_CONTENT_VERSION 28
+#else
+#define CERT_DB_CONTENT_VERSION 2
+#endif
+
+#define SEC_DB_ENTRY_HEADER_LEN 3
+#define SEC_DB_KEY_HEADER_LEN 1
+
+/* All database entries have this form:
+ *
+ * byte offset field
+ * ----------- -----
+ * 0 version
+ * 1 type
+ * 2 flags
+ */
+
+/* database entry types */
+typedef enum {
+ certDBEntryTypeVersion = 0,
+ certDBEntryTypeCert = 1,
+ certDBEntryTypeNickname = 2,
+ certDBEntryTypeSubject = 3,
+ certDBEntryTypeRevocation = 4,
+ certDBEntryTypeKeyRevocation = 5,
+ certDBEntryTypeSMimeProfile = 6,
+ certDBEntryTypeContentVersion = 7
+} certDBEntryType;
+
+typedef struct {
+ certDBEntryType type;
+ unsigned int version;
+ unsigned int flags;
+ PRArenaPool *arena;
+} certDBEntryCommon;
+
+/*
+ * Certificate entry:
+ *
+ * byte offset field
+ * ----------- -----
+ * 0 sslFlags-msb
+ * 1 sslFlags-lsb
+ * 2 emailFlags-msb
+ * 3 emailFlags-lsb
+ * 4 objectSigningFlags-msb
+ * 5 objectSigningFlags-lsb
+ * 6 derCert-len-msb
+ * 7 derCert-len-lsb
+ * 8 nickname-len-msb
+ * 9 nickname-len-lsb
+ * ... derCert
+ * ... nickname
+ *
+ * NOTE: the nickname string as stored in the database is null terminated,
+ * in other words, the last byte of the db entry is always 0
+ * if a nickname is present.
+ * NOTE: if nickname is not present, then nickname-len-msb and
+ * nickname-len-lsb will both be zero.
+ */
+struct _certDBEntryCert {
+ certDBEntryCommon common;
+ NSSLOWCERTCertTrust trust;
+ SECItem derCert;
+ char *nickname;
+};
+
+/*
+ * Certificate Nickname entry:
+ *
+ * byte offset field
+ * ----------- -----
+ * 0 subjectname-len-msb
+ * 1 subjectname-len-lsb
+ * 2... subjectname
+ *
+ * The database key for this type of entry is a nickname string
+ * The "subjectname" value is the DER encoded DN of the identity
+ * that matches this nickname.
+ */
+typedef struct {
+ certDBEntryCommon common;
+ char *nickname;
+ SECItem subjectName;
+} certDBEntryNickname;
+
+#define DB_NICKNAME_ENTRY_HEADER_LEN 2
+
+/*
+ * Certificate Subject entry:
+ *
+ * byte offset field
+ * ----------- -----
+ * 0 ncerts-msb
+ * 1 ncerts-lsb
+ * 2 nickname-msb
+ * 3 nickname-lsb
+ * 4 emailAddr-msb
+ * 5 emailAddr-lsb
+ * ... nickname
+ * ... emailAddr
+ * ...+2*i certkey-len-msb
+ * ...+1+2*i certkey-len-lsb
+ * ...+2*ncerts+2*i keyid-len-msb
+ * ...+1+2*ncerts+2*i keyid-len-lsb
+ * ... certkeys
+ * ... keyids
+ *
+ * The database key for this type of entry is the DER encoded subject name
+ * The "certkey" value is an array of certificate database lookup keys that
+ * points to the database entries for the certificates that matche
+ * this subject.
+ *
+ */
+typedef struct _certDBEntrySubject {
+ certDBEntryCommon common;
+ SECItem derSubject;
+ unsigned int ncerts;
+ char *nickname;
+ char *emailAddr;
+ SECItem *certKeys;
+ SECItem *keyIDs;
+} certDBEntrySubject;
+
+#define DB_SUBJECT_ENTRY_HEADER_LEN 6
+
+/*
+ * Certificate SMIME profile entry:
+ *
+ * byte offset field
+ * ----------- -----
+ * 0 subjectname-len-msb
+ * 1 subjectname-len-lsb
+ * 2 smimeoptions-len-msb
+ * 3 smimeoptions-len-lsb
+ * 4 options-date-len-msb
+ * 5 options-date-len-lsb
+ * 6... subjectname
+ * ... smimeoptions
+ * ... options-date
+ *
+ * The database key for this type of entry is the email address string
+ * The "subjectname" value is the DER encoded DN of the identity
+ * that matches this nickname.
+ * The "smimeoptions" value is a string that represents the algorithm
+ * capabilities on the remote user.
+ * The "options-date" is the date that the smime options value was created.
+ * This is generally the signing time of the signed message that contained
+ * the options. It is a UTCTime value.
+ */
+typedef struct {
+ certDBEntryCommon common;
+ char *emailAddr;
+ SECItem subjectName;
+ SECItem smimeOptions;
+ SECItem optionsDate;
+} certDBEntrySMime;
+
+#define DB_SMIME_ENTRY_HEADER_LEN 6
+
+/*
+ * Crl/krl entry:
+ *
+ * byte offset field
+ * ----------- -----
+ * 0 derCert-len-msb
+ * 1 derCert-len-lsb
+ * 2 url-len-msb
+ * 3 url-len-lsb
+ * ... derCert
+ * ... url
+ *
+ * NOTE: the url string as stored in the database is null terminated,
+ * in other words, the last byte of the db entry is always 0
+ * if a nickname is present.
+ * NOTE: if url is not present, then url-len-msb and
+ * url-len-lsb will both be zero.
+ */
+#define DB_CRL_ENTRY_HEADER_LEN 4
+struct _certDBEntryRevocation {
+ certDBEntryCommon common;
+ SECItem derCrl;
+ char *url; /* where to load the crl from */
+};
+
+/*
+ * Database Version Entry:
+ *
+ * byte offset field
+ * ----------- -----
+ * only the low level header...
+ *
+ * The database key for this type of entry is the string "Version"
+ */
+typedef struct {
+ certDBEntryCommon common;
+} certDBEntryVersion;
+
+#define SEC_DB_VERSION_KEY "Version"
+#define SEC_DB_VERSION_KEY_LEN sizeof(SEC_DB_VERSION_KEY)
+
+/*
+ * Database Content Version Entry:
+ *
+ * byte offset field
+ * ----------- -----
+ * 0 contentVersion
+ *
+ * The database key for this type of entry is the string "ContentVersion"
+ */
+typedef struct {
+ certDBEntryCommon common;
+ char contentVersion;
+} certDBEntryContentVersion;
+
+#define SEC_DB_CONTENT_VERSION_KEY "ContentVersion"
+#define SEC_DB_CONTENT_VERSION_KEY_LEN sizeof(SEC_DB_CONTENT_VERSION_KEY)
+
+typedef union {
+ certDBEntryCommon common;
+ certDBEntryVersion version;
+ certDBEntryCert cert;
+ certDBEntryNickname nickname;
+ certDBEntrySubject subject;
+ certDBEntryRevocation revocation;
+} certDBEntry;
+
+/* length of the fixed part of a database entry */
+#define DBCERT_V4_HEADER_LEN 7
+#define DB_CERT_V5_ENTRY_HEADER_LEN 7
+#define DB_CERT_V6_ENTRY_HEADER_LEN 7
+#define DB_CERT_ENTRY_HEADER_LEN 10
+
+/* common flags for all types of certificates */
+#define CERTDB_VALID_PEER (1<<0)
+#define CERTDB_TRUSTED (1<<1)
+#define CERTDB_SEND_WARN (1<<2)
+#define CERTDB_VALID_CA (1<<3)
+#define CERTDB_TRUSTED_CA (1<<4) /* trusted for issuing server certs */
+#define CERTDB_NS_TRUSTED_CA (1<<5)
+#define CERTDB_USER (1<<6)
+#define CERTDB_TRUSTED_CLIENT_CA (1<<7) /* trusted for issuing client certs */
+#define CERTDB_INVISIBLE_CA (1<<8) /* don't show in UI */
+#define CERTDB_GOVT_APPROVED_CA (1<<9) /* can do strong crypto in export ver */
+#define CERTDB_NOT_TRUSTED (1<<10) /* explicitly don't trust this cert */
+#define CERTDB_TRUSTED_UNKNOWN (1<<11) /* accept trust from another source */
+
+/* bits not affected by the CKO_NETSCAPE_TRUST object */
+#define CERTDB_PRESERVE_TRUST_BITS (CERTDB_USER | CERTDB_VALID_PEER | \
+ CERTDB_NS_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_INVISIBLE_CA | \
+ CERTDB_GOVT_APPROVED_CA)
+
+#endif /* _PCERTT_H_ */
diff --git a/security/nss/lib/softoken/pk11db.c b/security/nss/lib/softoken/pk11db.c
index ee0e94d0e..162d53714 100644
--- a/security/nss/lib/softoken/pk11db.c
+++ b/security/nss/lib/softoken/pk11db.c
@@ -38,68 +38,210 @@
#include "pk11pars.h"
#include "pkcs11i.h"
+#include "mcom_db.h"
#define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
static void
-secmod_parseFlags(char *tmp, pk11_parameters *parsed) {
+secmod_parseTokenFlags(char *tmp, pk11_token_parameters *parsed) {
parsed->readOnly = pk11_argHasFlag("flags","readOnly",tmp);
parsed->noCertDB = pk11_argHasFlag("flags","noCertDB",tmp);
+ parsed->noKeyDB = pk11_argHasFlag("flags","noKeyDB",tmp);
+ parsed->forceOpen = pk11_argHasFlag("flags","forceOpen",tmp);
+ parsed->pwRequired = pk11_argHasFlag("flags","passwordRequired",tmp);
+ return;
+}
+
+static void
+secmod_parseFlags(char *tmp, pk11_parameters *parsed) {
parsed->noModDB = pk11_argHasFlag("flags","noModDB",tmp);
+ parsed->readOnly = pk11_argHasFlag("flags","readOnly",tmp);
+ /* keep legacy interface working */
+ parsed->noCertDB = pk11_argHasFlag("flags","noCertDB",tmp);
parsed->forceOpen = pk11_argHasFlag("flags","forceOpen",tmp);
parsed->pwRequired = pk11_argHasFlag("flags","passwordRequired",tmp);
return;
}
+CK_RV
+secmod_parseTokenParameters(char *param, pk11_token_parameters *parsed)
+{
+ int next;
+ char *tmp;
+ char *index;
+ index = pk11_argStrip(param);
+
+ while (*index) {
+ PK11_HANDLE_STRING_ARG(index,parsed->configdir,"configdir=",;)
+ PK11_HANDLE_STRING_ARG(index,parsed->certPrefix,"certprefix=",;)
+ PK11_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyprefix=",;)
+ PK11_HANDLE_STRING_ARG(index,parsed->tokdes,"tokenDescription=",;)
+ PK11_HANDLE_STRING_ARG(index,parsed->slotdes,"slotDescription=",;)
+ PK11_HANDLE_STRING_ARG(index,tmp,"minPWLen=",
+ if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); })
+ PK11_HANDLE_STRING_ARG(index,tmp,"flags=",
+ if(tmp) { secmod_parseTokenFlags(param,parsed); PORT_Free(tmp); })
+ PK11_HANDLE_FINAL_ARG(index)
+ }
+ return CKR_OK;
+}
+
+static void
+secmod_parseTokens(char *tokenParams, pk11_parameters *parsed)
+{
+ char *tokenIndex;
+ pk11_token_parameters *tokens = NULL;
+ int i=0,count = 0,next;
+
+ if ((tokenParams == NULL) || (*tokenParams == 0)) return;
+ /* first count the number of slots */
+ for (tokenIndex = pk11_argStrip(tokenParams); *tokenIndex;
+ tokenIndex = pk11_argStrip(pk11_argSkipParameter(tokenIndex))) {
+ count++;
+ }
+
+ /* get the data structures */
+ tokens = (pk11_token_parameters *)
+ PORT_ZAlloc(count*sizeof(pk11_token_parameters));
+ if (tokens == NULL) return;
+
+ for (tokenIndex = pk11_argStrip(tokenParams), i = 0;
+ *tokenIndex && i < count ; i++ ) {
+ char *name;
+ name = pk11_argGetName(tokenIndex,&next);
+ tokenIndex += next;
+
+ tokens[i].slotID = pk11_argDecodeNumber(name);
+ tokens[i].readOnly = PR_TRUE;
+ tokens[i].noCertDB = PR_TRUE;
+ tokens[i].noKeyDB = PR_TRUE;
+ if (!pk11_argIsBlank(*tokenIndex)) {
+ char *args = pk11_argFetchValue(tokenIndex,&next);
+ tokenIndex += next;
+ if (args) {
+ secmod_parseTokenParameters(args,&tokens[i]);
+ PORT_Free(args);
+ }
+ }
+ if (name) PORT_Free(name);
+ tokenIndex = pk11_argStrip(tokenIndex);
+ }
+ parsed->token_count = i;
+ parsed->tokens = tokens;
+ return;
+}
CK_RV
-secmod_parseParameters(char *param, pk11_parameters *parsed)
+secmod_parseParameters(char *param, pk11_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 = pk11_argStrip(param);
PORT_Memset(parsed, 0, sizeof(pk11_parameters));
while (*index) {
PK11_HANDLE_STRING_ARG(index,parsed->configdir,"configdir=",;)
- PK11_HANDLE_STRING_ARG(index,parsed->certPrefix,"certprefix=",;)
- PK11_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyprefix=",;)
PK11_HANDLE_STRING_ARG(index,parsed->secmodName,"secmod=",;)
PK11_HANDLE_STRING_ARG(index,parsed->man,"manufactureID=",;)
PK11_HANDLE_STRING_ARG(index,parsed->libdes,"libraryDescription=",;)
- PK11_HANDLE_STRING_ARG(index,parsed->tokdes,"cryptoTokenDescription=",;)
- PK11_HANDLE_STRING_ARG(index,parsed->ptokdes,"dbTokenDescription=",;)
- PK11_HANDLE_STRING_ARG(index,parsed->slotdes,"cryptoSlotDescription=",;)
- PK11_HANDLE_STRING_ARG(index,parsed->pslotdes,"dbSlotDescription=",;)
- PK11_HANDLE_STRING_ARG(index,parsed->fslotdes,"FIPSSlotDescription=",;)
- PK11_HANDLE_STRING_ARG(index,parsed->fpslotdes,"FIPSTokenDescription=",;)
- PK11_HANDLE_STRING_ARG(index,tmp,"minPWLen=",
- if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); })
+ /* constructed values, used so legacy interfaces still work */
+ PK11_HANDLE_STRING_ARG(index,certPrefix,"certprefix=",;)
+ PK11_HANDLE_STRING_ARG(index,keyPrefix,"keyprefix=",;)
+ PK11_HANDLE_STRING_ARG(index,tokdes,"cryptoTokenDescription=",;)
+ PK11_HANDLE_STRING_ARG(index,ptokdes,"dbTokenDescription=",;)
+ PK11_HANDLE_STRING_ARG(index,slotdes,"cryptoSlotDescription=",;)
+ PK11_HANDLE_STRING_ARG(index,pslotdes,"dbSlotDescription=",;)
+ PK11_HANDLE_STRING_ARG(index,fslotdes,"FIPSSlotDescription=",;)
+ PK11_HANDLE_STRING_ARG(index,minPW,"FIPSTokenDescription=",;)
+ PK11_HANDLE_STRING_ARG(index,tmp,"minPWLen=",;)
+
PK11_HANDLE_STRING_ARG(index,tmp,"flags=",
if(tmp) { secmod_parseFlags(param,parsed); PORT_Free(tmp); })
+ PK11_HANDLE_STRING_ARG(index,tmp,"tokens=",
+ if(tmp) { secmod_parseTokens(tmp,parsed); PORT_Free(tmp); })
PK11_HANDLE_FINAL_ARG(index)
- }
- return CKR_OK;
+ }
+ if (parsed->tokens == NULL) {
+ int count = isFIPS ? 1 : 2;
+ int index = count-1;
+ pk11_token_parameters *tokens = NULL;
+
+ tokens = (pk11_token_parameters *)
+ PORT_ZAlloc(count*sizeof(pk11_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].forceOpen = parsed->forceOpen;
+ tokens[index].pwRequired = parsed->pwRequired;
+ 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(pk11_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->certPrefix);
- FREE_CLEAR(params->keyPrefix);
FREE_CLEAR(params->secmodName);
FREE_CLEAR(params->man);
FREE_CLEAR(params->libdes);
- FREE_CLEAR(params->tokdes);
- FREE_CLEAR(params->ptokdes);
- FREE_CLEAR(params->slotdes);
- FREE_CLEAR(params->pslotdes);
- FREE_CLEAR(params->fslotdes);
- FREE_CLEAR(params->fpslotdes);
+ FREE_CLEAR(params->tokens);
}
@@ -462,7 +604,7 @@ secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
trustOrder = 20;
}
- slotStrings[i] = pk11_mkSlotString(slotID,defaultFlags,
+ slotStrings[i] = pk11_mkSlotString(slotID,defaultFlags,
timeout,slots[i].askpw,hasRootCerts,hasRootTrust);
}
@@ -488,7 +630,7 @@ static DB *secmod_OpenDB(char *dbName, PRBool readOnly) {
if (readOnly) return NULL;
pkcs11db = dbopen( dbName,
- O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 );
+ O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 );
if (pkcs11db) (* pkcs11db->sync)(pkcs11db, 0);
}
return pkcs11db;
diff --git a/security/nss/lib/softoken/pk11pars.h b/security/nss/lib/softoken/pk11pars.h
index 7710820ab..9e273f104 100644
--- a/security/nss/lib/softoken/pk11pars.h
+++ b/security/nss/lib/softoken/pk11pars.h
@@ -45,8 +45,8 @@
#include "pkcs11.h"
#include "seccomon.h"
#include "prprf.h"
-#include "secmod.h"
-#include "secmodi.h"
+#include "secmodt.h"
+#include "pk11init.h"
#define PK11_ARG_LIBRARY_PARAMETER "library="
#define PK11_ARG_NAME_PARAMETER "name="
diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c
index 78a26cebf..e6eaf1f1e 100644
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -52,14 +52,13 @@
#include "pkcs11.h"
#include "pkcs11i.h"
#include "softoken.h"
-#include "cert.h"
-#include "keylow.h"
+#include "lowkeyi.h"
#include "blapi.h"
#include "secder.h"
#include "secport.h"
-#include "certdb.h"
+#include "pcert.h"
-#include "private.h"
+#include "keydbi.h"
/*
@@ -71,6 +70,7 @@ static char *manufacturerID = "mozilla.org ";
static char manufacturerID_space[33];
static char *libraryDescription = "NSS Internal Crypto Services ";
static char libraryDescription_space[33];
+#ifdef notdef
static char *tokDescription = "NSS Generic Crypto Services ";
static char tokDescription_space[33];
static char *privTokDescription = "NSS Certificate DB ";
@@ -83,7 +83,13 @@ static char slotDescription_space[65];
static char *privSlotDescription =
"NSS User Private Key and Certificate Services ";
static char privSlotDescription_space[65];
-static int minimumPinLen = 0;
+/* The next two strings must be exactly 64 characters long, with the
+ first 32 characters meaningful */
+static char *slotDescription =
+ "Netscape Internal FIPS-140-1 Cryptographic Services ";
+static char *privSlotDescription =
+ "Netscape FIPS-140-1 User Private Key Services ";
+#endif
#define __PASTE(x,y) x##y
@@ -104,7 +110,7 @@ static int minimumPinLen = 0;
/* build the crypto module table */
-static CK_FUNCTION_LIST pk11_funcList = {
+static const CK_FUNCTION_LIST pk11_funcList = {
{ 1, 10 },
#undef CK_PKCS11_FUNCTION_INFO
@@ -124,7 +130,7 @@ static CK_FUNCTION_LIST pk11_funcList = {
/* List of DES Weak Keys */
typedef unsigned char desKey[8];
-static desKey pk11_desWeakTable[] = {
+static const desKey pk11_desWeakTable[] = {
#ifdef noParity
/* weak */
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -178,12 +184,12 @@ static desKey pk11_desWeakTable[] = {
};
-static int pk11_desWeakTableSize = sizeof(pk11_desWeakTable)/
+static const int pk11_desWeakTableSize = sizeof(pk11_desWeakTable)/
sizeof(pk11_desWeakTable[0]);
/* DES KEY Parity conversion table. Takes each byte/2 as an index, returns
* that byte with the proper parity bit set */
-static unsigned char parityTable[256] = {
+static const unsigned char parityTable[256] = {
/* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */
/* E */ 0x01,0x02,0x04,0x07,0x08,0x0b,0x0d,0x0e,
/* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */
@@ -239,7 +245,9 @@ struct mechanismList {
#define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE
#define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE
-static struct mechanismList mechanisms[] = {
+#define CK_MAX 0xffffffff
+
+static const struct mechanismList mechanisms[] = {
/*
* PKCS #11 Mechanism List.
@@ -262,16 +270,16 @@ static struct mechanismList mechanisms[] = {
*/
/* ------------------------- RSA Operations ---------------------------*/
- {CKM_RSA_PKCS_KEY_PAIR_GEN,{128,0xffffffff,CKF_GENERATE_KEY_PAIR},PR_TRUE},
- {CKM_RSA_PKCS, {128,0xffffffff, CKF_DUZ_IT_ALL},PR_TRUE},
+ {CKM_RSA_PKCS_KEY_PAIR_GEN,{128,CK_MAX,CKF_GENERATE_KEY_PAIR},PR_TRUE},
+ {CKM_RSA_PKCS, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE},
#ifdef PK11_RSA9796_SUPPORTED
- {CKM_RSA_9796, {128,0xffffffff, CKF_DUZ_IT_ALL},PR_TRUE},
+ {CKM_RSA_9796, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE},
#endif
- {CKM_RSA_X_509, {128,0xffffffff, CKF_DUZ_IT_ALL},PR_TRUE},
+ {CKM_RSA_X_509, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE},
/* -------------- RSA Multipart Signing Operations -------------------- */
- {CKM_MD2_RSA_PKCS, {128,0xffffffff, CKF_SN_VR}, PR_TRUE},
- {CKM_MD5_RSA_PKCS, {128,0xffffffff, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA1_RSA_PKCS, {128,0xffffffff, CKF_SN_VR}, PR_TRUE},
+ {CKM_MD2_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE},
+ {CKM_MD5_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE},
+ {CKM_SHA1_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE},
/* ------------------------- DSA Operations --------------------------- */
{CKM_DSA_KEY_PAIR_GEN, {512, 1024, CKF_GENERATE_KEY_PAIR}, PR_TRUE},
{CKM_DSA, {512, 1024, CKF_SN_VR}, PR_TRUE},
@@ -330,7 +338,7 @@ static struct mechanismList mechanisms[] = {
{CKM_SHA_1_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_FALSE},
{CKM_TLS_PRF_GENERAL, {0, 512, CKF_SN_VR}, PR_FALSE},
/* ------------------------- CAST Operations --------------------------- */
-#ifdef PK11_CAST_SUPPORTED
+#ifdef NSS_SOFTOKEN_DOES_CAST
/* Cast operations are not supported ( yet? ) */
{CKM_CAST_KEY_GEN, {1, 8, CKF_GENERATE}, PR_FALSE},
{CKM_CAST_ECB, {1, 8, CKF_EN_DE_WR_UN}, PR_FALSE},
@@ -354,13 +362,13 @@ static struct mechanismList mechanisms[] = {
#if NSS_SOFTOKEN_DOES_RC5
/* ------------------------- RC5 Operations --------------------------- */
{CKM_RC5_KEY_GEN, {1, 32, CKF_GENERATE}, PR_FALSE},
- {CKM_RC5_ECB, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE},
+ {CKM_RC5_ECB, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE},
{CKM_RC5_CBC, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE},
{CKM_RC5_MAC, {1, 32, CKF_SN_VR}, PR_FALSE},
{CKM_RC5_MAC_GENERAL, {1, 32, CKF_SN_VR}, PR_FALSE},
{CKM_RC5_CBC_PAD, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE},
#endif
-#ifdef PK11_IDEA_SUPPORTED
+#ifdef NSS_SOFTOKEN_DOES_IDEA
/* ------------------------- IDEA Operations -------------------------- */
{CKM_IDEA_KEY_GEN, {16, 16, CKF_GENERATE}, PR_FALSE},
{CKM_IDEA_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_FALSE},
@@ -394,26 +402,19 @@ static struct mechanismList mechanisms[] = {
{CKM_PBE_MD5_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE},
/* ------------------ NETSCAPE PBE Key Derivations ------------------- */
{CKM_NETSCAPE_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE},
{CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC, {40,40, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC, {40,40, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4, {40,40, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4, {128,128, CKF_GENERATE}, PR_TRUE},
{CKM_PBE_SHA1_DES3_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE},
{CKM_PBE_SHA1_DES2_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE},
{CKM_PBE_SHA1_RC2_40_CBC, {40,40, CKF_GENERATE}, PR_TRUE},
{CKM_PBE_SHA1_RC2_128_CBC, {128,128, CKF_GENERATE}, PR_TRUE},
{CKM_PBE_SHA1_RC4_40, {40,40, CKF_GENERATE}, PR_TRUE},
{CKM_PBE_SHA1_RC4_128, {128,128, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE},
+ {CKM_PBA_SHA1_WITH_SHA1_HMAC, {20,20, CKF_GENERATE}, PR_TRUE},
+ {CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, {20,20, CKF_GENERATE}, PR_TRUE},
+ {CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE},
+ {CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE},
};
static CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]);
-/* load up our token database */
-static CK_RV pk11_importKeyDB(PK11Slot *slot);
-
static char *
pk11_setStringName(char *inString, char *buffer, int buffer_length) {
@@ -431,9 +432,7 @@ pk11_setStringName(char *inString, char *buffer, int buffer_length) {
* Configuration utils
*/
static CK_RV
-pk11_configure(char *man, char *libdes, char *tokdes, char *ptokdes,
- char *slotdes, char *pslotdes, char *fslotdes, char *fpslotdes,
- int minPwd, int pwRequired)
+pk11_configure(char *man, char *libdes)
{
/* make sure the internationalization was done correctly... */
@@ -445,32 +444,6 @@ pk11_configure(char *man, char *libdes, char *tokdes, char *ptokdes,
libraryDescription = pk11_setStringName(libdes,
libraryDescription_space, sizeof(libraryDescription_space));
}
- if (tokdes) {
- tokDescription = pk11_setStringName(tokdes,tokDescription_space,
- sizeof(tokDescription_space));
- }
- if (ptokdes) {
- privTokDescription = pk11_setStringName(ptokdes,
- privTokDescription_space, sizeof(privTokDescription_space));
- }
- if (slotdes) {
- slotDescription = pk11_setStringName(slotdes,slotDescription_space,
- sizeof(slotDescription_space));
- }
- if (pslotdes) {
- privSlotDescription = pk11_setStringName(pslotdes,
- privSlotDescription_space, sizeof(privSlotDescription_space));
- }
-
- if (minimumPinLen <= PK11_MAX_PIN) {
- minimumPinLen = minPwd;
- }
- if ((minimumPinLen == 0) && (pwRequired) &&
- (minimumPinLen <= PK11_MAX_PIN)) {
- minimumPinLen = 1;
- }
-
- PK11_ConfigureFIPS(fslotdes,fpslotdes);
return CKR_OK;
}
@@ -479,33 +452,20 @@ pk11_configure(char *man, char *libdes, char *tokdes, char *ptokdes,
* ******************** Password Utilities *******************************
*/
-/* Handle to give the password to the database. user arg should be a pointer
- * to the slot. */
-static SECItem *pk11_givePass(void *sp,SECKEYKeyDBHandle *handle)
-{
- PK11Slot *slot = (PK11Slot *)sp;
-
- if (slot->password == NULL) return NULL;
-
- return SECITEM_DupItem(slot->password);
-}
-
/*
* see if the key DB password is enabled
*/
PRBool
-pk11_hasNullPassword(SECItem **pwitem)
+pk11_hasNullPassword(NSSLOWKEYDBHandle *keydb,SECItem **pwitem)
{
PRBool pwenabled;
- SECKEYKeyDBHandle *keydb;
- keydb = SECKEY_GetDefaultKeyDB();
pwenabled = PR_FALSE;
*pwitem = NULL;
- if (SECKEY_HasKeyDBPassword (keydb) == SECSuccess) {
- *pwitem = SECKEY_HashPassword("", keydb->global_salt);
+ if (nsslowkey_HasKeyDBPassword (keydb) == SECSuccess) {
+ *pwitem = nsslowkey_HashPassword("", keydb->global_salt);
if ( *pwitem ) {
- if (SECKEY_CheckKeyDBPassword (keydb, *pwitem) == SECSuccess) {
+ if (nsslowkey_CheckKeyDBPassword (keydb, *pwitem) == SECSuccess) {
pwenabled = PR_TRUE;
} else {
SECITEM_ZfreeItem(*pwitem, PR_TRUE);
@@ -563,13 +523,12 @@ pk11_handleDataObject(PK11Session *session,PK11Object *object)
static CK_RV
pk11_handleCertObject(PK11Session *session,PK11Object *object)
{
- PK11Attribute *attribute;
CK_CERTIFICATE_TYPE type;
- SECItem derCert;
- char *label;
- CERTCertDBHandle *handle;
- CERTCertificate *cert;
+ PK11Attribute *attribute;
CK_RV crv;
+ PK11SessionObject *sessObject = pk11_narrowToSessionObject(object);
+
+ PORT_Assert(sessObject);
/* certificates must have a type */
if ( !pk11_hasAttribute(object,CKA_CERTIFICATE_TYPE) ) {
@@ -603,99 +562,393 @@ pk11_handleCertObject(PK11Session *session,PK11Object *object)
return CKR_TEMPLATE_INCOMPLETE;
}
- /*
- * now parse the certificate
- */
- handle = CERT_GetDefaultCertDB();
-
- /* get the nickname */
- label = pk11_getString(object,CKA_LABEL);
- object->label = label;
- if (label == NULL) {
- return CKR_HOST_MEMORY;
+ /* in PKCS #11, Issuer is a required field */
+ if ( !pk11_hasAttribute(object,CKA_ISSUER) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
}
-
- /* get the der cert */
- attribute = pk11_FindAttribute(object,CKA_VALUE);
- derCert.data = (unsigned char *)attribute->attrib.pValue;
- derCert.len = attribute->attrib.ulValueLen ;
-
- cert = CERT_NewTempCertificate(handle, &derCert, label, PR_FALSE, PR_TRUE);
- pk11_FreeAttribute(attribute);
- if (cert == NULL) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ /* in PKCS #11, Serial is a required field */
+ if ( !pk11_hasAttribute(object,CKA_SERIAL_NUMBER) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
}
/* add it to the object */
- object->objectInfo = cert;
- object->infoFree = (PK11Free) CERT_DestroyCertificate;
+ object->objectInfo = NULL;
+ object->infoFree = (PK11Free) NULL;
/* now just verify the required date fields */
crv = pk11_defaultAttribute(object, CKA_ID, NULL, 0);
if (crv != CKR_OK) { return crv; }
- crv = pk11_defaultAttribute(object,CKA_ISSUER,
- pk11_item_expand(&cert->derIssuer));
- if (crv != CKR_OK) { return crv; }
- crv = pk11_defaultAttribute(object,CKA_SERIAL_NUMBER,
- pk11_item_expand(&cert->serialNumber));
- if (crv != CKR_OK) { return crv; }
-
if (pk11_isTrue(object,CKA_TOKEN)) {
- SECCertUsage *certUsage = NULL;
- CERTCertTrust trust = { CERTDB_USER, CERTDB_USER, CERTDB_USER };
+ PK11Slot *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;
+ SECStatus rv;
+ PRBool inDB = PR_TRUE;
+
+ if (slot->certDB == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ /* get the der cert */
+ attribute = pk11_FindAttribute(object,CKA_VALUE);
+ PORT_Assert(attribute);
- attribute = pk11_FindAttribute(object,CKA_NETSCAPE_TRUST);
- if(attribute) {
- certUsage = (SECCertUsage*)attribute->attrib.pValue;
- pk11_FreeAttribute(attribute);
+ derCert.data = (unsigned char *)attribute->attrib.pValue;
+ derCert.len = attribute->attrib.ulValueLen ;
+
+ label = pk11_getString(object,CKA_LABEL);
+
+ cert = nsslowcert_FindCertByDERCert(slot->certDB, &derCert);
+ if (cert == NULL) {
+ cert = nsslowcert_DecodeDERCertificate(&derCert,PR_FALSE,label);
+ inDB = PR_FALSE;
+ }
+ if (cert == NULL) {
+ if (label) PORT_Free(label);
+ pk11_FreeAttribute(attribute);
+ return CKR_ATTRIBUTE_VALUE_INVALID;
}
- /* Temporary for PKCS 12 */
- if(cert->nickname == NULL) {
- /* use the arena so we at least don't leak memory */
- cert->nickname = PORT_ArenaStrdup(cert->arena, label);
+ if (slot->keyDB && nsslowkey_KeyForCertExists(slot->keyDB,cert)) {
+ trust = &userTrust;
+ }
+ if (!inDB) {
+ if (!trust) trust = &defTrust;
+ rv = nsslowcert_AddPermCert(slot->certDB, cert, label, trust);
+ } else {
+ rv = trust ? nsslowcert_ChangeCertTrust(slot->certDB,cert,trust) :
+ SECSuccess;
}
- /* only add certs that have a private key */
- if (SECKEY_KeyForCertExists(SECKEY_GetDefaultKeyDB(),cert)
- != SECSuccess) {
+ if (label) PORT_Free(label);
+ pk11_FreeAttribute(attribute);
+ if (rv != SECSuccess) {
+ nsslowcert_DestroyCertificate(cert);
+ return CKR_DEVICE_ERROR;
+ }
+ object->handle=pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_CERT);
+ nsslowcert_DestroyCertificate(cert);
+ }
+
+ return CKR_OK;
+}
+unsigned int
+pk11_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
+pk11_handleTrustObject(PK11Session *session,PK11Object *object)
+{
+ NSSLOWCERTIssuerAndSN issuerSN;
+
+ /* we can't store any certs private */
+ if (pk11_isTrue(object,CKA_PRIVATE)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ /* certificates must have a type */
+ if ( !pk11_hasAttribute(object,CKA_ISSUER) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if ( !pk11_hasAttribute(object,CKA_SERIAL_NUMBER) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if ( !pk11_hasAttribute(object,CKA_CERT_SHA1_HASH) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if ( !pk11_hasAttribute(object,CKA_CERT_MD5_HASH) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ if (pk11_isTrue(object,CKA_TOKEN)) {
+ PK11Slot *slot = session->slot;
+ PK11Attribute *issuer = NULL;
+ PK11Attribute *serial = NULL;
+ NSSLOWCERTCertificate *cert = NULL;
+ PK11Attribute *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;
+ NSSLOWCERTCertTrust dbTrust;
+ SECStatus rv;
+
+
+ if (slot->certDB == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ issuer = pk11_FindAttribute(object,CKA_ISSUER);
+ PORT_Assert(issuer);
+ issuerSN.derIssuer.data = (unsigned char *)issuer->attrib.pValue;
+ issuerSN.derIssuer.len = issuer->attrib.ulValueLen ;
+
+ serial = pk11_FindAttribute(object,CKA_SERIAL_NUMBER);
+ PORT_Assert(serial);
+ issuerSN.serialNumber.data = (unsigned char *)serial->attrib.pValue;
+ issuerSN.serialNumber.len = serial->attrib.ulValueLen ;
+
+ cert = nsslowcert_FindCertByIssuerAndSN(slot->certDB,&issuerSN);
+ pk11_FreeAttribute(serial);
+ pk11_FreeAttribute(issuer);
+
+ if (cert == NULL) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
- if (!cert->isperm) {
- if (CERT_AddTempCertToPerm(cert, label, &trust) != SECSuccess) {
- return CKR_HOST_MEMORY;
+
+ trust = pk11_FindAttribute(object,CKA_TRUST_SERVER_AUTH);
+ if (trust) {
+ if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) {
+ PORT_Memcpy(&sslTrust,trust->attrib.pValue, sizeof(sslTrust));
+ }
+ pk11_FreeAttribute(trust);
+ }
+ trust = pk11_FindAttribute(object,CKA_TRUST_CLIENT_AUTH);
+ if (trust) {
+ if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) {
+ PORT_Memcpy(&clientTrust,trust->attrib.pValue,
+ sizeof(clientTrust));
+ }
+ pk11_FreeAttribute(trust);
+ }
+ trust = pk11_FindAttribute(object,CKA_TRUST_EMAIL_PROTECTION);
+ if (trust) {
+ if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) {
+ PORT_Memcpy(&emailTrust,trust->attrib.pValue,
+ sizeof(emailTrust));
}
- } else {
- CERT_ChangeCertTrust(cert->dbhandle,cert,&trust);
+ pk11_FreeAttribute(trust);
}
- if(certUsage) {
- if(CERT_ChangeCertTrustByUsage(CERT_GetDefaultCertDB(),
- cert, *certUsage) != SECSuccess) {
- return CKR_HOST_MEMORY;
+ trust = pk11_FindAttribute(object,CKA_TRUST_CODE_SIGNING);
+ if (trust) {
+ if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) {
+ PORT_Memcpy(&signTrust,trust->attrib.pValue,
+ sizeof(signTrust));
}
+ pk11_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 = pk11_MapTrust(sslTrust,PR_FALSE);
+ dbTrust.sslFlags |= pk11_MapTrust(clientTrust,PR_TRUE);
+ dbTrust.emailFlags = pk11_MapTrust(emailTrust,PR_FALSE);
+ dbTrust.objectSigningFlags = pk11_MapTrust(signTrust,PR_FALSE);
+
+ rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&dbTrust);
+ object->handle=pk11_mkHandle(slot,&cert->certKey,PK11_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
+pk11_handleSMimeObject(PK11Session *session,PK11Object *object)
+{
+
+ /* we can't store any certs private */
+ if (pk11_isTrue(object,CKA_PRIVATE)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ /* certificates must have a type */
+ if ( !pk11_hasAttribute(object,CKA_SUBJECT) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if ( !pk11_hasAttribute(object,CKA_NETSCAPE_SMIME_TIMESTAMP) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if ( !pk11_hasAttribute(object,CKA_NETSCAPE_EMAIL) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if ( !pk11_hasAttribute(object,CKA_VALUE) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ if (pk11_isTrue(object,CKA_TOKEN)) {
+ PK11Slot *slot = session->slot;
+ SECItem derSubj,rawProfile,rawTime,emailKey;
+ char *email = NULL;
+ PK11Attribute *subject,*profile,*time;
+ SECStatus rv;
+
+ PORT_Assert(slot);
+ if (slot->certDB == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ /* lookup SUBJECT */
+ subject = pk11_FindAttribute(object,CKA_SUBJECT);
+ PORT_Assert(subject);
+ derSubj.data = (unsigned char *)subject->attrib.pValue;
+ derSubj.len = subject->attrib.ulValueLen ;
+
+ /* lookup VALUE */
+ profile = pk11_FindAttribute(object,CKA_VALUE);
+ PORT_Assert(profile);
+ rawProfile.data = (unsigned char *)profile->attrib.pValue;
+ rawProfile.len = profile->attrib.ulValueLen ;
+
+ /* lookup Time */
+ time = pk11_FindAttribute(object,CKA_NETSCAPE_SMIME_TIMESTAMP);
+ PORT_Assert(time);
+ rawTime.data = (unsigned char *)time->attrib.pValue;
+ rawTime.len = time->attrib.ulValueLen ;
+
+
+ email = pk11_getString(object,CKA_NETSCAPE_EMAIL);
+
+ /* Store CRL by SUBJECT */
+ rv = nsslowcert_SaveSMimeProfile(slot->certDB, email, &derSubj,
+ &rawProfile,&rawTime);
+
+ pk11_FreeAttribute(profile);
+ pk11_FreeAttribute(subject);
+ pk11_FreeAttribute(time);
+ if (rv != SECSuccess) {
+ PORT_Free(email);
+ return CKR_DEVICE_ERROR;
}
- object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT);
- object->inDB = PR_TRUE;
+ emailKey.data = (unsigned char *)email;
+ emailKey.len = PORT_Strlen(email)+1;
+
+ object->handle = pk11_mkHandle(slot, &emailKey, PK11_TOKEN_TYPE_SMIME);
+ PORT_Free(email);
+ }
+
+ return CKR_OK;
+}
+
+/*
+ * check the consistancy and initialize a Trust Object
+ */
+static CK_RV
+pk11_handleCrlObject(PK11Session *session,PK11Object *object)
+{
+
+ /* we can't store any certs private */
+ if (pk11_isTrue(object,CKA_PRIVATE)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ /* certificates must have a type */
+ if ( !pk11_hasAttribute(object,CKA_SUBJECT) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if ( !pk11_hasAttribute(object,CKA_VALUE) ) {
+ return CKR_TEMPLATE_INCOMPLETE;
}
- /* label has been adopted by object->label */
- /*PORT_Free(label); */
+ if (pk11_isTrue(object,CKA_TOKEN)) {
+ PK11Slot *slot = session->slot;
+ PRBool isKRL = PR_FALSE;
+ SECItem derSubj,derCrl;
+ char *url = NULL;
+ PK11Attribute *subject,*crl;
+ SECStatus rv;
+
+ PORT_Assert(slot);
+ if (slot->certDB == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ /* lookup SUBJECT */
+ subject = pk11_FindAttribute(object,CKA_SUBJECT);
+ PORT_Assert(subject);
+ derSubj.data = (unsigned char *)subject->attrib.pValue;
+ derSubj.len = subject->attrib.ulValueLen ;
+
+ /* lookup VALUE */
+ crl = pk11_FindAttribute(object,CKA_VALUE);
+ PORT_Assert(crl);
+ derCrl.data = (unsigned char *)crl->attrib.pValue;
+ derCrl.len = crl->attrib.ulValueLen ;
+
+
+ url = pk11_getString(object,CKA_NETSCAPE_URL);
+ isKRL = pk11_isTrue(object,CKA_NETSCAPE_KRL);
+
+ /* Store CRL by SUBJECT */
+ rv = nsslowcert_AddCrl(slot->certDB, &derCrl, &derSubj, url, isKRL);
+
+ if (url) {
+ PORT_Free(url);
+ }
+ pk11_FreeAttribute(crl);
+ if (rv != SECSuccess) {
+ pk11_FreeAttribute(subject);
+ return CKR_DEVICE_ERROR;
+ }
+
+ object->handle = pk11_mkHandle(slot,&derSubj,
+ isKRL ? PK11_TOKEN_KRL_HANDLE : PK11_TOKEN_TYPE_CRL);
+ pk11_FreeAttribute(subject);
+ }
return CKR_OK;
}
-SECKEYLowPublicKey * pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key);
+NSSLOWKEYPublicKey * pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key);
/*
* check the consistancy and initialize a Public Key Object
*/
static CK_RV
-pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type)
+pk11_handlePublicKeyObject(PK11Session *session, PK11Object *object,
+ CK_KEY_TYPE key_type)
{
- CK_BBOOL cktrue = CK_TRUE;
CK_BBOOL encrypt = CK_TRUE;
CK_BBOOL recover = CK_TRUE;
CK_BBOOL wrap = CK_TRUE;
+ CK_BBOOL derive = CK_FALSE;
+ CK_BBOOL verify = CK_TRUE;
+ CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE;
CK_RV crv;
switch (key_type) {
@@ -706,6 +959,7 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type)
if ( !pk11_hasAttribute(object, CKA_PUBLIC_EXPONENT)) {
return CKR_TEMPLATE_INCOMPLETE;
}
+ pubKeyAttr = CKA_MODULUS;
break;
case CKK_DSA:
if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) {
@@ -721,6 +975,10 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type)
if ( !pk11_hasAttribute(object, CKA_VALUE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
+ if (key_type == CKK_DH) {
+ verify = CK_FALSE;
+ derive = CK_TRUE;
+ }
encrypt = CK_FALSE;
recover = CK_FALSE;
wrap = CK_FALSE;
@@ -734,176 +992,55 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type)
if (crv != CKR_OK) return crv;
crv = pk11_defaultAttribute(object,CKA_ENCRYPT,&encrypt,sizeof(CK_BBOOL));
if (crv != CKR_OK) return crv;
- crv = pk11_defaultAttribute(object,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
+ crv = pk11_defaultAttribute(object,CKA_VERIFY,&verify,sizeof(CK_BBOOL));
if (crv != CKR_OK) return crv;
crv = pk11_defaultAttribute(object,CKA_VERIFY_RECOVER,
&recover,sizeof(CK_BBOOL));
if (crv != CKR_OK) return crv;
crv = pk11_defaultAttribute(object,CKA_WRAP,&wrap,sizeof(CK_BBOOL));
if (crv != CKR_OK) return crv;
+ crv = pk11_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL));
+ if (crv != CKR_OK) return crv;
object->objectInfo = pk11_GetPubKey(object,key_type);
- object->infoFree = (PK11Free) SECKEY_LowDestroyPublicKey;
+ object->infoFree = (PK11Free) nsslowkey_DestroyPublicKey;
if (pk11_isTrue(object,CKA_TOKEN)) {
- object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PUB);
- }
-
- return CKR_OK;
-}
-/* pk11_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 *
-pk11_GetPubItem(SECKEYPublicKey *pubKey) {
- SECItem *pubItem = NULL;
- /* get value to compare from the cert's public key */
- switch ( pubKey->keyType ) {
- case rsaKey:
- pubItem = &pubKey->u.rsa.modulus;
- break;
- case dsaKey:
- pubItem = &pubKey->u.dsa.publicValue;
- break;
- default:
- break;
- }
- return pubItem;
-}
-
-/* convert a high key type to a low key type. This will go away when
- * the last SECKEYPublicKey structs go away.
- */
-LowKeyType
-seckeyLow_KeyType(KeyType keyType)
-{
- switch (keyType) {
- case rsaKey:
- return lowRSAKey;
- case dsaKey:
- return lowDSAKey;
- case dhKey:
- return lowDHKey;
- default:
- break;
- }
- return lowNullKey;
-}
-
-typedef struct {
- CERTCertificate *cert;
- SECItem *pubKey;
-} find_cert_callback_arg;
-
-static SECStatus
-find_cert_by_pub_key(CERTCertificate *cert, SECItem *k, void *arg)
-{
- find_cert_callback_arg *cbarg;
- SECKEYPublicKey *pubKey = NULL;
- SECItem *pubItem;
-
- if((cert == NULL) || (arg == NULL)) {
- return SECFailure;
- }
-
- /* if this cert doesn't look like a user cert, we aren't interested */
- if (!((cert->isperm) && (cert->trust) &&
- (( cert->trust->sslFlags & CERTDB_USER ) ||
- ( cert->trust->emailFlags & CERTDB_USER ) ||
- ( cert->trust->objectSigningFlags & CERTDB_USER )) &&
- ( cert->nickname != NULL ) ) ) {
- goto done;
- }
-
- /* get cert's public key */
- pubKey = CERT_ExtractPublicKey(cert);
- if ( pubKey == NULL ) {
- goto done;
- }
- /* pk11_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.
- */
- pubItem = pk11_GetPubItem(pubKey);
- if (pubItem == NULL) goto done;
-
- cbarg = (find_cert_callback_arg *)arg;
-
- if(SECITEM_CompareItem(pubItem, cbarg->pubKey) == SECEqual) {
- cbarg->cert = CERT_DupCertificate(cert);
- return SECFailure;
- }
-
-done:
- if ( pubKey ) {
- SECKEY_DestroyPublicKey(pubKey);
- }
+ PK11Slot *slot = session->slot;
+ NSSLOWKEYPrivateKey *priv;
+ SECItem pubKey;
- return (SECSuccess);
-}
+ crv = pk11_Attribute2SSecItem(NULL,&pubKey,object,pubKeyAttr);
+ if (crv != CKR_OK) return crv;
-static PK11Object *pk11_importCertificate(PK11Slot *slot,CERTCertificate *cert,
- unsigned char *data, unsigned int size, PRBool needCert);
-/*
- * find a cert associated with the key and load it.
- */
-static SECStatus
-reload_existing_certificate(PK11Object *privKeyObject,SECItem *pubKey)
-{
- find_cert_callback_arg cbarg;
- SECItem nickName;
- CERTCertificate *cert = NULL;
- CK_RV crv;
- SECStatus rv;
-
- cbarg.pubKey = pubKey;
- cbarg.cert = NULL;
- SEC_TraversePermCerts(CERT_GetDefaultCertDB(),
- find_cert_by_pub_key, (void *)&cbarg);
- if (cbarg.cert != NULL) {
- CERTCertificate *cert = NULL;
- /* can anyone tell me why this is call is necessary? rjr */
- cert = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(),
- &cbarg.cert->derCert);
-
- /* does the certificate in the database have a
- * nickname? if not, it probably was inserted
- * through SMIME and a nickname needs to be
- * set.
- */
- if (cert && !cert->nickname) {
- crv=pk11_Attribute2SecItem(NULL,&nickName,privKeyObject,CKA_LABEL);
- if (crv != CKR_OK) {
- goto loser;
- }
- rv = CERT_AddPermNickname(cert, (char *)nickName.data);
- SECITEM_ZfreeItem(&nickName, PR_FALSE);
- if (rv != SECSuccess) {
- goto loser;
- }
+ PORT_Assert(pubKey.data);
+ if (slot->keyDB == NULL) {
+ PORT_Free(pubKey.data);
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ /* make sure the associated private key already exists */
+ /* only works if we are logged in */
+ priv = nsslowkey_FindKeyByPublicKey(slot->keyDB, &pubKey,
+ slot->password);
+ if (priv == NULL) {
+ PORT_Free(pubKey.data);
+ return CKR_ATTRIBUTE_VALUE_INVALID;
}
+ nsslowkey_DestroyPrivateKey(priv);
- /* associate the certificate with the key */
- pk11_importCertificate(privKeyObject->slot, cert, pubKey->data,
- pubKey->len, PR_FALSE);
+ object->handle = pk11_mkHandle(slot, &pubKey, PK11_TOKEN_TYPE_PUB);
+ PORT_Free(pubKey.data);
}
- return SECSuccess;
-loser:
- if (cert) CERT_DestroyCertificate(cert);
- if (cbarg.cert) CERT_DestroyCertificate(cbarg.cert);
- return SECFailure;
+ return CKR_OK;
}
-static SECKEYLowPrivateKey * pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key);
+static NSSLOWKEYPrivateKey * pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key);
/*
* check the consistancy and initialize a Private Key Object
*/
static CK_RV
-pk11_handlePrivateKeyObject(PK11Object *object,CK_KEY_TYPE key_type)
+pk11_handlePrivateKeyObject(PK11Session *session,PK11Object *object,CK_KEY_TYPE key_type)
{
CK_BBOOL cktrue = CK_TRUE;
CK_BBOOL encrypt = CK_TRUE;
@@ -996,60 +1133,59 @@ pk11_handlePrivateKeyObject(PK11Object *object,CK_KEY_TYPE key_type)
if (crv != CKR_OK) return crv;
if (pk11_isTrue(object,CKA_TOKEN)) {
- SECKEYLowPrivateKey *privKey;
+ PK11Slot *slot = session->slot;
+ NSSLOWKEYPrivateKey *privKey;
char *label;
SECStatus rv = SECSuccess;
SECItem pubKey;
+ if (slot->keyDB == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+
privKey=pk11_mkPrivKey(object,key_type);
if (privKey == NULL) return CKR_HOST_MEMORY;
- label = object->label = pk11_getString(object,CKA_LABEL);
+ label = pk11_getString(object,CKA_LABEL);
crv = pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
- if (crv == CKR_OK) {
- rv = SECKEY_StoreKeyByPublicKey(SECKEY_GetDefaultKeyDB(),
- privKey, &pubKey, label,
- (SECKEYLowGetPasswordKey) pk11_givePass, object->slot);
-
- /* check for the existance of an existing certificate and activate
- * it if necessary */
- if (rv == SECSuccess) {
- reload_existing_certificate(object,&pubKey);
- }
-
- if (pubKey.data) PORT_Free(pubKey.data);
- } else {
- rv = SECFailure;
+ if (crv != CKR_OK) {
+ if (label) PORT_Free(label);
+ nsslowkey_DestroyPrivateKey(privKey);
+ return CKR_TEMPLATE_INCOMPLETE;
}
+ rv = nsslowkey_StoreKeyByPublicKey(object->slot->keyDB,
+ privKey, &pubKey, label, object->slot->password);
- SECKEY_LowDestroyPrivateKey(privKey);
+ if (label) PORT_Free(label);
+ object->handle = pk11_mkHandle(slot,&pubKey,PK11_TOKEN_TYPE_PRIV);
+ if (pubKey.data) PORT_Free(pubKey.data);
+ nsslowkey_DestroyPrivateKey(privKey);
if (rv != SECSuccess) return CKR_DEVICE_ERROR;
- object->inDB = PR_TRUE;
- object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
} else {
object->objectInfo = pk11_mkPrivKey(object,key_type);
if (object->objectInfo == NULL) return CKR_HOST_MEMORY;
- object->infoFree = (PK11Free) SECKEY_LowDestroyPrivateKey;
- }
- /* now NULL out the sensitive attributes */
- if (pk11_isTrue(object,CKA_SENSITIVE)) {
- pk11_nullAttribute(object,CKA_PRIVATE_EXPONENT);
- pk11_nullAttribute(object,CKA_PRIME_1);
- pk11_nullAttribute(object,CKA_PRIME_2);
- pk11_nullAttribute(object,CKA_EXPONENT_1);
- pk11_nullAttribute(object,CKA_EXPONENT_2);
- pk11_nullAttribute(object,CKA_COEFFICIENT);
+ object->infoFree = (PK11Free) nsslowkey_DestroyPrivateKey;
+ /* now NULL out the sensitive attributes */
+ if (pk11_isTrue(object,CKA_SENSITIVE)) {
+ pk11_nullAttribute(object,CKA_PRIVATE_EXPONENT);
+ pk11_nullAttribute(object,CKA_PRIME_1);
+ pk11_nullAttribute(object,CKA_PRIME_2);
+ pk11_nullAttribute(object,CKA_EXPONENT_1);
+ pk11_nullAttribute(object,CKA_EXPONENT_2);
+ pk11_nullAttribute(object,CKA_COEFFICIENT);
+ }
}
return CKR_OK;
}
/* forward delcare the DES formating function for handleSecretKey */
void pk11_FormatDESKey(unsigned char *key, int length);
-static SECKEYLowPrivateKey *pk11_mkSecretKeyRep(PK11Object *object);
+static NSSLOWKEYPrivateKey *pk11_mkSecretKeyRep(PK11Object *object);
/* Validate secret key data, and set defaults */
static CK_RV
-validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS)
+validateSecretKey(PK11Session *session, PK11Object *object,
+ CK_KEY_TYPE key_type, PRBool isFIPS)
{
CK_RV crv;
CK_BBOOL cktrue = CK_TRUE;
@@ -1095,9 +1231,14 @@ validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS)
#if NSS_SOFTOKEN_DOES_RC5
case CKK_RC5:
#endif
+#ifdef NSS_SOFTOKEN_DOES_CAST
case CKK_CAST:
case CKK_CAST3:
case CKK_CAST5:
+#endif
+#if NSS_SOFTOKEN_DOES_IDEA
+ case CKK_IDEA:
+#endif
attribute = pk11_FindAttribute(object,CKA_VALUE);
/* shouldn't happen */
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
@@ -1127,45 +1268,51 @@ validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS)
* check the consistancy and initialize a Secret Key Object
*/
static CK_RV
-pk11_handleSecretKeyObject(PK11Object *object,CK_KEY_TYPE key_type,
- PRBool isFIPS)
+pk11_handleSecretKeyObject(PK11Session *session,PK11Object *object,
+ CK_KEY_TYPE key_type, PRBool isFIPS)
{
CK_RV crv;
- SECKEYLowPrivateKey *privKey = NULL;
+ NSSLOWKEYPrivateKey *privKey = NULL;
SECItem pubKey;
+ char *label = NULL;
pubKey.data = 0;
/* First validate and set defaults */
- crv = validateSecretKey(object, key_type, isFIPS);
+ crv = validateSecretKey(session, object, key_type, isFIPS);
if (crv != CKR_OK) goto loser;
/* If the object is a TOKEN object, store in the database */
if (pk11_isTrue(object,CKA_TOKEN)) {
- char *label;
+ PK11Slot *slot = session->slot;
SECStatus rv = SECSuccess;
+ if (slot->keyDB == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
privKey=pk11_mkSecretKeyRep(object);
if (privKey == NULL) return CKR_HOST_MEMORY;
- label = object->label = pk11_getString(object,CKA_LABEL);
+ label = pk11_getString(object,CKA_LABEL);
- crv = pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_ID); /* Should this be ID? */
+ crv = pk11_Attribute2SecItem(NULL, &pubKey, object, CKA_ID);
+ /* Should this be ID? */
if (crv != CKR_OK) goto loser;
- rv = SECKEY_StoreKeyByPublicKey(SECKEY_GetDefaultKeyDB(),
- privKey, &pubKey, label,
- (SECKEYLowGetPasswordKey) pk11_givePass, object->slot);
+ PORT_Assert(slot->keyDB);
+ rv = nsslowkey_StoreKeyByPublicKey(slot->keyDB,
+ privKey, &pubKey, label, slot->password);
if (rv != SECSuccess) {
crv = CKR_DEVICE_ERROR;
+ goto loser;
}
- object->inDB = PR_TRUE;
- object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
+ object->handle = pk11_mkHandle(slot,&pubKey,PK11_TOKEN_TYPE_KEY);
}
loser:
- if (privKey) SECKEY_LowDestroyPrivateKey(privKey);
+ if (label) PORT_Free(label);
+ if (privKey) nsslowkey_DestroyPrivateKey(privKey);
if (pubKey.data) PORT_Free(pubKey.data);
return crv;
@@ -1207,12 +1354,12 @@ pk11_handleKeyObject(PK11Session *session, PK11Object *object)
switch (object->objclass) {
case CKO_PUBLIC_KEY:
- return pk11_handlePublicKeyObject(object,key_type);
+ return pk11_handlePublicKeyObject(session,object,key_type);
case CKO_PRIVATE_KEY:
- return pk11_handlePrivateKeyObject(object,key_type);
+ return pk11_handlePrivateKeyObject(session,object,key_type);
case CKO_SECRET_KEY:
/* make sure the required fields exist */
- return pk11_handleSecretKeyObject(object,key_type,
+ return pk11_handleSecretKeyObject(session,object,key_type,
(PRBool)(session->slot->slotID == FIPS_SLOT_ID));
default:
break;
@@ -1223,8 +1370,8 @@ pk11_handleKeyObject(PK11Session *session, PK11Object *object)
/*
* Handle Object does all the object consistancy checks, automatic attribute
* generation, attribute defaulting, etc. If handleObject succeeds, the object
- * will be assigned an object handle, and the object pointer will be adopted
- * by the session. (that is don't free object).
+ * will be assigned an object handle, and the object installed in the session
+ * or stored in the DB.
*/
CK_RV
pk11_handleObject(PK11Object *object, PK11Session *session)
@@ -1257,17 +1404,6 @@ pk11_handleObject(PK11Object *object, PK11Session *session)
(pk11_isTrue(object,CKA_TOKEN))) {
return CKR_SESSION_READ_ONLY;
}
-
- if (pk11_isTrue(object, CKA_TOKEN)) {
- if (slot->DB_loaded == PR_FALSE) {
- /* we are creating a token object, make sure we load the database
- * first so we don't get duplicates....
- * ... NOTE: This assumes we are logged in as well!
- */
- pk11_importKeyDB(slot);
- slot->DB_loaded = PR_TRUE;
- }
- }
/* PKCS #11 object ID's are unique for all objects on a
* token */
@@ -1288,9 +1424,19 @@ pk11_handleObject(PK11Object *object, PK11Session *session)
switch (object->objclass) {
case CKO_DATA:
crv = pk11_handleDataObject(session,object);
+ break;
case CKO_CERTIFICATE:
crv = pk11_handleCertObject(session,object);
break;
+ case CKO_NETSCAPE_TRUST:
+ crv = pk11_handleTrustObject(session,object);
+ break;
+ case CKO_NETSCAPE_CRL:
+ crv = pk11_handleCrlObject(session,object);
+ break;
+ case CKO_NETSCAPE_SMIME:
+ crv = pk11_handleSMimeObject(session,object);
+ break;
case CKO_PRIVATE_KEY:
case CKO_PUBLIC_KEY:
case CKO_SECRET_KEY:
@@ -1308,632 +1454,23 @@ pk11_handleObject(PK11Object *object, PK11Session *session)
}
/* now link the object into the slot and session structures */
- object->slot = slot;
- pk11_AddObject(session,object);
-
- return CKR_OK;
-}
-
-/* import a private key as an object. We don't call handle object.
- * because we the private key came from the key DB and we don't want to
- * write back out again */
-static PK11Object *
-pk11_importPrivateKey(PK11Slot *slot,SECKEYLowPrivateKey *lowPriv,
- SECItem *dbKey)
-{
- PK11Object *privateKey;
- CK_KEY_TYPE key_type;
- CK_BBOOL cktrue = CK_TRUE;
- CK_BBOOL ckfalse = CK_FALSE;
- CK_BBOOL sign = CK_TRUE;
- CK_BBOOL recover = CK_TRUE;
- CK_BBOOL decrypt = CK_TRUE;
- CK_BBOOL derive = CK_FALSE;
- CK_RV crv = CKR_OK;
- CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
- unsigned char cka_id[SHA1_LENGTH];
-
- /*
- * now lets create an object to hang the attributes off of
- */
- privateKey = pk11_NewObject(slot); /* fill in the handle later */
- if (privateKey == NULL) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
-
- /* Netscape Private Attribute for dealing with database storeage */
- if (pk11_AddAttributeType(privateKey, CKA_NETSCAPE_DB,
- pk11_item_expand(dbKey)) ) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
-
- /* now force the CKA_ID */
- SHA1_HashBuf(cka_id, (unsigned char *)dbKey->data, (uint32)dbKey->len);
- if (pk11_AddAttributeType(privateKey, CKA_ID, cka_id, sizeof(cka_id))) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
-
-
- /* Fill in the common Default values */
- if (pk11_AddAttributeType(privateKey,CKA_CLASS, &privClass,
- sizeof(CK_OBJECT_CLASS)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_TOKEN, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_PRIVATE, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_MODIFIABLE, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_LABEL, NULL, 0) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_START_DATE, NULL, 0) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_END_DATE, NULL, 0) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_DERIVE, &ckfalse,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- /* local: well we really don't know for sure... it could have been an
- * imported key, but it's not a useful attribute anyway. */
- if (pk11_AddAttributeType(privateKey,CKA_LOCAL, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_SUBJECT, NULL, 0) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_SENSITIVE, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_EXTRACTABLE, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- /* is this really true? Maybe we should just say false here? */
- if (pk11_AddAttributeType(privateKey,CKA_ALWAYS_SENSITIVE, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_NEVER_EXTRACTABLE, &ckfalse,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
-
- /* Now Set up the parameters to generate the key (based on mechanism) */
- /* NOTE: for safety sake we *DO NOT* remember critical attributes. PKCS #11
- * will look them up again from the database when it needs them.
- */
- switch (lowPriv->keyType) {
- case lowRSAKey:
- /* format the keys */
- key_type = CKK_RSA;
- sign = CK_TRUE;
- recover = CK_TRUE;
- decrypt = CK_TRUE;
- derive = CK_FALSE;
- /* now fill in the RSA dependent parameters in the public key */
- crv = pk11_AddAttributeType(privateKey,CKA_MODULUS,
- pk11_item_expand(&lowPriv->u.rsa.modulus));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,NULL,0);
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT,
- pk11_item_expand(&lowPriv->u.rsa.publicExponent));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_PRIME_1,NULL,0);
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_PRIME_2,NULL,0);
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_1,NULL,0);
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_2,NULL,0);
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_COEFFICIENT,NULL,0);
- break;
- case lowDSAKey:
- key_type = CKK_DSA;
- sign = CK_TRUE;
- recover = CK_FALSE;
- decrypt = CK_FALSE;
- derive = CK_FALSE;
- crv = pk11_AddAttributeType(privateKey,CKA_PRIME,
- pk11_item_expand(&lowPriv->u.dsa.params.prime));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_SUBPRIME,
- pk11_item_expand(&lowPriv->u.dsa.params.subPrime));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_BASE,
- pk11_item_expand(&lowPriv->u.dsa.params.base));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_VALUE,NULL,0);
- if (crv != CKR_OK) break;
- break;
- case lowDHKey:
- key_type = CKK_DH;
- sign = CK_FALSE;
- decrypt = CK_FALSE;
- recover = CK_FALSE;
- derive = CK_TRUE;
- crv = CKR_MECHANISM_INVALID;
- break;
- default:
- crv = CKR_MECHANISM_INVALID;
- }
-
- if (crv != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
-
-
- if (pk11_AddAttributeType(privateKey,CKA_SIGN, &sign,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_SIGN_RECOVER, &recover,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_DECRYPT, &decrypt,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_UNWRAP, &decrypt,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_DERIVE, &derive,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- if (pk11_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type,
- sizeof(CK_KEY_TYPE)) != CKR_OK) {
- pk11_FreeObject(privateKey);
- return NULL;
- }
- PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
- privateKey->handle = slot->tokenIDCount++;
- privateKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
- PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
- privateKey->objclass = privClass;
- privateKey->slot = slot;
- privateKey->inDB = PR_TRUE;
-
- return privateKey;
-}
-
-/* import a private key or cert as a public key object.*/
-static PK11Object *
-pk11_importPublicKey(PK11Slot *slot,
- SECKEYLowPrivateKey *lowPriv, CERTCertificate *cert, SECItem *dbKey)
-{
- PK11Object *publicKey = NULL;
- CK_KEY_TYPE key_type;
- CK_BBOOL cktrue = CK_TRUE;
- CK_BBOOL ckfalse = CK_FALSE;
- CK_BBOOL verify = CK_TRUE;
- CK_BBOOL recover = CK_TRUE;
- CK_BBOOL encrypt = CK_TRUE;
- CK_BBOOL derive = CK_FALSE;
- CK_RV crv = CKR_OK;
- CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
- unsigned char cka_id[SHA1_LENGTH];
- LowKeyType keyType = nullKey;
- SECKEYPublicKey *pubKey = NULL;
- CK_ATTRIBUTE theTemplate[2];
- PK11ObjectListElement *objectList = NULL;
-
- if (lowPriv == NULL) {
- pubKey = CERT_ExtractPublicKey(cert);
- if (pubKey == NULL) {
- goto failed;
- }
- /* pk11_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.
- */
- dbKey = pk11_GetPubItem(pubKey);
- if (dbKey == NULL) {
- goto failed;
- }
- }
- SHA1_HashBuf(cka_id, (unsigned char *)dbKey->data, (uint32)dbKey->len);
- theTemplate[0].type = CKA_ID;
- theTemplate[0].pValue = cka_id;
- theTemplate[0].ulValueLen = sizeof(cka_id);
- theTemplate[1].type = CKA_CLASS;
- theTemplate[1].pValue = &pubClass;
- theTemplate[1].ulValueLen = sizeof(CK_OBJECT_CLASS);
- crv = pk11_searchObjectList(&objectList,slot->tokObjects,
- slot->objectLock, theTemplate, 2, slot->isLoggedIn);
- if ((crv == CKR_OK) && (objectList != NULL)) {
- goto failed;
- }
- /*
- * now lets create an object to hang the attributes off of
- */
- publicKey = pk11_NewObject(slot); /* fill in the handle later */
- if (publicKey == NULL) {
- goto failed;
- }
-
- /* now force the CKA_ID */
- if (pk11_AddAttributeType(publicKey, CKA_ID, cka_id, sizeof(cka_id))) {
- goto failed;
- }
-
- /* Fill in the common Default values */
- if (pk11_AddAttributeType(publicKey,CKA_CLASS,&pubClass,
- sizeof(CK_OBJECT_CLASS)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_TOKEN, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_PRIVATE, &ckfalse,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_MODIFIABLE, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_LABEL, NULL, 0) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_START_DATE, NULL, 0) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_END_DATE, NULL, 0) != CKR_OK) {
- goto failed;
- }
- /* local: well we really don't know for sure... it could have been an
- * imported key, but it's not a useful attribute anyway. */
- if (pk11_AddAttributeType(publicKey,CKA_LOCAL, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_SUBJECT, NULL, 0) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_SENSITIVE, &ckfalse,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_EXTRACTABLE, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_ALWAYS_SENSITIVE, &ckfalse,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_NEVER_EXTRACTABLE, &ckfalse,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
-
- /* Now Set up the parameters to generate the key (based on mechanism) */
- if (lowPriv == NULL) {
-
- keyType = seckeyLow_KeyType(pubKey->keyType);
- } else {
- keyType = lowPriv->keyType;
- }
-
-
- switch (keyType) {
- case lowRSAKey:
- /* format the keys */
- key_type = CKK_RSA;
- verify = CK_TRUE;
- recover = CK_TRUE;
- encrypt = CK_TRUE;
- derive = CK_FALSE;
- /* now fill in the RSA dependent parameters in the public key */
- if (lowPriv) {
- crv = pk11_AddAttributeType(publicKey,CKA_MODULUS,
- pk11_item_expand(&lowPriv->u.rsa.modulus));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_PUBLIC_EXPONENT,
- pk11_item_expand(&lowPriv->u.rsa.publicExponent));
- if (crv != CKR_OK) break;
- } else {
- crv = pk11_AddAttributeType(publicKey,CKA_MODULUS,
- pk11_item_expand(&pubKey->u.rsa.modulus));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_PUBLIC_EXPONENT,
- pk11_item_expand(&pubKey->u.rsa.publicExponent));
- if (crv != CKR_OK) break;
- }
- break;
- case lowDSAKey:
- key_type = CKK_DSA;
- verify = CK_TRUE;
- recover = CK_FALSE;
- encrypt = CK_FALSE;
- derive = CK_FALSE;
- if (lowPriv) {
- crv = pk11_AddAttributeType(publicKey,CKA_PRIME,
- pk11_item_expand(&lowPriv->u.dsa.params.prime));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_SUBPRIME,
- pk11_item_expand(&lowPriv->u.dsa.params.subPrime));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_BASE,
- pk11_item_expand(&lowPriv->u.dsa.params.base));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_VALUE,
- pk11_item_expand(&lowPriv->u.dsa.publicValue));
- if (crv != CKR_OK) break;
- } else {
- crv = pk11_AddAttributeType(publicKey,CKA_PRIME,
- pk11_item_expand(&pubKey->u.dsa.params.prime));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_SUBPRIME,
- pk11_item_expand(&pubKey->u.dsa.params.subPrime));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_BASE,
- pk11_item_expand(&pubKey->u.dsa.params.base));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_VALUE,
- pk11_item_expand(&pubKey->u.dsa.publicValue));
- if (crv != CKR_OK) break;
- }
- break;
- case lowDHKey:
- key_type = CKK_DH;
- verify = CK_FALSE;
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- derive = CK_TRUE;
- crv = CKR_MECHANISM_INVALID;
- break;
- default:
- crv = CKR_MECHANISM_INVALID;
- }
-
- if (pubKey) {
- SECKEY_DestroyPublicKey(pubKey);
- pubKey = NULL;
- }
-
- if (crv != CKR_OK) {
- goto failed;
- }
-
- if (pk11_AddAttributeType(publicKey,CKA_VERIFY, &verify,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_VERIFY_RECOVER, &recover,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_ENCRYPT, &encrypt,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_WRAP, &encrypt,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_DERIVE, &derive,
- sizeof(CK_BBOOL)) != CKR_OK) {
- goto failed;
- }
- if (pk11_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type,
- sizeof(CK_KEY_TYPE)) != CKR_OK) {
- goto failed;
- }
- PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
- publicKey->handle = slot->tokenIDCount++;
- publicKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PUB);
- PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
- publicKey->objclass = pubClass;
- publicKey->slot = slot;
- publicKey->inDB = PR_FALSE; /* not really in the Database */
-
- return publicKey;
-failed:
- if (pubKey) SECKEY_DestroyPublicKey(pubKey);
- if (publicKey) pk11_FreeObject(publicKey);
- return NULL;
-}
-
-/*
- * Question.. Why doesn't import Cert call pk11_handleObject, or
- * pk11 handleCertObject? Answer: because they will try to write
- * this cert back out to the Database, even though it is already in
- * the database.
- */
-static PK11Object *
-pk11_importCertificate(PK11Slot *slot, CERTCertificate *cert,
- unsigned char *data, unsigned int size, PRBool needObject)
-{
- PK11Object *certObject = NULL;
- CK_BBOOL cktrue = CK_TRUE;
- CK_BBOOL ckfalse = CK_FALSE;
- CK_CERTIFICATE_TYPE certType = CKC_X_509;
- CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
- unsigned char cka_id[SHA1_LENGTH];
- CK_ATTRIBUTE theTemplate;
- PK11ObjectListElement *objectList = NULL;
- CK_RV crv;
-
-
- /*
- * first make sure that no object for this cert already exists.
- */
- theTemplate.type = CKA_VALUE;
- theTemplate.pValue = cert->derCert.data;
- theTemplate.ulValueLen = cert->derCert.len;
- crv = pk11_searchObjectList(&objectList,slot->tokObjects,
- slot->objectLock, &theTemplate, 1, slot->isLoggedIn);
- if ((crv == CKR_OK) && (objectList != NULL)) {
- if (needObject) {
- pk11_ReferenceObject(objectList->object);
- certObject = objectList->object;
- }
- pk11_FreeObjectList(objectList);
- return certObject;
- }
-
- /*
- * now lets create an object to hang the attributes off of
- */
- certObject = pk11_NewObject(slot); /* fill in the handle later */
- if (certObject == NULL) {
- return NULL;
- }
-
- /* First set the CKA_ID */
- if (data == NULL) {
- SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(cert);
- SECItem *pubItem;
- if (pubKey == NULL) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- /* pk11_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.
- */
- pubItem =pk11_GetPubItem(pubKey);
- if (pubItem == NULL) {
- SECKEY_DestroyPublicKey(pubKey);
- pk11_FreeObject(certObject);
- return NULL;
- }
- SHA1_HashBuf(cka_id, (unsigned char *)pubItem->data,
- (uint32)pubItem->len);
- SECKEY_DestroyPublicKey(pubKey);
- } else {
- SHA1_HashBuf(cka_id, (unsigned char *)data, (uint32)size);
- }
- if (pk11_AddAttributeType(certObject, CKA_ID, cka_id, sizeof(cka_id))) {
- pk11_FreeObject(certObject);
- return NULL;
- }
-
- /* initalize the certificate attributes */
- if (pk11_AddAttributeType(certObject, CKA_CLASS, &certClass,
- sizeof(CK_OBJECT_CLASS)) != CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- if (pk11_AddAttributeType(certObject, CKA_TOKEN, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- if (pk11_AddAttributeType(certObject, CKA_PRIVATE, &ckfalse,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- if (pk11_AddAttributeType(certObject, CKA_LABEL, cert->nickname,
- PORT_Strlen(cert->nickname))
- != CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- if (pk11_AddAttributeType(certObject, CKA_MODIFIABLE, &cktrue,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- if (pk11_AddAttributeType(certObject, CKA_CERTIFICATE_TYPE, &certType,
- sizeof(CK_CERTIFICATE_TYPE))!=CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- if (pk11_AddAttributeType(certObject, CKA_VALUE,
- pk11_item_expand(&cert->derCert)) != CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- if (pk11_AddAttributeType(certObject, CKA_ISSUER,
- pk11_item_expand(&cert->derIssuer)) != CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- if (pk11_AddAttributeType(certObject, CKA_SUBJECT,
- pk11_item_expand(&cert->derSubject)) != CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
- if (pk11_AddAttributeType(certObject, CKA_SERIAL_NUMBER,
- pk11_item_expand(&cert->serialNumber)) != CKR_OK) {
- pk11_FreeObject(certObject);
- return NULL;
- }
-
-
- certObject->objectInfo = CERT_DupCertificate(cert);
- certObject->infoFree = (PK11Free) CERT_DestroyCertificate;
-
- /* now just verify the required date fields */
- PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
- certObject->handle = slot->tokenIDCount++;
- certObject->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT);
- PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
- certObject->objclass = certClass;
- certObject->slot = slot;
- certObject->inDB = PR_TRUE;
- pk11_AddSlotObject(slot, certObject);
- if (needObject) {
- pk11_ReferenceObject(certObject);
+ if (pk11_isToken(object->handle)) {
+ pk11_convertSessionToToken(object);
} else {
- certObject = NULL;
+ object->slot = slot;
+ pk11_AddObject(session,object);
}
- return certObject;
+ return CKR_OK;
}
/*
* ******************** Public Key Utilities ***************************
*/
/* Generate a low public key structure from an object */
-SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type)
+NSSLOWKEYPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type)
{
- SECKEYLowPublicKey *pubKey;
+ NSSLOWKEYPublicKey *pubKey;
PLArenaPool *arena;
CK_RV crv;
@@ -1941,17 +1478,21 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type)
return NULL;
}
+ if (pk11_isToken(object->handle)) {
+/* ferret out the token object handle */
+ }
+
/* If we already have a key, use it */
if (object->objectInfo) {
- return (SECKEYLowPublicKey *)object->objectInfo;
+ return (NSSLOWKEYPublicKey *)object->objectInfo;
}
/* allocate the structure */
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) return NULL;
- pubKey = (SECKEYLowPublicKey *)
- PORT_ArenaAlloc(arena,sizeof(SECKEYLowPublicKey));
+ pubKey = (NSSLOWKEYPublicKey *)
+ PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPublicKey));
if (pubKey == NULL) {
PORT_FreeArena(arena,PR_FALSE);
return NULL;
@@ -1961,7 +1502,7 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type)
pubKey->arena = arena;
switch (key_type) {
case CKK_RSA:
- pubKey->keyType = lowRSAKey;
+ pubKey->keyType = NSSLOWKEYRSAKey;
crv = pk11_Attribute2SSecItem(arena,&pubKey->u.rsa.modulus,
object,CKA_MODULUS);
if (crv != CKR_OK) break;
@@ -1969,7 +1510,7 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type)
object,CKA_PUBLIC_EXPONENT);
break;
case CKK_DSA:
- pubKey->keyType = lowDSAKey;
+ pubKey->keyType = NSSLOWKEYDSAKey;
crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dsa.params.prime,
object,CKA_PRIME);
if (crv != CKR_OK) break;
@@ -1983,7 +1524,7 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type)
object,CKA_VALUE);
break;
case CKK_DH:
- pubKey->keyType = lowDHKey;
+ pubKey->keyType = NSSLOWKEYDHKey;
crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dh.prime,
object,CKA_PRIME);
if (crv != CKR_OK) break;
@@ -2003,24 +1544,25 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type)
}
object->objectInfo = pubKey;
- object->infoFree = (PK11Free) SECKEY_LowDestroyPublicKey;
+ object->infoFree = (PK11Free) nsslowkey_DestroyPublicKey;
return pubKey;
}
/* make a private key from a verified object */
-static SECKEYLowPrivateKey *
+static NSSLOWKEYPrivateKey *
pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
{
- SECKEYLowPrivateKey *privKey;
+ NSSLOWKEYPrivateKey *privKey;
PLArenaPool *arena;
CK_RV crv = CKR_OK;
SECStatus rv;
+ PORT_Assert(!pk11_isToken(object->handle));
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) return NULL;
- privKey = (SECKEYLowPrivateKey *)
- PORT_ArenaAlloc(arena,sizeof(SECKEYLowPrivateKey));
+ privKey = (NSSLOWKEYPrivateKey *)
+ PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
if (privKey == NULL) {
PORT_FreeArena(arena,PR_FALSE);
return NULL;
@@ -2030,7 +1572,7 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
privKey->arena = arena;
switch (key_type) {
case CKK_RSA:
- privKey->keyType = lowRSAKey;
+ privKey->keyType = NSSLOWKEYRSAKey;
crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.modulus,
object,CKA_MODULUS);
if (crv != CKR_OK) break;
@@ -2056,12 +1598,12 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
CKA_COEFFICIENT);
if (crv != CKR_OK) break;
rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
- SEC_PRIVATE_KEY_VERSION);
+ NSSLOWKEY_VERSION);
if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
break;
case CKK_DSA:
- privKey->keyType = lowDSAKey;
+ privKey->keyType = NSSLOWKEYDSAKey;
crv = pk11_Attribute2SSecItem(arena,&privKey->u.dsa.params.prime,
object,CKA_PRIME);
if (crv != CKR_OK) break;
@@ -2080,7 +1622,7 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
break;
case CKK_DH:
- privKey->keyType = lowDHKey;
+ privKey->keyType = NSSLOWKEYDHKey;
crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.prime,
object,CKA_PRIME);
if (crv != CKR_OK) break;
@@ -2089,6 +1631,9 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
if (crv != CKR_OK) break;
crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.privateValue,
object,CKA_VALUE);
+ if (crv != CKR_OK) break;
+ crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.publicValue,
+ object,CKA_NETSCAPE_DB);
break;
default:
crv = CKR_KEY_TYPE_INCONSISTENT;
@@ -2103,52 +1648,31 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
/* Generate a low private key structure from an object */
-SECKEYLowPrivateKey *
+NSSLOWKEYPrivateKey *
pk11_GetPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
{
- SECKEYLowPrivateKey *priv = NULL;
+ NSSLOWKEYPrivateKey *priv = NULL;
if (object->objclass != CKO_PRIVATE_KEY) {
return NULL;
}
if (object->objectInfo) {
- return (SECKEYLowPrivateKey *)object->objectInfo;
+ return (NSSLOWKEYPrivateKey *)object->objectInfo;
}
- if (pk11_isTrue(object,CKA_TOKEN)) {
+ if (pk11_isToken(object->handle)) {
/* grab it from the data base */
- SECItem pubKey;
- CK_RV crv;
+ PK11TokenObject *to = pk11_narrowToTokenObject(object);
- /* KEYID is the public KEY for DSA and DH, and the MODULUS for
- * RSA */
- crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
- if (crv != CKR_OK) return NULL;
-
- priv=SECKEY_FindKeyByPublicKey(SECKEY_GetDefaultKeyDB(),&pubKey,
- (SECKEYLowGetPasswordKey) pk11_givePass,
- object->slot);
- if (!priv && pubKey.data[0] == 0) {
- /* Because of legacy code issues, sometimes the public key has
- * a '0' prepended to it, forcing it to be unsigned. The database
- * may not store that '0', so remove it and try again.
- */
- SECItem tmpPubKey;
- tmpPubKey.data = pubKey.data + 1;
- tmpPubKey.len = pubKey.len - 1;
- priv=SECKEY_FindKeyByPublicKey(SECKEY_GetDefaultKeyDB(),&tmpPubKey,
- (SECKEYLowGetPasswordKey) pk11_givePass,
- object->slot);
- }
- if (pubKey.data) PORT_Free(pubKey.data);
-
- /* don't 'cache' DB private keys */
- return priv;
- }
-
- priv = pk11_mkPrivKey(object, key_type);
+ PORT_Assert(to);
+ PORT_Assert(object->slot->keyDB);
+ priv = nsslowkey_FindKeyByPublicKey(object->slot->keyDB, &to->dbKey,
+ object->slot->password);
+ } else {
+ priv = pk11_mkPrivKey(object, key_type);
+ }
object->objectInfo = priv;
- object->infoFree = (PK11Free) SECKEY_LowDestroyPrivateKey;
+ object->infoFree = (PK11Free) nsslowkey_DestroyPrivateKey;
return priv;
}
@@ -2213,10 +1737,10 @@ pk11_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type)
/* make a fake private key representing a symmetric key */
-static SECKEYLowPrivateKey *
+static NSSLOWKEYPrivateKey *
pk11_mkSecretKeyRep(PK11Object *object)
{
- SECKEYLowPrivateKey *privKey;
+ NSSLOWKEYPrivateKey *privKey;
PLArenaPool *arena = 0;
CK_RV crv;
SECStatus rv;
@@ -2225,8 +1749,8 @@ pk11_mkSecretKeyRep(PK11Object *object)
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
- privKey = (SECKEYLowPrivateKey *)
- PORT_ArenaAlloc(arena,sizeof(SECKEYLowPrivateKey));
+ privKey = (NSSLOWKEYPrivateKey *)
+ PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
privKey->arena = arena;
@@ -2240,7 +1764,7 @@ pk11_mkSecretKeyRep(PK11Object *object)
* is used for the key.
* all others - set to integer 0
*/
- privKey->keyType = lowRSAKey;
+ privKey->keyType = NSSLOWKEYRSAKey;
/* The modulus is set to the key id of the symmetric key */
crv=pk11_Attribute2SecItem(arena,&privKey->u.rsa.modulus,object,CKA_ID);
@@ -2272,7 +1796,8 @@ pk11_mkSecretKeyRep(PK11Object *object)
if (crv != CKR_OK) goto loser;
/* Private key version field set normally for compatibility */
- rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,SEC_PRIVATE_KEY_VERSION);
+ rv = DER_SetUInteger(privKey->arena,
+ &privKey->u.rsa.version, NSSLOWKEY_VERSION);
if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; }
loser:
@@ -2285,117 +1810,178 @@ loser:
}
static PRBool
-isSecretKey(SECKEYLowPrivateKey *privKey)
+isSecretKey(NSSLOWKEYPrivateKey *privKey)
{
- if (privKey->keyType == lowRSAKey && privKey->u.rsa.publicExponent.len == 1 &&
- privKey->u.rsa.publicExponent.data[0] == 0)
+ if (privKey->keyType == NSSLOWKEYRSAKey &&
+ privKey->u.rsa.publicExponent.len == 1 &&
+ privKey->u.rsa.publicExponent.data[0] == 0)
return PR_TRUE;
return PR_FALSE;
}
-/* Import a Secret Key */
-static PRBool
-importSecretKey(PK11Slot *slot, SECKEYLowPrivateKey *priv)
-{
- PK11Object *object;
- CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
- CK_BBOOL cktrue = CK_TRUE;
- CK_BBOOL ckfalse = CK_FALSE;
- CK_KEY_TYPE key_type;
+/**********************************************************************
+ *
+ * Start of PKCS 11 functions
+ *
+ **********************************************************************/
- /* Check for secret key representation, return if it isn't one */
- if (!isSecretKey(priv))
- return PR_FALSE;
- /*
- * now lets create an object to hang the attributes off of
- */
- object = pk11_NewObject(slot); /* fill in the handle later */
- if (object == NULL) {
- goto loser;
- }
+/* return the function list */
+CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
+{
+ *pFunctionList = (CK_FUNCTION_LIST_PTR) &pk11_funcList;
+ return CKR_OK;
+}
- /* Set the ID value */
- if (pk11_AddAttributeType(object, CKA_ID,
- priv->u.rsa.modulus.data, priv->u.rsa.modulus.len)) {
- pk11_FreeObject(object);
- goto loser;
- }
+/* return the function list */
+CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
+{
+ return NSC_GetFunctionList(pFunctionList);
+}
- /* initalize the object attributes */
- if (pk11_AddAttributeType(object, CKA_CLASS, &secretClass,
- sizeof(secretClass)) != CKR_OK) {
- pk11_FreeObject(object);
- goto loser;
- }
+static PLHashNumber
+pk11_HashNumber(const void *key)
+{
+ return (PLHashNumber) key;
+}
- if (pk11_AddAttributeType(object, CKA_TOKEN, &cktrue,
- sizeof(cktrue)) != CKR_OK) {
- pk11_FreeObject(object);
- goto loser;
- }
+/*
+ * eventually I'd like to expunge all occurances of XXX_SLOT_ID and
+ * just go with the info in the slot. This is one place, however,
+ * where it might be a little difficult.
+ */
+char *
+pk11_getDefTokName(CK_SLOT_ID slotID)
+{
+ static char buf[33];
- if (pk11_AddAttributeType(object, CKA_PRIVATE, &ckfalse,
- sizeof(CK_BBOOL)) != CKR_OK) {
- pk11_FreeObject(object);
- goto loser;
+ switch (slotID) {
+ case NETSCAPE_SLOT_ID:
+ return "NSS Generic Crypto Services ";
+ case PRIVATE_KEY_SLOT_ID:
+ return "NSS Certificate DB ";
+ case FIPS_SLOT_ID:
+ return "NSS FIPS-140-1 Cerificate DB ";
+ default:
+ break;
}
+ sprintf(buf,"NSS Application Token %08x ",(unsigned int) slotID);
+ return buf;
+}
- if (pk11_AddAttributeType(object, CKA_VALUE,
- pk11_item_expand(&priv->u.rsa.privateExponent)) != CKR_OK) {
- pk11_FreeObject(object);
- goto loser;
- }
+char *
+pk11_getDefSlotName(CK_SLOT_ID slotID)
+{
+ static char buf[65];
- if (pk11_AddAttributeType(object, CKA_KEY_TYPE,
- pk11_item_expand(&priv->u.rsa.coefficient)) != CKR_OK) {
- pk11_FreeObject(object);
- goto loser;
+ switch (slotID) {
+ case NETSCAPE_SLOT_ID:
+ return
+ "NSS Internal Cryptographic Services Version 3.4 ";
+ case PRIVATE_KEY_SLOT_ID:
+ return
+ "NSS User Private Key and Certificate Services ";
+ case FIPS_SLOT_ID:
+ return
+ "Netscape FIPS-140-1 User Private Key Services ";
+ default:
+ break;
}
- key_type = *(CK_KEY_TYPE*)priv->u.rsa.coefficient.data;
+ sprintf(buf,
+ "NSS Application Slot %08x ",
+ (unsigned int) slotID);
+ return buf;
+}
- /* Validate and add default attributes */
- validateSecretKey(object, key_type, (PRBool)(slot->slotID == FIPS_SLOT_ID));
+static CK_ULONG nscSlotCount = 0;
+static CK_SLOT_ID_PTR nscSlotList = NULL;
+static CK_ULONG nscSlotListSize = 0;
+static PLHashTable *nscSlotHashTable = NULL;
- /* now just verify the required date fields */
- PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
- object->handle = slot->tokenIDCount++;
- object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
- PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
+/* look up a slot structure from the ID (used to be a macro when we only
+ * had two slots) */
+PK11Slot *
+pk11_SlotFromID(CK_SLOT_ID slotID)
+{
+ return (PK11Slot *)PL_HashTableLookupConst(nscSlotHashTable,
+ (void *)slotID);
+}
+
+PK11Slot *
+pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle)
+{
+ int slotIDIndex = (handle >> 24) & 0xff;
- object->objclass = secretClass;
- object->slot = slot;
- object->inDB = PR_TRUE;
- pk11_AddSlotObject(slot, object);
+ if (slotIDIndex >= nscSlotCount) {
+ return NULL;
+ }
-loser:
- return PR_TRUE;
+ return pk11_SlotFromID(nscSlotList[slotIDIndex]);
}
+
+PK11Slot * pk11_NewSlotFromID(CK_SLOT_ID slotID)
+{
+ PK11Slot *slot = NULL;
+ PLHashEntry *entry;
+
+ if (nscSlotList == NULL) {
+ nscSlotListSize = NSC_SLOT_LIST_BLOCK_SIZE;
+ nscSlotList = (CK_SLOT_ID *)
+ PORT_ZAlloc(nscSlotListSize*sizeof(CK_SLOT_ID));
+ if (nscSlotList == NULL) {
+ return NULL;
+ }
+ }
+ if (nscSlotCount >= nscSlotListSize) {
+ nscSlotListSize += NSC_SLOT_LIST_BLOCK_SIZE;
+ nscSlotList = (CK_SLOT_ID *) PORT_Realloc(nscSlotList,
+ nscSlotListSize*sizeof(CK_SLOT_ID));
+ if (nscSlotList == NULL) {
+ return NULL;
+ }
+ }
+ if (nscSlotHashTable == NULL) {
+ nscSlotHashTable = PL_NewHashTable(64,pk11_HashNumber,PL_CompareValues,
+ PL_CompareValues, NULL, 0);
+ if (nscSlotHashTable == NULL) {
+ return NULL;
+ }
+ }
-/**********************************************************************
- *
- * Start of PKCS 11 functions
- *
- **********************************************************************/
+ slot = (PK11Slot *) PORT_ZAlloc(sizeof(PK11Slot));
+ if (slot == NULL) {
+ return NULL;
+ }
+ entry = PL_HashTableAdd(nscSlotHashTable,(void *)slotID,slot);
+ if (entry == NULL) {
+ PORT_Free(slot);
+ return NULL;
+ }
+ slot->index = nscSlotCount;
+ nscSlotList[nscSlotCount++] = slotID;
-/* return the function list */
-CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
-{
- *pFunctionList = &pk11_funcList;
- return CKR_OK;
+ return slot;
}
/*
* initialize one of the slot structures. figure out which by the ID
*/
CK_RV
-PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin)
+PK11_SlotInit(char *configdir,pk11_token_parameters *params)
{
int i;
- PK11Slot *slot = pk11_SlotFromID(slotID);
+ CK_SLOT_ID slotID = params->slotID;
+ PK11Slot *slot = pk11_NewSlotFromID(slotID);
+ PRBool needLogin = !params->noKeyDB;
+ CK_RV crv;
+
+ if (slot == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+
#ifdef PKCS11_USE_THREADS
slot->sessionLock = PZ_NewLock(nssILockSession);
if (slot->sessionLock == NULL) return CKR_HOST_MEMORY;
@@ -2411,6 +1997,11 @@ PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin)
for(i=0; i < TOKEN_OBJECT_HASH_SIZE; i++) {
slot->tokObjects[i] = NULL;
}
+ slot->tokenHashTable = PL_NewHashTable(64,pk11_HashNumber,PL_CompareValues,
+ SECITEM_HashCompare, NULL, 0);
+ if (slot->tokenHashTable == NULL) {
+ return CKR_HOST_MEMORY;
+ }
slot->password = NULL;
slot->hasTokens = PR_FALSE;
slot->sessionIDCount = 1;
@@ -2422,61 +2013,39 @@ PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin)
slot->ssoLoggedIn = PR_FALSE;
slot->DB_loaded = PR_FALSE;
slot->slotID = slotID;
- if (needLogin) {
- /* if the data base is initialized with a null password,remember that */
- slot->needLogin = (PRBool)!pk11_hasNullPassword(&slot->password);
- }
- return CKR_OK;
-}
-
-
-/*
- * common initialization routines between PKCS #11 and FIPS
- */
-CK_RV PK11_LowInitialize(CK_VOID_PTR pReserved)
-{
- CK_RV crv = CKR_OK;
- CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *) pReserved;
-
- /* NOTE:
- * we should be getting out mutexes from this list, not statically binding
- * them from NSPR. This should happen before we allow the internal to split
- * off from the rest on NSS.
- */
-
- /* initialize the key and cert db's */
- SECKEY_SetDefaultKeyDBAlg(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC);
-
- if ((init_args && init_args->LibraryParameters)) {
- pk11_parameters paramStrings;
-
- crv = secmod_parseParameters
- ((char *)init_args->LibraryParameters,&paramStrings);
+ slot->certDB = NULL;
+ slot->keyDB = NULL;
+ slot->minimumPinLen = 0;
+ slot->readOnly = params->readOnly;
+ pk11_setStringName(params->tokdes ? params->tokdes :
+ pk11_getDefTokName(slotID), slot->tokDescription,
+ sizeof(slot->tokDescription));
+ pk11_setStringName(params->slotdes ? params->slotdes :
+ pk11_getDefSlotName(slotID), slot->slotDescription,
+ sizeof(slot->slotDescription));
+
+ if ((!params->noCertDB) || (!params->noKeyDB)) {
+ crv = pk11_DBInit(params->configdir ? params->configdir : configdir,
+ params->certPrefix, params->keyPrefix, params->readOnly,
+ params->noCertDB, params->noKeyDB, params->forceOpen,
+ &slot->certDB, &slot->keyDB);
if (crv != CKR_OK) {
+ /* shoutdown slot? */
return crv;
}
-
- crv = pk11_DBInit(paramStrings.configdir,paramStrings.certPrefix,
- paramStrings.keyPrefix,paramStrings.secmodName, paramStrings.readOnly,paramStrings.noCertDB,
- paramStrings.noModDB, paramStrings.forceOpen);
- if (crv != CKR_OK) {
- secmod_freeParams(&paramStrings);
- return crv;
+ }
+ if (needLogin) {
+ /* if the data base is initialized with a null password,remember that */
+ slot->needLogin =
+ (PRBool)!pk11_hasNullPassword(slot->keyDB,&slot->password);
+ if (params->minPW <= PK11_MAX_PIN) {
+ slot->minimumPinLen = params->minPW;
}
- crv = pk11_configure(paramStrings.man, paramStrings.libdes,
- paramStrings.tokdes,paramStrings.ptokdes,paramStrings.slotdes,
- paramStrings.pslotdes,paramStrings.fslotdes,
- paramStrings.fpslotdes, paramStrings.minPW,
- paramStrings.pwRequired);
- secmod_freeParams(&paramStrings);
- if (crv != CKR_OK) {
- return crv;
+ if ((slot->minimumPinLen == 0) && (params->pwRequired) &&
+ (slot->minimumPinLen <= PK11_MAX_PIN)) {
+ slot->minimumPinLen = 1;
}
- } else {
- return CKR_ARGUMENTS_BAD;
}
-
-
return CKR_OK;
}
@@ -2507,25 +2076,67 @@ NSC_ModuleDBFunc(unsigned long function,char *parameters, char *args)
/* NSC_Initialize initializes the Cryptoki library. */
-CK_RV NSC_Initialize(CK_VOID_PTR pReserved)
+CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
{
static PRBool init = PR_FALSE;
CK_RV crv = CKR_OK;
+ SECStatus rv;
+ CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *) pReserved;
+ int i;
- crv = PK11_LowInitialize(pReserved);
- if (crv != CKR_OK) return crv;
+ if (init) {
+ return crv;
+ }
- /* intialize all the slots */
- if (!init) {
- crv = PK11_SlotInit(NETSCAPE_SLOT_ID,PR_FALSE);
- if (crv != CKR_OK) return crv;
- crv = PK11_SlotInit(PRIVATE_KEY_SLOT_ID,PR_TRUE);
- init = PR_TRUE;
+ rv = RNG_RNGInit(); /* initialize random number generator */
+ if (rv != SECSuccess) {
+ crv = CKR_DEVICE_ERROR;
+ goto loser;
}
+ RNG_SystemInfoForRNG();
+
+
+ /* NOTE:
+ * we should be getting out mutexes from this list, not statically binding
+ * them from NSPR. This should happen before we allow the internal to split
+ * off from the rest on NSS.
+ */
+
+ /* initialize the key and cert db's */
+ nsslowkey_SetDefaultKeyDBAlg
+ (SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC);
+ crv = CKR_ARGUMENTS_BAD;
+ if ((init_args && init_args->LibraryParameters)) {
+ pk11_parameters paramStrings;
+
+ crv = secmod_parseParameters
+ ((char *)init_args->LibraryParameters,&paramStrings, isFIPS);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+ crv = pk11_configure(paramStrings.man, paramStrings.libdes);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+
+ for (i=0; i < paramStrings.token_count; i++) {
+ crv =
+ PK11_SlotInit(paramStrings.configdir,&paramStrings.tokens[i]);
+ if (crv != CKR_OK) break;
+ }
+loser:
+ secmod_freeParams(&paramStrings);
+ }
+ init = (PRBool) (crv == CKR_OK);
return crv;
}
+CK_RV NSC_Initialize(CK_VOID_PTR pReserved)
+{
+ return nsc_CommonInitialize(pReserved,PR_FALSE);
+}
+
/* NSC_Finalize indicates that an application is done with the
* Cryptoki library.*/
CK_RV NSC_Finalize (CK_VOID_PTR pReserved)
@@ -2538,7 +2149,7 @@ CK_RV NSC_Finalize (CK_VOID_PTR pReserved)
CK_RV NSC_GetInfo(CK_INFO_PTR pInfo)
{
pInfo->cryptokiVersion.major = 2;
- pInfo->cryptokiVersion.minor = 1;
+ pInfo->cryptokiVersion.minor = 11;
PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
pInfo->libraryVersion.major = 3;
pInfo->libraryVersion.minor = 2;
@@ -2551,10 +2162,9 @@ CK_RV NSC_GetInfo(CK_INFO_PTR pInfo)
CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent,
CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
{
- *pulCount = 2;
+ *pulCount = nscSlotCount;
if (pSlotList != NULL) {
- pSlotList[0] = NETSCAPE_SLOT_ID;
- pSlotList[1] = PRIVATE_KEY_SLOT_ID;
+ PORT_Memcpy(pSlotList,nscSlotList,nscSlotCount*sizeof(CK_SLOT_ID));
}
return CKR_OK;
}
@@ -2562,28 +2172,19 @@ CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent,
/* NSC_GetSlotInfo obtains information about a particular slot in the system. */
CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
{
+ PK11Slot *slot = pk11_SlotFromID(slotID);
+ if (slot == NULL) return CKR_SLOT_ID_INVALID;
+
pInfo->firmwareVersion.major = 0;
pInfo->firmwareVersion.minor = 0;
- switch (slotID) {
- case NETSCAPE_SLOT_ID:
- PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
- PORT_Memcpy(pInfo->slotDescription,slotDescription,64);
- pInfo->flags = CKF_TOKEN_PRESENT;
- pInfo->hardwareVersion.major = 3;
- pInfo->hardwareVersion.minor = 2;
- return CKR_OK;
- case PRIVATE_KEY_SLOT_ID:
- PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
- PORT_Memcpy(pInfo->slotDescription,privSlotDescription,64);
- pInfo->flags = CKF_TOKEN_PRESENT;
- /* ok we really should read it out of the keydb file. */
- pInfo->hardwareVersion.major = PRIVATE_KEY_DB_FILE_VERSION;
- pInfo->hardwareVersion.minor = 0;
- return CKR_OK;
- default:
- break;
- }
- return CKR_SLOT_ID_INVALID;
+ PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
+ PORT_Memcpy(pInfo->slotDescription,slot->slotDescription,64);
+ pInfo->flags = CKF_TOKEN_PRESENT;
+ /* ok we really should read it out of the keydb file. */
+ /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
+ pInfo->hardwareVersion.major = 3;
+ pInfo->hardwareVersion.minor = 2;
+ return CKR_OK;
}
#define CKF_THREAD_SAFE 0x8000 /* for now */
@@ -2593,12 +2194,12 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
{
PK11Slot *slot = pk11_SlotFromID(slotID);
- SECKEYKeyDBHandle *handle;
+ NSSLOWKEYDBHandle *handle;
if (slot == NULL) return CKR_SLOT_ID_INVALID;
PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
- PORT_Memcpy(pInfo->model,"Libsec 4.0 ",16);
+ PORT_Memcpy(pInfo->model,"NSS 3 ",16);
PORT_Memcpy(pInfo->serialNumber,"0000000000000000",16);
pInfo->ulMaxSessionCount = 0; /* arbitrarily large */
pInfo->ulSessionCount = slot->sessionCount;
@@ -2606,9 +2207,9 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->ulRwSessionCount = slot->rwSessionCount;
pInfo->firmwareVersion.major = 0;
pInfo->firmwareVersion.minor = 0;
- switch (slotID) {
- case NETSCAPE_SLOT_ID:
- PORT_Memcpy(pInfo->label,tokDescription,32);
+ PORT_Memcpy(pInfo->label,slot->tokDescription,32);
+ handle = slot->keyDB;
+ if (handle == NULL) {
pInfo->flags= CKF_RNG | CKF_WRITE_PROTECTED | CKF_THREAD_SAFE;
pInfo->ulMaxPinLen = 0;
pInfo->ulMinPinLen = 0;
@@ -2618,10 +2219,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->ulFreePrivateMemory = 0;
pInfo->hardwareVersion.major = 4;
pInfo->hardwareVersion.minor = 0;
- return CKR_OK;
- case PRIVATE_KEY_SLOT_ID:
- PORT_Memcpy(pInfo->label,privTokDescription,32);
- handle = SECKEY_GetDefaultKeyDB();
+ } else {
/*
* we have three possible states which we may be in:
* (1) No DB password has been initialized. This also means we
@@ -2631,7 +2229,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 (SECKEY_HasKeyDBPassword(handle) == SECFailure) {
+ if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) {
pInfo->flags = CKF_THREAD_SAFE | CKF_LOGIN_REQUIRED;
} else if (!slot->needLogin) {
pInfo->flags = CKF_THREAD_SAFE | CKF_USER_PIN_INITIALIZED;
@@ -2641,8 +2239,8 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
}
pInfo->ulMaxPinLen = PK11_MAX_PIN;
pInfo->ulMinPinLen = 0;
- if (minimumPinLen > 0) {
- pInfo->ulMinPinLen = (CK_ULONG)minimumPinLen;
+ if (slot->minimumPinLen > 0) {
+ pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen;
}
pInfo->ulTotalPublicMemory = 1;
pInfo->ulFreePublicMemory = 1;
@@ -2650,11 +2248,8 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->ulFreePrivateMemory = 1;
pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION;
pInfo->hardwareVersion.minor = 0;
- return CKR_OK;
- default:
- break;
}
- return CKR_SLOT_ID_INVALID;
+ return CKR_OK;
}
@@ -2674,8 +2269,8 @@ CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID,
pMechanismList[i] = mechanisms[i].type;
}
}
- return CKR_OK;
- case PRIVATE_KEY_SLOT_ID:
+ break;
+ default:
*pulCount = 0;
for (i=0; i < (int) mechanismCount; i++) {
if (mechanisms[i].privkey) {
@@ -2685,11 +2280,9 @@ CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID,
}
}
}
- return CKR_OK;
- default:
break;
}
- return CKR_SLOT_ID_INVALID;
+ return CKR_OK;
}
@@ -2705,11 +2298,9 @@ CK_RV NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
case NETSCAPE_SLOT_ID:
isPrivateKey = PR_FALSE;
break;
- case PRIVATE_KEY_SLOT_ID:
+ default:
isPrivateKey = PR_TRUE;
break;
- default:
- return CKR_SLOT_ID_INVALID;
}
for (i=0; i < (int) mechanismCount; i++) {
if (type == mechanisms[i].type) {
@@ -2725,19 +2316,19 @@ CK_RV NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
}
static SECStatus
-pk11_TurnOffUser(CERTCertificate *cert, SECItem *k, void *arg)
+pk11_TurnOffUser(NSSLOWCERTCertificate *cert, SECItem *k, void *arg)
{
- CERTCertTrust trust;
+ NSSLOWCERTCertTrust trust;
SECStatus rv;
- rv = CERT_GetCertTrust(cert,&trust);
+ 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;
- CERT_ChangeCertTrust(cert->dbhandle,cert,&trust);
+ nsslowcert_ChangeCertTrust(cert->dbhandle,cert,&trust);
}
return SECSuccess;
}
@@ -2746,8 +2337,8 @@ pk11_TurnOffUser(CERTCertificate *cert, SECItem *k, void *arg)
CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
CK_ULONG ulPinLen,CK_CHAR_PTR pLabel) {
PK11Slot *slot = pk11_SlotFromID(slotID);
- SECKEYKeyDBHandle *handle;
- CERTCertDBHandle *certHandle;
+ NSSLOWKEYDBHandle *handle;
+ NSSLOWCERTCertDBHandle *certHandle;
SECStatus rv;
int i;
PK11Object *object;
@@ -2784,19 +2375,19 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
/* then clear out the key database */
- handle = SECKEY_GetDefaultKeyDB();
+ handle = slot->keyDB;
if (handle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
/* what to do on an error here? */
- rv = SECKEY_ResetKeyDB(handle);
+ rv = nsslowkey_ResetKeyDB(handle);
/* finally mark all the user certs as non-user certs */
- certHandle = CERT_GetDefaultCertDB();
+ certHandle = slot->certDB;
if (certHandle == NULL) return CKR_OK;
- SEC_TraversePermCerts(certHandle,pk11_TurnOffUser, NULL);
+ nsslowcert_TraversePermCerts(certHandle,pk11_TurnOffUser, NULL);
return CKR_OK; /*is this the right function for not implemented*/
}
@@ -2808,9 +2399,9 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
{
PK11Session *sp;
PK11Slot *slot;
- SECKEYKeyDBHandle *handle;
+ NSSLOWKEYDBHandle *handle;
SECItem *newPin;
- char newPinStr[256];
+ char newPinStr[PK11_MAX_PIN+1];
SECStatus rv;
@@ -2819,36 +2410,35 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
return CKR_SESSION_HANDLE_INVALID;
}
- if (sp->info.slotID == NETSCAPE_SLOT_ID) {
+ slot = pk11_SlotFromSession(sp);
+ if (slot == NULL) {
pk11_FreeSession(sp);
- return CKR_PIN_LEN_RANGE;
+ return CKR_SESSION_HANDLE_INVALID;;
}
- /* should be an assert */
- if (!((sp->info.slotID == PRIVATE_KEY_SLOT_ID) ||
- (sp->info.slotID == FIPS_SLOT_ID)) ) {
+ handle = slot->keyDB;
+ if (handle == NULL) {
pk11_FreeSession(sp);
- return CKR_SESSION_HANDLE_INVALID;;
+ return CKR_PIN_LEN_RANGE;
}
+
if (sp->info.state != CKS_RW_SO_FUNCTIONS) {
pk11_FreeSession(sp);
return CKR_USER_NOT_LOGGED_IN;
}
- slot = pk11_SlotFromSession(sp);
pk11_FreeSession(sp);
/* make sure the pins aren't too long */
- if (ulPinLen > 255) {
+ if (ulPinLen > PK11_MAX_PIN) {
return CKR_PIN_LEN_RANGE;
}
-
- handle = SECKEY_GetDefaultKeyDB();
- if (handle == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
+ if (ulPinLen < slot->minimumPinLen) {
+ return CKR_PIN_LEN_RANGE;
}
- if (SECKEY_HasKeyDBPassword(handle) != SECFailure) {
+
+ if (nsslowkey_HasKeyDBPassword(handle) != SECFailure) {
return CKR_DEVICE_ERROR;
}
@@ -2857,11 +2447,11 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
newPinStr[ulPinLen] = 0;
/* build the hashed pins which we pass around */
- newPin = SECKEY_HashPassword(newPinStr,handle->global_salt);
+ newPin = nsslowkey_HashPassword(newPinStr,handle->global_salt);
PORT_Memset(newPinStr,0,sizeof(newPinStr));
/* change the data base */
- rv = SECKEY_SetKeyDBPassword(handle,newPin);
+ rv = nsslowkey_SetKeyDBPassword(handle,newPin);
/* Now update our local copy of the pin */
if (rv == SECSuccess) {
@@ -2884,10 +2474,10 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
{
PK11Session *sp;
PK11Slot *slot;
- SECKEYKeyDBHandle *handle;
+ NSSLOWKEYDBHandle *handle;
SECItem *newPin;
SECItem *oldPin;
- char newPinStr[256],oldPinStr[256];
+ char newPinStr[PK11_MAX_PIN+1],oldPinStr[PK11_MAX_PIN+1];
SECStatus rv;
@@ -2896,20 +2486,18 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
return CKR_SESSION_HANDLE_INVALID;
}
- if (sp->info.slotID == NETSCAPE_SLOT_ID) {
+ slot = pk11_SlotFromSession(sp);
+ if (!slot) {
pk11_FreeSession(sp);
- return CKR_PIN_LEN_RANGE;
+ return CKR_SESSION_HANDLE_INVALID;;
}
- /* should be an assert */
- /* should be an assert */
- if (!((sp->info.slotID == PRIVATE_KEY_SLOT_ID) ||
- (sp->info.slotID == FIPS_SLOT_ID)) ) {
+ handle = slot->keyDB;
+ if (handle == NULL) {
pk11_FreeSession(sp);
- return CKR_SESSION_HANDLE_INVALID;;
+ return CKR_PIN_LEN_RANGE;
}
- slot = pk11_SlotFromSession(sp);
if (slot->needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) {
pk11_FreeSession(sp);
return CKR_USER_NOT_LOGGED_IN;
@@ -2918,16 +2506,14 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
pk11_FreeSession(sp);
/* make sure the pins aren't too long */
- if ((ulNewLen > 255) || (ulOldLen > 255)) {
+ if ((ulNewLen > PK11_MAX_PIN) || (ulOldLen > PK11_MAX_PIN)) {
return CKR_PIN_LEN_RANGE;
}
-
-
- handle = SECKEY_GetDefaultKeyDB();
- if (handle == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
+ if (ulNewLen < slot->minimumPinLen) {
+ return CKR_PIN_LEN_RANGE;
}
+
/* convert to null terminated string */
PORT_Memcpy(newPinStr,pNewPin,ulNewLen);
newPinStr[ulNewLen] = 0;
@@ -2935,13 +2521,13 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
oldPinStr[ulOldLen] = 0;
/* build the hashed pins which we pass around */
- newPin = SECKEY_HashPassword(newPinStr,handle->global_salt);
- oldPin = SECKEY_HashPassword(oldPinStr,handle->global_salt);
+ 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 */
- rv = SECKEY_ChangeKeyDBPassword(handle,oldPin,newPin);
+ rv = nsslowkey_ChangeKeyDBPassword(handle,oldPin,newPin);
/* Now update our local copy of the pin */
SECITEM_ZfreeItem(oldPin, PR_TRUE);
@@ -2974,12 +2560,8 @@ CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
if (session == NULL) return CKR_HOST_MEMORY;
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
- sessionID = slot->sessionIDCount++;
- if (slotID == PRIVATE_KEY_SLOT_ID) {
- sessionID |= PK11_PRIVATE_KEY_FLAG;
- } else if (slotID == FIPS_SLOT_ID) {
- sessionID |= PK11_FIPS_FLAG;
- } else if (flags & CKF_RW_SESSION) {
+ sessionID = slot->sessionIDCount++ | (slot->index << 24);
+ if (slot->readOnly && (flags & CKF_RW_SESSION)) {
/* NETSCAPE_SLOT_ID is Read ONLY */
session->info.flags &= ~CKF_RW_SESSION;
}
@@ -3101,9 +2683,9 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
{
PK11Slot *slot;
PK11Session *session;
- SECKEYKeyDBHandle *handle;
+ NSSLOWKEYDBHandle *handle;
SECItem *pin;
- char pinStr[256];
+ char pinStr[PK11_MAX_PIN+1];
/* get the slot */
@@ -3123,20 +2705,23 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
if (slot->isLoggedIn) return CKR_USER_ALREADY_LOGGED_IN;
slot->ssoLoggedIn = PR_FALSE;
- if (ulPinLen > 255) return CKR_PIN_LEN_RANGE;
+ if (ulPinLen > PK11_MAX_PIN) return CKR_PIN_LEN_RANGE;
/* convert to null terminated string */
PORT_Memcpy(pinStr,pPin,ulPinLen);
pinStr[ulPinLen] = 0;
- handle = SECKEY_GetDefaultKeyDB();
+ handle = slot->keyDB;
+ if (handle == NULL) {
+ return CKR_USER_TYPE_INVALID;
+ }
/*
* Deal with bootstrap. We allow the SSO to login in with a NULL
* password if and only if we haven't initialized the KEY DB yet.
* We only allow this on a RW session.
*/
- if (SECKEY_HasKeyDBPassword(handle) == SECFailure) {
+ if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) {
/* allow SSO's to log in only if there is not password on the
* key database */
if (((userType == CKU_SO) && (session->info.flags & CKF_RW_SESSION))
@@ -3165,10 +2750,10 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
/* build the hashed pins which we pass around */
- pin = SECKEY_HashPassword(pinStr,handle->global_salt);
+ pin = nsslowkey_HashPassword(pinStr,handle->global_salt);
if (pin == NULL) return CKR_HOST_MEMORY;
- if (SECKEY_CheckKeyDBPassword(handle,pin) == SECSuccess) {
+ if (nsslowkey_CheckKeyDBPassword(handle,pin) == SECSuccess) {
SECItem *tmp;
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
tmp = slot->password;
@@ -3255,14 +2840,11 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession,
* handle the base object stuff
*/
crv = pk11_handleObject(object,session);
+ *phObject = object->handle;
pk11_FreeSession(session);
- if (crv != CKR_OK) {
- pk11_FreeObject(object);
- return crv;
- }
+ pk11_FreeObject(object);
- *phObject = object->handle;
- return CKR_OK;
+ return crv;
}
@@ -3343,12 +2925,9 @@ CK_RV NSC_CopyObject(CK_SESSION_HANDLE hSession,
crv = pk11_handleObject(destObject,session);
*phNewObject = destObject->handle;
pk11_FreeSession(session);
- if (crv != CKR_OK) {
- pk11_FreeObject(destObject);
- return crv;
- }
+ pk11_FreeObject(destObject);
- return CKR_OK;
+ return crv;
}
@@ -3497,568 +3076,641 @@ CK_RV NSC_SetAttributeValue (CK_SESSION_HANDLE hSession,
}
pk11_FreeObject(object);
- return CKR_OK;
+ return crv;
}
-/* stolen from keydb.c */
-#define KEYDB_PW_CHECK_STRING "password-check"
-#define KEYDB_PW_CHECK_LEN 14
-
-SECKEYLowPrivateKey * SECKEY_DecryptKey(DBT *key, SECItem *pwitem,
- SECKEYKeyDBHandle *handle);
-typedef struct pk11keyNodeStr {
- struct pk11keyNodeStr *next;
- SECKEYLowPrivateKey *privKey;
- CERTCertificate *cert;
- SECItem *pubItem;
-} pk11keyNode;
+/*
+ * 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
-typedef struct {
- PLArenaPool *arena;
- pk11keyNode *head;
+/*
+ * structure to collect key handles.
+ */
+typedef struct pk11CrlDataStr {
PK11Slot *slot;
-} keyList;
+ PK11SearchResults *searchHandles;
+ CK_ATTRIBUTE *template;
+ CK_ULONG templ_count;
+} pk11CrlData;
+
static SECStatus
-add_key_to_list(DBT *key, DBT *data, void *arg)
+pk11_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
{
- keyList *keylist;
- pk11keyNode *node;
- void *keydata;
- SECKEYLowPrivateKey *privKey = NULL;
+ pk11CrlData *crlData;
+ CK_OBJECT_HANDLE class_handle;
+ PK11Slot *slot;
- keylist = (keyList *)arg;
+ crlData = (pk11CrlData *)arg;
+ slot = crlData->slot;
- privKey = SECKEY_DecryptKey(key, keylist->slot->password,
- SECKEY_GetDefaultKeyDB());
- if ( privKey == NULL ) {
- goto loser;
+ class_handle = (type == certDBEntryTypeRevocation) ? PK11_TOKEN_TYPE_CRL :
+ PK11_TOKEN_KRL_HANDLE;
+ if (pk11_tokenMatch(slot, key, class_handle,
+ crlData->template, crlData->templ_count)) {
+ pk11_addHandle(crlData->searchHandles,
+ pk11_mkHandle(slot,key,class_handle));
}
+ return(SECSuccess);
+}
- /* allocate the node struct */
- node = (pk11keyNode*)PORT_ArenaZAlloc(keylist->arena, sizeof(pk11keyNode));
- if ( node == NULL ) {
- goto loser;
- }
-
- /* allocate room for key data */
- keydata = PORT_ArenaZAlloc(keylist->arena, key->size);
- if ( keydata == NULL ) {
- goto loser;
- }
+static void
+pk11_searchCrls(PK11Slot *slot, SECItem *derSubject, PRBool isKrl,
+ unsigned long classFlags, PK11SearchResults *search,
+ CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
+{
+ NSSLOWCERTCertDBHandle *certHandle = NULL;
- /* link node into list */
- node->next = keylist->head;
- keylist->head = node;
-
- node->privKey = privKey;
- switch (privKey->keyType) {
- case lowRSAKey:
- node->pubItem = &privKey->u.rsa.modulus;
- break;
- case lowDSAKey:
- node->pubItem = &privKey->u.dsa.publicValue;
- break;
- default:
- break;
- }
-
- return(SECSuccess);
-loser:
- if ( privKey ) {
- SECKEY_LowDestroyPrivateKey(privKey);
+ certHandle = slot->certDB;
+ if (certHandle == NULL) {
+ return;
}
- return(SECSuccess);
+ if (derSubject->data != NULL) {
+ SECItem *crl =
+ nsslowcert_FindCrlByKey(certHandle,derSubject,NULL,isKrl);
+
+ if (crl != NULL) {
+ pk11_addHandle(search, pk11_mkHandle(slot,derSubject,
+ isKrl ? PK11_TOKEN_KRL_HANDLE : PK11_TOKEN_TYPE_CRL));
+ }
+ } else {
+ pk11CrlData crlData;
+
+ /* traverse */
+ crlData.slot = slot;
+ crlData.searchHandles = search;
+ crlData.template = pTemplate;
+ crlData.templ_count = ulCount;
+ nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation,
+ pk11_crl_collect, (void *)&crlData);
+ nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation,
+ pk11_crl_collect, (void *)&crlData);
+ }
}
/*
- * If the cert is a user cert, then try to match it to a key on the
- * linked list of private keys built earlier.
- * If the cert matches one on the list, then save it.
+ * structure to collect key handles.
*/
+typedef struct pk11KeyDataStr {
+ PK11Slot *slot;
+ PK11SearchResults *searchHandles;
+ SECItem *id;
+ CK_ATTRIBUTE *template;
+ CK_ULONG templ_count;
+ unsigned long classFlags;
+ PRBool isLoggedIn;
+ PRBool strict;
+} pk11KeyData;
+
+
static SECStatus
-add_cert_to_list(CERTCertificate *cert, SECItem *k, void *pdata)
+pk11_key_collect(DBT *key, DBT *data, void *arg)
{
- keyList *keylist;
- pk11keyNode *node;
- SECKEYPublicKey *pubKey = NULL;
- SECItem *pubItem;
- CERTCertificate *oldcert;
-
- keylist = (keyList *)pdata;
+ pk11KeyData *keyData;
+ NSSLOWKEYPrivateKey *privKey = NULL;
+ SECItem tmpDBKey;
+ PK11Slot *slot;
- /* only if it is a user cert and has a nickname!! */
- if ( ( ( cert->trust->sslFlags & CERTDB_USER ) ||
- ( cert->trust->emailFlags & CERTDB_USER ) ||
- ( cert->trust->objectSigningFlags & CERTDB_USER ) ) &&
- ( cert->nickname != NULL ) ) {
-
- /* get cert's public key */
- pubKey = CERT_ExtractPublicKey(cert);
- if ( pubKey == NULL ) {
- goto done;
- }
-
- /* pk11_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.
- */
- pubItem = pk11_GetPubItem(pubKey);
- if (pubItem == NULL) goto done;
-
- node = keylist->head;
- while ( node ) {
- /* if key type is different, then there is no match */
- if (node->privKey->keyType == seckeyLow_KeyType(pubKey->keyType)) {
-
- /* compare public value from cert with public value from
- * the key
- */
- if ( SECITEM_CompareItem(pubItem, node->pubItem) == SECEqual ){
- /* this is a match */
-
- /* if no cert has yet been found for this key, or this
- * cert is newer, then save this cert
- */
- if ( ( node->cert == NULL ) ||
- CERT_IsNewer(cert, node->cert ) ) {
-
- oldcert = node->cert;
-
- /* get a real DB copy of the cert, since the one
- * passed in here is not properly recorded in the
- * temp database
- */
-
- /* We need a better way to deal with this */
- node->cert =
- CERT_FindCertByKeyNoLocking(CERT_GetDefaultCertDB(),
- &cert->certKey);
-
- /* free the old cert if there was one */
- if ( oldcert ) {
- CERT_DestroyCertificate(oldcert);
- }
- }
- }
+ keyData = (pk11KeyData *)arg;
+ slot = keyData->slot;
+
+ tmpDBKey.data = key->data;
+ tmpDBKey.len = key->size;
+
+ PORT_Assert(slot->keyDB);
+ if (!keyData->strict && keyData->id) {
+ SECItem result;
+ unsigned char hashKey[SHA1_LENGTH];
+ result.data = hashKey;
+ result.len = sizeof(hashKey);
+
+ SHA1_HashBuf( hashKey, key->data, key->size );
+ if (SECITEM_ItemsAreEqual(keyData->id,&result)) {
+ if (keyData->classFlags & NSC_PRIVATE) {
+ pk11_addHandle(keyData->searchHandles,
+ pk11_mkHandle(slot,&tmpDBKey,PK11_TOKEN_TYPE_PRIV));
}
-
- node = node->next;
+ if (keyData->classFlags & NSC_PUBLIC) {
+ pk11_addHandle(keyData->searchHandles,
+ pk11_mkHandle(slot,&tmpDBKey,PK11_TOKEN_TYPE_PUB));
+ }
+ /* NSC_KEY Already handled */
}
+ return SECSuccess;
}
-done:
- if ( pubKey ) {
- SECKEY_DestroyPublicKey(pubKey);
+
+ privKey = nsslowkey_FindKeyByPublicKey(keyData->slot->keyDB, &tmpDBKey,
+ keyData->slot->password);
+ if ( privKey == NULL ) {
+ goto loser;
+ }
+
+ if (isSecretKey(privKey)) {
+ if ((keyData->classFlags & NSC_KEY) &&
+ pk11_tokenMatch(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_KEY,
+ keyData->template, keyData->templ_count)) {
+ pk11_addHandle(keyData->searchHandles,
+ pk11_mkHandle(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_KEY));
+ }
+ } else {
+ if ((keyData->classFlags & NSC_PRIVATE) &&
+ pk11_tokenMatch(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_PRIV,
+ keyData->template, keyData->templ_count)) {
+ pk11_addHandle(keyData->searchHandles,
+ pk11_mkHandle(keyData->slot,&tmpDBKey,PK11_TOKEN_TYPE_PRIV));
+ }
+ if ((keyData->classFlags & NSC_PUBLIC) &&
+ pk11_tokenMatch(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_PUB,
+ keyData->template, keyData->templ_count)) {
+ pk11_addHandle(keyData->searchHandles,
+ pk11_mkHandle(keyData->slot, &tmpDBKey,PK11_TOKEN_TYPE_PUB));
+ }
}
+loser:
+ if ( privKey ) {
+ nsslowkey_DestroyPrivateKey(privKey);
+ }
return(SECSuccess);
}
-#if 0
-/* This appears to be obsolete - TNH */
-static SECItem *
-decodeKeyDBGlobalSalt(DBT *saltData)
+static void
+pk11_searchKeys(PK11Slot *slot, SECItem *key_id, PRBool isLoggedIn,
+ unsigned long classFlags, PK11SearchResults *search,
+ CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
{
- SECItem *saltitem;
-
- saltitem = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if ( saltitem == NULL ) {
- return(NULL);
+ NSSLOWKEYDBHandle *keyHandle = NULL;
+ NSSLOWKEYPrivateKey *privKey;
+ pk11KeyData keyData;
+
+ keyHandle = slot->keyDB;
+ if (keyHandle == NULL) {
+ return;
}
-
- saltitem->data = (unsigned char *)PORT_ZAlloc(saltData->size);
- if ( saltitem->data == NULL ) {
- PORT_Free(saltitem);
- return(NULL);
+
+ if (key_id->data && (classFlags & NSC_KEY)) {
+ privKey = nsslowkey_FindKeyByPublicKey(keyHandle,key_id, slot->password);
+ if (privKey) {
+ pk11_addHandle(search,pk11_mkHandle(slot,key_id,PK11_TOKEN_TYPE_KEY));
+ nsslowkey_DestroyPrivateKey(privKey);
+ }
+ if ( !(classFlags & (NSC_PRIVATE|NSC_PUBLIC)) ) {
+ /* skip the traverse, nothing new to find */
+ return;
+ }
}
-
- saltitem->len = saltData->size;
- PORT_Memcpy(saltitem->data, saltData->data, saltitem->len);
-
- return(saltitem);
+ keyData.slot = slot;
+ keyData.searchHandles = search;
+ keyData.id = key_id;
+ keyData.template = pTemplate;
+ keyData.templ_count = ulCount;
+ keyData.isLoggedIn = isLoggedIn;
+ keyData.classFlags = classFlags;
+ keyData.strict = NSC_STRICT;
+
+ nsslowkey_TraverseKeys(keyHandle, pk11_key_collect, &keyData);
}
-#endif
-#if 0
/*
- * Create a (fixed) DES3 key [ testing ]
+ * structure to collect certs into
*/
-static unsigned char keyValue[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
-};
-
-static SECItem keyItem = {
- 0,
- keyValue,
- sizeof keyValue
-};
-
-static unsigned char keyID[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
+typedef struct pk11CertDataStr {
+ PK11Slot *slot;
+ int cert_count;
+ int max_cert_count;
+ NSSLOWCERTCertificate **certs;
+ CK_ATTRIBUTE *template;
+ CK_ULONG templ_count;
+ unsigned long classFlags;
+ PRBool strict;
+} pk11CertData;
-static SECItem keyIDItem = {
- 0,
- keyID,
- sizeof keyID
-};
-/* +AAA */
-static CK_RV
-pk11_createFixedDES3Key(PK11Slot *slot)
+/*
+ * collect all the certs from the traverse call.
+ */
+static SECStatus
+pk11_cert_collect(NSSLOWCERTCertificate *cert,void *arg)
{
- CK_RV rv = CKR_OK;
- PK11Object *keyObject;
- CK_BBOOL true = CK_TRUE;
- CK_OBJECT_CLASS class = CKO_SECRET_KEY;
- CK_KEY_TYPE keyType = CKK_DES3;
+ pk11CertData *cd = (pk11CertData *)arg;
- /*
- * Create the object
- */
- keyObject = pk11_NewObject(slot); /* fill in the handle later */
- if (keyObject == NULL) {
- return CKR_HOST_MEMORY;
+ if (cd->certs == NULL) {
+ return SECFailure;
}
- /* Add attributes to the object */
- rv = pk11_AddAttributeType(keyObject, CKA_ID, keyID, sizeof keyID);
- if (rv != CKR_OK) {
- pk11_FreeObject(keyObject);
- return rv;
+ if (cd->strict) {
+ if ((cd->classFlags & NSC_CERT) && !pk11_tokenMatch(cd->slot,
+ &cert->certKey, PK11_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) {
+ return SECSuccess;
+ }
+ if ((cd->classFlags & NSC_TRUST) && !pk11_tokenMatch(cd->slot,
+ &cert->certKey, PK11_TOKEN_TYPE_TRUST,
+ cd->template, cd->templ_count)) {
+ return SECSuccess;
+ }
}
- rv = pk11_AddAttributeType(keyObject, CKA_VALUE, keyValue, sizeof keyValue);
- if (rv != CKR_OK) {
- pk11_FreeObject(keyObject);
- return rv;
+ /* 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;
+ }
}
- rv = pk11_AddAttributeType(keyObject, CKA_TOKEN, &true, sizeof true);
- if (rv != CKR_OK) {
- pk11_FreeObject(keyObject);
- return rv;
- }
+ cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert);
+ return SECSuccess;
+}
- rv = pk11_AddAttributeType(keyObject, CKA_CLASS, &class, sizeof class);
- if (rv != CKR_OK) {
- pk11_FreeObject(keyObject);
- return rv;
- }
+/* provide impedence matching ... */
+static SECStatus
+pk11_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg)
+{
+ return pk11_cert_collect(cert, arg);
+}
- rv = pk11_AddAttributeType(keyObject, CKA_KEY_TYPE, &keyType, sizeof keyType);
- if (rv != CKR_OK) {
- pk11_FreeObject(keyObject);
- return rv;
+static void
+pk11_searchSingleCert(pk11CertData *certData,NSSLOWCERTCertificate *cert)
+{
+ if (cert == NULL) {
+ return;
}
+ if (certData->strict &&
+ !pk11_tokenMatch(certData->slot, &cert->certKey, PK11_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;
+}
- pk11_handleSecretKeyObject(keyObject, keyType, PR_TRUE);
-
- PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
- keyObject->handle = slot->tokenIDCount++;
- PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
- keyObject->slot = slot;
- keyObject->objclass = CKO_SECRET_KEY;
- pk11_AddSlotObject(slot, keyObject);
+static void
+pk11_CertSetupData(pk11CertData *certData,int count)
+{
+ certData->max_cert_count = count;
- return rv;
+ if (certData->max_cert_count <= 0) {
+ return;
+ }
+ certData->certs = (NSSLOWCERTCertificate **)
+ PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *));
+ return;
}
-#endif /* Fixed DES key */
-/*
- * load up our token database
- */
-static CK_RV
-pk11_importKeyDB(PK11Slot *slot)
+static void
+pk11_searchCertsAndTrust(PK11Slot *slot, SECItem *derCert, SECItem *name,
+ SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN,
+ unsigned long classFlags, PK11SearchResults *handles,
+ CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
{
- keyList keylist;
- pk11keyNode *node;
- CK_RV crv;
- SECStatus rv;
- PK11Object *privateKeyObject;
- PK11Object *publicKeyObject;
- PK11Object *certObject;
+ NSSLOWCERTCertDBHandle *certHandle = NULL;
+ pk11CertData certData;
+ int i;
- /* traverse the database, collecting the index keys of all
- * records into a linked list
- */
- keylist.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if ( keylist.arena == NULL ) {
- return CKR_HOST_MEMORY;
- }
- keylist.head = NULL;
- keylist.slot = slot;
-
- /* collect all of the keys */
- rv = SECKEY_TraverseKeys(SECKEY_GetDefaultKeyDB(),
- add_key_to_list, (void *)&keylist);
- if (rv != SECSuccess) {
- PORT_FreeArena(keylist.arena, PR_FALSE);
- return CKR_HOST_MEMORY;
- }
+ certHandle = slot->certDB;
+ if (certHandle == NULL) return;
- /* find certs that match any of the keys */
- crv = SEC_TraversePermCerts(CERT_GetDefaultCertDB(),
- add_cert_to_list, (void *)&keylist);
- if ( crv != SECSuccess ) {
- PORT_FreeArena(keylist.arena, PR_FALSE);
- return CKR_HOST_MEMORY;
- }
+ 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;
- /* now traverse the list and entry certs/keys into the
- * pkcs11 world
+
+ /*
+ * Find the Cert.
*/
- for (node = keylist.head; node != NULL; node=node->next ) {
- /* Check for "special" private key that wraps a symmetric key */
- if (isSecretKey(node->privKey)) {
- importSecretKey(slot, node->privKey);
- goto end_loop;
- }
-
- /* create the private key object */
- privateKeyObject = pk11_importPrivateKey(slot, node->privKey,
- node->pubItem);
- if ( privateKeyObject == NULL ) {
- goto end_loop;
- }
+ if (derCert->data != NULL) {
+ NSSLOWCERTCertificate *cert =
+ nsslowcert_FindCertByDERCert(certHandle,derCert);
+ pk11_searchSingleCert(&certData,cert);
+ } else if (name->data != NULL) {
+ char *tmp_name = (char*)PORT_Alloc(name->len+1);
+ int count;
- publicKeyObject = pk11_importPublicKey(slot, node->privKey, NULL,
- node->pubItem);
- if ( node->cert ) {
- /* Now import the Cert */
- certObject = pk11_importCertificate(slot, node->cert,
- node->pubItem->data,
- node->pubItem->len, PR_TRUE);
-
- /* Copy the subject */
- if ( certObject ) {
- /* NOTE: cert has been adopted */
- PK11Attribute *attribute;
-
- /* Copy the Subject */
- attribute = pk11_FindAttribute(certObject,CKA_SUBJECT);
- if (attribute) {
- pk11_forceAttribute(privateKeyObject,
- pk11_attr_expand(&attribute->attrib));
- if (publicKeyObject) {
- pk11_forceAttribute(publicKeyObject,
- pk11_attr_expand(&attribute->attrib));
- }
- pk11_FreeAttribute(attribute);
- }
- pk11_FreeObject(certObject);
- }
+ if (tmp_name == NULL) {
+ return;
}
+ PORT_Memcpy(tmp_name,name->data,name->len);
+ tmp_name[name->len] = 0;
- if ( publicKeyObject != NULL ) {
- pk11_AddSlotObject(slot, publicKeyObject);
- }
+ count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name);
+ pk11_CertSetupData(&certData,count);
+ nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name,
+ pk11_cert_collect, &certData);
+ PORT_Free(tmp_name);
+ } else if (derSubject->data != NULL) {
+ int count;
+
+ count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject);
+ pk11_CertSetupData(&certData,count);
+ nsslowcert_TraversePermCertsForSubject(certHandle,derSubject,
+ pk11_cert_collect, &certData);
+ } else if ((issuerSN->derIssuer.data != NULL) &&
+ (issuerSN->serialNumber.data != NULL)) {
+ NSSLOWCERTCertificate *cert =
+ nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN);
+
+ pk11_searchSingleCert(&certData,cert);
+ } else {
+ /* we aren't filtering the certs, we are working on all, so turn
+ * on the strict filters. */
+ certData.strict = PR_TRUE;
+ pk11_CertSetupData(&certData,NSC_CERT_BLOCK_SIZE);
+ nsslowcert_TraversePermCerts(certHandle, pk11_cert_collect2, &certData);
+ }
- pk11_AddSlotObject(slot, privateKeyObject);
+ /*
+ * build the handles
+ */
+ for (i=0 ; i < certData.cert_count ; i++) {
+ NSSLOWCERTCertificate *cert = certData.certs[i];
-end_loop:
- SECKEY_LowDestroyPrivateKey(node->privKey);
- if ( node->cert ) {
- CERT_DestroyCertificate(node->cert);
+ /* if we filtered it would have been on the stuff above */
+ if (classFlags & NSC_CERT) {
+ pk11_addHandle(handles,
+ pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_CERT));
}
-
+ if ((classFlags & NSC_TRUST) && nsslowcert_hasTrust(cert)) {
+ pk11_addHandle(handles,
+ pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_TRUST));
+ }
+ nsslowcert_DestroyCertificate(cert);
}
- PORT_FreeArena(keylist.arena, PR_FALSE);
- return CKR_OK;
+ if (certData.certs) PORT_Free(certData.certs);
+ return;
}
-/*
- * structure to collect certs into
- */
-typedef struct pk11CertDataStr {
- int cert_count;
- int max_cert_count;
- CERTCertificate **certs;
-} pk11CertData;
+static void
+pk11_searchSMime(PK11Slot *slot, SECItem *email, PK11SearchResults *handles,
+ CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
+{
+ NSSLOWCERTCertDBHandle *certHandle = NULL;
+ certDBEntrySMime *entry;
-/*
- * collect all the certs from the traverse call.
- */
-static SECStatus
-pk11_cert_collect(CERTCertificate *cert,void *arg) {
- pk11CertData *cd = (pk11CertData *)arg;
+ certHandle = slot->certDB;
+ if (certHandle == NULL) return;
- /* shouldn't happen, but don't crash if it does */
- if (cd->cert_count >= cd->max_cert_count) {
- PORT_Assert(0);
- return SECFailure;
- }
+ if (email->data != NULL) {
+ char *tmp_name = (char*)PORT_Alloc(email->len+1);
- cd->certs[cd->cert_count++] = CERT_DupCertificate(cert);
- return SECSuccess;
+ 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;
+ pk11_addHandle(handles,
+ pk11_mkHandle(slot,&emailKey,PK11_TOKEN_TYPE_SMIME));
+ nsslowcert_DestroyDBEntry((certDBEntry *)entry);
+ }
+ PORT_Free(tmp_name);
+ }
+ return;
}
-/*
- * find any certs that may match the template and load them.
- */
-static void
-pk11_searchCerts(PK11Slot *slot, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) {
+
+static CK_RV
+pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search,
+ 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 };
- CERTIssuerAndSN issuerSN = {
+ 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 },
- { NULL, NULL },
{ siBuffer, NULL, 0 }
};
SECItem *copy = NULL;
- CERTCertDBHandle *handle = NULL;
- SECKEYKeyDBHandle *keyHandle = NULL;
- pk11CertData certData;
+ unsigned long classFlags =
+ NSC_CERT|NSC_TRUST|NSC_PRIVATE|NSC_PUBLIC|NSC_KEY|NSC_SMIME ;
+ /* if we aren't logged in, don't look for private or secret keys */
+ if (!isLoggedIn) {
+ classFlags &= ~(NSC_PRIVATE|NSC_KEY);
+ }
/*
- * These should be stored in the slot some day in the future
- */
- handle = CERT_GetDefaultCertDB();
- if (handle == NULL) return;
- keyHandle = SECKEY_GetDefaultKeyDB();
- if (keyHandle == NULL) return;
-
- /*
- * look for things to search on certs for. We only need one of these
- * items. If we find all the certs that match that item, import them
- * (as long as they are user certs). We'll let find objects filter out
- * the ones that don't apply.
+ * 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 ;i < (int)ulCount; i++) {
+ for (i=0 ;classFlags && i < (int)ulCount; i++) {
switch (pTemplate[i].type) {
- case CKA_SUBJECT: copy = &derSubject; break;
- case CKA_ISSUER: copy = &issuerSN.derIssuer; break;
- case CKA_SERIAL_NUMBER: copy = &issuerSN.serialNumber; break;
- case CKA_VALUE: copy = &derCert; break;
- case CKA_LABEL: copy = &name; break;
+ case CKA_SUBJECT:
+ copy = &derSubject;
+ classFlags &= (NSC_CERT|NSC_PRIVATE|NSC_PUBLIC|NSC_SMIME);
+ break;
+ case CKA_ISSUER:
+ copy = &issuerSN.derIssuer;
+ classFlags &= (NSC_CERT|NSC_CRL|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;
+ break;
+ case CKA_NETSCAPE_SMIME_TIMESTAMP:
+ classFlags &= NSC_SMIME;
+ break;
case CKA_CLASS:
if (pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS)) {
- return;
+ classFlags = 0;
+ break;;
}
- if (*((CK_OBJECT_CLASS *)pTemplate[i].pValue) != CKO_CERTIFICATE) {
- return;
+ 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;
}
- copy = NULL; break;
+ break;
case CKA_PRIVATE:
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
- return;
+ 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_FALSE) {
- return;
+ if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
+ classFlags &= (NSC_PRIVATE|NSC_KEY);
+ } else {
+ classFlags = 0;
}
- copy = NULL; break;
+ break;
case CKA_TOKEN:
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
- return;
+ classFlags = 0;
}
- if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
- return;
+ if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
+ *tokenOnly = PR_TRUE;
+ } else {
+ classFlags = 0;
}
- copy = NULL; break;
+ 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:
- copy = NULL; break;
+ 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: return;
+ default:
+ classFlags = 0;
+ break;
}
if (copy) {
copy->data = (unsigned char*)pTemplate[i].pValue;
copy->len = pTemplate[i].ulValueLen;
}
+ copy = NULL;
}
- certData.max_cert_count = 0;
- certData.certs = NULL;
- certData.cert_count = 0;
-
- if (derCert.data != NULL) {
- CERTCertificate *cert = CERT_FindCertByDERCert(handle,&derCert);
- if (cert != NULL) {
- certData.certs =
- (CERTCertificate **) PORT_Alloc(sizeof (CERTCertificate *));
- if (certData.certs) {
- certData.certs[0] = cert;
- certData.cert_count = 1;
- } else CERT_DestroyCertificate(cert);
- }
- } else if (name.data != NULL) {
- char *tmp_name = (char*)PORT_Alloc(name.len+1);
-
- if (tmp_name == NULL) {
- return;
- }
- PORT_Memcpy(tmp_name,name.data,name.len);
- tmp_name[name.len] = 0;
-
- certData.max_cert_count=CERT_NumPermCertsForNickname(handle,tmp_name);
- if (certData.max_cert_count > 0) {
- certData.certs = (CERTCertificate **)
- PORT_Alloc(certData.max_cert_count *sizeof(CERTCertificate *));
- if (certData.certs) {
- CERT_TraversePermCertsForNickname(handle,tmp_name,
- pk11_cert_collect, &certData);
- }
-
- }
- PORT_Free(tmp_name);
- } else if (derSubject.data != NULL) {
- certData.max_cert_count=CERT_NumPermCertsForSubject(handle,&derSubject);
- if (certData.max_cert_count > 0) {
- certData.certs = (CERTCertificate **)
- PORT_Alloc(certData.max_cert_count *sizeof(CERTCertificate *));
- if (certData.certs) {
- CERT_TraversePermCertsForSubject(handle,&derSubject,
- pk11_cert_collect, &certData);
- }
- }
- } else if ((issuerSN.derIssuer.data != NULL) &&
- (issuerSN.serialNumber.data != NULL)) {
- CERTCertificate *cert = CERT_FindCertByIssuerAndSN(handle,&issuerSN);
-
- if (cert != NULL) {
- certData.certs =
- (CERTCertificate **) PORT_Alloc(sizeof (CERTCertificate *));
- if (certData.certs) {
- certData.certs[0] = cert;
- certData.cert_count = 1;
- } else CERT_DestroyCertificate(cert);
- }
- } else {
- /* PORT_Assert(0); may get called when not looking for certs */
- /* look up all the certs sometime, and get rid of the assert */;
+ /* certs */
+ if (classFlags & (NSC_CERT|NSC_TRUST)) {
+ pk11_searchCertsAndTrust(slot,&derCert,&name,&derSubject,
+ &issuerSN,classFlags,search,
+ pTemplate, ulCount);
}
+ /* keys */
+ if (classFlags & (NSC_PRIVATE|NSC_PUBLIC|NSC_KEY)) {
+ pk11_searchKeys(slot, &key_id, isLoggedIn, classFlags, search,
+ pTemplate, ulCount);
+ }
- for (i=0 ; i < certData.cert_count ; i++) {
- CERTCertificate *cert = certData.certs[i];
-
- /* we are only interested in permanment user certs here */
- if ((cert->isperm) && (cert->trust) &&
- (( cert->trust->sslFlags & CERTDB_USER ) ||
- ( cert->trust->emailFlags & CERTDB_USER ) ||
- ( cert->trust->objectSigningFlags & CERTDB_USER )) &&
- ( cert->nickname != NULL ) &&
- (SECKEY_KeyForCertExists(keyHandle, cert) == SECSuccess)) {
- PK11Object *obj;
- pk11_importCertificate(slot, cert, NULL, 0, PR_FALSE);
- obj = pk11_importPublicKey(slot, NULL, cert, NULL);
- if (obj) pk11_AddSlotObject(slot, obj);
- }
- CERT_DestroyCertificate(cert);
+ /* crl's */
+ if (classFlags & NSC_CRL) {
+ pk11_searchCrls(slot, &derSubject, isKrl, classFlags, search,
+ pTemplate, ulCount);
+ }
+ /* Add S/MIME entry stuff */
+ if (classFlags & NSC_SMIME) {
+ pk11_searchSMime(slot, &email, search, pTemplate, ulCount);
}
- if (certData.certs) PORT_Free(certData.certs);
- return;
+ return CKR_OK;
}
@@ -4067,74 +3719,50 @@ pk11_searchCerts(PK11Slot *slot, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) {
CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession,
CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
{
- PK11ObjectListElement *objectList = NULL;
- PK11ObjectListElement *olp;
PK11SearchResults *search,*freeSearch;
- PK11Session *session;
+ PK11Session *session = NULL;
PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
- int count, i;
- CK_RV crv;
+ PRBool tokenOnly = PR_FALSE;
+ CK_RV crv = CKR_OK;
+ PRBool isLoggedIn;
session = pk11_SessionFromHandle(hSession);
if (session == NULL) {
- return CKR_SESSION_HANDLE_INVALID;
- }
-
- /* resync token objects with the data base */
- if ((session->info.slotID == PRIVATE_KEY_SLOT_ID) ||
- (session->info.slotID == FIPS_SLOT_ID)) {
- if (slot->DB_loaded == PR_FALSE) {
- /* if we aren't logged in, we can't unload all key keys
- * and certs. Just unload those certs we need for this search
- */
- if ((!slot->isLoggedIn) && (slot->needLogin)) {
- pk11_searchCerts(slot,pTemplate,ulCount);
- } else {
- pk11_importKeyDB(slot);
- slot->DB_loaded = PR_TRUE;
- }
- }
- }
-
-
- /* build list of found objects in the session */
- crv = pk11_searchObjectList(&objectList,slot->tokObjects,
- slot->objectLock, pTemplate, ulCount, (PRBool)((!slot->needLogin) ||
- slot->isLoggedIn));
- if (crv != CKR_OK) {
- pk11_FreeObjectList(objectList);
- pk11_FreeSession(session);
- return crv;
- }
-
-
- /* copy list to session */
- count = 0;
- for (olp = objectList; olp != NULL; olp = olp->next) {
- count++;
+ crv = CKR_SESSION_HANDLE_INVALID;
+ goto loser;
}
+
search = (PK11SearchResults *)PORT_Alloc(sizeof(PK11SearchResults));
if (search == NULL) {
- pk11_FreeObjectList(objectList);
- pk11_FreeSession(session);
- return CKR_HOST_MEMORY;
+ crv = CKR_HOST_MEMORY;
+ goto loser;
}
search->handles = (CK_OBJECT_HANDLE *)
- PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * count);
+ PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE);
if (search->handles == NULL) {
- PORT_Free(search);
- pk11_FreeObjectList(objectList);
- pk11_FreeSession(session);
- return CKR_HOST_MEMORY;
+ crv = CKR_HOST_MEMORY;
+ goto loser;
}
- for (i=0; i < count; i++) {
- search->handles[i] = objectList->object->handle;
- objectList = pk11_FreeObjectListElement(objectList);
+ search->index = 0;
+ search->size = 0;
+ search->array_size = NSC_SEARCH_BLOCK_SIZE;
+ isLoggedIn = (PRBool)((!slot->needLogin) || slot->isLoggedIn);
+
+ crv = pk11_searchTokenList(slot, search, pTemplate, ulCount, &tokenOnly,
+ isLoggedIn);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+
+ /* build list of found objects in the session */
+ if (!tokenOnly) {
+ crv = pk11_searchObjectList(search, slot->tokObjects,
+ slot->objectLock, pTemplate, ulCount, isLoggedIn);
+ }
+ if (crv != CKR_OK) {
+ goto loser;
}
- /* store the search info */
- search->index = 0;
- search->size = count;
if ((freeSearch = session->search) != NULL) {
session->search = NULL;
pk11_FreeSearch(freeSearch);
@@ -4142,6 +3770,15 @@ CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession,
session->search = search;
pk11_FreeSession(session);
return CKR_OK;
+
+loser:
+ if (freeSearch) {
+ pk11_FreeSearch(freeSearch);
+ }
+ if (session) {
+ pk11_FreeSession(session);
+ }
+ return crv;
}
@@ -4166,8 +3803,13 @@ CK_RV NSC_FindObjects(CK_SESSION_HANDLE hSession,
search = session->search;
left = session->search->size - session->search->index;
transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount;
- PORT_Memcpy(phObject,&search->handles[search->index],
- transfer*sizeof(CK_OBJECT_HANDLE_PTR));
+ if (transfer > 0) {
+ PORT_Memcpy(phObject,&search->handles[search->index],
+ transfer*sizeof(CK_OBJECT_HANDLE_PTR));
+ } else {
+ *phObject = CK_INVALID_HANDLE;
+ }
+
search->index += transfer;
if (search->index == search->size) {
session->search = NULL;
diff --git a/security/nss/lib/softoken/pkcs11.h b/security/nss/lib/softoken/pkcs11.h
index 9ada2625e..9b54421e7 100644
--- a/security/nss/lib/softoken/pkcs11.h
+++ b/security/nss/lib/softoken/pkcs11.h
@@ -16,7 +16,7 @@
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
- * Contributor(s):
+ * Contributor(s): RSA Labs
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
@@ -35,6 +35,9 @@
* is granted provided that it is identified as "RSA Security In.c Public-Key
* Cryptography Standards (PKCS)" in all material mentioning or referencing
* this document.
+ *
+ * The latest version of this header can be found at:
+ * http://www.rsalabs.com/pkcs/pkcs-11/index.html
*/
#ifndef _PKCS11_H_
#define _PKCS11_H_ 1
@@ -313,12 +316,4 @@ struct CK_FUNCTION_LIST {
}
#endif
-/*
-** Functions called directly by applications to configure the FIPS token.
-*/
-extern void PK11_ConfigurePKCS11(char *man, char *libdes, char *tokdes,
- char *ptokdes, char *slotdes, char *pslotdes, char *fslotdes,
- char *fpslotdes, int minPwd, int pwdRequired);
-extern void PK11_ConfigureFIPS(char *slotdes, char *pslotdes);
-
#endif
diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c
index 32eef81ca..cde08a599 100644
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -53,20 +53,20 @@
#include "blapi.h"
#include "pkcs11.h"
#include "pkcs11i.h"
-#include "keylow.h"
-#include "cert.h"
+#include "lowkeyi.h"
+#include "pcert.h"
#include "sechash.h"
#include "secder.h"
#include "secdig.h"
-#include "secpkcs5.h" /* We do PBE below */
+#include "lowpbe.h" /* We do PBE below */
#include "pkcs11t.h"
#include "secoid.h"
#include "alghmac.h"
#include "softoken.h"
#include "secasn1.h"
-#include "secmodi.h"
+/*#include "secmodi.h" */
-#include "certdb.h"
+#include "pcert.h"
#include "ssl3prot.h" /* for SSL3_RANDOM_LENGTH */
#define __PASTE(x,y) x##y
@@ -102,9 +102,9 @@ static void pk11_Null(void *data, PRBool freeit)
* other free routines to the destroy signature.
*/
static void
-pk11_FreePrivKey(SECKEYLowPrivateKey *key, PRBool freeit)
+pk11_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit)
{
- SECKEY_LowDestroyPrivateKey(key);
+ nsslowkey_DestroyPrivateKey(key);
}
static void
@@ -119,11 +119,6 @@ pk11_Space(void *data, PRBool freeit)
PORT_Free(data);
}
-static void pk11_FreeSignInfo(PK11HashSignInfo *data, PRBool freeit)
-{
- SECKEY_LowDestroyPrivateKey(data->key);
- PORT_Free(data);
-}
/*
* turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
@@ -176,9 +171,9 @@ pk11_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
static CK_RV
-pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+pk11_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype,
- PK11ContextType contextType);
+ PK11ContextType contextType, PRBool isEncrypt);
/*
* Calculate a Lynx checksum for CKM_LYNX_WRAP mechanism.
*/
@@ -206,7 +201,8 @@ pk11_calcLynxChecksum(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hWrapKey,
/* encrypt with key 1 */
- crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT);
+ crv = pk11_CryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT,
+ PR_TRUE);
if (crv != CKR_OK) return crv;
crv = NSC_Encrypt(hSession,key,len,E,&Elen);
@@ -215,7 +211,8 @@ pk11_calcLynxChecksum(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hWrapKey,
E[8] = (sum2 >> 8) & 0xff;
E[9] = sum2 & 0xff;
- crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT);
+ crv = pk11_CryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT,
+ PR_TRUE);
if (crv != CKR_OK) return crv;
crv = NSC_Encrypt(hSession,&E[2],len,C,&Clen);
@@ -422,18 +419,19 @@ pk11_InitGeneric(PK11Session *session,PK11SessionContext **contextPtr,
context->hashInfo = NULL;
context->doPad = PR_FALSE;
context->padDataLength = 0;
+ context->key = key;
*contextPtr = context;
return CKR_OK;
}
-/* NSC_EncryptInit initializes an encryption operation. */
+/* NSC_CryptInit initializes an encryption/Decryption operation. */
/* This function is used by NSC_EncryptInit and NSC_WrapKey. The only difference
* in their uses if whether or not etype is CKA_ENCRYPT or CKA_WRAP */
static CK_RV
-pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+pk11_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype,
- PK11ContextType contextType)
+ PK11ContextType contextType, PRBool isEncrypt)
{
PK11Session *session;
PK11Object *key;
@@ -446,7 +444,6 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
#endif
CK_KEY_TYPE key_type;
CK_RV crv = CKR_OK;
- SECKEYLowPublicKey *pubKey;
unsigned effectiveKeyLength;
unsigned char newdeskey[8];
PRBool useNewKey=PR_FALSE;
@@ -456,7 +453,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
crv = pk11_InitGeneric(session,&context,contextType,&key,hKey,&key_type,
- CKO_PUBLIC_KEY, etype);
+ isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, etype);
if (crv != CKR_OK) {
pk11_FreeSession(session);
@@ -472,14 +469,22 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
break;
}
context->multi = PR_FALSE;
- pubKey = pk11_GetPubKey(key,CKK_RSA);
- if (pubKey == NULL) {
+ context->cipherInfo = isEncrypt ?
+ (void *)pk11_GetPubKey(key,CKK_RSA) :
+ (void *)pk11_GetPrivKey(key,CKK_RSA);
+ if (context->cipherInfo == NULL) {
crv = CKR_HOST_MEMORY;
break;
}
- context->cipherInfo = pubKey;
- context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509
- ? RSA_EncryptRaw : RSA_EncryptBlock);
+ if (isEncrypt) {
+ context->update = (PK11Cipher)
+ (pMechanism->mechanism == CKM_RSA_X_509
+ ? RSA_EncryptRaw : RSA_EncryptBlock);
+ } else {
+ context->update = (PK11Cipher)
+ (pMechanism->mechanism == CKM_RSA_X_509
+ ? RSA_DecryptRaw : RSA_DecryptBlock);
+ }
context->destroy = pk11_Null;
break;
case CKM_RC2_CBC_PAD:
@@ -509,7 +514,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
crv = CKR_HOST_MEMORY;
break;
}
- context->update = (PK11Cipher) RC2_Encrypt;
+ context->update = (PK11Cipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt);
context->destroy = (PK11Destroy) RC2_DestroyContext;
break;
#if NSS_SOFTOKEN_DOES_RC5
@@ -541,7 +546,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
crv = CKR_HOST_MEMORY;
break;
}
- context->update = (PK11Cipher) RC5_Encrypt;
+ context->update = (PK11Cipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt);
context->destroy = (PK11Destroy) RC5_DestroyContext;
break;
#endif
@@ -563,7 +568,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
crv = CKR_HOST_MEMORY; /* WRONG !!! */
break;
}
- context->update = (PK11Cipher) RC4_Encrypt;
+ context->update = (PK11Cipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt);
context->destroy = (PK11Destroy) RC4_DestroyContext;
break;
case CKM_CDMF_CBC_PAD:
@@ -630,13 +635,13 @@ finish_des:
}
context->cipherInfo = DES_CreateContext(
useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue,
- (unsigned char*)pMechanism->pParameter,t, PR_TRUE);
+ (unsigned char*)pMechanism->pParameter,t, isEncrypt);
pk11_FreeAttribute(att);
if (context->cipherInfo == NULL) {
crv = CKR_HOST_MEMORY;
break;
}
- context->update = (PK11Cipher) DES_Encrypt;
+ context->update = (PK11Cipher) (isEncrypt ? DES_Encrypt : DES_Decrypt);
context->destroy = (PK11Destroy) DES_DestroyContext;
break;
@@ -659,13 +664,13 @@ finish_des:
(unsigned char*)att->attrib.pValue,
(unsigned char*)pMechanism->pParameter,
pMechanism->mechanism == CKM_AES_ECB ? NSS_AES : NSS_AES_CBC,
- PR_TRUE, att->attrib.ulValueLen, 16);
+ isEncrypt, att->attrib.ulValueLen, 16);
pk11_FreeAttribute(att);
if (context->cipherInfo == NULL) {
crv = CKR_HOST_MEMORY;
break;
}
- context->update = (PK11Cipher) AES_Encrypt;
+ context->update = (PK11Cipher) (isEncrypt ? AES_Encrypt : AES_Decrypt);
context->destroy = (PK11Destroy) AES_DestroyContext;
break;
@@ -674,7 +679,6 @@ finish_des:
break;
}
- pk11_FreeObject(key);
if (crv != CKR_OK) {
pk11_FreeContext(context);
pk11_FreeSession(session);
@@ -689,8 +693,8 @@ finish_des:
CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
{
- return pk11_EncryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT,
- PK11_ENCRYPT);
+ return pk11_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT,
+ PK11_ENCRYPT, PR_TRUE);
}
/* NSC_EncryptUpdate continues a multiple-part encryption operation. */
@@ -846,258 +850,11 @@ CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
*/
/* NSC_DecryptInit initializes a decryption operation. */
-static CK_RV pk11_DecryptInit( CK_SESSION_HANDLE hSession,
- CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE dtype,
- PK11ContextType contextType)
-{
- PK11Session *session;
- PK11Object *key;
- PK11Attribute *att;
- PK11SessionContext *context;
- CK_RC2_CBC_PARAMS *rc2_param;
-#if NSS_SOFTOKEN_DOES_RC5
- CK_RC5_CBC_PARAMS *rc5_param;
- SECItem rc5Key;
-#endif
- CK_KEY_TYPE key_type;
- CK_RV crv = CKR_OK;
- unsigned effectiveKeyLength;
- SECKEYLowPrivateKey *privKey;
- unsigned char newdeskey[8];
- PRBool useNewKey=PR_FALSE;
- int t;
-
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
-
- crv = pk11_InitGeneric(session,&context,contextType,&key,hKey,&key_type,
- CKO_PRIVATE_KEY,dtype);
- if (crv != CKR_OK) {
- pk11_FreeSession(session);
- return crv;
- }
-
- /*
- * now handle each mechanism
- */
- switch(pMechanism->mechanism) {
- case CKM_RSA_PKCS:
- case CKM_RSA_X_509:
- if (key_type != CKK_RSA) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- context->multi = PR_FALSE;
- privKey = pk11_GetPrivKey(key,CKK_RSA);
- if (privKey == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- context->cipherInfo = privKey;
- context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509
- ? RSA_DecryptRaw : RSA_DecryptBlock);
- context->destroy = (context->cipherInfo == key->objectInfo) ?
- (PK11Destroy) pk11_Null : (PK11Destroy) pk11_FreePrivKey;
- break;
- case CKM_RC2_CBC_PAD:
- context->doPad = PR_TRUE;
- context->blockSize = 8;
- /* fall thru */
- case CKM_RC2_ECB:
- case CKM_RC2_CBC:
- if (key_type != CKK_RC2) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- att = pk11_FindAttribute(key,CKA_VALUE);
- rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
- effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8;
- context->cipherInfo = RC2_CreateContext((unsigned char*)att->attrib.pValue,
- att->attrib.ulValueLen, rc2_param->iv,
- pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 :
- NSS_RC2_CBC, effectiveKeyLength);
- pk11_FreeAttribute(att);
- if (context->cipherInfo == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- context->update = (PK11Cipher) RC2_Decrypt;
- context->destroy = (PK11Destroy) RC2_DestroyContext;
- break;
-#if NSS_SOFTOKEN_DOES_RC5
- case CKM_RC5_CBC_PAD:
- context->doPad = PR_TRUE;
- /* fall thru */
- case CKM_RC5_ECB:
- case CKM_RC5_CBC:
- if (key_type != CKK_RC5) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- att = pk11_FindAttribute(key,CKA_VALUE);
- if (att == NULL) {
- crv = CKR_KEY_HANDLE_INVALID;
- break;
- }
- rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
- if (context->doPad) {
- context->blockSize = rc5_param->ulWordsize*2;
- }
- rc5Key.data = (unsigned char*)att->attrib.pValue;
- rc5Key.len = att->attrib.ulValueLen;
- context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds,
- rc5_param->ulWordsize,rc5_param->pIv,
- pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
- pk11_FreeAttribute(att);
- if (context->cipherInfo == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- context->update = (PK11Cipher) RC5_Decrypt;
- context->destroy = (PK11Destroy) RC5_DestroyContext;
- break;
-#endif
- case CKM_RC4:
- if (key_type != CKK_RC4) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- att = pk11_FindAttribute(key,CKA_VALUE);
- context->cipherInfo =
- RC4_CreateContext((unsigned char*)att->attrib.pValue,
- att->attrib.ulValueLen);
- pk11_FreeAttribute(att);
- if (context->cipherInfo == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- context->update = (PK11Cipher) RC4_Decrypt;
- context->destroy = (PK11Destroy) RC4_DestroyContext;
- break;
- case CKM_CDMF_CBC_PAD:
- context->doPad = PR_TRUE;
- context->blockSize = 8;
- /* fall thru */
- case CKM_CDMF_ECB:
- case CKM_CDMF_CBC:
- if (key_type != CKK_CDMF) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
- useNewKey = PR_TRUE;
- if (crv != CKR_OK) break;
- goto finish_des;
- case CKM_DES_ECB:
- if (key_type != CKK_DES) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- t = NSS_DES;
- goto finish_des;
- case CKM_DES_CBC_PAD:
- context->doPad = PR_TRUE;
- context->blockSize = 8;
- /* fall thru */
- case CKM_DES_CBC:
- if (key_type != CKK_DES) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- t = NSS_DES_CBC;
- goto finish_des;
- case CKM_DES3_ECB:
- if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- t = NSS_DES_EDE3;
- goto finish_des;
- case CKM_DES3_CBC_PAD:
- context->doPad = PR_TRUE;
- context->blockSize = 8;
- /* fall thru */
- case CKM_DES3_CBC:
- if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- t = NSS_DES_EDE3_CBC;
-finish_des:
- att = pk11_FindAttribute(key,CKA_VALUE);
- if (att == NULL) {
- crv = CKR_KEY_HANDLE_INVALID;
- break;
- }
- if (useNewKey) {
- crv = pk11_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey);
- if (crv != CKR_OK) {
- pk11_FreeAttribute(att);
- break;
- }
- }
- context->cipherInfo = DES_CreateContext(
- useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue,
- (unsigned char*)pMechanism->pParameter,t, PR_FALSE);
- pk11_FreeAttribute(att);
- if (context->cipherInfo == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- context->update = (PK11Cipher) DES_Decrypt;
- context->destroy = (PK11Destroy) DES_DestroyContext;
-
- break;
- case CKM_AES_CBC_PAD:
- context->doPad = PR_TRUE;
- context->blockSize = 16;
- /* fall thru */
- case CKM_AES_ECB:
- case CKM_AES_CBC:
- if (key_type != CKK_AES) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- att = pk11_FindAttribute(key,CKA_VALUE);
- if (att == NULL) {
- crv = CKR_KEY_HANDLE_INVALID;
- break;
- }
- context->cipherInfo = AES_CreateContext(
- (unsigned char*)att->attrib.pValue,
- (unsigned char*)pMechanism->pParameter,
- pMechanism->mechanism == CKM_AES_ECB ? NSS_AES : NSS_AES_CBC,
- PR_FALSE, att->attrib.ulValueLen,16);
- pk11_FreeAttribute(att);
- if (context->cipherInfo == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- context->update = (PK11Cipher) AES_Decrypt;
- context->destroy = (PK11Destroy) AES_DestroyContext;
-
- break;
- default:
- crv = CKR_MECHANISM_INVALID;
- break;
- }
-
- pk11_FreeObject(key);
- if (crv != CKR_OK) {
- pk11_FreeContext(context);
- pk11_FreeSession(session);
- return crv;
- }
- pk11_SetContextByType(session, contextType, context);
- pk11_FreeSession(session);
- return CKR_OK;
-}
-
-/* NSC_DecryptInit initializes a decryption operation. */
CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
{
- return pk11_DecryptInit(hSession,pMechanism,hKey,CKA_DECRYPT,PK11_DECRYPT);
+ return pk11_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT,
+ PK11_DECRYPT, PR_FALSE);
}
/* NSC_DecryptUpdate continues a multiple-part decryption operation. */
@@ -1448,17 +1205,19 @@ pk11_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen,
* common HMAC initalization routine
*/
static CK_RV
-pk11_doHMACInit(PK11SessionContext *context,SECOidTag oid,
+pk11_doHMACInit(PK11SessionContext *context,HASH_HashType hash,
PK11Object *key, CK_ULONG mac_size)
{
PK11Attribute *keyval;
HMACContext *HMACcontext;
CK_ULONG *intpointer;
+ const SECHashObject *hashObj = &SECRawHashObjects[hash];
keyval = pk11_FindAttribute(key,CKA_VALUE);
if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
- HMACcontext = HMAC_Create(oid, (const unsigned char*)keyval->attrib.pValue,
+ HMACcontext = HMAC_Create(hashObj,
+ (const unsigned char*)keyval->attrib.pValue,
keyval->attrib.ulValueLen);
context->hashInfo = HMACcontext;
context->multi = PR_TRUE;
@@ -1865,8 +1624,8 @@ pk11_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
return CKR_FUNCTION_NOT_SUPPORTED;
}
- crv = pk11_EncryptInit(hSession, &cbc_mechanism, hKey, keyUsage,
- contextType);
+ crv = pk11_CryptInit(hSession, &cbc_mechanism, hKey, keyUsage,
+ contextType, PR_TRUE);
if (crv != CKR_OK) return crv;
crv = pk11_GetContext(hSession,&context,contextType,PR_TRUE,NULL);
@@ -1926,7 +1685,7 @@ nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen,
void *dataBuf, unsigned int dataLen)
{
SECItem signature, digest;
- SECKEYLowPublicKey *key = (SECKEYLowPublicKey *)ctx;
+ NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
signature.data = (unsigned char *)sigBuf;
signature.len = sigLen;
@@ -1942,7 +1701,7 @@ nsc_DSA_Sign_Stub(void *ctx, void *sigBuf,
{
SECItem signature = { 0 }, digest;
SECStatus rv;
- SECKEYLowPrivateKey *key = (SECKEYLowPrivateKey *)ctx;
+ NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
(void)SECITEM_AllocItem(NULL, &signature, maxSigLen);
digest.data = (unsigned char *)dataBuf;
@@ -1984,7 +1743,7 @@ CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession,
PK11SessionContext *context;
CK_KEY_TYPE key_type;
CK_RV crv = CKR_OK;
- SECKEYLowPrivateKey *privKey;
+ NSSLOWKEYPrivateKey *privKey;
PK11HashSignInfo *info = NULL;
/* Block Cipher MACing Algorithms use a different Context init method..*/
@@ -2061,23 +1820,14 @@ finish_rsa:
/* OK, info is allocated only if we're doing hash and sign mechanism.
* It's necessary to be able to set the correct OID in the final
* signature.
- * Second, what's special about privKey == key->objectInfo?
- * Well we don't 'cache' token versions
- * of private keys because (1) it's sensitive data, and (2) it never
- * gets destroyed. Instead we grab the key out of the database as
- * necessary, but now the key is our context, and we need to free
- * it when we are done. Non-token private keys will get freed when
- * the user destroys the session object (or the session the session
- * object lives in) */
+ */
if (info) {
info->key = privKey;
context->cipherInfo = info;
- context->destroy = (privKey == key->objectInfo) ?
- (PK11Destroy)pk11_Space:(PK11Destroy)pk11_FreeSignInfo;
+ context->destroy = (PK11Destroy)pk11_Space;
} else {
context->cipherInfo = privKey;
- context->destroy = (privKey == key->objectInfo) ?
- (PK11Destroy)pk11_Null:(PK11Destroy)pk11_FreePrivKey;
+ context->destroy = (PK11Destroy)pk11_Null;
}
break;
@@ -2103,25 +1853,25 @@ finish_rsa:
break;
case CKM_MD2_HMAC_GENERAL:
- crv = pk11_doHMACInit(context,SEC_OID_MD2,key,
+ crv = pk11_doHMACInit(context,HASH_AlgMD2,key,
*(CK_ULONG *)pMechanism->pParameter);
break;
case CKM_MD2_HMAC:
- crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH);
+ crv = pk11_doHMACInit(context,HASH_AlgMD2,key,MD2_LENGTH);
break;
case CKM_MD5_HMAC_GENERAL:
- crv = pk11_doHMACInit(context,SEC_OID_MD5,key,
+ crv = pk11_doHMACInit(context,HASH_AlgMD5,key,
*(CK_ULONG *)pMechanism->pParameter);
break;
case CKM_MD5_HMAC:
- crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH);
+ crv = pk11_doHMACInit(context,HASH_AlgMD5,key,MD5_LENGTH);
break;
case CKM_SHA_1_HMAC_GENERAL:
- crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,
+ crv = pk11_doHMACInit(context,HASH_AlgSHA1,key,
*(CK_ULONG *)pMechanism->pParameter);
break;
case CKM_SHA_1_HMAC:
- crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH);
+ crv = pk11_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH);
break;
case CKM_SSL3_MD5_MAC:
crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key,
@@ -2139,9 +1889,8 @@ finish_rsa:
break;
}
- pk11_FreeObject(key);
if (crv != CKR_OK) {
- PORT_Free(context);
+ pk11_FreeContext(context);
pk11_FreeSession(session);
return crv;
}
@@ -2363,7 +2112,7 @@ pk11_hashCheckSign(PK11HashVerifyInfo *info, unsigned char *sig,
if (info->key == NULL) goto loser;
- it.len = SECKEY_LowPublicModulusLen(info->key);
+ it.len = nsslowkey_PublicModulusLen(info->key);
if (!it.len) goto loser;
it.data = (unsigned char *) PORT_Alloc(it.len);
@@ -2407,7 +2156,7 @@ CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession,
PK11SessionContext *context;
CK_KEY_TYPE key_type;
CK_RV crv = CKR_OK;
- SECKEYLowPublicKey *pubKey;
+ NSSLOWKEYPublicKey *pubKey;
PK11HashVerifyInfo *info = NULL;
/* Block Cipher MACing Algorithms use a different Context init method..*/
@@ -2508,25 +2257,25 @@ finish_rsa:
break;
case CKM_MD2_HMAC_GENERAL:
- crv = pk11_doHMACInit(context,SEC_OID_MD2,key,
+ crv = pk11_doHMACInit(context,HASH_AlgMD2,key,
*(CK_ULONG *)pMechanism->pParameter);
break;
case CKM_MD2_HMAC:
- crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH);
+ crv = pk11_doHMACInit(context,HASH_AlgMD2,key,MD2_LENGTH);
break;
case CKM_MD5_HMAC_GENERAL:
- crv = pk11_doHMACInit(context,SEC_OID_MD5,key,
+ crv = pk11_doHMACInit(context,HASH_AlgMD5,key,
*(CK_ULONG *)pMechanism->pParameter);
break;
case CKM_MD5_HMAC:
- crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH);
+ crv = pk11_doHMACInit(context,HASH_AlgMD5,key,MD5_LENGTH);
break;
case CKM_SHA_1_HMAC_GENERAL:
- crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,
+ crv = pk11_doHMACInit(context,HASH_AlgSHA1,key,
*(CK_ULONG *)pMechanism->pParameter);
break;
case CKM_SHA_1_HMAC:
- crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH);
+ crv = pk11_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH);
break;
case CKM_SSL3_MD5_MAC:
crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key,
@@ -2544,7 +2293,6 @@ finish_rsa:
break;
}
- pk11_FreeObject(key);
if (crv != CKR_OK) {
PORT_Free(context);
pk11_FreeSession(session);
@@ -2650,7 +2398,7 @@ CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
PK11SessionContext *context;
CK_KEY_TYPE key_type;
CK_RV crv = CKR_OK;
- SECKEYLowPublicKey *pubKey;
+ NSSLOWKEYPublicKey *pubKey;
session = pk11_SessionFromHandle(hSession);
if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
@@ -2686,7 +2434,6 @@ CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
break;
}
- pk11_FreeObject(key);
if (crv != CKR_OK) {
PORT_Free(context);
pk11_FreeSession(session);
@@ -2755,105 +2502,50 @@ CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
**************************** Key Functions: ************************
*/
-CK_RV
-pk11_pbe_hmac_key_gen(CK_MECHANISM_PTR pMechanism, char *buf,
- unsigned long *len, PRBool faultyPBE3DES)
-{
- PBEBitGenContext *pbeCx;
- SECItem pwd, salt, *key;
- SECOidTag hashAlg;
- unsigned long keylenbits;
- CK_PBE_PARAMS *pbe_params = NULL;
- pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
- pwd.data = (unsigned char *)pbe_params->pPassword;
- pwd.len = (unsigned int)pbe_params->ulPasswordLen;
- salt.data = (unsigned char *)pbe_params->pSalt;
- salt.len = (unsigned int)pbe_params->ulSaltLen;
- switch (pMechanism->mechanism) {
- case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
- hashAlg = SEC_OID_SHA1; keylenbits = 160; break;
- case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
- hashAlg = SEC_OID_MD5; keylenbits = 128; break;
- case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
- hashAlg = SEC_OID_MD2; keylenbits = 128; break;
- default:
- return CKR_MECHANISM_INVALID;
- }
- pbeCx = PBE_CreateContext(hashAlg, pbeBitGenIntegrityKey, &pwd,
- &salt, keylenbits, pbe_params->ulIteration);
- key = PBE_GenerateBits(pbeCx);
- PORT_Memcpy(buf, key->data, key->len);
- *len = key->len;
- PBE_DestroyContext(pbeCx);
- SECITEM_ZfreeItem(key, PR_TRUE);
- return CKR_OK;
-}
/*
* generate a password based encryption key. This code uses
- * PKCS5 to do the work. Note that it calls PBE_PK11ParamToAlgid, which is
- * a utility function in secpkcs5.c. This function is used in here
- * and in PK11_ParamToAlgid.
+ * PKCS5 to do the work.
*/
-CK_RV
-pk11_pbe_key_gen(SECOidTag algtag,CK_MECHANISM_PTR pMechanism,
- char *buf,CK_ULONG *key_length, PRBool faulty3DES)
+static CK_RV
+nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
+ char *buf, CK_ULONG *key_length, PRBool faulty3DES)
{
- SECAlgorithmID algid;
- SECItem *pbe_key = NULL, mech;
+ SECItem *pbe_key = NULL, iv, pwitem;
CK_PBE_PARAMS *pbe_params = NULL;
- SECStatus pbe_rv;
*key_length = 0;
+ iv.data = NULL; iv.len = 0;
- mech.data = (unsigned char *)pMechanism->pParameter;
- mech.len = (unsigned int)pMechanism->ulParameterLen;
-
- /* A common routine to map from Params to AlgIDs for PBE
- * algorithms was created in secpkcs5.c. This function is
- * called both by PK11_ParamToAlgid and this function.
- */
- pbe_rv = PBE_PK11ParamToAlgid(algtag, &mech, NULL, &algid);
- if (pbe_rv != SECSuccess) {
- return CKR_DATA_INVALID;
- }
pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
- mech.data = (unsigned char *)pbe_params->pPassword;
- mech.len = (unsigned int)pbe_params->ulPasswordLen;
- pbe_key = SEC_PKCS5GetKey(&algid, &mech, faulty3DES);
+
+ pwitem.data = (unsigned char *)pbe_params->pPassword;
+ pwitem.len = (unsigned int)pbe_params->ulPasswordLen;
+ pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES);
if (pbe_key == NULL) {
- SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
return CKR_HOST_MEMORY;
}
+
PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
*key_length = pbe_key->len;
SECITEM_ZfreeItem(pbe_key, PR_TRUE);
pbe_key = NULL;
- if (pbe_params->pInitVector == NULL) {
- pbe_key = SEC_PKCS5GetIV(&algid, &mech, faulty3DES);
- if (pbe_key == NULL) {
- SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
- SECITEM_ZfreeItem(pbe_key, PR_TRUE);
- return CKR_HOST_MEMORY;
- }
+ if (iv.data && pbe_params->pInitVector == NULL) {
pbe_params->pInitVector = (CK_CHAR_PTR)PORT_ZAlloc(pbe_key->len);
if (pbe_params->pInitVector == NULL) {
- SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
- SECITEM_ZfreeItem(pbe_key, PR_TRUE);
return CKR_HOST_MEMORY;
}
- PORT_Memcpy(pbe_params->pInitVector, pbe_key->data, pbe_key->len);
+ PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len);
}
- SECITEM_ZfreeItem(pbe_key, PR_TRUE);
- SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
return CKR_OK;
}
static CK_RV
-nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism,
- CK_KEY_TYPE *key_type,CK_ULONG *key_length) {
+nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
+ CK_ULONG *key_length)
+{
CK_RV crv = CKR_OK;
switch (mechanism) {
@@ -2904,81 +2596,111 @@ nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism,
return crv;
}
+CK_RV
+nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
+{
+ SECItem salt;
+ CK_PBE_PARAMS *pbe_params = NULL;
+ NSSPKCS5PBEParameter *params;
+ PRArenaPool *arena = NULL;
+ SECStatus rv;
+
+ *pbe = NULL;
+
+ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (arena == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+
+ params = (NSSPKCS5PBEParameter *) PORT_ArenaZAlloc(arena,
+ sizeof(NSSPKCS5PBEParameter));
+ if (params == NULL) {
+ PORT_FreeArena(arena,PR_TRUE);
+ return CKR_HOST_MEMORY;
+ }
+
+ params->ivLen = 0;
+ params->pbeType = NSSPKCS5_PKCS12_V2;
+ params->hashType = HASH_AlgSHA1;
+ params->encAlg = SEC_OID_SHA1; /* any invalid value */
+ params->is2KeyDES = PR_FALSE;
+ params->keyID = pbeBitGenIntegrityKey;
+ params->iter = pbe_params->ulIteration;
+
+ pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
+ salt.data = (unsigned char *)pbe_params->pSalt;
+ salt.len = (unsigned int)pbe_params->ulSaltLen;
+ rv = SECITEM_CopyItem(arena,&params->salt,&salt);
+ if (rv != SECSuccess) {
+ PORT_FreeArena(arena,PR_TRUE);
+ return CKR_HOST_MEMORY;
+ }
+ switch (pMechanism->mechanism) {
+ case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
+ case CKM_PBA_SHA1_WITH_SHA1_HMAC:
+ params->hashType = HASH_AlgSHA1;
+ params->keyLen = 20;
+ break;
+ case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
+ params->hashType = HASH_AlgMD5;
+ params->keyLen = 16;
+ break;
+ case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
+ params->hashType = HASH_AlgMD2;
+ params->keyLen = 16;
+ break;
+ default:
+ PORT_FreeArena(arena,PR_TRUE);
+ return CKR_MECHANISM_INVALID;
+ }
+ *pbe = params;
+ return CKR_OK;
+}
+/* maybe this should be table driven? */
static CK_RV
-nsc_SetupPBEKeyGen(CK_MECHANISM_TYPE mechanism,SECOidTag *algtag,
- CK_KEY_TYPE *key_type,CK_ULONG *key_length) {
+nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
+ CK_KEY_TYPE *key_type)
+{
CK_RV crv = CKR_OK;
+ SECOidData *oid;
+ CK_PBE_PARAMS *pbe_params;
+ NSSPKCS5PBEParameter *params;
+ SECItem salt;
- switch (mechanism) {
- case CKM_PBE_MD2_DES_CBC:
- *algtag = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC;
+ oid = SECOID_FindOIDByMechanism(pMechanism->mechanism);
+ if (oid == NULL) {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
+ salt.data = (unsigned char *)pbe_params->pSalt;
+ salt.len = (unsigned int)pbe_params->ulSaltLen;
+
+ params=nsspkcs5_NewParam(oid->offset, &salt, pbe_params->ulIteration);
+ if (params == NULL) {
+ return CKR_MECHANISM_INVALID;
+ }
+
+
+ switch (params->encAlg) {
+ case SEC_OID_DES_CBC:
*key_type = CKK_DES;
break;
+ case SEC_OID_DES_EDE3_CBC:
+ *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
case CKM_PBE_MD5_DES_CBC:
- *algtag = SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC;
- *key_type = CKK_DES;
- break;
- case CKM_PBE_SHA1_RC4_40:
- *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
- *key_length = 5;
- *key_type = CKK_RC4;
- break;
- case CKM_PBE_SHA1_RC4_128:
- *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
- *key_length = 16;
- *key_type = CKK_RC4;
- break;
- case CKM_PBE_SHA1_RC2_40_CBC:
- *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
- *key_length = 5;
- *key_type = CKK_RC2;
- break;
- case CKM_PBE_SHA1_RC2_128_CBC:
- *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
- *key_length = 16;
- *key_type = CKK_RC2;
- break;
- case CKM_PBE_SHA1_DES3_EDE_CBC:
- *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
- *key_length = 24;
- *key_type = CKK_DES3;
- break;
- case CKM_PBE_SHA1_DES2_EDE_CBC:
- *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
- *key_length = 16;
- *key_type = CKK_DES2;
- break;
- case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
- *algtag = SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
*key_type = CKK_DES;
break;
- case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
- case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
- *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
- *key_type = CKK_DES3;
- break;
- case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
- *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
- *key_type = CKK_RC2;
- break;
- case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:
- *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
- *key_type = CKK_RC2;
- break;
- case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4:
- *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4;
+ case SEC_OID_RC2_CBC:
*key_type = CKK_RC4;
break;
- case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4:
- *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4;
+ case SEC_OID_RC4:
*key_type = CKK_RC4;
break;
default:
- PORT_Assert(0);
crv = CKR_MECHANISM_INVALID;
break;
}
-
return crv;
}
@@ -2998,8 +2720,8 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
int i;
PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
char buf[MAX_KEY_LEN];
- enum {pk11_pbe, pk11_pbe_hmac, pk11_ssl, pk11_bulk} key_gen_type;
- SECOidTag algtag = SEC_OID_UNKNOWN;
+ enum {nsc_pbe, nsc_ssl, nsc_bulk} key_gen_type;
+ NSSPKCS5PBEParameter *pbe_param;
SSL3RSAPreMasterSecret *rsa_pms;
CK_VERSION *version;
/* in very old versions of NSS, there were implementation errors with key
@@ -3040,7 +2762,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
pk11_DeleteAttributeType(key,CKA_VALUE);
/* Now Set up the parameters to generate the key (based on mechanism) */
- key_gen_type = pk11_bulk; /* bulk key by default */
+ key_gen_type = nsc_bulk; /* bulk key by default */
switch (pMechanism->mechanism) {
case CKM_CDMF_KEY_GEN:
case CKM_DES_KEY_GEN:
@@ -3059,16 +2781,18 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
case CKM_SSL3_PRE_MASTER_KEY_GEN:
key_type = CKK_GENERIC_SECRET;
key_length = 48;
- key_gen_type = pk11_ssl;
+ key_gen_type = nsc_ssl;
break;
- case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
- faultyPBE3DES = PR_TRUE;
+ case CKM_PBA_SHA1_WITH_SHA1_HMAC:
case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
- key_gen_type = pk11_pbe_hmac;
+ key_gen_type = nsc_pbe;
key_type = CKK_GENERIC_SECRET;
+ crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
break;
+ case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
+ faultyPBE3DES = PR_TRUE;
case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
@@ -3083,9 +2807,8 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
case CKM_PBE_SHA1_RC4_40:
case CKM_PBE_MD5_DES_CBC:
case CKM_PBE_MD2_DES_CBC:
- key_gen_type = pk11_pbe;
- crv = nsc_SetupPBEKeyGen(pMechanism->mechanism,&algtag,
- &key_type,&key_length);
+ key_gen_type = nsc_pbe;
+ crv = nsc_SetupPBEKeyGen(pMechanism,&pbe_param, &key_type);
break;
default:
crv = CKR_MECHANISM_INVALID;
@@ -3109,15 +2832,11 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
* now to the actual key gen.
*/
switch (key_gen_type) {
- case pk11_pbe_hmac:
- crv = pk11_pbe_hmac_key_gen(pMechanism, buf, &key_length,
- faultyPBE3DES);
- break;
- case pk11_pbe:
- crv = pk11_pbe_key_gen(algtag, pMechanism, buf, &key_length,
+ case nsc_pbe:
+ crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length,
faultyPBE3DES);
break;
- case pk11_ssl:
+ case nsc_ssl:
rsa_pms = (SSL3RSAPreMasterSecret *)buf;
version = (CK_VERSION *)pMechanism->pParameter;
rsa_pms->client_version[0] = version->major;
@@ -3125,7 +2844,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
crv =
NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random));
break;
- case pk11_bulk:
+ case nsc_bulk:
/* get the key, check for weak keys and repeat if found */
do {
crv = NSC_GenerateRandom(0, (unsigned char *)buf, key_length);
@@ -3158,10 +2877,6 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
*/
crv = pk11_handleObject(key,session);
pk11_FreeSession(session);
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- return crv;
- }
if (pk11_isTrue(key,CKA_SENSITIVE)) {
pk11_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL));
}
@@ -3170,7 +2885,8 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
}
*phKey = key->handle;
- return CKR_OK;
+ pk11_FreeObject(key);
+ return crv;
}
@@ -3495,7 +3211,7 @@ dhgn_done:
/*
* handle the base object cleanup for the public Key
*/
- crv = pk11_handleObject(publicKey,session);
+ crv = pk11_handleObject(privateKey,session);
if (crv != CKR_OK) {
pk11_FreeSession(session);
pk11_FreeObject(privateKey);
@@ -3508,11 +3224,12 @@ dhgn_done:
* If we have any problems, we destroy the public Key we've
* created and linked.
*/
- crv = pk11_handleObject(privateKey,session);
+ crv = pk11_handleObject(publicKey,session);
pk11_FreeSession(session);
if (crv != CKR_OK) {
+ pk11_FreeObject(publicKey);
+ NSC_DestroyObject(hSession,privateKey->handle);
pk11_FreeObject(privateKey);
- NSC_DestroyObject(hSession,publicKey->handle);
return crv;
}
if (pk11_isTrue(privateKey,CKA_SENSITIVE)) {
@@ -3533,14 +3250,16 @@ dhgn_done:
}
*phPrivateKey = privateKey->handle;
*phPublicKey = publicKey->handle;
+ pk11_FreeObject(publicKey);
+ pk11_FreeObject(privateKey);
return CKR_OK;
}
static SECItem *pk11_PackagePrivateKey(PK11Object *key)
{
- SECKEYLowPrivateKey *lk = NULL;
- PrivateKeyInfo *pki = NULL;
+ NSSLOWKEYPrivateKey *lk = NULL;
+ NSSLOWKEYPrivateKeyInfo *pki = NULL;
PK11Attribute *attribute = NULL;
PLArenaPool *arena = NULL;
SECOidTag algorithm = SEC_OID_UNKNOWN;
@@ -3569,8 +3288,8 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key)
goto loser;
}
- pki = (PrivateKeyInfo*)PORT_ArenaZAlloc(arena,
- sizeof(PrivateKeyInfo));
+ pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPrivateKeyInfo));
if(!pki) {
rv = SECFailure;
goto loser;
@@ -3579,25 +3298,25 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key)
param = NULL;
switch(lk->keyType) {
- case lowRSAKey:
+ case NSSLOWKEYRSAKey:
dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
- SECKEY_LowRSAPrivateKeyTemplate);
+ nsslowkey_RSAPrivateKeyTemplate);
algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
break;
- case lowDSAKey:
+ case NSSLOWKEYDSAKey:
dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
- SECKEY_LowDSAPrivateKeyExportTemplate);
+ nsslowkey_DSAPrivateKeyExportTemplate);
param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
- SECKEY_LowPQGParamsTemplate);
+ nsslowkey_PQGParamsTemplate);
algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
break;
- case lowDHKey:
+ case NSSLOWKEYDHKey:
default:
dummy = NULL;
break;
}
- if(!dummy || ((lk->keyType == lowDSAKey) && !param)) {
+ if(!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
goto loser;
}
@@ -3609,14 +3328,14 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key)
}
dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
- SEC_PRIVATE_KEY_INFO_VERSION);
+ NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
if(!dummy) {
rv = SECFailure;
goto loser;
}
encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
- SECKEY_PrivateKeyInfoTemplate);
+ nsslowkey_PrivateKeyInfoTemplate);
loser:
if(arena) {
@@ -3624,7 +3343,7 @@ loser:
}
if(lk && (lk != key->objectInfo)) {
- SECKEY_LowDestroyPrivateKey(lk);
+ nsslowkey_DestroyPrivateKey(lk);
}
if(param) {
@@ -3680,8 +3399,8 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession,
len = *pulWrappedKeyLen;
}
- crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey,
- CKA_WRAP, PK11_ENCRYPT);
+ crv = pk11_CryptInit(hSession, pMechanism, hWrappingKey,
+ CKA_WRAP, PK11_ENCRYPT, PR_TRUE);
if (crv != CKR_OK) {
pk11_FreeAttribute(attribute);
break;
@@ -3712,8 +3431,8 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession,
break;
}
- crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey,
- CKA_WRAP, PK11_ENCRYPT);
+ crv = pk11_CryptInit(hSession, pMechanism, hWrappingKey,
+ CKA_WRAP, PK11_ENCRYPT, PR_TRUE);
if(crv != CKR_OK) {
SECITEM_ZfreeItem(bpki, PR_TRUE);
crv = CKR_KEY_TYPE_INCONSISTENT;
@@ -3747,8 +3466,8 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki)
const SEC_ASN1Template *keyTemplate, *paramTemplate;
void *paramDest = NULL;
PLArenaPool *arena;
- SECKEYLowPrivateKey *lpk = NULL;
- PrivateKeyInfo *pki = NULL;
+ NSSLOWKEYPrivateKey *lpk = NULL;
+ NSSLOWKEYPrivateKeyInfo *pki = NULL;
SECItem *ck_id = NULL;
CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
@@ -3757,21 +3476,21 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki)
return SECFailure;
}
- pki = (PrivateKeyInfo*)PORT_ArenaZAlloc(arena,
- sizeof(PrivateKeyInfo));
+ pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPrivateKeyInfo));
if(!pki) {
PORT_FreeArena(arena, PR_TRUE);
return SECFailure;
}
- if(SEC_ASN1DecodeItem(arena, pki, SECKEY_PrivateKeyInfoTemplate, bpki)
+ if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki)
!= SECSuccess) {
PORT_FreeArena(arena, PR_FALSE);
return SECFailure;
}
- lpk = (SECKEYLowPrivateKey *)PORT_ArenaZAlloc(arena,
- sizeof(SECKEYLowPrivateKey));
+ lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPrivateKey));
if(lpk == NULL) {
goto loser;
}
@@ -3779,18 +3498,18 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki)
switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
- keyTemplate = SECKEY_LowRSAPrivateKeyTemplate;
+ keyTemplate = nsslowkey_RSAPrivateKeyTemplate;
paramTemplate = NULL;
paramDest = NULL;
- lpk->keyType = lowRSAKey;
+ lpk->keyType = NSSLOWKEYRSAKey;
break;
case SEC_OID_ANSIX9_DSA_SIGNATURE:
- keyTemplate = SECKEY_LowDSAPrivateKeyExportTemplate;
- paramTemplate = SECKEY_LowPQGParamsTemplate;
+ keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
+ paramTemplate = nsslowkey_PQGParamsTemplate;
paramDest = &(lpk->u.dsa.params);
- lpk->keyType = lowDSAKey;
+ lpk->keyType = NSSLOWKEYDSAKey;
break;
- /* case lowDHKey: */
+ /* case NSSLOWKEYDHKey: */
default:
keyTemplate = NULL;
paramTemplate = NULL;
@@ -3818,7 +3537,7 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki)
rv = SECFailure;
switch (lpk->keyType) {
- case lowRSAKey:
+ case NSSLOWKEYRSAKey:
keyType = CKK_RSA;
if(pk11_hasAttribute(key, CKA_NETSCAPE_DB)) {
pk11_DeleteAttributeType(key, CKA_NETSCAPE_DB);
@@ -3862,7 +3581,7 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki)
crv = pk11_AddAttributeType(key, CKA_COEFFICIENT,
pk11_item_expand(&lpk->u.rsa.coefficient));
break;
- case lowDSAKey:
+ case NSSLOWKEYDSAKey:
keyType = CKK_DSA;
crv = (pk11_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK :
CKR_KEY_TYPE_INCONSISTENT;
@@ -3890,7 +3609,7 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki)
if(crv != CKR_OK) break;
break;
#ifdef notdef
- case lowDHKey:
+ case NSSLOWKEYDHKey:
template = dhTemplate;
templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE);
keyType = CKK_DH;
@@ -3908,7 +3627,7 @@ loser:
}
if(lpk) {
- SECKEY_LowDestroyPrivateKey(lpk);
+ nsslowkey_DestroyPrivateKey(lpk);
}
if(crv != CKR_OK) {
@@ -3972,8 +3691,8 @@ CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
ulWrappedKeyLen -= 2; /* don't decrypt the checksum */
}
- crv = pk11_DecryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP,
- PK11_DECRYPT);
+ crv = pk11_CryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP,
+ PK11_DECRYPT, PR_FALSE);
if (crv != CKR_OK) {
pk11_FreeObject(key);
return pk11_mapWrap(crv);
@@ -4050,14 +3769,11 @@ CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
* handle the base object stuff
*/
crv = pk11_handleObject(key,session);
+ *phKey = key->handle;
pk11_FreeSession(session);
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- return crv;
- }
+ pk11_FreeObject(key);
- *phKey = key->handle;
- return CKR_OK;
+ return crv;
}
@@ -4080,10 +3796,10 @@ pk11_buildSSLKey(CK_SESSION_HANDLE hSession, PK11Object *baseKey,
/*
* now lets create an object to hang the attributes off of
*/
- *keyHandle = CK_INVALID_KEY;
+ *keyHandle = CK_INVALID_HANDLE;
key = pk11_NewObject(baseKey->slot);
if (key == NULL) return CKR_HOST_MEMORY;
- key->wasDerived = PR_TRUE;
+ pk11_narrowToSessionObject(key)->wasDerived = PR_TRUE;
crv = pk11_CopyObject(key,baseKey);
if (crv != CKR_OK) goto loser;
@@ -4115,10 +3831,7 @@ pk11_buildSSLKey(CK_SESSION_HANDLE hSession, PK11Object *baseKey,
crv = pk11_handleObject(key,session);
pk11_FreeSession(session);
- if (crv == CKR_OK) {
- *keyHandle = key->handle;
- return crv;
- }
+ *keyHandle = key->handle;
loser:
if (key) pk11_FreeObject(key);
return crv;
@@ -4131,16 +3844,16 @@ loser:
static void
pk11_freeSSLKeys(CK_SESSION_HANDLE session,
CK_SSL3_KEY_MAT_OUT *returnedMaterial ) {
- if (returnedMaterial->hClientMacSecret != CK_INVALID_KEY) {
+ if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
NSC_DestroyObject(session,returnedMaterial->hClientMacSecret);
}
- if (returnedMaterial->hServerMacSecret != CK_INVALID_KEY) {
+ if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
}
- if (returnedMaterial->hClientKey != CK_INVALID_KEY) {
+ if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
NSC_DestroyObject(session, returnedMaterial->hClientKey);
}
- if (returnedMaterial->hServerKey != CK_INVALID_KEY) {
+ if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
NSC_DestroyObject(session, returnedMaterial->hServerKey);
}
}
@@ -4233,7 +3946,7 @@ pk11_MapKeySize(CK_KEY_TYPE keyType) {
/* TLS P_hash function */
static SECStatus
-pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label,
+pk11_P_hash(HASH_HashType hashType, const SECItem *secret, const char *label,
SECItem *seed, SECItem *result)
{
unsigned char state[PHASH_STATE_MAX_LEN];
@@ -4244,6 +3957,7 @@ pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label,
SECStatus status;
HMACContext *cx;
SECStatus rv = SECFailure;
+ const SECHashObject *hashObj = &SECRawHashObjects[hashType];
PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
PORT_Assert((seed != NULL) && (seed->data != NULL));
@@ -4255,7 +3969,7 @@ pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label,
if (label != NULL)
label_len = PORT_Strlen(label);
- cx = HMAC_Create(alg, secret->data, secret->len);
+ cx = HMAC_Create(hashObj, secret->data, secret->len);
if (cx == NULL)
goto loser;
@@ -4330,11 +4044,11 @@ pk11_PRF(const SECItem *secret, const char *label, SECItem *seed,
goto loser;
tmp.len = result->len;
- status = pk11_P_hash(SEC_OID_MD5, &S1, label, seed, result);
+ status = pk11_P_hash(HASH_AlgMD5, &S1, label, seed, result);
if (status != SECSuccess)
goto loser;
- status = pk11_P_hash(SEC_OID_SHA1, &S2, label, seed, &tmp);
+ status = pk11_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp);
if (status != SECSuccess)
goto loser;
@@ -4404,7 +4118,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
/*
* now lets create an object to hang the attributes off of
*/
- if (phKey) *phKey = CK_INVALID_KEY;
+ if (phKey) *phKey = CK_INVALID_HANDLE;
key = pk11_NewObject(slot); /* fill in the handle later */
if (key == NULL) {
@@ -4513,9 +4227,10 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
pMechanism->pParameter;
if (ssl3_master->pVersion) {
+ PK11SessionObject *sessKey = pk11_narrowToSessionObject(key);
rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue;
/* don't leak more key material then necessary for SSL to work */
- if (key->wasDerived) {
+ if ((sessKey == NULL) || sessKey->wasDerived) {
ssl3_master->pVersion->major = 0xff;
ssl3_master->pVersion->minor = 0xff;
} else {
@@ -4652,10 +4367,10 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
* clear out our returned keys so we can recover on failure
*/
ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
- ssl3_keys_out->hClientMacSecret = CK_INVALID_KEY;
- ssl3_keys_out->hServerMacSecret = CK_INVALID_KEY;
- ssl3_keys_out->hClientKey = CK_INVALID_KEY;
- ssl3_keys_out->hServerKey = CK_INVALID_KEY;
+ ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
+ ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
+ ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
+ ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
/*
* generate the key material: This looks amazingly similar to the
@@ -5222,8 +4937,10 @@ key_and_mac_derive_fail:
/* link the key object into the list */
if (key) {
+ PK11SessionObject *sessKey = pk11_narrowToSessionObject(key);
+ PORT_Assert(sessKey);
/* get the session */
- key->wasDerived = PR_TRUE;
+ sessKey->wasDerived = PR_TRUE;
session = pk11_SessionFromHandle(hSession);
if (session == NULL) {
pk11_FreeObject(key);
@@ -5232,10 +4949,7 @@ key_and_mac_derive_fail:
crv = pk11_handleObject(key,session);
pk11_FreeSession(session);
- if (crv == CKR_OK) {
- *phKey = key->handle;
- return crv;
- }
+ *phKey = key->handle;
pk11_FreeObject(key);
}
return crv;
diff --git a/security/nss/lib/softoken/pkcs11f.h b/security/nss/lib/softoken/pkcs11f.h
index 71ee2676a..70d34da5e 100644
--- a/security/nss/lib/softoken/pkcs11f.h
+++ b/security/nss/lib/softoken/pkcs11f.h
@@ -150,10 +150,11 @@ CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
CK_PKCS11_FUNCTION_INFO(C_InitToken)
#ifdef CK_NEED_ARG_LIST
(
- CK_SLOT_ID slotID, /* ID of the token's slot */
- CK_CHAR_PTR pPin, /* the SO's initial PIN */
- CK_ULONG ulPinLen, /* length in bytes of the PIN */
- CK_CHAR_PTR pLabel /* 32-byte token label (blank padded) */
+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_CHAR_PTR pPin, /* the SO's initial PIN */
+ CK_ULONG ulPinLen, /* length in bytes of the PIN */
+ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
);
#endif
diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h
index 2e924a4ef..c09b2635e 100644
--- a/security/nss/lib/softoken/pkcs11i.h
+++ b/security/nss/lib/softoken/pkcs11i.h
@@ -39,14 +39,67 @@
#include "nssilock.h"
#include "seccomon.h"
#include "secoidt.h"
-#include "keytlow.h"
+#include "lowkeyti.h"
#include "pkcs11t.h"
+#include "pcertt.h"
-#define PKCS11_USE_THREADS
-#define NO_ARENA
-#define MAX_OBJS_ATTRS 45
-#define ATTR_SPACE 50 /* hold up to a SSL premaster secret */
+/*
+ * Configuration Defines
+ *
+ * The following defines affect the space verse speed trade offs of
+ * the PKCS #11 module. For the most part the current settings are optimized
+ * for web servers, where we want faster speed and lower lock contention at
+ * the expense of space.
+ */
+
+#define PKCS11_USE_THREADS /* set to true of you are need threads */
+/*
+ * Attribute Allocation strategy:
+ *
+ * 1) static allocation (PKCS11_STATIC_ATTRIBUTES set
+ * PKCS11_REF_COUNT_ATTRIBUTES not set)
+ * Attributes are pre-allocated as part of the session object and used from
+ * the object array.
+ *
+ * 2) heap allocation with ref counting (PKCS11_STATIC_ATTRIBUTES not set
+ * PKCS11_REF_COUNT_ATTRIBUTES set)
+ * Attributes are allocated from the heap when needed and freed when their
+ * reference count goes to zero.
+ *
+ * 3) arena allocation (PKCS11_STATIC_ATTRIBUTES not set
+ * PKCS11_REF_COUNT_ATTRIBUTE not set)
+ * Attributes are allocated from the arena when needed and freed only when
+ * the object goes away.
+ */
+#define PKCS11_STATIC_ATTRIBUTES
+/*#define PKCS11_REF_COUNT_ATTRIBUTES */
+/* the next two are only active if PKCS11_STATIC_ATTRIBUTES is set */
+#define MAX_OBJS_ATTRS 45 /* number of attributes to preallocate in
+ * the object (must me the absolute max) */
+#define ATTR_SPACE 50 /* Maximum size of attribute data before extra
+ * data needs to be allocated. This is set to
+ * enough space to hold an SSL MASTER secret */
+
+#define NSC_STRICT PR_FALSE /* forces the code to do strict template
+ * matching when doing C_FindObject on token
+ * objects. This will slow down search in
+ * NSS. */
+/* default search block allocations and increments */
+#define NSC_CERT_BLOCK_SIZE 50
+#define NSC_SEARCH_BLOCK_SIZE 5
+#define NSC_SLOT_LIST_BLOCK_SIZE 10
+
+/* these are data base storage hashes, not cryptographic hashes.. The define
+ * the effective size of the various object hash tables */
+#define ATTRIBUTE_HASH_SIZE 32
+#define SESSION_OBJECT_HASH_SIZE 32
+#define TOKEN_OBJECT_HASH_SIZE 1024
+#define SESSION_HASH_SIZE 512
+#define MAX_OBJECT_LIST_SIZE 800 /* how many objects to keep on the free list
+ * before we start freeing them */
+#define MAX_KEY_LEN 256
+
#ifdef PKCS11_USE_THREADS
@@ -60,6 +113,8 @@ typedef struct PK11AttributeStr PK11Attribute;
typedef struct PK11ObjectListStr PK11ObjectList;
typedef struct PK11ObjectListElementStr PK11ObjectListElement;
typedef struct PK11ObjectStr PK11Object;
+typedef struct PK11SessionObjectStr PK11SessionObject;
+typedef struct PK11TokenObjectStr PK11TokenObject;
typedef struct PK11SessionStr PK11Session;
typedef struct PK11SlotStr PK11Slot;
typedef struct PK11SessionContextStr PK11SessionContext;
@@ -78,17 +133,6 @@ typedef void (*PK11Hash)(void *,void *,unsigned int);
typedef void (*PK11End)(void *,void *,unsigned int *,unsigned int);
typedef void (*PK11Free)(void *);
-/*
- * these are data base storage hashes, not cryptographic hashes.. The define
- * the effective size of the various object hash tables
- */
-#define ATTRIBUTE_HASH_SIZE 32
-#define SESSION_OBJECT_HASH_SIZE 32
-#define TOKEN_OBJECT_HASH_SIZE 1024
-#define SESSION_HASH_SIZE 512
-#define MAX_KEY_LEN 256
-#define MAX_OBJECT_LIST_SIZE 800
-
/* Value to tell if an attribute is modifiable or not.
* NEVER: attribute is only set on creation.
* ONCOPY: attribute is set on creation and can only be changed on copy.
@@ -118,14 +162,16 @@ typedef enum {
struct PK11AttributeStr {
PK11Attribute *next;
PK11Attribute *prev;
-#ifdef REF_COUNT_ATTRIBUTE
+ PRBool freeAttr;
+ PRBool freeData;
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
int refCount;
PZLock *refLock;
#endif
/*must be called handle to make pk11queue_find work */
CK_ATTRIBUTE_TYPE handle;
CK_ATTRIBUTE attrib;
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
unsigned char space[ATTR_SPACE];
#endif
};
@@ -145,27 +191,33 @@ struct PK11ObjectListStr {
*/
struct PK11ObjectStr {
PK11Object *next;
- PK11Object *prev;
- PK11ObjectList sessionList;
- CK_OBJECT_HANDLE handle;
-#ifdef NO_ARENA
- int nextAttr;
-#else
- PLArenaPool *arena;
-#endif
- int refCount;
+ PK11Object *prev;
+ CK_OBJECT_CLASS objclass;
+ CK_OBJECT_HANDLE handle;
+ int refCount;
PZLock *refLock;
- PZLock *attributeLock;
- PK11Session *session;
PK11Slot *slot;
- CK_OBJECT_CLASS objclass;
void *objectInfo;
PK11Free infoFree;
- char *label;
- PRBool inDB;
+#ifndef PKCS11_STATIC_ATTRIBUTES
+ PLArenaPool *arena;
+#endif
+};
+
+struct PK11TokenObjectStr {
+ PK11Object obj;
+ SECItem dbKey;
+};
+
+struct PK11SessionObjectStr {
+ PK11Object obj;
+ PK11ObjectList sessionList;
+ PZLock *attributeLock;
+ PK11Session *session;
PRBool wasDerived;
PK11Attribute *head[ATTRIBUTE_HASH_SIZE];
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ int nextAttr;
PK11Attribute attrList[MAX_OBJS_ATTRS];
#endif
};
@@ -185,6 +237,7 @@ struct PK11SearchResultsStr {
CK_OBJECT_HANDLE *handles;
int size;
int index;
+ int array_size;
};
@@ -227,6 +280,7 @@ struct PK11SessionContextStr {
PK11Destroy hashdestroy;
PK11Verify verify;
unsigned int maxLen;
+ PK11Object *key;
};
/*
@@ -264,12 +318,20 @@ struct PK11SlotStr {
PRBool ssoLoggedIn;
PRBool needLogin;
PRBool DB_loaded;
+ PRBool readOnly;
+ NSSLOWCERTCertDBHandle *certDB;
+ NSSLOWKEYDBHandle *keyDB;
+ int minimumPinLen;
int sessionIDCount;
int sessionCount;
int rwSessionCount;
int tokenIDCount;
+ int index;
+ PLHashTable *tokenHashTable;
PK11Object *tokObjects[TOKEN_OBJECT_HASH_SIZE];
PK11Session *head[SESSION_HASH_SIZE];
+ char tokDescription[33];
+ char slotDescription[64];
};
/*
@@ -277,12 +339,12 @@ struct PK11SlotStr {
*/
struct PK11HashVerifyInfoStr {
SECOidTag hashOid;
- SECKEYLowPublicKey *key;
+ NSSLOWKEYPublicKey *key;
};
struct PK11HashSignInfoStr {
SECOidTag hashOid;
- SECKEYLowPrivateKey *key;
+ NSSLOWKEYPrivateKey *key;
};
/* context for the Final SSLMAC message */
@@ -300,8 +362,7 @@ struct PK11SSLMACInfoStr {
/*
* session handle modifiers
*/
-#define PK11_PRIVATE_KEY_FLAG 0x80000000L
-#define PK11_FIPS_FLAG 0x40000000L
+#define PK11_SESSION_SLOT_MASK 0xff000000L
/*
* object handle modifiers
@@ -309,10 +370,17 @@ struct PK11SSLMACInfoStr {
#define PK11_TOKEN_MASK 0x80000000L
#define PK11_TOKEN_MAGIC 0x80000000L
#define PK11_TOKEN_TYPE_MASK 0x70000000L
-#define PK11_TOKEN_TYPE_CERT 0x00000000L
+/* keydb (high bit == 0) */
#define PK11_TOKEN_TYPE_PRIV 0x10000000L
#define PK11_TOKEN_TYPE_PUB 0x20000000L
-
+#define PK11_TOKEN_TYPE_KEY 0x30000000L
+/* certdb (high bit == 1) */
+#define PK11_TOKEN_TYPE_TRUST 0x40000000L
+#define PK11_TOKEN_TYPE_CRL 0x50000000L
+#define PK11_TOKEN_TYPE_SMIME 0x60000000L
+#define PK11_TOKEN_TYPE_CERT 0x70000000L
+
+#define PK11_TOKEN_KRL_HANDLE (PK11_TOKEN_MAGIC|PK11_TOKEN_TYPE_CRL|0)
/* how big a password/pin we can deal with */
#define PK11_MAX_PIN 255
@@ -351,27 +419,36 @@ struct PK11SSLMACInfoStr {
#define pk11_attr_expand(ap) (ap)->type,(ap)->pValue,(ap)->ulValueLen
#define pk11_item_expand(ip) (ip)->data,(ip)->len
-typedef struct pk11_parametersStr {
+typedef struct pk11_token_parametersStr {
+ CK_SLOT_ID slotID;
char *configdir;
char *certPrefix;
char *keyPrefix;
- char *secmodName;
- char *man;
- char *libdes;
char *tokdes;
- char *ptokdes;
char *slotdes;
- char *pslotdes;
- char *fslotdes;
- char *fpslotdes;
int minPW;
PRBool readOnly;
PRBool noCertDB;
+ PRBool noKeyDB;
+ PRBool forceOpen;
+ PRBool pwRequired;
+} pk11_token_parameters;
+
+typedef struct pk11_parametersStr {
+ char *configdir;
+ char *secmodName;
+ char *man;
+ char *libdes;
+ PRBool readOnly;
PRBool noModDB;
+ PRBool noCertDB;
PRBool forceOpen;
PRBool pwRequired;
+ pk11_token_parameters *tokens;
+ int token_count;
} pk11_parameters;
+
/* machine dependent path stuff used by dbinit.c and pk11db.c */
#ifdef macintosh
#define PATH_SEPARATOR ":"
@@ -387,9 +464,9 @@ typedef struct pk11_parametersStr {
SEC_BEGIN_PROTOS
+extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS);
/* shared functions between PKCS11.c and PK11FIPS.c */
-extern CK_RV PK11_LowInitialize(CK_VOID_PTR pReserved);
-extern CK_RV PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin);
+extern CK_RV PK11_SlotInit(char *configdir,pk11_token_parameters *params);
/* internal utility functions used by pkcs11.c */
extern PK11Attribute *pk11_FindAttribute(PK11Object *object,
@@ -422,14 +499,14 @@ extern CK_RV pk11_defaultAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type,
extern PK11Object *pk11_NewObject(PK11Slot *slot);
extern CK_RV pk11_CopyObject(PK11Object *destObject, PK11Object *srcObject);
extern PK11FreeStatus pk11_FreeObject(PK11Object *object);
-extern void pk11_DeleteObject(PK11Session *session, PK11Object *object);
+extern CK_RV pk11_DeleteObject(PK11Session *session, PK11Object *object);
extern void pk11_ReferenceObject(PK11Object *object);
extern PK11Object *pk11_ObjectFromHandle(CK_OBJECT_HANDLE handle,
PK11Session *session);
extern void pk11_AddSlotObject(PK11Slot *slot, PK11Object *object);
extern void pk11_AddObject(PK11Session *session, PK11Object *object);
-extern CK_RV pk11_searchObjectList(PK11ObjectListElement **objectList,
+extern CK_RV pk11_searchObjectList(PK11SearchResults *search,
PK11Object **head, PZLock *lock,
CK_ATTRIBUTE_PTR inTemplate, int count,
PRBool isLoggedIn);
@@ -449,15 +526,16 @@ extern void pk11_update_state(PK11Slot *slot,PK11Session *session);
extern void pk11_update_all_states(PK11Slot *slot);
extern void pk11_FreeContext(PK11SessionContext *context);
-extern SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,
+extern NSSLOWKEYPublicKey *pk11_GetPubKey(PK11Object *object,
CK_KEY_TYPE key_type);
-extern SECKEYLowPrivateKey *pk11_GetPrivKey(PK11Object *object,
+extern NSSLOWKEYPrivateKey *pk11_GetPrivKey(PK11Object *object,
CK_KEY_TYPE key_type);
extern void pk11_FormatDESKey(unsigned char *key, int length);
extern PRBool pk11_CheckDESKey(unsigned char *key);
extern PRBool pk11_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type);
-extern CK_RV secmod_parseParameters(char *param, pk11_parameters *parsed);
+extern CK_RV secmod_parseParameters(char *param, pk11_parameters *parsed,
+ PRBool isFIPS);
extern void secmod_freeParams(pk11_parameters *params);
extern char *secmod_getSecmodName(char *params, PRBool *rw);
extern char ** secmod_ReadPermDB(char *dbname, char *params, PRBool rw);
@@ -481,10 +559,26 @@ extern SECStatus secmod_AddPermDB(char *dbname, char *module, PRBool rw);
* be opened.
*/
CK_RV pk11_DBInit(const char *configdir, const char *certPrefix,
- const char *keyPrefix, const char *secmodName, PRBool readOnly,
- PRBool noCertDB, PRBool noModDB, PRBool forceOpen);
+ const char *keyPrefix, PRBool readOnly, PRBool noCertDB,
+ PRBool noKeyDB, PRBool forceOpen,
+ NSSLOWCERTCertDBHandle **certDB, NSSLOWKEYDBHandle **keyDB);
+/*
+ * narrow objects
+ */
+PK11SessionObject * pk11_narrowToSessionObject(PK11Object *);
+PK11TokenObject * pk11_narrowToTokenObject(PK11Object *);
+/*
+ * token object utilities
+ */
+void pk11_addHandle(PK11SearchResults *search, CK_OBJECT_HANDLE handle);
+PRBool pk11_tokenMatch(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class,
+ CK_ATTRIBUTE_PTR theTemplate,int count);
+CK_OBJECT_HANDLE pk11_mkHandle(PK11Slot *slot,
+ SECItem *dbKey, CK_OBJECT_HANDLE class);
+PK11Object * pk11_NewTokenObject(PK11Slot *slot, SECItem *dbKey,
+ CK_OBJECT_HANDLE handle);
SEC_END_PROTOS
#endif /* _PKCS11I_H_ */
diff --git a/security/nss/lib/softoken/pkcs11t.h b/security/nss/lib/softoken/pkcs11t.h
index aa3d70496..124a1bb27 100644
--- a/security/nss/lib/softoken/pkcs11t.h
+++ b/security/nss/lib/softoken/pkcs11t.h
@@ -17,7 +17,6 @@
* Rights Reserved.
*
* Contributor(s):
- * Dr Stephen Henson <stephen.henson@gemplus.com>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
@@ -61,12 +60,17 @@
#define CK_DECLARE_FUNCTION(rv,func) PR_EXTERN(rv) func
#define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (PR_CALLBACK * func)
+#define CK_INVALID_SESSION 0
+
/* an unsigned 8-bit value */
typedef unsigned char CK_BYTE;
/* an unsigned 8-bit character */
typedef CK_BYTE CK_CHAR;
+/* an unsigned 8-bit character */
+typedef CK_BYTE CK_UTF8CHAR;
+
/* a BYTE-sized Boolean flag */
typedef CK_BYTE CK_BBOOL;
@@ -88,6 +92,7 @@ typedef CK_ULONG CK_FLAGS;
typedef CK_BYTE CK_PTR CK_BYTE_PTR;
typedef CK_CHAR CK_PTR CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
typedef CK_ULONG CK_PTR CK_ULONG_PTR;
typedef void CK_PTR CK_VOID_PTR;
@@ -112,12 +117,14 @@ typedef CK_VERSION CK_PTR CK_VERSION_PTR;
typedef struct CK_INFO {
+ /* manufacturerID and libraryDecription have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
CK_VERSION cryptokiVersion; /* PKCS #11 interface ver */
- CK_CHAR manufacturerID[32]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
CK_FLAGS flags; /* must be zero */
/* libraryDescription and libraryVersion are new for v2.0 */
- CK_CHAR libraryDescription[32]; /* blank padded */
+ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
CK_VERSION libraryVersion; /* version of library */
} CK_INFO;
@@ -139,8 +146,10 @@ typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
/* CK_SLOT_INFO provides information about a slot */
typedef struct CK_SLOT_INFO {
- CK_CHAR slotDescription[64]; /* blank padded */
- CK_CHAR manufacturerID[32]; /* blank padded */
+ /* slotDescription and manufacturerID have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR slotDescription[64]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
CK_FLAGS flags;
/* hardwareVersion and firmwareVersion are new for v2.0 */
@@ -160,9 +169,11 @@ typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
/* CK_TOKEN_INFO provides information about a token */
typedef struct CK_TOKEN_INFO {
- CK_CHAR label[32]; /* blank padded */
- CK_CHAR manufacturerID[32]; /* blank padded */
- CK_CHAR model[16]; /* blank padded */
+ /* label, manufacturerID, and model have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR label[32]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_UTF8CHAR model[16]; /* blank padded */
CK_CHAR serialNumber[16]; /* blank padded */
CK_FLAGS flags; /* see below */
@@ -223,6 +234,57 @@ typedef struct CK_TOKEN_INFO {
* and sign) */
#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized. */
+#define CKF_TOKEN_INITIALIZED 0x00000400
+
+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
+ * true, the token supports secondary authentication for
+ * private key objects. */
+/* DEPRICATED in v2.11 */
+#define CKF_SECONDARY_AUTHENTICATION 0x00000800
+
+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication. */
+#define CKF_USER_PIN_COUNT_LOW 0x00010000
+
+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect user PIN will it to become locked. */
+#define CKF_USER_PIN_FINAL_TRY 0x00020000
+
+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible. */
+#define CKF_USER_PIN_LOCKED 0x00040000
+
+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing. */
+#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
+
+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication. */
+#define CKF_SO_PIN_COUNT_LOW 0x00100000
+
+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect SO PIN will it to become locked. */
+#define CKF_SO_PIN_FINAL_TRY 0x00200000
+
+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED 0x00400000
+
+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing. */
+#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
+
typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
@@ -289,15 +351,28 @@ typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
typedef CK_ULONG CK_OBJECT_CLASS;
/* The following classes of objects are defined: */
-#define CKO_DATA 0x00000000
-#define CKO_CERTIFICATE 0x00000001
-#define CKO_PUBLIC_KEY 0x00000002
-#define CKO_PRIVATE_KEY 0x00000003
-#define CKO_SECRET_KEY 0x00000004
-#define CKO_VENDOR_DEFINED 0x80000000
+/* CKO_HW_FEATURE is new for v2.10 */
+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
+#define CKO_DATA 0x00000000
+#define CKO_CERTIFICATE 0x00000001
+#define CKO_PUBLIC_KEY 0x00000002
+#define CKO_PRIVATE_KEY 0x00000003
+#define CKO_SECRET_KEY 0x00000004
+#define CKO_HW_FEATURE 0x00000005
+#define CKO_DOMAIN_PARAMETERS 0x00000006
+#define CKO_VENDOR_DEFINED 0x80000000
typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
+ * value that identifies the hardware feature type of an object
+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
+typedef CK_ULONG CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+#define CKH_MONOTONIC_COUNTER 0x00000001
+#define CKH_CLOCK 0x00000002
+#define CKH_VENDOR_DEFINED 0x80000000
/* CK_KEY_TYPE is a value that identifies a key type */
/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
@@ -309,10 +384,10 @@ typedef CK_ULONG CK_KEY_TYPE;
#define CKK_DH 0x00000002
/* CKK_ECDSA and CKK_KEA are new for v2.0 */
-
-/* PKCS #11 V2.01 probably won't actually have ECDSA in it */
-#define CKK_ECDSA 0x00000003
-
+/* CKK_X9_42_DH is new for v2.11 */
+#define CKK_ECDSA 0x00000003 /* deprecated in v2.11 */
+#define CKK_EC 0x00000003
+#define CKK_X9_42_DH 0x00000004
#define CKK_KEA 0x00000005
#define CKK_GENERIC_SECRET 0x00000010
@@ -325,8 +400,8 @@ typedef CK_ULONG CK_KEY_TYPE;
/* all these key types are new for v2.0 */
#define CKK_CAST 0x00000016
#define CKK_CAST3 0x00000017
-#define CKK_CAST5 0x00000018
-#define CKK_CAST128 0x00000018 /* CAST128=CAST5 */
+#define CKK_CAST5 0x00000018 /* deprecated in v2.11 */
+#define CKK_CAST128 0x00000018
#define CKK_RC5 0x00000019
#define CKK_IDEA 0x0000001A
#define CKK_SKIPJACK 0x0000001B
@@ -348,7 +423,9 @@ typedef CK_ULONG CK_KEY_TYPE;
typedef CK_ULONG CK_CERTIFICATE_TYPE;
/* The following certificate types are defined: */
+/* CKC_X_509_ATTR_CERT is new for v2.10 */
#define CKC_X_509 0x00000000
+#define CKC_X_509_ATTR_CERT 0x00000001
#define CKC_VENDOR_DEFINED 0x80000000
@@ -365,9 +442,22 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE;
#define CKA_LABEL 0x00000003
#define CKA_APPLICATION 0x00000010
#define CKA_VALUE 0x00000011
+
+/* CKA_OBJECT_ID is new for v2.10 */
+#define CKA_OBJECT_ID 0x00000012
+
#define CKA_CERTIFICATE_TYPE 0x00000080
#define CKA_ISSUER 0x00000081
#define CKA_SERIAL_NUMBER 0x00000082
+
+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
+ * for v2.10 */
+#define CKA_AC_ISSUER 0x00000083
+#define CKA_OWNER 0x00000084
+#define CKA_ATTR_TYPES 0x00000085
+/* CKA_TRUSTED is new for v2.11 */
+#define CKA_TRUSTED 0x00000086
+
#define CKA_KEY_TYPE 0x00000100
#define CKA_SUBJECT 0x00000101
#define CKA_ID 0x00000102
@@ -395,16 +485,34 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE;
#define CKA_PRIME 0x00000130
#define CKA_SUBPRIME 0x00000131
#define CKA_BASE 0x00000132
+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
+#define CKA_PRIME_BITS 0x00000133
+#define CKA_SUB_PRIME_BITS 0x00000134
#define CKA_VALUE_BITS 0x00000160
#define CKA_VALUE_LEN 0x00000161
/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
- * CKA_ALWAYS_SENSITIVE, and CKA_MODIFIABLE are new for v2.0 */
+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
+ * and CKA_EC_POINT are new for v2.0 */
#define CKA_EXTRACTABLE 0x00000162
#define CKA_LOCAL 0x00000163
#define CKA_NEVER_EXTRACTABLE 0x00000164
#define CKA_ALWAYS_SENSITIVE 0x00000165
+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
+#define CKA_KEY_GEN_MECHANISM 0x00000166
#define CKA_MODIFIABLE 0x00000170
+#define CKA_ECDSA_PARAMS 0x00000180 /* depricated v2.11 */
+#define CKA_EC_PARAMS 0x00000180
+#define CKA_EC_POINT 0x00000181
+
+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ * CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
+ * are new for v2.10 */
+#define CKA_SECONDARY_AUTH 0x00000200 /* depricated v2.11 */
+#define CKA_AUTH_PIN_FLAGS 0x00000201 /* depricated v2.11 */
+#define CKA_HW_FEATURE_TYPE 0x00000300
+#define CKA_RESET_ON_INIT 0x00000301
+#define CKA_HAS_RESET 0x00000302
#define CKA_VENDOR_DEFINED 0x80000000
@@ -448,11 +556,32 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_MD5_RSA_PKCS 0x00000005
#define CKM_SHA1_RSA_PKCS 0x00000006
+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS & CKM_RSA_OAEP
+ * are new for 2.10 */
+#define CKM_RIPEMD128_RSA_PKCS 0x00000007
+#define CKM_RIPEMD160_RSA_PKCS 0x00000008
+#define CKM_RSA_PKCS_OAEP 0x00000009
+
+/* CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31 & CKM_RSA_X9_31_KEY_PAIR_GEN
+ * are new for 2.11 */
+#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
+#define CKM_RSA_X9_31 0x0000000B
+#define CKM_SHA1_RSA_X9_31 0x0000000C
+
#define CKM_DSA_KEY_PAIR_GEN 0x00000010
#define CKM_DSA 0x00000011
#define CKM_DSA_SHA1 0x00000012
#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
#define CKM_DH_PKCS_DERIVE 0x00000021
+
+/* CKM_X9_42_DH_PKCS_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
+ * CKM_X9_42_DH_HYBRID_DERIVE, & CKM_X9_42_MQV_DERIVE
+ * are new for v2.11 */
+#define CKM_X9_42_DH_PKCS_KEY_PAIR_GEN 0x00000030
+#define CKM_X9_42_DH_DERIVE 0x00000031
+#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
+#define CKM_X9_42_MQV_DERIVE 0x00000033
+
#define CKM_RC2_KEY_GEN 0x00000100
#define CKM_RC2_ECB 0x00000101
#define CKM_RC2_CBC 0x00000102
@@ -509,6 +638,16 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_SHA_1_HMAC 0x00000221
#define CKM_SHA_1_HMAC_GENERAL 0x00000222
+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
+#define CKM_RIPEMD128 0x00000230
+#define CKM_RIPEMD128_HMAC 0x00000231
+#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
+#define CKM_RIPEMD160 0x00000240
+#define CKM_RIPEMD160_HMAC 0x00000241
+#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
+
/* All of the following mechanisms are new for v2.0 */
/* Note that CAST128 and CAST5 are the same algorithm */
#define CKM_CAST_KEY_GEN 0x00000300
@@ -556,6 +695,17 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
+
+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE,
+ * CKM_TLS_MASTER_KEY_DERIVE_DH, & CKM_SSL3_MASTER_KEY_DERIVE_DH
+ * are new for v2.11. */
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
+#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
+#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
+#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
+#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
+
#define CKM_SSL3_MD5_MAC 0x00000380
#define CKM_SSL3_SHA1_MAC 0x00000381
#define CKM_MD5_KEY_DERIVATION 0x00000390
@@ -575,6 +725,10 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
+
+/* CKM_PKCS5_PBKD2 is new for v2.10 */
+#define CKM_PKCS5_PBKD2 0x000003B0
+
#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
#define CKM_KEY_WRAP_LYNKS 0x00000400
#define CKM_KEY_WRAP_SET_OAEP 0x00000401
@@ -601,12 +755,16 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_BATON_COUNTER 0x00001034
#define CKM_BATON_SHUFFLE 0x00001035
#define CKM_BATON_WRAP 0x00001036
-
-/* PKCS #11 V2.01 probably won't actually have ECDSA in it */
-#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
+#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 /* depricated in v2.11 */
+#define CKM_EC_KEY_PAIR_GEN 0x00001040
#define CKM_ECDSA 0x00001041
#define CKM_ECDSA_SHA1 0x00001042
+/* ECDH1 is new for 2.11 */
+#define CKM_ECDH1_DERIVE 0x00001043
+#define CKM_ECDH1_COFACTOR_DERIVE 0x00001044
+#define CKM_ECMQV_DERIVE 0x00001045
+
#define CKM_JUNIPER_KEY_GEN 0x00001060
#define CKM_JUNIPER_ECB128 0x00001061
#define CKM_JUNIPER_CBC128 0x00001062
@@ -615,6 +773,7 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_JUNIPER_WRAP 0x00001065
#define CKM_FASTHASH 0x00001070
+/* AES is new for 2.11 */
#define CKM_AES_KEY_GEN 0x00001080
#define CKM_AES_ECB 0x00001081
#define CKM_AES_CBC 0x00001082
@@ -622,6 +781,12 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_AES_MAC_GENERAL 0x00001084
#define CKM_AES_CBC_PAD 0x00001085
+/* CKM_DSA_PARAMETER_GEN, CKM_DH_PKCS_PARAMETER_GEN,
+ * and CKM_DH_X9_42_PARAMETER_GEN are new for 2.11 */
+#define CKM_DSA_PARAMETER_GEN 0x00002000
+#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
+#define CKM_DH_X9_42_PARAMETER_GEN 0x00002002
+
#define CKM_VENDOR_DEFINED 0x80000000
typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
@@ -658,6 +823,8 @@ typedef struct CK_MECHANISM_INFO {
* CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
* and CKF_DERIVE are new for v2.0. They specify whether or not
* a mechanism can be used for a particular task */
+/* The flags CKF_EC_FP, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11 */
#define CKF_ENCRYPT 0x00000100
#define CKF_DECRYPT 0x00000200
#define CKF_DIGEST 0x00000400
@@ -670,6 +837,12 @@ typedef struct CK_MECHANISM_INFO {
#define CKF_WRAP 0x00020000
#define CKF_UNWRAP 0x00040000
#define CKF_DERIVE 0x00080000
+#define CKF_EC_FP 0x00100000
+#define CKF_EC_F_2M 0x00200000
+#define CKF_EC_ECPARAMETERS 0x00400000
+#define CKF_EC_NAMEDCURVE 0x00800000
+#define CKF_EC_UNCOMPRESS 0x01000000
+#define CKF_EC_COMPRESS 0x02000000
#define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */
@@ -735,6 +908,9 @@ typedef CK_ULONG CK_RV;
#define CKR_KEY_NOT_WRAPPABLE 0x00000069
#define CKR_KEY_UNEXTRACTABLE 0x0000006A
+/* CKR_KEY_PARAMS_INVALID is new for v2.11 */
+#define CKR_KEY_PARAMS_INVALID 0x0000006B
+
#define CKR_MECHANISM_INVALID 0x00000070
#define CKR_MECHANISM_PARAM_INVALID 0x00000071
@@ -790,8 +966,13 @@ typedef CK_ULONG CK_RV;
#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
-/* These are new to v2.0 */
+/* New for v2.0 */
#define CKR_RANDOM_NO_RNG 0x00000121
+
+/* New for v2.11 */
+#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
+
+/* These are new to v2.0 */
#define CKR_BUFFER_TOO_SMALL 0x00000150
#define CKR_SAVED_STATE_INVALID 0x00000160
#define CKR_INFORMATION_SENSITIVE 0x00000170
@@ -878,6 +1059,41 @@ typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
#define CKF_DONT_BLOCK 1
+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_MGF_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_MGF_TYPE CK_PTR CK_RSA_PKCS_OAEP_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+#define CKG_MGF1_SHA1 0x00000001
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED 0x00000001
+
+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism. */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_OAEP_MGF_TYPE mgf;
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+ CK_VOID_PTR pSourceData;
+ CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
/* CK_KEA_DERIVE_PARAMS provides the parameters to the
* CKM_KEA_DERIVE mechanism */
@@ -1102,36 +1318,46 @@ typedef CK_ULONG CK_EXTRACT_PARAMS;
typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
-/* Do not attempt to use these. They are only used by NETSCAPE's internal
- * PKCS #11 interface. Most of these are place holders for other mechanism
- * and will change in the future.
- */
-#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001L
-#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L
-#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L
-#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L
-#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L
-#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L
-#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L
-#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L
-#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L
-#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL
-#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL
-#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371L
-#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372L
-#define CKM_TLS_PRF_GENERAL 0x80000373L
-#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x80000374L
-#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x80000375L
-
-/* define used to pass in the database key for DSA private keys */
-#define CKA_NETSCAPE_DB 0xD5A0DB00L
-#define CKA_NETSCAPE_TRUST 0x80000001L
-
-#define SECMOD_MODULE_DB_FUNCTION_FIND 0
-#define SECMOD_MODULE_DB_FUNCTION_ADD 1
-#define SECMOD_MODULE_DB_FUNCTION_DEL 2
-typedef char ** (PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function,
- char *parameters, char *moduleSpec);
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+/* The following PRFs are defined in PKCS #5 v2.0. */
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
+
+
+/* CK_PKCS5_PBKD2_SALT_SOURCE_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED 0x00000001
+
+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+/* Netscape Specific defines */
+#include "pkcs11n.h"
/* undo packing */
#include "pkcs11u.h"
diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c
index 0aa42823a..1c8cd821a 100644
--- a/security/nss/lib/softoken/pkcs11u.c
+++ b/security/nss/lib/softoken/pkcs11u.c
@@ -35,18 +35,10 @@
*/
#include "pkcs11.h"
#include "pkcs11i.h"
-#include "key.h"
-#include "keylow.h"
-#include "certdb.h"
-
-
-/* declare the internal pkcs11 slot structures:
- * There are threee:
- * slot 0 is the generic crypto service token.
- * slot 1 is the Database service token.
- * slot 2 is the FIPS token (both generic and database).
- */
-static PK11Slot pk11_slot[3];
+#include "pcertt.h"
+#include "lowkeyi.h"
+#include "pcert.h"
+#include "secasn1.h"
/*
* ******************** Attribute Utilities *******************************
@@ -62,27 +54,36 @@ pk11_NewAttribute(PK11Object *object,
{
PK11Attribute *attribute;
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ PK11SessionObject *so = pk11_narrowToSessionObject(object);
int index;
+
+ if (so == NULL) {
+ /* allocate new attribute in a buffer */
+ PORT_Assert(0);
+ }
/*
- * NO_ARENA attempts to keep down contention on Malloc and Arena locks
+ * PKCS11_STATIC_ATTRIBUTES attempts to keep down contention on Malloc and Arena locks
* by limiting the number of these calls on high traversed paths. this
* is done for attributes by 'allocating' them from a pool already allocated
* by the parent object.
*/
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
- index = object->nextAttr++;
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ PK11_USE_THREADS(PZ_Lock(so->attributeLock);)
+ index = so->nextAttr++;
+ PK11_USE_THREADS(PZ_Unlock(so->attributeLock);)
PORT_Assert(index < MAX_OBJS_ATTRS);
if (index >= MAX_OBJS_ATTRS) return NULL;
- attribute = &object->attrList[index];
+ attribute = &so->attrList[index];
attribute->attrib.type = type;
+ attribute->freeAttr = PR_FALSE;
+ attribute->freeData = PR_FALSE;
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) {
return NULL;
@@ -94,23 +95,27 @@ pk11_NewAttribute(PK11Object *object,
attribute->attrib.ulValueLen = 0;
}
#else
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute));
+ attribute->freeAttr = PR_TRUE;
#else
attribute = (PK11Attribute*)PORT_ArenaAlloc(object->arena,sizeof(PK11Attribute));
-#endif /* REF_COUNT_ATTRIBUTE */
+ attribute->freeAttr = PR_FALSE;
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
if (attribute == NULL) return NULL;
+ attribute->freeData = PR_FALSE;
if (value) {
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
attribute->attrib.pValue = PORT_Alloc(len);
+ attribute->freeData = PR_TRUE;
#else
attribute->attrib.pValue = PORT_ArenaAlloc(object->arena,len);
-#endif /* REF_COUNT_ATTRIBUTE */
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
if (attribute->attrib.pValue == NULL) {
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
PORT_Free(attribute);
-#endif /* REF_COUNT_ATTRIBUTE */
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
return NULL;
}
PORT_Memcpy(attribute->attrib.pValue,value,len);
@@ -119,11 +124,11 @@ pk11_NewAttribute(PK11Object *object,
attribute->attrib.pValue = NULL;
attribute->attrib.ulValueLen = 0;
}
-#endif /* NO_ARENA */
+#endif /* PKCS11_STATIC_ATTRIBUTES */
attribute->attrib.type = type;
attribute->handle = type;
attribute->next = attribute->prev = NULL;
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
attribute->refCount = 1;
#ifdef PKCS11_USE_THREADS
attribute->refLock = PZ_NewLock(nssILockRefLock);
@@ -135,31 +140,893 @@ pk11_NewAttribute(PK11Object *object,
#else
attribute->refLock = NULL;
#endif
-#endif /* REF_COUNT_ATTRIBUTE */
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
+ return attribute;
+}
+
+static PK11Attribute *
+pk11_NewTokenAttribute(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value,
+ CK_ULONG len, PRBool copy)
+{
+ PK11Attribute *attribute;
+
+ attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute));
+
+ 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;
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ attribute->refCount = 1;
+#ifdef PKCS11_USE_THREADS
+ attribute->refLock = PZ_NewLock(nssILockRefLock);
+ if (attribute->refLock == NULL) {
+ PORT_Free(attribute);
+ return NULL;
+ }
+#else
+ attribute->refLock = NULL;
+#endif
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
+ attribute->attrib.type = type;
+ if (!copy) {
+ attribute->attrib.pValue = value;
+ attribute->attrib.ulValueLen = len;
+ return attribute;
+ }
+
+ if (value) {
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ if (len <= ATTR_SPACE) {
+ attribute->attrib.pValue = attribute->space;
+ } else {
+ attribute->attrib.pValue = PORT_Alloc(len);
+ attribute->freeData = PR_TRUE;
+ }
+#else
+ attribute->attrib.pValue = PORT_Alloc(len);
+ attribute->freeData = PR_TRUE;
+#endif
+ if (attribute->attrib.pValue == NULL) {
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ if (attribute->refLock) {
+ PK11_USE_THREADS(PZ_DestroyLock(attribute->refLock);)
+ }
+#endif
+ 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 PK11Attribute *
+pk11_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 pk11_NewTokenAttribute(type,dval,len,copy);
+}
+
/*
* Free up all the memory associated with an attribute. Reference count
* must be zero to call this.
*/
-#ifdef REF_COUNT_ATTRIBUTE
static void
pk11_DestroyAttribute(PK11Attribute *attribute)
{
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
PORT_Assert(attribute->refCount == 0);
PK11_USE_THREADS(PZ_DestroyLock(attribute->refLock);)
- if (attribute->attrib.pValue) {
- /* clear out the data in the attribute value... it may have been
- * sensitive data */
- PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
- PORT_Free(attribute->attrib.pValue);
+#endif
+ if (attribute->freeData) {
+ if (attribute->attrib.pValue) {
+ /* clear out the data in the attribute value... it may have been
+ * sensitive data */
+ PORT_Memset(attribute->attrib.pValue, 0,
+ attribute->attrib.ulValueLen);
+ }
+ PORT_Free(attribute->attrib.pValue);
}
PORT_Free(attribute);
}
+
+/*
+ * release a reference to an attribute structure
+ */
+void
+pk11_FreeAttribute(PK11Attribute *attribute)
+{
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ PRBool destroy = PR_FALSE;
#endif
+
+ if (attribute->freeAttr) {
+ pk11_DestroyAttribute(attribute);
+ return;
+ }
+
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ PK11_USE_THREADS(PZ_Lock(attribute->refLock);)
+ if (attribute->refCount == 1) destroy = PR_TRUE;
+ attribute->refCount--;
+ PK11_USE_THREADS(PZ_Unlock(attribute->refLock);)
+
+ if (destroy) pk11_DestroyAttribute(attribute);
+#endif
+}
+
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+#define PK11_DEF_ATTRIBUTE(value,len) \
+ { NULL, NULL, PR_FALSE, PR_FALSE, 1, NULL, 0, { 0, value, len } }
+
+#else
+#define PK11_DEF_ATTRIBUTE(value,len) \
+ { NULL, NULL, PR_FALSE, PR_FALSE, 0, { 0, value, len } }
+#endif
+
+CK_BBOOL pk11_staticTrueValue = CK_TRUE;
+CK_BBOOL pk11_staticFalseValue = CK_FALSE;
+static const PK11Attribute pk11_StaticTrueAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticTrueValue,sizeof(pk11_staticTrueValue));
+static const PK11Attribute pk11_StaticFalseAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticFalseValue,sizeof(pk11_staticFalseValue));
+static const PK11Attribute pk11_StaticNullAttr = PK11_DEF_ATTRIBUTE(NULL,0);
+
+CK_CERTIFICATE_TYPE pk11_staticX509Value = CKC_X_509;
+static const PK11Attribute pk11_StaticX509Attr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticX509Value, sizeof(pk11_staticX509Value));
+CK_TRUST pk11_staticTrustedValue = CKT_NETSCAPE_TRUSTED;
+CK_TRUST pk11_staticTrustedDelegatorValue = CKT_NETSCAPE_TRUSTED_DELEGATOR;
+CK_TRUST pk11_staticUnTrustedValue = CKT_NETSCAPE_UNTRUSTED;
+CK_TRUST pk11_staticTrustUnknownValue = CKT_NETSCAPE_TRUST_UNKNOWN;
+CK_TRUST pk11_staticMustVerifyValue = CKT_NETSCAPE_MUST_VERIFY;
+static const PK11Attribute pk11_StaticTrustedAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticTrustedValue,
+ sizeof(pk11_staticTrustedValue));
+static const PK11Attribute pk11_StaticTrustedDelegatorAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticTrustedDelegatorValue,
+ sizeof(pk11_staticTrustedDelegatorValue));
+static const PK11Attribute pk11_StaticUnTrustedAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticUnTrustedValue,
+ sizeof(pk11_staticUnTrustedValue));
+static const PK11Attribute pk11_StaticTrustUnknownAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticTrustUnknownValue,
+ sizeof(pk11_staticTrustUnknownValue));
+static const PK11Attribute pk11_StaticMustVerifyAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticMustVerifyValue,
+ sizeof(pk11_staticMustVerifyValue));
+
+static void pk11_FreeItem(SECItem *item)
+{
+ SECITEM_FreeItem(item, PR_TRUE);
+}
+
+static certDBEntrySMime *
+pk11_getSMime(PK11TokenObject *object)
+{
+ certDBEntrySMime *entry;
+
+ if (object->obj.objclass != CKO_NETSCAPE_SMIME) {
+ return NULL;
+ }
+ if (object->obj.objectInfo) {
+ return (certDBEntrySMime *)object->obj.objectInfo;
+ }
+
+ entry = nsslowcert_ReadDBSMimeEntry(object->obj.slot->certDB,
+ (char *)object->dbKey.data);
+ object->obj.objectInfo = (void *)entry;
+ object->obj.infoFree = (PK11Free) nsslowcert_DestroyDBEntry;
+ return entry;
+}
+
+static SECItem *
+pk11_getCrl(PK11TokenObject *object)
+{
+ SECItem *crl;
+ PRBool isKrl;
+
+ if (object->obj.objclass != CKO_NETSCAPE_CRL) {
+ return NULL;
+ }
+ if (object->obj.objectInfo) {
+ return (SECItem *)object->obj.objectInfo;
+ }
+
+ isKrl = (PRBool) object->obj.handle == PK11_TOKEN_KRL_HANDLE;
+ crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,&object->dbKey,
+ NULL,isKrl);
+ object->obj.objectInfo = (void *)crl;
+ object->obj.infoFree = (PK11Free) pk11_FreeItem;
+ return crl;
+}
+
+static char *
+pk11_getUrl(PK11TokenObject *object)
+{
+ SECItem *crl;
+ PRBool isKrl;
+ char *url = NULL;
+
+ if (object->obj.objclass != CKO_NETSCAPE_CRL) {
+ return NULL;
+ }
+
+ isKrl = (PRBool) object->obj.handle == PK11_TOKEN_KRL_HANDLE;
+ crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,&object->dbKey,
+ &url,isKrl);
+ if (object->obj.objectInfo == NULL) {
+ object->obj.objectInfo = (void *)crl;
+ object->obj.infoFree = (PK11Free) pk11_FreeItem;
+ } else {
+ if (crl) SECITEM_FreeItem(crl,PR_TRUE);
+ }
+ return url;
+}
+
+static NSSLOWCERTCertificate *
+pk11_getCert(PK11TokenObject *object)
+{
+ NSSLOWCERTCertificate *cert;
+
+ if ((object->obj.objclass != CKO_CERTIFICATE) &&
+ (object->obj.objclass != CKO_NETSCAPE_TRUST)) {
+ return NULL;
+ }
+ if (object->obj.objectInfo) {
+ return (NSSLOWCERTCertificate *)object->obj.objectInfo;
+ }
+ cert = nsslowcert_FindCertByKey(object->obj.slot->certDB,&object->dbKey);
+ object->obj.objectInfo = (void *)cert;
+ object->obj.infoFree = (PK11Free) nsslowcert_DestroyCertificate ;
+ return cert;
+}
+
+static NSSLOWKEYPublicKey *
+pk11_GetPublicKey(PK11TokenObject *object)
+{
+ NSSLOWKEYPublicKey *pubKey;
+ NSSLOWKEYPrivateKey *privKey;
+
+ if (object->obj.objclass != CKO_PUBLIC_KEY) {
+ return NULL;
+ }
+ if (object->obj.objectInfo) {
+ return (NSSLOWKEYPublicKey *)object->obj.objectInfo;
+ }
+ privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB,
+ &object->dbKey, object->obj.slot->password);
+ pubKey = nsslowkey_ConvertToPublicKey(privKey);
+ nsslowkey_DestroyPrivateKey(privKey);
+ object->obj.objectInfo = (void *) pubKey;
+ object->obj.infoFree = (PK11Free) nsslowkey_DestroyPublicKey ;
+ return pubKey;
+}
+
+static NSSLOWKEYPrivateKey *
+pk11_GetPrivateKey(PK11TokenObject *object)
+{
+ 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(object->obj.slot->keyDB,
+ &object->dbKey, object->obj.slot->password);
+ object->obj.objectInfo = (void *) privKey;
+ object->obj.infoFree = (PK11Free) nsslowkey_DestroyPrivateKey ;
+ return privKey;
+}
+
+/* pk11_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 *
+pk11_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;
+ default:
+ break;
+ }
+ return pubItem;
+}
+
+static const SEC_ASN1Template pk11_SerialTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) },
+ { 0 }
+};
+
+static PK11Attribute *
+pk11_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 pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_ENCRYPT:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ default:
+ case CKA_MODULUS:
+ return pk11_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
+ key->u.rsa.modulus.len, PR_FALSE);
+ case CKA_PUBLIC_EXPONENT:
+ return pk11_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
+ key->u.rsa.publicExponent.len, PR_FALSE);
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_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 pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ case CKA_ENCRYPT:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_VERIFY:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_VALUE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len, PR_FALSE);
+ case CKA_PRIME:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
+ key->u.dsa.params.prime.len, PR_FALSE);
+ case CKA_SUBPRIME:
+ return pk11_NewTokenAttributeSigned(type,
+ key->u.dsa.params.subPrime.data,
+ key->u.dsa.params.subPrime.len, PR_FALSE);
+ case CKA_BASE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
+ key->u.dsa.params.base.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_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 pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_ENCRYPT:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_VALUE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.publicValue.data,
+ key->u.dh.publicValue.len, PR_FALSE);
+ case CKA_PRIME:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.prime.data,
+ key->u.dh.prime.len, PR_FALSE);
+ case CKA_BASE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.base.data,
+ key->u.dh.base.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindPublicKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWKEYPublicKey *key;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_NEVER_EXTRACTABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_MODIFIABLE:
+ case CKA_EXTRACTABLE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ default:
+ break;
+ }
+
+ key = pk11_GetPublicKey(object);
+ if (key == NULL) {
+ return NULL;
+ }
+ switch (key->keyType) {
+ case NSSLOWKEYRSAKey:
+ return pk11_FindRSAPublicKeyAttribute(key,type);
+ case NSSLOWKEYDSAKey:
+ return pk11_FindDSAPublicKeyAttribute(key,type);
+ case NSSLOWKEYDHKey:
+ return pk11_FindDHPublicKeyAttribute(key,type);
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindSecretKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWKEYPrivateKey *key;
+ 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:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_NEVER_EXTRACTABLE:
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_VALUE:
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ default:
+ break;
+ }
+
+ key = pk11_GetPrivateKey(object);
+ if (key == NULL) {
+ return NULL;
+ }
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return pk11_NewTokenAttribute(type,key->u.rsa.coefficient.data,
+ key->u.rsa.coefficient.len, PR_FALSE);
+ case CKA_VALUE:
+ return pk11_NewTokenAttribute(type,key->u.rsa.privateExponent.data,
+ key->u.rsa.privateExponent.len, PR_FALSE);
+ }
+
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_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 pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_MODULUS:
+ return pk11_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
+ key->u.rsa.modulus.len, PR_FALSE);
+ case CKA_PUBLIC_EXPONENT:
+ return pk11_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
+ key->u.rsa.publicExponent.len, PR_FALSE);
+ case CKA_PRIVATE_EXPONENT:
+ case CKA_PRIME_1:
+ case CKA_PRIME_2:
+ case CKA_EXPONENT_1:
+ case CKA_EXPONENT_2:
+ case CKA_COEFFICIENT:
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_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 pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ case CKA_DECRYPT:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_SIGN:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_VALUE:
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ case CKA_PRIME:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
+ key->u.dsa.params.prime.len, PR_FALSE);
+ case CKA_SUBPRIME:
+ return pk11_NewTokenAttributeSigned(type,
+ key->u.dsa.params.subPrime.data,
+ key->u.dsa.params.subPrime.len, PR_FALSE);
+ case CKA_BASE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
+ key->u.dsa.params.base.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_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 pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_VALUE:
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ case CKA_PRIME:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.prime.data,
+ key->u.dh.prime.len, PR_FALSE);
+ case CKA_BASE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.base.data,
+ key->u.dh.base.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindPrivateKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWKEYPrivateKey *key;
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_EXTRACTABLE:
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_NEVER_EXTRACTABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ default:
+ break;
+ }
+ key = pk11_GetPrivateKey(object);
+ if (key == NULL) {
+ return NULL;
+ }
+ switch (key->keyType) {
+ case NSSLOWKEYRSAKey:
+ return pk11_FindRSAPrivateKeyAttribute(key,type);
+ case NSSLOWKEYDSAKey:
+ return pk11_FindDSAPrivateKeyAttribute(key,type);
+ case NSSLOWKEYDHKey:
+ return pk11_FindDHPrivateKeyAttribute(key,type);
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindSMIMEAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ certDBEntrySMime *entry;
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_NETSCAPE_EMAIL:
+ return pk11_NewTokenAttribute(type,object->dbKey.data,
+ object->dbKey.len, PR_FALSE);
+ default:
+ break;
+ }
+ entry = pk11_getSMime(object);
+ if (entry == NULL) {
+ return NULL;
+ }
+ switch (type) {
+ case CKA_NETSCAPE_SMIME_TIMESTAMP:
+ return pk11_NewTokenAttribute(type,entry->optionsDate.data,
+ entry->optionsDate.len, PR_FALSE);
+ case CKA_SUBJECT:
+ return pk11_NewTokenAttribute(type,entry->subjectName.data,
+ entry->subjectName.len, PR_FALSE);
+ case CKA_VALUE:
+ return pk11_NewTokenAttribute(type,entry->smimeOptions.data,
+ entry->smimeOptions.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindTrustAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWCERTCertificate *cert;
+ unsigned char hash[SHA1_LENGTH];
+ SECItem *item;
+ PK11Attribute *attr;
+ unsigned int trustFlags;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ default:
+ break;
+ }
+ cert = pk11_getCert(object);
+ if (cert == NULL) {
+ return NULL;
+ }
+ switch (type) {
+ case CKA_CERT_SHA1_HASH:
+ SHA1_HashBuf(hash,cert->derCert.data,cert->derCert.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_CERT_MD5_HASH:
+ MD5_HashBuf(hash,cert->derCert.data,cert->derCert.len);
+ return pk11_NewTokenAttribute(type,hash,MD5_LENGTH, PR_TRUE);
+ case CKA_ISSUER:
+ return pk11_NewTokenAttribute(type,cert->derIssuer.data,
+ cert->derIssuer.len, PR_FALSE);
+ case CKA_SERIAL_NUMBER:
+ item = SEC_ASN1EncodeItem(NULL,NULL,cert,pk11_SerialTemplate);
+ if (item == NULL) break;
+ attr = pk11_NewTokenAttribute(type, item->data, item->len, PR_TRUE);
+ SECITEM_FreeItem(item,PR_TRUE);
+ return attr;
+ case CKA_TRUST_CLIENT_AUTH:
+ trustFlags = cert->trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ?
+ cert->trust->sslFlags | CERTDB_TRUSTED_CA : 0 ;
+ goto trust;
+ case CKA_TRUST_SERVER_AUTH:
+ trustFlags = cert->trust->sslFlags;
+ goto trust;
+ case CKA_TRUST_EMAIL_PROTECTION:
+ trustFlags = cert->trust->emailFlags;
+ goto trust;
+ case CKA_TRUST_CODE_SIGNING:
+ trustFlags = cert->trust->objectSigningFlags;
+trust:
+ if (trustFlags & CERTDB_TRUSTED_CA ) {
+ return (PK11Attribute *)&pk11_StaticTrustedDelegatorAttr;
+ }
+ if (trustFlags & CERTDB_TRUSTED) {
+ return (PK11Attribute *)&pk11_StaticTrustedAttr;
+ }
+ if (trustFlags & CERTDB_NOT_TRUSTED) {
+ return (PK11Attribute *)&pk11_StaticUnTrustedAttr;
+ }
+ if (trustFlags & CERTDB_TRUSTED_UNKNOWN) {
+ return (PK11Attribute *)&pk11_StaticTrustUnknownAttr;
+ }
+ return (PK11Attribute *)&pk11_StaticMustVerifyAttr;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindCrlAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ SECItem *crl;
+ char *url;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_NETSCAPE_KRL:
+ return (PK11Attribute *) ((object->obj.handle == PK11_TOKEN_KRL_HANDLE)
+ ? &pk11_StaticTrueAttr : &pk11_StaticFalseAttr);
+ case CKA_NETSCAPE_URL:
+ url = pk11_getUrl(object);
+ if (url == NULL) {
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ }
+ return pk11_NewTokenAttribute(type, url, PORT_Strlen(url)+1, PR_TRUE);
+ case CKA_VALUE:
+ crl = pk11_getCrl(object);
+ if (crl == NULL) break;
+ return pk11_NewTokenAttribute(type, crl->data, crl->len, PR_FALSE);
+ case CKA_SUBJECT:
+ return pk11_NewTokenAttribute(type,object->dbKey.data,
+ object->dbKey.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWCERTCertificate *cert;
+ NSSLOWKEYPublicKey *pubKey;
+ unsigned char hash[SHA1_LENGTH];
+ SECItem *item;
+ PK11Attribute *attr;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_CERTIFICATE_TYPE:
+ /* hardcoding X.509 into here */
+ return (PK11Attribute *)&pk11_StaticX509Attr;
+ default:
+ break;
+ }
+ cert = pk11_getCert(object);
+ if (cert == NULL) {
+ return NULL;
+ }
+ switch (type) {
+ case CKA_VALUE:
+ return pk11_NewTokenAttribute(type,cert->derCert.data,
+ cert->derCert.len,PR_FALSE);
+ case CKA_ID:
+ pubKey = nsslowcert_ExtractPublicKey(cert);
+ if (pubKey == NULL) break;
+ item = pk11_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 pk11_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE);
+ case CKA_LABEL:
+ return cert->nickname ? pk11_NewTokenAttribute(type, cert->nickname,
+ PORT_Strlen(cert->nickname)+1, PR_FALSE) :
+ (PK11Attribute *) &pk11_StaticNullAttr;
+ case CKA_SUBJECT:
+ return pk11_NewTokenAttribute(type,cert->derSubject.data,
+ cert->derSubject.len, PR_FALSE);
+ case CKA_ISSUER:
+ return pk11_NewTokenAttribute(type,cert->derIssuer.data,
+ cert->derIssuer.len, PR_FALSE);
+ case CKA_SERIAL_NUMBER:
+ item = SEC_ASN1EncodeItem(NULL,NULL,cert,pk11_SerialTemplate);
+ if (item == NULL) break;
+ attr = pk11_NewTokenAttribute(type, item->data, item->len, PR_TRUE);
+ SECITEM_FreeItem(item,PR_TRUE);
+ return attr;
+ default:
+ break;
+ }
+ return NULL;
+}
-
+static PK11Attribute *
+pk11_FindTokenAttribute(PK11TokenObject *object,CK_ATTRIBUTE_TYPE type)
+{
+ /* handle the common ones */
+ switch (type) {
+ case CKA_CLASS:
+ return pk11_NewTokenAttribute(type,&object->obj.objclass,
+ sizeof(object->obj.objclass),PR_FALSE);
+ case CKA_TOKEN:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_LABEL:
+ return (object->obj.objclass != CKO_CERTIFICATE) ?
+ (PK11Attribute *) &pk11_StaticNullAttr :
+ pk11_FindCertAttribute(object,type);
+ default:
+ break;
+ }
+ switch (object->obj.objclass) {
+ case CKO_CERTIFICATE:
+ return pk11_FindCertAttribute(object,type);
+ case CKO_NETSCAPE_CRL:
+ return pk11_FindCrlAttribute(object,type);
+ case CKO_NETSCAPE_TRUST:
+ return pk11_FindTrustAttribute(object,type);
+ case CKO_NETSCAPE_SMIME:
+ return pk11_FindSMIMEAttribute(object,type);
+ case CKO_PUBLIC_KEY:
+ return pk11_FindPublicKeyAttribute(object,type);
+ case CKO_PRIVATE_KEY:
+ return pk11_FindPrivateKeyAttribute(object,type);
+ case CKO_SECRET_KEY:
+ return pk11_FindSecretKeyAttribute(object,type);
+ default:
+ break;
+ }
+ PORT_Assert(0);
+ return NULL;
+}
+
/*
* look up and attribute structure from a type and Object structure.
* The returned attribute is referenced and needs to be freed when
@@ -169,10 +1036,15 @@ PK11Attribute *
pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
{
PK11Attribute *attribute;
+ PK11SessionObject *sessObject = pk11_narrowToSessionObject(object);
+
+ if (sessObject == NULL) {
+ return pk11_FindTokenAttribute(pk11_narrowToTokenObject(object),type);
+ }
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
- pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE);
-#ifdef REF_COUNT_ATTRIBUTE
+ PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);)
+ pk11queue_find(attribute,type,sessObject->head,ATTRIBUTE_HASH_SIZE);
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
if (attribute) {
/* atomic increment would be nice here */
PK11_USE_THREADS(PZ_Lock(attribute->refLock);)
@@ -180,31 +1052,19 @@ pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
PK11_USE_THREADS(PZ_Unlock(attribute->refLock);)
}
#endif
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);)
return(attribute);
}
-/*
- * release a reference to an attribute structure
- */
-void
-pk11_FreeAttribute(PK11Attribute *attribute)
-{
-#ifdef REF_COUNT_ATTRIBUTE
- PRBool destroy = PR_FALSE;
-
- PK11_USE_THREADS(PZ_Lock(attribute->refLock);)
- if (attribute->refCount == 1) destroy = PR_TRUE;
- attribute->refCount--;
- PK11_USE_THREADS(PZ_Unlock(attribute->refLock);)
- if (destroy) pk11_DestroyAttribute(attribute);
-#endif
+PRBool
+pk11_hasAttributeToken(PK11TokenObject *object)
+{
+ return PR_FALSE;
}
-
/*
* return true if object has attribute
*/
@@ -212,10 +1072,15 @@ PRBool
pk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
{
PK11Attribute *attribute;
+ PK11SessionObject *sessObject = pk11_narrowToSessionObject(object);
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
- pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE);
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ if (sessObject == NULL) {
+ return pk11_hasAttributeToken(pk11_narrowToTokenObject(object));
+ }
+
+ PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);)
+ pk11queue_find(attribute,type,sessObject->head,ATTRIBUTE_HASH_SIZE);
+ PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);)
return (PRBool)(attribute != NULL);
}
@@ -223,12 +1088,16 @@ pk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
/*
* add an attribute to an object
*/
-static
-void pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute)
+static void
+pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute)
{
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
- pk11queue_add(attribute,attribute->handle,object->head,ATTRIBUTE_HASH_SIZE);
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ PK11SessionObject *sessObject = pk11_narrowToSessionObject(object);
+
+ if (sessObject == NULL) return;
+ PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);)
+ pk11queue_add(attribute,attribute->handle,
+ sessObject->head,ATTRIBUTE_HASH_SIZE);
+ PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);)
}
/*
@@ -277,13 +1146,18 @@ pk11_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,PK11Object *object,
static void
pk11_DeleteAttribute(PK11Object *object, PK11Attribute *attribute)
{
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
+ PK11SessionObject *sessObject = pk11_narrowToSessionObject(object);
+
+ if (sessObject == NULL) {
+ return ;
+ }
+ PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);)
if (pk11queue_is_queued(attribute,attribute->handle,
- object->head,ATTRIBUTE_HASH_SIZE)) {
+ sessObject->head,ATTRIBUTE_HASH_SIZE)) {
pk11queue_delete(attribute,attribute->handle,
- object->head,ATTRIBUTE_HASH_SIZE);
+ sessObject->head,ATTRIBUTE_HASH_SIZE);
}
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);)
pk11_FreeAttribute(attribute);
}
@@ -320,20 +1194,106 @@ pk11_nullAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
if (attribute->attrib.pValue != NULL) {
PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
-#ifdef REF_COUNT_ATTRIBUTE
- PORT_Free(attribute->attrib.pValue);
-#endif /* REF_COUNT_ATTRIBUTE */
-#ifdef NO_ARENA
- if (attribute->attrib.pValue != attribute->space) {
+ if (attribute->freeData) {
PORT_Free(attribute->attrib.pValue);
}
-#endif /* NO_ARENA */
+ attribute->freeData = PR_FALSE;
attribute->attrib.pValue = NULL;
attribute->attrib.ulValueLen = 0;
}
pk11_FreeAttribute(attribute);
}
+static CK_RV
+pk11_SetTrustAttribute(PK11TokenObject *to, CK_ATTRIBUTE_TYPE type,
+ void *value, unsigned int len)
+{
+ unsigned int flags;
+ CK_TRUST trust;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertTrust dbTrust;
+ SECStatus rv;
+
+ if (to->obj.slot->certDB == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ if (len != sizeof (CK_TRUST)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ trust = *(CK_TRUST *)value;
+ flags = pk11_MapTrust(trust, (PRBool) (type == CKA_TRUST_SERVER_AUTH));
+
+ cert = pk11_getCert(to);
+ if (cert == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+ 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:
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ rv = nsslowcert_ChangeCertTrust(to->obj.slot->certDB,cert,&dbTrust);
+ if (rv != SECSuccess) {
+ return CKR_DEVICE_ERROR;
+ }
+ return CKR_OK;
+}
+
+static CK_RV
+pk11_forceTokenAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type,
+ void *value, unsigned int len)
+{
+ PK11Attribute *attribute;
+ PK11TokenObject *to = pk11_narrowToTokenObject(object);
+ CK_RV crv = CKR_ATTRIBUTE_READ_ONLY;
+
+ 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. */
+ attribute=pk11_FindAttribute(object,type);
+ if ((attribute->attrib.ulValueLen == len) &&
+ PORT_Memcmp(attribute->attrib.pValue,value,len) == 0) {
+ pk11_FreeAttribute(attribute);
+ return CKR_OK;
+ }
+
+ switch (object->objclass) {
+ case CKO_CERTIFICATE:
+ /* change NICKNAME, EMAIL, */
+ break;
+ case CKO_NETSCAPE_CRL:
+ /* change URL */
+ break;
+ case CKO_NETSCAPE_TRUST:
+ crv = pk11_SetTrustAttribute(to,type,value,len);
+ break;
+ }
+ pk11_FreeAttribute(attribute);
+ return crv;
+}
+
/*
* force an attribute to a spaecif value.
*/
@@ -343,25 +1303,31 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value,
{
PK11Attribute *attribute;
void *att_val = NULL;
+ PRBool freeData = PR_FALSE;
+ if (pk11_isToken(object->handle)) {
+ return pk11_forceTokenAttribute(object,type,value,len);
+ }
attribute=pk11_FindAttribute(object,type);
if (attribute == NULL) return pk11_AddAttributeType(object,type,value,len);
if (value) {
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
if (len <= ATTR_SPACE) {
att_val = attribute->space;
} else {
att_val = PORT_Alloc(len);
+ freeData = PR_TRUE;
}
#else
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
att_val = PORT_Alloc(len);
+ freeData = PR_TRUE;
#else
att_val = PORT_ArenaAlloc(object->arena,len);
-#endif /* REF_COUNT_ATTRIBUTE */
-#endif /* NO_ARENA */
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
+#endif /* PKCS11_STATIC_ATTRIBUTES */
if (att_val == NULL) {
return CKR_HOST_MEMORY;
}
@@ -376,21 +1342,19 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value,
PORT_Memset(attribute->attrib.pValue,0,
attribute->attrib.ulValueLen);
}
-#ifdef REF_COUNT_ATTRIBUTE
- PORT_Free(attribute->attrib.pValue);
-#endif /* REF_COUNT_ATTRIBUTE */
-#ifdef NO_ARENA
- if (attribute->attrib.pValue != attribute->space) {
+ if (attribute->freeData) {
PORT_Free(attribute->attrib.pValue);
}
-#endif /* NO_ARENA */
+ attribute->freeData = PR_FALSE;
attribute->attrib.pValue = NULL;
attribute->attrib.ulValueLen = 0;
}
if (att_val) {
attribute->attrib.pValue = att_val;
attribute->attrib.ulValueLen = len;
+ attribute->freeData = freeData;
}
+ pk11_FreeAttribute(attribute);
return CKR_OK;
}
@@ -591,6 +1555,62 @@ pk11_AddAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *valPtr,
* ******************** Object Utilities *******************************
*/
+static SECStatus
+pk11_deleteTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle)
+{
+ SECItem *item;
+ PRBool rem;
+
+ item = (SECItem *)PL_HashTableLookupConst(slot->tokenHashTable,
+ (void *)handle);
+ if (item) {
+ SECITEM_FreeItem(item,PR_TRUE);
+ }
+ rem = PL_HashTableRemove(slot->tokenHashTable,(void *)handle) ;
+ return rem ? SECSuccess : SECFailure;
+}
+
+static SECStatus
+pk11_addTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle, SECItem *key)
+{
+ PLHashEntry *entry;
+ SECItem *item;
+
+ item = SECITEM_DupItem(key);
+ if (item == NULL) {
+ return SECFailure;
+ }
+ entry = PL_HashTableAdd(slot->tokenHashTable,(void *)handle,item);
+ if (entry == NULL) {
+ SECITEM_FreeItem(item,PR_TRUE);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+static SECItem *
+pk11_lookupTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle)
+{
+ return (SECItem *)PL_HashTableLookupConst(slot->tokenHashTable,
+ (void *)handle);
+}
+
+/*
+ * use the refLock. This operations should be very rare, so the added
+ * contention on the ref lock should be lower than the overhead of adding
+ * a new lock. We use separate functions for this just in case I'm wrong.
+ */
+static void
+pk11_tokenKeyLock(PK11Slot *slot) {
+ PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
+}
+
+static void
+pk11_tokenKeyUnlock(PK11Slot *slot) {
+ PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
+}
+
+
/* allocation hooks that allow us to recycle old object structures */
#ifdef MAX_OBJECT_LIST_SIZE
static PK11Object * objectFreeList = NULL;
@@ -620,26 +1640,26 @@ pk11_GetObjectFromList(PRBool *hasLocks) {
}
#endif
- object = (PK11Object*)PORT_ZAlloc(sizeof(PK11Object));
+ object = (PK11Object*)PORT_ZAlloc(sizeof(PK11SessionObject));
*hasLocks = PR_FALSE;
return object;
}
static void
-pk11_PutObjectToList(PK11Object *object) {
+pk11_PutObjectToList(PK11SessionObject *object) {
#ifdef MAX_OBJECT_LIST_SIZE
if (object_count < MAX_OBJECT_LIST_SIZE) {
PK11_USE_THREADS(PZ_Lock(objectLock));
- object->next = objectFreeList;
- objectFreeList = object;
+ object->obj.next = objectFreeList;
+ objectFreeList = &object->obj;
object_count++;
PK11_USE_THREADS(PZ_Unlock(objectLock));
return;
}
#endif
PK11_USE_THREADS(PZ_DestroyLock(object->attributeLock);)
- PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
- object->attributeLock = object->refLock = NULL;
+ PK11_USE_THREADS(PZ_DestroyLock(object->obj.refLock);)
+ object->attributeLock = object->obj.refLock = NULL;
PORT_Free(object);
}
@@ -651,58 +1671,63 @@ PK11Object *
pk11_NewObject(PK11Slot *slot)
{
PK11Object *object;
+ PK11SessionObject *sessObject;
PRBool hasLocks = PR_FALSE;
int i;
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
object = pk11_GetObjectFromList(&hasLocks);
if (object == NULL) {
return NULL;
}
- object->nextAttr = 0;
+ sessObject = (PK11SessionObject *)object;
+ sessObject->nextAttr = 0;
+
+ for (i=0; i < MAX_OBJS_ATTRS; i++) {
+ sessObject->attrList[i].attrib.pValue = NULL;
+ sessObject->attrList[i].freeData = PR_FALSE;
+ }
#else
+ PRArenaPool *arena;
+
arena = PORT_NewArena(2048);
if (arena == NULL) return NULL;
- object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11Object));
+ object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11SessionObject));
if (object == NULL) {
PORT_FreeArena(arena,PR_FALSE);
return NULL;
}
object->arena = arena;
- for (i=0; i < MAX_OBJS_ATTRS; i++) {
- object->attrList[i].attrib.pValue = NULL;
- }
+ sessObject = (PK11SessionObject *)object;
#endif
object->handle = 0;
object->next = object->prev = NULL;
- object->sessionList.next = NULL;
- object->sessionList.prev = NULL;
- object->sessionList.parent = object;
- object->inDB = PR_FALSE;
- object->label = NULL;
- object->refCount = 1;
- object->session = NULL;
object->slot = slot;
object->objclass = 0xffff;
- object->wasDerived = PR_FALSE;
+ object->refCount = 1;
+ sessObject->sessionList.next = NULL;
+ sessObject->sessionList.prev = NULL;
+ sessObject->sessionList.parent = object;
+ sessObject->session = NULL;
+ sessObject->wasDerived = PR_FALSE;
#ifdef PKCS11_USE_THREADS
if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock);
if (object->refLock == NULL) {
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
PORT_Free(object);
#else
PORT_FreeArena(arena,PR_FALSE);
#endif
return NULL;
}
- if (!hasLocks) object->attributeLock = PZ_NewLock(nssILockAttribute);
- if (object->attributeLock == NULL) {
+ if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute);
+ if (sessObject->attributeLock == NULL) {
PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
PORT_Free(object);
#else
PORT_FreeArena(arena,PR_FALSE);
@@ -710,17 +1735,55 @@ pk11_NewObject(PK11Slot *slot)
return NULL;
}
#else
- object->attributeLock = NULL;
+ sessObject->attributeLock = NULL;
object->refLock = NULL;
#endif
for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
- object->head[i] = NULL;
+ sessObject->head[i] = NULL;
}
object->objectInfo = NULL;
object->infoFree = NULL;
return object;
}
+static CK_RV
+pk11_DestroySessionObjectData(PK11SessionObject *so)
+{
+ int i;
+
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ for (i=0; i < MAX_OBJS_ATTRS; i++) {
+ unsigned char *value = so->attrList[i].attrib.pValue;
+ if (value) {
+ PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen);
+ if (so->attrList[i].freeData) {
+ PORT_Free(value);
+ }
+ so->attrList[i].attrib.pValue = NULL;
+ so->attrList[i].freeData = PR_FALSE;
+ }
+ }
+#endif
+
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ /* clean out the attributes */
+ /* since no one is referencing us, it's safe to walk the chain
+ * without a lock */
+ for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
+ PK11Attribute *ap,*next;
+ for (ap = so->head[i]; ap != NULL; ap = next) {
+ next = ap->next;
+ /* paranoia */
+ ap->next = ap->prev = NULL;
+ pk11_FreeAttribute(ap);
+ }
+ so->head[i] = NULL;
+ }
+#endif
+/* PK11_USE_THREADS(PZ_DestroyLock(so->attributeLock));*/
+ return CKR_OK;
+}
+
/*
* free all the data associated with an object. Object reference count must
* be 'zero'.
@@ -728,86 +1791,33 @@ pk11_NewObject(PK11Slot *slot)
static CK_RV
pk11_DestroyObject(PK11Object *object)
{
-#if defined(REF_COUNT_ATTRIBUTE) || defined(NO_ARENA)
- int i;
-#endif
- SECItem pubKey;
CK_RV crv = CKR_OK;
- SECStatus rv;
+ PK11SessionObject *so = pk11_narrowToSessionObject(object);
+ PK11TokenObject *to = pk11_narrowToTokenObject(object);
PORT_Assert(object->refCount == 0);
/* delete the database value */
- if (object->inDB) {
- if (pk11_isToken(object->handle)) {
- /* remove the objects from the real data base */
- switch (object->handle & PK11_TOKEN_TYPE_MASK) {
- case PK11_TOKEN_TYPE_PRIV:
- /* KEYID is the public KEY for DSA and DH, and the MODULUS for
- * RSA */
- crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
- if (crv != CKR_OK) break;
- rv = SECKEY_DeleteKey(SECKEY_GetDefaultKeyDB(), &pubKey);
- if (rv != SECSuccess && pubKey.data[0] == 0) {
- /* Because of legacy code issues, sometimes the public key
- * has a '0' prepended to it, forcing it to be unsigned.
- * The database may not store that '0', so remove it and
- * try again.
- */
- SECItem tmpPubKey;
- tmpPubKey.data = pubKey.data + 1;
- tmpPubKey.len = pubKey.len - 1;
- rv = SECKEY_DeleteKey(SECKEY_GetDefaultKeyDB(), &tmpPubKey);
- }
- if (rv != SECSuccess) crv= CKR_DEVICE_ERROR;
- break;
- case PK11_TOKEN_TYPE_CERT:
- rv = SEC_DeletePermCertificate((CERTCertificate *)object->objectInfo);
- if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
- break;
- }
+ if (to) {
+ if (to->dbKey.data) {
+ PORT_Free(to->dbKey.data);
+ to->dbKey.data = NULL;
}
}
- if (object->label) PORT_Free(object->label);
-
- object->inDB = PR_FALSE;
- object->label = NULL;
-
-#ifdef NO_ARENA
- for (i=0; i < MAX_OBJS_ATTRS; i++) {
- unsigned char *value = object->attrList[i].attrib.pValue;
- if (value) {
- PORT_Memset(value,0,object->attrList[i].attrib.ulValueLen);
- if (value != object->attrList[i].space) {
- PORT_Free(value);
- }
- object->attrList[i].attrib.pValue = NULL;
- }
+ if (so) {
+ pk11_DestroySessionObjectData(so);
}
-#endif
-
-#ifdef REF_COUNT_ATTRIBUTE
- /* clean out the attributes */
- /* since no one is referencing us, it's safe to walk the chain
- * without a lock */
- for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
- PK11Attribute *ap,*next;
- for (ap = object->head[i]; ap != NULL; ap = next) {
- next = ap->next;
- /* paranoia */
- ap->next = ap->prev = NULL;
- pk11_FreeAttribute(ap);
- }
- object->head[i] = NULL;
- }
-#endif
if (object->objectInfo) {
(*object->infoFree)(object->objectInfo);
}
-#ifdef NO_ARENA
- pk11_PutObjectToList(object);
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ if (so) {
+ pk11_PutObjectToList(so);
+ } else {
+ PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
+ PORT_Free(to);;
+ }
#else
- PK11_USE_THREADS(PZ_DestroyLock(object->attributeLock);)
PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
arena = object->arena;
PORT_FreeArena(arena,PR_FALSE);
@@ -830,6 +1840,10 @@ pk11_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, PK11Slot *slot)
PZLock *lock;
PK11Object *object;
+ if (pk11_isToken(handle)) {
+ return pk11_NewTokenObject(slot, NULL, handle);
+ }
+
head = slot->tokObjects;
lock = slot->objectLock;
@@ -888,7 +1902,8 @@ void
pk11_AddSlotObject(PK11Slot *slot, PK11Object *object)
{
PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
- pk11queue_add(object,object->handle,slot->tokObjects,TOKEN_OBJECT_HASH_SIZE);
+ pk11queue_add(object,object->handle,slot->tokObjects,
+ TOKEN_OBJECT_HASH_SIZE);
PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
}
@@ -896,35 +1911,98 @@ void
pk11_AddObject(PK11Session *session, PK11Object *object)
{
PK11Slot *slot = pk11_SlotFromSession(session);
+ PK11SessionObject *so = pk11_narrowToSessionObject(object);
- if (!pk11_isToken(object->handle)) {
+ if (so) {
PK11_USE_THREADS(PZ_Lock(session->objectLock);)
- pk11queue_add(&object->sessionList,0,session->objects,0);
- object->session = session;
+ pk11queue_add(&so->sessionList,0,session->objects,0);
+ so->session = session;
PK11_USE_THREADS(PZ_Unlock(session->objectLock);)
}
pk11_AddSlotObject(slot,object);
+ pk11_ReferenceObject(object);
}
/*
* add an object to a slot andsession queue
*/
-void
+CK_RV
pk11_DeleteObject(PK11Session *session, PK11Object *object)
{
PK11Slot *slot = pk11_SlotFromSession(session);
+ PK11SessionObject *so = pk11_narrowToSessionObject(object);
+ PK11TokenObject *to = pk11_narrowToTokenObject(object);
+ CK_RV crv = CKR_OK;
+ SECStatus rv;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertTrust tmptrust;
+ PRBool isKrl;
- if (object->session) {
- PK11Session *session = object->session;
+ /* Handle Token case */
+ if (so && so->session) {
+ PK11Session *session = so->session;
PK11_USE_THREADS(PZ_Lock(session->objectLock);)
- pk11queue_delete(&object->sessionList,0,session->objects,0);
+ pk11queue_delete(&so->sessionList,0,session->objects,0);
PK11_USE_THREADS(PZ_Unlock(session->objectLock);)
- }
- PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
- pk11queue_delete(object,object->handle,slot->tokObjects,
+ PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
+ pk11queue_delete(object,object->handle,slot->tokObjects,
TOKEN_OBJECT_HASH_SIZE);
- PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
- pk11_FreeObject(object);
+ PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
+ pk11_FreeObject(object); /* reduce it's reference count */
+ } else {
+ PORT_Assert(to);
+ /* remove the objects from the real data base */
+ switch (object->handle & PK11_TOKEN_TYPE_MASK) {
+ case PK11_TOKEN_TYPE_PRIV:
+ case PK11_TOKEN_TYPE_KEY:
+ /* KEYID is the public KEY for DSA and DH, and the MODULUS for
+ * RSA */
+ PORT_Assert(slot->keyDB);
+ rv = nsslowkey_DeleteKey(slot->keyDB, &to->dbKey);
+ if (rv != SECSuccess) crv= CKR_DEVICE_ERROR;
+ break;
+ case PK11_TOKEN_TYPE_PUB:
+ break; /* public keys only exist at the behest of the priv key */
+ case PK11_TOKEN_TYPE_CERT:
+ cert = nsslowcert_FindCertByKey(slot->certDB,&to->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 PK11_TOKEN_TYPE_CRL:
+ isKrl = (PRBool) (object->handle == PK11_TOKEN_KRL_HANDLE);
+ rv = nsslowcert_DeletePermCRL(slot->certDB,&to->dbKey,isKrl);
+ if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
+ break;
+ case PK11_TOKEN_TYPE_TRUST:
+ cert = nsslowcert_FindCertByKey(slot->certDB,&to->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(slot->certDB,cert,&tmptrust);
+ if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
+ nsslowcert_DestroyCertificate(cert);
+ break;
+ default:
+ break;
+ }
+ pk11_tokenKeyLock(object->slot);
+ pk11_deleteTokenKeyByHandle(object->slot,object->handle);
+ pk11_tokenKeyUnlock(object->slot);
+ }
+ return crv;
}
/*
@@ -936,11 +2014,16 @@ CK_RV
pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject)
{
PK11Attribute *attribute;
+ PK11SessionObject *src_so = pk11_narrowToSessionObject(srcObject);
int i;
- PK11_USE_THREADS(PZ_Lock(srcObject->attributeLock);)
+ if (src_so == NULL) {
+ return CKR_DEVICE_ERROR; /* can't copy token objects yet */
+ }
+
+ PK11_USE_THREADS(PZ_Lock(src_so->attributeLock);)
for(i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
- attribute = srcObject->head[i];
+ attribute = src_so->head[i];
do {
if (attribute) {
if (!pk11_hasAttribute(destObject,attribute->handle)) {
@@ -949,7 +2032,7 @@ pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject)
PK11Attribute *newAttribute = pk11_NewAttribute(
destObject,pk11_attr_expand(&attribute->attrib));
if (newAttribute == NULL) {
- PK11_USE_THREADS(PZ_Unlock(srcObject->attributeLock);)
+ PK11_USE_THREADS(PZ_Unlock(src_so->attributeLock);)
return CKR_HOST_MEMORY;
}
pk11_AddAttribute(destObject,newAttribute);
@@ -958,7 +2041,7 @@ pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject)
}
} while (attribute != NULL);
}
- PK11_USE_THREADS(PZ_Unlock(srcObject->attributeLock);)
+ PK11_USE_THREADS(PZ_Unlock(src_so->attributeLock);)
return CKR_OK;
}
@@ -1012,7 +2095,7 @@ pk11_objectMatch(PK11Object *object,CK_ATTRIBUTE_PTR theTemplate,int count)
* in the object list.
*/
CK_RV
-pk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head,
+pk11_searchObjectList(PK11SearchResults *search,PK11Object **head,
PZLock *lock, CK_ATTRIBUTE_PTR theTemplate, int count, PRBool isLoggedIn)
{
int i;
@@ -1027,10 +2110,7 @@ pk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head,
if (pk11_objectMatch(object,theTemplate,count)) {
/* don't return objects that aren't yet visible */
if ((!isLoggedIn) && pk11_isTrue(object,CKA_PRIVATE)) continue;
- crv = AddToList(objectList,object);
- if (crv != CKR_OK) {
- break;
- }
+ pk11_addHandle(search,object->handle);
}
}
PK11_USE_THREADS(PZ_Unlock(lock);)
@@ -1126,37 +2206,11 @@ pk11_FreeContext(PK11SessionContext *context)
if (context->hashInfo) {
(*context->hashdestroy)(context->hashInfo,PR_TRUE);
}
- PORT_Free(context);
-}
-
-/* look up a slot structure from the ID (used to be a macro when we only
- * had two slots) */
-PK11Slot *
-pk11_SlotFromID(CK_SLOT_ID slotID)
-{
- switch (slotID) {
- case NETSCAPE_SLOT_ID:
- return &pk11_slot[0];
- case PRIVATE_KEY_SLOT_ID:
- return &pk11_slot[1];
- case FIPS_SLOT_ID:
- return &pk11_slot[2];
- default:
- break; /* fall through to NULL */
+ if (context->key) {
+ pk11_FreeObject(context->key);
+ context->key = NULL;
}
- return NULL;
-}
-
-PK11Slot *
-pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle)
-{
- if (handle & PK11_PRIVATE_KEY_FLAG) {
- return &pk11_slot[1];
- }
- if (handle & PK11_FIPS_FLAG) {
- return &pk11_slot[2];
- }
- return &pk11_slot[0];
+ PORT_Free(context);
}
/*
@@ -1278,3 +2332,190 @@ pk11_FreeSession(PK11Session *session)
if (destroy) pk11_DestroySession(session);
}
+/*
+ * handle Token Object stuff
+ */
+
+/* Make a token handle for an object and record it so we can find it again */
+CK_OBJECT_HANDLE
+pk11_mkHandle(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class)
+{
+ unsigned char hashBuf[SHA1_LENGTH];
+ CK_OBJECT_HANDLE handle;
+ SECItem *key;
+
+ handle = class;
+ /* there is only one KRL, use a fixed handle for it */
+ if (handle != PK11_TOKEN_KRL_HANDLE) {
+ SHA1_HashBuf(hashBuf,dbKey->data,dbKey->len);
+ handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
+ (hashBuf[2] << 8) | hashBuf[3];
+ handle = PK11_TOKEN_MAGIC | class |
+ (handle & ~(PK11_TOKEN_TYPE_MASK|PK11_TOKEN_MASK));
+ /* we have a CRL who's handle has randomly matched the reserved KRL
+ * handle, increment it */
+ if (handle == PK11_TOKEN_KRL_HANDLE) {
+ handle++;
+ }
+ }
+
+ pk11_tokenKeyLock(slot);
+ while ((key = pk11_lookupTokenKeyByHandle(slot,handle)) != NULL) {
+ if (SECITEM_ItemsAreEqual(key,dbKey)) {
+ pk11_tokenKeyUnlock(slot);
+ return handle;
+ }
+ handle++;
+ }
+ pk11_addTokenKeyByHandle(slot,handle,dbKey);
+ pk11_tokenKeyUnlock(slot);
+ return handle;
+}
+
+void
+pk11_addHandle(PK11SearchResults *search, CK_OBJECT_HANDLE handle)
+{
+ if (search->handles == NULL) {
+ return;
+ }
+ if (search->size >= search->array_size) {
+ search->array_size += NSC_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++;
+}
+
+static const CK_OBJECT_HANDLE pk11_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) \
+ pk11_classArray[((handle & PK11_TOKEN_TYPE_MASK))>>28]
+
+PK11Object *
+pk11_NewTokenObject(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
+{
+ PK11Object *object = NULL;
+ PK11TokenObject *tokObject = NULL;
+ SECStatus rv;
+
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ object = (PK11Object *) PORT_ZAlloc(sizeof(PK11TokenObject));
+ if (object == NULL) {
+ return NULL;
+ }
+#else
+ PRArenaPool *arena;
+
+ arena = PORT_NewArena(2048);
+ if (arena == NULL) return NULL;
+
+ object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11TokenObject));
+ if (object == NULL) {
+ PORT_FreeArena(arena,PR_FALSE);
+ return NULL;
+ }
+ object->arena = arena;
+#endif
+ tokObject = (PK11TokenObject *) object;
+
+ object->objclass = handleToClass(handle);
+ object->handle = handle;
+ object->refCount = 1;
+ object->slot = slot;
+ object->objectInfo = NULL;
+ object->infoFree = NULL;
+ if (dbKey == NULL) {
+ pk11_tokenKeyLock(slot);
+ dbKey = pk11_lookupTokenKeyByHandle(slot,handle);
+ if (dbKey == NULL) {
+ pk11_tokenKeyUnlock(slot);
+ goto loser;
+ }
+ rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
+ pk11_tokenKeyUnlock(slot);
+ } else {
+ rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
+ }
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+#ifdef PKCS11_USE_THREADS
+ object->refLock = PZ_NewLock(nssILockRefLock);
+ if (object->refLock == NULL) {
+ goto loser;
+ }
+#endif
+
+ return object;
+loser:
+ if (object) {
+ pk11_FreeObject(object);
+ }
+ return NULL;
+
+}
+
+PRBool
+pk11_tokenMatch(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class,
+ CK_ATTRIBUTE_PTR theTemplate,int count)
+{
+ PK11Object *object;
+ PRBool ret;
+
+ object = pk11_NewTokenObject(slot,dbKey,PK11_TOKEN_MASK|class);
+ if (object == NULL) {
+ return PR_FALSE;
+ }
+
+ ret = pk11_objectMatch(object,theTemplate,count);
+ pk11_FreeObject(object);
+ return ret;
+}
+
+PK11TokenObject *
+pk11_convertSessionToToken(PK11SessionObject *so)
+{
+ SECItem *key;
+ PK11TokenObject *to = pk11_narrowToTokenObject(&so->obj);
+ SECStatus rv;
+
+ pk11_DestroySessionObjectData(so);
+ PK11_USE_THREADS(PZ_DestroyLock(so->attributeLock));
+ if (to == NULL) {
+ return NULL;
+ }
+ pk11_tokenKeyLock(so->obj.slot);
+ key = pk11_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle);
+ if (key == NULL) {
+ pk11_tokenKeyUnlock(so->obj.slot);
+ return NULL;
+ }
+ rv = SECITEM_CopyItem(NULL,&to->dbKey,key);
+ pk11_tokenKeyUnlock(so->obj.slot);
+ if (rv == SECFailure) {
+ return NULL;
+ }
+
+ return to;
+
+}
+
+PK11SessionObject *
+pk11_narrowToSessionObject(PK11Object *obj)
+{
+ return !pk11_isToken(obj->handle) ? (PK11SessionObject *)obj : NULL;
+}
+
+PK11TokenObject *
+pk11_narrowToTokenObject(PK11Object *obj)
+{
+ return pk11_isToken(obj->handle) ? (PK11TokenObject *)obj : NULL;
+}
+
diff --git a/security/nss/lib/softoken/rsawrapr.c b/security/nss/lib/softoken/rsawrapr.c
index 7ada1e28c..b1e499016 100644
--- a/security/nss/lib/softoken/rsawrapr.c
+++ b/security/nss/lib/softoken/rsawrapr.c
@@ -40,7 +40,7 @@
#include "softoken.h"
#include "sechash.h"
-#include "keylow.h"
+#include "lowkeyi.h"
#include "secerr.h"
#define RSA_BLOCK_MIN_PAD_LEN 8
@@ -182,8 +182,8 @@ oaep_xor_with_h2(unsigned char *salt, unsigned int saltlen,
* Format one block of data for public/private key encryption using
* the rules defined in PKCS #1.
*/
-unsigned char *
-RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
+static unsigned char *
+rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
SECItem *data)
{
unsigned char *block;
@@ -341,8 +341,8 @@ RSA_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
return block;
}
-SECStatus
-RSA_FormatBlock(SECItem *result, unsigned modulusLen,
+static SECStatus
+rsa_FormatBlock(SECItem *result, unsigned modulusLen,
RSA_BlockType blockType, SECItem *data)
{
/*
@@ -370,7 +370,7 @@ RSA_FormatBlock(SECItem *result, unsigned modulusLen,
*/
PORT_Assert (data->len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)));
- result->data = RSA_FormatOneBlock(modulusLen, blockType, data);
+ result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
if (result->data == NULL) {
result->len = 0;
return SECFailure;
@@ -390,7 +390,7 @@ RSA_FormatBlock(SECItem *result, unsigned modulusLen,
PORT_Assert (data->len <= (modulusLen - (2 + OAEP_SALT_LEN
+ OAEP_PAD_LEN)));
- result->data = RSA_FormatOneBlock(modulusLen, blockType, data);
+ result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
if (result->data == NULL) {
result->len = 0;
return SECFailure;
@@ -420,193 +420,9 @@ RSA_FormatBlock(SECItem *result, unsigned modulusLen,
return SECSuccess;
}
-/*
- * Takes a formatted block and returns the data part.
- * (This is the inverse of RSA_FormatOneBlock().)
- * In some formats the start of the data is ambiguous;
- * if it is non-zero, expectedLen will disambiguate.
- *
- * NOTE: this routine is not yet used/tested! (XXX please
- * remove this comment once that is no longer the case ;-)
- */
-unsigned char *
-RSA_DecodeOneBlock(unsigned char *data,
- unsigned int modulusLen,
- unsigned int expectedLen,
- RSA_BlockType *pResultType,
- unsigned int *pResultLen)
-{
- RSA_BlockType blockType;
- unsigned char *dp, *res;
- unsigned int i, len, padLen;
-
- dp = data;
- if (*dp++ != RSA_BLOCK_FIRST_OCTET) {
- PORT_SetError (SEC_ERROR_BAD_DATA);
- return NULL;
- }
-
- blockType = (RSA_BlockType)*dp++;
- switch (blockType) {
- case RSA_BlockPrivate0:
- if (expectedLen) {
- padLen = modulusLen - expectedLen - 3;
- PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN);
- for (i = 0; i < padLen; i++) {
- if (*dp++ != RSA_BLOCK_PRIVATE0_PAD_OCTET)
- break;
- }
- if ((i != padLen) || (*dp != RSA_BLOCK_AFTER_PAD_OCTET)) {
- PORT_SetError (SEC_ERROR_BAD_DATA);
- return NULL;
- }
- dp++;
- len = expectedLen;
- } else {
- for (i = 0; i < modulusLen; i++) {
- if (*dp++ != RSA_BLOCK_PRIVATE0_PAD_OCTET)
- break;
- }
- if (i == modulusLen) {
- PORT_SetError (SEC_ERROR_BAD_DATA);
- return NULL;
- }
- if (RSA_BLOCK_PRIVATE0_PAD_OCTET == RSA_BLOCK_AFTER_PAD_OCTET)
- dp--;
- padLen = dp - data - 2;
- if ((padLen < RSA_BLOCK_MIN_PAD_LEN)
- || (*dp != RSA_BLOCK_AFTER_PAD_OCTET)) {
- PORT_SetError (SEC_ERROR_BAD_DATA);
- return NULL;
- }
- dp++;
- len = modulusLen - (dp - data);
- }
- res = (unsigned char *) PORT_Alloc(len);
- if (res == NULL) {
- return NULL;
- }
- PORT_Memcpy (res, dp, len);
- break;
-
- case RSA_BlockPrivate:
- for (i = 0; i < modulusLen; i++) {
- if (*dp++ != RSA_BLOCK_PRIVATE_PAD_OCTET)
- break;
- }
- if ((i == modulusLen) || (*dp != RSA_BLOCK_AFTER_PAD_OCTET)) {
- PORT_SetError (SEC_ERROR_BAD_DATA);
- return NULL;
- }
- padLen = dp - data - 2;
- dp++;
- len = modulusLen - (dp - data);
- if ((padLen < RSA_BLOCK_MIN_PAD_LEN) || (expectedLen
- && (expectedLen != len))) {
- PORT_SetError (SEC_ERROR_BAD_DATA);
- return NULL;
- }
- res = (unsigned char *) PORT_Alloc(len);
- if (res == NULL) {
- return NULL;
- }
- PORT_Memcpy (res, dp, len);
- break;
-
- case RSA_BlockPublic:
- for (i = 0; i < modulusLen; i++) {
- if (*dp++ == RSA_BLOCK_AFTER_PAD_OCTET)
- break;
- }
- if (i == modulusLen) {
- PORT_SetError (SEC_ERROR_BAD_DATA);
- return NULL;
- }
- padLen = dp - data - 2;
- dp++;
- len = modulusLen - (dp - data);
- if ((padLen < RSA_BLOCK_MIN_PAD_LEN) || (expectedLen
- && (expectedLen != len))) {
- PORT_SetError (SEC_ERROR_BAD_DATA);
- return NULL;
- }
- res = (unsigned char *) PORT_Alloc(len);
- if (res == NULL) {
- return NULL;
- }
- PORT_Memcpy (res, dp, len);
- break;
-
- case RSA_BlockOAEP:
- {
- unsigned char *salt, *tmp_res;
- SECStatus rv;
-
- len = modulusLen - 2 - OAEP_SALT_LEN;
- /*
- * dp points to:
- * Modified2(Salt) || Modified1(PaddedData)
- * To recover Salt we need to XOR it with the low-order hash
- * of Modified1.
- */
- salt = (unsigned char *) PORT_Alloc(OAEP_SALT_LEN);
- if (salt == NULL) {
- return NULL;
- }
- PORT_Memcpy (salt, dp, OAEP_SALT_LEN);
- dp += OAEP_SALT_LEN;
- rv = oaep_xor_with_h2 (salt, OAEP_SALT_LEN, dp, len);
- if (rv != SECSuccess) {
- PORT_Free (salt);
- return NULL;
- }
- if (expectedLen) {
- PORT_Assert (expectedLen <= len);
- len = expectedLen;
- }
- tmp_res = (unsigned char *) PORT_Alloc(len);
- if (tmp_res == NULL) {
- PORT_Free (salt);
- return NULL;
- }
- PORT_Memcpy (tmp_res, dp, len);
- rv = oaep_xor_with_h1 (tmp_res, len, salt, OAEP_SALT_LEN);
- PORT_Free (salt);
- if (rv != SECSuccess) {
- return NULL;
- }
- for (i = 0; i < OAEP_PAD_LEN; i++) {
- if (tmp_res[i] != OAEP_PAD_OCTET) {
- PORT_SetError (SEC_ERROR_BAD_DATA);
- PORT_Free (tmp_res);
- return NULL;
- }
- }
- len -= OAEP_PAD_LEN;
- res = (unsigned char *) PORT_Alloc(len);
- if (res == NULL) {
- PORT_Free (tmp_res);
- return NULL;
- }
- PORT_Memcpy (res, tmp_res + OAEP_PAD_LEN, len);
- PORT_Free (tmp_res);
- }
- break;
-
- default:
- PORT_SetError (SEC_ERROR_BAD_DATA);
- return NULL;
- }
-
- PORT_Assert (res != NULL);
- *pResultLen = len;
- *pResultType = blockType;
- return res;
-}
-
/* XXX Doesn't set error code */
SECStatus
-RSA_Sign(SECKEYLowPrivateKey *key,
+RSA_Sign(NSSLOWKEYPrivateKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int maxOutputLen,
@@ -614,20 +430,20 @@ RSA_Sign(SECKEYLowPrivateKey *key,
unsigned int input_len)
{
SECStatus rv = SECSuccess;
- unsigned int modulus_len = SECKEY_LowPrivateModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PrivateModulusLen(key);
SECItem formatted;
SECItem unformatted;
if (maxOutputLen < modulus_len)
return SECFailure;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
return SECFailure;
unformatted.len = input_len;
unformatted.data = input;
formatted.data = NULL;
- rv = RSA_FormatBlock(&formatted, modulus_len, RSA_BlockPrivate,
+ rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPrivate,
&unformatted);
if (rv != SECSuccess)
goto done;
@@ -645,24 +461,24 @@ done:
/* XXX Doesn't set error code */
SECStatus
-RSA_CheckSign(SECKEYLowPublicKey *key,
+RSA_CheckSign(NSSLOWKEYPublicKey *key,
unsigned char * sign,
unsigned int sign_len,
unsigned char * hash,
unsigned int hash_len)
{
SECStatus rv;
- unsigned int modulus_len = SECKEY_LowPublicModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
unsigned int i;
unsigned char * buffer;
- modulus_len = SECKEY_LowPublicModulusLen(key);
+ modulus_len = nsslowkey_PublicModulusLen(key);
if (sign_len != modulus_len)
goto failure;
if (hash_len > modulus_len - 8)
goto failure;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
buffer = (unsigned char *)PORT_Alloc(modulus_len + 1);
@@ -702,7 +518,7 @@ failure:
/* XXX Doesn't set error code */
SECStatus
-RSA_CheckSignRecover(SECKEYLowPublicKey *key,
+RSA_CheckSignRecover(NSSLOWKEYPublicKey *key,
unsigned char * data,
unsigned int * data_len,
unsigned int max_output_len,
@@ -710,14 +526,14 @@ RSA_CheckSignRecover(SECKEYLowPublicKey *key,
unsigned int sign_len)
{
SECStatus rv;
- unsigned int modulus_len = SECKEY_LowPublicModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
unsigned int i;
unsigned char * buffer;
if (sign_len != modulus_len)
goto failure;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
buffer = (unsigned char *)PORT_Alloc(modulus_len + 1);
@@ -763,7 +579,7 @@ failure:
/* XXX Doesn't set error code */
SECStatus
-RSA_EncryptBlock(SECKEYLowPublicKey *key,
+RSA_EncryptBlock(NSSLOWKEYPublicKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int max_output_len,
@@ -771,21 +587,21 @@ RSA_EncryptBlock(SECKEYLowPublicKey *key,
unsigned int input_len)
{
SECStatus rv;
- unsigned int modulus_len = SECKEY_LowPublicModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
SECItem formatted;
SECItem unformatted;
formatted.data = NULL;
if (max_output_len < modulus_len)
goto failure;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
unformatted.len = input_len;
unformatted.data = input;
formatted.data = NULL;
- rv = RSA_FormatBlock(&formatted, modulus_len, RSA_BlockPublic,
+ rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPublic,
&unformatted);
if (rv != SECSuccess)
goto failure;
@@ -806,7 +622,7 @@ failure:
/* XXX Doesn't set error code */
SECStatus
-RSA_DecryptBlock(SECKEYLowPrivateKey *key,
+RSA_DecryptBlock(NSSLOWKEYPrivateKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int max_output_len,
@@ -814,12 +630,12 @@ RSA_DecryptBlock(SECKEYLowPrivateKey *key,
unsigned int input_len)
{
SECStatus rv;
- unsigned int modulus_len = SECKEY_LowPrivateModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PrivateModulusLen(key);
unsigned int i;
unsigned char * buffer;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
if (input_len != modulus_len)
goto failure;
@@ -863,7 +679,7 @@ failure:
* RAW is RSA_X_509
*/
SECStatus
-RSA_SignRaw(SECKEYLowPrivateKey *key,
+RSA_SignRaw(NSSLOWKEYPrivateKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int maxOutputLen,
@@ -871,20 +687,20 @@ RSA_SignRaw(SECKEYLowPrivateKey *key,
unsigned int input_len)
{
SECStatus rv = SECSuccess;
- unsigned int modulus_len = SECKEY_LowPrivateModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PrivateModulusLen(key);
SECItem formatted;
SECItem unformatted;
if (maxOutputLen < modulus_len)
return SECFailure;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
return SECFailure;
unformatted.len = input_len;
unformatted.data = input;
formatted.data = NULL;
- rv = RSA_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted);
+ rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted);
if (rv != SECSuccess)
goto done;
@@ -899,22 +715,22 @@ done:
/* XXX Doesn't set error code */
SECStatus
-RSA_CheckSignRaw(SECKEYLowPublicKey *key,
+RSA_CheckSignRaw(NSSLOWKEYPublicKey *key,
unsigned char * sign,
unsigned int sign_len,
unsigned char * hash,
unsigned int hash_len)
{
SECStatus rv;
- unsigned int modulus_len = SECKEY_LowPublicModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
unsigned char * buffer;
if (sign_len != modulus_len)
goto failure;
if (hash_len > modulus_len)
goto failure;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
buffer = (unsigned char *)PORT_Alloc(modulus_len + 1);
@@ -943,7 +759,7 @@ failure:
/* XXX Doesn't set error code */
SECStatus
-RSA_CheckSignRecoverRaw(SECKEYLowPublicKey *key,
+RSA_CheckSignRecoverRaw(NSSLOWKEYPublicKey *key,
unsigned char * data,
unsigned int * data_len,
unsigned int max_output_len,
@@ -951,14 +767,14 @@ RSA_CheckSignRecoverRaw(SECKEYLowPublicKey *key,
unsigned int sign_len)
{
SECStatus rv;
- unsigned int modulus_len = SECKEY_LowPublicModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
if (sign_len != modulus_len)
goto failure;
if (max_output_len < modulus_len)
goto failure;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
rv = RSA_PublicKeyOp(&key->u.rsa, data, sign);
@@ -975,7 +791,7 @@ failure:
/* XXX Doesn't set error code */
SECStatus
-RSA_EncryptRaw(SECKEYLowPublicKey *key,
+RSA_EncryptRaw(NSSLOWKEYPublicKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int max_output_len,
@@ -983,21 +799,21 @@ RSA_EncryptRaw(SECKEYLowPublicKey *key,
unsigned int input_len)
{
SECStatus rv;
- unsigned int modulus_len = SECKEY_LowPublicModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
SECItem formatted;
SECItem unformatted;
formatted.data = NULL;
if (max_output_len < modulus_len)
goto failure;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
unformatted.len = input_len;
unformatted.data = input;
formatted.data = NULL;
- rv = RSA_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted);
+ rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted);
if (rv != SECSuccess)
goto failure;
@@ -1017,7 +833,7 @@ failure:
/* XXX Doesn't set error code */
SECStatus
-RSA_DecryptRaw(SECKEYLowPrivateKey *key,
+RSA_DecryptRaw(NSSLOWKEYPrivateKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int max_output_len,
@@ -1025,14 +841,14 @@ RSA_DecryptRaw(SECKEYLowPrivateKey *key,
unsigned int input_len)
{
SECStatus rv;
- unsigned int modulus_len = SECKEY_LowPrivateModulusLen(key);
+ unsigned int modulus_len = nsslowkey_PrivateModulusLen(key);
if (modulus_len <= 0)
goto failure;
if (modulus_len > max_output_len)
goto failure;
- PORT_Assert(key->keyType == lowRSAKey);
- if (key->keyType != lowRSAKey)
+ PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
+ if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
if (input_len != modulus_len)
goto failure;
diff --git a/security/nss/lib/softoken/secpkcs5.c b/security/nss/lib/softoken/secpkcs5.c
deleted file mode 100644
index 1cfa37206..000000000
--- a/security/nss/lib/softoken/secpkcs5.c
+++ /dev/null
@@ -1,1849 +0,0 @@
-/*
- * 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 Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
-
-#include "plarena.h"
-
-#include "seccomon.h"
-#include "secitem.h"
-#include "secport.h"
-#include "hasht.h"
-#include "pkcs11t.h"
-#include "blapi.h"
-#include "sechash.h"
-#include "secasn1.h"
-#include "secder.h"
-#include "secpkcs5.h"
-#include "secoid.h"
-#include "alghmac.h"
-#include "softoken.h"
-#include "secerr.h"
-
-#define DES_IV_LENGTH 8
-#define RC2_IV_LENGTH 8
-#define MD2_LENGTH 16
-#define MD5_LENGTH 16
-#define SHA1_LENGTH 20
-#define SEED_LENGTH 16
-#define SALT_LENGTH 8
-#define PBE_SALT_LENGTH 16
-
-/* template for PKCS 5 PBE Parameter. This template has been expanded
- * based upon the additions in PKCS 12. This should eventually be moved
- * if RSA updates PKCS 5.
- */
-const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] =
-{
- { SEC_ASN1_SEQUENCE,
- 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
- { SEC_ASN1_OCTET_STRING,
- offsetof(SEC_PKCS5PBEParameter, salt) },
- { SEC_ASN1_INTEGER,
- offsetof(SEC_PKCS5PBEParameter, iteration) },
- { 0 }
-};
-
-const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] =
-{
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
- { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
- { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
- { 0 }
-};
-
-pbeBitGenParameters pbeHashAlgorithmParams[] = {
- { 0, 0, SEC_OID_UNKNOWN },
- { 128, 512, SEC_OID_MD2 },
- { 128, 512, SEC_OID_MD5 },
- { 160, 512, SEC_OID_SHA1 },
-};
-
-/* generate some random bytes. this is used to generate the
- * salt if it is not specified.
- */
-static SECStatus
-sec_pkcs5_generate_random_bytes(PRArenaPool *poolp,
- SECItem *dest, int len)
-{
- SECStatus rv = SECFailure;
-
- if(dest != NULL)
- {
- void *mark = PORT_ArenaMark(poolp);
- dest->data = (unsigned char *)PORT_ArenaZAlloc(poolp, len);
- if(dest->data != NULL)
- {
- dest->len = len;
- RNG_GenerateGlobalRandomBytes(dest->data, dest->len);
- PORT_ArenaUnmark(poolp, mark);
- rv = SECSuccess;
- } else
- PORT_ArenaRelease(poolp, mark);
- }
-
- return rv;
-}
-
-/* maps hash algorithm from PBE algorithm.
- */
-static SECOidTag
-sec_pkcs5_hash_algorithm(SECOidTag algorithm)
-{
- switch(algorithm)
- {
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- return SEC_OID_SHA1;
- case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
- return SEC_OID_MD5;
- case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
- return SEC_OID_MD2;
- default:
- break;
- }
- return SEC_OID_UNKNOWN;
-}
-
-/* get the iv length needed for the PBE algorithm
- */
-static int
-sec_pkcs5_iv_length(SECOidTag algorithm)
-{
- switch(algorithm)
- {
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
- return DES_IV_LENGTH;
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- return RC2_IV_LENGTH;
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
- return 0;
- default:
- break;
- }
- return -1;
-}
-
-/* get the key length needed for the PBE algorithm
- */
-static int
-sec_pkcs5_key_length(SECOidTag algorithm)
-{
- switch(algorithm)
- {
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
- return 24;
- case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
- return 8;
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- return 5;
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
- return 16;
- default:
- break;
- }
- return -1;
-}
-
-/* the V2 algorithms only encode the salt, there is no iteration
- * count so we need a check for V2 algorithm parameters.
- */
-static PRBool
-sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm)
-{
- switch(algorithm)
- {
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- return PR_TRUE;
- default:
- break;
- }
-
- return PR_FALSE;
-}
-
-/* creates a PBE parameter based on the PBE algorithm. the only required
- * parameters are algorithm and interation. the return is a PBE parameter
- * which conforms to PKCS 5 parameter unless an extended parameter is needed.
- * this is primarily if keyLen and a variable key length algorithm are
- * specified.
- * salt - if null, a salt will be generated from random bytes.
- * iteration - number of iterations to perform hashing.
- * keyLen - only used in variable key length algorithms
- * iv - if null, the IV will be generated based on PKCS 5 when needed.
- * params - optional, currently unsupported additional parameters.
- * once a parameter is allocated, it should be destroyed calling
- * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter.
- */
-static SEC_PKCS5PBEParameter *
-sec_pkcs5_create_pbe_parameter(SECOidTag algorithm,
- SECItem *salt,
- int iteration)
-{
- PRArenaPool *poolp = NULL;
- SEC_PKCS5PBEParameter *pbe_param = NULL;
- SECStatus rv;
- void *dummy = NULL;
-
- if(iteration < 0) {
- return NULL;
- }
-
- poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
- if(poolp == NULL)
- return NULL;
-
- pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp,
- sizeof(SEC_PKCS5PBEParameter));
- if(!pbe_param) {
- PORT_FreeArena(poolp, PR_TRUE);
- return NULL;
- }
-
- pbe_param->poolp = poolp;
- pbe_param->algorithm = algorithm;
-
- /* should we generate the salt? */
- if(!salt || !salt->data) {
- rv = sec_pkcs5_generate_random_bytes(poolp, &pbe_param->salt,
- SALT_LENGTH);
- } else {
- rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt);
- }
-
- if(rv != SECSuccess) {
- PORT_FreeArena(poolp, PR_TRUE);
- return NULL;
- }
-
- /* encode the integer */
- dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration,
- iteration);
- rv = (dummy) ? SECSuccess : SECFailure;
-
- if(rv != SECSuccess) {
- PORT_FreeArena(poolp, PR_FALSE);
- return NULL;
- }
-
- return pbe_param;
-}
-
-/* generate bits for key and iv using MD5 hashing
- */
-static SECItem *
-sec_pkcs5_compute_md5_hash(SECItem *salt, SECItem *pwd, int iter,
- PRBool dummy)
-{
- SECItem *hash = NULL, *pre_hash = NULL;
- SECStatus rv = SECFailure;
-
- if((salt == NULL) || (pwd == NULL) || (iter < 0)) {
- return NULL;
- }
-
- hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if((hash != NULL) && (pre_hash != NULL)) {
- unsigned int i, ph_len;
-
- ph_len = MD5_LENGTH;
- if(ph_len < (salt->len + pwd->len)) {
- ph_len = salt->len + pwd->len;
- }
-
- rv = SECFailure;
- hash->data = (unsigned char *)PORT_ZAlloc(MD5_LENGTH);
- hash->len = MD5_LENGTH;
- pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len);
- pre_hash->len = salt->len + pwd->len;
-
- if((hash->data != NULL) && (pre_hash->data != NULL)) {
- rv = SECSuccess;
- /* handle 0 length password */
- if(pwd->len > 0) {
- PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
- }
- if(salt->len > 0) {
- PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len);
- }
- for(i = 0; ((i < (unsigned int)iter) && (rv == SECSuccess)); i++) {
- rv = MD5_HashBuf(hash->data, pre_hash->data, pre_hash->len);
- if(rv != SECFailure) {
- PORT_Memcpy(pre_hash->data, hash->data, MD5_LENGTH);
- pre_hash->len = MD5_LENGTH;
- }
- }
- }
- }
-
- if(pre_hash != NULL)
- SECITEM_FreeItem(pre_hash, PR_TRUE);
-
- if((rv == SECFailure) && (hash)) {
- SECITEM_FreeItem(hash, PR_TRUE);
- hash = NULL;
- }
-
- return hash;
-}
-
-/* generate bits for key and iv using MD2 hashing
- */
-static SECItem *
-sec_pkcs5_compute_md2_hash(SECItem *salt, SECItem *pwd, int iter,
- PRBool dummy)
-{
- SECItem *hash = NULL, *pre_hash = NULL;
- SECStatus rv = SECFailure;
-
- if((salt == NULL) || (pwd == NULL) || (iter < 0))
- return NULL;
-
- hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if((hash != NULL) && (pre_hash != NULL))
- {
- int i, ph_len;
-
- ph_len = MD2_LENGTH;
- if((salt->len + pwd->len) > MD2_LENGTH)
- ph_len = salt->len+pwd->len;
-
- rv = SECFailure;
- hash->data = (unsigned char *)PORT_ZAlloc(MD2_LENGTH);
- hash->len = MD2_LENGTH;
- pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len);
- pre_hash->len = salt->len + pwd->len;
-
- if((hash->data != NULL) && (pre_hash->data != NULL))
- {
- MD2Context *ctxt;
-
- rv = SECSuccess;
- if(pwd->len > 0) {
- PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
- }
- if(salt->len > 0) {
- PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len);
- }
-
- for(i = 0; ((i < iter) && (rv == SECSuccess)); i++)
- {
- ctxt = MD2_NewContext();
- if(ctxt == NULL)
- rv = SECFailure;
- else
- {
- MD2_Update(ctxt, pre_hash->data, pre_hash->len);
- MD2_End(ctxt, hash->data, &hash->len, hash->len);
- PORT_Memcpy(pre_hash->data, hash->data, MD2_LENGTH);
- pre_hash->len = MD2_LENGTH;
- MD2_DestroyContext(ctxt, PR_TRUE);
- }
- }
- }
- }
-
- if(pre_hash != NULL)
- SECITEM_FreeItem(pre_hash, PR_TRUE);
-
- if(rv != SECSuccess)
- if(hash != NULL)
- {
- SECITEM_FreeItem(hash, PR_TRUE);
- hash = NULL;
- }
-
- return hash;
-}
-
-/* generate bits using SHA1 hash
- */
-static SECItem *
-sec_pkcs5_compute_sha1_hash(SECItem *salt, SECItem *pwd, int iter,
- PRBool faulty3DES)
-{
- SECItem *hash = NULL, *pre_hash = NULL;
- SECStatus rv = SECFailure;
-
- if((salt == NULL) || (pwd == NULL) || (iter < 0)) {
- return NULL;
- }
-
- hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
-
- if((hash != NULL) && (pre_hash != NULL)) {
- int i, ph_len;
-
- ph_len = SHA1_LENGTH;
- if((salt->len + pwd->len) > SHA1_LENGTH) {
- ph_len = salt->len + pwd->len;
- }
-
- rv = SECFailure;
-
- /* allocate buffers */
- hash->data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH);
- hash->len = SHA1_LENGTH;
- pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len);
-
- /* in pbeSHA1TripleDESCBC there was an allocation error that made
- * it into the caller. We do not want to propagate those errors
- * further, so we are doing it correctly, but reading the old method.
- */
- if(faulty3DES) {
- pre_hash->len = ph_len;
- } else {
- pre_hash->len = salt->len + pwd->len;
- }
-
- /* preform hash */
- if((hash->data != NULL) && (pre_hash->data != NULL)) {
- rv = SECSuccess;
- /* check for 0 length password */
- if(pwd->len > 0) {
- PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
- }
- if(salt->len > 0) {
- PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len);
- }
- for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) {
- rv = SHA1_HashBuf(hash->data, pre_hash->data, pre_hash->len);
- if(rv != SECFailure) {
- pre_hash->len = SHA1_LENGTH;
- PORT_Memcpy(pre_hash->data, hash->data, SHA1_LENGTH);
- }
- }
- }
- }
-
- if(pre_hash != NULL) {
- SECITEM_FreeItem(pre_hash, PR_TRUE);
- }
-
- if((rv != SECSuccess) && (hash != NULL)) {
- SECITEM_FreeItem(hash, PR_TRUE);
- hash = NULL;
- }
-
- return hash;
-}
-
-/* bit generation/key and iv generation routines. */
-typedef SECItem *(* sec_pkcs5_hash_func)(SECItem *s, SECItem *p,
- int iter, PRBool faulty3DES);
-
-/* generates bits needed for the key and iv based on PKCS 5,
- * be concatenating the password and salt and using the appropriate
- * hash algorithm. This function serves as a front end to the
- * specific hash functions above. a return of NULL indicates an
- * error.
- */
-static SECItem *
-sec_pkcs5_compute_hash(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem,
- PRBool faulty3DES)
-{
- sec_pkcs5_hash_func hash_func;
- SECOidTag hash_alg;
- SECItem *hash = NULL;
- SECItem *salt = NULL;
-
- hash_alg = sec_pkcs5_hash_algorithm(pbe_param->algorithm);
- salt = &(pbe_param->salt);
- switch(hash_alg)
- {
- case SEC_OID_SHA1:
- hash_func = sec_pkcs5_compute_sha1_hash;
- break;
- case SEC_OID_MD2:
- hash_func = sec_pkcs5_compute_md2_hash;
- break;
- case SEC_OID_MD5:
- hash_func = sec_pkcs5_compute_md5_hash;
- break;
- default:
- hash_func = NULL;
- }
-
- if(hash_func) {
- hash = (* hash_func)(salt, pwitem, pbe_param->iter, faulty3DES);
- }
-
- return hash;
-}
-
-/* determines the number of bits needed for key and iv generation
- * based upon the algorithm identifier. if a number of
- * bits greater than the hash algorithm can produce are needed,
- * the bits will be generated based upon the extended PKCS 5
- * described in PKCS 12.
- *
- * a return of -1 indicates an error.
- */
-static int
-sec_pkcs5_bits_needed(SEC_PKCS5PBEParameter *pbe_param)
-{
- int iv_bits;
- int key_bits;
-
- if(pbe_param == NULL) {
- return -1;
- }
-
- iv_bits = sec_pkcs5_iv_length(pbe_param->algorithm) * 8;
- key_bits = sec_pkcs5_key_length(pbe_param->algorithm) * 8;
-
- if(key_bits != 0) {
- return iv_bits + key_bits;
- }
-
- return -1;
-}
-
-/* determines the number of bits generated by each hash algorithm.
- * in case of an error, -1 is returned.
- */
-static int
-sec_pkcs5_hash_bits_generated(SEC_PKCS5PBEParameter *pbe_param)
-{
- if(pbe_param == NULL) {
- return -1;
- }
-
- switch(sec_pkcs5_hash_algorithm(pbe_param->algorithm)) {
- case SEC_OID_SHA1:
- return SHA1_LENGTH * 8;
- case SEC_OID_MD2:
- return MD2_LENGTH * 8;
- case SEC_OID_MD5:
- return MD5_LENGTH * 8;
- default:
- break;
- }
-
- return -1;
-}
-
-/* this bit generation routine is described in PKCS 12 and the proposed
- * extensions to PKCS 5. an initial hash is generated following the
- * instructions laid out in PKCS 5. If the number of bits generated is
- * insufficient, then the method discussed in the proposed extensions to
- * PKCS 5 in PKCS 12 are used. This extension makes use of the HMAC
- * function. And the P_Hash function from the TLS standard.
- */
-static SECItem *
-sec_pkcs5_bit_generator(SEC_PKCS5PBEParameter *pbe_param,
- SECItem *init_hash,
- unsigned int bits_needed)
-{
- SECItem *ret_bits = NULL;
- int hash_size = 0;
- unsigned int i;
- unsigned int hash_iter;
- unsigned int dig_len;
- SECStatus rv = SECFailure;
- unsigned char *state = NULL;
- unsigned int state_len;
- HMACContext *cx = NULL;
-
- hash_size = sec_pkcs5_hash_bits_generated(pbe_param);
- if(hash_size == -1)
- return NULL;
-
- hash_iter = (bits_needed + (unsigned int)hash_size - 1) / hash_size;
- hash_size /= 8;
-
- /* allocate return buffer */
- ret_bits = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if(ret_bits == NULL)
- return NULL;
- ret_bits->data = (unsigned char *)PORT_ZAlloc((hash_iter * hash_size) + 1);
- ret_bits->len = (hash_iter * hash_size);
- if(ret_bits->data == NULL) {
- PORT_Free(ret_bits);
- return NULL;
- }
-
- /* allocate intermediate hash buffer. 8 is for the 8 bytes of
- * data which are added based on iteration number
- */
-
- if ((unsigned int)hash_size > pbe_param->salt.len) {
- state_len = hash_size;
- } else {
- state_len = pbe_param->salt.len;
- }
- state = (unsigned char *)PORT_ZAlloc(state_len);
- if(state == NULL) {
- rv = SECFailure;
- goto loser;
- }
- if(pbe_param->salt.len > 0) {
- PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len);
- }
-
- cx = HMAC_Create(sec_pkcs5_hash_algorithm(pbe_param->algorithm),
- init_hash->data, init_hash->len);
- if (cx == NULL) {
- rv = SECFailure;
- goto loser;
- }
-
- for(i = 0; i < hash_iter; i++) {
-
- /* generate output bits */
- HMAC_Begin(cx);
- HMAC_Update(cx, state, state_len);
- HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len);
- rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size),
- &dig_len, hash_size);
- if (rv != SECSuccess)
- goto loser;
- PORT_Assert((unsigned int)hash_size == dig_len);
-
- /* generate new state */
- HMAC_Begin(cx);
- HMAC_Update(cx, state, state_len);
- rv = HMAC_Finish(cx, state, &state_len, state_len);
- if (rv != SECSuccess)
- goto loser;
- PORT_Assert(state_len == dig_len);
- }
-
-loser:
- if (state != NULL)
- PORT_ZFree(state, state_len);
- HMAC_Destroy(cx);
-
- if(rv != SECSuccess) {
- SECITEM_ZfreeItem(ret_bits, PR_TRUE);
- ret_bits = NULL;
- }
-
- return ret_bits;
-}
-
-/* generate bits for the key and iv determination. if enough bits
- * are not generated using PKCS 5, then we need to generate more bits
- * based on the extension proposed in PKCS 12
- */
-static SECItem *
-sec_pkcs5_generate_bits(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem,
- PRBool faulty3DES)
-{
- SECItem * hash = NULL;
- SECItem * newHash = NULL;
- int bits_needed;
- int bits_available;
-
- bits_needed = sec_pkcs5_bits_needed(pbe_param);
- bits_available = sec_pkcs5_hash_bits_generated(pbe_param);
-
- if((bits_needed == -1) || (bits_available == -1)) {
- return NULL;
- }
-
- hash = sec_pkcs5_compute_hash(pbe_param, pwitem, faulty3DES);
- if(hash == NULL) {
- return NULL;
- }
-
- if(bits_needed <= bits_available) {
- return hash;
- }
-
- newHash = sec_pkcs5_bit_generator(pbe_param, hash, bits_needed);
- if (hash != newHash)
- SECITEM_FreeItem(hash, PR_TRUE);
- return newHash;
-}
-
-/* compute the IV as per PKCS 5
- */
-static SECItem *
-sec_pkcs5_compute_iv(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem,
- PRBool faulty3DES)
-{
- SECItem *hash = NULL, *iv = NULL;
-
- if((pbe_param == NULL) || (pwitem == NULL)) {
- return NULL;
- }
-
- /* generate iv */
- iv = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if(!iv) {
- return NULL;
- }
-
- iv->len = sec_pkcs5_iv_length(pbe_param->algorithm);
- if(iv->len == -1) {
- PORT_Free(iv);
- return NULL;
- }
-
- iv->data = (unsigned char *)PORT_ZAlloc(iv->len);
- if(iv->data == NULL) {
- PORT_Free(iv);
- return NULL;
- }
-
- if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(pbe_param->algorithm)) {
- SECOidTag hashAlg;
- PBEBitGenContext *ctxt;
- hashAlg = sec_pkcs5_hash_algorithm(pbe_param->algorithm);
- ctxt = PBE_CreateContext(hashAlg, pbeBitGenCipherIV,
- pwitem, &pbe_param->salt,
- iv->len * 8, pbe_param->iter);
- if(!ctxt) {
- SECITEM_FreeItem(iv, PR_TRUE);
- return NULL;
- }
-
- hash = PBE_GenerateBits(ctxt);
- PBE_DestroyContext(ctxt);
- } else {
- hash = sec_pkcs5_generate_bits(pbe_param, pwitem, faulty3DES);
- }
-
- if(!hash) {
- SECITEM_FreeItem(iv, PR_TRUE);
- return NULL;
- }
-
- PORT_Memcpy(iv->data, (hash->data+(hash->len - iv->len)), iv->len);
- SECITEM_FreeItem(hash, PR_TRUE);
-
- return iv;
-}
-
-/* generate key as per PKCS 5
- */
-static SECItem *
-sec_pkcs5_compute_key(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem,
- PRBool faulty3DES)
-{
- SECItem *hash = NULL, *key = NULL;
-
- if((pbe_param == NULL) || (pwitem == NULL)) {
- return NULL;
- }
-
- key = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if(!key) {
- return NULL;
- }
-
- key->len = sec_pkcs5_key_length(pbe_param->algorithm);
- if(key->len == -1) {
- PORT_Free(key);
- return NULL;
- }
-
- key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
- key->len);
- if(!key->data) {
- PORT_Free(key);
- return NULL;
- }
-
-
- if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(pbe_param->algorithm)) {
- SECOidTag hashAlg;
- PBEBitGenContext *ctxt;
- hashAlg = sec_pkcs5_hash_algorithm(pbe_param->algorithm);
- ctxt = PBE_CreateContext(hashAlg, pbeBitGenCipherKey,
- pwitem, &pbe_param->salt,
- key->len * 8, pbe_param->iter);
- if(!ctxt) {
- SECITEM_FreeItem(key, PR_TRUE);
- return NULL;
- }
-
- hash = PBE_GenerateBits(ctxt);
- PBE_DestroyContext(ctxt);
- } else {
- hash = sec_pkcs5_generate_bits(pbe_param, pwitem, faulty3DES);
- }
-
- if(!hash) {
- SECITEM_FreeItem(key, PR_TRUE);
- return NULL;
- }
-
- if(pbe_param->algorithm ==
- SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC) {
- PORT_Memcpy(key->data, hash->data, (key->len * 2) / 3);
- PORT_Memcpy(&(key->data[(key->len * 2) / 3]), key->data,
- key->len / 3);
- } else {
- PORT_Memcpy(key->data, hash->data, key->len);
- }
-
- SECITEM_FreeItem(hash, PR_TRUE);
- return key;
-}
-
-/* decode the algid and generate a PKCS 5 parameter from it
- */
-static SEC_PKCS5PBEParameter *
-sec_pkcs5_convert_algid(SECAlgorithmID *algid)
-{
- PRArenaPool *poolp;
- SEC_PKCS5PBEParameter *pbe_param = NULL;
- SECOidTag algorithm;
- SECStatus rv = SECFailure;
-
- if(algid == NULL)
- return NULL;
-
- algorithm = SECOID_GetAlgorithmTag(algid);
-
- if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN)
- return NULL;
-
- poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
- if(poolp == NULL)
- return NULL;
-
- /* allocate memory for the parameter */
- pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp,
- sizeof(SEC_PKCS5PBEParameter));
-
- /* decode parameter */
- if(pbe_param && !sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
- pbe_param->poolp = poolp;
- rv = SEC_ASN1DecodeItem(poolp, pbe_param,
- SEC_PKCS5PBEParameterTemplate, &algid->parameters);
- if(rv != SECSuccess) {
- goto loser;
- }
- pbe_param->algorithm = algorithm;
- pbe_param->iter = DER_GetInteger(&pbe_param->iteration);
- } else if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
- pbe_param->algorithm = algorithm;
- pbe_param->poolp = poolp;
- rv = SEC_ASN1DecodeItem(poolp, pbe_param, SEC_V2PKCS12PBEParameterTemplate,
- &algid->parameters);
- if(rv != SECSuccess) {
- goto loser;
- }
- pbe_param->iter = DER_GetInteger(&pbe_param->iteration);
- }
-
-loser:
- if((pbe_param == NULL) || (rv != SECSuccess)) {
- PORT_FreeArena(poolp, PR_TRUE);
- pbe_param = NULL;
- }
-
- return pbe_param;
-}
-
-/* destroy a pbe parameter. it assumes that the parameter was
- * generated using the appropriate create function and therefor
- * contains an arena pool.
- */
-static void
-sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param)
-{
- if(pbe_param != NULL)
- PORT_FreeArena(pbe_param->poolp, PR_TRUE);
-}
-
-
-/* crypto routines */
-
-/* function pointer template for crypto functions */
-typedef SECItem *(* pkcs5_crypto_func)(SECItem *key, SECItem *iv,
- SECItem *src, PRBool op1, PRBool op2);
-
-/* map PBE algorithm to crypto algorithm */
-static SECOidTag
-sec_pkcs5_encryption_algorithm(SECOidTag algorithm)
-{
- switch(algorithm)
- {
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
- return SEC_OID_DES_EDE3_CBC;
- case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
- return SEC_OID_DES_CBC;
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- return SEC_OID_RC2_CBC;
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
- return SEC_OID_RC4;
- default:
- break;
- }
- return SEC_OID_UNKNOWN;
-}
-
-/* perform DES encryption and decryption. these routines are called
- * by SEC_PKCS5CipherData. In the case of an error, NULL is returned.
- */
-static SECItem *
-sec_pkcs5_des(SECItem *key,
- SECItem *iv,
- SECItem *src,
- PRBool triple_des,
- PRBool encrypt)
-{
- SECItem *dest;
- SECItem *dup_src;
- SECStatus rv = SECFailure;
- int pad;
-
- if((src == NULL) || (key == NULL) || (iv == NULL))
- return NULL;
-
- dup_src = SECITEM_DupItem(src);
- if(dup_src == NULL) {
- return NULL;
- }
-
- if(encrypt != PR_FALSE) {
- void *dummy;
-
- dummy = DES_PadBuffer(NULL, dup_src->data,
- dup_src->len, &dup_src->len);
- if(dummy == NULL) {
- SECITEM_FreeItem(dup_src, PR_TRUE);
- return NULL;
- }
- dup_src->data = (unsigned char*)dummy;
- }
-
- dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if(dest != NULL) {
- /* allocate with over flow */
- dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
- if(dest->data != NULL) {
- DESContext *ctxt;
- ctxt = DES_CreateContext(key->data, iv->data,
- (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC),
- encrypt);
-
- if(ctxt != NULL) {
- rv = ((encrypt != PR_TRUE) ? DES_Decrypt : DES_Encrypt)(
- ctxt, dest->data, &dest->len,
- dup_src->len + 64, dup_src->data, dup_src->len);
-
- /* remove padding -- assumes 64 bit blocks */
- if((encrypt == PR_FALSE) && (rv == SECSuccess)) {
- pad = dest->data[dest->len-1];
- if((pad > 0) && (pad <= 8)) {
- if(dest->data[dest->len-pad] != pad) {
- rv = SECFailure;
- PORT_SetError(SEC_ERROR_BAD_PASSWORD);
- } else {
- dest->len -= pad;
- }
- } else {
- rv = SECFailure;
- PORT_SetError(SEC_ERROR_BAD_PASSWORD);
- }
- }
- DES_DestroyContext(ctxt, PR_TRUE);
- }
- }
- }
-
- if(rv == SECFailure) {
- if(dest != NULL) {
- SECITEM_FreeItem(dest, PR_TRUE);
- }
- dest = NULL;
- }
-
- if(dup_src != NULL) {
- SECITEM_FreeItem(dup_src, PR_TRUE);
- }
-
- return dest;
-}
-
-/* perform rc2 encryption/decryption if an error occurs, NULL is returned
- */
-static SECItem *
-sec_pkcs5_rc2(SECItem *key,
- SECItem *iv,
- SECItem *src,
- PRBool cbc_mode,
- PRBool encrypt)
-{
- SECItem *dest;
- SECItem *dup_src;
- SECStatus rv = SECFailure;
- int pad;
-
- if((src == NULL) || (key == NULL) || (iv == NULL)) {
- return NULL;
- }
-
- dup_src = SECITEM_DupItem(src);
- if(dup_src == NULL) {
- return NULL;
- }
-
- if(encrypt != PR_FALSE) {
- void *dummy;
-
- dummy = DES_PadBuffer(NULL, dup_src->data,
- dup_src->len, &dup_src->len);
- if(dummy == NULL) {
- SECITEM_FreeItem(dup_src, PR_TRUE);
- return NULL;
- }
- dup_src->data = (unsigned char*)dummy;
- }
-
- dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if(dest != NULL) {
- dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
- if(dest->data != NULL) {
- RC2Context *ctxt;
-
- ctxt = RC2_CreateContext(key->data, key->len, iv->data,
- ((cbc_mode != PR_TRUE) ? NSS_RC2 : NSS_RC2_CBC),
- key->len);
-
- if(ctxt != NULL) {
- rv = ((encrypt != PR_TRUE) ? RC2_Decrypt : RC2_Encrypt)(
- ctxt, dest->data, &dest->len,
- dup_src->len + 64, dup_src->data, dup_src->len);
-
- /* assumes 8 byte blocks -- remove padding */
- if((rv == SECSuccess) && (encrypt != PR_TRUE) &&
- (cbc_mode == PR_TRUE)) {
- pad = dest->data[dest->len-1];
- if((pad > 0) && (pad <= 8)) {
- if(dest->data[dest->len-pad] != pad) {
- PORT_SetError(SEC_ERROR_BAD_PASSWORD);
- rv = SECFailure;
- } else {
- dest->len -= pad;
- }
- } else {
- PORT_SetError(SEC_ERROR_BAD_PASSWORD);
- rv = SECFailure;
- }
- }
-
- }
- }
- }
-
- if((rv != SECSuccess) && (dest != NULL)) {
- SECITEM_FreeItem(dest, PR_TRUE);
- dest = NULL;
- }
-
- if(dup_src != NULL) {
- SECITEM_FreeItem(dup_src, PR_TRUE);
- }
-
- return dest;
-}
-
-/* perform rc4 encryption and decryption */
-static SECItem *
-sec_pkcs5_rc4(SECItem *key,
- SECItem *iv,
- SECItem *src,
- PRBool dummy_op,
- PRBool encrypt)
-{
- SECItem *dest;
- SECStatus rv = SECFailure;
-
- if((src == NULL) || (key == NULL) || (iv == NULL)) {
- return NULL;
- }
-
- dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if(dest != NULL) {
- dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
- (src->len + 64));
- if(dest->data != NULL) {
- RC4Context *ctxt;
-
- ctxt = RC4_CreateContext(key->data, key->len);
- if(ctxt) {
- rv = ((encrypt != PR_FALSE) ? RC4_Decrypt : RC4_Encrypt)(
- ctxt, dest->data, &dest->len,
- src->len + 64, src->data, src->len);
- RC4_DestroyContext(ctxt, PR_TRUE);
- }
- }
- }
-
- if((rv != SECSuccess) && (dest)) {
- SECITEM_FreeItem(dest, PR_TRUE);
- dest = NULL;
- }
-
- return dest;
-}
-
-/* performs the cipher operation on the src and returns the result.
- * if an error occurs, NULL is returned.
- *
- * a null length password is allowed. this corresponds to encrypting
- * the data with ust the salt.
- */
-/* change this to use PKCS 11? */
-SECItem *
-SEC_PKCS5CipherData(SECAlgorithmID *algid,
- SECItem *pwitem,
- SECItem *src,
- PRBool encrypt, PRBool *update)
-{
- SEC_PKCS5PBEParameter *pbe_param;
- SECOidTag enc_alg;
- SECItem *key = NULL, *iv = NULL;
- SECItem *dest = NULL;
- int iv_len;
-
- if (update) {
- *update = PR_FALSE;
- }
-
- if((algid == NULL) || (pwitem == NULL) || (src == NULL)) {
- return NULL;
- }
-
- /* convert algid to pbe parameter */
- pbe_param = sec_pkcs5_convert_algid(algid);
- if(pbe_param == NULL) {
- return NULL;
- }
-
- /* get algorithm, key, and iv */
- enc_alg = sec_pkcs5_encryption_algorithm(pbe_param->algorithm);
- key = sec_pkcs5_compute_key(pbe_param, pwitem, PR_FALSE);
- if(key != NULL) {
- iv_len = sec_pkcs5_iv_length(pbe_param->algorithm);
- iv = sec_pkcs5_compute_iv(pbe_param, pwitem, PR_FALSE);
-
- if((iv != NULL) || (iv_len == 0)) {
- /*perform encryption / decryption */
- PRBool op1 = PR_TRUE;
- pkcs5_crypto_func cryptof;
-
- switch(enc_alg) {
- case SEC_OID_DES_EDE3_CBC:
- cryptof = sec_pkcs5_des;
- break;
- case SEC_OID_DES_CBC:
- cryptof = sec_pkcs5_des;
- op1 = PR_FALSE;
- break;
- case SEC_OID_RC2_CBC:
- cryptof = sec_pkcs5_rc2;
- break;
- case SEC_OID_RC4:
- cryptof = sec_pkcs5_rc4;
- break;
- default:
- cryptof = NULL;
- break;
- }
-
- if(cryptof) {
- dest = (*cryptof)(key, iv, src, op1, encrypt);
- /*
- * it's possible for some keys and keydb's to claim to
- * be triple des when they're really des. In this case
- * we simply try des. If des works we set the update flag
- * so the key db knows it needs to update all it's entries.
- * The case can only happen on decrypted of a
- * SEC_OID_DES_EDE3_CBD.
- */
- if ((dest == NULL) && (encrypt == PR_FALSE) &&
- (enc_alg == SEC_OID_DES_EDE3_CBC)) {
- dest = (*cryptof)(key, iv, src, PR_FALSE, encrypt);
- if (update && (dest != NULL)) *update = PR_TRUE;
- }
- }
- }
- }
-
- sec_pkcs5_destroy_pbe_param(pbe_param);
-
- if(key != NULL) {
- SECITEM_ZfreeItem(key, PR_TRUE);
- }
- if(iv != NULL) {
- SECITEM_ZfreeItem(iv, PR_TRUE);
- }
-
- return dest;
-}
-
-/* creates a algorithm ID containing the PBE algorithm and appropriate
- * parameters. the required parameter is the algorithm. if salt is
- * not specified, it is generated randomly. if IV is specified, it overrides
- * the PKCS 5 generation of the IV.
- *
- * the returned SECAlgorithmID should be destroyed using
- * SECOID_DestroyAlgorithmID
- */
-SECAlgorithmID *
-SEC_PKCS5CreateAlgorithmID(SECOidTag algorithm,
- SECItem *salt,
- int iteration)
-{
- PRArenaPool *poolp = NULL;
- SECAlgorithmID *algid, *ret_algid;
- SECItem der_param;
- SECStatus rv = SECFailure;
- SEC_PKCS5PBEParameter *pbe_param;
-
- if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN)
- return NULL;
-
- if(iteration <= 0) {
- return NULL;
- }
-
- der_param.data = NULL;
- der_param.len = 0;
-
- /* generate the parameter */
- pbe_param = sec_pkcs5_create_pbe_parameter(algorithm, salt, iteration);
- if(!pbe_param) {
- return NULL;
- }
-
- poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
- if(!poolp) {
- sec_pkcs5_destroy_pbe_param(pbe_param);
- return NULL;
- }
-
- /* generate the algorithm id */
- algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
- if(algid != NULL) {
- void *dummy;
- if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
- dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
- SEC_PKCS5PBEParameterTemplate);
- } else {
- dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
- SEC_V2PKCS12PBEParameterTemplate);
- }
-
- if(dummy) {
- rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param);
- }
- }
-
- ret_algid = NULL;
- if(algid != NULL) {
- ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
- if(ret_algid != NULL) {
- rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
- if(rv != SECSuccess) {
- SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
- ret_algid = NULL;
- }
- }
- }
-
- if(poolp != NULL) {
- PORT_FreeArena(poolp, PR_TRUE);
- algid = NULL;
- }
-
- sec_pkcs5_destroy_pbe_param(pbe_param);
-
- return ret_algid;
-}
-
-/* wrapper for converting the algid to a pbe parameter.
- */
-SEC_PKCS5PBEParameter *
-SEC_PKCS5GetPBEParameter(SECAlgorithmID *algid)
-{
- if(algid) {
- return sec_pkcs5_convert_algid(algid);
- }
-
- return NULL;
-}
-
-/* destroy a pbe parameter */
-void
-SEC_PKCS5DestroyPBEParameter(SEC_PKCS5PBEParameter *pbe_param)
-{
- sec_pkcs5_destroy_pbe_param(pbe_param);
-}
-
-/* return the initialization vector either the preset one if it
- * exists or generated based on pkcs 5.
- *
- * a null length password is allowed...but not a null password
- * secitem.
- */
-SECItem *
-SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
-{
- SECItem *iv;
- SEC_PKCS5PBEParameter *pbe_param;
-
- if((algid == NULL) || (pwitem == NULL)) {
- return NULL;
- }
-
- pbe_param = sec_pkcs5_convert_algid(algid);
- if(!pbe_param) {
- return NULL;
- }
-
- iv = sec_pkcs5_compute_iv(pbe_param, pwitem, faulty3DES);
-
- sec_pkcs5_destroy_pbe_param(pbe_param);
-
- return iv;
-}
-
-/* generate the key
- * a 0 length password is allowed. corresponds to a key generated
- * from just the salt.
- */
-SECItem *
-SEC_PKCS5GetKey(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
-{
- SECItem *key;
- SEC_PKCS5PBEParameter *pbe_param;
-
- if((algid == NULL) || (pwitem == NULL)) {
- return NULL;
- }
-
- pbe_param = sec_pkcs5_convert_algid(algid);
- if(pbe_param == NULL) {
- return NULL;
- }
-
- key = sec_pkcs5_compute_key(pbe_param, pwitem, faulty3DES);
-
- sec_pkcs5_destroy_pbe_param(pbe_param);
-
- return key;
-}
-
-/* retrieve the salt */
-SECItem *
-SEC_PKCS5GetSalt(SECAlgorithmID *algid)
-{
- SECItem *salt;
- SEC_PKCS5PBEParameter *pbe_param;
-
- if(algid == NULL)
- return NULL;
-
- pbe_param = sec_pkcs5_convert_algid(algid);
- if(pbe_param == NULL)
- return NULL;
-
- if(pbe_param->salt.data) {
- salt = SECITEM_DupItem(&pbe_param->salt);
- } else {
- salt = NULL;
- }
-
- sec_pkcs5_destroy_pbe_param(pbe_param);
-
- return salt;
-}
-
-/* check to see if an oid is a pbe algorithm
- */
-PRBool
-SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid)
-{
- SECOidTag algorithm;
-
- algorithm = SECOID_GetAlgorithmTag(algid);
- if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN) {
- return PR_FALSE;
- }
-
- return PR_TRUE;
-}
-
-int
-SEC_PKCS5GetKeyLength(SECAlgorithmID *algid)
-{
- SEC_PKCS5PBEParameter *pbe_param;
- int keyLen = -1;
-
- if(algid == NULL)
- return -1;
-
- pbe_param = sec_pkcs5_convert_algid(algid);
- if(pbe_param == NULL)
- return -1;
-
- keyLen = sec_pkcs5_key_length(pbe_param->algorithm);
-
- sec_pkcs5_destroy_pbe_param(pbe_param);
-
- return keyLen;
-}
-
-/* maps crypto algorithm from PBE algorithm.
- */
-SECOidTag
-SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid)
-{
- SEC_PKCS5PBEParameter *pbe_param;
-
- if(algid == NULL)
- return SEC_OID_UNKNOWN;
-
- pbe_param = sec_pkcs5_convert_algid(algid);
- if(pbe_param == NULL)
- return SEC_OID_UNKNOWN;
-
- switch(pbe_param->algorithm)
- {
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
- return SEC_OID_DES_EDE3_CBC;
- case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
- case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
- return SEC_OID_DES_CBC;
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
- return SEC_OID_RC2_CBC;
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
- case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
- case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
- return SEC_OID_RC4;
- default:
- break;
- }
-
- sec_pkcs5_destroy_pbe_param(pbe_param);
-
- return SEC_OID_UNKNOWN;
-}
-
-/* maps PBE algorithm from crypto algorithm, assumes SHA1 hashing.
- */
-SECOidTag
-SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen)
-{
- switch(algTag)
- {
- case SEC_OID_DES_EDE3_CBC:
- switch(keyLen) {
- case 168:
- case 192:
- return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
- case 128:
- case 92:
- return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
- default:
- break;
- }
- break;
- case SEC_OID_DES_CBC:
- return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
- case SEC_OID_RC2_CBC:
- switch(keyLen) {
- case 40:
- return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
- case 128:
- return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
- default:
- break;
- }
- break;
- case SEC_OID_RC4:
- switch(keyLen) {
- case 40:
- return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
- case 128:
- return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- return SEC_OID_UNKNOWN;
-}
-
-/* zero length password and salts are allowed. however, the items
- * containing the salt and password must be non-null.
- */
-PBEBitGenContext *
-__PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
- SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
- unsigned int iterations)
-{
- PRArenaPool *arena = NULL;
- PBEBitGenContext *pbeCtxt = NULL;
- HASH_HashType pbeHash;
- int vbytes, ubytes;
-
- unsigned int c;
-
- if(!pwitem || !salt) {
- return NULL;
- }
-
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if(!arena) {
- return NULL;
- }
-
- pbeCtxt = (PBEBitGenContext*)PORT_ArenaZAlloc(arena, sizeof(PBEBitGenContext));
- if(!pbeCtxt) {
- goto loser;
- }
-
- switch(hashAlgorithm) {
- case SEC_OID_MD2:
- pbeHash = HASH_AlgMD2;
- break;
- case SEC_OID_MD5:
- pbeHash = HASH_AlgMD5;
- break;
- case SEC_OID_SHA1:
- pbeHash = HASH_AlgSHA1;
- break;
- default:
- goto loser;
- }
-
- pbeCtxt->hashObject = &SECRawHashObjects[pbeHash];
- PORT_Memcpy(&pbeCtxt->pbeParams, &pbeHashAlgorithmParams[pbeHash],
- sizeof(pbeBitGenParameters));
- PORT_Assert(pbeCtxt->pbeParams.hashAlgorithm == hashAlgorithm);
-
- vbytes = pbeCtxt->pbeParams.v / 8;
- ubytes = pbeCtxt->pbeParams.u / 8;
-
- c = (bitsNeeded / pbeCtxt->pbeParams.u);
- c += ((bitsNeeded - (pbeCtxt->pbeParams.u * c)) > 0) ? 1 : 0;
- pbeCtxt->c = c;
- pbeCtxt->n = bitsNeeded;
- pbeCtxt->iterations = iterations;
-
- /* allocate buffers */
- pbeCtxt->D.len = vbytes;
- pbeCtxt->S.len = (((salt->len * 8) / pbeCtxt->pbeParams.v) +
- ((((salt->len * 8) % pbeCtxt->pbeParams.v) > 0) ? 1 : 0)) *
- vbytes;
- pbeCtxt->P.len = (((pwitem->len * 8) / pbeCtxt->pbeParams.v) +
- ((((pwitem->len * 8) % pbeCtxt->pbeParams.v) > 0) ? 1 : 0)) *
- vbytes;
- pbeCtxt->I.len = pbeCtxt->S.len + pbeCtxt->P.len;
- pbeCtxt->A.len = c * ubytes;
- pbeCtxt->B.len = pbeCtxt->D.len;
-
- pbeCtxt->D.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->D.len);
- if(pbeCtxt->S.len) {
- pbeCtxt->S.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->S.len);
- }
- if(pbeCtxt->P.len) {
- pbeCtxt->P.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->P.len);
- }
- if(pbeCtxt->I.len) {
- pbeCtxt->I.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->I.len);
- }
- pbeCtxt->A.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->A.len);
- pbeCtxt->B.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->B.len);
-
- if(!pbeCtxt->D.data || !pbeCtxt->A.data || !pbeCtxt->B.data ||
- (!pbeCtxt->S.data && pbeCtxt->S.len) ||
- (!pbeCtxt->P.data && pbeCtxt->P.len) ||
- (!pbeCtxt->I.data && pbeCtxt->I.len)) {
- goto loser;
- }
-
- PORT_Memset(pbeCtxt->D.data, (char)bitGenPurpose, pbeCtxt->D.len);
- if(pbeCtxt->P.len) {
- unsigned int z = 0;
- while(z < pbeCtxt->P.len) {
- PORT_Memcpy(&(pbeCtxt->P.data[z]), pwitem->data,
- ((z + pwitem->len > pbeCtxt->P.len) ? (pbeCtxt->P.len - z) :
- (pwitem->len)));
- z += pwitem->len;
- }
- }
- if(pbeCtxt->S.len) {
- unsigned int z = 0;
- while(z < pbeCtxt->S.len) {
- PORT_Memcpy(&(pbeCtxt->S.data[z]), salt->data,
- ((z + salt->len > pbeCtxt->S.len) ? (pbeCtxt->S.len - z) :
- (salt->len)));
- z += salt->len;
- }
- }
- if(pbeCtxt->I.len) {
- if(pbeCtxt->S.len) {
- PORT_Memcpy(pbeCtxt->I.data, pbeCtxt->S.data, pbeCtxt->S.len);
- }
- if(pbeCtxt->P.len) {
- PORT_Memcpy(&(pbeCtxt->I.data[pbeCtxt->S.len]), pbeCtxt->P.data,
- pbeCtxt->P.len);
- }
- }
-
- pbeCtxt->arena = arena;
-
- return pbeCtxt;
-
-loser:
- if(arena) {
- PORT_FreeArena(arena, PR_TRUE);
- }
-
- return NULL;
-}
-
-PBEBitGenContext *
-PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
- SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
- unsigned int iterations)
-{
- return __PBE_CreateContext(hashAlgorithm, bitGenPurpose, pwitem,
- salt, bitsNeeded, iterations);
-}
-
-SECItem *
-__PBE_GenerateBits(PBEBitGenContext *pbeCtxt)
-{
- unsigned int i;
- SECItem *A, *D, *I, *B, *S, *P;
- unsigned int u, v, c, z, hashLen, n, iter;
- unsigned int vbyte, ubyte;
- unsigned char *iterBuf;
- void *hash = NULL;
-
- if(!pbeCtxt) {
- return NULL;
- }
-
- A = &pbeCtxt->A;
- B = &pbeCtxt->B;
- I = &pbeCtxt->I;
- D = &pbeCtxt->D;
- S = &pbeCtxt->S;
- P = &pbeCtxt->P;
- u = pbeCtxt->pbeParams.u;
- v = pbeCtxt->pbeParams.v;
- vbyte = v / 8;
- ubyte = u / 8;
- c = pbeCtxt->c;
- n = pbeCtxt->n;
- z = 0;
-
- iterBuf = (unsigned char*)PORT_Alloc(ubyte);
- if(!iterBuf) {
- goto loser;
- }
-
- for(i = 1; i <= c; i++) {
- unsigned int Bidx;
- unsigned int k, j;
-
-
- for(iter = 1; iter <= pbeCtxt->iterations; iter++) {
- hash = pbeCtxt->hashObject->create();
- if(!hash) {
- goto loser;
- }
-
- pbeCtxt->hashObject->begin(hash);
-
- if(iter == 1) {
- pbeCtxt->hashObject->update(hash, D->data, D->len);
- pbeCtxt->hashObject->update(hash, I->data, I->len);
- } else {
- pbeCtxt->hashObject->update(hash, iterBuf, hashLen);
- }
-
- pbeCtxt->hashObject->end(hash, iterBuf, &hashLen, (ubyte));
- pbeCtxt->hashObject->destroy(hash, PR_TRUE);
- if(hashLen != (ubyte)) {
- goto loser;
- }
- }
-
- PORT_Memcpy(&(A->data[z]), iterBuf, (ubyte));
-
- Bidx = 0;
- while(Bidx < B->len) {
- PORT_Memcpy(&(B->data[Bidx]), &(A->data[z]),
- (((Bidx + (ubyte)) > B->len) ? (B->len - Bidx) :
- (ubyte)));
- Bidx += (ubyte);
- }
-
- k = (S->len / (vbyte)) + (P->len / (vbyte));
- for(j = 0; j < k; j++) {
- unsigned int byteIdx = (vbyte);
- unsigned int q, carryBit = 0;
-
- while(byteIdx > 0) {
- q = (unsigned int)I->data[(j * (vbyte)) + byteIdx - 1];
- q += (unsigned int)B->data[byteIdx - 1];
- q += carryBit;
- if(byteIdx == (vbyte)) {
- q += 1;
- }
-
- carryBit = ((q > 255) ? 1 : 0);
-
- I->data[(j * (vbyte)) + byteIdx - 1] = (unsigned char)(q & 255);
-
- byteIdx--;
- }
- }
-
- z += (ubyte);
- }
-
- A->len = (n / 8);
-
- return SECITEM_DupItem(A);
-
-loser:
- return NULL;
-}
-
-SECItem *
-PBE_GenerateBits(PBEBitGenContext *pbeCtxt)
-{
- return __PBE_GenerateBits(pbeCtxt);
-}
-
-void
-__PBE_DestroyContext(PBEBitGenContext *pbeCtxt)
-{
- if(pbeCtxt) {
- PORT_FreeArena(pbeCtxt->arena, PR_TRUE);
- }
-}
-
-void
-PBE_DestroyContext(PBEBitGenContext *pbeCtxt)
-{
- __PBE_DestroyContext(pbeCtxt);
-}
-
-SECStatus
-PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PRArenaPool *arena,
- SECAlgorithmID *algId)
-{
- CK_PBE_PARAMS *pbe_param;
- SECItem pbeSalt;
- SECAlgorithmID *pbeAlgID = NULL;
- SECStatus rv;
-
- if(!param || !algId) {
- return SECFailure;
- }
-
- pbe_param = (CK_PBE_PARAMS *)param->data;
- pbeSalt.data = (unsigned char *)pbe_param->pSalt;
- pbeSalt.len = pbe_param->ulSaltLen;
- pbeAlgID = SEC_PKCS5CreateAlgorithmID(algTag, &pbeSalt,
- (int)pbe_param->ulIteration);
- if(!pbeAlgID) {
- return SECFailure;
- }
-
- rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID);
- SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE);
- return rv;
-}
diff --git a/security/nss/lib/softoken/secpkcs5.h b/security/nss/lib/softoken/secpkcs5.h
deleted file mode 100644
index d538450dd..000000000
--- a/security/nss/lib/softoken/secpkcs5.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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 Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
-
-#ifndef _SECPKCS5_H_
-#define _SECPKCS5_H_
-
-#include "plarena.h"
-#include "secitem.h"
-#include "seccomon.h"
-#include "secoidt.h"
-#include "hasht.h"
-
-typedef SECItem * (* SEC_PKCS5GetPBEPassword)(void *arg);
-
-/* used for V2 PKCS 12 Draft Spec */
-typedef enum {
- pbeBitGenIDNull = 0,
- pbeBitGenCipherKey = 0x01,
- pbeBitGenCipherIV = 0x02,
- pbeBitGenIntegrityKey = 0x03
-} PBEBitGenID;
-
-typedef struct _pbeBitGenParameters {
- unsigned int u, v;
- SECOidTag hashAlgorithm;
-} pbeBitGenParameters;
-
-typedef struct _PBEBitGenContext {
- PRArenaPool *arena;
-
- /* hash algorithm information */
- pbeBitGenParameters pbeParams;
- const SECHashObject *hashObject;
- void *hash;
-
- /* buffers used in generation of bits */
- SECItem D, S, P, I, A, B;
- unsigned int c, n;
- unsigned int iterations;
-} PBEBitGenContext;
-
-extern const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[];
-typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter;
-
-struct SEC_PKCS5PBEParameterStr {
- PRArenaPool *poolp;
- SECItem salt; /* octet string */
- SECItem iteration; /* integer */
-
- /* used locally */
- SECOidTag algorithm;
- int iter;
-};
-
-
-SEC_BEGIN_PROTOS
-/* Create a PKCS5 Algorithm ID
- * The algorithm ID is set up using the PKCS #5 parameter structure
- * algorithm is the PBE algorithm ID for the desired algorithm
- * salt can be specified or can be NULL, if salt is NULL then the
- * salt is generated from random bytes
- * iteration is the number of iterations for which to perform the
- * hash prior to key and iv generation.
- * If an error occurs or the algorithm specified is not supported
- * or is not a password based encryption algorithm, NULL is returned.
- * Otherwise, a pointer to the algorithm id is returned.
- */
-extern SECAlgorithmID *
-SEC_PKCS5CreateAlgorithmID(SECOidTag algorithm,
- SECItem *salt,
- int iteration);
-
-/* Get the initialization vector. The password is passed in, hashing
- * is performed, and the initialization vector is returned.
- * algid is a pointer to a PBE algorithm ID
- * pwitem is the password
- * If an error occurs or the algorithm id is not a PBE algrithm,
- * NULL is returned. Otherwise, the iv is returned in a secitem.
- */
-extern SECItem *
-SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES);
-
-/* Get the key. The password is passed in, hashing is performed,
- * and the key is returned.
- * algid is a pointer to a PBE algorithm ID
- * pwitem is the password
- * If an error occurs or the algorithm id is not a PBE algrithm,
- * NULL is returned. Otherwise, the key is returned in a secitem.
- */
-extern SECItem *
-SEC_PKCS5GetKey(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES);
-
-/* Get PBE salt. The salt for the password based algorithm is returned.
- * algid is the PBE algorithm identifier
- * If an error occurs NULL is returned, otherwise the salt is returned
- * in a SECItem.
- */
-extern SECItem *
-SEC_PKCS5GetSalt(SECAlgorithmID *algid);
-
-/* Encrypt/Decrypt data using password based encryption.
- * algid is the PBE algorithm identifier,
- * pwitem is the password,
- * src is the source for encryption/decryption,
- * encrypt is PR_TRUE for encryption, PR_FALSE for decryption.
- * The key and iv are generated based upon PKCS #5 then the src
- * is either encrypted or decrypted. If an error occurs, NULL
- * is returned, otherwise the ciphered contents is returned.
- */
-extern SECItem *
-SEC_PKCS5CipherData(SECAlgorithmID *algid, SECItem *pwitem,
- SECItem *src, PRBool encrypt, PRBool *update);
-
-/* Checks to see if algid algorithm is a PBE algorithm. If
- * so, PR_TRUE is returned, otherwise PR_FALSE is returned.
- */
-extern PRBool
-SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid);
-
-/* Destroys PBE parameter */
-extern void
-SEC_PKCS5DestroyPBEParameter(SEC_PKCS5PBEParameter *param);
-
-/* Convert Algorithm ID to PBE parameter */
-extern SEC_PKCS5PBEParameter *
-SEC_PKCS5GetPBEParameter(SECAlgorithmID *algid);
-
-/* Determine how large the key generated is */
-extern int
-SEC_PKCS5GetKeyLength(SECAlgorithmID *algid);
-
-/* map crypto algorithm to pbe algorithm, assume sha 1 hashing for DES
- */
-extern SECOidTag
-SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen);
-
-/* return the underlying crypto algorithm */
-extern SECOidTag
-SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid);
-
-extern PBEBitGenContext *
-PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
- SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
- unsigned int interations);
-
-extern SECItem *
-PBE_GenerateBits(PBEBitGenContext *pbeCtxt);
-
-extern void PBE_DestroyContext(PBEBitGenContext *pbeCtxt);
-
-extern SECStatus PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param,
- PRArenaPool *arena, SECAlgorithmID *algId);
-SEC_END_PROTOS
-
-#endif
diff --git a/security/nss/lib/softoken/softoken.h b/security/nss/lib/softoken/softoken.h
index b13a93461..f9fb06222 100644
--- a/security/nss/lib/softoken/softoken.h
+++ b/security/nss/lib/softoken/softoken.h
@@ -39,8 +39,7 @@
#define _SOFTOKEN_H_
#include "blapi.h"
-#include "keytlow.h"
-#include "keytboth.h"
+#include "lowkeyti.h"
#include "softoknt.h"
#include "secoidt.h"
@@ -83,23 +82,23 @@ extern unsigned char *RSA_FormatOneBlock(unsigned int modulusLen,
* RSA_DecryptBlock.
*/
extern
-SECStatus RSA_Sign(SECKEYLowPrivateKey *key, unsigned char *output,
+SECStatus RSA_Sign(NSSLOWKEYPrivateKey *key, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
unsigned char *input, unsigned int inputLen);
extern
-SECStatus RSA_CheckSign(SECKEYLowPublicKey *key, unsigned char *sign,
+SECStatus RSA_CheckSign(NSSLOWKEYPublicKey *key, unsigned char *sign,
unsigned int signLength, unsigned char *hash,
unsigned int hashLength);
extern
-SECStatus RSA_CheckSignRecover(SECKEYLowPublicKey *key, unsigned char *data,
+SECStatus RSA_CheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data,
unsigned int *data_len,unsigned int max_output_len,
unsigned char *sign, unsigned int sign_len);
extern
-SECStatus RSA_EncryptBlock(SECKEYLowPublicKey *key, unsigned char *output,
+SECStatus RSA_EncryptBlock(NSSLOWKEYPublicKey *key, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
unsigned char *input, unsigned int inputLen);
extern
-SECStatus RSA_DecryptBlock(SECKEYLowPrivateKey *key, unsigned char *output,
+SECStatus RSA_DecryptBlock(NSSLOWKEYPrivateKey *key, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
unsigned char *input, unsigned int inputLen);
@@ -108,24 +107,24 @@ SECStatus RSA_DecryptBlock(SECKEYLowPrivateKey *key, unsigned char *output,
* RAW is RSA_X_509
*/
extern
-SECStatus RSA_SignRaw( SECKEYLowPrivateKey *key, unsigned char *output,
+SECStatus RSA_SignRaw( NSSLOWKEYPrivateKey *key, unsigned char *output,
unsigned int *output_len, unsigned int maxOutputLen,
unsigned char *input, unsigned int input_len);
extern
-SECStatus RSA_CheckSignRaw( SECKEYLowPublicKey *key, unsigned char *sign,
+SECStatus RSA_CheckSignRaw( NSSLOWKEYPublicKey *key, unsigned char *sign,
unsigned int sign_len, unsigned char *hash,
unsigned int hash_len);
extern
-SECStatus RSA_CheckSignRecoverRaw( SECKEYLowPublicKey *key, unsigned char *data,
+SECStatus RSA_CheckSignRecoverRaw( NSSLOWKEYPublicKey *key, unsigned char *data,
unsigned int *data_len, unsigned int max_output_len,
unsigned char *sign, unsigned int sign_len);
extern
-SECStatus RSA_EncryptRaw( SECKEYLowPublicKey *key, unsigned char *output,
+SECStatus RSA_EncryptRaw( NSSLOWKEYPublicKey *key, unsigned char *output,
unsigned int *output_len,
unsigned int max_output_len,
unsigned char *input, unsigned int input_len);
extern
-SECStatus RSA_DecryptRaw(SECKEYLowPrivateKey *key, unsigned char *output,
+SECStatus RSA_DecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
unsigned int *output_len,
unsigned int max_output_len,
unsigned char *input, unsigned int input_len);
diff --git a/security/nss/lib/softoken/softokn.def b/security/nss/lib/softoken/softokn.def
new file mode 100644
index 000000000..443583334
--- /dev/null
+++ b/security/nss/lib/softoken/softokn.def
@@ -0,0 +1,57 @@
+;+#
+;+# 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 Netscape are
+;+# Copyright (C) 2000 Netscape Communications Corporation. 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 the GNU General Public License Version 2 or later (the
+;+# "GPL"), in which case the provisions of the GPL are applicable
+;+# instead of those above. If you wish to allow use of your
+;+# version of this file only under the terms of the GPL and not to
+;+# allow others to use your version of this file under the MPL,
+;+# indicate your decision by deleting the provisions above and
+;+# replace them with the notice and other provisions required by
+;+# the GPL. If you do not delete the provisions above, a recipient
+;+# may use your version of this file under either the MPL or the
+;+# GPL.
+;+#
+;+#
+;+# 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 ";-"
+;+SOFTOKEN_3.4 { # Softoken 3.4 release
+;+ global:
+LIBRARY softoken ;-
+EXPORTS ;-
+NSC_GetFunctionList ;
+NSC_ModuleDBFunc ;
+FC_GetFunctionList ;
+C_GetFunctionList ; Make this function like a real PKCS #11 module as well
+;+ local:
+;+ *;
+;+};
diff --git a/security/nss/lib/softoken/softokn.rc b/security/nss/lib/softoken/softokn.rc
new file mode 100644
index 000000000..31bdb2272
--- /dev/null
+++ b/security/nss/lib/softoken/softokn.rc
@@ -0,0 +1,98 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 2001 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "nss.h"
+#include <winver.h>
+
+#define MY_LIBNAME "softoken"
+#define MY_FILEDESCRIPTION "NSS Builtin Crypto PKCS #11 Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define NSS_VMAJOR_STR STRINGIZE2(NSS_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if NSS_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#endif
+
+#define MY_INTERNAL_NAME MY_LIBNAME NSS_VMAJOR_STR
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0
+ PRODUCTVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Netscape Communications Corporation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", NSS_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "LegalCopyright", "Copyright \251 1994-2001 Netscape Communications Corporation\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Network Security Services\0"
+ VALUE "ProductVersion", NSS_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/security/nss/lib/softoken/keytlow.h b/security/nss/lib/softoken/sysrand.c
index 3c0c55ab0..2f647041a 100644
--- a/security/nss/lib/softoken/keytlow.h
+++ b/security/nss/lib/softoken/sysrand.c
@@ -30,46 +30,17 @@
* may use your version of this file under either the MPL or the
* GPL.
*/
-#ifndef _KEYTLOW_H_
-#define _KEYTLOW_H_ 1
-#include "blapit.h"
-
-typedef enum {
- lowNullKey = 0,
- lowRSAKey = 1,
- lowDSAKey = 2,
- lowDHKey = 4
-} LowKeyType;
-
-/*
-** An RSA public key object.
-*/
-struct SECKEYLowPublicKeyStr {
- PLArenaPool *arena;
- LowKeyType keyType ;
- union {
- RSAPublicKey rsa;
- DSAPublicKey dsa;
- DHPublicKey dh;
- } u;
-};
-typedef struct SECKEYLowPublicKeyStr SECKEYLowPublicKey;
-
-/*
-** 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 SECKEYLowPrivateKeyStr {
- PLArenaPool *arena;
- LowKeyType keyType;
- union {
- RSAPrivateKey rsa;
- DSAPrivateKey dsa;
- DHPrivateKey dh;
- } u;
-};
-typedef struct SECKEYLowPrivateKeyStr SECKEYLowPrivateKey;
-
-#endif /* _KEYTLOW_H_ */
+#include "seccomon.h"
+#ifdef XP_UNIX
+#include "unix_rand.c"
+#endif
+#ifdef XP_WIN
+#include "win_rand.c"
+#endif
+#ifdef XP_MAC
+#include "mac_rand.c"
+#endif
+#ifdef XP_OS2
+#include "os2_rand.c"
+#endif
diff --git a/security/nss/lib/softoken/unix_rand.c b/security/nss/lib/softoken/unix_rand.c
new file mode 100644
index 000000000..12b08aea3
--- /dev/null
+++ b/security/nss/lib/softoken/unix_rand.c
@@ -0,0 +1,891 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include "secrng.h"
+
+
+/*
+ * When copying data to the buffer we want the least signicant bytes
+ * from the input since those bits are changing the fastest. The address
+ * of least significant byte depends upon whether we are running on
+ * a big-endian or little-endian machine.
+ *
+ * Does this mean the least signicant bytes are the most significant
+ * to us? :-)
+ */
+
+static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen)
+{
+ union endianness {
+ int32 i;
+ char c[4];
+ } u;
+
+ if (srclen <= dstlen) {
+ memcpy(dst, src, srclen);
+ return srclen;
+ }
+ u.i = 0x01020304;
+ if (u.c[0] == 0x01) {
+ /* big-endian case */
+ memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
+ } else {
+ /* little-endian case */
+ memcpy(dst, src, dstlen);
+ }
+ return dstlen;
+}
+
+#if defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(FREEBSD) \
+ || defined(NETBSD)
+#include <sys/times.h>
+
+#define getdtablesize() sysconf(_SC_OPEN_MAX)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ int ticks;
+ struct tms buffer;
+
+ ticks=times(&buffer);
+ return CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
+}
+
+static void
+GiveSystemInfo(void)
+{
+ long si;
+
+ /*
+ * Is this really necessary? Why not use rand48 or something?
+ */
+ si = sysconf(_SC_CHILD_MAX);
+ RNG_RandomUpdate(&si, sizeof(si));
+
+ si = sysconf(_SC_STREAM_MAX);
+ RNG_RandomUpdate(&si, sizeof(si));
+
+ si = sysconf(_SC_OPEN_MAX);
+ RNG_RandomUpdate(&si, sizeof(si));
+}
+#endif
+
+#if defined(__sun)
+#if defined(__svr4) || defined(SVR4)
+#include <sys/systeminfo.h>
+#include <sys/times.h>
+#include <wait.h>
+
+int gettimeofday(struct timeval *);
+int gethostname(char *, int);
+
+#define getdtablesize() sysconf(_SC_OPEN_MAX)
+
+static void
+GiveSystemInfo(void)
+{
+ int rv;
+ char buf[2000];
+
+ rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+}
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ hrtime_t t;
+ t = gethrtime();
+ if (t) {
+ return CopyLowBits(buf, maxbytes, &t, sizeof(t));
+ }
+ return 0;
+}
+#else /* SunOS (Sun, but not SVR4) */
+
+#include <sys/wait.h>
+extern long sysconf(int name);
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+static void
+GiveSystemInfo(void)
+{
+ long si;
+
+ /* This is not very good */
+ si = sysconf(_SC_CHILD_MAX);
+ RNG_RandomUpdate(&si, sizeof(si));
+}
+#endif
+#endif /* Sun */
+
+#if defined(__hpux)
+#include <sys/unistd.h>
+#include <sys/wait.h>
+
+#define getdtablesize() sysconf(_SC_OPEN_MAX)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ extern int ret_cr16();
+ int cr16val;
+
+ cr16val = ret_cr16();
+ return CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val));
+}
+
+static void
+GiveSystemInfo(void)
+{
+ long si;
+
+ /* This is not very good */
+ si = sysconf(_AES_OS_VERSION);
+ RNG_RandomUpdate(&si, sizeof(si));
+ si = sysconf(_SC_CPU_VERSION);
+ RNG_RandomUpdate(&si, sizeof(si));
+}
+#endif /* HPUX */
+
+#if defined(OSF1)
+#include <sys/types.h>
+#include <sys/sysinfo.h>
+#include <sys/wait.h>
+#include <sys/systeminfo.h>
+#include <c_asm.h>
+
+static void
+GiveSystemInfo(void)
+{
+ char buf[BUFSIZ];
+ int rv;
+ int off = 0;
+
+ rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+}
+
+/*
+ * Use the "get the cycle counter" instruction on the alpha.
+ * The low 32 bits completely turn over in less than a minute.
+ * The high 32 bits are some non-counter gunk that changes sometimes.
+ */
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ unsigned long t;
+
+ t = asm("rpcc %v0");
+ return CopyLowBits(buf, maxbytes, &t, sizeof(t));
+}
+
+#endif /* Alpha */
+
+#if defined(_IBMR2)
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+static void
+GiveSystemInfo(void)
+{
+ /* XXX haven't found any yet! */
+}
+#endif /* IBM R2 */
+
+#if defined(LINUX)
+#include <linux/kernel.h>
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+static void
+GiveSystemInfo(void)
+{
+ /* XXX sysinfo() does not seem be implemented anywhwere */
+#if 0
+ struct sysinfo si;
+ char hn[2000];
+ if (sysinfo(&si) == 0) {
+ RNG_RandomUpdate(&si, sizeof(si));
+ }
+#endif
+}
+#endif /* LINUX */
+
+#if defined(NCR)
+
+#include <sys/utsname.h>
+#include <sys/systeminfo.h>
+
+#define getdtablesize() sysconf(_SC_OPEN_MAX)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+static void
+GiveSystemInfo(void)
+{
+ int rv;
+ char buf[2000];
+
+ rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+}
+
+#endif /* NCR */
+
+
+#if defined(sgi)
+#include <fcntl.h>
+#undef PRIVATE
+#include <sys/mman.h>
+#include <sys/syssgi.h>
+#include <sys/immu.h>
+#include <sys/systeminfo.h>
+#include <sys/utsname.h>
+#include <wait.h>
+
+static void
+GiveSystemInfo(void)
+{
+ int rv;
+ char buf[4096];
+
+ rv = syssgi(SGI_SYSID, &buf[0]);
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, MAXSYSIDSIZE);
+ }
+#ifdef SGI_RDUBLK
+ rv = syssgi(SGI_RDUBLK, getpid(), &buf[0], sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, sizeof(buf));
+ }
+#endif /* SGI_RDUBLK */
+ rv = syssgi(SGI_INVENT, SGI_INV_READ, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, sizeof(buf));
+ }
+ rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+}
+
+static size_t GetHighResClock(void *buf, size_t maxbuf)
+{
+ unsigned phys_addr, raddr, cycleval;
+ static volatile unsigned *iotimer_addr = NULL;
+ static int tries = 0;
+ static int cntr_size;
+ int mfd;
+ long s0[2];
+ struct timeval tv;
+
+#ifndef SGI_CYCLECNTR_SIZE
+#define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */
+#endif
+
+ if (iotimer_addr == NULL) {
+ if (tries++ > 1) {
+ /* Don't keep trying if it didn't work */
+ return 0;
+ }
+
+ /*
+ ** For SGI machines we can use the cycle counter, if it has one,
+ ** to generate some truly random numbers
+ */
+ phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);
+ if (phys_addr) {
+ int pgsz = getpagesize();
+ int pgoffmask = pgsz - 1;
+
+ raddr = phys_addr & ~pgoffmask;
+ mfd = open("/dev/mmem", O_RDONLY);
+ if (mfd < 0) {
+ return 0;
+ }
+ iotimer_addr = (unsigned *)
+ mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr);
+ if (iotimer_addr == (void*)-1) {
+ close(mfd);
+ iotimer_addr = NULL;
+ return 0;
+ }
+ iotimer_addr = (unsigned*)
+ ((__psint_t)iotimer_addr | (phys_addr & pgoffmask));
+ /*
+ * The file 'mfd' is purposefully not closed.
+ */
+ cntr_size = syssgi(SGI_CYCLECNTR_SIZE);
+ if (cntr_size < 0) {
+ struct utsname utsinfo;
+
+ /*
+ * We must be executing on a 6.0 or earlier system, since the
+ * SGI_CYCLECNTR_SIZE call is not supported.
+ *
+ * The only pre-6.1 platforms with 64-bit counters are
+ * IP19 and IP21 (Challenge, PowerChallenge, Onyx).
+ */
+ uname(&utsinfo);
+ if (!strncmp(utsinfo.machine, "IP19", 4) ||
+ !strncmp(utsinfo.machine, "IP21", 4))
+ cntr_size = 64;
+ else
+ cntr_size = 32;
+ }
+ cntr_size /= 8; /* Convert from bits to bytes */
+ }
+ }
+
+ s0[0] = *iotimer_addr;
+ if (cntr_size > 4)
+ s0[1] = *(iotimer_addr + 1);
+ memcpy(buf, (char *)&s0[0], cntr_size);
+ return CopyLowBits(buf, maxbuf, &s0, cntr_size);
+}
+#endif
+
+#if defined(sony)
+#include <sys/systeminfo.h>
+
+#define getdtablesize() sysconf(_SC_OPEN_MAX)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+static void
+GiveSystemInfo(void)
+{
+ int rv;
+ char buf[2000];
+
+ rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+}
+#endif /* sony */
+
+#if defined(sinix)
+#include <unistd.h>
+#include <sys/systeminfo.h>
+#include <sys/times.h>
+
+int gettimeofday(struct timeval *, struct timezone *);
+int gethostname(char *, int);
+
+#define getdtablesize() sysconf(_SC_OPEN_MAX)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ int ticks;
+ struct tms buffer;
+
+ ticks=times(&buffer);
+ return CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
+}
+
+static void
+GiveSystemInfo(void)
+{
+ int rv;
+ char buf[2000];
+
+ rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+}
+#endif /* sinix */
+
+#if defined(VMS)
+#include <c_asm.h>
+
+static void
+GiveSystemInfo(void)
+{
+ long si;
+
+ /*
+ * This is copied from the SCO/UNIXWARE etc section. And like the comment
+ * there says, what's the point? This isn't random, it generates the same
+ * stuff every time its run!
+ */
+ si = sysconf(_SC_CHILD_MAX);
+ RNG_RandomUpdate(&si, sizeof(si));
+
+ si = sysconf(_SC_STREAM_MAX);
+ RNG_RandomUpdate(&si, sizeof(si));
+
+ si = sysconf(_SC_OPEN_MAX);
+ RNG_RandomUpdate(&si, sizeof(si));
+}
+
+/*
+ * Use the "get the cycle counter" instruction on the alpha.
+ * The low 32 bits completely turn over in less than a minute.
+ * The high 32 bits are some non-counter gunk that changes sometimes.
+ */
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ unsigned long t;
+
+ t = asm("rpcc %v0");
+ return CopyLowBits(buf, maxbytes, &t, sizeof(t));
+}
+
+#endif /* VMS */
+
+#if defined(nec_ews)
+#include <sys/systeminfo.h>
+
+#define getdtablesize() sysconf(_SC_OPEN_MAX)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+static void
+GiveSystemInfo(void)
+{
+ int rv;
+ char buf[2000];
+
+ rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+ rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
+ if (rv > 0) {
+ RNG_RandomUpdate(buf, rv);
+ }
+}
+#endif /* nec_ews */
+
+size_t RNG_GetNoise(void *buf, size_t maxbytes)
+{
+ struct timeval tv;
+ int n = 0;
+ int c;
+
+ n = GetHighResClock(buf, maxbytes);
+ maxbytes -= n;
+
+#if defined(__sun) && (defined(_svr4) || defined(SVR4)) || defined(sony)
+ (void)gettimeofday(&tv);
+#else
+ (void)gettimeofday(&tv, 0);
+#endif
+ c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_usec, sizeof(tv.tv_usec));
+ n += c;
+ maxbytes -= c;
+ c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_sec, sizeof(tv.tv_sec));
+ n += c;
+ return n;
+}
+
+#define SAFE_POPEN_MAXARGS 10 /* must be at least 2 */
+
+/*
+ * safe_popen is static to this module and we know what arguments it is
+ * called with. Note that this version only supports a single open child
+ * process at any time.
+ */
+static pid_t safe_popen_pid;
+static struct sigaction oldact;
+
+static FILE *
+safe_popen(char *cmd)
+{
+ int p[2], fd, argc;
+ pid_t pid;
+ char *argv[SAFE_POPEN_MAXARGS + 1];
+ FILE *fp;
+ static char blank[] = " \t";
+ static struct sigaction newact;
+
+ if (pipe(p) < 0)
+ return 0;
+
+ /* Setup signals so that SIGCHLD is ignored as we want to do waitpid */
+ newact.sa_handler = SIG_DFL;
+ newact.sa_flags = 0;
+ sigfillset(&newact.sa_mask);
+ sigaction (SIGCHLD, &newact, &oldact);
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ close(p[0]);
+ close(p[1]);
+ sigaction (SIGCHLD, &oldact, NULL);
+ return 0;
+
+ case 0:
+ /* dup write-side of pipe to stderr and stdout */
+ if (p[1] != 1) dup2(p[1], 1);
+ if (p[1] != 2) dup2(p[1], 2);
+ close(0);
+ for (fd = getdtablesize(); --fd > 2; close(fd))
+ ;
+
+ /* clean up environment in the child process */
+ putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc");
+ putenv("SHELL=/bin/sh");
+ putenv("IFS= \t");
+
+ /*
+ * The caller may have passed us a string that is in text
+ * space. It may be illegal to modify the string
+ */
+ cmd = strdup(cmd);
+ /* format argv */
+ argv[0] = strtok(cmd, blank);
+ argc = 1;
+ while ((argv[argc] = strtok(0, blank)) != 0) {
+ if (++argc == SAFE_POPEN_MAXARGS) {
+ argv[argc] = 0;
+ break;
+ }
+ }
+
+ /* and away we go */
+ execvp(argv[0], argv);
+ exit(127);
+ break;
+
+ default:
+ close(p[1]);
+ fp = fdopen(p[0], "r");
+ if (fp == 0) {
+ close(p[0]);
+ sigaction (SIGCHLD, &oldact, NULL);
+ return 0;
+ }
+ break;
+ }
+
+ /* non-zero means there's a cmd running */
+ safe_popen_pid = pid;
+ return fp;
+}
+
+static int
+safe_pclose(FILE *fp)
+{
+ pid_t pid;
+ int count, status;
+
+ if ((pid = safe_popen_pid) == 0)
+ return -1;
+ safe_popen_pid = 0;
+
+ /* if the child hasn't exited, kill it -- we're done with its output */
+ count = 0;
+ while (waitpid(pid, &status, WNOHANG) == 0) {
+ if (kill(pid, SIGKILL) < 0 && errno == ESRCH)
+ break;
+ if (++count == 1000)
+ break;
+ }
+
+ /* Reset SIGCHLD signal hander before returning */
+ sigaction(SIGCHLD, &oldact, NULL);
+
+ fclose(fp);
+ return status;
+}
+
+
+#if !defined(VMS)
+void RNG_SystemInfoForRNG(void)
+{
+ FILE *fp;
+ char buf[BUFSIZ];
+ size_t bytes;
+ extern char **environ;
+ char **cp;
+ char *randfile;
+ char *files[] = {
+ "/etc/passwd",
+ "/etc/utmp",
+ "/tmp",
+ "/var/tmp",
+ "/usr/tmp",
+ 0
+ };
+
+#ifdef DO_PS
+For now it is considered that it is too expensive to run the ps command
+for the small amount of entropy it provides.
+#if defined(__sun) && (!defined(__svr4) && !defined(SVR4)) || defined(bsdi) || defined(LINUX)
+ static char ps_cmd[] = "ps aux";
+#else
+ static char ps_cmd[] = "ps -el";
+#endif
+#endif /* DO_PS */
+ static char netstat_ni_cmd[] = "netstat -ni";
+
+ GiveSystemInfo();
+
+ bytes = RNG_GetNoise(buf, sizeof(buf));
+ RNG_RandomUpdate(buf, bytes);
+
+#ifdef DO_PS
+ fp = safe_popen(ps_cmd);
+ if (fp != NULL) {
+ while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
+ RNG_RandomUpdate(buf, bytes);
+ safe_pclose(fp);
+ }
+#endif
+ fp = safe_popen(netstat_ni_cmd);
+ if (fp != NULL) {
+ while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
+ RNG_RandomUpdate(buf, bytes);
+ safe_pclose(fp);
+ }
+
+ /*
+ * Pass the C environment and the addresses of the pointers to the
+ * hash function. This makes the random number function depend on the
+ * execution environment of the user and on the platform the program
+ * is running on.
+ */
+ cp = environ;
+ while (*cp) {
+ RNG_RandomUpdate(*cp, strlen(*cp));
+ cp++;
+ }
+ RNG_RandomUpdate(environ, (char*)cp - (char*)environ);
+
+ /* Give in system information */
+ if (gethostname(buf, sizeof(buf)) > 0) {
+ RNG_RandomUpdate(buf, strlen(buf));
+ }
+ GiveSystemInfo();
+
+ /* If the user points us to a random file, pass it through the rng */
+ randfile = getenv("NSRANDFILE");
+ if ( ( randfile != NULL ) && ( randfile[0] != '\0') ) {
+ RNG_FileForRNG(randfile);
+ }
+
+ /* pass other files through */
+ for (cp = files; *cp; cp++)
+ RNG_FileForRNG(*cp);
+
+}
+#else
+void RNG_SystemInfoForRNG(void)
+{
+ FILE *fp;
+ char buf[BUFSIZ];
+ size_t bytes;
+ int extra;
+ extern char **environ;
+ char **cp;
+ char *randfile;
+
+ GiveSystemInfo();
+
+ bytes = RNG_GetNoise(buf, sizeof(buf));
+ RNG_RandomUpdate(buf, bytes);
+
+ /*
+ * Pass the C environment and the addresses of the pointers to the
+ * hash function. This makes the random number function depend on the
+ * execution environment of the user and on the platform the program
+ * is running on.
+ */
+ cp = environ;
+ while (*cp) {
+ RNG_RandomUpdate(*cp, strlen(*cp));
+ cp++;
+ }
+ RNG_RandomUpdate(environ, (char*)cp - (char*)environ);
+
+ /* Give in system information */
+ if (gethostname(buf, sizeof(buf)) > 0) {
+ RNG_RandomUpdate(buf, strlen(buf));
+ }
+ GiveSystemInfo();
+
+ /* If the user points us to a random file, pass it through the rng */
+ randfile = getenv("NSRANDFILE");
+ if ( ( randfile != NULL ) && ( randfile[0] != '\0') ) {
+ RNG_FileForRNG(randfile);
+ }
+
+ /*
+ ** We need to generate at least 1024 bytes of seed data. Since we don't
+ ** do the file stuff for VMS, and because the environ list is so short
+ ** on VMS, we need to make sure we generate enough. So do another 1000
+ ** bytes to be sure.
+ */
+ extra = 1000;
+ while (extra > 0) {
+ cp = environ;
+ while (*cp) {
+ int n = strlen(*cp);
+ RNG_RandomUpdate(*cp, n);
+ extra -= n;
+ cp++;
+ }
+ }
+}
+#endif
+
+void RNG_FileForRNG(char *fileName)
+{
+ struct stat stat_buf;
+ unsigned char buffer[BUFSIZ];
+ size_t bytes;
+ FILE *file;
+ static size_t totalFileBytes = 0;
+
+ if (stat((char *)fileName, &stat_buf) < 0)
+ return;
+ RNG_RandomUpdate(&stat_buf, sizeof(stat_buf));
+
+ file = fopen((char *)fileName, "r");
+ if (file != NULL) {
+ for (;;) {
+ bytes = fread(buffer, 1, sizeof(buffer), file);
+ if (bytes == 0) break;
+ RNG_RandomUpdate(buffer, bytes);
+ totalFileBytes += bytes;
+ if (totalFileBytes > 1024*1024) break;
+ }
+ fclose(file);
+ }
+ /*
+ * Pass yet another snapshot of our highest resolution clock into
+ * the hash function.
+ */
+ bytes = RNG_GetNoise(buffer, sizeof(buffer));
+ RNG_RandomUpdate(buffer, bytes);
+}
diff --git a/security/nss/lib/softoken/win_rand.c b/security/nss/lib/softoken/win_rand.c
new file mode 100644
index 000000000..de2e06ea7
--- /dev/null
+++ b/security/nss/lib/softoken/win_rand.c
@@ -0,0 +1,415 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "secrng.h"
+#ifdef XP_WIN
+#include <windows.h>
+#include <time.h>
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#ifndef _WIN32
+#define VTD_Device_ID 5
+#define OP_OVERRIDE _asm _emit 0x66
+#include <dos.h>
+#endif
+
+static BOOL
+CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow)
+{
+#ifdef _WIN32
+ LARGE_INTEGER liCount;
+
+ if (!QueryPerformanceCounter(&liCount))
+ return FALSE;
+
+ *lpdwHigh = liCount.u.HighPart;
+ *lpdwLow = liCount.u.LowPart;
+ return TRUE;
+
+#else /* is WIN16 */
+ BOOL bRetVal;
+ FARPROC lpAPI;
+ WORD w1, w2, w3, w4;
+
+ // Get direct access to the VTD and query the current clock tick time
+ _asm {
+ xor di, di
+ mov es, di
+ mov ax, 1684h
+ mov bx, VTD_Device_ID
+ int 2fh
+ mov ax, es
+ or ax, di
+ jz EnumerateFailed
+
+ ; VTD API is available. First store the API address (the address actually
+ ; contains an instruction that causes a fault, the fault handler then
+ ; makes the ring transition and calls the API in the VxD)
+ mov word ptr lpAPI, di
+ mov word ptr lpAPI+2, es
+ mov ax, 100h ; API function to VTD_Get_Real_Time
+; call dword ptr [lpAPI]
+ call [lpAPI]
+
+ ; Result is in EDX:EAX which we will get 16-bits at a time
+ mov w2, dx
+ OP_OVERRIDE
+ shr dx,10h ; really "shr edx, 16"
+ mov w1, dx
+
+ mov w4, ax
+ OP_OVERRIDE
+ shr ax,10h ; really "shr eax, 16"
+ mov w3, ax
+
+ mov bRetVal, 1 ; return TRUE
+ jmp EnumerateExit
+
+ EnumerateFailed:
+ mov bRetVal, 0 ; return FALSE
+
+ EnumerateExit:
+ }
+
+ *lpdwHigh = MAKELONG(w2, w1);
+ *lpdwLow = MAKELONG(w4, w3);
+
+ return bRetVal;
+#endif /* is WIN16 */
+}
+
+size_t RNG_GetNoise(void *buf, size_t maxbuf)
+{
+ DWORD dwHigh, dwLow, dwVal;
+ int n = 0;
+ int nBytes;
+ time_t sTime;
+
+ if (maxbuf <= 0)
+ return 0;
+
+ CurrentClockTickTime(&dwHigh, &dwLow);
+
+ // get the maximally changing bits first
+ nBytes = sizeof(dwLow) > maxbuf ? maxbuf : sizeof(dwLow);
+ memcpy((char *)buf, &dwLow, nBytes);
+ n += nBytes;
+ maxbuf -= nBytes;
+
+ if (maxbuf <= 0)
+ return n;
+
+ nBytes = sizeof(dwHigh) > maxbuf ? maxbuf : sizeof(dwHigh);
+ memcpy(((char *)buf) + n, &dwHigh, nBytes);
+ n += nBytes;
+ maxbuf -= nBytes;
+
+ if (maxbuf <= 0)
+ return n;
+
+ // get the number of milliseconds that have elapsed since Windows started
+ dwVal = GetTickCount();
+
+ nBytes = sizeof(dwVal) > maxbuf ? maxbuf : sizeof(dwVal);
+ memcpy(((char *)buf) + n, &dwVal, nBytes);
+ n += nBytes;
+ maxbuf -= nBytes;
+
+ if (maxbuf <= 0)
+ return n;
+
+ // get the time in seconds since midnight Jan 1, 1970
+ time(&sTime);
+ nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
+ memcpy(((char *)buf) + n, &sTime, nBytes);
+ n += nBytes;
+
+ return n;
+}
+
+static BOOL
+EnumSystemFiles(void (*func)(char *))
+{
+ int iStatus;
+ char szSysDir[_MAX_PATH];
+ char szFileName[_MAX_PATH];
+#ifdef _WIN32
+ struct _finddata_t fdData;
+ long lFindHandle;
+#else
+ struct _find_t fdData;
+#endif
+
+ if (!GetSystemDirectory(szSysDir, sizeof(szSysDir)))
+ return FALSE;
+
+ // tack *.* on the end so we actually look for files. this will
+ // not overflow
+ strcpy(szFileName, szSysDir);
+ strcat(szFileName, "\\*.*");
+
+#ifdef _WIN32
+ lFindHandle = _findfirst(szFileName, &fdData);
+ if (lFindHandle == -1)
+ return FALSE;
+#else
+ if (_dos_findfirst(szFileName, _A_NORMAL | _A_RDONLY | _A_ARCH | _A_SUBDIR, &fdData) != 0)
+ return FALSE;
+#endif
+
+ do {
+ // pass the full pathname to the callback
+ sprintf(szFileName, "%s\\%s", szSysDir, fdData.name);
+ (*func)(szFileName);
+
+#ifdef _WIN32
+ iStatus = _findnext(lFindHandle, &fdData);
+#else
+ iStatus = _dos_findnext(&fdData);
+#endif
+ } while (iStatus == 0);
+
+#ifdef _WIN32
+ _findclose(lFindHandle);
+#endif
+
+ return TRUE;
+}
+
+static DWORD dwNumFiles, dwReadEvery;
+
+static void
+CountFiles(char *file)
+{
+ dwNumFiles++;
+}
+
+static void
+ReadFiles(char *file)
+{
+ if ((dwNumFiles % dwReadEvery) == 0)
+ RNG_FileForRNG(file);
+
+ dwNumFiles++;
+}
+
+static void
+ReadSystemFiles()
+{
+ // first count the number of files
+ dwNumFiles = 0;
+ if (!EnumSystemFiles(CountFiles))
+ return;
+
+ RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles));
+
+ // now read 10 files
+ if (dwNumFiles == 0)
+ return;
+
+ dwReadEvery = dwNumFiles / 10;
+ if (dwReadEvery == 0)
+ dwReadEvery = 1; // less than 10 files
+
+ dwNumFiles = 0;
+ EnumSystemFiles(ReadFiles);
+}
+
+void RNG_SystemInfoForRNG(void)
+{
+ DWORD dwVal;
+ char buffer[256];
+ int nBytes;
+#ifdef _WIN32
+ MEMORYSTATUS sMem;
+ DWORD dwSerialNum;
+ DWORD dwComponentLen;
+ DWORD dwSysFlags;
+ char volName[128];
+ DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters;
+ HANDLE hVal;
+#else
+ int iVal;
+ HTASK hTask;
+ WORD wDS, wCS;
+ LPSTR lpszEnv;
+#endif
+
+ nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
+ RNG_RandomUpdate(buffer, nBytes);
+
+#ifdef _WIN32
+ sMem.dwLength = sizeof(sMem);
+ GlobalMemoryStatus(&sMem); // assorted memory stats
+ RNG_RandomUpdate(&sMem, sizeof(sMem));
+
+ dwVal = GetLogicalDrives();
+ RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25
+
+#else
+ dwVal = GetFreeSpace(0);
+ RNG_RandomUpdate(&dwVal, sizeof(dwVal));
+
+ _asm mov wDS, ds;
+ _asm mov wCS, cs;
+ RNG_RandomUpdate(&wDS, sizeof(wDS));
+ RNG_RandomUpdate(&wCS, sizeof(wCS));
+#endif
+
+#ifdef _WIN32
+ dwVal = sizeof(buffer);
+ if (GetComputerName(buffer, &dwVal))
+ RNG_RandomUpdate(buffer, dwVal);
+
+/* XXX This is code that got yanked because of NSPR20. We should put it
+ * back someday.
+ */
+#ifdef notdef
+ {
+ POINT ptVal;
+ GetCursorPos(&ptVal);
+ RNG_RandomUpdate(&ptVal, sizeof(ptVal));
+ }
+
+ dwVal = GetQueueStatus(QS_ALLINPUT); // high and low significant
+ RNG_RandomUpdate(&dwVal, sizeof(dwVal));
+
+ {
+ HWND hWnd;
+ hWnd = GetClipboardOwner(); // 2 or 4 bytes
+ RNG_RandomUpdate((void *)&hWnd, sizeof(hWnd));
+ }
+
+ {
+ UUID sUuid;
+ UuidCreate(&sUuid); // this will fail on machines with no ethernet
+ RNG_RandomUpdate(&sUuid, sizeof(sUuid)); // boards. shove the bits in regardless
+ }
+#endif
+
+ hVal = GetCurrentProcess(); // 4 byte handle of current task
+ RNG_RandomUpdate(&hVal, sizeof(hVal));
+
+ dwVal = GetCurrentProcessId(); // process ID (4 bytes)
+ RNG_RandomUpdate(&dwVal, sizeof(dwVal));
+
+ volName[0] = '\0';
+ buffer[0] = '\0';
+ GetVolumeInformation(NULL,
+ volName,
+ sizeof(volName),
+ &dwSerialNum,
+ &dwComponentLen,
+ &dwSysFlags,
+ buffer,
+ sizeof(buffer));
+
+ RNG_RandomUpdate(volName, strlen(volName));
+ RNG_RandomUpdate(&dwSerialNum, sizeof(dwSerialNum));
+ RNG_RandomUpdate(&dwComponentLen, sizeof(dwComponentLen));
+ RNG_RandomUpdate(&dwSysFlags, sizeof(dwSysFlags));
+ RNG_RandomUpdate(buffer, strlen(buffer));
+
+ if (GetDiskFreeSpace(NULL, &dwSectors, &dwBytes, &dwFreeClusters, &dwNumClusters)) {
+ RNG_RandomUpdate(&dwSectors, sizeof(dwSectors));
+ RNG_RandomUpdate(&dwBytes, sizeof(dwBytes));
+ RNG_RandomUpdate(&dwFreeClusters, sizeof(dwFreeClusters));
+ RNG_RandomUpdate(&dwNumClusters, sizeof(dwNumClusters));
+ }
+
+#else /* is WIN16 */
+ hTask = GetCurrentTask();
+ RNG_RandomUpdate((void *)&hTask, sizeof(hTask));
+
+ iVal = GetNumTasks();
+ RNG_RandomUpdate(&iVal, sizeof(iVal)); // number of running tasks
+
+ lpszEnv = GetDOSEnvironment();
+ while (*lpszEnv != '\0') {
+ RNG_RandomUpdate(lpszEnv, strlen(lpszEnv));
+
+ lpszEnv += strlen(lpszEnv) + 1;
+ }
+#endif /* is WIN16 */
+
+ // now let's do some files
+ ReadSystemFiles();
+
+ nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
+ RNG_RandomUpdate(buffer, nBytes);
+}
+
+void RNG_FileForRNG(char *filename)
+{
+ FILE* file;
+ int nBytes;
+ struct stat stat_buf;
+ unsigned char buffer[1024];
+
+ static DWORD totalFileBytes = 0;
+
+ /* windows doesn't initialize all the bytes in the stat buf,
+ * so initialize them all here to avoid UMRs.
+ */
+ memset(&stat_buf, 0, sizeof stat_buf);
+
+ if (stat((char *)filename, &stat_buf) < 0)
+ return;
+
+ RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf));
+
+ file = fopen((char *)filename, "r");
+ if (file != NULL) {
+ for (;;) {
+ size_t bytes = fread(buffer, 1, sizeof(buffer), file);
+
+ if (bytes == 0)
+ break;
+
+ RNG_RandomUpdate(buffer, bytes);
+ totalFileBytes += bytes;
+ if (totalFileBytes > 250000)
+ break;
+ }
+
+ fclose(file);
+ }
+
+ nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
+ RNG_RandomUpdate(buffer, nBytes);
+}
+
+#endif /* is XP_WIN */