summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkaie%kuix.de <devnull@localhost>2006-09-01 21:03:20 +0000
committerkaie%kuix.de <devnull@localhost>2006-09-01 21:03:20 +0000
commite037b14c56ca15921becded36580230f6a3b6ecb (patch)
treec07da6da2792dc439286fcc117e631c63094ea93
parentddaea507f54f66053182664fa2da68a7b734146a (diff)
downloadnss-hg-e037b14c56ca15921becded36580230f6a3b6ecb.tar.gz
Bug 340724, update NSS to stable snapshot NSS_3_11_20060831_TAG
r=wtchang, a=mtschrep Includes fix for bug 350640
-rw-r--r--security/coreconf/jdk.mk25
-rw-r--r--security/coreconf/rules.mk8
-rw-r--r--security/nss/lib/certdb/stanpcertdb.c33
-rw-r--r--security/nss/lib/freebl/Makefile32
-rw-r--r--security/nss/lib/freebl/mpi/mpmontg.c140
-rw-r--r--security/nss/lib/pk11wrap/pk11cert.c4
-rw-r--r--security/nss/lib/pki/certificate.c37
-rw-r--r--security/nss/lib/pki/cryptocontext.c26
-rw-r--r--security/nss/lib/pki/nsspki.h21
-rw-r--r--security/nss/lib/pki/pki3hack.c105
-rw-r--r--security/nss/lib/pki/pkibase.c126
-rw-r--r--security/nss/lib/pki/pkim.h9
-rw-r--r--security/nss/lib/pki/pkistore.c69
-rw-r--r--security/nss/lib/pki/pkistore.h9
-rw-r--r--security/nss/lib/pki/pkit.h11
-rw-r--r--security/nss/lib/pki/tdcache.c4
-rw-r--r--security/nss/lib/pki/trustdomain.c2
-rw-r--r--security/nss/lib/smime/smimeutil.c2
-rw-r--r--security/nss/lib/softoken/fipstest.c124
-rw-r--r--security/nss/lib/softoken/fipstokn.c36
-rw-r--r--security/nss/lib/softoken/keydb.c68
-rw-r--r--security/nss/lib/softoken/lowpbe.c2
-rw-r--r--security/nss/lib/softoken/pkcs11.c39
-rw-r--r--security/nss/lib/softoken/pkcs11c.c17
-rw-r--r--security/nss/lib/ssl/derive.c14
-rw-r--r--security/nss/lib/ssl/ssl3con.c13
-rw-r--r--security/nss/lib/ssl/ssl3ecc.c2
-rw-r--r--security/nss/lib/util/secasn1d.c4
-rw-r--r--security/nss/lib/util/secdig.c17
-rw-r--r--security/nss/lib/util/secport.c63
-rw-r--r--security/nss/lib/util/secport.h1
31 files changed, 645 insertions, 418 deletions
diff --git a/security/coreconf/jdk.mk b/security/coreconf/jdk.mk
index 2bc7336e1..98bc188ae 100644
--- a/security/coreconf/jdk.mk
+++ b/security/coreconf/jdk.mk
@@ -184,6 +184,31 @@ ifeq ($(OS_ARCH), Linux)
JDK_JIT_OPT =
endif
+# set [Mac OS X] platforms
+ifeq ($(OS_ARCH), Darwin)
+ JAVA_CLASSES = $(JAVA_HOME)/../Classes/classes.jar
+
+ ifeq ($(JRE_HOME),)
+ JRE_HOME = $(JAVA_HOME)
+ JRE_CLASSES = $(JAVA_CLASSES)
+ else
+ ifeq ($(JRE_CLASSES),)
+ JRE_CLASSES = $(JRE_HOME)/../Classes/classes.jar
+ endif
+ endif
+
+ PATH_SEPARATOR = :
+
+ # (2) specify "header" information
+ JAVA_ARCH = darwin
+
+ INCLUDES += -I$(JAVA_HOME)/include
+ INCLUDES += -I$(JAVA_HOME)/include/$(JAVA_ARCH)
+
+ # no JIT option available on this platform
+ JDK_JIT_OPT =
+endif
+
# set [IBM AIX] platforms
ifeq ($(OS_ARCH), AIX)
JAVA_CLASSES = $(JAVA_HOME)/jre/lib/rt.jar
diff --git a/security/coreconf/rules.mk b/security/coreconf/rules.mk
index ee9e5e8ce..fd1a4bb6a 100644
--- a/security/coreconf/rules.mk
+++ b/security/coreconf/rules.mk
@@ -873,8 +873,7 @@ endif
ifneq (,$(filter-out OpenVMS OS2 WIN%,$(OS_TARGET)))
# Can't use sed because of its 4000-char line length limit, so resort to perl
-.DEFAULT:
- @perl -e ' \
+PERL_DEPENDENCIES_PROGRAM = \
open(MD, "< $(DEPENDENCIES)"); \
while (<MD>) { \
if (m@ \.*/*$< @) { \
@@ -901,7 +900,10 @@ ifneq (,$(filter-out OpenVMS OS2 WIN%,$(OS_TARGET)))
} elsif ("$<" ne "$(DEPENDENCIES)") { \
print "$(MAKE): *** No rule to make target $<. Stop.\n"; \
exit(1); \
- }'
+ }
+
+.DEFAULT:
+ @perl -e '$(PERL_DEPENDENCIES_PROGRAM)'
endif
#############################################################################
diff --git a/security/nss/lib/certdb/stanpcertdb.c b/security/nss/lib/certdb/stanpcertdb.c
index 1cf14a84b..4f820463f 100644
--- a/security/nss/lib/certdb/stanpcertdb.c
+++ b/security/nss/lib/certdb/stanpcertdb.c
@@ -229,7 +229,7 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
PRStatus nssrv;
NSSCertificate *c;
CERTCertificate *cc;
- NSSCertificate *tempCert;
+ NSSCertificate *tempCert = NULL;
nssPKIObject *pkio;
NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext();
NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain();
@@ -260,7 +260,7 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
return cc;
}
}
- pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC);
+ pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor);
if (!pkio) {
return NULL;
}
@@ -311,33 +311,26 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
(NSSUTF8 *)cc->emailAddr,
PORT_Strlen(cc->emailAddr));
}
- /* this function cannot detect if the cert exists as a temp cert now, but
- * didn't when CERT_NewTemp was first called.
- */
- nssrv = NSSCryptoContext_ImportCertificate(gCC, c);
- if (nssrv != PR_SUCCESS) {
+
+ tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c);
+ if (!tempCert) {
goto loser;
}
- /* so find the entry in the temp store */
- tempCert = NSSCryptoContext_FindCertificateByIssuerAndSerialNumber(gCC,
- &c->issuer,
- &c->serial);
- /* destroy the copy */
+ /* destroy our copy */
NSSCertificate_Destroy(c);
- if (tempCert) {
- /* and use the "official" entry */
- c = tempCert;
- cc = STAN_GetCERTCertificateOrRelease(c);
- if (!cc) {
- return NULL;
- }
- } else {
+ /* and use the stored entry */
+ c = tempCert;
+ cc = STAN_GetCERTCertificateOrRelease(c);
+ if (!cc) {
+ /* STAN_GetCERTCertificateOrRelease destroys c on failure. */
return NULL;
}
+
cc->istemp = PR_TRUE;
cc->isperm = PR_FALSE;
return cc;
loser:
+ /* Perhaps this should be nssCertificate_Destroy(c) */
nssPKIObject_Destroy(&c->object);
return NULL;
}
diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile
index 6c4274447..b1c605e80 100644
--- a/security/nss/lib/freebl/Makefile
+++ b/security/nss/lib/freebl/Makefile
@@ -274,7 +274,10 @@ ifeq ($(CPU_ARCH),sparc)
# no FPU (non-VIS cpus).
# These flags were suggested by the compiler group for building
# with SunStudio 10.
- SOL_CFLAGS += -xO4 -xtarget=generic
+ ifdef BUILD_OPT
+ SOL_CFLAGS += -xO4
+ endif
+ SOL_CFLAGS += -xtarget=generic
ARCHFLAG = -xarch=v8plus
SOLARIS_AS_FLAGS = -xarch=v8plus -K PIC
endif
@@ -283,17 +286,23 @@ ifeq ($(CPU_ARCH),sparc)
# 32-bit ABI, it uses FPU code, and 32-bit word size.
# these flags were determined by running cc -### -fast and copying
# the generated flag settings
- SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fns -fsimple=1 -fsingle
- SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all
- SOL_CFLAGS += $(FPU_TARGET_OPTIMIZER) -xdepend
- SOL_CFLAGS += -xlibmil -xmemalign=8s -xO5
+ SOL_CFLAGS += -fsingle -xmemalign=8s
+ ifdef BUILD_OPT
+ SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fsimple=1
+ SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all
+ SOL_CFLAGS += $(FPU_TARGET_OPTIMIZER) -xdepend
+ SOL_CFLAGS += -xlibmil -xO5
+ endif
ARCHFLAG = -xarch=v8plusa
SOLARIS_AS_FLAGS = -xarch=v8plusa -K PIC
endif
ifdef USE_ABI64_INT
# this builds for Sparc v9a pure 64-bit architecture,
# no FPU (non-VIS cpus). For building with SunStudio 10.
- SOL_CFLAGS += -xO4 -xtarget=generic
+ ifdef BUILD_OPT
+ SOL_CFLAGS += -xO4
+ endif
+ SOL_CFLAGS += -xtarget=generic
ARCHFLAG = -xarch=v9
SOLARIS_AS_FLAGS = -xarch=v9 -K PIC
endif
@@ -301,10 +310,13 @@ ifeq ($(CPU_ARCH),sparc)
# this builds for Sparc v9a pure 64-bit architecture
# It uses floating point, and 32-bit word size.
# See comment for USE_ABI32_FPU.
- SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fns -fsimple=1 -fsingle
- SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all
- SOL_CFLAGS += $(FPU_TARGET_OPTIMIZER) -xdepend
- SOL_CFLAGS += -xlibmil -xmemalign=8s -xO5
+ SOL_CFLAGS += -fsingle -xmemalign=8s
+ ifdef BUILD_OPT
+ SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fsimple=1
+ SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all
+ SOL_CFLAGS += $(FPU_TARGET_OPTIMIZER) -xdepend
+ SOL_CFLAGS += -xlibmil -xO5
+ endif
ARCHFLAG = -xarch=v9a
SOLARIS_AS_FLAGS = -xarch=v9a -K PIC
endif
diff --git a/security/nss/lib/freebl/mpi/mpmontg.c b/security/nss/lib/freebl/mpi/mpmontg.c
index 312e0d089..bea8009c2 100644
--- a/security/nss/lib/freebl/mpi/mpmontg.c
+++ b/security/nss/lib/freebl/mpi/mpmontg.c
@@ -541,108 +541,106 @@ mp_err mp_set_safe_modexp(int value)
#ifndef MP_CHAR_STORE_SLOW
/*
- * mpi_to_weave takes MPI data and stores in into a byte array interleaved.
+ * mpi_to_weave takes an array of bignums, a matrix in which each bignum
+ * occupies all the columns of a row, and transposes it into a matrix in
+ * which each bignum occupies a column of every row. The first row of the
+ * input matrix becomes the first column of the output matrix. The n'th
+ * row of input becomes the n'th column of output. The input data is said
+ * to be "interleaved" or "woven" into the output matrix.
*
- * The purpose of this interleaving is to hide our access to the array of
- * modulus powers from and attacker snooping on cache hits and misses. Because
- * the array is interleaved, each reference will cause exactly the same cache
- * lines to reload.
+ * The array of bignums is left in this woven form. Each time a single
+ * bignum value is needed, it is recreated by fetching the n'th column,
+ * forming a single row which is the new bignum.
*
- * There are 2 different implementations in this file, one which works with just
- * byte loads and stores, the second which works with mp_weave_word loads and
- * stores. These 2 implementations have DIFFERENT results in exactly which byte
- * of an mp_digit winds up in which location in the byte array. That is why
- * there are 2 sets of explanations for how the array is set up.
+ * The purpose of this interleaving is make it impossible to determine which
+ * of the bignums is being used in any one operation by examining the pattern
+ * of cache misses.
*
+ * The weaving function does not transpose the entire input matrix in one call.
+ * It transposes 4 rows of mp_ints into their respective columns of output.
*
- * a is an array of WEAVE_WORD_SIZE mp_ints (that is 4).
- * It is a partial window into a logical array mp_int p[count] containing
- * the base to the 0 through count-1 powers. Ideally this code would be
- * simpler if we stored one element of that array at a time, but on some
- * platforms the cost of storing a byte incurs a full read modify write cycle
- * and increases the memory bandwidth cost by a factor of 4 or 8. By collecting
- * for mp_ints together, we can arrange to store all 4 values in a single
- * word write.
- *
- * b is the targeted weaved location. b[0] points to the first byte where
- * first byte of the a array needs to be stored. Each b is an offset into the
- * weave array.
- *
- * count is 2^window size.
- *
- * b_size is the size in mp_digits of each mp_int in the array. mp_ints
- * with less than b_size elements are logically padded with zeros before
- * storing.
+ * There are two different implementations of the weaving and unweaving code
+ * in this file. One uses byte loads and stores. The second uses loads and
+ * stores of mp_weave_word size values. The weaved forms of these two
+ * implementations differ. Consequently, each one has its own explanation.
*
+ * Here is the explanation for the byte-at-a-time implementation.
*
- * Data is stored as follows :
- * The mp_int array is treated as a byte array.
+ * This implementation treats each mp_int bignum as an array of bytes,
+ * rather than as an array of mp_digits. It stores those bytes as a
+ * column of bytes in the output matrix. It doesn't care if the machine
+ * uses big-endian or little-endian byte ordering within mp_digits.
+ * The first byte of the mp_digit array becomes the first byte in the output
+ * column, regardless of whether that byte is the MSB or LSB of the mp_digit.
*
+ * "bignums" is an array of mp_ints.
+ * It points to four rows, four mp_ints, a subset of a larger array of mp_ints.
*
- * we want to eventually store the logical array mp_int p[count] into the
- * weave array as follows:
-
- * p[count].digit is treated as a byte array (rather than * an mp_digit array),
- * N is count, and n is b_size * *sizeof(mp_digit):
- *
- * p[0].digit[0] p[1].digit[0] ...... p[N-2].digit[0] p[N-1].digit[0]
- * p[0].digit[1] p[1].digit[1] ...... p[N-2].digit[1] p[N-1].digit[1]
- * . .
- * . .
- * p[0].digit[n-2] p[1].digit[n-2] ...... p[N-2].digit[n-2] p[N-1].digit[n-2]
- * p[0].digit[n-1] p[1].digit[n-1] ...... p[N-2].digit[n-1] p[N-1].digit[n-1]
+ * "weaved" is the weaved output matrix.
+ * The first byte of bignums[0] is stored in weaved[0].
+ *
+ * "nBignums" is the total number of bignums in the array of which "bignums"
+ * is a part.
*
- * This function stores that a window of p in each call.
+ * "nDigits" is the size in mp_digits of each mp_int in the "bignums" array.
+ * mp_ints that use less than nDigits digits are logically padded with zeros
+ * while being stored in the weaved array.
*/
-mp_err mpi_to_weave(const mp_int *a, unsigned char *b,
- mp_size b_size, mp_size count)
+mp_err mpi_to_weave(const mp_int *bignums,
+ unsigned char *weaved,
+ mp_size nDigits, /* in each mp_int of input */
+ mp_size nBignums) /* in the entire source array */
{
- mp_size i, j;
- unsigned char *bsave = b;
+ mp_size i;
+ unsigned char * endDest = weaved + (nDigits * nBignums * sizeof(mp_digit));
for (i=0; i < WEAVE_WORD_SIZE; i++) {
- unsigned char *pb = (unsigned char *)MP_DIGITS(&a[i]);
- mp_size useda = MP_USED(&a[i]);
- mp_size zero = b_size - useda;
- unsigned char *end = pb+ (useda*sizeof(mp_digit));
- b = bsave+i;
-
+ mp_size used = MP_USED(&bignums[i]);
+ unsigned char *pSrc = (unsigned char *)MP_DIGITS(&bignums[i]);
+ unsigned char *endSrc = pSrc + (used * sizeof(mp_digit));
+ unsigned char *pDest = weaved + i;
- ARGCHK(MP_SIGN(&a[i]) == MP_ZPOS, MP_BADARG);
- ARGCHK(useda <= b_size, MP_BADARG);
+ ARGCHK(MP_SIGN(&bignums[i]) == MP_ZPOS, MP_BADARG);
+ ARGCHK(used <= nDigits, MP_BADARG);
- for (; pb < end; pb++) {
- *b = *pb;
- b += count;
+ for (; pSrc < endSrc; pSrc++) {
+ *pDest = *pSrc;
+ pDest += nBignums;
}
- for (j=0; j < zero; j++) {
- *b = 0;
- b += count;
+ while (pDest < endDest) {
+ *pDest = 0;
+ pDest += nBignums;
}
}
return MP_OKAY;
}
-/* reverse the operation above for one entry.
- * b points to the offset into the weave array of the power we are
- * calculating */
-mp_err weave_to_mpi(mp_int *a, const unsigned char *b,
- mp_size b_size, mp_size count)
+/* Reverse the operation above for one mp_int.
+ * Reconstruct one mp_int from its column in the weaved array.
+ * "pSrc" points to the offset into the weave array of the bignum we
+ * are going to reconstruct.
+ */
+mp_err weave_to_mpi(mp_int *a, /* output, result */
+ const unsigned char *pSrc, /* input, byte matrix */
+ mp_size nDigits, /* per mp_int output */
+ mp_size nBignums) /* bignums in weaved matrix */
{
- unsigned char *pb = (unsigned char *)MP_DIGITS(a);
- unsigned char *end = pb+ (b_size*sizeof(mp_digit));
+ unsigned char *pDest = (unsigned char *)MP_DIGITS(a);
+ unsigned char *endDest = pDest + (nDigits * sizeof(mp_digit));
MP_SIGN(a) = MP_ZPOS;
- MP_USED(a) = b_size;
+ MP_USED(a) = nDigits;
- for (; pb < end; b+=count, pb++) {
- *pb = *b;
+ for (; pDest < endDest; pSrc += nBignums, pDest++) {
+ *pDest = *pSrc;
}
s_mp_clamp(a);
return MP_OKAY;
}
+
#else
+
/* Need a primitive that we know is 32 bits long... */
/* this is true on all modern processors we know of today*/
typedef unsigned int mp_weave_word;
diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c
index 7e04ac6a9..eb1a358b1 100644
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -273,7 +273,7 @@ static CERTCertificate
}
/* Create a PKI object from the cryptoki instance */
- pkio = nssPKIObject_Create(NULL, co, td, NULL);
+ pkio = nssPKIObject_Create(NULL, co, td, NULL, nssPKIMonitor);
if (!pkio) {
nssCryptokiObject_Destroy(co);
return NULL;
@@ -1203,7 +1203,7 @@ PK11_FindCertByIssuerAndSNOnToken(PK11SlotInfo *slot,
if (!instance) {
goto loser;
}
- object = nssPKIObject_Create(NULL, instance, td, NULL);
+ object = nssPKIObject_Create(NULL, instance, td, NULL, nssPKIMonitor);
if (!object) {
goto loser;
}
diff --git a/security/nss/lib/pki/certificate.c b/security/nss/lib/pki/certificate.c
index 4229cbed0..8c7609a8b 100644
--- a/security/nss/lib/pki/certificate.c
+++ b/security/nss/lib/pki/certificate.c
@@ -79,6 +79,7 @@ nssCertificate_Create (
/* mark? */
NSSArena *arena = object->arena;
PR_ASSERT(object->instances != NULL && object->numInstances > 0);
+ PR_ASSERT(object->lockType == nssPKIMonitor);
rvCert = nss_ZNEW(arena, NSSCertificate);
if (!rvCert) {
return (NSSCertificate *)NULL;
@@ -155,7 +156,7 @@ nssCertificate_Destroy (
for (i=0; i<c->object.numInstances; i++) {
nssCryptokiObject_Destroy(c->object.instances[i]);
}
- PZ_DestroyLock(c->object.lock);
+ nssPKIObject_DestroyLock(&c->object);
nssArena_Destroy(c->object.arena);
nssDecodedCert_Destroy(dc);
} else {
@@ -318,25 +319,17 @@ nssCertificate_GetDecoding (
NSSCertificate *c
)
{
- /* There is a race in assigning c->decoding.
- ** This is a workaround. Bugzilla bug 225525.
- */
+ nssDecodedCert* deco = NULL;
+ nssPKIObject_Lock(&c->object);
if (!c->decoding) {
- nssDecodedCert * deco =
- nssDecodedCert_Create(NULL, &c->encoding, c->type);
- /* Once this race is fixed, an assertion should be put
- ** here to detect any regressions.
+ deco = nssDecodedCert_Create(NULL, &c->encoding, c->type);
PORT_Assert(!c->decoding);
- */
- if (!c->decoding) {
- /* we won the race. Use our copy. */
- c->decoding = deco;
- } else {
- /* we lost the race. discard deco. */
- nssDecodedCert_Destroy(deco);
- }
+ c->decoding = deco;
+ } else {
+ deco = c->decoding;
}
- return c->decoding;
+ nssPKIObject_Unlock(&c->object);
+ return deco;
}
static NSSCertificate **
@@ -910,7 +903,7 @@ nssSMIMEProfile_Create (
if (!arena) {
return NULL;
}
- object = nssPKIObject_Create(arena, NULL, td, cc);
+ object = nssPKIObject_Create(arena, NULL, td, cc, nssPKILock);
if (!object) {
goto loser;
}
@@ -1006,7 +999,7 @@ nssTrust_Create (
sha1_hash.data = sha1_hashin;
sha1_hash.size = sizeof (sha1_hashin);
/* trust has to peek into the base object members */
- PZ_Lock(object->lock);
+ nssPKIObject_Lock(object);
for (i=0; i<object->numInstances; i++) {
instance = object->instances[i];
myTrustOrder = nssToken_GetTrustOrder(instance->token);
@@ -1018,11 +1011,11 @@ nssTrust_Create (
&emailProtection,
&stepUp);
if (status != PR_SUCCESS) {
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return (NSSTrust *)NULL;
}
if (PORT_Memcmp(sha1_hashin,sha1_hashcmp,SHA1_LENGTH) != 0) {
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return (NSSTrust *)NULL;
}
if (rvt->serverAuth == nssTrustLevel_Unknown ||
@@ -1048,7 +1041,7 @@ nssTrust_Create (
rvt->stepUpApproved = stepUp;
lastTrustOrder = myTrustOrder;
}
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return rvt;
}
diff --git a/security/nss/lib/pki/cryptocontext.c b/security/nss/lib/pki/cryptocontext.c
index 68fe20003..5e1be597e 100644
--- a/security/nss/lib/pki/cryptocontext.c
+++ b/security/nss/lib/pki/cryptocontext.c
@@ -65,6 +65,7 @@ struct NSSCryptoContextStr
#endif
extern const NSSError NSS_ERROR_NOT_FOUND;
+extern const NSSError NSS_ERROR_INVALID_ARGUMENT;
NSS_IMPLEMENT NSSCryptoContext *
nssCryptoContext_Create (
@@ -142,22 +143,33 @@ NSSCryptoContext_GetTrustDomain (
return NULL;
}
-NSS_IMPLEMENT PRStatus
-NSSCryptoContext_ImportCertificate (
+
+NSS_IMPLEMENT NSSCertificate *
+NSSCryptoContext_FindOrImportCertificate (
NSSCryptoContext *cc,
NSSCertificate *c
)
{
- PRStatus nssrv;
+ NSSCertificate *rvCert = NULL;
+
PORT_Assert(cc->certStore);
if (!cc->certStore) {
- return PR_FAILURE;
+ nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
+ return rvCert;
}
- nssrv = nssCertificateStore_Add(cc->certStore, c);
- if (nssrv == PR_SUCCESS) {
+ rvCert = nssCertificateStore_FindOrAdd(cc->certStore, c);
+ if (rvCert == c && c->object.cryptoContext != cc) {
+ PORT_Assert(!c->object.cryptoContext);
c->object.cryptoContext = cc;
+ }
+ if (rvCert) {
+ /* an NSSCertificate cannot be part of two crypto contexts
+ ** simultaneously. If this assertion fails, then there is
+ ** a serious Stan design flaw.
+ */
+ PORT_Assert(cc == c->object.cryptoContext);
}
- return nssrv;
+ return rvCert;
}
NSS_IMPLEMENT NSSCertificate *
diff --git a/security/nss/lib/pki/nsspki.h b/security/nss/lib/pki/nsspki.h
index f50433620..689e4c240 100644
--- a/security/nss/lib/pki/nsspki.h
+++ b/security/nss/lib/pki/nsspki.h
@@ -2235,15 +2235,24 @@ NSSCryptoContext_GetTrustDomain
/* Importing things */
/*
- * NSSCryptoContext_ImportCertificate
+ * NSSCryptoContext_FindOrImportCertificate
*
- * If there's not a "distinguished certificate" for this context, this
- * sets the specified one to be it.
+ * If the certificate store already contains this DER cert, return the
+ * address of the matching NSSCertificate that is already in the store,
+ * and bump its reference count.
+ *
+ * If this DER cert is NOT already in the store, then add the new
+ * NSSCertificate to the store and bump its reference count,
+ * then return its address.
+ *
+ * if this DER cert is not in the store and cannot be added to it,
+ * return NULL;
+ *
+ * Record the associated crypto context in the certificate.
*/
-NSS_EXTERN PRStatus
-NSSCryptoContext_ImportCertificate
-(
+NSS_EXTERN NSSCertificate *
+NSSCryptoContext_FindOrImportCertificate (
NSSCryptoContext *cc,
NSSCertificate *c
);
diff --git a/security/nss/lib/pki/pki3hack.c b/security/nss/lib/pki/pki3hack.c
index dd1216210..64bb4295e 100644
--- a/security/nss/lib/pki/pki3hack.c
+++ b/security/nss/lib/pki/pki3hack.c
@@ -713,10 +713,18 @@ STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c)
static void
fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced)
{
+ CERTCertTrust* trust = NULL;
NSSTrust *nssTrust;
NSSCryptoContext *context = c->object.cryptoContext;
- nssCryptokiInstance *instance = get_cert_instance(c);
+ nssCryptokiInstance *instance;
NSSUTF8 *stanNick = NULL;
+
+ /* We are holding the base class object's lock on entry of this function
+ * This lock protects writes to fields of the CERTCertificate .
+ * It is also needed by some functions to compute values such as trust.
+ */
+ instance = get_cert_instance(c);
+
if (instance) {
stanNick = instance->label;
} else if (context) {
@@ -738,15 +746,16 @@ fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced
if (stanNick) {
nicklen = nssUTF8_Size(stanNick, &nssrv);
len = tokenlen + nicklen;
- cc->nickname = PORT_ArenaAlloc(cc->arena, len);
- nick = cc->nickname;
+ nick = PORT_ArenaAlloc(cc->arena, len);
if (tokenName) {
memcpy(nick, tokenName, tokenlen-1);
- nick += tokenlen-1;
- *nick++ = ':';
+ nick[tokenlen-1] = ':';
+ memcpy(nick+tokenlen, stanNick, nicklen-1);
+ } else {
+ memcpy(nick, stanNick, nicklen-1);
}
- memcpy(nick, stanNick, nicklen-1);
- cc->nickname[len-1] = '\0';
+ nick[len-1] = '\0';
+ cc->nickname = nick;
} else {
cc->nickname = NULL;
}
@@ -755,7 +764,13 @@ fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced
/* trust */
nssTrust = nssCryptoContext_FindTrustForCertificate(context, c);
if (nssTrust) {
- cc->trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
+ trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
+ if (trust) {
+ /* we should destroy cc->trust before replacing it, but it's
+ allocated in cc->arena, so memory growth will occur on each
+ refresh */
+ cc->trust = trust;
+ }
nssTrust_Destroy(nssTrust);
}
} else if (instance) {
@@ -770,7 +785,13 @@ fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced
/* pkcs11ID */
cc->pkcs11ID = instance->handle;
/* trust */
- cc->trust = nssTrust_GetCERTCertTrustForCert(c, cc);
+ trust = nssTrust_GetCERTCertTrustForCert(c, cc);
+ if (trust) {
+ /* we should destroy cc->trust before replacing it, but it's
+ allocated in cc->arena, so memory growth will occur on each
+ refresh */
+ cc->trust = trust;
+ }
nssCryptokiObject_Destroy(instance);
}
/* database handle is now the trust domain */
@@ -786,52 +807,54 @@ fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced
static CERTCertificate *
stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate)
{
- nssDecodedCert *dc = c->decoding;
- CERTCertificate *cc;
+ nssDecodedCert *dc = NULL;
+ CERTCertificate *cc = NULL;
+
+ nssPKIObject_Lock(&c->object);
- /* There is a race in assigning c->decoding.
- ** This is a workaround. Bugzilla bug 225525.
- */
+ dc = c->decoding;
if (!dc) {
dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
- if (!dc)
- return NULL;
+ if (!dc) {
+ goto loser;
+ }
cc = (CERTCertificate *)dc->data;
PORT_Assert(cc); /* software error */
if (!cc) {
nssDecodedPKIXCertificate_Destroy(dc);
nss_SetError(NSS_ERROR_INTERNAL_ERROR);
- return NULL;
+ goto loser;
}
- /* Once this race is fixed, an assertion should be put
- ** here to detect any regressions.
PORT_Assert(!c->decoding);
- */
if (!c->decoding) {
c->decoding = dc;
} else {
- /* Reduce the leaks here, until the race is fixed. */
+ /* this should never happen. Fail. */
nssDecodedPKIXCertificate_Destroy(dc);
- dc = c->decoding;
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ goto loser;
}
}
cc = (CERTCertificate *)dc->data;
PORT_Assert(cc);
- /* When c->decoding is non-NULL on input, but dc->data is
- * NULL, we don't destroy dc because some other errant
- * code allocated it .
- */
- if (cc) {
- if (!cc->nssCertificate || forceUpdate) {
- fill_CERTCertificateFields(c, cc, forceUpdate);
- } else if (!cc->trust && !c->object.cryptoContext) {
- /* if it's a perm cert, it might have been stored before the
- * trust, so look for the trust again. But a temp cert can be
- * ignored.
- */
- cc->trust = nssTrust_GetCERTCertTrustForCert(c, cc);
- }
+ if (!cc) {
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ goto loser;
+ }
+ if (!cc->nssCertificate || forceUpdate) {
+ fill_CERTCertificateFields(c, cc, forceUpdate);
+ } else if (!cc->trust && !c->object.cryptoContext) {
+ /* if it's a perm cert, it might have been stored before the
+ * trust, so look for the trust again. But a temp cert can be
+ * ignored.
+ */
+ CERTCertTrust* trust = NULL;
+ trust = nssTrust_GetCERTCertTrustForCert(c, cc);
+ cc->trust = trust;
}
+
+ loser:
+ nssPKIObject_Unlock(&c->object);
return cc;
}
@@ -916,7 +939,7 @@ STAN_GetNSSCertificate(CERTCertificate *cc)
}
NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
c->type = NSSCertificateType_PKIX;
- pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL);
+ pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor);
if (!pkiob) {
nssArena_Destroy(arena);
return NULL;
@@ -1036,7 +1059,7 @@ STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
arena = nssArena_Create();
if (!arena) return PR_FAILURE;
nssTrust = nss_ZNEW(arena, NSSTrust);
- pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL);
+ pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock);
if (!pkiob) {
nssArena_Destroy(arena);
return PR_FAILURE;
@@ -1178,6 +1201,9 @@ nssTrustDomain_TraverseCertificatesBySubject (
NSSCertificate *c;
PRIntn i;
tmpArena = NSSArena_Create();
+ if (!tmpArena) {
+ return PR_FAILURE;
+ }
subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
0, tmpArena);
if (subjectCerts) {
@@ -1205,6 +1231,9 @@ nssTrustDomain_TraverseCertificatesByNickname (
NSSCertificate *c;
PRIntn i;
tmpArena = NSSArena_Create();
+ if (!tmpArena) {
+ return PR_FAILURE;
+ }
nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
0, tmpArena);
if (nickCerts) {
diff --git a/security/nss/lib/pki/pkibase.c b/security/nss/lib/pki/pkibase.c
index deef58b52..f8b5a47ed 100644
--- a/security/nss/lib/pki/pkibase.c
+++ b/security/nss/lib/pki/pkibase.c
@@ -52,12 +52,79 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
extern const NSSError NSS_ERROR_NOT_FOUND;
+NSS_IMPLEMENT void
+nssPKIObject_Lock(nssPKIObject * object)
+{
+ switch (object->lockType) {
+ case nssPKIMonitor:
+ PZ_EnterMonitor(object->sync.mlock);
+ break;
+ case nssPKILock:
+ PZ_Lock(object->sync.lock);
+ break;
+ default:
+ PORT_Assert(0);
+ }
+}
+
+NSS_IMPLEMENT void
+nssPKIObject_Unlock(nssPKIObject * object)
+{
+ switch (object->lockType) {
+ case nssPKIMonitor:
+ PZ_ExitMonitor(object->sync.mlock);
+ break;
+ case nssPKILock:
+ PZ_Unlock(object->sync.lock);
+ break;
+ default:
+ PORT_Assert(0);
+ }
+}
+
+NSS_IMPLEMENT PRStatus
+nssPKIObject_NewLock(nssPKIObject * object, nssPKILockType lockType)
+{
+ object->lockType = lockType;
+ switch (lockType) {
+ case nssPKIMonitor:
+ object->sync.mlock = PZ_NewMonitor(nssILockSSL);
+ return (object->sync.mlock ? PR_SUCCESS : PR_FAILURE);
+ case nssPKILock:
+ object->sync.lock = PZ_NewLock(nssILockSSL);
+ return (object->sync.lock ? PR_SUCCESS : PR_FAILURE);
+ default:
+ PORT_Assert(0);
+ return PR_FAILURE;
+ }
+}
+
+NSS_IMPLEMENT void
+nssPKIObject_DestroyLock(nssPKIObject * object)
+{
+ switch (object->lockType) {
+ case nssPKIMonitor:
+ PZ_DestroyMonitor(object->sync.mlock);
+ object->sync.mlock = NULL;
+ break;
+ case nssPKILock:
+ PZ_DestroyLock(object->sync.lock);
+ object->sync.lock = NULL;
+ break;
+ default:
+ PORT_Assert(0);
+ }
+}
+
+
+
NSS_IMPLEMENT nssPKIObject *
nssPKIObject_Create (
NSSArena *arenaOpt,
nssCryptokiObject *instanceOpt,
NSSTrustDomain *td,
- NSSCryptoContext *cc
+ NSSCryptoContext *cc,
+ nssPKILockType lockType
)
{
NSSArena *arena;
@@ -79,8 +146,7 @@ nssPKIObject_Create (
object->arena = arena;
object->trustDomain = td; /* XXX */
object->cryptoContext = cc;
- object->lock = PZ_NewLock(nssILockOther);
- if (!object->lock) {
+ if (PR_SUCCESS != nssPKIObject_NewLock(object, lockType)) {
goto loser;
}
if (instanceOpt) {
@@ -113,7 +179,7 @@ nssPKIObject_Destroy (
for (i=0; i<object->numInstances; i++) {
nssCryptokiObject_Destroy(object->instances[i]);
}
- PZ_DestroyLock(object->lock);
+ nssPKIObject_DestroyLock(object);
nssArena_Destroy(object->arena);
return PR_TRUE;
}
@@ -135,7 +201,7 @@ nssPKIObject_AddInstance (
nssCryptokiObject *instance
)
{
- PZ_Lock(object->lock);
+ nssPKIObject_Lock(object);
if (object->numInstances == 0) {
object->instances = nss_ZNEWARRAY(object->arena,
nssCryptokiObject *,
@@ -144,7 +210,7 @@ nssPKIObject_AddInstance (
PRUint32 i;
for (i=0; i<object->numInstances; i++) {
if (nssCryptokiObject_Equal(object->instances[i], instance)) {
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
if (instance->label) {
if (!object->instances[i]->label ||
!nssUTF8_Equal(instance->label,
@@ -171,11 +237,11 @@ nssPKIObject_AddInstance (
object->numInstances + 1);
}
if (!object->instances) {
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return PR_FAILURE;
}
object->instances[object->numInstances++] = instance;
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return PR_SUCCESS;
}
@@ -187,14 +253,14 @@ nssPKIObject_HasInstance (
{
PRUint32 i;
PRBool hasIt = PR_FALSE;;
- PZ_Lock(object->lock);
+ nssPKIObject_Lock(object);
for (i=0; i<object->numInstances; i++) {
if (nssCryptokiObject_Equal(object->instances[i], instance)) {
hasIt = PR_TRUE;
break;
}
}
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return hasIt;
}
@@ -206,9 +272,9 @@ nssPKIObject_RemoveInstanceForToken (
{
PRUint32 i;
nssCryptokiObject *instanceToRemove = NULL;
- PZ_Lock(object->lock);
+ nssPKIObject_Lock(object);
if (object->numInstances == 0) {
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return PR_SUCCESS;
}
for (i=0; i<object->numInstances; i++) {
@@ -230,7 +296,7 @@ nssPKIObject_RemoveInstanceForToken (
nss_ZFreeIf(object->instances);
}
nssCryptokiObject_Destroy(instanceToRemove);
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return PR_SUCCESS;
}
@@ -253,7 +319,7 @@ nssPKIObject_DeleteStoredObject (
nssTrustDomain_GetDefaultCallback(td, NULL);
#endif
numNotDestroyed = 0;
- PZ_Lock(object->lock);
+ nssPKIObject_Lock(object);
for (i=0; i<object->numInstances; i++) {
nssCryptokiObject *instance = object->instances[i];
#ifndef NSS_3_4_CODE
@@ -288,7 +354,7 @@ nssPKIObject_DeleteStoredObject (
} else {
object->numInstances = numNotDestroyed;
}
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return status;
}
@@ -299,7 +365,7 @@ nssPKIObject_GetTokens (
)
{
NSSToken **tokens = NULL;
- PZ_Lock(object->lock);
+ nssPKIObject_Lock(object);
if (object->numInstances > 0) {
tokens = nss_ZNEWARRAY(NULL, NSSToken *, object->numInstances + 1);
if (tokens) {
@@ -309,7 +375,7 @@ nssPKIObject_GetTokens (
}
}
}
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
if (statusOpt) *statusOpt = PR_SUCCESS; /* until more logic here */
return tokens;
}
@@ -322,7 +388,7 @@ nssPKIObject_GetNicknameForToken (
{
PRUint32 i;
NSSUTF8 *nickname = NULL;
- PZ_Lock(object->lock);
+ nssPKIObject_Lock(object);
for (i=0; i<object->numInstances; i++) {
if ((!tokenOpt && object->instances[i]->label) ||
(object->instances[i]->token == tokenOpt))
@@ -332,7 +398,7 @@ nssPKIObject_GetNicknameForToken (
break;
}
}
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return nickname;
}
@@ -347,7 +413,7 @@ nssPKIObject_GetInstances (
if (object->numInstances == 0) {
return (nssCryptokiObject **)NULL;
}
- PZ_Lock(object->lock);
+ nssPKIObject_Lock(object);
instances = nss_ZNEWARRAY(NULL, nssCryptokiObject *,
object->numInstances + 1);
if (instances) {
@@ -355,7 +421,7 @@ nssPKIObject_GetInstances (
instances[i] = nssCryptokiObject_Clone(object->instances[i]);
}
}
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return instances;
}
#endif
@@ -595,12 +661,14 @@ struct nssPKIObjectCollectionStr
PRStatus (* getUIDFromInstance)(nssCryptokiObject *co, NSSItem *uid,
NSSArena *arena);
nssPKIObject * (* createObject)(nssPKIObject *o);
+ nssPKILockType lockType; /* type of lock to use for new proto-objects */
};
static nssPKIObjectCollection *
nssPKIObjectCollection_Create (
NSSTrustDomain *td,
- NSSCryptoContext *ccOpt
+ NSSCryptoContext *ccOpt,
+ nssPKILockType lockType
)
{
NSSArena *arena;
@@ -617,6 +685,7 @@ nssPKIObjectCollection_Create (
rvCollection->arena = arena;
rvCollection->td = td; /* XXX */
rvCollection->cc = ccOpt;
+ rvCollection->lockType = lockType;
return rvCollection;
loser:
nssArena_Destroy(arena);
@@ -763,7 +832,7 @@ add_object_instance (
*/
node = find_object_in_collection(collection, uid);
if (node) {
- /* This is a object with multiple instances */
+ /* This is an object with multiple instances */
status = nssPKIObject_AddInstance(node->object, instance);
} else {
/* This is a completely new object. Create a node for it. */
@@ -772,7 +841,8 @@ add_object_instance (
goto loser;
}
node->object = nssPKIObject_Create(NULL, instance,
- collection->td, collection->cc);
+ collection->td, collection->cc,
+ collection->lockType);
if (!node->object) {
goto loser;
}
@@ -1059,7 +1129,7 @@ nssCertificateCollection_Create (
{
PRStatus status;
nssPKIObjectCollection *collection;
- collection = nssPKIObjectCollection_Create(td, NULL);
+ collection = nssPKIObjectCollection_Create(td, NULL, nssPKIMonitor);
collection->objectType = pkiObjectType_Certificate;
collection->destroyObject = cert_destroyObject;
collection->getUIDFromObject = cert_getUIDFromObject;
@@ -1162,7 +1232,7 @@ nssCRLCollection_Create (
{
PRStatus status;
nssPKIObjectCollection *collection;
- collection = nssPKIObjectCollection_Create(td, NULL);
+ collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
collection->objectType = pkiObjectType_CRL;
collection->destroyObject = crl_destroyObject;
collection->getUIDFromObject = crl_getUIDFromObject;
@@ -1264,7 +1334,7 @@ nssPrivateKeyCollection_Create (
{
PRStatus status;
nssPKIObjectCollection *collection;
- collection = nssPKIObjectCollection_Create(td, NULL);
+ collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
collection->objectType = pkiObjectType_PrivateKey;
collection->destroyObject = privkey_destroyObject;
collection->getUIDFromObject = privkey_getUIDFromObject;
@@ -1365,7 +1435,7 @@ nssPublicKeyCollection_Create (
{
PRStatus status;
nssPKIObjectCollection *collection;
- collection = nssPKIObjectCollection_Create(td, NULL);
+ collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
collection->objectType = pkiObjectType_PublicKey;
collection->destroyObject = pubkey_destroyObject;
collection->getUIDFromObject = pubkey_getUIDFromObject;
diff --git a/security/nss/lib/pki/pkim.h b/security/nss/lib/pki/pkim.h
index 5fad8a13f..4e4268b77 100644
--- a/security/nss/lib/pki/pkim.h
+++ b/security/nss/lib/pki/pkim.h
@@ -72,6 +72,12 @@ PR_BEGIN_EXTERN_C
* nssPKIObject_DeleteStoredObject
*/
+NSS_EXTERN void nssPKIObject_Lock (nssPKIObject * object);
+NSS_EXTERN void nssPKIObject_Unlock (nssPKIObject * object);
+NSS_EXTERN PRStatus nssPKIObject_NewLock (nssPKIObject * object,
+ nssPKILockType lockType);
+NSS_EXTERN void nssPKIObject_DestroyLock(nssPKIObject * object);
+
/* nssPKIObject_Create
*
* A generic PKI object. It must live in a trust domain. It may be
@@ -83,7 +89,8 @@ nssPKIObject_Create
NSSArena *arenaOpt,
nssCryptokiObject *instanceOpt,
NSSTrustDomain *td,
- NSSCryptoContext *ccOpt
+ NSSCryptoContext *ccOpt,
+ nssPKILockType lockType
);
/* nssPKIObject_AddRef
diff --git a/security/nss/lib/pki/pkistore.c b/security/nss/lib/pki/pkistore.c
index b575d24d9..e44051b9e 100644
--- a/security/nss/lib/pki/pkistore.c
+++ b/security/nss/lib/pki/pkistore.c
@@ -89,6 +89,14 @@ struct certificate_hash_entry_str
nssSMIMEProfile *profile;
};
+/* forward static declarations */
+static NSSCertificate *
+nssCertStore_FindCertByIssuerAndSerialNumberLocked (
+ nssCertificateStore *store,
+ NSSDER *issuer,
+ NSSDER *serial
+);
+
NSS_IMPLEMENT nssCertificateStore *
nssCertificateStore_Create (
NSSArena *arenaOpt
@@ -225,29 +233,46 @@ remove_certificate_entry (
NSSCertificate *cert
);
-NSS_IMPLEMENT PRStatus
-nssCertificateStore_Add (
+/* Caller must hold store->lock */
+static PRStatus
+nssCertificateStore_AddLocked (
nssCertificateStore *store,
NSSCertificate *cert
)
{
- PRStatus nssrv;
- PZ_Lock(store->lock);
- if (nssHash_Exists(store->issuer_and_serial, cert)) {
- PZ_Unlock(store->lock);
- return PR_SUCCESS;
- }
- nssrv = add_certificate_entry(store, cert);
+ PRStatus nssrv = add_certificate_entry(store, cert);
if (nssrv == PR_SUCCESS) {
nssrv = add_subject_entry(store, cert);
if (nssrv == PR_FAILURE) {
remove_certificate_entry(store, cert);
}
}
- PZ_Unlock(store->lock);
return nssrv;
}
+
+NSS_IMPLEMENT NSSCertificate *
+nssCertificateStore_FindOrAdd (
+ nssCertificateStore *store,
+ NSSCertificate *c
+)
+{
+ PRStatus nssrv;
+ NSSCertificate *rvCert = NULL;
+
+ PZ_Lock(store->lock);
+ rvCert = nssCertStore_FindCertByIssuerAndSerialNumberLocked(
+ store, &c->issuer, &c->serial);
+ if (!rvCert) {
+ nssrv = nssCertificateStore_AddLocked(store, c);
+ if (PR_SUCCESS == nssrv) {
+ rvCert = nssCertificate_AddRef(c);
+ }
+ }
+ PZ_Unlock(store->lock);
+ return rvCert;
+}
+
static void
remove_certificate_entry (
nssCertificateStore *store,
@@ -524,24 +549,40 @@ nssCertificateStore_FindCertificatesByEmail (
return rvArray;
}
-NSS_IMPLEMENT NSSCertificate *
-nssCertificateStore_FindCertificateByIssuerAndSerialNumber (
+/* Caller holds store->lock */
+static NSSCertificate *
+nssCertStore_FindCertByIssuerAndSerialNumberLocked (
nssCertificateStore *store,
NSSDER *issuer,
NSSDER *serial
)
{
certificate_hash_entry *entry;
- NSSCertificate index;
NSSCertificate *rvCert = NULL;
+ NSSCertificate index;
+
index.issuer = *issuer;
index.serial = *serial;
- PZ_Lock(store->lock);
entry = (certificate_hash_entry *)
nssHash_Lookup(store->issuer_and_serial, &index);
if (entry) {
rvCert = nssCertificate_AddRef(entry->cert);
}
+ return rvCert;
+}
+
+NSS_IMPLEMENT NSSCertificate *
+nssCertificateStore_FindCertificateByIssuerAndSerialNumber (
+ nssCertificateStore *store,
+ NSSDER *issuer,
+ NSSDER *serial
+)
+{
+ NSSCertificate *rvCert = NULL;
+
+ PZ_Lock(store->lock);
+ rvCert = nssCertStore_FindCertByIssuerAndSerialNumberLocked (
+ store, issuer, serial);
PZ_Unlock(store->lock);
return rvCert;
}
diff --git a/security/nss/lib/pki/pkistore.h b/security/nss/lib/pki/pkistore.h
index a89ebbfac..0c347296f 100644
--- a/security/nss/lib/pki/pkistore.h
+++ b/security/nss/lib/pki/pkistore.h
@@ -81,11 +81,14 @@ nssCertificateStore_Destroy
nssCertificateStore *store
);
-NSS_EXTERN PRStatus
-nssCertificateStore_Add
+/* Atomic Find cert in store, or add this cert to the store.
+** Ref counts properly maintained.
+*/
+NSS_EXTERN NSSCertificate *
+nssCertificateStore_FindOrAdd
(
nssCertificateStore *store,
- NSSCertificate *cert
+ NSSCertificate *c
);
NSS_EXTERN void
diff --git a/security/nss/lib/pki/pkit.h b/security/nss/lib/pki/pkit.h
index fb04cbaed..46ae1a3b2 100644
--- a/security/nss/lib/pki/pkit.h
+++ b/security/nss/lib/pki/pkit.h
@@ -93,6 +93,11 @@ PR_BEGIN_EXTERN_C
* for each object.
*/
+typedef enum {
+ nssPKILock = 1,
+ nssPKIMonitor = 2
+} nssPKILockType;
+
/* nssPKIObject
*
* This is the base object class, common to all PKI objects defined in
@@ -105,7 +110,11 @@ struct nssPKIObjectStr
/* Atomically incremented/decremented reference counting */
PRInt32 refCount;
/* lock protects the array of nssCryptokiInstance's of the object */
- PZLock *lock;
+ union {
+ PZLock* lock;
+ PZMonitor *mlock;
+ } sync;
+ nssPKILockType lockType;
/* XXX with LRU cache, this cannot be guaranteed up-to-date. It cannot
* be compared against the update level of the trust domain, since it is
* also affected by import/export. Where is this array needed?
diff --git a/security/nss/lib/pki/tdcache.c b/security/nss/lib/pki/tdcache.c
index 1ae5ba6a9..3c3e0eeb1 100644
--- a/security/nss/lib/pki/tdcache.c
+++ b/security/nss/lib/pki/tdcache.c
@@ -429,7 +429,7 @@ remove_token_certs(const void *k, void *v, void *a)
nssPKIObject *object = &c->object;
struct token_cert_dtor *dtor = a;
PRUint32 i;
- PZ_Lock(object->lock);
+ nssPKIObject_Lock(object);
for (i=0; i<object->numInstances; i++) {
if (object->instances[i]->token == dtor->token) {
nssCryptokiObject_Destroy(object->instances[i]);
@@ -446,7 +446,7 @@ remove_token_certs(const void *k, void *v, void *a)
break;
}
}
- PZ_Unlock(object->lock);
+ nssPKIObject_Unlock(object);
return;
}
diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c
index 165669395..7e93bd092 100644
--- a/security/nss/lib/pki/trustdomain.c
+++ b/security/nss/lib/pki/trustdomain.c
@@ -1222,7 +1222,7 @@ nssTrustDomain_FindTrustForCertificate (
nssTokenSearchType_TokenOnly);
if (to) {
if (!pkio) {
- pkio = nssPKIObject_Create(NULL, to, td, NULL);
+ pkio = nssPKIObject_Create(NULL, to, td, NULL, nssPKILock);
if (!pkio) {
nssToken_Destroy(token);
nssCryptokiObject_Destroy(to);
diff --git a/security/nss/lib/smime/smimeutil.c b/security/nss/lib/smime/smimeutil.c
index 559d2fd37..c26330ba5 100644
--- a/security/nss/lib/smime/smimeutil.c
+++ b/security/nss/lib/smime/smimeutil.c
@@ -125,7 +125,7 @@ static const SEC_ASN1Template smime_encryptionkeypref_template[] = {
| SEC_ASN1_CONSTRUCTED,
offsetof(NSSSMIMEEncryptionKeyPreference,id.recipientKeyID),
NSSCMSRecipientKeyIdentifierTemplate,
- NSSSMIMEEncryptionKeyPref_IssuerSN },
+ NSSSMIMEEncryptionKeyPref_RKeyID },
{ SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2
| SEC_ASN1_CONSTRUCTED,
offsetof(NSSSMIMEEncryptionKeyPreference,id.subjectKeyID),
diff --git a/security/nss/lib/softoken/fipstest.c b/security/nss/lib/softoken/fipstest.c
index 6018b66a8..250c018fa 100644
--- a/security/nss/lib/softoken/fipstest.c
+++ b/security/nss/lib/softoken/fipstest.c
@@ -1499,46 +1499,27 @@ rsa_loser:
static CK_RV
sftk_fips_ECDSA_PowerUpSelfTest() {
- /* ECDSA Known info for curve nistp256 */
- static const PRUint8 ecdsa_publicValue[] = {
- EC_POINT_FORM_UNCOMPRESSED,
- 0x07, 0xb1, 0xcb, 0x57, 0x20, 0xa7, 0x10, 0xd6,
- 0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
- 0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
- 0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
- 0xb8, 0x03, 0xe6, 0x89, 0xe5, 0x06, 0x55, 0x22,
- 0x21, 0x0e, 0xcd, 0x1a, 0xf8, 0xc0, 0xd4, 0xa7,
- 0x8f, 0x47, 0x81, 0x1e, 0x4a, 0x81, 0xb5, 0x41,
- 0x3d, 0xa1, 0xf0, 0x4b, 0x65, 0xb4, 0x26, 0xe9};
-
- static const PRUint8 ecdsa_privateValue[] = {
+ /* ECDSA Known Seed info for curve nistp256 */
+ static const PRUint8 ecdsa_Known_Seed[] = {
0x6a, 0x9b, 0xf6, 0xf7, 0xce, 0xed, 0x79, 0x11,
0xf0, 0xc7, 0xc8, 0x9a, 0xa5, 0xd1, 0x57, 0xb1,
0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc,
0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f};
- static const PRUint8 ecdsa_version[] = { 0x01 };
-
- static const PRUint8 ecdsa_known_P256_signature[] = {
- 0xa8, 0x6f, 0x0a, 0x04, 0x6b, 0x6c, 0x47, 0x0c,
- 0x5a, 0xfd, 0xc6, 0x9f, 0xab, 0x65, 0x1d, 0x21,
- 0xa5, 0x8f, 0x0d, 0xe6, 0xac, 0xaa, 0x63, 0xb6,
- 0x7a, 0x39, 0x62, 0x4c, 0xae, 0xa1, 0x50, 0xb7,
- 0x30, 0xa9, 0x88, 0xeb, 0x44, 0x94, 0xb7, 0x1f,
- 0x23, 0x35, 0xe3, 0x52, 0x13, 0xd3, 0x46, 0xd0,
- 0x54, 0xfd, 0x43, 0xdc, 0x3b, 0x7f, 0xf5, 0x60,
- 0x92, 0xcc, 0x43, 0x67, 0x8c, 0xc5, 0xea, 0x75};
-
/* ECDSA Known curve nistp256 params */
static const PRUint8 knownEncodedParams[] = {
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
0x01, 0x07};
- static const PRUint8 ecdsa_Known_Seed[] = {
- 0xe3, 0x2f, 0x50, 0x8d, 0xde, 0xd3, 0x55, 0x74,
- 0xe7, 0x71, 0x86, 0x76, 0x3b, 0xeb, 0x84, 0x15,
- 0x1b, 0x49, 0xf5, 0x18, 0xe5, 0x5f, 0x84, 0x7e,
- 0x76, 0x16, 0x14, 0x4f, 0x79, 0x4f, 0xbb, 0xd6};
+ static const PRUint8 ecdsa_known_P256_signature[] = {
+ 0x07,0xb1,0xcb,0x57,0x20,0xa7,0x10,0xd6,
+ 0x9d,0x37,0x4b,0x1c,0xdc,0x35,0x90,0xff,
+ 0x1a,0x2d,0x98,0x95,0x1b,0x2f,0xeb,0x7f,
+ 0xbb,0x81,0xca,0xc0,0x69,0x75,0xea,0xc5,
+ 0x59,0x6a,0x62,0x49,0x3d,0x50,0xc9,0xe1,
+ 0x27,0x3b,0xff,0x9b,0x13,0x66,0x67,0xdd,
+ 0x7d,0xd1,0x0d,0x2d,0x7c,0x44,0x04,0x1b,
+ 0x16,0x21,0x12,0xc5,0xcb,0xbd,0x9e,0x75};
static const PRUint8 msg[] = {
"Firefox and ThunderBird are awesome!"};
@@ -1547,8 +1528,8 @@ sftk_fips_ECDSA_PowerUpSelfTest() {
unsigned char sig[2*MAX_ECKEY_LEN];
SECItem signature, digest;
SECItem encodedparams;
- ECParams *ecparams;
- ECPrivateKey ecdsa_private_key;
+ ECParams *ecparams = NULL;
+ ECPrivateKey *ecdsa_private_key = NULL;
ECPublicKey ecdsa_public_key;
SECStatus ecdsaStatus = SECSuccess;
@@ -1556,39 +1537,40 @@ sftk_fips_ECDSA_PowerUpSelfTest() {
encodedparams.type = siBuffer;
encodedparams.data = (unsigned char *) knownEncodedParams;
encodedparams.len = sizeof knownEncodedParams;
+
if (EC_DecodeParams(&encodedparams, &ecparams) != SECSuccess) {
return( CKR_DEVICE_ERROR );
}
- ecdsa_private_key.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (ecdsa_private_key.ecParams.arena == NULL) {
- PORT_FreeArena(ecparams->arena, PR_FALSE);
- return CKR_HOST_MEMORY;
+ /* Generates a new EC key pair. The private key is a supplied
+ * random value (in seed) and the public key is the result of
+ * performing a scalar point multiplication of that value with
+ * the curve's base point.
+ */
+ if (EC_NewKeyFromSeed(ecparams, &ecdsa_private_key, ecdsa_Known_Seed,
+ sizeof(ecdsa_Known_Seed)) != SECSuccess) {
+ return( CKR_DEVICE_ERROR );
}
- ecdsaStatus = EC_CopyParams(ecdsa_private_key.ecParams.arena,
- &ecdsa_private_key.ecParams, ecparams);
- PORT_FreeArena(ecparams->arena, PR_FALSE);
+ /* construct public key from private key. */
+ ecdsaStatus = EC_CopyParams(ecdsa_private_key->ecParams.arena,
+ &ecdsa_public_key.ecParams,
+ &ecdsa_private_key->ecParams);
+ if (ecdsaStatus != SECSuccess) {
+ goto loser;
+ }
+ ecdsa_public_key.publicValue = ecdsa_private_key->publicValue;
+ /* validate public key value */
+ ecdsaStatus = EC_ValidatePublicKey(&ecdsa_public_key.ecParams,
+ &ecdsa_public_key.publicValue);
if (ecdsaStatus != SECSuccess) {
goto loser;
}
-
- ecdsa_private_key.publicValue.type = siBuffer;
- ecdsa_private_key.publicValue.data = (unsigned char *)ecdsa_publicValue;
- ecdsa_private_key.publicValue.len = sizeof ecdsa_publicValue;
-
- ecdsa_private_key.privateValue.type = siBuffer;
- ecdsa_private_key.privateValue.data = (unsigned char *)ecdsa_privateValue;
- ecdsa_private_key.privateValue.len = sizeof ecdsa_privateValue;
-
- ecdsa_private_key.version.type = siBuffer;
- ecdsa_private_key.version.data = (unsigned char *)ecdsa_version;
- ecdsa_private_key.version.len = sizeof ecdsa_version;
/* validate public key value */
- ecdsaStatus = EC_ValidatePublicKey(&ecdsa_private_key.ecParams,
- &ecdsa_private_key.publicValue);
+ ecdsaStatus = EC_ValidatePublicKey(&ecdsa_private_key->ecParams,
+ &ecdsa_private_key->publicValue);
if (ecdsaStatus != SECSuccess) {
goto loser;
}
@@ -1610,7 +1592,7 @@ sftk_fips_ECDSA_PowerUpSelfTest() {
signature.data = sig;
signature.len = sizeof sig;
- ecdsaStatus = ECDSA_SignDigestWithSeed(&ecdsa_private_key, &signature,
+ ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature,
&digest, ecdsa_Known_Seed, sizeof ecdsa_Known_Seed);
if (ecdsaStatus != SECSuccess) {
goto loser;
@@ -1622,15 +1604,6 @@ sftk_fips_ECDSA_PowerUpSelfTest() {
ecdsaStatus = SECFailure;
goto loser;
}
-
- /* construct public key from private key. */
- ecdsaStatus = EC_CopyParams(ecdsa_private_key.ecParams.arena,
- &ecdsa_public_key.ecParams,
- &ecdsa_private_key.ecParams);
- if (ecdsaStatus != SECSuccess) {
- goto loser;
- }
- ecdsa_public_key.publicValue = ecdsa_private_key.publicValue;
/******************************************************/
/* ECDSA Single-Round Known Answer Verification Test. */
@@ -1640,9 +1613,9 @@ sftk_fips_ECDSA_PowerUpSelfTest() {
ecdsaStatus = ECDSA_VerifyDigest(&ecdsa_public_key, &signature, &digest);
loser:
- /* free the memory for the private */
- if (ecdsa_private_key.ecParams.arena != NULL) {
- PORT_FreeArena(ecdsa_private_key.ecParams.arena, PR_FALSE);
+ /* free the memory for the private key arena*/
+ if (ecdsa_private_key->ecParams.arena != NULL) {
+ PORT_FreeArena(ecdsa_private_key->ecParams.arena, PR_FALSE);
}
if (ecdsaStatus != SECSuccess) {
@@ -1831,6 +1804,19 @@ sftk_fips_RNG_PowerUpSelfTest( void )
return( CKR_OK );
}
+static CK_RV
+sftk_fipsSoftwareIntegrityTest(void)
+{
+ CK_RV crv = CKR_OK;
+
+ /* make sure that our check file signatures are OK */
+ if( !BLAPI_VerifySelf( NULL ) ||
+ !BLAPI_SHVerify( SOFTOKEN_LIB_NAME, (PRFuncPtr) sftk_fips_HMAC ) ) {
+ crv = CKR_DEVICE_ERROR; /* better error code? checksum error? */
+ }
+ return crv;
+}
+
CK_RV
sftk_fipsPowerUpSelfTest( void )
{
@@ -1928,6 +1914,12 @@ sftk_fipsPowerUpSelfTest( void )
return rv;
#endif
+ /* Software/Firmware Integrity Test. */
+ rv = sftk_fipsSoftwareIntegrityTest();
+
+ if( rv != CKR_OK )
+ return rv;
+
/* Passed Power-Up SelfTest(s). */
return( CKR_OK );
}
diff --git a/security/nss/lib/softoken/fipstokn.c b/security/nss/lib/softoken/fipstokn.c
index d2d19fda4..279ffaa12 100644
--- a/security/nss/lib/softoken/fipstokn.c
+++ b/security/nss/lib/softoken/fipstokn.c
@@ -438,7 +438,7 @@ CK_RV FC_Initialize(CK_VOID_PTR pReserved) {
char msg[128];
PR_snprintf(msg,sizeof msg,
"C_Initialize()=0x%08lX "
- "self-test: cryptographic algorithm test failed",
+ "power-up self-tests failed",
(PRUint32)crv);
sftk_LogAuditMessage(NSS_AUDIT_ERROR, msg);
}
@@ -484,7 +484,7 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CK_RV crv;
crv = NSC_GetTokenInfo(slotID,pInfo);
- pInfo->flags |= CKF_RNG | CKF_LOGIN_REQUIRED;
+ pInfo->flags |= CKF_LOGIN_REQUIRED;
return crv;
}
@@ -616,37 +616,19 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CK_RV FC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
CK_CHAR_PTR pPin, CK_ULONG usPinLen) {
CK_RV rv;
+ PRBool successful;
if (sftk_fatalError) return CKR_DEVICE_ERROR;
rv = NSC_Login(hSession,userType,pPin,usPinLen);
- if (rv == CKR_OK)
+ successful = (rv == CKR_OK) || (rv == CKR_USER_ALREADY_LOGGED_IN);
+ if (successful)
isLoggedIn = PR_TRUE;
- else if (rv == CKR_USER_ALREADY_LOGGED_IN)
- {
- isLoggedIn = PR_TRUE;
-
- /* Provide FIPS PUB 140-2 power-up self-tests on demand. */
- rv = sftk_fipsPowerUpSelfTest();
- if (rv == CKR_OK)
- rv = CKR_USER_ALREADY_LOGGED_IN;
- else
- sftk_fatalError = PR_TRUE;
- }
if (sftk_audit_enabled) {
char msg[128];
NSSAuditSeverity severity;
- if (sftk_fatalError) {
- severity = NSS_AUDIT_ERROR;
- PR_snprintf(msg,sizeof msg,
- "C_Login(hSession=%lu, userType=%lu)=0x%08lX ",
- "self-test: cryptographic algorithm test failed",
- (PRUint32)hSession,(PRUint32)userType,(PRUint32)rv);
- } else {
- severity = (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) ?
- NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
- PR_snprintf(msg,sizeof msg,
- "C_Login(hSession=%lu, userType=%lu)=0x%08lX",
- (PRUint32)hSession,(PRUint32)userType,(PRUint32)rv);
- }
+ severity = successful ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
+ PR_snprintf(msg,sizeof msg,
+ "C_Login(hSession=%lu, userType=%lu)=0x%08lX",
+ (PRUint32)hSession,(PRUint32)userType,(PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
return rv;
diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c
index da79f6b73..df17f7f4b 100644
--- a/security/nss/lib/softoken/keydb.c
+++ b/security/nss/lib/softoken/keydb.c
@@ -1425,50 +1425,6 @@ nsslowkey_DeriveKeyDBPassword(NSSLOWKEYDBHandle *keydb, char *pw)
return nsslowkey_HashPassword(pw, keydb->global_salt);
}
-#if 0
-/* Appears obsolete - TNH */
-/* get the algorithm with which a private key
- * is encrypted.
- */
-SECOidTag
-seckey_get_private_key_algorithm(NSSLOWKEYDBHandle *keydb, DBT *index)
-{
- NSSLOWKEYDBKey *dbkey = NULL;
- SECOidTag algorithm = SEC_OID_UNKNOWN;
- NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL;
- PLArenaPool *poolp = NULL;
- SECStatus rv;
-
- poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if(poolp == NULL)
- return (SECOidTag)SECFailure; /* TNH - this is bad */
-
- dbkey = get_dbkey(keydb, index);
- if(dbkey == NULL)
- return (SECOidTag)SECFailure;
-
- epki = (NSSLOWKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp,
- sizeof(NSSLOWKEYEncryptedPrivateKeyInfo));
- if(epki == NULL)
- goto loser;
- rv = SEC_ASN1DecodeItem(poolp, epki,
- nsslowkey_EncryptedPrivateKeyInfoTemplate, &dbkey->derPK);
- if(rv == SECFailure)
- goto loser;
-
- algorithm = SECOID_GetAlgorithmTag(&epki->algorithm);
-
- /* let success fall through */
-loser:
- if(poolp != NULL)
- PORT_FreeArena(poolp, PR_TRUE);\
- if(dbkey != NULL)
- sec_destroy_dbkey(dbkey);
-
- return algorithm;
-}
-#endif
-
/*
* Derive an RC4 key from a password key and a salt. This
* was the method to used to encrypt keys in the version 2?
@@ -1813,7 +1769,7 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem,
{
NSSLOWKEYDBKey *dbkey = NULL;
NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL;
- PLArenaPool *temparena = NULL, *permarena = NULL;
+ PLArenaPool *arena = NULL;
SECItem *dummy = NULL;
SECItem *salt = NULL;
SECStatus rv = SECFailure;
@@ -1822,14 +1778,14 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem,
(pk == NULL))
return SECFailure;
- permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
- if(permarena == NULL)
+ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if(arena == NULL)
return SECFailure;
- dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(permarena, sizeof(NSSLOWKEYDBKey));
+ dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYDBKey));
if(dbkey == NULL)
goto loser;
- dbkey->arena = permarena;
+ dbkey->arena = arena;
dbkey->nickname = nickname;
/* TNH - for RC4, the salt should be created here */
@@ -1837,15 +1793,14 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem,
epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm, &salt);
if(epki == NULL)
goto loser;
- temparena = epki->arena;
if(salt != NULL)
{
- rv = SECITEM_CopyItem(permarena, &(dbkey->salt), salt);
+ rv = SECITEM_CopyItem(arena, &(dbkey->salt), salt);
SECITEM_ZfreeItem(salt, PR_TRUE);
}
- dummy = SEC_ASN1EncodeItem(permarena, &(dbkey->derPK), epki,
+ dummy = SEC_ASN1EncodeItem(arena, &(dbkey->derPK), epki,
nsslowkey_EncryptedPrivateKeyInfoTemplate);
if(dummy == NULL)
rv = SECFailure;
@@ -1854,11 +1809,10 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem,
/* let success fall through */
loser:
- if(rv != SECSuccess)
- if(permarena != NULL)
- PORT_FreeArena(permarena, PR_TRUE);
- if(temparena != NULL)
- PORT_FreeArena(temparena, PR_TRUE);
+ if(arena != NULL)
+ PORT_FreeArena(arena, PR_TRUE);
+ if(epki != NULL)
+ PORT_FreeArena(epki->arena, PR_TRUE);
return rv;
}
diff --git a/security/nss/lib/softoken/lowpbe.c b/security/nss/lib/softoken/lowpbe.c
index b73485948..6b4605b4e 100644
--- a/security/nss/lib/softoken/lowpbe.c
+++ b/security/nss/lib/softoken/lowpbe.c
@@ -824,7 +824,7 @@ void
nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param)
{
if (pbe_param != NULL) {
- PORT_FreeArena(pbe_param->poolp, PR_TRUE);
+ PORT_FreeArena(pbe_param->poolp, PR_FALSE);
}
}
diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c
index 824938583..80f9c5f71 100644
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -2986,21 +2986,6 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
if (isFIPS) {
- /* make sure that our check file signatures are OK */
- if (!BLAPI_VerifySelf(NULL) ||
- !BLAPI_SHVerify(SOFTOKEN_LIB_NAME, (PRFuncPtr) sftk_closePeer)) {
- crv = CKR_DEVICE_ERROR; /* better error code? checksum error? */
- if (sftk_audit_enabled) {
- char msg[128];
- PR_snprintf(msg,sizeof msg,
- "C_Initialize()=0x%08lX "
- "self-test: software/firmware integrity test failed",
- (PRUint32)crv);
- sftk_LogAuditMessage(NSS_AUDIT_ERROR, msg);
- }
- return crv;
- }
-
loginWaitTime = PR_SecondsToInterval(1);
}
@@ -3232,7 +3217,6 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
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.
@@ -3268,6 +3252,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
PORT_Memcpy(pInfo->model,"NSS 3 ",16);
PORT_Memcpy(pInfo->serialNumber,"0000000000000000",16);
+ PORT_Memcpy(pInfo->utcTime,"0000000000000000",16);
pInfo->ulMaxSessionCount = 0; /* arbitrarily large */
pInfo->ulSessionCount = slot->sessionCount;
pInfo->ulMaxRwSessionCount = 0; /* arbitarily large */
@@ -3276,8 +3261,9 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->firmwareVersion.minor = 0;
PORT_Memcpy(pInfo->label,slot->tokDescription,32);
handle = sftk_getKeyDB(slot);
+ pInfo->flags = CKF_RNG | CKF_DUAL_CRYPTO_OPERATIONS;
if (handle == NULL) {
- pInfo->flags= CKF_RNG | CKF_WRITE_PROTECTED | CKF_THREAD_SAFE;
+ pInfo->flags |= CKF_WRITE_PROTECTED;
pInfo->ulMaxPinLen = 0;
pInfo->ulMinPinLen = 0;
pInfo->ulTotalPublicMemory = 0;
@@ -3297,12 +3283,11 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
* we will need to prompt for it.
*/
if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) {
- pInfo->flags = CKF_THREAD_SAFE | CKF_LOGIN_REQUIRED;
+ pInfo->flags |= CKF_LOGIN_REQUIRED;
} else if (!sftk_checkNeedLogin(slot,handle)) {
- pInfo->flags = CKF_THREAD_SAFE | CKF_USER_PIN_INITIALIZED;
+ pInfo->flags |= CKF_USER_PIN_INITIALIZED;
} else {
- pInfo->flags = CKF_THREAD_SAFE |
- CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED;
+ pInfo->flags |= CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED;
}
pInfo->ulMaxPinLen = SFTK_MAX_PIN;
pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen;
@@ -3314,6 +3299,18 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->hardwareVersion.minor = handle->version;
sftk_freeKeyDB(handle);
}
+ /*
+ * CKF_LOGIN_REQUIRED CKF_USER_PIN_INITIALIZED how CKF_TOKEN_INITIALIZED
+ * should be set
+ * 0 0 1
+ * 1 0 0
+ * 0 1 1
+ * 1 1 1
+ */
+ if (!(pInfo->flags & CKF_LOGIN_REQUIRED) ||
+ (pInfo->flags & CKF_USER_PIN_INITIALIZED)) {
+ pInfo->flags |= CKF_TOKEN_INITIALIZED;
+ }
return CKR_OK;
}
diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c
index 8bae971ec..11068de17 100644
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -1293,7 +1293,7 @@ static SECStatus
sftk_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen,
unsigned char *hash, unsigned int hashLen)
{
- return PORT_Memcmp(sig,hash,*copyLen) ? SECSuccess : SECFailure ;
+ return (PORT_Memcmp(sig,hash,*copyLen) == 0) ? SECSuccess : SECFailure ;
}
/*
@@ -2333,13 +2333,22 @@ CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
{
SFTKSession *session;
SFTKSessionContext *context;
- CK_RV crv;
+ CK_RV crv, crv2;
SECStatus rv;
/* make sure we're legal */
crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_FALSE,&session);
if (crv != CKR_OK) return crv;
+ /* multi part Verifying are completely implemented by VerifyUpdate and
+ * VerifyFinal */
+ if (context->multi) {
+ sftk_FreeSession(session);
+ crv = NSC_VerifyUpdate(hSession, pData, ulDataLen);
+ crv2 = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen);
+ return crv == CKR_OK ? crv2 :crv;
+ }
+
rv = (*context->verify)(context->cipherInfo,pSignature, ulSignatureLen,
pData, ulDataLen);
sftk_FreeContext(context);
@@ -4132,13 +4141,13 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
sizeof(NSSLOWKEYPrivateKeyInfo));
if(!pki) {
- PORT_FreeArena(arena, PR_TRUE);
+ PORT_FreeArena(arena, PR_FALSE);
return SECFailure;
}
if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki)
!= SECSuccess) {
- PORT_FreeArena(arena, PR_FALSE);
+ PORT_FreeArena(arena, PR_TRUE);
return SECFailure;
}
diff --git a/security/nss/lib/ssl/derive.c b/security/nss/lib/ssl/derive.c
index c00822bee..9e7727398 100644
--- a/security/nss/lib/ssl/derive.c
+++ b/security/nss/lib/ssl/derive.c
@@ -52,6 +52,7 @@ buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result)
result->type = siBuffer;
result->data = keyBlock;
result->len = keyLen;
+ PRINT_BUF(100, (NULL, "key value", keyBlock, keyLen));
}
#else
#define buildSSLKey(keyBlock, keyLen, result) \
@@ -59,6 +60,7 @@ buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result)
(result)->type = siBuffer; \
(result)->data = keyBlock; \
(result)->len = keyLen; \
+ PRINT_BUF(100, (NULL, "key value", keyBlock, keyLen)); \
}
#endif
@@ -122,6 +124,9 @@ ssl3_KeyAndMacDeriveBypass(
return rv;
}
+ PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
+ pwSpec->msItem.len));
+
/* figure out how much is needed */
macSize = pwSpec->mac_size;
keySize = cipher_def->key_size;
@@ -153,6 +158,7 @@ ssl3_KeyAndMacDeriveBypass(
crsr.len = sizeof crsrdata;
PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
+ PRINT_BUF(100, (NULL, "Key & MAC CRSR", crsr.data, crsr.len));
/*
* generate the key material:
@@ -203,6 +209,7 @@ ssl3_KeyAndMacDeriveBypass(
}
PORT_Assert(block_bytes >= block_needed);
PORT_Assert(block_bytes <= sizeof pwSpec->key_block);
+ PRINT_BUF(100, (NULL, "key block", key_block, block_bytes));
/*
* Put the key material where it goes.
@@ -395,7 +402,9 @@ key_and_mac_derive_fail:
/* derive the Master Secret from the PMS */
-/* Presently, this is only done wtih RSA PMS, os isRSA is always true. */
+/* Presently, this is only done wtih RSA PMS, and only on the server side,
+ * so isRSA is always true.
+ */
SECStatus
ssl3_MasterKeyDeriveBypass(
ssl3CipherSpec * pwSpec,
@@ -434,6 +443,7 @@ ssl3_MasterKeyDeriveBypass(
crsr.len = sizeof crsrdata;
PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
+ PRINT_BUF(100, (NULL, "Master Secret CRSR", crsr.data, crsr.len));
/* finally do the key gen */
if (isTLS) {
@@ -474,6 +484,8 @@ ssl3_MasterKeyDeriveBypass(
SSL3_MASTER_SECRET_LENGTH);
pwSpec->msItem.data = pwSpec->raw_master_secret;
pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
+ PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
+ pwSpec->msItem.len));
return rv;
}
diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c
index 37ca116c5..043e08886 100644
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -4102,6 +4102,19 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
goto loser;
}
+#if defined(TRACE)
+ if (ssl_trace >= 100) {
+ SECStatus extractRV = PK11_ExtractKeyValue(pms);
+ if (extractRV == SECSuccess) {
+ SECItem * keyData = PK11_GetKeyData(pms);
+ if (keyData && keyData->data && keyData->len) {
+ ssl_PrintBuf(ss, "Pre-Master Secret",
+ keyData->data, keyData->len);
+ }
+ }
+ }
+#endif
+
/* Get the wrapped (encrypted) pre-master secret, enc_pms */
enc_pms.len = SECKEY_PublicKeyStrength(svrPubKey);
enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len);
diff --git a/security/nss/lib/ssl/ssl3ecc.c b/security/nss/lib/ssl/ssl3ecc.c
index 144968c4d..a4c0f9da8 100644
--- a/security/nss/lib/ssl/ssl3ecc.c
+++ b/security/nss/lib/ssl/ssl3ecc.c
@@ -367,6 +367,8 @@ ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
CKD_NULL, NULL, NULL);
if (pms == NULL) {
+ SSL3AlertDescription desc = illegal_parameter;
+ (void)SSL3_SendAlert(ss, alert_fatal, desc);
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
goto loser;
}
diff --git a/security/nss/lib/util/secasn1d.c b/security/nss/lib/util/secasn1d.c
index e0a8f6439..068d52ed6 100644
--- a/security/nss/lib/util/secasn1d.c
+++ b/security/nss/lib/util/secasn1d.c
@@ -1414,7 +1414,7 @@ sec_asn1d_free_child (sec_asn1d_state *state, PRBool error)
if (state->child != NULL) {
PORT_Assert (error || state->child->consumed == 0);
PORT_Assert (state->our_mark != NULL);
- PORT_ArenaRelease (state->top->our_pool, state->our_mark);
+ PORT_ArenaZRelease (state->top->our_pool, state->our_mark);
if (error && state->top->their_pool == NULL) {
/*
* XXX We need to free anything allocated.
@@ -2849,7 +2849,7 @@ SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext *cx)
* XXX anything else that needs to be finished?
*/
- PORT_FreeArena (cx->our_pool, PR_FALSE);
+ PORT_FreeArena (cx->our_pool, PR_TRUE);
return rv;
}
diff --git a/security/nss/lib/util/secdig.c b/security/nss/lib/util/secdig.c
index 263c8030f..07c136a74 100644
--- a/security/nss/lib/util/secdig.c
+++ b/security/nss/lib/util/secdig.c
@@ -166,21 +166,26 @@ SGN_DecodeDigestInfo(SECItem *didata)
PRArenaPool *arena;
SGNDigestInfo *di;
SECStatus rv = SECFailure;
+ SECItem diCopy = {siBuffer, NULL, 0};
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if(arena == NULL)
return NULL;
+ rv = SECITEM_CopyItem(arena, &diCopy, didata);
+ if (rv != SECSuccess) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+ }
+
di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
- if(di != NULL)
- {
+ if (di != NULL) {
di->arena = arena;
- rv = SEC_ASN1DecodeItem(arena, di, sgn_DigestInfoTemplate, didata);
+ rv = SEC_QuickDERDecodeItem(arena, di, sgn_DigestInfoTemplate, &diCopy);
}
- if((di == NULL) || (rv != SECSuccess))
- {
- PORT_FreeArena(arena, PR_TRUE);
+ if ((di == NULL) || (rv != SECSuccess)) {
+ PORT_FreeArena(arena, PR_FALSE);
di = NULL;
}
diff --git a/security/nss/lib/util/secport.c b/security/nss/lib/util/secport.c
index 4ad02ba91..9b9fda1c5 100644
--- a/security/nss/lib/util/secport.c
+++ b/security/nss/lib/util/secport.c
@@ -271,7 +271,9 @@ PORT_ArenaZAlloc(PLArenaPool *arena, size_t size)
return(p);
}
-/* XXX - need to zeroize!! - jsw */
+/*
+ * If zero is true, zeroize the arena memory before freeing it.
+ */
void
PORT_FreeArena(PLArenaPool *arena, PRBool zero)
{
@@ -303,6 +305,13 @@ PORT_FreeArena(PLArenaPool *arena, PRBool zero)
if (!ev) doFreeArenaPool = PR_TRUE;
}
}
+ if (zero) {
+ PLArena *a;
+ for (a = arena->first.next; a; a = a->next) {
+ PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ memset((void *)a->base, 0, a->avail - a->base);
+ }
+ }
if (doFreeArenaPool) {
PL_FreeArenaPool(arena);
} else {
@@ -385,8 +394,32 @@ PORT_ArenaMark(PLArenaPool *arena)
return result;
}
-void
-PORT_ArenaRelease(PLArenaPool *arena, void *mark)
+static void
+port_ArenaZeroAfterMark(PLArenaPool *arena, void *mark)
+{
+ PLArena *a = arena->current;
+ if (a->base <= (PRUword)mark && (PRUword)mark <= a->avail) {
+ /* fast path: mark falls in the current arena */
+ memset(mark, 0, a->avail - (PRUword)mark);
+ } else {
+ /* slow path: need to find the arena that mark falls in */
+ for (a = arena->first.next; a; a = a->next) {
+ PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ if (a->base <= (PRUword)mark && (PRUword)mark <= a->avail) {
+ memset(mark, 0, a->avail - (PRUword)mark);
+ a = a->next;
+ break;
+ }
+ }
+ for (; a; a = a->next) {
+ PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ memset((void *)a->base, 0, a->avail - a->base);
+ }
+ }
+}
+
+static void
+port_ArenaRelease(PLArenaPool *arena, void *mark, PRBool zero)
{
PORTArenaPool *pool = (PORTArenaPool *)arena;
if (ARENAPOOL_MAGIC == pool->magic ) {
@@ -418,6 +451,9 @@ PORT_ArenaRelease(PLArenaPool *arena, void *mark)
tm = *pw;
*pw = (threadmark_mark *)NULL;
+ if (zero) {
+ port_ArenaZeroAfterMark(arena, mark);
+ }
PL_ARENA_RELEASE(arena, mark);
if (! pool->first_mark ) {
@@ -425,15 +461,36 @@ PORT_ArenaRelease(PLArenaPool *arena, void *mark)
}
}
#else /* THREADMARK */
+ if (zero) {
+ port_ArenaZeroAfterMark(arena, mark);
+ }
PL_ARENA_RELEASE(arena, mark);
#endif /* THREADMARK */
PZ_Unlock(pool->lock);
} else {
+ if (zero) {
+ port_ArenaZeroAfterMark(arena, mark);
+ }
PL_ARENA_RELEASE(arena, mark);
}
}
void
+PORT_ArenaRelease(PLArenaPool *arena, void *mark)
+{
+ port_ArenaRelease(arena, mark, PR_FALSE);
+}
+
+/*
+ * Zeroize the arena memory before releasing it.
+ */
+void
+PORT_ArenaZRelease(PLArenaPool *arena, void *mark)
+{
+ port_ArenaRelease(arena, mark, PR_TRUE);
+}
+
+void
PORT_ArenaUnmark(PLArenaPool *arena, void *mark)
{
#ifdef THREADMARK
diff --git a/security/nss/lib/util/secport.h b/security/nss/lib/util/secport.h
index 65c14def0..d30328de0 100644
--- a/security/nss/lib/util/secport.h
+++ b/security/nss/lib/util/secport.h
@@ -137,6 +137,7 @@ extern void *PORT_ArenaGrow(PLArenaPool *arena, void *ptr,
size_t oldsize, size_t newsize);
extern void *PORT_ArenaMark(PLArenaPool *arena);
extern void PORT_ArenaRelease(PLArenaPool *arena, void *mark);
+extern void PORT_ArenaZRelease(PLArenaPool *arena, void *mark);
extern void PORT_ArenaUnmark(PLArenaPool *arena, void *mark);
extern char *PORT_ArenaStrdup(PLArenaPool *arena, const char *str);