Blob Blame History Raw
diff --git a/cmd/strsclnt/strsclnt.c b/cmd/strsclnt/strsclnt.c
--- a/cmd/strsclnt/strsclnt.c
+++ b/cmd/strsclnt/strsclnt.c
@@ -117,17 +117,17 @@ static int active_threads = 8; /* number
                                ** connect */
 static PRInt32 numUsed;
 /* end of variables protected by threadLock */
 
 static SSL3Statistics * ssl3stats;
 
 static int failed_already = 0;
 static SSLVersionRange enabledVersions;
-static PRBool enableSSL2      = PR_TRUE;
+static PRBool enableSSL2      = PR_FALSE;
 static PRBool bypassPKCS11    = PR_FALSE;
 static PRBool disableLocking  = PR_FALSE;
 static PRBool ignoreErrors    = PR_FALSE;
 static PRBool enableSessionTickets = PR_FALSE;
 static PRBool enableCompression    = PR_FALSE;
 static PRBool enableFalseStart     = PR_FALSE;
 static PRBool enableCertStatus     = PR_FALSE;
 
@@ -158,17 +158,17 @@ Usage(const char *progName)
         "          2 -o's mean skip server certificate validation altogether.\n"
 	"       -D means no TCP delays\n"
 	"       -q means quit when server gone (timeout rather than retry forever)\n"
 	"       -s means disable SSL socket locking\n"
 	"       -N means no session reuse\n"
 	"       -P means do a specified percentage of full handshakes (0-100)\n"
         "       -V [min]:[max] restricts the set of enabled SSL/TLS protocols versions.\n"
         "          All versions are enabled by default.\n"
