Backed out 6 changesets (bug 1034855) for LSAN leaks on a CLOSED TREE.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 05 Aug 2014 14:04:08 -0400
changeset 198020 591fb2c4ee157f5089d03fe467954c31d734cfa9
parent 198019 7efc5743fc2b6a8b7d8de64e96ab87d1ed916732
child 198021 b2ba34d2805b843e9d848802fa0d3b771fbfaf16
push id1036
push userrnewman@mozilla.com
push dateWed, 06 Aug 2014 02:14:58 +0000
treeherderservices-central@3fd543e150c8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1034855
milestone34.0a1
backs out0dc569f749916ced0f5ee0b10320b31c339d118e
4eb0ee62db1ed3412bca570b32a969fbf669669a
4af8993f153429a593d8ff50c1553ecf069ebbb0
f4f5f5b8421d29117b5e613db73546d25dfc4051
33510bb7ad60a051b6666c2c82b7f2c12337d193
50b8670329aa9fa51a87b075f2f1280f1320dae3
Backed out 6 changesets (bug 1034855) for LSAN leaks on a CLOSED TREE. Backed out changeset 0dc569f74991 (bug 1034855) Backed out changeset 4eb0ee62db1e (bug 1034855) Backed out changeset 4af8993f1534 (bug 1034855) Backed out changeset f4f5f5b8421d (bug 1034855) Backed out changeset 33510bb7ad60 (bug 1034855) Backed out changeset 50b8670329aa (bug 1034855)
dom/crypto/CryptoKey.cpp
dom/crypto/EcKeyAlgorithm.cpp
dom/crypto/EcKeyAlgorithm.h
dom/crypto/KeyAlgorithm.cpp
dom/crypto/KeyAlgorithm.h
dom/crypto/WebCryptoCommon.h
dom/crypto/WebCryptoTask.cpp
dom/crypto/moz.build
dom/crypto/test/test-vectors.js
dom/crypto/test/tests.js
dom/webidl/SubtleCrypto.webidl
--- a/dom/crypto/CryptoKey.cpp
+++ b/dom/crypto/CryptoKey.cpp
@@ -317,33 +317,16 @@ CryptoKey::PublicKeyFromSpki(CryptoBuffe
     return nullptr;
   }
 
   ScopedCERTSubjectPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(spkiItem.get()));
   if (!spki) {
     return nullptr;
   }
 
-  // Check for id-ecDH. Per the WebCrypto spec we must support it but NSS
-  // does unfortunately not know about it. Let's change the algorithm to
-  // id-ecPublicKey to make NSS happy.
-  if (SECITEM_ItemsAreEqual(&SEC_OID_DATA_EC_DH, &spki->algorithm.algorithm)) {
-    // Retrieve OID data for id-ecPublicKey (1.2.840.10045.2.1).
-    SECOidData* oidData = SECOID_FindOIDByTag(SEC_OID_ANSIX962_EC_PUBLIC_KEY);
-    if (!oidData) {
-      return nullptr;
-    }
-
-    SECStatus rv = SECITEM_CopyItem(spki->arena, &spki->algorithm.algorithm,
-                                    &oidData->oid);
-    if (rv != SECSuccess) {
-      return nullptr;
-    }
-  }
-
   return SECKEY_ExtractPublicKey(spki.get());
 }
 
 nsresult
 CryptoKey::PrivateKeyToPkcs8(SECKEYPrivateKey* aPrivKey,
                        CryptoBuffer& aRetVal,
                        const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
@@ -355,212 +338,100 @@ CryptoKey::PrivateKeyToPkcs8(SECKEYPriva
   return NS_OK;
 }
 
 nsresult
 CryptoKey::PublicKeyToSpki(SECKEYPublicKey* aPubKey,
                      CryptoBuffer& aRetVal,
                      const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
-  ScopedCERTSubjectPublicKeyInfo spki(SECKEY_CreateSubjectPublicKeyInfo(aPubKey));
-  if (!spki) {
-    return NS_ERROR_DOM_OPERATION_ERR;
+  ScopedSECItem spkiItem(PK11_DEREncodePublicKey(aPubKey));
+  if (!spkiItem.get()) {
+    return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   }
 
-  // Per WebCrypto spec we must export ECDH SPKIs with the algorithm OID
-  // id-ecDH (1.3.132.112). NSS doesn't know about that OID and there is
-  // no way to specify the algorithm to use when exporting a public key.
-  if (aPubKey->keyType == ecKey) {
-    SECStatus rv = SECITEM_CopyItem(spki->arena, &spki->algorithm.algorithm,
-                                    &SEC_OID_DATA_EC_DH);
-    if (rv != SECSuccess) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
-  }
-
-  const SEC_ASN1Template* tpl = SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate);
-  ScopedSECItem spkiItem(SEC_ASN1EncodeItem(nullptr, nullptr, spki, tpl));
-
   aRetVal.Assign(spkiItem.get());
   return NS_OK;
 }
 
-SECItem*
-CreateECPointForCoordinates(const CryptoBuffer& aX,
-                            const CryptoBuffer& aY,
-                            PLArenaPool* aArena)
+SECKEYPrivateKey*
+CryptoKey::PrivateKeyFromJwk(const JsonWebKey& aJwk,
+                             const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
-  // Check that both points have the same length.
-  if (aX.Length() != aY.Length()) {
+  if (!aJwk.mKty.WasPassed() || !aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_RSA)) {
+    return nullptr;
+  }
+
+  // Verify that all of the required parameters are present
+  CryptoBuffer n, e, d, p, q, dp, dq, qi;
+  if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) ||
+      !aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value())) ||
+      !aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value())) ||
+      !aJwk.mP.WasPassed() || NS_FAILED(p.FromJwkBase64(aJwk.mP.Value())) ||
+      !aJwk.mQ.WasPassed() || NS_FAILED(q.FromJwkBase64(aJwk.mQ.Value())) ||
+      !aJwk.mDp.WasPassed() || NS_FAILED(dp.FromJwkBase64(aJwk.mDp.Value())) ||
+      !aJwk.mDq.WasPassed() || NS_FAILED(dq.FromJwkBase64(aJwk.mDq.Value())) ||
+      !aJwk.mQi.WasPassed() || NS_FAILED(qi.FromJwkBase64(aJwk.mQi.Value()))) {
     return nullptr;
   }
 
-  // Create point.
-  SECItem* point = ::SECITEM_AllocItem(aArena, nullptr, aX.Length() + aY.Length() + 1);
-  if (!point) {
+  // Compute the ID for this key
+  // This is generated with a SHA-1 hash, so unlikely to collide
+  ScopedSECItem nItem(n.ToSECItem());
+  ScopedSECItem objID(PK11_MakeIDFromPubKey(nItem.get()));
+  if (!nItem.get() || !objID.get()) {
     return nullptr;
   }
 
-  // Set point data.
-  point->data[0] = EC_POINT_FORM_UNCOMPRESSED;
-  memcpy(point->data + 1, aX.Elements(), aX.Length());
-  memcpy(point->data + 1 + aX.Length(), aY.Elements(), aY.Length());
+  // Populate template from parameters
+  CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY;
+  CK_KEY_TYPE rsaValue = CKK_RSA;
+  CK_BBOOL falseValue = CK_FALSE;
+  CK_ATTRIBUTE keyTemplate[14] = {
+    { CKA_CLASS,            &privateKeyValue,      sizeof(privateKeyValue) },
+    { CKA_KEY_TYPE,         &rsaValue,             sizeof(rsaValue) },
+    { CKA_TOKEN,            &falseValue,           sizeof(falseValue) },
+    { CKA_SENSITIVE,        &falseValue,           sizeof(falseValue) },
+    { CKA_PRIVATE,          &falseValue,           sizeof(falseValue) },
+    { CKA_ID,               objID->data,           objID->len },
+    { CKA_MODULUS,          (void*) n.Elements(),  n.Length() },
+    { CKA_PUBLIC_EXPONENT,  (void*) e.Elements(),  e.Length() },
+    { CKA_PRIVATE_EXPONENT, (void*) d.Elements(),  d.Length() },
+    { CKA_PRIME_1,          (void*) p.Elements(),  p.Length() },
+    { CKA_PRIME_2,          (void*) q.Elements(),  q.Length() },
+    { CKA_EXPONENT_1,       (void*) dp.Elements(), dp.Length() },
+    { CKA_EXPONENT_2,       (void*) dq.Elements(), dq.Length() },
+    { CKA_COEFFICIENT,      (void*) qi.Elements(), qi.Length() },
+  };
 
-  return point;
-}
 
-SECKEYPrivateKey*
-PrivateKeyFromPrivateKeyTemplate(SECItem* aObjID,
-                                 CK_ATTRIBUTE* aTemplate,
-                                 CK_ULONG aTemplateSize)
-{
   // Create a generic object with the contents of the key
   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
   if (!slot.get()) {
     return nullptr;
   }
 
   ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot.get(),
-                                                       aTemplate,
-                                                       aTemplateSize,
+                                                       keyTemplate,
+                                                       PR_ARRAY_SIZE(keyTemplate),
                                                        PR_FALSE));
   if (!obj.get()) {
     return nullptr;
   }
 
   // Have NSS translate the object to a private key by inspection
   // and make a copy we can own
