Bug 1398643 - Prohibit version changes during renegotiation, r=ttaubert NSS_TLS13_DRAFT19_BRANCH
authorMartin Thomson <martin.thomson@gmail.com>
Mon, 11 Sep 2017 10:43:02 +1000
branchNSS_TLS13_DRAFT19_BRANCH
changeset 13605 7b73101f31b7d8f89061df28034f5942464bebae
parent 13572 c3ccbe0e91cf2ed741f649f1b7f10054cfafc2dc
child 13606 9f0d109d125bb1302c37a4d0f77c6499f3ffbb54
push id2386
push usermartin.thomson@gmail.com
push dateMon, 25 Sep 2017 00:58:13 +0000
reviewersttaubert
bugs1398643
Bug 1398643 - Prohibit version changes during renegotiation, r=ttaubert
gtests/ssl_gtest/ssl_version_unittest.cc
lib/ssl/ssl3con.c
lib/ssl/ssl3ecc.c
lib/ssl/sslimpl.h
--- a/gtests/ssl_gtest/ssl_version_unittest.cc
+++ b/gtests/ssl_gtest/ssl_version_unittest.cc
@@ -176,27 +176,27 @@ TEST_P(TlsConnectStream, ConnectTls10And
   // Reset version and cipher suite so that the preinfo callback
   // doesn't fail.
   server_->ResetPreliminaryInfo();
   server_->StartRenegotiate();
 
   if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
     ExpectAlert(server_, kTlsAlertUnexpectedMessage);
   } else {
-    ExpectAlert(client_, kTlsAlertIllegalParameter);
+    ExpectAlert(server_, kTlsAlertProtocolVersion);
   }
 
   Handshake();
   if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
     // In TLS 1.3, the server detects this problem.
     client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
     server_->CheckErrorCode(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
   } else {
-    client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
-    server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+    client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
+    server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
   }
 }
 
 TEST_P(TlsConnectStream, ConnectTls10AndClientRenegotiateHigher) {
   if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
     return;
   }
   // Set the client so it will accept any version from 1.0
@@ -215,27 +215,95 @@ TEST_P(TlsConnectStream, ConnectTls10And
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, test_version);
   // Reset version and cipher suite so that the preinfo callback
   // doesn't fail.
   server_->ResetPreliminaryInfo();
   client_->StartRenegotiate();
   if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
     ExpectAlert(server_, kTlsAlertUnexpectedMessage);
   } else {
-    ExpectAlert(client_, kTlsAlertIllegalParameter);
+    ExpectAlert(server_, kTlsAlertProtocolVersion);
   }
   Handshake();
   if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
     // In TLS 1.3, the server detects this problem.
     client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
     server_->CheckErrorCode(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
   } else {
-    client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
-    server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+    client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
+    server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
+  }
+}
+
+TEST_P(TlsConnectStream, ConnectAndServerRenegotiateLower) {
+  if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
+    return;
+  }
+  Connect();
+
+  // Now renegotiate with the server set to TLS 1.0.
+  client_->PrepareForRenegotiate();
+  server_->PrepareForRenegotiate();
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, version_);
+  // Reset version and cipher suite so that the preinfo callback
+  // doesn't fail.
+  server_->ResetPreliminaryInfo();
+
+  SECStatus rv = SSL_ReHandshake(server_->ssl_fd(), PR_TRUE);
+  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    EXPECT_EQ(SECFailure, rv);
+    return;
   }
