Blame SOURCES/client_auth_for_sha384_prf_support.patch

1b6f66
diff -up ./lib/ssl/ssl3con.c.client_auth_prf ./lib/ssl/ssl3con.c
1b6f66
--- ./lib/ssl/ssl3con.c.client_auth_prf	2016-02-14 09:14:32.821182333 -0800
1b6f66
+++ ./lib/ssl/ssl3con.c	2016-02-14 09:52:47.506071502 -0800
1b6f66
@@ -270,6 +270,27 @@ static const /*SSL3ClientCertificateType
1b6f66
     ct_DSS_sign,
1b6f66
 };
1b6f66
 
1b6f66
+/* This block is the contents of the supported_signature_algorithms field of
1b6f66
+ * our TLS 1.2 CertificateRequest message, in wire format. See
1b6f66
+ * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
1b6f66
+ *
1b6f66
+ * We only support TLS 1.2
1b6f66
+ * CertificateVerify messages that use the handshake PRF hash. */
1b6f66
+static const PRUint8 supported_signature_algorithms_sha256[] = {
1b6f66
+    tls_hash_sha256, tls_sig_rsa,
1b6f66
+#ifndef NSS_DISABLE_ECC
1b6f66
+    tls_hash_sha256, tls_sig_ecdsa,
1b6f66
+#endif
1b6f66
+    tls_hash_sha256, tls_sig_dsa,
1b6f66
+};
1b6f66
+static const PRUint8 supported_signature_algorithms_sha384[] = {
1b6f66
+    tls_hash_sha384, tls_sig_rsa,
1b6f66
+#ifndef NSS_DISABLE_ECC
1b6f66
+    tls_hash_sha384, tls_sig_ecdsa,
1b6f66
+#endif
1b6f66
+    tls_hash_sha384, tls_sig_dsa,
1b6f66
+};
1b6f66
+
1b6f66
 #define EXPORT_RSA_KEY_LENGTH 64	/* bytes */
1b6f66
 
1b6f66
 
1b6f66
@@ -4904,6 +4925,7 @@ ssl3_ComputeHandshakeHashes(sslSocket *
1b6f66
 	unsigned int  stateLen;
1b6f66
 	unsigned char stackBuf[1024];
1b6f66
 	unsigned char *stateBuf = NULL;
1b6f66
+    SECOidData *hashOid;
1b6f66
 
1b6f66
 	h = ss->ssl3.hs.sha;
1b6f66
 	stateBuf = PK11_SaveContextAlloc(h, stackBuf,
1b6f66
@@ -4919,9 +4941,25 @@ ssl3_ComputeHandshakeHashes(sslSocket *
1b6f66
 	    rv = SECFailure;
1b6f66
 	    goto tls12_loser;
1b6f66
 	}
1b6f66
-	/* If we ever support ciphersuites where the PRF hash isn't SHA-256
1b6f66
-	 * then this will need to be updated. */
1b6f66
-	hashes->hashAlg = ssl_hash_sha256;
1b6f66
+
1b6f66
+	/* updated in support of ciphersuites where the PRF hash
1b6f66
+     * could be SHA-256 or SHA-384 */
1b6f66
+    hashOid = SECOID_FindOIDByMechanism(ssl3_GetPrfHashMechanism(ss));
1b6f66
+    if (hashOid == NULL) {
1b6f66
+        ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
1b6f66
+        rv = SECFailure;
1b6f66
+        goto tls12_loser;
1b6f66
+    }
1b6f66
+    hashes->hashAlg = hashOid->offset;
1b6f66
+    PORT_Assert(hashes->hashAlg == ssl_hash_sha256 ||
1b6f66
+                hashes->hashAlg == ssl_hash_sha384);
1b6f66
+    if (hashes->hashAlg != ssl_hash_sha256 &&
1b6f66
+        hashes->hashAlg != ssl_hash_sha384) {
1b6f66
+        ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
1b6f66
+        rv = SECFailure;
1b6f66
+        goto tls12_loser;
1b6f66
+    }
1b6f66
+
1b6f66
 	rv = SECSuccess;
1b6f66
 
1b6f66
 tls12_loser:
1b6f66
@@ -7242,7 +7280,7 @@ done:
1b6f66
 /* Destroys the backup handshake hash context if we don't need it. Note that
1b6f66
  * this function selects the hash algorithm for client authentication
1b6f66
  * signatures; ssl3_SendCertificateVerify uses the presence of the backup hash
1b6f66
- * to determine whether to use SHA-1 or SHA-256. */
1b6f66
+ * to determine whether to use SHA-1, or the PRF hash of the cipher suite. */
1b6f66
 static void
1b6f66
 ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
1b6f66
 					   const SECItem *algorithms)
1b6f66
@@ -7251,9 +7289,12 @@ ssl3_DestroyBackupHandshakeHashIfNotNeed
1b6f66
     SSLSignType sigAlg;
1b6f66
     PRBool preferSha1;
1b6f66
     PRBool supportsSha1 = PR_FALSE;
1b6f66
-    PRBool supportsSha256 = PR_FALSE;
1b6f66
+    PRBool supportsHandshakeHash = PR_FALSE;
1b6f66
     PRBool needBackupHash = PR_FALSE;
1b6f66
     unsigned int i;
1b6f66
+    SECOidData *hashOid;
1b6f66
+    TLSHashAlgorithm suitePRFHash;
1b6f66
+    PRBool suitePRFIs256Or384 = PR_FALSE;
1b6f66
 
1b6f66
 #ifndef NO_PKCS11_BYPASS
1b6f66
     /* Backup handshake hash is not supported in PKCS #11 bypass mode. */
1b6f66
@@ -7270,20 +7311,35 @@ ssl3_DestroyBackupHandshakeHashIfNotNeed
1b6f66
 	goto done;
1b6f66
     }