-  ScopedSECKEYPrivateKey privKey(PK11_FindKeyByKeyID(slot.get(), aObjID,
+  ScopedSECKEYPrivateKey privKey(PK11_FindKeyByKeyID(slot.get(), objID.get(),
                                                      nullptr));
   if (!privKey.get()) {
     return nullptr;
   }
-
   return SECKEY_CopyPrivateKey(privKey.get());
 }
 
-SECKEYPrivateKey*
-CryptoKey::PrivateKeyFromJwk(const JsonWebKey& aJwk,
-                             const nsNSSShutDownPreventionLock& /*proofOfLock*/)
-{
-  if (!aJwk.mKty.WasPassed()) {
-    return nullptr;
-  }
-
-  CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY;
-  CK_BBOOL falseValue = CK_FALSE;
-
-  if (aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_EC)) {
-    // Verify that all of the required parameters are present
-    CryptoBuffer x, y, d;
-    if (!aJwk.mCrv.WasPassed() ||
-        !aJwk.mX.WasPassed() || NS_FAILED(x.FromJwkBase64(aJwk.mX.Value())) ||
-        !aJwk.mY.WasPassed() || NS_FAILED(y.FromJwkBase64(aJwk.mY.Value())) ||
-        !aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value()))) {
-      return nullptr;
-    }
-
-    nsString namedCurve;
-    if (!NormalizeNamedCurveValue(aJwk.mCrv.Value(), namedCurve)) {
-      return nullptr;
-    }
-
-    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-    if (!arena) {
-      return nullptr;
-    }
-
-    // Create parameters.
-    SECItem* params = CreateECParamsForCurve(namedCurve, arena.get());
-    if (!params) {
-      return nullptr;
-    }
-
-    SECItem* ecPoint = CreateECPointForCoordinates(x, y, arena.get());
-    if (!ecPoint) {
-      return nullptr;
-    }
-
-    // Compute the ID for this key
-    // This is generated with a SHA-1 hash, so unlikely to collide
-    ScopedSECItem objID(PK11_MakeIDFromPubKey(ecPoint));
-    if (!objID.get()) {
-      return nullptr;
-    }
-
-    // Populate template from parameters
-    CK_KEY_TYPE ecValue = CKK_EC;
-    CK_ATTRIBUTE keyTemplate[9] = {
-      { CKA_CLASS,            &privateKeyValue,     sizeof(privateKeyValue) },
-      { CKA_KEY_TYPE,         &ecValue,             sizeof(ecValue) },
-      { CKA_TOKEN,            &falseValue,          sizeof(falseValue) },
-      { CKA_SENSITIVE,        &falseValue,          sizeof(falseValue) },
-      { CKA_PRIVATE,          &falseValue,          sizeof(falseValue) },
-      { CKA_ID,               objID->data,          objID->len },
-      { CKA_EC_PARAMS,        params->data,         params->len },
-      { CKA_EC_POINT,         ecPoint->data,        ecPoint->len },
-      { CKA_VALUE,            (void*) d.Elements(), d.Length() },
-    };
-
-    return PrivateKeyFromPrivateKeyTemplate(objID, keyTemplate,
-                                            PR_ARRAY_SIZE(keyTemplate));
-  }
-
-  if (aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_RSA)) {
-    // Verify that all of the required parameters are present
-    CryptoBuffer n, e, d, p, q, dp, dq, qi;
-    if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) ||
-        !aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value())) ||
-        !aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value())) ||
-        !aJwk.mP.WasPassed() || NS_FAILED(p.FromJwkBase64(aJwk.mP.Value())) ||
-        !aJwk.mQ.WasPassed() || NS_FAILED(q.FromJwkBase64(aJwk.mQ.Value())) ||
-        !aJwk.mDp.WasPassed() || NS_FAILED(dp.FromJwkBase64(aJwk.mDp.Value())) ||
-        !aJwk.mDq.WasPassed() || NS_FAILED(dq.FromJwkBase64(aJwk.mDq.Value())) ||
-        !aJwk.mQi.WasPassed() || NS_FAILED(qi.FromJwkBase64(aJwk.mQi.Value()))) {
-      return nullptr;
-    }
-
-    // Compute the ID for this key
-    // This is generated with a SHA-1 hash, so unlikely to collide
-    ScopedSECItem nItem(n.ToSECItem());
-    if (!nItem.get()) {
-      return nullptr;
-    }
-
-    ScopedSECItem objID(PK11_MakeIDFromPubKey(nItem.get()));
-    if (!objID.get()) {
-      return nullptr;
-    }
-
-    // Populate template from parameters
-    CK_KEY_TYPE rsaValue = CKK_RSA;
-    CK_ATTRIBUTE keyTemplate[14] = {
-      { CKA_CLASS,            &privateKeyValue,      sizeof(privateKeyValue) },
-      { CKA_KEY_TYPE,         &rsaValue,             sizeof(rsaValue) },
-      { CKA_TOKEN,            &falseValue,           sizeof(falseValue) },
-      { CKA_SENSITIVE,        &falseValue,           sizeof(falseValue) },
-      { CKA_PRIVATE,          &falseValue,           sizeof(falseValue) },
-      { CKA_ID,               objID->data,           objID->len },
-      { CKA_MODULUS,          (void*) n.Elements(),  n.Length() },
-      { CKA_PUBLIC_EXPONENT,  (void*) e.Elements(),  e.Length() },
-      { CKA_PRIVATE_EXPONENT, (void*) d.Elements(),  d.Length() },
-      { CKA_PRIME_1,          (void*) p.Elements(),  p.Length() },
-      { CKA_PRIME_2,          (void*) q.Elements(),  q.Length() },
-      { CKA_EXPONENT_1,       (void*) dp.Elements(), dp.Length() },
-      { CKA_EXPONENT_2,       (void*) dq.Elements(), dq.Length() },
-      { CKA_COEFFICIENT,      (void*) qi.Elements(), qi.Length() },
-    };
-
-    return PrivateKeyFromPrivateKeyTemplate(objID, keyTemplate,
-                                            PR_ARRAY_SIZE(keyTemplate));
-  }
-
-  return nullptr;
-}
-
 bool ReadAndEncodeAttribute(SECKEYPrivateKey* aKey,
                             CK_ATTRIBUTE_TYPE aAttribute,
                             Optional<nsString>& aDst)
 {
   ScopedSECItem item(new SECItem());
   if (PK11_ReadRawAttribute(PK11_TypePrivKey, aKey, aAttribute, item)
         != SECSuccess) {
     return false;
@@ -573,81 +444,16 @@ bool ReadAndEncodeAttribute(SECKEYPrivat
 
   if (NS_FAILED(buffer.ToJwkBase64(aDst.Value()))) {
     return false;
   }
 
   return true;
 }
 
-bool
-ECKeyToJwk(const PK11ObjectType aKeyType, void* aKey, const SECItem* aEcParams,
-           const SECItem* aPublicValue, JsonWebKey& aRetVal)
-{
-  aRetVal.mX.Construct();
-  aRetVal.mY.Construct();
-
-  // Check that the given EC parameters are valid.
-  if (!CheckEncodedECParameters(aEcParams)) {
-    return false;
-  }
-
-  // Construct the OID tag.
-  SECItem oid = { siBuffer, nullptr, 0 };
-  oid.len = aEcParams->data[1];
-  oid.data = aEcParams->data + 2;
-
-  uint32_t flen;
-  switch (SECOID_FindOIDTag(&oid)) {
-    case SEC_OID_SECG_EC_SECP256R1:
-      flen = 32; // bytes
-      aRetVal.mCrv.Construct(NS_LITERAL_STRING(WEBCRYPTO_NAMED_CURVE_P256));
-      break;
-    case SEC_OID_SECG_EC_SECP384R1:
-      flen = 48; // bytes
-      aRetVal.mCrv.Construct(NS_LITERAL_STRING(WEBCRYPTO_NAMED_CURVE_P384));
-      break;
-    case SEC_OID_SECG_EC_SECP521R1:
-      flen = 66; // bytes
-      aRetVal.mCrv.Construct(NS_LITERAL_STRING(WEBCRYPTO_NAMED_CURVE_P521));
-      break;
-    default:
-      return false;
-  }
-
-  // No support for compressed points.
-  if (aPublicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
-    return false;
-  }
-
-  // Check length of uncompressed point coordinates.
-  if (aPublicValue->len != (2 * flen + 1)) {
-    return false;
-  }
-
-  ScopedSECItem ecPointX(::SECITEM_AllocItem(nullptr, nullptr, flen));
-  ScopedSECItem ecPointY(::SECITEM_AllocItem(nullptr, nullptr, flen));
-  if (!ecPointX || !ecPointY) {
-    return false;
-  }
-
-  // Extract point data.
-  memcpy(ecPointX->data, aPublicValue->data + 1, flen);
-  memcpy(ecPointY->data, aPublicValue->data + 1 + flen, flen);
-
-  CryptoBuffer x, y;
-  if (!x.Assign(ecPointX) || NS_FAILED(x.ToJwkBase64(aRetVal.mX.Value())) ||
-      !y.Assign(ecPointY) || NS_FAILED(y.ToJwkBase64(aRetVal.mY.Value()))) {
-    return false;
-  }
-
-  aRetVal.mKty.Construct(NS_LITERAL_STRING(JWK_TYPE_EC));
-  return true;
-}
-
 nsresult
 CryptoKey::PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey,
                            JsonWebKey& aRetVal,
                            const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
   switch (aPrivKey->keyType) {
     case rsaKey: {
       aRetVal.mN.Construct();
@@ -668,138 +474,60 @@ CryptoKey::PrivateKeyToJwk(SECKEYPrivate
           !ReadAndEncodeAttribute(aPrivKey, CKA_EXPONENT_2, aRetVal.mDq) ||
           !ReadAndEncodeAttribute(aPrivKey, CKA_COEFFICIENT, aRetVal.mQi)) {
         return NS_ERROR_DOM_OPERATION_ERR;
       }
 
       aRetVal.mKty.Construct(NS_LITERAL_STRING(JWK_TYPE_RSA));
       return NS_OK;
     }
-    case ecKey: {
-      // Read EC params.
-      ScopedSECItem params(::SECITEM_AllocItem(nullptr, nullptr, 0));
-      SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, aPrivKey,
-                                           CKA_EC_PARAMS, params);
-      if (rv != SECSuccess) {
-        return NS_ERROR_DOM_OPERATION_ERR;
-      }
-
-      // Read public point Q.
-      ScopedSECItem ecPoint(::SECITEM_AllocItem(nullptr, nullptr, 0));
-      rv = PK11_ReadRawAttribute(PK11_TypePrivKey, aPrivKey, CKA_EC_POINT,
-                                 ecPoint);
-      if (rv != SECSuccess) {
-        return NS_ERROR_DOM_OPERATION_ERR;
-      }
-
-      if (!ECKeyToJwk(PK11_TypePrivKey, aPrivKey, params, ecPoint, aRetVal)) {
-        return NS_ERROR_DOM_OPERATION_ERR;
-      }
-
-      aRetVal.mD.Construct();
-
-      // Read private value.
-      if (!ReadAndEncodeAttribute(aPrivKey, CKA_VALUE, aRetVal.mD)) {
-        return NS_ERROR_DOM_OPERATION_ERR;
-      }
-
-      return NS_OK;
-    }
+    case ecKey: // TODO: Bug 1034855
     default:
       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 }
 
 SECKEYPublicKey*
 CryptoKey::PublicKeyFromJwk(const JsonWebKey& aJwk,
                             const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
-  if (!aJwk.mKty.WasPassed()) {
+  if (!aJwk.mKty.WasPassed() || !aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_RSA)) {
+    return nullptr;
+  }
+
+  // Verify that all of the required parameters are present
+  CryptoBuffer n, e;
+  if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) ||
+      !aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value()))) {
     return nullptr;
   }
 