+  ASSERT_EQ(SECSuccess, rv);
+
+  // Now, before handshaking, tweak the server configuration.
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
+                           SSL_LIBRARY_VERSION_TLS_1_0);
+
+  // The server should catch the own error.
+  ExpectAlert(server_, kTlsAlertProtocolVersion);
+
+  Handshake();
+  client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
+}
+
+TEST_P(TlsConnectStream, ConnectAndServerWontRenegotiateLower) {
+  if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
+    return;
+  }
+  Connect();
+
+  // Now renegotiate with the server set to TLS 1.0.
+  client_->PrepareForRenegotiate();
+  server_->PrepareForRenegotiate();
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, version_);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
+                           SSL_LIBRARY_VERSION_TLS_1_0);
+  // Reset version and cipher suite so that the preinfo callback
+  // doesn't fail.
+  server_->ResetPreliminaryInfo();
+
+  EXPECT_EQ(SECFailure, SSL_ReHandshake(server_->ssl_fd(), PR_TRUE));
+}
+
+TEST_P(TlsConnectStream, ConnectAndClientWontRenegotiateLower) {
+  if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
+    return;
+  }
+  Connect();
+
+  // Now renegotiate with the client set to TLS 1.0.
+  client_->PrepareForRenegotiate();
+  server_->PrepareForRenegotiate();
+  server_->ResetPreliminaryInfo();
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
+                           SSL_LIBRARY_VERSION_TLS_1_0);
+  // The client will refuse to renegotiate down.
+  EXPECT_EQ(SECFailure, SSL_ReHandshake(client_->ssl_fd(), PR_TRUE));
 }
 
 TEST_F(TlsConnectTest, Tls13RejectsRehandshakeClient) {
   EnsureTlsSetup();
   ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
   Connect();
   SECStatus rv = SSL_ReHandshake(client_->ssl_fd(), PR_TRUE);
   EXPECT_EQ(SECFailure, rv);
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -1055,30 +1055,37 @@ Null_Cipher(void *ctx, unsigned char *ou
  *
  * If allowLargerPeerVersion is true, peerVersion is the peer's highest
  * enabled version rather than the peer's selected version.
  */
 SECStatus
 ssl3_NegotiateVersion(sslSocket *ss, SSL3ProtocolVersion peerVersion,
                       PRBool allowLargerPeerVersion)
 {
+    SSL3ProtocolVersion negotiated;
+
     if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
         PORT_SetError(SSL_ERROR_SSL_DISABLED);
         return SECFailure;
     }
 
     if (peerVersion < ss->vrange.min ||
         (peerVersion > ss->vrange.max && !allowLargerPeerVersion)) {
         PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
         return SECFailure;
     }
 
-    ss->version = PR_MIN(peerVersion, ss->vrange.max);
-    PORT_Assert(ssl3_VersionIsSupported(ss->protocolVariant, ss->version));
-
+    negotiated = PR_MIN(peerVersion, ss->vrange.max);
+    PORT_Assert(ssl3_VersionIsSupported(ss->protocolVariant, negotiated));
+    if (ss->firstHsDone && ss->version != negotiated) {
+        PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+        return SECFailure;
+    }
+
+    ss->version = negotiated;
     return SECSuccess;
 }
 
 /* Used by the client when the server produces a version number.
  * This reads, validates, and normalizes the value. */
 SECStatus
 ssl_ClientReadVersion(sslSocket *ss, PRUint8 **b, unsigned int *len,
                       SSL3ProtocolVersion *version)
@@ -1140,17 +1147,17 @@ ssl3_GetNewRandom(SSL3Random *random)
 
 /* Called by ssl3_SendServerKeyExchange and ssl3_SendCertificateVerify */
 SECStatus
 ssl3_SignHashes(sslSocket *ss, SSL3Hashes *hash, SECKEYPrivateKey *key,
                 SECItem *buf)
 {
     SECStatus rv = SECFailure;
     PRBool doDerEncode = PR_FALSE;
-    PRBool isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+    PRBool isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
     PRBool useRsaPss = ssl_IsRsaPssSignatureScheme(ss->ssl3.hs.signatureScheme);
     SECItem hashItem;
 
     buf->data = NULL;
 
     switch (SECKEY_GetPrivateKeyType(key)) {
         case rsaKey:
             hashItem.data = hash->u.raw;
@@ -2099,36 +2106,16 @@ fail:
     if (pwSpec->server.write_mac_context != NULL) {
         PK11_DestroyContext(pwSpec->server.write_mac_context, PR_TRUE);
         pwSpec->server.write_mac_context = NULL;
     }
 
     return SECFailure;
 }
 
-HASH_HashType
-ssl3_GetTls12HashType(sslSocket *ss)
-{
-    if (ss->ssl3.pwSpec->version < SSL_LIBRARY_VERSION_TLS_1_2) {
-        return HASH_AlgNULL;
-    }
-
-    switch (ss->ssl3.hs.suite_def->prf_hash) {
-        case ssl_hash_sha384:
-            return HASH_AlgSHA384;
-        case ssl_hash_sha256:
-        case ssl_hash_none:
-            /* ssl_hash_none is for pre-1.2 suites, which use SHA-256. */
-            return HASH_AlgSHA256;
-        default:
-            PORT_Assert(0);
-    }
-    return HASH_AlgSHA256;
-}
-
 /* Complete the initialization of all keys, ciphers, MACs and their contexts
  * for the pending Cipher Spec.
  * Called from: ssl3_SendClientKeyExchange  (for Full handshake)
  *              ssl3_HandleRSAClientKeyExchange (for Full handshake)
  *              ssl3_HandleServerHello      (for session restart)
  *              ssl3_HandleClientHello      (for session restart)
  * Sets error code, but caller probably should override to disambiguate.
  * NULL pms means re-use old master_secret.
@@ -3728,22 +3715,20 @@ ssl3_ComputeMasterSecretFinish(sslSocket
  ** 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;
     unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
     unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
-    PRBool isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    PRBool isTLS12 =
-        (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+    PRBool isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
+    PRBool isTLS12 = (PRBool)(ss->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, and does not expect to return the version.
      */
     PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_dh) ||
                            (ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_ecdh));
     CK_MECHANISM_TYPE master_derive;
