Index: net/third_party/nss/ssl/ssl3con.c |
=================================================================== |
--- net/third_party/nss/ssl/ssl3con.c (revision 242942) |
+++ net/third_party/nss/ssl/ssl3con.c (working copy) |
@@ -111,98 +111,117 @@ |
* precedence (desirability). It only includes cipher suites we implement. |
* This table is modified by SSL3_SetPolicy(). The ordering of cipher suites |
* in this table must match the ordering in SSL_ImplementedCiphers (sslenum.c) |
+ * |
+ * Important: See bug 946147 before enabling, reordering, or adding any cipher |
+ * suites to this list. |
*/ |
static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = { |
- /* cipher_suite policy enabled is_present*/ |
-#ifdef NSS_ENABLE_ECC |
- { TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
-#endif /* NSS_ENABLE_ECC */ |
- { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
- { TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
+ /* cipher_suite policy enabled isPresent */ |
#ifdef NSS_ENABLE_ECC |
- { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
+ { 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_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_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}, |
+ { TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
#endif /* NSS_ENABLE_ECC */ |
- { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
- { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
- { TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
-#ifdef NSS_ENABLE_ECC |
- { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
-#endif /* NSS_ENABLE_ECC */ |
- { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
- { TLS_RSA_WITH_AES_256_CBC_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
-#ifdef NSS_ENABLE_ECC |
- { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
-#endif /* NSS_ENABLE_ECC */ |
- { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
- { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
- { TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
-#ifdef NSS_ENABLE_ECC |
- { TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
-#endif /* NSS_ENABLE_ECC */ |
- { TLS_RSA_WITH_SEED_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { SSL_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
- { SSL_RSA_WITH_RC4_128_MD5, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
- { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
- { TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
+ { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, 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_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_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}, |
+ { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
#ifdef NSS_ENABLE_ECC |
- { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
+ { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
#endif /* NSS_ENABLE_ECC */ |
- { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
- { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
-#ifdef NSS_ENABLE_ECC |
- { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
-#endif /* NSS_ENABLE_ECC */ |
- { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
- { SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
+ /* RSA */ |
+ { TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { TLS_RSA_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_RSA_WITH_SEED_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { SSL_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { SSL_RSA_WITH_RC4_128_MD5, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
- { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
- { SSL_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
- { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
- { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
+ /* 56-bit DES "domestic" cipher suites */ |
+ { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { SSL_RSA_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
- { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
- { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
+ /* export ciphersuites with 1024-bit public key exchange keys */ |
+ { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ /* export ciphersuites with 512-bit public key exchange keys */ |
+ { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ |
+ /* ciphersuites with no encryption */ |
#ifdef NSS_ENABLE_ECC |
- { TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
- { TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
- { TLS_ECDH_RSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
- { TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDH_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
#endif /* NSS_ENABLE_ECC */ |
- { SSL_RSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_RSA_WITH_NULL_SHA256, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { SSL_RSA_WITH_NULL_MD5, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- |
+ { SSL_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_RSA_WITH_NULL_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
}; |
+/* Verify that SSL_ImplementedCiphers and cipherSuites are in consistent order. |
+ */ |
+#ifdef DEBUG |
+void ssl3_CheckCipherSuiteOrderConsistency() |
+{ |
+ unsigned int i; |
+ |
+ /* Note that SSL_ImplementedCiphers has more elements than cipherSuites |
+ * because it SSL_ImplementedCiphers includes SSL 2.0 cipher suites. |
+ */ |
+ PORT_Assert(SSL_NumImplementedCiphers >= PR_ARRAY_SIZE(cipherSuites)); |
+ |
+ for (i = 0; i < PR_ARRAY_SIZE(cipherSuites); ++i) { |
+ PORT_Assert(SSL_ImplementedCiphers[i] == cipherSuites[i].cipher_suite); |
+ } |
+} |
+#endif |
+ |
/* This list of SSL3 compression methods is sorted in descending order of |
* precedence (desirability). It only includes compression methods we |
* implement. |
@@ -494,8 +513,6 @@ |
#define mmech_md5_hmac CKM_MD5_HMAC |
#define mmech_sha_hmac CKM_SHA_1_HMAC |
#define mmech_sha256_hmac CKM_SHA256_HMAC |
-#define mmech_sha384_hmac CKM_SHA384_HMAC |
-#define mmech_sha512_hmac CKM_SHA512_HMAC |
static const ssl3MACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */ |
/* pad_size is only used for SSL 3.0 MAC. See RFC 6101 Sec. 5.2.3.1. */ |
@@ -839,7 +856,7 @@ |
int i, count = 0; |
if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { |
- return 0; |
+ return 0; |
} |
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { |
if (config_match(&ss->cipherSuites[i], policy, enabled, &ss->vrange)) |
@@ -905,16 +922,10 @@ |
static SECStatus |
ssl3_GetNewRandom(SSL3Random *random) |
{ |
- PRUint32 gmt = ssl_Time(); |
SECStatus rv; |
- random->rand[0] = (unsigned char)(gmt >> 24); |
- random->rand[1] = (unsigned char)(gmt >> 16); |
- random->rand[2] = (unsigned char)(gmt >> 8); |
- random->rand[3] = (unsigned char)(gmt); |
- |
/* first 4 bytes are reserverd for time */ |
- rv = PK11_GenerateRandom(&random->rand[4], SSL3_RANDOM_LENGTH - 4); |
+ rv = PK11_GenerateRandom(random->rand, SSL3_RANDOM_LENGTH); |
if (rv != SECSuccess) { |
ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE); |
} |
@@ -1052,7 +1063,7 @@ |
} |
/* Allow DER encoded DSA signatures in SSL 3.0 */ |
if (isTLS || buf->len != SECKEY_SignatureLen(key)) { |
- signature = DSAU_DecodeDerSig(buf); |
+ signature = DSAU_DecodeDerSigToLen(buf, SECKEY_SignatureLen(key)); |
if (!signature) { |
PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); |
return SECFailure; |
@@ -1637,7 +1648,7 @@ |
calg = cipher_def->calg; |
- if (calg == calg_aes_gcm) { |
+ if (calg == ssl_calg_aes_gcm) { |
pwSpec->encode = NULL; |
pwSpec->decode = NULL; |
pwSpec->destroy = NULL; |
@@ -1753,6 +1764,7 @@ |
case ssl_calg_rc2: |
case ssl_calg_idea: |
case ssl_calg_fortezza: |
+ case ssl_calg_aes_gcm: |
break; |
} |
@@ -2506,20 +2518,6 @@ |
return rv; |
} |
-/* This is a bodge to allow this code to be compiled against older NSS headers |
- * that don't contain the CBC constant-time changes. */ |
-#ifndef CKM_NSS_HMAC_CONSTANT_TIME |
-#define CKM_NSS_HMAC_CONSTANT_TIME (CKM_NSS + 19) |
-#define CKM_NSS_SSL3_MAC_CONSTANT_TIME (CKM_NSS + 20) |
- |
-typedef struct CK_NSS_MAC_CONSTANT_TIME_PARAMS { |
- CK_MECHANISM_TYPE macAlg; /* in */ |
- CK_ULONG ulBodyTotalLen; /* in */ |
- CK_BYTE * pHeader; /* in */ |
- CK_ULONG ulHeaderLen; /* in */ |
-} CK_NSS_MAC_CONSTANT_TIME_PARAMS; |
-#endif |
- |
/* Called from: ssl3_HandleRecord() |
* Caller must already hold the SpecReadLock. (wish we could assert that!) |
* |
@@ -2540,8 +2538,7 @@ |
{ |
CK_MECHANISM_TYPE macType; |
CK_NSS_MAC_CONSTANT_TIME_PARAMS params; |
- PK11Context * mac_context; |
- SECItem param; |
+ SECItem param, inputItem, outputItem; |
SECStatus rv; |
PK11SymKey * key; |
@@ -2573,27 +2570,34 @@ |
param.len = sizeof(params); |
param.type = 0; |
+ inputItem.data = (unsigned char *) input; |
+ inputItem.len = inputLen; |
+ inputItem.type = 0; |
+ |
+ outputItem.data = outbuf; |
+ outputItem.len = *outLen; |
+ outputItem.type = 0; |
+ |
key = spec->server.write_mac_key; |
if (!useServerMacKey) { |
key = spec->client.write_mac_key; |
} |
- mac_context = PK11_CreateContextBySymKey(macType, CKA_SIGN, key, ¶m); |
- if (mac_context == NULL) { |
- /* Older versions of NSS may not support constant-time MAC. */ |
- goto fallback; |
- } |
- rv = PK11_DigestBegin(mac_context); |
- rv |= PK11_DigestOp(mac_context, input, inputLen); |
- rv |= PK11_DigestFinal(mac_context, outbuf, outLen, spec->mac_size); |
- PK11_DestroyContext(mac_context, PR_TRUE); |
+ rv = PK11_SignWithSymKey(key, macType, ¶m, &outputItem, &inputItem); |
+ if (rv != SECSuccess) { |
+ if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) { |
+ goto fallback; |
+ } |
- PORT_Assert(rv != SECSuccess || *outLen == (unsigned)spec->mac_size); |
- |
- if (rv != SECSuccess) { |
+ *outLen = 0; |
rv = SECFailure; |
ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); |
+ return rv; |
} |
+ |
+ PORT_Assert(outputItem.len == (unsigned)spec->mac_size); |
+ *outLen = outputItem.len; |
+ |
return rv; |
fallback: |
@@ -2876,8 +2880,8 @@ |
* addition, if the record layer version number of ClientHello is { 3, 2 } |
* (TLS 1.1) or higher, these servers reset the TCP connections. Lastly, |
* some F5 BIG-IP servers hang if a record containing a ClientHello has a |
- * version greater than 0x0301 and a length greater than 255. Set this flag |
- * to work around such servers. |
+ * version greater than { 3, 1 } and a length greater than 255. Set this |
+ * flag to work around such servers. |
*/ |
PRInt32 |
ssl3_SendRecord( sslSocket * ss, |
@@ -4017,15 +4021,23 @@ |
return SECFailure; |
} |
- /* A backup SHA-1 hash for a potential client auth signature. */ |
+ /* Create a backup SHA-1 hash for a potential client auth |
+ * signature. |
+ * |
+ * In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the |
+ * handshake hash function (SHA-256). If the server or the client |
+ * does not support SHA-256 as a signature hash, we can either |
+ * maintain a backup SHA-1 handshake hash or buffer all handshake |
+ * messages. |
+ */ |
if (!ss->sec.isServer) { |
- ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_SHA1); |
- if (ss->ssl3.hs.md5 == NULL) { |
+ ss->ssl3.hs.backupHash = PK11_CreateDigestContext(SEC_OID_SHA1); |
+ if (ss->ssl3.hs.backupHash == NULL) { |
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
return SECFailure; |
} |
- if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) { |
+ if (PK11_DigestBegin(ss->ssl3.hs.backupHash) != SECSuccess) { |
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
return SECFailure; |
} |
@@ -4140,8 +4152,8 @@ |
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
return rv; |
} |
- if (ss->ssl3.hs.md5) { |
- rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l); |
+ if (ss->ssl3.hs.backupHash) { |
+ rv = PK11_DigestOp(ss->ssl3.hs.backupHash, b, l); |
if (rv != SECSuccess) { |
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
return rv; |
@@ -4902,9 +4914,10 @@ |
SECStatus rv = SECSuccess; |
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
+ PORT_Assert( !ss->sec.isServer ); |
PORT_Assert( ss->ssl3.hs.hashType == handshake_hash_single ); |
- rv = PK11_DigestFinal(ss->ssl3.hs.md5, hashes->u.raw, &hashes->len, |
+ rv = PK11_DigestFinal(ss->ssl3.hs.backupHash, hashes->u.raw, &hashes->len, |
sizeof(hashes->u.raw)); |
if (rv != SECSuccess) { |
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
@@ -4914,8 +4927,8 @@ |
hashes->hashAlg = SEC_OID_SHA1; |
loser: |
- PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); |
- ss->ssl3.hs.md5 = NULL; |
+ PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE); |
+ ss->ssl3.hs.backupHash = NULL; |
return rv; |
} |
@@ -4995,6 +5008,9 @@ |
ss->ssl3.hs.sendingSCSV = PR_FALSE; /* Must be reset every handshake */ |
PORT_Assert(IS_DTLS(ss) || !resending); |
+ SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE); |
+ ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE; |
+ |
/* We might be starting a session renegotiation in which case we should |
* clear previous state. |
*/ |
@@ -5119,11 +5135,6 @@ |
requestingResume = PR_TRUE; |
SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_hits ); |
- /* Are we attempting a stateless session resume? */ |
- if (sid->version > SSL_LIBRARY_VERSION_3_0 && |
- sid->u.ssl3.sessionTicket.ticket.data) |
- SSL_AtomicIncrementLong(& ssl3stats.sch_sid_stateless_resumes ); |
- |
PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl3.sessionID, |
sid->u.ssl3.sessionIDLength)); |
@@ -5192,12 +5203,24 @@ |
ss->ssl3.hs.sendingSCSV = PR_TRUE; |
} |
+ /* When we attempt session resumption (only), we must lock the sid to |
+ * prevent races with other resumption connections that receive a |
+ * NewSessionTicket that will cause the ticket in the sid to be replaced. |
+ * Once we've copied the session ticket into our ClientHello message, it |
+ * is OK for the ticket to change, so we just need to make sure we hold |
+ * the lock across the calls to ssl3_CallHelloExtensionSenders. |
+ */ |
+ if (sid->u.ssl3.lock) { |
+ PR_RWLock_Rlock(sid->u.ssl3.lock); |
+ } |
+ |
if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) { |
PRUint32 maxBytes = 65535; /* 2^16 - 1 */ |
PRInt32 extLen; |
extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, NULL); |
if (extLen < 0) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return SECFailure; |
} |
maxBytes -= extLen; |
@@ -5224,8 +5247,10 @@ |
/* how many suites are permitted by policy and user preference? */ |
num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE); |
- if (!num_suites) |
+ if (!num_suites) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return SECFailure; /* count_cipher_suites has set error code. */ |
+ } |
fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume || |
ss->version < sid->version); |
@@ -5268,6 +5293,7 @@ |
rv = ssl3_AppendHandshakeHeader(ss, client_hello, length); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
@@ -5286,18 +5312,21 @@ |
rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2); |
} |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
if (!resending) { /* Don't re-generate if we are in DTLS re-sending mode */ |
rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by GetNewRandom. */ |
} |
} |
rv = ssl3_AppendHandshake(ss, &ss->ssl3.hs.client_random, |
SSL3_RANDOM_LENGTH); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
@@ -5307,6 +5336,7 @@ |
else |
rv = ssl3_AppendHandshakeVariable(ss, NULL, 0, 1); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
@@ -5314,12 +5344,14 @@ |
rv = ssl3_AppendHandshakeVariable( |
ss, ss->ssl3.hs.cookie, ss->ssl3.hs.cookieLen, 1); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
} |
rv = ssl3_AppendHandshakeNumber(ss, num_suites*sizeof(ssl3CipherSuite), 2); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
@@ -5328,6 +5360,7 @@ |
rv = ssl3_AppendHandshakeNumber(ss, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, |
sizeof(ssl3CipherSuite)); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
actual_count++; |
@@ -5336,6 +5369,7 @@ |
rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV, |
sizeof(ssl3CipherSuite)); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
actual_count++; |
@@ -5345,6 +5379,7 @@ |
if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange)) { |
actual_count++; |
if (actual_count > num_suites) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
/* set error card removal/insertion error */ |
PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); |
return SECFailure; |
@@ -5352,6 +5387,7 @@ |
rv = ssl3_AppendHandshakeNumber(ss, suite->cipher_suite, |
sizeof(ssl3CipherSuite)); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
} |
@@ -5362,12 +5398,14 @@ |
* the server.. */ |
if (actual_count != num_suites) { |
/* Card removal/insertion error */ |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); |
return SECFailure; |
} |
rv = ssl3_AppendHandshakeNumber(ss, numCompressionMethods, 1); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
for (i = 0; i < compressionMethodsCount; i++) { |
@@ -5375,6 +5413,7 @@ |
continue; |
rv = ssl3_AppendHandshakeNumber(ss, compressions[i], 1); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by ssl3_AppendHandshake* */ |
} |
} |
@@ -5385,23 +5424,35 @@ |
rv = ssl3_AppendHandshakeNumber(ss, maxBytes, 2); |
if (rv != SECSuccess) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return rv; /* err set by AppendHandshake. */ |
} |
extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL); |
if (extLen < 0) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return SECFailure; |
} |
maxBytes -= extLen; |
extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes); |
if (extLen < 0) { |
+ if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
return SECFailure; |
} |
maxBytes -= extLen; |
PORT_Assert(!maxBytes); |
} |
+ |
+ if (sid->u.ssl3.lock) { |
+ PR_RWLock_Unlock(sid->u.ssl3.lock); |
+ } |
+ |
+ if (ss->xtnData.sentSessionTicketInClientHello) { |
+ SSL_AtomicIncrementLong(&ssl3stats.sch_sid_stateless_resumes); |
+ } |
+ |
if (ss->ssl3.hs.sendingSCSV) { |
/* Since we sent the SCSV, pretend we sent empty RI extension. */ |
TLSExtensionData *xtnData = &ss->xtnData; |
@@ -6208,14 +6259,10 @@ |
SSL_GETPID(), ss->fd)); |
ssl_GetSpecReadLock(ss); |
- /* In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the handshake hash |
- * function (SHA-256). If the server or the client does not support SHA-256 |
- * as a signature hash, we can either maintain a backup SHA-1 handshake |
- * hash or buffer all handshake messages. |
- */ |
- if (ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) { |
+ if (ss->ssl3.hs.hashType == handshake_hash_single && |
+ ss->ssl3.hs.backupHash) { |
rv = ssl3_ComputeBackupHandshakeHashes(ss, &hashes); |
- PORT_Assert(ss->ssl3.hs.md5 == NULL); |
+ PORT_Assert(!ss->ssl3.hs.backupHash); |
} else { |
rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0); |
} |
@@ -6611,8 +6658,7 @@ |
SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits ); |
/* If we sent a session ticket, then this is a stateless resume. */ |
- if (sid->version > SSL_LIBRARY_VERSION_3_0 && |
- sid->u.ssl3.sessionTicket.ticket.data != NULL) |
+ if (ss->xtnData.sentSessionTicketInClientHello) |
SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes ); |
if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) |
@@ -7037,7 +7083,7 @@ |
*preferSha1 = PR_FALSE; |
} |
- done: |
+done: |
if (pubk) |
SECKEY_DestroyPublicKey(pubk); |
return rv; |
@@ -7059,7 +7105,14 @@ |
PRBool needBackupHash = PR_FALSE; |
unsigned int i; |
- PORT_Assert(ss->ssl3.hs.md5); |
+#ifndef NO_PKCS11_BYPASS |
+ /* Backup handshake hash is not supported in PKCS #11 bypass mode. */ |
+ if (ss->opt.bypassPKCS11) { |
+ PORT_Assert(!ss->ssl3.hs.backupHash); |
+ return; |
+ } |
+#endif |
+ PORT_Assert(ss->ssl3.hs.backupHash); |
/* Determine the key's signature algorithm and whether it prefers SHA-1. */ |
rv = ssl3_ExtractClientKeyInfo(ss, &sigAlg, &preferSha1); |
@@ -7086,8 +7139,8 @@ |
done: |
if (!needBackupHash) { |
- PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); |
- ss->ssl3.hs.md5 = NULL; |
+ PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE); |
+ ss->ssl3.hs.backupHash = NULL; |
} |
} |
@@ -7283,7 +7336,7 @@ |
} |
goto send_no_certificate; |
} |
- if (isTLS12) { |
+ if (ss->ssl3.hs.hashType == handshake_hash_single) { |
ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms); |
} |
break; /* not an error */ |
@@ -7311,17 +7364,13 @@ |
ss->ssl3.clientCertificate, |
certUsageSSLClient, PR_FALSE); |
if (ss->ssl3.clientCertChain == NULL) { |
- if (ss->ssl3.clientCertificate != NULL) { |
- CERT_DestroyCertificate(ss->ssl3.clientCertificate); |
- ss->ssl3.clientCertificate = NULL; |
- } |
- if (ss->ssl3.clientPrivateKey != NULL) { |
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); |
- ss->ssl3.clientPrivateKey = NULL; |
- } |
+ CERT_DestroyCertificate(ss->ssl3.clientCertificate); |
+ ss->ssl3.clientCertificate = NULL; |
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); |
+ ss->ssl3.clientPrivateKey = NULL; |
goto send_no_certificate; |
} |
- if (isTLS12) { |
+ if (ss->ssl3.hs.hashType == handshake_hash_single) { |
ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms); |
} |
break; /* not an error */ |
@@ -7559,10 +7608,11 @@ |
ss->ssl3.clientPrivateKey != NULL); |
if (!sendClientCert && |
- ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) { |
+ ss->ssl3.hs.hashType == handshake_hash_single && |
+ ss->ssl3.hs.backupHash) { |
/* Don't need the backup handshake hash. */ |
- PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); |
- ss->ssl3.hs.md5 = NULL; |
+ PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE); |
+ ss->ssl3.hs.backupHash = NULL; |
} |
/* We must wait for the server's certificate to be authenticated before |
@@ -8331,7 +8381,7 @@ |
goto alert_loser; |
suite_found: |
- /* Look for a matching compression algorithm. */ |
+ /* Select a compression algorithm. */ |
for (i = 0; i < comps.len; i++) { |
if (!compressionEnabled(ss, comps.data[i])) |
continue; |
@@ -9773,8 +9823,8 @@ |
SECStatus |
ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
{ |
- SECStatus rv; |
- NewSessionTicket session_ticket; |
+ SECStatus rv; |
+ SECItem ticketData; |
SSL_TRC(3, ("%d: SSL3[%d]: handle session_ticket handshake", |
SSL_GETPID(), ss->fd)); |
@@ -9782,35 +9832,41 @@ |
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
+ PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data); |
+ PORT_Assert(!ss->ssl3.hs.receivedNewSessionTicket); |
+ |
if (ss->ssl3.hs.ws != wait_new_session_ticket) { |
SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET); |
return SECFailure; |
} |
- session_ticket.received_timestamp = ssl_Time(); |
+ /* RFC5077 Section 3.3: "The client MUST NOT treat the ticket as valid |
+ * until it has verified the server's Finished message." See the comment in |
+ * ssl3_FinishHandshake for more details. |
+ */ |
+ ss->ssl3.hs.newSessionTicket.received_timestamp = ssl_Time(); |
if (length < 4) { |
(void)SSL3_SendAlert(ss, alert_fatal, decode_error); |
PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET); |
return SECFailure; |
} |
- session_ticket.ticket_lifetime_hint = |
+ ss->ssl3.hs.newSessionTicket.ticket_lifetime_hint = |
(PRUint32)ssl3_ConsumeHandshakeNumber(ss, 4, &b, &length); |
- rv = ssl3_ConsumeHandshakeVariable(ss, &session_ticket.ticket, 2, |
- &b, &length); |
+ rv = ssl3_ConsumeHandshakeVariable(ss, &ticketData, 2, &b, &length); |
if (length != 0 || rv != SECSuccess) { |
(void)SSL3_SendAlert(ss, alert_fatal, decode_error); |
PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET); |
return SECFailure; /* malformed */ |
} |
- |
- rv = ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &session_ticket); |
+ rv = SECITEM_CopyItem(NULL, &ss->ssl3.hs.newSessionTicket.ticket, |
+ &ticketData); |
if (rv != SECSuccess) { |
- (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure); |
- PORT_SetError(SSL_ERROR_INTERNAL_ERROR_ALERT); |
- return SECFailure; |
+ return rv; |
} |
+ ss->ssl3.hs.receivedNewSessionTicket = PR_TRUE; |
+ |
ss->ssl3.hs.ws = wait_change_cipher; |
return SECSuccess; |
} |
@@ -10501,14 +10557,11 @@ |
SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with" |
" peer's finished message", SSL_GETPID(), ss->fd)); |
- PORT_Assert(!ss->firstHsDone); |
- PORT_Assert(!ss->sec.isServer); |
PORT_Assert(!ss->ssl3.hs.isResuming); |
PORT_Assert(ss->ssl3.hs.ws != idle_handshake); |
if (ss->opt.enableFalseStart && |
!ss->firstHsDone && |
- !ss->sec.isServer && |
!ss->ssl3.hs.isResuming && |
ssl3_WaitingForStartOfServerSecondRound(ss)) { |
/* ssl3_SendClientSecondRound deferred the false start check because |
@@ -10607,7 +10660,8 @@ |
return rv; |
} |
-/* called from ssl3_HandleServerHelloDone |
+/* called from ssl3_SendClientSecondRound |
+ * ssl3_HandleFinished |
*/ |
static SECStatus |
ssl3_SendNextProto(sslSocket *ss) |
@@ -10880,7 +10934,7 @@ |
return SECSuccess; |
} |
-/* called from ssl3_HandleServerHelloDone |
+/* called from ssl3_SendClientSecondRound |
* ssl3_HandleClientHello |
* ssl3_HandleFinished |
*/ |
@@ -11116,6 +11170,11 @@ |
*/ |
if (isServer && !ss->ssl3.hs.isResuming && |
ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) { |
+ /* 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 |
+ * certificate, if any, must be verified beforehand too. |
+ */ |
rv = ssl3_SendNewSessionTicket(ss); |
if (rv != SECSuccess) { |
goto xmit_loser; |
@@ -11240,7 +11299,27 @@ |
/* The first handshake is now completed. */ |
ss->handshake = NULL; |
+ /* RFC 5077 Section 3.3: "The client MUST NOT treat the ticket as valid |
+ * until it has verified the server's Finished message." When the server |
+ * sends a NewSessionTicket in a resumption handshake, we must wait until |
+ * the handshake is finished (we have verified the server's Finished |
+ * AND the server's certificate) before we update the ticket in the sid. |
+ * |
+ * This must be done before we call (*ss->sec.cache)(ss->sec.ci.sid) |
+ * because CacheSID requires the session ticket to already be set, and also |
+ * because of the lazy lock creation scheme used by CacheSID and |
+ * ssl3_SetSIDSessionTicket. |
+ */ |
+ if (ss->ssl3.hs.receivedNewSessionTicket) { |
+ PORT_Assert(!ss->sec.isServer); |
+ ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &ss->ssl3.hs.newSessionTicket); |
+ /* The sid took over the ticket data */ |
+ PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data); |
+ ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE; |
+ } |
+ |
if (ss->ssl3.hs.cacheSID && ss->sec.isServer) { |
+ PORT_Assert(ss->sec.ci.sid->cached == never_cached); |
(*ss->sec.cache)(ss->sec.ci.sid); |
ss->ssl3.hs.cacheSID = PR_FALSE; |
} |
@@ -12311,6 +12390,10 @@ |
ss->ssl3.hs.messages.buf = NULL; |
ss->ssl3.hs.messages.space = 0; |
+ ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE; |
+ PORT_Memset(&ss->ssl3.hs.newSessionTicket, 0, |
+ sizeof(ss->ssl3.hs.newSessionTicket)); |
+ |
ss->ssl3.initialized = PR_TRUE; |
return SECSuccess; |
} |
@@ -12745,6 +12828,8 @@ |
/* free the SSL3Buffer (msg_body) */ |
PORT_Free(ss->ssl3.hs.msg_body.buf); |
+ SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE); |
+ |
/* free up the CipherSpecs */ |
ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE/*freeSrvName*/); |
ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE/*freeSrvName*/); |