-  if (aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_RSA)) {
-    // Verify that all of the required parameters are present
-    CryptoBuffer n, e;
-    if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) ||
-        !aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value()))) {
-      return nullptr;
-    }
+  // Transcode to a DER RSAPublicKey structure
+  struct RSAPublicKeyData {
+    SECItem n;
+    SECItem e;
+  };
+  const RSAPublicKeyData input = {
+    { siUnsignedInteger, n.Elements(), (unsigned int) n.Length() },
+    { siUnsignedInteger, e.Elements(), (unsigned int) e.Length() }
+  };
+  const SEC_ASN1Template rsaPublicKeyTemplate[] = {
+    {SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(RSAPublicKeyData)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPublicKeyData, n),},
+    {SEC_ASN1_INTEGER, offsetof(RSAPublicKeyData, e),},
+    {0,}
+  };
 
-    // Transcode to a DER RSAPublicKey structure
-    struct RSAPublicKeyData {
-      SECItem n;
-      SECItem e;
-    };
-    const RSAPublicKeyData input = {
-      { siUnsignedInteger, n.Elements(), (unsigned int) n.Length() },
-      { siUnsignedInteger, e.Elements(), (unsigned int) e.Length() }
-    };
-    const SEC_ASN1Template rsaPublicKeyTemplate[] = {
-      {SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(RSAPublicKeyData)},
-      {SEC_ASN1_INTEGER, offsetof(RSAPublicKeyData, n),},
-      {SEC_ASN1_INTEGER, offsetof(RSAPublicKeyData, e),},
-      {0,}
-    };
-
-    ScopedSECItem pkDer(SEC_ASN1EncodeItem(nullptr, nullptr, &input,
-                                           rsaPublicKeyTemplate));
-    if (!pkDer.get()) {
-      return nullptr;
-    }
-
-    return SECKEY_ImportDERPublicKey(pkDer.get(), CKK_RSA);
+  ScopedSECItem pkDer(SEC_ASN1EncodeItem(nullptr, nullptr, &input,
+                                         rsaPublicKeyTemplate));
+  if (!pkDer.get()) {
+    return nullptr;
   }
 
