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