diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ssl/SSLerrs.h | 6 | ||||
-rw-r--r-- | lib/ssl/derive.c | 2 | ||||
-rw-r--r-- | lib/ssl/ssl.h | 8 | ||||
-rw-r--r-- | lib/ssl/ssl3con.c | 535 | ||||
-rw-r--r-- | lib/ssl/ssl3ecc.c | 16 | ||||
-rw-r--r-- | lib/ssl/ssl3ext.c | 116 | ||||
-rw-r--r-- | lib/ssl/sslerr.h | 3 | ||||
-rw-r--r-- | lib/ssl/sslimpl.h | 7 | ||||
-rw-r--r-- | lib/ssl/sslinfo.c | 2 | ||||
-rw-r--r-- | lib/ssl/sslsnce.c | 7 | ||||
-rw-r--r-- | lib/ssl/sslsock.c | 14 | ||||
-rw-r--r-- | lib/ssl/sslt.h | 9 |
12 files changed, 550 insertions, 175 deletions
diff --git a/lib/ssl/SSLerrs.h b/lib/ssl/SSLerrs.h index da5616441..602839680 100644 --- a/lib/ssl/SSLerrs.h +++ b/lib/ssl/SSLerrs.h @@ -434,3 +434,9 @@ ER3(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 134), ER3(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 135), "The peer used an unsupported combination of signature and hash algorithm.") + +ER3(SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 136), +"The peer tried to resume without a correct extended_master_secret extension") + +ER3(SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 137), +"The peer tried to resume with an unexpected extended_master_secret extension") diff --git a/lib/ssl/derive.c b/lib/ssl/derive.c index b7c38c30b..8b58b800d 100644 --- a/lib/ssl/derive.c +++ b/lib/ssl/derive.c @@ -431,7 +431,7 @@ key_and_mac_derive_fail: * so isRSA is always true. */ SECStatus -ssl3_MasterKeyDeriveBypass( +ssl3_MasterSecretDeriveBypass( ssl3CipherSpec * pwSpec, const unsigned char * cr, const unsigned char * sr, diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h index 40f8476d5..2a527693b 100644 --- a/lib/ssl/ssl.h +++ b/lib/ssl/ssl.h @@ -196,6 +196,14 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd); */ #define SSL_ENABLE_SERVER_DHE 29 +/* Use draft-ietf-tls-session-hash. Controls whether we offer the + * extended_master_secret extension which, when accepted, hashes + * the handshake transcript into the master secret. This option is + * disabled by default. + */ +#define SSL_ENABLE_EXTENDED_MASTER_SECRET 30 + + #ifdef SSL_DEPRECATED_FUNCTION /* Old deprecated function names */ SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRBool on); diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c index 717ece17a..877f1fcb0 100644 --- a/lib/ssl/ssl3con.c +++ b/lib/ssl/ssl3con.c @@ -62,6 +62,10 @@ static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, const unsigned char *b, unsigned int l); static SECOidTag ssl3_TLSHashAlgorithmToOID(SSLHashType hashFunc); +static SECStatus ssl3_ComputeHandshakeHashes(sslSocket *ss, + ssl3CipherSpec *spec, + SSL3Hashes *hashes, + PRUint32 sender); static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags); static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, @@ -2177,7 +2181,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 @@ -3583,13 +3591,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; @@ -3599,26 +3664,23 @@ 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_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_TLS12_MASTER_KEY_DERIVE_DH; else master_derive = CKM_TLS12_MASTER_KEY_DERIVE; @@ -3636,93 +3698,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 (isTLS12) { - master_params.prfHashMechanism = CKM_SHA256; - master_params_len = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS); - } else { - master_params_len = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS); - } + if (!isDH) { + pms_version_ptr = &pms_version; + } - params.data = (unsigned char *) &master_params; - params.len = master_params_len; + 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, - ¶ms, 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, ¶ms, + 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, ¶ms, 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, ¶ms, 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, ¶ms, + 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; @@ -3733,7 +3844,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. */ @@ -3748,10 +3859,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. @@ -4584,11 +4695,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)); @@ -4607,15 +4713,15 @@ 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); if (!isTLS) { + if (!spec->msItem.data) { + PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); + return SECFailure; + } + /* compute hashes for SSL3. */ unsigned char s[4]; @@ -4691,11 +4797,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); @@ -4735,11 +4836,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) { @@ -4757,6 +4853,11 @@ tls12_loser: sha = ss->ssl3.hs.sha; if (!isTLS) { + if (!spec->master_secret) { + PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); + return SECFailure; + } + /* compute hashes for SSL3. */ unsigned char s[4]; @@ -6005,14 +6106,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) { @@ -6027,6 +6120,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: @@ -6096,14 +6198,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) { @@ -6119,8 +6213,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: @@ -6517,6 +6619,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; @@ -6618,7 +6746,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); } - /* 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 */ @@ -6647,6 +6775,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); + 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., @@ -7584,6 +7715,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; @@ -8144,6 +8276,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; @@ -8155,6 +8289,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); @@ -8295,7 +8453,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(); @@ -8486,6 +8644,8 @@ 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); @@ -9496,7 +9656,6 @@ 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; @@ -9541,6 +9700,13 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, #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 @@ -9568,8 +9734,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; @@ -9579,46 +9745,101 @@ 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. + */ - if (pms == NULL) { - /* last gasp. */ + /* Generate the bogus PMS (R) */ + slot = PK11_GetSlotFromPrivateKey(serverKey); + if (!PK11_DoesMechanism(slot, CKM_SSL3_MASTER_KEY_DERIVE)) { + slot = PK11_GetBestSlot(CKM_SSL3_MASTER_KEY_DERIVE, NULL); + if (!slot) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + } + + 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; } diff --git a/lib/ssl/ssl3ecc.c b/lib/ssl/ssl3ecc.c index 5dbca1658..539ddbbab 100644 --- a/lib/ssl/ssl3ecc.c +++ b/lib/ssl/ssl3ecc.c @@ -319,14 +319,6 @@ ssl3_SendECDHClientKeyExchange(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.ec.publicValue.len + 1); if (rv != SECSuccess) { @@ -343,6 +335,14 @@ ssl3_SendECDHClientKeyExchange(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: diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c index c45f29542..07d792944 100644 --- a/lib/ssl/ssl3ext.c +++ b/lib/ssl/ssl3ext.c @@ -91,6 +91,12 @@ static PRInt32 ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes); static SECStatus ssl3_ServerHandleDraftVersionXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data); +static PRInt32 ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append, + PRUint32 maxBytes); +static SECStatus ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss, + PRUint16 ex_type, + SECItem *data); + /* * Write bytes. Using this function means the SECItem structure @@ -256,6 +262,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = { { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn }, { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn }, { ssl_tls13_draft_version_xtn, &ssl3_ServerHandleDraftVersionXtn }, + { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn }, { -1, NULL } }; @@ -270,6 +277,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn }, { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn }, { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, + { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn }, { -1, NULL } }; @@ -299,6 +307,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }, { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn }, + { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn}, /* any extra entries will appear as { 0, NULL } */ }; @@ -1182,6 +1191,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss) + cert_length /* cert */ + 1 /* server name type */ + srvNameLen /* name len + length field */ + + 1 /* extendedMasterSecretUsed */ + sizeof(ticket.ticket_lifetime_hint); padding_length = AES_BLOCK_SIZE - (ciphertext_length % AES_BLOCK_SIZE); @@ -1280,6 +1290,11 @@ ssl3_SendNewSessionTicket(sslSocket *ss) if (rv != SECSuccess) goto loser; } + /* extendedMasterSecretUsed */ + rv = ssl3_AppendNumberToItem( + &plaintext, ss->sec.ci.sid->u.ssl3.keys.extendedMasterSecretUsed, 1); + if (rv != SECSuccess) goto loser; + PORT_Assert(plaintext.len == padding_length); for (i = 0; i < padding_length; i++) plaintext.data[i] = (unsigned char)padding_length; @@ -1637,9 +1652,10 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, goto loser; } - /* Read ticket_version (which is ignored for now.) */ + /* Read ticket_version and reject if the version is wrong */ temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); - if (temp < 0) goto no_ticket; + if (temp != TLS_EX_SESS_TICKET_VERSION) goto no_ticket; + parsed_session_ticket->ticket_version = (SSL3ProtocolVersion)temp; /* Read SSLVersion. */ @@ -1740,6 +1756,13 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, parsed_session_ticket->srvName.type = nameType; } + /* Read extendedMasterSecretUsed */ + temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + if (temp < 0) + goto no_ticket; + PORT_Assert(temp == PR_TRUE || temp == PR_FALSE); + parsed_session_ticket->extendedMasterSecretUsed = (PRBool)temp; + /* Done parsing. Check that all bytes have been consumed. */ if (buffer_len != padding_length) goto no_ticket; @@ -1786,6 +1809,8 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, parsed_session_ticket->ms_is_wrapped; sid->u.ssl3.masterValid = PR_TRUE; sid->u.ssl3.keys.resumable = PR_TRUE; + sid->u.ssl3.keys.extendedMasterSecretUsed = parsed_session_ticket-> + extendedMasterSecretUsed; /* Copy over client cert from session ticket if there is one. */ if (parsed_session_ticket->peer_cert.data != NULL) { @@ -2559,3 +2584,90 @@ ssl3_ServerHandleDraftVersionXtn(sslSocket * ss, PRUint16 ex_type, return SECSuccess; } + +static PRInt32 +ssl3_SendExtendedMasterSecretXtn(sslSocket * ss, PRBool append, + PRUint32 maxBytes) +{ + PRInt32 extension_length; + + if (!ss->opt.enableExtendedMS) { + return 0; + } + +#ifndef NO_PKCS11_BYPASS + /* Extended MS can only be used w/o bypass mode */ + if (ss->opt.bypassPKCS11) { + PORT_Assert(0); + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); + return -1; + } +#endif + + /* Always send the extension in this function, since the + * client always sends it and this function is only called on + * the server if we negotiated the extension. */ + extension_length = 4; /* Type + length (0) */ + if (maxBytes < extension_length) { + PORT_Assert(0); + return 0; + } + + if (append) { + SECStatus rv; + rv = ssl3_AppendHandshakeNumber(ss, ssl_extended_master_secret_xtn, 2); + if (rv != SECSuccess) + goto loser; + rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + if (rv != SECSuccess) + goto loser; + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + ssl_extended_master_secret_xtn; + } + + return extension_length; + +loser: + return -1; +} + + +static SECStatus +ssl3_HandleExtendedMasterSecretXtn(sslSocket * ss, PRUint16 ex_type, + SECItem *data) +{ + if (ss->version < SSL_LIBRARY_VERSION_TLS_1_0) { + return SECSuccess; + } + + if (!ss->opt.enableExtendedMS) { + return SECSuccess; + } + +#ifndef NO_PKCS11_BYPASS + /* Extended MS can only be used w/o bypass mode */ + if (ss->opt.bypassPKCS11) { + PORT_Assert(0); + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); + return SECFailure; + } +#endif + + if (data->len != 0) { + SSL_TRC(30, ("%d: SSL3[%d]: Bogus extended master secret extension", + SSL_GETPID(), ss->fd)); + return SECFailure; + } + + SSL_DBG(("%d: SSL[%d]: Negotiated extended master secret extension.", + SSL_GETPID(), ss->fd)); + + /* Keep track of negotiated extensions. */ + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + + if (ss->sec.isServer) { + return ssl3_RegisterServerHelloExtensionSender( + ss, ex_type, ssl3_SendExtendedMasterSecretXtn); + } + return SECSuccess; +} diff --git a/lib/ssl/sslerr.h b/lib/ssl/sslerr.h index 4e905438e..192a10758 100644 --- a/lib/ssl/sslerr.h +++ b/lib/ssl/sslerr.h @@ -205,6 +205,9 @@ SSL_ERROR_RX_SHORT_DTLS_READ = (SSL_ERROR_BASE + 133), SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 134), SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 135), +SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 136), +SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 137), + SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ } SSLErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */ diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h index e155a0800..41b51d8a8 100644 --- a/lib/ssl/sslimpl.h +++ b/lib/ssl/sslimpl.h @@ -346,6 +346,7 @@ typedef struct sslOptionsStr { unsigned int reuseServerECDHEKey : 1; /* 28 */ unsigned int enableFallbackSCSV : 1; /* 29 */ unsigned int enableServerDhe : 1; /* 30 */ + unsigned int enableExtendedMS : 1; /* 31 */ } sslOptions; typedef enum { sslHandshakingUndetermined = 0, @@ -518,6 +519,7 @@ typedef struct { PRUint16 wrapped_master_secret_len; PRUint8 msIsWrapped; PRUint8 resumable; + PRUint8 extendedMasterSecretUsed; } ssl3SidKeys; /* 52 bytes */ typedef struct { @@ -1070,6 +1072,7 @@ typedef struct SessionTicketStr { CK_MECHANISM_TYPE msWrapMech; PRUint16 ms_length; SSL3Opaque master_secret[48]; + PRBool extendedMasterSecretUsed; ClientIdentity client_identity; SECItem peer_cert; PRUint32 timestamp; @@ -1595,7 +1598,7 @@ extern PRBool ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant, extern SECStatus ssl3_KeyAndMacDeriveBypass(ssl3CipherSpec * pwSpec, const unsigned char * cr, const unsigned char * sr, PRBool isTLS, PRBool isExport); -extern SECStatus ssl3_MasterKeyDeriveBypass( ssl3CipherSpec * pwSpec, +extern SECStatus ssl3_MasterSecretDeriveBypass( ssl3CipherSpec * pwSpec, const unsigned char * cr, const unsigned char * sr, const SECItem * pms, PRBool isTLS, PRBool isRSA); @@ -1846,7 +1849,7 @@ extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey, /* Tell clients to consider tickets valid for this long. */ #define TLS_EX_SESS_TICKET_LIFETIME_HINT (2 * 24 * 60 * 60) /* 2 days */ -#define TLS_EX_SESS_TICKET_VERSION (0x0100) +#define TLS_EX_SESS_TICKET_VERSION (0x0101) extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned int length); diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c index d2df8c2ec..216ab0fa0 100644 --- a/lib/ssl/sslinfo.c +++ b/lib/ssl/sslinfo.c @@ -67,6 +67,8 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) inf.creationTime = sid->creationTime; inf.lastAccessTime = sid->lastAccessTime; inf.expirationTime = sid->expirationTime; + inf.extendedMasterSecretUsed = sid->u.ssl3.keys.extendedMasterSecretUsed; + if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */ inf.sessionIDLength = SSL2_SESSIONID_BYTES; memcpy(inf.sessionID, sid->u.ssl2.sessionID, diff --git a/lib/ssl/sslsnce.c b/lib/ssl/sslsnce.c index 6d908c86e..16bfbe49b 100644 --- a/lib/ssl/sslsnce.c +++ b/lib/ssl/sslsnce.c @@ -120,14 +120,14 @@ struct sidCacheEntryStr { /* 2 */ ssl3CipherSuite cipherSuite; /* 2 */ PRUint16 compression; /* SSLCompressionMethod */ -/* 52 */ ssl3SidKeys keys; /* keys, wrapped as needed. */ +/* 54 */ ssl3SidKeys keys; /* keys, wrapped as needed. */ /* 4 */ PRUint32 masterWrapMech; /* 4 */ SSL3KEAType exchKeyType; /* 4 */ PRInt32 certIndex; /* 4 */ PRInt32 srvNameIndex; /* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */ -/*104 */} ssl3; +/*108 */} ssl3; /* force sizeof(sidCacheEntry) to be a multiple of cache line size */ struct { /*120 */ PRUint8 filler[120]; /* 72+120==192, a multiple of 16 */ @@ -507,7 +507,6 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from) to->sessionIDLength = from->u.ssl3.sessionIDLength; to->u.ssl3.certIndex = -1; to->u.ssl3.srvNameIndex = -1; - PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID, to->sessionIDLength); @@ -637,7 +636,7 @@ ConvertToSID(sidCacheEntry * from, to->authKeyBits = from->authKeyBits; to->keaType = from->keaType; to->keaKeyBits = from->keaKeyBits; - + return to; loser: diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c index 2ab9d2d52..f73500925 100644 --- a/lib/ssl/sslsock.c +++ b/lib/ssl/sslsock.c @@ -85,6 +85,7 @@ static sslOptions ssl_defaults = { PR_TRUE, /* reuseServerECDHEKey */ PR_FALSE, /* enableFallbackSCSV */ PR_TRUE, /* enableServerDhe */ + PR_FALSE /* enableExtendedMS */ }; /* @@ -825,6 +826,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) ss->opt.enableServerDhe = on; break; + case SSL_ENABLE_EXTENDED_MASTER_SECRET: + ss->opt.enableExtendedMS = on; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -901,6 +906,8 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) on = ss->opt.reuseServerECDHEKey; break; case SSL_ENABLE_FALLBACK_SCSV: on = ss->opt.enableFallbackSCSV; break; case SSL_ENABLE_SERVER_DHE: on = ss->opt.enableServerDhe; break; + case SSL_ENABLE_EXTENDED_MASTER_SECRET: + on = ss->opt.enableExtendedMS; break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -973,6 +980,9 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) case SSL_ENABLE_SERVER_DHE: on = ssl_defaults.enableServerDhe; break; + case SSL_ENABLE_EXTENDED_MASTER_SECRET: + on = ssl_defaults.enableExtendedMS; + break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -1160,6 +1170,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) ssl_defaults.enableServerDhe = on; break; + case SSL_ENABLE_EXTENDED_MASTER_SECRET: + ssl_defaults.enableExtendedMS = on; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h index f9d83c851..cd742bbb2 100644 --- a/lib/ssl/sslt.h +++ b/lib/ssl/sslt.h @@ -145,6 +145,12 @@ typedef struct SSLChannelInfoStr { /* compression method info */ const char * compressionMethodName; SSLCompressionMethod compressionMethod; + + /* The following fields are added in NSS 3.21. + * This field only has meaning in TLS < 1.3 and will be set to + * PR_FALSE in TLS 1.3. + */ + PRBool extendedMasterSecretUsed; } SSLChannelInfo; /* Preliminary channel info */ @@ -229,13 +235,14 @@ typedef enum { ssl_use_srtp_xtn = 14, ssl_app_layer_protocol_xtn = 16, ssl_padding_xtn = 21, + ssl_extended_master_secret_xtn = 23, ssl_session_ticket_xtn = 35, ssl_next_proto_nego_xtn = 13172, ssl_renegotiation_info_xtn = 0xff01, ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */ } SSLExtensionType; -#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. */ +#define SSL_MAX_EXTENSIONS 12 /* doesn't include ssl_padding_xtn. */ typedef enum { ssl_dhe_group_none = 0, |