-  if (aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_EC)) {
-    // Verify that all of the required parameters are present
-    CryptoBuffer x, y;
-    if (!aJwk.mCrv.WasPassed() ||
-        !aJwk.mX.WasPassed() || NS_FAILED(x.FromJwkBase64(aJwk.mX.Value())) ||
-        !aJwk.mY.WasPassed() || NS_FAILED(y.FromJwkBase64(aJwk.mY.Value()))) {
-      return nullptr;
-    }
-
-    ScopedSECKEYPublicKey key(PORT_ZNew(SECKEYPublicKey));
-    if (!key) {
-      return nullptr;
-    }
-
-    key->keyType = ecKey;
-    key->pkcs11Slot = nullptr;
-    key->pkcs11ID = CK_INVALID_HANDLE;
-
-    nsString namedCurve;
-    if (!NormalizeNamedCurveValue(aJwk.mCrv.Value(), namedCurve)) {
-      return nullptr;
-    }
-
-    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-    if (!arena) {
-      return nullptr;
-    }
-
-    // Create parameters.
-    SECItem* params = CreateECParamsForCurve(namedCurve, arena.get());
-    if (!params) {
-      return nullptr;
-    }
-    key->u.ec.DEREncodedParams = *params;
-
-    // Create point.
-    SECItem* point = CreateECPointForCoordinates(x, y, arena.get());
-    if (!point) {
-      return nullptr;
-    }
-    key->u.ec.publicValue = *point;
-
-    return SECKEY_CopyPublicKey(key);
-  }
-
-  return nullptr;
+  return SECKEY_ImportDERPublicKey(pkDer.get(), CKK_RSA);
 }
 
 nsresult
 CryptoKey::PublicKeyToJwk(SECKEYPublicKey* aPubKey,
                           JsonWebKey& aRetVal,
                           const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
   switch (aPubKey->keyType) {
@@ -813,22 +541,17 @@ CryptoKey::PublicKeyToJwk(SECKEYPublicKe
           NS_FAILED(n.ToJwkBase64(aRetVal.mN.Value())) ||
           NS_FAILED(e.ToJwkBase64(aRetVal.mE.Value()))) {
         return NS_ERROR_DOM_OPERATION_ERR;
       }
 
       aRetVal.mKty.Construct(NS_LITERAL_STRING(JWK_TYPE_RSA));
       return NS_OK;
     }
-    case ecKey:
-      if (!ECKeyToJwk(PK11_TypePubKey, aPubKey, &aPubKey->u.ec.DEREncodedParams,
-                      &aPubKey->u.ec.publicValue, aRetVal)) {
-        return NS_ERROR_DOM_OPERATION_ERR;
-      }
-      return NS_OK;
+    case ecKey: // TODO
     default:
       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 }
 
 bool
 CryptoKey::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
 {
deleted file mode 100644
--- a/dom/crypto/EcKeyAlgorithm.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/EcKeyAlgorithm.h"
-#include "mozilla/dom/SubtleCryptoBinding.h"
-#include "mozilla/dom/WebCryptoCommon.h"
-
-namespace mozilla {
-namespace dom {
-
-JSObject*
-EcKeyAlgorithm::WrapObject(JSContext* aCx)
-{
-  return EcKeyAlgorithmBinding::Wrap(aCx, this);
-}
-
-bool
-EcKeyAlgorithm::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
-{
-  return JS_WriteUint32Pair(aWriter, SCTAG_ECKEYALG, 0) &&
-         WriteString(aWriter, mNamedCurve) &&
-         WriteString(aWriter, mName);
-}
-
-KeyAlgorithm*
-EcKeyAlgorithm::Create(nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader)
-{
-  nsString name;
-  nsString namedCurve;
-  bool read = ReadString(aReader, namedCurve) &&
-              ReadString(aReader, name);
-  if (!read) {
-    return nullptr;
-  }
-
-  return new EcKeyAlgorithm(aGlobal, name, namedCurve);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/crypto/EcKeyAlgorithm.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_EcKeyAlgorithm_h
-#define mozilla_dom_EcKeyAlgorithm_h
-
-#include "mozilla/ErrorResult.h"
-#include "mozilla/dom/KeyAlgorithm.h"
-#include "js/TypeDecls.h"
-
-namespace mozilla {
-namespace dom {
-
-class EcKeyAlgorithm : public KeyAlgorithm
-{
-public:
-  EcKeyAlgorithm(nsIGlobalObject* aGlobal,
-                 const nsString& aName,
-                 const nsString& aNamedCurve)
-    : KeyAlgorithm(aGlobal, aName)
-    , mNamedCurve(aNamedCurve)
-  {}
-
-  ~EcKeyAlgorithm()
-  {}
-
-  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
-
-  void GetNamedCurve(nsString& aRetVal) const
-  {
-    aRetVal.Assign(mNamedCurve);
-  }
-
-  virtual bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const MOZ_OVERRIDE;
-  static KeyAlgorithm* Create(nsIGlobalObject* aGlobal,
-                              JSStructuredCloneReader* aReader);
-
-protected:
-  nsString mNamedCurve;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_EcKeyAlgorithm_h
--- a/dom/crypto/KeyAlgorithm.cpp
+++ b/dom/crypto/KeyAlgorithm.cpp
@@ -2,17 +2,16 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/KeyAlgorithm.h"
 #include "mozilla/dom/WebCryptoCommon.h"
 #include "mozilla/dom/AesKeyAlgorithm.h"
-#include "mozilla/dom/EcKeyAlgorithm.h"
 #include "mozilla/dom/HmacKeyAlgorithm.h"
 #include "mozilla/dom/RsaKeyAlgorithm.h"
 #include "mozilla/dom/RsaHashedKeyAlgorithm.h"
 #include "mozilla/dom/SubtleCryptoBinding.h"
 #include "mozilla/dom/WebCryptoCommon.h"
 
 namespace mozilla {
 namespace dom {
@@ -85,20 +84,16 @@ KeyAlgorithm::Create(nsIGlobalObject* aG
       }
       algorithm = new KeyAlgorithm(aGlobal, name);
       break;
     }
     case SCTAG_AESKEYALG: {
       algorithm = AesKeyAlgorithm::Create(aGlobal, aReader);
       break;
     }
-    case SCTAG_ECKEYALG: {
-      algorithm = EcKeyAlgorithm::Create(aGlobal, aReader);
-      break;
-    }
     case SCTAG_HMACKEYALG: {
       algorithm = HmacKeyAlgorithm::Create(aGlobal, aReader);
       break;
     }
     case SCTAG_RSAKEYALG: {
       algorithm = RsaKeyAlgorithm::Create(aGlobal, aReader);
       break;
     }
--- a/dom/crypto/KeyAlgorithm.h
+++ b/dom/crypto/KeyAlgorithm.h
@@ -19,17 +19,16 @@ namespace mozilla {
 namespace dom {
 
 class CryptoKey;
 class KeyAlgorithm;
 
 enum KeyAlgorithmStructuredCloneTags {
   SCTAG_KEYALG,
   SCTAG_AESKEYALG,
-  SCTAG_ECKEYALG,
   SCTAG_HMACKEYALG,
   SCTAG_RSAKEYALG,
   SCTAG_RSAHASHEDKEYALG
 };
 
 }
 
 namespace dom {
--- a/dom/crypto/WebCryptoCommon.h
+++ b/dom/crypto/WebCryptoCommon.h
@@ -21,17 +21,16 @@
 #define WEBCRYPTO_ALG_SHA256        "SHA-256"
 #define WEBCRYPTO_ALG_SHA384        "SHA-384"
 #define WEBCRYPTO_ALG_SHA512        "SHA-512"
 #define WEBCRYPTO_ALG_HMAC          "HMAC"
 #define WEBCRYPTO_ALG_PBKDF2        "PBKDF2"
 #define WEBCRYPTO_ALG_RSAES_PKCS1   "RSAES-PKCS1-v1_5"
 #define WEBCRYPTO_ALG_RSASSA_PKCS1  "RSASSA-PKCS1-v1_5"
 #define WEBCRYPTO_ALG_RSA_OAEP      "RSA-OAEP"
-#define WEBCRYPTO_ALG_ECDH          "ECDH"
 
 // WebCrypto key formats
 #define WEBCRYPTO_KEY_FORMAT_RAW    "raw"
 #define WEBCRYPTO_KEY_FORMAT_PKCS8  "pkcs8"
 #define WEBCRYPTO_KEY_FORMAT_SPKI   "spki"
 #define WEBCRYPTO_KEY_FORMAT_JWK    "jwk"
 
 // WebCrypto key types
@@ -44,21 +43,16 @@
 #define WEBCRYPTO_KEY_USAGE_DECRYPT     "decrypt"
 #define WEBCRYPTO_KEY_USAGE_SIGN        "sign"
 #define WEBCRYPTO_KEY_USAGE_VERIFY      "verify"
 #define WEBCRYPTO_KEY_USAGE_DERIVEKEY   "deriveKey"
 #define WEBCRYPTO_KEY_USAGE_DERIVEBITS  "deriveBits"
 #define WEBCRYPTO_KEY_USAGE_WRAPKEY     "wrapKey"
 #define WEBCRYPTO_KEY_USAGE_UNWRAPKEY   "unwrapKey"
 
-// WebCrypto named curves
-#define WEBCRYPTO_NAMED_CURVE_P256  "P-256"
-#define WEBCRYPTO_NAMED_CURVE_P384  "P-384"
-#define WEBCRYPTO_NAMED_CURVE_P521  "P-521"
-
 // JWK key types
 #define JWK_TYPE_SYMMETRIC          "oct"
 #define JWK_TYPE_RSA                "RSA"
 #define JWK_TYPE_EC                 "EC"
 
 // JWK algorithms
 #define JWK_ALG_A128CBC             "A128CBC"  // CBC
 #define JWK_ALG_A192CBC             "A192CBC"
@@ -87,21 +81,16 @@
 
 // JWK usages
 #define JWK_USE_ENC                 "enc"
 #define JWK_USE_SIG                 "sig"
 
 // Define an unknown mechanism type
 #define UNKNOWN_CK_MECHANISM        CKM_VENDOR_DEFINED+1
 
-// python security/pkix/tools/DottedOIDToCode.py id-ecDH 1.3.132.112
-static const uint8_t id_ecDH[] = { 0x2b, 0x81, 0x04, 0x70 };
-const SECItem SEC_OID_DATA_EC_DH = { siBuffer, (unsigned char*)id_ecDH,
-                                     PR_ARRAY_SIZE(id_ecDH) };
-
 namespace mozilla {
 namespace dom {
 
 // Helper functions for structured cloning
 inline bool
 ReadString(JSStructuredCloneReader* aReader, nsString& aString)
 {
   bool read;
@@ -182,101 +171,17 @@ MapAlgorithmNameToMechanism(const nsStri
   } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
     mechanism = CKM_PKCS5_PBKD2;
   } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
     mechanism = CKM_RSA_PKCS;
   } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
     mechanism = CKM_RSA_PKCS;
   } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
     mechanism = CKM_RSA_PKCS_OAEP;
-  } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
-    mechanism = CKM_ECDH1_DERIVE;
   }
 
   return mechanism;
 }
 
-inline bool
-NormalizeNamedCurveValue(const nsString& aNamedCurve, nsString& aDest)
-{
-  if (aNamedCurve.EqualsIgnoreCase(WEBCRYPTO_NAMED_CURVE_P256)) {
-    aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P256);
-  } else if (aNamedCurve.EqualsIgnoreCase(WEBCRYPTO_NAMED_CURVE_P384)) {
-    aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P384);
-  } else if (aNamedCurve.EqualsIgnoreCase(WEBCRYPTO_NAMED_CURVE_P521)) {
-    aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P521);
-  } else {
-    return false;
-  }
-
-  return true;
-}
-
-inline bool
-CheckEncodedECParameters(const SECItem* aEcParams)
-{
-  // Need at least two bytes for a valid ASN.1 encoding.
-  if (aEcParams->len < 2) {
-    return false;
-  }
-
-  // Check the ASN.1 tag.
-  if (aEcParams->data[0] != SEC_ASN1_OBJECT_ID) {
-    return false;
-  }
-
-  // OID tags are short, we never need more than one length byte.
-  if (aEcParams->data[1] >= 128) {
-    return false;
-  }
-
-  // Check that the SECItem's length is correct.
-  if (aEcParams->len != (unsigned)aEcParams->data[1] + 2) {
-    return false;
-  }
-
-  return true;
-}
-
-inline SECItem*
-CreateECParamsForCurve(const nsString& aNamedCurve, PLArenaPool* aArena)
-{
-  SECOidTag curveOIDTag;
-
-  if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P256)) {
-    curveOIDTag = SEC_OID_SECG_EC_SECP256R1;
-  } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P384)) {
-    curveOIDTag = SEC_OID_SECG_EC_SECP384R1;
-  } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P521)) {
-    curveOIDTag = SEC_OID_SECG_EC_SECP521R1;
-  } else {
-    return nullptr;
-  }
-
-  // Retrieve curve data by OID tag.
-  SECOidData* oidData = SECOID_FindOIDByTag(curveOIDTag);
-  if (!oidData) {
-    return nullptr;
-  }
-
-  // Create parameters.
-  SECItem* params = ::SECITEM_AllocItem(aArena, nullptr, 2 + oidData->oid.len);
-  if (!params) {
-    return nullptr;
-  }
-
-  // Set parameters.
-  params->data[0] = SEC_ASN1_OBJECT_ID;
-  params->data[1] = oidData->oid.len;
-  memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
-
-  // Sanity check the params we just created.
-  if (!CheckEncodedECParameters(params)) {
-    return nullptr;
-  }
-
-  return params;
-}
-
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_WebCryptoCommon_h
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -10,17 +10,16 @@
 #include "ScopedNSSTypes.h"
 
 #include "jsapi.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/AesKeyAlgorithm.h"
 #include "mozilla/dom/CryptoBuffer.h"
 #include "mozilla/dom/CryptoKey.h"
 #include "mozilla/dom/CryptoKeyPair.h"
-#include "mozilla/dom/EcKeyAlgorithm.h"
 #include "mozilla/dom/HmacKeyAlgorithm.h"
 #include "mozilla/dom/KeyAlgorithm.h"
 #include "mozilla/dom/RsaHashedKeyAlgorithm.h"
 #include "mozilla/dom/RsaKeyAlgorithm.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/dom/WebCryptoCommon.h"
 #include "mozilla/dom/WebCryptoTask.h"
@@ -155,18 +154,16 @@ GetAlgorithmName(JSContext* aCx, const O
   } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_PBKDF2)) {
     aName.AssignLiteral(WEBCRYPTO_ALG_PBKDF2);
   } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_RSAES_PKCS1)) {
     aName.AssignLiteral(WEBCRYPTO_ALG_RSAES_PKCS1);
   } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
     aName.AssignLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1);
   } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_RSA_OAEP)) {
     aName.AssignLiteral(WEBCRYPTO_ALG_RSA_OAEP);
-  } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_ECDH)) {
-    aName.AssignLiteral(WEBCRYPTO_ALG_ECDH);
   }
 
   return NS_OK;
 }
 
 template<class T, class OOS>
 static nsresult
 Coerce(JSContext* aCx, T& aTarget, const OOS& aAlgorithm)
@@ -253,36 +250,16 @@ GetKeySizeForAlgorithm(JSContext* aCx, c
 
     aLength = length;
     return NS_OK;
   }
 
   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 }
 
-inline bool
-MapOIDTagToNamedCurve(SECOidTag aOIDTag, nsString& aResult)
-{
-  switch (aOIDTag) {
-    case SEC_OID_SECG_EC_SECP256R1:
-      aResult.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P256);
-      break;
-    case SEC_OID_SECG_EC_SECP384R1:
-      aResult.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P384);
-      break;
-    case SEC_OID_SECG_EC_SECP521R1:
-      aResult.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P521);
-      break;
-    default:
-      return false;
-  }
-
-  return true;
-}
-
 // Helper function to clone data from an ArrayBuffer or ArrayBufferView object
 inline bool
 CloneData(JSContext* aCx, CryptoBuffer& aDst, JS::Handle<JSObject*> aSrc)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Try ArrayBuffer
   RootedTypedArray<ArrayBuffer> ab(aCx);