-        "          Possible values for min/max: ssl2 ssl3 tls1.0 tls1.1 tls1.2\n"
+        "          Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2\n"
         "          Example: \"-V ssl3:\" enables SSL 3 and newer.\n"
         "       -U means enable throttling up threads\n"
 	"       -B bypasses the PKCS11 layer for SSL encryption and MACing\n"
 	"       -T enable the cert_status extension (OCSP stapling)\n"
 	"       -u enable TLS Session Ticket extension\n"
 	"       -z enable compression\n"
 	"       -g enable false start\n",
 	progName);
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -242,25 +242,32 @@ static const /*SSL3ClientCertificateType
 #endif /* NSS_DISABLE_ECC */
     ct_DSS_sign,
 };
 
 /* This block is the contents of the supported_signature_algorithms field of
  * our TLS 1.2 CertificateRequest message, in wire format. See
  * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
  *
- * This block contains only sha256 entries because we only support TLS 1.2
- * CertificateVerify messages that use the handshake hash. */
-static const PRUint8 supported_signature_algorithms[] = {
+ * We only support TLS 1.2
+ * CertificateVerify messages that use the handshake PRF hash. */
+static const PRUint8 supported_signature_algorithms_sha256[] = {
     tls_hash_sha256, tls_sig_rsa,
 #ifndef NSS_DISABLE_ECC
     tls_hash_sha256, tls_sig_ecdsa,
 #endif
     tls_hash_sha256, tls_sig_dsa,
 };
+static const PRUint8 supported_signature_algorithms_sha384[] = {
+    tls_hash_sha384, tls_sig_rsa,
+#ifndef NSS_DISABLE_ECC
+    tls_hash_sha384, tls_sig_ecdsa,
+#endif
+    tls_hash_sha384, tls_sig_dsa,
+};
 
 #define EXPORT_RSA_KEY_LENGTH 64	/* bytes */
 
 
 /* This global item is used only in servers.  It is is initialized by
 ** SSL_ConfigSecureServer(), and is used in ssl3_SendCertificateRequest().
 */
 CERTDistNames *ssl3_server_ca_list = NULL;
@@ -4018,17 +4025,18 @@ ssl3_InitHandshakeHashes(sslSocket *ss)
 		ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
 		return SECFailure;
 	    }
 
 	    /* Create a backup SHA-1 hash for a potential client auth
 	     * signature.
 	     *
 	     * In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the
-	     * handshake hash function (SHA-256). If the server or the client
+	     * handshake PRF hash function (either SHA-256 or SHA384).
+	     * If the server or the client
 	     * does not support SHA-256 as a signature hash, we can either
 	     * maintain a backup SHA-1 handshake hash or buffer all handshake
 	     * messages.
 	     */
 	    if (!ss->sec.isServer) {
 		ss->ssl3.hs.backupHash = PK11_CreateDigestContext(SEC_OID_SHA1);
 		if (ss->ssl3.hs.backupHash == NULL) {
 		    ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
@@ -4750,16 +4758,24 @@ ssl3_ComputeHandshakeHashes(sslSocket * 
 
     hashOid = SECOID_FindOIDByMechanism(ssl3_GetPrfHashMechanism(ss));
     if (hashOid == NULL) {
         ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
         rv = SECFailure;
         goto tls12_loser;
     }
     hashes->hashAlg = hashOid->offset;
+    PORT_Assert(hashes->hashAlg == SEC_OID_SHA256 ||
+                hashes->hashAlg == SEC_OID_SHA384);
+    if (hashes->hashAlg != SEC_OID_SHA256 &&
+        hashes->hashAlg != SEC_OID_SHA384) {
+        ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+        rv = SECFailure;
+        goto tls12_loser;
+    }
 
 	rv = SECSuccess;
 
 tls12_loser:
 	if (stateBuf) {
 	    if (PK11_RestoreContext(h, stateBuf, stateLen) != SECSuccess) {
 		ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
 		rv = SECFailure;
@@ -7015,58 +7031,76 @@ done:
     if (pubk)
 	SECKEY_DestroyPublicKey(pubk);
     return rv;
 }
 
 /* Destroys the backup handshake hash context if we don't need it. Note that
  * this function selects the hash algorithm for client authentication
  * signatures; ssl3_SendCertificateVerify uses the presence of the backup hash
- * to determine whether to use SHA-1 or SHA-256. */
+ * to determine whether to use SHA-1, or the PRF hash of the cipher suite. */
 static void
 ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
 					   const SECItem *algorithms)
 {
     SECStatus rv;
     TLSSignatureAlgorithm sigAlg;
     PRBool preferSha1;
     PRBool supportsSha1 = PR_FALSE;
-    PRBool supportsSha256 = PR_FALSE;
+    PRBool supportsHandshakeHash = PR_FALSE;
     PRBool needBackupHash = PR_FALSE;
     unsigned int i;
+    SECOidData *hashOid;
+    TLSHashAlgoritm suitePRFHash;
+    PRBool suitePRFIs256Or384 = PR_FALSE;
 
 #ifndef NO_PKCS11_BYPASS
     /* Backup handshake hash is not supported in PKCS #11 bypass mode. */
     if (ss->opt.bypassPKCS11) {
 	PORT_Assert(!ss->ssl3.hs.backupHash);
 	return;
     }
 #endif
     PORT_Assert(ss->ssl3.hs.backupHash);
 
     /* Determine the key's signature algorithm and whether it prefers SHA-1. */
     rv = ssl3_ExtractClientKeyInfo(ss, &sigAlg, &preferSha1);
     if (rv != SECSuccess) {
 	goto done;
     }
 
+    hashOid = SECOID_FindOIDByMechanism(ssl3_GetPrfHashMechanism(ss));
+    if (hashOid == NULL) {
+        rv = SECFailure;
+	goto done;
+    }
+
+    if (hashOid->offset == SEC_OID_SHA256) {
+	suitePRFHash = tls_hash_sha256;
+	suitePRFIs256Or384 = PR_TRUE;
+    } else if (hashOid->offset == SEC_OID_SHA384) {
+	suitePRFHash = tls_hash_sha384;
+	suitePRFIs256Or384 = PR_TRUE;
+    } 
+
     /* Determine the server's hash support for that signature algorithm. */
     for (i = 0; i < algorithms->len; i += 2) {
 	if (algorithms->data[i+1] == sigAlg) {
 	    if (algorithms->data[i] == tls_hash_sha1) {
 		supportsSha1 = PR_TRUE;
-	    } else if (algorithms->data[i] == tls_hash_sha256) {
-		supportsSha256 = PR_TRUE;
-	    }
-	}
-    }
-
-    /* If either the server does not support SHA-256 or the client key prefers
-     * SHA-1, leave the backup hash. */
-    if (supportsSha1 && (preferSha1 || !supportsSha256)) {
+	    } else if (suitePRFIs256Or384 &&
+	               algorithms->data[i] == suitePRFHash) {
+		supportsHandshakeHash = PR_TRUE;
+	    }
+	}
+    }
+
+    /* If either the server does not support SHA-256/384, or the client key
+     * prefers SHA-1, leave the backup hash. */
+    if (supportsSha1 && (preferSha1 || !supportsHandshakeHash)) {
 	needBackupHash = PR_TRUE;
     }
 
 done:
     if (!needBackupHash) {
 	PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE);
 	ss->ssl3.hs.backupHash = NULL;
     }
@@ -9226,16 +9260,17 @@ ssl3_SendCertificateRequest(sslSocket *s
     SECItem *      names	= NULL;
     SECStatus      rv;
     int            length;
     int            i;
     int            calen	= 0;
     int            nnames	= 0;
     int            certTypesLength;
     int            sigAlgsLength;
+    SECOidData     *hashOid;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake",
 		SSL_GETPID(), ss->fd));
 
     PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
