diff options
author | kaie%kuix.de <devnull@localhost> | 2006-09-01 21:03:20 +0000 |
---|---|---|
committer | kaie%kuix.de <devnull@localhost> | 2006-09-01 21:03:20 +0000 |
commit | e037b14c56ca15921becded36580230f6a3b6ecb (patch) | |
tree | c07da6da2792dc439286fcc117e631c63094ea93 | |
parent | ddaea507f54f66053182664fa2da68a7b734146a (diff) | |
download | nss-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
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); |