@@ -1669,123 +1646,16 @@ private:
     if (mDataIsJwk && !JwkCompatible(mJwk, mKey)) {
       return NS_ERROR_DOM_DATA_ERR;
     }
 
     return NS_OK;
   }
 };
 
-class ImportEcKeyTask : public ImportKeyTask
-{
-public:
-  ImportEcKeyTask(JSContext* aCx, const nsAString& aFormat,
-                  const ObjectOrString& aAlgorithm, bool aExtractable,
-                  const Sequence<nsString>& aKeyUsages)
-  {
-    ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
-  }
-
-  ImportEcKeyTask(JSContext* aCx, const nsAString& aFormat,
-                  JS::Handle<JSObject*> aKeyData,
-                  const ObjectOrString& aAlgorithm, bool aExtractable,
-                  const Sequence<nsString>& aKeyUsages)
-  {
-    ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
-    if (NS_FAILED(mEarlyRv)) {
-      return;
-    }
-
-    SetKeyData(aCx, aKeyData);
-  }
-
-private:
-  nsString mNamedCurve;
-
-  virtual nsresult DoCrypto() MOZ_OVERRIDE
-  {
-    // Import the key data itself
-    ScopedSECKEYPublicKey pubKey;
-    ScopedSECKEYPrivateKey privKey;
-
-    nsNSSShutDownPreventionLock locker;
-    if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK) && mJwk.mD.WasPassed()) {
-      // Private key import
-      privKey = CryptoKey::PrivateKeyFromJwk(mJwk, locker);
-      if (!privKey) {
-        return NS_ERROR_DOM_DATA_ERR;
-      }
-
-      mKey->SetPrivateKey(privKey.get());
-      mKey->SetType(CryptoKey::PRIVATE);
-    } else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI) ||
-               (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK) &&
-                !mJwk.mD.WasPassed())) {
-      // Public key import
-      if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) {
-        pubKey = CryptoKey::PublicKeyFromSpki(mKeyData, locker);
-      } else {
-        pubKey = CryptoKey::PublicKeyFromJwk(mJwk, locker);
-      }
-
-      if (!pubKey) {
-        return NS_ERROR_DOM_DATA_ERR;
-      }
-
-      if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) {
-        if (!CheckEncodedECParameters(&pubKey->u.ec.DEREncodedParams)) {
-          return NS_ERROR_DOM_OPERATION_ERR;
-        }
-
-        // Construct the OID tag.
-        SECItem oid = { siBuffer, nullptr, 0 };
-        oid.len = pubKey->u.ec.DEREncodedParams.data[1];
-        oid.data = pubKey->u.ec.DEREncodedParams.data + 2;
-
-        // Find a matching and supported named curve.
-        if (!MapOIDTagToNamedCurve(SECOID_FindOIDTag(&oid), mNamedCurve)) {
-          return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
-        }
-      }
-
-      mKey->SetPublicKey(pubKey.get());
-      mKey->SetType(CryptoKey::PUBLIC);
-    } else {
-      return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
-    }
-
-    // Extract 'crv' parameter from JWKs.
-    if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
-      if (!NormalizeNamedCurveValue(mJwk.mCrv.Value(), mNamedCurve)) {
-        return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
-      }
-    }
-
-    return NS_OK;
-  }
-
-  virtual nsresult AfterCrypto() MOZ_OVERRIDE
-  {
-    // Check permissions for the requested operation
-    if (mKey->GetKeyType() == CryptoKey::PRIVATE &&
-        mKey->HasUsageOtherThan(CryptoKey::DERIVEBITS | CryptoKey::DERIVEKEY)) {
-      return NS_ERROR_DOM_DATA_ERR;
-    }
-
-    nsIGlobalObject* global = mKey->GetParentObject();
-    mKey->SetAlgorithm(new EcKeyAlgorithm(global, mAlgName, mNamedCurve));
-
-    if (mDataIsJwk && !JwkCompatible(mJwk, mKey)) {
-      return NS_ERROR_DOM_DATA_ERR;
-    }
-
-    return NS_OK;
-  }
-};
-
 class ExportKeyTask : public WebCryptoTask
 {
 public:
   ExportKeyTask(const nsAString& aFormat, CryptoKey& aKey)
     : mFormat(aFormat)
     , mSymKey(aKey.GetSymKey())
     , mPrivateKey(aKey.GetPrivateKey())
     , mPublicKey(aKey.GetPublicKey())
@@ -2122,50 +1992,29 @@ public:
 
       // Set up params struct
       mRsaParams.keySizeInBits = modulusLength;
       bool converted = publicExponent.GetBigIntValue(mRsaParams.pe);
       if (!converted) {
         mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
         return;
       }
-    } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
-      RootedDictionary<EcKeyGenParams> params(aCx);
-      mEarlyRv = Coerce(aCx, params, aAlgorithm);
-      if (NS_FAILED(mEarlyRv) || !params.mNamedCurve.WasPassed()) {
-        mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
-        return;
-      }
-
-      if (!NormalizeNamedCurveValue(params.mNamedCurve.Value(), mNamedCurve)) {
-        mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
-        return;
-      }
-
-      // Create algorithm.
-      algorithm = new EcKeyAlgorithm(global, algName, mNamedCurve);
-      mKeyPair->PublicKey()->SetAlgorithm(algorithm);
-      mKeyPair->PrivateKey()->SetAlgorithm(algorithm);
-      mMechanism = CKM_EC_KEY_PAIR_GEN;
     } else {
       mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
       return;
     }
 
     // Set key usages.
     if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
       privateAllowedUsages = CryptoKey::SIGN;
       publicAllowedUsages = CryptoKey::VERIFY;
     } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
                algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
       privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY;
       publicAllowedUsages = CryptoKey::ENCRYPT | CryptoKey::WRAPKEY;
-    } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
-      privateAllowedUsages = CryptoKey::DERIVEKEY | CryptoKey::DERIVEBITS;
-      publicAllowedUsages = 0;
     }
 
     mKeyPair->PrivateKey()->SetExtractable(aExtractable);
     mKeyPair->PrivateKey()->SetType(CryptoKey::PRIVATE);
 
     mKeyPair->PublicKey()->SetExtractable(true);
     mKeyPair->PublicKey()->SetType(CryptoKey::PUBLIC);
 
@@ -2187,50 +2036,32 @@ public:
   }
 
 private:
   nsRefPtr<CryptoKeyPair> mKeyPair;
   CK_MECHANISM_TYPE mMechanism;
   PK11RSAGenParams mRsaParams;
   ScopedSECKEYPublicKey mPublicKey;
   ScopedSECKEYPrivateKey mPrivateKey;
-  nsString mNamedCurve;
 
   virtual void ReleaseNSSResources() MOZ_OVERRIDE
   {
     mPublicKey.dispose();
     mPrivateKey.dispose();
   }
 
   virtual nsresult DoCrypto() MOZ_OVERRIDE
   {
     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
     MOZ_ASSERT(slot.get());
 
     void* param;
-    ScopedPLArenaPool arena;
-
     switch (mMechanism) {
-      case CKM_RSA_PKCS_KEY_PAIR_GEN:
-        param = &mRsaParams;
-        break;
-      case CKM_EC_KEY_PAIR_GEN: {
-        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-        if (!arena) {
-          return NS_ERROR_DOM_UNKNOWN_ERR;
-        }
-
-        param = CreateECParamsForCurve(mNamedCurve, arena.get());
-        if (!param) {
-          return NS_ERROR_DOM_UNKNOWN_ERR;
-        }
-        break;
-      }
-      default:
-        return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+      case CKM_RSA_PKCS_KEY_PAIR_GEN: param = &mRsaParams; break;
+      default: return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     }
 
     SECKEYPublicKey* pubKey = nullptr;
     mPrivateKey = PK11_GenerateKeyPair(slot.get(), mMechanism, param, &pubKey,
                                        PR_FALSE, PR_FALSE, nullptr);
     mPublicKey = pubKey;
     if (!mPrivateKey.get() || !mPublicKey.get()) {
       return NS_ERROR_DOM_UNKNOWN_ERR;
@@ -2366,166 +2197,55 @@ private:
     // This doesn't leak, because the SECItem* returned by PK11_GetKeyData
     // just refers to a buffer managed by symKey. The assignment copies the
     // data, so mResult manages one copy, while symKey manages another.
     ATTEMPT_BUFFER_ASSIGN(mResult, PK11_GetKeyData(symKey));
     return NS_OK;
   }
 };
 
-template<class DeriveBitsTask>
-class DeriveKeyTask : public DeriveBitsTask
+class DerivePbkdfKeyTask : public DerivePbkdfBitsTask
 {
 public:
-  DeriveKeyTask(JSContext* aCx,
-                const ObjectOrString& aAlgorithm, CryptoKey& aBaseKey,
-                const ObjectOrString& aDerivedKeyType, bool aExtractable,
-                const Sequence<nsString>& aKeyUsages)
-    : DeriveBitsTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType)
+  DerivePbkdfKeyTask(JSContext* aCx,
+                     const ObjectOrString& aAlgorithm, CryptoKey& aBaseKey,
+                     const ObjectOrString& aDerivedKeyType, bool aExtractable,
+                     const Sequence<nsString>& aKeyUsages)
+    : DerivePbkdfBitsTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType)
     , mResolved(false)
   {
-    if (NS_FAILED(this->mEarlyRv)) {
+    if (NS_FAILED(mEarlyRv)) {
       return;
     }
 
     NS_NAMED_LITERAL_STRING(format, WEBCRYPTO_KEY_FORMAT_RAW);
     mTask = new ImportSymmetricKeyTask(aCx, format, aDerivedKeyType,
                                        aExtractable, aKeyUsages);
   }
 
 protected:
   nsRefPtr<ImportSymmetricKeyTask> mTask;
   bool mResolved;
 
 private:
   virtual void Resolve() MOZ_OVERRIDE {
-    mTask->SetKeyData(this->mResult);
-    mTask->DispatchWithPromise(this->mResultPromise);
+    mTask->SetKeyData(mResult);
+    mTask->DispatchWithPromise(mResultPromise);
     mResolved = true;
   }
 
   virtual void Cleanup() MOZ_OVERRIDE
   {
     if (mTask && !mResolved) {
       mTask->Skip();
     }
     mTask = nullptr;
   }
 };
 
