Chromium Code Reviews| 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 |
|
agl
2014/01/06 18:19:28
Is this no longer needed then? Even for Linux buil
wtc
2014/01/06 23:22:59
Correct. These types were added in NSS 3.14.3, and
|
| - * 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); } |
|
agl
2014/01/06 18:19:28
seems like these could have been a "goto loser", b
wtc
2014/01/06 23:22:59
I also suggested that while reviewing the upstream
|
| 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*/); |