Bug 1166031 - Update NSS to NSS_3_19_1_BETA1. r=mt
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 20 May 2015 21:06:06 -0400
changeset 275965 5b0d7c8c9cdaf61670a11ba50aedf73e9f861e6a
parent 275964 9e140d3141a83c975051d9384bf1566461adb069
child 275966 c2c83077fe1c55ad79dc76d016166b9d9539f0bd
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmt
bugs1166031
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1166031 - Update NSS to NSS_3_19_1_BETA1. r=mt
CLOBBER
security/nss/TAG-INFO
security/nss/cmd/certutil/certutil.c
security/nss/coreconf/coreconf.dep
security/nss/lib/ckfw/builtins/config.mk
security/nss/lib/ckfw/capi/config.mk
security/nss/lib/cryptohi/keyhi.h
security/nss/lib/cryptohi/seckey.c
security/nss/lib/freebl/blapit.h
security/nss/lib/freebl/ecl/ecp_jac.c
security/nss/lib/freebl/ecl/ecp_jm.c
security/nss/lib/nss/nss.def
security/nss/lib/nss/nss.h
security/nss/lib/softoken/sftkpwd.c
security/nss/lib/softoken/softkver.h
security/nss/lib/ssl/SSLerrs.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/sslerr.h
security/nss/lib/util/nssutil.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1163201 needs clobber.
+Bug 1166031 - NSS update hit needs-clobber bustage.
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_19_RTM
+NSS_3_19_1_BETA1
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -175,17 +175,17 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHa
     CERT_DestroyCertificate (cert);
     PORT_Free(trust);
 
     return rv;
 }
 
 static SECStatus
 CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
-        SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii, 
+        SECOidTag hashAlgTag, CERTName *subject, const char *phone, int ascii,
 	const char *emailAddrs, const char *dnsNames,
         certutilExtnList extnList, const char *extGeneric,
         /*out*/ SECItem *result)
 {
     CERTSubjectPublicKeyInfo *spki;
     CERTCertificateRequest *cr;
     SECItem *encoding;
     SECOidTag signAlgTag;
@@ -265,17 +265,17 @@ CertReq(SECKEYPrivateKey *privk, SECKEYP
 	}
 
 	name = CERT_GetCommonName(subject);
 	if (!name) {
 	    name = PORT_Strdup("(not specified)");
 	}
 
 	if (!phone)
-	    phone = strdup("(not specified)");
+	    phone = "(not specified)";
 
 	email = CERT_GetCertEmailAddress(subject);
 	if (!email)
 	    email = PORT_Strdup("(not specified)");
 
 	org = CERT_GetOrgName(subject);
 	if (!org)
 	    org = PORT_Strdup("(not specified)");
@@ -318,16 +318,17 @@ CertReq(SECKEYPrivateKey *privk, SECKEYP
 		    PORT_Memcpy(result->data + headerLen, obuf, obufLen);
 		    PORT_Memcpy(result->data + headerLen + obufLen,
 				trailer, trailerLen);
 		}
 		PR_smprintf_free(trailer);
 	    }
 	    PR_smprintf_free(header);
 	}