-class DeriveEcdhBitsTask : public ReturnArrayBufferViewTask
-{
-public:
-  DeriveEcdhBitsTask(JSContext* aCx,
-      const ObjectOrString& aAlgorithm, CryptoKey& aKey, uint32_t aLength)
-    : mLength(aLength),
-      mPrivKey(aKey.GetPrivateKey())
-  {
-    Init(aCx, aAlgorithm, aKey);
-  }
-
-  DeriveEcdhBitsTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
-                     CryptoKey& aKey, const ObjectOrString& aTargetAlgorithm)
-    : mPrivKey(aKey.GetPrivateKey())
-  {
-    mEarlyRv = GetKeySizeForAlgorithm(aCx, aTargetAlgorithm, mLength);
-    if (NS_SUCCEEDED(mEarlyRv)) {
-      Init(aCx, aAlgorithm, aKey);
-    }
-  }
-
-  void Init(JSContext* aCx, const ObjectOrString& aAlgorithm, CryptoKey& aKey)
-  {
-    // Check that we have a private key.
-    if (!mPrivKey) {
-      mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
-      return;
-    }
-
-    // Length must be a multiple of 8 bigger than zero.
-    if (mLength == 0 || mLength % 8) {
-      mEarlyRv = NS_ERROR_DOM_DATA_ERR;
-      return;
-    }
-
-    mLength = mLength >> 3; // bits to bytes
-
-    // Retrieve the peer's public key.
-    RootedDictionary<EcdhKeyDeriveParams> params(aCx);
-    mEarlyRv = Coerce(aCx, params, aAlgorithm);
-    if (NS_FAILED(mEarlyRv) || !params.mPublic.WasPassed()) {
-      mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
-      return;
-    }
-
-    CryptoKey* publicKey = params.mPublic.Value();
-    mPubKey = publicKey->GetPublicKey();
-    if (!mPubKey) {
-      mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
-      return;
-    }
-
-    nsRefPtr<KeyAlgorithm> publicAlgorithm = publicKey->Algorithm();
-
-    // Given public key must be an ECDH key.
-    nsString algName;
-    publicAlgorithm->GetName(algName);
-    if (!algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
-      mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
-      return;
-    }
-
-    // Both keys must use the same named curve.
-    nsString curve1, curve2;
-    static_cast<EcKeyAlgorithm*>(aKey.Algorithm())->GetNamedCurve(curve1);
-    static_cast<EcKeyAlgorithm*>(publicAlgorithm.get())->GetNamedCurve(curve2);
-
-    if (!curve1.Equals(curve2)) {
-      mEarlyRv = NS_ERROR_DOM_DATA_ERR;
-      return;
-    }
-  }
-
-private:
-  size_t mLength;
-  ScopedSECKEYPrivateKey mPrivKey;
-  ScopedSECKEYPublicKey mPubKey;
-
-  virtual nsresult DoCrypto() MOZ_OVERRIDE
-  {
-    ScopedPK11SymKey symKey(PK11_PubDeriveWithKDF(
-      mPrivKey, mPubKey, PR_FALSE, nullptr, nullptr, CKM_ECDH1_DERIVE,
-      CKM_CONCATENATE_DATA_AND_BASE, CKA_DERIVE, 0, CKD_NULL, nullptr, nullptr));
-
-    if (!symKey.get()) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
-
-    nsresult rv = MapSECStatus(PK11_ExtractKeyValue(symKey));
-    if (NS_FAILED(rv)) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
-
-    // This doesn't leak, because the SECItem* returned by PK11_GetKeyData
-    // just refers to a buffer managed by symKey. The assignment copies the
-    // data, so mResult manages one copy, while symKey manages another.
-    ATTEMPT_BUFFER_ASSIGN(mResult, PK11_GetKeyData(symKey));
-
-    if (mLength > mResult.Length()) {
-      return NS_ERROR_DOM_DATA_ERR;
-    }
-
-    if (!mResult.SetLength(mLength)) {
-      return NS_ERROR_DOM_UNKNOWN_ERR;
-    }
-
-    return NS_OK;
-  }
-};
-
 template<class KeyEncryptTask>
 class WrapKeyTask : public ExportKeyTask
 {
 public:
   WrapKeyTask(JSContext* aCx,
               const nsAString& aFormat,
               CryptoKey& aKey,
               CryptoKey& aWrappingKey,
@@ -2712,19 +2432,16 @@ WebCryptoTask::CreateImportKeyTask(JSCon
       algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
     return new ImportSymmetricKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
                                       aExtractable, aKeyUsages);
   } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
              algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
              algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
     return new ImportRsaKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
                                 aExtractable, aKeyUsages);
-  } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
-    return new ImportEcKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
-                               aExtractable, aKeyUsages);
   } else {
     return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   }
 }
 
 WebCryptoTask*
 WebCryptoTask::CreateExportKeyTask(const nsAString& aFormat,
                              CryptoKey& aKey)
@@ -2752,18 +2469,17 @@ WebCryptoTask::CreateGenerateKeyTask(JSC
   if (algName.EqualsASCII(WEBCRYPTO_ALG_AES_CBC) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_AES_CTR) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_AES_GCM) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_AES_KW) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) {
     return new GenerateSymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
   } else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSAES_PKCS1) ||
              algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