@@ -9252,18 +9287,30 @@ ssl3_SendCertificateRequest(sslSocket *s
     }
 
     for (i = 0, name = names; i < nnames; i++, name++) {
 	calen += 2 + name->len;
     }
 
     certTypes       = certificate_types;
     certTypesLength = sizeof certificate_types;
-    sigAlgs         = supported_signature_algorithms;
-    sigAlgsLength   = sizeof supported_signature_algorithms;
+
+    hashOid = SECOID_FindOIDByMechanism(ssl3_GetPrfHashMechanism(ss));
+    if (hashOid == NULL) {
+	return SECFailure; 		/* err set by AppendHandshake. */
+    }
+    if (hashOid->offset == SEC_OID_SHA256) {
+	sigAlgs         = supported_signature_algorithms_sha256;
+	sigAlgsLength   = sizeof supported_signature_algorithms_sha256;
+    } else if (hashOid->offset == SEC_OID_SHA384) {
+	sigAlgs         = supported_signature_algorithms_sha384;
+	sigAlgsLength   = sizeof supported_signature_algorithms_sha384;
+    } else {
+	return SECFailure; 		/* err set by AppendHandshake. */
+    }
 
     length = 1 + certTypesLength + 2 + calen;
     if (isTLS12) {
 	length += 2 + sigAlgsLength;
     }
 
     rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length);
     if (rv != SECSuccess) {
diff --git a/lib/ssl/ssl3prot.h b/lib/ssl/ssl3prot.h
--- a/lib/ssl/ssl3prot.h
+++ b/lib/ssl/ssl3prot.h
@@ -216,24 +216,24 @@ typedef struct {
         SSL3ServerRSAParams rsa;
     } u;
 } SSL3ServerParams;
 
 /* This enum reflects HashAlgorithm enum from
  * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
  *
  * When updating, be sure to also update ssl3_TLSHashAlgorithmToOID. */