+	PORT_Free(obuf);
     } else {
 	(void) SECITEM_CopyItem(NULL, result, &signedReq);
     }
 
     if (!result->data) {
 oom:    SECU_PrintError(progName, "out of memory");
 	PORT_SetError(SEC_ERROR_NO_MEMORY);
 	rv = SECFailure;
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,8 +5,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/security/nss/lib/ckfw/builtins/config.mk
+++ b/security/nss/lib/ckfw/builtins/config.mk
@@ -25,13 +25,10 @@ endif
 
 # Needed for compilation of $(OBJDIR)/certdata.c
 INCLUDES += -I.
 
 #
 # To create a loadable module on Darwin, we must use -bundle.
 #
 ifeq ($(OS_TARGET),Darwin)
-ifndef USE_64
 DSO_LDOPTS = -bundle
 endif
-endif
-
--- a/security/nss/lib/ckfw/capi/config.mk
+++ b/security/nss/lib/ckfw/capi/config.mk
@@ -22,13 +22,10 @@ endif
 ifdef BUILD_IDG
     DEFINES += -DNSSDEBUG
 endif
 
 #
 # To create a loadable module on Darwin, we must use -bundle.
 #
 ifeq ($(OS_TARGET),Darwin)
-ifndef USE_64
 DSO_LDOPTS = -bundle
 endif
-endif
-
--- a/security/nss/lib/cryptohi/keyhi.h
+++ b/security/nss/lib/cryptohi/keyhi.h
@@ -32,16 +32,21 @@ extern SECStatus SECKEY_CopySubjectPubli
 
 /*
 ** Update the PQG parameters for a cert's public key.
 ** Only done for DSA certs
 */
 extern SECStatus
 SECKEY_UpdateCertPQG(CERTCertificate * subjectCert);
 
+/*
+** Return the number of bits in the provided big integer.  This assumes that the
+** SECItem contains a big-endian number and counts from the first non-zero bit.
+*/
+extern unsigned SECKEY_BigIntegerBitLength(const SECItem *number);
 
 /*
 ** Return the strength of the public key in bytes
 */
 extern unsigned SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk);
 
 /*
 ** Return the strength of the public key in bits
--- a/security/nss/lib/cryptohi/seckey.c
+++ b/security/nss/lib/cryptohi/seckey.c
@@ -173,18 +173,18 @@ SECKEY_CreateRSAPrivateKey(int keySizeIn
 */
 SECKEYPrivateKey *
 SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
 {
     SECKEYPrivateKey *privk;
     PK11SlotInfo *slot;
 
     if (!param || !param->base.data || !param->prime.data ||
-        param->prime.len < 512/8 || param->base.len == 0 || 
-        param->base.len > param->prime.len + 1 || 
+        SECKEY_BigIntegerBitLength(&param->prime) < DH_MIN_P_BITS ||
+        param->base.len == 0 || param->base.len > param->prime.len + 1 ||
 	(param->base.len == 1 && param->base.data[0] == 0)) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return NULL;
     }
 
     slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx);
     if (!slot) {
 	return NULL;
@@ -936,71 +936,86 @@ SECKEY_ECParamsToBasePointOrderLen(const
 	return 570;
 
     default:
 	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
 	return 0;
     }
 }
 
+/* The number of bits in the number from the first non-zero bit onward. */
+unsigned
+SECKEY_BigIntegerBitLength(const SECItem *number)
+{
+    const unsigned char *p;
+    unsigned octets;
+    unsigned bits;
+
+    if (!number || !number->data) {
+        PORT_SetError(SEC_ERROR_INVALID_KEY);
+        return 0;
+    }
+
+    p = number->data;
+    octets = number->len;
+    while (octets > 0 && !*p) {
+        ++p;
+        --octets;
+    }
+    if (octets == 0) {
+        return 0;
+    }
+    /* bits = 7..1 because we know at least one bit is set already */
+    /* Note: This could do a binary search, but this is faster for keys if we
+     * assume that good keys will have the MSB set. */
+    for (bits = 7; bits > 0; --bits) {
+        if (*p & (1 << bits)) {
+            break;
+        }
+    }
+    return octets * 8 + bits - 7;
+}
+
 /* returns key strength in bytes (not bits) */
 unsigned
 SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
 {
-    unsigned char b0;
-    unsigned size;
-
-    /* interpret modulus length as key strength */
-    if (!pubk)
-    	goto loser;
-    switch (pubk->keyType) {
-    case rsaKey:
-	if (!pubk->u.rsa.modulus.data) break;
-    	b0 = pubk->u.rsa.modulus.data[0];
-    	return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
-    case dsaKey:
-	if (!pubk->u.dsa.publicValue.data) break;
-    	b0 = pubk->u.dsa.publicValue.data[0];
-    	return b0 ? pubk->u.dsa.publicValue.len :
-	    pubk->u.dsa.publicValue.len - 1;
-    case dhKey:
-	if (!pubk->u.dh.publicValue.data) break;
-    	b0 = pubk->u.dh.publicValue.data[0];
-    	return b0 ? pubk->u.dh.publicValue.len :
-	    pubk->u.dh.publicValue.len - 1;
-    case ecKey:
-	/* Get the key size in bits and adjust */
-	size =	SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
-	return (size + 7)/8;
-    default:
-	break;
-    }
-loser:
-    PORT_SetError(SEC_ERROR_INVALID_KEY);
-    return 0;
+    return (SECKEY_PublicKeyStrengthInBits(pubk) + 7) / 8;
 }
 
 /* returns key strength in bits */
 unsigned
 SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
 {
-    unsigned size;
+    unsigned bitSize = 0;
+
+    if (!pubk) {
+        PORT_SetError(SEC_ERROR_INVALID_KEY);
+        return 0;
+    }
+
+    /* interpret modulus length as key strength */
     switch (pubk->keyType) {
     case rsaKey:
+        bitSize = SECKEY_BigIntegerBitLength(&pubk->u.rsa.modulus);
+        break;
     case dsaKey:
+        bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dsa.publicValue);
+        break;
     case dhKey:
-	return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
+        bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dh.publicValue);
+        break;
     case ecKey:
-	size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
-	return size;
+        bitSize = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
+        break;
     default:
-	break;
+        PORT_SetError(SEC_ERROR_INVALID_KEY);
+        break;
     }
-    PORT_SetError(SEC_ERROR_INVALID_KEY);
-    return 0;
+    return bitSize;
 }
 
 /* returns signature length in bytes (not bits) */
 unsigned
 SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
 {
     unsigned char b0;
     unsigned size;
--- a/security/nss/lib/freebl/blapit.h
+++ b/security/nss/lib/freebl/blapit.h
@@ -133,20 +133,23 @@ typedef int __BLAPI_DEPRECATED __attribu
 #define SEED_KEY_LENGTH 16              /* bytes */
 
 #define NSS_FREEBL_DEFAULT_CHUNKSIZE 2048
 
 /*
  * These values come from the initial key size limits from the PKCS #11
  * module. They may be arbitrarily adjusted to any value freebl supports.
  */
-#define RSA_MIN_MODULUS_BITS   128
+#define RSA_MIN_MODULUS_BITS   512
 #define RSA_MAX_MODULUS_BITS 16384
 #define RSA_MAX_EXPONENT_BITS   64
-#define DH_MIN_P_BITS	       128
+/* 1023 to avoid cases where p = 2q+1 for a 512-bit q turns out to be
+ * only 1023 bits and similar.  We don't have good data on whether this
+ * happens because NSS used to count bit lengths incorrectly. */
+#define DH_MIN_P_BITS	      1023
 #define DH_MAX_P_BITS        16384
 
 /*
  * The FIPS 186-1 algorithm for generating primes P and Q allows only 9
  * distinct values for the length of P, and only one value for the
  * length of Q.
  * The algorithm uses a variable j to indicate which of the 9 lengths
  * of P is to be used.
@@ -176,17 +179,17 @@ typedef int __BLAPI_DEPRECATED __attribu
  *      3072           256
  *
  * The FIPS-186-3 complaiant PQG generator (PQG V2) takes arbitrary p and q
  * lengths as input and returns an error if they aren't in this list.
  */
 
 #define DSA1_Q_BITS      160
 #define DSA_MAX_P_BITS	3072
-#define DSA_MIN_P_BITS	 512
+#define DSA_MIN_P_BITS  1023
 #define DSA_MAX_Q_BITS   256
 #define DSA_MIN_Q_BITS   160
 
 #if DSA_MAX_Q_BITS != DSA_MAX_SUBPRIME_LEN*8
 #error "Inconsistent declaration of DSA SUBPRIME/Q parameters in blapit.h"
 #endif
 
 
--- a/security/nss/lib/freebl/ecl/ecp_jac.c
+++ b/security/nss/lib/freebl/ecl/ecp_jac.c
@@ -139,16 +139,30 @@ ec_GFp_pt_add_jac_aff(const mp_int *px, 
 	MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth));
 	MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth));
 	MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth));
 
 	/* C = A - px, D = B - py */
 	MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth));
 	MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth));
 
+	if (mp_cmp_z(&C) == 0) {
+		/* P == Q or P == -Q */
+		if (mp_cmp_z(&D) == 0) {
+			/* P == Q */
+			/* It is cheaper to double (qx, qy, 1) than (px, py, pz). */
+			MP_DIGIT(&D, 0) = 1; /* Set D to 1. */
+			MP_CHECKOK(ec_GFp_pt_dbl_jac(qx, qy, &D, rx, ry, rz, group));
+		} else {
+			/* P == -Q */
+			MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
+		}
+		goto CLEANUP;
+	}
+
 	/* C2 = C^2, C3 = C^3 */
 	MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth));
 	MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth));
 
 	/* rz = pz * C */
 	MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth));
 
 	/* C = px * C^2 */