-             algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
-             algName.EqualsASCII(WEBCRYPTO_ALG_ECDH)) {
+             algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP)) {
     return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
   } else {
     return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   }
 }
 
 WebCryptoTask*
 WebCryptoTask::CreateDeriveKeyTask(JSContext* aCx,
@@ -2777,25 +2493,18 @@ WebCryptoTask::CreateDeriveKeyTask(JSCon
 
   nsString algName;
   nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
   if (NS_FAILED(rv)) {
     return new FailureTask(rv);
   }
 
   if (algName.EqualsASCII(WEBCRYPTO_ALG_PBKDF2)) {
-    return new DeriveKeyTask<DerivePbkdfBitsTask>(aCx, aAlgorithm, aBaseKey,
-                                                  aDerivedKeyType, aExtractable,
-                                                  aKeyUsages);
-  }
-
-  if (algName.EqualsASCII(WEBCRYPTO_ALG_ECDH)) {
-    return new DeriveKeyTask<DeriveEcdhBitsTask>(aCx, aAlgorithm, aBaseKey,
-                                                 aDerivedKeyType, aExtractable,
-                                                 aKeyUsages);
+    return new DerivePbkdfKeyTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType,
+                                  aExtractable, aKeyUsages);
   }
 
   return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 }
 
 WebCryptoTask*
 WebCryptoTask::CreateDeriveBitsTask(JSContext* aCx,
                               const ObjectOrString& aAlgorithm,
@@ -2809,20 +2518,16 @@ WebCryptoTask::CreateDeriveBitsTask(JSCo
   if (NS_FAILED(rv)) {
     return new FailureTask(rv);
   }
 
   if (algName.EqualsASCII(WEBCRYPTO_ALG_PBKDF2)) {
     return new DerivePbkdfBitsTask(aCx, aAlgorithm, aKey, aLength);
   }
 
-  if (algName.EqualsASCII(WEBCRYPTO_ALG_ECDH)) {
-    return new DeriveEcdhBitsTask(aCx, aAlgorithm, aKey, aLength);
-  }
-
   return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 }
 
 WebCryptoTask*
 WebCryptoTask::CreateWrapKeyTask(JSContext* aCx,
                              const nsAString& aFormat,
                            CryptoKey& aKey,
                            CryptoKey& aWrappingKey,
--- a/dom/crypto/moz.build
+++ b/dom/crypto/moz.build
@@ -5,31 +5,29 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS.mozilla.dom += [
     'AesKeyAlgorithm.h',
     'BasicSymmetricKeyAlgorithm.h',
     'CryptoBuffer.h',
     'CryptoKey.h',
     'CryptoKeyPair.h',
-    'EcKeyAlgorithm.h',
     'HmacKeyAlgorithm.h',
     'KeyAlgorithm.h',
     'RsaHashedKeyAlgorithm.h',
     'RsaKeyAlgorithm.h',
     'WebCryptoCommon.h',
     'WebCryptoTask.h',
 ]
 
 UNIFIED_SOURCES += [
     'AesKeyAlgorithm.cpp',
     'CryptoBuffer.cpp',
     'CryptoKey.cpp',
     'CryptoKeyPair.cpp',
-    'EcKeyAlgorithm.cpp',
     'HmacKeyAlgorithm.cpp',
     'KeyAlgorithm.cpp',
     'RsaHashedKeyAlgorithm.cpp',
     'RsaKeyAlgorithm.cpp',
     'WebCryptoTask.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
--- a/dom/crypto/test/test-vectors.js
+++ b/dom/crypto/test/test-vectors.js
@@ -447,133 +447,10 @@ tv = {
       "41fc6064b147071a4c30426d82fc90d888f94990267c64beef8c304a4b2b26fb" +
       "93724d6a9472fa16bc50c5b9b8b59afb62cfe9ea3ba042c73a6ade3502818100" +
       "a51883e9ac0539859df3d25c716437008bb4bd8ec4786eb4bc643299daef5e3e" +
       "5af5863a6ac40a597b83a27583f6a658d408825105b16d31b6ed088fc623f648" +
       "fd6d95e9cefcb0745763cddf564c87bcf4ba7928e74fd6a3080481f588d535e4" +
       "c026b58a21e1e5ec412ff241b436043e29173f1dc6cb943c09742de989547288" +
       "0416021442c6ee70beb7465928a1efe692d2281b8f7b53d6"
     )
-  },
-
-  // KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.fax [EC]
-  // <http://csrc.nist.gov/groups/STM/cavp/documents/keymgmt/kastestvectors.zip>
-  ecdh_p256: {
-    jwk_pub: {
-      kty: "EC",
-      crv: "P-256",
-      x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
-      y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8"
-    },
-
-    jwk_priv: {
-      kty: "EC",
-      crv: "P-256",
-      d: "qq_LEzeJpR00KM5DQvL2MNtJcbi0KcGVcoPIHNnwm2A",
-      x: "FNwJHA-FwnSx5tKXFV_iLN408gbKUHRV06WnQlzTdN4",
-      y: "is9pWAaneK4RdxmdLfsq5IwizDmUS2w8OGS99sKm3ek"
-    },
-
-    // vector with algorithm = id-ecDH
-    spki: util.hex2abv(
-      "3056301006042b81047006082a8648ce3d030107034200045ce7b86e3b326604" +
-      "03e63712ef0998deae1027faec3c1be9f76f934dfeb58e98f4cf075b39405dd1" +
-      "f1adeb090107edcfb2b4963739d87679e3056cb0557d0adf"
-    ),
-
-    // vector with algorithm = id-ecPublicKey
-    spki_id_ecpk: util.hex2abv(
-      "3059301306072a8648ce3d020106082a8648ce3d030107034200045ce7b86e3b" +
-      "32660403e63712ef0998deae1027faec3c1be9f76f934dfeb58e98f4cf075b39" +
-      "405dd1f1adeb090107edcfb2b4963739d87679e3056cb0557d0adf"
-    ),
-
-    secret: util.hex2abv(
-      "35669cd5c244ba6c1ea89b8802c3d1db815cd769979072e6556eb98548c65f7d"
-    )
-  },
-
-  // KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.fax [ED]
-  // <http://csrc.nist.gov/groups/STM/cavp/documents/keymgmt/kastestvectors.zip>
-  ecdh_p384: {
-    jwk_pub: {
-      kty: "EC",
-      crv: "P-384",
-      x: "YoV6fhCph4kyt7sUkqiZOtbRs0rF6etPqlnrn1nzSB95NElaw4uTK7Pn2nlFFqqH",
-      y: "bf3tRz6icq3-W6hhmoqDTBKjdOQUJ5xHr5kX4X-h5MZk_P_nCrG3IUVl1SAbhWDw"
-    },
-
-    jwk_priv: {
-      kty: "EC",
-      crv: "P-384",
-      d: "RT8f0pRw4CL1Tgk4rwuNnNbFoQBNTTBkr7WVLLm4fDA3boYZpNB_t-rbMVLx0CRp",
-      x: "_XwhXRnOzEfCsWIRCz3QLClaDkigQFvXmqYNdh/7vJdADykPbfGi1VgAu3XJdXoD",
-      y: "S1P_FBCXYGE-5VPvTCRnFT7bPIPmUPV9qKTM24TQFYEUgIDfzCLsyGCWK-rhP6jU"
-    },
-
-    secret: util.hex2abv(
-      "a3d28aa18f905a48a5f166b4ddbf5f6b499e43858ccdd80b869946aba2c5d461" +
-      "db6a1e5b1137687801878ff0f8d9a7b3"
-    )
-  },
-
-  // KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.fax [EE]
-  // <http://csrc.nist.gov/groups/STM/cavp/documents/keymgmt/kastestvectors.zip>
-  ecdh_p521: {
-    jwk_pub: {
-      kty: "EC",
-      crv: "P-521",
-      x: "AeCLgRZ-BPqfhq4jt409-E26VHW5l29q74cHbIbQiS_-Gcqdo-087jHdPXUksGpr" +
-         "Nyp_RcTZd94t3peXzQziQIqo",
-      y: "AZIAp8QVnU9hBOkLScv0dy540uGtBWHkWj4DGh-Exh4iWZ0E-YBS8-HVx2eB-nfG" +
-         "AGEy4-BzfpFFlfidOS1Tg77J"
-    },
-
-    jwk_priv: {
-      kty: "EC",
-      crv: "P-521",
-      d: "ABtsfkDGFarQU4kb7e2gPszGCTT8GLDaaJbFQenFZce3qp_dh0qZarXHKBZ-BVic" +
-         "NeIW5Sk661UoNfwykSvmh77S",
-      x: "AcD_6Eb4A-8QdUM70c6F0WthN1kvV4fohS8QHbod6B4y1ZDU54mQuCR-3IBjcV1c" +
-         "oh18uxbyUn5szMuCgjZUiD0y",
-      y: "AU3WKJffztkhAQetBXaLvUSIHa87HMn8vZFB04lWipH-SrsrAu_4N-6iam0OD4EJ" +
-         "0kOMH8iEh7yuivaKsFRzm2-m"
-    },
-
-    secret: util.hex2abv(
-      "00561eb17d856552c21b8cbe7d3d60d1ea0db738b77d4050fa2dbd0773edc395" +
-      "09854d9e30e843964ed3fd303339e338f31289120a38f94e9dc9ff7d4b3ea8f2" +
-      "5e01"
-    )
-  },
-
-  // Some test vectors that we should fail to import.
-  ecdh_p256_negative: {
-    // The given curve doesn't exist / isn't supported.
-    jwk_bad_crv: {
-      kty: "EC",
-      crv: "P-123",
-      x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
-      y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8"
-    },
-
-    // The crv parameter is missing.
-    jwk_missing_crv: {
-      kty: "EC",
-      x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
-      y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8"
-    },
-
-    // The X coordinate is missing.
-    jwk_missing_x: {
-      kty: "EC",
-      crv: "P-256",
-      y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8"
-    },
-
-    // The Y coordinate is missing.
-    jwk_missing_y: {
-      kty: "EC",
-      crv: "P-256",
-      x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
-    }
-  },
+  }
 }
