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),