@@ -200,17 +214,18 @@ ec_GFp_pt_dbl_jac(const mp_int *px, cons
 	MP_DIGITS(&t1) = 0;
 	MP_DIGITS(&M) = 0;
 	MP_DIGITS(&S) = 0;
 	MP_CHECKOK(mp_init(&t0));
 	MP_CHECKOK(mp_init(&t1));
 	MP_CHECKOK(mp_init(&M));
 	MP_CHECKOK(mp_init(&S));
 
-	if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
+	/* P == inf or P == -P */
+	if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES || mp_cmp_z(py) == 0) {
 		MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
 		goto CLEANUP;
 	}
 
 	if (mp_cmp_d(pz, 1) == 0) {
 		/* M = 3 * px^2 + a */
 		MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
 		MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
--- a/security/nss/lib/freebl/ecl/ecp_jm.c
+++ b/security/nss/lib/freebl/ecl/ecp_jm.c
@@ -11,17 +11,17 @@
 
 /* Computes R = 2P.  Elliptic curve points P and R can be identical.  Uses 
  * Modified Jacobian coordinates.
  *
  * Assumes input is already field-encoded using field_enc, and returns 
  * output that is still field-encoded.
  *
  */
-mp_err
+static mp_err
 ec_GFp_pt_dbl_jm(const mp_int *px, const mp_int *py, const mp_int *pz,
 				 const mp_int *paz4, mp_int *rx, mp_int *ry, mp_int *rz,
 				 mp_int *raz4, mp_int scratch[], const ECGroup *group)
 {
 	mp_err res = MP_OKAY;
 	mp_int *t0, *t1, *M, *S;
 
 	t0 = &scratch[0];
@@ -81,17 +81,17 @@ ec_GFp_pt_dbl_jm(const mp_int *px, const
 	return res;
 }
 
 /* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
  * (qx, qy, 1).  Elliptic curve points P, Q, and R can all be identical.
  * Uses mixed Modified_Jacobian-affine coordinates. Assumes input is
  * already field-encoded using field_enc, and returns output that is still
  * field-encoded. */
-mp_err
+static mp_err
 ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
 					 const mp_int *paz4, const mp_int *qx,
 					 const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz,
 					 mp_int *raz4, mp_int scratch[], const ECGroup *group)
 {
 	mp_err res = MP_OKAY;
 	mp_int *A, *B, *C, *D, *C2, *C3;
 
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -1071,8 +1071,14 @@ SEC_GetCrlTimes;
 ;+       *;
 ;+};
 ;+NSS_3.19 { 	# NSS 3.19 release
 ;+    global:
 CERT_GetImposedNameConstraints;
 ;+    local:
 ;+       *;
 ;+};
+;+NSS_3.19.1 { 	# NSS 3.19.1 release
+;+    global:
+SECKEY_BigIntegerBitLength;
+;+    local:
+;+       *;
+;+};
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -28,22 +28,22 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION  "3.19" _NSS_ECC_STRING _NSS_CUSTOMIZED
+#define NSS_VERSION  "3.19.1" _NSS_ECC_STRING _NSS_CUSTOMIZED " Beta"
 #define NSS_VMAJOR   3
 #define NSS_VMINOR   19
-#define NSS_VPATCH   0
+#define NSS_VPATCH   1
 #define NSS_VBUILD   0
-#define NSS_BETA     PR_FALSE
+#define NSS_BETA     PR_TRUE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
 typedef struct NSSInitParametersStr NSSInitParameters;
 
 /*
--- a/security/nss/lib/softoken/sftkpwd.c
+++ b/security/nss/lib/softoken/sftkpwd.c
@@ -1242,17 +1242,17 @@ sftkdb_ChangePassword(SFTKDBHandle *keyd
 
     sftkdb_switchKeys(keydb, &newKey);
 
 loser:
     if (newKey.data) {
 	PORT_ZFree(newKey.data,newKey.len);
     }
     if (result) {
-	SECITEM_FreeItem(result, PR_FALSE);
+	SECITEM_FreeItem(result, PR_TRUE);
     }
     if (rv != SECSuccess) {
         (*keydb->db->sdb_Abort)(keydb->db);
     }
     
     return rv;
 }
 
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -20,16 +20,16 @@
 
 /*
  * Softoken's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define SOFTOKEN_VERSION  "3.19" SOFTOKEN_ECC_STRING
+#define SOFTOKEN_VERSION  "3.19.1" SOFTOKEN_ECC_STRING " Beta"
 #define SOFTOKEN_VMAJOR   3
 #define SOFTOKEN_VMINOR   19
-#define SOFTOKEN_VPATCH   0
+#define SOFTOKEN_VPATCH   1
 #define SOFTOKEN_VBUILD   0
-#define SOFTOKEN_BETA     PR_FALSE
+#define SOFTOKEN_BETA     PR_TRUE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/ssl/SSLerrs.h
+++ b/security/nss/lib/ssl/SSLerrs.h
@@ -417,8 +417,11 @@ ER3(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK,
 "The next protocol negotiation extension was enabled, but the callback was cleared prior to being needed.")
 
 ER3(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL, (SSL_ERROR_BASE + 130),
 "The server supports no protocols that the client advertises in the ALPN extension.")
 
 ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 131),
 "The server rejected the handshake because the client downgraded to a lower "
 "TLS version than the server supports.")
+
+ER3(SSL_ERROR_WEAK_SERVER_CERT_KEY, (SSL_ERROR_BASE + 132),
+"The server certificate included a public key that was too weak.")
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -5396,19 +5396,17 @@ ssl3_HandleHelloRequest(sslSocket *ss)
     if (ss->ssl3.hs.ws == wait_server_hello)
 	return SECSuccess;
     if (ss->ssl3.hs.ws != idle_handshake || ss->sec.isServer) {
 	(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
 	PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
 	return SECFailure;
     }
     if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
-	ssl_GetXmitBufLock(ss);
-	rv = SSL3_SendAlert(ss, alert_warning, no_renegotiation);
-	ssl_ReleaseXmitBufLock(ss);
+	(void)SSL3_SendAlert(ss, alert_warning, no_renegotiation);
 	PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
 	return SECFailure;
     }
 
     if (sid) {
 	if (ss->sec.uncache)
             ss->sec.uncache(sid);
 	ssl_FreeSID(sid);
@@ -6596,39 +6594,16 @@ ssl3_HandleServerHello(sslSocket *ss, SS
 alert_loser:
     (void)SSL3_SendAlert(ss, alert_fatal, desc);
 
 loser:
     errCode = ssl_MapLowLevelError(errCode);
     return SECFailure;
 }
 
-/* ssl3_BigIntGreaterThanOne returns true iff |mpint|, taken as an unsigned,
- * big-endian integer is > 1 */
-static PRBool
-ssl3_BigIntGreaterThanOne(const SECItem* mpint) {
-    unsigned char firstNonZeroByte = 0;
-    unsigned int i;
-
-    for (i = 0; i < mpint->len; i++) {
-	if (mpint->data[i]) {
-	    firstNonZeroByte = mpint->data[i];
-	    break;
-	}
-    }
-
-    if (firstNonZeroByte == 0)
-	return PR_FALSE;
-    if (firstNonZeroByte > 1)
-	return PR_TRUE;
-
-    /* firstNonZeroByte == 1, therefore mpint > 1 iff the first non-zero byte
-     * is followed by another byte. */
-    return (i < mpint->len - 1);
-}
 
 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
  * ssl3 ServerKeyExchange message.
  * Caller must hold Handshake and RecvBuf locks.
  */
 static SECStatus
 ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
@@ -6663,16 +6638,22 @@ ssl3_HandleServerKeyExchange(sslSocket *
     case kt_rsa: {
 	SECItem          modulus   = {siBuffer, NULL, 0};
 	SECItem          exponent  = {siBuffer, NULL, 0};
 
     	rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length);
     	if (rv != SECSuccess) {
 	    goto loser;		/* malformed. */
 	}
+        /* This exchange method is only used by export cipher suites.
+         * Those are broken and so this code will eventually be removed. */
+        if (SECKEY_BigIntegerBitLength(&modulus) < 512) {
+            desc = isTLS ? insufficient_security : illegal_parameter;
+            goto alert_loser;
+        }
     	rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length);
     	if (rv != SECSuccess) {
 	    goto loser;		/* malformed. */
 	}
 	if (isTLS12) {
 	    rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
 						       &sigAndHash);
 	    if (rv != SECSuccess) {
@@ -6748,36 +6729,43 @@ ssl3_HandleServerKeyExchange(sslSocket *
     	ss->ssl3.hs.ws = wait_cert_request;
     	return SECSuccess;
     }
 
     case kt_dh: {
 	SECItem          dh_p      = {siBuffer, NULL, 0};
 	SECItem          dh_g      = {siBuffer, NULL, 0};
 	SECItem          dh_Ys     = {siBuffer, NULL, 0};
+        unsigned dh_p_bits;
+        unsigned dh_g_bits;
+        unsigned dh_Ys_bits;
 
     	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
     	if (rv != SECSuccess) {
 	    goto loser;		/* malformed. */
 	}
-	if (dh_p.len < 512/8) {
+        dh_p_bits = SECKEY_BigIntegerBitLength(&dh_p);
+        if (dh_p_bits < DH_MIN_P_BITS) {
 	    errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY;
 	    goto alert_loser;
 	}
     	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length);
     	if (rv != SECSuccess) {
 	    goto loser;		/* malformed. */
 	}
-	if (dh_g.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_g))
+        /* Abort if dh_g is 0, 1, or obviously too big. */
+        dh_g_bits = SECKEY_BigIntegerBitLength(&dh_g);
+        if (dh_g_bits > dh_p_bits || dh_g_bits <= 1)
 	    goto alert_loser;
     	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);
     	if (rv != SECSuccess) {
 	    goto loser;		/* malformed. */
 	}
-	if (dh_Ys.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_Ys))
+        dh_Ys_bits = SECKEY_BigIntegerBitLength(&dh_Ys);
+        if (dh_Ys_bits > dh_p_bits || dh_Ys_bits <= 1)
 	    goto alert_loser;
 	if (isTLS12) {
 	    rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
 						       &sigAndHash);
 	    if (rv != SECSuccess) {
 		goto loser;	/* malformed or unsupported. */
 	    }
 	    rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