1b6f66
 
1b6f66
+    hashOid = SECOID_FindOIDByMechanism(ssl3_GetPrfHashMechanism(ss));
1b6f66
+    if (hashOid == NULL) {
1b6f66
+        rv = SECFailure;
1b6f66
+	goto done;
1b6f66
+    }
1b6f66
+
1b6f66
+    if (hashOid->offset == SEC_OID_SHA256) {
1b6f66
+	suitePRFHash = tls_hash_sha256;
1b6f66
+	suitePRFIs256Or384 = PR_TRUE;
1b6f66
+    } else if (hashOid->offset == SEC_OID_SHA384) {
1b6f66
+	suitePRFHash = tls_hash_sha384;
1b6f66
+	suitePRFIs256Or384 = PR_TRUE;
1b6f66
+    } 
1b6f66
+
1b6f66
     /* Determine the server's hash support for that signature algorithm. */
1b6f66
     for (i = 0; i < algorithms->len; i += 2) {
1b6f66
 	if (algorithms->data[i+1] == sigAlg) {
1b6f66
 	    if (algorithms->data[i] == ssl_hash_sha1) {
1b6f66
 		supportsSha1 = PR_TRUE;
1b6f66
-	    } else if (algorithms->data[i] == ssl_hash_sha256) {
1b6f66
-		supportsSha256 = PR_TRUE;
1b6f66
+	    } else if (suitePRFIs256Or384 &&
1b6f66
+	               algorithms->data[i] == suitePRFHash) {
1b6f66
+		supportsHandshakeHash = PR_TRUE;
1b6f66
 	    }
1b6f66
 	}
1b6f66
     }
1b6f66
 
1b6f66
     /* If either the server does not support SHA-256 or the client key prefers
1b6f66
      * SHA-1, leave the backup hash. */
1b6f66
-    if (supportsSha1 && (preferSha1 || !supportsSha256)) {
1b6f66
+    if (supportsSha1 && (preferSha1 || !supportsHandshakeHash)) {
1b6f66
 	needBackupHash = PR_TRUE;
1b6f66
     }
1b6f66
 
1b6f66
@@ -9548,6 +9604,7 @@ ssl3_SendCertificateRequest(sslSocket *s
1b6f66
     int            certTypesLength;
1b6f66
     PRUint8        sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2];
1b6f66
     unsigned int   sigAlgsLength = 0;
1b6f66
+    SECOidData *hashOid;
1b6f66
 
1b6f66
     SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake",
1b6f66
 		SSL_GETPID(), ss->fd));
1b6f66
@@ -9575,6 +9632,20 @@ ssl3_SendCertificateRequest(sslSocket *s
1b6f66
     certTypes       = certificate_types;
1b6f66
     certTypesLength = sizeof certificate_types;
1b6f66
 
1b6f66
+    hashOid = SECOID_FindOIDByMechanism(ssl3_GetPrfHashMechanism(ss));
1b6f66
+    if (hashOid == NULL) {
1b6f66
+	return SECFailure; 		/* err set by AppendHandshake. */
1b6f66
+    }
1b6f66
+    if (hashOid->offset == SEC_OID_SHA256) {
1b6f66
+	sigAlgsLength = sizeof supported_signature_algorithms_sha256;
1b6f66
+    PORT_Memcpy(sigAlgs, supported_signature_algorithms_sha256, sigAlgsLength);
1b6f66
+    } else if (hashOid->offset == SEC_OID_SHA384) {
1b6f66
+	sigAlgsLength = sizeof supported_signature_algorithms_sha384;
1b6f66
+    PORT_Memcpy(sigAlgs, supported_signature_algorithms_sha384, sigAlgsLength);
1b6f66
+    } else {
1b6f66
+	return SECFailure; 		/* err set by AppendHandshake. */
1b6f66
+    }
1b6f66
+
1b6f66
     length = 1 + certTypesLength + 2 + calen;
1b6f66
     if (isTLS12) {
1b6f66
         rv = ssl3_EncodeCertificateRequestSigAlgs(ss, sigAlgs, sizeof(sigAlgs),