-enum {
+typedef enum {
     tls_hash_md5 = 1,
     tls_hash_sha1 = 2,
     tls_hash_sha224 = 3,
     tls_hash_sha256 = 4,
     tls_hash_sha384 = 5,
     tls_hash_sha512 = 6
-};
+} TLSHashAlgoritm;
 
 /* This enum reflects SignatureAlgorithm enum from
  * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
 typedef enum {
     tls_sig_rsa = 1,
     tls_sig_dsa = 2,
     tls_sig_ecdsa = 3
 } TLSSignatureAlgorithm;
diff --git a/tests/ssl/ssl.sh b/tests/ssl/ssl.sh
--- a/tests/ssl/ssl.sh
+++ b/tests/ssl/ssl.sh
@@ -64,16 +64,17 @@ ssl_init()
   # Test case files
   if [ "${NSS_NO_SSL2}" = "1" ]; then
     SSLCOV=${QADIR}/ssl/sslcov.noSSL2orExport.txt
     SSLSTRESS=${QADIR}/ssl/sslstress.noSSL2orExport.txt
   else
     SSLCOV=${QADIR}/ssl/sslcov.txt
     SSLSTRESS=${QADIR}/ssl/sslstress.txt
   fi
+  SSLAUTH=${QADIR}/ssl/sslauth.txt
   REQUEST_FILE=${QADIR}/ssl/sslreq.dat
 
   #temparary files
   SERVEROUTFILE=${TMP}/tests_server.$$
   SERVERPID=${TMP}/tests_pid.$$
 
   R_SERVERPID=../tests_pid.$$
 
@@ -87,18 +88,18 @@ ssl_init()
   NORM_EXT=""
 
   if [ -z "$NSS_DISABLE_ECC" ] ; then
       ECC_STRING=" - with ECC"
   else
       ECC_STRING=""
   fi
 
-  CSHORT="-c ABCDEF:0016:0032:0033:0038:0039:003B:003C:003D:0040:0041:0067:006A:006B:0084:009C:009E:00A2cdefgijklmnvyz"
-  CLONG="-c ABCDEF:C001:C002:C003:C004:C005:C006:C007:C008:C009:C00A:C00B:C00C:C00D:C00E:C00F:C010:C011:C012:C013:C014:C023:C027:C02B:C02F:0016:0032:0033:0038:0039:003B:003C:003D:0040:0041:0067:006A:006B:0084:009C:009E:00A2cdefgijklmnvyz"
+  CSHORT="-c ABCDEF:0016:0032:0033:0038:0039:003B:003C:003D:0040:0041:0067:006A:006B:0084:009C:009D:009E:009F:00A2:00A3cdefgijklmnvyz"
+  CLONG="-c ABCDEF:C001:C002:C003:C004:C005:C006:C007:C008:C009:C00A:C00B:C00C:C00D:C00E:C00F:C010:C011:C012:C013:C014:C023:C024:C027:C028:C02B:C02C:C02F:C030:0016:0032:0033:0038:0039:003B:003C:003D:0040:0041:0067:006A:006B:0084:009C:009D:009E:009F:00A2:00A3cdefgijklmnvyz"
 
   if [ "${OS_ARCH}" != "WINNT" ]; then
       ulimit -n 1000 # make sure we have enough file descriptors
   fi
 
   cd ${CLIENTDIR}
 }
 
@@ -119,17 +120,17 @@ is_selfserv_alive()
   if [ "${OS_ARCH}" = "WINNT" ] && \
      [ "$OS_NAME" = "CYGWIN_NT" -o "$OS_NAME" = "MINGW32_NT" ]; then
       PID=${SHELL_SERVERPID}
   else
       PID=`cat ${SERVERPID}`
   fi
 
   echo "kill -0 ${PID} >/dev/null 2>/dev/null" 
-  if [[ "${NSS_NO_SSL2}" = "1" ] && [ -n ${EXP} -o -n ${SSL2} ]]; then
+  if [ "${NSS_NO_SSL2}" = "1" ] && [ -n ${EXP} -o -n ${SSL2} ]; then
   echo "No server to kill"
   else
   kill -0 ${PID} >/dev/null 2>/dev/null || Exit 10 "Fatal - selfserv process not detectable"
   fi
 
   echo "selfserv with PID ${PID} found at `date`"
 }
 
@@ -221,25 +222,26 @@ start_selfserv()
       ECC_OPTIONS=""
   fi
   if [ "$1" = "mixed" ]; then
       ECC_OPTIONS="-e ${HOSTADDR}-ecmixed"
   fi
   echo "selfserv starting at `date`"
   echo "selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} -n ${HOSTADDR} ${SERVER_OPTIONS} \\"
   echo "         ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss ${sparam} -i ${R_SERVERPID}\\"
-  echo "         $verbose -H 1 &"
+  echo "         $verbose -H 1 -V ssl3: &"
   if [ ${fileout} -eq 1 ]; then
       ${PROFTOOL} ${BINDIR}/selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} -n ${HOSTADDR} ${SERVER_OPTIONS} \
                ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss ${sparam} -i ${R_SERVERPID} $verbose -H 1 \
-               > ${SERVEROUTFILE} 2>&1 &
+               -V ssl3:> ${SERVEROUTFILE} 2>&1 &
       RET=$?
   else
       ${PROFTOOL} ${BINDIR}/selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} -n ${HOSTADDR} ${SERVER_OPTIONS} \
-               ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss ${sparam} -i ${R_SERVERPID} $verbose -H 1 &
+               ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss ${sparam} -i ${R_SERVERPID} $verbose -H 1 \
+               -V ssl3: &
       RET=$?
   fi
 
   # The PID $! returned by the MKS or Cygwin shell is not the PID of
   # the real background process, but rather the PID of a helper
   # process (sh.exe).  MKS's kill command has a bug: invoking kill
   # on the helper process does not terminate the real background
   # process.  Our workaround has been to have selfserv save its PID
diff --git a/tests/ssl/sslcov.txt b/tests/ssl/sslcov.txt
--- a/tests/ssl/sslcov.txt
+++ b/tests/ssl/sslcov.txt
@@ -171,9 +171,9 @@
    ECC   TLS12  :C014 TLS12_ECDHE_RSA_WITH_AES_256_CBC_SHA
    ECC   TLS12  :C023 TLS12_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
    ECC   TLS12  :C024 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
    ECC   TLS12  :C027 TLS12_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    ECC   TLS12  :C028 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
    ECC   TLS12  :C02B TLS12_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    ECC   TLS12  :C02C TLS12_ECDHE_ECDSA_WITH_AES_128_GCM_SHA384
    ECC   TLS12  :C02F TLS12_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-   ECC   TLS12  :0030 TLS12_ECDHE_RSA_WITH_AES_128_GCM_SHA384
+   ECC   TLS12  :C030 TLS12_ECDHE_RSA_WITH_AES_128_GCM_SHA384