@@ -8876,16 +8864,20 @@ ssl3_SendServerKeyExchange(sslSocket *ss
 	    /* how can this happen and rv == SECSuccess ?? */
 	    PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
 	    goto loser;
 	}
 	length = 2 + sdPub->u.rsa.modulus.len +
 	         2 + sdPub->u.rsa.publicExponent.len +
 	         2 + signed_hash.len;
 
+	if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+	    length += 2;
+	}
+
 	rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
 	if (rv != SECSuccess) {
 	    goto loser; 	/* err set by AppendHandshake. */
 	}
 
 	rv = ssl3_AppendHandshakeVariable(ss, sdPub->u.rsa.modulus.data,
 					  sdPub->u.rsa.modulus.len, 2);
 	if (rv != SECSuccess) {
@@ -10050,43 +10042,35 @@ ssl3_AuthCertificate(sslSocket *ss)
 	** it will get fixed when we handle the server key exchange message.
 	*/
 	SECKEYPublicKey * pubKey  = CERT_ExtractPublicKey(cert);
 	ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
 	ss->sec.keaType       = ss->ssl3.hs.kea_def->exchKeyType;
 	if (pubKey) {
 	    ss->sec.keaKeyBits = ss->sec.authKeyBits =
 		SECKEY_PublicKeyStrengthInBits(pubKey);
-#ifndef NSS_DISABLE_ECC
-	    if (ss->sec.keaType == kt_ecdh) {
-		/* Get authKeyBits from signing key.
-		 * XXX The code below uses a quick approximation of
-		 * key size based on cert->signatureWrap.signature.data
-		 * (which contains the DER encoded signature). The field
-		 * cert->signatureWrap.signature.len contains the
-		 * length of the encoded signature in bits.
-		 */
-		if (ss->ssl3.hs.kea_def->kea == kea_ecdh_ecdsa) {
-		    ss->sec.authKeyBits = 
-			cert->signatureWrap.signature.data[3]*8;
-		    if (cert->signatureWrap.signature.data[4] == 0x00)
-			    ss->sec.authKeyBits -= 8;
-		    /* 
-		     * XXX: if cert is not signed by ecdsa we should
-		     * destroy pubKey and goto bad_cert
-		     */
-		} else if (ss->ssl3.hs.kea_def->kea == kea_ecdh_rsa) {
-		    ss->sec.authKeyBits = cert->signatureWrap.signature.len;
-		    /* 
-		     * XXX: if cert is not signed by rsa we should
-		     * destroy pubKey and goto bad_cert
-		     */
-		}
-	    }
-#endif /* NSS_DISABLE_ECC */
+            KeyType pubKeyType = SECKEY_GetPublicKeyType(pubKey);
+            /* Too small: not good enough. Send a fatal alert. */
+            /* TODO: Use 1023 for RSA because a higher RSA_MIN_MODULUS_BITS
+             * breaks export cipher suites, not 1024 to be conservative; when
+             * export removed, increase RSA_MIN_MODULUS_BITS and use that. */
+            /* We aren't checking EC here on the understanding that we only
+             * support curves we like, a decision that might need revisiting. */
+            if (((pubKeyType == rsaKey || pubKeyType == rsaPssKey ||
+                  pubKeyType == rsaOaepKey) && ss->sec.authKeyBits < 1023) ||
+                (pubKeyType == dsaKey && ss->sec.authKeyBits < DSA_MIN_P_BITS) ||
+                (pubKeyType == dhKey && ss->sec.authKeyBits < DH_MIN_P_BITS)) {
+                PORT_SetError(SSL_ERROR_WEAK_SERVER_CERT_KEY);
+                (void)SSL3_SendAlert(ss, alert_fatal,
+                                     ss->version >= SSL_LIBRARY_VERSION_TLS_1_0
+                                     ? insufficient_security
+                                     : illegal_parameter);
+                SECKEY_DestroyPublicKey(pubKey);
+                return SECFailure;
+            }
 	    SECKEY_DestroyPublicKey(pubKey); 
 	    pubKey = NULL;
     	}
 
         if (ss->ssl3.hs.kea_def->ephemeral) {
             ss->ssl3.hs.ws = wait_server_key; /* require server_key_exchange */
         } else {
             ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -620,18 +620,18 @@ static SECStatus
 ssl3_SelectAppProtocol(sslSocket *ss, PRUint16 ex_type, SECItem *data)
 {
     SECStatus rv;
     unsigned char resultBuffer[255];
     SECItem result = { siBuffer, resultBuffer, 0 };
 
     rv = ssl3_ValidateNextProtoNego(data->data, data->len);
     if (rv != SECSuccess) {
+        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         return rv;
     }
 
     PORT_Assert(ss->nextProtoCallback);
     rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len,
                                result.data, &result.len, sizeof(resultBuffer));
     if (rv != SECSuccess) {
         /* Expect callback to call PORT_SetError() */
@@ -648,18 +648,18 @@ ssl3_SelectAppProtocol(sslSocket *ss, PR
     }
 
     SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
 
     if (ex_type == ssl_app_layer_protocol_xtn &&
         ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) {
         /* The callback might say OK, but then it picks a default value - one
          * that was not listed.  That's OK for NPN, but not ALPN. */
+        (void)SSL3_SendAlert(ss, alert_fatal, no_application_protocol);
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL);
-        (void)SSL3_SendAlert(ss, alert_fatal, no_application_protocol);
         return SECFailure;
     }
 
     ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
     return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
 }
 
 /* handle an incoming ALPN extension at the server */
@@ -668,18 +668,18 @@ ssl3_ServerHandleAppProtoXtn(sslSocket *
 {
     int count;
     SECStatus rv;
 
     /* We expressly don't want to allow ALPN on renegotiation,
      * despite it being permitted by the spec. */
     if (ss->firstHsDone || data->len == 0) {
         /* Clients MUST send a non-empty ALPN extension. */
+        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
         return SECFailure;
     }
 
     /* Unlike NPN, ALPN has extra redundant length information so that
      * the extension is the same in both ClientHello and ServerHello. */
     count = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
     if (count != data->len) {
         (void)ssl3_DecodeError(ss);
@@ -696,18 +696,18 @@ ssl3_ServerHandleAppProtoXtn(sslSocket *
       return rv;
     }
 
     /* prepare to send back a response, if we negotiated */
     if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED) {
         rv = ssl3_RegisterServerHelloExtensionSender(
             ss, ex_type, ssl3_ServerSendAppProtoXtn);
         if (rv != SECSuccess) {
+            (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
             return rv;
         }
     }
     return SECSuccess;
 }
 
 static SECStatus
 ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
@@ -717,29 +717,29 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSoc
 
     if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) {
         /* If the server negotiated ALPN then it has already told us what
          * protocol to use, so it doesn't make sense for us to try to negotiate
          * a different one by sending the NPN handshake message. However, if
          * we've negotiated NPN then we're required to send the NPN handshake
          * message. Thus, these two extensions cannot both be negotiated on the
          * same connection. */
+        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
         PORT_SetError(SSL_ERROR_BAD_SERVER);
-        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
         return SECFailure;
     }
 
     /* We should only get this call if we sent the extension, so
      * ss->nextProtoCallback needs to be non-NULL.  However, it is possible
      * that an application erroneously cleared the callback between the time
      * we sent the ClientHello and now. */
     if (!ss->nextProtoCallback) {
         PORT_Assert(0);
+        (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK);
-        (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
         return SECFailure;
     }
 
     return ssl3_SelectAppProtocol(ss, ex_type, data);
 }
 
 static SECStatus
 ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
@@ -753,35 +753,35 @@ ssl3_ClientHandleAppProtoXtn(sslSocket *
         return SECFailure;
     }
 
     /* The extension data from the server has the following format:
      *   uint16 name_list_len;
      *   uint8 len;  // where len >= 1
      *   uint8 protocol_name[len]; */
     if (data->len < 4 || data->len > 2 + 1 + 255) {
+        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         return SECFailure;
     }
 
     list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
     /* The list has to be the entire extension. */
     if (list_len != data->len) {
+        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         return SECFailure;
     }
 
     rv = ssl3_ConsumeHandshakeVariable(ss, &protocol_name, 1,
                                        &data->data, &data->len);
     /* The list must have exactly one value. */
     if (rv != SECSuccess || data->len != 0) {
+        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         return SECFailure;
     }
 
     SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
     ss->ssl3.nextProtoState = SSL_NEXT_PROTO_SELECTED;
     ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
     return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &protocol_name);
 }
