Blob Blame History Raw
diff -up ./lib/ssl/ssl3con.c.client_auth_prf ./lib/ssl/ssl3con.c
--- ./lib/ssl/ssl3con.c.client_auth_prf	2016-02-14 09:14:32.821182333 -0800
+++ ./lib/ssl/ssl3con.c	2016-02-14 09:52:47.506071502 -0800
@@ -270,6 +270,27 @@ static const /*SSL3ClientCertificateType
     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
+ *
+ * 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 */
 
 
@@ -4904,6 +4925,7 @@ ssl3_ComputeHandshakeHashes(sslSocket *
 	unsigned int  stateLen;
 	unsigned char stackBuf[1024];
 	unsigned char *stateBuf = NULL;
+    SECOidData *hashOid;
 
 	h = ss->ssl3.hs.sha;
 	stateBuf = PK11_SaveContextAlloc(h, stackBuf,
@@ -4919,9 +4941,25 @@ ssl3_ComputeHandshakeHashes(sslSocket *
 	    rv = SECFailure;
 	    goto tls12_loser;
 	}
-	/* If we ever support ciphersuites where the PRF hash isn't SHA-256
-	 * then this will need to be updated. */
-	hashes->hashAlg = ssl_hash_sha256;
+
+	/* updated in support of ciphersuites where the PRF hash
+     * could be SHA-256 or SHA-384 */
+    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 == ssl_hash_sha256 ||
+                hashes->hashAlg == ssl_hash_sha384);
+    if (hashes->hashAlg != ssl_hash_sha256 &&
+        hashes->hashAlg != ssl_hash_sha384) {
+        ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+        rv = SECFailure;
+        goto tls12_loser;
+    }
+
 	rv = SECSuccess;
 
 tls12_loser:
@@ -7242,7 +7280,7 @@ done:
 /* 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)
@@ -7251,9 +7289,12 @@ ssl3_DestroyBackupHandshakeHashIfNotNeed
     SSLSignType sigAlg;
     PRBool preferSha1;
     PRBool supportsSha1 = PR_FALSE;
-    PRBool supportsSha256 = PR_FALSE;
+    PRBool supportsHandshakeHash = PR_FALSE;
     PRBool needBackupHash = PR_FALSE;
     unsigned int i;
+    SECOidData *hashOid;
+    TLSHashAlgorithm suitePRFHash;
+    PRBool suitePRFIs256Or384 = PR_FALSE;
 
 #ifndef NO_PKCS11_BYPASS
     /* Backup handshake hash is not supported in PKCS #11 bypass mode. */
@@ -7270,20 +7311,35 @@ ssl3_DestroyBackupHandshakeHashIfNotNeed
 	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] == ssl_hash_sha1) {
 		supportsSha1 = PR_TRUE;
-	    } else if (algorithms->data[i] == ssl_hash_sha256) {
-		supportsSha256 = PR_TRUE;
+	    } else if (suitePRFIs256Or384 &&
+	               algorithms->data[i] == suitePRFHash) {
+		supportsHandshakeHash = 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)) {
+    if (supportsSha1 && (preferSha1 || !supportsHandshakeHash)) {
 	needBackupHash = PR_TRUE;
     }
 
@@ -9548,6 +9604,7 @@ ssl3_SendCertificateRequest(sslSocket *s
     int            certTypesLength;
     PRUint8        sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2];
     unsigned int   sigAlgsLength = 0;
+    SECOidData *hashOid;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake",
 		SSL_GETPID(), ss->fd));
@@ -9575,6 +9632,20 @@ ssl3_SendCertificateRequest(sslSocket *s
     certTypes       = certificate_types;
     certTypesLength = sizeof certificate_types;
 
+    hashOid = SECOID_FindOIDByMechanism(ssl3_GetPrfHashMechanism(ss));
+    if (hashOid == NULL) {
+	return SECFailure; 		/* err set by AppendHandshake. */
+    }
+    if (hashOid->offset == SEC_OID_SHA256) {
+	sigAlgsLength = sizeof supported_signature_algorithms_sha256;
+    PORT_Memcpy(sigAlgs, supported_signature_algorithms_sha256, sigAlgsLength);
+    } else if (hashOid->offset == SEC_OID_SHA384) {
+	sigAlgsLength = sizeof supported_signature_algorithms_sha384;
+    PORT_Memcpy(sigAlgs, supported_signature_algorithms_sha384, sigAlgsLength);
+    } else {
+	return SECFailure; 		/* err set by AppendHandshake. */
+    }
+
     length = 1 + certTypesLength + 2 + calen;
     if (isTLS12) {
         rv = ssl3_EncodeCertificateRequestSigAlgs(ss, sigAlgs, sizeof(sigAlgs),