@@ -3841,17 +3826,17 @@ tls_ComputeExtendedMasterSecretInt(sslSo
 
     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->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
         /* TLS 1.2+ */
         extended_master_params.prfHashMechanism = ssl3_GetPrfHashMechanism(ss);
         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;
     }
@@ -3933,19 +3918,19 @@ ssl3_DeriveMasterSecret(sslSocket *ss, P
  *
  */
 static SECStatus
 ssl3_DeriveConnectionKeys(sslSocket *ss)
 {
     ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
     unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
     unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
-    PRBool isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+    PRBool isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
     PRBool isTLS12 =
-        (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+        (PRBool)(isTLS && ss->version >= SSL_LIBRARY_VERSION_TLS_1_2);
     const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
     PK11SlotInfo *slot = NULL;
     PK11SymKey *symKey = NULL;
     void *pwArg = ss->pkcs11PinArg;
     int keySize;
     CK_TLS12_KEY_MAT_PARAMS key_material_params; /* may be used as a
                                                   * CK_SSL3_KEY_MAT_PARAMS */
     unsigned int key_material_params_len;
@@ -5975,17 +5960,17 @@ ssl3_SendRSAClientKeyExchange(sslSocket 
     SECItem enc_pms = { siBuffer, NULL, 0 };
     PRBool isTLS;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     /* Generate the pre-master secret ...  */
     ssl_GetSpecWriteLock(ss);
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+    isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
 
     pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.pwSpec, NULL);
     ssl_ReleaseSpecWriteLock(ss);
     if (pms == NULL) {
         ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
         goto loser;
     }
 
@@ -6121,17 +6106,17 @@ ssl3_SendDHClientKeyExchange(sslSocket *
     sslEphemeralKeyPair *keyPair = NULL;
     SECKEYPublicKey *pubKey;
     PRUint8 dhData[1026]; /* Enough for the 8192-bit group. */
     sslBuffer dhBuf = SSL_BUFFER(dhData);
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+    isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
 
     /* Copy DH parameters from server key */
 
     if (SECKEY_GetPublicKeyType(svrPubKey) != dhKey) {
         PORT_SetError(SEC_ERROR_BAD_KEY);
         return SECFailure;
     }
 
@@ -6672,17 +6657,17 @@ ssl3_HandleServerHello(sslSocket *ss, PR
         }
     }
 
     /* Check that the server negotiated the same version as it did
      * in the first handshake. This isn't really the best place for
      * us to be getting this version number, but it's what we have.
      * (1294697). */
     if (ss->firstHsDone && (ss->version != ss->ssl3.crSpec->version)) {
-        desc = illegal_parameter;
+        desc = protocol_version;
         errCode = SSL_ERROR_UNSUPPORTED_VERSION;
         goto alert_loser;
     }
     ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
     isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
 
     rv = ssl3_ConsumeHandshake(
         ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length);
@@ -9467,17 +9452,17 @@ ssl3_SendDHServerKeyExchange(sslSocket *
     params = ssl_GetDHEParams(groupDef);
     rv = ssl_CreateDHEKeyPair(groupDef, params, &keyPair);
     if (rv == SECFailure) {
         ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
         return SECFailure;
     }
     PR_APPEND_LINK(&keyPair->link, &ss->ephemeralKeyPairs);
 
-    if (ss->ssl3.pwSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) {
+    if (ss->version == SSL_LIBRARY_VERSION_TLS_1_2) {
         hashAlg = ssl_SignatureSchemeToHashType(ss->ssl3.hs.signatureScheme);
     } else {
         /* Use ssl_hash_none to represent the MD5+SHA1 combo. */
         hashAlg = ssl_hash_none;
     }
 
     pubKey = keyPair->keys->pubKey;
     PRINT_BUF(50, (ss, "DH public value:",
@@ -9499,17 +9484,17 @@ ssl3_SendDHServerKeyExchange(sslSocket *
         goto loser; /* ssl3_SignHashes has set err. */
     }
 
     length = 2 + pubKey->u.dh.prime.len +
              2 + pubKey->u.dh.base.len +
              2 + pubKey->u.dh.prime.len +
              2 + signed_hash.len;
 
-    if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
         length += 2;
     }
 
     rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_server_key_exchange, length);
     if (rv != SECSuccess) {
         goto loser; /* err set by AppendHandshake. */
     }
 
@@ -9529,17 +9514,17 @@ ssl3_SendDHServerKeyExchange(sslSocket *
     if (rv != SECSuccess) {
         goto loser; /* err set by AppendPaddedDHKeyShare. */
     }
     rv = ssl3_AppendBufferToHandshake(ss, &dhBuf);
     if (rv != SECSuccess) {
         goto loser; /* err set by AppendHandshake. */
     }
 
-    if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
         rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.signatureScheme, 2);
         if (rv != SECSuccess) {
             goto loser; /* err set by AppendHandshake. */
         }
     }
 
     rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
                                       signed_hash.len, 2);
@@ -9649,17 +9634,17 @@ ssl3_SendCertificateRequest(sslSocket *s
     sslBuffer sigAlgsBuf = SSL_BUFFER(sigAlgs);
 
     SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
-    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+    isTLS12 = (PRBool)(ss->version >= SSL_LIBRARY_VERSION_TLS_1_2);
 
     rv = ssl_GetCertificateRequestCAs(ss, &calen, &names, &nnames);
     if (rv != SECSuccess) {
         return rv;
     }
     certTypes = certificate_types;
     certTypesLength = sizeof certificate_types;
 
@@ -13234,16 +13219,21 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool
         dtls_RehandshakeCleanup(ss);
     }
 
     if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER ||
         ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
         PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
         return SECFailure;
     }
+    if (ss->version > ss->vrange.max || ss->version < ss->vrange.min) {
+        PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+        return SECFailure;
+    }
+
     if (sid && flushCache) {
         ss->sec.uncache(sid); /* remove it from whichever cache it's in. */
         ssl_FreeSID(sid);     /* dec ref count and free if zero. */
         ss->sec.ci.sid = NULL;
     }
 
     ssl_GetXmitBufLock(ss); /**************************************/
 
--- a/lib/ssl/ssl3ecc.c
+++ b/lib/ssl/ssl3ecc.c
@@ -170,18 +170,18 @@ ssl3_SendECDHClientKeyExchange(sslSocket
     CK_MECHANISM_TYPE target;
     const sslNamedGroupDef *groupDef;
     sslEphemeralKeyPair *keyPair = NULL;
     SECKEYPublicKey *pubKey;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+    isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
+    isTLS12 = (PRBool)(ss->version >= SSL_LIBRARY_VERSION_TLS_1_2);
 
     /* Generate ephemeral EC keypair */
     if (svrPubKey->keyType != ecKey) {
         PORT_SetError(SEC_ERROR_BAD_KEY);
         goto loser;
     }
     groupDef = ssl_ECPubKey2NamedGroup(svrPubKey);
     if (!groupDef) {
@@ -685,33 +685,33 @@ ssl3_SendECDHServerKeyExchange(sslSocket
     ec_params.data = paramBuf;
     PORT_Assert(keyPair->group);
     PORT_Assert(keyPair->group->keaType == ssl_kea_ecdh);
     ec_params.data[0] = ec_type_named;
     ec_params.data[1] = keyPair->group->name >> 8;
     ec_params.data[2] = keyPair->group->name & 0xff;
 
     pubKey = keyPair->keys->pubKey;
-    if (ss->ssl3.pwSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) {
+    if (ss->version == SSL_LIBRARY_VERSION_TLS_1_2) {
         hashAlg = ssl_SignatureSchemeToHashType(ss->ssl3.hs.signatureScheme);
     } else {
         /* Use ssl_hash_none to represent the MD5+SHA1 combo. */
         hashAlg = ssl_hash_none;
     }
     rv = ssl3_ComputeECDHKeyHash(hashAlg, ec_params,
                                  pubKey->u.ec.publicValue,
                                  &ss->ssl3.hs.client_random,
                                  &ss->ssl3.hs.server_random,
                                  &hashes);
     if (rv != SECSuccess) {
         ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
         goto loser;
     }
 
-    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+    isTLS12 = (PRBool)(ss->version >= SSL_LIBRARY_VERSION_TLS_1_2);
 
     rv = ssl3_SignHashes(ss, &hashes,
                          ss->sec.serverCert->serverKeyPair->privKey, &signed_hash);
     if (rv != SECSuccess) {
         goto loser; /* ssl3_SignHashes has set err. */
     }
 
     length = ec_params.len +
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
@@ -1862,19 +1862,16 @@ extern PRUint32 ssl_TimeSec(void);
 #define ssl_TimeUsec() (PR_Now())
 #endif
 extern PRBool ssl_TicketTimeValid(const NewSessionTicket *ticket);
 
 extern void SSL_AtomicIncrementLong(long *x);
 
 SECStatus ssl3_ApplyNSSPolicy(void);
 
-extern HASH_HashType
-ssl3_GetTls12HashType(sslSocket *ss);
-
 extern SECStatus
 ssl3_TLSPRFWithMasterSecret(sslSocket *ss, ssl3CipherSpec *spec,
                             const char *label, unsigned int labelLen,
                             const unsigned char *val, unsigned int valLen,
                             unsigned char *out, unsigned int outLen);
 
 PRBool ssl_AlpnTagAllowed(const sslSocket *ss, const SECItem *tag);