--- a/dom/crypto/test/tests.js
+++ b/dom/crypto/test/tests.js
@@ -1862,394 +1862,8 @@ TestArray.addTest(
 
     crypto.subtle.generateKey(alg, false, ["sign"])
       .then(doGenerateAesKey)
       .then(doGenerateRsaOaepKey)
       .then(doGenerateRsaSsaPkcs1Key)
       .then(complete(that), error(that));
   }
 );
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Generate an ECDH key for named curve P-256",
-  function() {
-    var that = this;
-    var alg = { name: "ECDH", namedCurve: "P-256" };
-    crypto.subtle.generateKey(alg, false, ["deriveKey", "deriveBits"]).then(
-      complete(that, function(x) {
-        return exists(x.publicKey) &&
-               (x.publicKey.algorithm.name == alg.name) &&
-               (x.publicKey.algorithm.namedCurve == alg.namedCurve) &&
-               (x.publicKey.type == "public") &&
-               x.publicKey.extractable &&
-               (x.publicKey.usages.length == 0) &&
-               exists(x.privateKey) &&
-               (x.privateKey.algorithm.name == alg.name) &&
-               (x.privateKey.algorithm.namedCurve == alg.namedCurve) &&
-               (x.privateKey.type == "private") &&
-               !x.privateKey.extractable &&
-               (x.privateKey.usages.length == 2) &&
-               (x.privateKey.usages[0] == "deriveKey") &&
-               (x.privateKey.usages[1] == "deriveBits");
-      }),
-      error(that)
-    );
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Generate an ECDH key and derive some bits",
-  function() {
-    var that = this;
-    var alg = { name: "ECDH", namedCurve: "P-256" };
-
-    var pair;
-    function setKeyPair(x) { pair = x; }
-
-    function doDerive(n) {
-      return function (x) {
-        var alg = { name: "ECDH", public: pair.publicKey };
-        return crypto.subtle.deriveBits(alg, pair.privateKey, n * 8);
-      }
-    }
-
-    crypto.subtle.generateKey(alg, false, ["deriveBits"])
-      .then(setKeyPair, error(that))
-      .then(doDerive(2), error(that))
-      .then(function (x) {
-        // Deriving less bytes works.
-        if (x.byteLength != 2) {
-          throw "should have derived two bytes";
-        }
-      })
-      // Deriving more than the curve yields doesn't.
-      .then(doDerive(33), error(that))
-      .then(error(that), complete(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Test that ECDH deriveBits() fails when the public key is not an ECDH key",
-  function() {
-    var that = this;
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x.publicKey; }
-    function setPriv(x) { privKey = x.privateKey; }
-
-    function doGenerateP256() {
-      var alg = { name: "ECDH", namedCurve: "P-256" };
-      return crypto.subtle.generateKey(alg, false, ["deriveBits"]);
-    }
-
-    function doGenerateRSA() {
-      var alg = {
-        name: "RSA-OAEP",
-        hash: "SHA-256",
-        modulusLength: 2048,
-        publicExponent: new Uint8Array([0x01, 0x00, 0x01])
-      };
-      return crypto.subtle.generateKey(alg, false, ["encrypt"])
-    }
-
-    function doDerive() {
-      var alg = { name: "ECDH", public: pubKey };
-      return crypto.subtle.deriveBits(alg, privKey, 16);
-    }
-
-    doGenerateP256()
-      .then(setPriv, error(that))
-      .then(doGenerateRSA, error(that))
-      .then(setPub, error(that))
-      .then(doDerive, error(that))
-      .then(error(that), complete(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Test that ECDH deriveBits() fails when the given keys' curves don't match",
-  function() {
-    var that = this;
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x.publicKey; }
-    function setPriv(x) { privKey = x.privateKey; }
-
-    function doGenerateP256() {
-      var alg = { name: "ECDH", namedCurve: "P-256" };
-      return crypto.subtle.generateKey(alg, false, ["deriveBits"]);
-    }
-
-    function doGenerateP384() {
-      var alg = { name: "ECDH", namedCurve: "P-384" };
-      return crypto.subtle.generateKey(alg, false, ["deriveBits"]);
-    }
-
-    function doDerive() {
-      var alg = { name: "ECDH", public: pubKey };
-      return crypto.subtle.deriveBits(alg, privKey, 16);
-    }
-
-    doGenerateP256()
-      .then(setPriv, error(that))
-      .then(doGenerateP384, error(that))
-      .then(setPub, error(that))
-      .then(doDerive, error(that))
-      .then(error(that), complete(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "JWK import an ECDH public and private key and derive bits (P-256)",
-  function () {
-    var that = this;
-    var alg = { name: "ECDH" };
-
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x; }
-    function setPriv(x) { privKey = x; }
-
-    function doDerive() {
-      var alg = { name: "ECDH", public: pubKey };
-      return crypto.subtle.deriveBits(alg, privKey, tv.ecdh_p256.secret.byteLength * 8);
-    }
-
-    Promise.all([
-      crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_priv, alg, false, ["deriveBits"])
-        .then(setPriv, error(that)),
-      crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_pub, alg, false, ["deriveBits"])
-        .then(setPub, error(that))
-    ]).then(doDerive, error(that))
-      .then(memcmp_complete(that, tv.ecdh_p256.secret), error(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "JWK import an ECDH public and private key and derive bits (P-384)",
-  function () {
-    var that = this;
-    var alg = { name: "ECDH" };
-
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x; }
-    function setPriv(x) { privKey = x; }
-
-    function doDerive() {
-      var alg = { name: "ECDH", public: pubKey };
-      return crypto.subtle.deriveBits(alg, privKey, tv.ecdh_p384.secret.byteLength * 8);
-    }
-
-    Promise.all([
-      crypto.subtle.importKey("jwk", tv.ecdh_p384.jwk_priv, alg, false, ["deriveBits"])
-        .then(setPriv, error(that)),
-      crypto.subtle.importKey("jwk", tv.ecdh_p384.jwk_pub, alg, false, ["deriveBits"])
-        .then(setPub, error(that))
-    ]).then(doDerive, error(that))
-      .then(memcmp_complete(that, tv.ecdh_p384.secret), error(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "JWK import an ECDH public and private key and derive bits (P-521)",
-  function () {
-    var that = this;
-    var alg = { name: "ECDH" };
-
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x; }
-    function setPriv(x) { privKey = x; }
-
-    function doDerive() {
-      var alg = { name: "ECDH", public: pubKey };
-      return crypto.subtle.deriveBits(alg, privKey, tv.ecdh_p521.secret.byteLength * 8);
-    }
-
-    Promise.all([
-      crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_priv, alg, false, ["deriveBits"])
-        .then(setPriv, error(that)),
-      crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_pub, alg, false, ["deriveBits"])
-        .then(setPub, error(that))
-    ]).then(doDerive, error(that))
-      .then(memcmp_complete(that, tv.ecdh_p521.secret), error(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "JWK import/export roundtrip with ECDH (P-256)",
-  function () {
-    var that = this;
-    var alg = { name: "ECDH" };
-
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x; }
-    function setPriv(x) { privKey = x; }
-
-    function doExportPub() {
-      return crypto.subtle.exportKey("jwk", pubKey);
-    }
-    function doExportPriv() {
-      return crypto.subtle.exportKey("jwk", privKey);
-    }
-
-    Promise.all([
-      crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_priv, alg, true, ["deriveBits"])
-        .then(setPriv, error(that)),
-      crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_pub, alg, true, ["deriveBits"])
-        .then(setPub, error(that))
-    ]).then(doExportPub, error(that))
-      .then(function (x) {
-        var tp = tv.ecdh_p256.jwk_pub;
-        if ((tp.kty != x.kty) &&
-            (tp.crv != x.crv) &&
-            (tp.x != x.x) &&
-            (tp.y != x.y)) {
-          throw "exported public key doesn't match";
-        }
-      }, error(that))
-      .then(doExportPriv, error(that))
-      .then(complete(that, function (x) {
-        var tp = tv.ecdh_p256.jwk_priv;
-        return (tp.kty == x.kty) &&
-               (tp.crv == x.crv) &&
-               (tp.d == x.d) &&
-               (tp.x == x.x) &&
-               (tp.y == x.y);
-      }), error(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Test that importing bad JWKs fails",
-  function () {
-    var that = this;
-    var alg = { name: "ECDH" };
-    var tvs = tv.ecdh_p256_negative;
-
-    function doTryImport(jwk) {
-      return function () {
-        return crypto.subtle.importKey("jwk", jwk, alg, false, ["deriveBits"]);
-      }
-    }
-
-    doTryImport(tvs.jwk_bad_crv)()
-      .then(error(that), doTryImport(tvs.jwk_missing_crv))
-      .then(error(that), doTryImport(tvs.jwk_missing_x))
-      .then(error(that), doTryImport(tvs.jwk_missing_y))
-      .then(error(that), complete(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Derive an HMAC key from two ECDH keys and test sign/verify",
-  function() {
-    var that = this;
-    var alg = { name: "ECDH" };
-    var algDerived = { name: "HMAC", hash: {name: "SHA-1"} };
-
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x; }
-    function setPriv(x) { privKey = x; }
-
-    function doDerive() {
-      var alg = { name: "ECDH", public: pubKey };
-      return crypto.subtle.deriveKey(alg, privKey, algDerived, false, ["sign", "verify"])
-        .then(function (x) {
-          if (!hasKeyFields(x)) {
-            throw "Invalid key; missing field(s)";
-          }
-
-          // 512 bit is the default for HMAC-SHA1.
-          if (x.algorithm.length != 512) {
-            throw "Invalid key; incorrect length";
-          }
-
-          return x;
-        });
-    }
-
-    function doSignAndVerify(x) {
-      var data = crypto.getRandomValues(new Uint8Array(1024));
-      return crypto.subtle.sign("HMAC", x, data)
-        .then(function (sig) {
-          return crypto.subtle.verify("HMAC", x, sig, data);
-        });
-    }
-
-    Promise.all([
-      crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_priv, alg, false, ["deriveBits"])
-        .then(setPriv, error(that)),
-      crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_pub, alg, false, ["deriveBits"])
-        .then(setPub, error(that))
-    ]).then(doDerive, error(that))
-      .then(doSignAndVerify, error(that))
-      .then(complete(that), error(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "SPKI import/export of public ECDH keys (P-256)",
-  function () {
-    var that = this;
-    var alg = { name: "ECDH" };
-    var keys = ["spki", "spki_id_ecpk"];
-
-    function doImport(key) {
-      return crypto.subtle.importKey("spki", tv.ecdh_p256[key], alg, true, ["deriveBits"]);
-    }
-
-    function doExport(x) {
-      return crypto.subtle.exportKey("spki", x);
-    }
-
-    function nextKey() {
-      var key = keys.shift();
-      var imported = doImport(key);
-      var derived = imported.then(doExport);
-
-      return derived.then(function (x) {
-        if (!util.memcmp(x, tv.ecdh_p256.spki)) {
-          throw "exported key is invalid";
-        }
-
-        if (keys.length) {
-          return nextKey();
-        }
-      });
-    }
-
-    nextKey().then(complete(that), error(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "SPKI/JWK import ECDH keys (P-256) and derive a known secret",
-  function () {
-    var that = this;
-    var alg = { name: "ECDH" };
-
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x; }
-    function setPriv(x) { privKey = x; }
-
-    function doDerive() {
-      var alg = { name: "ECDH", public: pubKey };
-      return crypto.subtle.deriveBits(alg, privKey, tv.ecdh_p256.secret.byteLength * 8);
-    }
-
-    Promise.all([
-      crypto.subtle.importKey("spki", tv.ecdh_p256.spki, alg, false, ["deriveBits"])
-        .then(setPub),
-      crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_priv, alg, false, ["deriveBits"])
-        .then(setPriv)
-    ]).then(doDerive)
-      .then(memcmp_complete(that, tv.ecdh_p256.secret), error(that));
-  }
-);
--- a/dom/webidl/SubtleCrypto.webidl
+++ b/dom/webidl/SubtleCrypto.webidl
@@ -36,21 +36,16 @@ interface RsaKeyAlgorithm : KeyAlgorithm
   readonly attribute BigInteger publicExponent;
 };
 
 [NoInterfaceObject]
 interface RsaHashedKeyAlgorithm : RsaKeyAlgorithm {
   readonly attribute KeyAlgorithm hash;
 };
 
-[NoInterfaceObject]
-interface EcKeyAlgorithm : KeyAlgorithm {
-  readonly attribute NamedCurve namedCurve;
-};
-
 
 /***** Algorithm dictionaries *****/
 
 dictionary Algorithm {
   DOMString name;
 };
 
 dictionary AesCbcParams : Algorithm {
@@ -109,20 +104,16 @@ dictionary DhKeyGenParams : Algorithm {
   BigInteger generator;
 };
 
 typedef DOMString NamedCurve;
 dictionary EcKeyGenParams : Algorithm {
   NamedCurve namedCurve;
 };
 
-dictionary EcdhKeyDeriveParams : Algorithm {
-  CryptoKey public;
-};
-
 
 /***** JWK *****/
 
 dictionary RsaOtherPrimesInfo {
   // The following fields are defined in Section 6.3.2.7 of JSON Web Algorithms
   DOMString r;
   DOMString d;
   DOMString t;