Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(362)

Unified Diff: net/third_party/nss/ssl/ssl3con.c

Issue 1511123006: Uprev NSS (in libssl) to NSS 3.21 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updated deps Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/third_party/nss/ssl/ssl.h ('k') | net/third_party/nss/ssl/ssl3ecc.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/third_party/nss/ssl/ssl3con.c
diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
index 02b0ddaf9f1d3d049a5d7e0b24b3f339925f1d6c..e5e620fd34cfc87a1ba9a24ddf22b3c095fe5ed7 100644
--- a/net/third_party/nss/ssl/ssl3con.c
+++ b/net/third_party/nss/ssl/ssl3con.c
@@ -25,6 +25,8 @@
#include "prerror.h"
#include "pratom.h"
#include "prthread.h"
+#include "nss.h"
+#include "nssoptions.h"
#include "pk11func.h"
#include "secmod.h"
@@ -91,8 +93,11 @@ static SECStatus ssl3_SendServerKeyExchange( sslSocket *ss);
static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss,
const unsigned char *b,
unsigned int l);
+static SECStatus ssl3_ComputeHandshakeHashes(sslSocket *ss,
+ ssl3CipherSpec *spec,
+ SSL3Hashes *hashes,
+ PRUint32 sender);
static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
-static int ssl3_OIDToTLSHashAlgorithm(SECOidTag oid);
static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
int maxOutputLen, const unsigned char *input,
@@ -122,17 +127,17 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
#ifndef NSS_DISABLE_ECC
{ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
+ { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
/* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is out of order to work around
* bug 946147.
*/
- { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
+ { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
@@ -140,14 +145,17 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
#endif /* NSS_DISABLE_ECC */
{ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
@@ -205,6 +213,23 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
{ TLS_RSA_WITH_NULL_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE},
};
+static const SSLSignatureAndHashAlg defaultSignatureAlgorithms[] = {
+ {ssl_hash_sha256, ssl_sign_rsa},
+ {ssl_hash_sha384, ssl_sign_rsa},
+ {ssl_hash_sha512, ssl_sign_rsa},
+ {ssl_hash_sha1, ssl_sign_rsa},
+#ifndef NSS_DISABLE_ECC
+ {ssl_hash_sha256, ssl_sign_ecdsa},
+ {ssl_hash_sha384, ssl_sign_ecdsa},
+ {ssl_hash_sha512, ssl_sign_ecdsa},
+ {ssl_hash_sha1, ssl_sign_ecdsa},
+#endif
+ {ssl_hash_sha256, ssl_sign_dsa},
+ {ssl_hash_sha1, ssl_sign_dsa}
+};
+PR_STATIC_ASSERT(PR_ARRAY_SIZE(defaultSignatureAlgorithms) <=
+ MAX_SIGNATURE_ALGORITHMS);
+
/* Verify that SSL_ImplementedCiphers and cipherSuites are in consistent order.
*/
#ifdef DEBUG
@@ -265,20 +290,6 @@ static const /*SSL3ClientCertificateType */ PRUint8 certificate_types [] = {
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[] = {
- tls_hash_sha256, tls_sig_rsa,
-#ifndef NSS_DISABLE_ECC
- tls_hash_sha256, tls_sig_ecdsa,
-#endif
- tls_hash_sha256, tls_sig_dsa,
-};
-
#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
@@ -322,8 +333,8 @@ static const ssl3KEADef kea_defs[] =
/* kea exchKeyType signKeyType is_limited limit tls_keygen ephemeral */
{kea_null, kt_null, sign_null, PR_FALSE, 0, PR_FALSE, PR_FALSE},
{kea_rsa, kt_rsa, sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE},
- {kea_rsa_export, kt_rsa, sign_rsa, PR_TRUE, 512, PR_FALSE, PR_TRUE},
- {kea_rsa_export_1024,kt_rsa, sign_rsa, PR_TRUE, 1024, PR_FALSE, PR_TRUE},
+ {kea_rsa_export, kt_rsa, sign_rsa, PR_TRUE, 512, PR_FALSE, PR_FALSE},
+ {kea_rsa_export_1024,kt_rsa, sign_rsa, PR_TRUE, 1024, PR_FALSE, PR_FALSE},
{kea_dh_dss, kt_dh, sign_dsa, PR_FALSE, 0, PR_FALSE, PR_FALSE},
{kea_dh_dss_export, kt_dh, sign_dsa, PR_TRUE, 512, PR_FALSE, PR_FALSE},
{kea_dh_rsa, kt_dh, sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE},
@@ -443,6 +454,10 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] =
{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, cipher_chacha20, mac_aead, kea_ecdhe_rsa},
{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, cipher_chacha20, mac_aead, kea_ecdhe_ecdsa},
+ {TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_dss},
+ {TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_dhe_dss},
+ {TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, cipher_aes_256, hmac_sha256, kea_dhe_dss},
+
#ifndef NSS_DISABLE_ECC
{TLS_ECDH_ECDSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdh_ecdsa},
{TLS_ECDH_ECDSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdh_ecdsa},
@@ -680,6 +695,8 @@ ssl3_CipherSuiteAllowedForVersionRange(
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
case TLS_RSA_WITH_AES_128_CBC_SHA256:
case TLS_RSA_WITH_AES_128_GCM_SHA256:
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
case TLS_RSA_WITH_NULL_SHA256:
return vrange->max == SSL_LIBRARY_VERSION_TLS_1_2;
@@ -688,6 +705,7 @@ ssl3_CipherSuiteAllowedForVersionRange(
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2;
/* RFC 4492: ECC cipher suites need TLS extensions to negotiate curves and
@@ -810,16 +828,11 @@ ssl3_config_match_init(sslSocket *ss)
* that the server uses an RSA cert for (EC)DHE-RSA.
*/
switch (cipher_def->key_exchange_alg) {
+ case kea_dhe_dss:
+ svrAuth = ss->serverCerts + ssl_kea_dh;
+ break;
case kea_ecdhe_rsa:
-#if NSS_SERVER_DHE_IMPLEMENTED
- /* XXX NSS does not yet implement the server side of _DHE_
- * cipher suites. Correcting the computation for svrAuth,
- * as the case below does, causes NSS SSL servers to begin to
- * negotiate cipher suites they do not implement. So, until
- * server side _DHE_ is implemented, keep this disabled.
- */
case kea_dhe_rsa:
-#endif
svrAuth = ss->serverCerts + kt_rsa;
break;
case kea_ecdh_ecdsa:
@@ -831,6 +844,8 @@ ssl3_config_match_init(sslSocket *ss)
* simultaneously. For now, both of them use
* whatever is in the certificate slot for kt_ecdh
*/
+ case kea_dhe_dss_export:
+ case kea_dhe_rsa_export:
default:
svrAuth = ss->serverCerts + exchKeyType;
break;
@@ -867,11 +882,22 @@ ssl3_config_match_init(sslSocket *ss)
* cipher suite. */
static PRBool
config_match(ssl3CipherSuiteCfg *suite, int policy, PRBool enabled,
- const SSLVersionRange *vrange)
+ const SSLVersionRange *vrange, const sslSocket *ss)
{
+ const ssl3CipherSuiteDef *cipher_def;
+
PORT_Assert(policy != SSL_NOT_ALLOWED && enabled != PR_FALSE);
if (policy == SSL_NOT_ALLOWED || !enabled)
- return PR_FALSE;
+ return PR_FALSE;
+
+ cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
+ PORT_Assert(cipher_def != NULL);
+
+ PORT_Assert(ss != NULL);
+ if (ss->sec.isServer && !ss->opt.enableServerDhe &&
+ kea_defs[cipher_def->key_exchange_alg].exchKeyType == ssl_kea_dh)
+ return PR_FALSE;
+
return (PRBool)(suite->enabled &&
suite->isPresent &&
suite->policy != SSL_NOT_ALLOWED &&
@@ -892,7 +918,7 @@ count_cipher_suites(sslSocket *ss, int policy, PRBool enabled)
return 0;
}
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
- if (config_match(&ss->cipherSuites[i], policy, enabled, &ss->vrange))
+ if (config_match(&ss->cipherSuites[i], policy, enabled, &ss->vrange, ss))
count++;
}
if (count <= 0) {
@@ -984,9 +1010,9 @@ ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
break;
case dsaKey:
doDerEncode = isTLS;
- /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash.
+ /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
* In that case, we use just the SHA1 part. */
- if (hash->hashAlg == SEC_OID_UNKNOWN) {
+ if (hash->hashAlg == ssl_hash_none) {
hashItem.data = hash->u.s.sha;
hashItem.len = sizeof(hash->u.s.sha);
} else {
@@ -997,9 +1023,9 @@ ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
#ifndef NSS_DISABLE_ECC
case ecKey:
doDerEncode = PR_TRUE;
- /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash.
+ /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
* In that case, we use just the SHA1 part. */
- if (hash->hashAlg == SEC_OID_UNKNOWN) {
+ if (hash->hashAlg == ssl_hash_none) {
hashItem.data = hash->u.s.sha;
hashItem.len = sizeof(hash->u.s.sha);
} else {
@@ -1014,7 +1040,7 @@ ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
}
PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
- if (hash->hashAlg == SEC_OID_UNKNOWN) {
+ if (hash->hashAlg == ssl_hash_none) {
signatureLen = PK11_SignatureLen(key);
if (signatureLen <= 0) {
PORT_SetError(SEC_ERROR_INVALID_KEY);
@@ -1028,7 +1054,8 @@ ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
rv = PK11_Sign(key, buf, &hashItem);
} else {
- rv = SGN_Digest(key, hash->hashAlg, buf, &hashItem);
+ SECOidTag hashOID = ssl3_TLSHashAlgorithmToOID(hash->hashAlg);
+ rv = SGN_Digest(key, hashOID, buf, &hashItem);
}
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
@@ -1076,7 +1103,7 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
return SECFailure;
}
- hashAlg = hash->hashAlg;
+ hashAlg = ssl3_TLSHashAlgorithmToOID(hash->hashAlg);
switch (key->keyType) {
case rsaKey:
encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
@@ -1085,9 +1112,9 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
break;
case dsaKey:
encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE;
- /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash.
+ /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
* In that case, we use just the SHA1 part. */
- if (hash->hashAlg == SEC_OID_UNKNOWN) {
+ if (hash->hashAlg == ssl_hash_none) {
hashItem.data = hash->u.s.sha;
hashItem.len = sizeof(hash->u.s.sha);
} else {
@@ -1108,13 +1135,13 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
#ifndef NSS_DISABLE_ECC
case ecKey:
encAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
- /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash.
+ /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
* In that case, we use just the SHA1 part.
* ECDSA signatures always encode the integers r and s using ASN.1
* (unlike DSA where ASN.1 encoding is used with TLS but not with
* SSL3). So we can use VFY_VerifyDigestDirect for ECDSA.
*/
- if (hash->hashAlg == SEC_OID_UNKNOWN) {
+ if (hash->hashAlg == ssl_hash_none) {
hashAlg = SEC_OID_SHA1;
hashItem.data = hash->u.s.sha;
hashItem.len = sizeof(hash->u.s.sha);
@@ -1142,8 +1169,8 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
*/
rv = PK11_Verify(key, buf, &hashItem, pwArg);
} else {
- rv = VFY_VerifyDigestDirect(&hashItem, key, buf, encAlg, hashAlg,
- pwArg);
+ rv = VFY_VerifyDigestDirect(&hashItem, key, buf, encAlg, hashAlg,
+ pwArg);
}
SECKEY_DestroyPublicKey(key);
if (signature) {
@@ -1159,75 +1186,71 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
/* Caller must set hiLevel error code. */
/* Called from ssl3_ComputeExportRSAKeyHash
* ssl3_ComputeDHKeyHash
- * which are called from ssl3_HandleServerKeyExchange.
+ * which are called from ssl3_HandleServerKeyExchange.
*
- * hashAlg: either the OID for a hash algorithm or SEC_OID_UNKNOWN to specify
- * the pre-1.2, MD5/SHA1 combination hash.
+ * hashAlg: ssl_hash_none indicates the pre-1.2, MD5/SHA1 combination hash.
*/
SECStatus
-ssl3_ComputeCommonKeyHash(SECOidTag hashAlg,
- PRUint8 * hashBuf, unsigned int bufLen,
- SSL3Hashes *hashes, PRBool bypassPKCS11)
+ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
+ PRUint8 * hashBuf, unsigned int bufLen,
+ SSL3Hashes *hashes, PRBool bypassPKCS11)
{
- SECStatus rv = SECSuccess;
+ SECStatus rv;
+ SECOidTag hashOID;
#ifndef NO_PKCS11_BYPASS
if (bypassPKCS11) {
- if (hashAlg == SEC_OID_UNKNOWN) {
- MD5_HashBuf (hashes->u.s.md5, hashBuf, bufLen);
- SHA1_HashBuf(hashes->u.s.sha, hashBuf, bufLen);
- hashes->len = MD5_LENGTH + SHA1_LENGTH;
- } else if (hashAlg == SEC_OID_SHA1) {
- SHA1_HashBuf(hashes->u.raw, hashBuf, bufLen);
- hashes->len = SHA1_LENGTH;
- } else if (hashAlg == SEC_OID_SHA256) {
- SHA256_HashBuf(hashes->u.raw, hashBuf, bufLen);
- hashes->len = SHA256_LENGTH;
- } else if (hashAlg == SEC_OID_SHA384) {
- SHA384_HashBuf(hashes->u.raw, hashBuf, bufLen);
- hashes->len = SHA384_LENGTH;
- } else if (hashAlg == SEC_OID_SHA512) {
- SHA512_HashBuf(hashes->u.raw, hashBuf, bufLen);
- hashes->len = SHA512_LENGTH;
- } else {
- PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
- return SECFailure;
- }
- } else
+ if (hashAlg == ssl_hash_none) {
+ MD5_HashBuf (hashes->u.s.md5, hashBuf, bufLen);
+ SHA1_HashBuf(hashes->u.s.sha, hashBuf, bufLen);
+ hashes->len = MD5_LENGTH + SHA1_LENGTH;
+ } else if (hashAlg == ssl_hash_sha1) {
+ SHA1_HashBuf(hashes->u.raw, hashBuf, bufLen);
+ hashes->len = SHA1_LENGTH;
+ } else if (hashAlg == ssl_hash_sha256) {
+ SHA256_HashBuf(hashes->u.raw, hashBuf, bufLen);
+ hashes->len = SHA256_LENGTH;
+ } else if (hashAlg == ssl_hash_sha384) {
+ SHA384_HashBuf(hashes->u.raw, hashBuf, bufLen);
+ hashes->len = SHA384_LENGTH;
+ } else if (hashAlg == ssl_hash_sha512) {
+ SHA512_HashBuf(hashes->u.raw, hashBuf, bufLen);
+ hashes->len = SHA512_LENGTH;
+ } else {
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
+ return SECFailure;
+ }
+ } else
#endif
{
- if (hashAlg == SEC_OID_UNKNOWN) {
- rv = PK11_HashBuf(SEC_OID_MD5, hashes->u.s.md5, hashBuf, bufLen);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- rv = SECFailure;
- goto done;
- }
-
- rv = PK11_HashBuf(SEC_OID_SHA1, hashes->u.s.sha, hashBuf, bufLen);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- rv = SECFailure;
- }
- hashes->len = MD5_LENGTH + SHA1_LENGTH;
- } else {
- hashes->len = HASH_ResultLenByOidTag(hashAlg);
- if (hashes->len > sizeof(hashes->u.raw)) {
- ssl_MapLowLevelError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
- rv = SECFailure;
- goto done;
- }
- rv = PK11_HashBuf(hashAlg, hashes->u.raw, hashBuf, bufLen);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
- rv = SECFailure;
- }
- }
+ if (hashAlg == ssl_hash_none) {
+ rv = PK11_HashBuf(SEC_OID_MD5, hashes->u.s.md5, hashBuf, bufLen);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ return rv;
+ }
+ rv = PK11_HashBuf(SEC_OID_SHA1, hashes->u.s.sha, hashBuf, bufLen);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return rv;
+ }
+ hashes->len = MD5_LENGTH + SHA1_LENGTH;
+ } else {
+ hashOID = ssl3_TLSHashAlgorithmToOID(hashAlg);
+ hashes->len = HASH_ResultLenByOidTag(hashOID);
+ if (hashes->len == 0 || hashes->len > sizeof(hashes->u.raw)) {
+ ssl_MapLowLevelError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
+ return SECFailure;
+ }
+ rv = PK11_HashBuf(hashOID, hashes->u.raw, hashBuf, bufLen);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+ return rv;
+ }
+ }
}
hashes->hashAlg = hashAlg;
-
-done:
- return rv;
+ return SECSuccess;
}
/* Caller must set hiLevel error code.
@@ -1235,10 +1258,10 @@ done:
** ssl3_HandleServerKeyExchange.
*/
static SECStatus
-ssl3_ComputeExportRSAKeyHash(SECOidTag hashAlg,
- SECItem modulus, SECItem publicExponent,
- SSL3Random *client_rand, SSL3Random *server_rand,
- SSL3Hashes *hashes, PRBool bypassPKCS11)
+ssl3_ComputeExportRSAKeyHash(SSLHashType hashAlg,
+ SECItem modulus, SECItem publicExponent,
+ SSL3Random *client_rand, SSL3Random *server_rand,
+ SSL3Hashes *hashes, PRBool bypassPKCS11)
{
PRUint8 * hashBuf;
PRUint8 * pBuf;
@@ -1276,7 +1299,7 @@ ssl3_ComputeExportRSAKeyHash(SECOidTag hashAlg,
bypassPKCS11);
PRINT_BUF(95, (NULL, "RSAkey hash: ", hashBuf, bufLen));
- if (hashAlg == SEC_OID_UNKNOWN) {
+ if (hashAlg == ssl_hash_none) {
PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result",
hashes->u.s.md5, MD5_LENGTH));
PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result",
@@ -1294,10 +1317,10 @@ ssl3_ComputeExportRSAKeyHash(SECOidTag hashAlg,
/* Caller must set hiLevel error code. */
/* Called from ssl3_HandleServerKeyExchange. */
static SECStatus
-ssl3_ComputeDHKeyHash(SECOidTag hashAlg,
- SECItem dh_p, SECItem dh_g, SECItem dh_Ys,
- SSL3Random *client_rand, SSL3Random *server_rand,
- SSL3Hashes *hashes, PRBool bypassPKCS11)
+ssl3_ComputeDHKeyHash(SSLHashType hashAlg,
+ SECItem dh_p, SECItem dh_g, SECItem dh_Ys,
+ SSL3Random *client_rand, SSL3Random *server_rand,
+ SSL3Hashes *hashes, PRBool bypassPKCS11)
{
PRUint8 * hashBuf;
PRUint8 * pBuf;
@@ -1340,7 +1363,7 @@ ssl3_ComputeDHKeyHash(SECOidTag hashAlg,
bypassPKCS11);
PRINT_BUF(95, (NULL, "DHkey hash: ", hashBuf, bufLen));
- if (hashAlg == SEC_OID_UNKNOWN) {
+ if (hashAlg == ssl_hash_none) {
PRINT_BUF(95, (NULL, "DHkey hash: MD5 result",
hashes->u.s.md5, MD5_LENGTH));
PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result",
@@ -2298,7 +2321,11 @@ fail:
* Sets error code, but caller probably should override to disambiguate.
* NULL pms means re-use old master_secret.
*
- * This code is common to the bypass and PKCS11 execution paths.
+ * This code is common to the bypass and PKCS11 execution paths. For
+ * the bypass case, pms is NULL. If the old master secret is reused,
+ * pms is NULL and the master secret is already in either
+ * pwSpec->msItem.len (the bypass case) or pwSpec->master_secret.
+ *
* For the bypass case, pms is NULL.
*/
SECStatus
@@ -2682,7 +2709,7 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
PRUint32 fragLen;
PRUint32 p1Len, p2Len, oddLen = 0;
PRUint16 headerLen;
- int ivLen = 0;
+ unsigned int ivLen = 0;
int cipherBytes = 0;
unsigned char pseudoHeader[13];
unsigned int pseudoHeaderLen;
@@ -3244,7 +3271,8 @@ ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
{
static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER |
ssl_SEND_FLAG_CAP_RECORD_VERSION;
- PRInt32 rv = SECSuccess;
+ PRInt32 count = -1;
+ SECStatus rv = SECSuccess;
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
@@ -3258,18 +3286,19 @@ ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
} else {
- rv = ssl3_SendRecord(ss, 0, content_handshake, ss->sec.ci.sendBuf.buf,
+ count = ssl3_SendRecord(ss, 0, content_handshake, ss->sec.ci.sendBuf.buf,
ss->sec.ci.sendBuf.len, flags);
}
- if (rv < 0) {
+ if (count < 0) {
int err = PORT_GetError();
PORT_Assert(err != PR_WOULD_BLOCK_ERROR);
if (err == PR_WOULD_BLOCK_ERROR) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
}
- } else if (rv < ss->sec.ci.sendBuf.len) {
+ rv = SECFailure;
+ } else if ((unsigned int)count < ss->sec.ci.sendBuf.len) {
/* short write should never happen */
- PORT_Assert(rv >= ss->sec.ci.sendBuf.len);
+ PORT_Assert((unsigned int)count >= ss->sec.ci.sendBuf.len);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
rv = SECFailure;
} else {
@@ -3705,13 +3734,70 @@ ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf)
return SECSuccess;
}
-/* This method uses PKCS11 to derive the MS from the PMS, where PMS
-** is a PKCS11 symkey. This is used in all cases except the
-** "triple bypass" with RSA key exchange.
-** Called from ssl3_InitPendingCipherSpec. prSpec is pwSpec.
+/* This method completes the derivation of the MS from the PMS.
+**
+** 1. Derive the MS, if possible, else return an error.
+**
+** 2. Check the version if |pms_version| is non-zero and if wrong,
+** return an error.
+**
+** 3. If |msp| is nonzero, return MS in |*msp|.
+
+** Called from:
+** ssl3_ComputeMasterSecretInt
+** tls_ComputeExtendedMasterSecretInt
*/
static SECStatus
-ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
+ssl3_ComputeMasterSecretFinish(sslSocket *ss,
+ CK_MECHANISM_TYPE master_derive,
+ CK_MECHANISM_TYPE key_derive,
+ CK_VERSION *pms_version,
+ SECItem *params, CK_FLAGS keyFlags,
+ PK11SymKey *pms, PK11SymKey **msp)
+{
+ PK11SymKey *ms = NULL;
+
+ ms = PK11_DeriveWithFlags(pms, master_derive,
+ params, key_derive,
+ CKA_DERIVE, 0, keyFlags);
+ if (!ms) {
+ ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ return SECFailure;
+ }
+
+ if (pms_version && ss->opt.detectRollBack) {
+ SSL3ProtocolVersion client_version;
+ client_version = pms_version->major << 8 | pms_version->minor;
+
+ if (IS_DTLS(ss)) {
+ client_version = dtls_DTLSVersionToTLSVersion(client_version);
+ }
+
+ if (client_version != ss->clientHelloVersion) {
+ /* Destroy MS. Version roll-back detected. */
+ PK11_FreeSymKey(ms);
+ ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ return SECFailure;
+ }
+ }
+
+ if (msp) {
+ *msp = ms;
+ } else {
+ PK11_FreeSymKey(ms);
+ }
+
+ return SECSuccess;
+}
+
+/* Compute the ordinary (pre draft-ietf-tls-session-hash) master
+ ** secret and return it in |*msp|.
+ **
+ ** Called from: ssl3_ComputeMasterSecret
+ */
+static SECStatus
+ssl3_ComputeMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
+ PK11SymKey **msp)
{
ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec;
const ssl3KEADef *kea_def= ss->ssl3.hs.kea_def;
@@ -3721,28 +3807,27 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
(pwSpec->version > SSL_LIBRARY_VERSION_3_0));
PRBool isTLS12=
(PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
- /*
+ /*
* Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH
* which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size
- * data into a 48-byte value.
+ * data into a 48-byte value, and does not expect to return the version.
*/
PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
(ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
- SECStatus rv = SECFailure;
CK_MECHANISM_TYPE master_derive;
CK_MECHANISM_TYPE key_derive;
SECItem params;
CK_FLAGS keyFlags;
CK_VERSION pms_version;
- CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;
+ CK_VERSION *pms_version_ptr = NULL;
+ /* master_params may be used as a CK_SSL3_MASTER_KEY_DERIVE_PARAMS */
+ CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
+ unsigned int master_params_len;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
- PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
if (isTLS12) {
- if(isDH) master_derive = CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256;
- else master_derive = CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256;
- key_derive = CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256;
+ if(isDH) master_derive = CKM_TLS12_MASTER_KEY_DERIVE_DH;
+ else master_derive = CKM_TLS12_MASTER_KEY_DERIVE;
+ key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
keyFlags = CKF_SIGN | CKF_VERIFY;
} else if (isTLS) {
if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
@@ -3756,87 +3841,142 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
keyFlags = 0;
}
- if (pms || !pwSpec->master_secret) {
- if (isDH) {
- master_params.pVersion = NULL;
- } else {
- master_params.pVersion = &pms_version;
- }
- master_params.RandomInfo.pClientRandom = cr;
- master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
- master_params.RandomInfo.pServerRandom = sr;
- master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
+ if (!isDH) {
+ pms_version_ptr = &pms_version;
+ }
- params.data = (unsigned char *) &master_params;
- params.len = sizeof master_params;
+ master_params.pVersion = pms_version_ptr;
+ master_params.RandomInfo.pClientRandom = cr;
+ master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
+ master_params.RandomInfo.pServerRandom = sr;
+ master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
+ if (isTLS12) {
+ master_params.prfHashMechanism = CKM_SHA256;
+ master_params_len = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS);
+ } else {
+ /* prfHashMechanism is not relevant with this PRF */
+ master_params_len = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
}
- if (pms != NULL) {
-#if defined(TRACE)
- if (ssl_trace >= 100) {
- SECStatus extractRV = PK11_ExtractKeyValue(pms);
- if (extractRV == SECSuccess) {
- SECItem * keyData = PK11_GetKeyData(pms);
- if (keyData && keyData->data && keyData->len) {
- ssl_PrintBuf(ss, "Pre-Master Secret",
- keyData->data, keyData->len);
- }
- }
- }
-#endif
- pwSpec->master_secret = PK11_DeriveWithFlags(pms, master_derive,
- &params, key_derive, CKA_DERIVE, 0, keyFlags);
- if (!isDH && pwSpec->master_secret && ss->opt.detectRollBack) {
- SSL3ProtocolVersion client_version;
- client_version = pms_version.major << 8 | pms_version.minor;
+ params.data = (unsigned char *) &master_params;
+ params.len = master_params_len;
- if (IS_DTLS(ss)) {
- client_version = dtls_DTLSVersionToTLSVersion(client_version);
- }
+ return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive,
+ pms_version_ptr, &params,
+ keyFlags, pms, msp);
+}
- if (client_version != ss->clientHelloVersion) {
- /* Destroy it. Version roll-back detected. */
- PK11_FreeSymKey(pwSpec->master_secret);
- pwSpec->master_secret = NULL;
- }
- }
- if (pwSpec->master_secret == NULL) {
- /* Generate a faux master secret in the same slot as the old one. */
- PK11SlotInfo * slot = PK11_GetSlotFromKey((PK11SymKey *)pms);
- PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot);
+/* Compute the draft-ietf-tls-session-hash master
+** secret and return it in |*msp|.
+**
+** Called from: ssl3_ComputeMasterSecret
+*/
+static SECStatus
+tls_ComputeExtendedMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
+ PK11SymKey **msp)
+{
+ ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
+ CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS extended_master_params;
+ SSL3Hashes hashes;
+ /*
+ * Determine whether to use the DH/ECDH or RSA derivation modes.
+ */
+ /*
+ * TODO(ekr@rtfm.com): Verify that the slot can handle this key expansion
+ * mode. Bug 1198298 */
+ PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
+ (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
+ CK_MECHANISM_TYPE master_derive;
+ CK_MECHANISM_TYPE key_derive;
+ SECItem params;
+ const CK_FLAGS keyFlags = CKF_SIGN | CKF_VERIFY;
+ CK_VERSION pms_version;
+ CK_VERSION *pms_version_ptr = NULL;
+ SECStatus rv;
- PK11_FreeSlot(slot);
- if (fpms != NULL) {
- pwSpec->master_secret = PK11_DeriveWithFlags(fpms,
- master_derive, &params, key_derive,
- CKA_DERIVE, 0, keyFlags);
- PK11_FreeSymKey(fpms);
- }
- }
+ rv = ssl3_ComputeHandshakeHashes(ss, pwSpec, &hashes, 0);
+ if (rv != SECSuccess) {
+ PORT_Assert(0); /* Should never fail */
+ ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ return SECFailure;
}
- if (pwSpec->master_secret == NULL) {
- /* Generate a faux master secret from the internal slot. */
- PK11SlotInfo * slot = PK11_GetInternalSlot();
- PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot);
- PK11_FreeSlot(slot);
- if (fpms != NULL) {
- pwSpec->master_secret = PK11_DeriveWithFlags(fpms,
- master_derive, &params, key_derive,
- CKA_DERIVE, 0, keyFlags);
- if (pwSpec->master_secret == NULL) {
- pwSpec->master_secret = fpms; /* use the fpms as the master. */
- fpms = NULL;
- }
- }
- if (fpms) {
- PK11_FreeSymKey(fpms);
- }
+ if (isDH) {
+ master_derive = CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH;
+ } else {
+ master_derive = CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE;
+ pms_version_ptr = &pms_version;
}
- if (pwSpec->master_secret == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
- return rv;
+
+ if (pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ /* TLS 1.2 */
+ extended_master_params.prfHashMechanism = CKM_SHA256;
+ key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
+ } else {
+ /* TLS < 1.2 */
+ extended_master_params.prfHashMechanism = CKM_TLS_PRF;
+ key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
+ }
+
+ extended_master_params.pVersion = pms_version_ptr;
+ extended_master_params.pSessionHash = hashes.u.raw;
+ extended_master_params.ulSessionHashLen = hashes.len;
+
+ params.data = (unsigned char *) &extended_master_params;
+ params.len = sizeof extended_master_params;
+
+ return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive,
+ pms_version_ptr, &params,
+ keyFlags, pms, msp);
+}
+
+
+/* Wrapper method to compute the master secret and return it in |*msp|.
+**
+** Called from ssl3_ComputeMasterSecret
+*/
+static SECStatus
+ssl3_ComputeMasterSecret(sslSocket *ss, PK11SymKey *pms,
+ PK11SymKey **msp)
+{
+ PORT_Assert(pms != NULL);
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
+
+ if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
+ return tls_ComputeExtendedMasterSecretInt(ss, pms, msp);
+ } else {
+ return ssl3_ComputeMasterSecretInt(ss, pms, msp);
+ }
+}
+
+/* This method uses PKCS11 to derive the MS from the PMS, where PMS
+** is a PKCS11 symkey. We call ssl3_ComputeMasterSecret to do the
+** computations and then modify the pwSpec->state as a side effect.
+**
+** This is used in all cases except the "triple bypass" with RSA key
+** exchange.
+**
+** Called from ssl3_InitPendingCipherSpec. prSpec is pwSpec.
+*/
+static SECStatus
+ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
+{
+ SECStatus rv;
+ PK11SymKey* ms = NULL;
+ ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
+ PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
+
+ if (pms) {
+ rv = ssl3_ComputeMasterSecret(ss, pms, &ms);
+ pwSpec->master_secret = ms;
+ if (rv != SECSuccess)
+ return rv;
}
+
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
SECItem * keydata;
@@ -3847,7 +3987,7 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
rv = PK11_ExtractKeyValue(pwSpec->master_secret);
if (rv != SECSuccess) {
return rv;
- }
+ }
/* This returns the address of the secItem inside the key struct,
* not a copy or a reference. So, there's no need to free it.
*/
@@ -3862,10 +4002,10 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
}
}
#endif
+
return SECSuccess;
}
-
/*
* Derive encryption and MAC Keys (and IVs) from master secret
* Sets a useful error code when returning SECFailure.
@@ -3898,7 +4038,9 @@ ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss)
PK11SymKey * symKey = NULL;
void * pwArg = ss->pkcs11PinArg;
int keySize;
- CK_SSL3_KEY_MAT_PARAMS key_material_params;
+ CK_TLS12_KEY_MAT_PARAMS key_material_params; /* may be used as a
+ * CK_SSL3_KEY_MAT_PARAMS */
+ unsigned int key_material_params_len;
CK_SSL3_KEY_MAT_OUT returnedKeys;
CK_MECHANISM_TYPE key_derive;
CK_MECHANISM_TYPE bulk_mechanism;
@@ -3952,17 +4094,21 @@ ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss)
PORT_Assert( alg2Mech[calg].calg == calg);
bulk_mechanism = alg2Mech[calg].cmech;
- params.data = (unsigned char *)&key_material_params;
- params.len = sizeof(key_material_params);
-
if (isTLS12) {
- key_derive = CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256;
+ key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
+ key_material_params.prfHashMechanism = CKM_SHA256;
+ key_material_params_len = sizeof(CK_TLS12_KEY_MAT_PARAMS);
} else if (isTLS) {
key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
+ key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
} else {
key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
+ key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
}
+ params.data = (unsigned char *)&key_material_params;
+ params.len = key_material_params_len;
+
/* CKM_SSL3_KEY_AND_MAC_DERIVE is defined to set ENCRYPT, DECRYPT, and
* DERIVE by DEFAULT */
symKey = PK11_Derive(pwSpec->master_secret, key_derive, &params,
@@ -4273,6 +4419,12 @@ ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num, PRInt32 lenSize)
PRUint8 b[4];
PRUint8 * p = b;
+ PORT_Assert(lenSize <= 4 && lenSize > 0);
+ if (lenSize < 4 && num >= (1L << (lenSize * 8))) {
+ PORT_SetError(SSL_ERROR_TX_RECORD_TOO_LONG);
+ return SECFailure;
+ }
+
switch (lenSize) {
case 4:
*p++ = (num >> 24) & 0xff;
@@ -4365,17 +4517,12 @@ ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length)
* |sigAndHash| to the current handshake message. */
SECStatus
ssl3_AppendSignatureAndHashAlgorithm(
- sslSocket *ss, const SSL3SignatureAndHashAlgorithm* sigAndHash)
+ sslSocket *ss, const SSLSignatureAndHashAlg* sigAndHash)
{
- unsigned char serialized[2];
-
- serialized[0] = ssl3_OIDToTLSHashAlgorithm(sigAndHash->hashAlg);
- if (serialized[0] == 0) {
- PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
- return SECFailure;
- }
+ PRUint8 serialized[2];
- serialized[1] = sigAndHash->sigAlg;
+ serialized[0] = (PRUint8)sigAndHash->hashAlg;
+ serialized[1] = (PRUint8)sigAndHash->sigAlg;
return ssl3_AppendHandshake(ss, serialized, sizeof(serialized));
}
@@ -4470,6 +4617,7 @@ ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes,
PORT_Assert(bytes <= 3);
i->len = 0;
i->data = NULL;
+ i->type = siBuffer;
count = ssl3_ConsumeHandshakeNumber(ss, bytes, b, length);
if (count < 0) { /* Can't test for SECSuccess here. */
return SECFailure;
@@ -4489,15 +4637,13 @@ ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes,
/* tlsHashOIDMap contains the mapping between TLS hash identifiers and the
* SECOidTag used internally by NSS. */
static const struct {
- int tlsHash;
+ SSLHashType tlsHash;
SECOidTag oid;
} tlsHashOIDMap[] = {
- { tls_hash_md5, SEC_OID_MD5 },
- { tls_hash_sha1, SEC_OID_SHA1 },
- { tls_hash_sha224, SEC_OID_SHA224 },
- { tls_hash_sha256, SEC_OID_SHA256 },
- { tls_hash_sha384, SEC_OID_SHA384 },
- { tls_hash_sha512, SEC_OID_SHA512 }
+ { ssl_hash_sha1, SEC_OID_SHA1 },
+ { ssl_hash_sha256, SEC_OID_SHA256 },
+ { ssl_hash_sha384, SEC_OID_SHA384 },
+ { ssl_hash_sha512, SEC_OID_SHA512 }
};
/* ssl3_TLSHashAlgorithmToOID converts a TLS hash identifier into an OID value.
@@ -4505,7 +4651,7 @@ static const struct {
*
* See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
SECOidTag
-ssl3_TLSHashAlgorithmToOID(int hashFunc)
+ssl3_TLSHashAlgorithmToOID(SSLHashType hashFunc)
{
unsigned int i;
@@ -4517,42 +4663,24 @@ ssl3_TLSHashAlgorithmToOID(int hashFunc)
return SEC_OID_UNKNOWN;
}
-/* ssl3_OIDToTLSHashAlgorithm converts an OID to a TLS hash algorithm
- * identifier. If the hash is not recognised, zero is returned.
- *
- * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
-static int
-ssl3_OIDToTLSHashAlgorithm(SECOidTag oid)
-{
- unsigned int i;
-
- for (i = 0; i < PR_ARRAY_SIZE(tlsHashOIDMap); i++) {
- if (oid == tlsHashOIDMap[i].oid) {
- return tlsHashOIDMap[i].tlsHash;
- }
- }
- return 0;
-}
-
/* ssl3_TLSSignatureAlgorithmForKeyType returns the TLS 1.2 signature algorithm
* identifier for a given KeyType. */
static SECStatus
-ssl3_TLSSignatureAlgorithmForKeyType(KeyType keyType,
- TLSSignatureAlgorithm *out)
+ssl3_TLSSignatureAlgorithmForKeyType(KeyType keyType, SSLSignType *out)
{
switch (keyType) {
case rsaKey:
- *out = tls_sig_rsa;
- return SECSuccess;
+ *out = ssl_sign_rsa;
+ return SECSuccess;
case dsaKey:
- *out = tls_sig_dsa;
- return SECSuccess;
+ *out = ssl_sign_dsa;
+ return SECSuccess;
case ecKey:
- *out = tls_sig_ecdsa;
- return SECSuccess;
+ *out = ssl_sign_ecdsa;
+ return SECSuccess;
default:
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ return SECFailure;
}
}
@@ -4560,15 +4688,15 @@ ssl3_TLSSignatureAlgorithmForKeyType(KeyType keyType,
* algorithm identifier for the given certificate. */
static SECStatus
ssl3_TLSSignatureAlgorithmForCertificate(CERTCertificate *cert,
- TLSSignatureAlgorithm *out)
+ SSLSignType *out)
{
SECKEYPublicKey *key;
KeyType keyType;
key = CERT_ExtractPublicKey(cert);
if (key == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
- return SECFailure;
+ ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
+ return SECFailure;
}
keyType = key->keyType;
@@ -4578,24 +4706,75 @@ ssl3_TLSSignatureAlgorithmForCertificate(CERTCertificate *cert,
/* ssl3_CheckSignatureAndHashAlgorithmConsistency checks that the signature
* algorithm identifier in |sigAndHash| is consistent with the public key in
- * |cert|. If so, SECSuccess is returned. Otherwise, PORT_SetError is called
- * and SECFailure is returned. */
+ * |cert|. It also checks the hash algorithm against the configured signature
+ * algorithms. If all the tests pass, SECSuccess is returned. Otherwise,
+ * PORT_SetError is called and SECFailure is returned. */
SECStatus
ssl3_CheckSignatureAndHashAlgorithmConsistency(
- const SSL3SignatureAndHashAlgorithm *sigAndHash, CERTCertificate* cert)
+ sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash,
+ CERTCertificate* cert)
{
SECStatus rv;
- TLSSignatureAlgorithm sigAlg;
+ SSLSignType sigAlg;
+ unsigned int i;
rv = ssl3_TLSSignatureAlgorithmForCertificate(cert, &sigAlg);
if (rv != SECSuccess) {
- return rv;
+ return rv;
}
if (sigAlg != sigAndHash->sigAlg) {
- PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
+ return SECFailure;
}
- return SECSuccess;
+
+ for (i = 0; i < ss->ssl3.signatureAlgorithmCount; ++i) {
+ const SSLSignatureAndHashAlg *alg = &ss->ssl3.signatureAlgorithms[i];
+ if (sigAndHash->sigAlg == alg->sigAlg &&
+ sigAndHash->hashAlg == alg->hashAlg) {
+ return SECSuccess;
+ }
+ }
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
+ return SECFailure;
+}
+
+PRBool
+ssl3_IsSupportedSignatureAlgorithm(const SSLSignatureAndHashAlg *alg)
+{
+ static const SSLHashType supportedHashes[] = {
+ ssl_hash_sha1,
+ ssl_hash_sha256,
+ ssl_hash_sha384,
+ ssl_hash_sha512
+ };
+
+ static const SSLSignType supportedSigAlgs[] = {
+ ssl_sign_rsa,
+#ifndef NSS_DISABLE_ECC
+ ssl_sign_ecdsa,
+#endif
+ ssl_sign_dsa
+ };
+
+ unsigned int i;
+ PRBool hashOK = PR_FALSE;
+ PRBool signOK = PR_FALSE;
+
+ for (i = 0; i < PR_ARRAY_SIZE(supportedHashes); ++i) {
+ if (alg->hashAlg == supportedHashes[i]) {
+ hashOK = PR_TRUE;
+ break;
+ }
+ }
+
+ for (i = 0; i < PR_ARRAY_SIZE(supportedSigAlgs); ++i) {
+ if (alg->sigAlg == supportedSigAlgs[i]) {
+ signOK = PR_TRUE;
+ break;
+ }
+ }
+
+ return hashOK && signOK;
}
/* ssl3_ConsumeSignatureAndHashAlgorithm reads a SignatureAndHashAlgorithm
@@ -4605,25 +4784,24 @@ ssl3_CheckSignatureAndHashAlgorithmConsistency(
* See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
SECStatus
ssl3_ConsumeSignatureAndHashAlgorithm(sslSocket *ss,
- SSL3Opaque **b,
- PRUint32 *length,
- SSL3SignatureAndHashAlgorithm *out)
+ SSL3Opaque **b,
+ PRUint32 *length,
+ SSLSignatureAndHashAlg *out)
{
- unsigned char bytes[2];
+ PRUint8 bytes[2];
SECStatus rv;
rv = ssl3_ConsumeHandshake(ss, bytes, sizeof(bytes), b, length);
if (rv != SECSuccess) {
- return rv;
+ return rv;
}
- out->hashAlg = ssl3_TLSHashAlgorithmToOID(bytes[0]);
- if (out->hashAlg == SEC_OID_UNKNOWN) {
- PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
- return SECFailure;
+ out->hashAlg = (SSLHashType)bytes[0];
+ out->sigAlg = (SSLSignType)bytes[1];
+ if (!ssl3_IsSupportedSignatureAlgorithm(out)) {
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
+ return SECFailure;
}
-
- out->sigAlg = bytes[1];
return SECSuccess;
}
@@ -4653,7 +4831,12 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss,
SSL3Opaque sha_inner[MAX_MAC_LENGTH];
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- hashes->hashAlg = SEC_OID_UNKNOWN;
+ if (ss->ssl3.hs.hashType == handshake_hash_unknown) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ hashes->hashAlg = ssl_hash_none;
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11 &&
@@ -4661,11 +4844,6 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss,
/* compute them without PKCS11 */
PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
- if (!spec->msItem.data) {
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
- return SECFailure;
- }
-
ss->ssl3.hs.sha_clone(sha_cx, ss->ssl3.hs.sha_cx);
ss->ssl3.hs.sha_obj->end(sha_cx, hashes->u.raw, &hashes->len,
sizeof(hashes->u.raw));
@@ -4674,7 +4852,7 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss,
/* If we ever support ciphersuites where the PRF hash isn't SHA-256
* then this will need to be updated. */
- hashes->hashAlg = SEC_OID_SHA256;
+ hashes->hashAlg = ssl_hash_sha256;
rv = SECSuccess;
} else if (ss->opt.bypassPKCS11) {
/* compute them without PKCS11 */
@@ -4684,11 +4862,6 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss,
#define md5cx ((MD5Context *)md5_cx)
#define shacx ((SHA1Context *)sha_cx)
- if (!spec->msItem.data) {
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
- return SECFailure;
- }
-
MD5_Clone (md5cx, (MD5Context *)ss->ssl3.hs.md5_cx);
SHA1_Clone(shacx, (SHA1Context *)ss->ssl3.hs.sha_cx);
@@ -4696,6 +4869,11 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss,
/* compute hashes for SSL3. */
unsigned char s[4];
+ if (!spec->msItem.data) {
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
+ return SECFailure;
+ }
+
s[0] = (unsigned char)(sender >> 24);
s[1] = (unsigned char)(sender >> 16);
s[2] = (unsigned char)(sender >> 8);
@@ -4768,11 +4946,6 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss,
unsigned char stackBuf[1024];
unsigned char *stateBuf = NULL;
- if (!spec->master_secret) {
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
- return SECFailure;
- }
-
h = ss->ssl3.hs.sha;
stateBuf = PK11_SaveContextAlloc(h, stackBuf,
sizeof(stackBuf), &stateLen);
@@ -4789,7 +4962,7 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss,
}
/* If we ever support ciphersuites where the PRF hash isn't SHA-256
* then this will need to be updated. */
- hashes->hashAlg = SEC_OID_SHA256;
+ hashes->hashAlg = ssl_hash_sha256;
rv = SECSuccess;
tls12_loser:
@@ -4812,11 +4985,6 @@ tls12_loser:
unsigned char md5StackBuf[256];
unsigned char shaStackBuf[512];
- if (!spec->master_secret) {
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
- return SECFailure;
- }
-
md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf,
sizeof md5StackBuf, &md5StateLen);
if (md5StateBuf == NULL) {
@@ -4837,6 +5005,11 @@ tls12_loser:
/* compute hashes for SSL3. */
unsigned char s[4];
+ if (!spec->master_secret) {
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
+ return SECFailure;
+ }
+
s[0] = (unsigned char)(sender >> 24);
s[1] = (unsigned char)(sender >> 16);
s[2] = (unsigned char)(sender >> 8);
@@ -4968,7 +5141,7 @@ ssl3_ComputeBackupHandshakeHashes(sslSocket * ss,
rv = SECFailure;
goto loser;
}
- hashes->hashAlg = SEC_OID_SHA1;
+ hashes->hashAlg = ssl_hash_sha1;
loser:
PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE);
@@ -5049,7 +5222,9 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
if (rv != SECSuccess) {
return rv; /* ssl3_InitState has set the error code. */
}
- ss->ssl3.hs.sendingSCSV = PR_FALSE; /* Must be reset every handshake */
+ /* These must be reset every handshake. */
+ ss->ssl3.hs.sendingSCSV = PR_FALSE;
+ ss->ssl3.hs.preliminaryInfo = 0;
PORT_Assert(IS_DTLS(ss) || !resending);
SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE);
@@ -5425,7 +5600,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
}
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
- if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange)) {
+ if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange, ss)) {
actual_count++;
if (actual_count > num_suites) {
if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
@@ -6083,14 +6258,6 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
}
}
- rv = ssl3_InitPendingCipherSpec(ss, pms);
- PK11_FreeSymKey(pms); pms = NULL;
-
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- goto loser;
- }
-
rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
isTLS ? enc_pms.len + 2 : enc_pms.len);
if (rv != SECSuccess) {
@@ -6105,6 +6272,15 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
goto loser; /* err set by ssl3_AppendHandshake* */
}
+ rv = ssl3_InitPendingCipherSpec(ss, pms);
+ PK11_FreeSymKey(pms);
+ pms = NULL;
+
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
+ }
+
rv = SECSuccess;
loser:
@@ -6174,14 +6350,6 @@ sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
SECKEY_DestroyPrivateKey(privKey);
privKey = NULL;
- rv = ssl3_InitPendingCipherSpec(ss, pms);
- PK11_FreeSymKey(pms); pms = NULL;
-
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- goto loser;
- }
-
rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
pubKey->u.dh.publicValue.len + 2);
if (rv != SECSuccess) {
@@ -6197,8 +6365,16 @@ sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
goto loser; /* err set by ssl3_AppendHandshake* */
}
- rv = SECSuccess;
+ rv = ssl3_InitPendingCipherSpec(ss, pms);
+ PK11_FreeSymKey(pms);
+ pms = NULL;
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
+ }
+
+ rv = SECSuccess;
loser:
@@ -6240,9 +6416,9 @@ ssl3_SendClientKeyExchange(sslSocket *ss)
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
/* enforce limits on kea key sizes. */
if (ss->ssl3.hs.kea_def->is_limited) {
- int keyLen = SECKEY_PublicKeyStrength(serverKey); /* bytes */
+ unsigned int keyLen = SECKEY_PublicKeyStrengthInBits(serverKey);
- if (keyLen * BPB > ss->ssl3.hs.kea_def->key_size_limit) {
+ if (keyLen > ss->ssl3.hs.kea_def->key_size_limit) {
if (isTLS)
(void)SSL3_SendAlert(ss, alert_fatal, export_restriction);
else
@@ -6297,7 +6473,7 @@ ssl3_SendCertificateVerify(sslSocket *ss)
SSL3Hashes hashes;
KeyType keyType;
unsigned int len;
- SSL3SignatureAndHashAlgorithm sigAndHash;
+ SSLSignatureAndHashAlg sigAndHash;
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
@@ -6362,11 +6538,11 @@ ssl3_SendCertificateVerify(sslSocket *ss)
}
if (isTLS12) {
rv = ssl3_TLSSignatureAlgorithmForKeyType(keyType,
- &sigAndHash.sigAlg);
+ &sigAndHash.sigAlg);
if (rv != SECSuccess) {
goto done;
}
- sigAndHash.hashAlg = hashes.hashAlg;
+ sigAndHash.hashAlg = hashes.hashAlg;
rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
if (rv != SECSuccess) {
@@ -6474,6 +6650,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
errCode = SSL_ERROR_UNSUPPORTED_VERSION;
goto alert_loser;
}
+ ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
rv = ssl3_InitHandshakeHashes(ss);
@@ -6509,7 +6686,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
if (temp == suite->cipher_suite) {
SSLVersionRange vrange = {ss->version, ss->version};
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange)) {
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
/* config_match already checks whether the cipher suite is
* acceptable for the version, but the check is repeated here
* in order to give a more precise error code. */
@@ -6533,6 +6710,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)temp;
ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef((ssl3CipherSuite)temp);
+ ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
PORT_Assert(ss->ssl3.hs.suite_def);
if (!ss->ssl3.hs.suite_def) {
PORT_SetError(errCode = SEC_ERROR_LIBRARY_FAILURE);
@@ -6619,6 +6797,32 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECItem wrappedMS; /* wrapped master secret. */
+ /* [draft-ietf-tls-session-hash-06; Section 5.3]
+ *
+ * o If the original session did not use the "extended_master_secret"
+ * extension but the new ServerHello contains the extension, the
+ * client MUST abort the handshake.
+ */
+ if (!sid->u.ssl3.keys.extendedMasterSecretUsed &&
+ ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
+ errCode = SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET;
+ goto alert_loser;
+ }
+
+ /*
+ * o If the original session used an extended master secret but the new
+ * ServerHello does not contain the "extended_master_secret"
+ * extension, the client SHOULD abort the handshake.
+ *
+ * TODO(ekr@rtfm.com): Add option to refuse to resume when EMS is not
+ * used at all (bug 1176526).
+ */
+ if (sid->u.ssl3.keys.extendedMasterSecretUsed &&
+ !ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
+ errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
+ goto alert_loser;
+ }
+
ss->sec.authAlgorithm = sid->authAlgorithm;
ss->sec.authKeyBits = sid->authKeyBits;
ss->sec.keaType = sid->keaType;
@@ -6721,7 +6925,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ssl3_CopyPeerCertsFromSID(ss, sid);
}
- /* NULL value for PMS signifies re-use of the old MS */
+ /* NULL value for PMS because we are reusing the old MS */
rv = ssl3_InitPendingCipherSpec(ss, NULL);
if (rv != SECSuccess) {
goto alert_loser; /* err code was set */
@@ -6750,6 +6954,9 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
sid->u.ssl3.sessionIDLength = sidBytes.len;
PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);
+ sid->u.ssl3.keys.extendedMasterSecretUsed =
+ ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
+
/* Copy Signed Certificate Timestamps, if any. */
if (ss->xtnData.signedCertTimestamps.data) {
rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
@@ -6761,13 +6968,14 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ss->ssl3.hs.isResuming = PR_FALSE;
if (ss->ssl3.hs.kea_def->signKeyType != sign_null) {
/* All current cipher suites other than those with sign_null (i.e.,
- * DH_anon_* suites) require a certificate, so use that signal. */
+ * (EC)DH_anon_* suites) require a certificate, so use that signal. */
ss->ssl3.hs.ws = wait_server_cert;
- } else if (ss->ssl3.hs.kea_def->ephemeral) {
- /* Only ephemeral cipher suites use ServerKeyExchange. */
- ss->ssl3.hs.ws = wait_server_key;
} else {
- ss->ssl3.hs.ws = wait_cert_request;
+ /* All the remaining cipher suites must be (EC)DH_anon_* and so
+ * must be ephemeral. Note, if we ever add PSK this might
+ * change. */
+ PORT_Assert(ss->ssl3.hs.kea_def->ephemeral);
+ ss->ssl3.hs.ws = wait_server_key;
}
winner:
@@ -6807,29 +7015,6 @@ loser:
return SECFailure;
}
-/* ssl3_BigIntGreaterThanOne returns true iff |mpint|, taken as an unsigned,
- * big-endian integer is > 1 */
-static PRBool
-ssl3_BigIntGreaterThanOne(const SECItem* mpint) {
- unsigned char firstNonZeroByte = 0;
- unsigned int i;
-
- for (i = 0; i < mpint->len; i++) {
- if (mpint->data[i]) {
- firstNonZeroByte = mpint->data[i];
- break;
- }
- }
-
- if (firstNonZeroByte == 0)
- return PR_FALSE;
- if (firstNonZeroByte > 1)
- return PR_TRUE;
-
- /* firstNonZeroByte == 1, therefore mpint > 1 iff the first non-zero byte
- * is followed by another byte. */
- return (i < mpint->len - 1);
-}
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
* ssl3 ServerKeyExchange message.
@@ -6846,9 +7031,9 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SSL3AlertDescription desc = illegal_parameter;
SSL3Hashes hashes;
SECItem signature = {siBuffer, NULL, 0};
- SSL3SignatureAndHashAlgorithm sigAndHash;
+ SSLSignatureAndHashAlg sigAndHash;
- sigAndHash.hashAlg = SEC_OID_UNKNOWN;
+ sigAndHash.hashAlg = ssl_hash_none;
SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake",
SSL_GETPID(), ss->fd));
@@ -6874,6 +7059,12 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
+ /* This exchange method is only used by export cipher suites.
+ * Those are broken and so this code will eventually be removed. */
+ if (SECKEY_BigIntegerBitLength(&modulus) < 512) {
+ desc = isTLS ? insufficient_security : illegal_parameter;
+ goto alert_loser;
+ }
rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed. */
@@ -6884,7 +7075,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
if (rv != SECSuccess) {
goto loser; /* malformed or unsupported. */
}
- rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
+ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(ss,
&sigAndHash, ss->sec.peerCert);
if (rv != SECSuccess) {
goto loser;
@@ -6907,10 +7098,10 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
/*
* check to make sure the hash is signed by right guy
*/
- rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg, modulus, exponent,
- &ss->ssl3.hs.client_random,
- &ss->ssl3.hs.server_random,
- &hashes, ss->opt.bypassPKCS11);
+ rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg, modulus, exponent,
+ &ss->ssl3.hs.client_random,
+ &ss->ssl3.hs.server_random,
+ &hashes, ss->opt.bypassPKCS11);
if (rv != SECSuccess) {
errCode =
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
@@ -6936,7 +7127,6 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
if (peerKey == NULL) {
- PORT_FreeArena(arena, PR_FALSE);
goto no_memory;
}
@@ -6947,7 +7137,6 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus, &modulus) ||
SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent))
{
- PORT_FreeArena(arena, PR_FALSE);
goto no_memory;
}
ss->sec.peerKey = peerKey;
@@ -6959,13 +7148,22 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECItem dh_p = {siBuffer, NULL, 0};
SECItem dh_g = {siBuffer, NULL, 0};
SECItem dh_Ys = {siBuffer, NULL, 0};
+ unsigned dh_p_bits;
+ unsigned dh_g_bits;
+ unsigned dh_Ys_bits;
+ PRInt32 minDH;
rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
- if (dh_p.len < 1024/8 ||
- (dh_p.len == 1024/8 && (dh_p.data[0] & 0x80) == 0)) {
+
+ rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minDH);
+ if (rv != SECSuccess) {
+ minDH = SSL_DH_MIN_P_BITS;
+ }
+ dh_p_bits = SECKEY_BigIntegerBitLength(&dh_p);
+ if (dh_p_bits < minDH) {
errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY;
goto alert_loser;
}
@@ -6973,13 +7171,16 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
- if (dh_g.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_g))
+ /* Abort if dh_g is 0, 1, or obviously too big. */
+ dh_g_bits = SECKEY_BigIntegerBitLength(&dh_g);
+ if (dh_g_bits > dh_p_bits || dh_g_bits <= 1)
goto alert_loser;
rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
- if (dh_Ys.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_Ys))
+ dh_Ys_bits = SECKEY_BigIntegerBitLength(&dh_Ys);
+ if (dh_Ys_bits > dh_p_bits || dh_Ys_bits <= 1)
goto alert_loser;
if (isTLS12) {
rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
@@ -6987,7 +7188,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
if (rv != SECSuccess) {
goto loser; /* malformed or unsupported. */
}
- rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
+ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(ss,
&sigAndHash, ss->sec.peerCert);
if (rv != SECSuccess) {
goto loser;
@@ -7014,10 +7215,10 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
/*
* check to make sure the hash is signed by right guy
*/
- rv = ssl3_ComputeDHKeyHash(sigAndHash.hashAlg, dh_p, dh_g, dh_Ys,
- &ss->ssl3.hs.client_random,
- &ss->ssl3.hs.server_random,
- &hashes, ss->opt.bypassPKCS11);
+ rv = ssl3_ComputeDHKeyHash(sigAndHash.hashAlg, dh_p, dh_g, dh_Ys,
+ &ss->ssl3.hs.client_random,
+ &ss->ssl3.hs.server_random,
+ &hashes, ss->opt.bypassPKCS11);
if (rv != SECSuccess) {
errCode =
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
@@ -7041,7 +7242,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
goto no_memory;
}
- ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
+ peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
if (peerKey == NULL) {
goto no_memory;
}
@@ -7055,7 +7256,6 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECITEM_CopyItem(arena, &peerKey->u.dh.base, &dh_g) ||
SECITEM_CopyItem(arena, &peerKey->u.dh.publicValue, &dh_Ys))
{
- PORT_FreeArena(arena, PR_FALSE);
goto no_memory;
}
ss->sec.peerKey = peerKey;
@@ -7078,10 +7278,16 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
alert_loser:
(void)SSL3_SendAlert(ss, alert_fatal, desc);
loser:
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
PORT_SetError( errCode );
return SECFailure;
no_memory: /* no-memory error has already been set. */
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
return SECFailure;
}
@@ -7092,7 +7298,7 @@ no_memory: /* no-memory error has already been set. */
*/
static SECStatus
ssl3_ExtractClientKeyInfo(sslSocket *ss,
- TLSSignatureAlgorithm *sigAlg,
+ SSLSignType *sigAlg,
PRBool *preferSha1)
{
SECStatus rv = SECSuccess;
@@ -7148,7 +7354,7 @@ ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
const SECItem *algorithms)
{
SECStatus rv;
- TLSSignatureAlgorithm sigAlg;
+ SSLSignType sigAlg;
PRBool preferSha1;
PRBool supportsSha1 = PR_FALSE;
PRBool supportsSha256 = PR_FALSE;
@@ -7173,9 +7379,9 @@ ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
/* 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) {
+ if (algorithms->data[i] == ssl_hash_sha1) {
supportsSha1 = PR_TRUE;
- } else if (algorithms->data[i] == tls_hash_sha256) {
+ } else if (algorithms->data[i] == ssl_hash_sha256) {
supportsSha256 = PR_TRUE;
}
}
@@ -7334,6 +7540,8 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
} else
#endif
if (ss->getClientAuthData != NULL) {
+ PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
+ ssl_preinfo_all);
/* XXX Should pass cert_types and algorithms in this call!! */
rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
ss->fd, &ca_list,
@@ -7565,6 +7773,8 @@ ssl3_CheckFalseStart(sslSocket *ss)
SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher",
SSL_GETPID(), ss->fd));
} else {
+ PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
+ ssl_preinfo_all);
rv = (ss->canFalseStartCallback)(ss->fd,
ss->canFalseStartCallbackData,
&ss->ssl3.hs.canFalseStart);
@@ -7923,6 +8133,7 @@ ssl3_NewSessionID(sslSocket *ss, PRBool is_server)
sid->u.ssl3.policy = SSL_ALLOWED;
sid->u.ssl3.clientWriteKey = NULL;
sid->u.ssl3.serverWriteKey = NULL;
+ sid->u.ssl3.keys.extendedMasterSecretUsed = PR_FALSE;
if (is_server) {
SECStatus rv;
@@ -7975,7 +8186,7 @@ ssl3_SendServerHelloSequence(sslSocket *ss)
if (kea_def->is_limited && kea_def->exchKeyType == kt_rsa) {
/* see if we can legally use the key in the cert. */
- int keyLen; /* bytes */
+ unsigned int keyLen; /* bytes */
keyLen = PK11_GetPrivateModulusLen(
ss->serverCerts[kea_def->exchKeyType].SERVERKEY);
@@ -8022,6 +8233,22 @@ ssl3_SendServerHelloSequence(sslSocket *ss)
/* An empty TLS Renegotiation Info (RI) extension */
static const PRUint8 emptyRIext[5] = {0xff, 0x01, 0x00, 0x01, 0x00};
+static PRBool
+ssl3_KEAAllowsSessionTicket(SSL3KeyExchangeAlgorithm kea)
+{
+ switch (kea) {
+ case kea_dhe_dss:
+ case kea_dhe_dss_export:
+ case kea_dh_dss_export:
+ case kea_dh_dss:
+ /* TODO: Fix session tickets for DSS. The server code rejects the
+ * session ticket received from the client. Bug 1174677 */
+ return PR_FALSE;
+ default:
+ return PR_TRUE;
+ };
+}
+
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
* ssl3 Client Hello message.
* Caller must hold Handshake and RecvBuf locks.
@@ -8044,6 +8271,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECItem comps = {siBuffer, NULL, 0};
PRBool haveSpecWriteLock = PR_FALSE;
PRBool haveXmitBufLock = PR_FALSE;
+ PRBool canOfferSessionTicket = PR_FALSE;
SSL_TRC(3, ("%d: SSL3[%d]: handle client_hello handshake",
SSL_GETPID(), ss->fd));
@@ -8051,6 +8279,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert( ss->ssl3.initialized );
+ ss->ssl3.hs.preliminaryInfo = 0;
if (!ss->sec.isServer ||
(ss->ssl3.hs.ws != wait_client_hello &&
@@ -8116,6 +8345,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
errCode = SSL_ERROR_UNSUPPORTED_VERSION;
goto alert_loser;
}
+ ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
rv = ssl3_InitHandshakeHashes(ss);
if (rv != SECSuccess) {
@@ -8283,8 +8513,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
* resuming.)
*/
if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) && sid == NULL) {
- ssl3_RegisterServerHelloExtensionSender(ss,
- ssl_session_ticket_xtn, ssl3_SendSessionTicketXtn);
+ canOfferSessionTicket = PR_TRUE;
}
if (sid != NULL) {
@@ -8367,7 +8596,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
* The product policy won't change during the process lifetime.
* Implemented ("isPresent") shouldn't change for servers.
*/
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange))
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss))
break;
#else
if (!suite->enabled)
@@ -8380,6 +8609,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ss->ssl3.hs.cipher_suite = suite->cipher_suite;
ss->ssl3.hs.suite_def =
ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
+ ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
/* Use the cached compression method. */
ss->ssl3.hs.compression = sid->u.ssl3.compression;
@@ -8416,7 +8646,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
SSLVersionRange vrange = {ss->version, ss->version};
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange)) {
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
continue;
}
for (i = 0; i + 1 < suites.len; i += 2) {
@@ -8425,6 +8655,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ss->ssl3.hs.cipher_suite = suite->cipher_suite;
ss->ssl3.hs.suite_def =
ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
+ ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
goto suite_found;
}
}
@@ -8433,6 +8664,15 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
goto alert_loser;
suite_found:
+ if (canOfferSessionTicket)
+ canOfferSessionTicket = ssl3_KEAAllowsSessionTicket(
+ ss->ssl3.hs.suite_def->key_exchange_alg);
+
+ if (canOfferSessionTicket) {
+ ssl3_RegisterServerHelloExtensionSender(ss,
+ ssl_session_ticket_xtn, ssl3_SendSessionTicketXtn);
+ }
+
/* Select a compression algorithm. */
for (i = 0; i < comps.len; i++) {
if (!compressionEnabled(ss, comps.data[i]))
@@ -8458,6 +8698,8 @@ compression_found:
/* If there are any failures while processing the old sid,
* we don't consider them to be errors. Instead, We just behave
* as if the client had sent us no sid to begin with, and make a new one.
+ * The exception here is attempts to resume extended_master_secret
+ * sessions without the extension, which causes an alert.
*/
if (sid != NULL) do {
ssl3CipherSpec *pwSpec;
@@ -8469,6 +8711,30 @@ compression_found:
break; /* not an error */
}
+ /* [draft-ietf-tls-session-hash-06; Section 5.3]
+ * o If the original session did not use the "extended_master_secret"
+ * extension but the new ClientHello contains the extension, then the
+ * server MUST NOT perform the abbreviated handshake. Instead, it
+ * SHOULD continue with a full handshake (as described in
+ * Section 5.2) to negotiate a new session.
+ *
+ * o If the original session used the "extended_master_secret"
+ * extension but the new ClientHello does not contain the extension,
+ * the server MUST abort the abbreviated handshake.
+ */
+ if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
+ if (!sid->u.ssl3.keys.extendedMasterSecretUsed) {
+ break; /* not an error */
+ }
+ } else {
+ if (sid->u.ssl3.keys.extendedMasterSecretUsed) {
+ /* Note: we do not destroy the session */
+ desc = handshake_failure;
+ errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
+ goto alert_loser;
+ }
+ }
+
if (ss->sec.ci.sid) {
if (ss->sec.uncache)
ss->sec.uncache(ss->sec.ci.sid);
@@ -8610,7 +8876,7 @@ compression_found:
haveSpecWriteLock = PR_FALSE;
}
- /* NULL value for PMS signifies re-use of the old MS */
+ /* NULL value for PMS because we are re-using the old MS */
rv = ssl3_InitPendingCipherSpec(ss, NULL);
if (rv != SECSuccess) {
errCode = PORT_GetError();
@@ -8654,6 +8920,9 @@ compression_found:
if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn)) {
int ret = 0;
if (ss->sniSocketConfig) do { /* not a loop */
+ PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
+ ssl_preinfo_all);
+
ret = SSL_SNI_SEND_ALERT;
/* If extension is negotiated, the len of names should > 0. */
if (ss->xtnData.sniNameArrSize) {
@@ -8701,7 +8970,7 @@ compression_found:
ret = SSL_SNI_SEND_ALERT;
break;
}
- } else if (ret < ss->xtnData.sniNameArrSize) {
+ } else if ((unsigned int)ret < ss->xtnData.sniNameArrSize) {
/* Application has configured new socket info. Lets check it
* and save the name. */
SECStatus rv;
@@ -8752,7 +9021,7 @@ compression_found:
ssl3_SendServerNameXtn);
} else {
/* Callback returned index outside of the boundary. */
- PORT_Assert(ret < ss->xtnData.sniNameArrSize);
+ PORT_Assert((unsigned int)ret < ss->xtnData.sniNameArrSize);
errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
desc = internal_error;
ret = SSL_SNI_SEND_ALERT;
@@ -8798,13 +9067,16 @@ compression_found:
}
ss->sec.ci.sid = sid;
+ sid->u.ssl3.keys.extendedMasterSecretUsed =
+ ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
ss->ssl3.hs.isResuming = PR_FALSE;
ssl_GetXmitBufLock(ss);
rv = ssl3_SendServerHelloSequence(ss);
ssl_ReleaseXmitBufLock(ss);
if (rv != SECSuccess) {
- errCode = PORT_GetError();
- goto loser;
+ errCode = PORT_GetError();
+ desc = handshake_failure;
+ goto alert_loser;
}
if (haveXmitBufLock) {
@@ -8896,6 +9168,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
errCode = SSL_ERROR_UNSUPPORTED_VERSION;
goto alert_loser;
}
+ ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
rv = ssl3_InitHandshakeHashes(ss);
if (rv != SECSuccess) {
@@ -8951,7 +9224,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
SSLVersionRange vrange = {ss->version, ss->version};
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange)) {
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
continue;
}
for (i = 0; i+2 < suite_length; i += 3) {
@@ -8960,6 +9233,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
ss->ssl3.hs.cipher_suite = suite->cipher_suite;
ss->ssl3.hs.suite_def =
ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
+ ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
goto suite_found;
}
}
@@ -9150,6 +9424,154 @@ ssl3_SendServerHello(sslSocket *ss)
return SECSuccess;
}
+static SECStatus
+ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
+ SSLSignatureAndHashAlg* out);
+
+static SECStatus
+ssl3_SendDHServerKeyExchange(sslSocket *ss)
+{
+ const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
+ SECStatus rv = SECFailure;
+ int length;
+ PRBool isTLS;
+ SECItem signed_hash = {siBuffer, NULL, 0};
+ SSL3Hashes hashes;
+ SSLSignatureAndHashAlg sigAndHash;
+ SECKEYDHParams dhParam;
+
+ ssl3KeyPair *keyPair = NULL;
+ SECKEYPublicKey *pubKey = NULL; /* Ephemeral DH key */
+ SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */
+ int certIndex = -1;
+
+ if (kea_def->kea != kea_dhe_dss && kea_def->kea != kea_dhe_rsa) {
+ /* TODO: Support DH_anon. It might be sufficient to drop the signature.
+ See bug 1170510. */
+ PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ return SECFailure;
+ }
+
+ dhParam.prime.data = ss->dheParams->prime.data;
+ dhParam.prime.len = ss->dheParams->prime.len;
+ dhParam.base.data = ss->dheParams->base.data;
+ dhParam.base.len = ss->dheParams->base.len;
+
+ PRINT_BUF(60, (NULL, "Server DH p", dhParam.prime.data,
+ dhParam.prime.len));
+ PRINT_BUF(60, (NULL, "Server DH g", dhParam.base.data,
+ dhParam.base.len));
+
+ /* Generate ephemeral DH keypair */
+ privKey = SECKEY_CreateDHPrivateKey(&dhParam, &pubKey, NULL);
+ if (!privKey || !pubKey) {
+ ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
+ rv = SECFailure;
+ goto loser;
+ }
+
+ keyPair = ssl3_NewKeyPair(privKey, pubKey);
+ if (!keyPair) {
+ ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
+ goto loser;
+ }
+
+ PRINT_BUF(50, (ss, "DH public value:",
+ pubKey->u.dh.publicValue.data,
+ pubKey->u.dh.publicValue.len));
+
+ if (ssl3_PickSignatureHashAlgorithm(ss, &sigAndHash) != SECSuccess) {
+ ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
+ goto loser;
+ }
+
+ rv = ssl3_ComputeDHKeyHash(sigAndHash.hashAlg,
+ pubKey->u.dh.prime,
+ pubKey->u.dh.base,
+ pubKey->u.dh.publicValue,
+ &ss->ssl3.hs.client_random,
+ &ss->ssl3.hs.server_random,
+ &hashes, ss->opt.bypassPKCS11);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ goto loser;
+ }
+
+ /* It has been suggested to test kea_def->signKeyType instead, and to use
+ * ssl_auth_* instead. Investigate what to do. See bug 102794. */
+ if (kea_def->kea == kea_dhe_rsa)
+ certIndex = ssl_kea_rsa;
+ else
+ certIndex = ssl_kea_dh;
+
+ isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+ rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY,
+ &signed_hash, isTLS);
+ if (rv != SECSuccess) {
+ goto loser; /* ssl3_SignHashes has set err. */
+ }
+ if (signed_hash.data == NULL) {
+ PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ goto loser;
+ }
+ length = 2 + pubKey->u.dh.prime.len +
+ 2 + pubKey->u.dh.base.len +
+ 2 + pubKey->u.dh.publicValue.len +
+ 2 + signed_hash.len;
+
+ if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ length += 2;
+ }
+
+ rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+
+ rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.dh.prime.data,
+ pubKey->u.dh.prime.len, 2);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+
+ rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.dh.base.data,
+ pubKey->u.dh.base.len, 2);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+
+ rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.dh.publicValue.data,
+ pubKey->u.dh.publicValue.len, 2);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+
+ if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+ }
+
+ rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
+ signed_hash.len, 2);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+ PORT_Free(signed_hash.data);
+ ss->dheKeyPair = keyPair;
+ return SECSuccess;
+
+loser:
+ if (signed_hash.data)
+ PORT_Free(signed_hash.data);
+ if (privKey)
+ SECKEY_DestroyPrivateKey(privKey);
+ if (pubKey)
+ SECKEY_DestroyPublicKey(pubKey);
+ return SECFailure;
+}
+
/* ssl3_PickSignatureHashAlgorithm selects a hash algorithm to use when signing
* elements of the handshake. (The negotiated cipher suite determines the
* signature algorithm.) Prior to TLS 1.2, the MD5/SHA1 combination is always
@@ -9157,18 +9579,11 @@ ssl3_SendServerHello(sslSocket *ss)
* hash combinations. */
static SECStatus
ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
- SSL3SignatureAndHashAlgorithm* out)
+ SSLSignatureAndHashAlg* out)
{
- TLSSignatureAlgorithm sigAlg;
+ SSLSignType sigAlg;
+ PRUint32 policy;
unsigned int i, j;
- /* hashPreference expresses our preferences for hash algorithms, most
- * preferable first. */
- static const SECOidTag hashPreference[] = {
- SEC_OID_SHA256,
- SEC_OID_SHA384,
- SEC_OID_SHA512,
- SEC_OID_SHA1,
- };
switch (ss->ssl3.hs.kea_def->kea) {
case kea_rsa:
@@ -9181,48 +9596,63 @@ ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
case kea_rsa_fips:
case kea_ecdh_rsa:
case kea_ecdhe_rsa:
- sigAlg = tls_sig_rsa;
- break;
+ sigAlg = ssl_sign_rsa;
+ break;
case kea_dh_dss:
case kea_dh_dss_export:
case kea_dhe_dss:
case kea_dhe_dss_export:
- sigAlg = tls_sig_dsa;
- break;
+ sigAlg = ssl_sign_dsa;
+ break;
case kea_ecdh_ecdsa:
case kea_ecdhe_ecdsa:
- sigAlg = tls_sig_ecdsa;
- break;
+ sigAlg = ssl_sign_ecdsa;
+ break;
default:
- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+ return SECFailure;
}
out->sigAlg = sigAlg;
if (ss->version <= SSL_LIBRARY_VERSION_TLS_1_1) {
- /* SEC_OID_UNKNOWN means the MD5/SHA1 combo hash used in TLS 1.1 and
- * prior. */
- out->hashAlg = SEC_OID_UNKNOWN;
- return SECSuccess;
+ /* SEC_OID_UNKNOWN means the MD5/SHA1 combo hash used in TLS 1.1 and
+ * prior. */
+ out->hashAlg = ssl_hash_none;
+ return SECSuccess;
}
if (ss->ssl3.hs.numClientSigAndHash == 0) {
- /* If the client didn't provide any signature_algorithms extension then
- * we can assume that they support SHA-1:
- * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
- out->hashAlg = SEC_OID_SHA1;
- return SECSuccess;
+ /* If the client didn't provide any signature_algorithms extension then
+ * we can assume that they support SHA-1:
+ * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
+ out->hashAlg = ssl_hash_sha1;
+ return SECSuccess;
}
- for (i = 0; i < PR_ARRAY_SIZE(hashPreference); i++) {
- for (j = 0; j < ss->ssl3.hs.numClientSigAndHash; j++) {
- const SSL3SignatureAndHashAlgorithm* sh =
- &ss->ssl3.hs.clientSigAndHash[j];
- if (sh->sigAlg == sigAlg && sh->hashAlg == hashPreference[i]) {
- out->hashAlg = sh->hashAlg;
- return SECSuccess;
- }
+ /* Here we look for the first server preference that the client has
+ * indicated support for in their signature_algorithms extension. */
+ for (i = 0; i < ss->ssl3.signatureAlgorithmCount; ++i) {
+ const SSLSignatureAndHashAlg *serverPref =
+ &ss->ssl3.signatureAlgorithms[i];
+ SECOidTag hashOID;
+ if (serverPref->sigAlg != sigAlg) {
+ continue;
+ }
+ hashOID = ssl3_TLSHashAlgorithmToOID(serverPref->hashAlg);
+ if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess)
+ || !(policy & NSS_USE_ALG_IN_SSL_KX)) {
+ /* we ignore hashes we don't support */
+ continue;
}
+ for (j = 0; j < ss->ssl3.hs.numClientSigAndHash; j++) {
+ const SSLSignatureAndHashAlg *clientPref =
+ &ss->ssl3.hs.clientSigAndHash[j];
+ if (clientPref->hashAlg == serverPref->hashAlg &&
+ clientPref->sigAlg == sigAlg) {
+ out->hashAlg = serverPref->hashAlg;
+ return SECSuccess;
+ }
+ }
}
PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
@@ -9240,7 +9670,7 @@ ssl3_SendServerKeyExchange(sslSocket *ss)
SECItem signed_hash = {siBuffer, NULL, 0};
SSL3Hashes hashes;
SECKEYPublicKey * sdPub; /* public key for step-down */
- SSL3SignatureAndHashAlgorithm sigAndHash;
+ SSLSignatureAndHashAlg sigAndHash;
SSL_TRC(3, ("%d: SSL3[%d]: send server_key_exchange handshake",
SSL_GETPID(), ss->fd));
@@ -9287,6 +9717,10 @@ ssl3_SendServerKeyExchange(sslSocket *ss)
2 + sdPub->u.rsa.publicExponent.len +
2 + signed_hash.len;
+ if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ length += 2;
+ }
+
rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
if (rv != SECSuccess) {
goto loser; /* err set by AppendHandshake. */
@@ -9320,6 +9754,11 @@ ssl3_SendServerKeyExchange(sslSocket *ss)
PORT_Free(signed_hash.data);
return SECSuccess;
+ case ssl_kea_dh: {
+ rv = ssl3_SendDHServerKeyExchange(ss);
+ return rv;
+ }
+
#ifndef NSS_DISABLE_ECC
case kt_ecdh: {
rv = ssl3_SendECDHServerKeyExchange(ss, &sigAndHash);
@@ -9327,7 +9766,6 @@ ssl3_SendServerKeyExchange(sslSocket *ss)
}
#endif /* NSS_DISABLE_ECC */
- case kt_dh:
case kt_null:
default:
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
@@ -9339,6 +9777,36 @@ loser:
return SECFailure;
}
+static SECStatus
+ssl3_EncodeCertificateRequestSigAlgs(sslSocket *ss, PRUint8 *buf,
+ unsigned maxLen, PRUint32 *len)
+{
+ unsigned int i;
+
+ PORT_Assert(maxLen >= ss->ssl3.signatureAlgorithmCount * 2);
+ if (maxLen < ss->ssl3.signatureAlgorithmCount * 2) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ *len = 0;
+ for (i = 0; i < ss->ssl3.signatureAlgorithmCount; ++i) {
+ const SSLSignatureAndHashAlg *alg = &ss->ssl3.signatureAlgorithms[i];
+ /* Note that we don't support a handshake hash with anything other than
+ * SHA-256, so asking for a signature from clients for something else
+ * would be inviting disaster. */
+ if (alg->hashAlg == ssl_hash_sha256) {
+ buf[(*len)++] = (PRUint8)alg->hashAlg;
+ buf[(*len)++] = (PRUint8)alg->sigAlg;
+ }
+ }
+
+ if (*len == 0) {
+ PORT_SetError(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
static SECStatus
ssl3_SendCertificateRequest(sslSocket *ss)
@@ -9347,7 +9815,6 @@ ssl3_SendCertificateRequest(sslSocket *ss)
SECItem * name;
CERTDistNames *ca_list;
const PRUint8 *certTypes;
- const PRUint8 *sigAlgs;
SECItem * names = NULL;
SECStatus rv;
int length;
@@ -9355,7 +9822,8 @@ ssl3_SendCertificateRequest(sslSocket *ss)
int calen = 0;
int nnames = 0;
int certTypesLength;
- int sigAlgsLength;
+ PRUint8 sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2];
+ unsigned int sigAlgsLength = 0;
SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake",
SSL_GETPID(), ss->fd));
@@ -9382,12 +9850,15 @@ ssl3_SendCertificateRequest(sslSocket *ss)
certTypes = certificate_types;
certTypesLength = sizeof certificate_types;
- sigAlgs = supported_signature_algorithms;
- sigAlgsLength = sizeof supported_signature_algorithms;
length = 1 + certTypesLength + 2 + calen;
if (isTLS12) {
- length += 2 + sigAlgsLength;
+ rv = ssl3_EncodeCertificateRequestSigAlgs(ss, sigAlgs, sizeof(sigAlgs),
+ &sigAlgsLength);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ length += 2 + sigAlgsLength;
}
rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length);
@@ -9453,7 +9924,7 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
int errCode = SSL_ERROR_RX_MALFORMED_CERT_VERIFY;
SSL3AlertDescription desc = handshake_failure;
PRBool isTLS, isTLS12;
- SSL3SignatureAndHashAlgorithm sigAndHash;
+ SSLSignatureAndHashAlg sigAndHash;
SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_verify handshake",
SSL_GETPID(), ss->fd));
@@ -9469,6 +9940,13 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
goto alert_loser;
}
+ if (!hashes) {
+ PORT_Assert(0);
+ desc = internal_error;
+ errCode = SEC_ERROR_LIBRARY_FAILURE;
+ goto alert_loser;
+ }
+
if (isTLS12) {
rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
&sigAndHash);
@@ -9476,7 +9954,7 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
goto loser; /* malformed or unsupported. */
}
rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
- &sigAndHash, ss->sec.peerCert);
+ ss, &sigAndHash, ss->sec.peerCert);
if (rv != SECSuccess) {
errCode = PORT_GetError();
desc = decrypt_error;
@@ -9485,7 +9963,7 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
/* We only support CertificateVerify messages that use the handshake
* hash. */
- if (sigAndHash.hashAlg != hashes->hashAlg) {
+ if (sigAndHash.hashAlg != hashes->hashAlg) {
errCode = SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM;
desc = decrypt_error;
goto alert_loser;
@@ -9616,18 +10094,17 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
PRUint32 length,
SECKEYPrivateKey *serverKey)
{
- PK11SymKey * pms;
#ifndef NO_PKCS11_BYPASS
unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random;
unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random;
ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec;
unsigned int outLen = 0;
-#endif
PRBool isTLS = PR_FALSE;
+ SECItem pmsItem = {siBuffer, NULL, 0};
+ unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
+#endif
SECStatus rv;
SECItem enc_pms;
- unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
- SECItem pmsItem = {siBuffer, NULL, 0};
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
@@ -9635,8 +10112,10 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
enc_pms.data = b;
enc_pms.len = length;
+#ifndef NO_PKCS11_BYPASS
pmsItem.data = rsaPmsBuf;
pmsItem.len = sizeof rsaPmsBuf;
+#endif
if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
PRInt32 kLen;
@@ -9648,13 +10127,24 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
if ((unsigned)kLen < enc_pms.len) {
enc_pms.len = kLen;
}
+#ifndef NO_PKCS11_BYPASS
isTLS = PR_TRUE;
+#endif
} else {
+#ifndef NO_PKCS11_BYPASS
isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0);
+#endif
}
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
+ /* We have not implemented a tls_ExtendedMasterKeyDeriveBypass
+ * and will not negotiate this extension in bypass mode. This
+ * assert just double-checks that.
+ */
+ PORT_Assert(
+ !ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn));
+
/* TRIPLE BYPASS, get PMS directly from RSA decryption.
* Use PK11_PrivDecryptPKCS1 to decrypt the PMS to a buffer,
* then, check for version rollback attack, then
@@ -9682,8 +10172,8 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
}
}
/* have PMS, build MS without PKCS11 */
- rv = ssl3_MasterKeyDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS,
- PR_TRUE);
+ rv = ssl3_MasterSecretDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS,
+ PR_TRUE);
if (rv != SECSuccess) {
pwSpec->msItem.data = pwSpec->raw_master_secret;
pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
@@ -9693,49 +10183,163 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
} else
#endif
{
+ PK11SymKey *tmpPms[2] = {NULL, NULL};
+ PK11SlotInfo *slot;
+ int useFauxPms = 0;
+#define currentPms tmpPms[!useFauxPms]
+#define unusedPms tmpPms[useFauxPms]
+#define realPms tmpPms[1]
+#define fauxPms tmpPms[0]
+
#ifndef NO_PKCS11_BYPASS
double_bypass:
#endif
- /*
- * unwrap pms out of the incoming buffer
- * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do
- * the unwrap. Rather, it is the mechanism with which the
- * unwrapped pms will be used.
- */
- pms = PK11_PubUnwrapSymKey(serverKey, &enc_pms,
- CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0);
- if (pms != NULL) {
- PRINT_BUF(60, (ss, "decrypted premaster secret:",
- PK11_GetKeyData(pms)->data,
- PK11_GetKeyData(pms)->len));
- } else {
- /* unwrap failed. Generate a bogus PMS and carry on. */
- PK11SlotInfo * slot = PK11_GetSlotFromPrivateKey(serverKey);
- ssl_GetSpecWriteLock(ss);
- pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.prSpec, slot);
- ssl_ReleaseSpecWriteLock(ss);
- PK11_FreeSlot(slot);
- }
+ /*
+ * Get as close to algorithm 2 from RFC 5246; Section 7.4.7.1
+ * as we can within the constraints of the PKCS#11 interface.
+ *
+ * 1. Unconditionally generate a bogus PMS (what RFC 5246
+ * calls R).
+ * 2. Attempt the RSA decryption to recover the PMS (what
+ * RFC 5246 calls M).
+ * 3. Set PMS = (M == NULL) ? R : M
+ * 4. Use ssl3_ComputeMasterSecret(PMS) to attempt to derive
+ * the MS from PMS. This includes performing the version
+ * check and length check.
+ * 5. If either the initial RSA decryption failed or
+ * ssl3_ComputeMasterSecret(PMS) failed, then discard
+ * M and set PMS = R. Else, discard R and set PMS = M.
+ *
+ * We do two derivations here because we can't rely on having
+ * a function that only performs the PMS version and length
+ * check. The only redundant cost is that this runs the PRF,
+ * which isn't necessary here.
+ */
+
+ /* Generate the bogus PMS (R) */
+ slot = PK11_GetSlotFromPrivateKey(serverKey);
+ if (!slot) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ if (!PK11_DoesMechanism(slot, CKM_SSL3_MASTER_KEY_DERIVE)) {
+ PK11_FreeSlot(slot);
+ slot = PK11_GetBestSlot(CKM_SSL3_MASTER_KEY_DERIVE, NULL);
+ if (!slot) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ }
- if (pms == NULL) {
- /* last gasp. */
+ ssl_GetSpecWriteLock(ss);
+ fauxPms = ssl3_GenerateRSAPMS(ss, ss->ssl3.prSpec, slot);
+ ssl_ReleaseSpecWriteLock(ss);
+ PK11_FreeSlot(slot);
+
+ if (fauxPms == NULL) {
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
return SECFailure;
}
+ /*
+ * unwrap pms out of the incoming buffer
+ * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do
+ * the unwrap. Rather, it is the mechanism with which the
+ * unwrapped pms will be used.
+ */
+ realPms = PK11_PubUnwrapSymKey(serverKey, &enc_pms,
+ CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0);
+ /* Temporarily use the PMS if unwrapping the real PMS fails. */
+ useFauxPms |= (realPms == NULL);
+
+ /* Attempt to derive the MS from the PMS. This is the only way to
+ * check the version field in the RSA PMS. If this fails, we
+ * then use the faux PMS in place of the PMS. Note that this
+ * operation should never fail if we are using the faux PMS
+ * since it is correctly formatted. */
+ rv = ssl3_ComputeMasterSecret(ss, currentPms, NULL);
+
+ /* If we succeeded, then select the true PMS and discard the
+ * FPMS. Else, select the FPMS and select the true PMS */
+ useFauxPms |= (rv != SECSuccess);
+
+ if (unusedPms) {
+ PK11_FreeSymKey(unusedPms);
+ }
+
/* This step will derive the MS from the PMS, among other things. */
- rv = ssl3_InitPendingCipherSpec(ss, pms);
- PK11_FreeSymKey(pms);
+ rv = ssl3_InitPendingCipherSpec(ss, currentPms);
+ PK11_FreeSymKey(currentPms);
}
if (rv != SECSuccess) {
SEND_ALERT
return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
}
+
+#undef currentPms
+#undef unusedPms
+#undef realPms
+#undef fauxPms
+
return SECSuccess;
}
+static SECStatus
+ssl3_HandleDHClientKeyExchange(sslSocket *ss,
+ SSL3Opaque *b,
+ PRUint32 length,
+ SECKEYPublicKey *srvrPubKey,
+ SECKEYPrivateKey *serverKey)
+{
+ PK11SymKey *pms;
+ SECStatus rv;
+ SECKEYPublicKey clntPubKey;
+ CK_MECHANISM_TYPE target;
+ PRBool isTLS;
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert( srvrPubKey );
+
+ clntPubKey.keyType = dhKey;
+ clntPubKey.u.dh.prime.len = srvrPubKey->u.dh.prime.len;
+ clntPubKey.u.dh.prime.data = srvrPubKey->u.dh.prime.data;
+ clntPubKey.u.dh.base.len = srvrPubKey->u.dh.base.len;
+ clntPubKey.u.dh.base.data = srvrPubKey->u.dh.base.data;
+
+ rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.dh.publicValue,
+ 2, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
+
+ if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
+ else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
+
+ /* Determine the PMS */
+ pms = PK11_PubDerive(serverKey, &clntPubKey, PR_FALSE, NULL, NULL,
+ CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);
+ if (pms == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
+ }
+
+ rv = ssl3_InitPendingCipherSpec(ss, pms);
+ PK11_FreeSymKey(pms); pms = NULL;
+
+loser:
+ if (ss->dheKeyPair) {
+ ssl3_FreeKeyPair(ss->dheKeyPair);
+ ss->dheKeyPair = NULL;
+ }
+ return rv;
+}
+
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
* ssl3 ClientKeyExchange message from the remote client
@@ -9748,9 +10352,7 @@ ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECStatus rv;
const ssl3KEADef *kea_def;
ssl3KeyPair *serverKeyPair = NULL;
-#ifndef NSS_DISABLE_ECC
SECKEYPublicKey *serverPubKey = NULL;
-#endif /* NSS_DISABLE_ECC */
SSL_TRC(3, ("%d: SSL3[%d]: handle client_key_exchange handshake",
SSL_GETPID(), ss->fd));
@@ -9780,6 +10382,16 @@ ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB;
} else
skip:
+ if (kea_def->kea == kea_dhe_dss ||
+ kea_def->kea == kea_dhe_rsa) {
+ if (ss->dheKeyPair) {
+ serverKeyPair = ss->dheKeyPair;
+ if (serverKeyPair->pubKey) {
+ ss->sec.keaKeyBits =
+ SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
+ }
+ }
+ } else
#ifndef NSS_DISABLE_ECC
/* XXX Using SSLKEAType to index server certifiates
* does not work for (EC)DHE ciphers. Until we have
@@ -9825,6 +10437,21 @@ skip:
}
break;
+ case ssl_kea_dh:
+ if (ss->dheKeyPair && ss->dheKeyPair->pubKey) {
+ serverPubKey = ss->dheKeyPair->pubKey;
+ }
+ if (!serverPubKey) {
+ PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
+ return SECFailure;
+ }
+ rv = ssl3_HandleDHClientKeyExchange(ss, b, length,
+ serverPubKey, serverKey);
+ if (rv != SECSuccess) {
+ SSL3_SendAlert(ss, alert_fatal, handshake_failure);
+ return SECFailure; /* error code set */
+ }
+ break;
#ifndef NSS_DISABLE_ECC
case kt_ecdh:
@@ -10454,6 +11081,8 @@ ssl3_AuthCertificate(sslSocket *ss)
ss->ssl3.hs.authCertificatePending = PR_FALSE;
+ PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
+ ssl_preinfo_all);
/*
* Ask caller-supplied callback function to validate cert chain.
*/
@@ -10498,40 +11127,60 @@ ssl3_AuthCertificate(sslSocket *ss)
ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
if (pubKey) {
+ KeyType pubKeyType;
+ PRInt32 minKey;
ss->sec.keaKeyBits = ss->sec.authKeyBits =
SECKEY_PublicKeyStrengthInBits(pubKey);
-#ifndef NSS_DISABLE_ECC
- if (ss->sec.keaType == kt_ecdh) {
- /* Get authKeyBits from signing key.
- * XXX The code below uses a quick approximation of
- * key size based on cert->signatureWrap.signature.data
- * (which contains the DER encoded signature). The field
- * cert->signatureWrap.signature.len contains the
- * length of the encoded signature in bits.
- */
- if (ss->ssl3.hs.kea_def->kea == kea_ecdh_ecdsa) {
- ss->sec.authKeyBits =
- cert->signatureWrap.signature.data[3]*8;
- if (cert->signatureWrap.signature.data[4] == 0x00)
- ss->sec.authKeyBits -= 8;
- /*
- * XXX: if cert is not signed by ecdsa we should
- * destroy pubKey and goto bad_cert
- */
- } else if (ss->ssl3.hs.kea_def->kea == kea_ecdh_rsa) {
- ss->sec.authKeyBits = cert->signatureWrap.signature.len;
- /*
- * XXX: if cert is not signed by rsa we should
- * destroy pubKey and goto bad_cert
- */
+ pubKeyType = SECKEY_GetPublicKeyType(pubKey);
+ minKey = ss->sec.authKeyBits;
+ switch (pubKeyType) {
+ case rsaKey:
+ case rsaPssKey:
+ case rsaOaepKey:
+ rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minKey);
+ if (rv != SECSuccess) {
+ minKey = SSL_RSA_MIN_MODULUS_BITS;
+ }
+ break;
+ case dsaKey:
+ rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minKey);
+ if (rv != SECSuccess) {
+ minKey = SSL_DSA_MIN_P_BITS;
}
+ break;
+ case dhKey:
+ rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minKey);
+ if (rv != SECSuccess) {
+ minKey = SSL_DH_MIN_P_BITS;
+ }
+ break;
+ default:
+ break;
}
-#endif /* NSS_DISABLE_ECC */
+
+ /* Too small: not good enough. Send a fatal alert. */
+ /* We aren't checking EC here on the understanding that we only
+ * support curves we like, a decision that might need revisiting. */
+ if ( ss->sec.authKeyBits < minKey) {
+ PORT_SetError(SSL_ERROR_WEAK_SERVER_CERT_KEY);
+ (void)SSL3_SendAlert(ss, alert_fatal,
+ ss->version >= SSL_LIBRARY_VERSION_TLS_1_0
+ ? insufficient_security
+ : illegal_parameter);
+ SECKEY_DestroyPublicKey(pubKey);
+ return SECFailure;
+ }
SECKEY_DestroyPublicKey(pubKey);
pubKey = NULL;
}
- if (ss->ssl3.hs.kea_def->ephemeral) {
+ /* Ephemeral suites require ServerKeyExchange. Export cipher suites
+ * with RSA key exchange also require ServerKeyExchange if the
+ * authentication key exceeds the key size limit. */
+ if (ss->ssl3.hs.kea_def->ephemeral ||
+ (ss->ssl3.hs.kea_def->is_limited &&
+ ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_rsa &&
+ ss->sec.authKeyBits > ss->ssl3.hs.kea_def->key_size_limit)) {
ss->ssl3.hs.ws = wait_server_key; /* require server_key_exchange */
} else {
ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */
@@ -10643,16 +11292,42 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
const SSL3Hashes * hashes,
TLSFinished * tlsFinished)
{
- const char * label;
- unsigned int len;
- SECStatus rv;
+ SECStatus rv;
+ CK_TLS_MAC_PARAMS tls_mac_params;
+ SECItem param = {siBuffer, NULL, 0};
+ PK11Context *prf_context;
+ unsigned int retLen;
- label = isServer ? "server finished" : "client finished";
- len = 15;
+ if (!spec->master_secret || spec->bypassCiphers) {
+ const char *label = isServer ? "server finished" : "client finished";
+ unsigned int len = 15;
- rv = ssl3_TLSPRFWithMasterSecret(spec, label, len, hashes->u.raw,
- hashes->len, tlsFinished->verify_data,
- sizeof tlsFinished->verify_data);
+ return ssl3_TLSPRFWithMasterSecret(spec, label, len, hashes->u.raw,
+ hashes->len, tlsFinished->verify_data,
+ sizeof tlsFinished->verify_data);
+ }
+
+ if (spec->version < SSL_LIBRARY_VERSION_TLS_1_2) {
+ tls_mac_params.prfMechanism = CKM_TLS_PRF;
+ } else {
+ tls_mac_params.prfMechanism = CKM_SHA256;
+ }
+ tls_mac_params.ulMacLength = 12;
+ tls_mac_params.ulServerOrClient = isServer ? 1 : 2;
+ param.data = (unsigned char *)&tls_mac_params;
+ param.len = sizeof(tls_mac_params);
+ prf_context = PK11_CreateContextBySymKey(CKM_TLS_MAC, CKA_SIGN,
+ spec->master_secret, &param);
+ if (!prf_context)
+ return SECFailure;
+
+ rv = PK11_DigestBegin(prf_context);
+ rv |= PK11_DigestOp(prf_context, hashes->u.raw, hashes->len);
+ rv |= PK11_DigestFinal(prf_context, tlsFinished->verify_data, &retLen,
+ sizeof tlsFinished->verify_data);
+ PORT_Assert(rv != SECSuccess || retLen == sizeof tlsFinished->verify_data);
+
+ PK11_DestroyContext(prf_context, PR_TRUE);
return rv;
}
@@ -11170,6 +11845,13 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
return SECFailure;
}
+ if (!hashes) {
+ PORT_Assert(0);
+ SSL3_SendAlert(ss, alert_fatal, internal_error);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0);
if (isTLS) {
TLSFinished tlsFinished;
@@ -11225,7 +11907,8 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
* ServerHello message.)
*/
if (isServer && !ss->ssl3.hs.isResuming &&
- ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) {
+ ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) &&
+ ssl3_KEAAllowsSessionTicket(ss->ssl3.hs.suite_def->key_exchange_alg)) {
/* RFC 5077 Section 3.3: "In the case of a full handshake, the
* server MUST verify the client's Finished message before sending
* the ticket." Presumably, this also means that the client's
@@ -11278,7 +11961,8 @@ xmit_loser:
return rv;
}
- if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
+ if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
+ ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) {
effectiveExchKeyType = kt_rsa;
} else {
effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
@@ -11398,6 +12082,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECStatus rv = SECSuccess;
SSL3HandshakeType type = ss->ssl3.hs.msg_type;
SSL3Hashes hashes; /* computed hashes are put here. */
+ SSL3Hashes *hashesPtr = NULL; /* Set when hashes are computed */
PRUint8 hdr[4];
PRUint8 dtlsData[8];
@@ -11408,7 +12093,8 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
* current message.
*/
ssl_GetSpecReadLock(ss); /************************************/
- if((type == finished) || (type == certificate_verify)) {
+ if(((type == finished) && (ss->ssl3.hs.ws == wait_finished)) ||
+ ((type == certificate_verify) && (ss->ssl3.hs.ws == wait_cert_verify))) {
SSL3Sender sender = (SSL3Sender)0;
ssl3CipherSpec *rSpec = ss->ssl3.prSpec;
@@ -11417,6 +12103,9 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
rSpec = ss->ssl3.crSpec;
}
rv = ssl3_ComputeHandshakeHashes(ss, rSpec, &hashes, sender);
+ if (rv == SECSuccess) {
+ hashesPtr = &hashes;
+ }
}
ssl_ReleaseSpecReadLock(ss); /************************************/
if (rv != SECSuccess) {
@@ -11567,7 +12256,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY);
return SECFailure;
}
- rv = ssl3_HandleCertificateVerify(ss, b, length, &hashes);
+ rv = ssl3_HandleCertificateVerify(ss, b, length, hashesPtr);
break;
case client_key_exchange:
if (!ss->sec.isServer) {
@@ -11586,7 +12275,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
rv = ssl3_HandleNewSessionTicket(ss, b, length);
break;
case finished:
- rv = ssl3_HandleFinished(ss, b, length, &hashes);
+ rv = ssl3_HandleFinished(ss, b, length, hashesPtr);
break;
default:
(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
@@ -11641,7 +12330,7 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
if (ss->ssl3.hs.msg_len > MAX_HANDSHAKE_MSG_LEN) {
(void)ssl3_DecodeError(ss);
- PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
return SECFailure;
}
#undef MAX_HANDSHAKE_MSG_LEN
@@ -11942,7 +12631,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
SSL3Opaque *givenHash;
sslBuffer *plaintext;
sslBuffer temp_buf;
- PRUint64 dtls_seq_num;
+ PRUint64 dtls_seq_num = 0;
unsigned int ivLen = 0;
unsigned int originalLen = 0;
unsigned int good;
@@ -12423,6 +13112,7 @@ ssl3_InitState(sslSocket *ss)
ss->ssl3.hs.sendingSCSV = PR_FALSE;
ssl3_InitCipherSpec(ss, ss->ssl3.crSpec);
ssl3_InitCipherSpec(ss, ss->ssl3.prSpec);
+ ss->ssl3.hs.preliminaryInfo = 0;
ss->ssl3.hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello;
#ifndef NSS_DISABLE_ECC
@@ -12496,8 +13186,6 @@ ssl3_FreeKeyPair(ssl3KeyPair * keyPair)
}
}
-
-
/*
* Creates the public and private RSA keys for SSL Step down.
* Called from SSL_ConfigSecureServer in sslsecur.c
@@ -12529,7 +13217,6 @@ ssl3_CreateRSAStepDownKeys(sslSocket *ss)
return rv;
}
-
/* record the export policy for this cipher suite */
SECStatus
ssl3_SetPolicy(ssl3CipherSuite which, int policy)
@@ -12631,6 +13318,79 @@ ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled)
}
SECStatus
+SSL_SignaturePrefSet(PRFileDesc *fd, const SSLSignatureAndHashAlg *algorithms,
+ unsigned int count)
+{
+ sslSocket *ss;
+ unsigned int i;
+
+ ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SignaturePrefSet",
+ SSL_GETPID(), fd));
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!count || count > MAX_SIGNATURE_ALGORITHMS) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ ss->ssl3.signatureAlgorithmCount = 0;
+ for (i = 0; i < count; ++i) {
+ if (!ssl3_IsSupportedSignatureAlgorithm(&algorithms[i])) {
+ SSL_DBG(("%d: SSL[%d]: invalid signature algorithm set %d/%d",
+ SSL_GETPID(), fd, algorithms[i].sigAlg,
+ algorithms[i].hashAlg));
+ continue;
+ }
+
+ ss->ssl3.signatureAlgorithms[ss->ssl3.signatureAlgorithmCount++] =
+ algorithms[i];
+ }
+
+ if (ss->ssl3.signatureAlgorithmCount == 0) {
+ PORT_SetError(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+SSL_SignaturePrefGet(PRFileDesc *fd, SSLSignatureAndHashAlg *algorithms,
+ unsigned int *count, unsigned int maxCount)
+{
+ sslSocket *ss;
+ unsigned int requiredSpace;
+
+ ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SignaturePrefGet",
+ SSL_GETPID(), fd));
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!algorithms || !count ||
+ maxCount < ss->ssl3.signatureAlgorithmCount) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ requiredSpace =
+ ss->ssl3.signatureAlgorithmCount * sizeof(SSLSignatureAndHashAlg);
+ PORT_Memcpy(algorithms, ss->ssl3.signatureAlgorithms, requiredSpace);
+ *count = ss->ssl3.signatureAlgorithmCount;
+ return SECSuccess;
+}
+
+unsigned int
+SSL_SignatureMaxCount() {
+ return MAX_SIGNATURE_ALGORITHMS;
+}
+
+SECStatus
ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int len)
{
/* |i| iterates over |ciphers| while |done| and |j| iterate over
@@ -12675,6 +13435,9 @@ void
ssl3_InitSocketPolicy(sslSocket *ss)
{
PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites);
+ PORT_Memcpy(ss->ssl3.signatureAlgorithms, defaultSignatureAlgorithms,
+ sizeof(defaultSignatureAlgorithms));
+ ss->ssl3.signatureAlgorithmCount = PR_ARRAY_SIZE(defaultSignatureAlgorithms);
}
SECStatus
@@ -12764,7 +13527,7 @@ ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, unsigned char *cs, int *size)
/* ssl3_config_match_init was called by the caller of this function. */
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
- if (config_match(suite, SSL_ALLOWED, PR_TRUE, &ss->vrange)) {
+ if (config_match(suite, SSL_ALLOWED, PR_TRUE, &ss->vrange, ss)) {
if (cs != NULL) {
*cs++ = 0x00;
*cs++ = (suite->cipher_suite >> 8) & 0xFF;
@@ -12898,6 +13661,10 @@ ssl3_DestroySSL3Info(sslSocket *ss)
}
}
+ if (ss->ssl3.dheGroups) {
+ PORT_Free(ss->ssl3.dheGroups);
+ }
+
ss->ssl3.initialized = PR_FALSE;
SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
« no previous file with comments | « net/third_party/nss/ssl/ssl.h ('k') | net/third_party/nss/ssl/ssl3ecc.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698