From 430790c1b1240f4f4c8fc3171819fad458a0b5e8 Mon Sep 17 00:00:00 2001 From: Roy Tam Date: Tue, 7 Jan 2020 15:11:52 +0800 Subject: [PATCH] cherry-picked mozilla NSS upstream changes (to rev 5fe63c0b, sha512.c changes are refined for VC6): bug1182667(other parts), bug1117022, bug1190248, bug1192020, bug1185033, bug1199349, bug1199467, bug1199494 --- security/nss/cmd/bltest/blapitest.c | 2 +- security/nss/cmd/certcgi/certcgi.c | 4 +- security/nss/cmd/lib/secpwd.c | 6 +- security/nss/cmd/selfserv/selfserv.c | 34 +- security/nss/cmd/signtool/certgen.c | 31 +- security/nss/cmd/tstclnt/tstclnt.c | 20 +- security/nss/coreconf/Darwin.mk | 20 + security/nss/coreconf/Linux.mk | 30 +- security/nss/coreconf/rules.mk | 24 +- security/nss/lib/dbm/src/h_page.c | 12 +- security/nss/lib/dbm/src/hash.c | 2 +- security/nss/lib/freebl/drbg.c | 2 +- security/nss/lib/freebl/ecl/ecp_192.c | 4 +- security/nss/lib/freebl/ecl/ecp_224.c | 2 +- security/nss/lib/freebl/mpi/mpi.c | 29 +- security/nss/lib/freebl/pqg.c | 2 +- security/nss/lib/freebl/sha512.c | 18 +- security/nss/lib/jar/jarfile.c | 2 +- .../module/pkix_pl_ldapdefaultclient.c | 2 +- .../pkix_pl_nss/module/pkix_pl_ldapresponse.c | 2 +- .../pkix_pl_nss/system/pkix_pl_object.c | 4 +- security/nss/lib/pk11wrap/pk11mech.c | 4 + security/nss/lib/pk11wrap/pk11merge.c | 6 +- security/nss/lib/pk11wrap/pk11obj.c | 4 +- security/nss/lib/pk11wrap/pk11pk12.c | 8 +- security/nss/lib/softoken/legacydb/keydb.c | 2 +- security/nss/lib/softoken/legacydb/lginit.c | 2 +- security/nss/lib/softoken/pkcs11.c | 10 +- security/nss/lib/softoken/pkcs11c.c | 101 +++- security/nss/lib/softoken/sftkdb.c | 6 +- security/nss/lib/ssl/SSLerrs.h | 6 + security/nss/lib/ssl/derive.c | 2 +- security/nss/lib/ssl/ssl.h | 8 + security/nss/lib/ssl/ssl3con.c | 565 +++++++++++++----- security/nss/lib/ssl/ssl3ecc.c | 16 +- security/nss/lib/ssl/ssl3ext.c | 116 +++- security/nss/lib/ssl/sslerr.h | 3 + security/nss/lib/ssl/sslimpl.h | 7 +- security/nss/lib/ssl/sslinfo.c | 2 + security/nss/lib/ssl/sslsnce.c | 95 +-- security/nss/lib/ssl/sslsock.c | 14 + security/nss/lib/ssl/sslt.h | 9 +- security/nss/lib/util/pkcs11n.h | 43 +- security/nss/lib/util/secport.h | 10 +- security/nss/lib/util/utilmod.c | 12 +- security/nss/tests/common/cleanup.sh | 12 +- 46 files changed, 969 insertions(+), 346 deletions(-) diff --git a/security/nss/cmd/bltest/blapitest.c b/security/nss/cmd/bltest/blapitest.c index 81c3061b..204814d8 100644 --- a/security/nss/cmd/bltest/blapitest.c +++ b/security/nss/cmd/bltest/blapitest.c @@ -3552,7 +3552,7 @@ int main(int argc, char **argv) unsigned int keySize = 1024; unsigned long exponent = 65537; int rounds = 1; - int ret; + int ret = -1; if (bltest.options[opt_KeySize].activated) { keySize = PORT_Atoi(bltest.options[opt_KeySize].arg); diff --git a/security/nss/cmd/certcgi/certcgi.c b/security/nss/cmd/certcgi/certcgi.c index 889de254..1095d80e 100644 --- a/security/nss/cmd/certcgi/certcgi.c +++ b/security/nss/cmd/certcgi/certcgi.c @@ -508,8 +508,8 @@ get_serial_number(Pair *data) if (find_field_bool(data, "serial-auto", PR_TRUE)) { serialFile = fopen(filename, "r"); if (serialFile != NULL) { - fread(&serial, sizeof(int), 1, serialFile); - if (ferror(serialFile) != 0) { + size_t nread = fread(&serial, sizeof(int), 1, serialFile); + if (ferror(serialFile) != 0 || nread != 1) { error_out("Error: Unable to read serial number file"); } if (serial == -1) { diff --git a/security/nss/cmd/lib/secpwd.c b/security/nss/cmd/lib/secpwd.c index 2c4579d7..d78e56cc 100644 --- a/security/nss/cmd/lib/secpwd.c +++ b/security/nss/cmd/lib/secpwd.c @@ -74,7 +74,9 @@ char *SEC_GetPassword(FILE *input, FILE *output, char *prompt, echoOff(infd); } - QUIET_FGETS ( phrase, sizeof(phrase), input); + if (QUIET_FGETS(phrase, sizeof(phrase), input) == NULL) { + return NULL; + } if (isTTY) { fprintf(output, "\n"); @@ -87,7 +89,7 @@ char *SEC_GetPassword(FILE *input, FILE *output, char *prompt, /* Validate password */ if (!(*ok)(phrase)) { /* Not weird enough */ - if (!isTTY) return 0; + if (!isTTY) return NULL; fprintf(output, "Password must be at least 8 characters long with one or more\n"); fprintf(output, "non-alphabetic characters\n"); continue; diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c index 9509892d..549fda53 100644 --- a/security/nss/cmd/selfserv/selfserv.c +++ b/security/nss/cmd/selfserv/selfserv.c @@ -65,7 +65,7 @@ static const char inheritableSockName[] = { "SELFSERV_LISTEN_SOCKET" }; #define MAX_BULK_TEST 1048576 /* 1 MB */ static PRBool testBulk; static PRUint32 testBulkSize = DEFAULT_BULK_TEST; -static PRUint32 testBulkTotal; +static PRInt32 testBulkTotal; static char* testBulkBuf; static PRDescIdentity log_layer_id = PR_INVALID_IO_LAYER; static PRFileDesc *loggingFD; @@ -74,10 +74,10 @@ static PRIOMethods loggingMethods; static PRBool logStats; static PRBool loggingLayer; static int logPeriod = 30; -static PRUint32 loggerOps; -static PRUint32 loggerBytes; -static PRUint32 loggerBytesTCP; -static PRUint32 bulkSentChunks; +static PRInt32 loggerOps; +static PRInt32 loggerBytes; +static PRInt32 loggerBytesTCP; +static PRInt32 bulkSentChunks; static enum ocspStaplingModeEnum { osm_disabled, /* server doesn't support stapling */ osm_good, /* supply a signed good status */ @@ -428,10 +428,11 @@ printSecurityInfo(PRFileDesc *fd) suite.macBits, suite.macAlgorithmName); FPRINTF(stderr, "selfserv: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n" - " Compression: %s\n", + " Compression: %s, Extended Master Secret: %s\n", channel.authKeyBits, suite.authAlgorithmName, channel.keaKeyBits, suite.keaTypeName, - channel.compressionMethodName); + channel.compressionMethodName, + channel.extendedMasterSecretUsed ? "Yes": "No"); } } if (verbose) { @@ -751,8 +752,8 @@ logger(void *arg) PRIntervalTime period; PRIntervalTime previousTime; PRIntervalTime latestTime; - PRUint32 previousOps; - PRUint32 ops; + PRInt32 previousOps; + PRInt32 ops; PRIntervalTime logPeriodTicks = PR_TicksPerSecond(); PRFloat64 secondsPerTick = 1.0 / (PRFloat64)logPeriodTicks; int iterations = 0; @@ -771,7 +772,7 @@ logger(void *arg) */ PR_Sleep(logPeriodTicks); secondsElapsed++; - totalPeriodBytes += PR_ATOMIC_SET(&loggerBytes, 0); + totalPeriodBytes += PR_ATOMIC_SET(&loggerBytes, 0); totalPeriodBytesTCP += PR_ATOMIC_SET(&loggerBytesTCP, 0); if (secondsElapsed != logPeriod) { continue; @@ -837,6 +838,8 @@ PRBool testbypass = PR_FALSE; PRBool enableSessionTickets = PR_FALSE; PRBool enableCompression = PR_FALSE; PRBool failedToNegotiateName = PR_FALSE; +PRBool enableExtendedMasterSecret = PR_FALSE; + static char *virtServerNameArray[MAX_VIRT_SERVER_NAME_ARRAY_INDEX]; static int virtServerNameIndex = 1; @@ -1942,6 +1945,13 @@ server_main( } } + if (enableExtendedMasterSecret) { + rv = SSL_OptionSet(model_sock, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE); + if (rv != SECSuccess) { + errExit("error enabling extended master secret "); + } + } + for (kea = kt_rsa; kea < kt_kea_size; kea++) { if (cert[kea] != NULL) { secStatus = SSL_ConfigSecureServer(model_sock, @@ -2218,7 +2228,7 @@ main(int argc, char **argv) ** numbers, then capital letters, then lower case, alphabetical. */ optstate = PL_CreateOptState(argc, argv, - "2:A:BC:DEH:L:M:NP:RS:T:U:V:W:Ya:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:xyz"); + "2:A:BC:DEGH:L:M:NP:RS:T:U:V:W:Ya:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:xyz"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { ++optionsFound; switch(optstate->option) { @@ -2234,6 +2244,8 @@ main(int argc, char **argv) case 'E': disableStepDown = PR_TRUE; break; case 'H': configureDHE = (PORT_Atoi(optstate->value) != 0); break; + case 'G': enableExtendedMasterSecret = PR_TRUE; break; + case 'I': /* reserved for OCSP multi-stapling */ break; case 'L': diff --git a/security/nss/cmd/signtool/certgen.c b/security/nss/cmd/signtool/certgen.c index 0f7c596d..5a645049 100644 --- a/security/nss/cmd/signtool/certgen.c +++ b/security/nss/cmd/signtool/certgen.c @@ -73,6 +73,9 @@ GenerateCert(char *nickname, int keysize, char *token) LL_L2UI(serial, PR_Now()); subject = GetSubjectFromUser(serial); + if (!subject) { + FatalError("Unable to get subject from user"); + } cert = GenerateSelfSignedObjectSigningCert(nickname, db, subject, serial, keysize, token); @@ -122,7 +125,9 @@ GetSubjectFromUser(unsigned long serial) #else PR_fprintf(PR_STDOUT, "certificate common name: "); #endif - fgets(buf, STDIN_BUF_SIZE, stdin); + if (!fgets(buf, STDIN_BUF_SIZE, stdin)) { + return NULL; + } cp = chop(buf); if (*cp == '\0') { sprintf(common_name_buf, "%s (%lu)", DEFAULT_COMMON_NAME, @@ -144,7 +149,9 @@ GetSubjectFromUser(unsigned long serial) #else PR_fprintf(PR_STDOUT, "organization: "); #endif - fgets(buf, STDIN_BUF_SIZE, stdin); + if (!fgets(buf, STDIN_BUF_SIZE, stdin)) { + return NULL; + } cp = chop(buf); if (*cp != '\0') { org = PORT_ZAlloc(strlen(cp) + 5); @@ -163,7 +170,9 @@ GetSubjectFromUser(unsigned long serial) #else PR_fprintf(PR_STDOUT, "organization unit: "); #endif - fgets(buf, STDIN_BUF_SIZE, stdin); + if (!fgets(buf, STDIN_BUF_SIZE, stdin)) { + return NULL; + } cp = chop(buf); if (*cp != '\0') { orgunit = PORT_ZAlloc(strlen(cp) + 6); @@ -181,7 +190,9 @@ GetSubjectFromUser(unsigned long serial) #else PR_fprintf(PR_STDOUT, "state or province: "); #endif - fgets(buf, STDIN_BUF_SIZE, stdin); + if (!fgets(buf, STDIN_BUF_SIZE, stdin)) { + return NULL; + } cp = chop(buf); if (*cp != '\0') { state = PORT_ZAlloc(strlen(cp) + 6); @@ -199,7 +210,9 @@ GetSubjectFromUser(unsigned long serial) #else PR_fprintf(PR_STDOUT, "country (must be exactly 2 characters): "); #endif - fgets(buf, STDIN_BUF_SIZE, stdin); + if (!fgets(buf, STDIN_BUF_SIZE, stdin)) { + return NULL; + } cp = chop(cp); if (strlen(cp) != 2) { *cp = '\0'; /* country code must be 2 chars */ @@ -220,7 +233,9 @@ GetSubjectFromUser(unsigned long serial) #else PR_fprintf(PR_STDOUT, "username: "); #endif - fgets(buf, STDIN_BUF_SIZE, stdin); + if (!fgets(buf, STDIN_BUF_SIZE, stdin)) { + return NULL; + } cp = chop(buf); if (*cp != '\0') { uid = PORT_ZAlloc(strlen(cp) + 7); @@ -238,7 +253,9 @@ GetSubjectFromUser(unsigned long serial) #else PR_fprintf(PR_STDOUT, "email address: "); #endif - fgets(buf, STDIN_BUF_SIZE, stdin); + if (!fgets(buf, STDIN_BUF_SIZE, stdin)) { + return NULL; + } cp = chop(buf); if (*cp != '\0') { email = PORT_ZAlloc(strlen(cp) + 5); diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c index ddfadafd..93a70222 100644 --- a/security/nss/cmd/tstclnt/tstclnt.c +++ b/security/nss/cmd/tstclnt/tstclnt.c @@ -129,10 +129,11 @@ void printSecurityInfo(PRFileDesc *fd) suite.macBits, suite.macAlgorithmName); FPRINTF(stderr, "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n" - " Compression: %s\n", + " Compression: %s, Extended Master Secret: %s\n", channel.authKeyBits, suite.authAlgorithmName, channel.keaKeyBits, suite.keaTypeName, - channel.compressionMethodName); + channel.compressionMethodName, + channel.extendedMasterSecretUsed ? "Yes": "No"); } } cert = SSL_RevealCert(fd); @@ -231,6 +232,7 @@ static void PrintParameterUsage(void) fprintf(stderr, "%-20s Enable compression.\n", "-z"); fprintf(stderr, "%-20s Enable false start.\n", "-g"); fprintf(stderr, "%-20s Enable the cert_status extension (OCSP stapling).\n", "-T"); + fprintf(stderr, "%-20s Enable the extended master secret extension (session hash).\n", "-G"); fprintf(stderr, "%-20s Require fresh revocation info from side channel.\n" "%-20s -F once means: require for server cert only\n" "%-20s -F twice means: require for intermediates, too\n" @@ -919,6 +921,7 @@ int main(int argc, char **argv) int enableFalseStart = 0; int enableCertStatus = 0; int forceFallbackSCSV = 0; + int enableExtendedMasterSecret = 0; PRSocketOptionData opt; PRNetAddr addr; PRPollDesc pollset[2]; @@ -967,7 +970,7 @@ int main(int argc, char **argv) SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions); optstate = PL_CreateOptState(argc, argv, - "46BCDFKM:OR:STV:W:Ya:bc:d:fgh:m:n:op:qr:st:uvw:xz"); + "46BCDFGKM:OR:STV:W:Ya:bc:d:fgh:m:n:op:qr:st:uvw:xz"); while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': @@ -989,6 +992,8 @@ int main(int argc, char **argv) serverCertAuth.testFreshStatusFromSideChannel = PR_TRUE; break; + case 'G': enableExtendedMasterSecret = PR_TRUE; break; + case 'I': /* reserved for OCSP multi-stapling */ break; case 'O': serverCertAuth.shouldPause = PR_FALSE; break; @@ -1386,6 +1391,15 @@ int main(int argc, char **argv) return 1; } + /* enable extended master secret mode */ + if (enableExtendedMasterSecret) { + rv = SSL_OptionSet(s, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE); + if (rv != SECSuccess) { + SECU_PrintError(progName, "error enabling extended master secret"); + return 1; + } + } + SSL_SetPKCS11PinArg(s, &pwdata); serverCertAuth.dbHandle = CERT_GetDefaultCertDB(); diff --git a/security/nss/coreconf/Darwin.mk b/security/nss/coreconf/Darwin.mk index 18a13481..786825c7 100644 --- a/security/nss/coreconf/Darwin.mk +++ b/security/nss/coreconf/Darwin.mk @@ -83,6 +83,26 @@ endif OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) -Wall -fno-common -pipe -DDARWIN -DHAVE_STRERROR -DHAVE_BSD_FLOCK $(DARWIN_SDK_CFLAGS) +ifeq (clang,$(shell $(CC) -? 2>&1 >/dev/null | sed -e 's/:.*//;1q')) +NSS_HAS_GCC48 = true +endif +ifndef NSS_HAS_GCC48 +NSS_HAS_GCC48 := $(shell \ + [ `$(CC) -dumpversion | cut -f 1 -d . -` -gt 4 -a \ + `$(CC) -dumpversion | cut -f 2 -d . -` -ge 8 -o \ + `$(CC) -dumpversion | cut -f 1 -d . -` -ge 5 ] && \ + echo true || echo false) +export NSS_HAS_GCC48 +endif +ifeq (true,$(NSS_HAS_GCC48)) +OS_CFLAGS += -Werror +else +# Old versions of gcc (< 4.8) don't support #pragma diagnostic in functions. +# Use this to disable use of that #pragma and the warnings it suppresses. +OS_CFLAGS += -DNSS_NO_GCC48 -Wno-unused-variable -Wno-strict-aliasing +$(warning Unable to find gcc >= 4.8 disabling -Werror) +endif + ifdef BUILD_OPT ifeq (11,$(ALLOW_OPT_CODE_SIZE)$(OPT_CODE_SIZE)) OPTIMIZER = -Oz diff --git a/security/nss/coreconf/Linux.mk b/security/nss/coreconf/Linux.mk index 414aef53..cbd5e05c 100644 --- a/security/nss/coreconf/Linux.mk +++ b/security/nss/coreconf/Linux.mk @@ -134,7 +134,7 @@ ifeq ($(USE_PTHREADS),1) OS_PTHREAD = -lpthread endif -OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) $(ARCHFLAG) -Wall -Werror -pipe -ffunction-sections -fdata-sections -DLINUX -Dlinux -DHAVE_STRERROR +OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) $(ARCHFLAG) -Wall -pipe -ffunction-sections -fdata-sections -DLINUX -Dlinux -DHAVE_STRERROR OS_LIBS = $(OS_PTHREAD) -ldl -lc ifeq ($(COMPILER_TAG),_clang) @@ -152,29 +152,21 @@ endif NSS_HAS_GCC48 = true endif -# Check for the existence of gcc 4.8 ifndef NSS_HAS_GCC48 -define GCC48_TEST = -int main() {\n -#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)\n - return 1;\n -#else\n - return 0;\n -#endif\n -}\n -endef -TEST_GCC48 := /tmp/test_gcc48_$(shell echo $$$$) -NSS_HAS_GCC48 := (,$(shell echo -e "$(GCC48_TEST)" > $(TEST_GCC48).c && \ - $(CC) -o $(TEST_GCC48) $(TEST_GCC48).c && \ - $(TEST_GCC48) && echo true || echo false; \ - rm -f $(TEST_GCC48) $(TEST_GCC48).c)) +NSS_HAS_GCC48 := $(shell \ + [ `$(CC) -dumpversion | cut -f 1 -d . -` -gt 4 -a \ + `$(CC) -dumpversion | cut -f 2 -d . -` -ge 8 -o \ + `$(CC) -dumpversion | cut -f 1 -d . -` -ge 5 ] && \ + echo true || echo false) export NSS_HAS_GCC48 endif - ifeq (true,$(NSS_HAS_GCC48)) +OS_CFLAGS += -Werror +else # Old versions of gcc (< 4.8) don't support #pragma diagnostic in functions. -# Here, we disable use of that #pragma and the warnings it suppresses. -OS_CFLAGS += -DNSS_NO_GCC48 -Wno-unused-variable +# Use this to disable use of that #pragma and the warnings it suppresses. +OS_CFLAGS += -DNSS_NO_GCC48 +$(warning Unable to find gcc >= 4.8 disabling -Werror) endif ifdef USE_PTHREADS diff --git a/security/nss/coreconf/rules.mk b/security/nss/coreconf/rules.mk index 0a891ebc..34b742a7 100644 --- a/security/nss/coreconf/rules.mk +++ b/security/nss/coreconf/rules.mk @@ -424,12 +424,12 @@ $(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.S $(OBJDIR)/$(PROG_PREFIX)%: %.cpp @$(MAKE_OBJDIR) ifdef USE_NT_C_SYNTAX - $(CCC) -Fo$@ -c $(CFLAGS) $(call core_abspath,$<) + $(CCC) -Fo$@ -c $(CFLAGS) $(CXXFLAGS) $(call core_abspath,$<) else ifdef NEED_ABSOLUTE_PATH - $(CCC) -o $@ -c $(CFLAGS) $(call core_abspath,$<) + $(CCC) -o $@ -c $(CFLAGS) $(CXXFLAGS) $(call core_abspath,$<) else - $(CCC) -o $@ -c $(CFLAGS) $< + $(CCC) -o $@ -c $(CFLAGS) $(CXXFLAGS) $< endif endif @@ -440,16 +440,16 @@ $(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.cc $(MAKE_OBJDIR) ifdef STRICT_CPLUSPLUS_SUFFIX echo "#line 1 \"$<\"" | cat - $< > $(OBJDIR)/t_$*.cc - $(CCC) -o $@ -c $(CFLAGS) $(OBJDIR)/t_$*.cc + $(CCC) -o $@ -c $(CFLAGS) $(CXXFLAGS) $(OBJDIR)/t_$*.cc rm -f $(OBJDIR)/t_$*.cc else ifdef USE_NT_C_SYNTAX - $(CCC) -Fo$@ -c $(CFLAGS) $(call core_abspath,$<) + $(CCC) -Fo$@ -c $(CFLAGS) $(CXXFLAGS) $(call core_abspath,$<) else ifdef NEED_ABSOLUTE_PATH - $(CCC) -o $@ -c $(CFLAGS) $(call core_abspath,$<) + $(CCC) -o $@ -c $(CFLAGS) $(CXXFLAGS) $(call core_abspath,$<) else - $(CCC) -o $@ -c $(CFLAGS) $< + $(CCC) -o $@ -c $(CFLAGS) $(CXXFLAGS) $< endif endif endif #STRICT_CPLUSPLUS_SUFFIX @@ -458,22 +458,22 @@ $(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.cpp @$(MAKE_OBJDIR) ifdef STRICT_CPLUSPLUS_SUFFIX echo "#line 1 \"$<\"" | cat - $< > $(OBJDIR)/t_$*.cc - $(CCC) -o $@ -c $(CFLAGS) $(OBJDIR)/t_$*.cc + $(CCC) -o $@ -c $(CFLAGS) $(CXXFLAGS) $(OBJDIR)/t_$*.cc rm -f $(OBJDIR)/t_$*.cc else ifdef USE_NT_C_SYNTAX - $(CCC) -Fo$@ -c $(CFLAGS) $(call core_abspath,$<) + $(CCC) -Fo$@ -c $(CFLAGS) $(CXXFLAGS) $(call core_abspath,$<) else ifdef NEED_ABSOLUTE_PATH - $(CCC) -o $@ -c $(CFLAGS) $(call core_abspath,$<) + $(CCC) -o $@ -c $(CFLAGS) $(CXXFLAGS) $(call core_abspath,$<) else - $(CCC) -o $@ -c $(CFLAGS) $< + $(CCC) -o $@ -c $(CFLAGS) $(CXXFLAGS) $< endif endif endif #STRICT_CPLUSPLUS_SUFFIX %.i: %.cpp - $(CCC) -C -E $(CFLAGS) $< > $@ + $(CCC) -C -E $(CFLAGS) $(CXXFLAGS) $< > $@ %.i: %.c ifeq (,$(filter-out WIN%,$(OS_TARGET))) diff --git a/security/nss/lib/dbm/src/h_page.c b/security/nss/lib/dbm/src/h_page.c index cc024947..669f3b32 100644 --- a/security/nss/lib/dbm/src/h_page.c +++ b/security/nss/lib/dbm/src/h_page.c @@ -158,10 +158,11 @@ long new_lseek(int fd, long offset, int origin) { char buffer[1024]; long len = seek_pos-end_pos; - memset(&buffer, 0, 1024); + memset(buffer, 0, 1024); while(len > 0) { - write(fd, (char*)&buffer, (size_t)(1024 > len ? len : 1024)); + if(write(fd, buffer, (size_t)(1024 > len ? len : 1024)) < 0) + return(-1); len -= 1024; } return(lseek(fd, seek_pos, SEEK_SET)); @@ -981,7 +982,7 @@ overflow_page(HTAB *hashp) if (offset > SPLITMASK) { if (++splitnum >= NCACHED) { #ifndef macintosh - (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + (void)fwrite(OVMSG, 1, sizeof(OVMSG) - 1, stderr); #endif return (0); } @@ -996,7 +997,7 @@ overflow_page(HTAB *hashp) free_page++; if (free_page >= NCACHED) { #ifndef macintosh - (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + (void)fwrite(OVMSG, 1, sizeof(OVMSG) - 1, stderr); #endif return (0); } @@ -1022,8 +1023,7 @@ overflow_page(HTAB *hashp) if (offset > SPLITMASK) { if (++splitnum >= NCACHED) { #ifndef macintosh - (void)write(STDERR_FILENO, OVMSG, - sizeof(OVMSG) - 1); + (void)fwrite(OVMSG, 1, sizeof(OVMSG) - 1, stderr); #endif return (0); } diff --git a/security/nss/lib/dbm/src/hash.c b/security/nss/lib/dbm/src/hash.c index 3f9a516e..b3a904a8 100644 --- a/security/nss/lib/dbm/src/hash.c +++ b/security/nss/lib/dbm/src/hash.c @@ -911,7 +911,7 @@ hash_seq( uint flag) { register uint32 bucket; - register BUFHEAD *bufp; + register BUFHEAD *bufp = NULL; HTAB *hashp; uint16 *bp, ndx; diff --git a/security/nss/lib/freebl/drbg.c b/security/nss/lib/freebl/drbg.c index e20db2e6..391d4560 100644 --- a/security/nss/lib/freebl/drbg.c +++ b/security/nss/lib/freebl/drbg.c @@ -24,7 +24,7 @@ * for SHA-1, SHA-224, and SHA-256 it's 440 bits. * for SHA-384 and SHA-512 it's 888 bits */ #define PRNG_SEEDLEN (440/PR_BITS_PER_BYTE) -static const PRInt64 PRNG_MAX_ADDITIONAL_BYTES = LL_INIT(0x1, 0x0); +#define PRNG_MAX_ADDITIONAL_BYTES PR_INT64(0x100000000) /* 2^35 bits or 2^32 bytes */ #define PRNG_MAX_REQUEST_SIZE 0x10000 /* 2^19 bits or 2^16 bytes */ #define PRNG_ADDITONAL_DATA_CACHE_SIZE (8*1024) /* must be less than diff --git a/security/nss/lib/freebl/ecl/ecp_192.c b/security/nss/lib/freebl/ecl/ecp_192.c index ef11cef9..0bfd95e1 100644 --- a/security/nss/lib/freebl/ecl/ecp_192.c +++ b/security/nss/lib/freebl/ecl/ecp_192.c @@ -120,8 +120,8 @@ ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth) if (((r2b == 0xffffffff) && (r2a == 0xffffffff) && (r1b == 0xffffffff) ) && ((r1a == 0xffffffff) || - (r1a == 0xfffffffe) && (r0a == 0xffffffff) && - (r0b == 0xffffffff)) ) { + ((r1a == 0xfffffffe) && (r0a == 0xffffffff) && + (r0b == 0xffffffff))) ) { /* do a quick subtract */ carry = 0; MP_ADD_CARRY(r0a, 1, r0a, carry); diff --git a/security/nss/lib/freebl/ecl/ecp_224.c b/security/nss/lib/freebl/ecl/ecp_224.c index 4faab215..142f255d 100644 --- a/security/nss/lib/freebl/ecl/ecp_224.c +++ b/security/nss/lib/freebl/ecl/ecp_224.c @@ -22,7 +22,7 @@ ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth) mp_digit carry; #ifdef ECL_THIRTY_TWO_BIT mp_digit a6a = 0, a6b = 0, - a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0; + a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3b = 0; mp_digit r0a, r0b, r1a, r1b, r2a, r2b, r3a; #else mp_digit a6 = 0, a5 = 0, a4 = 0, a3b = 0, a5a = 0; diff --git a/security/nss/lib/freebl/mpi/mpi.c b/security/nss/lib/freebl/mpi/mpi.c index 43ce83ae..84f9b97b 100644 --- a/security/nss/lib/freebl/mpi/mpi.c +++ b/security/nss/lib/freebl/mpi/mpi.c @@ -4190,6 +4190,7 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */ MP_SIGN(rem) = ZPOS; MP_SIGN(div) = ZPOS; + MP_SIGN(&part) = ZPOS; /* A working temporary for division */ MP_CHECKOK( mp_init_size(&t, MP_ALLOC(rem))); @@ -4197,8 +4198,6 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */ /* Normalize to optimize guessing */ MP_CHECKOK( s_mp_norm(rem, div, &d) ); - part = *rem; - /* Perform the division itself...woo! */ MP_USED(quot) = MP_ALLOC(quot); @@ -4207,11 +4206,15 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */ while (MP_USED(rem) > MP_USED(div) || s_mp_cmp(rem, div) >= 0) { int i; int unusedRem; + int partExtended = 0; /* set to true if we need to extend part */ unusedRem = MP_USED(rem) - MP_USED(div); MP_DIGITS(&part) = MP_DIGITS(rem) + unusedRem; MP_ALLOC(&part) = MP_ALLOC(rem) - unusedRem; MP_USED(&part) = MP_USED(div); + + /* We have now truncated the part of the remainder to the same length as + * the divisor. If part is smaller than div, extend part by one digit. */ if (s_mp_cmp(&part, div) < 0) { -- unusedRem; #if MP_ARGCHK == 2 @@ -4220,26 +4223,34 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */ -- MP_DIGITS(&part); ++ MP_USED(&part); ++ MP_ALLOC(&part); + partExtended = 1; } /* Compute a guess for the next quotient digit */ q_msd = MP_DIGIT(&part, MP_USED(&part) - 1); div_msd = MP_DIGIT(div, MP_USED(div) - 1); - if (q_msd >= div_msd) { + if (!partExtended) { + /* In this case, q_msd /= div_msd is always 1. First, since div_msd is + * normalized to have the high bit set, 2*div_msd > MP_DIGIT_MAX. Since + * we didn't extend part, q_msd >= div_msd. Therefore we know that + * div_msd <= q_msd <= MP_DIGIT_MAX < 2*div_msd. Dividing by div_msd we + * get 1 <= q_msd/div_msd < 2. So q_msd /= div_msd must be 1. */ q_msd = 1; - } else if (MP_USED(&part) > 1) { + } else { #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD) q_msd = (q_msd << MP_DIGIT_BIT) | MP_DIGIT(&part, MP_USED(&part) - 2); q_msd /= div_msd; if (q_msd == RADIX) --q_msd; #else - mp_digit r; - MP_CHECKOK( s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2), - div_msd, &q_msd, &r) ); + if (q_msd == div_msd) { + q_msd = MP_DIGIT_MAX; + } else { + mp_digit r; + MP_CHECKOK( s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2), + div_msd, &q_msd, &r) ); + } #endif - } else { - q_msd = 0; } #if MP_ARGCHK == 2 assert(q_msd > 0); /* This case should never occur any more. */ diff --git a/security/nss/lib/freebl/pqg.c b/security/nss/lib/freebl/pqg.c index f7971557..fd1351ed 100644 --- a/security/nss/lib/freebl/pqg.c +++ b/security/nss/lib/freebl/pqg.c @@ -1143,7 +1143,7 @@ makeGfromIndex(HASH_HashType hashtype, unsigned int len; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; - const SECHashObject *hashobj; + const SECHashObject *hashobj = NULL; void *hashcx = NULL; MP_DIGITS(&e) = 0; diff --git a/security/nss/lib/freebl/sha512.c b/security/nss/lib/freebl/sha512.c index 0e6baa87..3298e39f 100644 --- a/security/nss/lib/freebl/sha512.c +++ b/security/nss/lib/freebl/sha512.c @@ -67,11 +67,11 @@ static const PRUint32 H256[8] = { 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; +#if defined(IS_LITTLE_ENDIAN) #if (_MSC_VER >= 1300) #include #pragma intrinsic(_byteswap_ulong) #define SHA_HTONL(x) _byteswap_ulong(x) -#define BYTESWAP4(x) x = SHA_HTONL(x) #elif defined(_MSC_VER) && defined(NSS_X86_OR_X64) #ifndef FORCEINLINE #if (_MSC_VER >= 1200) @@ -92,7 +92,6 @@ swap4b(PRUint32 dwd) } #define SHA_HTONL(x) swap4b(x) -#define BYTESWAP4(x) x = SHA_HTONL(x) #elif defined(__GNUC__) && defined(NSS_X86_OR_X64) static __inline__ PRUint32 swap4b(PRUint32 value) @@ -101,7 +100,6 @@ static __inline__ PRUint32 swap4b(PRUint32 value) return (value); } #define SHA_HTONL(x) swap4b(x) -#define BYTESWAP4(x) x = SHA_HTONL(x) #elif defined(__GNUC__) && (defined(__thumb2__) || \ (!defined(__thumb__) && \ @@ -121,14 +119,14 @@ static __inline__ PRUint32 swap4b(PRUint32 value) return ret; } #define SHA_HTONL(x) swap4b(x) -#define BYTESWAP4(x) x = SHA_HTONL(x) #else #define SWAP4MASK 0x00FF00FF #define SHA_HTONL(x) (t1 = (x), t1 = (t1 << 16) | (t1 >> 16), \ ((t1 & SWAP4MASK) << 8) | ((t1 >> 8) & SWAP4MASK)) -#define BYTESWAP4(x) x = SHA_HTONL(x) #endif +#define BYTESWAP4(x) x = SHA_HTONL(x) +#endif /* defined(IS_LITTLE_ENDIAN) */ #if defined(_MSC_VER) #pragma intrinsic (_lrotr, _lrotl) @@ -665,6 +663,7 @@ void SHA224_Clone(SHA224Context *dest, SHA224Context *src) #define ULLC(hi,lo) 0x ## hi ## lo ## ULL #endif +#if defined(IS_LITTLE_ENDIAN) #if defined(_MSC_VER) #pragma intrinsic(_byteswap_uint64) #define SHA_HTONLL(x) _byteswap_uint64(x) @@ -686,19 +685,20 @@ static __inline__ PRUint64 swap8b(PRUint64 value) (t1 >> 32) | (t1 << 32)) #endif #define BYTESWAP8(x) x = SHA_HTONLL(x) +#endif /* defined(IS_LITTLE_ENDIAN) */ #else /* no long long */ #if defined(IS_LITTLE_ENDIAN) #define ULLC(hi,lo) { 0x ## lo ## U, 0x ## hi ## U } -#else -#define ULLC(hi,lo) { 0x ## hi ## U, 0x ## lo ## U } -#endif - #define SHA_HTONLL(x) ( BYTESWAP4(x.lo), BYTESWAP4(x.hi), \ x.hi ^= x.lo ^= x.hi ^= x.lo, x) #define BYTESWAP8(x) do { PRUint32 tmp; BYTESWAP4(x.lo); BYTESWAP4(x.hi); \ tmp = x.lo; x.lo = x.hi; x.hi = tmp; } while (0) +#else +#define ULLC(hi,lo) { 0x ## hi ## U, 0x ## lo ## U } +#endif + #endif /* SHA-384 and SHA-512 constants, K512. */ diff --git a/security/nss/lib/jar/jarfile.c b/security/nss/lib/jar/jarfile.c index 3346dbec..96da4d79 100644 --- a/security/nss/lib/jar/jarfile.c +++ b/security/nss/lib/jar/jarfile.c @@ -76,7 +76,7 @@ dostime(char *time, const char *s); #ifdef NSS_X86_OR_X64 /* The following macros throw up warnings. */ -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(NSS_NO_GCC48) #pragma GCC diagnostic ignored "-Wstrict-aliasing" #endif #define x86ShortToUint32(ii) ((const PRUint32)*((const PRUint16 *)(ii))) diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c index a191ad65..3dc06be9 100644 --- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c @@ -359,7 +359,7 @@ pkix_pl_LdapDefaultClient_VerifyBindResponse( "pkix_pl_LdapDefaultClient_VerifyBindResponse"); PKIX_NULLCHECK_TWO(client, client->rcvBuf); - decode.data = (void *)(client->rcvBuf); + decode.data = (unsigned char *)(client->rcvBuf); decode.len = bufLen; PKIX_CHECK(pkix_pl_LdapDefaultClient_DecodeBindResponse diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c index 9d37f58f..cd2543f3 100644 --- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c @@ -730,7 +730,7 @@ pkix_pl_LdapResponse_GetResultCode( resultMsg = &response->decoded.protocolOp.op.searchResponseResultMsg; - *pResultCode = *(char *)(resultMsg->resultCode.data); + *pResultCode = *(resultMsg->resultCode.data); cleanup: diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c index 9a33fd5e..7dafa0b2 100644 --- a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c @@ -600,7 +600,7 @@ PKIX_PL_Object_Alloc( object = NULL; /* Atomically increment object counter */ - PR_ATOMIC_INCREMENT(&ctEntry->objCounter); + PR_ATOMIC_INCREMENT((PRInt32*)&ctEntry->objCounter); cleanup: @@ -897,7 +897,7 @@ PKIX_PL_Object_DecRef( } /* Atomically decrement object counter */ - PR_ATOMIC_DECREMENT(&ctEntry->objCounter); + PR_ATOMIC_DECREMENT((PRInt32*)&ctEntry->objCounter); /* pkix_pl_Object_Destroy assumes the lock is held */ /* It will call unlock and destroy the object */ diff --git a/security/nss/lib/pk11wrap/pk11mech.c b/security/nss/lib/pk11wrap/pk11mech.c index d8b82277..f70c3094 100644 --- a/security/nss/lib/pk11wrap/pk11mech.c +++ b/security/nss/lib/pk11wrap/pk11mech.c @@ -380,6 +380,8 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type,unsigned long len) case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: case CKM_TLS_KEY_AND_MAC_DERIVE: case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: + case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE: + case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA224_HMAC: @@ -575,6 +577,8 @@ PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size) case CKM_TLS_MASTER_KEY_DERIVE: case CKM_TLS_KEY_AND_MAC_DERIVE: case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: + case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE: + case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: return CKM_SSL3_PRE_MASTER_KEY_GEN; case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: diff --git a/security/nss/lib/pk11wrap/pk11merge.c b/security/nss/lib/pk11wrap/pk11merge.c index 187e2e1f..8fadc7ca 100644 --- a/security/nss/lib/pk11wrap/pk11merge.c +++ b/security/nss/lib/pk11wrap/pk11merge.c @@ -1261,7 +1261,8 @@ pk11_mergeByObjectIDs(PK11SlotInfo *targetSlot, PK11SlotInfo *sourceSlot, PK11MergeLog *log, void *targetPwArg, void *sourcePwArg) { SECStatus rv = SECSuccess; - int error, i; + int error = SEC_ERROR_LIBRARY_FAILURE; + int i; for (i=0; i < count; i++) { /* try to update the entire database. On failure, keep going, @@ -1325,7 +1326,8 @@ PK11_MergeTokens(PK11SlotInfo *targetSlot, PK11SlotInfo *sourceSlot, PK11MergeLog *log, void *targetPwArg, void *sourcePwArg) { SECStatus rv = SECSuccess, lrv = SECSuccess; - int error, count = 0; + int error = SEC_ERROR_LIBRARY_FAILURE; + int count = 0; CK_ATTRIBUTE search[2]; CK_OBJECT_HANDLE *objectIDs = NULL; CK_BBOOL ck_true = CK_TRUE; diff --git a/security/nss/lib/pk11wrap/pk11obj.c b/security/nss/lib/pk11wrap/pk11obj.c index e09d2276..848b45a0 100644 --- a/security/nss/lib/pk11wrap/pk11obj.c +++ b/security/nss/lib/pk11wrap/pk11obj.c @@ -1577,7 +1577,7 @@ PK11_WriteRawAttribute(PK11ObjectType objType, void *objSpec, CK_ATTRIBUTE_TYPE attrType, SECItem *item) { PK11SlotInfo *slot = NULL; - CK_OBJECT_HANDLE handle; + CK_OBJECT_HANDLE handle = 0; CK_ATTRIBUTE setTemplate; CK_RV crv; CK_SESSION_HANDLE rwsession; @@ -1630,7 +1630,7 @@ PK11_ReadRawAttribute(PK11ObjectType objType, void *objSpec, CK_ATTRIBUTE_TYPE attrType, SECItem *item) { PK11SlotInfo *slot = NULL; - CK_OBJECT_HANDLE handle; + CK_OBJECT_HANDLE handle = 0; switch (objType) { case PK11_TypeGeneric: diff --git a/security/nss/lib/pk11wrap/pk11pk12.c b/security/nss/lib/pk11wrap/pk11pk12.c index 2152a41e..e5a0a21c 100644 --- a/security/nss/lib/pk11wrap/pk11pk12.c +++ b/security/nss/lib/pk11wrap/pk11pk12.c @@ -234,13 +234,17 @@ PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI, rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate, derPKI); if( rv != SECSuccess ) { - goto finish; + /* If SEC_ASN1DecodeItem fails, we cannot assume anything about the + * validity of the data in pki. The best we can do is free the arena + * and return. + */ + PORT_FreeArena(temparena, PR_TRUE); + return rv; } rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname, publicValue, isPerm, isPrivate, keyUsage, privk, wincx); -finish: /* this zeroes the key and frees the arena */ SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/); return rv; diff --git a/security/nss/lib/softoken/legacydb/keydb.c b/security/nss/lib/softoken/legacydb/keydb.c index c3dd887b..d54f10c0 100644 --- a/security/nss/lib/softoken/legacydb/keydb.c +++ b/security/nss/lib/softoken/legacydb/keydb.c @@ -1378,7 +1378,7 @@ nsslowkey_PutPWCheckEntry(NSSLOWKEYDBHandle *handle,NSSLOWKEYPasswordEntry *entr NSSLOWKEYDBKey *dbkey = NULL; SECItem *item = NULL; SECItem salt; - SECOidTag algid; + SECOidTag algid = SEC_OID_UNKNOWN; SECStatus rv = SECFailure; PLArenaPool *arena; int ret; diff --git a/security/nss/lib/softoken/legacydb/lginit.c b/security/nss/lib/softoken/legacydb/lginit.c index 47da8f04..b2ff521a 100644 --- a/security/nss/lib/softoken/legacydb/lginit.c +++ b/security/nss/lib/softoken/legacydb/lginit.c @@ -601,7 +601,7 @@ legacy_Open(const char *configdir, const char *certPrefix, if (certDB) *certDB = NULL; if (certDB) { - NSSLOWCERTCertDBHandle *certdbPtr; + NSSLOWCERTCertDBHandle *certdbPtr = NULL; crv = lg_OpenCertDB(configdir, certPrefix, readOnly, &certdbPtr); if (crv != CKR_OK) { diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 1a835238..adf98115 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -475,6 +475,10 @@ static const struct mechanismList mechanisms[] = { {CKM_TLS12_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, {CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256, {48, 48, CKF_DERIVE}, PR_FALSE}, + {CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE, + {48,128, CKF_DERIVE}, PR_FALSE}, + {CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH, + {48,128, CKF_DERIVE}, PR_FALSE}, /* ---------------------- PBE Key Derivations ------------------------ */ {CKM_PBE_MD2_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, {CKM_PBE_MD5_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, @@ -2603,7 +2607,7 @@ CK_RV sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout) --slot->sessionCount; SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); if (session->info.flags & CKF_RW_SESSION) { - PR_ATOMIC_DECREMENT(&slot->rwSessionCount); + (void)PR_ATOMIC_DECREMENT(&slot->rwSessionCount); } } else { SKIP_AFTER_FORK(PZ_Unlock(lock)); @@ -3720,7 +3724,7 @@ CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, ++slot->sessionCount; PZ_Unlock(slot->slotLock); if (session->info.flags & CKF_RW_SESSION) { - PR_ATOMIC_INCREMENT(&slot->rwSessionCount); + (void)PR_ATOMIC_INCREMENT(&slot->rwSessionCount); } do { @@ -3788,7 +3792,7 @@ CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession) sftk_freeDB(handle); } if (session->info.flags & CKF_RW_SESSION) { - PR_ATOMIC_DECREMENT(&slot->rwSessionCount); + (void)PR_ATOMIC_DECREMENT(&slot->rwSessionCount); } } diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index 0a2c5dc8..a1aec599 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -3840,7 +3840,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, * produce them any more. The affected algorithm was 3DES. */ PRBool faultyPBE3DES = PR_FALSE; - HASH_HashType hashType; + HASH_HashType hashType = HASH_AlgNULL; CHECK_FORK(); @@ -4081,7 +4081,7 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, */ CK_MECHANISM mech = {0, NULL, 0}; - CK_ULONG modulusLen; + CK_ULONG modulusLen = 0; CK_ULONG subPrimeLen = 0; PRBool isEncryptable = PR_FALSE; PRBool canSignVerify = PR_FALSE; @@ -6007,7 +6007,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, isDH = PR_TRUE; } - /* first do the consistancy checks */ + /* first do the consistency checks */ if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { crv = CKR_KEY_TYPE_INCONSISTENT; break; @@ -6136,6 +6136,101 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, break; } + /* Extended master key derivation [draft-ietf-tls-session-hash] */ + case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE: + case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: + { + CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params; + SSL3RSAPreMasterSecret *rsa_pms; + SECStatus status; + SECItem pms = { siBuffer, NULL, 0 }; + SECItem seed = { siBuffer, NULL, 0 }; + SECItem master = { siBuffer, NULL, 0 }; + + ems_params = (CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS*) + pMechanism->pParameter; + + /* First do the consistency checks */ + if ((mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE) && + (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); + if ((att2 == NULL) || + (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) { + if (att2) sftk_FreeAttribute(att2); + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + sftk_FreeAttribute(att2); + if (keyType != CKK_GENERIC_SECRET) { + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + + /* Do the key derivation */ + pms.data = (unsigned char*) att->attrib.pValue; + pms.len = att->attrib.ulValueLen; + seed.data = ems_params->pSessionHash; + seed.len = ems_params->ulSessionHashLen; + master.data = key_block; + master.len = SSL3_MASTER_SECRET_LENGTH; + if (ems_params-> prfHashMechanism == CKM_TLS_PRF) { + /* + * In this case, the session hash is the concatenation of SHA-1 + * and MD5, so it should be 36 bytes long. + */ + if (seed.len != MD5_LENGTH + SHA1_LENGTH) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + + status = TLS_PRF(&pms, "extended master secret", + &seed, &master, isFIPS); + } else { + const SECHashObject *hashObj; + + tlsPrfHash = GetHashTypeFromMechanism(ems_params->prfHashMechanism); + if (tlsPrfHash == HASH_AlgNULL) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + + hashObj = HASH_GetRawHashObject(tlsPrfHash); + if (seed.len != hashObj->length) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + + status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret", + &seed, &master, isFIPS); + } + + /* Reflect the version if required */ + if (ems_params->pVersion) { + SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); + rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue; + /* don't leak more key material than necessary for SSL to work */ + if ((sessKey == NULL) || sessKey->wasDerived) { + ems_params->pVersion->major = 0xff; + ems_params->pVersion->minor = 0xff; + } else { + ems_params->pVersion->major = rsa_pms->client_version[0]; + ems_params->pVersion->minor = rsa_pms->client_version[1]; + } + } + + /* Store the results */ + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, + SSL3_MASTER_SECRET_LENGTH); + break; + } + case CKM_TLS12_KEY_AND_MAC_DERIVE: case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: case CKM_TLS_KEY_AND_MAC_DERIVE: diff --git a/security/nss/lib/softoken/sftkdb.c b/security/nss/lib/softoken/sftkdb.c index b686e8e1..61f1e9e4 100644 --- a/security/nss/lib/softoken/sftkdb.c +++ b/security/nss/lib/softoken/sftkdb.c @@ -2408,7 +2408,7 @@ sftk_getCertDB(SFTKSlot *slot) PZ_Lock(slot->slotLock); dbHandle = slot->certDB; if (dbHandle) { - PR_ATOMIC_INCREMENT(&dbHandle->ref); + (void)PR_ATOMIC_INCREMENT(&dbHandle->ref); } PZ_Unlock(slot->slotLock); return dbHandle; @@ -2426,7 +2426,7 @@ sftk_getKeyDB(SFTKSlot *slot) SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); dbHandle = slot->keyDB; if (dbHandle) { - PR_ATOMIC_INCREMENT(&dbHandle->ref); + (void)PR_ATOMIC_INCREMENT(&dbHandle->ref); } SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); return dbHandle; @@ -2444,7 +2444,7 @@ sftk_getDBForTokenObject(SFTKSlot *slot, CK_OBJECT_HANDLE objectID) PZ_Lock(slot->slotLock); dbHandle = objectID & SFTK_KEYDB_TYPE ? slot->keyDB : slot->certDB; if (dbHandle) { - PR_ATOMIC_INCREMENT(&dbHandle->ref); + (void)PR_ATOMIC_INCREMENT(&dbHandle->ref); } PZ_Unlock(slot->slotLock); return dbHandle; diff --git a/security/nss/lib/ssl/SSLerrs.h b/security/nss/lib/ssl/SSLerrs.h index da561644..60283968 100644 --- a/security/nss/lib/ssl/SSLerrs.h +++ b/security/nss/lib/ssl/SSLerrs.h @@ -434,3 +434,9 @@ ER3(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 134), ER3(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 135), "The peer used an unsupported combination of signature and hash algorithm.") + +ER3(SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 136), +"The peer tried to resume without a correct extended_master_secret extension") + +ER3(SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 137), +"The peer tried to resume with an unexpected extended_master_secret extension") diff --git a/security/nss/lib/ssl/derive.c b/security/nss/lib/ssl/derive.c index b7c38c30..8b58b800 100644 --- a/security/nss/lib/ssl/derive.c +++ b/security/nss/lib/ssl/derive.c @@ -431,7 +431,7 @@ key_and_mac_derive_fail: * so isRSA is always true. */ SECStatus -ssl3_MasterKeyDeriveBypass( +ssl3_MasterSecretDeriveBypass( ssl3CipherSpec * pwSpec, const unsigned char * cr, const unsigned char * sr, diff --git a/security/nss/lib/ssl/ssl.h b/security/nss/lib/ssl/ssl.h index 40f8476d..2a527693 100644 --- a/security/nss/lib/ssl/ssl.h +++ b/security/nss/lib/ssl/ssl.h @@ -196,6 +196,14 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd); */ #define SSL_ENABLE_SERVER_DHE 29 +/* Use draft-ietf-tls-session-hash. Controls whether we offer the + * extended_master_secret extension which, when accepted, hashes + * the handshake transcript into the master secret. This option is + * disabled by default. + */ +#define SSL_ENABLE_EXTENDED_MASTER_SECRET 30 + + #ifdef SSL_DEPRECATED_FUNCTION /* Old deprecated function names */ SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRBool on); diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index b22bc004..5d7734f8 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -62,6 +62,10 @@ static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, const unsigned char *b, unsigned int l); static SECOidTag ssl3_TLSHashAlgorithmToOID(SSLHashType hashFunc); +static SECStatus ssl3_ComputeHandshakeHashes(sslSocket *ss, + ssl3CipherSpec *spec, + SSL3Hashes *hashes, + PRUint32 sender); static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags); static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, @@ -2221,7 +2225,11 @@ fail: * Sets error code, but caller probably should override to disambiguate. * NULL pms means re-use old master_secret. * - * This code is common to the bypass and PKCS11 execution paths. + * This code is common to the bypass and PKCS11 execution paths. For + * the bypass case, pms is NULL. If the old master secret is reused, + * pms is NULL and the master secret is already in either + * pwSpec->msItem.len (the bypass case) or pwSpec->master_secret. + * * For the bypass case, pms is NULL. */ SECStatus @@ -3627,13 +3635,70 @@ ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf) return SECSuccess; } -/* This method uses PKCS11 to derive the MS from the PMS, where PMS -** is a PKCS11 symkey. This is used in all cases except the -** "triple bypass" with RSA key exchange. -** Called from ssl3_InitPendingCipherSpec. prSpec is pwSpec. +/* This method completes the derivation of the MS from the PMS. +** +** 1. Derive the MS, if possible, else return an error. +** +** 2. Check the version if |pms_version| is non-zero and if wrong, +** return an error. +** +** 3. If |msp| is nonzero, return MS in |*msp|. + +** Called from: +** ssl3_ComputeMasterSecretInt +** tls_ComputeExtendedMasterSecretInt */ static SECStatus -ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) +ssl3_ComputeMasterSecretFinish(sslSocket *ss, + CK_MECHANISM_TYPE master_derive, + CK_MECHANISM_TYPE key_derive, + CK_VERSION *pms_version, + SECItem *params, CK_FLAGS keyFlags, + PK11SymKey *pms, PK11SymKey **msp) +{ + PK11SymKey *ms = NULL; + + ms = PK11_DeriveWithFlags(pms, master_derive, + params, key_derive, + CKA_DERIVE, 0, keyFlags); + if (!ms) { + ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); + return SECFailure; + } + + if (pms_version && ss->opt.detectRollBack) { + SSL3ProtocolVersion client_version; + client_version = pms_version->major << 8 | pms_version->minor; + + if (IS_DTLS(ss)) { + client_version = dtls_DTLSVersionToTLSVersion(client_version); + } + + if (client_version != ss->clientHelloVersion) { + /* Destroy MS. Version roll-back detected. */ + PK11_FreeSymKey(ms); + ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); + return SECFailure; + } + } + + if (msp) { + *msp = ms; + } else { + PK11_FreeSymKey(ms); + } + + return SECSuccess; +} + +/* Compute the ordinary (pre draft-ietf-tls-session-hash) master + ** secret and return it in |*msp|. + ** + ** Called from: ssl3_ComputeMasterSecret + */ +static SECStatus +ssl3_ComputeMasterSecretInt(sslSocket *ss, PK11SymKey *pms, + PK11SymKey **msp) { ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec; const ssl3KEADef *kea_def= ss->ssl3.hs.kea_def; @@ -3643,26 +3708,23 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) (pwSpec->version > SSL_LIBRARY_VERSION_3_0)); PRBool isTLS12= (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); - /* + /* * Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH * which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size - * data into a 48-byte value. + * data into a 48-byte value, and does not expect to return the version. */ PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) || (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh)); - SECStatus rv = SECFailure; CK_MECHANISM_TYPE master_derive; CK_MECHANISM_TYPE key_derive; SECItem params; CK_FLAGS keyFlags; CK_VERSION pms_version; + CK_VERSION *pms_version_ptr = NULL; /* master_params may be used as a CK_SSL3_MASTER_KEY_DERIVE_PARAMS */ CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params; unsigned int master_params_len; - PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); - PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); if (isTLS12) { if(isDH) master_derive = CKM_TLS12_MASTER_KEY_DERIVE_DH; else master_derive = CKM_TLS12_MASTER_KEY_DERIVE; @@ -3680,93 +3742,142 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) keyFlags = 0; } - if (pms || !pwSpec->master_secret) { - if (isDH) { - master_params.pVersion = NULL; - } else { - master_params.pVersion = &pms_version; - } - master_params.RandomInfo.pClientRandom = cr; - master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH; - master_params.RandomInfo.pServerRandom = sr; - master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH; - if (isTLS12) { - master_params.prfHashMechanism = CKM_SHA256; - master_params_len = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS); - } else { - master_params_len = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS); - } - - params.data = (unsigned char *) &master_params; - params.len = master_params_len; + if (!isDH) { + pms_version_ptr = &pms_version; } - if (pms != NULL) { -#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 - pwSpec->master_secret = PK11_DeriveWithFlags(pms, master_derive, - ¶ms, key_derive, CKA_DERIVE, 0, keyFlags); - if (!isDH && pwSpec->master_secret && ss->opt.detectRollBack) { - SSL3ProtocolVersion client_version; - client_version = pms_version.major << 8 | pms_version.minor; - - if (IS_DTLS(ss)) { - client_version = dtls_DTLSVersionToTLSVersion(client_version); - } - - if (client_version != ss->clientHelloVersion) { - /* Destroy it. Version roll-back detected. */ - PK11_FreeSymKey(pwSpec->master_secret); - pwSpec->master_secret = NULL; - } - } - if (pwSpec->master_secret == NULL) { - /* Generate a faux master secret in the same slot as the old one. */ - PK11SlotInfo * slot = PK11_GetSlotFromKey((PK11SymKey *)pms); - PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot); - - PK11_FreeSlot(slot); - if (fpms != NULL) { - pwSpec->master_secret = PK11_DeriveWithFlags(fpms, - master_derive, ¶ms, key_derive, - CKA_DERIVE, 0, keyFlags); - PK11_FreeSymKey(fpms); - } - } + master_params.pVersion = pms_version_ptr; + master_params.RandomInfo.pClientRandom = cr; + master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH; + master_params.RandomInfo.pServerRandom = sr; + master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH; + if (isTLS12) { + master_params.prfHashMechanism = CKM_SHA256; + master_params_len = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS); + } else { + /* prfHashMechanism is not relevant with this PRF */ + master_params_len = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS); } - if (pwSpec->master_secret == NULL) { - /* Generate a faux master secret from the internal slot. */ - PK11SlotInfo * slot = PK11_GetInternalSlot(); - PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot); - PK11_FreeSlot(slot); - if (fpms != NULL) { - pwSpec->master_secret = PK11_DeriveWithFlags(fpms, - master_derive, ¶ms, key_derive, - CKA_DERIVE, 0, keyFlags); - if (pwSpec->master_secret == NULL) { - pwSpec->master_secret = fpms; /* use the fpms as the master. */ - fpms = NULL; - } - } - if (fpms) { - PK11_FreeSymKey(fpms); - } + params.data = (unsigned char *) &master_params; + params.len = master_params_len; + + return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive, + pms_version_ptr, ¶ms, + keyFlags, pms, msp); +} + +/* Compute the draft-ietf-tls-session-hash master +** secret and return it in |*msp|. +** +** Called from: ssl3_ComputeMasterSecret +*/ +static SECStatus +tls_ComputeExtendedMasterSecretInt(sslSocket *ss, PK11SymKey *pms, + PK11SymKey **msp) +{ + ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; + CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS extended_master_params; + SSL3Hashes hashes; + /* + * Determine whether to use the DH/ECDH or RSA derivation modes. + */ + /* + * TODO(ekr@rtfm.com): Verify that the slot can handle this key expansion + * mode. Bug 1198298 */ + PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) || + (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh)); + CK_MECHANISM_TYPE master_derive; + CK_MECHANISM_TYPE key_derive; + SECItem params; + const CK_FLAGS keyFlags = CKF_SIGN | CKF_VERIFY; + CK_VERSION pms_version; + CK_VERSION *pms_version_ptr = NULL; + SECStatus rv; + + rv = ssl3_ComputeHandshakeHashes(ss, pwSpec, &hashes, 0); + if (rv != SECSuccess) { + PORT_Assert(0); /* Should never fail */ + ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); + return SECFailure; } - if (pwSpec->master_secret == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); - return rv; + + if (isDH) { + master_derive = CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH; + } else { + master_derive = CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE; + pms_version_ptr = &pms_version; } + + if (pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) { + /* TLS 1.2 */ + extended_master_params.prfHashMechanism = CKM_SHA256; + key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE; + } else { + /* TLS < 1.2 */ + extended_master_params.prfHashMechanism = CKM_TLS_PRF; + key_derive = CKM_TLS_KEY_AND_MAC_DERIVE; + } + + extended_master_params.pVersion = pms_version_ptr; + extended_master_params.pSessionHash = hashes.u.raw; + extended_master_params.ulSessionHashLen = hashes.len; + + params.data = (unsigned char *) &extended_master_params; + params.len = sizeof extended_master_params; + + return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive, + pms_version_ptr, ¶ms, + keyFlags, pms, msp); +} + + +/* Wrapper method to compute the master secret and return it in |*msp|. +** +** Called from ssl3_ComputeMasterSecret +*/ +static SECStatus +ssl3_ComputeMasterSecret(sslSocket *ss, PK11SymKey *pms, + PK11SymKey **msp) +{ + PORT_Assert(pms != NULL); + PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); + + if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) { + return tls_ComputeExtendedMasterSecretInt(ss, pms, msp); + } else { + return ssl3_ComputeMasterSecretInt(ss, pms, msp); + } +} + +/* This method uses PKCS11 to derive the MS from the PMS, where PMS +** is a PKCS11 symkey. We call ssl3_ComputeMasterSecret to do the +** computations and then modify the pwSpec->state as a side effect. +** +** This is used in all cases except the "triple bypass" with RSA key +** exchange. +** +** Called from ssl3_InitPendingCipherSpec. prSpec is pwSpec. +*/ +static SECStatus +ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) +{ + SECStatus rv; + PK11SymKey* ms = NULL; + ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; + + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); + PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); + + if (pms) { + rv = ssl3_ComputeMasterSecret(ss, pms, &ms); + pwSpec->master_secret = ms; + if (rv != SECSuccess) + return rv; + } + #ifndef NO_PKCS11_BYPASS if (ss->opt.bypassPKCS11) { SECItem * keydata; @@ -3777,7 +3888,7 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) rv = PK11_ExtractKeyValue(pwSpec->master_secret); if (rv != SECSuccess) { return rv; - } + } /* This returns the address of the secItem inside the key struct, * not a copy or a reference. So, there's no need to free it. */ @@ -3792,10 +3903,10 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) } } #endif + return SECSuccess; } - /* * Derive encryption and MAC Keys (and IVs) from master secret * Sets a useful error code when returning SECFailure. @@ -4628,11 +4739,6 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, /* compute them without PKCS11 */ PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; - if (!spec->msItem.data) { - PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); - return SECFailure; - } - ss->ssl3.hs.sha_clone(sha_cx, ss->ssl3.hs.sha_cx); ss->ssl3.hs.sha_obj->end(sha_cx, hashes->u.raw, &hashes->len, sizeof(hashes->u.raw)); @@ -4651,11 +4757,6 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, #define md5cx ((MD5Context *)md5_cx) #define shacx ((SHA1Context *)sha_cx) - if (!spec->msItem.data) { - PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); - return SECFailure; - } - MD5_Clone (md5cx, (MD5Context *)ss->ssl3.hs.md5_cx); SHA1_Clone(shacx, (SHA1Context *)ss->ssl3.hs.sha_cx); @@ -4663,6 +4764,12 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, /* compute hashes for SSL3. */ unsigned char s[4]; + if (!spec->msItem.data) { + PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); + return SECFailure; + } + + s[0] = (unsigned char)(sender >> 24); s[1] = (unsigned char)(sender >> 16); s[2] = (unsigned char)(sender >> 8); @@ -4735,11 +4842,6 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, unsigned char stackBuf[1024]; unsigned char *stateBuf = NULL; - if (!spec->master_secret) { - PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); - return SECFailure; - } - h = ss->ssl3.hs.sha; stateBuf = PK11_SaveContextAlloc(h, stackBuf, sizeof(stackBuf), &stateLen); @@ -4779,11 +4881,6 @@ tls12_loser: unsigned char md5StackBuf[256]; unsigned char shaStackBuf[512]; - if (!spec->master_secret) { - PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); - return SECFailure; - } - md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf, sizeof md5StackBuf, &md5StateLen); if (md5StateBuf == NULL) { @@ -4804,6 +4901,12 @@ tls12_loser: /* compute hashes for SSL3. */ unsigned char s[4]; + if (!spec->master_secret) { + PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); + return SECFailure; + } + + s[0] = (unsigned char)(sender >> 24); s[1] = (unsigned char)(sender >> 16); s[2] = (unsigned char)(sender >> 8); @@ -6049,14 +6152,6 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) } } - rv = ssl3_InitPendingCipherSpec(ss, pms); - PK11_FreeSymKey(pms); pms = NULL; - - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, isTLS ? enc_pms.len + 2 : enc_pms.len); if (rv != SECSuccess) { @@ -6071,6 +6166,15 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) goto loser; /* err set by ssl3_AppendHandshake* */ } + rv = ssl3_InitPendingCipherSpec(ss, pms); + PK11_FreeSymKey(pms); + pms = NULL; + + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + goto loser; + } + rv = SECSuccess; loser: @@ -6140,14 +6244,6 @@ sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) SECKEY_DestroyPrivateKey(privKey); privKey = NULL; - rv = ssl3_InitPendingCipherSpec(ss, pms); - PK11_FreeSymKey(pms); pms = NULL; - - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, pubKey->u.dh.publicValue.len + 2); if (rv != SECSuccess) { @@ -6163,8 +6259,16 @@ sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) goto loser; /* err set by ssl3_AppendHandshake* */ } - rv = SECSuccess; + rv = ssl3_InitPendingCipherSpec(ss, pms); + PK11_FreeSymKey(pms); + pms = NULL; + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + goto loser; + } + + rv = SECSuccess; loser: @@ -6561,6 +6665,32 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SECItem wrappedMS; /* wrapped master secret. */ + /* [draft-ietf-tls-session-hash-06; Section 5.3] + * + * o If the original session did not use the "extended_master_secret" + * extension but the new ServerHello contains the extension, the + * client MUST abort the handshake. + */ + if (!sid->u.ssl3.keys.extendedMasterSecretUsed && + ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) { + errCode = SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET; + goto alert_loser; + } + + /* + * o If the original session used an extended master secret but the new + * ServerHello does not contain the "extended_master_secret" + * extension, the client SHOULD abort the handshake. + * + * TODO(ekr@rtfm.com): Add option to refuse to resume when EMS is not + * used at all (bug 1176526). + */ + if (sid->u.ssl3.keys.extendedMasterSecretUsed && + !ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) { + errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET; + goto alert_loser; + } + ss->sec.authAlgorithm = sid->authAlgorithm; ss->sec.authKeyBits = sid->authKeyBits; ss->sec.keaType = sid->keaType; @@ -6662,7 +6792,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); } - /* NULL value for PMS signifies re-use of the old MS */ + /* NULL value for PMS because we are reusing the old MS */ rv = ssl3_InitPendingCipherSpec(ss, NULL); if (rv != SECSuccess) { goto alert_loser; /* err code was set */ @@ -6691,6 +6821,9 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) sid->u.ssl3.sessionIDLength = sidBytes.len; PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len); + sid->u.ssl3.keys.extendedMasterSecretUsed = + ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn); + ss->ssl3.hs.isResuming = PR_FALSE; if (ss->ssl3.hs.kea_def->signKeyType != sign_null) { /* All current cipher suites other than those with sign_null (i.e., @@ -7628,6 +7761,7 @@ ssl3_NewSessionID(sslSocket *ss, PRBool is_server) sid->u.ssl3.policy = SSL_ALLOWED; sid->u.ssl3.clientWriteKey = NULL; sid->u.ssl3.serverWriteKey = NULL; + sid->u.ssl3.keys.extendedMasterSecretUsed = PR_FALSE; if (is_server) { SECStatus rv; @@ -8188,6 +8322,8 @@ compression_found: /* If there are any failures while processing the old sid, * we don't consider them to be errors. Instead, We just behave * as if the client had sent us no sid to begin with, and make a new one. + * The exception here is attempts to resume extended_master_secret + * sessions without the extension, which causes an alert. */ if (sid != NULL) do { ssl3CipherSpec *pwSpec; @@ -8199,6 +8335,30 @@ compression_found: break; /* not an error */ } + /* [draft-ietf-tls-session-hash-06; Section 5.3] + * o If the original session did not use the "extended_master_secret" + * extension but the new ClientHello contains the extension, then the + * server MUST NOT perform the abbreviated handshake. Instead, it + * SHOULD continue with a full handshake (as described in + * Section 5.2) to negotiate a new session. + * + * o If the original session used the "extended_master_secret" + * extension but the new ClientHello does not contain the extension, + * the server MUST abort the abbreviated handshake. + */ + if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) { + if (!sid->u.ssl3.keys.extendedMasterSecretUsed) { + break; /* not an error */ + } + } else { + if (sid->u.ssl3.keys.extendedMasterSecretUsed) { + /* Note: we do not destroy the session */ + desc = handshake_failure; + errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET; + goto alert_loser; + } + } + if (ss->sec.ci.sid) { if (ss->sec.uncache) ss->sec.uncache(ss->sec.ci.sid); @@ -8339,7 +8499,7 @@ compression_found: haveSpecWriteLock = PR_FALSE; } - /* NULL value for PMS signifies re-use of the old MS */ + /* NULL value for PMS because we are re-using the old MS */ rv = ssl3_InitPendingCipherSpec(ss, NULL); if (rv != SECSuccess) { errCode = PORT_GetError(); @@ -8530,6 +8690,8 @@ compression_found: } ss->sec.ci.sid = sid; + sid->u.ssl3.keys.extendedMasterSecretUsed = + ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn); ss->ssl3.hs.isResuming = PR_FALSE; ssl_GetXmitBufLock(ss); rv = ssl3_SendServerHelloSequence(ss); @@ -9276,7 +9438,7 @@ ssl3_SendCertificateRequest(sslSocket *ss) int nnames = 0; int certTypesLength; PRUint8 sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2]; - unsigned int sigAlgsLength; + unsigned int sigAlgsLength = 0; SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake", SSL_GETPID(), ss->fd)); @@ -9540,18 +9702,17 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, PRUint32 length, SECKEYPrivateKey *serverKey) { - PK11SymKey * pms; #ifndef NO_PKCS11_BYPASS unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random; unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random; ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec; unsigned int outLen = 0; -#endif PRBool isTLS = PR_FALSE; + SECItem pmsItem = {siBuffer, NULL, 0}; + unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH]; +#endif SECStatus rv; SECItem enc_pms; - unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH]; - SECItem pmsItem = {siBuffer, NULL, 0}; PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); @@ -9559,8 +9720,10 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, enc_pms.data = b; enc_pms.len = length; +#ifndef NO_PKCS11_BYPASS pmsItem.data = rsaPmsBuf; pmsItem.len = sizeof rsaPmsBuf; +#endif if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ PRInt32 kLen; @@ -9572,13 +9735,24 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, if ((unsigned)kLen < enc_pms.len) { enc_pms.len = kLen; } +#ifndef NO_PKCS11_BYPASS isTLS = PR_TRUE; +#endif } else { +#ifndef NO_PKCS11_BYPASS isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0); +#endif } #ifndef NO_PKCS11_BYPASS if (ss->opt.bypassPKCS11) { + /* We have not implemented a tls_ExtendedMasterKeyDeriveBypass + * and will not negotiate this extension in bypass mode. This + * assert just double-checks that. + */ + PORT_Assert( + !ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)); + /* TRIPLE BYPASS, get PMS directly from RSA decryption. * Use PK11_PrivDecryptPKCS1 to decrypt the PMS to a buffer, * then, check for version rollback attack, then @@ -9606,8 +9780,8 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, } } /* have PMS, build MS without PKCS11 */ - rv = ssl3_MasterKeyDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS, - PR_TRUE); + rv = ssl3_MasterSecretDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS, + PR_TRUE); if (rv != SECSuccess) { pwSpec->msItem.data = pwSpec->raw_master_secret; pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH; @@ -9617,46 +9791,107 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, } else #endif { + PK11SymKey *tmpPms[2] = {NULL, NULL}; + PK11SlotInfo *slot; + int useFauxPms = 0; +#define currentPms tmpPms[!useFauxPms] +#define unusedPms tmpPms[useFauxPms] +#define realPms tmpPms[1] +#define fauxPms tmpPms[0] + #ifndef NO_PKCS11_BYPASS double_bypass: #endif - /* - * unwrap pms out of the incoming buffer - * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do - * the unwrap. Rather, it is the mechanism with which the - * unwrapped pms will be used. - */ - pms = PK11_PubUnwrapSymKey(serverKey, &enc_pms, - CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0); - if (pms != NULL) { - PRINT_BUF(60, (ss, "decrypted premaster secret:", - PK11_GetKeyData(pms)->data, - PK11_GetKeyData(pms)->len)); - } else { - /* unwrap failed. Generate a bogus PMS and carry on. */ - PK11SlotInfo * slot = PK11_GetSlotFromPrivateKey(serverKey); - ssl_GetSpecWriteLock(ss); - pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.prSpec, slot); - ssl_ReleaseSpecWriteLock(ss); - PK11_FreeSlot(slot); - } + /* + * Get as close to algorithm 2 from RFC 5246; Section 7.4.7.1 + * as we can within the constraints of the PKCS#11 interface. + * + * 1. Unconditionally generate a bogus PMS (what RFC 5246 + * calls R). + * 2. Attempt the RSA decryption to recover the PMS (what + * RFC 5246 calls M). + * 3. Set PMS = (M == NULL) ? R : M + * 4. Use ssl3_ComputeMasterSecret(PMS) to attempt to derive + * the MS from PMS. This includes performing the version + * check and length check. + * 5. If either the initial RSA decryption failed or + * ssl3_ComputeMasterSecret(PMS) failed, then discard + * M and set PMS = R. Else, discard R and set PMS = M. + * + * We do two derivations here because we can't rely on having + * a function that only performs the PMS version and length + * check. The only redundant cost is that this runs the PRF, + * which isn't necessary here. + */ - if (pms == NULL) { - /* last gasp. */ + /* Generate the bogus PMS (R) */ + slot = PK11_GetSlotFromPrivateKey(serverKey); + if (!slot) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + if (!PK11_DoesMechanism(slot, CKM_SSL3_MASTER_KEY_DERIVE)) { + PK11_FreeSlot(slot); + slot = PK11_GetBestSlot(CKM_SSL3_MASTER_KEY_DERIVE, NULL); + if (!slot) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + } + + ssl_GetSpecWriteLock(ss); + fauxPms = ssl3_GenerateRSAPMS(ss, ss->ssl3.prSpec, slot); + ssl_ReleaseSpecWriteLock(ss); + PK11_FreeSlot(slot); + + if (fauxPms == NULL) { ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); return SECFailure; } + /* + * unwrap pms out of the incoming buffer + * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do + * the unwrap. Rather, it is the mechanism with which the + * unwrapped pms will be used. + */ + realPms = PK11_PubUnwrapSymKey(serverKey, &enc_pms, + CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0); + /* Temporarily use the PMS if unwrapping the real PMS fails. */ + useFauxPms |= (realPms == NULL); + + /* Attempt to derive the MS from the PMS. This is the only way to + * check the version field in the RSA PMS. If this fails, we + * then use the faux PMS in place of the PMS. Note that this + * operation should never fail if we are using the faux PMS + * since it is correctly formatted. */ + rv = ssl3_ComputeMasterSecret(ss, currentPms, NULL); + + /* If we succeeded, then select the true PMS and discard the + * FPMS. Else, select the FPMS and select the true PMS */ + useFauxPms |= (rv != SECSuccess); + + if (unusedPms) { + PK11_FreeSymKey(unusedPms); + } + /* This step will derive the MS from the PMS, among other things. */ - rv = ssl3_InitPendingCipherSpec(ss, pms); - PK11_FreeSymKey(pms); + rv = ssl3_InitPendingCipherSpec(ss, currentPms); + PK11_FreeSymKey(currentPms); } if (rv != SECSuccess) { SEND_ALERT return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */ } + +#undef currentPms +#undef unusedPms +#undef realPms +#undef fauxPms + return SECSuccess; } diff --git a/security/nss/lib/ssl/ssl3ecc.c b/security/nss/lib/ssl/ssl3ecc.c index 43af5294..dac21744 100644 --- a/security/nss/lib/ssl/ssl3ecc.c +++ b/security/nss/lib/ssl/ssl3ecc.c @@ -319,14 +319,6 @@ ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) SECKEY_DestroyPrivateKey(privKey); privKey = NULL; - rv = ssl3_InitPendingCipherSpec(ss, pms); - PK11_FreeSymKey(pms); pms = NULL; - - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, pubKey->u.ec.publicValue.len + 1); if (rv != SECSuccess) { @@ -343,6 +335,14 @@ ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) goto loser; /* err set by ssl3_AppendHandshake* */ } + rv = ssl3_InitPendingCipherSpec(ss, pms); + PK11_FreeSymKey(pms); pms = NULL; + + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + goto loser; + } + rv = SECSuccess; loser: diff --git a/security/nss/lib/ssl/ssl3ext.c b/security/nss/lib/ssl/ssl3ext.c index c45f2954..07d79294 100644 --- a/security/nss/lib/ssl/ssl3ext.c +++ b/security/nss/lib/ssl/ssl3ext.c @@ -91,6 +91,12 @@ static PRInt32 ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes); static SECStatus ssl3_ServerHandleDraftVersionXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data); +static PRInt32 ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append, + PRUint32 maxBytes); +static SECStatus ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss, + PRUint16 ex_type, + SECItem *data); + /* * Write bytes. Using this function means the SECItem structure @@ -256,6 +262,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = { { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn }, { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn }, { ssl_tls13_draft_version_xtn, &ssl3_ServerHandleDraftVersionXtn }, + { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn }, { -1, NULL } }; @@ -270,6 +277,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn }, { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn }, { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, + { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn }, { -1, NULL } }; @@ -299,6 +307,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }, { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn }, + { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn}, /* any extra entries will appear as { 0, NULL } */ }; @@ -1182,6 +1191,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss) + cert_length /* cert */ + 1 /* server name type */ + srvNameLen /* name len + length field */ + + 1 /* extendedMasterSecretUsed */ + sizeof(ticket.ticket_lifetime_hint); padding_length = AES_BLOCK_SIZE - (ciphertext_length % AES_BLOCK_SIZE); @@ -1280,6 +1290,11 @@ ssl3_SendNewSessionTicket(sslSocket *ss) if (rv != SECSuccess) goto loser; } + /* extendedMasterSecretUsed */ + rv = ssl3_AppendNumberToItem( + &plaintext, ss->sec.ci.sid->u.ssl3.keys.extendedMasterSecretUsed, 1); + if (rv != SECSuccess) goto loser; + PORT_Assert(plaintext.len == padding_length); for (i = 0; i < padding_length; i++) plaintext.data[i] = (unsigned char)padding_length; @@ -1637,9 +1652,10 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, goto loser; } - /* Read ticket_version (which is ignored for now.) */ + /* Read ticket_version and reject if the version is wrong */ temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); - if (temp < 0) goto no_ticket; + if (temp != TLS_EX_SESS_TICKET_VERSION) goto no_ticket; + parsed_session_ticket->ticket_version = (SSL3ProtocolVersion)temp; /* Read SSLVersion. */ @@ -1740,6 +1756,13 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, parsed_session_ticket->srvName.type = nameType; } + /* Read extendedMasterSecretUsed */ + temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + if (temp < 0) + goto no_ticket; + PORT_Assert(temp == PR_TRUE || temp == PR_FALSE); + parsed_session_ticket->extendedMasterSecretUsed = (PRBool)temp; + /* Done parsing. Check that all bytes have been consumed. */ if (buffer_len != padding_length) goto no_ticket; @@ -1786,6 +1809,8 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, parsed_session_ticket->ms_is_wrapped; sid->u.ssl3.masterValid = PR_TRUE; sid->u.ssl3.keys.resumable = PR_TRUE; + sid->u.ssl3.keys.extendedMasterSecretUsed = parsed_session_ticket-> + extendedMasterSecretUsed; /* Copy over client cert from session ticket if there is one. */ if (parsed_session_ticket->peer_cert.data != NULL) { @@ -2559,3 +2584,90 @@ ssl3_ServerHandleDraftVersionXtn(sslSocket * ss, PRUint16 ex_type, return SECSuccess; } + +static PRInt32 +ssl3_SendExtendedMasterSecretXtn(sslSocket * ss, PRBool append, + PRUint32 maxBytes) +{ + PRInt32 extension_length; + + if (!ss->opt.enableExtendedMS) { + return 0; + } + +#ifndef NO_PKCS11_BYPASS + /* Extended MS can only be used w/o bypass mode */ + if (ss->opt.bypassPKCS11) { + PORT_Assert(0); + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); + return -1; + } +#endif + + /* Always send the extension in this function, since the + * client always sends it and this function is only called on + * the server if we negotiated the extension. */ + extension_length = 4; /* Type + length (0) */ + if (maxBytes < extension_length) { + PORT_Assert(0); + return 0; + } + + if (append) { + SECStatus rv; + rv = ssl3_AppendHandshakeNumber(ss, ssl_extended_master_secret_xtn, 2); + if (rv != SECSuccess) + goto loser; + rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + if (rv != SECSuccess) + goto loser; + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + ssl_extended_master_secret_xtn; + } + + return extension_length; + +loser: + return -1; +} + + +static SECStatus +ssl3_HandleExtendedMasterSecretXtn(sslSocket * ss, PRUint16 ex_type, + SECItem *data) +{ + if (ss->version < SSL_LIBRARY_VERSION_TLS_1_0) { + return SECSuccess; + } + + if (!ss->opt.enableExtendedMS) { + return SECSuccess; + } + +#ifndef NO_PKCS11_BYPASS + /* Extended MS can only be used w/o bypass mode */ + if (ss->opt.bypassPKCS11) { + PORT_Assert(0); + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); + return SECFailure; + } +#endif + + if (data->len != 0) { + SSL_TRC(30, ("%d: SSL3[%d]: Bogus extended master secret extension", + SSL_GETPID(), ss->fd)); + return SECFailure; + } + + SSL_DBG(("%d: SSL[%d]: Negotiated extended master secret extension.", + SSL_GETPID(), ss->fd)); + + /* Keep track of negotiated extensions. */ + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + + if (ss->sec.isServer) { + return ssl3_RegisterServerHelloExtensionSender( + ss, ex_type, ssl3_SendExtendedMasterSecretXtn); + } + return SECSuccess; +} diff --git a/security/nss/lib/ssl/sslerr.h b/security/nss/lib/ssl/sslerr.h index 4e905438..192a1075 100644 --- a/security/nss/lib/ssl/sslerr.h +++ b/security/nss/lib/ssl/sslerr.h @@ -205,6 +205,9 @@ SSL_ERROR_RX_SHORT_DTLS_READ = (SSL_ERROR_BASE + 133), SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 134), SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 135), +SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 136), +SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 137), + SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ } SSLErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */ diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index dc3c73ee..43daa9d6 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -347,6 +347,7 @@ typedef struct sslOptionsStr { unsigned int reuseServerECDHEKey : 1; /* 28 */ unsigned int enableFallbackSCSV : 1; /* 29 */ unsigned int enableServerDhe : 1; /* 30 */ + unsigned int enableExtendedMS : 1; /* 31 */ } sslOptions; typedef enum { sslHandshakingUndetermined = 0, @@ -520,6 +521,7 @@ typedef struct { PRUint16 wrapped_master_secret_len; PRUint8 msIsWrapped; PRUint8 resumable; + PRUint8 extendedMasterSecretUsed; } ssl3SidKeys; /* 52 bytes */ typedef struct { @@ -1073,6 +1075,7 @@ typedef struct SessionTicketStr { CK_MECHANISM_TYPE msWrapMech; PRUint16 ms_length; SSL3Opaque master_secret[48]; + PRBool extendedMasterSecretUsed; ClientIdentity client_identity; SECItem peer_cert; PRUint32 timestamp; @@ -1598,7 +1601,7 @@ extern PRBool ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant, extern SECStatus ssl3_KeyAndMacDeriveBypass(ssl3CipherSpec * pwSpec, const unsigned char * cr, const unsigned char * sr, PRBool isTLS, PRBool isExport); -extern SECStatus ssl3_MasterKeyDeriveBypass( ssl3CipherSpec * pwSpec, +extern SECStatus ssl3_MasterSecretDeriveBypass( ssl3CipherSpec * pwSpec, const unsigned char * cr, const unsigned char * sr, const SECItem * pms, PRBool isTLS, PRBool isRSA); @@ -1849,7 +1852,7 @@ extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey, /* Tell clients to consider tickets valid for this long. */ #define TLS_EX_SESS_TICKET_LIFETIME_HINT (2 * 24 * 60 * 60) /* 2 days */ -#define TLS_EX_SESS_TICKET_VERSION (0x0100) +#define TLS_EX_SESS_TICKET_VERSION (0x0101) extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned int length); diff --git a/security/nss/lib/ssl/sslinfo.c b/security/nss/lib/ssl/sslinfo.c index 48b77b01..f631ec40 100644 --- a/security/nss/lib/ssl/sslinfo.c +++ b/security/nss/lib/ssl/sslinfo.c @@ -67,6 +67,8 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) inf.creationTime = sid->creationTime; inf.lastAccessTime = sid->lastAccessTime; inf.expirationTime = sid->expirationTime; + inf.extendedMasterSecretUsed = sid->u.ssl3.keys.extendedMasterSecretUsed; + if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */ inf.sessionIDLength = SSL2_SESSIONID_BYTES; memcpy(inf.sessionID, sid->u.ssl2.sessionID, diff --git a/security/nss/lib/ssl/sslsnce.c b/security/nss/lib/ssl/sslsnce.c index 3a80d060..f31b2e9c 100644 --- a/security/nss/lib/ssl/sslsnce.c +++ b/security/nss/lib/ssl/sslsnce.c @@ -120,14 +120,14 @@ struct sidCacheEntryStr { /* 2 */ ssl3CipherSuite cipherSuite; /* 2 */ PRUint16 compression; /* SSLCompressionMethod */ -/* 52 */ ssl3SidKeys keys; /* keys, wrapped as needed. */ +/* 54 */ ssl3SidKeys keys; /* keys, wrapped as needed. */ /* 4 */ PRUint32 masterWrapMech; /* 4 */ SSL3KEAType exchKeyType; /* 4 */ PRInt32 certIndex; /* 4 */ PRInt32 srvNameIndex; /* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */ -/*104 */} ssl3; +/*108 */} ssl3; /* force sizeof(sidCacheEntry) to be a multiple of cache line size */ struct { /*120 */ PRUint8 filler[120]; /* 72+120==192, a multiple of 16 */ @@ -507,7 +507,6 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from) to->sessionIDLength = from->u.ssl3.sessionIDLength; to->u.ssl3.certIndex = -1; to->u.ssl3.srvNameIndex = -1; - PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID, to->sessionIDLength); @@ -637,7 +636,7 @@ ConvertToSID(sidCacheEntry * from, to->authKeyBits = from->authKeyBits; to->keaType = from->keaType; to->keaKeyBits = from->keaKeyBits; - + return to; loser: @@ -1027,10 +1026,6 @@ CloseCache(cacheDesc *cache) memset(cache, 0, sizeof *cache); } -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif static SECStatus InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries, int maxSrvNameCacheEntries, PRUint32 ssl2_timeout, @@ -1232,20 +1227,32 @@ InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries, /* Fix pointers in our private copy of cache descriptor to point to ** spaces in shared memory */ - ptr = (ptrdiff_t)cache->cacheMem; - *(ptrdiff_t *)(&cache->sidCacheLocks) += ptr; - *(ptrdiff_t *)(&cache->keyCacheLock ) += ptr; - *(ptrdiff_t *)(&cache->certCacheLock) += ptr; - *(ptrdiff_t *)(&cache->srvNameCacheLock) += ptr; - *(ptrdiff_t *)(&cache->sidCacheSets ) += ptr; - *(ptrdiff_t *)(&cache->sidCacheData ) += ptr; - *(ptrdiff_t *)(&cache->certCacheData) += ptr; - *(ptrdiff_t *)(&cache->keyCacheData ) += ptr; - *(ptrdiff_t *)(&cache->ticketKeyNameSuffix) += ptr; - *(ptrdiff_t *)(&cache->ticketEncKey ) += ptr; - *(ptrdiff_t *)(&cache->ticketMacKey ) += ptr; - *(ptrdiff_t *)(&cache->ticketKeysValid) += ptr; - *(ptrdiff_t *)(&cache->srvNameCacheData) += ptr; + cache->sidCacheLocks = (sidCacheLock *) + (cache->cacheMem + (ptrdiff_t)cache->sidCacheLocks); + cache->keyCacheLock = (sidCacheLock *) + (cache->cacheMem + (ptrdiff_t)cache->keyCacheLock); + cache->certCacheLock = (sidCacheLock *) + (cache->cacheMem + (ptrdiff_t)cache->certCacheLock); + cache->srvNameCacheLock = (sidCacheLock *) + (cache->cacheMem + (ptrdiff_t)cache->srvNameCacheLock); + cache->sidCacheSets = (sidCacheSet *) + (cache->cacheMem + (ptrdiff_t)cache->sidCacheSets); + cache->sidCacheData = (sidCacheEntry *) + (cache->cacheMem + (ptrdiff_t)cache->sidCacheData); + cache->certCacheData = (certCacheEntry *) + (cache->cacheMem + (ptrdiff_t)cache->certCacheData); + cache->keyCacheData = (SSLWrappedSymWrappingKey *) + (cache->cacheMem + (ptrdiff_t)cache->keyCacheData); + cache->ticketKeyNameSuffix = (PRUint8 *) + (cache->cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix); + cache->ticketEncKey = (encKeyCacheEntry *) + (cache->cacheMem + (ptrdiff_t)cache->ticketEncKey); + cache->ticketMacKey = (encKeyCacheEntry *) + (cache->cacheMem + (ptrdiff_t)cache->ticketMacKey); + cache->ticketKeysValid = (PRUint32 *) + (cache->cacheMem + (ptrdiff_t)cache->ticketKeysValid); + cache->srvNameCacheData = (srvNameCacheEntry *) + (cache->cacheMem + (ptrdiff_t)cache->srvNameCacheData); /* initialize the locks */ init_time = ssl_Time(); @@ -1270,9 +1277,6 @@ loser: CloseCache(cache); return SECFailure; } -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif PRUint32 SSL_GetMaxServerCacheLocks(void) @@ -1491,7 +1495,6 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString) char * fmString = NULL; char * myEnvString = NULL; unsigned int decoLen; - ptrdiff_t ptr; inheritance inherit; cacheDesc my; #ifdef WINNT @@ -1587,20 +1590,32 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString) /* Fix pointers in our private copy of cache descriptor to point to ** spaces in shared memory, whose address is now in "my". */ - ptr = (ptrdiff_t)my.cacheMem; - *(ptrdiff_t *)(&cache->sidCacheLocks) += ptr; - *(ptrdiff_t *)(&cache->keyCacheLock ) += ptr; - *(ptrdiff_t *)(&cache->certCacheLock) += ptr; - *(ptrdiff_t *)(&cache->srvNameCacheLock) += ptr; - *(ptrdiff_t *)(&cache->sidCacheSets ) += ptr; - *(ptrdiff_t *)(&cache->sidCacheData ) += ptr; - *(ptrdiff_t *)(&cache->certCacheData) += ptr; - *(ptrdiff_t *)(&cache->keyCacheData ) += ptr; - *(ptrdiff_t *)(&cache->ticketKeyNameSuffix) += ptr; - *(ptrdiff_t *)(&cache->ticketEncKey ) += ptr; - *(ptrdiff_t *)(&cache->ticketMacKey ) += ptr; - *(ptrdiff_t *)(&cache->ticketKeysValid) += ptr; - *(ptrdiff_t *)(&cache->srvNameCacheData) += ptr; + cache->sidCacheLocks = (sidCacheLock *) + (my.cacheMem + (ptrdiff_t)cache->sidCacheLocks); + cache->keyCacheLock = (sidCacheLock *) + (my.cacheMem + (ptrdiff_t)cache->keyCacheLock); + cache->certCacheLock = (sidCacheLock *) + (my.cacheMem + (ptrdiff_t)cache->certCacheLock); + cache->srvNameCacheLock = (sidCacheLock *) + (my.cacheMem + (ptrdiff_t)cache->srvNameCacheLock); + cache->sidCacheSets = (sidCacheSet *) + (my.cacheMem + (ptrdiff_t)cache->sidCacheSets); + cache->sidCacheData = (sidCacheEntry *) + (my.cacheMem + (ptrdiff_t)cache->sidCacheData); + cache->certCacheData = (certCacheEntry *) + (my.cacheMem + (ptrdiff_t)cache->certCacheData); + cache->keyCacheData = (SSLWrappedSymWrappingKey *) + (my.cacheMem + (ptrdiff_t)cache->keyCacheData); + cache->ticketKeyNameSuffix = (PRUint8 *) + (my.cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix); + cache->ticketEncKey = (encKeyCacheEntry *) + (my.cacheMem + (ptrdiff_t)cache->ticketEncKey); + cache->ticketMacKey = (encKeyCacheEntry *) + (my.cacheMem + (ptrdiff_t)cache->ticketMacKey); + cache->ticketKeysValid = (PRUint32 *) + (my.cacheMem + (ptrdiff_t)cache->ticketKeysValid); + cache->srvNameCacheData = (srvNameCacheEntry *) + (my.cacheMem + (ptrdiff_t)cache->srvNameCacheData); cache->cacheMemMap = my.cacheMemMap; cache->cacheMem = my.cacheMem; diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index e3521516..81c3eec2 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -85,6 +85,7 @@ static sslOptions ssl_defaults = { PR_TRUE, /* reuseServerECDHEKey */ PR_FALSE, /* enableFallbackSCSV */ PR_TRUE, /* enableServerDhe */ + PR_FALSE /* enableExtendedMS */ }; /* @@ -825,6 +826,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) ss->opt.enableServerDhe = on; break; + case SSL_ENABLE_EXTENDED_MASTER_SECRET: + ss->opt.enableExtendedMS = on; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -901,6 +906,8 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) on = ss->opt.reuseServerECDHEKey; break; case SSL_ENABLE_FALLBACK_SCSV: on = ss->opt.enableFallbackSCSV; break; case SSL_ENABLE_SERVER_DHE: on = ss->opt.enableServerDhe; break; + case SSL_ENABLE_EXTENDED_MASTER_SECRET: + on = ss->opt.enableExtendedMS; break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -973,6 +980,9 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) case SSL_ENABLE_SERVER_DHE: on = ssl_defaults.enableServerDhe; break; + case SSL_ENABLE_EXTENDED_MASTER_SECRET: + on = ssl_defaults.enableExtendedMS; + break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -1160,6 +1170,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) ssl_defaults.enableServerDhe = on; break; + case SSL_ENABLE_EXTENDED_MASTER_SECRET: + ssl_defaults.enableExtendedMS = on; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; diff --git a/security/nss/lib/ssl/sslt.h b/security/nss/lib/ssl/sslt.h index 7aaa1604..6f5d609e 100644 --- a/security/nss/lib/ssl/sslt.h +++ b/security/nss/lib/ssl/sslt.h @@ -146,6 +146,12 @@ typedef struct SSLChannelInfoStr { /* compression method info */ const char * compressionMethodName; SSLCompressionMethod compressionMethod; + + /* The following fields are added in NSS 3.21. + * This field only has meaning in TLS < 1.3 and will be set to + * PR_FALSE in TLS 1.3. + */ + PRBool extendedMasterSecretUsed; } SSLChannelInfo; /* Preliminary channel info */ @@ -230,13 +236,14 @@ typedef enum { ssl_use_srtp_xtn = 14, ssl_app_layer_protocol_xtn = 16, ssl_padding_xtn = 21, + ssl_extended_master_secret_xtn = 23, ssl_session_ticket_xtn = 35, ssl_next_proto_nego_xtn = 13172, ssl_renegotiation_info_xtn = 0xff01, ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */ } SSLExtensionType; -#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. */ +#define SSL_MAX_EXTENSIONS 12 /* doesn't include ssl_padding_xtn. */ typedef enum { ssl_dhe_group_none = 0, diff --git a/security/nss/lib/util/pkcs11n.h b/security/nss/lib/util/pkcs11n.h index 097ff9c5..22e86b1e 100644 --- a/security/nss/lib/util/pkcs11n.h +++ b/security/nss/lib/util/pkcs11n.h @@ -28,7 +28,7 @@ /* * NSS-defined object classes - * + * */ #define CKO_NSS (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NSS) @@ -166,7 +166,7 @@ #define CKM_NSS_JPAKE_ROUND1_SHA512 (CKM_NSS + 10) /* J-PAKE round 2 key derivation mechanisms. - * + * * Required template attributes: CKA_NSS_JPAKE_PEERID * Input key type: CKK_NSS_JPAKE_ROUND1 * Output key type: CKK_NSS_JPAKE_ROUND2 @@ -178,14 +178,14 @@ #define CKM_NSS_JPAKE_ROUND2_SHA384 (CKM_NSS + 13) #define CKM_NSS_JPAKE_ROUND2_SHA512 (CKM_NSS + 14) -/* J-PAKE final key material derivation mechanisms +/* J-PAKE final key material derivation mechanisms * * Input key type: CKK_NSS_JPAKE_ROUND2 * Output key type: CKK_GENERIC_SECRET * Output key class: CKO_SECRET_KEY * Parameter type: CK_NSS_JPAKEFinalParams * - * You must apply a KDF (e.g. CKM_NSS_HKDF_*) to resultant keying material + * You must apply a KDF (e.g. CKM_NSS_HKDF_*) to resultant keying material * to get a key with uniformly distributed bits. */ #define CKM_NSS_JPAKE_FINAL_SHA1 (CKM_NSS + 15) @@ -216,6 +216,10 @@ #define CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256 (CKM_NSS + 23) #define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24) +/* TLS extended master secret derivation */ +#define CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE (CKM_NSS + 25) +#define CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH (CKM_NSS + 26) + /* * HISTORICAL: * Do not attempt to use these. They are only used by NETSCAPE's internal @@ -294,7 +298,7 @@ typedef struct CK_NSS_MAC_CONSTANT_TIME_PARAMS { /* Mandatory parameter for the CKM_NSS_HKDF_* key deriviation mechanisms. See RFC 5869. - + bExtract: If set, HKDF-Extract will be applied to the input key. If the optional salt is given, it is used; otherwise, the salt is set to a sequence of zeros equal in length to the HMAC output. @@ -319,6 +323,31 @@ typedef struct CK_NSS_HKDFParams { CK_ULONG ulInfoLen; } CK_NSS_HKDFParams; +/* + * Parameter for the TLS extended master secret key derivation mechanisms: + * + * * CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE + * * CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH + * + * For the TLS 1.2 PRF, the prfHashMechanism parameter determines the hash + * function used. For earlier versions of the PRF, set the prfHashMechanism + * value to CKM_TLS_PRF. + * + * The session hash input is expected to be the output of the same hash + * function as the PRF uses (as required by draft-ietf-tls-session-hash). So + * the ulSessionHashLen member must be equal the output length of the hash + * function specified by the prfHashMechanism member (or, for pre-TLS 1.2 PRF, + * the length of concatenated MD5 and SHA-1 digests). + * + */ +typedef struct CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS { + CK_MECHANISM_TYPE prfHashMechanism; + CK_BYTE_PTR pSessionHash; + CK_ULONG ulSessionHashLen; + CK_VERSION_PTR pVersion; +} CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS; + + /* * Trust info * @@ -343,7 +372,7 @@ typedef CK_ULONG CK_TRUST; #define CKT_NSS_NOT_TRUSTED (CKT_NSS + 10) #define CKT_NSS_TRUST_UNKNOWN (CKT_NSS + 5) /* default */ -/* +/* * These may well remain NSS-specific; I'm only using them * to cache resolution data. */ @@ -454,7 +483,7 @@ typedef CK_TRUST __CKT_NSS_MUST_VERIFY __attribute__((deprecated #define SECMOD_MODULE_DB_FUNCTION_FIND 0 #define SECMOD_MODULE_DB_FUNCTION_ADD 1 #define SECMOD_MODULE_DB_FUNCTION_DEL 2 -#define SECMOD_MODULE_DB_FUNCTION_RELEASE 3 +#define SECMOD_MODULE_DB_FUNCTION_RELEASE 3 typedef char ** (PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function, char *parameters, void *moduleSpec); diff --git a/security/nss/lib/util/secport.h b/security/nss/lib/util/secport.h index 1b8f4616..7d2f5e07 100644 --- a/security/nss/lib/util/secport.h +++ b/security/nss/lib/util/secport.h @@ -87,8 +87,14 @@ extern char *PORT_ArenaStrdup(PLArenaPool *arena, const char *str); SEC_END_PROTOS #define PORT_Assert PR_ASSERT -/* This runs a function that should return SECSuccess. */ -/* The value is asserted in a debug build, otherwise it is ignored. */ +/* This runs a function that should return SECSuccess. + * Intended for NSS internal use only. + * The return value is asserted in a debug build, otherwise it is ignored. + * This is no substitute for proper error handling. It is OK only if you + * have ensured that the function cannot fail by other means such as checking + * prerequisites. In that case this can be used as a safeguard against + * unexpected changes in a function. + */ #ifdef DEBUG #define PORT_CheckSuccess(f) PR_ASSERT((f) == SECSuccess) #else diff --git a/security/nss/lib/util/utilmod.c b/security/nss/lib/util/utilmod.c index 50e6c839..4be99ade 100644 --- a/security/nss/lib/util/utilmod.c +++ b/security/nss/lib/util/utilmod.c @@ -75,14 +75,15 @@ /* * Smart string cat functions. Automatically manage the memory. - * The first parameter is the source string. If it's null, we + * The first parameter is the destination string. If it's null, we * allocate memory for it. If it's not, we reallocate memory * so the the concanenated string fits. */ static char * nssutil_DupnCat(char *baseString, const char *str, int str_len) { - int len = (baseString ? PORT_Strlen(baseString) : 0) + 1; + int baseStringLen = baseString ? PORT_Strlen(baseString) : 0; + int len = baseStringLen + 1; char *newString; len += str_len; @@ -91,8 +92,9 @@ nssutil_DupnCat(char *baseString, const char *str, int str_len) PORT_Free(baseString); return NULL; } - if (baseString == NULL) *newString = 0; - return PORT_Strncat(newString,str, str_len); + PORT_Memcpy(&newString[baseStringLen], str, str_len); + newString[len - 1] = 0; + return newString; } /* Same as nssutil_DupnCat except it concatenates the full string, not a @@ -480,7 +482,7 @@ nssutil_DeleteSecmodDBEntry(const char *appName, char *block = NULL; char *name = NULL; char *lib = NULL; - int name_len, lib_len = 0; + int name_len = 0, lib_len = 0; PRBool skip = PR_FALSE; PRBool found = PR_FALSE; diff --git a/security/nss/tests/common/cleanup.sh b/security/nss/tests/common/cleanup.sh index 17a62bbc..8030045d 100644 --- a/security/nss/tests/common/cleanup.sh +++ b/security/nss/tests/common/cleanup.sh @@ -32,10 +32,10 @@ if [ -z "${CLEANUP}" -o "${CLEANUP}" = "${SCRIPTNAME}" ]; then echo "--------------" LINES_CNT=$(cat ${RESULTS} | grep ">Passed<" | wc -l | sed s/\ *//) echo "Passed: ${LINES_CNT}" - LINES_CNT=$(cat ${RESULTS} | grep ">Failed<" | wc -l | sed s/\ *//) - echo "Failed: ${LINES_CNT}" - LINES_CNT=$(cat ${RESULTS} | grep ">Failed Core<" | wc -l | sed s/\ *//) - echo "Failed with core: ${LINES_CNT}" + FAILED_CNT=$(cat ${RESULTS} | grep ">Failed<" | wc -l | sed s/\ *//) + echo "Failed: ${FAILED_CNT}" + CORE_CNT=$(cat ${RESULTS} | grep ">Failed Core<" | wc -l | sed s/\ *//) + echo "Failed with core: ${CORE_CNT}" LINES_CNT=$(cat ${RESULTS} | grep ">Unknown<" | wc -l | sed s/\ *//) echo "Unknown status: ${LINES_CNT}" if [ ${LINES_CNT} -gt 0 ]; then @@ -46,4 +46,8 @@ if [ -z "${CLEANUP}" -o "${CLEANUP}" = "${SCRIPTNAME}" ]; then html "END_OF_TEST
" html "" rm -f ${TEMPFILES} 2>/dev/null + if [ ${FAILED_CNT} -gt 0 ]; then + exit 1 + fi + fi