fixup commit for branch 'BOOKMARKS_20030320_BRANCH' BOOKMARKS_20030320_BRANCH
authorcvs2hg
Tue, 25 Feb 2003 01:43:55 +0000
branchBOOKMARKS_20030320_BRANCH
changeset 4213 64ba5379499056bd903b8cd3a3b84957ef2b5fb4
parent 3921 66928a952340e47619bb822b3de6899c7a96e295
child 13794 38a9485aa53a03ad88129f6bffb8019b381be4e5
push idunknown
push userunknown
push dateunknown
fixup commit for branch 'BOOKMARKS_20030320_BRANCH'
dbm/include/mcom_db.h
dbm/src/Makefile.in
dbm/src/hash.c
dbm/src/mktemp.c
dbm/src/ndbm.c
security/coreconf/Darwin.mk
security/coreconf/OS2.mk
security/coreconf/platform.mk
security/coreconf/rules.mk
security/dbm/Makefile
security/dbm/config/config.mk
security/dbm/include/Makefile
security/dbm/include/manifest.mn
security/dbm/manifest.mn
security/dbm/src/Makefile
security/dbm/src/config.mk
security/dbm/src/dirent.c
security/dbm/src/dirent.h
security/dbm/src/manifest.mn
security/dbm/tests/Makefile
security/nss/cmd/bltest/blapitest.c
security/nss/cmd/bltest/tests/sha256/ciphertext0
security/nss/cmd/bltest/tests/sha256/ciphertext1
security/nss/cmd/bltest/tests/sha256/numtests
security/nss/cmd/bltest/tests/sha256/plaintext0
security/nss/cmd/bltest/tests/sha256/plaintext1
security/nss/cmd/bltest/tests/sha384/ciphertext0
security/nss/cmd/bltest/tests/sha384/ciphertext1
security/nss/cmd/bltest/tests/sha384/numtests
security/nss/cmd/bltest/tests/sha384/plaintext0
security/nss/cmd/bltest/tests/sha384/plaintext1
security/nss/cmd/bltest/tests/sha512/ciphertext0
security/nss/cmd/bltest/tests/sha512/ciphertext1
security/nss/cmd/bltest/tests/sha512/numtests
security/nss/cmd/bltest/tests/sha512/plaintext0
security/nss/cmd/bltest/tests/sha512/plaintext1
security/nss/cmd/certutil/certutil.c
security/nss/cmd/smimetools/cmsutil.c
security/nss/cmd/strsclnt/strsclnt.c
security/nss/cmd/vfychain/Makefile
security/nss/cmd/vfychain/manifest.mn
security/nss/cmd/vfychain/vfychain.c
security/nss/cmd/vfyserv/vfyutil.c
security/nss/lib/base/errorval.c
security/nss/lib/certdb/cert.h
security/nss/lib/certdb/certdb.c
security/nss/lib/certdb/certi.h
security/nss/lib/certdb/certv3.c
security/nss/lib/certhigh/certvfy.c
security/nss/lib/ckfw/nssck.api
security/nss/lib/crmf/respcmn.c
security/nss/lib/cryptohi/hasht.h
security/nss/lib/cryptohi/sechash.c
security/nss/lib/dev/devtoken.c
security/nss/lib/freebl/blapi.h
security/nss/lib/freebl/ldvector.c
security/nss/lib/freebl/loader.c
security/nss/lib/freebl/loader.h
security/nss/lib/freebl/manifest.mn
security/nss/lib/nss/nss.def
security/nss/lib/nss/nss.h
security/nss/lib/nss/nssinit.c
security/nss/lib/pk11wrap/debug_module.c
security/nss/lib/pk11wrap/manifest.mn
security/nss/lib/pk11wrap/pk11cert.c
security/nss/lib/pk11wrap/pk11func.h
security/nss/lib/pk11wrap/pk11init.h
security/nss/lib/pk11wrap/pk11sdr.c
security/nss/lib/pk11wrap/pk11skey.c
security/nss/lib/pk11wrap/pk11slot.c
security/nss/lib/pk11wrap/secmodi.h
security/nss/lib/pki/cryptocontext.c
security/nss/lib/pki/pki3hack.c
security/nss/lib/pki/pki3hack.h
security/nss/lib/pki/pkibase.c
security/nss/lib/pki/pkistore.c
security/nss/lib/pki/pkistore.h
security/nss/lib/pki/tdcache.c
security/nss/lib/pki/trustdomain.c
security/nss/lib/pki1/config.mk
security/nss/lib/pki1/manifest.mn
security/nss/lib/smime/cms.h
security/nss/lib/smime/cmsencdata.c
security/nss/lib/smime/cmslocal.h
security/nss/lib/smime/cmspubkey.c
security/nss/lib/smime/cmsrecinfo.c
security/nss/lib/smime/cmssigdata.c
security/nss/lib/smime/cmssiginfo.c
security/nss/lib/smime/cmst.h
security/nss/lib/smime/smime.def
security/nss/lib/softoken/alghmac.c
security/nss/lib/softoken/dbmshim.c
security/nss/lib/softoken/keydb.c
security/nss/lib/softoken/pcertdb.c
security/nss/lib/softoken/pkcs11.c
security/nss/lib/softoken/pkcs11c.c
security/nss/lib/softoken/pkcs11i.h
security/nss/lib/softoken/pkcs11n.h
security/nss/lib/softoken/rawhash.c
security/nss/lib/ssl/ssl3con.c
security/nss/lib/util/secerr.h
security/nss/lib/util/secoid.c
security/nss/lib/util/secoidt.h
security/nss/tests/cipher/cipher.txt
security/nss/tests/cmdtests/cmdtests.sh
security/nss/tests/dbtests/dbtests.sh
--- a/dbm/include/mcom_db.h
+++ b/dbm/include/mcom_db.h
@@ -217,16 +217,24 @@
 #if defined(_WINDOWS) || defined(XP_OS2)
 #include <stdio.h>
 #include <io.h>
 
 #ifndef XP_OS2 
 #define MAXPATHLEN 	1024               
 #endif
 
+#ifdef XP_OS2_VACPP
+#include <os2.h>
+#define	MAXPATHLEN	CCHMAXPATH
+#define	EPERM		EINVAL
+#define	ENOTDIR		EBADPOS
+#define	S_ISDIR(s)	((s) & S_IFDIR)
+#endif
+
 #define	EFTYPE		EINVAL		/* POSIX 1003.1 format errno. */
 
 #ifndef	STDERR_FILENO
 #define	STDIN_FILENO	0		/* ANSI C #defines */
 #define	STDOUT_FILENO	1
 #define	STDERR_FILENO	2
 #endif
 
--- a/dbm/src/Makefile.in
+++ b/dbm/src/Makefile.in
@@ -46,21 +46,21 @@ CSRCS		= \
 		ndbm.c \
 		strerror.c \
 		nsres.c \
 		$(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
 CSRCS		+= memmove.c snprintf.c
 else
-ifeq (,$(filter -DHAVE_MEMMOVE=1,$(DEFS)))
+ifeq (,$(filter -DHAVE_MEMMOVE=1,$(ACDEFINES)))
 CSRCS += memmove.c
 endif
 
-ifeq (,$(filter -DHAVE_SNPRINTF=1,$(DEFS)))
+ifeq (,$(filter -DHAVE_SNPRINTF=1,$(ACDEFINES)))
 CSRCS += snprintf.c
 endif
 endif # WINNT
 
 LOCAL_INCLUDES	= -I$(srcdir)/../include
 
 FORCE_STATIC_LIB = 1
 FORCE_USE_PIC = 1
--- a/dbm/src/hash.c
+++ b/dbm/src/hash.c
@@ -64,21 +64,16 @@ static char sccsid[] = "@(#)hash.c	8.9 (
 
 #if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) && !defined(XP_OS2_VACPP)
 #include <unistd.h>
 #endif
 #if defined(_WIN32) || defined(_WINDOWS) 
 #include <windows.h>
 #endif
 
-#ifdef XP_OS2_VACPP
-#include "types.h"
-#define EPERM SOCEPERM
-#endif
-
 #include <assert.h>
 
 #include "mcom_db.h"
 #include "hash.h"
 #include "page.h"
 
 /*
 #include "extern.h"
--- a/dbm/src/mktemp.c
+++ b/dbm/src/mktemp.c
@@ -49,19 +49,17 @@ static char sccsid[] = "@(#)mktemp.c	8.1
 #include <ctype.h>
 #include "mcom_db.h"
 
 #if !defined(_WINDOWS) && !defined(XP_OS2_VACPP)
 #include <unistd.h>
 #endif
 
 #ifdef XP_OS2_VACPP
-#define ENOTDIR EBADPOS
 #include <process.h>
-#include <dirent.h>
 #endif
 
 #ifdef _WINDOWS
 #include <process.h>
 #include "winfile.h"
 #endif
 
 static int _gettemp(char *path, register int *doopen, int extraFlags);
--- a/dbm/src/ndbm.c
+++ b/dbm/src/ndbm.c
@@ -47,20 +47,16 @@ static char sccsid[] = "@(#)ndbm.c	8.4 (
 #if !defined(_WIN32) && !defined(_WINDOWS) && !defined(XP_OS2_VACPP)
 #include <sys/param.h>
 #endif
 
 #if defined(__linux)
 #include <linux/limits.h>
 #endif
 
-#ifdef __OS2__
-#include "dirent.h"
-#endif
-
 #include <stdio.h>
 #include <string.h>
 
 #include "ndbm.h"
 #include "hash.h"
 
 /*
  * Returns:
--- a/security/coreconf/Darwin.mk
+++ b/security/coreconf/Darwin.mk
@@ -30,16 +30,18 @@
 # may use your version of this file under either the MPL or the
 # GPL.
 #
 # Config stuff for Darwin.
 #
 
 include $(CORE_DEPTH)/coreconf/UNIX.mk
 
+DEFAULT_COMPILER = cc
+
 CC		= cc
 CCC		= c++
 RANLIB		= ranlib
 
 ifeq (86,$(findstring 86,$(OS_TEST)))
 OS_REL_CFLAGS	= -Di386
 CPU_ARCH	= i386
 else
--- a/security/coreconf/OS2.mk
+++ b/security/coreconf/OS2.mk
@@ -81,20 +81,26 @@ MKSHLIB                 = $(CXX) $(CXXFL
 MKCSHLIB                = $(CC) $(CFLAGS) $(DSO_LDOPTS) -o $@
 MKSHLIB_FORCE_ALL       = 
 MKSHLIB_UNFORCE_ALL     = 
 DSO_LDOPTS              = -Zomf -Zdll -Zmt -Zcrtdll -Zlinker /NOO
 # DLL_SUFFIX              = .dll
 SHLIB_LDSTARTFILE	= 
 SHLIB_LDENDFILE		= 
 ifdef MAPFILE
-# Add LD options to restrict exported symbols to those in the map file
+MKSHLIB += $(MAPFILE)
 endif
-# Change PROCESS to put the mapfile in the correct format for this platform
-PROCESS_MAP_FILE = copy $(LIBRARY_NAME).def $@
+PROCESS_MAP_FILE = \
+	echo LIBRARY $(LIBRARY_NAME)$(LIBRARY_VERSION) INITINSTANCE TERMINSTANCE > $@; \
+	echo PROTMODE >> $@; \
+	echo CODE    LOADONCALL MOVEABLE DISCARDABLE >> $@; \
+	echo DATA    PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@; \
+	echo EXPORTS >> $@; \
+	grep -v ';+' $(LIBRARY_NAME).def | grep -v ';-' | \
+	sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' >> $@
 
 endif   #NO_SHARED_LIB
 
 OS_CFLAGS          = -Wall -W -Wno-unused -Wpointer-arith -Wcast-align -Zmtd -Zomf -Zmt  -DDEBUG -DDEBUG_wintrinh -DTRACING -g
 
 # Where the libraries are
 MOZ_COMPONENT_NSPR_LIBS=-L$(DIST)/lib $(NSPR_LIBS)
 NSPR_LIBS	= -lplds4 -lplc4 -lnspr4 
@@ -142,42 +148,55 @@ DSO_PIC_CFLAGS          =
 MKSHLIB                 = $(LD) $(DSO_LDOPTS)
 MKCSHLIB                = $(LD) $(DSO_LDOPTS)
 MKSHLIB_FORCE_ALL       = 
 MKSHLIB_UNFORCE_ALL     = 
 DSO_LDOPTS              = 
 # DLL_SUFFIX              = .dll
 SHLIB_LDSTARTFILE	= 
 SHLIB_LDENDFILE		= 
+ifdef MAPFILE
+MKSHLIB += $(MAPFILE)
+endif
+PROCESS_MAP_FILE = \
+	echo LIBRARY $(LIBRARY_NAME)$(LIBRARY_VERSION) INITINSTANCE TERMINSTANCE > $@; \
+	echo PROTMODE >> $@; \
+	echo CODE    LOADONCALL MOVEABLE DISCARDABLE >> $@; \
+	echo DATA    PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@; \
+	echo EXPORTS >> $@; \
+	grep -v ';+' $(LIBRARY_NAME).def | grep -v ';-' | \
+	sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' >> $@
 endif   #NO_SHARED_LIB
 
 OS_CFLAGS          = /Q /qlibansi /Gd /Gm /Su4 /Mp /Tl-
 INCLUDES        += -I$(CORE_DEPTH)/../dist/include
 DEFINES         += -DXP_OS2_VACPP -DTCPV40HDRS
 
 # Where the libraries are
 NSPR_LIBS	= $(DIST)/lib/nspr4.lib $(DIST)/lib/plc4.lib $(DIST)/lib/plds4.lib
 MOZ_COMPONENT_NSPR_LIBS=-L$(DIST)/lib $(NSPR_LIBS)
 NSPR_INCLUDE_DIR =   
 
 
+DLLFLAGS    = /DLL /O:$@ /INC:_dllentry /MAP:$(@:.dll=.map)
+EXEFLAGS    = -PMTYPE:VIO -OUT:$@ -MAP:$(@:.exe=.map) -nologo -NOE
+LDFLAGS     = /FREE /NOE /LINENUMBERS /nologo
+
 ifdef BUILD_OPT
-OPTIMIZER		= -Oi -G5
+OPTIMIZER		= /O+ /Gl+ /G5 /qarch=pentium
 DEFINES 		+= -UDEBUG -U_DEBUG -DNDEBUG
-DLLFLAGS		= /DLL /O:$@ /INC:_dllentry /MAP:$(@:.dll=.map)
-EXEFLAGS    		= -PMTYPE:VIO -OUT:$@ -MAP:$(@:.exe=.map) -nologo -NOE
 OBJDIR_TAG 		= _OPT
-LDFLAGS     = /FREE /NODEBUG /NOE /LINENUMBERS /nologo
+LDFLAGS     += /NODEBUG /OPTFUNC /EXEPACK:2 /PACKCODE /PACKDATA
 else
 OS_CFLAGS   += /Ti+
 DEFINES 		+= -DDEBUG -D_DEBUG -DDEBUGPRINTS     #HCT Need += to avoid overidding manifest.mn 
-DLLFLAGS		= /DEBUG /DLL /O:$@ /INC:_dllentry /MAP:$(@:.dll=.map)
-EXEFLAGS    		= -DEBUG -PMTYPE:VIO -OUT:$@ -MAP:$(@:.exe=.map) -nologo -NOE
+DLLFLAGS    += /DE
+EXEFLAGS    += /DE
 OBJDIR_TAG 		= _DBG
-LDFLAGS 		= /FREE /DE /NOE /LINENUMBERS /nologo 
+LDFLAGS     += /DE
 endif   # BUILD_OPT
 
 endif   # XP_OS2_VACPP
 
 # OS/2 use nsinstall that is included in the toolkit.
 # since we do not wish to support and maintain 3 version of nsinstall in mozilla, nspr and nss
 
 ifdef BUILD_TREE
new file mode 100644
--- /dev/null
+++ b/security/coreconf/platform.mk
@@ -0,0 +1,38 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+# 
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+# 
+# The Original Code is the Netscape security libraries.
+# 
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation.  Portions created by Netscape are 
+# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
+# Rights Reserved.
+# 
+# Contributor(s):
+# 
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable 
+# instead of those above.  If you wish to allow use of your 
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL.  If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# Master "Core Components" <platform> tag                             #
+#######################################################################
+
+PLATFORM = $(OBJDIR_NAME)
--- a/security/coreconf/rules.mk
+++ b/security/coreconf/rules.mk
@@ -307,17 +307,17 @@ else
 	$(AR) $(OBJS)
 endif
 	$(RANLIB) $@
 
 
 ifeq ($(OS_TARGET),OS2)
 $(IMPORT_LIBRARY): $(SHARED_LIBRARY)
 	rm -f $@
-	$(IMPLIB) $@ $(patsubst %.lib,%.dll.def,$@)
+	$(IMPLIB) $@ $(SHARED_LIBRARY)
 	$(RANLIB) $@
 endif
 
 ifdef SHARED_LIBRARY_LIBS
 ifdef BUILD_TREE
 SUB_SHLOBJS = $(foreach dir,$(SHARED_LIBRARY_DIRS),$(shell $(MAKE) -C $(dir) --no-print-directory get_objs))
 else
 SUB_SHLOBJS = $(foreach dir,$(SHARED_LIBRARY_DIRS),$(addprefix $(dir)/,$(shell $(MAKE) -C $(dir) --no-print-directory get_objs)))
@@ -334,35 +334,18 @@ ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.1)
 	| sed -e 's/^\.//' \
 	| sort -u >> $(OBJDIR)/lib$(LIBRARY_NAME)_syms
 	$(LD) $(XCFLAGS) -o $@ $(OBJS) -bE:$(OBJDIR)/lib$(LIBRARY_NAME)_syms \
 	-bM:SRE -bnoentry $(OS_LIBS) $(EXTRA_LIBS) $(EXTRA_SHARED_LIBS)
 else
 ifeq (,$(filter-out WIN%,$(OS_TARGET)))
 	$(LINK_DLL) -MAP $(DLLBASE) $(subst /,\\,$(OBJS) $(SUB_SHLOBJS) $(EXTRA_LIBS) $(EXTRA_SHARED_LIBS) $(OS_LIBS) $(LD_LIBS) $(RES))
 else
-ifeq ($(OS_TARGET),OS2)
-	@cmd /C "echo LIBRARY $(notdir $(basename $(SHARED_LIBRARY))) INITINSTANCE TERMINSTANCE >$@.def"
-	@cmd /C "echo PROTMODE >>$@.def"
-	@cmd /C "echo CODE    LOADONCALL MOVEABLE DISCARDABLE >>$@.def"
-	@cmd /C "echo DATA    PRELOAD MOVEABLE MULTIPLE NONSHARED >>$@.def"	
-	@cmd /C "echo EXPORTS >>$@.def"
-	$(FILTER) $(OBJS) >>$@.def
-ifdef SUB_SHLOBJS
-	@echo Number of words in OBJ list = $(words $(SUB_SHLOBJS))
-	@echo If above number is over 100, need to reedit coreconf/rules.mk
-	-$(FILTER) $(wordlist 1,20,$(SUB_SHLOBJS)) >>$@.def
-	-$(FILTER) $(wordlist 21,40,$(SUB_SHLOBJS)) >>$@.def
-	-$(FILTER) $(wordlist 41,60,$(SUB_SHLOBJS)) >>$@.def
-	-$(FILTER) $(wordlist 61,80,$(SUB_SHLOBJS)) >>$@.def
-	-$(FILTER) $(wordlist 81,100,$(SUB_SHLOBJS)) >>$@.def
-endif
-endif #OS2
 ifdef XP_OS2_VACPP
-	$(MKSHLIB) $(DLLFLAGS) $(LDFLAGS) $(OBJS) $(SUB_SHLOBJS) $(LD_LIBS) $(EXTRA_LIBS) $(EXTRA_SHARED_LIBS) $@.def
+	$(MKSHLIB) $(DLLFLAGS) $(LDFLAGS) $(OBJS) $(SUB_SHLOBJS) $(LD_LIBS) $(EXTRA_LIBS) $(EXTRA_SHARED_LIBS)
 else
 	$(MKSHLIB) -o $@ $(OBJS) $(SUB_SHLOBJS) $(LD_LIBS) $(EXTRA_LIBS) $(EXTRA_SHARED_LIBS)
 endif
 	chmod +x $@
 ifeq ($(OS_TARGET),Darwin)
 ifdef MAPFILE
 	nmedit -s $(MAPFILE) $@
 endif
deleted file mode 100644
--- a/security/dbm/Makefile
+++ /dev/null
@@ -1,80 +0,0 @@
-#! gmake
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-#######################################################################
-# (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).      #
-#######################################################################
-
-
-
-#######################################################################
-# (5) Execute "global" rules. (OPTIONAL)                              #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/rules.mk
-
-#######################################################################
-# (6) Execute "component" rules. (OPTIONAL)                           #
-#######################################################################
-
-
-
-#######################################################################
-# (7) Execute "local" rules. (OPTIONAL).                              #
-#######################################################################
-
-coreconf_hack:
-	cd ../coreconf; gmake
-	gmake import
-
-RelEng_bld: coreconf_hack
-	gmake
deleted file mode 100644
--- a/security/dbm/config/config.mk
+++ /dev/null
@@ -1,67 +0,0 @@
-#! gmake
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-#
-# These macros are defined by mozilla's configure script.
-# We define them manually here.
-#
-
-DEFINES += -DSTDC_HEADERS -DHAVE_STRERROR
-
-#
-# Most platforms have snprintf, so it's simpler to list the exceptions.
-#
-HAVE_SNPRINTF = 1
-#
-# OSF1 V4.0D doesn't have snprintf but V5.0A does.
-#
-ifeq ($(OS_TARGET)$(OS_RELEASE),OSF1V4.0D)
-HAVE_SNPRINTF =
-endif
-ifdef HAVE_SNPRINTF
-DEFINES += -DHAVE_SNPRINTF
-endif
-
-ifeq (,$(filter-out IRIX Linux,$(OS_TARGET)))
-DEFINES += -DHAVE_SYS_CDEFS_H
-endif
-
-ifeq (,$(filter-out DGUX NCR ReliantUNIX SCO_SV SCOOS UNIXWARE,$(OS_TARGET)))
-DEFINES += -DHAVE_SYS_BYTEORDER_H
-endif
-
-#
-# None of the platforms that we are interested in need to
-# define HAVE_MEMORY_H.
-#
deleted file mode 100644
--- a/security/dbm/include/Makefile
+++ /dev/null
@@ -1,76 +0,0 @@
-#! gmake
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-#######################################################################
-# (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).      #
-#######################################################################
-
-
-
-#######################################################################
-# (5) Execute "global" rules. (OPTIONAL)                              #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/rules.mk
-
-#######################################################################
-# (6) Execute "component" rules. (OPTIONAL)                           #
-#######################################################################
-
-
-
-#######################################################################
-# (7) Execute "local" rules. (OPTIONAL).                              #
-#######################################################################
-
-
-
deleted file mode 100644
--- a/security/dbm/include/manifest.mn
+++ /dev/null
@@ -1,57 +0,0 @@
-#! gmake
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-CORE_DEPTH = ../..
-
-VPATH  = $(CORE_DEPTH)/../dbm/include
-
-MODULE = dbm
-
-EXPORTS =	nsres.h   \
-		cdefs.h   \
-		mcom_db.h \
-		ncompat.h \
-		winfile.h \
-		$(NULL)
-
-PRIVATE_EXPORTS =	hsearch.h \
-			page.h    \
-			extern.h  \
-			ndbm.h    \
-			queue.h   \
-			hash.h    \
-			mpool.h   \
-			search.h  \
-			$(NULL)
-
deleted file mode 100644
--- a/security/dbm/manifest.mn
+++ /dev/null
@@ -1,45 +0,0 @@
-#! gmake
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-CORE_DEPTH = ..
-
-MODULE = dbm
-
-IMPORTS = nspr20/v4.1.2
-
-RELEASE = dbm
-
-DIRS =  include \
-        src     \
-	$(NULL)
deleted file mode 100644
--- a/security/dbm/src/Makefile
+++ /dev/null
@@ -1,76 +0,0 @@
-#! gmake
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-#######################################################################
-# (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)       #
-#######################################################################
-
-include $(CORE_DEPTH)/dbm/config/config.mk
-
-#######################################################################
-# (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).                              #
-#######################################################################
-
-
-
deleted file mode 100644
--- a/security/dbm/src/config.mk
+++ /dev/null
@@ -1,63 +0,0 @@
-#! gmake
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-DEFINES += -DMEMMOVE -D__DBINTERFACE_PRIVATE $(SECURITY_FLAG)
-
-INCLUDES += -I$(CORE_DEPTH)/../dbm/include
-
-#
-#  Currently, override TARGETS variable so that only static libraries
-#  are specifed as dependencies within rules.mk.
-#
-
-TARGETS        = $(LIBRARY)
-SHARED_LIBRARY =
-IMPORT_LIBRARY =
-PURE_LIBRARY   =
-PROGRAM        =
-
-ifdef SHARED_LIBRARY
-	ifeq (,$(filter-out WINNT WIN95 WINCE,$(OS_TARGET))) # list omits WIN16
-		DLLBASE=/BASE:0x30000000
-		RES=$(OBJDIR)/dbm.res
-		RESNAME=../include/dbm.rc
-	endif
-	ifeq ($(DLL_SUFFIX),dll)
-		DEFINES += -D_DLL
-	endif
-endif
-
-ifeq ($(OS_TARGET),AIX)
-	OS_LIBS += -lc_r
-endif
deleted file mode 100644
--- a/security/dbm/src/dirent.c
+++ /dev/null
@@ -1,348 +0,0 @@
-#ifdef OS2
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <dirent.h>
-#include <errno.h>
-
-/*#ifndef __EMX__ 
-#include <libx.h>
-#endif */
-
-#define INCL_DOSFILEMGR
-#define INCL_DOSERRORS
-#include <os2.h>
-
-#if OS2 >= 2
-# define FFBUF	FILEFINDBUF3
-# define Word	ULONG
-  /*
-   * LS20 recommends a request count of 100, but according to the
-   * APAR text it does not lead to missing files, just to funny
-   * numbers of returned entries.
-   *
-   * LS30 HPFS386 requires a count greater than 2, or some files
-   * are missing (those starting with a character less that '.').
-   *
-   * Novell looses entries which overflow the buffer. In previous
-   * versions of dirent2, this could have lead to missing files
-   * when the average length of 100 directory entries was 40 bytes
-   * or more (quite unlikely for files on a Novell server).
-   *
-   * Conclusion: Make sure that the entries all fit into the buffer
-   * and that the buffer is large enough for more than 2 entries
-   * (each entry is at most 300 bytes long). And ignore the LS20
-   * effect.
-   */
-# define Count	25
-# define BufSz	(25 * (sizeof(FILEFINDBUF3)+1))
-#else
-# define FFBUF	FILEFINDBUF
-# define Word	USHORT
-# define BufSz	1024
-# define Count	3
-#endif
-
-#if defined(__IBMC__) || defined(__IBMCPP__)
-  #define error(rc) _doserrno = rc, errno = EOS2ERR
-#elif defined(MICROSOFT)
-  #define error(rc) _doserrno = rc, errno = 255
-#else
-  #define error(rc) errno = 255
-#endif
-
-struct _dirdescr {
-	HDIR		handle;		/* DosFindFirst handle */
-	char		fstype;		/* filesystem type */
-	Word		count;		/* valid entries in <ffbuf> */
-	long		number;		/* absolute number of next entry */
-	int		index;		/* relative number of next entry */
-	FFBUF *		next;		/* pointer to next entry */
-	char		name[MAXPATHLEN+3]; /* directory name */
-	unsigned	attrmask;	/* attribute mask for seekdir */
-	struct dirent	entry;		/* buffer for directory entry */
-	BYTE		ffbuf[BufSz];
-};
-
-/*
- * Return first char of filesystem type, or 0 if unknown.
- */
-static char
-getFSType(const char *path)
-{
-	static char cache[1+26];
-	char drive[3], info[512];
-	Word unit, infolen;
-	char r;
-
-	if (isalpha(path[0]) && path[1] == ':') {
-		unit = toupper(path[0]) - '@';
-		path += 2;
-	} else {
-		ULONG driveMap;
-#if OS2 >= 2
-		if (DosQueryCurrentDisk(&unit, &driveMap))
-#else
-		if (DosQCurDisk(&unit, &driveMap))
-#endif
-			return 0;
-	}
-
-	if ((path[0] == '\\' || path[0] == '/')
-	 && (path[1] == '\\' || path[1] == '/'))
-		return 0;
-
-	if (cache [unit])
-		return cache [unit];
-
-	drive[0] = '@' + unit;
-	drive[1] = ':';
-	drive[2] = '\0';
-	infolen = sizeof info;
-#if OS2 >= 2
-	if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen))
-		return 0;
-	if (infolen >= sizeof(FSQBUFFER2)) {
-		FSQBUFFER2 *p = (FSQBUFFER2 *)info;
-		r = p->szFSDName[p->cbName];
-	} else
-#else
-	if (DosQFSAttach((PSZ)drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen, 0))
-		return 0;
-	if (infolen >= 9) {
-		char *p = info + sizeof(USHORT);
-		p += sizeof(USHORT) + *(USHORT *)p + 1 + sizeof(USHORT);
-		r = *p;
-	} else
-#endif
-		r = 0;
-	return cache [unit] = r;
-}
-
-char *
-abs_path(const char *name, char *buffer, int len)
-{
-	char buf[4];
-	if (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') {
-		buf[0] = name[0];
-		buf[1] = name[1];
-		buf[2] = '.';
-		buf[3] = '\0';
-		name = buf;
-	}
-#if OS2 >= 2
-	if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len))
-#else
-	if (DosQPathInfo((PSZ)name, FIL_QUERYFULLNAME, (PBYTE)buffer, len, 0L))
-#endif
-		return NULL;
-	return buffer;
-}
-
-DIR *
-openxdir(const char *path, unsigned att_mask)
-{
-	DIR *dir;
-	char name[MAXPATHLEN+3];
-	Word rc;
-
-	dir = malloc(sizeof(DIR));
-	if (dir == NULL) {
-		errno = ENOMEM;
-		return NULL;
-	}
-
-	strncpy(name, path, MAXPATHLEN);
-	name[MAXPATHLEN] = '\0';
-	switch (name[strlen(name)-1]) {
-	default:
-		strcat(name, "\\");
-	case '\\':
-	case '/':
-	case ':':
-		;
-	}
-	strcat(name, ".");
-	if (!abs_path(name, dir->name, MAXPATHLEN+1))
-		strcpy(dir->name, name);
-	if (dir->name[strlen(dir->name)-1] == '\\')
-		strcat(dir->name, "*");
-	else
-		strcat(dir->name, "\\*");
-
-	dir->fstype = getFSType(dir->name);
-	dir->attrmask = att_mask | A_DIR;
-
-	dir->handle = HDIR_CREATE;
-	dir->count = 100;
-#if OS2 >= 2
-	rc = DosFindFirst(dir->name, &dir->handle, dir->attrmask,
-		dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
-#else
-	rc = DosFindFirst((PSZ)dir->name, &dir->handle, dir->attrmask,
-		(PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
-#endif
-	switch (rc) {
-	default:
-		free(dir);
-		error(rc);
-		return NULL;
-	case NO_ERROR:
-	case ERROR_NO_MORE_FILES:
-		;
-	}
-
-	dir->number = 0;
-	dir->index = 0;
-	dir->next = (FFBUF *)dir->ffbuf;
-
-	return (DIR *)dir;
-}
-
-DIR *
-opendir(const char *pathname)
-{
-	return openxdir(pathname, 0);
-}
-
-struct dirent *
-readdir(DIR *dir)
-{
-	static int dummy_ino = 2;
-
-	if (dir->index == dir->count) {
-		Word rc;
-		dir->count = 100;
-#if OS2 >= 2
-		rc = DosFindNext(dir->handle, dir->ffbuf,
-			sizeof dir->ffbuf, &dir->count);
-#else
-		rc = DosFindNext(dir->handle, (PFILEFINDBUF)dir->ffbuf,
-			sizeof dir->ffbuf, &dir->count);
-#endif
-		if (rc) {
-			error(rc);
-			return NULL;
-		}
-
-		dir->index = 0;
-		dir->next = (FFBUF *)dir->ffbuf;
-	}
-
-	if (dir->index == dir->count)
-		return NULL;
-
-	memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName);
-	dir->entry.d_name[dir->next->cchName] = '\0';
-	dir->entry.d_ino = dummy_ino++;
-	dir->entry.d_reclen = dir->next->cchName;
-	dir->entry.d_namlen = dir->next->cchName;
-	dir->entry.d_size = dir->next->cbFile;
-	dir->entry.d_attribute = dir->next->attrFile;
-	dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite;
-	dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite;
-
-	switch (dir->fstype) {
-	case 'F': /* FAT */
-	case 'C': /* CDFS */
-		if (dir->next->attrFile & FILE_DIRECTORY)
-			strupr(dir->entry.d_name);
-		else
-			strlwr(dir->entry.d_name);
-	}
-
-#if OS2 >= 2
-	dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset);
-#else
-	dir->next = (FFBUF *)((BYTE *)dir->next->achName + dir->next->cchName + 1);
-#endif
-	++dir->number;
-	++dir->index;
-
-	return &dir->entry;
-}
-
-long
-telldir(DIR *dir)
-{
-	return dir->number;
-}
-
-void
-seekdir(DIR *dir, long off)
-{
-	if (dir->number > off) {
-		char name[MAXPATHLEN+2];
-		Word rc;
-
-		DosFindClose(dir->handle);
-
-		strcpy(name, dir->name);
-		strcat(name, "*");
-
-		dir->handle = HDIR_CREATE;
-		dir->count = 32767;
-#if OS2 >= 2
-		rc = DosFindFirst(name, &dir->handle, dir->attrmask,
-			dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
-#else
-		rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask,
-			(PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
-#endif
-		switch (rc) {
-		default:
-			error(rc);
-			return;
-		case NO_ERROR:
-		case ERROR_NO_MORE_FILES:
-			;
-		}
-
-		dir->number = 0;
-		dir->index = 0;
-		dir->next = (FFBUF *)dir->ffbuf;
-	}
-
-	while (dir->number < off && readdir(dir))
-		;
-}
-
-void
-closedir(DIR *dir)
-{
-	DosFindClose(dir->handle);
-	free(dir);
-}
-
-/*****************************************************************************/
-
-#ifdef TEST
-
-main(int argc, char **argv)
-{
-	int i;
-	DIR *dir;
-	struct dirent *ep;
-
-	for (i = 1; i < argc; ++i) {
-		dir = opendir(argv[i]);
-		if (!dir)
-			continue;
-		while (ep = readdir(dir))
-			if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1]))
-				printf("%s%s\n", argv[i], ep->d_name);
-			else
-				printf("%s/%s\n", argv[i], ep->d_name);
-		closedir(dir);
-	}
-
-	return 0;
-}
-
-#endif
-
-#endif /* OS2 */
-
deleted file mode 100644
--- a/security/dbm/src/dirent.h
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef __DIRENT_H__
-#define __DIRENT_H__
-/*
- * @(#)msd_dir.h 1.4 87/11/06   Public Domain.
- *
- *  A public domain implementation of BSD directory routines for
- *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
- *  August 1897
- *
- *  Extended by Peter Lim (lim@mullian.oz) to overcome some MS DOS quirks
- *  and returns 2 more pieces of information - file size & attribute.
- *  Plus a little reshuffling of some #define's positions    December 1987
- *
- *  Some modifications by Martin Junius                      02-14-89
- *
- *	AK900712
- *	AK910410	abs_path - make absolute path
- *
- */
-
-#ifdef __EMX__
-#include <sys/param.h>
-#else
-#if defined(__IBMC__) || defined(__IBMCPP__) || defined(XP_W32_MSVC)
-#include <stdio.h>
-#ifdef MAXPATHLEN
-	#undef MAXPATHLEN
-#endif
-#define MAXPATHLEN (FILENAME_MAX*4)
-#define MAXNAMLEN FILENAME_MAX
-
-#else
-#include <param.h>
-#endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* attribute stuff */
-#ifndef A_RONLY
-# define A_RONLY   0x01
-# define A_HIDDEN  0x02
-# define A_SYSTEM  0x04
-# define A_LABEL   0x08
-# define A_DIR     0x10
-# define A_ARCHIVE 0x20
-#endif
-
-struct dirent {
-#if defined(OS2) || defined(WIN32)        /* use the layout of EMX to avoid trouble */
-    int            d_ino;                 /* Dummy */
-    int            d_reclen;		  /* Dummy, same as d_namlen */
-    int            d_namlen;              /* length of name */
-    char           d_name[MAXNAMLEN + 1];
-    unsigned long  d_size;
-    unsigned short d_attribute;           /* attributes (see above) */
-    unsigned short d_time;                /* modification time */
-    unsigned short d_date;                /* modification date */
-#else
-    char	   d_name[MAXNAMLEN + 1]; /* garentee null termination */
-    char	   d_attribute;		  /* .. extension .. */
-    unsigned long  d_size;		  /* .. extension .. */
-#endif
-};
-
-typedef struct _dirdescr DIR;
-/* the structs do not have to be defined here */
-
-extern DIR		*opendir(const char *);
-extern DIR		*openxdir(const char *, unsigned);
-extern struct dirent	*readdir(DIR *);
-extern void		seekdir(DIR *, long);
-extern long		telldir(DIR *);
-extern void 		closedir(DIR *);
-#define			rewinddir(dirp) seekdir(dirp, 0L)
-
-extern char *		abs_path(const char *name, char *buffer, int len);
-
-#ifndef S_IFMT
-#define S_IFMT ( S_IFDIR | S_IFREG )
-#endif
-
-#ifndef S_ISDIR
-#define S_ISDIR( m )                    (((m) & S_IFMT) == S_IFDIR)
-#endif
-
-#ifndef S_ISREG
-#define S_ISREG( m )                    (((m) & S_IFMT) == S_IFREG)
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
deleted file mode 100644
--- a/security/dbm/src/manifest.mn
+++ /dev/null
@@ -1,61 +0,0 @@
-#! gmake
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-CORE_DEPTH = ../..
-
-VPATH  = $(CORE_DEPTH)/../dbm/src
-
-MODULE = dbm
-
-#
-# memmove.c, snprintf.c, and strerror.c are not in CSRCS because
-# the Standard C Library has memmove and strerror and DBM is not
-# using snprintf.
-#
-
-CSRCS = db.c	   \
-	h_bigkey.c \
-	h_func.c   \
-	h_log2.c   \
-	h_page.c   \
-	hash.c	   \
-	hash_buf.c \
-	hsearch.c  \
-	mktemp.c   \
-	ndbm.c	   \
-	nsres.c	   \
-	dirent.c	   \
-	$(NULL)
-
-LIBRARY_NAME = dbm
deleted file mode 100644
--- a/security/dbm/tests/Makefile
+++ /dev/null
@@ -1,69 +0,0 @@
-#! gmake
-#
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-DEPTH		= ../..
-CORE_DEPTH	= ../..
-
-VPATH		= $(CORE_DEPTH)/../dbm/tests
-
-MODULE		= dbm
-
-CSRCS		= lots.c
-
-PROGRAM		= lots
-
-include $(DEPTH)/coreconf/config.mk
-
-include $(DEPTH)/dbm/config/config.mk
-
-ifeq (,$(filter-out WIN%,$(OS_TARGET))) 
-LIBDBM		= ../src/$(PLATFORM)/dbm$(STATIC_LIB_SUFFIX)
-else
-LIBDBM		= ../src/$(PLATFORM)/libdbm$(STATIC_LIB_SUFFIX)
-endif
-
-INCLUDES	+= -I$(CORE_DEPTH)/../dbm/include
-
-LDFLAGS		= $(LDOPTS) $(LIBDBM)
-
-include $(DEPTH)/coreconf/rules.mk
-
-lots.pure: lots
-	purify $(CC) -o lots.pure $(CFLAGS) $(OBJS) $(MYLIBS)
-
-crash: crash.o $(MYLIBS)
-	$(CC) -o crash $(CFLAGS) $^
-
-crash.pure: crash.o $(MYLIBS)
-	purify $(CC) -o crash.pure $(CFLAGS) $^
-
--- a/security/nss/cmd/bltest/blapitest.c
+++ b/security/nss/cmd/bltest/blapitest.c
@@ -1251,133 +1251,16 @@ sha1_restart(unsigned char *dest, const 
     }
     SHA1_End(cx, dest, &len, MD5_LENGTH);
 finish:
     SHA1_DestroyContext(cx, PR_TRUE);
     return rv;
 }
 
 SECStatus
-SHA256_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
-{
-    SECStatus rv = SECSuccess;
-    SHA256Context *cx, *cx_cpy;
-    unsigned char *cxbytes;
-    unsigned int len;
-    unsigned int i, quarter;
-    cx = SHA256_NewContext();
-    SHA256_Begin(cx);
-    /* divide message by 4, restarting 3 times */
-    quarter = (src_length + 3)/ 4;
-    for (i=0; i < 4 && src_length > 0; i++) {
-	SHA256_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
-	len = SHA256_FlattenSize(cx);
-	cxbytes = PORT_Alloc(len);
-	SHA256_Flatten(cx, cxbytes);
-	cx_cpy = SHA256_Resurrect(cxbytes, NULL);
-	if (!cx_cpy) {
-	    PR_fprintf(PR_STDERR, "%s: SHA256_Resurrect failed!\n", progName);
-	    rv = SECFailure;
-	    goto finish;
-	}
-	rv = PORT_Memcmp(cx, cx_cpy, len);
-	if (rv) {
-	    SHA256_DestroyContext(cx_cpy, PR_TRUE);
-	    PR_fprintf(PR_STDERR, "%s: SHA256_restart failed!\n", progName);
-	    goto finish;
-	}
-	SHA256_DestroyContext(cx_cpy, PR_TRUE);
-	PORT_Free(cxbytes);
-	src_length -= quarter;
-    }
-    SHA256_End(cx, dest, &len, MD5_LENGTH);
-finish:
-    SHA256_DestroyContext(cx, PR_TRUE);
-    return rv;
-}
-
-SECStatus
-SHA384_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
-{
-    SECStatus rv = SECSuccess;
-    SHA384Context *cx, *cx_cpy;
-    unsigned char *cxbytes;
-    unsigned int len;
-    unsigned int i, quarter;
-    cx = SHA384_NewContext();
-    SHA384_Begin(cx);
-    /* divide message by 4, restarting 3 times */
-    quarter = (src_length + 3)/ 4;
-    for (i=0; i < 4 && src_length > 0; i++) {
-	SHA384_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
-	len = SHA384_FlattenSize(cx);
-	cxbytes = PORT_Alloc(len);
-	SHA384_Flatten(cx, cxbytes);
-	cx_cpy = SHA384_Resurrect(cxbytes, NULL);
-	if (!cx_cpy) {
-	    PR_fprintf(PR_STDERR, "%s: SHA384_Resurrect failed!\n", progName);
-	    rv = SECFailure;
-	    goto finish;
-	}
-	rv = PORT_Memcmp(cx, cx_cpy, len);
-	if (rv) {
-	    SHA384_DestroyContext(cx_cpy, PR_TRUE);
-	    PR_fprintf(PR_STDERR, "%s: SHA384_restart failed!\n", progName);
-	    goto finish;
-	}
-	SHA384_DestroyContext(cx_cpy, PR_TRUE);
-	PORT_Free(cxbytes);
-	src_length -= quarter;
-    }
-    SHA384_End(cx, dest, &len, MD5_LENGTH);
-finish:
-    SHA384_DestroyContext(cx, PR_TRUE);
-    return rv;
-}
-
-SECStatus
-SHA512_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
-{
-    SECStatus rv = SECSuccess;
-    SHA512Context *cx, *cx_cpy;
-    unsigned char *cxbytes;
-    unsigned int len;
-    unsigned int i, quarter;
-    cx = SHA512_NewContext();
-    SHA512_Begin(cx);
-    /* divide message by 4, restarting 3 times */
-    quarter = (src_length + 3)/ 4;
-    for (i=0; i < 4 && src_length > 0; i++) {
-	SHA512_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
-	len = SHA512_FlattenSize(cx);
-	cxbytes = PORT_Alloc(len);
-	SHA512_Flatten(cx, cxbytes);
-	cx_cpy = SHA512_Resurrect(cxbytes, NULL);
-	if (!cx_cpy) {
-	    PR_fprintf(PR_STDERR, "%s: SHA512_Resurrect failed!\n", progName);
-	    rv = SECFailure;
-	    goto finish;
-	}
-	rv = PORT_Memcmp(cx, cx_cpy, len);
-	if (rv) {
-	    SHA512_DestroyContext(cx_cpy, PR_TRUE);
-	    PR_fprintf(PR_STDERR, "%s: SHA512_restart failed!\n", progName);
-	    goto finish;
-	}
-	SHA512_DestroyContext(cx_cpy, PR_TRUE);
-	PORT_Free(cxbytes);
-	src_length -= quarter;
-    }
-    SHA512_End(cx, dest, &len, MD5_LENGTH);
-finish:
-    SHA512_DestroyContext(cx, PR_TRUE);
-    return rv;
-}
-
-SECStatus
 pubkeyInitKey(bltestCipherInfo *cipherInfo, PRFileDesc *file,
 	      int keysize, int exponent)
 {
     int i;
     SECStatus rv = SECSuccess;
     bltestRSAParams *rsap;
     bltestDSAParams *dsap;
     switch (cipherInfo->mode) {
@@ -1483,39 +1366,18 @@ cipherInit(bltestCipherInfo *cipherInfo,
     case bltestSHA1:
 	restart = cipherInfo->params.hash.restart;
 	SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
 			  SHA1_LENGTH);
 	cipherInfo->cipher.hashCipher = (restart) ? sha1_restart : SHA1_HashBuf;
 	return SECSuccess;
 	break;
     case bltestSHA256:
-	restart = cipherInfo->params.hash.restart;
-	SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
-			  SHA256_LENGTH);
-	cipherInfo->cipher.hashCipher = (restart) ? SHA256_restart 
-	                                          : SHA256_HashBuf;
-	return SECSuccess;
-	break;
     case bltestSHA384:
-	restart = cipherInfo->params.hash.restart;
-	SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
-			  SHA384_LENGTH);
-	cipherInfo->cipher.hashCipher = (restart) ? SHA384_restart 
-	                                          : SHA384_HashBuf;
-	return SECSuccess;
-	break;
     case bltestSHA512:
-	restart = cipherInfo->params.hash.restart;
-	SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
-			  SHA512_LENGTH);
-	cipherInfo->cipher.hashCipher = (restart) ? SHA512_restart 
-	                                          : SHA512_HashBuf;
-	return SECSuccess;
-	break;
     default:
 	return SECFailure;
     }
     return SECSuccess;
 }
 
 SECStatus
 dsaOp(bltestCipherInfo *cipherInfo)
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha256/ciphertext0
+++ /dev/null
@@ -1,1 +0,0 @@
-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha256/ciphertext1
+++ /dev/null
@@ -1,1 +0,0 @@
-JI1qYdIGOLjlwCaTDD5gOaM85Flk/yFn9uzt1BnbBsE=
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha256/numtests
+++ /dev/null
@@ -1,1 +0,0 @@
-2
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha256/plaintext0
+++ /dev/null
@@ -1,1 +0,0 @@
-abc
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha256/plaintext1
+++ /dev/null
@@ -1,1 +0,0 @@
-abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha384/ciphertext0
+++ /dev/null
@@ -1,1 +0,0 @@
-ywB1P0WjXou1oD1pmsZQBycsMqsO3tFjGotgWkP/W+2AhgcroefMI1i67KE0yCWn
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha384/ciphertext1
+++ /dev/null
@@ -1,1 +0,0 @@
-CTMMM/cRR+g9GS/Hgs0bR1MRGxc7OwXSL6CAhuOw9xL8x8caVX4tuWbD6fqRdGA5
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha384/numtests
+++ /dev/null
@@ -1,1 +0,0 @@
-2
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha384/plaintext0
+++ /dev/null
@@ -1,1 +0,0 @@
-abc
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha384/plaintext1
+++ /dev/null
@@ -1,1 +0,0 @@
-abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha512/ciphertext0
+++ /dev/null
@@ -1,2 +0,0 @@
-3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9
-RU1EI2Q86A4qmslPpUyknw==
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha512/ciphertext1
+++ /dev/null
@@ -1,2 +0,0 @@
-jpWbddrjE9qM9PcoFPwUP493ecbrn3+hcpmurbaIkBhQHSieSQD35DMbmd7EtUM6
-x9Mp7rbdJlReluVbh0vpCQ==
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha512/numtests
+++ /dev/null
@@ -1,1 +0,0 @@
-2
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha512/plaintext0
+++ /dev/null
@@ -1,1 +0,0 @@
-abc
deleted file mode 100644
--- a/security/nss/cmd/bltest/tests/sha512/plaintext1
+++ /dev/null
@@ -1,1 +0,0 @@
-abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -238,19 +238,18 @@ GetCertRequest(PRFileDesc *inFile, PRBoo
 	if (rv)
 	    break;
 	
         rv = SEC_ASN1DecodeItem(arena, certReq, 
 		SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data);
    } while (0);
 
    if (!rv) {
-   	rv = CERT_VerifySignedDataWithPubKeyInfo(&signedData, 
-					         &certReq->subjectPublicKeyInfo,
-					         NULL /* wincx */);
+   	rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData, 
+		&certReq->subjectPublicKeyInfo, NULL /* wincx */);
    }
 
    if (rv) {
        PRErrorCode  perr = PR_GetError();
        fprintf(stderr, "%s: unable to decode DER cert request (%s)\n", progName,
                SECU_Strerror(perr));
    }
    return (certReq);
--- a/security/nss/cmd/smimetools/cmsutil.c
+++ b/security/nss/cmd/smimetools/cmsutil.c
@@ -110,17 +110,16 @@ Usage(char *progName)
     fprintf(stderr, "  -n           suppress output of content\n");
     fprintf(stderr, "  -h num       generate email headers with info about CMS message\n");
     fprintf(stderr, " -S            create a CMS signed message\n");
     fprintf(stderr, "  -N nick      use certificate named \"nick\" for signing\n");
     fprintf(stderr, "  -T           do not include content in CMS message\n");
     fprintf(stderr, "  -G           include a signing time attribute\n");
     fprintf(stderr, "  -P           include a SMIMECapabilities attribute\n");
     fprintf(stderr, "  -Y nick      include a EncryptionKeyPreference attribute with cert\n");
-    fprintf(stderr, "                 (use \"NONE\" to omit)\n");
     fprintf(stderr, " -E            create a CMS enveloped message (NYI)\n");
     fprintf(stderr, "  -r id,...    create envelope for these recipients,\n");
     fprintf(stderr, "               where id can be a certificate nickname or email address\n");
     fprintf(stderr, " -v            print debugging information\n");
     fprintf(stderr, "\nCert usage codes:\n");
     fprintf(stderr, "%-25s  0 - certUsageSSLClient\n", " ");
     fprintf(stderr, "%-25s  1 - certUsageSSLServer\n", " ");
     fprintf(stderr, "%-25s  2 - certUsageSSLServerWithStepUp\n", " ");
@@ -412,17 +411,17 @@ signed_data(struct signOptionsStr *signO
     }
     if (signOptions->nickname == NULL) {
 	fprintf(stderr, 
         "ERROR: please indicate the nickname of a certificate to sign with.\n");
 	return NULL;
     }
     if ((cert = CERT_FindUserCertByUsage(signOptions->options->certHandle, 
                                          signOptions->nickname,
-                                         signOptions->options->certUsage,
+                                         certUsageEmailSigner,
                                          PR_FALSE,
                                          NULL)) == NULL) {
 	SECU_PrintError(progName, 
 	                "the corresponding cert for key \"%s\" does not exist",
 	                signOptions->nickname);
 	return NULL;
     }
     if (cms_verbose) {
@@ -488,17 +487,45 @@ signed_data(struct signOptionsStr *signO
     }
     if (signOptions->smimeProfile) {
 	if (NSS_CMSSignerInfo_AddSMIMECaps(signerinfo) != SECSuccess) {
 	    fprintf(stderr, "ERROR: cannot add SMIMECaps attribute.\n");
 	    goto loser;
 	}
     }
 
-    if (!signOptions->encryptionKeyPreferenceNick) {
+    if (signOptions->encryptionKeyPreferenceNick) {
+	/* get the cert, add it to the message */
+	if ((ekpcert = CERT_FindUserCertByUsage(
+                                     signOptions->options->certHandle, 
+	                             signOptions->encryptionKeyPreferenceNick,
+                                     certUsageEmailRecipient, PR_FALSE, NULL))
+	      == NULL) {
+	    SECU_PrintError(progName, 
+	               "the corresponding cert for key \"%s\" does not exist",
+	                signOptions->encryptionKeyPreferenceNick);
+	    goto loser;
+	}
+	if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ekpcert, 
+	                                     signOptions->options->certHandle)
+	      != SECSuccess) {
+	    fprintf(stderr, "ERROR: cannot add SMIMEEncKeyPrefs attribute.\n");
+	    goto loser;
+	}
+	if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, ekpcert, 
+	                                     signOptions->options->certHandle)
+	      != SECSuccess) {
+	    fprintf(stderr, "ERROR: cannot add MS SMIMEEncKeyPrefs attribute.\n");
+	    goto loser;
+	}
+	if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
+	    fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
+	    goto loser;
+	}
+    } else {
 	/* check signing cert for fitness as encryption cert */
         SECStatus FitForEncrypt = CERT_CheckCertUsage(cert,
                                                       certUsageEmailRecipient);
 
         if (SECSuccess == FitForEncrypt) {
             /* if yes, add signing cert as EncryptionKeyPreference */
             if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, cert, 
                                               signOptions->options->certHandle)
@@ -543,46 +570,16 @@ signed_data(struct signOptionsStr *signO
                         "ERROR: cannot add MS SMIMEEncKeyPrefs attribute.\n");
                 goto loser;
             }
             if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
                 fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
                 goto loser;
             }
         }
-    } else if (PL_strcmp(signOptions->encryptionKeyPreferenceNick, "NONE") == 0) {
-        /* No action */
-    } else {
-	/* get the cert, add it to the message */
-	if ((ekpcert = CERT_FindUserCertByUsage(
-                                     signOptions->options->certHandle, 
-	                             signOptions->encryptionKeyPreferenceNick,
-                                     certUsageEmailRecipient, PR_FALSE, NULL))
-	      == NULL) {
-	    SECU_PrintError(progName, 
-	               "the corresponding cert for key \"%s\" does not exist",
-	                signOptions->encryptionKeyPreferenceNick);
-	    goto loser;
-	}
-	if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ekpcert, 
-	                                     signOptions->options->certHandle)
-	      != SECSuccess) {
-	    fprintf(stderr, "ERROR: cannot add SMIMEEncKeyPrefs attribute.\n");
-	    goto loser;
-	}
-	if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, ekpcert, 
-	                                     signOptions->options->certHandle)
-	      != SECSuccess) {
-	    fprintf(stderr, "ERROR: cannot add MS SMIMEEncKeyPrefs attribute.\n");
-	    goto loser;
-	}
-	if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
-	    fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
-	    goto loser;
-	}
     }
 
     if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess) {
 	fprintf(stderr, "ERROR: cannot add CMS signerInfo object.\n");
 	goto loser;
     }
     if (cms_verbose) {
 	fprintf(stderr, "created signed-date message\n");
@@ -957,16 +954,27 @@ loser:
 	NSS_CMSMessage_Destroy(cmsg);
     if (tmppoolp)
 	PORT_FreeArena(tmppoolp, PR_FALSE);
     return NULL;
 }
 
 typedef enum { UNKNOWN, DECODE, SIGN, ENCRYPT, ENVELOPE, CERTSONLY } Mode;
 
+#if 0
+void
+parse_message_for_recipients(PRFileDesc *inFile, 
+                             struct envelopeOptionsStr *envelopeOptions)
+{
+    SECItem filedata;
+    SECStatus rv;
+    rv = SECU_FileToItem(&filedata, inFile);
+}
+#endif
+
 int
 main(int argc, char **argv)
 {
     FILE *outFile;
     NSSCMSMessage *cmsg = NULL;
     PRFileDesc *inFile;
     PLOptState *optstate;
     PLOptStatus status;
@@ -1014,17 +1022,17 @@ main(int argc, char **argv)
     encryptOptions.bulkalgtag = SEC_OID_UNKNOWN;
     encryptOptions.bulkkey = NULL;
     encryptOptions.keysize = -1;
 
     /*
      * Parse command line arguments
      */
     optstate = PL_CreateOptState(argc, argv, 
-                                 "CDSEOnN:TGPY:vh:p:i:c:d:e:o:s:u:r:");
+                                 "CDSEOnN:TGPYv:h:p:i:c:d:e:o:s:u:r:");
     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
 	switch (optstate->option) {
 	case '?':
 	    Usage(progName);
 	    break;
 	
 	case 'C':
 	    mode = ENCRYPT;
@@ -1157,30 +1165,40 @@ main(int argc, char **argv)
 	          PR_Open(optstate->value, PR_RDONLY, 006600)) == NULL) {
 		fprintf(stderr, "%s: unable to open \"%s\" for reading.\n",
 			progName, optstate->value);
 		exit(1);
 	    }
 	    break;
 
 	case 'o':
+#if 0
+	    if (mode == DECODE) {
+		outFile = fopen(optstate->value, "w");
+	    } else {
+		outFile = fopen(optstate->value, "wb");
+	    }
+#endif
 	    outFile = fopen(optstate->value, "wb");
 	    if (outFile == NULL) {
 		fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
 			progName, optstate->value);
 		exit(1);
 	    }
 	    break;
 
 	case 'r':
 	    if (!optstate->value) {
 		fprintf(stderr, "%s: option -r must have a value.\n", progName);
 		Usage(progName);
 		exit(1);
 	    }
+#if 0
+	    fprintf(stderr, "recipient = %s\n", optstate->value);
+#endif
 	    envelopeOptions.recipients = ptrarray;
 	    str = (char *)optstate->value;
 	    do {
 		tok = strchr(str, ',');
 		if (tok) *tok = '\0';
 		envelopeOptions.recipients[nrecipients++] = strdup(str);
 		if (tok) str = tok + 1;
 	    } while (tok);
@@ -1237,16 +1255,17 @@ main(int argc, char **argv)
 	SECU_PrintError(progName, "No default cert DB");
 	exit(1);
     }
     if (cms_verbose) {
 	fprintf(stderr, "Got default certdb\n");
     }
 
 #if defined(_WIN32)
+    /*if (outFile == stdout && mode != DECODE) {*/
     if (outFile == stdout) {
 	/* If we're going to write binary data to stdout, we must put stdout
 	** into O_BINARY mode or else outgoing \n's will become \r\n's.
 	*/
 	int smrv = _setmode(_fileno(stdout), _O_BINARY);
 	if (smrv == -1) {
 	    fprintf(stderr,
 	    "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
@@ -1332,16 +1351,20 @@ main(int argc, char **argv)
 	}
 	if (encryptOptions.bulkkey) {
 	    PK11_FreeSymKey(encryptOptions.bulkkey);
 	    encryptOptions.bulkkey = NULL;
 	}
 	break;
     case ENVELOPE:
 	envelopeOptions.options = &options;
+#if 0
+	if (!envelopeOptions.recipients)
+	    parse_message_for_recipients(myIn, &envelopeOptions);
+#endif
 	cmsg = enveloped_data(&envelopeOptions);
 	if (!cmsg) {
 	    SECU_PrintError(progName, "problem enveloping");
 	    exitstatus = 1;
 	}
 	break;
     case CERTSONLY:
 	certsonlyOptions.options = &options;
--- a/security/nss/cmd/strsclnt/strsclnt.c
+++ b/security/nss/cmd/strsclnt/strsclnt.c
@@ -1139,13 +1139,14 @@ main(int argc, char **argv)
 	exitVal = (ssl3stats->hsh_sid_cache_misses > 1) ||
                 (ssl3stats->hsh_sid_cache_not_ok != 0) ||
                 (certsTested > 1);
     else
 	exitVal = (ssl3stats->hsh_sid_cache_misses != connections) ||
                 (certsTested != connections);
 
     exitVal = ( exitVal || failed_already );
+    SSL_ClearSessionCache();
     NSS_Shutdown();
     PR_Cleanup();
     return exitVal;
 }
 
deleted file mode 100644
--- a/security/nss/cmd/vfychain/Makefile
+++ /dev/null
@@ -1,82 +0,0 @@
-#! gmake
-# 
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-#######################################################################
-# (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 ../platlibs.mk
-
-ifeq (,$(filter-out WINNT WIN95 WIN16,$(OS_TARGET)))  # omits WINCE
-ifndef BUILD_OPT
-LDFLAGS   +=  /subsystem:console /profile /debug /machine:I386 /incremental:no
-OS_CFLAGS += -D_CONSOLE
-endif
-endif
-
-
-#######################################################################
-# (5) Execute "global" rules. (OPTIONAL)                              #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/rules.mk
-
-#######################################################################
-# (6) Execute "component" rules. (OPTIONAL)                           #
-#######################################################################
-
-#include ../platlibs.mk
-
-#######################################################################
-# (7) Execute "local" rules. (OPTIONAL).                              #
-#######################################################################
-
-include ../platrules.mk
-
deleted file mode 100644
--- a/security/nss/cmd/vfychain/manifest.mn
+++ /dev/null
@@ -1,51 +0,0 @@
-# 
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-# 
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-# 
-# The Original Code is the Netscape security libraries.
-# 
-# The Initial Developer of the Original Code is Netscape
-# Communications Corporation.  Portions created by Netscape are 
-# Copyright (C) 1994-2000 Netscape Communications Corporation.  All
-# Rights Reserved.
-# 
-# Contributor(s):
-# 
-# Alternatively, the contents of this file may be used under the
-# terms of the GNU General Public License Version 2 or later (the
-# "GPL"), in which case the provisions of the GPL are applicable 
-# instead of those above.  If you wish to allow use of your 
-# version of this file only under the terms of the GPL and not to
-# allow others to use your version of this file under the MPL,
-# indicate your decision by deleting the provisions above and
-# replace them with the notice and other provisions required by
-# the GPL.  If you do not delete the provisions above, a recipient
-# may use your version of this file under either the MPL or the
-# GPL.
-#
-
-CORE_DEPTH = ../../..
-
-# MODULE public and private header  directories are implicitly REQUIRED.
-MODULE = nss
-
-# This next line is used by .mk files
-# and gets translated into $LINCS in manifest.mnw
-# The MODULE is always implicitly required.
-# Listing it here in REQUIRES makes it appear twice in the cc command line.
-REQUIRES = seccmd 
-
-# DIRS = 
-
-CSRCS	= vfychain.c  
-DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
-
-PROGRAM	= vfychain
-
deleted file mode 100644
--- a/security/nss/cmd/vfychain/vfychain.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is the Netscape security libraries.
- * 
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation.  Portions created by Netscape are 
- * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
- * Rights Reserved.
- * 
- * Contributor(s):
- * 
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable 
- * instead of those above.  If you wish to allow use of your 
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL.  If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
-
-/****************************************************************************
- *  Read in a cert chain from one or more files, and verify the chain for
- *  some usage.
- *                                                                          *
- *  This code was modified from other code also kept in the NSS directory.
- ****************************************************************************/ 
-
-#include <stdio.h>
-#include <string.h>
-
-#if defined(XP_UNIX)
-#include <unistd.h>
-#endif
-
-#include "prerror.h"
-
-#include "nssrenam.h"
-#include "pk11func.h"
-#include "seccomon.h"
-#include "secutil.h"
-#include "secmod.h"
-#include "secitem.h"
-#include "cert.h"
-
-
-/* #include <stdlib.h> */
-/* #include <errno.h> */
-/* #include <fcntl.h> */
-/* #include <stdarg.h> */
-
-#include "nspr.h"
-#include "plgetopt.h"
-#include "prio.h"
-#include "nss.h"
-
-/* #include "vfyutil.h" */
-
-#define RD_BUF_SIZE (60 * 1024)
-
-int verbose;
-
-char *password = NULL;
-
-/* Function: char * myPasswd()
- * 
- * Purpose: This function is our custom password handler that is called by
- * SSL when retreiving private certs and keys from the database. Returns a
- * pointer to a string that with a password for the database. Password pointer
- * should point to dynamically allocated memory that will be freed later.
- */
-char *
-myPasswd(PK11SlotInfo *info, PRBool retry, void *arg)
-{
-    char * passwd = NULL;
-
-    if ( (!retry) && arg ) {
-	passwd = PORT_Strdup((char *)arg);
-    }
-    return passwd;
-}
-
-static void
-Usage(const char *progName)
-{
-    fprintf(stderr, 
-	    "Usage: %s [-d dbdir] certfile [certfile ...]\n",
-            progName);
-    exit(1);
-}
-
-/**************************************************************************
-** 
-** Error and information routines.
-**
-**************************************************************************/
-
-void
-errWarn(char *function)
-{
-    PRErrorCode  errorNumber = PR_GetError();
-    const char * errorString = SECU_Strerror(errorNumber);
-
-    fprintf(stderr, "Error in function %s: %d\n - %s\n",
-		    function, errorNumber, errorString);
-}
-
-void
-exitErr(char *function)
-{
-    errWarn(function);
-    /* Exit gracefully. */
-    NSS_Shutdown();
-    PR_Cleanup();
-    exit(1);
-}
-
-static char *
-bestCertName(CERTCertificate *cert) {
-    if (cert->nickname) {
-	return cert->nickname;
-    }
-    if (cert->emailAddr) {
-	return cert->emailAddr;
-    }
-    return cert->subjectName;
-}
-
-void
-printCertProblems(FILE *outfile, CERTCertDBHandle *handle, 
-	CERTCertificate *cert, PRBool checksig, 
-	SECCertUsage certUsage, void *pinArg)
-{
-    CERTVerifyLog      log;
-    CERTVerifyLogNode *node   = NULL;
-    unsigned int       depth  = (unsigned int)-1;
-    unsigned int       flags  = 0;
-    char *             errstr = NULL;
-    PRErrorCode	       err    = PORT_GetError();
-
-    log.arena = PORT_NewArena(512);
-    log.head = log.tail = NULL;
-    log.count = 0;
-    CERT_VerifyCert(handle, cert, checksig, certUsage,
-	            PR_Now(), pinArg, &log);
-
-    if (log.count > 0) {
-	fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
-	for (node = log.head; node; node = node->next) {
-	    if (depth != node->depth) {
-		depth = node->depth;
-		fprintf(outfile,"CERT %d. %s %s:\n", depth,
-				 bestCertName(node->cert), 
-			  	 depth ? "[Certificate Authority]": "");
-	    	if (verbose) {
-		    const char * emailAddr;
-		    emailAddr = CERT_GetFirstEmailAddress(node->cert);
-		    if (emailAddr) {
-		    	fprintf(outfile,"Email Address(es): ");
-			do {
-			    fprintf(outfile, "%s\n", emailAddr);
-			    emailAddr = CERT_GetNextEmailAddress(node->cert,
-			                                         emailAddr);
-			} while (emailAddr);
-		    }
-		}
-	    }
-	    fprintf(outfile,"  ERROR %d: %s\n", node->error,
-						SECU_Strerror(node->error));
-	    errstr = NULL;
-	    switch (node->error) {
-	    case SEC_ERROR_INADEQUATE_KEY_USAGE:
-		flags = (unsigned int)node->arg;
-		switch (flags) {
-		case KU_DIGITAL_SIGNATURE:
-		    errstr = "Cert cannot sign.";
-		    break;
-		case KU_KEY_ENCIPHERMENT:
-		    errstr = "Cert cannot encrypt.";
-		    break;
-		case KU_KEY_CERT_SIGN:
-		    errstr = "Cert cannot sign other certs.";
-		    break;
-		default:
-		    errstr = "[unknown usage].";
-		    break;
-		}
-	    case SEC_ERROR_INADEQUATE_CERT_TYPE:
-		flags = (unsigned int)node->arg;
-		switch (flags) {
-		case NS_CERT_TYPE_SSL_CLIENT:
-		case NS_CERT_TYPE_SSL_SERVER:
-		    errstr = "Cert cannot be used for SSL.";
-		    break;
-		case NS_CERT_TYPE_SSL_CA:
-		    errstr = "Cert cannot be used as an SSL CA.";
-		    break;
-		case NS_CERT_TYPE_EMAIL:
-		    errstr = "Cert cannot be used for SMIME.";
-		    break;
-		case NS_CERT_TYPE_EMAIL_CA:
-		    errstr = "Cert cannot be used as an SMIME CA.";
-		    break;
-		case NS_CERT_TYPE_OBJECT_SIGNING:
-		    errstr = "Cert cannot be used for object signing.";
-		    break;
-		case NS_CERT_TYPE_OBJECT_SIGNING_CA:
-		    errstr = "Cert cannot be used as an object signing CA.";
-		    break;
-		default:
-		    errstr = "[unknown usage].";
-		    break;
-		}
-	    case SEC_ERROR_UNKNOWN_ISSUER:
-	    case SEC_ERROR_UNTRUSTED_ISSUER:
-	    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
-		errstr = node->cert->issuerName;
-		break;
-	    default:
-		break;
-	    }
-	    if (errstr) {
-		fprintf(stderr,"    %s\n",errstr);
-	    }
-	    CERT_DestroyCertificate(node->cert);
-	}    
-    }
-    PORT_SetError(err); /* restore original error code */
-}
-
-typedef struct certMemStr {
-    struct certMemStr * next;
-    CERTCertificate * cert;
-} certMem;
-
-certMem * theCerts;
-
-void
-rememberCert(CERTCertificate * cert)
-{
-    certMem * newCertMem = PORT_ZNew(certMem);
-    if (newCertMem) {
-	newCertMem->next = theCerts;
-	newCertMem->cert = cert;
-	theCerts = newCertMem;
-    }
-}
-
-void
-forgetCerts(void)
-{
-    certMem * oldCertMem;
-    while (oldCertMem = theCerts) {
-    	theCerts = oldCertMem->next;
-	CERT_DestroyCertificate(oldCertMem->cert);
-	PORT_Free(oldCertMem);
-    }
-    theCerts = NULL;
-}
-
-
-CERTCertificate *
-readCertFile(const char * fileName, PRBool isAscii)
-{
-    unsigned char * pb;
-    CERTCertificate * cert  = NULL;
-    CERTCertDBHandle *defaultDB = NULL;
-    PRFileDesc*     fd;
-    PRInt32         cc      = -1;
-    PRInt32         total;
-    PRInt32         remaining;
-    SECItem         item;
-    static unsigned char certBuf[RD_BUF_SIZE];
-
-    fd = PR_Open(fileName, PR_RDONLY, 0777); 
-    if (!fd) {
-	PRIntn err = PR_GetError();
-    	fprintf(stderr, "open of %s failed, %d = %s\n", 
-	        fileName, err, SECU_Strerror(err));
-	return cert;
-    }
-    /* read until EOF or buffer is full */
-    pb = certBuf;
-    while (0 < (remaining = (sizeof certBuf) - (pb - certBuf))) {
-	cc = PR_Read(fd, pb, remaining);
-	if (cc == 0) 
-	    break;
-	if (cc < 0) {
-	    PRIntn err = PR_GetError();
-	    fprintf(stderr, "read of %s failed, %d = %s\n", 
-	        fileName, err, SECU_Strerror(err));
-	    break;
-	}
-	/* cc > 0 */
-	pb += cc;
-    }
-    PR_Close(fd);
-    if (cc < 0)
-    	return cert;
-    if (!remaining || cc > 0) { /* file was too big. */
-	fprintf(stderr, "cert file %s was too big.\n");
-	return cert;
-    }
-    total = pb - certBuf;
-    if (!total) { /* file was empty */
-	fprintf(stderr, "cert file %s was empty.\n");
-	return cert;
-    }
-    if (isAscii) {
-    	/* convert from Base64 to binary here ... someday */
-    }
-    item.type = siBuffer;
-    item.data = certBuf;
-    item.len  = total;
-    defaultDB = CERT_GetDefaultCertDB();
-    cert = CERT_NewTempCertificate(defaultDB, &item, 
-                                   NULL     /* nickname */, 
-                                   PR_FALSE /* isPerm */, 
-				   PR_TRUE  /* copyDER */);
-    if (!cert) {
-	PRIntn err = PR_GetError();
-	fprintf(stderr, "couldn't import %s, %d = %s\n",
-	        fileName, err, SECU_Strerror(err));
-    }
-    return cert;
-}
-
-int
-main(int argc, char *argv[], char *envp[])
-{
-    char *               certDir      = NULL;
-    char *               progName     = NULL;
-    char *               cipherString = NULL;
-    CERTCertificate *    cert;
-    CERTCertificate *    firstCert    = NULL;
-    CERTCertDBHandle *   defaultDB    = NULL;
-    PRBool               isAscii      = PR_FALSE;
-    SECStatus            secStatus;
-    SECCertUsage         certUsage    = certUsageSSLServer;
-    PLOptState *         optstate;
-    PLOptStatus          status;
-
-    PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
-
-    progName = PL_strdup(argv[0]);
-
-    optstate = PL_CreateOptState(argc, argv, "ad:ru:w:v");
-    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
-	switch(optstate->option) {
-	case  0  : /* positional parameter */  goto breakout;
-	case 'a' : isAscii  = PR_TRUE;                        break;
-	case 'd' : certDir  = PL_strdup(optstate->value);     break;
-	case 'r' : isAscii  = PR_FALSE;                       break;
-	case 'u' : certUsage = (SECCertUsage)PORT_Atoi(optstate->value); break;
-	case 'w' : password = PL_strdup(optstate->value);     break;
-	case 'v' : verbose++;                                 break;
-	default  : Usage(progName);                           break;
-	}
-    }
-breakout:
-    if (status != PL_OPT_OK)
-	Usage(progName);
-
-    /* Set our password function callback. */
-    PK11_SetPasswordFunc(myPasswd);
-
-    /* Initialize the NSS libraries. */
-    if (certDir) {
-	secStatus = NSS_Init(certDir);
-    } else {
-	secStatus = NSS_NoDB_Init(NULL);
-
-	/* load the builtins */
-	SECMOD_AddNewModule("Builtins", DLL_PREFIX"nssckbi."DLL_SUFFIX, 0, 0);
-    }
-    if (secStatus != SECSuccess) {
-	exitErr("NSS_Init");
-    }
-
-
-    while (status == PL_OPT_OK) {
-	switch(optstate->option) {
-	default  : Usage(progName);                           break;
-	case 'a' : isAscii  = PR_TRUE;                        break;
-	case 'r' : isAscii  = PR_FALSE;                       break;
-	case  0  : /* positional parameter */
-	    cert = readCertFile(optstate->value, isAscii);
-	    if (!cert) 
-	        goto punt;
-	    rememberCert(cert);
-	    if (!firstCert)
-	        firstCert = cert;
-	    break;
-	}
-        status = PL_GetNextOpt(optstate);
-    }
-    if (status == PL_OPT_BAD || !firstCert)
-	Usage(progName);
-
-    /* NOW, verify the cert chain. */
-    defaultDB = CERT_GetDefaultCertDB();
-    secStatus = CERT_VerifyCert(defaultDB, firstCert, 
-                                PR_TRUE /* check sig */,
-				certUsage, 
-				PR_Now(), 
-				NULL, 		/* wincx  */
-				NULL);		/* error log */
-
-    if (secStatus != SECSuccess) {
-	PRIntn err = PR_GetError();
-	fprintf(stderr, "Chain is bad, %d = %s\n", err, SECU_Strerror(err));
-	printCertProblems(stderr, defaultDB, firstCert, 
-			  PR_TRUE, certUsage, NULL);
-    } else {
-    	fprintf(stderr, "Chain is good!\n");
-    }
-
-punt:
-    forgetCerts();
-    NSS_Shutdown();
-    PR_Cleanup();
-    return 0;
-}
--- a/security/nss/cmd/vfyserv/vfyutil.c
+++ b/security/nss/cmd/vfyserv/vfyutil.c
@@ -45,29 +45,42 @@ int ssl2CipherSuites[] = {
     SSL_EN_RC2_128_CBC_WITH_MD5,          /* C */
     SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
     SSL_EN_DES_64_CBC_WITH_MD5,           /* E */
     SSL_EN_DES_192_EDE3_CBC_WITH_MD5,     /* F */
     0
 };
 
 int ssl3CipherSuites[] = {
-    SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* a */
-    SSL_FORTEZZA_DMS_WITH_RC4_128_SHA,      /* b */
-    SSL_RSA_WITH_RC4_128_MD5,               /* c */
-    SSL_RSA_WITH_3DES_EDE_CBC_SHA,          /* d */
-    SSL_RSA_WITH_DES_CBC_SHA,               /* e */
-    SSL_RSA_EXPORT_WITH_RC4_40_MD5,         /* f */
-    SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,     /* g */
-    SSL_FORTEZZA_DMS_WITH_NULL_SHA,         /* h */
-    SSL_RSA_WITH_NULL_MD5,                  /* i */
-    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,     /* j */
-    SSL_RSA_FIPS_WITH_DES_CBC_SHA,          /* k */
-    TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,    /* l */
-    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,     /* m */
+    SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,	/* a */
+    SSL_FORTEZZA_DMS_WITH_RC4_128_SHA,		/* b */
+    SSL_RSA_WITH_RC4_128_MD5,			/* c */
+    SSL_RSA_WITH_3DES_EDE_CBC_SHA,		/* d */
+    SSL_RSA_WITH_DES_CBC_SHA,			/* e */
+    SSL_RSA_EXPORT_WITH_RC4_40_MD5,		/* f */
+    SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,		/* g */
+    SSL_FORTEZZA_DMS_WITH_NULL_SHA,		/* h */
+    SSL_RSA_WITH_NULL_MD5,			/* i */
+    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,		/* j */
+    SSL_RSA_FIPS_WITH_DES_CBC_SHA,		/* k */
+    TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,	/* l */
+    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,	        /* m */
+    SSL_RSA_WITH_RC4_128_SHA,			/* n */
+    TLS_DHE_DSS_WITH_RC4_128_SHA,		/* o */
+    SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,		/* p */
+    SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,		/* q */
+    SSL_DHE_RSA_WITH_DES_CBC_SHA,		/* r */
+    SSL_DHE_DSS_WITH_DES_CBC_SHA,		/* s */
+    TLS_DHE_DSS_WITH_AES_128_CBC_SHA, 	    	/* t */
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,       	/* u */
+    TLS_RSA_WITH_AES_128_CBC_SHA,     	    	/* v */
+    TLS_DHE_DSS_WITH_AES_256_CBC_SHA, 	    	/* w */
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,       	/* x */
+    TLS_RSA_WITH_AES_256_CBC_SHA,     	    	/* y */
+    SSL_RSA_WITH_NULL_SHA,			/* z */
     0
 };
 
 /**************************************************************************
 ** 
 ** SSL callback routines.
 **
 **************************************************************************/
--- a/security/nss/lib/base/errorval.c
+++ b/security/nss/lib/base/errorval.c
@@ -83,9 +83,11 @@ const NSSError NSS_ERROR_MAXIMUM_FOUND  
 
 const NSSError NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND   = 31;
 
 const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE           = 32;
 
 const NSSError NSS_ERROR_HASH_COLLISION                 = 33;
 const NSSError NSS_ERROR_DEVICE_ERROR                   = 34;
 const NSSError NSS_ERROR_INVALID_CERTIFICATE            = 35;
+const NSSError NSS_ERROR_BUSY                           = 36;
+const NSSError NSS_ERROR_ALREADY_INITIALIZED            = 37;
 
--- a/security/nss/lib/certdb/cert.h
+++ b/security/nss/lib/certdb/cert.h
@@ -473,16 +473,19 @@ CERT_FindCertByKeyID (CERTCertDBHandle *
 /*
 ** 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 CERTCertificate *
 CERT_FindCertByIssuerAndSN (CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN);
 
+extern CERTCertificate *
+CERT_FindCertBySubjectKeyID (CERTCertDBHandle *handle, SECItem *subjKeyID);
+
 /*
 ** Find a certificate in the database by a nickname
 **	"nickname" is the ascii string nickname to look for
 */
 extern CERTCertificate *
 CERT_FindCertByNickname (CERTCertDBHandle *handle, char *nickname);
 
 /*
@@ -564,19 +567,19 @@ extern CERTIssuerAndSN *CERT_GetCertIssu
 extern SECStatus CERT_VerifySignedData(CERTSignedData *sd,
 				       CERTCertificate *cert,
 				       int64 t,
 				       void *wincx);
 /*
 ** verify the signature of a signed data object with the given DER publickey
 */
 extern SECStatus
-CERT_VerifySignedDataWithPubKeyInfo(CERTSignedData *sd,
-                                    CERTSubjectPublicKeyInfo *pubKeyInfo,
-                                    void *wincx);
+CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd,
+                                       CERTSubjectPublicKeyInfo *pubKeyInfo,
+                                       void *wincx);
 
 /*
 ** verify the signature of a signed data object with a SECKEYPublicKey.
 */
 extern SECStatus
 CERT_VerifySignedDataWithPublicKey(CERTSignedData *sd,
                                    SECKEYPublicKey *pubKey, void *wincx);
 
@@ -917,17 +920,17 @@ extern CERTCrlDistributionPoints * CERT_
 ** allocated in value->data.
 */
 extern SECStatus CERT_FindKeyUsageExtension (CERTCertificate *cert, 
 							SECItem *value);
 
 /* Return the decoded value of the subjectKeyID extension. The caller should 
 ** free up the storage allocated in retItem->data.
 */
-extern SECStatus CERT_FindSubjectKeyIDExten (CERTCertificate *cert, 
+extern SECStatus CERT_FindSubjectKeyIDExtension (CERTCertificate *cert, 
 							   SECItem *retItem);
 
 /*
 ** If cert is a v3 certificate, and a critical keyUsage extension is included,
 ** then check the usage against the extension value.  If a non-critical 
 ** keyUsage extension is included, this will return SECSuccess without 
 ** checking, since the extension is an advisory field, not a restriction.  
 ** If cert is not a v3 certificate, this will return SECSuccess.
--- a/security/nss/lib/certdb/certdb.c
+++ b/security/nss/lib/certdb/certdb.c
@@ -665,17 +665,17 @@ cert_GetKeyID(CERTCertificate *cert)
 {
     SECItem tmpitem;
     SECStatus rv;
     SECKEYPublicKey *key;
     
     cert->subjectKeyID.len = 0;
 
     /* see of the cert has a key identifier extension */
-    rv = CERT_FindSubjectKeyIDExten(cert, &tmpitem);
+    rv = CERT_FindSubjectKeyIDExtension(cert, &tmpitem);
     if ( rv == SECSuccess ) {
 	cert->subjectKeyID.data = (unsigned char*) PORT_ArenaAlloc(cert->arena, tmpitem.len);
 	if ( cert->subjectKeyID.data != NULL ) {
 	    PORT_Memcpy(cert->subjectKeyID.data, tmpitem.data, tmpitem.len);
 	    cert->subjectKeyID.len = tmpitem.len;
 	    cert->keyIDGenerated = PR_FALSE;
 	}
 	
@@ -742,17 +742,17 @@ cert_IsRootCert(CERTCertificate *cert)
 	return PR_FALSE;
     }
 
     /* check the authKeyID extension */
     if (cert->authKeyID) {
 	/* authority key identifier is present */
 	if (cert->authKeyID->keyID.len > 0) {
 	    /* the keyIdentifier field is set, look for subjectKeyID */
-	    rv = CERT_FindSubjectKeyIDExten(cert, &tmpitem);
+	    rv = CERT_FindSubjectKeyIDExtension(cert, &tmpitem);
 	    if (rv == SECSuccess) {
 		PRBool match;
 		/* also present, they MUST match for it to be a root */
 		match = SECITEM_ItemsAreEqual(&cert->authKeyID->keyID,
 		                              &tmpitem);
 		PORT_Free(tmpitem.data);
 		if (!match) return PR_FALSE; /* else fall through */
 	    } else {
@@ -2732,8 +2732,164 @@ CERT_GetStatusConfig(CERTCertDBHandle *h
  * should not be another configuration set.
  */
 void
 CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *statusConfig)
 {
   PORT_Assert(handle->statusConfig == NULL);
   handle->statusConfig = statusConfig;
 }
+
+/*
+ * Code for dealing with subjKeyID to cert mappings.
+ */
+
+static PLHashTable *gSubjKeyIDHash = NULL;
+static PRLock      *gSubjKeyIDLock = NULL;
+
+static void *cert_AllocTable(void *pool, PRSize size)
+{
+    return PORT_Alloc(size);
+}
+
+static void cert_FreeTable(void *pool, void *item)
+{
+    PORT_Free(item);
+}
+
+static PLHashEntry* cert_AllocEntry(void *pool, const void *key)
+{
+    return PORT_New(PLHashEntry);
+}
+
+static void cert_FreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+    SECITEM_FreeItem((SECItem*)(he->value), PR_TRUE);
+    if (flag == HT_FREE_ENTRY) {
+        SECITEM_FreeItem((SECItem*)(he->key), PR_TRUE);
+        PORT_Free(he);
+    }
+}
+
+static PLHashAllocOps cert_AllocOps = {
+    cert_AllocTable, cert_FreeTable, cert_AllocEntry, cert_FreeEntry
+};
+
+SECStatus
+cert_CreateSubjectKeyIDHashTable(void)
+{
+    gSubjKeyIDHash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare,
+                                    SECITEM_HashCompare,
+                                    &cert_AllocOps, NULL);
+    if (!gSubjKeyIDHash) {
+        PORT_SetError(SEC_ERROR_NO_MEMORY);
+        return SECFailure;
+    }
+    gSubjKeyIDLock = PR_NewLock();
+    if (!gSubjKeyIDLock) {
+        PL_HashTableDestroy(gSubjKeyIDHash);
+        gSubjKeyIDHash = NULL;
+        PORT_SetError(SEC_ERROR_NO_MEMORY);
+        return SECFailure;
+    }
+    return SECSuccess;
+
+}
+
+SECStatus
+cert_AddSubjectKeyIDMapping(SECItem *subjKeyID, CERTCertificate *cert)
+{
+    SECItem *newKeyID, *oldVal, *newVal;
+    SECStatus rv = SECFailure;
+
+    if (!gSubjKeyIDLock) {
+	/* If one is created, then both are there.  So only check for one. */
+	return SECFailure;
+    }
+
+    newVal = SECITEM_DupItem(&cert->derCert);
+    if (!newVal) {
+        PORT_SetError(SEC_ERROR_NO_MEMORY);
+        goto done;
+    }
+    newKeyID = SECITEM_DupItem(subjKeyID);
+    if (!newKeyID) {
+        SECITEM_FreeItem(newVal, PR_TRUE);
+        PORT_SetError(SEC_ERROR_NO_MEMORY);
+        goto done;
+    }
+
+    PR_Lock(gSubjKeyIDLock);
+    /* The hash table implementation does not free up the memory 
+     * associated with the key of an already existing entry if we add a 
+     * duplicate, so we would wind up leaking the previously allocated 
+     * key if we don't remove before adding.
+     */
+    oldVal = (SECItem*)PL_HashTableLookup(gSubjKeyIDHash, subjKeyID);
+    if (oldVal) {
+        PL_HashTableRemove(gSubjKeyIDHash, subjKeyID);
+    }
+
+    rv = (PL_HashTableAdd(gSubjKeyIDHash, newKeyID, newVal)) ? SECSuccess :
+                                                               SECFailure;
+    PR_Unlock(gSubjKeyIDLock);
+done:
+    return rv;
+}
+
+SECStatus
+cert_RemoveSubjectKeyIDMapping(SECItem *subjKeyID)
+{
+    SECStatus rv;
+    if (!gSubjKeyIDLock)
+        return SECFailure;
+
+    PR_Lock(gSubjKeyIDLock);
+    rv = (PL_HashTableRemove(gSubjKeyIDHash, subjKeyID)) ? SECSuccess :
+                                                           SECFailure;
+    PR_Unlock(gSubjKeyIDLock);
+    return rv;
+}
+
+SECStatus
+cert_DestroySubjectKeyIDHashTable(void)
+{
+    if (gSubjKeyIDHash) {
+        PR_Lock(gSubjKeyIDLock);
+        PL_HashTableDestroy(gSubjKeyIDHash);
+        gSubjKeyIDHash = NULL;
+        PR_Unlock(gSubjKeyIDLock);
+        PR_DestroyLock(gSubjKeyIDLock);
+        gSubjKeyIDLock = NULL;
+    }
+    return SECSuccess;
+}
+
+SECItem*
+cert_FindDERCertBySubjectKeyID(SECItem *subjKeyID)
+{
+    SECItem   *val;
+ 
+    if (!gSubjKeyIDLock)
+        return NULL;
+
+    PR_Lock(gSubjKeyIDLock);
+    val = (SECItem*)PL_HashTableLookup(gSubjKeyIDHash, subjKeyID);
+    if (val) {
+        val = SECITEM_DupItem(val);
+    }
+    PR_Unlock(gSubjKeyIDLock);
+    return val;
+}
+
+CERTCertificate*
+CERT_FindCertBySubjectKeyID(CERTCertDBHandle *handle, SECItem *subjKeyID)
+{
+    CERTCertificate *cert = NULL;
+    SECItem *derCert;
+
+    derCert = cert_FindDERCertBySubjectKeyID(subjKeyID);
+    if (derCert) {
+        cert = CERT_FindCertByDERCert(handle, derCert);
+        SECITEM_FreeItem(derCert, PR_TRUE);
+    }
+    return cert;
+}
--- a/security/nss/lib/certdb/certi.h
+++ b/security/nss/lib/certdb/certi.h
@@ -183,10 +183,31 @@ SECStatus InitCRLCache(void);
 SECStatus ShutdownCRLCache(void);
 
 /* Returns a pointer to an environment-like string, a series of
 ** null-terminated strings, terminated by a zero-length string.
 ** This function is intended to be internal to NSS.
 */
 extern char * cert_GetCertificateEmailAddresses(CERTCertificate *cert);
 
+/*
+ * These functions are used to map subjectKeyID extension values to certs.
+ */
+SECStatus
+cert_CreateSubjectKeyIDHashTable(void);
+
+SECStatus
+cert_AddSubjectKeyIDMapping(SECItem *subjKeyID, CERTCertificate *cert);
+
+/*
+ * Call this function to remove an entry from the mapping table.
+ */
+SECStatus
+cert_RemoveSubjectKeyIDMapping(SECItem *subjKeyID);
+
+SECStatus
+cert_DestroySubjectKeyIDHashTable(void);
+
+SECItem*
+cert_FindDERCertBySubjectKeyID(SECItem *subjKeyID);
+
 #endif /* _CERTI_H_ */
 
--- a/security/nss/lib/certdb/certv3.c
+++ b/security/nss/lib/certdb/certv3.c
@@ -286,17 +286,17 @@ CERT_FindKeyUsageExtension(CERTCertifica
     return (CERT_FindBitStringExtension(cert->extensions,
 					SEC_OID_X509_KEY_USAGE, retItem));    
 }
 
 /*
  * get the value of the X.509 v3 Key Usage Extension
  */
 SECStatus
-CERT_FindSubjectKeyIDExten(CERTCertificate *cert, SECItem *retItem)
+CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem)
 {
 
     SECItem encodedValue;
     SECStatus rv;
 
     encodedValue.data = NULL;
     rv = cert_FindExtension
 	 (cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID, &encodedValue);
--- a/security/nss/lib/certhigh/certvfy.c
+++ b/security/nss/lib/certhigh/certvfy.c
@@ -117,19 +117,19 @@ CERT_VerifySignedDataWithPublicKey(CERTS
 
     return rv ? SECFailure : SECSuccess;
 }
 
 /*
  * verify the signature of a signed data object with the given DER publickey
  */
 SECStatus
-CERT_VerifySignedDataWithPubKeyInfo(CERTSignedData *sd, 
-                                    CERTSubjectPublicKeyInfo *pubKeyInfo,
-		                    void *wincx)
+CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd, 
+                                       CERTSubjectPublicKeyInfo *pubKeyInfo,
+		                       void *wincx)
 {
     SECKEYPublicKey *pubKey;
     SECStatus        rv		= SECFailure;
 
     /* get cert's public key */
     pubKey = SECKEY_ExtractPublicKey(pubKeyInfo);
     if (pubKey) {
 	rv =  CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
--- a/security/nss/lib/ckfw/nssck.api
+++ b/security/nss/lib/ckfw/nssck.api
@@ -1869,17 +1869,17 @@ static CK_RV CK_ENTRY
   CK_FUNCTION_LIST_PTR_PTR ppFunctionList
 )
 {
   *ppFunctionList = &FunctionList;
   return CKR_OK;
 }
 
 /* This one is always present */
-#ifdef WIN32
+#if defined(WIN32) || defined(XP_OS2_VACPP)
 CK_RV _declspec(dllexport)
 #else
 CK_RV CK_ENTRY
 #endif
 C_GetFunctionList
 (
   CK_FUNCTION_LIST_PTR_PTR ppFunctionList
 )
--- a/security/nss/lib/crmf/respcmn.c
+++ b/security/nss/lib/crmf/respcmn.c
@@ -76,34 +76,27 @@ CMMF_DestroyCertResponse(CMMFCertRespons
 SECStatus
 CMMF_DestroyCertRepContent(CMMFCertRepContent *inCertRepContent)
 {
     CMMFCertifiedKeyPair *certKeyPair;
     int i;
 
     PORT_Assert(inCertRepContent != NULL);
     if (inCertRepContent != NULL && inCertRepContent->poolp != NULL) {
-	if (!inCertRepContent->isDecoded) {
-	  if (inCertRepContent->response != NULL) {
-	    for (i=0; inCertRepContent->response[i] != NULL; i++) {
-	        certKeyPair = inCertRepContent->response[i]->certifiedKeyPair;
-		if (certKeyPair != NULL                    &&
-		    certKeyPair->certOrEncCert.choice == cmmfCertificate &&
-		    certKeyPair->certOrEncCert.cert.certificate != NULL) {
-		    CERT_DestroyCertificate
-		                 (certKeyPair->certOrEncCert.cert.certificate);
-		}
-	    }
-	  }
-	  if (inCertRepContent->caPubs != NULL) {
-	    for (i=0; inCertRepContent->caPubs[i] != NULL; i++) {
-	        CERT_DestroyCertificate(inCertRepContent->caPubs[i]);
-	    }
-	  }
-	}
+        if (inCertRepContent->response != NULL) {
+            for (i=0; inCertRepContent->response[i] != NULL; i++) {
+                certKeyPair = inCertRepContent->response[i]->certifiedKeyPair;
+                if (certKeyPair != NULL                    &&
+                    certKeyPair->certOrEncCert.choice == cmmfCertificate &&
+                    certKeyPair->certOrEncCert.cert.certificate != NULL) {
+                    CERT_DestroyCertificate
+                                 (certKeyPair->certOrEncCert.cert.certificate);
+                }
+            }
+        }
         PORT_FreeArena(inCertRepContent->poolp, PR_TRUE);
     }
     return SECSuccess;
 }
 
 SECStatus
 CMMF_DestroyPOPODecKeyChallContent(CMMFPOPODecKeyChallContent *inDecKeyCont)
 {
--- a/security/nss/lib/cryptohi/hasht.h
+++ b/security/nss/lib/cryptohi/hasht.h
@@ -42,36 +42,29 @@
 typedef struct SECHashObjectStr SECHashObject;
 typedef struct HASHContextStr HASHContext;
 
 /*
  * The hash functions the security library supports
  * NOTE the order must match the definition of SECHashObjects[]!
  */
 typedef enum {
-    HASH_AlgNULL   = 0,
-    HASH_AlgMD2    = 1,
-    HASH_AlgMD5    = 2,
-    HASH_AlgSHA1   = 3,
-    HASH_AlgSHA256 = 4,
-    HASH_AlgSHA384 = 5,
-    HASH_AlgSHA512 = 6,
+    HASH_AlgNULL = 0,
+    HASH_AlgMD2 = 1,
+    HASH_AlgMD5 = 2,
+    HASH_AlgSHA1 = 3,
     HASH_AlgTOTAL
 } HASH_HashType;
 
 /*
  * Number of bytes each hash algorithm produces
  */
 #define MD2_LENGTH	16
 #define MD5_LENGTH	16
 #define SHA1_LENGTH	20
-#define SHA256_LENGTH 	32
-#define SHA384_LENGTH 	48
-#define SHA512_LENGTH 	64
-#define HASH_LENGTH_MAX SHA512_LENGTH
 
 /*
  * Structure to hold hash computation info and routines
  */
 struct SECHashObjectStr {
     unsigned int length;
     void * (*create)(void);
     void * (*clone)(void *);
--- a/security/nss/lib/cryptohi/sechash.c
+++ b/security/nss/lib/cryptohi/sechash.c
@@ -82,31 +82,16 @@ md5_NewContext(void) {
 	return (void *) PK11_CreateDigestContext(SEC_OID_MD5);
 }
 
 static void *
 sha1_NewContext(void) {
 	return (void *) PK11_CreateDigestContext(SEC_OID_SHA1);
 }
 
-static void *
-sha256_NewContext(void) {
-	return (void *) PK11_CreateDigestContext(SEC_OID_SHA256);
-}
-
-static void *
-sha384_NewContext(void) {
-	return (void *) PK11_CreateDigestContext(SEC_OID_SHA384);
-}
-
-static void *
-sha512_NewContext(void) {
-	return (void *) PK11_CreateDigestContext(SEC_OID_SHA512);
-}
-
 const SECHashObject SECHashObjects[] = {
   { 0,
     (void * (*)(void)) null_hash_new_context,
     (void * (*)(void *)) null_hash_clone_context,
     (void (*)(void *, PRBool)) null_hash_destroy_context,
     (void (*)(void *)) null_hash_begin,
     (void (*)(void *, const unsigned char *, unsigned int)) null_hash_update,
     (void (*)(void *, unsigned char *, unsigned int *,
@@ -134,43 +119,16 @@ const SECHashObject SECHashObjects[] = {
     (void * (*)(void)) sha1_NewContext,
     (void * (*)(void *)) PK11_CloneContext,
     (void (*)(void *, PRBool)) PK11_DestroyContext,
     (void (*)(void *)) PK11_DigestBegin,
     (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp,
     (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) 
 							PK11_DigestFinal
   },
-  { SHA256_LENGTH,
-    (void * (*)(void)) sha256_NewContext,
-    (void * (*)(void *)) PK11_CloneContext,
-    (void (*)(void *, PRBool)) PK11_DestroyContext,
-    (void (*)(void *)) PK11_DigestBegin,
-    (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp,
-    (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) 
-							PK11_DigestFinal
-  },
-  { SHA384_LENGTH,
-    (void * (*)(void)) sha384_NewContext,
-    (void * (*)(void *)) PK11_CloneContext,
-    (void (*)(void *, PRBool)) PK11_DestroyContext,
-    (void (*)(void *)) PK11_DigestBegin,
-    (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp,
-    (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) 
-							PK11_DigestFinal
-  },
-  { SHA512_LENGTH,
-    (void * (*)(void)) sha512_NewContext,
-    (void * (*)(void *)) PK11_CloneContext,
-    (void (*)(void *, PRBool)) PK11_DestroyContext,
-    (void (*)(void *)) PK11_DigestBegin,
-    (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp,
-    (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) 
-							PK11_DigestFinal
-  },
 };
 
 const SECHashObject * 
 HASH_GetHashObject(HASH_HashType type)
 {
     return &SECHashObjects[type];
 }
 
--- a/security/nss/lib/dev/devtoken.c
+++ b/security/nss/lib/dev/devtoken.c
@@ -388,17 +388,17 @@ find_objects
   NSSToken *tok,
   nssSession *sessionOpt,
   CK_ATTRIBUTE_PTR obj_template,
   CK_ULONG otsize,
   PRUint32 maximumOpt,
   PRStatus *statusOpt
 )
 {
-    CK_RV ckrv;
+    CK_RV ckrv = CKR_OK;
     CK_ULONG count;
     CK_OBJECT_HANDLE *objectHandles;
     CK_OBJECT_HANDLE staticObjects[OBJECT_STACK_SIZE];
     PRUint32 arraySize, numHandles;
     void *epv = nssToken_GetCryptokiEPV(tok);
     nssCryptokiObject **objects;
     nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
 
@@ -410,16 +410,17 @@ find_objects
     }
     numHandles = 0;
     if (arraySize <= OBJECT_STACK_SIZE) {
 	objectHandles = staticObjects;
     } else {
 	objectHandles = nss_ZNEWARRAY(NULL, CK_OBJECT_HANDLE, arraySize);
     }
     if (!objectHandles) {
+	ckrv = CKR_HOST_MEMORY;
 	goto loser;
     }
     nssSession_EnterMonitor(session); /* ==== session lock === */
     /* Initialize the find with the template */
     ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, 
                                          obj_template, otsize);
     if (ckrv != CKR_OK) {
 	nssSession_ExitMonitor(session);
@@ -454,16 +455,17 @@ find_objects
 	    }
 	} else {
 	    objectHandles = nss_ZREALLOCARRAY(objectHandles, 
 	                                  CK_OBJECT_HANDLE, 
 	                                  arraySize);
 	}
 	if (!objectHandles) {
 	    nssSession_ExitMonitor(session);
+	    ckrv = CKR_HOST_MEMORY;
 	    goto loser;
 	}
     }
     ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
     nssSession_ExitMonitor(session); /* ==== end session lock === */
     if (ckrv != CKR_OK) {
 	goto loser;
     }
@@ -478,17 +480,33 @@ find_objects
 	nss_ZFreeIf(objectHandles);
     }
     if (statusOpt) *statusOpt = PR_SUCCESS;
     return objects;
 loser:
     if (objectHandles && objectHandles != staticObjects) {
 	nss_ZFreeIf(objectHandles);
     }
-    if (statusOpt) *statusOpt = PR_FAILURE;
+    /*
+     * These errors should be treated the same as if the objects just weren't
+     * found..
+     */
+    if ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
+	(ckrv == CKR_ATTRIBUTE_VALUE_INVALID) ||
+	(ckrv == CKR_DATA_INVALID) ||
+	(ckrv == CKR_DATA_LEN_RANGE) ||
+	(ckrv == CKR_FUNCTION_NOT_SUPPORTED) ||
+	(ckrv == CKR_TEMPLATE_INCOMPLETE) ||
+	(ckrv == CKR_TEMPLATE_INCONSISTENT)) {
+
+	nss_SetError(NSS_ERROR_NOT_FOUND);
+	if (statusOpt) *statusOpt = PR_SUCCESS;
+    } else {
+	if (statusOpt) *statusOpt = PR_FAILURE;
+    }
     return (nssCryptokiObject **)NULL;
 }
 
 static nssCryptokiObject **
 find_objects_by_template
 (
   NSSToken *token,
   nssSession *sessionOpt,
--- a/security/nss/lib/freebl/blapi.h
+++ b/security/nss/lib/freebl/blapi.h
@@ -702,68 +702,16 @@ extern SECStatus SHA1_Flatten(SHA1Contex
 /*
  * Resurrect a flattened context into a SHA-1 Context
  *    "space" the buffer of the flattend buffer
  *    "arg" ptr to void used by cryptographic resurrect
  *  returns resurected context;
  */
 extern SHA1Context * SHA1_Resurrect(unsigned char *space, void *arg);
 
-/******************************************/
-
-extern SHA256Context *SHA256_NewContext(void);
-extern void SHA256_DestroyContext(SHA256Context *cx, PRBool freeit);
-extern void SHA256_Begin(SHA256Context *cx);
-extern void SHA256_Update(SHA256Context *cx, const unsigned char *input,
-			unsigned int inputLen);
-extern void SHA256_End(SHA256Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen);
-extern SECStatus SHA256_HashBuf(unsigned char *dest, const unsigned char *src,
-			      uint32 src_length);
-extern SECStatus SHA256_Hash(unsigned char *dest, const char *src);
-extern void SHA256_TraceState(SHA256Context *cx);
-extern unsigned int SHA256_FlattenSize(SHA256Context *cx);
-extern SECStatus SHA256_Flatten(SHA256Context *cx,unsigned char *space);
-extern SHA256Context * SHA256_Resurrect(unsigned char *space, void *arg);
-
-/******************************************/
-
-extern SHA512Context *SHA512_NewContext(void);
-extern void SHA512_DestroyContext(SHA512Context *cx, PRBool freeit);
-extern void SHA512_Begin(SHA512Context *cx);
-extern void SHA512_Update(SHA512Context *cx, const unsigned char *input,
-			unsigned int inputLen);
-extern void SHA512_End(SHA512Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen);
-extern SECStatus SHA512_HashBuf(unsigned char *dest, const unsigned char *src,
-			      uint32 src_length);
-extern SECStatus SHA512_Hash(unsigned char *dest, const char *src);
-extern void SHA512_TraceState(SHA512Context *cx);
-extern unsigned int SHA512_FlattenSize(SHA512Context *cx);
-extern SECStatus SHA512_Flatten(SHA512Context *cx,unsigned char *space);
-extern SHA512Context * SHA512_Resurrect(unsigned char *space, void *arg);
-
-/******************************************/
-
-extern SHA384Context *SHA384_NewContext(void);
-extern void SHA384_DestroyContext(SHA384Context *cx, PRBool freeit);
-extern void SHA384_Begin(SHA384Context *cx);
-extern void SHA384_Update(SHA384Context *cx, const unsigned char *input,
-			unsigned int inputLen);
-extern void SHA384_End(SHA384Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen);
-extern SECStatus SHA384_HashBuf(unsigned char *dest, const unsigned char *src,
-			      uint32 src_length);
-extern SECStatus SHA384_Hash(unsigned char *dest, const char *src);
-extern void SHA384_TraceState(SHA384Context *cx);
-extern unsigned int SHA384_FlattenSize(SHA384Context *cx);
-extern SECStatus SHA384_Flatten(SHA384Context *cx,unsigned char *space);
-extern SHA384Context * SHA384_Resurrect(unsigned char *space, void *arg);
-
-/******************************************/
 /*
 ** Pseudo Random Number Generation.  FIPS compliance desirable.
 */
 
 /*
 ** Initialize the global RNG context and give it some seed input taken
 ** from the system.  This function is thread-safe and will only allow
 ** the global context to be initialized once.  The seed input is likely
--- a/security/nss/lib/freebl/ldvector.c
+++ b/security/nss/lib/freebl/ldvector.c
@@ -108,63 +108,19 @@ static const struct FREEBLVectorStr vect
     SHA1_Resurrect,
     RNG_RNGInit,
     RNG_RandomUpdate,
     RNG_GenerateGlobalRandomBytes,
     RNG_RNGShutdown,
     PQG_ParamGen,
     PQG_ParamGenSeedLen,
     PQG_VerifyParams,
-
-    /* End of Version 3.001. */
-
     RSA_PrivateKeyOpDoubleChecked,
     RSA_PrivateKeyCheck,
     BL_Cleanup,
-
-    /* End of Version 3.002. */
-
-    SHA256_NewContext,
-    SHA256_DestroyContext,
-    SHA256_Begin,
-    SHA256_Update,
-    SHA256_End,
-    SHA256_HashBuf,
-    SHA256_Hash,
-    SHA256_TraceState,
-    SHA256_FlattenSize,
-    SHA256_Flatten,
-    SHA256_Resurrect,
-
-    SHA512_NewContext,
-    SHA512_DestroyContext,
-    SHA512_Begin,
-    SHA512_Update,
-    SHA512_End,
-    SHA512_HashBuf,
-    SHA512_Hash,
-    SHA512_TraceState,
-    SHA512_FlattenSize,
-    SHA512_Flatten,
-    SHA512_Resurrect,
-
-    SHA384_NewContext,
-    SHA384_DestroyContext,
-    SHA384_Begin,
-    SHA384_Update,
-    SHA384_End,
-    SHA384_HashBuf,
-    SHA384_Hash,
-    SHA384_TraceState,
-    SHA384_FlattenSize,
-    SHA384_Flatten,
-    SHA384_Resurrect,
-
-    /* End of Version 3.003. */
-
 };
 
 
 const FREEBLVector * 
 FREEBL_GetVector(void)
 {
   return &vector;
 }
--- a/security/nss/lib/freebl/loader.c
+++ b/security/nss/lib/freebl/loader.c
@@ -954,283 +954,8 @@ PQG_DestroyVerify(PQGVerify *vfy)
 void 
 BL_Cleanup(void)
 {
   if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
       return;
   (vector->p_BL_Cleanup)();
 }
 
-/* ============== New for 3.003 =============================== */
-
-SECStatus 
-SHA256_Hash(unsigned char *dest, const char *src)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return SECFailure;
-  return (vector->p_SHA256_Hash)(dest, src);
-}
-
-SECStatus 
-SHA256_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return SECFailure;
-  return (vector->p_SHA256_HashBuf)(dest, src, src_length);
-}
-
-SHA256Context *
-SHA256_NewContext(void)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return NULL;
-  return (vector->p_SHA256_NewContext)();
-}
-
-void 
-SHA256_DestroyContext(SHA256Context *cx, PRBool freeit)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA256_DestroyContext)(cx, freeit);
-}
-
-void 
-SHA256_Begin(SHA256Context *cx)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA256_Begin)(cx);
-}
-
-void 
-SHA256_Update(SHA256Context *cx, const unsigned char *input,
-			unsigned int inputLen)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA256_Update)(cx, input, inputLen);
-}
-
-void 
-SHA256_End(SHA256Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA256_End)(cx, digest, digestLen, maxDigestLen);
-}
-
-void 
-SHA256_TraceState(SHA256Context *cx)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA256_TraceState)(cx);
-}
-
-unsigned int 
-SHA256_FlattenSize(SHA256Context *cx)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return 0;
-  return (vector->p_SHA256_FlattenSize)(cx);
-}
-
-SECStatus 
-SHA256_Flatten(SHA256Context *cx,unsigned char *space)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return SECFailure;
-  return (vector->p_SHA256_Flatten)(cx, space);
-}
-
-SHA256Context * 
-SHA256_Resurrect(unsigned char *space, void *arg)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return NULL;
-  return (vector->p_SHA256_Resurrect)(space, arg);
-}
-
-SECStatus 
-SHA512_Hash(unsigned char *dest, const char *src)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return SECFailure;
-  return (vector->p_SHA512_Hash)(dest, src);
-}
-
-SECStatus 
-SHA512_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return SECFailure;
-  return (vector->p_SHA512_HashBuf)(dest, src, src_length);
-}
-
-SHA512Context *
-SHA512_NewContext(void)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return NULL;
-  return (vector->p_SHA512_NewContext)();
-}
-
-void 
-SHA512_DestroyContext(SHA512Context *cx, PRBool freeit)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA512_DestroyContext)(cx, freeit);
-}
-
-void 
-SHA512_Begin(SHA512Context *cx)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA512_Begin)(cx);
-}
-
-void 
-SHA512_Update(SHA512Context *cx, const unsigned char *input,
-			unsigned int inputLen)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA512_Update)(cx, input, inputLen);
-}
-
-void 
-SHA512_End(SHA512Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA512_End)(cx, digest, digestLen, maxDigestLen);
-}
-
-void 
-SHA512_TraceState(SHA512Context *cx)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA512_TraceState)(cx);
-}
-
-unsigned int 
-SHA512_FlattenSize(SHA512Context *cx)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return 0;
-  return (vector->p_SHA512_FlattenSize)(cx);
-}
-
-SECStatus 
-SHA512_Flatten(SHA512Context *cx,unsigned char *space)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return SECFailure;
-  return (vector->p_SHA512_Flatten)(cx, space);
-}
-
-SHA512Context * 
-SHA512_Resurrect(unsigned char *space, void *arg)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return NULL;
-  return (vector->p_SHA512_Resurrect)(space, arg);
-}
-
-
-SECStatus 
-SHA384_Hash(unsigned char *dest, const char *src)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return SECFailure;
-  return (vector->p_SHA384_Hash)(dest, src);
-}
-
-SECStatus 
-SHA384_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return SECFailure;
-  return (vector->p_SHA384_HashBuf)(dest, src, src_length);
-}
-
-SHA384Context *
-SHA384_NewContext(void)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return NULL;
-  return (vector->p_SHA384_NewContext)();
-}
-
-void 
-SHA384_DestroyContext(SHA384Context *cx, PRBool freeit)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA384_DestroyContext)(cx, freeit);
-}
-
-void 
-SHA384_Begin(SHA384Context *cx)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA384_Begin)(cx);
-}
-
-void 
-SHA384_Update(SHA384Context *cx, const unsigned char *input,
-			unsigned int inputLen)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA384_Update)(cx, input, inputLen);
-}
-
-void 
-SHA384_End(SHA384Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA384_End)(cx, digest, digestLen, maxDigestLen);
-}
-
-void 
-SHA384_TraceState(SHA384Context *cx)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return ;
-  (vector->p_SHA384_TraceState)(cx);
-}
-
-unsigned int 
-SHA384_FlattenSize(SHA384Context *cx)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return 0;
-  return (vector->p_SHA384_FlattenSize)(cx);
-}
-
-SECStatus 
-SHA384_Flatten(SHA384Context *cx,unsigned char *space)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return SECFailure;
-  return (vector->p_SHA384_Flatten)(cx, space);
-}
-
-SHA384Context * 
-SHA384_Resurrect(unsigned char *space, void *arg)
-{
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-      return NULL;
-  return (vector->p_SHA384_Resurrect)(space, arg);
-}
-
-
-
--- a/security/nss/lib/freebl/loader.h
+++ b/security/nss/lib/freebl/loader.h
@@ -35,17 +35,17 @@
  * $Id$
  */
 
 #ifndef _LOADER_H_
 #define _LOADER_H_ 1
 
 #include "blapi.h"
 
-#define FREEBL_VERSION 0x0303
+#define FREEBL_VERSION 0x0302
 
 struct FREEBLVectorStr {
 
   unsigned short length;  /* of this struct in bytes */
   unsigned short version; /* of this struct. */
 
   RSAPrivateKey * (* p_RSA_NewKey)(int         keySizeInBits,
 				 SECItem *   publicExponent);
@@ -260,63 +260,16 @@ struct FREEBLVectorStr {
                               const unsigned char *input);
 
   SECStatus (* p_RSA_PrivateKeyCheck)(RSAPrivateKey *key);
 
   void (* p_BL_Cleanup)(void);
 
   /* Version 3.002 came to here */
 
- SHA256Context *(* p_SHA256_NewContext)(void);
- void (* p_SHA256_DestroyContext)(SHA256Context *cx, PRBool freeit);
- void (* p_SHA256_Begin)(SHA256Context *cx);
- void (* p_SHA256_Update)(SHA256Context *cx, const unsigned char *input,
-			unsigned int inputLen);
- void (* p_SHA256_End)(SHA256Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen);
- SECStatus (* p_SHA256_HashBuf)(unsigned char *dest, const unsigned char *src,
-			      uint32 src_length);
- SECStatus (* p_SHA256_Hash)(unsigned char *dest, const char *src);
- void (* p_SHA256_TraceState)(SHA256Context *cx);
- unsigned int (* p_SHA256_FlattenSize)(SHA256Context *cx);
- SECStatus (* p_SHA256_Flatten)(SHA256Context *cx,unsigned char *space);
- SHA256Context * (* p_SHA256_Resurrect)(unsigned char *space, void *arg);
-
- SHA512Context *(* p_SHA512_NewContext)(void);
- void (* p_SHA512_DestroyContext)(SHA512Context *cx, PRBool freeit);
- void (* p_SHA512_Begin)(SHA512Context *cx);
- void (* p_SHA512_Update)(SHA512Context *cx, const unsigned char *input,
-			unsigned int inputLen);
- void (* p_SHA512_End)(SHA512Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen);
- SECStatus (* p_SHA512_HashBuf)(unsigned char *dest, const unsigned char *src,
-			      uint32 src_length);
- SECStatus (* p_SHA512_Hash)(unsigned char *dest, const char *src);
- void (* p_SHA512_TraceState)(SHA512Context *cx);
- unsigned int (* p_SHA512_FlattenSize)(SHA512Context *cx);
- SECStatus (* p_SHA512_Flatten)(SHA512Context *cx,unsigned char *space);
- SHA512Context * (* p_SHA512_Resurrect)(unsigned char *space, void *arg);
-
- SHA384Context *(* p_SHA384_NewContext)(void);
- void (* p_SHA384_DestroyContext)(SHA384Context *cx, PRBool freeit);
- void (* p_SHA384_Begin)(SHA384Context *cx);
- void (* p_SHA384_Update)(SHA384Context *cx, const unsigned char *input,
-			unsigned int inputLen);
- void (* p_SHA384_End)(SHA384Context *cx, unsigned char *digest,
-		     unsigned int *digestLen, unsigned int maxDigestLen);
- SECStatus (* p_SHA384_HashBuf)(unsigned char *dest, const unsigned char *src,
-			      uint32 src_length);
- SECStatus (* p_SHA384_Hash)(unsigned char *dest, const char *src);
- void (* p_SHA384_TraceState)(SHA384Context *cx);
- unsigned int (* p_SHA384_FlattenSize)(SHA384Context *cx);
- SECStatus (* p_SHA384_Flatten)(SHA384Context *cx,unsigned char *space);
- SHA384Context * (* p_SHA384_Resurrect)(unsigned char *space, void *arg);
-
-  /* Version 3.003 came to here */
-
 };
 
 typedef struct FREEBLVectorStr FREEBLVector;
 
 SEC_BEGIN_PROTOS
 
 typedef const FREEBLVector * FREEBLGetVectorFn(void);
 
--- a/security/nss/lib/freebl/manifest.mn
+++ b/security/nss/lib/freebl/manifest.mn
@@ -76,17 +76,16 @@ CSRCS = \
 else
 CSRCS = \
 	ldvector.c \
 	prng_fips1861.c \
 	sysrand.c \
 	sha_fast.c \
 	md2.c \
 	md5.c \
-	sha512.c \
 	alg2268.c \
 	arcfour.c \
 	arcfive.c \
 	desblapi.c \
 	des.c \
 	rijndael.c \
 	dh.c \
 	pqg.c \
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -712,16 +712,26 @@ PK11_TokenKeyGen;
 SEC_QuickDERDecodeItem;
 SECKEY_CopyPublicKey;
 ;+    local:
 ;+       *;
 ;+};
 ;+NSS_3.7 { 	# NSS 3.7 release
 ;+    global:
 CERT_CRLCacheRefreshIssuer;
+CERT_DestroyOCSPResponse;
 CERT_EncodeAltNameExtension;
+CERT_FindCertBySubjectKeyID;
+CERT_FindSubjectKeyIDExtension;
 CERT_GetFirstEmailAddress;
 CERT_GetNextEmailAddress;
-CERT_VerifySignedDataWithPubKeyInfo;
 CERT_VerifySignedDataWithPublicKey;
+CERT_VerifySignedDataWithPublicKeyInfo;
+PK11_WaitForTokenEvent;
 ;+    local:
 ;+       *;
 ;+};
+;+NSS_3.7.1 { 	# NSS 3.7.1 release
+;+    global:
+PK11_TokenRefresh;
+;+    local:
+;+       *;
+;+};
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -44,20 +44,20 @@ SEC_BEGIN_PROTOS
 
 /*
  * NSS's major version, minor version, patch level, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>] [<Beta>]"
  */
-#define NSS_VERSION  "3.7 Beta"
+#define NSS_VERSION  "3.7.2 Beta"
 #define NSS_VMAJOR   3
 #define NSS_VMINOR   7
-#define NSS_VPATCH   0
+#define NSS_VPATCH   2
 #define NSS_BETA     PR_TRUE
 
 
 /*
  * Return a boolean that indicates whether the underlying library
  * will perform as the caller expects.
  *
  * The only argument is a string, which should be the verson
--- a/security/nss/lib/nss/nssinit.c
+++ b/security/nss/lib/nss/nssinit.c
@@ -44,19 +44,22 @@
 #include "key.h"
 #include "ssl.h"
 #include "sslproto.h"
 #include "secmod.h"
 #include "secoid.h"
 #include "nss.h"
 #include "secrng.h"
 #include "pk11func.h"
+#include "secerr.h"
+#include "nssbase.h"
 
 #include "pki3hack.h"
 #include "certi.h"
+#include "secmodi.h"
 
 /*
  * On Windows nss3.dll needs to export the symbol 'mktemp' to be
  * fully backward compatible with the nss3.dll in NSS 3.2.x and
  * 3.3.x.  This symbol was unintentionally exported and its
  * definition (in DBM) was moved from nss3.dll to softokn3.dll
  * in NSS 3.4.  See bug 142575.
  */
@@ -458,29 +461,32 @@ loser:
 	PR_smprintf_free(moduleSpec);
 	if (module) {
 	    if (module->loaded) rv=SECSuccess;
 	    SECMOD_DestroyModule(module);
 	}
     }
 
     if (rv == SECSuccess) {
-	/* can this function fail?? */
-	STAN_LoadDefaultNSS3TrustDomain();
+	if (STAN_LoadDefaultNSS3TrustDomain() != PR_SUCCESS) {
+	    return SECFailure;
+	}
 	CERT_SetDefaultCertDB((CERTCertDBHandle *)
 				STAN_GetDefaultTrustDomain());
 #ifndef XP_MAC
 	/* only servers need this. We currently do not have a mac server */
 	if ((!noModDB) && (!noCertDB) && (!noRootInit)) {
 	    if (!SECMOD_HasRootCerts()) {
 		nss_FindExternalRoot(configdir, secmodName);
 	    }
 	}
 #endif
 	pk11sdr_Init();
+	cert_CreateSubjectKeyIDHashTable();
+	SECMOD_InitCallOnce();
 	nss_IsInitted = PR_TRUE;
     }
     return rv;
 }
 
 
 SECStatus
 NSS_Init(const char *configdir)
@@ -532,26 +538,37 @@ NSS_Initialize(const char *configdir, co
  */
 SECStatus
 NSS_NoDB_Init(const char * configdir)
 {
       return nss_Init("","","","",
 			PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE);
 }
 
+extern const NSSError NSS_ERROR_BUSY;
+
 SECStatus
 NSS_Shutdown(void)
 {
     SECStatus rv;
+    PRStatus status;
 
     ShutdownCRLCache();
     SECOID_Shutdown();
-    STAN_Shutdown();
+    status = STAN_Shutdown();
+    cert_DestroySubjectKeyIDHashTable();
+    SECMOD_CleanupCallOnce();
     rv = SECMOD_Shutdown();
     pk11sdr_Shutdown();
+    if (status == PR_FAILURE) {
+	if (NSS_GetError() == NSS_ERROR_BUSY) {
+	    PORT_SetError(SEC_ERROR_BUSY);
+	}
+	rv = SECFailure;
+    }
     nss_IsInitted = PR_FALSE;
     return rv;
 }
 
 
 
 extern const char __nss_base_rcsid[];
 extern const char __nss_base_sccsid[];
--- a/security/nss/lib/pk11wrap/debug_module.c
+++ b/security/nss/lib/pk11wrap/debug_module.c
@@ -265,1768 +265,1824 @@ static void print_template(CK_ATTRIBUTE_
     }
 }
 
 static void print_mechanism(CK_MECHANISM_PTR m)
 {
     PR_LOG(modlog, 4, ("      mechanism = 0x%p", m->mechanism));
 }
 
-struct nssdbg_prof_str {
-    PRUint32 time;
-    PRUint32 calls;
-    char *function;
-};
-
-#define NSSDBG_DEFINE(func) { 0, 0, #func }
+#define MAX_UINT32 0xffffffff
 
-struct nssdbg_prof_str nssdbg_prof_data[] = {
-#define FUNC_C_INITIALIZE 0
-    NSSDBG_DEFINE(C_Initialize),
-#define FUNC_C_FINALIZE 1
-    NSSDBG_DEFINE(C_Finalize),
-#define FUNC_C_GETINFO 2
-    NSSDBG_DEFINE(C_GetInfo),
-#define FUNC_C_GETFUNCITONLIST 3
-    NSSDBG_DEFINE(C_GetFunctionList),
-#define FUNC_C_GETSLOTLIST 4
-    NSSDBG_DEFINE(C_GetSlotList),
-#define FUNC_C_GETSLOTINFO 5
-    NSSDBG_DEFINE(C_GetSlotInfo),
-#define FUNC_C_GETTOKENINFO 6
-    NSSDBG_DEFINE(C_GetTokenInfo),
-#define FUNC_C_GETMECHANISMLIST 7
-    NSSDBG_DEFINE(C_GetMechanismList),
-#define FUNC_C_GETMECHANISMINFO 8
-    NSSDBG_DEFINE(C_GetMechanismInfo),
-#define FUNC_C_INITTOKEN 9
-    NSSDBG_DEFINE(C_InitToken),
-#define FUNC_C_INITPIN 10
-    NSSDBG_DEFINE(C_InitPIN),
-#define FUNC_C_SETPIN 11
-    NSSDBG_DEFINE(C_SetPIN),
-#define FUNC_C_OPENSESSION 12
-    NSSDBG_DEFINE(C_OpenSession),
-#define FUNC_C_CLOSESESSION 13
-    NSSDBG_DEFINE(C_CloseSession),
-#define FUNC_C_CLOSEALLSESSIONS 14
-    NSSDBG_DEFINE(C_CloseAllSessions),
-#define FUNC_C_GETSESSIONINFO 15
-    NSSDBG_DEFINE(C_GetSessionInfo),
-#define FUNC_C_GETOPERATIONSTATE 16
-    NSSDBG_DEFINE(C_GetOperationState),
-#define FUNC_C_SETOPERATIONSTATE 17
-    NSSDBG_DEFINE(C_SetOperationState),
-#define FUNC_C_LOGIN 18
-    NSSDBG_DEFINE(C_Login),
-#define FUNC_C_LOGOUT 19
-    NSSDBG_DEFINE(C_Logout),
-#define FUNC_C_CREATEOBJECT 20
-    NSSDBG_DEFINE(C_CreateObject),
-#define FUNC_C_COPYOBJECT 21
-    NSSDBG_DEFINE(C_CopyObject),
-#define FUNC_C_DESTROYOBJECT 22
-    NSSDBG_DEFINE(C_DestroyObject),
-#define FUNC_C_GETOBJECTSIZE  23
-    NSSDBG_DEFINE(C_GetObjectSize),
-#define FUNC_C_GETATTRIBUTEVALUE 24
-    NSSDBG_DEFINE(C_GetAttributeValue),
-#define FUNC_C_SETATTRIBUTEVALUE 25
-    NSSDBG_DEFINE(C_SetAttributeValue),
-#define FUNC_C_FINDOBJECTSINIT 26
-    NSSDBG_DEFINE(C_FindObjectsInit),
-#define FUNC_C_FINDOBJECTS 27
-    NSSDBG_DEFINE(C_FindObjects),
-#define FUNC_C_FINDOBJECTSFINAL 28
-    NSSDBG_DEFINE(C_FindObjectsFinal),
-#define FUNC_C_ENCRYPTINIT 29
-    NSSDBG_DEFINE(C_EncryptInit),
-#define FUNC_C_ENCRYPT 30
-    NSSDBG_DEFINE(C_Encrypt),
-#define FUNC_C_ENCRYPTUPDATE 31
-    NSSDBG_DEFINE(C_EncryptUpdate),
-#define FUNC_C_ENCRYPTFINAL 32
-    NSSDBG_DEFINE(C_EncryptFinal),
-#define FUNC_C_DECRYPTINIT 33
-    NSSDBG_DEFINE(C_DecryptInit),
-#define FUNC_C_DECRYPT 34
-    NSSDBG_DEFINE(C_Decrypt),
-#define FUNC_C_DECRYPTUPDATE 35
-    NSSDBG_DEFINE(C_DecryptUpdate),
-#define FUNC_C_DECRYPTFINAL 36
-    NSSDBG_DEFINE(C_DecryptFinal),
-#define FUNC_C_DIGESTINIT 37
-    NSSDBG_DEFINE(C_DigestInit),
-#define FUNC_C_DIGEST 38
-    NSSDBG_DEFINE(C_Digest),
-#define FUNC_C_DIGESTUPDATE 39
-    NSSDBG_DEFINE(C_DigestUpdate),
-#define FUNC_C_DIGESTKEY 40
-    NSSDBG_DEFINE(C_DigestKey),
-#define FUNC_C_DIGESTFINAL 41
-    NSSDBG_DEFINE(C_DigestFinal),
-#define FUNC_C_SIGNINIT 42
-    NSSDBG_DEFINE(C_SignInit),
-#define FUNC_C_SIGN 43
-    NSSDBG_DEFINE(C_Sign),
-#define FUNC_C_SIGNUPDATE 44
-    NSSDBG_DEFINE(C_SignUpdate),
-#define FUNC_C_SIGNFINAL 45
-    NSSDBG_DEFINE(C_SignFinal),
-#define FUNC_C_SIGNRECOVERINIT 46
-    NSSDBG_DEFINE(C_SignRecoverInit),
-#define FUNC_C_SIGNRECOVER 47
-    NSSDBG_DEFINE(C_SignRecover),
-#define FUNC_C_VERIFYINIT 48
-    NSSDBG_DEFINE(C_VerifyInit),
-#define FUNC_C_VERIFY 49
-    NSSDBG_DEFINE(C_Verify),
-#define FUNC_C_VERIFYUPDATE 50
-    NSSDBG_DEFINE(C_VerifyUpdate),
-#define FUNC_C_VERIFYFINAL 51
-    NSSDBG_DEFINE(C_VerifyFinal),
-#define FUNC_C_VERIFYRECOVERINIT 52
-    NSSDBG_DEFINE(C_VerifyRecoverInit),
-#define FUNC_C_VERIFYRECOVER 53
-    NSSDBG_DEFINE(C_VerifyRecover),
-#define FUNC_C_DIGESTENCRYPTUPDATE 54
-    NSSDBG_DEFINE(C_DigestEncryptUpdate),
-#define FUNC_C_DECRYPTDIGESTUPDATE 55
-    NSSDBG_DEFINE(C_DecryptDigestUpdate),
-#define FUNC_C_SIGNENCRYPTUPDATE 56
-    NSSDBG_DEFINE(C_SignEncryptUpdate),
-#define FUNC_C_DECRYPTVERIFYUPDATE 57
-    NSSDBG_DEFINE(C_DecryptVerifyUpdate),
-#define FUNC_C_GENERATEKEY 58
-    NSSDBG_DEFINE(C_GenerateKey),
-#define FUNC_C_GENERATEKEYPAIR 59
-    NSSDBG_DEFINE(C_GenerateKeyPair),
-#define FUNC_C_WRAPKEY 60
-    NSSDBG_DEFINE(C_WrapKey),
-#define FUNC_C_UNWRAPKEY 61
-    NSSDBG_DEFINE(C_UnWrapKey),
-#define FUNC_C_DERIVEKEY 62 
-    NSSDBG_DEFINE(C_DeriveKey),
-#define FUNC_C_SEEDRANDOM 63
-    NSSDBG_DEFINE(C_SeedRandom),
-#define FUNC_C_GENERATERANDOM 64
-    NSSDBG_DEFINE(C_GenerateRandom),
-#define FUNC_C_GETFUNCTIONSTATUS 65
-    NSSDBG_DEFINE(C_GetFunctionStatus),
-#define FUNC_C_CANCELFUNCTION 66
-    NSSDBG_DEFINE(C_CancelFunction),
-#define FUNC_C_WAITFORSLOTEVENT 67
-    NSSDBG_DEFINE(C_WaitForSlotEvent)
-};
-
-int nssdbg_prof_size = sizeof(nssdbg_prof_data)/sizeof(nssdbg_prof_data[0]);
-    
-
-static void nssdbg_finish_time(PRInt32 fun_number, PRIntervalTime start)
+static void nssdbg_finish_time(PRInt32 *counter, PRIntervalTime start)
 {
     PRIntervalTime ival;
     PRIntervalTime end = PR_IntervalNow();
 
-    ival = end-start;
-    /* sigh, lie to PRAtomic add and say we are using signed values */
-    PR_AtomicAdd((PRInt32 *)&nssdbg_prof_data[fun_number].time, (PRInt32)ival);
+    if (end >= start) {
+	ival = PR_IntervalToMilliseconds(end-start);
+    } else {
+	/* the interval timer rolled over. presume it only tripped once */
+	ival = PR_IntervalToMilliseconds(MAX_UINT32-start) +
+			PR_IntervalToMilliseconds(end);
+    }
+    PR_AtomicAdd(counter, ival);
 }
 
-static void nssdbg_start_time(PRInt32 fun_number, PRIntervalTime *start)
-{
-    PR_AtomicIncrement((PRInt32 *)&nssdbg_prof_data[fun_number].calls);
-    *start = PR_IntervalNow();
-}
-
+static PRInt32 counter_C_Initialize = 0;
+static PRInt32 calls_C_Initialize = 0;
 CK_RV NSSDBGC_Initialize(
   CK_VOID_PTR pInitArgs
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_Initialize);
     PR_LOG(modlog, 1, ("C_Initialize"));
     PR_LOG(modlog, 3, ("  pInitArgs = 0x%p", pInitArgs));
-    nssdbg_start_time(FUNC_C_INITIALIZE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_Initialize(pInitArgs);
-    nssdbg_finish_time(FUNC_C_INITIALIZE,start);
+    nssdbg_finish_time(&counter_C_Initialize,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_Finalize = 0;
+static PRInt32 calls_C_Finalize = 0;
 CK_RV NSSDBGC_Finalize(
   CK_VOID_PTR pReserved
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_Finalize);
     PR_LOG(modlog, 1, ("C_Finalize"));
     PR_LOG(modlog, 3, ("  pReserved = 0x%p", pReserved));
-    nssdbg_start_time(FUNC_C_FINALIZE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_Finalize(pReserved);
-    nssdbg_finish_time(FUNC_C_FINALIZE,start);
+    nssdbg_finish_time(&counter_C_Finalize,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetInfo = 0;
+static PRInt32 calls_C_GetInfo = 0;
 CK_RV NSSDBGC_GetInfo(
   CK_INFO_PTR pInfo
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetInfo);
     PR_LOG(modlog, 1, ("C_GetInfo"));
     PR_LOG(modlog, 3, ("  pInfo = 0x%p", pInfo));
-    nssdbg_start_time(FUNC_C_GETINFO,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetInfo(pInfo);
-    nssdbg_finish_time(FUNC_C_GETINFO,start);
+    nssdbg_finish_time(&counter_C_GetInfo,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetFunctionList = 0;
+static PRInt32 calls_C_GetFunctionList = 0;
 CK_RV NSSDBGC_GetFunctionList(
   CK_FUNCTION_LIST_PTR_PTR ppFunctionList
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetFunctionList);
     PR_LOG(modlog, 1, ("C_GetFunctionList"));
     PR_LOG(modlog, 3, ("  ppFunctionList = 0x%p", ppFunctionList));
-    nssdbg_start_time(FUNC_C_GETFUNCITONLIST,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetFunctionList(ppFunctionList);
-    nssdbg_finish_time(FUNC_C_GETFUNCITONLIST,start);
+    nssdbg_finish_time(&counter_C_GetFunctionList,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetSlotList = 0;
+static PRInt32 calls_C_GetSlotList = 0;
 CK_RV NSSDBGC_GetSlotList(
   CK_BBOOL       tokenPresent,
   CK_SLOT_ID_PTR pSlotList,
   CK_ULONG_PTR   pulCount
 )
 {
     CK_RV rv;
     PRIntervalTime start;
     CK_ULONG i;
+    PR_AtomicIncrement(&calls_C_GetSlotList);
     PR_LOG(modlog, 1, ("C_GetSlotList"));
     PR_LOG(modlog, 3, ("  tokenPresent = 0x%x", tokenPresent));
     PR_LOG(modlog, 3, ("  pSlotList = 0x%p", pSlotList));
     PR_LOG(modlog, 3, ("  pulCount = 0x%p", pulCount));
-    nssdbg_start_time(FUNC_C_GETSLOTLIST,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetSlotList(tokenPresent,
                                  pSlotList,
                                  pulCount);
-    nssdbg_finish_time(FUNC_C_GETSLOTLIST,start);
+    nssdbg_finish_time(&counter_C_GetSlotList,start);
     PR_LOG(modlog, 4, ("  *pulCount = 0x%x", *pulCount));
     if (pSlotList) {
 	for (i=0; i<*pulCount; i++) {
 	    PR_LOG(modlog, 4, ("  slotID[%d] = %x", i, pSlotList[i]));
 	}
     }
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetSlotInfo = 0;
+static PRInt32 calls_C_GetSlotInfo = 0;
 CK_RV NSSDBGC_GetSlotInfo(
   CK_SLOT_ID       slotID,
   CK_SLOT_INFO_PTR pInfo
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetSlotInfo);
     PR_LOG(modlog, 1, ("C_GetSlotInfo"));
     PR_LOG(modlog, 3, ("  slotID = 0x%x", slotID));
     PR_LOG(modlog, 3, ("  pInfo = 0x%p", pInfo));
-    nssdbg_start_time(FUNC_C_GETSLOTINFO,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetSlotInfo(slotID,
                                  pInfo);
-    nssdbg_finish_time(FUNC_C_GETSLOTINFO,start);
+    nssdbg_finish_time(&counter_C_GetSlotInfo,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetTokenInfo = 0;
+static PRInt32 calls_C_GetTokenInfo = 0;
 CK_RV NSSDBGC_GetTokenInfo(
   CK_SLOT_ID        slotID,
   CK_TOKEN_INFO_PTR pInfo
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetTokenInfo);
     PR_LOG(modlog, 1, ("C_GetTokenInfo"));
     PR_LOG(modlog, 3, ("  slotID = 0x%x", slotID));
     PR_LOG(modlog, 3, ("  pInfo = 0x%p", pInfo));
-    nssdbg_start_time(FUNC_C_GETTOKENINFO,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetTokenInfo(slotID,
                                  pInfo);
-    nssdbg_finish_time(FUNC_C_GETTOKENINFO,start);
+    nssdbg_finish_time(&counter_C_GetTokenInfo,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetMechanismList = 0;
+static PRInt32 calls_C_GetMechanismList = 0;
 CK_RV NSSDBGC_GetMechanismList(
   CK_SLOT_ID            slotID,
   CK_MECHANISM_TYPE_PTR pMechanismList,
   CK_ULONG_PTR          pulCount
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetMechanismList);
     PR_LOG(modlog, 1, ("C_GetMechanismList"));
     PR_LOG(modlog, 3, ("  slotID = 0x%x", slotID));
     PR_LOG(modlog, 3, ("  pMechanismList = 0x%p", pMechanismList));
     PR_LOG(modlog, 3, ("  pulCount = 0x%p", pulCount));
-    nssdbg_start_time(FUNC_C_GETMECHANISMLIST,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetMechanismList(slotID,
                                  pMechanismList,
                                  pulCount);
-    nssdbg_finish_time(FUNC_C_GETMECHANISMLIST,start);
+    nssdbg_finish_time(&counter_C_GetMechanismList,start);
     PR_LOG(modlog, 4, ("  *pulCount = 0x%x", *pulCount));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetMechanismInfo = 0;
+static PRInt32 calls_C_GetMechanismInfo = 0;
 CK_RV NSSDBGC_GetMechanismInfo(
   CK_SLOT_ID            slotID,
   CK_MECHANISM_TYPE     type,
   CK_MECHANISM_INFO_PTR pInfo
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetMechanismInfo);
     PR_LOG(modlog, 1, ("C_GetMechanismInfo"));
     PR_LOG(modlog, 3, ("  slotID = 0x%x", slotID));
     PR_LOG(modlog, 3, ("  type = 0x%x", type));
     PR_LOG(modlog, 3, ("  pInfo = 0x%p", pInfo));
-    nssdbg_start_time(FUNC_C_GETMECHANISMINFO,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetMechanismInfo(slotID,
                                  type,
                                  pInfo);
-    nssdbg_finish_time(FUNC_C_GETMECHANISMINFO,start);
+    nssdbg_finish_time(&counter_C_GetMechanismInfo,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_InitToken = 0;
+static PRInt32 calls_C_InitToken = 0;
 CK_RV NSSDBGC_InitToken(
   CK_SLOT_ID  slotID,
   CK_CHAR_PTR pPin,
   CK_ULONG    ulPinLen,
   CK_CHAR_PTR pLabel
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_InitToken);
     PR_LOG(modlog, 1, ("C_InitToken"));
     PR_LOG(modlog, 3, ("  slotID = 0x%x", slotID));
     PR_LOG(modlog, 3, ("  pPin = 0x%p", pPin));
     PR_LOG(modlog, 3, ("  ulPinLen = %d", ulPinLen));
     PR_LOG(modlog, 3, ("  pLabel = 0x%p", pLabel));
-    nssdbg_start_time(FUNC_C_INITTOKEN,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_InitToken(slotID,
                                  pPin,
                                  ulPinLen,
                                  pLabel);
-    nssdbg_finish_time(FUNC_C_INITTOKEN,start);
+    nssdbg_finish_time(&counter_C_InitToken,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_InitPIN = 0;
+static PRInt32 calls_C_InitPIN = 0;
 CK_RV NSSDBGC_InitPIN(
   CK_SESSION_HANDLE hSession,
   CK_CHAR_PTR       pPin,
   CK_ULONG          ulPinLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_InitPIN);
     PR_LOG(modlog, 1, ("C_InitPIN"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pPin = 0x%p", pPin));
     PR_LOG(modlog, 3, ("  ulPinLen = %d", ulPinLen));
-    nssdbg_start_time(FUNC_C_INITPIN,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_InitPIN(hSession,
                                  pPin,
                                  ulPinLen);
-    nssdbg_finish_time(FUNC_C_INITPIN,start);
+    nssdbg_finish_time(&counter_C_InitPIN,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SetPIN = 0;
+static PRInt32 calls_C_SetPIN = 0;
 CK_RV NSSDBGC_SetPIN(
   CK_SESSION_HANDLE hSession,
   CK_CHAR_PTR       pOldPin,
   CK_ULONG          ulOldLen,
   CK_CHAR_PTR       pNewPin,
   CK_ULONG          ulNewLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SetPIN);
     PR_LOG(modlog, 1, ("C_SetPIN"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pOldPin = 0x%p", pOldPin));
     PR_LOG(modlog, 3, ("  ulOldLen = %d", ulOldLen));
     PR_LOG(modlog, 3, ("  pNewPin = 0x%p", pNewPin));
     PR_LOG(modlog, 3, ("  ulNewLen = %d", ulNewLen));
-    nssdbg_start_time(FUNC_C_SETPIN,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SetPIN(hSession,
                                  pOldPin,
                                  ulOldLen,
                                  pNewPin,
                                  ulNewLen);
-    nssdbg_finish_time(FUNC_C_SETPIN,start);
+    nssdbg_finish_time(&counter_C_SetPIN,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
-static PRUint32 numOpenSessions = 0;
-static PRUint32 maxOpenSessions = 0;
+static PRInt32 counter_C_OpenSession = 0;
+static PRInt32 calls_C_OpenSession = 0;
+static PRInt32 numOpenSessions = 0;
+static PRInt32 maxOpenSessions = 0;
 CK_RV NSSDBGC_OpenSession(
   CK_SLOT_ID            slotID,
   CK_FLAGS              flags,
   CK_VOID_PTR           pApplication,
   CK_NOTIFY             Notify,
   CK_SESSION_HANDLE_PTR phSession
 )
 {
     CK_RV rv;
     PRIntervalTime start;
-    PR_AtomicIncrement((PRInt32 *)&numOpenSessions);
+    PR_AtomicIncrement(&calls_C_OpenSession);
+    PR_AtomicIncrement(&numOpenSessions);
     maxOpenSessions = PR_MAX(numOpenSessions, maxOpenSessions);
     PR_LOG(modlog, 1, ("C_OpenSession"));
     PR_LOG(modlog, 3, ("  slotID = 0x%x", slotID));
     PR_LOG(modlog, 3, ("  flags = 0x%x", flags));
     PR_LOG(modlog, 3, ("  pApplication = 0x%p", pApplication));
     PR_LOG(modlog, 3, ("  Notify = 0x%x", Notify));
     PR_LOG(modlog, 3, ("  phSession = 0x%p", phSession));
-    nssdbg_start_time(FUNC_C_OPENSESSION,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_OpenSession(slotID,
                                  flags,
                                  pApplication,
                                  Notify,
                                  phSession);
-    nssdbg_finish_time(FUNC_C_OPENSESSION,start);
+    nssdbg_finish_time(&counter_C_OpenSession,start);
     PR_LOG(modlog, 4, ("  *phSession = 0x%x", *phSession));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_CloseSession = 0;
+static PRInt32 calls_C_CloseSession = 0;
 CK_RV NSSDBGC_CloseSession(
   CK_SESSION_HANDLE hSession
 )
 {
     CK_RV rv;
     PRIntervalTime start;
-    PR_AtomicDecrement((PRInt32 *)&numOpenSessions);
+    PR_AtomicIncrement(&calls_C_CloseSession);
+    PR_AtomicDecrement(&numOpenSessions);
     PR_LOG(modlog, 1, ("C_CloseSession"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
-    nssdbg_start_time(FUNC_C_CLOSESESSION,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_CloseSession(hSession);
-    nssdbg_finish_time(FUNC_C_CLOSESESSION,start);
+    nssdbg_finish_time(&counter_C_CloseSession,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_CloseAllSessions = 0;
+static PRInt32 calls_C_CloseAllSessions = 0;
 CK_RV NSSDBGC_CloseAllSessions(
   CK_SLOT_ID slotID
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_CloseAllSessions);
     PR_LOG(modlog, 1, ("C_CloseAllSessions"));
     PR_LOG(modlog, 3, ("  slotID = 0x%x", slotID));
-    nssdbg_start_time(FUNC_C_CLOSEALLSESSIONS,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_CloseAllSessions(slotID);
-    nssdbg_finish_time(FUNC_C_CLOSEALLSESSIONS,start);
+    nssdbg_finish_time(&counter_C_CloseAllSessions,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetSessionInfo = 0;
+static PRInt32 calls_C_GetSessionInfo = 0;
 CK_RV NSSDBGC_GetSessionInfo(
   CK_SESSION_HANDLE   hSession,
   CK_SESSION_INFO_PTR pInfo
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetSessionInfo);
     PR_LOG(modlog, 1, ("C_GetSessionInfo"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pInfo = 0x%p", pInfo));
-    nssdbg_start_time(FUNC_C_GETSESSIONINFO,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetSessionInfo(hSession,
                                  pInfo);
-    nssdbg_finish_time(FUNC_C_GETSESSIONINFO,start);
+    nssdbg_finish_time(&counter_C_GetSessionInfo,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetOperationState = 0;
+static PRInt32 calls_C_GetOperationState = 0;
 CK_RV NSSDBGC_GetOperationState(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pOperationState,
   CK_ULONG_PTR      pulOperationStateLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetOperationState);
     PR_LOG(modlog, 1, ("C_GetOperationState"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pOperationState = 0x%p", pOperationState));
     PR_LOG(modlog, 3, ("  pulOperationStateLen = 0x%p", pulOperationStateLen));
-    nssdbg_start_time(FUNC_C_GETOPERATIONSTATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetOperationState(hSession,
                                  pOperationState,
                                  pulOperationStateLen);
-    nssdbg_finish_time(FUNC_C_GETOPERATIONSTATE,start);
+    nssdbg_finish_time(&counter_C_GetOperationState,start);
     PR_LOG(modlog, 4, ("  *pulOperationStateLen = 0x%x", *pulOperationStateLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SetOperationState = 0;
+static PRInt32 calls_C_SetOperationState = 0;
 CK_RV NSSDBGC_SetOperationState(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR      pOperationState,
   CK_ULONG         ulOperationStateLen,
   CK_OBJECT_HANDLE hEncryptionKey,
   CK_OBJECT_HANDLE hAuthenticationKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SetOperationState);
     PR_LOG(modlog, 1, ("C_SetOperationState"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pOperationState = 0x%p", pOperationState));
     PR_LOG(modlog, 3, ("  ulOperationStateLen = %d", ulOperationStateLen));
     PR_LOG(modlog, 3, ("  hEncryptionKey = 0x%x", hEncryptionKey));
     PR_LOG(modlog, 3, ("  hAuthenticationKey = 0x%x", hAuthenticationKey));
-    nssdbg_start_time(FUNC_C_SETOPERATIONSTATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SetOperationState(hSession,
                                  pOperationState,
                                  ulOperationStateLen,
                                  hEncryptionKey,
                                  hAuthenticationKey);
-    nssdbg_finish_time(FUNC_C_SETOPERATIONSTATE,start);
+    nssdbg_finish_time(&counter_C_SetOperationState,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_Login = 0;
+static PRInt32 calls_C_Login = 0;
 CK_RV NSSDBGC_Login(
   CK_SESSION_HANDLE hSession,
   CK_USER_TYPE      userType,
   CK_CHAR_PTR       pPin,
   CK_ULONG          ulPinLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_Login);
     PR_LOG(modlog, 1, ("C_Login"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  userType = 0x%x", userType));
     PR_LOG(modlog, 3, ("  pPin = 0x%p", pPin));
     PR_LOG(modlog, 3, ("  ulPinLen = %d", ulPinLen));
-    nssdbg_start_time(FUNC_C_LOGIN,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_Login(hSession,
                                  userType,
                                  pPin,
                                  ulPinLen);
-    nssdbg_finish_time(FUNC_C_LOGIN,start);
+    nssdbg_finish_time(&counter_C_Login,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_Logout = 0;
+static PRInt32 calls_C_Logout = 0;
 CK_RV NSSDBGC_Logout(
   CK_SESSION_HANDLE hSession
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_Logout);
     PR_LOG(modlog, 1, ("C_Logout"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
-    nssdbg_start_time(FUNC_C_LOGOUT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_Logout(hSession);
-    nssdbg_finish_time(FUNC_C_LOGOUT,start);
+    nssdbg_finish_time(&counter_C_Logout,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_CreateObject = 0;
+static PRInt32 calls_C_CreateObject = 0;
 CK_RV NSSDBGC_CreateObject(
   CK_SESSION_HANDLE    hSession,
   CK_ATTRIBUTE_PTR     pTemplate,
   CK_ULONG             ulCount,
   CK_OBJECT_HANDLE_PTR phObject
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_CreateObject);
     PR_LOG(modlog, 1, ("C_CreateObject"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pTemplate = 0x%p", pTemplate));
     PR_LOG(modlog, 3, ("  ulCount = %d", ulCount));
     PR_LOG(modlog, 3, ("  phObject = 0x%p", phObject));
     print_template(pTemplate, ulCount);
-    nssdbg_start_time(FUNC_C_CREATEOBJECT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_CreateObject(hSession,
                                  pTemplate,
                                  ulCount,
                                  phObject);
-    nssdbg_finish_time(FUNC_C_CREATEOBJECT,start);
+    nssdbg_finish_time(&counter_C_CreateObject,start);
     PR_LOG(modlog, 4, ("  *phObject = 0x%x", *phObject));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_CopyObject = 0;
+static PRInt32 calls_C_CopyObject = 0;
 CK_RV NSSDBGC_CopyObject(
   CK_SESSION_HANDLE    hSession,
   CK_OBJECT_HANDLE     hObject,
   CK_ATTRIBUTE_PTR     pTemplate,
   CK_ULONG             ulCount,
   CK_OBJECT_HANDLE_PTR phNewObject
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_CopyObject);
     PR_LOG(modlog, 1, ("C_CopyObject"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  hObject = 0x%x", hObject));
     PR_LOG(modlog, 3, ("  pTemplate = 0x%p", pTemplate));
     PR_LOG(modlog, 3, ("  ulCount = %d", ulCount));
     PR_LOG(modlog, 3, ("  phNewObject = 0x%p", phNewObject));
     print_template(pTemplate, ulCount);
-    nssdbg_start_time(FUNC_C_COPYOBJECT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_CopyObject(hSession,
                                  hObject,
                                  pTemplate,
                                  ulCount,
                                  phNewObject);
-    nssdbg_finish_time(FUNC_C_COPYOBJECT,start);
+    nssdbg_finish_time(&counter_C_CopyObject,start);
     PR_LOG(modlog, 4, ("  *phNewObject = 0x%x", *phNewObject));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DestroyObject = 0;
+static PRInt32 calls_C_DestroyObject = 0;
 CK_RV NSSDBGC_DestroyObject(
   CK_SESSION_HANDLE hSession,
   CK_OBJECT_HANDLE  hObject
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DestroyObject);
     PR_LOG(modlog, 1, ("C_DestroyObject"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  hObject = 0x%x", hObject));
-    nssdbg_start_time(FUNC_C_DESTROYOBJECT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DestroyObject(hSession,
                                  hObject);
-    nssdbg_finish_time(FUNC_C_DESTROYOBJECT,start);
+    nssdbg_finish_time(&counter_C_DestroyObject,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetObjectSize = 0;
+static PRInt32 calls_C_GetObjectSize = 0;
 CK_RV NSSDBGC_GetObjectSize(
   CK_SESSION_HANDLE hSession,
   CK_OBJECT_HANDLE  hObject,
   CK_ULONG_PTR      pulSize
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetObjectSize);
     PR_LOG(modlog, 1, ("C_GetObjectSize"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  hObject = 0x%x", hObject));
     PR_LOG(modlog, 3, ("  pulSize = 0x%p", pulSize));
-    nssdbg_start_time(FUNC_C_GETOBJECTSIZE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetObjectSize(hSession,
                                  hObject,
                                  pulSize);
-    nssdbg_finish_time(FUNC_C_GETOBJECTSIZE,start);
+    nssdbg_finish_time(&counter_C_GetObjectSize,start);
     PR_LOG(modlog, 4, ("  *pulSize = 0x%x", *pulSize));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetAttributeValue = 0;
+static PRInt32 calls_C_GetAttributeValue = 0;
 CK_RV NSSDBGC_GetAttributeValue(
   CK_SESSION_HANDLE hSession,
   CK_OBJECT_HANDLE  hObject,
   CK_ATTRIBUTE_PTR  pTemplate,
   CK_ULONG          ulCount
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetAttributeValue);
     PR_LOG(modlog, 1, ("C_GetAttributeValue"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  hObject = 0x%x", hObject));
     PR_LOG(modlog, 3, ("  pTemplate = 0x%p", pTemplate));
     PR_LOG(modlog, 3, ("  ulCount = %d", ulCount));
-    nssdbg_start_time(FUNC_C_GETATTRIBUTEVALUE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetAttributeValue(hSession,
                                  hObject,
                                  pTemplate,
                                  ulCount);
-    nssdbg_finish_time(FUNC_C_GETATTRIBUTEVALUE,start);
+    nssdbg_finish_time(&counter_C_GetAttributeValue,start);
     print_template(pTemplate, ulCount);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SetAttributeValue = 0;
+static PRInt32 calls_C_SetAttributeValue = 0;
 CK_RV NSSDBGC_SetAttributeValue(
   CK_SESSION_HANDLE hSession,
   CK_OBJECT_HANDLE  hObject,
   CK_ATTRIBUTE_PTR  pTemplate,
   CK_ULONG          ulCount
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SetAttributeValue);
     PR_LOG(modlog, 1, ("C_SetAttributeValue"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  hObject = 0x%x", hObject));
     PR_LOG(modlog, 3, ("  pTemplate = 0x%p", pTemplate));
     PR_LOG(modlog, 3, ("  ulCount = %d", ulCount));
     print_template(pTemplate, ulCount);
-    nssdbg_start_time(FUNC_C_SETATTRIBUTEVALUE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SetAttributeValue(hSession,
                                  hObject,
                                  pTemplate,
                                  ulCount);
-    nssdbg_finish_time(FUNC_C_SETATTRIBUTEVALUE,start);
+    nssdbg_finish_time(&counter_C_SetAttributeValue,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_FindObjectsInit = 0;
+static PRInt32 calls_C_FindObjectsInit = 0;
 CK_RV NSSDBGC_FindObjectsInit(
   CK_SESSION_HANDLE hSession,
   CK_ATTRIBUTE_PTR  pTemplate,
   CK_ULONG          ulCount
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_FindObjectsInit);
     PR_LOG(modlog, 1, ("C_FindObjectsInit"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pTemplate = 0x%p", pTemplate));
     PR_LOG(modlog, 3, ("  ulCount = %d", ulCount));
     print_template(pTemplate, ulCount);
-    nssdbg_start_time(FUNC_C_FINDOBJECTSINIT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_FindObjectsInit(hSession,
                                  pTemplate,
                                  ulCount);
-    nssdbg_finish_time(FUNC_C_FINDOBJECTSINIT,start);
+    nssdbg_finish_time(&counter_C_FindObjectsInit,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_FindObjects = 0;
+static PRInt32 calls_C_FindObjects = 0;
 CK_RV NSSDBGC_FindObjects(
   CK_SESSION_HANDLE    hSession,
   CK_OBJECT_HANDLE_PTR phObject,
   CK_ULONG             ulMaxObjectCount,
   CK_ULONG_PTR         pulObjectCount
 )
 {
     CK_RV rv;
     CK_ULONG i;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_FindObjects);
     PR_LOG(modlog, 1, ("C_FindObjects"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  phObject = 0x%p", phObject));
     PR_LOG(modlog, 3, ("  ulMaxObjectCount = %d", ulMaxObjectCount));
     PR_LOG(modlog, 3, ("  pulObjectCount = 0x%p", pulObjectCount));
-    nssdbg_start_time(FUNC_C_FINDOBJECTS,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_FindObjects(hSession,
                                  phObject,
                                  ulMaxObjectCount,
                                  pulObjectCount);
-    nssdbg_finish_time(FUNC_C_FINDOBJECTS,start);
+    nssdbg_finish_time(&counter_C_FindObjects,start);
     PR_LOG(modlog, 4, ("  *pulObjectCount = 0x%x", *pulObjectCount));
     for (i=0; i<*pulObjectCount; i++) {
 	PR_LOG(modlog, 4, ("  phObject[%d] = 0x%x", i, phObject[i]));
     }
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_FindObjectsFinal = 0;
+static PRInt32 calls_C_FindObjectsFinal = 0;
 CK_RV NSSDBGC_FindObjectsFinal(
   CK_SESSION_HANDLE hSession
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_FindObjectsFinal);
     PR_LOG(modlog, 1, ("C_FindObjectsFinal"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
-    nssdbg_start_time(FUNC_C_FINDOBJECTSFINAL,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_FindObjectsFinal(hSession);
-    nssdbg_finish_time(FUNC_C_FINDOBJECTSFINAL,start);
+    nssdbg_finish_time(&counter_C_FindObjectsFinal,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_EncryptInit = 0;
+static PRInt32 calls_C_EncryptInit = 0;
 CK_RV NSSDBGC_EncryptInit(
   CK_SESSION_HANDLE hSession,
   CK_MECHANISM_PTR  pMechanism,
   CK_OBJECT_HANDLE  hKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_EncryptInit);
     PR_LOG(modlog, 1, ("C_EncryptInit"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  hKey = 0x%x", hKey));
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_ENCRYPTINIT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_EncryptInit(hSession,
                                  pMechanism,
                                  hKey);
-    nssdbg_finish_time(FUNC_C_ENCRYPTINIT,start);
+    nssdbg_finish_time(&counter_C_EncryptInit,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_Encrypt = 0;
+static PRInt32 calls_C_Encrypt = 0;
 CK_RV NSSDBGC_Encrypt(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pData,
   CK_ULONG          ulDataLen,
   CK_BYTE_PTR       pEncryptedData,
   CK_ULONG_PTR      pulEncryptedDataLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_Encrypt);
     PR_LOG(modlog, 1, ("C_Encrypt"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pData = 0x%p", pData));
     PR_LOG(modlog, 3, ("  ulDataLen = %d", ulDataLen));
     PR_LOG(modlog, 3, ("  pEncryptedData = 0x%p", pEncryptedData));
     PR_LOG(modlog, 3, ("  pulEncryptedDataLen = 0x%p", pulEncryptedDataLen));
-    nssdbg_start_time(FUNC_C_ENCRYPT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_Encrypt(hSession,
                                  pData,
                                  ulDataLen,
                                  pEncryptedData,
                                  pulEncryptedDataLen);
-    nssdbg_finish_time(FUNC_C_ENCRYPT,start);
+    nssdbg_finish_time(&counter_C_Encrypt,start);
     PR_LOG(modlog, 4, ("  *pulEncryptedDataLen = 0x%x", *pulEncryptedDataLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_EncryptUpdate = 0;
+static PRInt32 calls_C_EncryptUpdate = 0;
 CK_RV NSSDBGC_EncryptUpdate(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pPart,
   CK_ULONG          ulPartLen,
   CK_BYTE_PTR       pEncryptedPart,
   CK_ULONG_PTR      pulEncryptedPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_EncryptUpdate);
     PR_LOG(modlog, 1, ("C_EncryptUpdate"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pPart = 0x%p", pPart));
     PR_LOG(modlog, 3, ("  ulPartLen = %d", ulPartLen));
     PR_LOG(modlog, 3, ("  pEncryptedPart = 0x%p", pEncryptedPart));
     PR_LOG(modlog, 3, ("  pulEncryptedPartLen = 0x%p", pulEncryptedPartLen));
-    nssdbg_start_time(FUNC_C_ENCRYPTUPDATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_EncryptUpdate(hSession,
                                  pPart,
                                  ulPartLen,
                                  pEncryptedPart,
                                  pulEncryptedPartLen);
-    nssdbg_finish_time(FUNC_C_ENCRYPTUPDATE,start);
+    nssdbg_finish_time(&counter_C_EncryptUpdate,start);
     PR_LOG(modlog, 4, ("  *pulEncryptedPartLen = 0x%x", *pulEncryptedPartLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_EncryptFinal = 0;
+static PRInt32 calls_C_EncryptFinal = 0;
 CK_RV NSSDBGC_EncryptFinal(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pLastEncryptedPart,
   CK_ULONG_PTR      pulLastEncryptedPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_EncryptFinal);
     PR_LOG(modlog, 1, ("C_EncryptFinal"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pLastEncryptedPart = 0x%p", pLastEncryptedPart));
     PR_LOG(modlog, 3, ("  pulLastEncryptedPartLen = 0x%p", pulLastEncryptedPartLen));
-    nssdbg_start_time(FUNC_C_ENCRYPTFINAL,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_EncryptFinal(hSession,
                                  pLastEncryptedPart,
                                  pulLastEncryptedPartLen);
-    nssdbg_finish_time(FUNC_C_ENCRYPTFINAL,start);
+    nssdbg_finish_time(&counter_C_EncryptFinal,start);
     PR_LOG(modlog, 4, ("  *pulLastEncryptedPartLen = 0x%x", *pulLastEncryptedPartLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DecryptInit = 0;
+static PRInt32 calls_C_DecryptInit = 0;
 CK_RV NSSDBGC_DecryptInit(
   CK_SESSION_HANDLE hSession,
   CK_MECHANISM_PTR  pMechanism,
   CK_OBJECT_HANDLE  hKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DecryptInit);
     PR_LOG(modlog, 1, ("C_DecryptInit"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  hKey = 0x%x", hKey));
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_DECRYPTINIT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DecryptInit(hSession,
                                  pMechanism,
                                  hKey);
-    nssdbg_finish_time(FUNC_C_DECRYPTINIT,start);
+    nssdbg_finish_time(&counter_C_DecryptInit,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_Decrypt = 0;
+static PRInt32 calls_C_Decrypt = 0;
 CK_RV NSSDBGC_Decrypt(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pEncryptedData,
   CK_ULONG          ulEncryptedDataLen,
   CK_BYTE_PTR       pData,
   CK_ULONG_PTR      pulDataLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_Decrypt);
     PR_LOG(modlog, 1, ("C_Decrypt"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pEncryptedData = 0x%p", pEncryptedData));
     PR_LOG(modlog, 3, ("  ulEncryptedDataLen = %d", ulEncryptedDataLen));
     PR_LOG(modlog, 3, ("  pData = 0x%p", pData));
     PR_LOG(modlog, 3, ("  pulDataLen = 0x%p", pulDataLen));
-    nssdbg_start_time(FUNC_C_DECRYPT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_Decrypt(hSession,
                                  pEncryptedData,
                                  ulEncryptedDataLen,
                                  pData,
                                  pulDataLen);
-    nssdbg_finish_time(FUNC_C_DECRYPT,start);
+    nssdbg_finish_time(&counter_C_Decrypt,start);
     PR_LOG(modlog, 4, ("  *pulDataLen = 0x%x", *pulDataLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DecryptUpdate = 0;
+static PRInt32 calls_C_DecryptUpdate = 0;
 CK_RV NSSDBGC_DecryptUpdate(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pEncryptedPart,
   CK_ULONG          ulEncryptedPartLen,
   CK_BYTE_PTR       pPart,
   CK_ULONG_PTR      pulPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DecryptUpdate);
     PR_LOG(modlog, 1, ("C_DecryptUpdate"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pEncryptedPart = 0x%p", pEncryptedPart));
     PR_LOG(modlog, 3, ("  ulEncryptedPartLen = %d", ulEncryptedPartLen));
     PR_LOG(modlog, 3, ("  pPart = 0x%p", pPart));
     PR_LOG(modlog, 3, ("  pulPartLen = 0x%p", pulPartLen));
-    nssdbg_start_time(FUNC_C_DECRYPTUPDATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DecryptUpdate(hSession,
                                  pEncryptedPart,
                                  ulEncryptedPartLen,
                                  pPart,
                                  pulPartLen);
-    nssdbg_finish_time(FUNC_C_DECRYPTUPDATE,start);
+    nssdbg_finish_time(&counter_C_DecryptUpdate,start);
     PR_LOG(modlog, 4, ("  *pulPartLen = 0x%x", *pulPartLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DecryptFinal = 0;
+static PRInt32 calls_C_DecryptFinal = 0;
 CK_RV NSSDBGC_DecryptFinal(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pLastPart,
   CK_ULONG_PTR      pulLastPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DecryptFinal);
     PR_LOG(modlog, 1, ("C_DecryptFinal"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pLastPart = 0x%p", pLastPart));
     PR_LOG(modlog, 3, ("  pulLastPartLen = 0x%p", pulLastPartLen));
-    nssdbg_start_time(FUNC_C_DECRYPTFINAL,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DecryptFinal(hSession,
                                  pLastPart,
                                  pulLastPartLen);
-    nssdbg_finish_time(FUNC_C_DECRYPTFINAL,start);
+    nssdbg_finish_time(&counter_C_DecryptFinal,start);
     PR_LOG(modlog, 4, ("  *pulLastPartLen = 0x%x", *pulLastPartLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DigestInit = 0;
+static PRInt32 calls_C_DigestInit = 0;
 CK_RV NSSDBGC_DigestInit(
   CK_SESSION_HANDLE hSession,
   CK_MECHANISM_PTR  pMechanism
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DigestInit);
     PR_LOG(modlog, 1, ("C_DigestInit"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_DIGESTINIT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DigestInit(hSession,
                                  pMechanism);
-    nssdbg_finish_time(FUNC_C_DIGESTINIT,start);
+    nssdbg_finish_time(&counter_C_DigestInit,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_Digest = 0;
+static PRInt32 calls_C_Digest = 0;
 CK_RV NSSDBGC_Digest(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pData,
   CK_ULONG          ulDataLen,
   CK_BYTE_PTR       pDigest,
   CK_ULONG_PTR      pulDigestLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_Digest);
     PR_LOG(modlog, 1, ("C_Digest"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pData = 0x%p", pData));
     PR_LOG(modlog, 3, ("  ulDataLen = %d", ulDataLen));
     PR_LOG(modlog, 3, ("  pDigest = 0x%p", pDigest));
     PR_LOG(modlog, 3, ("  pulDigestLen = 0x%p", pulDigestLen));
-    nssdbg_start_time(FUNC_C_DIGEST,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_Digest(hSession,
                                  pData,
                                  ulDataLen,
                                  pDigest,
                                  pulDigestLen);
-    nssdbg_finish_time(FUNC_C_DIGEST,start);
+    nssdbg_finish_time(&counter_C_Digest,start);
     PR_LOG(modlog, 4, ("  *pulDigestLen = 0x%x", *pulDigestLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DigestUpdate = 0;
+static PRInt32 calls_C_DigestUpdate = 0;
 CK_RV NSSDBGC_DigestUpdate(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pPart,
   CK_ULONG          ulPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DigestUpdate);
     PR_LOG(modlog, 1, ("C_DigestUpdate"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pPart = 0x%p", pPart));
     PR_LOG(modlog, 3, ("  ulPartLen = %d", ulPartLen));
-    nssdbg_start_time(FUNC_C_DIGESTUPDATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DigestUpdate(hSession,
                                  pPart,
                                  ulPartLen);
-    nssdbg_finish_time(FUNC_C_DIGESTUPDATE,start);
+    nssdbg_finish_time(&counter_C_DigestUpdate,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DigestKey = 0;
+static PRInt32 calls_C_DigestKey = 0;
 CK_RV NSSDBGC_DigestKey(
   CK_SESSION_HANDLE hSession,
   CK_OBJECT_HANDLE  hKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DigestKey);
     PR_LOG(modlog, 1, ("C_DigestKey"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
-    nssdbg_start_time(FUNC_C_DIGESTKEY,&start);
+    PR_LOG(modlog, 3, ("  hKey = 0x%x", hKey));
+    start = PR_IntervalNow();
     rv = module_functions->C_DigestKey(hSession,
                                  hKey);
-    nssdbg_finish_time(FUNC_C_DIGESTKEY,start);
+    nssdbg_finish_time(&counter_C_DigestKey,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DigestFinal = 0;
+static PRInt32 calls_C_DigestFinal = 0;
 CK_RV NSSDBGC_DigestFinal(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pDigest,
   CK_ULONG_PTR      pulDigestLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DigestFinal);
     PR_LOG(modlog, 1, ("C_DigestFinal"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pDigest = 0x%p", pDigest));
     PR_LOG(modlog, 3, ("  pulDigestLen = 0x%p", pulDigestLen));
-    nssdbg_start_time(FUNC_C_DIGESTFINAL,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DigestFinal(hSession,
                                  pDigest,
                                  pulDigestLen);
-    nssdbg_finish_time(FUNC_C_DIGESTFINAL,start);
+    nssdbg_finish_time(&counter_C_DigestFinal,start);
     PR_LOG(modlog, 4, ("  *pulDigestLen = 0x%x", *pulDigestLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SignInit = 0;
+static PRInt32 calls_C_SignInit = 0;
 CK_RV NSSDBGC_SignInit(
   CK_SESSION_HANDLE hSession,
   CK_MECHANISM_PTR  pMechanism,
   CK_OBJECT_HANDLE  hKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SignInit);
     PR_LOG(modlog, 1, ("C_SignInit"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  hKey = 0x%x", hKey));
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_SIGNINIT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SignInit(hSession,
                                  pMechanism,
                                  hKey);
-    nssdbg_finish_time(FUNC_C_SIGNINIT,start);
+    nssdbg_finish_time(&counter_C_SignInit,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_Sign = 0;
+static PRInt32 calls_C_Sign = 0;
 CK_RV NSSDBGC_Sign(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pData,
   CK_ULONG          ulDataLen,
   CK_BYTE_PTR       pSignature,
   CK_ULONG_PTR      pulSignatureLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_Sign);
     PR_LOG(modlog, 1, ("C_Sign"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pData = 0x%p", pData));
     PR_LOG(modlog, 3, ("  ulDataLen = %d", ulDataLen));
     PR_LOG(modlog, 3, ("  pSignature = 0x%p", pSignature));
     PR_LOG(modlog, 3, ("  pulSignatureLen = 0x%p", pulSignatureLen));
-    nssdbg_start_time(FUNC_C_SIGN,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_Sign(hSession,
                                  pData,
                                  ulDataLen,
                                  pSignature,
                                  pulSignatureLen);
-    nssdbg_finish_time(FUNC_C_SIGN,start);
+    nssdbg_finish_time(&counter_C_Sign,start);
     PR_LOG(modlog, 4, ("  *pulSignatureLen = 0x%x", *pulSignatureLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SignUpdate = 0;
+static PRInt32 calls_C_SignUpdate = 0;
 CK_RV NSSDBGC_SignUpdate(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pPart,
   CK_ULONG          ulPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SignUpdate);
     PR_LOG(modlog, 1, ("C_SignUpdate"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pPart = 0x%p", pPart));
     PR_LOG(modlog, 3, ("  ulPartLen = %d", ulPartLen));
-    nssdbg_start_time(FUNC_C_SIGNUPDATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SignUpdate(hSession,
                                  pPart,
                                  ulPartLen);
-    nssdbg_finish_time(FUNC_C_SIGNUPDATE,start);
+    nssdbg_finish_time(&counter_C_SignUpdate,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SignFinal = 0;
+static PRInt32 calls_C_SignFinal = 0;
 CK_RV NSSDBGC_SignFinal(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pSignature,
   CK_ULONG_PTR      pulSignatureLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SignFinal);
     PR_LOG(modlog, 1, ("C_SignFinal"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pSignature = 0x%p", pSignature));
     PR_LOG(modlog, 3, ("  pulSignatureLen = 0x%p", pulSignatureLen));
-    nssdbg_start_time(FUNC_C_SIGNFINAL,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SignFinal(hSession,
                                  pSignature,
                                  pulSignatureLen);
-    nssdbg_finish_time(FUNC_C_SIGNFINAL,start);
+    nssdbg_finish_time(&counter_C_SignFinal,start);
     PR_LOG(modlog, 4, ("  *pulSignatureLen = 0x%x", *pulSignatureLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SignRecoverInit = 0;
+static PRInt32 calls_C_SignRecoverInit = 0;
 CK_RV NSSDBGC_SignRecoverInit(
   CK_SESSION_HANDLE hSession,
   CK_MECHANISM_PTR  pMechanism,
   CK_OBJECT_HANDLE  hKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SignRecoverInit);
     PR_LOG(modlog, 1, ("C_SignRecoverInit"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  hKey = 0x%x", hKey));
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_SIGNRECOVERINIT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SignRecoverInit(hSession,
                                  pMechanism,
                                  hKey);
-    nssdbg_finish_time(FUNC_C_SIGNRECOVERINIT,start);
+    nssdbg_finish_time(&counter_C_SignRecoverInit,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SignRecover = 0;
+static PRInt32 calls_C_SignRecover = 0;
 CK_RV NSSDBGC_SignRecover(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pData,
   CK_ULONG          ulDataLen,
   CK_BYTE_PTR       pSignature,
   CK_ULONG_PTR      pulSignatureLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SignRecover);
     PR_LOG(modlog, 1, ("C_SignRecover"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pData = 0x%p", pData));
     PR_LOG(modlog, 3, ("  ulDataLen = %d", ulDataLen));
     PR_LOG(modlog, 3, ("  pSignature = 0x%p", pSignature));
     PR_LOG(modlog, 3, ("  pulSignatureLen = 0x%p", pulSignatureLen));
-    nssdbg_start_time(FUNC_C_SIGNRECOVER,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SignRecover(hSession,
                                  pData,
                                  ulDataLen,
                                  pSignature,
                                  pulSignatureLen);
-    nssdbg_finish_time(FUNC_C_SIGNRECOVER,start);
+    nssdbg_finish_time(&counter_C_SignRecover,start);
     PR_LOG(modlog, 4, ("  *pulSignatureLen = 0x%x", *pulSignatureLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_VerifyInit = 0;
+static PRInt32 calls_C_VerifyInit = 0;
 CK_RV NSSDBGC_VerifyInit(
   CK_SESSION_HANDLE hSession,
   CK_MECHANISM_PTR  pMechanism,
   CK_OBJECT_HANDLE  hKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_VerifyInit);
     PR_LOG(modlog, 1, ("C_VerifyInit"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  hKey = 0x%x", hKey));
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_VERIFYINIT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_VerifyInit(hSession,
                                  pMechanism,
                                  hKey);
-    nssdbg_finish_time(FUNC_C_VERIFYINIT,start);
+    nssdbg_finish_time(&counter_C_VerifyInit,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_Verify = 0;
+static PRInt32 calls_C_Verify = 0;
 CK_RV NSSDBGC_Verify(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pData,
   CK_ULONG          ulDataLen,
   CK_BYTE_PTR       pSignature,
   CK_ULONG          ulSignatureLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_Verify);
     PR_LOG(modlog, 1, ("C_Verify"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pData = 0x%p", pData));
     PR_LOG(modlog, 3, ("  ulDataLen = %d", ulDataLen));
     PR_LOG(modlog, 3, ("  pSignature = 0x%p", pSignature));
     PR_LOG(modlog, 3, ("  ulSignatureLen = %d", ulSignatureLen));
-    nssdbg_start_time(FUNC_C_VERIFY,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_Verify(hSession,
                                  pData,
                                  ulDataLen,
                                  pSignature,
                                  ulSignatureLen);
-    nssdbg_finish_time(FUNC_C_VERIFY,start);
+    nssdbg_finish_time(&counter_C_Verify,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_VerifyUpdate = 0;
+static PRInt32 calls_C_VerifyUpdate = 0;
 CK_RV NSSDBGC_VerifyUpdate(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pPart,
   CK_ULONG          ulPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_VerifyUpdate);
     PR_LOG(modlog, 1, ("C_VerifyUpdate"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pPart = 0x%p", pPart));
     PR_LOG(modlog, 3, ("  ulPartLen = %d", ulPartLen));
-    nssdbg_start_time(FUNC_C_VERIFYUPDATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_VerifyUpdate(hSession,
                                  pPart,
                                  ulPartLen);
-    nssdbg_finish_time(FUNC_C_VERIFYUPDATE,start);
+    nssdbg_finish_time(&counter_C_VerifyUpdate,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_VerifyFinal = 0;
+static PRInt32 calls_C_VerifyFinal = 0;
 CK_RV NSSDBGC_VerifyFinal(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pSignature,
   CK_ULONG          ulSignatureLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_VerifyFinal);
     PR_LOG(modlog, 1, ("C_VerifyFinal"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pSignature = 0x%p", pSignature));
     PR_LOG(modlog, 3, ("  ulSignatureLen = %d", ulSignatureLen));
-    nssdbg_start_time(FUNC_C_VERIFYFINAL,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_VerifyFinal(hSession,
                                  pSignature,
                                  ulSignatureLen);
-    nssdbg_finish_time(FUNC_C_VERIFYFINAL,start);
+    nssdbg_finish_time(&counter_C_VerifyFinal,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_VerifyRecoverInit = 0;
+static PRInt32 calls_C_VerifyRecoverInit = 0;
 CK_RV NSSDBGC_VerifyRecoverInit(
   CK_SESSION_HANDLE hSession,
   CK_MECHANISM_PTR  pMechanism,
   CK_OBJECT_HANDLE  hKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_VerifyRecoverInit);
     PR_LOG(modlog, 1, ("C_VerifyRecoverInit"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  hKey = 0x%x", hKey));
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_VERIFYRECOVERINIT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_VerifyRecoverInit(hSession,
                                  pMechanism,
                                  hKey);
-    nssdbg_finish_time(FUNC_C_VERIFYRECOVERINIT,start);
+    nssdbg_finish_time(&counter_C_VerifyRecoverInit,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_VerifyRecover = 0;
+static PRInt32 calls_C_VerifyRecover = 0;
 CK_RV NSSDBGC_VerifyRecover(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pSignature,
   CK_ULONG          ulSignatureLen,
   CK_BYTE_PTR       pData,
   CK_ULONG_PTR      pulDataLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_VerifyRecover);
     PR_LOG(modlog, 1, ("C_VerifyRecover"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pSignature = 0x%p", pSignature));
     PR_LOG(modlog, 3, ("  ulSignatureLen = %d", ulSignatureLen));
     PR_LOG(modlog, 3, ("  pData = 0x%p", pData));
     PR_LOG(modlog, 3, ("  pulDataLen = 0x%p", pulDataLen));
-    nssdbg_start_time(FUNC_C_VERIFYRECOVER,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_VerifyRecover(hSession,
                                  pSignature,
                                  ulSignatureLen,
                                  pData,
                                  pulDataLen);
-    nssdbg_finish_time(FUNC_C_VERIFYRECOVER,start);
+    nssdbg_finish_time(&counter_C_VerifyRecover,start);
     PR_LOG(modlog, 4, ("  *pulDataLen = 0x%x", *pulDataLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DigestEncryptUpdate = 0;
+static PRInt32 calls_C_DigestEncryptUpdate = 0;
 CK_RV NSSDBGC_DigestEncryptUpdate(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pPart,
   CK_ULONG          ulPartLen,
   CK_BYTE_PTR       pEncryptedPart,
   CK_ULONG_PTR      pulEncryptedPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DigestEncryptUpdate);
     PR_LOG(modlog, 1, ("C_DigestEncryptUpdate"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pPart = 0x%p", pPart));
     PR_LOG(modlog, 3, ("  ulPartLen = %d", ulPartLen));
     PR_LOG(modlog, 3, ("  pEncryptedPart = 0x%p", pEncryptedPart));
     PR_LOG(modlog, 3, ("  pulEncryptedPartLen = 0x%p", pulEncryptedPartLen));
-    nssdbg_start_time(FUNC_C_DIGESTENCRYPTUPDATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DigestEncryptUpdate(hSession,
                                  pPart,
                                  ulPartLen,
                                  pEncryptedPart,
                                  pulEncryptedPartLen);
-    nssdbg_finish_time(FUNC_C_DIGESTENCRYPTUPDATE,start);
+    nssdbg_finish_time(&counter_C_DigestEncryptUpdate,start);
     PR_LOG(modlog, 4, ("  *pulEncryptedPartLen = 0x%x", *pulEncryptedPartLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DecryptDigestUpdate = 0;
+static PRInt32 calls_C_DecryptDigestUpdate = 0;
 CK_RV NSSDBGC_DecryptDigestUpdate(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pEncryptedPart,
   CK_ULONG          ulEncryptedPartLen,
   CK_BYTE_PTR       pPart,
   CK_ULONG_PTR      pulPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DecryptDigestUpdate);
     PR_LOG(modlog, 1, ("C_DecryptDigestUpdate"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pEncryptedPart = 0x%p", pEncryptedPart));
     PR_LOG(modlog, 3, ("  ulEncryptedPartLen = %d", ulEncryptedPartLen));
     PR_LOG(modlog, 3, ("  pPart = 0x%p", pPart));
     PR_LOG(modlog, 3, ("  pulPartLen = 0x%p", pulPartLen));
-    nssdbg_start_time(FUNC_C_DECRYPTDIGESTUPDATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DecryptDigestUpdate(hSession,
                                  pEncryptedPart,
                                  ulEncryptedPartLen,
                                  pPart,
                                  pulPartLen);
-    nssdbg_finish_time(FUNC_C_DECRYPTDIGESTUPDATE,start);
+    nssdbg_finish_time(&counter_C_DecryptDigestUpdate,start);
     PR_LOG(modlog, 4, ("  *pulPartLen = 0x%x", *pulPartLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SignEncryptUpdate = 0;
+static PRInt32 calls_C_SignEncryptUpdate = 0;
 CK_RV NSSDBGC_SignEncryptUpdate(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pPart,
   CK_ULONG          ulPartLen,
   CK_BYTE_PTR       pEncryptedPart,
   CK_ULONG_PTR      pulEncryptedPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SignEncryptUpdate);
     PR_LOG(modlog, 1, ("C_SignEncryptUpdate"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pPart = 0x%p", pPart));
     PR_LOG(modlog, 3, ("  ulPartLen = %d", ulPartLen));
     PR_LOG(modlog, 3, ("  pEncryptedPart = 0x%p", pEncryptedPart));
     PR_LOG(modlog, 3, ("  pulEncryptedPartLen = 0x%p", pulEncryptedPartLen));
-    nssdbg_start_time(FUNC_C_SIGNENCRYPTUPDATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SignEncryptUpdate(hSession,
                                  pPart,
                                  ulPartLen,
                                  pEncryptedPart,
                                  pulEncryptedPartLen);
-    nssdbg_finish_time(FUNC_C_SIGNENCRYPTUPDATE,start);
+    nssdbg_finish_time(&counter_C_SignEncryptUpdate,start);
     PR_LOG(modlog, 4, ("  *pulEncryptedPartLen = 0x%x", *pulEncryptedPartLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DecryptVerifyUpdate = 0;
+static PRInt32 calls_C_DecryptVerifyUpdate = 0;
 CK_RV NSSDBGC_DecryptVerifyUpdate(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pEncryptedPart,
   CK_ULONG          ulEncryptedPartLen,
   CK_BYTE_PTR       pPart,
   CK_ULONG_PTR      pulPartLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DecryptVerifyUpdate);
     PR_LOG(modlog, 1, ("C_DecryptVerifyUpdate"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pEncryptedPart = 0x%p", pEncryptedPart));
     PR_LOG(modlog, 3, ("  ulEncryptedPartLen = %d", ulEncryptedPartLen));
     PR_LOG(modlog, 3, ("  pPart = 0x%p", pPart));
     PR_LOG(modlog, 3, ("  pulPartLen = 0x%p", pulPartLen));
-    nssdbg_start_time(FUNC_C_DECRYPTVERIFYUPDATE,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DecryptVerifyUpdate(hSession,
                                  pEncryptedPart,
                                  ulEncryptedPartLen,
                                  pPart,
                                  pulPartLen);
-    nssdbg_finish_time(FUNC_C_DECRYPTVERIFYUPDATE,start);
+    nssdbg_finish_time(&counter_C_DecryptVerifyUpdate,start);
     PR_LOG(modlog, 4, ("  *pulPartLen = 0x%x", *pulPartLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GenerateKey = 0;
+static PRInt32 calls_C_GenerateKey = 0;
 CK_RV NSSDBGC_GenerateKey(
   CK_SESSION_HANDLE    hSession,
   CK_MECHANISM_PTR     pMechanism,
   CK_ATTRIBUTE_PTR     pTemplate,
   CK_ULONG             ulCount,
   CK_OBJECT_HANDLE_PTR phKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GenerateKey);
     PR_LOG(modlog, 1, ("C_GenerateKey"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  pTemplate = 0x%p", pTemplate));
     PR_LOG(modlog, 3, ("  ulCount = %d", ulCount));
     PR_LOG(modlog, 3, ("  phKey = 0x%p", phKey));
     print_template(pTemplate, ulCount);
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_GENERATEKEY,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GenerateKey(hSession,
                                  pMechanism,
                                  pTemplate,
                                  ulCount,
                                  phKey);
-    nssdbg_finish_time(FUNC_C_GENERATEKEY,start);
+    nssdbg_finish_time(&counter_C_GenerateKey,start);
     PR_LOG(modlog, 4, ("  *phKey = 0x%x", *phKey));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GenerateKeyPair = 0;
+static PRInt32 calls_C_GenerateKeyPair = 0;
 CK_RV NSSDBGC_GenerateKeyPair(
   CK_SESSION_HANDLE    hSession,
   CK_MECHANISM_PTR     pMechanism,
   CK_ATTRIBUTE_PTR     pPublicKeyTemplate,
   CK_ULONG             ulPublicKeyAttributeCount,
   CK_ATTRIBUTE_PTR     pPrivateKeyTemplate,
   CK_ULONG             ulPrivateKeyAttributeCount,
   CK_OBJECT_HANDLE_PTR phPublicKey,
   CK_OBJECT_HANDLE_PTR phPrivateKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GenerateKeyPair);
     PR_LOG(modlog, 1, ("C_GenerateKeyPair"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  pPublicKeyTemplate = 0x%p", pPublicKeyTemplate));
     PR_LOG(modlog, 3, ("  ulPublicKeyAttributeCount = %d", ulPublicKeyAttributeCount));
     PR_LOG(modlog, 3, ("  pPrivateKeyTemplate = 0x%p", pPrivateKeyTemplate));
     PR_LOG(modlog, 3, ("  ulPrivateKeyAttributeCount = %d", ulPrivateKeyAttributeCount));
     PR_LOG(modlog, 3, ("  phPublicKey = 0x%p", phPublicKey));
     PR_LOG(modlog, 3, ("  phPrivateKey = 0x%p", phPrivateKey));
     print_template(pPublicKeyTemplate, ulPublicKeyAttributeCount);
     print_template(pPrivateKeyTemplate, ulPrivateKeyAttributeCount);
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_GENERATEKEYPAIR,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GenerateKeyPair(hSession,
                                  pMechanism,
                                  pPublicKeyTemplate,
                                  ulPublicKeyAttributeCount,
                                  pPrivateKeyTemplate,
                                  ulPrivateKeyAttributeCount,
                                  phPublicKey,
                                  phPrivateKey);
-    nssdbg_finish_time(FUNC_C_GENERATEKEYPAIR,start);
+    nssdbg_finish_time(&counter_C_GenerateKeyPair,start);
     PR_LOG(modlog, 4, ("  *phPublicKey = 0x%x", *phPublicKey));
     PR_LOG(modlog, 4, ("  *phPrivateKey = 0x%x", *phPrivateKey));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_WrapKey = 0;
+static PRInt32 calls_C_WrapKey = 0;
 CK_RV NSSDBGC_WrapKey(
   CK_SESSION_HANDLE hSession,
   CK_MECHANISM_PTR  pMechanism,
   CK_OBJECT_HANDLE  hWrappingKey,
   CK_OBJECT_HANDLE  hKey,
   CK_BYTE_PTR       pWrappedKey,
   CK_ULONG_PTR      pulWrappedKeyLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_WrapKey);
     PR_LOG(modlog, 1, ("C_WrapKey"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  hWrappingKey = 0x%x", hWrappingKey));
     PR_LOG(modlog, 3, ("  hKey = 0x%x", hKey));
     PR_LOG(modlog, 3, ("  pWrappedKey = 0x%p", pWrappedKey));
     PR_LOG(modlog, 3, ("  pulWrappedKeyLen = 0x%p", pulWrappedKeyLen));
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_WRAPKEY,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_WrapKey(hSession,
                                  pMechanism,
                                  hWrappingKey,
                                  hKey,
                                  pWrappedKey,
                                  pulWrappedKeyLen);
-    nssdbg_finish_time(FUNC_C_WRAPKEY,start);
+    nssdbg_finish_time(&counter_C_WrapKey,start);
     PR_LOG(modlog, 4, ("  *pulWrappedKeyLen = 0x%x", *pulWrappedKeyLen));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_UnwrapKey = 0;
+static PRInt32 calls_C_UnwrapKey = 0;
 CK_RV NSSDBGC_UnwrapKey(
   CK_SESSION_HANDLE    hSession,
   CK_MECHANISM_PTR     pMechanism,
   CK_OBJECT_HANDLE     hUnwrappingKey,
   CK_BYTE_PTR          pWrappedKey,
   CK_ULONG             ulWrappedKeyLen,
   CK_ATTRIBUTE_PTR     pTemplate,
   CK_ULONG             ulAttributeCount,
   CK_OBJECT_HANDLE_PTR phKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_UnwrapKey);
     PR_LOG(modlog, 1, ("C_UnwrapKey"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  hUnwrappingKey = 0x%x", hUnwrappingKey));
     PR_LOG(modlog, 3, ("  pWrappedKey = 0x%p", pWrappedKey));
     PR_LOG(modlog, 3, ("  ulWrappedKeyLen = %d", ulWrappedKeyLen));
     PR_LOG(modlog, 3, ("  pTemplate = 0x%p", pTemplate));
     PR_LOG(modlog, 3, ("  ulAttributeCount = %d", ulAttributeCount));
     PR_LOG(modlog, 3, ("  phKey = 0x%p", phKey));
     print_template(pTemplate, ulAttributeCount);
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_UNWRAPKEY,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_UnwrapKey(hSession,
                                  pMechanism,
                                  hUnwrappingKey,
                                  pWrappedKey,
                                  ulWrappedKeyLen,
                                  pTemplate,
                                  ulAttributeCount,
                                  phKey);
-    nssdbg_finish_time(FUNC_C_UNWRAPKEY,start);
+    nssdbg_finish_time(&counter_C_UnwrapKey,start);
     PR_LOG(modlog, 4, ("  *phKey = 0x%x", *phKey));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_DeriveKey = 0;
+static PRInt32 calls_C_DeriveKey = 0;
 CK_RV NSSDBGC_DeriveKey(
   CK_SESSION_HANDLE    hSession,
   CK_MECHANISM_PTR     pMechanism,
   CK_OBJECT_HANDLE     hBaseKey,
   CK_ATTRIBUTE_PTR     pTemplate,
   CK_ULONG             ulAttributeCount,
   CK_OBJECT_HANDLE_PTR phKey
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_DeriveKey);
     PR_LOG(modlog, 1, ("C_DeriveKey"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pMechanism = 0x%p", pMechanism));
     PR_LOG(modlog, 3, ("  hBaseKey = 0x%x", hBaseKey));
     PR_LOG(modlog, 3, ("  pTemplate = 0x%p", pTemplate));
     PR_LOG(modlog, 3, ("  ulAttributeCount = %d", ulAttributeCount));
     PR_LOG(modlog, 3, ("  phKey = 0x%p", phKey));
     print_template(pTemplate, ulAttributeCount);
     print_mechanism(pMechanism);
-    nssdbg_start_time(FUNC_C_DERIVEKEY,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_DeriveKey(hSession,
                                  pMechanism,
                                  hBaseKey,
                                  pTemplate,
                                  ulAttributeCount,
                                  phKey);
-    nssdbg_finish_time(FUNC_C_DERIVEKEY,start);
+    nssdbg_finish_time(&counter_C_DeriveKey,start);
     PR_LOG(modlog, 4, ("  *phKey = 0x%x", *phKey));
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_SeedRandom = 0;
+static PRInt32 calls_C_SeedRandom = 0;
 CK_RV NSSDBGC_SeedRandom(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       pSeed,
   CK_ULONG          ulSeedLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_SeedRandom);
     PR_LOG(modlog, 1, ("C_SeedRandom"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  pSeed = 0x%p", pSeed));
     PR_LOG(modlog, 3, ("  ulSeedLen = %d", ulSeedLen));
-    nssdbg_start_time(FUNC_C_SEEDRANDOM,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_SeedRandom(hSession,
                                  pSeed,
                                  ulSeedLen);
-    nssdbg_finish_time(FUNC_C_SEEDRANDOM,start);
+    nssdbg_finish_time(&counter_C_SeedRandom,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GenerateRandom = 0;
+static PRInt32 calls_C_GenerateRandom = 0;
 CK_RV NSSDBGC_GenerateRandom(
   CK_SESSION_HANDLE hSession,
   CK_BYTE_PTR       RandomData,
   CK_ULONG          ulRandomLen
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GenerateRandom);
     PR_LOG(modlog, 1, ("C_GenerateRandom"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
     PR_LOG(modlog, 3, ("  RandomData = 0x%p", RandomData));
     PR_LOG(modlog, 3, ("  ulRandomLen = %d", ulRandomLen));
-    nssdbg_start_time(FUNC_C_GENERATERANDOM,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GenerateRandom(hSession,
                                  RandomData,
                                  ulRandomLen);
-    nssdbg_finish_time(FUNC_C_GENERATERANDOM,start);
+    nssdbg_finish_time(&counter_C_GenerateRandom,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_GetFunctionStatus = 0;
+static PRInt32 calls_C_GetFunctionStatus = 0;
 CK_RV NSSDBGC_GetFunctionStatus(
   CK_SESSION_HANDLE hSession
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_GetFunctionStatus);
     PR_LOG(modlog, 1, ("C_GetFunctionStatus"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
-    nssdbg_start_time(FUNC_C_GETFUNCTIONSTATUS,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_GetFunctionStatus(hSession);
-    nssdbg_finish_time(FUNC_C_GETFUNCTIONSTATUS,start);
+    nssdbg_finish_time(&counter_C_GetFunctionStatus,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_CancelFunction = 0;
+static PRInt32 calls_C_CancelFunction = 0;
 CK_RV NSSDBGC_CancelFunction(
   CK_SESSION_HANDLE hSession
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_CancelFunction);
     PR_LOG(modlog, 1, ("C_CancelFunction"));
     PR_LOG(modlog, 3, ("  hSession = 0x%x", hSession));
-    nssdbg_start_time(FUNC_C_CANCELFUNCTION,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_CancelFunction(hSession);
-    nssdbg_finish_time(FUNC_C_CANCELFUNCTION,start);
+    nssdbg_finish_time(&counter_C_CancelFunction,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
+static PRInt32 counter_C_WaitForSlotEvent = 0;
+static PRInt32 calls_C_WaitForSlotEvent = 0;
 CK_RV NSSDBGC_WaitForSlotEvent(
   CK_FLAGS       flags,
   CK_SLOT_ID_PTR pSlot,
   CK_VOID_PTR    pRserved
 )
 {
     CK_RV rv;
     PRIntervalTime start;
+    PR_AtomicIncrement(&calls_C_WaitForSlotEvent);
     PR_LOG(modlog, 1, ("C_WaitForSlotEvent"));
     PR_LOG(modlog, 3, ("  flags = 0x%x", flags));
     PR_LOG(modlog, 3, ("  pSlot = 0x%p", pSlot));
     PR_LOG(modlog, 3, ("  pRserved = 0x%p", pRserved));
-    nssdbg_start_time(FUNC_C_WAITFORSLOTEVENT,&start);
+    start = PR_IntervalNow();
     rv = module_functions->C_WaitForSlotEvent(flags,
                                  pSlot,
                                  pRserved);
-    nssdbg_finish_time(FUNC_C_WAITFORSLOTEVENT,start);
+    nssdbg_finish_time(&counter_C_WaitForSlotEvent,start);
     PR_LOG(modlog, 1, ("  rv = 0x%x\n", rv));
     return rv;
 }
 
 CK_FUNCTION_LIST_PTR nss_InsertDeviceLog(
   CK_FUNCTION_LIST_PTR devEPV
 )
 {
@@ -2098,112 +2154,716 @@ CK_FUNCTION_LIST_PTR nss_InsertDeviceLog
     debug_functions.C_SeedRandom = NSSDBGC_SeedRandom;
     debug_functions.C_GenerateRandom = NSSDBGC_GenerateRandom;
     debug_functions.C_GetFunctionStatus = NSSDBGC_GetFunctionStatus;
     debug_functions.C_CancelFunction = NSSDBGC_CancelFunction;
     debug_functions.C_WaitForSlotEvent = NSSDBGC_WaitForSlotEvent;
     return &debug_functions;
 }
 
-/*
- * scale the time factor up accordingly.
- * This routine tries to keep at least 2 significant figures on output.
- *    If the time is 0, then indicate that with a 'z' for units.
- *    If the time is greater than 10 minutes, output the time in minutes.
- *    If the time is less than 10 minutes but greater than 10 seconds output 
- * the time in second.
- *    If the time is less than 10 seconds but greater than 10 milliseconds 
- * output * the time in millisecond.
- *    If the time is less than 10 milliseconds but greater than 0 ticks output 
- * the time in microsecond.
- *
- */
-static PRUint32 getPrintTime(PRIntervalTime time ,char **type)
-{
-	PRUint32 prTime;
-
-        /* detect a programming error by outputting 'bu' to the output stream
-	 * rather than crashing */
- 	*type = "bug";
-	if (time == 0) {
-	    *type = "z";
-	    return 0;
-	}
-
-	prTime = PR_IntervalToSeconds(time);
-
-	if (prTime >= 600) {
-	    *type="m";
-	    return prTime/60;
-	}
-        if (prTime >= 10) {
-	    *type="s";
-	    return prTime;
-	} 
-	prTime = PR_IntervalToMilliseconds(time);
-        if (prTime >= 10) {
-	    *type="ms";
-	    return prTime;
-	} 
- 	*type = "us";
-	return PR_IntervalToMicroseconds(time);
-}
-
 static void print_final_statistics(void)
 {
     int total_calls = 0;
-    PRIntervalTime total_time = 0;
-    PRUint32 pr_total_time;
-    char *type;
+    PRInt32 total_time = 0;
     char *fname;
     FILE *outfile = NULL;
-    int i;
 
     fname = PR_GetEnv("NSS_OUTPUT_FILE");
     if (fname) {
-	/* need to add an optional process id to the filename */
 	outfile = fopen(fname,"w+");
     }
     if (!outfile) {
 	outfile = stdout;
     }
 	
 
-    fprintf(outfile,"%-25s %10s %12s %12s %10s\n", "Function", "# Calls", 
-				"Time", "Avg.", "% Time");
+    fprintf(outfile,"%-25s %10s %11s %10s %10s\n", "Function", "# Calls", "Time (ms)", "Avg. (ms)", "% Time");
+    fprintf(outfile,"\n");
+    total_calls += calls_C_CancelFunction;
+    total_time += counter_C_CancelFunction;
+    total_calls += calls_C_CloseAllSessions;
+    total_time += counter_C_CloseAllSessions;
+    total_calls += calls_C_CloseSession;
+    total_time += counter_C_CloseSession;
+    total_calls += calls_C_CopyObject;
+    total_time += counter_C_CopyObject;
+    total_calls += calls_C_CreateObject;
+    total_time += counter_C_CreateObject;
+    total_calls += calls_C_Decrypt;
+    total_time += counter_C_Decrypt;
+    total_calls += calls_C_DecryptDigestUpdate;
+    total_time += counter_C_DecryptDigestUpdate;
+    total_calls += calls_C_DecryptFinal;
+    total_time += counter_C_DecryptFinal;
+    total_calls += calls_C_DecryptInit;
+    total_time += counter_C_DecryptInit;
+    total_calls += calls_C_DecryptUpdate;
+    total_time += counter_C_DecryptUpdate;
+    total_calls += calls_C_DecryptVerifyUpdate;
+    total_time += counter_C_DecryptVerifyUpdate;
+    total_calls += calls_C_DeriveKey;
+    total_time += counter_C_DeriveKey;
+    total_calls += calls_C_DestroyObject;
+    total_time += counter_C_DestroyObject;
+    total_calls += calls_C_Digest;
+    total_time += counter_C_Digest;
+    total_calls += calls_C_DigestEncryptUpdate;
+    total_time += counter_C_DigestEncryptUpdate;
+    total_calls += calls_C_DigestFinal;
+    total_time += counter_C_DigestFinal;
+    total_calls += calls_C_DigestInit;
+    total_time += counter_C_DigestInit;
+    total_calls += calls_C_DigestKey;
+    total_time += counter_C_DigestKey;
+    total_calls += calls_C_DigestUpdate;
+    total_time += counter_C_DigestUpdate;
+    total_calls += calls_C_Encrypt;
+    total_time += counter_C_Encrypt;
+    total_calls += calls_C_EncryptFinal;
+    total_time += counter_C_EncryptFinal;
+    total_calls += calls_C_EncryptInit;
+    total_time += counter_C_EncryptInit;
+    total_calls += calls_C_EncryptUpdate;
+    total_time += counter_C_EncryptUpdate;
+    total_calls += calls_C_Finalize;
+    total_time += counter_C_Finalize;
+    total_calls += calls_C_FindObjects;
+    total_time += counter_C_FindObjects;
+    total_calls += calls_C_FindObjectsFinal;
+    total_time += counter_C_FindObjectsFinal;
+    total_calls += calls_C_FindObjectsInit;
+    total_time += counter_C_FindObjectsInit;
+    total_calls += calls_C_GenerateKey;
+    total_time += counter_C_GenerateKey;
+    total_calls += calls_C_GenerateKeyPair;
+    total_time += counter_C_GenerateKeyPair;
+    total_calls += calls_C_GenerateRandom;
+    total_time += counter_C_GenerateRandom;
+    total_calls += calls_C_GetAttributeValue;
+    total_time += counter_C_GetAttributeValue;
+    total_calls += calls_C_GetFunctionList;
+    total_time += counter_C_GetFunctionList;
+    total_calls += calls_C_GetFunctionStatus;
+    total_time += counter_C_GetFunctionStatus;
+    total_calls += calls_C_GetInfo;
+    total_time += counter_C_GetInfo;
+    total_calls += calls_C_GetMechanismInfo;
+    total_time += counter_C_GetMechanismInfo;
+    total_calls += calls_C_GetMechanismList;
+    total_time += counter_C_GetMechanismList;
+    total_calls += calls_C_GetObjectSize;
+    total_time += counter_C_GetObjectSize;
+    total_calls += calls_C_GetOperationState;
+    total_time += counter_C_GetOperationState;
+    total_calls += calls_C_GetSessionInfo;
+    total_time += counter_C_GetSessionInfo;
+    total_calls += calls_C_GetSlotInfo;
+    total_time += counter_C_GetSlotInfo;
+    total_calls += calls_C_GetSlotList;
+    total_time += counter_C_GetSlotList;
+    total_calls += calls_C_GetTokenInfo;
+    total_time += counter_C_GetTokenInfo;
+    total_calls += calls_C_InitPIN;
+    total_time += counter_C_InitPIN;
+    total_calls += calls_C_InitToken;
+    total_time += counter_C_InitToken;
+    total_calls += calls_C_Initialize;
+    total_time += counter_C_Initialize;
+    total_calls += calls_C_Login;
+    total_time += counter_C_Login;
+    total_calls += calls_C_Logout;
+    total_time += counter_C_Logout;
+    total_calls += calls_C_OpenSession;
+    total_time += counter_C_OpenSession;
+    total_calls += calls_C_SeedRandom;
+    total_time += counter_C_SeedRandom;
+    total_calls += calls_C_SetAttributeValue;
+    total_time += counter_C_SetAttributeValue;
+    total_calls += calls_C_SetOperationState;
+    total_time += counter_C_SetOperationState;
+    total_calls += calls_C_SetPIN;
+    total_time += counter_C_SetPIN;
+    total_calls += calls_C_Sign;
+    total_time += counter_C_Sign;
+    total_calls += calls_C_SignEncryptUpdate;
+    total_time += counter_C_SignEncryptUpdate;
+    total_calls += calls_C_SignFinal;
+    total_time += counter_C_SignFinal;
+    total_calls += calls_C_SignInit;
+    total_time += counter_C_SignInit;
+    total_calls += calls_C_SignRecover;
+    total_time += counter_C_SignRecover;
+    total_calls += calls_C_SignRecoverInit;
+    total_time += counter_C_SignRecoverInit;
+    total_calls += calls_C_SignUpdate;
+    total_time += counter_C_SignUpdate;
+    total_calls += calls_C_UnwrapKey;
+    total_time += counter_C_UnwrapKey;
+    total_calls += calls_C_Verify;
+    total_time += counter_C_Verify;
+    total_calls += calls_C_VerifyFinal;
+    total_time += counter_C_VerifyFinal;
+    total_calls += calls_C_VerifyInit;
+    total_time += counter_C_VerifyInit;
+    total_calls += calls_C_VerifyRecover;
+    total_time += counter_C_VerifyRecover;
+    total_calls += calls_C_VerifyRecoverInit;
+    total_time += counter_C_VerifyRecoverInit;
+    total_calls += calls_C_VerifyUpdate;
+    total_time += counter_C_VerifyUpdate;
+    total_calls += calls_C_WaitForSlotEvent;
+    total_time += counter_C_WaitForSlotEvent;
+    total_calls += calls_C_WrapKey;
+    total_time += counter_C_WrapKey;
+    fprintf(outfile,"%-25s %10d %10d ", "C_CancelFunction", calls_C_CancelFunction, counter_C_CancelFunction);
+    if (calls_C_CancelFunction > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_CancelFunction / (float)calls_C_CancelFunction);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_CancelFunction / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_CloseAllSessions", calls_C_CloseAllSessions, counter_C_CloseAllSessions);
+    if (calls_C_CloseAllSessions > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_CloseAllSessions / (float)calls_C_CloseAllSessions);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_CloseAllSessions / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_CloseSession", calls_C_CloseSession, counter_C_CloseSession);
+    if (calls_C_CloseSession > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_CloseSession / (float)calls_C_CloseSession);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_CloseSession / (float)total_time * 100);
     fprintf(outfile,"\n");
-    for (i=0; i < nssdbg_prof_size; i++) {
-	total_calls += nssdbg_prof_data[i].calls;
-	total_time += nssdbg_prof_data[i].time;
+    fprintf(outfile,"%-25s %10d %10d ", "C_CopyObject", calls_C_CopyObject, counter_C_CopyObject);
+    if (calls_C_CopyObject > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_CopyObject / (float)calls_C_CopyObject);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_CopyObject / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_CreateObject", calls_C_CreateObject, counter_C_CreateObject);
+    if (calls_C_CreateObject > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_CreateObject / (float)calls_C_CreateObject);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_CreateObject / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_Decrypt", calls_C_Decrypt, counter_C_Decrypt);
+    if (calls_C_Decrypt > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_Decrypt / (float)calls_C_Decrypt);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_Decrypt / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DecryptDigestUpdate", calls_C_DecryptDigestUpdate, counter_C_DecryptDigestUpdate);
+    if (calls_C_DecryptDigestUpdate > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DecryptDigestUpdate / (float)calls_C_DecryptDigestUpdate);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DecryptDigestUpdate / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DecryptFinal", calls_C_DecryptFinal, counter_C_DecryptFinal);
+    if (calls_C_DecryptFinal > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DecryptFinal / (float)calls_C_DecryptFinal);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DecryptFinal / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DecryptInit", calls_C_DecryptInit, counter_C_DecryptInit);
+    if (calls_C_DecryptInit > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DecryptInit / (float)calls_C_DecryptInit);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DecryptInit / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DecryptUpdate", calls_C_DecryptUpdate, counter_C_DecryptUpdate);
+    if (calls_C_DecryptUpdate > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DecryptUpdate / (float)calls_C_DecryptUpdate);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DecryptUpdate / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DecryptVerifyUpdate", calls_C_DecryptVerifyUpdate, counter_C_DecryptVerifyUpdate);
+    if (calls_C_DecryptVerifyUpdate > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DecryptVerifyUpdate / (float)calls_C_DecryptVerifyUpdate);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DecryptVerifyUpdate / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DeriveKey", calls_C_DeriveKey, counter_C_DeriveKey);
+    if (calls_C_DeriveKey > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DeriveKey / (float)calls_C_DeriveKey);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DeriveKey / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DestroyObject", calls_C_DestroyObject, counter_C_DestroyObject);
+    if (calls_C_DestroyObject > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DestroyObject / (float)calls_C_DestroyObject);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DestroyObject / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_Digest", calls_C_Digest, counter_C_Digest);
+    if (calls_C_Digest > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_Digest / (float)calls_C_Digest);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_Digest / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DigestEncryptUpdate", calls_C_DigestEncryptUpdate, counter_C_DigestEncryptUpdate);
+    if (calls_C_DigestEncryptUpdate > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DigestEncryptUpdate / (float)calls_C_DigestEncryptUpdate);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DigestEncryptUpdate / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DigestFinal", calls_C_DigestFinal, counter_C_DigestFinal);
+    if (calls_C_DigestFinal > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DigestFinal / (float)calls_C_DigestFinal);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DigestFinal / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DigestInit", calls_C_DigestInit, counter_C_DigestInit);
+    if (calls_C_DigestInit > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DigestInit / (float)calls_C_DigestInit);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DigestInit / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DigestKey", calls_C_DigestKey, counter_C_DigestKey);
+    if (calls_C_DigestKey > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DigestKey / (float)calls_C_DigestKey);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DigestKey / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_DigestUpdate", calls_C_DigestUpdate, counter_C_DigestUpdate);
+    if (calls_C_DigestUpdate > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_DigestUpdate / (float)calls_C_DigestUpdate);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_DigestUpdate / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_Encrypt", calls_C_Encrypt, counter_C_Encrypt);
+    if (calls_C_Encrypt > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_Encrypt / (float)calls_C_Encrypt);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_Encrypt / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_EncryptFinal", calls_C_EncryptFinal, counter_C_EncryptFinal);
+    if (calls_C_EncryptFinal > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_EncryptFinal / (float)calls_C_EncryptFinal);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_EncryptFinal / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_EncryptInit", calls_C_EncryptInit, counter_C_EncryptInit);
+    if (calls_C_EncryptInit > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_EncryptInit / (float)calls_C_EncryptInit);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_EncryptInit / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_EncryptUpdate", calls_C_EncryptUpdate, counter_C_EncryptUpdate);
+    if (calls_C_EncryptUpdate > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_EncryptUpdate / (float)calls_C_EncryptUpdate);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_EncryptUpdate / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_Finalize", calls_C_Finalize, counter_C_Finalize);
+    if (calls_C_Finalize > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_Finalize / (float)calls_C_Finalize);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_Finalize / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_FindObjects", calls_C_FindObjects, counter_C_FindObjects);
+    if (calls_C_FindObjects > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_FindObjects / (float)calls_C_FindObjects);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
     }
-    for (i=0; i < nssdbg_prof_size; i++) {
-	PRIntervalTime time = nssdbg_prof_data[i].time;
-	PRUint32 usTime = PR_IntervalToMicroseconds(time);
-	PRUint32 prTime = 0;
-	PRUint32 calls = nssdbg_prof_data[i].calls;
-	/* don't print out functions that weren't even called */
-	if (calls == 0) {
-	    continue;
-	}
-
-	prTime = getPrintTime(time,&type);
-
-	fprintf(outfile,"%-25s %10d %10d%2s ", nssdbg_prof_data[i].function, 
-						calls, prTime, type);
-	/* for now always output the average in microseconds */
-	fprintf(outfile,"%10.2f%2s", (float)usTime / (float)calls, "us" );
-	fprintf(outfile,"%10.2f%%", ((float)time / (float)total_time) * 100);
-	fprintf(outfile,"\n");
+    fprintf(outfile,"%10.2f", (float)counter_C_FindObjects / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_FindObjectsFinal", calls_C_FindObjectsFinal, counter_C_FindObjectsFinal);
+    if (calls_C_FindObjectsFinal > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_FindObjectsFinal / (float)calls_C_FindObjectsFinal);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_FindObjectsFinal / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_FindObjectsInit", calls_C_FindObjectsInit, counter_C_FindObjectsInit);
+    if (calls_C_FindObjectsInit > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_FindObjectsInit / (float)calls_C_FindObjectsInit);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_FindObjectsInit / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GenerateKey", calls_C_GenerateKey, counter_C_GenerateKey);
+    if (calls_C_GenerateKey > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GenerateKey / (float)calls_C_GenerateKey);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GenerateKey / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GenerateKeyPair", calls_C_GenerateKeyPair, counter_C_GenerateKeyPair);
+    if (calls_C_GenerateKeyPair > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GenerateKeyPair / (float)calls_C_GenerateKeyPair);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GenerateKeyPair / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GenerateRandom", calls_C_GenerateRandom, counter_C_GenerateRandom);
+    if (calls_C_GenerateRandom > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GenerateRandom / (float)calls_C_GenerateRandom);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GenerateRandom / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetAttributeValue", calls_C_GetAttributeValue, counter_C_GetAttributeValue);
+    if (calls_C_GetAttributeValue > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetAttributeValue / (float)calls_C_GetAttributeValue);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetAttributeValue / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetFunctionList", calls_C_GetFunctionList, counter_C_GetFunctionList);
+    if (calls_C_GetFunctionList > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetFunctionList / (float)calls_C_GetFunctionList);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetFunctionList / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetFunctionStatus", calls_C_GetFunctionStatus, counter_C_GetFunctionStatus);
+    if (calls_C_GetFunctionStatus > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetFunctionStatus / (float)calls_C_GetFunctionStatus);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetFunctionStatus / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetInfo", calls_C_GetInfo, counter_C_GetInfo);
+    if (calls_C_GetInfo > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetInfo / (float)calls_C_GetInfo);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetInfo / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetMechanismInfo", calls_C_GetMechanismInfo, counter_C_GetMechanismInfo);
+    if (calls_C_GetMechanismInfo > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetMechanismInfo / (float)calls_C_GetMechanismInfo);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetMechanismInfo / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetMechanismList", calls_C_GetMechanismList, counter_C_GetMechanismList);
+    if (calls_C_GetMechanismList > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetMechanismList / (float)calls_C_GetMechanismList);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetMechanismList / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetObjectSize", calls_C_GetObjectSize, counter_C_GetObjectSize);
+    if (calls_C_GetObjectSize > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetObjectSize / (float)calls_C_GetObjectSize);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetObjectSize / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetOperationState", calls_C_GetOperationState, counter_C_GetOperationState);
+    if (calls_C_GetOperationState > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetOperationState / (float)calls_C_GetOperationState);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetOperationState / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetSessionInfo", calls_C_GetSessionInfo, counter_C_GetSessionInfo);
+    if (calls_C_GetSessionInfo > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetSessionInfo / (float)calls_C_GetSessionInfo);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetSessionInfo / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetSlotInfo", calls_C_GetSlotInfo, counter_C_GetSlotInfo);
+    if (calls_C_GetSlotInfo > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetSlotInfo / (float)calls_C_GetSlotInfo);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetSlotInfo / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetSlotList", calls_C_GetSlotList, counter_C_GetSlotList);
+    if (calls_C_GetSlotList > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetSlotList / (float)calls_C_GetSlotList);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetSlotList / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_GetTokenInfo", calls_C_GetTokenInfo, counter_C_GetTokenInfo);
+    if (calls_C_GetTokenInfo > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_GetTokenInfo / (float)calls_C_GetTokenInfo);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_GetTokenInfo / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_InitPIN", calls_C_InitPIN, counter_C_InitPIN);
+    if (calls_C_InitPIN > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_InitPIN / (float)calls_C_InitPIN);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_InitPIN / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_InitToken", calls_C_InitToken, counter_C_InitToken);
+    if (calls_C_InitToken > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_InitToken / (float)calls_C_InitToken);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_InitToken / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_Initialize", calls_C_Initialize, counter_C_Initialize);
+    if (calls_C_Initialize > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_Initialize / (float)calls_C_Initialize);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_Initialize / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_Login", calls_C_Login, counter_C_Login);
+    if (calls_C_Login > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_Login / (float)calls_C_Login);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
     }
+    fprintf(outfile,"%10.2f", (float)counter_C_Login / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_Logout", calls_C_Logout, counter_C_Logout);
+    if (calls_C_Logout > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_Logout / (float)calls_C_Logout);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_Logout / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_OpenSession", calls_C_OpenSession, counter_C_OpenSession);
+    if (calls_C_OpenSession > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_OpenSession / (float)calls_C_OpenSession);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_OpenSession / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SeedRandom", calls_C_SeedRandom, counter_C_SeedRandom);
+    if (calls_C_SeedRandom > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SeedRandom / (float)calls_C_SeedRandom);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SeedRandom / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SetAttributeValue", calls_C_SetAttributeValue, counter_C_SetAttributeValue);
+    if (calls_C_SetAttributeValue > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SetAttributeValue / (float)calls_C_SetAttributeValue);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SetAttributeValue / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SetOperationState", calls_C_SetOperationState, counter_C_SetOperationState);
+    if (calls_C_SetOperationState > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SetOperationState / (float)calls_C_SetOperationState);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SetOperationState / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SetPIN", calls_C_SetPIN, counter_C_SetPIN);
+    if (calls_C_SetPIN > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SetPIN / (float)calls_C_SetPIN);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SetPIN / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_Sign", calls_C_Sign, counter_C_Sign);
+    if (calls_C_Sign > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_Sign / (float)calls_C_Sign);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_Sign / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SignEncryptUpdate", calls_C_SignEncryptUpdate, counter_C_SignEncryptUpdate);
+    if (calls_C_SignEncryptUpdate > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SignEncryptUpdate / (float)calls_C_SignEncryptUpdate);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SignEncryptUpdate / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SignFinal", calls_C_SignFinal, counter_C_SignFinal);
+    if (calls_C_SignFinal > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SignFinal / (float)calls_C_SignFinal);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SignFinal / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SignInit", calls_C_SignInit, counter_C_SignInit);
+    if (calls_C_SignInit > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SignInit / (float)calls_C_SignInit);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SignInit / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SignRecover", calls_C_SignRecover, counter_C_SignRecover);
+    if (calls_C_SignRecover > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SignRecover / (float)calls_C_SignRecover);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SignRecover / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SignRecoverInit", calls_C_SignRecoverInit, counter_C_SignRecoverInit);
+    if (calls_C_SignRecoverInit > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SignRecoverInit / (float)calls_C_SignRecoverInit);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SignRecoverInit / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_SignUpdate", calls_C_SignUpdate, counter_C_SignUpdate);
+    if (calls_C_SignUpdate > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_SignUpdate / (float)calls_C_SignUpdate);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_SignUpdate / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_UnwrapKey", calls_C_UnwrapKey, counter_C_UnwrapKey);
+    if (calls_C_UnwrapKey > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_UnwrapKey / (float)calls_C_UnwrapKey);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_UnwrapKey / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_Verify", calls_C_Verify, counter_C_Verify);
+    if (calls_C_Verify > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_Verify / (float)calls_C_Verify);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_Verify / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_VerifyFinal", calls_C_VerifyFinal, counter_C_VerifyFinal);
+    if (calls_C_VerifyFinal > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_VerifyFinal / (float)calls_C_VerifyFinal);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_VerifyFinal / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_VerifyInit", calls_C_VerifyInit, counter_C_VerifyInit);
+    if (calls_C_VerifyInit > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_VerifyInit / (float)calls_C_VerifyInit);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_VerifyInit / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_VerifyRecover", calls_C_VerifyRecover, counter_C_VerifyRecover);
+    if (calls_C_VerifyRecover > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_VerifyRecover / (float)calls_C_VerifyRecover);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_VerifyRecover / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_VerifyRecoverInit", calls_C_VerifyRecoverInit, counter_C_VerifyRecoverInit);
+    if (calls_C_VerifyRecoverInit > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_VerifyRecoverInit / (float)calls_C_VerifyRecoverInit);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_VerifyRecoverInit / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_VerifyUpdate", calls_C_VerifyUpdate, counter_C_VerifyUpdate);
+    if (calls_C_VerifyUpdate > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_VerifyUpdate / (float)calls_C_VerifyUpdate);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_VerifyUpdate / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_WaitForSlotEvent", calls_C_WaitForSlotEvent, counter_C_WaitForSlotEvent);
+    if (calls_C_WaitForSlotEvent > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_WaitForSlotEvent / (float)calls_C_WaitForSlotEvent);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_WaitForSlotEvent / (float)total_time * 100);
+    fprintf(outfile,"\n");
+    fprintf(outfile,"%-25s %10d %10d ", "C_WrapKey", calls_C_WrapKey, counter_C_WrapKey);
+    if (calls_C_WrapKey > 0) {
+        fprintf(outfile,"%10.2f", (float)counter_C_WrapKey / (float)calls_C_WrapKey);
+    } else {
+        fprintf(outfile,"%10.2f", 0.0);
+    }
+    fprintf(outfile,"%10.2f", (float)counter_C_WrapKey / (float)total_time * 100);
+    fprintf(outfile,"\n");
     fprintf(outfile,"\n");
 
-    pr_total_time = getPrintTime(total_time,&type);
-
-    fprintf(outfile,"%25s %10d %10d%2s\n", "Totals", total_calls, 
-							pr_total_time, type);
-    fprintf(outfile,"\n\nMaximum number of concurrent open sessions: %d\n\n",
-							 maxOpenSessions);
+    fprintf(outfile,"%25s %10d %10d\n", "Totals", total_calls, total_time);
+    fprintf(outfile,"\n\nMaximum number of concurrent open sessions: %d\n\n", maxOpenSessions);
     fflush (outfile);
     if (outfile != stdout) {
 	fclose(outfile);
     }
 }
 
--- a/security/nss/lib/pk11wrap/manifest.mn
+++ b/security/nss/lib/pk11wrap/manifest.mn
@@ -37,16 +37,18 @@ EXPORTS = \
 	secmodt.h \
 	secpkcs5.h \
 	pk11func.h \
 	pk11sdr.h \
 	pk11pqg.h \
 	$(NULL)
 
 PRIVATE_EXPORTS = \
+	secmodi.h \
+	secmodti.h \
 	pk11init.h \
 	dev3hack.h \
 	$(NULL)
 
 MODULE = nss
 
 CSRCS = \
 	dev3hack.c \
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -38,16 +38,17 @@
 #include "secport.h"
 #include "seccomon.h"
 #include "secmod.h"
 #include "nssilock.h"
 #include "secmodi.h"
 #include "pkcs11.h"
 #include "pk11func.h"
 #include "cert.h"
+#include "certi.h"
 #include "secitem.h"
 #include "key.h"
 #include "hasht.h"
 #include "secoid.h"
 #include "pkcs7t.h"
 #include "cmsreclist.h"
 
 #include "certdb.h"
@@ -2148,33 +2149,37 @@ loser:
 static CERTCertificate *
 pk11_FindCertObjectByRecipientNew(PK11SlotInfo *slot, NSSCMSRecipient **recipientlist, int *rlIndex, void *pwarg)
 {
     NSSCMSRecipient *ri = NULL;
     int i;
 
     for (i=0; (ri = recipientlist[i]) != NULL; i++) {
 	CERTCertificate *cert = NULL;
-	/* XXXXX fixme - not yet implemented! */
-	if (ri->kind == RLSubjKeyID)
-	    continue;
-	cert = PK11_FindCertByIssuerAndSNOnToken(slot, ri->id.issuerAndSN, 
-								pwarg);
+	if (ri->kind == RLSubjKeyID) {
+	    SECItem *derCert = cert_FindDERCertBySubjectKeyID(ri->id.subjectKeyID);
+	    if (derCert) {
+		cert = PK11_FindCertFromDERCertItem(slot, derCert, pwarg);
+		SECITEM_FreeItem(derCert, PR_TRUE);
+	    }
+	} else {
+	    cert = PK11_FindCertByIssuerAndSNOnToken(slot, ri->id.issuerAndSN, 
+						     pwarg);
+	}
 	if (cert) {
 	    /* this isn't our cert */
 	    if ((cert->trust == NULL) ||
        		((cert->trust->emailFlags & CERTDB_USER) != CERTDB_USER)) {
 		 CERT_DestroyCertificate(cert);
 		continue;
 	    }
 	    ri->slot = PK11_ReferenceSlot(slot);
 	    *rlIndex = i;
 	    return cert;
 	}
-
     }
     *rlIndex = -1;
     return NULL;
 }
 
 /*
  * This function is the same as above, but it searches all the slots.
  * this is the new version for NSS SMIME code
@@ -2330,28 +2335,61 @@ PK11_FindCertAndKeyByRecipientList(PK11S
     return cert;
 loser:
     if (cert) CERT_DestroyCertificate(cert);
     if (*slotPtr) PK11_FreeSlot(*slotPtr);
     *slotPtr = NULL;
     return NULL;
 }
 
+static SECMODCallOnceType keyIDHashCallOnce;
+
+static SECStatus PR_CALLBACK
+pk11_keyIDHash_populate(void *wincx)
+{
+    CERTCertList     *certList;
+    CERTCertListNode *node = NULL;
+    SECItem           subjKeyID = {siBuffer, NULL, 0};
+
+    certList = PK11_ListCerts(PK11CertListUser, wincx);
+    if (!certList) {
+	return SECFailure;
+    }
+
+    for (node = CERT_LIST_HEAD(certList);
+         !CERT_LIST_END(node, certList);
+         node = CERT_LIST_NEXT(node)) {
+	if (CERT_FindSubjectKeyIDExtension(node->cert, 
+	                                   &subjKeyID) == SECSuccess && 
+	    subjKeyID.data != NULL) {
+	    cert_AddSubjectKeyIDMapping(&subjKeyID, node->cert);
+	    SECITEM_FreeItem(&subjKeyID, PR_FALSE);
+	}
+    }
+    CERT_DestroyCertList(certList);
+    return SECSuccess;
+}
+
 /*
  * This is the new version of the above function for NSS SMIME code
  * this stuff should REALLY be in the SMIME code, but some things in here are not public
  * (they should be!)
  */
 int
 PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *wincx)
 {
     CERTCertificate *cert;
     NSSCMSRecipient *rl;
+    SECStatus srv;
     int rlIndex;
 
+    srv = SECMOD_CallOnce(&keyIDHashCallOnce, pk11_keyIDHash_populate, wincx);
+    if (srv != SECSuccess)
+	return -1;
+
     cert = pk11_AllFindCertObjectByRecipientNew(recipientlist, wincx, &rlIndex);
     if (!cert) {
 	return -1;
     }
 
     rl = recipientlist[rlIndex];
 
     /* at this point, rl->slot is set */
@@ -2883,53 +2921,31 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *s
 
 /*
  * return the certificate associated with a derCert 
  */
 CERTCertificate *
 PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert,
 								 void *wincx)
 {
-#ifdef NSS_CLASSIC
-    CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
-    CK_ATTRIBUTE theTemplate[] = {
-	{ CKA_VALUE, NULL, 0 },
-	{ CKA_CLASS, NULL, 0 }
-    };
-    /* if you change the array, change the variable below as well */
-    int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
-    CK_OBJECT_HANDLE certh;
-    CK_ATTRIBUTE *attrs = theTemplate;
-    SECStatus rv;
-
-    PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, 
-						cert->derCert.len); attrs++;
-    PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
-
-    /*
-     * issue the find
-     */
-    if ( !PK11_IsFriendly(slot)) {
-	rv = PK11_Authenticate(slot, PR_TRUE, wincx);
-	if (rv != SECSuccess) return NULL;
-    }
-
-    certh = pk11_getcerthandle(slot,cert,theTemplate,tsize);
-    if (certh == CK_INVALID_HANDLE) {
-	return NULL;
-    }
-    return PK11_MakeCertFromHandle(slot, certh, NULL);
-#else
+    return PK11_FindCertFromDERCertItem(slot, &cert->derCert, wincx);
+}
+
+CERTCertificate *
+PK11_FindCertFromDERCertItem(PK11SlotInfo *slot, SECItem *inDerCert,
+								 void *wincx)
+
+{
     CERTCertificate *rvCert = NULL;
     NSSCertificate *c;
     NSSDER derCert;
     NSSToken *tok;
     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
     tok = PK11Slot_GetNSSToken(slot);
-    NSSITEM_FROM_SECITEM(&derCert, &cert->derCert);
+    NSSITEM_FROM_SECITEM(&derCert, inDerCert);
     if (!PK11_IsFriendly(slot)) {
 	if (PK11_Authenticate(slot, PR_TRUE, wincx) != SECSuccess) {
 	    PK11_FreeSlot(slot);
 	    return NULL;
 	}
     }
     c = NSSTrustDomain_FindCertificateByEncodedCertificate(td, &derCert);
     if (c) {
@@ -2949,17 +2965,16 @@ PK11_FindCertFromDERCert(PK11SlotInfo *s
 	    }
 	    nssTokenArray_Destroy(tokens);
 	}
     }
     if (c) {
 	rvCert = STAN_GetCERTCertificate(c);
     }
     return rvCert;
-#endif
 } 
 
 /* mcgreer 3.4 -- nobody uses this, ignoring */
 /*
  * return the certificate associated with a derCert 
  */
 CERTCertificate *
 PK11_FindCertFromDERSubjectAndNickname(PK11SlotInfo *slot, 
@@ -4132,8 +4147,59 @@ CERTSignedCrl* PK11_ImportCRL(PK11SlotIn
 
     } while (0);
 
     if (crl == NULL) {
 	SEC_DestroyCrl (newCrl);
     }
     return (crl);
 }
+
+/*
+ * This code takes the NSPR CallOnce functionality and modifies it so 
+ * that we can pass an argument to our function
+ */
+static struct {
+    PRLock *ml;
+    PRCondVar *cv;
+} mod_init;
+
+void SECMOD_InitCallOnce(void) {
+    mod_init.ml = PR_NewLock();
+    PORT_Assert(NULL != mod_init.ml);
+    mod_init.cv = PR_NewCondVar(mod_init.ml);
+    PORT_Assert(NULL != mod_init.cv);
+}
+
+void SECMOD_CleanupCallOnce()
+{
+    if (mod_init.ml) {
+	PR_DestroyLock(mod_init.ml);
+	mod_init.ml = NULL;
+    }
+    if (mod_init.cv) {
+	PR_DestroyCondVar(mod_init.cv);
+	mod_init.cv = NULL;
+    }
+}
+
+SECStatus SECMOD_CallOnce(SECMODCallOnceType *once,
+                          SECMODCallOnceFN    func,
+                          void               *arg)
+{
+
+    if (!once->initialized) {
+	if (PR_AtomicSet(&once->inProgress, 1) == 0) {
+	    once->status = (PRStatus)(*func)(arg);
+	    PR_Lock(mod_init.ml);
+	    once->initialized = 1;
+	    PR_NotifyAllCondVar(mod_init.cv);
+	    PR_Unlock(mod_init.ml);
+	} else {
+	    PR_Lock(mod_init.ml);
+	    while (!once->initialized) {
+		PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
+	    }
+	    PR_Unlock(mod_init.ml);
+	}
+    }
+    return once->status;
+}
--- a/security/nss/lib/pk11wrap/pk11func.h
+++ b/security/nss/lib/pk11wrap/pk11func.h
@@ -61,17 +61,16 @@ PK11SlotListElement *PK11_GetNextSafe(PK
 				PK11SlotListElement *le, PRBool restart);
 PK11SlotListElement *PK11_FindSlotElement(PK11SlotList *list,
 							PK11SlotInfo *slot);
 
 /************************************************************
  * Generic Slot Management
  ************************************************************/
 PK11SlotInfo *PK11_ReferenceSlot(PK11SlotInfo *slot);
-PK11SlotInfo *PK11_FindSlotByID(SECMODModuleID modID,CK_SLOT_ID slotID);
 void PK11_FreeSlot(PK11SlotInfo *slot);
 SECStatus PK11_DestroyObject(PK11SlotInfo *slot,CK_OBJECT_HANDLE object);
 SECStatus PK11_DestroyTokenObject(PK11SlotInfo *slot,CK_OBJECT_HANDLE object);
 CK_OBJECT_HANDLE PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject);
 SECStatus PK11_ReadAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
          CK_ATTRIBUTE_TYPE type, PRArenaPool *arena, SECItem *result);
 CK_ULONG PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
          CK_ATTRIBUTE_TYPE type);
@@ -126,16 +125,17 @@ void PK11_ClearSlotList(PK11SlotInfo *sl
  ******************************************************************/
 PRBool PK11_VerifyMechanism(PK11SlotInfo *slot,PK11SlotInfo *intern,
   CK_MECHANISM_TYPE mech, SECItem *data, SECItem *iv);
 PRBool PK11_VerifySlotMechanisms(PK11SlotInfo *slot);
 SECStatus pk11_CheckVerifyTest(PK11SlotInfo *slot);
 SECStatus PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts);
 SECStatus PK11_Authenticate(PK11SlotInfo *slot, PRBool loadCerts, void *wincx);
 void PK11_InitSlot(SECMODModule *mod,CK_SLOT_ID slotID,PK11SlotInfo *slot);
+SECStatus PK11_TokenRefresh(PK11SlotInfo *slot);
 
 
 /******************************************************************
  *           Slot info functions
  ******************************************************************/
 PK11SlotInfo *PK11_FindSlotByName(char *name);
 PK11SlotInfo *PK11_FindSlotBySerial(char *serial);
 PRBool PK11_IsReadOnly(PK11SlotInfo *slot);
@@ -456,16 +456,18 @@ CK_RV PK11_GetAttributes(PRArenaPool *ar
 int PK11_NumberCertsForCertSubject(CERTCertificate *cert);
 SECStatus PK11_TraverseCertsForSubject(CERTCertificate *cert, 
 	SECStatus(*callback)(CERTCertificate *, void *), void *arg);
 SECStatus PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert,
 	PK11SlotInfo *slot, SECStatus(*callback)(CERTCertificate *, void *),
 	void *arg);
 CERTCertificate *PK11_FindCertFromDERCert(PK11SlotInfo *slot, 
 					  CERTCertificate *cert, void *wincx);
+CERTCertificate *PK11_FindCertFromDERCertItem(PK11SlotInfo *slot, 
+					  SECItem *derCert, void *wincx);
 CERTCertificate *PK11_FindCertFromDERSubjectAndNickname(
 					PK11SlotInfo *slot, 
 					CERTCertificate *cert, char *nickname,
 					void *wincx);
 SECStatus PK11_ImportCertForKeyToSlot(PK11SlotInfo *slot, CERTCertificate *cert,
 					char *nickname, PRBool addUsage,
 					void *wincx);
 CERTCertificate *PK11_FindBestKEAMatch(CERTCertificate *serverCert,void *wincx);
--- a/security/nss/lib/pk11wrap/pk11init.h
+++ b/security/nss/lib/pk11wrap/pk11init.h
@@ -53,12 +53,10 @@ struct PK11PreSlotInfoStr {
 
 #define SECMOD_MAKE_NSS_FLAGS(fips,slot) \
 "Flags=internal,critical"fips" slotparams=("#slot"={"SECMOD_SLOT_FLAGS"})"
 
 #define SECMOD_INT_NAME "NSS Internal PKCS #11 Module"
 #define SECMOD_INT_FLAGS SECMOD_MAKE_NSS_FLAGS("",1)
 #define SECMOD_FIPS_NAME "NSS Internal FIPS PKCS #11 Module"
 #define SECMOD_FIPS_FLAGS SECMOD_MAKE_NSS_FLAGS(",fips",3)
-extern void PK11SDR_Init(void);
-extern void PK11SDR_Shutdown(void);
 
 #endif /* _PK11_INIT_H_ 1 */
--- a/security/nss/lib/pk11wrap/pk11sdr.c
+++ b/security/nss/lib/pk11wrap/pk11sdr.c
@@ -36,17 +36,16 @@
  */
 
 #include "seccomon.h"
 #include "secoid.h"
 #include "secasn1.h"
 #include "pkcs11.h"
 #include "pk11func.h"
 #include "pk11sdr.h"
-#include "pk11init.h"
 
 /*
  * Data structure and template for encoding the result of an SDR operation
  *  This is temporary.  It should include the algorithm ID of the encryption mechanism
  */
 struct SDRResult
 {
   SECItem keyid;
--- a/security/nss/lib/pk11wrap/pk11skey.c
+++ b/security/nss/lib/pk11wrap/pk11skey.c
@@ -944,50 +944,52 @@ PK11_MakePrivKey(PK11SlotInfo *slot, Key
 
     return privKey;
 }
 
 /* return the keylength if possible.  '0' if not */
 unsigned int
 PK11_GetKeyLength(PK11SymKey *key)
 {
-   if (key->size != 0) return key->size ;
+    CK_KEY_TYPE keyType;
+
+    if (key->size != 0) return key->size;
+
+    /* First try to figure out the key length from its type */
+    keyType = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_KEY_TYPE);
+    switch (keyType) {
+      case CKK_DES: key->size = 8; break;
+      case CKK_DES2: key->size = 16; break;
+      case CKK_DES3: key->size = 24; break;
+      case CKK_SKIPJACK: key->size = 10; break;
+      case CKK_BATON: key->size = 20; break;
+      case CKK_JUNIPER: key->size = 20; break;
+      case CKK_GENERIC_SECRET:
+	if (key->type == CKM_SSL3_PRE_MASTER_KEY_GEN)  {
+	    key->size=48;
+	}
+	break;
+      default: break;
+    }
+   if( key->size != 0 ) return key->size;
+
    if (key->data.data == NULL) {
 	PK11_ExtractKeyValue(key);
    }
-   /* key is probably secret. Look up it's type and length */
+   /* key is probably secret. Look up its length */
    /*  this is new PKCS #11 version 2.0 functionality. */
    if (key->size == 0) {
 	CK_ULONG keyLength;
 
 	keyLength = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_VALUE_LEN);
-	/* doesn't have a length field, check the known PKCS #11 key types,
-	 * which don't have this field */
-	if (keyLength == CK_UNAVAILABLE_INFORMATION) {
-	    CK_KEY_TYPE keyType;
-	    keyType = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_KEY_TYPE);
-	    switch (keyType) {
-	    case CKK_DES: key->size = 8; break;
-	    case CKK_DES2: key->size = 16; break;
-	    case CKK_DES3: key->size = 24; break;
-	    case CKK_SKIPJACK: key->size = 10; break;
-	    case CKK_BATON: key->size = 20; break;
-	    case CKK_JUNIPER: key->size = 20; break;
-	    case CKK_GENERIC_SECRET:
-		if (key->type == CKM_SSL3_PRE_MASTER_KEY_GEN)  {
-		    key->size=48;
-		}
-		break;
-	    default: break;
-	    }
-	} else {
+	if (keyLength != CK_UNAVAILABLE_INFORMATION) {
 	    key->size = (unsigned int)keyLength;
 	}
     }
-	
+
    return key->size;
 }
 
 /* return the strength of a key. This is different from length in that
  * 1) it returns the size in bits, and 2) it returns only the secret portions
  * of the key minus any checksums or parity.
  */
 unsigned int
@@ -1370,16 +1372,17 @@ PK11_TokenKeyGen(PK11SlotInfo *slot, CK_
 	mechanism.pParameter = param->data;
 	mechanism.ulParameterLen = param->len;
     }
 
     /* Get session and perform locking */
     if (isToken) {
 	PK11_Authenticate(symKey->slot,PR_TRUE,wincx);
         session = PK11_GetRWSession(symKey->slot);  /* Should always be original slot */
+	symKey->owner = PR_FALSE;
     } else {
         session = symKey->session;
         pk11_EnterKeyMonitor(symKey);
     }
 
     crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session,
 			 &mechanism, genTemplate, count, &symKey->objectID);
 
@@ -4118,32 +4121,42 @@ finalize:
 	                                              buffer, &count);
 	break;
     default:
 	crv = CKR_OPERATION_NOT_INITIALIZED;
 	break;
     }
 
     if (crv != CKR_OK) {
+	if (buffer != stackBuf) {
+	    PORT_Free(buffer);
+	}
 	if (crv == CKR_OPERATION_NOT_INITIALIZED) {
 	    /* if there's no operation, it is finalized */
 	    return SECSuccess;
 	}
         PORT_SetError( PK11_MapError(crv) );
         return SECFailure;
     }
 
     /* try to finalize the session with a buffer */
-    if (buffer == NULL && count > 0) { 
-	if (count < sizeof stackBuf) {
+    if (buffer == NULL) { 
+	if (count <= sizeof stackBuf) {
 	    buffer = stackBuf;
-	    goto finalize;
 	} else {
-	    return SECFailure;
+	    buffer = PORT_Alloc(count);
+	    if (buffer == NULL) {
+		PORT_SetError(SEC_ERROR_NO_MEMORY);
+		return SECFailure;
+	    }
 	}
+	goto finalize;
+    }
+    if (buffer != stackBuf) {
+	PORT_Free(buffer);
     }
     return SECSuccess;
 }
 
 /*
  *  Return the final digested or signed data...
  *  this routine can either take pre initialized data, or allocate data
  *  either out of an arena or out of the standard heap.
--- a/security/nss/lib/pk11wrap/pk11slot.c
+++ b/security/nss/lib/pk11wrap/pk11slot.c
@@ -1844,16 +1844,55 @@ PK11_InitToken(PK11SlotInfo *slot, PRBoo
 	    PK11_FreeSlot(int_slot);
 	}
     }
 
 	
     return SECSuccess;
 }
 
+/*
+ * initialize a new token
+ * unlike initialize slot, this can be called multiple times in the lifetime
+ * of NSS. It reads the information associated with a card or token,
+ * that is not going to change unless the card or token changes.
+ */
+SECStatus
+PK11_TokenRefresh(PK11SlotInfo *slot)
+{
+    CK_TOKEN_INFO tokenInfo;
+    CK_RV crv;
+    SECStatus rv;
+
+    /* set the slot flags to the current token values */
+    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
+    crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID,&tokenInfo);
+    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
+    if (crv != CKR_OK) {
+	PORT_SetError(PK11_MapError(crv));
+	return SECFailure;
+    }
+
+    slot->flags = tokenInfo.flags;
+    slot->needLogin = ((tokenInfo.flags & CKF_LOGIN_REQUIRED) ? 
+							PR_TRUE : PR_FALSE);
+    slot->readOnly = ((tokenInfo.flags & CKF_WRITE_PROTECTED) ? 
+							PR_TRUE : PR_FALSE);
+    slot->hasRandom = ((tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE);
+    slot->protectedAuthPath =
+    		((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) 
+	 						? PR_TRUE : PR_FALSE);
+    /* on some platforms Active Card incorrectly sets the 
+     * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
+    if (slot->isActiveCard) {
+	slot->protectedAuthPath = PR_FALSE;
+    }
+    return SECSuccess;
+}
+
 static PRBool
 pk11_isRootSlot(PK11SlotInfo *slot) 
 {
     CK_ATTRIBUTE findTemp[1];
     CK_ATTRIBUTE *attrs;
     CK_OBJECT_CLASS oclass = CKO_NETSCAPE_BUILTIN_ROOT_LIST;
     int tsize;
     CK_OBJECT_HANDLE handle;
@@ -4634,17 +4673,17 @@ PK11_WaitForTokenEvent(PK11SlotInfo *slo
 	PRIntervalTime interval;
 
 	if (waitForRemoval && series != PK11_GetSlotSeries(slot)) {
 	    return PK11TokenChanged;
 	}
 	if (timeout == PR_INTERVAL_NO_WAIT) {
 	    return waitForRemoval ? PK11TokenPresent : PK11TokenRemoved;
 	}
-	if (timeout == PR_INTERVAL_NO_TIMEOUT ) {
+	if (timeout != PR_INTERVAL_NO_TIMEOUT ) {
 	    interval = PR_IntervalNow();
 	    if (!first_time_set) {
 		first_time = interval;
 		first_time_set = PR_TRUE;
 	    }
 	    if ((interval-first_time) > timeout) {
 		return waitForRemoval ? PK11TokenPresent : PK11TokenRemoved;
 	    }
--- a/security/nss/lib/pk11wrap/secmodi.h
+++ b/security/nss/lib/pk11wrap/secmodi.h
@@ -102,12 +102,32 @@ SECStatus PK11_UpdateSlotAttribute(PK11S
 		(x)->pValue=(v); (x)->ulValueLen = (l);
 SECStatus PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
                                CK_ATTRIBUTE *theTemplate, int count,
                                 PRBool token, CK_OBJECT_HANDLE *objectID);
 
 SECStatus pbe_PK11AlgidToParam(SECAlgorithmID *algid,SECItem *mech);
 SECStatus PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, 
 				PRArenaPool *arena, SECAlgorithmID *algId);
+
+extern void pk11sdr_Init(void);
+extern void pk11sdr_Shutdown(void);
+
+typedef struct SECMODCallOnceType {
+    PRIntn initialized;
+    PRInt32 inProgress;
+    SECStatus status;
+} SECMODCallOnceType;
+
+typedef SECStatus (PR_CALLBACK *SECMODCallOnceFN)(void *arg);
+
+extern void SECMOD_InitCallOnce();
+
+extern SECStatus SECMOD_CallOnce(SECMODCallOnceType *once,
+                                 SECMODCallOnceFN    func,
+                                 void               *arg);
+
+extern void SECMOD_CleanupCallOnce();
+
 SEC_END_PROTOS
 
 #endif
 
--- a/security/nss/lib/pki/cryptocontext.c
+++ b/security/nss/lib/pki/cryptocontext.c
@@ -84,21 +84,25 @@ nssCryptoContext_Create (
     return rvCC;
 }
 
 NSS_IMPLEMENT PRStatus
 NSSCryptoContext_Destroy (
   NSSCryptoContext *cc
 )
 {
+    PRStatus status = PR_SUCCESS;
     if (cc->certStore) {
-	nssCertificateStore_Destroy(cc->certStore);
+	status = nssCertificateStore_Destroy(cc->certStore);
+	if (status == PR_FAILURE) {
+	    return status;
+	}
     }
     nssArena_Destroy(cc->arena);
-    return PR_SUCCESS;
+    return status;
 }
 
 NSS_IMPLEMENT PRStatus
 NSSCryptoContext_SetDefaultCallback (
   NSSCryptoContext *td,
   NSSCallback *newCallback,
   NSSCallback **oldCallbackOpt
 )
--- a/security/nss/lib/pki/pki3hack.c
+++ b/security/nss/lib/pki/pki3hack.c
@@ -82,27 +82,34 @@ STAN_GetDefaultTrustDomain()
 }
 
 NSSCryptoContext *
 STAN_GetDefaultCryptoContext()
 {
     return g_default_crypto_context;
 }
 
+extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
+
 NSS_IMPLEMENT PRStatus
 STAN_LoadDefaultNSS3TrustDomain (
   void
 )
 {
     NSSTrustDomain *td;
     NSSToken *token;
     SECMODModuleList *mlp;
     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
     int i;
 
+    if (g_default_trust_domain || g_default_crypto_context) {
+	/* Stan is already initialized or a previous shutdown failed. */
+	nss_SetError(NSS_ERROR_ALREADY_INITIALIZED);
+	return PR_FAILURE;
+    }
     td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL);
     if (!td) {
 	return PR_FAILURE;
     }
     td->tokenList = nssList_Create(td->arena, PR_TRUE);
     SECMOD_GetReadLock(moduleLock);
     for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp=mlp->next) {
 	for (i=0; i < mlp->module->slotCount; i++) {
@@ -155,25 +162,35 @@ STAN_RemoveModuleFromDefaultTrustDomain 
 	    nssToken_Destroy(token);
  	}
     }
     nssListIterator_Destroy(td->tokens);
     td->tokens = nssList_CreateIterator(td->tokenList);
     return SECSuccess;
 }
 
-NSS_IMPLEMENT void
+NSS_IMPLEMENT PRStatus
 STAN_Shutdown()
 {
+    PRStatus status = PR_SUCCESS;
     if (g_default_trust_domain) {
-	NSSTrustDomain_Destroy(g_default_trust_domain);
+	if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) {
+	    g_default_trust_domain = NULL;
+	} else {
+	    status = PR_FAILURE;
+	}
     }
     if (g_default_crypto_context) {
-	NSSCryptoContext_Destroy(g_default_crypto_context);
+	if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) {
+	    g_default_crypto_context = NULL;
+	} else {
+	    status = PR_FAILURE;
+	}
     }
+    return status;
 }
 
 /* this function should not be a hack; it will be needed in 4.0 (rename) */
 NSS_IMPLEMENT NSSItem *
 STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der)
 {
     NSSItem *rvKey;
     SECItem secDER;
@@ -243,17 +260,17 @@ nss3certificate_matchIdentifier(nssDecod
 {
     CERTCertificate *c = (CERTCertificate *)dc->data;
     CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
     SECItem skid;
     nssCertIDMatch match = nssCertIDMatch_Unknown;
 
     /* keyIdentifier */
     if (authKeyID->keyID.len > 0) {
-	if (CERT_FindSubjectKeyIDExten(c, &skid) == SECSuccess) {
+	if (CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) {
 	    PRBool skiEqual;
 	    skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
 	    PORT_Free(skid.data);
 	    if (skiEqual) {
 		/* change the state to positive match, but keep going */
 		match = nssCertIDMatch_Yes;
 	    } else {
 		/* exit immediately on failure */
--- a/security/nss/lib/pki/pki3hack.h
+++ b/security/nss/lib/pki/pki3hack.h
@@ -67,17 +67,17 @@ NSS_EXTERN NSSCryptoContext *
 STAN_GetDefaultCryptoContext();
 
 NSS_EXTERN PRStatus
 STAN_LoadDefaultNSS3TrustDomain
 (
   void
 );
 
-NSS_EXTERN void
+NSS_EXTERN PRStatus
 STAN_Shutdown();
 
 NSS_EXTERN SECStatus
 STAN_AddModuleToDefaultTrustDomain
 (
   SECMODModule *module
 );
 
--- a/security/nss/lib/pki/pkibase.c
+++ b/security/nss/lib/pki/pkibase.c
@@ -715,36 +715,39 @@ find_object_in_collection (
 	link = PR_NEXT_LINK(link);
     }
     return (pkiObjectCollectionNode *)NULL;
 }
 
 static pkiObjectCollectionNode *
 add_object_instance (
   nssPKIObjectCollection *collection,
-  nssCryptokiObject *instance
+  nssCryptokiObject *instance,
+  PRBool *foundIt
 )
 {
     PRUint32 i;
     PRStatus status;
     pkiObjectCollectionNode *node;
     nssArenaMark *mark = NULL;
     NSSItem uid[MAX_ITEMS_FOR_UID];
     nsslibc_memset(uid, 0, sizeof uid);
     /* The list is traversed twice, first (here) looking to match the
      * { token, handle } tuple, and if that is not found, below a search
      * for unique identifier is done.  Here, a match means this exact object
      * instance is already in the collection, and we have nothing to do.
      */
+    *foundIt = PR_FALSE;
     node = find_instance_in_collection(collection, instance);
     if (node) {
 	/* The collection is assumed to take over the instance.  Since we
 	 * are not using it, it must be destroyed.
 	 */
 	nssCryptokiObject_Destroy(instance);
+	*foundIt = PR_TRUE;
 	return node;
     }
     mark = nssArena_Mark(collection->arena);
     if (!mark) {
 	goto loser;
     }
     status = (*collection->getUIDFromInstance)(instance, uid, 
                                                collection->arena);
@@ -793,23 +796,24 @@ NSS_IMPLEMENT PRStatus
 nssPKIObjectCollection_AddInstances (
   nssPKIObjectCollection *collection,
   nssCryptokiObject **instances,
   PRUint32 numInstances
 )
 {
     PRStatus status = PR_SUCCESS;
     PRUint32 i = 0;
+    PRBool foundIt;
     pkiObjectCollectionNode *node;
     if (instances) {
 	for (; *instances; instances++, i++) {
 	    if (numInstances > 0 && i == numInstances) {
 		break;
 	    }
-	    node = add_object_instance(collection, *instances);
+	    node = add_object_instance(collection, *instances, &foundIt);
 	    if (node == NULL) {
 		goto loser;
 	    }
 	}
     }
     return status;
 loser:
     /* free the remaining instances */
@@ -912,35 +916,39 @@ nssPKIObjectCollection_Traverse (
 
 NSS_IMPLEMENT PRStatus
 nssPKIObjectCollection_AddInstanceAsObject (
   nssPKIObjectCollection *collection,
   nssCryptokiObject *instance
 )
 {
     pkiObjectCollectionNode *node;
-    node = add_object_instance(collection, instance);
+    PRBool foundIt;
+    node = add_object_instance(collection, instance, &foundIt);
     if (node == NULL) {
 	return PR_FAILURE;
     }
     if (!node->haveObject) {
 	node->object = (*collection->createObject)(node->object);
 	if (!node->object) {
 	    /*remove bogus object from list*/
 	    nssPKIObjectCollection_RemoveNode(collection,node);
 	    return PR_FAILURE;
 	}
 	node->haveObject = PR_TRUE;
     }
 #ifdef NSS_3_4_CODE
-    else {
+    else if (!foundIt) {
 	/* The instance was added to a pre-existing node.  This
 	 * function is *only* being used for certificates, and having
 	 * multiple instances of certs in 3.X requires updating the
 	 * CERTCertificate.
+	 * But only do it if it was a new instance!!!  If the same instance
+	 * is encountered, we set *foundIt to true.  Detect that here and
+	 * ignore it.
 	 */
 	STAN_ForceCERTCertificateUpdate((NSSCertificate *)node->object);
     }
 #endif
     return PR_SUCCESS;
 }
 
 /*
--- a/security/nss/lib/pki/pkistore.c
+++ b/security/nss/lib/pki/pkistore.c
@@ -155,29 +155,36 @@ loser:
 	}
     }
     if (i_alloced_arena) {
 	nssArena_Destroy(arena);
     }
     return NULL;
 }
 
-NSS_IMPLEMENT void
+extern const NSSError NSS_ERROR_BUSY;
+
+NSS_IMPLEMENT PRStatus
 nssCertificateStore_Destroy (
   nssCertificateStore *store
 )
 {
+    if (nssHash_Count(store->issuer_and_serial) > 0) {
+	nss_SetError(NSS_ERROR_BUSY);
+	return PR_FAILURE;
+    }
     PZ_DestroyLock(store->lock);
     nssHash_Destroy(store->issuer_and_serial);
     nssHash_Destroy(store->subject);
     if (store->i_alloced_arena) {
 	nssArena_Destroy(store->arena);
     } else {
 	nss_ZFreeIf(store);
     }
+    return PR_SUCCESS;
 }
 
 static PRStatus
 add_certificate_entry (
   nssCertificateStore *store,
   NSSCertificate *cert
 )
 {
--- a/security/nss/lib/pki/pkistore.h
+++ b/security/nss/lib/pki/pkistore.h
@@ -67,17 +67,17 @@ PR_BEGIN_EXTERN_C
  */
 
 NSS_EXTERN nssCertificateStore *
 nssCertificateStore_Create
 (
   NSSArena *arenaOpt
 );
 
-NSS_EXTERN void
+NSS_EXTERN PRStatus
 nssCertificateStore_Destroy
 (
   nssCertificateStore *store
 );
 
 NSS_EXTERN PRStatus
 nssCertificateStore_Add
 (
--- a/security/nss/lib/pki/tdcache.c
+++ b/security/nss/lib/pki/tdcache.c
@@ -229,22 +229,30 @@ loser:
 
 /* The entries of the hashtable are currently dependent on the certificate(s)
  * that produced them.  That is, the entries will be freed when the cert is
  * released from the cache.  If there are certs in the cache at any time,
  * including shutdown, the hash table entries will hold memory.  In order for
  * clean shutdown, it is necessary for there to be no certs in the cache.
  */
 
+extern const NSSError NSS_ERROR_INTERNAL_ERROR;
+extern const NSSError NSS_ERROR_BUSY;
+
 NSS_IMPLEMENT PRStatus
 nssTrustDomain_DestroyCache (
   NSSTrustDomain *td
 )
 {
     if (!td->cache) {
+	nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+	return PR_FAILURE;
+    }
+    if (nssHash_Count(td->cache->issuerAndSN) > 0) {
+	nss_SetError(NSS_ERROR_BUSY);
 	return PR_FAILURE;
     }
     PZ_DestroyLock(td->cache->lock);
     nssHash_Destroy(td->cache->issuerAndSN);
     nssHash_Destroy(td->cache->subject);
     nssHash_Destroy(td->cache->nickname);
     nssHash_Destroy(td->cache->email);
     nssArena_Destroy(td->cache->arena);
--- a/security/nss/lib/pki/trustdomain.c
+++ b/security/nss/lib/pki/trustdomain.c
@@ -111,28 +111,32 @@ token_destructor(void *t)
     nssToken_Destroy(tok);
 }
 
 NSS_IMPLEMENT PRStatus
 NSSTrustDomain_Destroy (
   NSSTrustDomain *td
 )
 {
+    PRStatus status = PR_SUCCESS;
     if (--td->refCount == 0) {
 	/* Destroy each token in the list of tokens */
 	if (td->tokens) {
 	    nssListIterator_Destroy(td->tokens);
 	    nssList_Clear(td->tokenList, token_destructor);
 	    nssList_Destroy(td->tokenList);
 	}
-	nssTrustDomain_DestroyCache(td);
+	status = nssTrustDomain_DestroyCache(td);
+	if (status == PR_FAILURE) {
+	    return status;
+	}
 	/* Destroy the trust domain */
 	nssArena_Destroy(td->arena);
     }
-    return PR_SUCCESS;
+    return status;
 }
 
 /* XXX uses tokens until slot list is in place */
 static NSSSlot **
 nssTrustDomain_GetActiveSlots (
   NSSTrustDomain *td,
   nssUpdateLevel *updateLevel
 )
--- a/security/nss/lib/pki1/config.mk
+++ b/security/nss/lib/pki1/config.mk
@@ -36,12 +36,12 @@ ifdef BUILD_IDG
 DEFINES += -DNSSDEBUG
 endif
 
 #
 #  Override TARGETS variable so that only static libraries
 #  are specifed as dependencies within rules.mk.
 #
 
-TARGETS        = 
+TARGETS        = $(LIBRARY)
 SHARED_LIBRARY =
 IMPORT_LIBRARY =
 PROGRAM        =
--- a/security/nss/lib/pki1/manifest.mn
+++ b/security/nss/lib/pki1/manifest.mn
@@ -43,23 +43,22 @@ PRIVATE_EXPORTS = \
 	nsspki1t.h \
 	$(NULL)
 
 EXPORTS =	   \
 	$(NULL)
 
 MODULE = nss
 
-CSRCS = $(NULL)
-xCSRCS =	  \
+CSRCS =		  \
 	atav.c	  \
 	genname.c \
 	gnseq.c	  \
 	name.c	  \
 	oid.c	  \
 	oiddata.c \
 	rdn.c	  \
 	rdnseq.c  \
 	$(NULL)
 
 REQUIRES = nspr
 
-#LIBRARY_NAME = pki1
+LIBRARY_NAME = pki1
--- a/security/nss/lib/smime/cms.h
+++ b/security/nss/lib/smime/cms.h
@@ -854,16 +854,25 @@ NSS_CMSEnvelopedData_Decode_AfterEnd(NSS
  * NSS_CMSRecipientInfo_Create - create a recipientinfo
  *
  * we currently do not create KeyAgreement recipientinfos with multiple recipientEncryptedKeys
  * the certificate is supposed to have been verified by the caller
  */
 extern NSSCMSRecipientInfo *
 NSS_CMSRecipientInfo_Create(NSSCMSMessage *cmsg, CERTCertificate *cert);
 
+extern NSSCMSRecipientInfo *
+NSS_CMSRecipientInfo_CreateWithSubjKeyID(NSSCMSMessage   *cmsg, 
+                                         SECItem         *subjKeyID,
+                                         SECKEYPublicKey *pubKey);
+
+extern NSSCMSRecipientInfo *
+NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert(NSSCMSMessage *cmsg, 
+                                                 CERTCertificate *cert);
+
 extern void
 NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo *ri);
 
 extern int
 NSS_CMSRecipientInfo_GetVersion(NSSCMSRecipientInfo *ri);
 
 extern SECItem *
 NSS_CMSRecipientInfo_GetEncryptedKey(NSSCMSRecipientInfo *ri, int subIndex);
--- a/security/nss/lib/smime/cmsencdata.c
+++ b/security/nss/lib/smime/cmsencdata.c
@@ -156,16 +156,17 @@ NSS_CMSEncryptedData_Encode_BeforeStart(
     if (encd->cmsg->decrypt_key_cb)
 	bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, 
 		    NSS_CMSContentInfo_GetContentEncAlg(cinfo));
     if (bulkkey == NULL)
 	return SECFailure;
 
     /* store the bulk key in the contentInfo so that the encoder can find it */
     NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey);
+    PK11_FreeSymKey(bulkkey);
 
     return SECSuccess;
 }
 
 /*
  * NSS_CMSEncryptedData_Encode_BeforeData - set up encryption
  */
 SECStatus
--- a/security/nss/lib/smime/cmslocal.h
+++ b/security/nss/lib/smime/cmslocal.h
@@ -156,18 +156,24 @@ NSS_CMSCipherContext_Encrypt(NSSCMSCiphe
 
 /*
  * NSS_CMSUtil_EncryptSymKey_RSA - wrap a symmetric key with RSA
  *
  * this function takes a symmetric key and encrypts it using an RSA public key
  * according to PKCS#1 and RFC2633 (S/MIME)
  */
 extern SECStatus
-NSS_CMSUtil_EncryptSymKey_RSA(PLArenaPool *poolp, CERTCertificate *cert, PK11SymKey *key,
-			SECItem *encKey);
+NSS_CMSUtil_EncryptSymKey_RSA(PLArenaPool *poolp, CERTCertificate *cert,
+                              PK11SymKey *key,
+                              SECItem *encKey);
+
+extern SECStatus
+NSS_CMSUtil_EncryptSymKey_RSAPubKey(PLArenaPool *poolp,
+                                    SECKEYPublicKey *publickey,
+                                    PK11SymKey *bulkkey, SECItem *encKey);
 
 /*
  * NSS_CMSUtil_DecryptSymKey_RSA - unwrap a RSA-wrapped symmetric key
  *
  * this function takes an RSA-wrapped symmetric key and unwraps it, returning a symmetric
  * key handle. Please note that the actual unwrapped key data may not be allowed to leave
  * a hardware token...
  */
--- a/security/nss/lib/smime/cmspubkey.c
+++ b/security/nss/lib/smime/cmspubkey.c
@@ -51,51 +51,64 @@
 
 /*
  * NSS_CMSUtil_EncryptSymKey_RSA - wrap a symmetric key with RSA
  *
  * this function takes a symmetric key and encrypts it using an RSA public key
  * according to PKCS#1 and RFC2633 (S/MIME)
  */
 SECStatus
-NSS_CMSUtil_EncryptSymKey_RSA(PLArenaPool *poolp, CERTCertificate *cert, PK11SymKey *bulkkey,
-			SECItem *encKey)
+NSS_CMSUtil_EncryptSymKey_RSA(PLArenaPool *poolp, CERTCertificate *cert, 
+                              PK11SymKey *bulkkey,
+                              SECItem *encKey)
 {
-    SECOidTag certalgtag;	/* the certificate's encryption algorithm */
-    SECOidTag encalgtag;	/* the algorithm used for key exchange/agreement */
     SECStatus rv;
     SECKEYPublicKey *publickey;
+
+    publickey = CERT_ExtractPublicKey(cert);
+    if (publickey == NULL)
+	return SECFailure;
+
+    rv = NSS_CMSUtil_EncryptSymKey_RSAPubKey(poolp, publickey, bulkkey, encKey);
+    SECKEY_DestroyPublicKey(publickey);
+    return rv;
+}
+
+SECStatus
+NSS_CMSUtil_EncryptSymKey_RSAPubKey(PLArenaPool *poolp, 
+                                    SECKEYPublicKey *publickey, 
+                                    PK11SymKey *bulkkey, SECItem *encKey)
+{
+    SECStatus rv;
     int data_len;
+    KeyType keyType;
     void *mark = NULL;
 
-    /* sanity check */
-    certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
-    PORT_Assert(certalgtag == SEC_OID_PKCS1_RSA_ENCRYPTION);
 
-    encalgtag = SEC_OID_PKCS1_RSA_ENCRYPTION;
-    publickey = CERT_ExtractPublicKey(cert);
-    if (publickey == NULL)
-	goto loser;
-	
     mark = PORT_ArenaMark(poolp);
     if (!mark)
 	goto loser;
 
+    /* sanity check */
+    keyType = SECKEY_GetPublicKeyType(publickey);
+    PORT_Assert(keyType == rsaKey);
+    if (keyType != rsaKey) {
+	goto loser;
+    }
     /* allocate memory for the encrypted key */
     data_len = SECKEY_PublicKeyStrength(publickey);	/* block size (assumed to be > keylen) */
     encKey->data = (unsigned char*)PORT_ArenaAlloc(poolp, data_len);
     encKey->len = data_len;
     if (encKey->data == NULL)
 	goto loser;
 
     /* encrypt the key now */
     rv = PK11_PubWrapSymKey(PK11_AlgtagToMechanism(SEC_OID_PKCS1_RSA_ENCRYPTION),
 				publickey, bulkkey, encKey);
 
-    SECKEY_DestroyPublicKey(publickey);
     if (rv != SECSuccess)
 	goto loser;
 
     PORT_ArenaUnmark(poolp, mark);
     return SECSuccess;
 
 loser:
     if (mark) {
--- a/security/nss/lib/smime/cmsrecinfo.c
+++ b/security/nss/lib/smime/cmsrecinfo.c
@@ -42,75 +42,130 @@
 #include "cert.h"
 #include "key.h"
 #include "secasn1.h"
 #include "secitem.h"
 #include "secoid.h"
 #include "pk11func.h"
 #include "secerr.h"
 
-/*
- * NSS_CMSRecipientInfo_Create - create a recipientinfo
- *
- * we currently do not create KeyAgreement recipientinfos with multiple recipientEncryptedKeys
- * the certificate is supposed to have been verified by the caller
- */
+PRBool
+nss_cmsrecipientinfo_usessubjectkeyid(NSSCMSRecipientInfo *ri)
+{
+    if (ri->recipientInfoType == NSSCMSRecipientInfoID_KeyTrans) {
+	NSSCMSRecipientIdentifier *rid;
+	rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier;
+	if (rid->identifierType == NSSCMSRecipientID_SubjectKeyID) {
+	    return PR_TRUE;
+	}
+    }
+    return PR_FALSE;
+}
+
+
 NSSCMSRecipientInfo *
-NSS_CMSRecipientInfo_Create(NSSCMSMessage *cmsg, CERTCertificate *cert)
+nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type,
+                            CERTCertificate *cert, SECKEYPublicKey *pubKey, 
+                            SECItem *subjKeyID)
 {
     NSSCMSRecipientInfo *ri;
     void *mark;
     SECOidTag certalgtag;
     SECStatus rv = SECSuccess;
     NSSCMSRecipientEncryptedKey *rek;
     NSSCMSOriginatorIdentifierOrKey *oiok;
     unsigned long version;
     SECItem *dummy;
     PLArenaPool *poolp;
+    CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL;
+    NSSCMSRecipientIdentifier *rid;
 
     poolp = cmsg->poolp;
 
     mark = PORT_ArenaMark(poolp);
 
     ri = (NSSCMSRecipientInfo *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSRecipientInfo));
     if (ri == NULL)
 	goto loser;
 
     ri->cmsg = cmsg;
-    ri->cert = CERT_DupCertificate(cert);
-    if (ri->cert == NULL)
-	goto loser;
+    if (type == NSSCMSRecipientID_IssuerSN) {
+	ri->cert = CERT_DupCertificate(cert);
+	if (ri->cert == NULL)
+	    goto loser;
+	spki = &(cert->subjectPublicKeyInfo);
+    } else {
+	PORT_Assert(pubKey);
+	spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
+    }
 
-    certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
+    certalgtag = SECOID_GetAlgorithmTag(&(spki->algorithm));
 
+    rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier;
     switch (certalgtag) {
     case SEC_OID_PKCS1_RSA_ENCRYPTION:
 	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans;
-	/* hardcoded issuerSN choice for now */
-	ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType = NSSCMSRecipientID_IssuerSN;
-	ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);
-	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) {
+	rid->identifierType = type;
+	if (type == NSSCMSRecipientID_IssuerSN) {
+	    rid->id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);
+	    if (rid->id.issuerAndSN == NULL) {
+	      break;
+	    }
+	} else if (type == NSSCMSRecipientID_SubjectKeyID){
+	    NSSCMSKeyTransRecipientInfoEx *riExtra;
+
+	    rid->id.subjectKeyID = PORT_ArenaNew(poolp, SECItem);
+	    if (rid->id.subjectKeyID == NULL) {
+		rv = SECFailure;
+		PORT_SetError(SEC_ERROR_NO_MEMORY);
+		break;
+	    } 
+	    SECITEM_CopyItem(poolp, rid->id.subjectKeyID, subjKeyID);
+	    if (rid->id.subjectKeyID->data == NULL) {
+		rv = SECFailure;
+		PORT_SetError(SEC_ERROR_NO_MEMORY);
+		break;
+	    }
+	    riExtra = &ri->ri.keyTransRecipientInfoEx;
+	    riExtra->version = 0;
+	    riExtra->pubKey = SECKEY_CopyPublicKey(pubKey);
+	    if (riExtra->pubKey == NULL) {
+		rv = SECFailure;
+		PORT_SetError(SEC_ERROR_NO_MEMORY);
+		break;
+	    }
+	} else {
+	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	    rv = SECFailure;
-	    break;
 	}
 	break;
     case SEC_OID_MISSI_KEA_DSS_OLD:
     case SEC_OID_MISSI_KEA_DSS:
     case SEC_OID_MISSI_KEA:
+        PORT_Assert(type != NSSCMSRecipientID_SubjectKeyID);
+	if (type == NSSCMSRecipientID_SubjectKeyID) {
+	    rv = SECFailure;
+	    break;
+	}
 	/* backward compatibility - this is not really a keytrans operation */
 	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans;
 	/* hardcoded issuerSN choice for now */
 	ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType = NSSCMSRecipientID_IssuerSN;
 	ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);
 	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) {
 	    rv = SECFailure;
 	    break;
 	}
 	break;
     case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
+        PORT_Assert(type != NSSCMSRecipientID_SubjectKeyID);
+	if (type == NSSCMSRecipientID_SubjectKeyID) {
+	    rv = SECFailure;
+	    break;
+	}
 	/* a key agreement op */
 	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyAgree;
 
 	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) {
 	    rv = SECFailure;
 	    break;
 	}
 	/* we do not support the case where multiple recipients 
@@ -179,30 +234,95 @@ NSS_CMSRecipientInfo_Create(NSSCMSMessag
 						NSS_CMS_KEK_RECIPIENT_INFO_VERSION);
 	if (dummy == NULL)
 	    goto loser;
 	break;
     
     }
 
     PORT_ArenaUnmark (poolp, mark);
+    if (freeSpki)
+      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
     return ri;
 
 loser:
+    if (freeSpki)
+      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
     PORT_ArenaRelease (poolp, mark);
     return NULL;
 }
 
+/*
+ * NSS_CMSRecipientInfo_Create - create a recipientinfo
+ *
+ * we currently do not create KeyAgreement recipientinfos with multiple 
+ * recipientEncryptedKeys the certificate is supposed to have been 
+ * verified by the caller
+ */
+NSSCMSRecipientInfo *
+NSS_CMSRecipientInfo_Create(NSSCMSMessage *cmsg, CERTCertificate *cert)
+{
+    return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_IssuerSN, cert, 
+                                       NULL, NULL);
+}
+
+NSSCMSRecipientInfo *
+NSS_CMSRecipientInfo_CreateWithSubjKeyID(NSSCMSMessage   *cmsg, 
+                                     SECItem         *subjKeyID,
+                                     SECKEYPublicKey *pubKey)
+{
+    return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_SubjectKeyID, 
+                                       NULL, pubKey, subjKeyID);
+}
+
+NSSCMSRecipientInfo *
+NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert(NSSCMSMessage *cmsg,
+                                             CERTCertificate *cert)
+{
+    SECKEYPublicKey *pubKey = NULL;
+    SECItem subjKeyID = {siBuffer, NULL, 0};
+    NSSCMSRecipientInfo *retVal = NULL;
+
+    if (!cmsg || !cert) {
+	return NULL;
+    }
+    pubKey = CERT_ExtractPublicKey(cert);
+    if (!pubKey) {
+	goto done;
+    }
+    if (CERT_FindSubjectKeyIDExtension(cert, &subjKeyID) != SECSuccess ||
+        subjKeyID.data == NULL) {
+	goto done;
+    }
+    retVal = NSS_CMSRecipientInfo_CreateWithSubjKeyID(cmsg, &subjKeyID, pubKey);
+done:
+    if (pubKey)
+	SECKEY_DestroyPublicKey(pubKey);
+
+    if (subjKeyID.data)
+	SECITEM_FreeItem(&subjKeyID, PR_FALSE);
+
+    return retVal;
+}
+
 void
 NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo *ri)
 {
     /* version was allocated on the pool, so no need to destroy it */
     /* issuerAndSN was allocated on the pool, so no need to destroy it */
     if (ri->cert != NULL)
 	CERT_DestroyCertificate(ri->cert);
+
+    if (nss_cmsrecipientinfo_usessubjectkeyid(ri)) {
+	NSSCMSKeyTransRecipientInfoEx *extra;
+	extra = &ri->ri.keyTransRecipientInfoEx;
+	if (extra->pubKey)
+	    SECKEY_DestroyPublicKey(extra->pubKey);
+    }
+
     /* recipientInfo structure itself was allocated on the pool, so no need to destroy it */
     /* we're done. */
 }
 
 int
 NSS_CMSRecipientInfo_GetVersion(NSSCMSRecipientInfo *ri)
 {
     unsigned long version;
@@ -270,42 +390,68 @@ NSS_CMSRecipientInfo_GetKeyEncryptionAlg
     case NSSCMSRecipientInfoID_KEK:
 	encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.kekRecipientInfo.keyEncAlg));
 	break;
     }
     return encalgtag;
 }
 
 SECStatus
-NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey, SECOidTag bulkalgtag)
+NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey, 
+                                 SECOidTag bulkalgtag)
 {
     CERTCertificate *cert;
     SECOidTag certalgtag;
     SECStatus rv = SECSuccess;
     SECItem *params = NULL;
     NSSCMSRecipientEncryptedKey *rek;
     NSSCMSOriginatorIdentifierOrKey *oiok;
+    CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL;
     PLArenaPool *poolp;
+    NSSCMSKeyTransRecipientInfoEx *extra;
+    PRBool usesSubjKeyID;
 
     poolp = ri->cmsg->poolp;
     cert = ri->cert;
-    PORT_Assert (cert != NULL);
-    if (cert == NULL)
+    usesSubjKeyID = nss_cmsrecipientinfo_usessubjectkeyid(ri);
+    if (cert) {
+	spki = &cert->subjectPublicKeyInfo;
+	certalgtag = SECOID_GetAlgorithmTag(&(spki->algorithm));
+    } else if (usesSubjKeyID) {
+	extra = &ri->ri.keyTransRecipientInfoEx;
+	/* sanity check */
+	PORT_Assert(extra->pubKey);
+	if (!extra->pubKey) {
+	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
+	    return SECFailure;
+	}
+	spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(extra->pubKey);
+	certalgtag = SECOID_GetAlgorithmTag(&spki->algorithm);
+    } else {
+	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return SECFailure;
+    }
 
     /* XXX set ri->recipientInfoType to the proper value here */
     /* or should we look if it's been set already ? */
 
-    certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
+    certalgtag = SECOID_GetAlgorithmTag(&spki->algorithm);
     switch (certalgtag) {
     case SEC_OID_PKCS1_RSA_ENCRYPTION:
 	/* wrap the symkey */
-	if (NSS_CMSUtil_EncryptSymKey_RSA(poolp, cert, bulkkey, &ri->ri.keyTransRecipientInfo.encKey) != SECSuccess) {
-	    rv = SECFailure;
-	    break;
+	if (cert) {
+	    rv = NSS_CMSUtil_EncryptSymKey_RSA(poolp, cert, bulkkey, 
+	                         &ri->ri.keyTransRecipientInfo.encKey);
+ 	    if (rv != SECSuccess)
+		break;
+	} else if (usesSubjKeyID) {
+	    rv = NSS_CMSUtil_EncryptSymKey_RSAPubKey(poolp, extra->pubKey,
+	                         bulkkey, &ri->ri.keyTransRecipientInfo.encKey);
+ 	    if (rv != SECSuccess)
+		break;
 	}
 
 	rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL);
 	break;
     case SEC_OID_MISSI_KEA_DSS_OLD:
     case SEC_OID_MISSI_KEA_DSS:
     case SEC_OID_MISSI_KEA:
 	rv = NSS_CMSUtil_EncryptSymKey_MISSI(poolp, cert, bulkkey,
@@ -348,16 +494,19 @@ NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSR
 	break;
     default:
 	/* other algorithms not supported yet */
 	/* NOTE that we do not support any KEK algorithm */
 	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
 	rv = SECFailure;
 	break;
     }
+    if (freeSpki)
+	SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
+
     return rv;
 }
 
 PK11SymKey *
 NSS_CMSRecipientInfo_UnwrapBulkKey(NSSCMSRecipientInfo *ri, int subIndex, 
 	CERTCertificate *cert, SECKEYPrivateKey *privkey, SECOidTag bulkalgtag)
 {
     PK11SymKey *bulkkey = NULL;
--- a/security/nss/lib/smime/cmssigdata.c
+++ b/security/nss/lib/smime/cmssigdata.c
@@ -455,30 +455,110 @@ NSS_CMSSignedData_GetCertificateList(NSS
     return sigd->rawCerts;
 }
 
 SECStatus
 NSS_CMSSignedData_ImportCerts(NSSCMSSignedData *sigd, CERTCertDBHandle *certdb,
 				SECCertUsage certusage, PRBool keepcerts)
 {
     int certcount;
+    CERTCertificate **certArray = NULL;
+    CERTCertList *certList = NULL;
+    CERTCertListNode *node;
     SECStatus rv;
+    SECItem **rawArray;
     int i;
+    PRTime now;
 
     certcount = NSS_CMSArray_Count((void **)sigd->rawCerts);
 
-    rv = CERT_ImportCerts(certdb, certusage, certcount, sigd->rawCerts, NULL,
-			  keepcerts, PR_FALSE, NULL);
+    /* get the certs in the temp DB */
+    rv = CERT_ImportCerts(certdb, certusage, certcount, sigd->rawCerts, 
+			 &certArray, PR_FALSE, PR_FALSE, NULL);
+    if (rv != SECSuccess) {
+	goto loser;
+    }
+
+    if (!keepcerts) {
+	goto done;
+    }
+
+    /* build a CertList for filtering */
+    certList = CERT_NewCertList();
+    if (certList == NULL) {
+	rv = SECFailure;
+	goto loser;
+    }
+    for (i=0; i < certcount; i++) {
+	CERTCertificate *cert = CERT_DupCertificate(certArray[i]);
+	CERT_AddCertToListTail(certList,cert);
+    }
+
+    /* filter out the certs we don't want */
+    rv = CERT_FilterCertListByUsage(certList,certusage, PR_FALSE);
+    if (rv != SECSuccess) {
+	goto loser;
+    }
+
+    /* go down the remaining list of certs and verify that they have
+     * valid chains, then import them.
+     */
+    now = PR_Now();
+    for (node = CERT_LIST_HEAD(certList) ; !CERT_LIST_END(node,certList);
+						node= CERT_LIST_NEXT(node)) {
+	CERTCertificateList *certChain;
+
+	if (CERT_VerifyCert(certdb, node->cert, 
+		PR_TRUE, certusage, now, NULL, NULL) != SECSuccess) {
+	    continue;
+	}
+
+	certChain = CERT_CertChainFromCert(node->cert, certusage, PR_FALSE);
+	if (!certChain) {
+	    continue;
+	}
+
+	/*
+	 * CertChain returns an array of SECItems, import expects an array of
+	 * SECItem pointers. Create the SECItem Pointers from the array of
+	 * SECItems.
+ 	 */
+	rawArray = (SECItem **)PORT_Alloc(certChain->len*sizeof (SECItem *));
+	if (!rawArray) {
+	    CERT_DestroyCertificateList(certChain);
+	    continue;
+	}
+	for (i=0; i < certChain->len; i++) {
+	    rawArray[i] = &certChain->certs[i];
+	}
+	(void )CERT_ImportCerts(certdb, certusage, certChain->len, 
+			rawArray,  NULL, keepcerts, PR_FALSE, NULL);
+	PORT_Free(rawArray);
+	CERT_DestroyCertificateList(certChain);
+    }
+
+    rv = SECSuccess;
 
     /* XXX CRL handling */
 
+done:
     if (sigd->signerInfos != NULL) {
 	/* fill in all signerinfo's certs */
 	for (i = 0; sigd->signerInfos[i] != NULL; i++)
-	    (void)NSS_CMSSignerInfo_GetSigningCertificate(sigd->signerInfos[i], certdb);
+	    (void)NSS_CMSSignerInfo_GetSigningCertificate(
+						sigd->signerInfos[i], certdb);
+    }
+
+loser:
+    /* now free everything */
+    if (certArray) {
+	CERT_DestroyCertArray(certArray,certcount);
+    }
+    if (certList) {
+	CERT_DestroyCertList(certList);
     }
 
     return rv;
 }
 
 /*
  * XXX the digests need to be passed in BETWEEN the decoding and the verification in case
  *     of external signatures!
@@ -526,34 +606,36 @@ SECStatus
 NSS_CMSSignedData_VerifyCertsOnly(NSSCMSSignedData *sigd, 
                                   CERTCertDBHandle *certdb, 
                                   SECCertUsage usage)
 {
     CERTCertificate *cert;
     SECStatus rv = SECSuccess;
     int i;
     int count;
+    PRTime now;
 
     if (!sigd || !certdb || !sigd->rawCerts) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return SECFailure;
     }
 
     count = NSS_CMSArray_Count((void**)sigd->rawCerts);
+    now = PR_Now();
     for (i=0; i < count; i++) {
 	if (sigd->certs && sigd->certs[i]) {
 	    cert = CERT_DupCertificate(sigd->certs[i]);
 	} else {
 	    cert = CERT_FindCertByDERCert(certdb, sigd->rawCerts[i]);
 	    if (!cert) {
 		rv = SECFailure;
 		break;
 	    }
 	}
-	rv |= CERT_VerifyCert(certdb, cert, PR_TRUE, usage, PR_Now(), 
+	rv |= CERT_VerifyCert(certdb, cert, PR_TRUE, usage, now, 
                               NULL, NULL);
 	CERT_DestroyCertificate(cert);
     }
 
     return rv;
 }
 
 /*
--- a/security/nss/lib/smime/cmssiginfo.c
+++ b/security/nss/lib/smime/cmssiginfo.c
@@ -561,40 +561,38 @@ NSS_CMSSignerInfo_GetSigningTime(NSSCMSS
  * Return the signing cert of a CMS signerInfo.
  *
  * the certs in the enclosing SignedData must have been imported already
  */
 CERTCertificate *
 NSS_CMSSignerInfo_GetSigningCertificate(NSSCMSSignerInfo *signerinfo, CERTCertDBHandle *certdb)
 {
     CERTCertificate *cert;
+    NSSCMSSignerIdentifier *sid;
 
     if (signerinfo->cert != NULL)
 	return signerinfo->cert;
 
     /* no certdb, and cert hasn't been set yet? */
     if (certdb == NULL)
 	return NULL;
 
     /*
      * This cert will also need to be freed, but since we save it
      * in signerinfo for later, we do not want to destroy it when
      * we leave this function -- we let the clean-up of the entire
      * cinfo structure later do the destroy of this cert.
      */
-    switch (signerinfo->signerIdentifier.identifierType) {
+    sid = &signerinfo->signerIdentifier;
+    switch (sid->identifierType) {
     case NSSCMSSignerID_IssuerSN:
-	cert = CERT_FindCertByIssuerAndSN(certdb, signerinfo->signerIdentifier.id.issuerAndSN);
+	cert = CERT_FindCertByIssuerAndSN(certdb, sid->id.issuerAndSN);
 	break;
     case NSSCMSSignerID_SubjectKeyID:
-#if 0 /* not yet implemented */
-	cert = CERT_FindCertBySubjectKeyID(certdb, signerinfo->signerIdentifier.id.subjectKeyID);
-#else
-	cert = NULL;
-#endif
+	cert = CERT_FindCertBySubjectKeyID(certdb, sid->id.subjectKeyID);
 	break;
     default:
 	cert = NULL;
 	break;
     }
 
     /* cert can be NULL at that point */
     signerinfo->cert = cert;	/* earmark it */
--- a/security/nss/lib/smime/cmst.h
+++ b/security/nss/lib/smime/cmst.h
@@ -298,16 +298,28 @@ typedef struct NSSCMSRecipientIdentifier
 struct NSSCMSKeyTransRecipientInfoStr {
     SECItem			version;
     NSSCMSRecipientIdentifier	recipientIdentifier;
     SECAlgorithmID		keyEncAlg;
     SECItem			encKey;
 };
 typedef struct NSSCMSKeyTransRecipientInfoStr NSSCMSKeyTransRecipientInfo;
 
+/*
+ * View comments before NSSCMSRecipientInfoStr for purpose of this
+ * structure.
+ */
+struct NSSCMSKeyTransRecipientInfoExStr {
+    NSSCMSKeyTransRecipientInfo recipientInfo;
+    int version;
+    SECKEYPublicKey *pubKey;
+};
+
+typedef struct NSSCMSKeyTransRecipientInfoExStr NSSCMSKeyTransRecipientInfoEx;
+
 #define NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN	0	/* what we *create* */
 #define NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY		2	/* what we *create* */
 
 /* -----------------------------------------------------------------------------
  * key agreement recipient info
  */
 struct NSSCMSOriginatorPublicKeyStr {
     SECAlgorithmID			algorithmIdentifier;
@@ -394,22 +406,45 @@ typedef struct NSSCMSKEKRecipientInfoStr
  */
 
 typedef enum {
     NSSCMSRecipientInfoID_KeyTrans = 0,
     NSSCMSRecipientInfoID_KeyAgree = 1,
     NSSCMSRecipientInfoID_KEK = 2
 } NSSCMSRecipientInfoIDSelector;
 
+/*
+ * In order to preserve backwards binary compatibility when implementing
+ * creation of Recipient Info's that uses subjectKeyID in the 
+ * keyTransRecipientInfo we need to stash a public key pointer in this
+ * structure somewhere.  We figured out that NSSCMSKeyTransRecipientInfo
+ * is the smallest member of the ri union.  We're in luck since that's
+ * the very structure that would need to use the public key. So we created
+ * a new structure NSSCMSKeyTransRecipientInfoEx which has a member 
+ * NSSCMSKeyTransRecipientInfo as the first member followed by a version
+ * and a public key pointer.  This way we can keep backwards compatibility
+ * without changing the size of this structure.
+ *
+ * BTW, size of structure:
+ * NSSCMSKeyTransRecipientInfo:  9 ints, 4 pointers
+ * NSSCMSKeyAgreeRecipientInfo: 12 ints, 8 pointers
+ * NSSCMSKEKRecipientInfo:      10 ints, 7 pointers
+ *
+ * The new structure:
+ * NSSCMSKeyTransRecipientInfoEx: sizeof(NSSCMSKeyTransRecipientInfo) +
+ *                                1 int, 1 pointer
+ */
+
 struct NSSCMSRecipientInfoStr {
     NSSCMSRecipientInfoIDSelector recipientInfoType;
     union {
 	NSSCMSKeyTransRecipientInfo keyTransRecipientInfo;
 	NSSCMSKeyAgreeRecipientInfo keyAgreeRecipientInfo;
 	NSSCMSKEKRecipientInfo kekRecipientInfo;
+	NSSCMSKeyTransRecipientInfoEx keyTransRecipientInfoEx;
     } ri;
     /* --------- local; not part of encoding --------- */
     NSSCMSMessage *		cmsg;			/* back pointer to message */
     CERTCertificate *		cert;			/* recipient's certificate */
 };
 
 /* =============================================================================
  * DIGESTED DATA
--- a/security/nss/lib/smime/smime.def
+++ b/security/nss/lib/smime/smime.def
@@ -211,8 +211,22 @@ NSS_CMSMessage_IsEncrypted;
 ;+};
 ;+NSS_3.6 {     # NSS 3.6 release
 ;+    global:
 NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs;
 NSS_CMSSignerInfo_CreateWithSubjKeyID;
 ;+    local:
 ;+       *;
 ;+};
+;+NSS_3.7 {     # NSS 3.7 release
+;+    global:
+NSS_CMSRecipientInfo_CreateWithSubjKeyID;
+NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert;
+;+    local:
+;+       *;
+;+};
+;+NSS_3.7.2 {   # NSS 3.7.2 release
+;+    global:
+NSS_CMSRecipientInfo_WrapBulkKey;
+NSS_CMSRecipientInfo_UnwrapBulkKey;
+;+    local:
+;+       *;
+;+};
--- a/security/nss/lib/softoken/alghmac.c
+++ b/security/nss/lib/softoken/alghmac.c
@@ -57,17 +57,17 @@ HMAC_Destroy(HMACContext *cx)
 }
 
 HMACContext *
 HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret, 
             unsigned int secret_len, PRBool isFIPS)
 {
     HMACContext *cx;
     unsigned int i;
-    unsigned char hashed_secret[HASH_LENGTH_MAX];
+    unsigned char hashed_secret[SHA1_LENGTH];
 
     /* required by FIPS 198 Section 3 */
     if (isFIPS && secret_len < hash_obj->length/2) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return NULL;
     }
     cx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext));
     if (cx == NULL)
--- a/security/nss/lib/softoken/dbmshim.c
+++ b/security/nss/lib/softoken/dbmshim.c
@@ -48,41 +48,26 @@
 #include "secasn1.h"
 #include "secerr.h"
 #include "nssb64.h"
 #include "blapi.h"
 #include "sechash.h"
 
 #include "pkcs11i.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
+#define BLOB_NAMELENGTH_START BLOB_HEAD_LEN
+#define BLOB_NAMELENGTH_LEN 4
+#define BLOB_NAME_START BLOB_NAMELENGTH_START+BLOB_NAMELENGTH_LEN
+#define BLOB_NAME_LEN 1+ROUNDDIV(SHA1_LENGTH*4,3)+2
+#define BLOB_BUF_LEN BLOB_HEAD_LEN+BLOB_NAMELENGTH_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;
@@ -123,20 +108,20 @@ dbs_getBlobFileName(DBT *blobData)
 /*
  * 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];
+    return (PRUint32)(addr[BLOB_NAMELENGTH_START+3] << 24) | 
+			(addr[BLOB_NAMELENGTH_START+2] << 16) | 
+			(addr[BLOB_NAMELENGTH_START+1] << 8) | 
+			addr[BLOB_NAMELENGTH_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.
  */
@@ -161,26 +146,26 @@ dbs_mkBlob(DBS *dbsp,const DBT *key, con
    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;
+   b[BLOB_NAMELENGTH_START] = length & 0xff;
+   b[BLOB_NAMELENGTH_START+1] = (length >> 8) & 0xff;
+   b[BLOB_NAMELENGTH_START+2] = (length >> 16) & 0xff;
+   b[BLOB_NAMELENGTH_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 */
+   PORT_Memset(&b[BLOB_NAME_START+1],0, BLOB_NAME_LEN-1);
    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;
 }
    
 
 /*
--- a/security/nss/lib/softoken/keydb.c
+++ b/security/nss/lib/softoken/keydb.c
@@ -488,16 +488,38 @@ GetKeyDBGlobalSalt(NSSLOWKEYDBHandle *ha
     if ( ret ) {
 	return(NULL);
     }
 
     return(decodeKeyDBGlobalSalt(&saltData));
 }
 
 static SECStatus
+StoreKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
+{
+    DBT saltKey;
+    DBT saltData;
+    int status;
+    
+    saltKey.data = SALT_STRING;
+    saltKey.size = sizeof(SALT_STRING) - 1;
+
+    saltData.data = (void *)handle->global_salt->data;
+    saltData.size = handle->global_salt->len;
+
+    /* put global salt into the database now */
+    status = (* handle->db->put)( handle->db, &saltKey, &saltData, 0);
+    if ( status ) {
+	return(SECFailure);
+    }
+
+    return(SECSuccess);
+}
+
+static SECStatus
 makeGlobalVersion(NSSLOWKEYDBHandle *handle)
 {
     unsigned char version;
     DBT versionData;
     DBT versionKey;
     int status;
     
     version = NSSLOWKEY_DB_FILE_VERSION;
@@ -2491,25 +2513,27 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *
     }
     
     rv = makeGlobalVersion(handle);
     if ( rv != SECSuccess ) {
 	errors++;
 	goto done;
     }
 
-    rv = makeGlobalSalt(handle);
+    if (handle->global_salt) {
+	rv = StoreKeyDBGlobalSalt(handle);
+    } else {
+	rv = makeGlobalSalt(handle);
+	if ( rv == SECSuccess ) {
+	    handle->global_salt = GetKeyDBGlobalSalt(handle);
+	}
+    }
     if ( rv != SECSuccess ) {
 	errors++;
-	goto done;
     }
 
-    if (handle->global_salt) {
-	SECITEM_FreeItem(handle->global_salt,PR_TRUE);
-    }
-    handle->global_salt = GetKeyDBGlobalSalt(handle);
-
 done:
     /* sync the database */
     ret = (* handle->db->sync)(handle->db, 0);
+    db_InitComplete(handle->db);
 
     return (errors == 0 ? SECSuccess : SECFailure);
 }
--- a/security/nss/lib/softoken/pcertdb.c
+++ b/security/nss/lib/softoken/pcertdb.c
@@ -56,17 +56,26 @@
 #include "sechash.h"
 #include "plhash.h"
 
 #include "cdbhdl.h"
 
 /* forward declaration */
 NSSLOWCERTCertificate *
 nsslowcert_FindCertByDERCertNoLocking(NSSLOWCERTCertDBHandle *handle, SECItem *derCert);
-
+static SECStatus
+nsslowcert_UpdateSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, 
+	char *emailAddr, SECItem *derSubject, SECItem *emailProfile, 
+							SECItem *profileTime);
+static SECStatus
+nsslowcert_UpdatePermCert(NSSLOWCERTCertDBHandle *dbhandle,
+    NSSLOWCERTCertificate *cert, char *nickname, NSSLOWCERTCertTrust *trust);
+static SECStatus
+nsslowcert_UpdateCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl, 
+			SECItem *crlKey, char *url, PRBool isKRL);
 
 static NSSLOWCERTCertificate *certListHead = NULL;
 static NSSLOWCERTTrust *trustListHead = NULL;
 static certDBEntryCert *entryListHead = NULL;
 static int certListCount = 0;
 static int trustListCount = 0;
 static int entryListCount = 0;
 #define MAX_CERT_LIST_COUNT 10
@@ -2362,16 +2371,17 @@ DecodeDBSubjectEntry(certDBEntrySubject 
 	PORT_Memcpy(entry->keyIDs[i].data, tmpbuf, entry->keyIDs[i].len);
 	tmpbuf = &tmpbuf[entry->keyIDs[i].len];
     }
 
     end = &dbentry->data[dbentry->len];
     if ((eaddrlen == 0) && (tmpbuf+1 < end)) {
 	/* read in the additional email addresses */
 	entry->nemailAddrs = tmpbuf[0] << 8 | tmpbuf[1];
+	tmpbuf += 2;
 	entry->emailAddrs = (char **)
 		PORT_ArenaAlloc(arena, entry->nemailAddrs * sizeof(char *));
 	if (entry->emailAddrs == NULL) {
 	    PORT_SetError(SEC_ERROR_NO_MEMORY);
 	    goto loser;
 	}
 	for (i=0; i < entry->nemailAddrs; i++) {
 	    int nameLen = tmpbuf[0] << 8 | tmpbuf[1];
@@ -3487,17 +3497,17 @@ UpdateV7DB(NSSLOWCERTCertDBHandle *handl
 	    rv = DecodeDBCertEntry(&certEntry,&dbEntry);
 	    if (rv != SECSuccess) {
 		break;
 	    }
 	    /* should we check for existing duplicates? */
 	    cert = nsslowcert_DecodeDERCertificate(&certEntry.derCert, 
 						certEntry.nickname);
 	    if (cert) {
-		nsslowcert_AddPermCert(handle, cert, certEntry.nickname,
+		nsslowcert_UpdatePermCert(handle, cert, certEntry.nickname,
 					 		&certEntry.trust);
 		nsslowcert_DestroyCertificate(cert);
 	    }
 	    /* free any data the decode may have allocated. */
 	    pkcs11_freeStaticData(certEntry.derCert.data, 
 						certEntry.derCertSpace);
 	    pkcs11_freeNickname(certEntry.nickname, certEntry.nicknameSpace);
 	    break;
@@ -3512,31 +3522,31 @@ UpdateV7DB(NSSLOWCERTCertDBHandle *handl
 	    crlEntry.common.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 	    if (crlEntry.common.arena == NULL) {
 		break;
 	    }
 	    rv = DecodeDBCrlEntry(&crlEntry,&dbEntry);
 	    if (rv != SECSuccess) {
 		break;
 	    }
-	    nsslowcert_AddCrl(handle, &crlEntry.derCrl, &dbKey, 
+	    nsslowcert_UpdateCrl(handle, &crlEntry.derCrl, &dbKey, 
 						crlEntry.url, isKRL);
 	    /* free data allocated by the decode */
 	    PORT_FreeArena(crlEntry.common.arena, PR_FALSE);
 	    crlEntry.common.arena = NULL;
 	    break;
 
 	case certDBEntryTypeSMimeProfile:
     	    smimeEntry.common.version = (unsigned int)dataBuf[0];
 	    smimeEntry.common.type = entryType;
 	    smimeEntry.common.flags = (unsigned int)dataBuf[2];
 	    smimeEntry.common.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 	    rv = DecodeDBSMimeEntry(&smimeEntry,&dbEntry,(char *)dbKey.data);
 	    /* decode entry */
-	    nsslowcert_SaveSMimeProfile(handle, smimeEntry.emailAddr,
+	    nsslowcert_UpdateSMimeProfile(handle, smimeEntry.emailAddr,
 		&smimeEntry.subjectName, &smimeEntry.smimeOptions,
 						 &smimeEntry.optionsDate);
 	    PORT_FreeArena(smimeEntry.common.arena, PR_FALSE);
 	    smimeEntry.common.arena = NULL;
 	    break;
 	}
     } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 );
 
@@ -4491,32 +4501,25 @@ nsslowcert_ChangeCertTrust(NSSLOWCERTCer
     
 done:
     nsslowcert_UnlockCertTrust(cert);
     nsslowcert_UnlockDB(handle);
     return(ret);
 }
 
 
-SECStatus
-nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *dbhandle,
+static SECStatus
+nsslowcert_UpdatePermCert(NSSLOWCERTCertDBHandle *dbhandle,
     NSSLOWCERTCertificate *cert, char *nickname, NSSLOWCERTCertTrust *trust)
 {
     char *oldnn;
     certDBEntryCert *entry;
     PRBool conflict;
     SECStatus ret;
     SECStatus rv;
-
-    nsslowcert_LockDB(dbhandle);
-    rv = db_BeginTransaction(dbhandle->permCertDB);
-    if (rv != SECSuccess) {
-	nsslowcert_UnlockDB(dbhandle);
-	return SECFailure;
-    }
     
     PORT_Assert(!cert->dbEntry);
 
     /* don't add a conflicting nickname */
     conflict = nsslowcert_CertNicknameConflict(nickname, &cert->derSubject,
 					dbhandle);
     if ( conflict ) {
 	ret = SECFailure;
@@ -4537,16 +4540,38 @@ nsslowcert_AddPermCert(NSSLOWCERTCertDBH
     
     cert->nickname = (entry->nickname) ? pkcs11_copyNickname(entry->nickname,
 		cert->nicknameSpace, sizeof(cert->nicknameSpace)) : NULL;
     cert->trust = &entry->trust;
     cert->dbEntry = entry;
     
     ret = SECSuccess;
 done:
+    return(ret);
+}
+
+SECStatus
+nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *dbhandle,
+    NSSLOWCERTCertificate *cert, char *nickname, NSSLOWCERTCertTrust *trust)
+{
+    char *oldnn;
+    certDBEntryCert *entry;
+    PRBool conflict;
+    SECStatus ret;
+    SECStatus rv;
+
+    nsslowcert_LockDB(dbhandle);
+    rv = db_BeginTransaction(dbhandle->permCertDB);
+    if (rv != SECSuccess) {
+	nsslowcert_UnlockDB(dbhandle);
+	return SECFailure;
+    }
+
+    ret = nsslowcert_UpdatePermCert(dbhandle, cert, nickname, trust);
+    
     db_FinishTransaction(dbhandle->permCertDB, ret != SECSuccess);
     nsslowcert_UnlockDB(dbhandle);
     return(ret);
 }
 
 /*
  * Open the certificate database and index databases.  Create them if
  * they are not there or bad.
@@ -5060,41 +5085,52 @@ loser:
     }
     
     return entry;
 }
 
 /*
  * replace the existing URL in the data base with a new one
  */
-SECStatus
-nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl, 
+static SECStatus
+nsslowcert_UpdateCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl, 
 			SECItem *crlKey, char *url, PRBool isKRL)
 {
     SECStatus rv = SECFailure;
     certDBEntryRevocation *entry = NULL;
     certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation  
 					: certDBEntryTypeRevocation;
-    rv = db_BeginTransaction(handle->permCertDB);
-    if (rv != SECSuccess) {
-	return SECFailure;
-    }
     DeleteDBCrlEntry(handle, crlKey, crlType);
 
     /* Write the new entry into the data base */
     entry = NewDBCrlEntry(derCrl, url, crlType, 0);
     if (entry == NULL) goto done;
 
     rv = WriteDBCrlEntry(handle, entry, crlKey);
     if (rv != SECSuccess) goto done;
 
 done:
     if (entry) {
 	DestroyDBEntry((certDBEntry *)entry);
     }
+    return rv;
+}
+
+SECStatus
+nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl, 
+			SECItem *crlKey, char *url, PRBool isKRL)
+{
+    SECStatus rv;
+
+    rv = db_BeginTransaction(handle->permCertDB);
+    if (rv != SECSuccess) {
+	return SECFailure;
+    }
+    rv = nsslowcert_UpdateCrl(handle, derCrl, crlKey, url, isKRL);
+
     db_FinishTransaction(handle->permCertDB, rv != SECSuccess);
     return rv;
 }
 
 SECStatus
 nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle, SECItem *derName,
 								 PRBool isKRL)
 {
@@ -5126,27 +5162,24 @@ nsslowcert_hasTrust(NSSLOWCERTCertTrust 
 			(trust->objectSigningFlags & CERTDB_TRUSTED_UNKNOWN));
 }
 
 /*
  * This function has the logic that decides if another person's cert and
  * email profile from an S/MIME message should be saved.  It can deal with
  * the case when there is no profile.
  */
-SECStatus
-nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr, 
-	SECItem *derSubject, SECItem *emailProfile, SECItem *profileTime)
+static SECStatus
+nsslowcert_UpdateSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, 
+	char *emailAddr, SECItem *derSubject, SECItem *emailProfile, 
+							SECItem *profileTime)
 {
     certDBEntrySMime *entry = NULL;
     SECStatus rv = SECFailure;;
 
-    rv = db_BeginTransaction(dbhandle->permCertDB);
-    if (rv != SECSuccess) {
-	return SECFailure;
-    }
 
     /* find our existing entry */
     entry = nsslowcert_ReadDBSMimeEntry(dbhandle, emailAddr);
 
     if ( entry ) {
 	/* keep our old db entry consistant for old applications. */
 	if (!SECITEM_ItemsAreEqual(derSubject, &entry->subjectName)) {
 	    nsslowcert_UpdateSubjectEmailAddr(dbhandle, &entry->subjectName, 
@@ -5186,16 +5219,34 @@ nsslowcert_SaveSMimeProfile(NSSLOWCERTCe
     nsslowcert_UnlockDB(dbhandle);
 
     rv = SECSuccess;
     
 loser:
     if ( entry ) {
 	DestroyDBEntry((certDBEntry *)entry);
     }
+    return(rv);
+}
+
+SECStatus
+nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr, 
+	SECItem *derSubject, SECItem *emailProfile, SECItem *profileTime)
+{
+    certDBEntrySMime *entry = NULL;
+    SECStatus rv = SECFailure;;
+
+    rv = db_BeginTransaction(dbhandle->permCertDB);
+    if (rv != SECSuccess) {
+	return SECFailure;
+    }
+
+    rv = nsslowcert_UpdateSMimeProfile(dbhandle, emailAddr, 
+	 derSubject, emailProfile, profileTime);
+    
     db_FinishTransaction(dbhandle->permCertDB, rv != SECSuccess);
     return(rv);
 }
 
 void
 nsslowcert_DestroyGlobalLocks()
 {
     if (dbLock) {
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -969,17 +969,16 @@ pk11_handleCrlObject(PK11Session *sessio
 	object->handle = pk11_mkHandle(slot,&derSubj,
 			isKRL ? PK11_TOKEN_KRL_HANDLE : PK11_TOKEN_TYPE_CRL);
     	pk11_FreeAttribute(subject);
     }
 
     return CKR_OK;
 }
 
-NSSLOWKEYPublicKey * pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key);
 /*
  * check the consistancy and initialize a Public Key Object 
  */
 static CK_RV
 pk11_handlePublicKeyObject(PK11Session *session, PK11Object *object,
 							 CK_KEY_TYPE key_type)
 {
     CK_BBOOL encrypt = CK_TRUE;
@@ -1037,17 +1036,20 @@ pk11_handlePublicKeyObject(PK11Session *
     crv = pk11_defaultAttribute(object,CKA_VERIFY_RECOVER,
 						&recover,sizeof(CK_BBOOL));
     if (crv != CKR_OK)  return crv; 
     crv = pk11_defaultAttribute(object,CKA_WRAP,&wrap,sizeof(CK_BBOOL));
     if (crv != CKR_OK)  return crv; 
     crv = pk11_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL));
     if (crv != CKR_OK)  return crv; 
 
-    object->objectInfo = pk11_GetPubKey(object,key_type);
+    object->objectInfo = pk11_GetPubKey(object,key_type, &crv);
+    if (object->objectInfo == NULL) {
+	return crv;
+    }
     object->infoFree = (PK11Free) nsslowkey_DestroyPublicKey;
 
     if (pk11_isTrue(object,CKA_TOKEN)) {
 	PK11Slot *slot = session->slot;
 	NSSLOWKEYPrivateKey *priv;
 	SECItem pubKey;
 
 	crv = pk11_Attribute2SSecItem(NULL,&pubKey,object,pubKeyAttr);
@@ -1076,17 +1078,19 @@ pk11_handlePublicKeyObject(PK11Session *
 
 	object->handle = pk11_mkHandle(slot, &pubKey, PK11_TOKEN_TYPE_PUB);
 	PORT_Free(pubKey.data);
     }
 
     return CKR_OK;
 }
 
-static NSSLOWKEYPrivateKey * pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key);
+static NSSLOWKEYPrivateKey * 
+pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key, CK_RV *rvp);
+
 /*
  * check the consistancy and initialize a Private Key Object 
  */
 static CK_RV
 pk11_handlePrivateKeyObject(PK11Session *session,PK11Object *object,CK_KEY_TYPE key_type)
 {
     CK_BBOOL cktrue = CK_TRUE;
     CK_BBOOL encrypt = CK_TRUE;
@@ -1187,18 +1191,18 @@ pk11_handlePrivateKeyObject(PK11Session 
 	char *label;
 	SECStatus rv = SECSuccess;
 	SECItem pubKey;
 
 	if (slot->keyDB == NULL) {
 	    return CKR_TOKEN_WRITE_PROTECTED;
 	}
 
-	privKey=pk11_mkPrivKey(object,key_type);
-	if (privKey == NULL) return CKR_HOST_MEMORY;
+	privKey=pk11_mkPrivKey(object,key_type,&crv);
+	if (privKey == NULL) return crv;
 	label = pk11_getString(object,CKA_LABEL);
 
 	crv = pk11_Attribute2SSecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
 	if (crv != CKR_OK) {
 	    if (label) PORT_Free(label);
 	    nsslowkey_DestroyPrivateKey(privKey);
 	    return CKR_TEMPLATE_INCOMPLETE;
 	}
@@ -1220,18 +1224,18 @@ pk11_handlePrivateKeyObject(PK11Session 
 
 fail:
 	if (label) PORT_Free(label);
 	object->handle = pk11_mkHandle(slot,&pubKey,PK11_TOKEN_TYPE_PRIV);
 	if (pubKey.data) PORT_Free(pubKey.data);
 	nsslowkey_DestroyPrivateKey(privKey);
 	if (rv != SECSuccess) return CKR_DEVICE_ERROR;
     } else {
-	object->objectInfo = pk11_mkPrivKey(object,key_type);
-	if (object->objectInfo == NULL) return CKR_HOST_MEMORY;
+	object->objectInfo = pk11_mkPrivKey(object,key_type,&crv);
+	if (object->objectInfo == NULL) return crv;
 	object->infoFree = (PK11Free) nsslowkey_DestroyPrivateKey;
 	/* now NULL out the sensitive attributes */
 	if (pk11_isTrue(object,CKA_SENSITIVE)) {
 	    pk11_nullAttribute(object,CKA_PRIVATE_EXPONENT);
 	    pk11_nullAttribute(object,CKA_PRIME_1);
 	    pk11_nullAttribute(object,CKA_PRIME_2);
 	    pk11_nullAttribute(object,CKA_EXPONENT_1);
 	    pk11_nullAttribute(object,CKA_EXPONENT_2);
@@ -1696,42 +1700,49 @@ pk11_handleObject(PK11Object *object, PK
 
     return CKR_OK;
 }
 
 /*
  * ******************** Public Key Utilities ***************************
  */
 /* Generate a low public key structure from an object */
-NSSLOWKEYPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type)
+NSSLOWKEYPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type,
+								CK_RV *crvp)
 {
     NSSLOWKEYPublicKey *pubKey;
     PLArenaPool *arena;
     CK_RV crv;
 
     if (object->objclass != CKO_PUBLIC_KEY) {
+	*crvp = CKR_KEY_TYPE_INCONSISTENT;
 	return NULL;
     }
 
     if (pk11_isToken(object->handle)) {
 /* ferret out the token object handle */
     }
 
     /* If we already have a key, use it */
     if (object->objectInfo) {
+	*crvp = CKR_OK;
 	return (NSSLOWKEYPublicKey *)object->objectInfo;
     }
 
     /* allocate the structure */
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (arena == NULL) return NULL;
+    if (arena == NULL) {
+	*crvp = CKR_HOST_MEMORY;
+	return NULL;
+    }
 
     pubKey = (NSSLOWKEYPublicKey *)
 			PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPublicKey));
     if (pubKey == NULL) {
+	*crvp = CKR_HOST_MEMORY;
     	PORT_FreeArena(arena,PR_FALSE);
 	return NULL;
     }
 
     /* fill in the structure */
     pubKey->arena = arena;
     switch (key_type) {
     case CKK_RSA:
@@ -1759,50 +1770,55 @@ NSSLOWKEYPublicKey *pk11_GetPubKey(PK11O
     case CKK_DH:
 	pubKey->keyType = NSSLOWKEYDHKey;
 	crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dh.prime,
 							object,CKA_PRIME);
     	if (crv != CKR_OK) break;
 	crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dh.base,
 							object,CKA_BASE);
     	if (crv != CKR_OK) break;
-    	crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dsa.publicValue,
+    	crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dh.publicValue,
 							object,CKA_VALUE);
 	break;
     default:
 	crv = CKR_KEY_TYPE_INCONSISTENT;
 	break;
     }
+    *crvp = crv;
     if (crv != CKR_OK) {
     	PORT_FreeArena(arena,PR_FALSE);
 	return NULL;
     }
 
     object->objectInfo = pubKey;
     object->infoFree = (PK11Free) nsslowkey_DestroyPublicKey;
     return pubKey;
 }
 
 /* make a private key from a verified object */
 static NSSLOWKEYPrivateKey *
-pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
+pk11_mkPrivKey(PK11Object *object, CK_KEY_TYPE key_type, CK_RV *crvp)
 {
     NSSLOWKEYPrivateKey *privKey;
     PLArenaPool *arena;
     CK_RV crv = CKR_OK;
     SECStatus rv;
 
     PORT_Assert(!pk11_isToken(object->handle));
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (arena == NULL) return NULL;
+    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;
@@ -1867,47 +1883,51 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY
     	if (crv != CKR_OK) break;
     	crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.publicValue,
 							object,CKA_NETSCAPE_DB);
 	break;
     default:
 	crv = CKR_KEY_TYPE_INCONSISTENT;
 	break;
     }
+    *crvp = crv;
     if (crv != CKR_OK) {
 	PORT_FreeArena(arena,PR_FALSE);
 	return NULL;
     }
     return privKey;
 }
 
 
 /* Generate a low private key structure from an object */
 NSSLOWKEYPrivateKey *
-pk11_GetPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
+pk11_GetPrivKey(PK11Object *object,CK_KEY_TYPE key_type, CK_RV *crvp)
 {
     NSSLOWKEYPrivateKey *priv = NULL;
 
     if (object->objclass != CKO_PRIVATE_KEY) {
+	*crvp = CKR_KEY_TYPE_INCONSISTENT;
 	return NULL;
     }
     if (object->objectInfo) {
+	*crvp = CKR_OK;
 	return (NSSLOWKEYPrivateKey *)object->objectInfo;
     }
 
     if (pk11_isToken(object->handle)) {
 	/* grab it from the data base */
 	PK11TokenObject *to = pk11_narrowToTokenObject(object);
 
 	PORT_Assert(to);
 	PORT_Assert(object->slot->keyDB);	
 	priv = nsslowkey_FindKeyByPublicKey(object->slot->keyDB, &to->dbKey,
 				       object->slot->password);
+	*crvp = priv ? CKR_OK : CKR_DEVICE_ERROR;
     } else {
-	priv = pk11_mkPrivKey(object, key_type);
+	priv = pk11_mkPrivKey(object, key_type, crvp);
     }
     object->objectInfo = priv;
     object->infoFree = (PK11Free) nsslowkey_DestroyPrivateKey;
     return priv;
 }
 
 /*
  **************************** Symetric Key utils ************************
@@ -2220,38 +2240,44 @@ PK11Slot * pk11_NewSlotFromID(CK_SLOT_ID
     nscSlotList[index][nscSlotCount[index]++] = slotID;
 
     return slot;
 }
 
 static SECStatus
 pk11_set_user(NSSLOWCERTCertificate *cert, SECItem *dummy, void *arg)
 {
-    NSSLOWKEYDBHandle *keydb = (NSSLOWKEYDBHandle *)arg;
-
-    if (nsslowkey_KeyForCertExists(keydb,cert)) {
-	cert->trust->sslFlags |= CERTDB_USER;
-	cert->trust->emailFlags |= CERTDB_USER;
-	cert->trust->objectSigningFlags |= CERTDB_USER;
+    PK11Slot  *slot = (PK11Slot *)arg;
+    NSSLOWCERTCertTrust trust = *cert->trust;
+
+    if (nsslowkey_KeyForCertExists(slot->keyDB,cert)) {
+	trust.sslFlags |= CERTDB_USER;
+	trust.emailFlags |= CERTDB_USER;
+	trust.objectSigningFlags |= CERTDB_USER;
     } else {
-	cert->trust->sslFlags &= ~CERTDB_USER;
-	cert->trust->emailFlags &= ~CERTDB_USER;
-	cert->trust->objectSigningFlags &= ~CERTDB_USER;
+	trust.sslFlags &= ~CERTDB_USER;
+	trust.emailFlags &= ~CERTDB_USER;
+	trust.objectSigningFlags &= ~CERTDB_USER;
+    }
+
+    if (PORT_Memcmp(&trust,cert->trust, sizeof (trust)) != 0) {
+	nsslowcert_ChangeCertTrust(slot->certDB,cert, &trust);
     }
 
     /* should check for email address and make sure we have an s/mime profile */
+    return SECSuccess;
 }
 
 static  void
 pk11_DBVerify(PK11Slot *slot)
 {
     /* walk through all the certs and check to see if there are any 
      * user certs, and make sure there are s/mime profiles for all certs with
      * email addresses */
-    nsslowcert_TraversePermCerts(slot->certDB,pk11_set_user,slot->keyDB);
+    nsslowcert_TraversePermCerts(slot->certDB,pk11_set_user,slot);
 
     return;
 }
 
 /*
  * initialize one of the slot structures. figure out which by the ID
  */
 CK_RV
@@ -2727,16 +2753,39 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID,
     /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
     pInfo->hardwareVersion.major = 3;
     pInfo->hardwareVersion.minor = 7;
     return CKR_OK;
 }
 
 #define CKF_THREAD_SAFE 0x8000 /* for now */
 
+/*
+ * check the current state of the 'needLogin' flag in case the database has
+ * been changed underneath us.
+ */
+static PRBool
+pk11_checkNeedLogin(PK11Slot *slot)
+{
+    if (slot->password) {
+	if (nsslowkey_CheckKeyDBPassword(slot->keyDB,slot->password) 
+							== SECSuccess) {
+	    return slot->needLogin;
+	} else {
+	    SECITEM_FreeItem(slot->password, PR_TRUE);
+	    slot->password = NULL;
+	    slot->isLoggedIn = PR_FALSE;
+	}
+    }
+    slot->needLogin = 
+		(PRBool)!pk11_hasNullPassword(slot->keyDB,&slot->password);
+    return (slot->needLogin);
+}
+
+
 /* NSC_GetTokenInfo obtains information about a particular token in 
  * the system. */
 CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
 {
     PK11Slot *slot = pk11_SlotFromID(slotID);
     NSSLOWKEYDBHandle *handle;
 
     if (slot == NULL) return CKR_SLOT_ID_INVALID;
@@ -2769,17 +2818,17 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID
 	 *   have no keys in the key db.
 	 *   (2) Password initialized to NULL. This means we have keys, but
 	 *   the user has chosen not use a password.
 	 *   (3) Finally we have an initialized password whicn is not NULL, and
 	 *   we will need to prompt for it.
 	 */
 	if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) {
 	    pInfo->flags = CKF_THREAD_SAFE | CKF_LOGIN_REQUIRED;
-	} else if (!slot->needLogin) {
+	} else if (!pk11_checkNeedLogin(slot)) {
 	    pInfo->flags = CKF_THREAD_SAFE | CKF_USER_PIN_INITIALIZED;
 	} else {
 	    pInfo->flags = CKF_THREAD_SAFE | 
 				CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED;
 	}
 	pInfo->ulMaxPinLen = PK11_MAX_PIN;
 	pInfo->ulMinPinLen = 0;
 	if (slot->minimumPinLen > 0) {
@@ -2790,18 +2839,16 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID
 	pInfo->ulTotalPrivateMemory = 1;
 	pInfo->ulFreePrivateMemory = 1;
 	pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION;
 	pInfo->hardwareVersion.minor = handle->version;
     }
     return CKR_OK;
 }
 
-
-
 /* NSC_GetMechanismList obtains a list of mechanism types 
  * supported by a token. */
 CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID,
 	CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
 {
     int i;
 
     switch (slotID) {
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -489,20 +489,19 @@ pk11_CryptInit(CK_SESSION_HANDLE hSessio
     case CKM_RSA_PKCS:
     case CKM_RSA_X_509:
 	if (key_type != CKK_RSA) {
 	    crv = CKR_KEY_TYPE_INCONSISTENT;
 	    break;
 	}
 	context->multi = PR_FALSE;
 	context->cipherInfo =  isEncrypt ? 
-			(void *)pk11_GetPubKey(key,CKK_RSA) :
-					(void *)pk11_GetPrivKey(key,CKK_RSA);
+			(void *)pk11_GetPubKey(key,CKK_RSA,&crv) :
+				(void *)pk11_GetPrivKey(key,CKK_RSA,&crv);
 	if (context->cipherInfo == NULL) {
-	    crv = CKR_HOST_MEMORY;
 	    break;
 	}
 	if (isEncrypt) {
 	    context->update = (PK11Cipher) 
 		(pMechanism->mechanism == CKM_RSA_X_509
 					? RSA_EncryptRaw : RSA_EncryptBlock);
 	} else {
 	    context->update = (PK11Cipher) 
@@ -750,17 +749,17 @@ CK_RV NSC_EncryptUpdate(CK_SESSION_HANDL
 	    }
 
 	    /* not enough data to encrypt yet? then return */
 	    if (context->padDataLength != context->blockSize) {
 		*pulEncryptedPartLen = 0;
 		return CKR_OK;
 	    }
 	    /* encrypt the current padded data */
-    	    rv = (*context->update)(context->cipherInfo, pEncryptedPart, 
+    	    rv = (*context->update)(context->cipherInfo,pEncryptedPart, 
 		&padoutlen, context->blockSize, context->padBuf,
 							context->blockSize);
     	    if (rv != SECSuccess) return CKR_DEVICE_ERROR;
 	    pEncryptedPart += padoutlen;
 	    maxout -= padoutlen;
 	}
 	/* save the residual */
 	context->padDataLength = ulPartLen % context->blockSize;
@@ -1891,20 +1890,19 @@ CK_RV NSC_SignInit(CK_SESSION_HANDLE hSe
 	context->update = (PK11Cipher)  RSA_SignRaw;
 finish_rsa:
 	if (key_type != CKK_RSA) {
 	    if (info) PORT_Free(info);
 	    crv = CKR_KEY_TYPE_INCONSISTENT;
 	    break;
 	}
 	context->multi = PR_FALSE;
-	privKey = pk11_GetPrivKey(key,CKK_RSA);
+	privKey = pk11_GetPrivKey(key,CKK_RSA,&crv);
 	if (privKey == NULL) {
 	    if (info) PORT_Free(info);
-	    crv = CKR_HOST_MEMORY;
 	    break;
 	}
 	/* OK, info is allocated only if we're doing hash and sign mechanism.
 	 * It's necessary to be able to set the correct OID in the final 
 	 * signature.
 	 */
 	if (info) {
 	    info->key = privKey;
@@ -1922,19 +1920,18 @@ finish_rsa:
 	crv = pk11_doSubSHA1(context);
 	if (crv != CKR_OK) break;
 	/* fall through */
     case CKM_DSA:
 	if (key_type != CKK_DSA) {
 	    crv = CKR_KEY_TYPE_INCONSISTENT;
 	    break;
 	}
-	privKey = pk11_GetPrivKey(key,CKK_DSA);
+	privKey = pk11_GetPrivKey(key,CKK_DSA,&crv);
 	if (privKey == NULL) {
-	    crv = CKR_HOST_MEMORY;
 	    break;
 	}
 	context->cipherInfo = privKey;
 	context->update     = (PK11Cipher) nsc_DSA_Sign_Stub;
 	context->destroy    = (privKey == key->objectInfo) ?
 		(PK11Destroy) pk11_Null:(PK11Destroy)pk11_FreePrivKey;
 	context->maxLen     = DSA_SIGNATURE_LEN;
 
@@ -2315,19 +2312,18 @@ CK_RV NSC_VerifyInit(CK_SESSION_HANDLE h
 	goto finish_rsa;
     case CKM_RSA_X_509:
 	context->verify = (PK11Verify) RSA_CheckSignRaw;
 finish_rsa:
 	if (key_type != CKK_RSA) {
 	    crv = CKR_KEY_TYPE_INCONSISTENT;
 	    break;
 	}
-	pubKey = pk11_GetPubKey(key,CKK_RSA);
+	pubKey = pk11_GetPubKey(key,CKK_RSA,&crv);
 	if (pubKey == NULL) {
-	    crv = CKR_HOST_MEMORY;
 	    break;
 	}
 	if (info) {
 	    info->key = pubKey;
 	    context->cipherInfo = info;
 	    context->destroy = pk11_Space;
 	} else {
 	    context->cipherInfo = pubKey;
@@ -2340,19 +2336,18 @@ finish_rsa:
 	if (crv != CKR_OK) break;
 	/* fall through */
     case CKM_DSA:
 	if (key_type != CKK_DSA) {
 	    crv = CKR_KEY_TYPE_INCONSISTENT;
 	    break;
 	}
 	context->multi = PR_FALSE;
-	pubKey = pk11_GetPubKey(key,CKK_DSA);
+	pubKey = pk11_GetPubKey(key,CKK_DSA,&crv);
 	if (pubKey == NULL) {
-	    crv = CKR_HOST_MEMORY;
 	    break;
 	}
 	context->cipherInfo = pubKey;
 	context->verify     = (PK11Verify) nsc_DSA_Verify_Stub;
 	context->destroy    = pk11_Null;
 	break;
 
     case CKM_MD2_HMAC_GENERAL:
@@ -2514,19 +2509,18 @@ CK_RV NSC_VerifyRecoverInit(CK_SESSION_H
     switch(pMechanism->mechanism) {
     case CKM_RSA_PKCS:
     case CKM_RSA_X_509:
 	if (key_type != CKK_RSA) {
 	    crv = CKR_KEY_TYPE_INCONSISTENT;
 	    break;
 	}
 	context->multi = PR_FALSE;
-	pubKey = pk11_GetPubKey(key,CKK_RSA);
+	pubKey = pk11_GetPubKey(key,CKK_RSA,&crv);
 	if (pubKey == NULL) {
-	    crv = CKR_HOST_MEMORY;
 	    break;
 	}
 	context->cipherInfo = pubKey;
 	context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509
 			? RSA_CheckSignRecoverRaw : RSA_CheckSignRecover);
 	context->destroy = pk11_Null;
 	break;
     default:
@@ -3306,16 +3300,17 @@ dsagn_done:
 	/* should zeroize, since this function doesn't. */
 	PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
 	break;
 
     case CKM_DH_PKCS_KEY_PAIR_GEN:
 	pk11_DeleteAttributeType(privateKey,CKA_PRIME);
 	pk11_DeleteAttributeType(privateKey,CKA_BASE);
 	pk11_DeleteAttributeType(privateKey,CKA_VALUE);
+    	pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
 	key_type = CKK_DH;
 
 	/* extract the necessary parameters and copy them to private keys */
         crv = pk11_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, 
 				      CKA_PRIME);
 	if (crv != CKR_OK) break;
 	crv = pk11_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
 	if (crv != CKR_OK) {
@@ -3340,16 +3335,20 @@ dsagn_done:
 	  crv = CKR_DEVICE_ERROR;
 	  break;
 	}
 
 	crv=pk11_AddAttributeType(publicKey, CKA_VALUE, 
 				pk11_item_expand(&dhPriv->publicValue));
 	if (crv != CKR_OK) goto dhgn_done;
 
+        crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
+			   pk11_item_expand(&dhPriv->publicValue));
+	if (crv != CKR_OK) goto dhgn_done;
+
 	crv=pk11_AddAttributeType(privateKey, CKA_VALUE, 
 			      pk11_item_expand(&dhPriv->privateValue));
 
 dhgn_done:
 	/* should zeroize, since this function doesn't. */
 	PORT_FreeArena(dhPriv->arena, PR_TRUE);
 	break;
 
@@ -3434,51 +3433,55 @@ dhgn_done:
     *phPrivateKey = privateKey->handle;
     *phPublicKey = publicKey->handle;
     pk11_FreeObject(publicKey);
     pk11_FreeObject(privateKey);
 
     return CKR_OK;
 }
 
-static SECItem *pk11_PackagePrivateKey(PK11Object *key)
+static SECItem *pk11_PackagePrivateKey(PK11Object *key, CK_RV *crvp)
 {
     NSSLOWKEYPrivateKey *lk = NULL;
     NSSLOWKEYPrivateKeyInfo *pki = NULL;
     PK11Attribute *attribute = NULL;
     PLArenaPool *arena = NULL;
     SECOidTag algorithm = SEC_OID_UNKNOWN;
     void *dummy, *param = NULL;
     SECStatus rv = SECSuccess;
     SECItem *encodedKey = NULL;
 
     if(!key) {
+	*crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */
 	return NULL;
     }
 
     attribute = pk11_FindAttribute(key, CKA_KEY_TYPE);
     if(!attribute) {
+	*crvp = CKR_KEY_TYPE_INCONSISTENT;
 	return NULL;
     }
 
-    lk = pk11_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue);
+    lk = pk11_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp);
     pk11_FreeAttribute(attribute);
     if(!lk) {
 	return NULL;
     }
 
     arena = PORT_NewArena(2048); 	/* XXX different size? */
     if(!arena) {
 	rv = SECFailure;
+	*crvp = CKR_HOST_MEMORY;
 	goto loser;
     }
 
     pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, 
 					sizeof(NSSLOWKEYPrivateKeyInfo));
     if(!pki) {
+	*crvp = CKR_HOST_MEMORY;
 	rv = SECFailure;
 	goto loser;
     }
     pki->arena = arena;
 
     param = NULL;
     switch(lk->keyType) {
 	case NSSLOWKEYRSAKey:
@@ -3498,35 +3501,40 @@ static SECItem *pk11_PackagePrivateKey(P
 	    break;
 	case NSSLOWKEYDHKey:
 	default:
 	    dummy = NULL;
 	    break;
     }
  
     if(!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
+	*crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
+	rv = SECFailure;
 	goto loser;
     }
 
     rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, 
 			       (SECItem*)param);
     if(rv != SECSuccess) {
+	*crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
 	rv = SECFailure;
 	goto loser;
     }
 
     dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
 				  NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
     if(!dummy) {
+	*crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
 	rv = SECFailure;
 	goto loser;
     }
 
     encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, 
 				    nsslowkey_PrivateKeyInfoTemplate);
+    *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR;
 
 loser:
     if(arena) {
 	PORT_FreeArena(arena, PR_TRUE);
     }
 
     if(lk && (lk != key->objectInfo)) {
 	nsslowkey_DestroyPrivateKey(lk);
@@ -3605,20 +3613,19 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSes
 		    *pulWrappedKeyLen = 10;
 		}
 	    }
 	    pk11_FreeAttribute(attribute);
 	    break;
 
 	case CKO_PRIVATE_KEY:
 	    {
-		SECItem *bpki = pk11_PackagePrivateKey(key);
+		SECItem *bpki = pk11_PackagePrivateKey(key, &crv);
 
 		if(!bpki) {
-		    crv = CKR_KEY_TYPE_INCONSISTENT;
 		    break;
 		}
 
 		crv = pk11_CryptInit(hSession, pMechanism, hWrappingKey,
 					CKA_WRAP, PK11_ENCRYPT, PR_TRUE);
 		if(crv != CKR_OK) {
 		    SECITEM_ZfreeItem(bpki, PR_TRUE);
 		    crv = CKR_KEY_TYPE_INCONSISTENT;
--- a/security/nss/lib/softoken/pkcs11i.h
+++ b/security/nss/lib/softoken/pkcs11i.h
@@ -292,18 +292,18 @@ typedef enum {
     PK11_SIGN,
     PK11_SIGN_RECOVER,
     PK11_VERIFY,
     PK11_VERIFY_RECOVER
 } PK11ContextType;
 
 
 #define PK11_MAX_BLOCK_SIZE 16
-/* currently SHA512 is the biggest hash length */
-#define PK11_MAX_MAC_LENGTH 64
+/* currently SHA1 is the biggest hash length */
+#define PK11_MAX_MAC_LENGTH 20
 #define PK11_INVALID_MAC_SIZE 0xffffffff
 
 struct PK11SessionContextStr {
     PK11ContextType	type;
     PRBool		multi; 		/* is multipart */
     PRBool		doPad; 		/* use PKCS padding for block ciphers */
     unsigned int	blockSize; 	/* blocksize for padding */
     unsigned int	padDataLength; 	/* length of the valid data in padbuf */
@@ -597,19 +597,19 @@ extern void pk11_FreeSession(PK11Session
 extern PK11Session *pk11_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify,
 				    CK_VOID_PTR pApplication, CK_FLAGS flags);
 extern void pk11_update_state(PK11Slot *slot,PK11Session *session);
 extern void pk11_update_all_states(PK11Slot *slot);
 extern void pk11_FreeContext(PK11SessionContext *context);
 extern void pk11_CleanupFreeLists(void);
 
 extern NSSLOWKEYPublicKey *pk11_GetPubKey(PK11Object *object,
-					  CK_KEY_TYPE key_type);
+					  CK_KEY_TYPE key_type, CK_RV *crvp);
 extern NSSLOWKEYPrivateKey *pk11_GetPrivKey(PK11Object *object,
-					    CK_KEY_TYPE key_type);
+					    CK_KEY_TYPE key_type, CK_RV *crvp);
 extern void pk11_FormatDESKey(unsigned char *key, int length);
 extern PRBool pk11_CheckDESKey(unsigned char *key);
 extern PRBool pk11_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type);
 
 extern CK_RV secmod_parseParameters(char *param, pk11_parameters *parsed,
 								PRBool isFIPS);
 extern void secmod_freeParams(pk11_parameters *params);
 extern char *secmod_getSecmodName(char *params, char **domain, 
--- a/security/nss/lib/softoken/pkcs11n.h
+++ b/security/nss/lib/softoken/pkcs11n.h
@@ -160,26 +160,16 @@ static const char CKT_CVS_ID[] = "@(#) $
 #define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4       0x80000007L
 #define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC   0x80000008L
 #define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN      0x80000009L
 #define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN       0x8000000aL
 #define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN       0x8000000bL
 
 #define CKM_TLS_PRF_GENERAL                     0x80000373L
 
-/* These new SHAxxx mechanisms will be defined as vendor-defined until
-** they are given standard mechanism numbers.
-*/
-#define CKM_SHA256				0x80000401L
-#define CKM_SHA384				0x80000402L
-#define CKM_SHA512				0x80000403L
-
-#define CKM_SHA256_RSA_PKCS			0x80000411L
-#define CKM_SHA384_RSA_PKCS			0x80000412L
-#define CKM_SHA512_RSA_PKCS			0x80000413L
 
 /*
  * Netscape-defined return values
  *
  */
 #define CKR_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
 
 /*
--- a/security/nss/lib/softoken/rawhash.c
+++ b/security/nss/lib/softoken/rawhash.c
@@ -102,34 +102,10 @@ const SECHashObject SECRawHashObjects[] 
   { SHA1_LENGTH,
     (void * (*)(void)) SHA1_NewContext,
     (void * (*)(void *)) null_hash_clone_context,
     (void (*)(void *, PRBool)) SHA1_DestroyContext,
     (void (*)(void *)) SHA1_Begin,