@@ -2058,18 +2058,18 @@ ssl3_HandleRenegotiationInfoXtn(sslSocke
                                : ss->ssl3.hs.finishedBytes * 2;
     }
     if (data->len != 1 + len || data->data[0] != len ) {
         (void)ssl3_DecodeError(ss);
         return SECFailure;
     }
     if (len && NSS_SecureMemcmp(ss->ssl3.hs.finishedMsgs.data,
                                 data->data + 1, len)) {
+        (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
         PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
-        (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
         return SECFailure;
     }
     /* remember that we got this extension and it was correct. */
     ss->peerRequestedProtection = 1;
     ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
     if (ss->sec.isServer) {
         /* prepare to send back the appropriate response */
         rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
@@ -2183,32 +2183,32 @@ ssl3_ClientHandleUseSRTPXtn(sslSocket * 
     for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) {
         if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) {
             found = PR_TRUE;
             break;
         }
     }
 
     if (!found) {
+        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
         PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
-        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
         return SECFailure;
     }
 
     /* Get the srtp_mki value */
     rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1,
                                        &data->data, &data->len);
     if (rv != SECSuccess) {
         return SECFailure; /* alert already sent */
     }
 
     /* We didn't offer an MKI, so this must be 0 length */
     if (litem.len != 0) {
+        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
         PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
-        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
         return SECFailure;
     }
 
     /* extra trailing bytes */
     if (data->len != 0) {
         (void)ssl3_DecodeError(ss);
         return SECFailure;
     }
@@ -2308,33 +2308,33 @@ ssl3_ServerHandleSigAlgsXtn(sslSocket * 
 
     rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &data->data,
                                        &data->len);
     if (rv != SECSuccess) {
         return SECFailure;
     }
     /* Trailing data, empty value, or odd-length value is invalid. */
     if (data->len != 0 || algorithms.len == 0 || (algorithms.len & 1) != 0) {
+        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
-        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
         return SECFailure;
     }
 
     numAlgorithms = algorithms.len/2;
 
     /* We don't care to process excessive numbers of algorithms. */
     if (numAlgorithms > 512) {
         numAlgorithms = 512;
     }
 
     ss->ssl3.hs.clientSigAndHash =
             PORT_NewArray(SSL3SignatureAndHashAlgorithm, numAlgorithms);
     if (!ss->ssl3.hs.clientSigAndHash) {
+        (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
         PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
-        (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
         return SECFailure;
     }
     ss->ssl3.hs.numClientSigAndHash = 0;
 
     b = algorithms.data;
     for (i = j = 0; i < numAlgorithms; i++) {
         unsigned char tls_hash = *(b++);
         unsigned char tls_sig = *(b++);
--- a/security/nss/lib/ssl/sslerr.h
+++ b/security/nss/lib/ssl/sslerr.h
@@ -193,13 +193,15 @@ SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM    
 SSL_ERROR_DIGEST_FAILURE                = (SSL_ERROR_BASE + 127),
 SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
 
 SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK     = (SSL_ERROR_BASE + 129),
 SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL     = (SSL_ERROR_BASE + 130),
 
 SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT  = (SSL_ERROR_BASE + 131),
 
+SSL_ERROR_WEAK_SERVER_CERT_KEY          = (SSL_ERROR_BASE + 132),
+
 SSL_ERROR_END_OF_LIST   /* let the c compiler determine the value of this. */
 } SSLErrorCodes;
 #endif /* NO_SECURITY_ERROR_ENUM */
 
 #endif /* __SSL_ERR_H_ */
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -14,22 +14,22 @@
 
 /*
  * NSS utilities's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
  */
-#define NSSUTIL_VERSION  "3.19"
+#define NSSUTIL_VERSION  "3.19.1 Beta"
 #define NSSUTIL_VMAJOR   3
 #define NSSUTIL_VMINOR   19
-#define NSSUTIL_VPATCH   0
+#define NSSUTIL_VPATCH   1
 #define NSSUTIL_VBUILD   0
-#define NSSUTIL_BETA     PR_FALSE
+#define NSSUTIL_BETA     PR_TRUE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.
  */
 extern const char *NSSUTIL_GetVersion(void);