Add support to dbm databases as a separate shared library.
git-svn-id: svn://10.0.0.236/branches/NSS_BOB_SHARED@224109 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: fipstest.c,v 1.21 2006-09-22 18:33:25 wtchang%redhat.com Exp $ */
|
||||
/* $Id: fipstest.c,v 1.21.2.1 2007-04-03 22:50:01 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#include "softoken.h" /* Required for RC2-ECB, RC2-CBC, RC4, DES-ECB, */
|
||||
/* DES-CBC, DES3-ECB, DES3-CBC, RSA */
|
||||
@@ -49,11 +49,6 @@
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
#include "secdert.h" /* Required for ECDSA */
|
||||
#include "ec.h" /* Required for ECDSA */
|
||||
extern SECStatus
|
||||
EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
|
||||
extern SECStatus
|
||||
EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
|
||||
const ECParams *srcParams);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
80
mozilla/security/nss/lib/softoken/legacydb/Makefile
Normal file
80
mozilla/security/nss/lib/softoken/legacydb/Makefile
Normal file
@@ -0,0 +1,80 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include config.mk
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
export:: private_export
|
||||
|
||||
85
mozilla/security/nss/lib/softoken/legacydb/cdbhdl.h
Normal file
85
mozilla/security/nss/lib/softoken/legacydb/cdbhdl.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* cdbhdl.h - certificate database handle
|
||||
* private to the certdb module
|
||||
*
|
||||
* $Id: cdbhdl.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
#ifndef _CDBHDL_H_
|
||||
#define _CDBHDL_H_
|
||||
|
||||
#include "nspr.h"
|
||||
#include "mcom_db.h"
|
||||
#include "pcertt.h"
|
||||
#include "prtypes.h"
|
||||
|
||||
/*
|
||||
* Handle structure for open certificate databases
|
||||
*/
|
||||
struct NSSLOWCERTCertDBHandleStr {
|
||||
DB *permCertDB;
|
||||
PZMonitor *dbMon;
|
||||
PRBool dbVerify;
|
||||
PRInt32 ref; /* reference count */
|
||||
};
|
||||
|
||||
#ifdef DBM_USING_NSPR
|
||||
#define NO_RDONLY PR_RDONLY
|
||||
#define NO_RDWR PR_RDWR
|
||||
#define NO_CREATE (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE)
|
||||
#else
|
||||
#define NO_RDONLY O_RDONLY
|
||||
#define NO_RDWR O_RDWR
|
||||
#define NO_CREATE (O_RDWR | O_CREAT | O_TRUNC)
|
||||
#endif
|
||||
|
||||
typedef DB * (*rdbfunc)(const char *appName, const char *prefix,
|
||||
const char *type, int flags);
|
||||
typedef int (*rdbstatusfunc)(void);
|
||||
|
||||
#define RDB_FAIL 1
|
||||
#define RDB_RETRY 2
|
||||
|
||||
DB * rdbopen(const char *appName, const char *prefix,
|
||||
const char *type, int flags, int *status);
|
||||
|
||||
DB *dbsopen (const char *dbname , int flags, int mode, DBTYPE type,
|
||||
const void * appData);
|
||||
SECStatus db_Copy(DB *dest,DB *src);
|
||||
int db_InitComplete(DB *db);
|
||||
|
||||
#endif
|
||||
102
mozilla/security/nss/lib/softoken/legacydb/config.mk
Normal file
102
mozilla/security/nss/lib/softoken/legacydb/config.mk
Normal file
@@ -0,0 +1,102 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
|
||||
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
|
||||
CRYPTODIR=../freebl
|
||||
ifdef MOZILLA_SECURITY_BUILD
|
||||
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
|
||||
CRYPTODIR=../crypto
|
||||
endif
|
||||
|
||||
EXTRA_LIBS += \
|
||||
$(CRYPTOLIB) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
# can't do this in manifest.mn because OS_TARGET isn't defined there.
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
|
||||
# don't want the 32 in the shared library name
|
||||
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
|
||||
IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
|
||||
|
||||
RES = $(OBJDIR)/$(LIBRARY_NAME).res
|
||||
RESNAME = $(LIBRARY_NAME).rc
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
else # ! NS_USE_GCC
|
||||
|
||||
EXTRA_SHARED_LIBS += \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
|
||||
$(NULL)
|
||||
endif # NS_USE_GCC
|
||||
|
||||
else
|
||||
|
||||
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
|
||||
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),SunOS)
|
||||
# The -R '$ORIGIN' linker option instructs this library to search for its
|
||||
# dependencies in the same directory where it resides.
|
||||
MKSHLIB += -R '$$ORIGIN'
|
||||
OS_LIBS += -lbsm
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),WINCE)
|
||||
DEFINES += -DDBM_USING_NSPR
|
||||
endif
|
||||
|
||||
# indicates dependency on freebl static lib
|
||||
$(SHARED_LIBRARY): $(CRYPTOLIB)
|
||||
647
mozilla/security/nss/lib/softoken/legacydb/dbmshim.c
Normal file
647
mozilla/security/nss/lib/softoken/legacydb/dbmshim.c
Normal file
@@ -0,0 +1,647 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Berkeley DB 1.85 Shim code to handle blobs.
|
||||
*
|
||||
* $Id: dbmshim.c,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
#include "mcom_db.h"
|
||||
#include "secitem.h"
|
||||
#include "nssb64.h"
|
||||
#include "blapi.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "lgdb.h"
|
||||
|
||||
/*
|
||||
* Blob block:
|
||||
* Byte 0 CERTDB Version -+ -+
|
||||
* Byte 1 certDBEntryTypeBlob | BLOB_HEAD_LEN |
|
||||
* Byte 2 flags (always '0'); | |
|
||||
* Byte 3 reserved (always '0'); -+ |
|
||||
* Byte 4 LSB length | <--BLOB_LENGTH_START | BLOB_BUF_LEN
|
||||
* Byte 5 . | |
|
||||
* Byte 6 . | BLOB_LENGTH_LEN |
|
||||
* Byte 7 MSB length | |
|
||||
* Byte 8 blob_filename -+ -+ <-- BLOB_NAME_START |
|
||||
* Byte 9 . | BLOB_NAME_LEN |
|
||||
* . . | |
|
||||
* Byte 37 . -+ -+
|
||||
*/
|
||||
#define DBS_BLOCK_SIZE (16*1024) /* 16 k */
|
||||
#define DBS_MAX_ENTRY_SIZE (DBS_BLOCK_SIZE - (2048)) /* 14 k */
|
||||
#define DBS_CACHE_SIZE DBS_BLOCK_SIZE*8
|
||||
#define ROUNDDIV(x,y) (x+(y-1))/y
|
||||
#define BLOB_HEAD_LEN 4
|
||||
#define BLOB_LENGTH_START BLOB_HEAD_LEN
|
||||
#define BLOB_LENGTH_LEN 4
|
||||
#define BLOB_NAME_START BLOB_LENGTH_START+BLOB_LENGTH_LEN
|
||||
#define BLOB_NAME_LEN 1+ROUNDDIV(SHA1_LENGTH,3)*4+1
|
||||
#define BLOB_BUF_LEN BLOB_HEAD_LEN+BLOB_LENGTH_LEN+BLOB_NAME_LEN
|
||||
|
||||
/* a Shim data structure. This data structure has a db built into it. */
|
||||
typedef struct DBSStr DBS;
|
||||
|
||||
struct DBSStr {
|
||||
DB db;
|
||||
char *blobdir;
|
||||
int mode;
|
||||
PRBool readOnly;
|
||||
PRFileMap *dbs_mapfile;
|
||||
unsigned char *dbs_addr;
|
||||
PRUint32 dbs_len;
|
||||
char staticBlobArea[BLOB_BUF_LEN];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* return true if the Datablock contains a blobtype
|
||||
*/
|
||||
static PRBool
|
||||
dbs_IsBlob(DBT *blobData)
|
||||
{
|
||||
unsigned char *addr = (unsigned char *)blobData->data;
|
||||
if (blobData->size < BLOB_BUF_LEN) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return addr && ((certDBEntryType) addr[1] == certDBEntryTypeBlob);
|
||||
}
|
||||
|
||||
/*
|
||||
* extract the filename in the blob of the real data set.
|
||||
* This value is not malloced (does not need to be freed by the caller.
|
||||
*/
|
||||
static const char *
|
||||
dbs_getBlobFileName(DBT *blobData)
|
||||
{
|
||||
char *addr = (char *)blobData->data;
|
||||
|
||||
return &addr[BLOB_NAME_START];
|
||||
}
|
||||
|
||||
/*
|
||||
* extract the size of the actual blob from the blob record
|
||||
*/
|
||||
static PRUint32
|
||||
dbs_getBlobSize(DBT *blobData)
|
||||
{
|
||||
unsigned char *addr = (unsigned char *)blobData->data;
|
||||
|
||||
return (PRUint32)(addr[BLOB_LENGTH_START+3] << 24) |
|
||||
(addr[BLOB_LENGTH_START+2] << 16) |
|
||||
(addr[BLOB_LENGTH_START+1] << 8) |
|
||||
addr[BLOB_LENGTH_START];
|
||||
}
|
||||
|
||||
|
||||
/* We are using base64 data for the filename, but base64 data can include a
|
||||
* '/' which is interpreted as a path separator on many platforms. Replace it
|
||||
* with an inocuous '-'. We don't need to convert back because we never actual
|
||||
* decode the filename.
|
||||
*/
|
||||
|
||||
static void
|
||||
dbs_replaceSlash(char *cp, int len)
|
||||
{
|
||||
while (len--) {
|
||||
if (*cp == '/') *cp = '-';
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* create a blob record from a key, data and return it in blobData.
|
||||
* NOTE: The data element is static data (keeping with the dbm model).
|
||||
*/
|
||||
static void
|
||||
dbs_mkBlob(DBS *dbsp,const DBT *key, const DBT *data, DBT *blobData)
|
||||
{
|
||||
unsigned char sha1_data[SHA1_LENGTH];
|
||||
char *b = dbsp->staticBlobArea;
|
||||
PRUint32 length = data->size;
|
||||
SECItem sha1Item;
|
||||
|
||||
b[0] = CERT_DB_FILE_VERSION; /* certdb version number */
|
||||
b[1] = (char) certDBEntryTypeBlob; /* type */
|
||||
b[2] = 0; /* flags */
|
||||
b[3] = 0; /* reserved */
|
||||
b[BLOB_LENGTH_START] = length & 0xff;
|
||||
b[BLOB_LENGTH_START+1] = (length >> 8) & 0xff;
|
||||
b[BLOB_LENGTH_START+2] = (length >> 16) & 0xff;
|
||||
b[BLOB_LENGTH_START+3] = (length >> 24) & 0xff;
|
||||
sha1Item.data = sha1_data;
|
||||
sha1Item.len = SHA1_LENGTH;
|
||||
SHA1_HashBuf(sha1_data,key->data,key->size);
|
||||
b[BLOB_NAME_START]='b'; /* Make sure we start with a alpha */
|
||||
NSSBase64_EncodeItem(NULL,&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1,&sha1Item);
|
||||
b[BLOB_BUF_LEN-1] = 0;
|
||||
dbs_replaceSlash(&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1);
|
||||
blobData->data = b;
|
||||
blobData->size = BLOB_BUF_LEN;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* construct a path to the actual blob. The string returned must be
|
||||
* freed by the caller with PR_smprintf_free.
|
||||
*
|
||||
* Note: this file does lots of consistancy checks on the DBT. The
|
||||
* routines that call this depend on these checks, so they don't worry
|
||||
* about them (success of this routine implies a good blobdata record).
|
||||
*/
|
||||
static char *
|
||||
dbs_getBlobFilePath(char *blobdir,DBT *blobData)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
if (blobdir == NULL) {
|
||||
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
|
||||
return NULL;
|
||||
}
|
||||
if (!dbs_IsBlob(blobData)) {
|
||||
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
|
||||
return NULL;
|
||||
}
|
||||
name = dbs_getBlobFileName(blobData);
|
||||
if (!name || *name == 0) {
|
||||
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
|
||||
return NULL;
|
||||
}
|
||||
return PR_smprintf("%s" PATH_SEPARATOR "%s", blobdir, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a blob file pointed to by the blob record.
|
||||
*/
|
||||
static void
|
||||
dbs_removeBlob(DBS *dbsp, DBT *blobData)
|
||||
{
|
||||
char *file;
|
||||
|
||||
file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
PR_Delete(file);
|
||||
PR_smprintf_free(file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Directory modes are slightly different, the 'x' bit needs to be on to
|
||||
* access them. Copy all the read bits to 'x' bits
|
||||
*/
|
||||
static int
|
||||
dbs_DirMode(int mode)
|
||||
{
|
||||
int x_bits = (mode >> 2) & 0111;
|
||||
return mode | x_bits;
|
||||
}
|
||||
|
||||
/*
|
||||
* write a data blob to it's file. blobdData is the blob record that will be
|
||||
* stored in the database. data is the actual data to go out on disk.
|
||||
*/
|
||||
static int
|
||||
dbs_writeBlob(DBS *dbsp, int mode, DBT *blobData, const DBT *data)
|
||||
{
|
||||
char *file = NULL;
|
||||
PRFileDesc *filed;
|
||||
PRStatus status;
|
||||
int len;
|
||||
int error = 0;
|
||||
|
||||
file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
|
||||
if (!file) {
|
||||
goto loser;
|
||||
}
|
||||
if (PR_Access(dbsp->blobdir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
|
||||
status = PR_MkDir(dbsp->blobdir,dbs_DirMode(mode));
|
||||
if (status != PR_SUCCESS) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
filed = PR_OpenFile(file,PR_CREATE_FILE|PR_TRUNCATE|PR_WRONLY, mode);
|
||||
if (filed == NULL) {
|
||||
error = PR_GetError();
|
||||
goto loser;
|
||||
}
|
||||
len = PR_Write(filed,data->data,data->size);
|
||||
error = PR_GetError();
|
||||
PR_Close(filed);
|
||||
if (len < (int)data->size) {
|
||||
goto loser;
|
||||
}
|
||||
PR_smprintf_free(file);
|
||||
return 0;
|
||||
|
||||
loser:
|
||||
if (file) {
|
||||
PR_Delete(file);
|
||||
PR_smprintf_free(file);
|
||||
}
|
||||
/* don't let close or delete reset the error */
|
||||
PR_SetError(error,0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* we need to keep a address map in memory between calls to DBM.
|
||||
* remember what we have mapped can close it when we get another dbm
|
||||
* call.
|
||||
*
|
||||
* NOTE: Not all platforms support mapped files. This code is designed to
|
||||
* detect this at runtime. If map files aren't supported the OS will indicate
|
||||
* this by failing the PR_Memmap call. In this case we emulate mapped files
|
||||
* by just reading in the file into regular memory. We signal this state by
|
||||
* making dbs_mapfile NULL and dbs_addr non-NULL.
|
||||
*/
|
||||
|
||||
static void
|
||||
dbs_freemap(DBS *dbsp)
|
||||
{
|
||||
if (dbsp->dbs_mapfile) {
|
||||
PR_MemUnmap(dbsp->dbs_addr,dbsp->dbs_len);
|
||||
PR_CloseFileMap(dbsp->dbs_mapfile);
|
||||
dbsp->dbs_mapfile = NULL;
|
||||
dbsp->dbs_addr = NULL;
|
||||
dbsp->dbs_len = 0;
|
||||
} else if (dbsp->dbs_addr) {
|
||||
PORT_Free(dbsp->dbs_addr);
|
||||
dbsp->dbs_addr = NULL;
|
||||
dbsp->dbs_len = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dbs_setmap(DBS *dbsp, PRFileMap *mapfile, unsigned char *addr, PRUint32 len)
|
||||
{
|
||||
dbsp->dbs_mapfile = mapfile;
|
||||
dbsp->dbs_addr = addr;
|
||||
dbsp->dbs_len = len;
|
||||
}
|
||||
|
||||
/*
|
||||
* platforms that cannot map the file need to read it into a temp buffer.
|
||||
*/
|
||||
static unsigned char *
|
||||
dbs_EmulateMap(PRFileDesc *filed, int len)
|
||||
{
|
||||
unsigned char *addr;
|
||||
PRInt32 dataRead;
|
||||
|
||||
addr = PORT_Alloc(len);
|
||||
if (addr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dataRead = PR_Read(filed,addr,len);
|
||||
if (dataRead != len) {
|
||||
PORT_Free(addr);
|
||||
if (dataRead > 0) {
|
||||
/* PR_Read didn't set an error, we need to */
|
||||
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pull a database record off the disk
|
||||
* data points to the blob record on input and the real record (if we could
|
||||
* read it) on output. if there is an error data is not modified.
|
||||
*/
|
||||
static int
|
||||
dbs_readBlob(DBS *dbsp, DBT *data)
|
||||
{
|
||||
char *file = NULL;
|
||||
PRFileDesc *filed = NULL;
|
||||
PRFileMap *mapfile = NULL;
|
||||
unsigned char *addr = NULL;
|
||||
int error;
|
||||
int len = -1;
|
||||
|
||||
file = dbs_getBlobFilePath(dbsp->blobdir, data);
|
||||
if (!file) {
|
||||
goto loser;
|
||||
}
|
||||
filed = PR_OpenFile(file,PR_RDONLY,0);
|
||||
PR_smprintf_free(file); file = NULL;
|
||||
if (filed == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
len = dbs_getBlobSize(data);
|
||||
mapfile = PR_CreateFileMap(filed, len, PR_PROT_READONLY);
|
||||
if (mapfile == NULL) {
|
||||
/* USE PR_GetError instead of PORT_GetError here
|
||||
* because we are getting the error from PR_xxx
|
||||
* function */
|
||||
if (PR_GetError() != PR_NOT_IMPLEMENTED_ERROR) {
|
||||
goto loser;
|
||||
}
|
||||
addr = dbs_EmulateMap(filed, len);
|
||||
} else {
|
||||
addr = PR_MemMap(mapfile, 0, len);
|
||||
}
|
||||
if (addr == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
PR_Close(filed);
|
||||
dbs_setmap(dbsp,mapfile,addr,len);
|
||||
|
||||
data->data = addr;
|
||||
data->size = len;
|
||||
return 0;
|
||||
|
||||
loser:
|
||||
/* preserve the error code */
|
||||
error = PR_GetError();
|
||||
if (mapfile) {
|
||||
PR_CloseFileMap(mapfile);
|
||||
}
|
||||
if (filed) {
|
||||
PR_Close(filed);
|
||||
}
|
||||
PR_SetError(error,0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* actual DBM shims
|
||||
*/
|
||||
static int
|
||||
dbs_get(const DB *dbs, const DBT *key, DBT *data, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
ret = (* db->get)(db, key, data, flags);
|
||||
if ((ret == 0) && dbs_IsBlob(data)) {
|
||||
ret = dbs_readBlob(dbsp,data);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_put(const DB *dbs, DBT *key, const DBT *data, unsigned int flags)
|
||||
{
|
||||
DBT blob;
|
||||
int ret = 0;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
/* If the db is readonly, just pass the data down to rdb and let it fail */
|
||||
if (!dbsp->readOnly) {
|
||||
DBT oldData;
|
||||
int ret1;
|
||||
|
||||
/* make sure the current record is deleted if it's a blob */
|
||||
ret1 = (*db->get)(db,key,&oldData,0);
|
||||
if ((ret1 == 0) && flags == R_NOOVERWRITE) {
|
||||
/* let DBM return the error to maintain consistancy */
|
||||
return (* db->put)(db, key, data, flags);
|
||||
}
|
||||
if ((ret1 == 0) && dbs_IsBlob(&oldData)) {
|
||||
dbs_removeBlob(dbsp, &oldData);
|
||||
}
|
||||
|
||||
if (data->size > DBS_MAX_ENTRY_SIZE) {
|
||||
dbs_mkBlob(dbsp,key,data,&blob);
|
||||
ret = dbs_writeBlob(dbsp, dbsp->mode, &blob, data);
|
||||
data = &blob;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = (* db->put)(db, key, data, flags);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_sync(const DB *dbs, unsigned int flags)
|
||||
{
|
||||
DB *db = (DB *)dbs->internal;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
return (* db->sync)(db, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_del(const DB *dbs, const DBT *key, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
if (!dbsp->readOnly) {
|
||||
DBT oldData;
|
||||
ret = (*db->get)(db,key,&oldData,0);
|
||||
if ((ret == 0) && dbs_IsBlob(&oldData)) {
|
||||
dbs_removeBlob(dbsp,&oldData);
|
||||
}
|
||||
}
|
||||
|
||||
return (* db->del)(db, key, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_seq(const DB *dbs, DBT *key, DBT *data, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
ret = (* db->seq)(db, key, data, flags);
|
||||
if ((ret == 0) && dbs_IsBlob(data)) {
|
||||
/* don't return a blob read as an error so traversals keep going */
|
||||
(void) dbs_readBlob(dbsp,data);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_close(DB *dbs)
|
||||
{
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
int ret;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
ret = (* db->close)(db);
|
||||
PORT_Free(dbsp->blobdir);
|
||||
PORT_Free(dbsp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_fd(const DB *dbs)
|
||||
{
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
return (* db->fd)(db);
|
||||
}
|
||||
|
||||
/*
|
||||
* the naming convention we use is
|
||||
* change the .xxx into .dir. (for nss it's always .db);
|
||||
* if no .extension exists or is equal to .dir, add a .dir
|
||||
* the returned data must be freed.
|
||||
*/
|
||||
#define DIRSUFFIX ".dir"
|
||||
static char *
|
||||
dbs_mkBlobDirName(const char *dbname)
|
||||
{
|
||||
int dbname_len = PORT_Strlen(dbname);
|
||||
int dbname_end = dbname_len;
|
||||
const char *cp;
|
||||
char *blobDir = NULL;
|
||||
|
||||
/* scan back from the end looking for either a directory separator, a '.',
|
||||
* or the end of the string. NOTE: Windows should check for both separators
|
||||
* here. For now this is safe because we know NSS always uses a '.'
|
||||
*/
|
||||
for (cp = &dbname[dbname_len];
|
||||
(cp > dbname) && (*cp != '.') && (*cp != *PATH_SEPARATOR) ;
|
||||
cp--)
|
||||
/* Empty */ ;
|
||||
if (*cp == '.') {
|
||||
dbname_end = cp - dbname;
|
||||
if (PORT_Strcmp(cp,DIRSUFFIX) == 0) {
|
||||
dbname_end = dbname_len;
|
||||
}
|
||||
}
|
||||
blobDir = PORT_ZAlloc(dbname_end+sizeof(DIRSUFFIX));
|
||||
if (blobDir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PORT_Memcpy(blobDir,dbname,dbname_end);
|
||||
PORT_Memcpy(&blobDir[dbname_end],DIRSUFFIX,sizeof(DIRSUFFIX));
|
||||
return blobDir;
|
||||
}
|
||||
|
||||
#define DBM_DEFAULT 0
|
||||
static const HASHINFO dbs_hashInfo = {
|
||||
DBS_BLOCK_SIZE, /* bucket size, must be greater than = to
|
||||
* or maximum entry size (+ header)
|
||||
* we allow before blobing */
|
||||
DBM_DEFAULT, /* Fill Factor */
|
||||
DBM_DEFAULT, /* number of elements */
|
||||
DBS_CACHE_SIZE, /* cache size */
|
||||
DBM_DEFAULT, /* hash function */
|
||||
DBM_DEFAULT, /* byte order */
|
||||
};
|
||||
|
||||
/*
|
||||
* the open function. NOTE: this is the only exposed function in this file.
|
||||
* everything else is called through the function table pointer.
|
||||
*/
|
||||
DB *
|
||||
dbsopen(const char *dbname, int flags, int mode, DBTYPE type,
|
||||
const void *userData)
|
||||
{
|
||||
DB *db = NULL,*dbs = NULL;
|
||||
DBS *dbsp = NULL;
|
||||
|
||||
/* NOTE: we are overriding userData with dbs_hashInfo. since all known
|
||||
* callers pass 0, this is ok, otherwise we should merge the two */
|
||||
|
||||
dbsp = (DBS *)PORT_ZAlloc(sizeof(DBS));
|
||||
if (!dbsp) {
|
||||
return NULL;
|
||||
}
|
||||
dbs = &dbsp->db;
|
||||
|
||||
dbsp->blobdir=dbs_mkBlobDirName(dbname);
|
||||
if (dbsp->blobdir == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
dbsp->mode = mode;
|
||||
dbsp->readOnly = (PRBool)(flags == NO_RDONLY);
|
||||
dbsp->dbs_mapfile = NULL;
|
||||
dbsp->dbs_addr = NULL;
|
||||
dbsp->dbs_len = 0;
|
||||
|
||||
/* the real dbm call */
|
||||
db = dbopen(dbname, flags, mode, type, &dbs_hashInfo);
|
||||
if (db == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
dbs->internal = (void *) db;
|
||||
dbs->type = type;
|
||||
dbs->close = dbs_close;
|
||||
dbs->get = dbs_get;
|
||||
dbs->del = dbs_del;
|
||||
dbs->put = dbs_put;
|
||||
dbs->seq = dbs_seq;
|
||||
dbs->sync = dbs_sync;
|
||||
dbs->fd = dbs_fd;
|
||||
|
||||
return dbs;
|
||||
loser:
|
||||
if (db) {
|
||||
(*db->close)(db);
|
||||
}
|
||||
if (dbsp) {
|
||||
if (dbsp->blobdir) {
|
||||
PORT_Free(dbsp->blobdir);
|
||||
}
|
||||
PORT_Free(dbsp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
2270
mozilla/security/nss/lib/softoken/legacydb/keydb.c
Normal file
2270
mozilla/security/nss/lib/softoken/legacydb/keydb.c
Normal file
File diff suppressed because it is too large
Load Diff
86
mozilla/security/nss/lib/softoken/legacydb/keydbi.h
Normal file
86
mozilla/security/nss/lib/softoken/legacydb/keydbi.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* private.h - Private data structures for the software token library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: keydbi.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifndef _KEYDBI_H_
|
||||
#define _KEYDBI_H_
|
||||
|
||||
#include "nspr.h"
|
||||
#include "seccomon.h"
|
||||
#include "mcom_db.h"
|
||||
|
||||
/*
|
||||
* Handle structure for open key databases
|
||||
*/
|
||||
struct NSSLOWKEYDBHandleStr {
|
||||
DB *db;
|
||||
DB *updatedb; /* used when updating an old version */
|
||||
SECItem *global_salt; /* password hashing salt for this db */
|
||||
int version; /* version of the database */
|
||||
char *appname; /* multiaccess app name */
|
||||
char *dbname; /* name of the openned DB */
|
||||
PRBool readOnly; /* is the DB read only */
|
||||
PRLock *lock;
|
||||
PRInt32 ref; /* reference count */
|
||||
};
|
||||
|
||||
/*
|
||||
** Typedef for callback for traversing key database.
|
||||
** "key" is the key used to index the data in the database (nickname)
|
||||
** "data" is the key data
|
||||
** "pdata" is the user's data
|
||||
*/
|
||||
typedef SECStatus (* NSSLOWKEYTraverseKeysFunc)(DBT *key, DBT *data, void *pdata);
|
||||
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/*
|
||||
** Traverse the entire key database, and pass the nicknames and keys to a
|
||||
** user supplied function.
|
||||
** "f" is the user function to call for each key
|
||||
** "udata" is the user's data, which is passed through to "f"
|
||||
*/
|
||||
extern SECStatus nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWKEYTraverseKeysFunc f,
|
||||
void *udata);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _KEYDBI_H_ */
|
||||
1704
mozilla/security/nss/lib/softoken/legacydb/lgattr.c
Normal file
1704
mozilla/security/nss/lib/softoken/legacydb/lgattr.c
Normal file
File diff suppressed because it is too large
Load Diff
955
mozilla/security/nss/lib/softoken/legacydb/lgcreate.c
Normal file
955
mozilla/security/nss/lib/softoken/legacydb/lgcreate.c
Normal file
@@ -0,0 +1,955 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "secitem.h"
|
||||
#include "pkcs11.h"
|
||||
#include "lgdb.h"
|
||||
#include "pcert.h"
|
||||
#include "lowkeyi.h"
|
||||
#include "blapi.h"
|
||||
#include "secder.h"
|
||||
|
||||
#include "keydbi.h"
|
||||
|
||||
/*
|
||||
* ******************** Object Creation Utilities ***************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Certificate Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createCertObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
SECItem derCert;
|
||||
NSSLOWCERTCertificate *cert;
|
||||
NSSLOWCERTCertTrust *trust = NULL;
|
||||
NSSLOWCERTCertTrust userTrust =
|
||||
{ CERTDB_USER, CERTDB_USER, CERTDB_USER };
|
||||
NSSLOWCERTCertTrust defTrust =
|
||||
{ CERTDB_TRUSTED_UNKNOWN,
|
||||
CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN };
|
||||
char *label = NULL;
|
||||
char *email = NULL;
|
||||
SECStatus rv;
|
||||
PRBool inDB = PR_TRUE;
|
||||
NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
|
||||
NSSLOWKEYDBHandle *keyHandle = NULL;
|
||||
CK_CERTIFICATE_TYPE type;
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
|
||||
/* we can't store any certs private */
|
||||
if (lg_isTrue(CKA_PRIVATE, templ, count)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
/* We only support X.509 Certs for now */
|
||||
attribute = lg_FindAttribute(CKA_CERTIFICATE_TYPE, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
type = *(CK_CERTIFICATE_TYPE *)attribute->pValue;
|
||||
|
||||
if (type != CKC_X_509) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
/* X.509 Certificate */
|
||||
|
||||
|
||||
if (certHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* get the der cert */
|
||||
attribute = lg_FindAttribute(CKA_VALUE, templ, count);
|
||||
if (!attribute) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
derCert.type = 0;
|
||||
derCert.data = (unsigned char *)attribute->pValue;
|
||||
derCert.len = attribute->ulValueLen ;
|
||||
|
||||
label = lg_getString(CKA_LABEL, templ, count);
|
||||
|
||||
cert = nsslowcert_FindCertByDERCert(certHandle, &derCert);
|
||||
if (cert == NULL) {
|
||||
cert = nsslowcert_DecodeDERCertificate(&derCert, label);
|
||||
inDB = PR_FALSE;
|
||||
}
|
||||
if (cert == NULL) {
|
||||
if (label) PORT_Free(label);
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
if (keyHandle) {
|
||||
if (nsslowkey_KeyForCertExists(keyHandle,cert)) {
|
||||
trust = &userTrust;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inDB) {
|
||||
if (!trust) trust = &defTrust;
|
||||
rv = nsslowcert_AddPermCert(certHandle, cert, label, trust);
|
||||
} else {
|
||||
rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) :
|
||||
SECSuccess;
|
||||
}
|
||||
|
||||
if (label) PORT_Free(label);
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a NULL S/MIME profile if necessary.
|
||||
*/
|
||||
email = lg_getString(CKA_NETSCAPE_EMAIL, templ, count);
|
||||
if (email) {
|
||||
certDBEntrySMime *entry;
|
||||
|
||||
entry = nsslowcert_ReadDBSMimeEntry(certHandle,email);
|
||||
if (!entry) {
|
||||
nsslowcert_SaveSMimeProfile(certHandle, email,
|
||||
&cert->derSubject, NULL, NULL);
|
||||
} else {
|
||||
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
|
||||
}
|
||||
PORT_Free(email);
|
||||
}
|
||||
*handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT);
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
lg_MapTrust(CK_TRUST trust, PRBool clientAuth)
|
||||
{
|
||||
unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA :
|
||||
CERTDB_TRUSTED_CA;
|
||||
switch (trust) {
|
||||
case CKT_NETSCAPE_TRUSTED:
|
||||
return CERTDB_VALID_PEER|CERTDB_TRUSTED;
|
||||
case CKT_NETSCAPE_TRUSTED_DELEGATOR:
|
||||
return CERTDB_VALID_CA|trustCA;
|
||||
case CKT_NETSCAPE_UNTRUSTED:
|
||||
return CERTDB_NOT_TRUSTED;
|
||||
case CKT_NETSCAPE_MUST_VERIFY:
|
||||
return 0;
|
||||
case CKT_NETSCAPE_VALID: /* implies must verify */
|
||||
return CERTDB_VALID_PEER;
|
||||
case CKT_NETSCAPE_VALID_DELEGATOR: /* implies must verify */
|
||||
return CERTDB_VALID_CA;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CERTDB_TRUSTED_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Trust Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createTrustObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
const CK_ATTRIBUTE *issuer = NULL;
|
||||
const CK_ATTRIBUTE *serial = NULL;
|
||||
NSSLOWCERTCertificate *cert = NULL;
|
||||
const CK_ATTRIBUTE *trust;
|
||||
CK_TRUST sslTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
|
||||
CK_TRUST clientTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
|
||||
CK_TRUST emailTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
|
||||
CK_TRUST signTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
|
||||
CK_BBOOL stepUp;
|
||||
NSSLOWCERTCertTrust dbTrust = { 0 };
|
||||
SECStatus rv;
|
||||
NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
|
||||
NSSLOWCERTIssuerAndSN issuerSN;
|
||||
|
||||
/* we can't store any certs private */
|
||||
if (lg_isTrue(CKA_PRIVATE, templ, count)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
if (certHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
issuer = lg_FindAttribute(CKA_ISSUER, templ, count);
|
||||
serial = lg_FindAttribute(CKA_SERIAL_NUMBER, templ, count);
|
||||
|
||||
if (issuer && serial) {
|
||||
issuerSN.derIssuer.data = (unsigned char *)issuer->pValue;
|
||||
issuerSN.derIssuer.len = issuer->ulValueLen ;
|
||||
|
||||
issuerSN.serialNumber.data = (unsigned char *)serial->pValue;
|
||||
issuerSN.serialNumber.len = serial->ulValueLen ;
|
||||
|
||||
cert = nsslowcert_FindCertByIssuerAndSN(certHandle,&issuerSN);
|
||||
}
|
||||
|
||||
if (cert == NULL) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
lg_GetULongAttribute(CKA_TRUST_SERVER_AUTH, templ, count, &sslTrust);
|
||||
lg_GetULongAttribute(CKA_TRUST_CLIENT_AUTH, templ, count, &clientTrust);
|
||||
lg_GetULongAttribute(CKA_TRUST_EMAIL_PROTECTION, templ, count, &emailTrust);
|
||||
lg_GetULongAttribute(CKA_TRUST_CODE_SIGNING, templ, count, &signTrust);
|
||||
stepUp = CK_FALSE;
|
||||
trust = lg_FindAttribute(CKA_TRUST_STEP_UP_APPROVED, templ, count);
|
||||
if (trust) {
|
||||
if (trust->ulValueLen == sizeof(CK_BBOOL)) {
|
||||
stepUp = *(CK_BBOOL*)trust->pValue;
|
||||
}
|
||||
}
|
||||
|
||||
/* preserve certain old fields */
|
||||
if (cert->trust) {
|
||||
dbTrust.sslFlags = cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS;
|
||||
dbTrust.emailFlags=
|
||||
cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS;
|
||||
dbTrust.objectSigningFlags =
|
||||
cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS;
|
||||
}
|
||||
|
||||
dbTrust.sslFlags |= lg_MapTrust(sslTrust,PR_FALSE);
|
||||
dbTrust.sslFlags |= lg_MapTrust(clientTrust,PR_TRUE);
|
||||
dbTrust.emailFlags |= lg_MapTrust(emailTrust,PR_FALSE);
|
||||
dbTrust.objectSigningFlags |= lg_MapTrust(signTrust,PR_FALSE);
|
||||
if (stepUp) {
|
||||
dbTrust.sslFlags |= CERTDB_GOVT_APPROVED_CA;
|
||||
}
|
||||
|
||||
rv = nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust);
|
||||
*handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST);
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
if (rv != SECSuccess) {
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Trust Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createSMimeObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
SECItem derSubj,rawProfile,rawTime,emailKey;
|
||||
SECItem *pRawProfile = NULL;
|
||||
SECItem *pRawTime = NULL;
|
||||
char *email = NULL;
|
||||
const CK_ATTRIBUTE *subject = NULL,
|
||||
*profile = NULL,
|
||||
*time = NULL;
|
||||
SECStatus rv;
|
||||
NSSLOWCERTCertDBHandle *certHandle;
|
||||
CK_RV ck_rv = CKR_OK;
|
||||
|
||||
/* we can't store any certs private */
|
||||
if (lg_isTrue(CKA_PRIVATE,templ,count)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (certHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* lookup SUBJECT */
|
||||
subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
|
||||
PORT_Assert(subject);
|
||||
if (!subject) {
|
||||
ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
derSubj.data = (unsigned char *)subject->pValue;
|
||||
derSubj.len = subject->ulValueLen ;
|
||||
derSubj.type = 0;
|
||||
|
||||
/* lookup VALUE */
|
||||
profile = lg_FindAttribute(CKA_VALUE,templ,count);
|
||||
if (profile) {
|
||||
rawProfile.data = (unsigned char *)profile->pValue;
|
||||
rawProfile.len = profile->ulValueLen ;
|
||||
rawProfile.type = siBuffer;
|
||||
pRawProfile = &rawProfile;
|
||||
}
|
||||
|
||||
/* lookup Time */
|
||||
time = lg_FindAttribute(CKA_NETSCAPE_SMIME_TIMESTAMP,templ,count);
|
||||
if (time) {
|
||||
rawTime.data = (unsigned char *)time->pValue;
|
||||
rawTime.len = time->ulValueLen ;
|
||||
rawTime.type = siBuffer;
|
||||
pRawTime = &rawTime;
|
||||
}
|
||||
|
||||
|
||||
email = lg_getString(CKA_NETSCAPE_EMAIL,templ,count);
|
||||
if (!email) {
|
||||
ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Store S/MIME Profile by SUBJECT */
|
||||
rv = nsslowcert_SaveSMimeProfile(certHandle, email, &derSubj,
|
||||
pRawProfile,pRawTime);
|
||||
if (rv != SECSuccess) {
|
||||
ck_rv = CKR_DEVICE_ERROR;
|
||||
goto loser;
|
||||
}
|
||||
emailKey.data = (unsigned char *)email;
|
||||
emailKey.len = PORT_Strlen(email)+1;
|
||||
|
||||
*handle = lg_mkHandle(sdb, &emailKey, LG_TOKEN_TYPE_SMIME);
|
||||
|
||||
loser:
|
||||
if (email) PORT_Free(email);
|
||||
|
||||
return ck_rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Trust Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createCrlObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
PRBool isKRL = PR_FALSE;
|
||||
SECItem derSubj,derCrl;
|
||||
char *url = NULL;
|
||||
const CK_ATTRIBUTE *subject,*crl;
|
||||
SECStatus rv;
|
||||
NSSLOWCERTCertDBHandle *certHandle;
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
|
||||
/* we can't store any private crls */
|
||||
if (lg_isTrue(CKA_PRIVATE,templ,count)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
if (certHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* lookup SUBJECT */
|
||||
subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
|
||||
if (!subject) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
derSubj.data = (unsigned char *)subject->pValue;
|
||||
derSubj.len = subject->ulValueLen ;
|
||||
|
||||
/* lookup VALUE */
|
||||
crl = lg_FindAttribute(CKA_VALUE,templ,count);
|
||||
PORT_Assert(crl);
|
||||
if (!crl) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
derCrl.data = (unsigned char *)crl->pValue;
|
||||
derCrl.len = crl->ulValueLen ;
|
||||
|
||||
url = lg_getString(CKA_NETSCAPE_URL,templ,count);
|
||||
isKRL = lg_isTrue(CKA_NETSCAPE_KRL,templ,count);
|
||||
|
||||
/* Store CRL by SUBJECT */
|
||||
rv = nsslowcert_AddCrl(certHandle, &derCrl, &derSubj, url, isKRL);
|
||||
|
||||
if (url) {
|
||||
PORT_Free(url);
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/* if we overwrote the existing CRL, poison the handle entry so we get
|
||||
* a new object handle */
|
||||
(void) lg_poisonHandle(sdb, &derSubj,
|
||||
isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
|
||||
*handle = lg_mkHandle(sdb, &derSubj,
|
||||
isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Public Key Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
|
||||
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE;
|
||||
CK_RV crv;
|
||||
NSSLOWKEYPrivateKey *priv;
|
||||
SECItem pubKey;
|
||||
NSSLOWKEYDBHandle *keyHandle = NULL;
|
||||
|
||||
switch (key_type) {
|
||||
case CKK_RSA:
|
||||
pubKeyAttr = CKA_MODULUS;
|
||||
break;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case CKK_EC:
|
||||
pubKeyAttr = CKA_EC_POINT;
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
case CKK_DSA:
|
||||
case CKK_DH:
|
||||
break;
|
||||
default:
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
|
||||
crv = lg_Attribute2SSecItem(NULL,pubKeyAttr,templ,count,&pubKey);
|
||||
if (crv != CKR_OK) return crv;
|
||||
|
||||
PORT_Assert(pubKey.data);
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
if (keyHandle == NULL) {
|
||||
PORT_Free(pubKey.data);
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
if (keyHandle->version != 3) {
|
||||
unsigned char buf[SHA1_LENGTH];
|
||||
SHA1_HashBuf(buf,pubKey.data,pubKey.len);
|
||||
PORT_Memcpy(pubKey.data,buf,sizeof(buf));
|
||||
pubKey.len = sizeof(buf);
|
||||
}
|
||||
/* make sure the associated private key already exists */
|
||||
/* only works if we are logged in */
|
||||
priv = nsslowkey_FindKeyByPublicKey(keyHandle, &pubKey, sdb /*password*/);
|
||||
if (priv == NULL) {
|
||||
PORT_Free(pubKey.data);
|
||||
return crv;
|
||||
}
|
||||
nsslowkey_DestroyPrivateKey(priv);
|
||||
|
||||
*handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_PUB);
|
||||
PORT_Free(pubKey.data);
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/* make a private key from a verified object */
|
||||
static NSSLOWKEYPrivateKey *
|
||||
lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
CK_KEY_TYPE key_type, CK_RV *crvp)
|
||||
{
|
||||
NSSLOWKEYPrivateKey *privKey;
|
||||
PLArenaPool *arena;
|
||||
CK_RV crv = CKR_OK;
|
||||
SECStatus rv;
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
*crvp = CKR_HOST_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
privKey = (NSSLOWKEYPrivateKey *)
|
||||
PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
|
||||
if (privKey == NULL) {
|
||||
PORT_FreeArena(arena,PR_FALSE);
|
||||
*crvp = CKR_HOST_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* in future this would be a switch on key_type */
|
||||
privKey->arena = arena;
|
||||
switch (key_type) {
|
||||
case CKK_RSA:
|
||||
privKey->keyType = NSSLOWKEYRSAKey;
|
||||
crv=lg_Attribute2SSecItem(arena,CKA_MODULUS,templ,count,
|
||||
&privKey->u.rsa.modulus);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_Attribute2SSecItem(arena,CKA_PUBLIC_EXPONENT,templ,count,
|
||||
&privKey->u.rsa.publicExponent);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_PRIVATE_EXPONENT,templ,count,
|
||||
&privKey->u.rsa.privateExponent, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_1,templ,count,
|
||||
&privKey->u.rsa.prime1, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_2,templ,count,
|
||||
&privKey->u.rsa.prime2, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_1,templ,count,
|
||||
&privKey->u.rsa.exponent1, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_2,templ,count,
|
||||
&privKey->u.rsa.exponent2, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_COEFFICIENT,templ,count,
|
||||
&privKey->u.rsa.coefficient, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
|
||||
NSSLOWKEY_VERSION);
|
||||
if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
|
||||
break;
|
||||
|
||||
case CKK_DSA:
|
||||
privKey->keyType = NSSLOWKEYDSAKey;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
|
||||
&privKey->u.dsa.params.prime);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_SUBPRIME,templ,count,
|
||||
&privKey->u.dsa.params.subPrime);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
|
||||
&privKey->u.dsa.params.base);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
|
||||
&privKey->u.dsa.privateValue, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
if (lg_hasAttribute(CKA_NETSCAPE_DB, templ,count)) {
|
||||
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
|
||||
&privKey->u.dsa.publicValue);
|
||||
/* privKey was zero'd so public value is already set to NULL, 0
|
||||
* if we don't set it explicitly */
|
||||
}
|
||||
break;
|
||||
|
||||
case CKK_DH:
|
||||
privKey->keyType = NSSLOWKEYDHKey;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
|
||||
&privKey->u.dh.prime);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
|
||||
&privKey->u.dh.base);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
|
||||
&privKey->u.dh.privateValue, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
|
||||
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
|
||||
&privKey->u.dh.publicValue);
|
||||
/* privKey was zero'd so public value is already set to NULL, 0
|
||||
* if we don't set it explicitly */
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case CKK_EC:
|
||||
privKey->keyType = NSSLOWKEYECKey;
|
||||
crv = lg_Attribute2SSecItem(arena, CKA_EC_PARAMS,templ,count,
|
||||
&privKey->u.ec.ecParams.DEREncoding);
|
||||
if (crv != CKR_OK) break;
|
||||
|
||||
/* Fill out the rest of the ecParams structure
|
||||
* based on the encoded params
|
||||
*/
|
||||
if (LGEC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding,
|
||||
&privKey->u.ec.ecParams) != SECSuccess) {
|
||||
crv = CKR_DOMAIN_PARAMS_INVALID;
|
||||
break;
|
||||
}
|
||||
crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
|
||||
&privKey->u.ec.privateValue, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
if (lg_hasAttribute(CKA_NETSCAPE_DB,templ,count)) {
|
||||
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
|
||||
&privKey->u.ec.publicValue);
|
||||
if (crv != CKR_OK) break;
|
||||
/* privKey was zero'd so public value is already set to NULL, 0
|
||||
* if we don't set it explicitly */
|
||||
}
|
||||
rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version,
|
||||
NSSLOWKEY_EC_PRIVATE_KEY_VERSION);
|
||||
if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
default:
|
||||
crv = CKR_KEY_TYPE_INCONSISTENT;
|
||||
break;
|
||||
}
|
||||
*crvp = crv;
|
||||
if (crv != CKR_OK) {
|
||||
PORT_FreeArena(arena,PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
return privKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Private Key Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createPrivateKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
|
||||
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
NSSLOWKEYPrivateKey *privKey;
|
||||
char *label;
|
||||
SECStatus rv = SECSuccess;
|
||||
CK_RV crv = CKR_DEVICE_ERROR;
|
||||
SECItem pubKey;
|
||||
NSSLOWKEYDBHandle *keyHandle = lg_getKeyDB(sdb);
|
||||
|
||||
if (keyHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
privKey=lg_mkPrivKey(sdb, templ,count,key_type,&crv);
|
||||
if (privKey == NULL) return crv;
|
||||
label = lg_getString(CKA_LABEL,templ,count);
|
||||
|
||||
crv = lg_Attribute2SSecItem(NULL,CKA_NETSCAPE_DB,templ,count,&pubKey);
|
||||
if (crv != CKR_OK) {
|
||||
crv = CKR_TEMPLATE_INCOMPLETE;
|
||||
rv = SECFailure;
|
||||
goto fail;
|
||||
}
|
||||
#ifdef notdef
|
||||
if (keyHandle->version != 3) {
|
||||
unsigned char buf[SHA1_LENGTH];
|
||||
SHA1_HashBuf(buf,pubKey.data,pubKey.len);
|
||||
PORT_Memcpy(pubKey.data,buf,sizeof(buf));
|
||||
pubKey.len = sizeof(buf);
|
||||
}
|
||||
#endif
|
||||
/* get the key type */
|
||||
if (key_type == CKK_RSA) {
|
||||
rv = RSA_PrivateKeyCheck(&privKey->u.rsa);
|
||||
if (rv == SECFailure) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey,
|
||||
label, sdb /*->password*/);
|
||||
|
||||
fail:
|
||||
if (label) PORT_Free(label);
|
||||
*handle = lg_mkHandle(sdb,&pubKey,LG_TOKEN_TYPE_PRIV);
|
||||
if (pubKey.data) PORT_Free(pubKey.data);
|
||||
nsslowkey_DestroyPrivateKey(privKey);
|
||||
if (rv != SECSuccess) return crv;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
#define LG_KEY_MAX_RETRIES 10 /* don't hang if we are having problems with the rng */
|
||||
#define LG_KEY_ID_SIZE 18 /* don't use either SHA1 or MD5 sizes */
|
||||
/*
|
||||
* Secret keys must have a CKA_ID value to be stored in the database. This code
|
||||
* will generate one if there wasn't one already.
|
||||
*/
|
||||
static CK_RV
|
||||
lg_GenerateSecretCKA_ID(NSSLOWKEYDBHandle *handle, SECItem *id, char *label)
|
||||
{
|
||||
unsigned int retries;
|
||||
SECStatus rv = SECSuccess;
|
||||
CK_RV crv = CKR_OK;
|
||||
|
||||
id->data = NULL;
|
||||
if (label) {
|
||||
id->data = (unsigned char *)PORT_Strdup(label);
|
||||
if (id->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
id->len = PORT_Strlen(label)+1;
|
||||
if (!nsslowkey_KeyForIDExists(handle,id)) {
|
||||
return CKR_OK;
|
||||
}
|
||||
PORT_Free(id->data);
|
||||
id->data = NULL;
|
||||
id->len = 0;
|
||||
}
|
||||
id->data = (unsigned char *)PORT_Alloc(LG_KEY_ID_SIZE);
|
||||
if (id->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
id->len = LG_KEY_ID_SIZE;
|
||||
|
||||
retries = 0;
|
||||
do {
|
||||
rv = RNG_GenerateGlobalRandomBytes(id->data,id->len);
|
||||
} while (rv == SECSuccess && nsslowkey_KeyForIDExists(handle,id) &&
|
||||
(++retries <= LG_KEY_MAX_RETRIES));
|
||||
|
||||
if ((rv != SECSuccess) || (retries > LG_KEY_MAX_RETRIES)) {
|
||||
crv = CKR_DEVICE_ERROR; /* random number generator is bad */
|
||||
PORT_Free(id->data);
|
||||
id->data = NULL;
|
||||
id->len = 0;
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
|
||||
static NSSLOWKEYPrivateKey *lg_mkSecretKeyRep(const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count, CK_KEY_TYPE key_type,
|
||||
SECItem *pubkey, SDB *sdbpw)
|
||||
{
|
||||
NSSLOWKEYPrivateKey *privKey = 0;
|
||||
PLArenaPool *arena = 0;
|
||||
CK_KEY_TYPE keyType;
|
||||
PRUint32 keyTypeStorage;
|
||||
SECItem keyTypeItem;
|
||||
CK_RV crv;
|
||||
SECStatus rv;
|
||||
static unsigned char derZero[1] = { 0 };
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
|
||||
|
||||
privKey = (NSSLOWKEYPrivateKey *)
|
||||
PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
|
||||
if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
|
||||
|
||||
privKey->arena = arena;
|
||||
|
||||
/* Secret keys are represented in the database as "fake" RSA keys.
|
||||
* The RSA key is marked as a secret key representation by setting the
|
||||
* public exponent field to 0, which is an invalid RSA exponent.
|
||||
* The other fields are set as follows:
|
||||
* modulus - CKA_ID value for the secret key
|
||||
* private exponent - CKA_VALUE (the key itself)
|
||||
* coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm
|
||||
* is used for the key.
|
||||
* all others - set to integer 0
|
||||
*/
|
||||
privKey->keyType = NSSLOWKEYRSAKey;
|
||||
|
||||
/* The modulus is set to the key id of the symmetric key */
|
||||
crv = lg_Attribute2SecItem(arena, CKA_ID, templ, count,
|
||||
&privKey->u.rsa.modulus);
|
||||
if (crv != CKR_OK) goto loser;
|
||||
|
||||
/* The public exponent is set to 0 length to indicate a special key */
|
||||
privKey->u.rsa.publicExponent.len = sizeof derZero;
|
||||
privKey->u.rsa.publicExponent.data = derZero;
|
||||
|
||||
/* The private exponent is the actual key value */
|
||||
crv = lg_PrivAttr2SecItem(arena, CKA_VALUE, templ, count,
|
||||
&privKey->u.rsa.privateExponent, sdbpw);
|
||||
if (crv != CKR_OK) goto loser;
|
||||
|
||||
/* All other fields empty - needs testing */
|
||||
privKey->u.rsa.prime1.len = sizeof derZero;
|
||||
privKey->u.rsa.prime1.data = derZero;
|
||||
|
||||
privKey->u.rsa.prime2.len = sizeof derZero;
|
||||
privKey->u.rsa.prime2.data = derZero;
|
||||
|
||||
privKey->u.rsa.exponent1.len = sizeof derZero;
|
||||
privKey->u.rsa.exponent1.data = derZero;
|
||||
|
||||
privKey->u.rsa.exponent2.len = sizeof derZero;
|
||||
privKey->u.rsa.exponent2.data = derZero;
|
||||
|
||||
/* Coeficient set to KEY_TYPE */
|
||||
crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &keyType);
|
||||
if (crv != CKR_OK) goto loser;
|
||||
/* on 64 bit platforms, we still want to store 32 bits of keyType (This is
|
||||
* safe since the PKCS #11 defines for all types are 32 bits or less). */
|
||||
keyTypeStorage = (PRUint32) keyType;
|
||||
keyTypeStorage = PR_htonl(keyTypeStorage);
|
||||
keyTypeItem.data = (unsigned char *)&keyTypeStorage;
|
||||
keyTypeItem.len = sizeof (keyTypeStorage);
|
||||
rv = SECITEM_CopyItem(arena, &privKey->u.rsa.coefficient, &keyTypeItem);
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Private key version field set normally for compatibility */
|
||||
rv = DER_SetUInteger(privKey->arena,
|
||||
&privKey->u.rsa.version, NSSLOWKEY_VERSION);
|
||||
if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; }
|
||||
|
||||
loser:
|
||||
if (crv != CKR_OK) {
|
||||
PORT_FreeArena(arena,PR_FALSE);
|
||||
privKey = 0;
|
||||
}
|
||||
|
||||
return privKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Secret Key Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createSecretKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
|
||||
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
CK_RV crv;
|
||||
NSSLOWKEYPrivateKey *privKey = NULL;
|
||||
NSSLOWKEYDBHandle *keyHandle = NULL;
|
||||
SECItem pubKey;
|
||||
char *label = NULL;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
pubKey.data = 0;
|
||||
|
||||
/* If the object is a TOKEN object, store in the database */
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
|
||||
if (keyHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
label = lg_getString(CKA_LABEL,templ,count);
|
||||
|
||||
crv = lg_Attribute2SecItem(NULL,CKA_ID,templ,count,&pubKey);
|
||||
/* Should this be ID? */
|
||||
if (crv != CKR_OK) goto loser;
|
||||
|
||||
/* if we don't have an ID, generate one */
|
||||
if (pubKey.len == 0) {
|
||||
if (pubKey.data) {
|
||||
PORT_Free(pubKey.data);
|
||||
pubKey.data = NULL;
|
||||
}
|
||||
crv = lg_GenerateSecretCKA_ID(keyHandle, &pubKey, label);
|
||||
if (crv != CKR_OK) goto loser;
|
||||
}
|
||||
|
||||
privKey = lg_mkSecretKeyRep(templ, count, key_type, &pubKey, sdb);
|
||||
if (privKey == NULL) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv = nsslowkey_StoreKeyByPublicKey(keyHandle,
|
||||
privKey, &pubKey, label, sdb /*->password*/);
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
*handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_KEY);
|
||||
|
||||
loser:
|
||||
if (label) PORT_Free(label);
|
||||
if (privKey) nsslowkey_DestroyPrivateKey(privKey);
|
||||
if (pubKey.data) PORT_Free(pubKey.data);
|
||||
|
||||
return crv;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Key Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createKeyObject(SDB *sdb, CK_OBJECT_CLASS objclass,
|
||||
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
CK_RV crv;
|
||||
CK_KEY_TYPE key_type;
|
||||
|
||||
/* get the key type */
|
||||
crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &key_type);
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
|
||||
switch (objclass) {
|
||||
case CKO_PUBLIC_KEY:
|
||||
return lg_createPublicKeyObject(sdb,key_type,handle,templ,count);
|
||||
case CKO_PRIVATE_KEY:
|
||||
return lg_createPrivateKeyObject(sdb,key_type,handle,templ,count);
|
||||
case CKO_SECRET_KEY:
|
||||
return lg_createSecretKeyObject(sdb,key_type,handle,templ,count);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the template and create an object stored in the DB that reflects.
|
||||
* the object specified in the database.
|
||||
*/
|
||||
CK_RV
|
||||
lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
CK_RV crv;
|
||||
CK_OBJECT_CLASS objclass;
|
||||
|
||||
/* get the object class */
|
||||
crv = lg_GetULongAttribute(CKA_CLASS, templ, count, &objclass);
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
|
||||
/* Now handle the specific object class.
|
||||
*/
|
||||
switch (objclass) {
|
||||
case CKO_CERTIFICATE:
|
||||
crv = lg_createCertObject(sdb,handle,templ,count);
|
||||
break;
|
||||
case CKO_NETSCAPE_TRUST:
|
||||
crv = lg_createTrustObject(sdb,handle,templ,count);
|
||||
break;
|
||||
case CKO_NETSCAPE_CRL:
|
||||
crv = lg_createCrlObject(sdb,handle,templ,count);
|
||||
break;
|
||||
case CKO_NETSCAPE_SMIME:
|
||||
crv = lg_createSMimeObject(sdb,handle,templ,count);
|
||||
break;
|
||||
case CKO_PRIVATE_KEY:
|
||||
case CKO_PUBLIC_KEY:
|
||||
case CKO_SECRET_KEY:
|
||||
crv = lg_createKeyObject(sdb,objclass,handle,templ,count);
|
||||
break;
|
||||
default:
|
||||
crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
return crv;
|
||||
}
|
||||
|
||||
197
mozilla/security/nss/lib/softoken/legacydb/lgdb.h
Normal file
197
mozilla/security/nss/lib/softoken/legacydb/lgdb.h
Normal file
@@ -0,0 +1,197 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* Internal data structures and functions used by pkcs11.c
|
||||
*/
|
||||
#ifndef _LGDB_H_
|
||||
#define _LGDB_H_ 1
|
||||
|
||||
#include "nssilock.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "lowkeyti.h"
|
||||
#include "pkcs11t.h"
|
||||
#include "sdb.h"
|
||||
#include "cdbhdl.h"
|
||||
|
||||
|
||||
#define MULTIACCESS "multiaccess:"
|
||||
|
||||
|
||||
/* machine dependent path stuff used by dbinit.c and pk11db.c */
|
||||
#ifdef macintosh
|
||||
#define PATH_SEPARATOR ":"
|
||||
#define SECMOD_DB "Security Modules"
|
||||
#define CERT_DB_FMT "%sCertificates%s"
|
||||
#define KEY_DB_FMT "%sKey Database%s"
|
||||
#else
|
||||
#define PATH_SEPARATOR "/"
|
||||
#define SECMOD_DB "secmod.db"
|
||||
#define CERT_DB_FMT "%scert%s.db"
|
||||
#define KEY_DB_FMT "%skey%s.db"
|
||||
#endif
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
|
||||
/* internal utility functions used by pkcs11.c */
|
||||
extern const CK_ATTRIBUTE *lg_FindAttribute(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
extern CK_RV lg_Attribute2SecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item);
|
||||
extern CK_RV lg_Attribute2SSecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item);
|
||||
extern CK_RV lg_PrivAttr2SecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw);
|
||||
extern CK_RV lg_PrivAttr2SSecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw);
|
||||
extern CK_RV lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
CK_ULONG *out);
|
||||
extern PRBool lg_hasAttribute(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
extern PRBool lg_isTrue(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
extern PRBool lg_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass);
|
||||
extern char *lg_getString(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
extern unsigned int lg_MapTrust(CK_TRUST trust, PRBool clientAuth);
|
||||
|
||||
/* clear out all the existing object ID to database key mappings.
|
||||
* used to reinit a token */
|
||||
extern CK_RV SFTK_ClearTokenKeyHashTable(SDB *sdb);
|
||||
|
||||
|
||||
extern void lg_FreeSearch(SDBFind *search);
|
||||
|
||||
NSSLOWCERTCertDBHandle *lg_getCertDB(SDB *sdb);
|
||||
NSSLOWKEYDBHandle *lg_getKeyDB(SDB *sdb);
|
||||
|
||||
const char *lg_EvaluateConfigDir(const char *configdir, char **domain);
|
||||
|
||||
|
||||
/*
|
||||
* object handle modifiers
|
||||
*/
|
||||
#define LG_TOKEN_MASK 0xc0000000L
|
||||
#define LG_TOKEN_TYPE_MASK 0x38000000L
|
||||
#define LG_TOKEN_TYPE_SHIFT 27
|
||||
/* keydb (high bit == 0) */
|
||||
#define LG_TOKEN_TYPE_PRIV 0x08000000L
|
||||
#define LG_TOKEN_TYPE_PUB 0x10000000L
|
||||
#define LG_TOKEN_TYPE_KEY 0x18000000L
|
||||
/* certdb (high bit == 1) */
|
||||
#define LG_TOKEN_TYPE_TRUST 0x20000000L
|
||||
#define LG_TOKEN_TYPE_CRL 0x28000000L
|
||||
#define LG_TOKEN_TYPE_SMIME 0x30000000L
|
||||
#define LG_TOKEN_TYPE_CERT 0x38000000L
|
||||
|
||||
#define LG_TOKEN_KRL_HANDLE (LG_TOKEN_TYPE_CRL|1)
|
||||
|
||||
#define LG_SEARCH_BLOCK_SIZE 10
|
||||
#define LG_BUF_SPACE 50
|
||||
#define LG_STRICT PR_FALSE
|
||||
|
||||
/*
|
||||
* token object utilities
|
||||
*/
|
||||
void lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle);
|
||||
PRBool lg_poisonHandle(SDB *sdb, SECItem *dbkey, CK_OBJECT_HANDLE handle);
|
||||
PRBool lg_tokenMatch(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE class,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
const SECItem *lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle);
|
||||
CK_OBJECT_HANDLE lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class);
|
||||
SECStatus lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle);
|
||||
|
||||
SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdbpw,
|
||||
SECItem *plainText, SECItem **cipherText);
|
||||
SECStatus lg_util_decrypt(SDB *sdbpw,
|
||||
SECItem *cipherText, SECItem **plainText);
|
||||
PLHashTable *lg_GetHashTable(SDB *sdb);
|
||||
void lg_DBLock(SDB *sdb);
|
||||
void lg_DBUnlock(SDB *sdb);
|
||||
|
||||
typedef void (*LGFreeFunc)(void *);
|
||||
|
||||
|
||||
/*
|
||||
* database functions
|
||||
*/
|
||||
|
||||
/* lg_FindObjectsInit initializes a search for token and session objects
|
||||
* that match a template. */
|
||||
CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
|
||||
CK_ULONG ulCount, SDBFind **search);
|
||||
/* lg_FindObjects continues a search for token and session objects
|
||||
* that match a template, obtaining additional object handles. */
|
||||
CK_RV lg_FindObjects(SDB *sdb, SDBFind *search,
|
||||
CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
|
||||
CK_ULONG *pulObjectCount);
|
||||
|
||||
/* lg_FindObjectsFinal finishes a search for token and session objects. */
|
||||
CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search);
|
||||
|
||||
/* lg_CreateObject parses the template and create an object stored in the
|
||||
* DB that reflects the object specified in the template. */
|
||||
CK_RV lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
|
||||
CK_RV lg_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
CK_ATTRIBUTE *template, CK_ULONG count);
|
||||
CK_RV lg_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
const CK_ATTRIBUTE *template, CK_ULONG count);
|
||||
CK_RV lg_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id);
|
||||
|
||||
CK_RV lg_Close(SDB *sdb);
|
||||
CK_RV lg_Reset(SDB *sdb);
|
||||
|
||||
/*
|
||||
* The old database doesn't share and doesn't support
|
||||
* transactions.
|
||||
*/
|
||||
CK_RV lg_Begin(SDB *sdb);
|
||||
CK_RV lg_Commit(SDB *sdb);
|
||||
CK_RV lg_Abort(SDB *sdb);
|
||||
CK_RV lg_GetPWEntry(SDB *sdb, SDBPasswordEntry *entry);
|
||||
CK_RV lg_PutPWEntry(SDB *sdb, SDBPasswordEntry *entry);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _LGDB_H_ */
|
||||
64
mozilla/security/nss/lib/softoken/legacydb/lgdbm.def
Normal file
64
mozilla/security/nss/lib/softoken/legacydb/lgdbm.def
Normal file
@@ -0,0 +1,64 @@
|
||||
;+#
|
||||
;+# ***** BEGIN LICENSE BLOCK *****
|
||||
;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;+#
|
||||
;+# The contents of this file are subject to the Mozilla Public License Version
|
||||
;+# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
;+# the License. You may obtain a copy of the License at
|
||||
;+# http://www.mozilla.org/MPL/
|
||||
;+#
|
||||
;+# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
;+# for the specific language governing rights and limitations under the
|
||||
;+# License.
|
||||
;+#
|
||||
;+# The Original Code is the Netscape security libraries.
|
||||
;+#
|
||||
;+# The Initial Developer of the Original Code is
|
||||
;+# Netscape Communications Corporation.
|
||||
;+# Portions created by the Initial Developer are Copyright (C) 2000
|
||||
;+# the Initial Developer. All Rights Reserved.
|
||||
;+#
|
||||
;+# Contributor(s):
|
||||
;+# Dr Stephen Henson <stephen.henson@gemplus.com>
|
||||
;+#
|
||||
;+# Alternatively, the contents of this file may be used under the terms of
|
||||
;+# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
;+# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
;+# of those above. If you wish to allow use of your version of this file only
|
||||
;+# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
;+# use your version of this file under the terms of the MPL, indicate your
|
||||
;+# decision by deleting the provisions above and replace them with the notice
|
||||
;+# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
;+# the provisions above, a recipient may use your version of this file under
|
||||
;+# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;+#
|
||||
;+# ***** END LICENSE BLOCK *****
|
||||
;+#
|
||||
;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
|
||||
;+# 1. For all unix platforms, the string ";-" means "remove this line"
|
||||
;+# 2. For all unix platforms, the string " DATA " will be removed from any
|
||||
;+# line on which it occurs.
|
||||
;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
|
||||
;+# On AIX, lines containing ";+" will be removed.
|
||||
;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
|
||||
;+# 5. For all unix platforms, after the above processing has taken place,
|
||||
;+# all characters after the first ";" on the line will be removed.
|
||||
;+# And for AIX, the first ";" will also be removed.
|
||||
;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
|
||||
;+# directives are hidden behind ";", ";+", and ";-"
|
||||
;+LGDBM_3.12 { # NSS 3.12 release
|
||||
;+ global:
|
||||
LIBRARY lgdbm3 ;-
|
||||
EXPORTS ;-
|
||||
legacy_Open;
|
||||
legacy_Shutdown;
|
||||
legacy_ReadSecmodDB;
|
||||
legacy_ReleaseSecmodDBData;
|
||||
legacy_AddSecmodDB;
|
||||
legacy_DeleteSecmodDB;
|
||||
legacy_SetCryptFunctions;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
144
mozilla/security/nss/lib/softoken/legacydb/lgdestroy.c
Normal file
144
mozilla/security/nss/lib/softoken/legacydb/lgdestroy.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* Internal PKCS #11 functions. Should only be called by pkcs11.c
|
||||
*/
|
||||
#include "pkcs11.h"
|
||||
#include "lgdb.h"
|
||||
#include "pcert.h"
|
||||
#include "lowkeyi.h"
|
||||
|
||||
/*
|
||||
* remove an object.
|
||||
*/
|
||||
CK_RV
|
||||
lg_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
|
||||
{
|
||||
CK_RV crv = CKR_OK;
|
||||
SECStatus rv;
|
||||
NSSLOWCERTCertificate *cert;
|
||||
NSSLOWCERTCertTrust tmptrust;
|
||||
PRBool isKrl;
|
||||
NSSLOWKEYDBHandle *keyHandle;
|
||||
NSSLOWCERTCertDBHandle *certHandle;
|
||||
const SECItem *dbKey;
|
||||
|
||||
object_id &= ~LG_TOKEN_MASK;
|
||||
dbKey = lg_lookupTokenKeyByHandle(sdb,object_id);
|
||||
if (dbKey == NULL) {
|
||||
return CKR_OBJECT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
/* remove the objects from the real data base */
|
||||
switch (object_id & LG_TOKEN_TYPE_MASK) {
|
||||
case LG_TOKEN_TYPE_PRIV:
|
||||
case LG_TOKEN_TYPE_KEY:
|
||||
/* KEYID is the public KEY for DSA and DH, and the MODULUS for
|
||||
* RSA */
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
if (!keyHandle) {
|
||||
crv = CKR_TOKEN_WRITE_PROTECTED;
|
||||
break;
|
||||
}
|
||||
rv = nsslowkey_DeleteKey(keyHandle, dbKey);
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
}
|
||||
break;
|
||||
case LG_TOKEN_TYPE_PUB:
|
||||
break; /* public keys only exist at the behest of the priv key */
|
||||
case LG_TOKEN_TYPE_CERT:
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (!certHandle) {
|
||||
crv = CKR_TOKEN_WRITE_PROTECTED;
|
||||
break;
|
||||
}
|
||||
cert = nsslowcert_FindCertByKey(certHandle,dbKey);
|
||||
if (cert == NULL) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
rv = nsslowcert_DeletePermCertificate(cert);
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
}
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
break;
|
||||
case LG_TOKEN_TYPE_CRL:
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (!certHandle) {
|
||||
crv = CKR_TOKEN_WRITE_PROTECTED;
|
||||
break;
|
||||
}
|
||||
isKrl = (PRBool) (object_id == LG_TOKEN_KRL_HANDLE);
|
||||
rv = nsslowcert_DeletePermCRL(certHandle, dbKey, isKrl);
|
||||
if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
|
||||
break;
|
||||
case LG_TOKEN_TYPE_TRUST:
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (!certHandle) {
|
||||
crv = CKR_TOKEN_WRITE_PROTECTED;
|
||||
break;
|
||||
}
|
||||
cert = nsslowcert_FindCertByKey(certHandle, dbKey);
|
||||
if (cert == NULL) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
tmptrust = *cert->trust;
|
||||
tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS;
|
||||
tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS;
|
||||
tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS;
|
||||
tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN;
|
||||
tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN;
|
||||
tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN;
|
||||
rv = nsslowcert_ChangeCertTrust(certHandle, cert, &tmptrust);
|
||||
if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
lg_DBLock(sdb);
|
||||
lg_deleteTokenKeyByHandle(sdb,object_id);
|
||||
lg_DBUnlock(sdb);
|
||||
|
||||
return crv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
910
mozilla/security/nss/lib/softoken/legacydb/lgfind.c
Normal file
910
mozilla/security/nss/lib/softoken/legacydb/lgfind.c
Normal file
@@ -0,0 +1,910 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "secitem.h"
|
||||
#include "pkcs11.h"
|
||||
#include "lgdb.h"
|
||||
#include "lowkeyi.h"
|
||||
#include "pcert.h"
|
||||
#include "blapi.h"
|
||||
|
||||
#include "keydbi.h"
|
||||
|
||||
/*
|
||||
* This code maps PKCS #11 Finds to legacy database searches. This code
|
||||
* was orginally in pkcs11.c in previous versions of NSS.
|
||||
*/
|
||||
|
||||
struct SDBFindStr {
|
||||
CK_OBJECT_HANDLE *handles;
|
||||
int size;
|
||||
int index;
|
||||
int array_size;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* free a search structure
|
||||
*/
|
||||
void
|
||||
lg_FreeSearch(SDBFind *search)
|
||||
{
|
||||
if (search->handles) {
|
||||
PORT_Free(search->handles);
|
||||
}
|
||||
PORT_Free(search);
|
||||
}
|
||||
|
||||
void
|
||||
lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle)
|
||||
{
|
||||
if (search->handles == NULL) {
|
||||
return;
|
||||
}
|
||||
if (search->size >= search->array_size) {
|
||||
search->array_size += LG_SEARCH_BLOCK_SIZE;
|
||||
search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
|
||||
sizeof(CK_OBJECT_HANDLE)* search->array_size);
|
||||
if (search->handles == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
search->handles[search->size] = handle;
|
||||
search->size++;
|
||||
}
|
||||
|
||||
/*
|
||||
* find any certs that may match the template and load them.
|
||||
*/
|
||||
#define LG_CERT 0x00000001
|
||||
#define LG_TRUST 0x00000002
|
||||
#define LG_CRL 0x00000004
|
||||
#define LG_SMIME 0x00000008
|
||||
#define LG_PRIVATE 0x00000010
|
||||
#define LG_PUBLIC 0x00000020
|
||||
#define LG_KEY 0x00000040
|
||||
|
||||
/*
|
||||
* structure to collect key handles.
|
||||
*/
|
||||
typedef struct lgCrlDataStr {
|
||||
SDB *sdb;
|
||||
SDBFind *searchHandles;
|
||||
const CK_ATTRIBUTE *template;
|
||||
CK_ULONG templ_count;
|
||||
} lgCrlData;
|
||||
|
||||
|
||||
static SECStatus
|
||||
lg_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
|
||||
{
|
||||
lgCrlData *crlData;
|
||||
CK_OBJECT_HANDLE class_handle;
|
||||
SDB *sdb;
|
||||
|
||||
crlData = (lgCrlData *)arg;
|
||||
sdb = crlData->sdb;
|
||||
|
||||
class_handle = (type == certDBEntryTypeRevocation) ? LG_TOKEN_TYPE_CRL :
|
||||
LG_TOKEN_KRL_HANDLE;
|
||||
if (lg_tokenMatch(sdb, key, class_handle,
|
||||
crlData->template, crlData->templ_count)) {
|
||||
lg_addHandle(crlData->searchHandles,
|
||||
lg_mkHandle(sdb,key,class_handle));
|
||||
}
|
||||
return(SECSuccess);
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchCrls(SDB *sdb, SECItem *derSubject, PRBool isKrl,
|
||||
unsigned long classFlags, SDBFind *search,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certHandle = NULL;
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (certHandle == NULL) {
|
||||
return;
|
||||
}
|
||||
if (derSubject->data != NULL) {
|
||||
certDBEntryRevocation *crl =
|
||||
nsslowcert_FindCrlByKey(certHandle, derSubject, isKrl);
|
||||
|
||||
if (crl != NULL) {
|
||||
lg_addHandle(search, lg_mkHandle(sdb, derSubject,
|
||||
isKrl ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL));
|
||||
nsslowcert_DestroyDBEntry((certDBEntry *)crl);
|
||||
}
|
||||
} else {
|
||||
lgCrlData crlData;
|
||||
|
||||
/* traverse */
|
||||
crlData.sdb = sdb;
|
||||
crlData.searchHandles = search;
|
||||
crlData.template = pTemplate;
|
||||
crlData.templ_count = ulCount;
|
||||
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation,
|
||||
lg_crl_collect, (void *)&crlData);
|
||||
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation,
|
||||
lg_crl_collect, (void *)&crlData);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* structure to collect key handles.
|
||||
*/
|
||||
typedef struct lgKeyDataStr {
|
||||
SDB *sdb;
|
||||
NSSLOWKEYDBHandle *keyHandle;
|
||||
SDBFind *searchHandles;
|
||||
SECItem *id;
|
||||
const CK_ATTRIBUTE *template;
|
||||
CK_ULONG templ_count;
|
||||
unsigned long classFlags;
|
||||
PRBool strict;
|
||||
} lgKeyData;
|
||||
|
||||
static PRBool
|
||||
isSecretKey(NSSLOWKEYPrivateKey *privKey)
|
||||
{
|
||||
if (privKey->keyType == NSSLOWKEYRSAKey &&
|
||||
privKey->u.rsa.publicExponent.len == 1 &&
|
||||
privKey->u.rsa.publicExponent.data[0] == 0)
|
||||
return PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static SECStatus
|
||||
lg_key_collect(DBT *key, DBT *data, void *arg)
|
||||
{
|
||||
lgKeyData *keyData;
|
||||
NSSLOWKEYPrivateKey *privKey = NULL;
|
||||
SECItem tmpDBKey;
|
||||
SDB *sdb;
|
||||
|
||||
keyData = (lgKeyData *)arg;
|
||||
sdb = keyData->sdb;
|
||||
|
||||
tmpDBKey.data = key->data;
|
||||
tmpDBKey.len = key->size;
|
||||
tmpDBKey.type = siBuffer;
|
||||
|
||||
PORT_Assert(keyData->keyHandle);
|
||||
if (!keyData->strict && keyData->id) {
|
||||
SECItem result;
|
||||
PRBool haveMatch= PR_FALSE;
|
||||
unsigned char hashKey[SHA1_LENGTH];
|
||||
result.data = hashKey;
|
||||
result.len = sizeof(hashKey);
|
||||
|
||||
if (keyData->id->len == 0) {
|
||||
/* Make sure this isn't a LG_KEY */
|
||||
privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle,
|
||||
&tmpDBKey, keyData->sdb/*->password*/);
|
||||
if (privKey) {
|
||||
haveMatch = isSecretKey(privKey) ?
|
||||
(PRBool)(keyData->classFlags & LG_KEY) != 0:
|
||||
(PRBool)(keyData->classFlags &
|
||||
(LG_PRIVATE|LG_PUBLIC)) != 0;
|
||||
nsslowkey_DestroyPrivateKey(privKey);
|
||||
}
|
||||
} else {
|
||||
SHA1_HashBuf( hashKey, key->data, key->size ); /* match id */
|
||||
haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
|
||||
if (!haveMatch && ((unsigned char *)key->data)[0] == 0) {
|
||||
/* This is a fix for backwards compatibility. The key
|
||||
* database indexes private keys by the public key, and
|
||||
* versions of NSS prior to 3.4 stored the public key as
|
||||
* a signed integer. The public key is now treated as an
|
||||
* unsigned integer, with no leading zero. In order to
|
||||
* correctly compute the hash of an old key, it is necessary
|
||||
* to fallback and detect the leading zero.
|
||||
*/
|
||||
SHA1_HashBuf(hashKey,
|
||||
(unsigned char *)key->data + 1, key->size - 1);
|
||||
haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
|
||||
}
|
||||
}
|
||||
if (haveMatch) {
|
||||
if (keyData->classFlags & LG_PRIVATE) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
|
||||
}
|
||||
if (keyData->classFlags & LG_PUBLIC) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PUB));
|
||||
}
|
||||
if (keyData->classFlags & LG_KEY) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_KEY));
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey,
|
||||
keyData->sdb/*->password*/);
|
||||
if ( privKey == NULL ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (isSecretKey(privKey)) {
|
||||
if ((keyData->classFlags & LG_KEY) &&
|
||||
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY,
|
||||
keyData->template, keyData->templ_count)) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY));
|
||||
}
|
||||
} else {
|
||||
if ((keyData->classFlags & LG_PRIVATE) &&
|
||||
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV,
|
||||
keyData->template, keyData->templ_count)) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(keyData->sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
|
||||
}
|
||||
if ((keyData->classFlags & LG_PUBLIC) &&
|
||||
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB,
|
||||
keyData->template, keyData->templ_count)) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(keyData->sdb, &tmpDBKey,LG_TOKEN_TYPE_PUB));
|
||||
}
|
||||
}
|
||||
|
||||
loser:
|
||||
if ( privKey ) {
|
||||
nsslowkey_DestroyPrivateKey(privKey);
|
||||
}
|
||||
return(SECSuccess);
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchKeys(SDB *sdb, SECItem *key_id,
|
||||
unsigned long classFlags, SDBFind *search, PRBool mustStrict,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
|
||||
{
|
||||
NSSLOWKEYDBHandle *keyHandle = NULL;
|
||||
NSSLOWKEYPrivateKey *privKey;
|
||||
lgKeyData keyData;
|
||||
PRBool found = PR_FALSE;
|
||||
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
if (keyHandle == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (key_id->data) {
|
||||
privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, sdb);
|
||||
if (privKey) {
|
||||
if ((classFlags & LG_KEY) && isSecretKey(privKey)) {
|
||||
lg_addHandle(search,
|
||||
lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_KEY));
|
||||
found = PR_TRUE;
|
||||
}
|
||||
if ((classFlags & LG_PRIVATE) && !isSecretKey(privKey)) {
|
||||
lg_addHandle(search,
|
||||
lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PRIV));
|
||||
found = PR_TRUE;
|
||||
}
|
||||
if ((classFlags & LG_PUBLIC) && !isSecretKey(privKey)) {
|
||||
lg_addHandle(search,
|
||||
lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PUB));
|
||||
found = PR_TRUE;
|
||||
}
|
||||
nsslowkey_DestroyPrivateKey(privKey);
|
||||
}
|
||||
/* don't do the traversal if we have an up to date db */
|
||||
if (keyHandle->version != 3) {
|
||||
goto loser;
|
||||
}
|
||||
/* don't do the traversal if it can't possibly be the correct id */
|
||||
/* all soft token id's are SHA1_HASH_LEN's */
|
||||
if (key_id->len != SHA1_LENGTH) {
|
||||
goto loser;
|
||||
}
|
||||
if (found) {
|
||||
/* if we already found some keys, don't do the traversal */
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
keyData.sdb = sdb;
|
||||
keyData.keyHandle = keyHandle;
|
||||
keyData.searchHandles = search;
|
||||
keyData.id = key_id;
|
||||
keyData.template = pTemplate;
|
||||
keyData.templ_count = ulCount;
|
||||
keyData.classFlags = classFlags;
|
||||
keyData.strict = mustStrict ? mustStrict : LG_STRICT;
|
||||
|
||||
nsslowkey_TraverseKeys(keyHandle, lg_key_collect, &keyData);
|
||||
|
||||
loser:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* structure to collect certs into
|
||||
*/
|
||||
typedef struct lgCertDataStr {
|
||||
SDB *sdb;
|
||||
int cert_count;
|
||||
int max_cert_count;
|
||||
NSSLOWCERTCertificate **certs;
|
||||
const CK_ATTRIBUTE *template;
|
||||
CK_ULONG templ_count;
|
||||
unsigned long classFlags;
|
||||
PRBool strict;
|
||||
} lgCertData;
|
||||
|
||||
/*
|
||||
* collect all the certs from the traverse call.
|
||||
*/
|
||||
static SECStatus
|
||||
lg_cert_collect(NSSLOWCERTCertificate *cert,void *arg)
|
||||
{
|
||||
lgCertData *cd = (lgCertData *)arg;
|
||||
|
||||
if (cert == NULL) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
if (cd->certs == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (cd->strict) {
|
||||
if ((cd->classFlags & LG_CERT) && !lg_tokenMatch(cd->sdb,
|
||||
&cert->certKey, LG_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) {
|
||||
return SECSuccess;
|
||||
}
|
||||
if ((cd->classFlags & LG_TRUST) && !lg_tokenMatch(cd->sdb,
|
||||
&cert->certKey, LG_TOKEN_TYPE_TRUST,
|
||||
cd->template, cd->templ_count)) {
|
||||
return SECSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate more space if we need it. This should only happen in
|
||||
* the general traversal case */
|
||||
if (cd->cert_count >= cd->max_cert_count) {
|
||||
int size;
|
||||
cd->max_cert_count += LG_SEARCH_BLOCK_SIZE;
|
||||
size = cd->max_cert_count * sizeof (NSSLOWCERTCertificate *);
|
||||
cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs,size);
|
||||
if (cd->certs == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* provide impedence matching ... */
|
||||
static SECStatus
|
||||
lg_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg)
|
||||
{
|
||||
return lg_cert_collect(cert, arg);
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchSingleCert(lgCertData *certData,NSSLOWCERTCertificate *cert)
|
||||
{
|
||||
if (cert == NULL) {
|
||||
return;
|
||||
}
|
||||
if (certData->strict &&
|
||||
!lg_tokenMatch(certData->sdb, &cert->certKey, LG_TOKEN_TYPE_CERT,
|
||||
certData->template,certData->templ_count)) {
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
return;
|
||||
}
|
||||
certData->certs = (NSSLOWCERTCertificate **)
|
||||
PORT_Alloc(sizeof (NSSLOWCERTCertificate *));
|
||||
if (certData->certs == NULL) {
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
return;
|
||||
}
|
||||
certData->certs[0] = cert;
|
||||
certData->cert_count = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
lg_CertSetupData(lgCertData *certData,int count)
|
||||
{
|
||||
certData->max_cert_count = count;
|
||||
|
||||
if (certData->max_cert_count <= 0) {
|
||||
return;
|
||||
}
|
||||
certData->certs = (NSSLOWCERTCertificate **)
|
||||
PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *));
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchCertsAndTrust(SDB *sdb, SECItem *derCert, SECItem *name,
|
||||
SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN,
|
||||
SECItem *email,
|
||||
unsigned long classFlags, SDBFind *handles,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certHandle = NULL;
|
||||
lgCertData certData;
|
||||
int i;
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (certHandle == NULL) return;
|
||||
|
||||
certData.sdb = sdb;
|
||||
certData.max_cert_count = 0;
|
||||
certData.certs = NULL;
|
||||
certData.cert_count = 0;
|
||||
certData.template = pTemplate;
|
||||
certData.templ_count = ulCount;
|
||||
certData.classFlags = classFlags;
|
||||
certData.strict = LG_STRICT;
|
||||
|
||||
|
||||
/*
|
||||
* Find the Cert.
|
||||
*/
|
||||
if (derCert->data != NULL) {
|
||||
NSSLOWCERTCertificate *cert =
|
||||
nsslowcert_FindCertByDERCert(certHandle,derCert);
|
||||
lg_searchSingleCert(&certData,cert);
|
||||
} else if (name->data != NULL) {
|
||||
char *tmp_name = (char*)PORT_Alloc(name->len+1);
|
||||
int count;
|
||||
|
||||
if (tmp_name == NULL) {
|
||||
return;
|
||||
}
|
||||
PORT_Memcpy(tmp_name,name->data,name->len);
|
||||
tmp_name[name->len] = 0;
|
||||
|
||||
count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name);
|
||||
lg_CertSetupData(&certData,count);
|
||||
nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name,
|
||||
lg_cert_collect, &certData);
|
||||
PORT_Free(tmp_name);
|
||||
} else if (derSubject->data != NULL) {
|
||||
int count;
|
||||
|
||||
count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject);
|
||||
lg_CertSetupData(&certData,count);
|
||||
nsslowcert_TraversePermCertsForSubject(certHandle,derSubject,
|
||||
lg_cert_collect, &certData);
|
||||
} else if ((issuerSN->derIssuer.data != NULL) &&
|
||||
(issuerSN->serialNumber.data != NULL)) {
|
||||
if (classFlags & LG_CERT) {
|
||||
NSSLOWCERTCertificate *cert =
|
||||
nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN);
|
||||
|
||||
lg_searchSingleCert(&certData,cert);
|
||||
}
|
||||
if (classFlags & LG_TRUST) {
|
||||
NSSLOWCERTTrust *trust =
|
||||
nsslowcert_FindTrustByIssuerAndSN(certHandle, issuerSN);
|
||||
|
||||
if (trust) {
|
||||
lg_addHandle(handles,
|
||||
lg_mkHandle(sdb,&trust->dbKey,LG_TOKEN_TYPE_TRUST));
|
||||
nsslowcert_DestroyTrust(trust);
|
||||
}
|
||||
}
|
||||
} else if (email->data != NULL) {
|
||||
char *tmp_name = (char*)PORT_Alloc(email->len+1);
|
||||
certDBEntrySMime *entry = NULL;
|
||||
|
||||
if (tmp_name == NULL) {
|
||||
return;
|
||||
}
|
||||
PORT_Memcpy(tmp_name,email->data,email->len);
|
||||
tmp_name[email->len] = 0;
|
||||
|
||||
entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
|
||||
if (entry) {
|
||||
int count;
|
||||
SECItem *subjectName = &entry->subjectName;
|
||||
|
||||
count = nsslowcert_NumPermCertsForSubject(certHandle, subjectName);
|
||||
lg_CertSetupData(&certData,count);
|
||||
nsslowcert_TraversePermCertsForSubject(certHandle, subjectName,
|
||||
lg_cert_collect, &certData);
|
||||
|
||||
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
|
||||
}
|
||||
PORT_Free(tmp_name);
|
||||
} else {
|
||||
/* we aren't filtering the certs, we are working on all, so turn
|
||||
* on the strict filters. */
|
||||
certData.strict = PR_TRUE;
|
||||
lg_CertSetupData(&certData,LG_SEARCH_BLOCK_SIZE);
|
||||
nsslowcert_TraversePermCerts(certHandle, lg_cert_collect2, &certData);
|
||||
}
|
||||
|
||||
/*
|
||||
* build the handles
|
||||
*/
|
||||
for (i=0 ; i < certData.cert_count ; i++) {
|
||||
NSSLOWCERTCertificate *cert = certData.certs[i];
|
||||
|
||||
/* if we filtered it would have been on the stuff above */
|
||||
if (classFlags & LG_CERT) {
|
||||
lg_addHandle(handles,
|
||||
lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT));
|
||||
}
|
||||
if ((classFlags & LG_TRUST) && nsslowcert_hasTrust(cert->trust)) {
|
||||
lg_addHandle(handles,
|
||||
lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST));
|
||||
}
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
}
|
||||
|
||||
if (certData.certs) PORT_Free(certData.certs);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchSMime(SDB *sdb, SECItem *email, SDBFind *handles,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certHandle = NULL;
|
||||
certDBEntrySMime *entry;
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (certHandle == NULL) return;
|
||||
|
||||
if (email->data != NULL) {
|
||||
char *tmp_name = (char*)PORT_Alloc(email->len+1);
|
||||
|
||||
if (tmp_name == NULL) {
|
||||
return;
|
||||
}
|
||||
PORT_Memcpy(tmp_name,email->data,email->len);
|
||||
tmp_name[email->len] = 0;
|
||||
|
||||
entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
|
||||
if (entry) {
|
||||
SECItem emailKey;
|
||||
|
||||
emailKey.data = (unsigned char *)tmp_name;
|
||||
emailKey.len = PORT_Strlen(tmp_name)+1;
|
||||
emailKey.type = 0;
|
||||
lg_addHandle(handles,
|
||||
lg_mkHandle(sdb,&emailKey,LG_TOKEN_TYPE_SMIME));
|
||||
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
|
||||
}
|
||||
PORT_Free(tmp_name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
lg_searchTokenList(SDB *sdb, SDBFind *search,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
|
||||
{
|
||||
int i;
|
||||
PRBool isKrl = PR_FALSE;
|
||||
SECItem derCert = { siBuffer, NULL, 0 };
|
||||
SECItem derSubject = { siBuffer, NULL, 0 };
|
||||
SECItem name = { siBuffer, NULL, 0 };
|
||||
SECItem email = { siBuffer, NULL, 0 };
|
||||
SECItem key_id = { siBuffer, NULL, 0 };
|
||||
SECItem cert_sha1_hash = { siBuffer, NULL, 0 };
|
||||
SECItem cert_md5_hash = { siBuffer, NULL, 0 };
|
||||
NSSLOWCERTIssuerAndSN issuerSN = {
|
||||
{ siBuffer, NULL, 0 },
|
||||
{ siBuffer, NULL, 0 }
|
||||
};
|
||||
SECItem *copy = NULL;
|
||||
CK_CERTIFICATE_TYPE certType;
|
||||
CK_OBJECT_CLASS objectClass;
|
||||
CK_RV crv;
|
||||
unsigned long classFlags =
|
||||
LG_CERT|LG_TRUST|LG_PRIVATE|LG_PUBLIC|LG_KEY|LG_SMIME|LG_CRL;
|
||||
|
||||
if (lg_getCertDB(sdb) == NULL) {
|
||||
classFlags = LG_PRIVATE|LG_KEY;
|
||||
} else {
|
||||
classFlags = LG_CERT|LG_TRUST|LG_PUBLIC|LG_SMIME|LG_CRL;
|
||||
}
|
||||
|
||||
/*
|
||||
* look for things to search on token objects for. If the right options
|
||||
* are specified, we can use them as direct indeces into the database
|
||||
* (rather than using linear searches. We can also use the attributes to
|
||||
* limit the kinds of objects we are searching for. Later we can use this
|
||||
* array to filter the remaining objects more finely.
|
||||
*/
|
||||
for (i=0 ;classFlags && i < (int)ulCount; i++) {
|
||||
|
||||
switch (pTemplate[i].type) {
|
||||
case CKA_SUBJECT:
|
||||
copy = &derSubject;
|
||||
classFlags &= (LG_CERT|LG_PRIVATE|LG_PUBLIC|LG_SMIME|LG_CRL);
|
||||
break;
|
||||
case CKA_ISSUER:
|
||||
copy = &issuerSN.derIssuer;
|
||||
classFlags &= (LG_CERT|LG_TRUST);
|
||||
break;
|
||||
case CKA_SERIAL_NUMBER:
|
||||
copy = &issuerSN.serialNumber;
|
||||
classFlags &= (LG_CERT|LG_TRUST);
|
||||
break;
|
||||
case CKA_VALUE:
|
||||
copy = &derCert;
|
||||
classFlags &= (LG_CERT|LG_CRL|LG_SMIME);
|
||||
break;
|
||||
case CKA_LABEL:
|
||||
copy = &name;
|
||||
break;
|
||||
case CKA_NETSCAPE_EMAIL:
|
||||
copy = &email;
|
||||
classFlags &= LG_SMIME|LG_CERT;
|
||||
break;
|
||||
case CKA_NETSCAPE_SMIME_TIMESTAMP:
|
||||
classFlags &= LG_SMIME;
|
||||
break;
|
||||
case CKA_CLASS:
|
||||
crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1, &objectClass);
|
||||
if (crv != CKR_OK) {
|
||||
classFlags = 0;
|
||||
break;;
|
||||
}
|
||||
switch (objectClass) {
|
||||
case CKO_CERTIFICATE:
|
||||
classFlags &= LG_CERT;
|
||||
break;
|
||||
case CKO_NETSCAPE_TRUST:
|
||||
classFlags &= LG_TRUST;
|
||||
break;
|
||||
case CKO_NETSCAPE_CRL:
|
||||
classFlags &= LG_CRL;
|
||||
break;
|
||||
case CKO_NETSCAPE_SMIME:
|
||||
classFlags &= LG_SMIME;
|
||||
break;
|
||||
case CKO_PRIVATE_KEY:
|
||||
classFlags &= LG_PRIVATE;
|
||||
break;
|
||||
case CKO_PUBLIC_KEY:
|
||||
classFlags &= LG_PUBLIC;
|
||||
break;
|
||||
case CKO_SECRET_KEY:
|
||||
classFlags &= LG_KEY;
|
||||
break;
|
||||
default:
|
||||
classFlags = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CKA_PRIVATE:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
}
|
||||
if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
|
||||
classFlags &= (LG_PRIVATE|LG_KEY);
|
||||
} else {
|
||||
classFlags &= ~(LG_PRIVATE|LG_KEY);
|
||||
}
|
||||
break;
|
||||
case CKA_SENSITIVE:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
}
|
||||
if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
|
||||
classFlags &= (LG_PRIVATE|LG_KEY);
|
||||
} else {
|
||||
classFlags = 0;
|
||||
}
|
||||
break;
|
||||
case CKA_TOKEN:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
}
|
||||
if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
|
||||
classFlags = 0;
|
||||
}
|
||||
break;
|
||||
case CKA_CERT_SHA1_HASH:
|
||||
classFlags &= LG_TRUST;
|
||||
copy = &cert_sha1_hash; break;
|
||||
case CKA_CERT_MD5_HASH:
|
||||
classFlags &= LG_TRUST;
|
||||
copy = &cert_md5_hash; break;
|
||||
case CKA_CERTIFICATE_TYPE:
|
||||
crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1,&certType);
|
||||
if (crv != CKR_OK) {
|
||||
classFlags = 0;
|
||||
}
|
||||
classFlags &= LG_CERT;
|
||||
if (certType != CKC_X_509) {
|
||||
classFlags = 0;
|
||||
}
|
||||
break;
|
||||
case CKA_ID:
|
||||
copy = &key_id;
|
||||
classFlags &= (LG_CERT|LG_PRIVATE|LG_KEY|LG_PUBLIC);
|
||||
break;
|
||||
case CKA_NETSCAPE_KRL:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
}
|
||||
classFlags &= LG_CRL;
|
||||
isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE);
|
||||
break;
|
||||
case CKA_MODIFIABLE:
|
||||
break;
|
||||
case CKA_KEY_TYPE:
|
||||
case CKA_DERIVE:
|
||||
classFlags &= LG_PUBLIC|LG_PRIVATE|LG_KEY;
|
||||
break;
|
||||
case CKA_VERIFY_RECOVER:
|
||||
classFlags &= LG_PUBLIC;
|
||||
break;
|
||||
case CKA_SIGN_RECOVER:
|
||||
classFlags &= LG_PRIVATE;
|
||||
break;
|
||||
case CKA_ENCRYPT:
|
||||
case CKA_VERIFY:
|
||||
case CKA_WRAP:
|
||||
classFlags &= LG_PUBLIC|LG_KEY;
|
||||
break;
|
||||
case CKA_DECRYPT:
|
||||
case CKA_SIGN:
|
||||
case CKA_UNWRAP:
|
||||
case CKA_ALWAYS_SENSITIVE:
|
||||
case CKA_EXTRACTABLE:
|
||||
case CKA_NEVER_EXTRACTABLE:
|
||||
classFlags &= LG_PRIVATE|LG_KEY;
|
||||
break;
|
||||
/* can't be a certificate if it doesn't match one of the above
|
||||
* attributes */
|
||||
default:
|
||||
classFlags = 0;
|
||||
break;
|
||||
}
|
||||
if (copy) {
|
||||
copy->data = (unsigned char*)pTemplate[i].pValue;
|
||||
copy->len = pTemplate[i].ulValueLen;
|
||||
}
|
||||
copy = NULL;
|
||||
}
|
||||
|
||||
/* certs */
|
||||
if (classFlags & (LG_CERT|LG_TRUST)) {
|
||||
lg_searchCertsAndTrust(sdb,&derCert,&name,&derSubject,
|
||||
&issuerSN, &email,classFlags,search,
|
||||
pTemplate, ulCount);
|
||||
}
|
||||
|
||||
/* keys */
|
||||
if (classFlags & (LG_PRIVATE|LG_PUBLIC|LG_KEY)) {
|
||||
PRBool mustStrict = ((classFlags & LG_KEY) != 0) && (name.len != 0);
|
||||
lg_searchKeys(sdb, &key_id, classFlags, search,
|
||||
mustStrict, pTemplate, ulCount);
|
||||
}
|
||||
|
||||
/* crl's */
|
||||
if (classFlags & LG_CRL) {
|
||||
lg_searchCrls(sdb, &derSubject, isKrl, classFlags, search,
|
||||
pTemplate, ulCount);
|
||||
}
|
||||
/* Add S/MIME entry stuff */
|
||||
if (classFlags & LG_SMIME) {
|
||||
lg_searchSMime(sdb, &email, search, pTemplate, ulCount);
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
/* lg_FindObjectsInit initializes a search for token and session objects
|
||||
* that match a template. */
|
||||
CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
|
||||
CK_ULONG ulCount, SDBFind **retSearch)
|
||||
{
|
||||
SDBFind *search;
|
||||
CK_RV crv = CKR_OK;
|
||||
|
||||
*retSearch = NULL;
|
||||
|
||||
search = (SDBFind *)PORT_Alloc(sizeof(SDBFind));
|
||||
if (search == NULL) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
search->handles = (CK_OBJECT_HANDLE *)
|
||||
PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * LG_SEARCH_BLOCK_SIZE);
|
||||
if (search->handles == NULL) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
search->index = 0;
|
||||
search->size = 0;
|
||||
search->array_size = LG_SEARCH_BLOCK_SIZE;
|
||||
/* FIXME - do we still need to get Login state? */
|
||||
|
||||
crv = lg_searchTokenList(sdb, search, pTemplate, ulCount);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
*retSearch = search;
|
||||
return CKR_OK;
|
||||
|
||||
loser:
|
||||
if (search) {
|
||||
lg_FreeSearch(search);
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
|
||||
/* lg_FindObjects continues a search for token and session objects
|
||||
* that match a template, obtaining additional object handles. */
|
||||
CK_RV lg_FindObjects(SDB *sdb, SDBFind *search,
|
||||
CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
|
||||
CK_ULONG *pulObjectCount)
|
||||
{
|
||||
int transfer;
|
||||
int left;
|
||||
|
||||
*pulObjectCount = 0;
|
||||
left = search->size - search->index;
|
||||
transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount;
|
||||
if (transfer > 0) {
|
||||
PORT_Memcpy(phObject,&search->handles[search->index],
|
||||
transfer*sizeof(CK_OBJECT_HANDLE_PTR));
|
||||
} else {
|
||||
*phObject = CK_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
search->index += transfer;
|
||||
*pulObjectCount = transfer;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/* lg_FindObjectsFinal finishes a search for token and session objects. */
|
||||
CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search)
|
||||
{
|
||||
|
||||
if (search != NULL) {
|
||||
lg_FreeSearch(search);
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
644
mozilla/security/nss/lib/softoken/legacydb/lginit.c
Normal file
644
mozilla/security/nss/lib/softoken/legacydb/lginit.c
Normal file
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
* NSS utility functions
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: lginit.c,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#include "lowkeyi.h"
|
||||
#include "pcert.h"
|
||||
#include "keydbi.h"
|
||||
#include "lgdb.h"
|
||||
|
||||
typedef struct LGPrivateStr {
|
||||
NSSLOWCERTCertDBHandle *certDB;
|
||||
NSSLOWKEYDBHandle *keyDB;
|
||||
PRLock *dbLock;
|
||||
PLHashTable *hashTable;
|
||||
} LGPrivate;
|
||||
|
||||
static char *
|
||||
lg_certdb_name_cb(void *arg, int dbVersion)
|
||||
{
|
||||
const char *configdir = (const char *)arg;
|
||||
const char *dbver;
|
||||
char *smpname = NULL;
|
||||
char *dbname = NULL;
|
||||
|
||||
switch (dbVersion) {
|
||||
case 8:
|
||||
dbver = "8";
|
||||
break;
|
||||
case 7:
|
||||
dbver = "7";
|
||||
break;
|
||||
case 6:
|
||||
dbver = "6";
|
||||
break;
|
||||
case 5:
|
||||
dbver = "5";
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
dbver = "";
|
||||
break;
|
||||
}
|
||||
|
||||
/* make sure we return something allocated with PORT_ so we have properly
|
||||
* matched frees at the end */
|
||||
smpname = PR_smprintf(CERT_DB_FMT, configdir, dbver);
|
||||
if (smpname) {
|
||||
dbname = PORT_Strdup(smpname);
|
||||
PR_smprintf_free(smpname);
|
||||
}
|
||||
return dbname;
|
||||
}
|
||||
|
||||
static char *
|
||||
lg_keydb_name_cb(void *arg, int dbVersion)
|
||||
{
|
||||
const char *configdir = (const char *)arg;
|
||||
const char *dbver;
|
||||
char *smpname = NULL;
|
||||
char *dbname = NULL;
|
||||
|
||||
switch (dbVersion) {
|
||||
case 4:
|
||||
dbver = "4";
|
||||
break;
|
||||
case 3:
|
||||
dbver = "3";
|
||||
break;
|
||||
case 1:
|
||||
dbver = "1";
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
dbver = "";
|
||||
break;
|
||||
}
|
||||
|
||||
smpname = PR_smprintf(KEY_DB_FMT, configdir, dbver);
|
||||
if (smpname) {
|
||||
dbname = PORT_Strdup(smpname);
|
||||
PR_smprintf_free(smpname);
|
||||
}
|
||||
return dbname;
|
||||
}
|
||||
|
||||
const char *
|
||||
lg_EvaluateConfigDir(const char *configdir,char **appName)
|
||||
{
|
||||
if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) {
|
||||
char *cdir;
|
||||
|
||||
*appName = PORT_Strdup(configdir+sizeof(MULTIACCESS)-1);
|
||||
if (*appName == NULL) {
|
||||
return configdir;
|
||||
}
|
||||
cdir = *appName;
|
||||
while (*cdir && *cdir != ':') {
|
||||
cdir++;
|
||||
}
|
||||
if (*cdir == ':') {
|
||||
*cdir = 0;
|
||||
cdir++;
|
||||
}
|
||||
configdir = cdir;
|
||||
}
|
||||
return configdir;
|
||||
}
|
||||
|
||||
static int rdbmapflags(int flags);
|
||||
static rdbfunc lg_rdbfunc = NULL;
|
||||
static rdbstatusfunc lg_rdbstatusfunc = NULL;
|
||||
|
||||
/* NOTE: SHLIB_SUFFIX is defined on the command line */
|
||||
#define RDBLIB SHLIB_PREFIX"rdb."SHLIB_SUFFIX
|
||||
|
||||
DB * rdbopen(const char *appName, const char *prefix,
|
||||
const char *type, int flags, int *status)
|
||||
{
|
||||
PRLibrary *lib;
|
||||
DB *db;
|
||||
|
||||
if (lg_rdbfunc) {
|
||||
db = (*lg_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
|
||||
if (!db && status && lg_rdbstatusfunc) {
|
||||
*status = (*lg_rdbstatusfunc)();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
/*
|
||||
* try to open the library.
|
||||
*/
|
||||
lib = PR_LoadLibrary(RDBLIB);
|
||||
|
||||
if (!lib) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get the entry points */
|
||||
lg_rdbstatusfunc = (rdbstatusfunc) PR_FindSymbol(lib,"rdbstatus");
|
||||
lg_rdbfunc = (rdbfunc) PR_FindSymbol(lib,"rdbopen");
|
||||
if (lg_rdbfunc) {
|
||||
db = (*lg_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
|
||||
if (!db && status && lg_rdbstatusfunc) {
|
||||
*status = (*lg_rdbstatusfunc)();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
/* couldn't find the entry point, unload the library and fail */
|
||||
PR_UnloadLibrary(lib);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* the following data structures are from rdb.h.
|
||||
*/
|
||||
struct RDBStr {
|
||||
DB db;
|
||||
int (*xactstart)(DB *db);
|
||||
int (*xactdone)(DB *db, PRBool abort);
|
||||
int version;
|
||||
int (*dbinitcomplete)(DB *db);
|
||||
};
|
||||
|
||||
#define DB_RDB ((DBTYPE) 0xff)
|
||||
#define RDB_RDONLY 1
|
||||
#define RDB_RDWR 2
|
||||
#define RDB_CREATE 4
|
||||
|
||||
static int
|
||||
rdbmapflags(int flags) {
|
||||
switch (flags) {
|
||||
case NO_RDONLY:
|
||||
return RDB_RDONLY;
|
||||
case NO_RDWR:
|
||||
return RDB_RDWR;
|
||||
case NO_CREATE:
|
||||
return RDB_CREATE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
db_IsRDB(DB *db)
|
||||
{
|
||||
return (PRBool) db->type == DB_RDB;
|
||||
}
|
||||
|
||||
int
|
||||
db_BeginTransaction(DB *db)
|
||||
{
|
||||
struct RDBStr *rdb = (struct RDBStr *)db;
|
||||
if (db->type != DB_RDB) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rdb->xactstart(db);
|
||||
}
|
||||
|
||||
int
|
||||
db_FinishTransaction(DB *db, PRBool abort)
|
||||
{
|
||||
struct RDBStr *rdb = (struct RDBStr *)db;
|
||||
if (db->type != DB_RDB) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rdb->xactdone(db, abort);
|
||||
}
|
||||
|
||||
static DB *
|
||||
lg_getRawDB(SDB *sdb)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certDB;
|
||||
NSSLOWKEYDBHandle *keyDB;
|
||||
|
||||
certDB = lg_getCertDB(sdb);
|
||||
if (certDB) {
|
||||
return certDB->permCertDB;
|
||||
}
|
||||
keyDB = lg_getKeyDB(sdb);
|
||||
if (keyDB) {
|
||||
return keyDB->db;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_Begin(SDB *sdb)
|
||||
{
|
||||
DB *db = lg_getRawDB(sdb);
|
||||
int ret;
|
||||
|
||||
if (db == NULL) {
|
||||
return CKR_GENERAL_ERROR; /* shouldn't happen */
|
||||
}
|
||||
ret = db_BeginTransaction(db);
|
||||
if (ret != 0) {
|
||||
return CKR_GENERAL_ERROR; /* could happen */
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_Commit(SDB *sdb)
|
||||
{
|
||||
DB *db = lg_getRawDB(sdb);
|
||||
int ret;
|
||||
|
||||
if (db == NULL) {
|
||||
return CKR_GENERAL_ERROR; /* shouldn't happen */
|
||||
}
|
||||
ret = db_FinishTransaction(db, PR_FALSE);
|
||||
if (ret != 0) {
|
||||
return CKR_GENERAL_ERROR; /* could happen */
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_Abort(SDB *sdb)
|
||||
{
|
||||
DB *db = lg_getRawDB(sdb);
|
||||
int ret;
|
||||
|
||||
if (db == NULL) {
|
||||
return CKR_GENERAL_ERROR; /* shouldn't happen */
|
||||
}
|
||||
ret = db_FinishTransaction(db, PR_TRUE);
|
||||
if (ret != 0) {
|
||||
return CKR_GENERAL_ERROR; /* could happen */
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
int
|
||||
db_InitComplete(DB *db)
|
||||
{
|
||||
struct RDBStr *rdb = (struct RDBStr *)db;
|
||||
if (db->type != DB_RDB) {
|
||||
return 0;
|
||||
}
|
||||
/* we should have added a version number to the RDBS structure. Since we
|
||||
* didn't, we detect that we have and 'extended' structure if the rdbstatus
|
||||
* func exists */
|
||||
if (!lg_rdbstatusfunc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rdb->dbinitcomplete(db);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SECStatus
|
||||
db_Copy(DB *dest,DB *src)
|
||||
{
|
||||
int ret;
|
||||
DBT key,data;
|
||||
ret = (*src->seq)(src, &key, &data, R_FIRST);
|
||||
if (ret) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
do {
|
||||
(void)(*dest->put)(dest,&key,&data, R_NOOVERWRITE);
|
||||
} while ( (*src->seq)(src, &key, &data, R_NEXT) == 0);
|
||||
(void)(*dest->sync)(dest,0);
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
static CK_RV
|
||||
lg_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly,
|
||||
NSSLOWCERTCertDBHandle **certdbPtr)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certdb = NULL;
|
||||
CK_RV crv = CKR_NETSCAPE_CERTDB_FAILED;
|
||||
SECStatus rv;
|
||||
char * name = NULL;
|
||||
char * appName = NULL;
|
||||
|
||||
if (prefix == NULL) {
|
||||
prefix = "";
|
||||
}
|
||||
|
||||
configdir = lg_EvaluateConfigDir(configdir, &appName);
|
||||
|
||||
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
|
||||
if (name == NULL) goto loser;
|
||||
|
||||
certdb = (NSSLOWCERTCertDBHandle*)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle));
|
||||
if (certdb == NULL)
|
||||
goto loser;
|
||||
|
||||
certdb->ref = 1;
|
||||
/* fix when we get the DB in */
|
||||
rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix,
|
||||
lg_certdb_name_cb, (void *)name, PR_FALSE);
|
||||
if (rv == SECSuccess) {
|
||||
crv = CKR_OK;
|
||||
*certdbPtr = certdb;
|
||||
certdb = NULL;
|
||||
}
|
||||
loser:
|
||||
if (certdb) PR_Free(certdb);
|
||||
if (name) PR_smprintf_free(name);
|
||||
if (appName) PORT_Free(appName);
|
||||
return crv;
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
lg_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly,
|
||||
NSSLOWKEYDBHandle **keydbPtr)
|
||||
{
|
||||
NSSLOWKEYDBHandle *keydb;
|
||||
char * name = NULL;
|
||||
char * appName = NULL;
|
||||
|
||||
if (prefix == NULL) {
|
||||
prefix = "";
|
||||
}
|
||||
configdir = lg_EvaluateConfigDir(configdir, &appName);
|
||||
|
||||
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
|
||||
if (name == NULL)
|
||||
return CKR_HOST_MEMORY;
|
||||
keydb = nsslowkey_OpenKeyDB(readOnly, appName, prefix,
|
||||
lg_keydb_name_cb, (void *)name);
|
||||
PR_smprintf_free(name);
|
||||
if (appName) PORT_Free(appName);
|
||||
if (keydb == NULL)
|
||||
return CKR_NETSCAPE_KEYDB_FAILED;
|
||||
*keydbPtr = keydb;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accessors for the private parts of the sdb structure.
|
||||
*/
|
||||
void
|
||||
lg_DBLock(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
PR_Lock(lgdb_p->dbLock);
|
||||
}
|
||||
|
||||
void
|
||||
lg_DBUnlock(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
PR_Unlock(lgdb_p->dbLock);
|
||||
}
|
||||
|
||||
PLHashTable *
|
||||
lg_GetHashTable(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
return lgdb_p->hashTable;
|
||||
}
|
||||
|
||||
NSSLOWCERTCertDBHandle *
|
||||
lg_getCertDB(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
|
||||
return lgdb_p->certDB;
|
||||
}
|
||||
|
||||
NSSLOWKEYDBHandle *
|
||||
lg_getKeyDB(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
|
||||
return lgdb_p->keyDB;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_Close(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
if (lgdb_p) {
|
||||
if (lgdb_p->certDB) {
|
||||
nsslowcert_ClosePermCertDB(lgdb_p->certDB);
|
||||
} else if (lgdb_p->keyDB) {
|
||||
nsslowkey_CloseKeyDB(lgdb_p->keyDB);
|
||||
}
|
||||
if (lgdb_p->dbLock) {
|
||||
PR_DestroyLock(lgdb_p->dbLock);
|
||||
}
|
||||
if (lgdb_p->hashTable) {
|
||||
PL_HashTableDestroy(lgdb_p->hashTable);
|
||||
}
|
||||
PORT_Free(lgdb_p);
|
||||
}
|
||||
PORT_Free(sdb);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
static PLHashNumber
|
||||
lg_HashNumber(const void *key)
|
||||
{
|
||||
return (PLHashNumber) key;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* helper function to wrap a NSSLOWCERTCertDBHandle or a NSSLOWKEYDBHandle
|
||||
* with and sdb structure.
|
||||
*/
|
||||
CK_RV
|
||||
lg_init(SDB **pSdb, int flags, NSSLOWCERTCertDBHandle *certdbPtr,
|
||||
NSSLOWKEYDBHandle *keydbPtr)
|
||||
{
|
||||
SDB *sdb = NULL;
|
||||
LGPrivate *lgdb_p = NULL;
|
||||
CK_RV error = CKR_HOST_MEMORY;
|
||||
|
||||
*pSdb = NULL;
|
||||
sdb = (SDB *) PORT_Alloc(sizeof(SDB));
|
||||
if (sdb == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
lgdb_p = (LGPrivate *) PORT_Alloc(sizeof(LGPrivate));
|
||||
if (lgdb_p == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
/* invariant fields */
|
||||
lgdb_p->certDB = certdbPtr;
|
||||
lgdb_p->keyDB = keydbPtr;
|
||||
lgdb_p->dbLock = PR_NewLock();
|
||||
if (lgdb_p->dbLock == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
lgdb_p->hashTable = PL_NewHashTable(64, lg_HashNumber, PL_CompareValues,
|
||||
SECITEM_HashCompare, NULL, 0);
|
||||
if (lgdb_p->hashTable == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
sdb->sdb_type = SDB_LEGACY;
|
||||
sdb->sdb_flags = flags;
|
||||
sdb->private = lgdb_p;
|
||||
sdb->sdb_FindObjectsInit = lg_FindObjectsInit;
|
||||
sdb->sdb_FindObjects = lg_FindObjects;
|
||||
sdb->sdb_FindObjectsFinal = lg_FindObjectsFinal;
|
||||
sdb->sdb_GetAttributeValue = lg_GetAttributeValue;
|
||||
sdb->sdb_SetAttributeValue = lg_SetAttributeValue;
|
||||
sdb->sdb_CreateObject = lg_CreateObject;
|
||||
sdb->sdb_DestroyObject = lg_DestroyObject;
|
||||
sdb->sdb_GetPWEntry = lg_GetPWEntry;
|
||||
sdb->sdb_PutPWEntry = lg_PutPWEntry;
|
||||
sdb->sdb_Begin = lg_Begin;
|
||||
sdb->sdb_Commit = lg_Commit;
|
||||
sdb->sdb_Abort = lg_Abort;
|
||||
sdb->sdb_Close = lg_Reset;
|
||||
sdb->sdb_Close = lg_Close;
|
||||
|
||||
|
||||
*pSdb = sdb;
|
||||
return CKR_OK;
|
||||
|
||||
loser:
|
||||
if (sdb) {
|
||||
PORT_Free(sdb);
|
||||
}
|
||||
if (lgdb_p) {
|
||||
if (lgdb_p->dbLock) {
|
||||
PR_DestroyLock(lgdb_p->dbLock);
|
||||
}
|
||||
if (lgdb_p->hashTable) {
|
||||
PL_HashTableDestroy(lgdb_p->hashTable);
|
||||
}
|
||||
PORT_Free(lgdb_p);
|
||||
}
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
extern SECStatus secoid_Init(void); /* util *REALLY* needs
|
||||
* to be a shared library */
|
||||
/*
|
||||
* OK there are now lots of options here, lets go through them all:
|
||||
*
|
||||
* configdir - base directory where all the cert, key, and module datbases live.
|
||||
* certPrefix - prefix added to the beginning of the cert database example: "
|
||||
* "https-server1-"
|
||||
* keyPrefix - prefix added to the beginning of the key database example: "
|
||||
* "https-server1-"
|
||||
* secmodName - name of the security module database (usually "secmod.db").
|
||||
* readOnly - Boolean: true if the databases are to be openned read only.
|
||||
* nocertdb - Don't open the cert DB and key DB's, just initialize the
|
||||
* Volatile certdb.
|
||||
* nomoddb - Don't open the security module DB, just initialize the
|
||||
* PKCS #11 module.
|
||||
* forceOpen - Continue to force initializations even if the databases cannot
|
||||
* be opened.
|
||||
*/
|
||||
CK_RV
|
||||
legacy_Open(const char *configdir, const char *certPrefix,
|
||||
const char *keyPrefix, int certVersion, int keyVersion,
|
||||
int flags, SDB **certDB, SDB **keyDB)
|
||||
{
|
||||
CK_RV crv = CKR_OK;
|
||||
PRBool readOnly = (flags == SDB_RDONLY)? PR_TRUE: PR_FALSE;
|
||||
|
||||
secoid_Init();
|
||||
nsslowcert_InitLocks();
|
||||
|
||||
if (keyDB) *keyDB = NULL;
|
||||
if (certDB) *certDB = NULL;
|
||||
|
||||
if (certDB) {
|
||||
NSSLOWCERTCertDBHandle *certdbPtr;
|
||||
|
||||
crv = lg_OpenCertDB(configdir, certPrefix, readOnly, &certdbPtr);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
crv = lg_init(certDB, flags, certdbPtr, NULL);
|
||||
if (crv != CKR_OK) {
|
||||
nsslowcert_ClosePermCertDB(certdbPtr);
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
if (keyDB) {
|
||||
NSSLOWKEYDBHandle *keydbPtr;
|
||||
|
||||
crv = lg_OpenKeyDB(configdir, keyPrefix, readOnly, &keydbPtr);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
crv = lg_init(keyDB, flags, NULL, keydbPtr);
|
||||
if (crv != CKR_OK) {
|
||||
nsslowkey_CloseKeyDB(keydbPtr);
|
||||
goto loser;
|
||||
}
|
||||
if (certDB && *certDB) {
|
||||
LGPrivate *lgdb_p = (LGPrivate *)(*certDB)->private;
|
||||
lgdb_p->keyDB = keydbPtr;
|
||||
}
|
||||
}
|
||||
|
||||
loser:
|
||||
if (crv != CKR_OK) {
|
||||
if (keyDB && *keyDB) {
|
||||
lg_Close(*keyDB);
|
||||
*keyDB = NULL;
|
||||
}
|
||||
if (certDB && *certDB) {
|
||||
lg_Close(*certDB);
|
||||
*certDB = NULL;
|
||||
}
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
legacy_Shutdown(void)
|
||||
{
|
||||
nsslowcert_DestroyFreeLists();
|
||||
nsslowcert_DestroyGlobalLocks();
|
||||
}
|
||||
423
mozilla/security/nss/lib/softoken/legacydb/lgutil.c
Normal file
423
mozilla/security/nss/lib/softoken/legacydb/lgutil.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "lgdb.h"
|
||||
#include "secerr.h"
|
||||
#include "lgglue.h"
|
||||
|
||||
/*
|
||||
* ******************** Attribute Utilities *******************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* look up and attribute structure from a type and Object structure.
|
||||
* The returned attribute is referenced and needs to be freed when
|
||||
* it is no longer needed.
|
||||
*/
|
||||
const CK_ATTRIBUTE *
|
||||
lg_FindAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < count; i++) {
|
||||
if (templ[i].type == type) {
|
||||
return &templ[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* return true if object has attribute
|
||||
*/
|
||||
PRBool
|
||||
lg_hasAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count )
|
||||
{
|
||||
if (lg_FindAttribute(type, templ, count) == NULL) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy an attribute into a SECItem. Secitem is allocated in the specified
|
||||
* arena.
|
||||
*/
|
||||
CK_RV
|
||||
lg_Attribute2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item)
|
||||
{
|
||||
int len;
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
len = attribute->ulValueLen;
|
||||
|
||||
if (arena) {
|
||||
item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
|
||||
} else {
|
||||
item->data = (unsigned char *) PORT_Alloc(len);
|
||||
}
|
||||
if (item->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
item->len = len;
|
||||
PORT_Memcpy(item->data, attribute->pValue, len);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* copy an unsigned attribute into a SECItem. Secitem is allocated in
|
||||
* the specified arena.
|
||||
*/
|
||||
CK_RV
|
||||
lg_Attribute2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
item->data = NULL;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
(void)SECITEM_AllocItem(arena, item, attribute->ulValueLen);
|
||||
if (item->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
PORT_Memcpy(item->data, attribute->pValue, item->len);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy an unsigned attribute into a SECItem. Secitem is allocated in
|
||||
* the specified arena.
|
||||
*/
|
||||
CK_RV
|
||||
lg_PrivAttr2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
SECItem epki, *dest = NULL;
|
||||
SECStatus rv;
|
||||
|
||||
item->data = NULL;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
epki.data = attribute->pValue;
|
||||
epki.len = attribute->ulValueLen;
|
||||
|
||||
rv = lg_util_decrypt(sdbpw, &epki, &dest);
|
||||
if (rv != SECSuccess) {
|
||||
return CKR_USER_NOT_LOGGED_IN;
|
||||
}
|
||||
(void)SECITEM_AllocItem(arena, item, dest->len);
|
||||
if (item->data == NULL) {
|
||||
SECITEM_FreeItem(dest, PR_TRUE);
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
|
||||
PORT_Memcpy(item->data, dest->data, item->len);
|
||||
SECITEM_FreeItem(dest, PR_TRUE);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_PrivAttr2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw)
|
||||
{
|
||||
return lg_PrivAttr2SSecItem(arena, type, templ, count, item, sdbpw);
|
||||
}
|
||||
|
||||
/*
|
||||
* this is only valid for CK_BBOOL type attributes. Return the state
|
||||
* of that attribute.
|
||||
*/
|
||||
PRBool
|
||||
lg_isTrue(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
PRBool tok = PR_FALSE;
|
||||
|
||||
attribute=lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) { return PR_FALSE; }
|
||||
tok = (PRBool)(*(CK_BBOOL *)attribute->pValue);
|
||||
|
||||
return tok;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a null terminated string from attribute 'type'. This string
|
||||
* is allocated and needs to be freed with PORT_Free() When complete.
|
||||
*/
|
||||
char *
|
||||
lg_getString(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
char *label = NULL;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return NULL;
|
||||
|
||||
if (attribute->pValue != NULL) {
|
||||
label = (char *) PORT_Alloc(attribute->ulValueLen+1);
|
||||
if (label == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PORT_Memcpy(label,attribute->pValue, attribute->ulValueLen);
|
||||
label[attribute->ulValueLen] = 0;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count, CK_ULONG *longData)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
CK_ULONG value = 0;
|
||||
const unsigned char *data;
|
||||
int i;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
if (attribute->ulValueLen != sizeof(CK_ULONG)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
data = (const unsigned char *)attribute->pValue;
|
||||
for (i=0; i < 4; i++) {
|
||||
value |= (CK_ULONG)(data[i]) << ((3-i)*8);
|
||||
}
|
||||
|
||||
*longData = value;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************** Object Utilities *******************************
|
||||
*/
|
||||
|
||||
SECStatus
|
||||
lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
|
||||
{
|
||||
SECItem *item;
|
||||
PRBool rem;
|
||||
PLHashTable *hashTable= lg_GetHashTable(sdb);
|
||||
|
||||
item = (SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
|
||||
rem = PL_HashTableRemove(hashTable,(void *)handle) ;
|
||||
if (rem && item) {
|
||||
SECITEM_FreeItem(item,PR_TRUE);
|
||||
}
|
||||
return rem ? SECSuccess : SECFailure;
|
||||
}
|
||||
|
||||
/* must be called holding lg_DBLock(sdb) */
|
||||
static SECStatus
|
||||
lg_addTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle, SECItem *key)
|
||||
{
|
||||
PLHashEntry *entry;
|
||||
SECItem *item;
|
||||
PLHashTable *hashTable= lg_GetHashTable(sdb);
|
||||
|
||||
item = SECITEM_DupItem(key);
|
||||
if (item == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
entry = PL_HashTableAdd(hashTable,(void *)handle,item);
|
||||
if (entry == NULL) {
|
||||
SECITEM_FreeItem(item,PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* must be called holding lg_DBLock(sdb) */
|
||||
const SECItem *
|
||||
lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
|
||||
{
|
||||
PLHashTable *hashTable= lg_GetHashTable(sdb);
|
||||
return (const SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
|
||||
}
|
||||
|
||||
|
||||
static PRIntn
|
||||
lg_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
|
||||
{
|
||||
SECItem *item = (SECItem *)entry->value;
|
||||
|
||||
SECITEM_FreeItem(item, PR_TRUE);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
LG_ClearTokenKeyHashTable(SDB *sdb)
|
||||
{
|
||||
lg_DBLock(sdb);
|
||||
PLHashTable *hashTable= lg_GetHashTable(sdb);
|
||||
PL_HashTableEnumerateEntries(hashTable, lg_freeHashItem, NULL);
|
||||
lg_DBLock(sdb);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle Token Object stuff
|
||||
*/
|
||||
static void
|
||||
lg_XORHash(unsigned char *key, unsigned char *dbkey, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
PORT_Memset(key, 0, 4);
|
||||
|
||||
for (i=0; i < len-4; i += 4) {
|
||||
key[0] ^= dbkey[i];
|
||||
key[1] ^= dbkey[i+1];
|
||||
key[2] ^= dbkey[i+2];
|
||||
key[3] ^= dbkey[i+3];
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a token handle for an object and record it so we can find it again */
|
||||
CK_OBJECT_HANDLE
|
||||
lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
|
||||
{
|
||||
unsigned char hashBuf[4];
|
||||
CK_OBJECT_HANDLE handle;
|
||||
const SECItem *key;
|
||||
|
||||
handle = class;
|
||||
/* there is only one KRL, use a fixed handle for it */
|
||||
if (handle != LG_TOKEN_KRL_HANDLE) {
|
||||
lg_XORHash(hashBuf,dbKey->data,dbKey->len);
|
||||
handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
|
||||
(hashBuf[2] << 8) | hashBuf[3];
|
||||
handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
|
||||
/* we have a CRL who's handle has randomly matched the reserved KRL
|
||||
* handle, increment it */
|
||||
if (handle == LG_TOKEN_KRL_HANDLE) {
|
||||
handle++;
|
||||
}
|
||||
}
|
||||
|
||||
lg_DBLock(sdb);
|
||||
while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
|
||||
if (SECITEM_ItemsAreEqual(key,dbKey)) {
|
||||
lg_DBUnlock(sdb);
|
||||
return handle;
|
||||
}
|
||||
handle++;
|
||||
}
|
||||
lg_addTokenKeyByHandle(sdb,handle,dbKey);
|
||||
lg_DBUnlock(sdb);
|
||||
return handle;
|
||||
}
|
||||
|
||||
PRBool
|
||||
lg_poisonHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
|
||||
{
|
||||
unsigned char hashBuf[4];
|
||||
CK_OBJECT_HANDLE handle;
|
||||
const SECItem *key;
|
||||
|
||||
handle = class;
|
||||
/* there is only one KRL, use a fixed handle for it */
|
||||
if (handle != LG_TOKEN_KRL_HANDLE) {
|
||||
lg_XORHash(hashBuf,dbKey->data,dbKey->len);
|
||||
handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
|
||||
(hashBuf[2] << 8) | hashBuf[3];
|
||||
handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
|
||||
/* we have a CRL who's handle has randomly matched the reserved KRL
|
||||
* handle, increment it */
|
||||
if (handle == LG_TOKEN_KRL_HANDLE) {
|
||||
handle++;
|
||||
}
|
||||
}
|
||||
lg_DBLock(sdb);
|
||||
while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
|
||||
if (SECITEM_ItemsAreEqual(key,dbKey)) {
|
||||
key->data[0] ^= 0x80;
|
||||
lg_DBUnlock(sdb);
|
||||
return PR_TRUE;
|
||||
}
|
||||
handle++;
|
||||
}
|
||||
lg_DBUnlock(sdb);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static LGEncryptFunc lg_encrypt_stub = NULL;
|
||||
static LGDecryptFunc lg_decrypt_stub = NULL;
|
||||
|
||||
void
|
||||
legacy_SetCryptFunctions(LGEncryptFunc enc, LGDecryptFunc dec)
|
||||
{
|
||||
lg_encrypt_stub = enc;
|
||||
lg_decrypt_stub = dec;
|
||||
}
|
||||
|
||||
SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdb,
|
||||
SECItem *plainText, SECItem **cipherText)
|
||||
{
|
||||
if (lg_encrypt_stub == NULL) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*lg_encrypt_stub)(arena, sdb, plainText, cipherText);
|
||||
}
|
||||
|
||||
SECStatus lg_util_decrypt(SDB *sdb, SECItem *cipherText, SECItem **plainText)
|
||||
{
|
||||
if (lg_decrypt_stub == NULL) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*lg_decrypt_stub)(sdb, cipherText, plainText);
|
||||
}
|
||||
|
||||
|
||||
618
mozilla/security/nss/lib/softoken/legacydb/lowcert.c
Normal file
618
mozilla/security/nss/lib/softoken/legacydb/lowcert.c
Normal file
@@ -0,0 +1,618 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Certificate handling code
|
||||
*
|
||||
* $Id: lowcert.c,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "secder.h"
|
||||
#include "nssilock.h"
|
||||
#include "lowkeyi.h"
|
||||
#include "secasn1.h"
|
||||
#include "secoid.h"
|
||||
#include "secerr.h"
|
||||
#include "pcert.h"
|
||||
|
||||
static 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, }
|
||||
};
|
||||
|
||||
static 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, }
|
||||
};
|
||||
static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), },
|
||||
{ 0, }
|
||||
};
|
||||
static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
/*
|
||||
* See bugzilla bug 125359
|
||||
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
|
||||
* all of the templates above that en/decode into integers must be converted
|
||||
* from ASN.1's signed integer type. This is done by marking either the
|
||||
* source or destination (encoding or decoding, respectively) type as
|
||||
* siUnsignedInteger.
|
||||
*/
|
||||
|
||||
static void
|
||||
prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
pubk->u.rsa.modulus.type = siUnsignedInteger;
|
||||
pubk->u.rsa.publicExponent.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_low_dsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
pubk->u.dsa.publicValue.type = siUnsignedInteger;
|
||||
pubk->u.dsa.params.prime.type = siUnsignedInteger;
|
||||
pubk->u.dsa.params.subPrime.type = siUnsignedInteger;
|
||||
pubk->u.dsa.params.base.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
pubk->u.dh.prime.type = siUnsignedInteger;
|
||||
pubk->u.dh.base.type = siUnsignedInteger;
|
||||
pubk->u.dh.publicValue.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
/*
|
||||
* simple cert decoder to avoid the cost of asn1 engine
|
||||
*/
|
||||
static unsigned char *
|
||||
nsslowcert_dataStart(unsigned char *buf, unsigned int length,
|
||||
unsigned int *data_length, PRBool includeTag,
|
||||
unsigned char* rettag) {
|
||||
unsigned char tag;
|
||||
unsigned int used_length= 0;
|
||||
|
||||
tag = buf[used_length++];
|
||||
|
||||
if (rettag) {
|
||||
*rettag = tag;
|
||||
}
|
||||
|
||||
/* blow out when we come to the end */
|
||||
if (tag == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*data_length = buf[used_length++];
|
||||
|
||||
if (*data_length&0x80) {
|
||||
int len_count = *data_length & 0x7f;
|
||||
|
||||
*data_length = 0;
|
||||
|
||||
while (len_count-- > 0) {
|
||||
*data_length = (*data_length << 8) | buf[used_length++];
|
||||
}
|
||||
}
|
||||
|
||||
if (*data_length > (length-used_length) ) {
|
||||
*data_length = length-used_length;
|
||||
return NULL;
|
||||
}
|
||||
if (includeTag) *data_length += used_length;
|
||||
|
||||
return (buf + (includeTag ? 0 : used_length));
|
||||
}
|
||||
|
||||
static void SetTimeType(SECItem* item, unsigned char tagtype)
|
||||
{
|
||||
switch (tagtype) {
|
||||
case SEC_ASN1_UTC_TIME:
|
||||
item->type = siUTCTime;
|
||||
break;
|
||||
|
||||
case SEC_ASN1_GENERALIZED_TIME:
|
||||
item->type = siGeneralizedTime;
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_Assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
|
||||
SECItem *notBefore, SECItem *notAfter)
|
||||
{
|
||||
unsigned char tagtype;
|
||||
notBefore->data = nsslowcert_dataStart(buf,buf_length,
|
||||
¬Before->len,PR_FALSE, &tagtype);
|
||||
if (notBefore->data == NULL) return SECFailure;
|
||||
SetTimeType(notBefore, tagtype);
|
||||
buf_length -= (notBefore->data-buf) + notBefore->len;
|
||||
buf = notBefore->data + notBefore->len;
|
||||
notAfter->data = nsslowcert_dataStart(buf,buf_length,
|
||||
¬After->len,PR_FALSE, &tagtype);
|
||||
if (notAfter->data == NULL) return SECFailure;
|
||||
SetTimeType(notAfter, tagtype);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static int
|
||||
nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
|
||||
SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
|
||||
SECItem *valid, SECItem *subjkey)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned int buf_length;
|
||||
unsigned char *dummy;
|
||||
unsigned int dummylen;
|
||||
|
||||
/* get past the signature wrap */
|
||||
buf = nsslowcert_dataStart(cert,cert_length,&buf_length,PR_FALSE, NULL);
|
||||
if (buf == NULL) return SECFailure;
|
||||
/* get into the raw cert data */
|
||||
buf = nsslowcert_dataStart(buf,buf_length,&buf_length,PR_FALSE, NULL);
|
||||
if (buf == NULL) return SECFailure;
|
||||
/* skip past any optional version number */
|
||||
if ((buf[0] & 0xa0) == 0xa0) {
|
||||
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
|
||||
if (dummy == NULL) return SECFailure;
|
||||
buf_length -= (dummy-buf) + dummylen;
|
||||
buf = dummy + dummylen;
|
||||
}
|
||||
/* serial number */
|
||||
if (derSN) {
|
||||
derSN->data=nsslowcert_dataStart(buf,buf_length,&derSN->len,PR_TRUE, NULL);
|
||||
}
|
||||
serial->data = nsslowcert_dataStart(buf,buf_length,&serial->len,PR_FALSE, NULL);
|
||||
if (serial->data == NULL) return SECFailure;
|
||||
buf_length -= (serial->data-buf) + serial->len;
|
||||
buf = serial->data + serial->len;
|
||||
/* skip the OID */
|
||||
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
|
||||
if (dummy == NULL) return SECFailure;
|
||||
buf_length -= (dummy-buf) + dummylen;
|
||||
buf = dummy + dummylen;
|
||||
/* issuer */
|
||||
issuer->data = nsslowcert_dataStart(buf,buf_length,&issuer->len,PR_TRUE, NULL);
|
||||
if (issuer->data == NULL) return SECFailure;
|
||||
buf_length -= (issuer->data-buf) + issuer->len;
|
||||
buf = issuer->data + issuer->len;
|
||||
|
||||
/* only wanted issuer/SN */
|
||||
if (valid == NULL) {
|
||||
return SECSuccess;
|
||||
}
|
||||
/* validity */
|
||||
valid->data = nsslowcert_dataStart(buf,buf_length,&valid->len,PR_FALSE, NULL);
|
||||
if (valid->data == NULL) return SECFailure;
|
||||
buf_length -= (valid->data-buf) + valid->len;
|
||||
buf = valid->data + valid->len;
|
||||
/*subject */
|
||||
subject->data=nsslowcert_dataStart(buf,buf_length,&subject->len,PR_TRUE, NULL);
|
||||
if (subject->data == NULL) return SECFailure;
|
||||
buf_length -= (subject->data-buf) + subject->len;
|
||||
buf = subject->data + subject->len;
|
||||
/* subject key info */
|
||||
subjkey->data=nsslowcert_dataStart(buf,buf_length,&subjkey->len,PR_TRUE, NULL);
|
||||
if (subjkey->data == NULL) return SECFailure;
|
||||
buf_length -= (subjkey->data-buf) + subjkey->len;
|
||||
buf = subjkey->data + subjkey->len;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
|
||||
{
|
||||
int rv;
|
||||
NSSLOWCERTValidity validity;
|
||||
|
||||
rv = nsslowcert_GetValidityFields(c->validity.data,c->validity.len,
|
||||
&validity.notBefore,&validity.notAfter);
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* convert DER not-before time */
|
||||
rv = DER_DecodeTimeChoice(notBefore, &validity.notBefore);
|
||||
if (rv) {
|
||||
return(SECFailure);
|
||||
}
|
||||
|
||||
/* convert DER not-after time */
|
||||
rv = DER_DecodeTimeChoice(notAfter, &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, ¬BeforeA, ¬AfterA);
|
||||
if ( rv != SECSuccess ) {
|
||||
return(PR_FALSE);
|
||||
}
|
||||
|
||||
rv = nsslowcert_GetCertTimes(certb, ¬BeforeB, ¬AfterB);
|
||||
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 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
|
||||
|
||||
static SECStatus
|
||||
nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena,
|
||||
SECItem *issuer, SECItem *sn, SECItem *key)
|
||||
{
|
||||
unsigned int len = sn->len + issuer->len;
|
||||
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto loser;
|
||||
}
|
||||
key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
|
||||
if ( !key->data ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
key->len = len;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
nsslowcert_KeyFromIssuerAndSNStatic(unsigned char *space,
|
||||
int spaceLen, SECItem *issuer, SECItem *sn, SECItem *key)
|
||||
{
|
||||
unsigned int len = sn->len + issuer->len;
|
||||
|
||||
key->data = pkcs11_allocStaticData(len, space, spaceLen);
|
||||
if ( !key->data ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
key->len = len;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* take a DER certificate and decode it into a certificate structure
|
||||
*/
|
||||
NSSLOWCERTCertificate *
|
||||
nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
|
||||
{
|
||||
NSSLOWCERTCertificate *cert;
|
||||
int rv;
|
||||
|
||||
/* allocate the certificate structure */
|
||||
cert = nsslowcert_CreateCert();
|
||||
|
||||
if ( !cert ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* point to passed in DER data */
|
||||
cert->derCert = *derSignedCert;
|
||||
cert->nickname = NULL;
|
||||
cert->certKey.data = NULL;
|
||||
cert->referenceCount = 1;
|
||||
|
||||
/* decode the certificate info */
|
||||
rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
|
||||
&cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
|
||||
&cert->validity, &cert->derSubjKeyInfo);
|
||||
|
||||
/* cert->subjectKeyID; x509v3 subject key identifier */
|
||||
cert->subjectKeyID.data = NULL;
|
||||
cert->subjectKeyID.len = 0;
|
||||
cert->dbEntry = NULL;
|
||||
cert ->trust = NULL;
|
||||
cert ->dbhandle = NULL;
|
||||
|
||||
/* generate and save the database key for the cert */
|
||||
rv = nsslowcert_KeyFromIssuerAndSNStatic(cert->certKeySpace,
|
||||
sizeof(cert->certKeySpace), &cert->derIssuer,
|
||||
&cert->serialNumber, &cert->certKey);
|
||||
if ( rv ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* set the nickname */
|
||||
if ( nickname == NULL ) {
|
||||
cert->nickname = NULL;
|
||||
} else {
|
||||
/* copy and install the nickname */
|
||||
cert->nickname = pkcs11_copyNickname(nickname,cert->nicknameSpace,
|
||||
sizeof(cert->nicknameSpace));
|
||||
}
|
||||
|
||||
#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 (cert) {
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
NSSLOWCERTCertKey certkey;
|
||||
|
||||
PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
|
||||
|
||||
rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
|
||||
&certkey.derIssuer, &certkey.serialNumber, NULL, NULL, NULL, NULL);
|
||||
|
||||
if ( rv ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
|
||||
&certkey.serialNumber, key));
|
||||
loser:
|
||||
return(SECFailure);
|
||||
}
|
||||
|
||||
NSSLOWKEYPublicKey *
|
||||
nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
|
||||
{
|
||||
NSSLOWCERTSubjectPublicKeyInfo spki;
|
||||
NSSLOWKEYPublicKey *pubk;
|
||||
SECItem os;
|
||||
SECStatus rv;
|
||||
PRArenaPool *arena;
|
||||
SECOidTag tag;
|
||||
SECItem newDerSubjKeyInfo;
|
||||
|
||||
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;
|
||||
PORT_Memset(&spki,0,sizeof(spki));
|
||||
|
||||
/* copy the DER into the arena, since Quick DER returns data that points
|
||||
into the DER input, which may get freed by the caller */
|
||||
rv = SECITEM_CopyItem(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo);
|
||||
if ( rv != SECSuccess ) {
|
||||
PORT_FreeArena (arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* we haven't bothered decoding the spki struct yet, do it now */
|
||||
rv = SEC_QuickDERDecodeItem(arena, &spki,
|
||||
nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_FreeArena (arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
prepare_low_rsa_pub_key_for_asn1(pubk);
|
||||
rv = SEC_QuickDERDecodeItem(arena, pubk,
|
||||
nsslowcert_RSAPublicKeyTemplate, &os);
|
||||
if (rv == SECSuccess)
|
||||
return pubk;
|
||||
break;
|
||||
case SEC_OID_ANSIX9_DSA_SIGNATURE:
|
||||
pubk->keyType = NSSLOWKEYDSAKey;
|
||||
prepare_low_dsa_pub_key_for_asn1(pubk);
|
||||
rv = SEC_QuickDERDecodeItem(arena, pubk,
|
||||
nsslowcert_DSAPublicKeyTemplate, &os);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
break;
|
||||
case SEC_OID_X942_DIFFIE_HELMAN_KEY:
|
||||
pubk->keyType = NSSLOWKEYDHKey;
|
||||
prepare_low_dh_pub_key_for_asn1(pubk);
|
||||
rv = SEC_QuickDERDecodeItem(arena, pubk,
|
||||
nsslowcert_DHPublicKeyTemplate, &os);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
break;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
|
||||
pubk->keyType = NSSLOWKEYECKey;
|
||||
/* Since PKCS#11 directly takes the DER encoding of EC params
|
||||
* and public value, we don't need any decoding here.
|
||||
*/
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding,
|
||||
&spki.algorithm.parameters);
|
||||
if ( rv != SECSuccess )
|
||||
break;
|
||||
|
||||
/* Fill out the rest of the ecParams structure
|
||||
* based on the encoded params
|
||||
*/
|
||||
if (LGEC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
|
||||
&pubk->u.ec.ecParams) != SECSuccess)
|
||||
break;
|
||||
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
default:
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
nsslowkey_DestroyPublicKey (pubk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
462
mozilla/security/nss/lib/softoken/legacydb/lowkey.c
Normal file
462
mozilla/security/nss/lib/softoken/legacydb/lowkey.c
Normal file
@@ -0,0 +1,462 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "lowkeyi.h"
|
||||
#include "secoid.h"
|
||||
#include "secitem.h"
|
||||
#include "secder.h"
|
||||
#include "secasn1.h"
|
||||
#include "secerr.h"
|
||||
|
||||
static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(NSSLOWKEYAttribute) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
|
||||
{ SEC_ASN1_SET_OF, offsetof(NSSLOWKEYAttribute, attrValue),
|
||||
SEC_AnyTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
|
||||
{ SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
|
||||
};
|
||||
/* ASN1 Templates for new decoder/encoder */
|
||||
const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
|
||||
{ SEC_ASN1_INTEGER,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo,version) },
|
||||
{ SEC_ASN1_INLINE,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
|
||||
SECOID_AlgorithmIDTemplate },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
|
||||
nsslowkey_SetOfAttributeTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
/* XXX This is just a placeholder for later when we support
|
||||
* generic curves and need full-blown support for parsing EC
|
||||
* parameters. For now, we only support named curves in which
|
||||
* EC params are simply encoded as an object ID and we don't
|
||||
* use nsslowkey_ECParamsTemplate.
|
||||
*/
|
||||
const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = {
|
||||
{ SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
||||
/* NOTE: The SECG specification allows the private key structure
|
||||
* to contain curve parameters but recommends that they be stored
|
||||
* in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
|
||||
* instead.
|
||||
*/
|
||||
const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
|
||||
/* XXX The following template works for now since we only
|
||||
* support named curves for which the parameters are
|
||||
* encoded as an object ID. When we support generic curves,
|
||||
* we'll need to define nsslowkey_ECParamsTemplate
|
||||
*/
|
||||
#if 1
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID),
|
||||
SEC_ObjectIDTemplate },
|
||||
#else
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams),
|
||||
nsslowkey_ECParamsTemplate },
|
||||
#endif
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
|
||||
SEC_BitStringTemplate },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* smaller version of EC_FillParams. In this code, we only need
|
||||
* oid and DER data.
|
||||
*/
|
||||
SECStatus
|
||||
LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
|
||||
ECParams *params)
|
||||
{
|
||||
SECOidTag tag;
|
||||
SECItem oid = { siBuffer, NULL, 0};
|
||||
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
|
||||
printf("Encoded params in EC_DecodeParams: ");
|
||||
for (i = 0; i < encodedParams->len; i++) {
|
||||
printf("%02x:", encodedParams->data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
oid.len = encodedParams->len - 2;
|
||||
oid.data = encodedParams->data + 2;
|
||||
if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
|
||||
((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
params->arena = arena;
|
||||
|
||||
/* For named curves, fill out curveOID */
|
||||
params->curveOID.len = oid.len;
|
||||
params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
|
||||
if (params->curveOID.data == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
memcpy(params->curveOID.data, oid.data, oid.len);
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Copy all of the fields from srcParams into dstParams
|
||||
*/
|
||||
SECStatus
|
||||
LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
|
||||
const ECParams *srcParams)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
dstParams->arena = arena;
|
||||
rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding,
|
||||
&srcParams->DEREncoding);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
rv =SECITEM_CopyItem(arena, &dstParams->curveOID,
|
||||
&srcParams->curveOID);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
return SECFailure;
|
||||
}
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
/*
|
||||
* See bugzilla bug 125359
|
||||
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
|
||||
* all of the templates above that en/decode into integers must be converted
|
||||
* from ASN.1's signed integer type. This is done by marking either the
|
||||
* source or destination (encoding or decoding, respectively) type as
|
||||
* siUnsignedInteger.
|
||||
*/
|
||||
|
||||
void
|
||||
prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.rsa.modulus.type = siUnsignedInteger;
|
||||
key->u.rsa.publicExponent.type = siUnsignedInteger;
|
||||
key->u.rsa.privateExponent.type = siUnsignedInteger;
|
||||
key->u.rsa.prime1.type = siUnsignedInteger;
|
||||
key->u.rsa.prime2.type = siUnsignedInteger;
|
||||
key->u.rsa.exponent1.type = siUnsignedInteger;
|
||||
key->u.rsa.exponent2.type = siUnsignedInteger;
|
||||
key->u.rsa.coefficient.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_pqg_params_for_asn1(PQGParams *params)
|
||||
{
|
||||
params->prime.type = siUnsignedInteger;
|
||||
params->subPrime.type = siUnsignedInteger;
|
||||
params->base.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.dsa.publicValue.type = siUnsignedInteger;
|
||||
key->u.dsa.privateValue.type = siUnsignedInteger;
|
||||
key->u.dsa.params.prime.type = siUnsignedInteger;
|
||||
key->u.dsa.params.subPrime.type = siUnsignedInteger;
|
||||
key->u.dsa.params.base.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.dsa.privateValue.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.dh.prime.type = siUnsignedInteger;
|
||||
key->u.dh.base.type = siUnsignedInteger;
|
||||
key->u.dh.publicValue.type = siUnsignedInteger;
|
||||
key->u.dh.privateValue.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
void
|
||||
prepare_low_ecparams_for_asn1(ECParams *params)
|
||||
{
|
||||
params->DEREncoding.type = siUnsignedInteger;
|
||||
params->curveOID.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.ec.version.type = siUnsignedInteger;
|
||||
key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
|
||||
key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
|
||||
key->u.ec.privateValue.type = siUnsignedInteger;
|
||||
key->u.ec.publicValue.type = siUnsignedInteger;
|
||||
}
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
void
|
||||
nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
if (privk && privk->arena) {
|
||||
PORT_FreeArena(privk->arena, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
if (pubk && pubk->arena) {
|
||||
PORT_FreeArena(pubk->arena, PR_FALSE);
|
||||
}
|
||||
}
|
||||
unsigned
|
||||
nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
unsigned char b0;
|
||||
|
||||
/* interpret modulus length as key strength... in
|
||||
* fortezza that's the public key length */
|
||||
|
||||
switch (pubk->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
b0 = pubk->u.rsa.modulus.data[0];
|
||||
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
|
||||
unsigned char b0;
|
||||
|
||||
switch (privk->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
b0 = privk->u.rsa.modulus.data[0];
|
||||
return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
NSSLOWKEYPublicKey *
|
||||
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
NSSLOWKEYPublicKey *pubk;
|
||||
PLArenaPool *arena;
|
||||
|
||||
|
||||
arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
PORT_SetError (SEC_ERROR_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch(privk->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
case NSSLOWKEYNullKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof (NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
if (privk->keyType == NSSLOWKEYNullKey) return pubk;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
|
||||
&privk->u.rsa.modulus);
|
||||
if (rv == SECSuccess) {
|
||||
rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
|
||||
&privk->u.rsa.publicExponent);
|
||||
if (rv == SECSuccess)
|
||||
return pubk;
|
||||
}
|
||||
} else {
|
||||
PORT_SetError (SEC_ERROR_NO_MEMORY);
|
||||
}
|
||||
break;
|
||||
case NSSLOWKEYDSAKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
|
||||
&privk->u.dsa.publicValue);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
|
||||
&privk->u.dsa.params.prime);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
|
||||
&privk->u.dsa.params.subPrime);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
|
||||
&privk->u.dsa.params.base);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
}
|
||||
break;
|
||||
case NSSLOWKEYDHKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
|
||||
&privk->u.dh.publicValue);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
|
||||
&privk->u.dh.prime);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
|
||||
&privk->u.dh.base);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
}
|
||||
break;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case NSSLOWKEYECKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
|
||||
&privk->u.ec.publicValue);
|
||||
if (rv != SECSuccess) break;
|
||||
pubk->u.ec.ecParams.arena = arena;
|
||||
/* Copy the rest of the params */
|
||||
rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams),
|
||||
&(privk->u.ec.ecParams));
|
||||
if (rv == SECSuccess) return pubk;
|
||||
}
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
/* No Fortezza in Low Key implementations (Fortezza keys aren't
|
||||
* stored in our data base */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
PORT_FreeArena (arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
198
mozilla/security/nss/lib/softoken/legacydb/lowkeyi.h
Normal file
198
mozilla/security/nss/lib/softoken/legacydb/lowkeyi.h
Normal file
@@ -0,0 +1,198 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: lowkeyi.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifndef _LOWKEYI_H_
|
||||
#define _LOWKEYI_H_
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "pcertt.h"
|
||||
#include "lowkeyti.h"
|
||||
#include "sdb.h"
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/*
|
||||
* See bugzilla bug 125359
|
||||
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
|
||||
* all of the templates above that en/decode into integers must be converted
|
||||
* from ASN.1's signed integer type. This is done by marking either the
|
||||
* source or destination (encoding or decoding, respectively) type as
|
||||
* siUnsignedInteger.
|
||||
*/
|
||||
extern void prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_pqg_params_for_asn1(PQGParams *params);
|
||||
extern void prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
extern void prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_ecparams_for_asn1(ECParams *params);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion);
|
||||
|
||||
/*
|
||||
** Open a key database.
|
||||
*/
|
||||
extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDB(PRBool readOnly,
|
||||
const char *domain,
|
||||
const char *prefix,
|
||||
NSSLOWKEYDBNameFunc namecb,
|
||||
void *cbarg);
|
||||
|
||||
/*
|
||||
** Close the specified key database.
|
||||
*/
|
||||
extern void nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle);
|
||||
|
||||
/*
|
||||
* Get the version number of the database
|
||||
*/
|
||||
extern int nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle);
|
||||
|
||||
/*
|
||||
** Delete a key from the database
|
||||
*/
|
||||
extern SECStatus nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle,
|
||||
const SECItem *pubkey);
|
||||
|
||||
/*
|
||||
** Store a key in the database, indexed by its public key modulus.
|
||||
** "pk" is the private key to store
|
||||
** "f" is a the callback function for getting the password
|
||||
** "arg" is the argument for the callback
|
||||
*/
|
||||
extern SECStatus nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWKEYPrivateKey *pk,
|
||||
SECItem *pubKeyData,
|
||||
char *nickname,
|
||||
SDB *sdb);
|
||||
|
||||
/* does the key for this cert exist in the database filed by modulus */
|
||||
extern PRBool nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWCERTCertificate *cert);
|
||||
/* does a key with this ID already exist? */
|
||||
extern PRBool nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id);
|
||||
|
||||
/*
|
||||
** Destroy a private key object.
|
||||
** "key" the object
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *key);
|
||||
|
||||
/*
|
||||
** Destroy a public key object.
|
||||
** "key" the object
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *key);
|
||||
|
||||
/*
|
||||
** Return the modulus length of "pubKey".
|
||||
*/
|
||||
extern unsigned int nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubKey);
|
||||
|
||||
|
||||
/*
|
||||
** Return the modulus length of "privKey".
|
||||
*/
|
||||
extern unsigned int nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privKey);
|
||||
|
||||
|
||||
/*
|
||||
** Convert a low private key "privateKey" into a public low key
|
||||
*/
|
||||
extern NSSLOWKEYPublicKey
|
||||
*nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privateKey);
|
||||
|
||||
|
||||
SECStatus
|
||||
nsslowkey_UpdateNickname(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWKEYPrivateKey *privkey,
|
||||
SECItem *pubKeyData,
|
||||
char *nickname,
|
||||
SDB *sdb);
|
||||
|
||||
/* Store key by modulus and specify an encryption algorithm to use.
|
||||
* handle is the pointer to the key database,
|
||||
* privkey is the private key to be stored,
|
||||
* f and arg are the function and arguments to the callback
|
||||
* to get a password,
|
||||
* algorithm is the algorithm which the privKey is to be stored.
|
||||
* A return of anything but SECSuccess indicates failure.
|
||||
*/
|
||||
extern SECStatus
|
||||
nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWKEYPrivateKey *privkey,
|
||||
SECItem *pubKeyData,
|
||||
char *nickname,
|
||||
SDB *sdb,
|
||||
PRBool update);
|
||||
|
||||
/* Find key by modulus. This function is the inverse of store key
|
||||
* by modulus. An attempt to locate the key with "modulus" is
|
||||
* performed. If the key is found, the private key is returned,
|
||||
* else NULL is returned.
|
||||
* modulus is the modulus to locate
|
||||
*/
|
||||
extern NSSLOWKEYPrivateKey *
|
||||
nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
|
||||
SDB *sdb);
|
||||
|
||||
extern char *
|
||||
nsslowkey_FindKeyNicknameByPublicKey(NSSLOWKEYDBHandle *handle,
|
||||
SECItem *modulus, SDB *sdb);
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
/*
|
||||
* smaller version of EC_FillParams. In this code, we only need
|
||||
* oid and DER data.
|
||||
*/
|
||||
SECStatus LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
|
||||
ECParams *params);
|
||||
|
||||
/* Copy all of the fields from srcParams into dstParams */
|
||||
SECStatus LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
|
||||
const ECParams *srcParams);
|
||||
#endif
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _LOWKEYI_H_ */
|
||||
161
mozilla/security/nss/lib/softoken/legacydb/lowkeyti.h
Normal file
161
mozilla/security/nss/lib/softoken/legacydb/lowkeyti.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef _LOWKEYTI_H_
|
||||
#define _LOWKEYTI_H_ 1
|
||||
|
||||
#include "blapit.h"
|
||||
#include "prtypes.h"
|
||||
#include "plarena.h"
|
||||
#include "secitem.h"
|
||||
#include "secasn1t.h"
|
||||
#include "secoidt.h"
|
||||
|
||||
|
||||
/*
|
||||
* a key in/for the data base
|
||||
*/
|
||||
struct NSSLOWKEYDBKeyStr {
|
||||
PLArenaPool *arena;
|
||||
int version;
|
||||
char *nickname;
|
||||
SECItem salt;
|
||||
SECItem derPK;
|
||||
};
|
||||
typedef struct NSSLOWKEYDBKeyStr NSSLOWKEYDBKey;
|
||||
|
||||
typedef struct NSSLOWKEYDBHandleStr NSSLOWKEYDBHandle;
|
||||
|
||||
#ifdef NSS_USE_KEY4_DB
|
||||
#define NSSLOWKEY_DB_FILE_VERSION 4
|
||||
#else
|
||||
#define NSSLOWKEY_DB_FILE_VERSION 3
|
||||
#endif
|
||||
|
||||
#define NSSLOWKEY_VERSION 0 /* what we *create* */
|
||||
|
||||
/*
|
||||
** Typedef for callback to get a password "key".
|
||||
*/
|
||||
extern const SEC_ASN1Template nsslowkey_PQGParamsTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyExportTemplate[];
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
#define NSSLOWKEY_EC_PRIVATE_KEY_VERSION 1 /* as per SECG 1 C.4 */
|
||||
extern const SEC_ASN1Template nsslowkey_ECParamsTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[];
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[];
|
||||
|
||||
/*
|
||||
* PKCS #8 attributes
|
||||
*/
|
||||
struct NSSLOWKEYAttributeStr {
|
||||
SECItem attrType;
|
||||
SECItem *attrValue;
|
||||
};
|
||||
typedef struct NSSLOWKEYAttributeStr NSSLOWKEYAttribute;
|
||||
|
||||
/*
|
||||
** A PKCS#8 private key info object
|
||||
*/
|
||||
struct NSSLOWKEYPrivateKeyInfoStr {
|
||||
PLArenaPool *arena;
|
||||
SECItem version;
|
||||
SECAlgorithmID algorithm;
|
||||
SECItem privateKey;
|
||||
NSSLOWKEYAttribute **attributes;
|
||||
};
|
||||
typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo;
|
||||
#define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */
|
||||
|
||||
/*
|
||||
** A PKCS#8 private key info object
|
||||
*/
|
||||
struct NSSLOWKEYEncryptedPrivateKeyInfoStr {
|
||||
PLArenaPool *arena;
|
||||
SECAlgorithmID algorithm;
|
||||
SECItem encryptedData;
|
||||
};
|
||||
typedef struct NSSLOWKEYEncryptedPrivateKeyInfoStr NSSLOWKEYEncryptedPrivateKeyInfo;
|
||||
|
||||
|
||||
typedef enum {
|
||||
NSSLOWKEYNullKey = 0,
|
||||
NSSLOWKEYRSAKey = 1,
|
||||
NSSLOWKEYDSAKey = 2,
|
||||
NSSLOWKEYDHKey = 4,
|
||||
NSSLOWKEYECKey = 5
|
||||
} NSSLOWKEYType;
|
||||
|
||||
/*
|
||||
** An RSA public key object.
|
||||
*/
|
||||
struct NSSLOWKEYPublicKeyStr {
|
||||
PLArenaPool *arena;
|
||||
NSSLOWKEYType keyType ;
|
||||
union {
|
||||
RSAPublicKey rsa;
|
||||
DSAPublicKey dsa;
|
||||
DHPublicKey dh;
|
||||
ECPublicKey ec;
|
||||
} u;
|
||||
};
|
||||
typedef struct NSSLOWKEYPublicKeyStr NSSLOWKEYPublicKey;
|
||||
|
||||
/*
|
||||
** Low Level private key object
|
||||
** This is only used by the raw Crypto engines (crypto), keydb (keydb),
|
||||
** and PKCS #11. Everyone else uses the high level key structure.
|
||||
*/
|
||||
struct NSSLOWKEYPrivateKeyStr {
|
||||
PLArenaPool *arena;
|
||||
NSSLOWKEYType keyType;
|
||||
union {
|
||||
RSAPrivateKey rsa;
|
||||
DSAPrivateKey dsa;
|
||||
DHPrivateKey dh;
|
||||
ECPrivateKey ec;
|
||||
} u;
|
||||
};
|
||||
typedef struct NSSLOWKEYPrivateKeyStr NSSLOWKEYPrivateKey;
|
||||
|
||||
#endif /* _LOWKEYTI_H_ */
|
||||
261
mozilla/security/nss/lib/softoken/legacydb/pcert.h
Normal file
261
mozilla/security/nss/lib/softoken/legacydb/pcert.h
Normal file
@@ -0,0 +1,261 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _PCERTDB_H_
|
||||
#define _PCERTDB_H_
|
||||
|
||||
#include "plarena.h"
|
||||
#include "prlong.h"
|
||||
#include "pcertt.h"
|
||||
|
||||
#include "lowkeyti.h" /* for struct NSSLOWKEYPublicKeyStr */
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/*
|
||||
* initialize any global certificate locks
|
||||
*/
|
||||
SECStatus nsslowcert_InitLocks(void);
|
||||
|
||||
/*
|
||||
** 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_AddPermNickname(NSSLOWCERTCertDBHandle *dbhandle,
|
||||
NSSLOWCERTCertificate *cert, char *nickname);
|
||||
|
||||
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);
|
||||
|
||||
certDBEntryRevocation *
|
||||
nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle,
|
||||
SECItem *crlKey, PRBool isKRL);
|
||||
|
||||
SECStatus
|
||||
nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle,const 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);
|
||||
void nsslowcert_DestroyTrust(NSSLOWCERTTrust *Trust);
|
||||
|
||||
/*
|
||||
* 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, const SECItem *certKey);
|
||||
|
||||
/*
|
||||
* Lookup trust for 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.
|
||||
*/
|
||||
NSSLOWCERTTrust *
|
||||
nsslowcert_FindTrustByKey(NSSLOWCERTCertDBHandle *handle, const 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);
|
||||
|
||||
/*
|
||||
** 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 NSSLOWCERTTrust *
|
||||
nsslowcert_FindTrustByIssuerAndSN (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, 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,
|
||||
const char *domain, const char *prefix,
|
||||
NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile);
|
||||
|
||||
void
|
||||
nsslowcert_ClosePermCertDB(NSSLOWCERTCertDBHandle *handle);
|
||||
|
||||
/*
|
||||
* is certa newer than certb? If one is expired, pick the other one.
|
||||
*/
|
||||
PRBool
|
||||
nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb);
|
||||
|
||||
|
||||
SECStatus
|
||||
nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle,
|
||||
certDBEntryType type,
|
||||
SECStatus (* callback)(SECItem *data, SECItem *key,
|
||||
certDBEntryType type, void *pdata),
|
||||
void *udata );
|
||||
SECStatus
|
||||
nsslowcert_TraversePermCertsForSubject(NSSLOWCERTCertDBHandle *handle,
|
||||
SECItem *derSubject,
|
||||
NSSLOWCERTCertCallback cb, void *cbarg);
|
||||
int
|
||||
nsslowcert_NumPermCertsForSubject(NSSLOWCERTCertDBHandle *handle,
|
||||
SECItem *derSubject);
|
||||
SECStatus
|
||||
nsslowcert_TraversePermCertsForNickname(NSSLOWCERTCertDBHandle *handle,
|
||||
char *nickname, NSSLOWCERTCertCallback cb, void *cbarg);
|
||||
|
||||
int
|
||||
nsslowcert_NumPermCertsForNickname(NSSLOWCERTCertDBHandle *handle,
|
||||
char *nickname);
|
||||
SECStatus
|
||||
nsslowcert_GetCertTrust(NSSLOWCERTCertificate *cert,
|
||||
NSSLOWCERTCertTrust *trust);
|
||||
|
||||
SECStatus
|
||||
nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr,
|
||||
SECItem *derSubject, SECItem *emailProfile, SECItem *profileTime);
|
||||
|
||||
/*
|
||||
* Change the trust attributes of a certificate and make them permanent
|
||||
* in the database.
|
||||
*/
|
||||
SECStatus
|
||||
nsslowcert_ChangeCertTrust(NSSLOWCERTCertDBHandle *handle,
|
||||
NSSLOWCERTCertificate *cert, NSSLOWCERTCertTrust *trust);
|
||||
|
||||
PRBool
|
||||
nsslowcert_needDBVerify(NSSLOWCERTCertDBHandle *handle);
|
||||
|
||||
void
|
||||
nsslowcert_setDBVerify(NSSLOWCERTCertDBHandle *handle, PRBool value);
|
||||
|
||||
PRBool
|
||||
nsslowcert_hasTrust(NSSLOWCERTCertTrust *trust);
|
||||
|
||||
void
|
||||
nsslowcert_DestroyFreeLists(void);
|
||||
|
||||
void
|
||||
nsslowcert_DestroyGlobalLocks(void);
|
||||
|
||||
void
|
||||
pkcs11_freeNickname(char *nickname, char *space);
|
||||
|
||||
char *
|
||||
pkcs11_copyNickname(char *nickname, char *space, int spaceLen);
|
||||
|
||||
void
|
||||
pkcs11_freeStaticData(unsigned char *data, unsigned char *space);
|
||||
|
||||
unsigned char *
|
||||
pkcs11_allocStaticData(int datalen, unsigned char *space, int spaceLen);
|
||||
|
||||
unsigned char *
|
||||
pkcs11_copyStaticData(unsigned char *data, int datalen, unsigned char *space,
|
||||
int spaceLen);
|
||||
NSSLOWCERTCertificate *
|
||||
nsslowcert_CreateCert(void);
|
||||
|
||||
certDBEntry *
|
||||
nsslowcert_DecodeAnyDBEntry(SECItem *dbData, const SECItem *dbKey,
|
||||
certDBEntryType entryType, void *pdata);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _PCERTDB_H_ */
|
||||
5362
mozilla/security/nss/lib/softoken/legacydb/pcertdb.c
Normal file
5362
mozilla/security/nss/lib/softoken/legacydb/pcertdb.c
Normal file
File diff suppressed because it is too large
Load Diff
448
mozilla/security/nss/lib/softoken/legacydb/pcertt.h
Normal file
448
mozilla/security/nss/lib/softoken/legacydb/pcertt.h
Normal file
@@ -0,0 +1,448 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* certt.h - public data structures for the certificate library
|
||||
*
|
||||
* $Id: pcertt.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
#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 NSSLOWCERTTrustStr NSSLOWCERTTrust;
|
||||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
** PKCS11 Trust representation
|
||||
*/
|
||||
struct NSSLOWCERTTrustStr {
|
||||
NSSLOWCERTTrust *next;
|
||||
NSSLOWCERTCertDBHandle *dbhandle;
|
||||
SECItem dbKey; /* database key for this cert */
|
||||
certDBEntryCert *dbEntry; /* database entry struct */
|
||||
NSSLOWCERTCertTrust *trust;
|
||||
SECItem *derCert; /* original DER for the cert */
|
||||
unsigned char dbKeySpace[512];
|
||||
};
|
||||
|
||||
/*
|
||||
** 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
|
||||
*/
|
||||
NSSLOWCERTCertificate *next;
|
||||
NSSLOWCERTCertDBHandle *dbhandle;
|
||||
|
||||
SECItem derCert; /* original DER for the cert */
|
||||
SECItem derIssuer; /* DER for issuer name */
|
||||
SECItem derSN;
|
||||
SECItem serialNumber;
|
||||
SECItem derSubject; /* DER for subject name */
|
||||
SECItem derSubjKeyInfo;
|
||||
NSSLOWCERTSubjectPublicKeyInfo *subjectPublicKeyInfo;
|
||||
SECItem certKey; /* database key for this cert */
|
||||
SECItem 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;
|
||||
|
||||
char nicknameSpace[200];
|
||||
unsigned char certKeySpace[512];
|
||||
};
|
||||
|
||||
#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 */
|
||||
|
||||
/*
|
||||
* Certificate Database related definitions and data structures
|
||||
*/
|
||||
|
||||
/* version number of certificate database */
|
||||
#define CERT_DB_FILE_VERSION 8
|
||||
#define CERT_DB_V7_FILE_VERSION 7
|
||||
#define CERT_DB_CONTENT_VERSION 2
|
||||
|
||||
#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,
|
||||
certDBEntryTypeBlob = 8
|
||||
} 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;
|
||||
certDBEntryCert *next;
|
||||
NSSLOWCERTCertTrust trust;
|
||||
SECItem derCert;
|
||||
char *nickname;
|
||||
char nicknameSpace[200];
|
||||
unsigned char derCertSpace[2048];
|
||||
};
|
||||
|
||||
/*
|
||||
* 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;
|
||||
SECItem *certKeys;
|
||||
SECItem *keyIDs;
|
||||
char **emailAddrs;
|
||||
unsigned int nemailAddrs;
|
||||
} 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;
|
||||
certDBEntryCert cert;
|
||||
certDBEntryContentVersion content;
|
||||
certDBEntryNickname nickname;
|
||||
certDBEntryRevocation revocation;
|
||||
certDBEntrySMime smime;
|
||||
certDBEntrySubject subject;
|
||||
certDBEntryVersion version;
|
||||
} 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_ */
|
||||
773
mozilla/security/nss/lib/softoken/legacydb/pk11db.c
Normal file
773
mozilla/security/nss/lib/softoken/legacydb/pk11db.c
Normal file
@@ -0,0 +1,773 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* The following code handles the storage of PKCS 11 modules used by the
|
||||
* NSS. This file is written to abstract away how the modules are
|
||||
* stored so we can deside that later.
|
||||
*/
|
||||
|
||||
#include "pk11pars.h"
|
||||
#include "lgdb.h"
|
||||
#include "mcom_db.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
|
||||
|
||||
/* Construct a database key for a given module */
|
||||
static SECStatus secmod_MakeKey(DBT *key, char * module) {
|
||||
int len = 0;
|
||||
char *commonName;
|
||||
|
||||
commonName = secmod_argGetParamValue("name",module);
|
||||
if (commonName == NULL) {
|
||||
commonName = secmod_argGetParamValue("library",module);
|
||||
}
|
||||
if (commonName == NULL) return SECFailure;
|
||||
len = PORT_Strlen(commonName);
|
||||
key->data = commonName;
|
||||
key->size = len;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* free out constructed database key */
|
||||
static void
|
||||
secmod_FreeKey(DBT *key)
|
||||
{
|
||||
if (key->data) {
|
||||
PORT_Free(key->data);
|
||||
}
|
||||
key->data = NULL;
|
||||
key->size = 0;
|
||||
}
|
||||
|
||||
typedef struct secmodDataStr secmodData;
|
||||
typedef struct secmodSlotDataStr secmodSlotData;
|
||||
struct secmodDataStr {
|
||||
unsigned char major;
|
||||
unsigned char minor;
|
||||
unsigned char nameStart[2];
|
||||
unsigned char slotOffset[2];
|
||||
unsigned char internal;
|
||||
unsigned char fips;
|
||||
unsigned char ssl[8];
|
||||
unsigned char trustOrder[4];
|
||||
unsigned char cipherOrder[4];
|
||||
unsigned char reserved1;
|
||||
unsigned char isModuleDB;
|
||||
unsigned char isModuleDBOnly;
|
||||
unsigned char isCritical;
|
||||
unsigned char reserved[4];
|
||||
unsigned char names[6]; /* enough space for the length fields */
|
||||
};
|
||||
|
||||
struct secmodSlotDataStr {
|
||||
unsigned char slotID[4];
|
||||
unsigned char defaultFlags[4];
|
||||
unsigned char timeout[4];
|
||||
unsigned char askpw;
|
||||
unsigned char hasRootCerts;
|
||||
unsigned char reserved[18]; /* this makes it a round 32 bytes */
|
||||
};
|
||||
|
||||
#define SECMOD_DB_VERSION_MAJOR 0
|
||||
#define SECMOD_DB_VERSION_MINOR 6
|
||||
#define SECMOD_DB_EXT1_VERSION_MAJOR 0
|
||||
#define SECMOD_DB_EXT1_VERSION_MINOR 6
|
||||
#define SECMOD_DB_NOUI_VERSION_MAJOR 0
|
||||
#define SECMOD_DB_NOUI_VERSION_MINOR 4
|
||||
|
||||
#define SECMOD_PUTSHORT(dest,src) \
|
||||
(dest)[1] = (unsigned char) ((src)&0xff); \
|
||||
(dest)[0] = (unsigned char) (((src) >> 8) & 0xff);
|
||||
#define SECMOD_PUTLONG(dest,src) \
|
||||
(dest)[3] = (unsigned char) ((src)&0xff); \
|
||||
(dest)[2] = (unsigned char) (((src) >> 8) & 0xff); \
|
||||
(dest)[1] = (unsigned char) (((src) >> 16) & 0xff); \
|
||||
(dest)[0] = (unsigned char) (((src) >> 24) & 0xff);
|
||||
#define SECMOD_GETSHORT(src) \
|
||||
((unsigned short) (((src)[0] << 8) | (src)[1]))
|
||||
#define SECMOD_GETLONG(src) \
|
||||
((unsigned long) (( (unsigned long) (src)[0] << 24) | \
|
||||
( (unsigned long) (src)[1] << 16) | \
|
||||
( (unsigned long) (src)[2] << 8) | \
|
||||
(unsigned long) (src)[3]))
|
||||
|
||||
/*
|
||||
* build a data base entry from a module
|
||||
*/
|
||||
static SECStatus
|
||||
secmod_EncodeData(DBT *data, char * module)
|
||||
{
|
||||
secmodData *encoded = NULL;
|
||||
secmodSlotData *slot;
|
||||
unsigned char *dataPtr;
|
||||
unsigned short len, len2 = 0, len3 = 0;
|
||||
int count = 0;
|
||||
unsigned short offset;
|
||||
int dataLen, i;
|
||||
unsigned long order;
|
||||
unsigned long ssl[2];
|
||||
char *commonName = NULL , *dllName = NULL, *param = NULL, *nss = NULL;
|
||||
char *slotParams, *ciphers;
|
||||
PK11PreSlotInfo *slotInfo = NULL;
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
rv = secmod_argParseModuleSpec(module,&dllName,&commonName,¶m,&nss);
|
||||
if (rv != SECSuccess) return rv;
|
||||
rv = SECFailure;
|
||||
|
||||
if (commonName == NULL) {
|
||||
/* set error */
|
||||
goto loser;
|
||||
}
|
||||
|
||||
len = PORT_Strlen(commonName);
|
||||
if (dllName) {
|
||||
len2 = PORT_Strlen(dllName);
|
||||
}
|
||||
if (param) {
|
||||
len3 = PORT_Strlen(param);
|
||||
}
|
||||
|
||||
slotParams = secmod_argGetParamValue("slotParams",nss);
|
||||
slotInfo = secmod_argParseSlotInfo(NULL,slotParams,&count);
|
||||
if (slotParams) PORT_Free(slotParams);
|
||||
|
||||
if (count && slotInfo == NULL) {
|
||||
/* set error */
|
||||
goto loser;
|
||||
}
|
||||
|
||||
dataLen = sizeof(secmodData) + len + len2 + len3 + sizeof(unsigned short) +
|
||||
count*sizeof(secmodSlotData);
|
||||
|
||||
data->data = (unsigned char *) PORT_ZAlloc(dataLen);
|
||||
encoded = (secmodData *)data->data;
|
||||
dataPtr = (unsigned char *) data->data;
|
||||
data->size = dataLen;
|
||||
|
||||
if (encoded == NULL) {
|
||||
/* set error */
|
||||
goto loser;
|
||||
}
|
||||
|
||||
encoded->major = SECMOD_DB_VERSION_MAJOR;
|
||||
encoded->minor = SECMOD_DB_VERSION_MINOR;
|
||||
encoded->internal = (unsigned char)
|
||||
(secmod_argHasFlag("flags","internal",nss) ? 1 : 0);
|
||||
encoded->fips = (unsigned char)
|
||||
(secmod_argHasFlag("flags","FIPS",nss) ? 1 : 0);
|
||||
encoded->isModuleDB = (unsigned char)
|
||||
(secmod_argHasFlag("flags","isModuleDB",nss) ? 1 : 0);
|
||||
encoded->isModuleDBOnly = (unsigned char)
|
||||
(secmod_argHasFlag("flags","isModuleDBOnly",nss) ? 1 : 0);
|
||||
encoded->isCritical = (unsigned char)
|
||||
(secmod_argHasFlag("flags","critical",nss) ? 1 : 0);
|
||||
|
||||
order = secmod_argReadLong("trustOrder", nss, SECMOD_DEFAULT_TRUST_ORDER,
|
||||
NULL);
|
||||
SECMOD_PUTLONG(encoded->trustOrder,order);
|
||||
order = secmod_argReadLong("cipherOrder", nss, SECMOD_DEFAULT_CIPHER_ORDER,
|
||||
NULL);
|
||||
SECMOD_PUTLONG(encoded->cipherOrder,order);
|
||||
|
||||
|
||||
ciphers = secmod_argGetParamValue("ciphers",nss);
|
||||
secmod_argSetNewCipherFlags(&ssl[0], ciphers);
|
||||
SECMOD_PUTLONG(encoded->ssl,ssl[0]);
|
||||
SECMOD_PUTLONG(&encoded->ssl[4],ssl[1]);
|
||||
if (ciphers) PORT_Free(ciphers);
|
||||
|
||||
offset = (unsigned short) &(((secmodData *)0)->names[0]);
|
||||
SECMOD_PUTSHORT(encoded->nameStart,offset);
|
||||
offset = offset + len + len2 + len3 + 3*sizeof(unsigned short);
|
||||
SECMOD_PUTSHORT(encoded->slotOffset,offset);
|
||||
|
||||
|
||||
SECMOD_PUTSHORT(&dataPtr[offset],((unsigned short)count));
|
||||
slot = (secmodSlotData *)(dataPtr+offset+sizeof(unsigned short));
|
||||
|
||||
offset = 0;
|
||||
SECMOD_PUTSHORT(encoded->names,len);
|
||||
offset += sizeof(unsigned short);
|
||||
PORT_Memcpy(&encoded->names[offset],commonName,len);
|
||||
offset += len;
|
||||
|
||||
|
||||
SECMOD_PUTSHORT(&encoded->names[offset],len2);
|
||||
offset += sizeof(unsigned short);
|
||||
if (len2) PORT_Memcpy(&encoded->names[offset],dllName,len2);
|
||||
offset += len2;
|
||||
|
||||
SECMOD_PUTSHORT(&encoded->names[offset],len3);
|
||||
offset += sizeof(unsigned short);
|
||||
if (len3) PORT_Memcpy(&encoded->names[offset],param,len3);
|
||||
offset += len3;
|
||||
|
||||
if (count) {
|
||||
for (i=0; i < count; i++) {
|
||||
SECMOD_PUTLONG(slot[i].slotID, slotInfo[i].slotID);
|
||||
SECMOD_PUTLONG(slot[i].defaultFlags,
|
||||
slotInfo[i].defaultFlags);
|
||||
SECMOD_PUTLONG(slot[i].timeout,slotInfo[i].timeout);
|
||||
slot[i].askpw = slotInfo[i].askpw;
|
||||
slot[i].hasRootCerts = slotInfo[i].hasRootCerts;
|
||||
PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
|
||||
}
|
||||
}
|
||||
rv = SECSuccess;
|
||||
|
||||
loser:
|
||||
if (commonName) PORT_Free(commonName);
|
||||
if (dllName) PORT_Free(dllName);
|
||||
if (param) PORT_Free(param);
|
||||
if (slotInfo) PORT_Free(slotInfo);
|
||||
if (nss) PORT_Free(nss);
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
secmod_FreeData(DBT *data)
|
||||
{
|
||||
if (data->data) {
|
||||
PORT_Free(data->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
secmod_FreeSlotStrings(char **slotStrings, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < count; i++) {
|
||||
if (slotStrings[i]) {
|
||||
PR_smprintf_free(slotStrings[i]);
|
||||
slotStrings[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* build a module from the data base entry.
|
||||
*/
|
||||
static char *
|
||||
secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
|
||||
{
|
||||
secmodData *encoded;
|
||||
secmodSlotData *slots;
|
||||
PLArenaPool *arena;
|
||||
char *commonName = NULL;
|
||||
char *dllName = NULL;
|
||||
char *parameters = NULL;
|
||||
char *nss;
|
||||
char *moduleSpec;
|
||||
char **slotStrings = NULL;
|
||||
unsigned char *names;
|
||||
unsigned long slotCount;
|
||||
unsigned long ssl0 =0;
|
||||
unsigned long ssl1 =0;
|
||||
unsigned long slotID;
|
||||
unsigned long defaultFlags;
|
||||
unsigned long timeout;
|
||||
unsigned long trustOrder =SECMOD_DEFAULT_TRUST_ORDER;
|
||||
unsigned long cipherOrder =SECMOD_DEFAULT_CIPHER_ORDER;
|
||||
unsigned short len;
|
||||
unsigned short namesOffset = 0; /* start of the names block */
|
||||
unsigned long namesRunningOffset; /* offset to name we are
|
||||
* currently processing */
|
||||
unsigned short slotOffset;
|
||||
PRBool isOldVersion = PR_FALSE;
|
||||
PRBool internal;
|
||||
PRBool isFIPS;
|
||||
PRBool isModuleDB =PR_FALSE;
|
||||
PRBool isModuleDBOnly =PR_FALSE;
|
||||
PRBool extended =PR_FALSE;
|
||||
int i;
|
||||
|
||||
|
||||
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
|
||||
if (arena == NULL)
|
||||
return NULL;
|
||||
|
||||
#define CHECK_SIZE(x) \
|
||||
if ((unsigned int) data->size < (unsigned int)(x)) goto db_loser
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
** Process the buffer header, which is the secmodData struct.
|
||||
** It may be an old or new version. Check the length for each.
|
||||
*/
|
||||
|
||||
CHECK_SIZE( offsetof(secmodData, trustOrder[0]) );
|
||||
|
||||
encoded = (secmodData *)data->data;
|
||||
|
||||
internal = (encoded->internal != 0) ? PR_TRUE: PR_FALSE;
|
||||
isFIPS = (encoded->fips != 0) ? PR_TRUE: PR_FALSE;
|
||||
|
||||
if (retInternal)
|
||||
*retInternal = internal;
|
||||
if (internal) {
|
||||
parameters = PORT_ArenaStrdup(arena,defParams);
|
||||
if (parameters == NULL)
|
||||
goto loser;
|
||||
}
|
||||
if (internal && (encoded->major == SECMOD_DB_NOUI_VERSION_MAJOR) &&
|
||||
(encoded->minor <= SECMOD_DB_NOUI_VERSION_MINOR)) {
|
||||
isOldVersion = PR_TRUE;
|
||||
}
|
||||
if ((encoded->major == SECMOD_DB_EXT1_VERSION_MAJOR) &&
|
||||
(encoded->minor >= SECMOD_DB_EXT1_VERSION_MINOR)) {
|
||||
CHECK_SIZE( sizeof(secmodData));
|
||||
trustOrder = SECMOD_GETLONG(encoded->trustOrder);
|
||||
cipherOrder = SECMOD_GETLONG(encoded->cipherOrder);
|
||||
isModuleDB = (encoded->isModuleDB != 0) ? PR_TRUE: PR_FALSE;
|
||||
isModuleDBOnly = (encoded->isModuleDBOnly != 0) ? PR_TRUE: PR_FALSE;
|
||||
extended = PR_TRUE;
|
||||
}
|
||||
if (internal && !extended) {
|
||||
trustOrder = 0;
|
||||
cipherOrder = 100;
|
||||
}
|
||||
/* decode SSL cipher enable flags */
|
||||
ssl0 = SECMOD_GETLONG(encoded->ssl);
|
||||
ssl1 = SECMOD_GETLONG(encoded->ssl + 4);
|
||||
|
||||
slotOffset = SECMOD_GETSHORT(encoded->slotOffset);
|
||||
namesOffset = SECMOD_GETSHORT(encoded->nameStart);
|
||||
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
** Now process the variable length set of names.
|
||||
** The names have this structure:
|
||||
** struct {
|
||||
** BYTE commonNameLen[ 2 ];
|
||||
** BYTE commonName [ commonNameLen ];
|
||||
** BTTE libNameLen [ 2 ];
|
||||
** BYTE libName [ libNameLen ];
|
||||
** If it is "extended" it also has these members:
|
||||
** BYTE initStringLen[ 2 ];
|
||||
** BYTE initString [ initStringLen ];
|
||||
** }
|
||||
*/
|
||||
|
||||
namesRunningOffset = namesOffset;
|
||||
/* copy the module's common name */
|
||||
CHECK_SIZE( namesRunningOffset + 2);
|
||||
names = (unsigned char *)data->data;
|
||||
len = SECMOD_GETSHORT(names+namesRunningOffset);
|
||||
|
||||
CHECK_SIZE( namesRunningOffset + 2 + len);
|
||||
commonName = (char*)PORT_ArenaAlloc(arena,len+1);
|
||||
if (commonName == NULL)
|
||||
goto loser;
|
||||
PORT_Memcpy(commonName, names + namesRunningOffset + 2, len);
|
||||
commonName[len] = 0;
|
||||
namesRunningOffset += len + 2;
|
||||
|
||||
/* copy the module's shared library file name. */
|
||||
CHECK_SIZE( namesRunningOffset + 2);
|
||||
len = SECMOD_GETSHORT(names + namesRunningOffset);
|
||||
if (len) {
|
||||
CHECK_SIZE( namesRunningOffset + 2 + len);
|
||||
dllName = (char*)PORT_ArenaAlloc(arena,len + 1);
|
||||
if (dllName == NULL)
|
||||
goto loser;
|
||||
PORT_Memcpy(dllName, names + namesRunningOffset + 2, len);
|
||||
dllName[len] = 0;
|
||||
}
|
||||
namesRunningOffset += len + 2;
|
||||
|
||||
/* copy the module's initialization string, if present. */
|
||||
if (!internal && extended) {
|
||||
CHECK_SIZE( namesRunningOffset + 2);
|
||||
len = SECMOD_GETSHORT(names+namesRunningOffset);
|
||||
if (len) {
|
||||
CHECK_SIZE( namesRunningOffset + 2 + len );
|
||||
parameters = (char*)PORT_ArenaAlloc(arena,len + 1);
|
||||
if (parameters == NULL)
|
||||
goto loser;
|
||||
PORT_Memcpy(parameters,names + namesRunningOffset + 2, len);
|
||||
parameters[len] = 0;
|
||||
}
|
||||
namesRunningOffset += len + 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Consistency check: Make sure the slot and names blocks don't
|
||||
* overlap. These blocks can occur in any order, so this check is made
|
||||
* in 2 parts. First we check the case where the slot block starts
|
||||
* after the name block. Later, when we have the slot block length,
|
||||
* we check the case where slot block starts before the name block.
|
||||
* NOTE: in most cases any overlap will likely be detected by invalid
|
||||
* data read from the blocks, but it's better to find out sooner
|
||||
* than later.
|
||||
*/
|
||||
if (slotOffset >= namesOffset) { /* slot block starts after name block */
|
||||
if (slotOffset < namesRunningOffset) {
|
||||
goto db_loser;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
** Part 3, process the slot table.
|
||||
** This part has this structure:
|
||||
** struct {
|
||||
** BYTE slotCount [ 2 ];
|
||||
** secmodSlotData [ slotCount ];
|
||||
** {
|
||||
*/
|
||||
|
||||
CHECK_SIZE( slotOffset + 2 );
|
||||
slotCount = SECMOD_GETSHORT((unsigned char *)data->data + slotOffset);
|
||||
|
||||
/*
|
||||
* Consistency check: Part 2. We now have the slot block length, we can
|
||||
* check the case where the slotblock procedes the name block.
|
||||
*/
|
||||
if (slotOffset < namesOffset) { /* slot block starts before name block */
|
||||
if (namesOffset < slotOffset + 2 + slotCount*sizeof(secmodSlotData)) {
|
||||
goto db_loser;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_SIZE( (slotOffset + 2 + slotCount * sizeof(secmodSlotData)));
|
||||
slots = (secmodSlotData *) ((unsigned char *)data->data + slotOffset + 2);
|
||||
|
||||
/* slotCount; */
|
||||
slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *));
|
||||
if (slotStrings == NULL)
|
||||
goto loser;
|
||||
for (i=0; i < (int) slotCount; i++, slots++) {
|
||||
PRBool hasRootCerts =PR_FALSE;
|
||||
PRBool hasRootTrust =PR_FALSE;
|
||||
slotID = SECMOD_GETLONG(slots->slotID);
|
||||
defaultFlags = SECMOD_GETLONG(slots->defaultFlags);
|
||||
timeout = SECMOD_GETLONG(slots->timeout);
|
||||
hasRootCerts = slots->hasRootCerts;
|
||||
if (isOldVersion && internal && (slotID != 2)) {
|
||||
unsigned long internalFlags=
|
||||
secmod_argSlotFlags("slotFlags",SECMOD_SLOT_FLAGS);
|
||||
defaultFlags |= internalFlags;
|
||||
}
|
||||
if (hasRootCerts && !extended) {
|
||||
trustOrder = 100;
|
||||
}
|
||||
|
||||
slotStrings[i] = secmod_mkSlotString(slotID, defaultFlags, timeout,
|
||||
(unsigned char)slots->askpw,
|
||||
hasRootCerts, hasRootTrust);
|
||||
if (slotStrings[i] == NULL) {
|
||||
secmod_FreeSlotStrings(slotStrings,i);
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
||||
nss = secmod_mkNSS(slotStrings, slotCount, internal, isFIPS, isModuleDB,
|
||||
isModuleDBOnly, internal, trustOrder, cipherOrder,
|
||||
ssl0, ssl1);
|
||||
secmod_FreeSlotStrings(slotStrings,slotCount);
|
||||
/* it's permissible (and normal) for nss to be NULL. it simply means
|
||||
* there are no NSS specific parameters in the database */
|
||||
moduleSpec = secmod_mkNewModuleSpec(dllName,commonName,parameters,nss);
|
||||
PR_smprintf_free(nss);
|
||||
PORT_FreeArena(arena,PR_TRUE);
|
||||
return moduleSpec;
|
||||
|
||||
db_loser:
|
||||
PORT_SetError(SEC_ERROR_BAD_DATABASE);
|
||||
loser:
|
||||
PORT_FreeArena(arena,PR_TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DB *
|
||||
secmod_OpenDB(const char *appName, const char *filename, const char *dbName,
|
||||
PRBool readOnly, PRBool update)
|
||||
{
|
||||
DB *pkcs11db = NULL;
|
||||
|
||||
|
||||
if (appName) {
|
||||
char *secname = PORT_Strdup(filename);
|
||||
int len = strlen(secname);
|
||||
int status = RDB_FAIL;
|
||||
|
||||
if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) {
|
||||
secname[len-3] = 0;
|
||||
}
|
||||
pkcs11db=
|
||||
rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_RDWR, NULL);
|
||||
if (update && !pkcs11db) {
|
||||
DB *updatedb;
|
||||
|
||||
pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
|
||||
if (!pkcs11db) {
|
||||
if (status == RDB_RETRY) {
|
||||
pkcs11db= rdbopen(appName, "", secname,
|
||||
readOnly ? NO_RDONLY:NO_RDWR, NULL);
|
||||
}
|
||||
PORT_Free(secname);
|
||||
return pkcs11db;
|
||||
}
|
||||
updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
|
||||
if (updatedb) {
|
||||
db_Copy(pkcs11db,updatedb);
|
||||
(*updatedb->close)(updatedb);
|
||||
} else {
|
||||
(*pkcs11db->close)(pkcs11db);
|
||||
PORT_Free(secname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
PORT_Free(secname);
|
||||
return pkcs11db;
|
||||
}
|
||||
|
||||
/* I'm sure we should do more checks here sometime... */
|
||||
pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0);
|
||||
|
||||
/* didn't exist? create it */
|
||||
if (pkcs11db == NULL) {
|
||||
if (readOnly)
|
||||
return NULL;
|
||||
|
||||
pkcs11db = dbopen( dbName, NO_CREATE, 0600, DB_HASH, 0 );
|
||||
if (pkcs11db)
|
||||
(* pkcs11db->sync)(pkcs11db, 0);
|
||||
}
|
||||
return pkcs11db;
|
||||
}
|
||||
|
||||
static void
|
||||
secmod_CloseDB(DB *pkcs11db)
|
||||
{
|
||||
(*pkcs11db->close)(pkcs11db);
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_addEscape(const char *string, char quote)
|
||||
{
|
||||
char *newString = 0;
|
||||
int escapes = 0, size = 0;
|
||||
const char *src;
|
||||
char *dest;
|
||||
|
||||
for (src=string; *src ; src++) {
|
||||
if ((*src == quote) || (*src == '\\')) escapes++;
|
||||
size++;
|
||||
}
|
||||
|
||||
newString = PORT_ZAlloc(escapes+size+1);
|
||||
if (newString == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (src=string, dest=newString; *src; src++,dest++) {
|
||||
if ((*src == '\\') || (*src == quote)) {
|
||||
*dest++ = '\\';
|
||||
}
|
||||
*dest = *src;
|
||||
}
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
SECStatus legacy_AddSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *module, PRBool rw);
|
||||
|
||||
#define SECMOD_STEP 10
|
||||
#define SFTK_DEFAULT_INTERNAL_INIT "library= name=\"NSS Internal PKCS #11 Module\" parameters=\"%s\" NSS=\"Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={%s askpw=any timeout=30})\""
|
||||
/*
|
||||
* Read all the existing modules in
|
||||
*/
|
||||
char **
|
||||
legacy_ReadSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *params, PRBool rw)
|
||||
{
|
||||
DBT key,data;
|
||||
int ret;
|
||||
DB *pkcs11db = NULL;
|
||||
char **moduleList = NULL, **newModuleList = NULL;
|
||||
int moduleCount = 1;
|
||||
int useCount = SECMOD_STEP;
|
||||
|
||||
moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
|
||||
if (moduleList == NULL) return NULL;
|
||||
|
||||
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_TRUE,rw);
|
||||
if (pkcs11db == NULL) goto done;
|
||||
|
||||
/* read and parse the file or data base */
|
||||
ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
|
||||
if (ret) goto done;
|
||||
|
||||
|
||||
do {
|
||||
char *moduleString;
|
||||
PRBool internal = PR_FALSE;
|
||||
if ((moduleCount+1) >= useCount) {
|
||||
useCount += SECMOD_STEP;
|
||||
newModuleList =
|
||||
(char **)PORT_Realloc(moduleList,useCount*sizeof(char *));
|
||||
if (newModuleList == NULL) goto done;
|
||||
moduleList = newModuleList;
|
||||
PORT_Memset(&moduleList[moduleCount+1],0,
|
||||
sizeof(char *)*SECMOD_STEP);
|
||||
}
|
||||
moduleString = secmod_DecodeData(params,&data,&internal);
|
||||
if (internal) {
|
||||
moduleList[0] = moduleString;
|
||||
} else {
|
||||
moduleList[moduleCount] = moduleString;
|
||||
moduleCount++;
|
||||
}
|
||||
} while ( (*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
|
||||
|
||||
done:
|
||||
if (!moduleList[0]) {
|
||||
char * newparams = secmod_addEscape(params,'"');
|
||||
if (newparams) {
|
||||
moduleList[0] = PR_smprintf(SFTK_DEFAULT_INTERNAL_INIT,newparams,
|
||||
SECMOD_SLOT_FLAGS);
|
||||
PORT_Free(newparams);
|
||||
}
|
||||
}
|
||||
/* deal with trust cert db here */
|
||||
|
||||
if (pkcs11db) {
|
||||
secmod_CloseDB(pkcs11db);
|
||||
} else if (moduleList[0] && rw) {
|
||||
legacy_AddSecmodDB(appName,filename,dbname,moduleList[0], rw) ;
|
||||
}
|
||||
if (!moduleList[0]) {
|
||||
PORT_Free(moduleList);
|
||||
moduleList = NULL;
|
||||
}
|
||||
return moduleList;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
legacy_ReleaseSecmodDBData(const char *appName, const char *filename,
|
||||
const char *dbname, char **moduleSpecList, PRBool rw)
|
||||
{
|
||||
if (moduleSpecList) {
|
||||
char **index;
|
||||
for(index = moduleSpecList; *index; index++) {
|
||||
PR_smprintf_free(*index);
|
||||
}
|
||||
PORT_Free(moduleSpecList);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a module from the Data Base
|
||||
*/
|
||||
SECStatus
|
||||
legacy_DeleteSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *args, PRBool rw)
|
||||
{
|
||||
DBT key;
|
||||
SECStatus rv = SECFailure;
|
||||
DB *pkcs11db = NULL;
|
||||
int ret;
|
||||
|
||||
if (!rw) return SECFailure;
|
||||
|
||||
/* make sure we have a db handle */
|
||||
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
|
||||
if (pkcs11db == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = secmod_MakeKey(&key,args);
|
||||
if (rv != SECSuccess) goto done;
|
||||
rv = SECFailure;
|
||||
ret = (*pkcs11db->del)(pkcs11db, &key, 0);
|
||||
secmod_FreeKey(&key);
|
||||
if (ret != 0) goto done;
|
||||
|
||||
|
||||
ret = (*pkcs11db->sync)(pkcs11db, 0);
|
||||
if (ret == 0) rv = SECSuccess;
|
||||
|
||||
done:
|
||||
secmod_CloseDB(pkcs11db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a module to the Data base
|
||||
*/
|
||||
SECStatus
|
||||
legacy_AddSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *module, PRBool rw)
|
||||
{
|
||||
DBT key,data;
|
||||
SECStatus rv = SECFailure;
|
||||
DB *pkcs11db = NULL;
|
||||
int ret;
|
||||
|
||||
|
||||
if (!rw) return SECFailure;
|
||||
|
||||
/* make sure we have a db handle */
|
||||
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
|
||||
if (pkcs11db == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = secmod_MakeKey(&key,module);
|
||||
if (rv != SECSuccess) goto done;
|
||||
rv = secmod_EncodeData(&data,module);
|
||||
if (rv != SECSuccess) {
|
||||
secmod_FreeKey(&key);
|
||||
goto done;
|
||||
}
|
||||
rv = SECFailure;
|
||||
ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
|
||||
secmod_FreeKey(&key);
|
||||
secmod_FreeData(&data);
|
||||
if (ret != 0) goto done;
|
||||
|
||||
ret = (*pkcs11db->sync)(pkcs11db, 0);
|
||||
if (ret == 0) rv = SECSuccess;
|
||||
|
||||
done:
|
||||
secmod_CloseDB(pkcs11db);
|
||||
return rv;
|
||||
}
|
||||
@@ -43,9 +43,7 @@
|
||||
#include "secerr.h"
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
extern SECStatus EC_CopyParams(PRArenaPool *arena,
|
||||
ECParams *dstParams,
|
||||
const ECParams *srcParams);
|
||||
#include "softoken.h"
|
||||
#endif
|
||||
|
||||
const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = nss
|
||||
DIRS = legacydb
|
||||
|
||||
REQUIRES = dbm
|
||||
|
||||
@@ -44,7 +45,7 @@ LIBRARY_NAME = softokn
|
||||
LIBRARY_VERSION = 3
|
||||
MAPFILE = $(OBJDIR)/softokn.def
|
||||
|
||||
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
|
||||
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\" -DSHLIB_VERSION=\"$(LIBRARY_VERSION)\"
|
||||
|
||||
|
||||
EXPORTS = \
|
||||
@@ -55,9 +56,11 @@ EXPORTS = \
|
||||
pkcs11n.h \
|
||||
pkcs11u.h \
|
||||
sdb.h \
|
||||
sftkdbt.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
lgglue.h \
|
||||
pk11pars.h \
|
||||
pkcs11ni.h \
|
||||
softoken.h \
|
||||
@@ -70,6 +73,7 @@ CSRCS = \
|
||||
fipsaudt.c \
|
||||
fipstest.c \
|
||||
fipstokn.c \
|
||||
lgglue.c \
|
||||
lowkey.c \
|
||||
lowpbe.c \
|
||||
padbuf.c \
|
||||
@@ -88,3 +92,7 @@ ifdef NSS_ENABLE_ECC
|
||||
DEFINES += -DNSS_ENABLE_ECC
|
||||
endif
|
||||
|
||||
ifdef SQLITE_UNSAFE_THREADS
|
||||
DEFINES += -DSQLITE_UNSAFE_THREADS
|
||||
endif
|
||||
|
||||
|
||||
@@ -2170,16 +2170,21 @@ loser:
|
||||
|
||||
static CK_RV sft_CloseAllSession(SFTKSlot *slot)
|
||||
{
|
||||
SECItem *pw = NULL;
|
||||
SFTKSession *session;
|
||||
unsigned int i;
|
||||
SFTKDBHandle *handle;
|
||||
|
||||
/* first log out the card */
|
||||
handle = sftk_getKeyDB(slot);
|
||||
PZ_Lock(slot->slotLock);
|
||||
pw = slot->password;
|
||||
slot->isLoggedIn = PR_FALSE;
|
||||
slot->password = NULL;
|
||||
if (handle) {
|
||||
sftkdb_ClearPassword(handle);
|
||||
}
|
||||
PZ_Unlock(slot->slotLock);
|
||||
if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
|
||||
if (handle) {
|
||||
sftk_freeDB(handle);
|
||||
}
|
||||
|
||||
/* now close all the current sessions */
|
||||
/* NOTE: If you try to open new sessions before NSC_CloseAllSessions
|
||||
@@ -2335,7 +2340,7 @@ NSC_ModuleDBFunc(unsigned long function,char *parameters, void *args)
|
||||
char *secmod = NULL;
|
||||
char *appName = NULL;
|
||||
char *filename = NULL;
|
||||
const char *dbType = NULL;
|
||||
SDBType dbType = SDB_LEGACY;
|
||||
PRBool rw;
|
||||
static char *success="Success";
|
||||
char **rvstr = NULL;
|
||||
@@ -2449,14 +2454,6 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
|
||||
}
|
||||
RNG_SystemInfoForRNG();
|
||||
|
||||
#ifdef SHDB_FIXME
|
||||
rv = nsslowcert_InitLocks();
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
return crv;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* NOTE:
|
||||
* we should be getting out mutexes from this list, not statically binding
|
||||
@@ -2465,10 +2462,6 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
|
||||
*/
|
||||
|
||||
/* initialize the key and cert db's */
|
||||
#ifdef SHDB_FIXME
|
||||
nsslowkey_SetDefaultKeyDBAlg
|
||||
(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC);
|
||||
#endif
|
||||
if (init_args && (!(init_args->flags & CKF_OS_LOCKING_OK))) {
|
||||
if (init_args->CreateMutex && init_args->DestroyMutex &&
|
||||
init_args->LockMutex && init_args->UnlockMutex) {
|
||||
@@ -2563,11 +2556,7 @@ CK_RV nsc_CommonFinalize (CK_VOID_PTR pReserved, PRBool isFIPS)
|
||||
}
|
||||
|
||||
sftk_CleanupFreeLists();
|
||||
#ifdef SHDB_FIXME
|
||||
/* shdb shutdown code here */
|
||||
nsslowcert_DestroyFreeLists();
|
||||
nsslowcert_DestroyGlobalLocks();
|
||||
#endif
|
||||
sftkdb_Shutdown();
|
||||
|
||||
/* This function does not discard all our previously aquired entropy. */
|
||||
RNG_RNGShutdown();
|
||||
@@ -3127,7 +3116,6 @@ CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession)
|
||||
{
|
||||
SFTKSlot *slot;
|
||||
SFTKSession *session;
|
||||
SECItem *pw = NULL;
|
||||
PRBool sessionFound;
|
||||
PZLock *lock;
|
||||
|
||||
@@ -3148,20 +3136,25 @@ CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession)
|
||||
PZ_Unlock(lock);
|
||||
|
||||
if (sessionFound) {
|
||||
SFTKDBHandle *handle;
|
||||
handle = sftk_getKeyDB(slot);
|
||||
PZ_Lock(slot->slotLock);
|
||||
if (--slot->sessionCount == 0) {
|
||||
pw = slot->password;
|
||||
slot->isLoggedIn = PR_FALSE;
|
||||
slot->password = NULL;
|
||||
if (handle) {
|
||||
sftkdb_ClearPassword(handle);
|
||||
}
|
||||
}
|
||||
PZ_Unlock(slot->slotLock);
|
||||
if (handle) {
|
||||
sftk_freeDB(handle);
|
||||
}
|
||||
if (session->info.flags & CKF_RW_SESSION) {
|
||||
PR_AtomicDecrement(&slot->rwSessionCount);
|
||||
}
|
||||
}
|
||||
|
||||
sftk_FreeSession(session);
|
||||
if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
@@ -3309,7 +3302,7 @@ CK_RV NSC_Logout(CK_SESSION_HANDLE hSession)
|
||||
{
|
||||
SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
|
||||
SFTKSession *session;
|
||||
SECItem *pw = NULL;
|
||||
SFTKDBHandle *handle;
|
||||
|
||||
if (slot == NULL) {
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
@@ -3321,13 +3314,17 @@ CK_RV NSC_Logout(CK_SESSION_HANDLE hSession)
|
||||
|
||||
if (!slot->isLoggedIn) return CKR_USER_NOT_LOGGED_IN;
|
||||
|
||||
handle = sftk_getKeyDB(slot);
|
||||
PZ_Lock(slot->slotLock);
|
||||
pw = slot->password;
|
||||
slot->isLoggedIn = PR_FALSE;
|
||||
slot->ssoLoggedIn = PR_FALSE;
|
||||
slot->password = NULL;
|
||||
if (handle) {
|
||||
sftkdb_ClearPassword(handle);
|
||||
}
|
||||
PZ_Unlock(slot->slotLock);
|
||||
if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
|
||||
if (handle) {
|
||||
sftk_freeDB(handle);
|
||||
}
|
||||
|
||||
sftk_update_all_states(slot);
|
||||
return CKR_OK;
|
||||
@@ -3754,13 +3751,13 @@ sftk_expandSearchList(SFTKSearchResults *search, int count)
|
||||
|
||||
static CK_RV
|
||||
sftk_searchDatabase(SFTKDBHandle *handle, SFTKSearchResults *search,
|
||||
CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
|
||||
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
|
||||
{
|
||||
CK_RV crv;
|
||||
int objectListSize = search->array_size-search->size;
|
||||
CK_OBJECT_HANDLE *array = &search->handles[search->size];
|
||||
SDBFind *find;
|
||||
int count;
|
||||
CK_ULONG count;
|
||||
|
||||
crv = sftkdb_FindObjectsInit(handle, pTemplate, ulCount, &find);
|
||||
if (crv != CKR_OK)
|
||||
|
||||
@@ -95,8 +95,6 @@ static void sftk_Null(void *data, PRBool freeit)
|
||||
}
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
extern SECStatus EC_DecodeParams(const SECItem *encodedParams,
|
||||
ECParams **ecparams);
|
||||
#ifdef EC_DEBUG
|
||||
#define SEC_PRINT(str1, str2, num, sitem) \
|
||||
printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
|
||||
|
||||
@@ -349,7 +349,6 @@ struct SFTKSlotStr {
|
||||
unsigned long sessionLockMask; /* invariant */
|
||||
PZLock *objectLock; /* invariant */
|
||||
PRLock *pwCheckLock; /* invariant */
|
||||
SECItem *password; /* variable - reset */
|
||||
PRBool present; /* variable -set */
|
||||
PRBool hasTokens; /* per load */
|
||||
PRBool isLoggedIn; /* variable - reset */
|
||||
|
||||
@@ -178,13 +178,14 @@ sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type)
|
||||
myattribute->freeData = PR_TRUE;
|
||||
crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
|
||||
&myattribute->attrib, 1);
|
||||
}
|
||||
}
|
||||
loser:
|
||||
if (dbHandle) {
|
||||
sftk_freeDB(dbHandle);
|
||||
}
|
||||
if (crv != CKR_OK) {
|
||||
if (myattribute) {
|
||||
myattribute->attrib.ulValueLen = 0;
|
||||
sftk_FreeAttribute(myattribute);
|
||||
myattribute = NULL;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,20 @@
|
||||
|
||||
#include "prlock.h"
|
||||
|
||||
#ifdef SQLITE_UNSAFE_THREADS
|
||||
/*
|
||||
* SQLite can be compiled to be thread safe or not.
|
||||
* turn on SQLITE_UNSAFE_THREADS if the OS does not support
|
||||
* a thread safe version of sqlite.
|
||||
*/
|
||||
static PRLock *sqlite_lock = NULL;
|
||||
|
||||
#define LOCK_SQLITE() PR_Lock(sqlite_lock);
|
||||
#define UNLOCK_SQLITE() PR_Unlock(sqlite_lock);
|
||||
#else
|
||||
#define LOCK_SQLITE()
|
||||
#define UNLOCK_SQLITE()
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
SDB_CERT = 1,
|
||||
@@ -266,7 +280,7 @@ struct SDBFindStr {
|
||||
#define FIND_OBJECTS_CMD "SELECT ALL * FROM %s WHERE %s;"
|
||||
#define FIND_OBJECTS_ALL_CMD "SELECT ALL * FROM %s;"
|
||||
CK_RV
|
||||
sdb_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *template, int count,
|
||||
sdb_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *template, CK_ULONG count,
|
||||
SDBFind **find)
|
||||
{
|
||||
SDBPrivate *sdb_p = sdb->private;
|
||||
@@ -278,6 +292,7 @@ sdb_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *template, int count,
|
||||
CK_RV error = CKR_OK;
|
||||
int i;
|
||||
|
||||
LOCK_SQLITE()
|
||||
*find = NULL;
|
||||
error = sdb_openDBLocal(sdb_p, &sqlDB);
|
||||
if (error != CKR_OK) {
|
||||
@@ -322,6 +337,7 @@ sdb_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *template, int count,
|
||||
}
|
||||
(*find)->findstmt = findstmt;
|
||||
(*find)->sqlDB = sqlDB;
|
||||
UNLOCK_SQLITE()
|
||||
return CKR_OK;
|
||||
}
|
||||
error = sdb_mapSQLError(sdb_p->type, sqlerr);
|
||||
@@ -333,13 +349,14 @@ loser:
|
||||
if (sqlDB) {
|
||||
sdb_closeDBLocal(sdb_p, sqlDB) ;
|
||||
}
|
||||
UNLOCK_SQLITE()
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
CK_RV
|
||||
sdb_FindObjects(SDB *sdb, SDBFind *sdbFind, CK_OBJECT_HANDLE *object,
|
||||
int arraySize, int *count)
|
||||
CK_ULONG arraySize, CK_ULONG *count)
|
||||
{
|
||||
SDBPrivate *sdb_p = sdb->private;
|
||||
sqlite3_stmt *stmt = sdbFind->findstmt;
|
||||
@@ -351,6 +368,7 @@ sdb_FindObjects(SDB *sdb, SDBFind *sdbFind, CK_OBJECT_HANDLE *object,
|
||||
if (arraySize == 0) {
|
||||
return CKR_OK;
|
||||
}
|
||||
LOCK_SQLITE()
|
||||
|
||||
do {
|
||||
sqlerr = sqlite3_step(stmt);
|
||||
@@ -370,6 +388,7 @@ sdb_FindObjects(SDB *sdb, SDBFind *sdbFind, CK_OBJECT_HANDLE *object,
|
||||
if (sqlerr == SQLITE_ROW && arraySize == 0) {
|
||||
sqlerr = SQLITE_DONE;
|
||||
}
|
||||
UNLOCK_SQLITE()
|
||||
|
||||
return sdb_mapSQLError(sdb_p->type, sqlerr);
|
||||
}
|
||||
@@ -382,6 +401,7 @@ sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
|
||||
sqlite3 *sqlDB = sdbFind->sqlDB;
|
||||
int sqlerr = SQLITE_OK;
|
||||
|
||||
LOCK_SQLITE()
|
||||
if (stmt) {
|
||||
sqlite3_reset(stmt);
|
||||
sqlerr = sqlite3_finalize(stmt);
|
||||
@@ -391,13 +411,14 @@ sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
|
||||
}
|
||||
PORT_Free(sdbFind);
|
||||
|
||||
UNLOCK_SQLITE()
|
||||
return sdb_mapSQLError(sdb_p->type, sqlerr);
|
||||
}
|
||||
|
||||
#define GET_ATTRIBUTE_CMD "SELECT ALL %s FROM %s WHERE id=$ID;"
|
||||
CK_RV
|
||||
sdb_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
CK_ATTRIBUTE *template, int count)
|
||||
CK_ATTRIBUTE *template, CK_ULONG count)
|
||||
{
|
||||
SDBPrivate *sdb_p = sdb->private;
|
||||
sqlite3 *sqlDB = NULL;
|
||||
@@ -414,6 +435,7 @@ sdb_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
LOCK_SQLITE()
|
||||
getStr = sqlite3_mprintf("");
|
||||
for (i=0; getStr && i < count; i++) {
|
||||
if (i==0) {
|
||||
@@ -506,13 +528,14 @@ loser:
|
||||
if (sqlDB) {
|
||||
sdb_closeDBLocal(sdb_p, sqlDB) ;
|
||||
}
|
||||
UNLOCK_SQLITE()
|
||||
return error;
|
||||
}
|
||||
|
||||
#define SET_ATTRIBUTE_CMD "UPDATE %s SET %s WHERE id=$ID;"
|
||||
CK_RV
|
||||
sdb_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
const CK_ATTRIBUTE *template, int count)
|
||||
const CK_ATTRIBUTE *template, CK_ULONG count)
|
||||
{
|
||||
SDBPrivate *sdb_p = sdb->private;
|
||||
sqlite3 *sqlDB = NULL;
|
||||
@@ -532,6 +555,7 @@ sdb_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
LOCK_SQLITE()
|
||||
setStr = sqlite3_mprintf("");
|
||||
for (i=0; setStr && i < count; i++) {
|
||||
if (i==0) {
|
||||
@@ -553,6 +577,7 @@ sdb_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
newStr = sqlite3_mprintf(SET_ATTRIBUTE_CMD, sdb_p->table, setStr);
|
||||
sqlite3_free(setStr);
|
||||
if (newStr == NULL) {
|
||||
UNLOCK_SQLITE()
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
error = sdb_openDBLocal(sdb_p, &sqlDB);
|
||||
@@ -598,6 +623,7 @@ loser:
|
||||
sdb_closeDBLocal(sdb_p, sqlDB) ;
|
||||
}
|
||||
|
||||
UNLOCK_SQLITE()
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -606,7 +632,7 @@ static CK_OBJECT_HANDLE next_obj = 0;
|
||||
#define CREATE_CMD "INSERT INTO %s (id%s) VALUES($ID%s);"
|
||||
CK_RV
|
||||
sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
|
||||
const CK_ATTRIBUTE *template, int count)
|
||||
const CK_ATTRIBUTE *template, CK_ULONG count)
|
||||
{
|
||||
SDBPrivate *sdb_p = sdb->private;
|
||||
sqlite3 *sqlDB = NULL;
|
||||
@@ -623,8 +649,9 @@ sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
LOCK_SQLITE()
|
||||
/* This needs to get the next object ID from the database */
|
||||
/* reviewers don't let this code through as is */
|
||||
/* SDB_FIX_ME reviewers don't let this code through as is */
|
||||
if (next_obj == 0) {
|
||||
PRTime time;
|
||||
time = PR_Now();
|
||||
@@ -650,6 +677,7 @@ sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
|
||||
if (valueStr) {
|
||||
sqlite3_free(valueStr);
|
||||
}
|
||||
UNLOCK_SQLITE()
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
newStr = sqlite3_mprintf(CREATE_CMD, sdb_p->table, columnStr, valueStr);
|
||||
@@ -697,6 +725,7 @@ loser:
|
||||
if (sqlDB) {
|
||||
sdb_closeDBLocal(sdb_p, sqlDB) ;
|
||||
}
|
||||
UNLOCK_SQLITE()
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -717,6 +746,7 @@ sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
LOCK_SQLITE()
|
||||
error = sdb_openDBLocal(sdb_p, &sqlDB);
|
||||
if (error != CKR_OK) {
|
||||
goto loser;
|
||||
@@ -753,6 +783,7 @@ loser:
|
||||
sdb_closeDBLocal(sdb_p, sqlDB) ;
|
||||
}
|
||||
|
||||
UNLOCK_SQLITE()
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -780,6 +811,7 @@ sdb_Begin(SDB *sdb)
|
||||
}
|
||||
|
||||
|
||||
LOCK_SQLITE()
|
||||
/* get a new version that we will use for the entire transaction */
|
||||
sqlerr = sqlite3_open(sdb_p->sqlDBName, &sqlDB);
|
||||
if (sqlerr != SQLITE_OK) {
|
||||
@@ -827,6 +859,7 @@ loser:
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK_SQLITE()
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -851,6 +884,7 @@ sdb_complete(SDB *sdb, const char *cmd)
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
|
||||
/* We must have a transation database, or we shouldn't have arrived here */
|
||||
PR_Lock(sdb_p->lock);
|
||||
PORT_Assert(sdb_p->sqlXactDB);
|
||||
@@ -864,7 +898,8 @@ sdb_complete(SDB *sdb, const char *cmd)
|
||||
return CKR_GENERAL_ERROR; /* shouldn't happen */
|
||||
}
|
||||
sqlDB = sdb_p->sqlXactDB;
|
||||
sdb_p->sqlXactDB = NULL; /* no one else can get to this DB, safe to unlock */
|
||||
sdb_p->sqlXactDB = NULL; /* no one else can get to this DB,
|
||||
* safe to unlock */
|
||||
sdb_p->sqlXactThread = NULL;
|
||||
PR_Unlock(sdb_p->lock);
|
||||
|
||||
@@ -894,18 +929,25 @@ sdb_complete(SDB *sdb, const char *cmd)
|
||||
}
|
||||
|
||||
#define COMMIT_CMD "COMMIT TRANSACTION;"
|
||||
|
||||
CK_RV
|
||||
sdb_Commit(SDB *sdb)
|
||||
{
|
||||
return sdb_complete(sdb,COMMIT_CMD);
|
||||
CK_RV crv;
|
||||
LOCK_SQLITE()
|
||||
crv = sdb_complete(sdb,COMMIT_CMD);
|
||||
UNLOCK_SQLITE()
|
||||
return crv;
|
||||
}
|
||||
|
||||
#define ROLLBACK_CMD "ROLLBACK TRANSACTION;"
|
||||
CK_RV
|
||||
sdb_Abort(SDB *sdb)
|
||||
{
|
||||
return sdb_complete(sdb,ROLLBACK_CMD);
|
||||
CK_RV crv;
|
||||
LOCK_SQLITE()
|
||||
crv = sdb_complete(sdb,ROLLBACK_CMD);
|
||||
UNLOCK_SQLITE()
|
||||
return crv;
|
||||
}
|
||||
|
||||
#define GET_PW_CMD "SELECT ALL * FROM password WHERE id='password';"
|
||||
@@ -925,6 +967,7 @@ sdb_GetPWEntry(SDB *sdb, SDBPasswordEntry *entry)
|
||||
return CKR_OBJECT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
LOCK_SQLITE()
|
||||
error = sdb_openDBLocal(sdb_p, &sqlDB);
|
||||
if (error != CKR_OK) {
|
||||
goto loser;
|
||||
@@ -975,6 +1018,7 @@ loser:
|
||||
if (sqlDB) {
|
||||
sdb_closeDBLocal(sdb_p, sqlDB) ;
|
||||
}
|
||||
UNLOCK_SQLITE()
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -999,6 +1043,7 @@ sdb_PutPWEntry(SDB *sdb, SDBPasswordEntry *entry)
|
||||
return CKR_OBJECT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
LOCK_SQLITE()
|
||||
error = sdb_openDBLocal(sdb_p, &sqlDB);
|
||||
if (error != CKR_OK) {
|
||||
goto loser;
|
||||
@@ -1038,6 +1083,7 @@ loser:
|
||||
if (sqlDB) {
|
||||
sdb_closeDBLocal(sdb_p, sqlDB) ;
|
||||
}
|
||||
UNLOCK_SQLITE()
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -1057,6 +1103,7 @@ sdb_Reset(SDB *sdb)
|
||||
return CKR_OBJECT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
LOCK_SQLITE()
|
||||
error = sdb_openDBLocal(sdb_p, &sqlDB);
|
||||
if (error != CKR_OK) {
|
||||
goto loser;
|
||||
@@ -1087,6 +1134,7 @@ loser:
|
||||
sdb_closeDBLocal(sdb_p, sqlDB) ;
|
||||
}
|
||||
|
||||
UNLOCK_SQLITE()
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1157,6 +1205,7 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
|
||||
* open the database read only. If the db doesn't exist,
|
||||
* sqlite3 will always create it.
|
||||
*/
|
||||
LOCK_SQLITE();
|
||||
if ((flags == SDB_RDONLY) && PR_Access(dbname, PR_ACCESS_EXISTS)) {
|
||||
error = sdb_mapSQLError(type, SQLITE_CANTOPEN);
|
||||
goto loser;
|
||||
@@ -1223,7 +1272,7 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
|
||||
sdb_p->sqlXactDB = NULL;
|
||||
sdb_p->sqlXactThread = NULL;
|
||||
sdb->private = sdb_p;
|
||||
sdb->sdb_type = SDB_INTERNAL;
|
||||
sdb->sdb_type = SDB_SHARED;
|
||||
sdb->sdb_flags = flags;
|
||||
sdb->sdb_FindObjectsInit = sdb_FindObjectsInit;
|
||||
sdb->sdb_FindObjects = sdb_FindObjects;
|
||||
@@ -1257,6 +1306,7 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
|
||||
sqlite3_close(sqlDB);
|
||||
|
||||
*pSdb = sdb;
|
||||
UNLOCK_SQLITE();
|
||||
return CKR_OK;
|
||||
|
||||
loser:
|
||||
@@ -1273,6 +1323,7 @@ loser:
|
||||
if (sqlDB) {
|
||||
sqlite3_close(sqlDB);
|
||||
}
|
||||
UNLOCK_SQLITE();
|
||||
return error;
|
||||
|
||||
}
|
||||
@@ -1303,6 +1354,16 @@ s_open(const char *directory, const char *certPrefix, const char *keyPrefix,
|
||||
*certdb = NULL;
|
||||
*keydb = NULL;
|
||||
|
||||
#ifdef SQLITE_UNSAFE_THREADS
|
||||
if (sqlite_lock == NULL) {
|
||||
sqlite_lock = PR_NewLock();
|
||||
if (sqlite_lock == NULL) {
|
||||
error = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* open the cert data base
|
||||
*/
|
||||
@@ -1332,6 +1393,7 @@ s_open(const char *directory, const char *certPrefix, const char *keyPrefix,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
loser:
|
||||
if (cert) {
|
||||
sqlite3_free(cert);
|
||||
@@ -1353,3 +1415,15 @@ loser:
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
s_shutdown()
|
||||
{
|
||||
#ifdef SQLITE_UNSAFE_THREADS
|
||||
if (sqlite_lock) {
|
||||
PR_DestroyLock(sqlite_lock);
|
||||
sqlite_lock = NULL;
|
||||
}
|
||||
#endif
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#define _SDB_H 1
|
||||
#include "pkcs11t.h"
|
||||
#include "secitem.h"
|
||||
#include "sftkdbt.h"
|
||||
#include <sqlite3.h>
|
||||
|
||||
#define STATIC_CMD_SIZE 2048
|
||||
@@ -69,19 +70,21 @@ typedef struct SDBPasswordEntryStr SDBPasswordEntry;
|
||||
|
||||
struct SDBStr {
|
||||
void *private;
|
||||
int sdb_type;
|
||||
int version;
|
||||
SDBType sdb_type;
|
||||
int sdb_flags;
|
||||
void *app_private;
|
||||
CK_RV (*sdb_FindObjectsInit)(SDB *sdb, const CK_ATTRIBUTE *template,
|
||||
int count, SDBFind **find);
|
||||
CK_ULONG count, SDBFind **find);
|
||||
CK_RV (*sdb_FindObjects)(SDB *sdb, SDBFind *find, CK_OBJECT_HANDLE *ids,
|
||||
int arraySize, int *count);
|
||||
CK_ULONG arraySize, CK_ULONG *count);
|
||||
CK_RV (*sdb_FindObjectsFinal)(SDB *sdb, SDBFind *find);
|
||||
CK_RV (*sdb_GetAttributeValue)(SDB *sdb, CK_OBJECT_HANDLE object,
|
||||
CK_ATTRIBUTE *template, int count);
|
||||
CK_ATTRIBUTE *template, CK_ULONG count);
|
||||
CK_RV (*sdb_SetAttributeValue)(SDB *sdb, CK_OBJECT_HANDLE object,
|
||||
const CK_ATTRIBUTE *template, int count);
|
||||
const CK_ATTRIBUTE *template, CK_ULONG count);
|
||||
CK_RV (*sdb_CreateObject)(SDB *sdb, CK_OBJECT_HANDLE *object,
|
||||
const CK_ATTRIBUTE *template, int count);
|
||||
const CK_ATTRIBUTE *template, CK_ULONG count);
|
||||
CK_RV (*sdb_DestroyObject)(SDB *sdb, CK_OBJECT_HANDLE object);
|
||||
CK_RV (*sdb_GetPWEntry)(SDB *sdb, SDBPasswordEntry *entry);
|
||||
CK_RV (*sdb_PutPWEntry)(SDB *sdb, SDBPasswordEntry *entry);
|
||||
@@ -98,13 +101,11 @@ struct SDBPasswordEntryStr {
|
||||
unsigned char data[128];
|
||||
};
|
||||
|
||||
#define SDB_INTERNAL 1
|
||||
|
||||
CK_RV s_open(const char *directory, const char *certPrefix,
|
||||
const char *keyPrefix,
|
||||
int cert_version, int key_version,
|
||||
int flags, SDB **certdb, SDB **keydb);
|
||||
|
||||
CK_RV s_shutdown();
|
||||
|
||||
/* flags */
|
||||
#define SDB_RDONLY 1
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
#include "secoid.h"
|
||||
#include "sechash.h"
|
||||
#include "lowpbe.h"
|
||||
#include "secdert.h"
|
||||
#include "prsystem.h"
|
||||
#include "lgglue.h"
|
||||
|
||||
/*
|
||||
* private defines
|
||||
@@ -95,6 +98,24 @@ sftkdb_isULONG(CK_ATTRIBUTE_TYPE type)
|
||||
case CKA_CERTIFICATE_CATEGORY:
|
||||
case CKA_KEY_TYPE:
|
||||
case CKA_JAVA_MIDP_SECURITY_DOMAIN:
|
||||
|
||||
case CKA_TRUST_DIGITAL_SIGNATURE:
|
||||
case CKA_TRUST_NON_REPUDIATION:
|
||||
case CKA_TRUST_KEY_ENCIPHERMENT:
|
||||
case CKA_TRUST_DATA_ENCIPHERMENT:
|
||||
case CKA_TRUST_KEY_AGREEMENT:
|
||||
case CKA_TRUST_KEY_CERT_SIGN:
|
||||
case CKA_TRUST_CRL_SIGN:
|
||||
|
||||
case CKA_TRUST_SERVER_AUTH:
|
||||
case CKA_TRUST_CLIENT_AUTH:
|
||||
case CKA_TRUST_CODE_SIGNING:
|
||||
case CKA_TRUST_EMAIL_PROTECTION:
|
||||
case CKA_TRUST_IPSEC_END_SYSTEM:
|
||||
case CKA_TRUST_IPSEC_TUNNEL:
|
||||
case CKA_TRUST_IPSEC_USER:
|
||||
case CKA_TRUST_TIME_STAMPING:
|
||||
case CKA_TRUST_STEP_UP_APPROVED:
|
||||
return PR_TRUE;
|
||||
default:
|
||||
break;
|
||||
@@ -179,7 +200,7 @@ sftkdb_fixupTemplateIn(const CK_ATTRIBUTE *template, int count,
|
||||
if ( sftkdb_isULONG(template[i].type) ) {
|
||||
CK_ULONG value = *(CK_ULONG *) template[i].pValue;
|
||||
for (j=0; j < DB_ULONG_SIZE; j++) {
|
||||
data[j] = (value >> (DB_ULONG_SIZE-j)*BBP) & 0xff;
|
||||
data[j] = (value >> (DB_ULONG_SIZE-1-j)*BBP) & 0xff;
|
||||
}
|
||||
ntemplate[i].pValue = data;
|
||||
ntemplate[i].ulValueLen = DB_ULONG_SIZE;
|
||||
@@ -215,7 +236,7 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_ATTRIBUTE *ntemplate,
|
||||
|
||||
data = (unsigned char *)ntemplate[i].pValue;
|
||||
for (j=0; j < DB_ULONG_SIZE; j++) {
|
||||
value |= (((CK_ULONG)data[j]) << (DB_ULONG_SIZE-j)*BBP);
|
||||
value |= (((CK_ULONG)data[j]) << (DB_ULONG_SIZE-1-j)*BBP);
|
||||
}
|
||||
if (length < sizeof(CK_ULONG)) {
|
||||
template[i].ulValueLen = -1;
|
||||
@@ -232,6 +253,8 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_ATTRIBUTE *ntemplate,
|
||||
(template[i].pValue != NULL) && (template[i].ulValueLen != -1)
|
||||
&& sftkdb_isPrivate(ntemplate[i].type)) {
|
||||
/* we have a private attribute */
|
||||
/* This code depends on the fact that the cipherText is bigger
|
||||
* than the plain text */
|
||||
SECItem cipherText;
|
||||
SECItem *plainText;
|
||||
SECStatus rv;
|
||||
@@ -253,6 +276,16 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_ATTRIBUTE *ntemplate,
|
||||
crv = CKR_GENERAL_ERROR;
|
||||
continue;
|
||||
}
|
||||
PORT_Assert(template[i].ulValueLen >= plainText->len);
|
||||
if (template[i].ulValueLen < plainText->len) {
|
||||
SECITEM_FreeItem(plainText,PR_TRUE);
|
||||
PORT_Memset(template[i].pValue, 0, template[i].ulValueLen);
|
||||
template[i].ulValueLen = -1;
|
||||
crv = CKR_GENERAL_ERROR;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy the plain text back into the template */
|
||||
PORT_Memcpy(template[i].pValue, plainText->data, plainText->len);
|
||||
template[i].ulValueLen = plainText->len;
|
||||
SECITEM_FreeItem(plainText,PR_TRUE);
|
||||
@@ -314,7 +347,7 @@ sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object,
|
||||
break;
|
||||
}
|
||||
for (j=0; j < DB_ULONG_SIZE; j++) {
|
||||
data[j] = (value >> (DB_ULONG_SIZE-j)*BBP) & 0xff;
|
||||
data[j] = (value >> (DB_ULONG_SIZE-1-j)*BBP) & 0xff;
|
||||
}
|
||||
tp->ulValueLen = DB_ULONG_SIZE;
|
||||
}
|
||||
@@ -422,7 +455,7 @@ loser:
|
||||
|
||||
CK_RV
|
||||
sftkdb_FindObjectsInit(SFTKDBHandle *handle, const CK_ATTRIBUTE *template,
|
||||
int count, SDBFind **find)
|
||||
CK_ULONG count, SDBFind **find)
|
||||
{
|
||||
unsigned char *data = NULL;
|
||||
CK_ATTRIBUTE *ntemplate = NULL;
|
||||
@@ -450,7 +483,7 @@ sftkdb_FindObjectsInit(SFTKDBHandle *handle, const CK_ATTRIBUTE *template,
|
||||
|
||||
CK_RV
|
||||
sftkdb_FindObjects(SFTKDBHandle *handle, SDBFind *find,
|
||||
CK_OBJECT_HANDLE *ids, int arraySize, int *count)
|
||||
CK_OBJECT_HANDLE *ids, int arraySize, CK_ULONG *count)
|
||||
{
|
||||
CK_RV crv;
|
||||
if (handle == NULL) {
|
||||
@@ -479,7 +512,7 @@ CK_RV sftkdb_FindObjectsFinal(SFTKDBHandle *handle, SDBFind *find)
|
||||
|
||||
CK_RV
|
||||
sftkdb_GetAttributeValue(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id,
|
||||
CK_ATTRIBUTE *template, int count)
|
||||
CK_ATTRIBUTE *template, CK_ULONG count)
|
||||
{
|
||||
CK_RV crv,crv2;
|
||||
CK_ATTRIBUTE *ntemplate;
|
||||
@@ -511,7 +544,7 @@ sftkdb_GetAttributeValue(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id,
|
||||
|
||||
CK_RV
|
||||
sftkdb_SetAttributeValue(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id,
|
||||
const CK_ATTRIBUTE *template, int count)
|
||||
const CK_ATTRIBUTE *template, CK_ULONG count)
|
||||
{
|
||||
CK_RV crv = CKR_OK;
|
||||
CK_ATTRIBUTE *ntemplate;
|
||||
@@ -673,7 +706,6 @@ sftkdb_Abort(SFTKDBHandle *handle)
|
||||
* name="My other PKCS#11 module"
|
||||
*/
|
||||
|
||||
|
||||
static char *
|
||||
sftkdb_quote(const char *string, char quote)
|
||||
{
|
||||
@@ -759,7 +791,7 @@ sftkdb_releaseSpecList(char **moduleSpecList)
|
||||
* Read all the existing modules in out of the file.
|
||||
*/
|
||||
char **
|
||||
sftkdb_ReadSecmodDB(const char *dbType, const char *appName,
|
||||
sftkdb_ReadSecmodDB(SDBType dbType, const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *params, PRBool rw)
|
||||
{
|
||||
@@ -774,9 +806,8 @@ sftkdb_ReadSecmodDB(const char *dbType, const char *appName,
|
||||
char *paramsValue=NULL;
|
||||
PRBool failed = PR_TRUE;
|
||||
|
||||
if ((dbType == NULL) || (PORT_Strcmp(dbType, MULTIACCESS) == 0)) {
|
||||
/* SHDB_FIXME: Handle Legacy code */
|
||||
return moduleList;
|
||||
if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
|
||||
return sftkdbCall_ReadSecmodDB(appName, filename, dbname, params, rw);
|
||||
}
|
||||
|
||||
moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
|
||||
@@ -987,10 +1018,14 @@ loser:
|
||||
}
|
||||
|
||||
SECStatus
|
||||
sftkdb_ReleaseSecmodDBData(const char *dbType, const char *appName,
|
||||
sftkdb_ReleaseSecmodDBData(SDBType dbType, const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char **moduleSpecList, PRBool rw)
|
||||
{
|
||||
if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
|
||||
return sftkdbCall_ReleaseSecmodDBData(appName, filename, dbname,
|
||||
moduleSpecList, rw);
|
||||
}
|
||||
if (moduleSpecList) {
|
||||
sftkdb_releaseSpecList(moduleSpecList);
|
||||
}
|
||||
@@ -1002,7 +1037,7 @@ sftkdb_ReleaseSecmodDBData(const char *dbType, const char *appName,
|
||||
* Delete a module from the Data Base
|
||||
*/
|
||||
SECStatus
|
||||
sftkdb_DeleteSecmodDB(const char *dbType, const char *appName,
|
||||
sftkdb_DeleteSecmodDB(SDBType dbType, const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *args, PRBool rw)
|
||||
{
|
||||
@@ -1018,9 +1053,8 @@ sftkdb_DeleteSecmodDB(const char *dbType, const char *appName,
|
||||
PRBool skip = PR_FALSE;
|
||||
PRBool found = PR_FALSE;
|
||||
|
||||
if ((dbType == NULL) || (PORT_Strcmp(dbType, MULTIACCESS) == 0)) {
|
||||
/* SHDB_FIXME: Handle Legacy code */
|
||||
return SECFailure;
|
||||
if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
|
||||
return sftkdbCall_DeleteSecmodDB(appName, filename, dbname, args, rw);
|
||||
}
|
||||
|
||||
if (!rw) {
|
||||
@@ -1127,7 +1161,7 @@ loser:
|
||||
* Add a module to the Data base
|
||||
*/
|
||||
SECStatus
|
||||
sftkdb_AddSecmodDB(const char *dbType, const char *appName,
|
||||
sftkdb_AddSecmodDB(SDBType dbType, const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *module, PRBool rw)
|
||||
{
|
||||
@@ -1135,9 +1169,8 @@ sftkdb_AddSecmodDB(const char *dbType, const char *appName,
|
||||
char *block = NULL;
|
||||
PRBool libFound = PR_FALSE;
|
||||
|
||||
if ((dbType == NULL) || (PORT_Strcmp(dbType, MULTIACCESS) == 0)) {
|
||||
/* SHDB_FIXME: Handle Legacy code */
|
||||
return SECFailure;
|
||||
if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
|
||||
return sftkdbCall_AddSecmodDB(appName, filename, dbname, module, rw);
|
||||
}
|
||||
|
||||
/* can't write to a read only module */
|
||||
@@ -1259,13 +1292,32 @@ loser:
|
||||
*/
|
||||
typedef struct sftkCipherValueStr sftkCipherValue;
|
||||
struct sftkCipherValueStr {
|
||||
PLArenaPool *arena;
|
||||
SECOidTag alg;
|
||||
NSSPKCS5PBEParameter *param;
|
||||
SECItem salt;
|
||||
SECItem value;
|
||||
};
|
||||
|
||||
#define SFTK_CIPHERTEXT_VERSION 3
|
||||
|
||||
struct SFTKDBEncryptedDataInfoStr {
|
||||
SECAlgorithmID algorithm;
|
||||
SECItem encryptedData;
|
||||
};
|
||||
typedef struct SFTKDBEncryptedDataInfoStr SFTKDBEncryptedDataInfo;
|
||||
|
||||
const SEC_ASN1Template sftkdb_EncryptedDataInfoTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(SFTKDBEncryptedDataInfo) },
|
||||
{ SEC_ASN1_INLINE,
|
||||
offsetof(SFTKDBEncryptedDataInfo,algorithm),
|
||||
SECOID_AlgorithmIDTemplate },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(SFTKDBEncryptedDataInfo,encryptedData) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* This parses the cipherText into cipher value. NOTE: cipherValue will point
|
||||
* to data in cipherText, if cipherText is freed, cipherValue will be invalid.
|
||||
@@ -1288,44 +1340,44 @@ struct sftkCipherValueStr {
|
||||
static SECStatus
|
||||
sftkdb_decodeCipherText(SECItem *cipherText, sftkCipherValue *cipherValue)
|
||||
{
|
||||
int slen, olen, vlen, nlen;
|
||||
SECItem oid;
|
||||
PLArenaPool *arena = NULL;
|
||||
SFTKDBEncryptedDataInfo edi;
|
||||
SECStatus rv;
|
||||
|
||||
/* make sure we have data to check */
|
||||
if (cipherText->data == NULL || cipherText->len <= 3 ) {
|
||||
goto loser;
|
||||
}
|
||||
if (cipherText->data[0] != SFTK_CIPHERTEXT_VERSION) {
|
||||
goto loser;
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
cipherValue->arena = NULL;
|
||||
cipherValue->param = NULL;
|
||||
|
||||
/* parse the header */
|
||||
slen = cipherText->data[1];
|
||||
nlen = cipherText->data[2];
|
||||
if (cipherText->len <= (3+nlen+slen) ) {
|
||||
rv = SEC_QuickDERDecodeItem(arena, &edi, sftkdb_EncryptedDataInfoTemplate,
|
||||
cipherText);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
olen = cipherText->data[3+nlen+slen];
|
||||
vlen = cipherText->len - (4+nlen+slen+olen);
|
||||
if (vlen <= 0 ) {
|
||||
goto loser;
|
||||
}
|
||||
cipherValue->salt.data = &cipherText->data[3];
|
||||
cipherValue->salt.len = slen;
|
||||
oid.data = &cipherText->data[4+nlen+slen];
|
||||
oid.len = olen;
|
||||
cipherValue->value.data = &cipherText->data[4+nlen+slen+olen];
|
||||
cipherValue->value.len = vlen;
|
||||
cipherValue->alg = SECOID_FindOIDTag(&oid);
|
||||
if (cipherValue->alg == SEC_OID_UNKNOWN) {
|
||||
cipherValue->alg = SECOID_GetAlgorithmTag(&edi.algorithm);
|
||||
cipherValue->param = nsspkcs5_AlgidToParam(&edi.algorithm);
|
||||
if (cipherValue->param == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
cipherValue->value = edi.encryptedData;
|
||||
cipherValue->arena = arena;
|
||||
|
||||
return SECSuccess;
|
||||
loser:
|
||||
/* PORT_SETERROR */
|
||||
if (cipherValue->param) {
|
||||
nsspkcs5_DestroyPBEParameter(cipherValue->param);
|
||||
cipherValue->param = NULL;
|
||||
}
|
||||
if (arena) {
|
||||
PORT_FreeArena(arena,PR_FALSE);
|
||||
}
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* unlike decode, Encode actually allocates a SECItem the caller must free
|
||||
* The caller can pass an optional arena to to indicate where to place
|
||||
@@ -1335,38 +1387,42 @@ static SECStatus
|
||||
sftkdb_encodeCipherText(PLArenaPool *arena, sftkCipherValue *cipherValue,
|
||||
SECItem **cipherText)
|
||||
{
|
||||
int slen, olen, vlen, len;
|
||||
SECOidData *oid;
|
||||
SFTKDBEncryptedDataInfo edi;
|
||||
SECAlgorithmID *algid;
|
||||
SECStatus rv;
|
||||
PLArenaPool *localArena = NULL;
|
||||
|
||||
/* First get the entire length */
|
||||
oid = SECOID_FindOIDByTag(cipherValue->alg);
|
||||
if (oid == NULL) {
|
||||
goto loser;
|
||||
|
||||
localArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (localArena == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
slen = cipherValue->salt.len;
|
||||
olen = oid->oid.len;
|
||||
vlen = cipherValue->value.len;
|
||||
/* now get the total length */
|
||||
len = 4 + slen + olen + vlen;
|
||||
algid = nsspkcs5_CreateAlgorithmID(localArena, cipherValue->alg,
|
||||
cipherValue->param);
|
||||
if (algid == NULL) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
}
|
||||
rv = SECOID_CopyAlgorithmID(localArena, &edi.algorithm, algid);
|
||||
SECOID_DestroyAlgorithmID(algid, PR_TRUE);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
edi.encryptedData = cipherValue->value;
|
||||
|
||||
/* get our new secitem */
|
||||
*cipherText = SECITEM_AllocItem(arena, NULL, len);
|
||||
*cipherText = SEC_ASN1EncodeItem(arena, NULL, &edi,
|
||||
sftkdb_EncryptedDataInfoTemplate);
|
||||
if (*cipherText == NULL) {
|
||||
goto loser;
|
||||
rv = SECFailure;
|
||||
}
|
||||
(*cipherText)->data[0] = SFTK_CIPHERTEXT_VERSION;
|
||||
(*cipherText)->data[1] = slen;
|
||||
(*cipherText)->data[2] = 0;
|
||||
PORT_Memcpy(&(*cipherText)->data[3],cipherValue->salt.data,slen);
|
||||
(*cipherText)->data[3+slen] = olen;
|
||||
PORT_Memcpy(&(*cipherText)->data[4+slen],oid->oid.data,olen);
|
||||
PORT_Memcpy(&(*cipherText)->data[4+slen+olen],cipherValue->value.data,vlen);
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
return SECFailure;
|
||||
if (localArena) {
|
||||
PORT_FreeArena(localArena,PR_FALSE);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
@@ -1381,7 +1437,6 @@ sftkdb_decrypt(SECItem *passKey, SECItem *cipherText, SECItem **plain)
|
||||
{
|
||||
SECStatus rv;
|
||||
sftkCipherValue cipherValue;
|
||||
NSSPKCS5PBEParameter *param = NULL;
|
||||
|
||||
/* First get the cipher type */
|
||||
rv = sftkdb_decodeCipherText(cipherText, &cipherValue);
|
||||
@@ -1389,12 +1444,7 @@ sftkdb_decrypt(SECItem *passKey, SECItem *cipherText, SECItem **plain)
|
||||
goto loser;
|
||||
}
|
||||
|
||||
param = nsspkcs5_NewParam(cipherValue.alg, &cipherValue.salt, 1);
|
||||
if (param == NULL) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
}
|
||||
*plain = nsspkcs5_CipherData(param, passKey, &cipherValue.value,
|
||||
*plain = nsspkcs5_CipherData(cipherValue.param, passKey, &cipherValue.value,
|
||||
PR_FALSE, NULL);
|
||||
if (*plain == NULL) {
|
||||
rv = SECFailure;
|
||||
@@ -1402,8 +1452,11 @@ sftkdb_decrypt(SECItem *passKey, SECItem *cipherText, SECItem **plain)
|
||||
}
|
||||
|
||||
loser:
|
||||
if (param) {
|
||||
nsspkcs5_DestroyPBEParameter(param);
|
||||
if (cipherValue.param) {
|
||||
nsspkcs5_DestroyPBEParameter(cipherValue.param);
|
||||
}
|
||||
if (cipherValue.arena) {
|
||||
PORT_FreeArena(cipherValue.arena,PR_FALSE);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -1441,8 +1494,8 @@ sftkdb_encrypt(PLArenaPool *arena, SECItem *passKey, SECItem *plainText,
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
}
|
||||
cipherValue.value.data = cipher->data;
|
||||
cipherValue.value.len = cipher->len;
|
||||
cipherValue.value = *cipher;
|
||||
cipherValue.param = param;
|
||||
|
||||
rv = sftkdb_encodeCipherText(arena, &cipherValue, cipherText);
|
||||
if (rv != SECSuccess) {
|
||||
@@ -1458,6 +1511,61 @@ loser:
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* stub files for legacy db's to be able to encrypt and decrypt
|
||||
* various keys and attributes.
|
||||
*/
|
||||
SECStatus
|
||||
sftkdb_encrypt_stub(PRArenaPool *arena, SDB *sdb, SECItem *plainText,
|
||||
SECItem **cipherText)
|
||||
{
|
||||
SFTKDBHandle *handle = sdb->app_private;
|
||||
SECStatus rv;
|
||||
|
||||
/* not a key handle */
|
||||
if (handle == NULL || handle->passwordLock == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
PZ_Lock(handle->passwordLock);
|
||||
if (handle->passwordKey.data == NULL) {
|
||||
PZ_Unlock(handle->passwordLock);
|
||||
/* PORT_SetError */
|
||||
return SECFailure;
|
||||
}
|
||||
rv = sftkdb_encrypt(arena, &handle->passwordKey, plainText, cipherText);
|
||||
PZ_Unlock(handle->passwordLock);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* stub files for legacy db's to be able to encrypt and decrypt
|
||||
* various keys and attributes.
|
||||
*/
|
||||
SECStatus
|
||||
sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText)
|
||||
{
|
||||
SFTKDBHandle *handle = sdb->app_private;
|
||||
SECStatus rv;
|
||||
|
||||
if (handle == NULL || handle->passwordLock == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
PZ_Lock(handle->passwordLock);
|
||||
if (handle->passwordKey.data == NULL) {
|
||||
PZ_Unlock(handle->passwordLock);
|
||||
/* PORT_SetError */
|
||||
return SECFailure;
|
||||
}
|
||||
rv = sftkdb_decrypt(&handle->passwordKey, cipherText, plainText);
|
||||
PZ_Unlock(handle->passwordLock);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* safely swith the passed in key for the one caches in the keydb handle
|
||||
@@ -1713,7 +1821,7 @@ SECStatus
|
||||
sftkdb_convertPrivateObjects(SFTKDBHandle *keydb, SECItem *newKey)
|
||||
{
|
||||
SDBFind *find = NULL;
|
||||
int idCount = MAX_IDS;
|
||||
CK_ULONG idCount = MAX_IDS;
|
||||
CK_OBJECT_HANDLE ids[MAX_IDS];
|
||||
CK_RV crv, crv2;
|
||||
int i;
|
||||
@@ -1759,6 +1867,8 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb, char *oldPin, char *newPin)
|
||||
SDBPasswordEntry entry;
|
||||
CK_RV crv;
|
||||
|
||||
newKey.data = NULL;
|
||||
|
||||
/* make sure we have a valid old pin */
|
||||
crv = (*keydb->db->sdb_Begin)(keydb->db);
|
||||
if (crv != CKR_OK) {
|
||||
@@ -1934,6 +2044,7 @@ sftk_NewDBHandle(SDB *sdb, int type)
|
||||
if (type == SFTK_KEYDB_TYPE) {
|
||||
handle->passwordLock = PZ_NewLock();
|
||||
}
|
||||
sdb->app_private = handle;
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -1968,7 +2079,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
|
||||
SFTKDBHandle **certDB, SFTKDBHandle **keyDB)
|
||||
{
|
||||
const char *confdir;
|
||||
const char *dbType = NULL;
|
||||
SDBType dbType;
|
||||
char *appName = NULL;
|
||||
SDB *keySDB, *certSDB;
|
||||
CK_RV crv = CKR_OK;
|
||||
@@ -1985,9 +2096,29 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
|
||||
return CKR_OK;
|
||||
}
|
||||
confdir = sftk_EvaluateConfigDir(configdir, &dbType, &appName);
|
||||
/* FIXME_ -- prefixes */
|
||||
crv = s_open(confdir, certPrefix, keyPrefix, 9, 4, flags,
|
||||
noCertDB? NULL : &certSDB, noKeyDB ? NULL : &keySDB);
|
||||
|
||||
/*
|
||||
* now initialize the appropriate database
|
||||
*/
|
||||
switch (dbType) {
|
||||
case SDB_LEGACY:
|
||||
crv = sftkdbCall_open(confdir, certPrefix, keyPrefix, 8, 3, flags,
|
||||
noCertDB? NULL : &certSDB, noKeyDB ? NULL: &keySDB);
|
||||
break;
|
||||
case SDB_MULTIACCESS:
|
||||
crv = sftkdbCall_open(configdir, certPrefix, keyPrefix, 8, 3, flags,
|
||||
noCertDB? NULL : &certSDB, noKeyDB ? NULL: &keySDB);
|
||||
break;
|
||||
case SDB_SHARED:
|
||||
case SDB_LOADABLE: /* SHOULD open a loadable db */
|
||||
crv = s_open(confdir, certPrefix, keyPrefix, 9, 4, flags,
|
||||
noCertDB? NULL : &certSDB, noKeyDB ? NULL : &keySDB);
|
||||
break;
|
||||
default:
|
||||
crv = CKR_GENERAL_ERROR; /* can't happen, EvaluationConfigDir MUST
|
||||
* return one of the types we already
|
||||
* specified. */
|
||||
}
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
@@ -1998,6 +2129,9 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
|
||||
}
|
||||
if (!noKeyDB) {
|
||||
*keyDB = sftk_NewDBHandle(keySDB, SFTK_KEYDB_TYPE);
|
||||
if (certSDB) {
|
||||
certSDB->app_private = *keyDB;
|
||||
}
|
||||
} else {
|
||||
*keyDB = NULL;
|
||||
}
|
||||
@@ -2009,3 +2143,10 @@ loser:
|
||||
return forceOpen ? CKR_OK : crv;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
sftkdb_Shutdown(void)
|
||||
{
|
||||
s_shutdown();
|
||||
sftkdbCall_Shutdown();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,29 +10,30 @@
|
||||
/* raw database stuff */
|
||||
CK_RV sftkdb_write(SFTKDBHandle *handle, SFTKObject *,CK_OBJECT_HANDLE *);
|
||||
CK_RV sftkdb_FindObjectsInit(SFTKDBHandle *sdb, const CK_ATTRIBUTE *template,
|
||||
int count, SDBFind **find);
|
||||
CK_ULONG count, SDBFind **find);
|
||||
CK_RV sftkdb_FindObjects(SFTKDBHandle *sdb, SDBFind *find,
|
||||
CK_OBJECT_HANDLE *ids, int arraySize, int *count);
|
||||
CK_OBJECT_HANDLE *ids, int arraySize, CK_ULONG *count);
|
||||
CK_RV sftkdb_FindObjectsFinal(SFTKDBHandle *sdb, SDBFind *find);
|
||||
CK_RV sftkdb_GetAttributeValue(SFTKDBHandle *handle,
|
||||
CK_OBJECT_HANDLE object_id, CK_ATTRIBUTE *template, int count);
|
||||
CK_OBJECT_HANDLE object_id, CK_ATTRIBUTE *template, CK_ULONG count);
|
||||
CK_RV sftkdb_SetAttributeValue(SFTKDBHandle *handle,
|
||||
CK_OBJECT_HANDLE object_id, const CK_ATTRIBUTE *template, int count);
|
||||
CK_OBJECT_HANDLE object_id, const CK_ATTRIBUTE *template,
|
||||
CK_ULONG count);
|
||||
CK_RV sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id);
|
||||
CK_RV sftkdb_closeDB(SFTKDBHandle *handle);
|
||||
|
||||
|
||||
/* secmod.db functions */
|
||||
char ** sftkdb_ReadSecmodDB(const char *dbType, const char *appName,
|
||||
char ** sftkdb_ReadSecmodDB(SDBType dbType, const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *params, PRBool rw);
|
||||
SECStatus sftkdb_ReleaseSecmodDBData(const char *dbType, const char *appName,
|
||||
SECStatus sftkdb_ReleaseSecmodDBData(SDBType dbType, const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char **moduleSpecList, PRBool rw);
|
||||
SECStatus sftkdb_DeleteSecmodDB(const char *dbType, const char *appName,
|
||||
SECStatus sftkdb_DeleteSecmodDB(SDBType dbType, const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *args, PRBool rw);
|
||||
SECStatus sftkdb_AddSecmodDB(const char *dbType, const char *appName,
|
||||
SECStatus sftkdb_AddSecmodDB(SDBType dbType, const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *module, PRBool rw);
|
||||
|
||||
@@ -68,10 +69,21 @@ CK_RV sftk_DBInit(const char *configdir, const char *certPrefix,
|
||||
const char *keyPrefix, PRBool readOnly, PRBool noCertDB,
|
||||
PRBool noKeyDB, PRBool forceOpen,
|
||||
SFTKDBHandle **certDB, SFTKDBHandle **keyDB);
|
||||
CK_RV sftkdb_Shutdown(void);
|
||||
|
||||
SFTKDBHandle *sftk_getCertDB(SFTKSlot *slot);
|
||||
SFTKDBHandle *sftk_getKeyDB(SFTKSlot *slot);
|
||||
SFTKDBHandle *sftk_getDBForObject(SFTKSlot *slot, CK_OBJECT_HANDLE objectID);
|
||||
void sftk_freeDB(SFTKDBHandle *certHandle);
|
||||
|
||||
/*
|
||||
* for lgglue, stubs to encrypt and decrypt password entries
|
||||
*/
|
||||
SECStatus sftkdb_encrypt_stub(PRArenaPool *arena, SDB *sdb, SECItem *plainText,
|
||||
SECItem **cipherText);
|
||||
SECStatus sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText,
|
||||
SECItem **plainText);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,4 +7,11 @@
|
||||
#define SFTKDBT_H 1
|
||||
typedef struct SFTKDBHandleStr SFTKDBHandle;
|
||||
|
||||
typedef enum {
|
||||
SDB_SHARED,
|
||||
SDB_LOADABLE,
|
||||
SDB_LEGACY,
|
||||
SDB_MULTIACCESS
|
||||
} SDBType;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "pkcs11i.h"
|
||||
#include "sdb.h"
|
||||
#include "prprf.h"
|
||||
#include "prenv.h"
|
||||
|
||||
/*
|
||||
* this file contains routines for parsing PKCS #11 module spec
|
||||
@@ -519,14 +520,15 @@ sftk_freeParams(sftk_parameters *params)
|
||||
|
||||
#define SHAREDB "shared:"
|
||||
#define LOADABLE "load:"
|
||||
#define LEGACY "dbm:"
|
||||
const char *
|
||||
sftk_EvaluateConfigDir(const char *configdir, const char **dbType, char **appName)
|
||||
sftk_EvaluateConfigDir(const char *configdir, SDBType *dbType, char **appName)
|
||||
{
|
||||
*appName = NULL;
|
||||
*dbType = NULL;
|
||||
*dbType = SDB_LEGACY;
|
||||
if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) {
|
||||
char *cdir;
|
||||
*dbType = MULTIACCESS;
|
||||
*dbType = SDB_MULTIACCESS;
|
||||
|
||||
*appName = PORT_Strdup(configdir+sizeof(MULTIACCESS)-1);
|
||||
if (*appName == NULL) {
|
||||
@@ -542,16 +544,35 @@ sftk_EvaluateConfigDir(const char *configdir, const char **dbType, char **appNam
|
||||
}
|
||||
configdir = cdir;
|
||||
} else if (PORT_Strncmp(configdir, SHAREDB, sizeof(SHAREDB)-1) == 0) {
|
||||
*dbType = SHAREDB;
|
||||
*dbType = SDB_SHARED;
|
||||
configdir = configdir + sizeof(SHAREDB) -1;
|
||||
} else if (PORT_Strncmp(configdir, LOADABLE, sizeof(LOADABLE)-1) == 0) {
|
||||
*dbType = SDB_LOADABLE;
|
||||
configdir = configdir + sizeof(LOADABLE) -1;
|
||||
} else if (PORT_Strncmp(configdir, LEGACY, sizeof(LEGACY)-1) == 0) {
|
||||
*dbType = SDB_LEGACY;
|
||||
configdir = configdir + sizeof(LEGACY) -1;
|
||||
} else {
|
||||
/* look up the default from the environment */
|
||||
char *defaultType = PR_GetEnv("NSS_DEFAULT_DB_TYPE");
|
||||
if (defaultType == NULL) {
|
||||
/* none specified, go with the legacy */
|
||||
return configdir;
|
||||
}
|
||||
if (PORT_Strncmp(defaultType, SHAREDB, sizeof(SHAREDB)-2) == 0) {
|
||||
*dbType = SDB_SHARED;
|
||||
} else if (PORT_Strncmp(defaultType,LOADABLE,sizeof(LOADABLE)-2)==0) {
|
||||
*dbType = SDB_LOADABLE;
|
||||
} else if (PORT_Strncmp(defaultType, LEGACY, sizeof(LEGACY)-2) == 0) {
|
||||
*dbType = SDB_LEGACY;
|
||||
}
|
||||
}
|
||||
/* comment this out to support legacy */
|
||||
*dbType = SHAREDB;
|
||||
return configdir;
|
||||
}
|
||||
|
||||
char *
|
||||
sftk_getSecmodName(char *param, const char **dbType, char **appName, char **filename,PRBool *rw)
|
||||
sftk_getSecmodName(char *param, SDBType *dbType, char **appName,
|
||||
char **filename,PRBool *rw)
|
||||
{
|
||||
int next;
|
||||
char *configdir = NULL;
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
* license
|
||||
*/
|
||||
#include "pkcs11i.h"
|
||||
#include "sftkdbt.h"
|
||||
|
||||
/* parsing functions */
|
||||
char * sftk_argFetchValue(char *string, int *pcount);
|
||||
char * sftk_getSecmodName(char *param, const char **dbType, char **appName, char **filename,PRBool *rw);
|
||||
char * sftk_getSecmodName(char *param, SDBType *dbType, char **appName, char **filename,PRBool *rw);
|
||||
char *sftk_argStrip(char *c);
|
||||
CK_RV sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS);
|
||||
void sftk_freeParams(sftk_parameters *params);
|
||||
const char *sftk_EvaluateConfigDir(const char *configdir, const char **dbType, char **app);
|
||||
const char *sftk_EvaluateConfigDir(const char *configdir, SDBType *dbType, char **app);
|
||||
char * sftk_argGetParamValue(char *paramName,char *parameters);
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: softoken.h,v 1.14 2006-10-02 22:48:31 wtchang%redhat.com Exp $ */
|
||||
/* $Id: softoken.h,v 1.14.2.1 2007-04-03 22:50:01 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifndef _SOFTOKEN_H_
|
||||
#define _SOFTOKEN_H_
|
||||
@@ -147,6 +147,10 @@ SECStatus RSA_DecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
|
||||
*/
|
||||
extern SECStatus EC_FillParams(PRArenaPool *arena,
|
||||
const SECItem *encodedParams, ECParams *params);
|
||||
extern SECStatus EC_DecodeParams(const SECItem *encodedParams,
|
||||
ECParams **ecparams);
|
||||
extern SECStatus EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
|
||||
const ECParams *srcParams);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user