Backed out 7 changesets (bug 1034856) for WebCrypto test failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 29 Oct 2014 20:52:31 -0400
changeset 234865 86f3ce4cf56a676edfb6a15ee4d16559549d1ef5
parent 234864 6675f988b6c56879fda0113eef9135693d76db28
child 234866 9b7a09c5d8bce18cd01772ef1ff4f7bcb65b1a1d
push id611
push userraliiev@mozilla.com
push dateMon, 05 Jan 2015 23:23:16 +0000
treeherdermozilla-release@345cd3b9c445 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1034856
milestone35.0a2
backs out2cfa6e659ae62535c0676df74ce3ed833466b7ae
29cf6a01532fdac997990b0e3cc9abd994b19f34
f6adbda3e224a2bc1c7a4c448bc307ea99483d35
7c17b33485f0fb826963206ff78ea4081d9c95ed
0112f05475130bb4ac736cecb0313d5d228e3ee9
ce89df7057f06e34d847de8f307eb91668de5857
526f7c0682e16ab194a16ef61f969ce5abf8ac92
Backed out 7 changesets (bug 1034856) for WebCrypto test failures. Backed out changeset 2cfa6e659ae6 (bug 1034856) Backed out changeset 29cf6a01532f (bug 1034856) Backed out changeset f6adbda3e224 (bug 1034856) Backed out changeset 7c17b33485f0 (bug 1034856) Backed out changeset 0112f0547513 (bug 1034856) Backed out changeset ce89df7057f0 (bug 1034856) Backed out changeset 526f7c0682e1 (bug 1034856)
dom/crypto/CryptoBuffer.cpp
dom/crypto/CryptoBuffer.h
dom/crypto/CryptoKey.cpp
dom/crypto/CryptoKey.h
dom/crypto/KeyAlgorithmProxy.cpp
dom/crypto/KeyAlgorithmProxy.h
dom/crypto/WebCryptoCommon.h
dom/crypto/WebCryptoTask.cpp
dom/crypto/test/mochitest.ini
dom/crypto/test/test-vectors.js
dom/crypto/test/test_WebCrypto_DH.html
dom/webidl/KeyAlgorithm.webidl
dom/webidl/SubtleCrypto.webidl
--- a/dom/crypto/CryptoBuffer.cpp
+++ b/dom/crypto/CryptoBuffer.cpp
@@ -138,28 +138,32 @@ CryptoBuffer::ToJwkBase64(nsString& aBas
   if (base64.FindCharInSet("+/", 0) != kNotFound) {
     return NS_ERROR_FAILURE;
   }
 
   CopyASCIItoUTF16(base64, aBase64);
   return NS_OK;
 }
 
-bool
-CryptoBuffer::ToSECItem(PLArenaPool *aArena, SECItem* aItem) const
+SECItem*
+CryptoBuffer::ToSECItem() const
 {
-  aItem->type = siBuffer;
-  aItem->data = nullptr;
-
-  if (!::SECITEM_AllocItem(aArena, aItem, Length())) {
-    return false;
+  uint8_t* data = (uint8_t*) moz_malloc(Length());
+  if (!data) {
+    return nullptr;
   }
 
-  memcpy(aItem->data, Elements(), Length());
-  return true;
+  SECItem* item = ::SECITEM_AllocItem(nullptr, nullptr, 0);
+  item->type = siBuffer;
+  item->data = data;
+  item->len = Length();
+
+  memcpy(item->data, Elements(), Length());
+
+  return item;
 }
 
 JSObject*
 CryptoBuffer::ToUint8Array(JSContext* aCx) const
 {
   return Uint8Array::Create(aCx, Length(), Elements());
 }
 
--- a/dom/crypto/CryptoBuffer.h
+++ b/dom/crypto/CryptoBuffer.h
@@ -34,17 +34,17 @@ public:
   uint8_t* Assign(const TypedArray_base<T, UnwrapArray, GetLengthAndData>& aArray)
   {
     aArray.ComputeLengthAndData();
     return Assign(aArray.Data(), aArray.Length());
   }
 
   nsresult FromJwkBase64(const nsString& aBase64);
   nsresult ToJwkBase64(nsString& aBase64);
-  bool ToSECItem(PLArenaPool* aArena, SECItem* aItem) const;
+  SECItem* ToSECItem() const;
   JSObject* ToUint8Array(JSContext* aCx) const;
 
   bool GetBigIntValue(unsigned long& aRetVal);
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/crypto/CryptoKey.cpp
+++ b/dom/crypto/CryptoKey.cpp
@@ -7,31 +7,16 @@
 #include "pk11pub.h"
 #include "cryptohi.h"
 #include "ScopedNSSTypes.h"
 #include "mozilla/dom/CryptoKey.h"
 #include "mozilla/dom/WebCryptoCommon.h"
 #include "mozilla/dom/SubtleCryptoBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 
-// Templates taken from security/nss/lib/cryptohi/seckey.c
-// These would ideally be exported by NSS and until that
-// happens we have to keep our own copies.
-const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
-    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), },
-    { 0, }
-};
-const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
-    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
-    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), },
-    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), },
-    { SEC_ASN1_SKIP_REST },
-    { 0, }
-};
-
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CryptoKey, mGlobal)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(CryptoKey)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(CryptoKey)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CryptoKey)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@@ -122,22 +107,16 @@ CryptoKey::GetAlgorithm(JSContext* cx, J
       RootedDictionary<RsaHashedKeyAlgorithm> rsa(cx);
       mAlgorithm.mRsa.ToKeyAlgorithm(cx, rsa);
       converted = ToJSValue(cx, rsa, &val);
       break;
     }
     case KeyAlgorithmProxy::EC:
       converted = ToJSValue(cx, mAlgorithm.mEc, &val);
       break;
-    case KeyAlgorithmProxy::DH: {
-      RootedDictionary<DhKeyAlgorithm> dh(cx);
-      mAlgorithm.mDh.ToKeyAlgorithm(cx, dh);
-      converted = ToJSValue(cx, dh, &val);
-      break;
-    }
   }
   if (!converted) {
     aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
     return;
   }
 
   aRetVal.set(&val.toObject());
 }
@@ -362,78 +341,54 @@ void CryptoKey::destructorSafeDestroyNSS
 // Serialization and deserialization convenience methods
 
 SECKEYPrivateKey*
 CryptoKey::PrivateKeyFromPkcs8(CryptoBuffer& aKeyData,
                          const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
   SECKEYPrivateKey* privKey;
   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
-
-  ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  if (!arena) {
-    return nullptr;
-  }
-
-  SECItem pkcs8Item = { siBuffer, nullptr, 0 };
-  if (!aKeyData.ToSECItem(arena, &pkcs8Item)) {
+  ScopedSECItem pkcs8Item(aKeyData.ToSECItem());
+  if (!pkcs8Item) {
     return nullptr;
   }
 
   // Allow everything, we enforce usage ourselves
   unsigned int usage = KU_ALL;
 
   SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
-                 slot.get(), &pkcs8Item, nullptr, nullptr, false, false,
+                 slot.get(), pkcs8Item.get(), nullptr, nullptr, false, false,
                  usage, &privKey, nullptr);
 
   if (rv == SECFailure) {
     return nullptr;
   }
   return privKey;
 }
 
 SECKEYPublicKey*
 CryptoKey::PublicKeyFromSpki(CryptoBuffer& aKeyData,
                        const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
-  ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  if (!arena) {
+  ScopedSECItem spkiItem(aKeyData.ToSECItem());
+  if (!spkiItem) {
     return nullptr;
   }
 
-  SECItem spkiItem = { siBuffer, nullptr, 0 };
-  if (!aKeyData.ToSECItem(arena, &spkiItem)) {
-    return nullptr;
-  }
-
-  ScopedCERTSubjectPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem));
+  ScopedCERTSubjectPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(spkiItem.get()));
   if (!spki) {
     return nullptr;
   }
 
-  bool isECDHAlgorithm = SECITEM_ItemsAreEqual(&SEC_OID_DATA_EC_DH,
-                                               &spki->algorithm.algorithm);
-  bool isDHAlgorithm = SECITEM_ItemsAreEqual(&SEC_OID_DATA_DH_KEY_AGREEMENT,
-                                             &spki->algorithm.algorithm);
-
-  // Check for |id-ecDH| and |dhKeyAgreement|. Per the WebCrypto spec we must
-  // support these OIDs but NSS does unfortunately not know about them. Let's
-  // change the algorithm to |id-ecPublicKey| or |dhPublicKey| to make NSS happy.
-  if (isECDHAlgorithm || isDHAlgorithm) {
-    SECOidTag oid = SEC_OID_UNKNOWN;
-    if (isECDHAlgorithm) {
-      oid = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
-    } else if (isDHAlgorithm) {
-      oid = SEC_OID_X942_DIFFIE_HELMAN_KEY;
-    } else {
-      MOZ_ASSERT(false);
-    }
-
-    SECOidData* oidData = SECOID_FindOIDByTag(oid);
+  // 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;
@@ -457,100 +412,31 @@ CryptoKey::PrivateKeyToPkcs8(SECKEYPriva
   if (!pkcs8Item.get()) {
     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   }
   aRetVal.Assign(pkcs8Item.get());
   return NS_OK;
 }
 
 nsresult
-PublicDhKeyToSpki(SECKEYPublicKey* aPubKey,
-                  CERTSubjectPublicKeyInfo* aSpki)
+CryptoKey::PublicKeyToSpki(SECKEYPublicKey* aPubKey,
+                     CryptoBuffer& aRetVal,
+                     const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
-  SECItem* params = ::SECITEM_AllocItem(aSpki->arena, nullptr, 0);
-  if (!params) {
-    return NS_ERROR_DOM_OPERATION_ERR;
-  }
-
-  SECItem* rvItem = SEC_ASN1EncodeItem(aSpki->arena, params, aPubKey,
-                                       SECKEY_DHParamKeyTemplate);
-  if (!rvItem) {
-    return NS_ERROR_DOM_OPERATION_ERR;
-  }
-
-  SECStatus rv = SECOID_SetAlgorithmID(aSpki->arena, &aSpki->algorithm,
-                                       SEC_OID_X942_DIFFIE_HELMAN_KEY, params);
-  if (rv != SECSuccess) {
-    return NS_ERROR_DOM_OPERATION_ERR;
-  }
-
-  rvItem = SEC_ASN1EncodeItem(aSpki->arena, &aSpki->subjectPublicKey, aPubKey,
-                              SECKEY_DHPublicKeyTemplate);
-  if (!rvItem) {
+  ScopedCERTSubjectPublicKeyInfo spki(SECKEY_CreateSubjectPublicKeyInfo(aPubKey));
+  if (!spki) {
     return NS_ERROR_DOM_OPERATION_ERR;
   }
 
-  // The public value is a BIT_STRING encoded as an INTEGER. After encoding
-  // an INT we need to adjust the length to reflect the number of bits.
-  aSpki->subjectPublicKey.len <<= 3;
-
-  return NS_OK;
-}
-
-nsresult
-CryptoKey::PublicKeyToSpki(SECKEYPublicKey* aPubKey,
-                           CryptoBuffer& aRetVal,
-                           const nsNSSShutDownPreventionLock& /*proofOfLock*/)
-{
-  ScopedCERTSubjectPublicKeyInfo spki;
-
-  // NSS doesn't support exporting DH public keys.
-  if (aPubKey->keyType == dhKey) {
-    // Mimic the behavior of SECKEY_CreateSubjectPublicKeyInfo() and create
-    // a new arena for the SPKI object.
-    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-    if (!arena) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
-
-    spki = PORT_ArenaZNew(arena, CERTSubjectPublicKeyInfo);
-    if (!spki) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
-
-    // Assign |arena| to |spki| and null the variable afterwards so that the
-    // arena created above that holds the SPKI object is free'd when |spki|
-    // goes out of scope, not when |arena| does.
-    spki->arena = arena.forget();
-
-    nsresult rv = PublicDhKeyToSpki(aPubKey, spki);
-    NS_ENSURE_SUCCESS(rv, rv);
-  } else {
-    spki = SECKEY_CreateSubjectPublicKeyInfo(aPubKey);
-    if (!spki) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
-  }
-
   // Per WebCrypto spec we must export ECDH SPKIs with the algorithm OID
-  // id-ecDH (1.3.132.112) and DH SPKIs with OID dhKeyAgreement
-  // (1.2.840.113549.1.3.1). NSS doesn't know about these OIDs and there is
+  // 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 || aPubKey->keyType == dhKey) {
-    const SECItem* oidData = nullptr;
-    if (aPubKey->keyType == ecKey) {
-      oidData = &SEC_OID_DATA_EC_DH;
-    } else if (aPubKey->keyType == dhKey) {
-      oidData = &SEC_OID_DATA_DH_KEY_AGREEMENT;
-    } else {
-      MOZ_ASSERT(false);
-    }
-
+  if (aPubKey->keyType == ecKey) {
     SECStatus rv = SECITEM_CopyItem(spki->arena, &spki->algorithm.algorithm,
-                                    oidData);
+                                    &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));
 
@@ -684,29 +570,24 @@ CryptoKey::PrivateKeyFromJwk(const JsonW
         !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;
     }
 
-    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-    if (!arena) {
+    // 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;
     }
 
-    // Compute the ID for this key
-    // This is generated with a SHA-1 hash, so unlikely to collide
-    SECItem nItem = { siBuffer, nullptr, 0 };
-    if (!n.ToSECItem(arena, &nItem)) {
-      return nullptr;
-    }
-
-    ScopedSECItem objID(PK11_MakeIDFromPubKey(&nItem));
+    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) },
@@ -1004,59 +885,16 @@ CryptoKey::PublicKeyToJwk(SECKEYPublicKe
         return NS_ERROR_DOM_OPERATION_ERR;
       }
       return NS_OK;
     default:
       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 }
 
-SECKEYPublicKey*
-CryptoKey::PublicDhKeyFromRaw(CryptoBuffer& aKeyData,
-                              const CryptoBuffer& aPrime,
-                              const CryptoBuffer& aGenerator,
-                              const nsNSSShutDownPreventionLock& /*proofOfLock*/)
-{
-  ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  if (!arena) {
-    return nullptr;
-  }
-
-  SECKEYPublicKey* key = PORT_ArenaZNew(arena, SECKEYPublicKey);
-  if (!key) {
-    return nullptr;
-  }
-
-  key->keyType = dhKey;
-  key->pkcs11Slot = nullptr;
-  key->pkcs11ID = CK_INVALID_HANDLE;
-
-  // Set DH public key params.
-  if (!aPrime.ToSECItem(arena, &key->u.dh.prime) ||
-      !aGenerator.ToSECItem(arena, &key->u.dh.base) ||
-      !aKeyData.ToSECItem(arena, &key->u.dh.publicValue)) {
-    return nullptr;
-  }
-
-  key->u.dh.prime.type = siUnsignedInteger;
-  key->u.dh.base.type = siUnsignedInteger;
-  key->u.dh.publicValue.type = siUnsignedInteger;
-
-  return SECKEY_CopyPublicKey(key);
-}
-
-nsresult
-CryptoKey::PublicDhKeyToRaw(SECKEYPublicKey* aPubKey,
-                            CryptoBuffer& aRetVal,
-                            const nsNSSShutDownPreventionLock& /*proofOfLock*/)
-{
-  aRetVal.Assign(&aPubKey->u.dh.publicValue);
-  return NS_OK;
-}
-
 bool
 CryptoKey::PublicKeyValid(SECKEYPublicKey* aPubKey)
 {
   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
   if (!slot.get()) {
     return false;
   }
 
--- a/dom/crypto/CryptoKey.h
+++ b/dom/crypto/CryptoKey.h
@@ -166,24 +166,16 @@ public:
                                   const nsNSSShutDownPreventionLock& /*proofOfLock*/);
 
   static SECKEYPublicKey* PublicKeyFromJwk(const JsonWebKey& aKeyData,
                                            const nsNSSShutDownPreventionLock& /*proofOfLock*/);
   static nsresult PublicKeyToJwk(SECKEYPublicKey* aPrivKey,
                                  JsonWebKey& aRetVal,
                                  const nsNSSShutDownPreventionLock& /*proofOfLock*/);
 
-  static SECKEYPublicKey* PublicDhKeyFromRaw(CryptoBuffer& aKeyData,
-                                             const CryptoBuffer& aPrime,
-                                             const CryptoBuffer& aGenerator,
-                                             const nsNSSShutDownPreventionLock& /*proofOfLock*/);
-  static nsresult PublicDhKeyToRaw(SECKEYPublicKey* aPubKey,
-                                   CryptoBuffer& aRetVal,
-                                   const nsNSSShutDownPreventionLock& /*proofOfLock*/);
-
   static bool PublicKeyValid(SECKEYPublicKey* aPubKey);
 
   // Structured clone methods use these to clone keys
   bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const;
   bool ReadStructuredClone(JSStructuredCloneReader* aReader);
 
 private:
   ~CryptoKey();
--- a/dom/crypto/KeyAlgorithmProxy.cpp
+++ b/dom/crypto/KeyAlgorithmProxy.cpp
@@ -26,20 +26,16 @@ KeyAlgorithmProxy::WriteStructuredClone(
              WriteString(aWriter, mHmac.mHash.mName);
     case RSA: {
       return JS_WriteUint32Pair(aWriter, mRsa.mModulusLength, 0) &&
              WriteBuffer(aWriter, mRsa.mPublicExponent) &&
              WriteString(aWriter, mRsa.mHash.mName);
     }
     case EC:
       return WriteString(aWriter, mEc.mNamedCurve);
-    case DH: {
-      return WriteBuffer(aWriter, mDh.mPrime) &&
-             WriteBuffer(aWriter, mDh.mGenerator);
-    }
   }
 
   return false;
 }
 
 bool
 KeyAlgorithmProxy::ReadStructuredClone(JSStructuredCloneReader* aReader)
 {
@@ -91,25 +87,16 @@ KeyAlgorithmProxy::ReadStructuredClone(J
       nsString namedCurve;
       if (!ReadString(aReader, mEc.mNamedCurve)) {
         return false;
       }
 
       mEc.mName = mName;
       return true;
     }
-    case DH: {
-      if (!ReadBuffer(aReader, mDh.mPrime) ||
-          !ReadBuffer(aReader, mDh.mGenerator)) {
-        return false;
-      }
-
-      mDh.mName = mName;
-      return true;
-    }
   }
 
   return false;
 }
 
 CK_MECHANISM_TYPE
 KeyAlgorithmProxy::Mechanism() const
 {
--- a/dom/crypto/KeyAlgorithmProxy.h
+++ b/dom/crypto/KeyAlgorithmProxy.h
@@ -31,55 +31,35 @@ struct RsaHashedKeyAlgorithmStorage {
     aRsa.mName = mName;
     aRsa.mModulusLength = mModulusLength;
     aRsa.mHash.mName = mHash.mName;
     aRsa.mPublicExponent.Init(mPublicExponent.ToUint8Array(aCx));
     aRsa.mPublicExponent.ComputeLengthAndData();
   }
 };
 
-// A heap-safe variant of DhKeyAlgorithm
-// The only difference is that it uses CryptoBuffers instead of Uint8Arrays
-struct DhKeyAlgorithmStorage {
-  nsString mName;
-  CryptoBuffer mPrime;
-  CryptoBuffer mGenerator;
-
-  void
-  ToKeyAlgorithm(JSContext* aCx, DhKeyAlgorithm& aDh) const
-  {
-    aDh.mName = mName;
-    aDh.mPrime.Init(mPrime.ToUint8Array(aCx));
-    aDh.mPrime.ComputeLengthAndData();
-    aDh.mGenerator.Init(mGenerator.ToUint8Array(aCx));
-    aDh.mGenerator.ComputeLengthAndData();
-  }
-};
-
 // This class encapuslates a KeyAlgorithm object, and adds several
 // methods that make WebCrypto operations simpler.
 struct KeyAlgorithmProxy
 {
   enum KeyAlgorithmType {
     AES,
     HMAC,
     RSA,
-    EC,
-    DH,
+    EC
   };
   KeyAlgorithmType mType;
 
   // Plain is always populated with the algorithm name
   // Others are only populated for the corresponding key type
   nsString mName;
   AesKeyAlgorithm mAes;
   HmacKeyAlgorithm mHmac;
   RsaHashedKeyAlgorithmStorage mRsa;
   EcKeyAlgorithm mEc;
-  DhKeyAlgorithmStorage mDh;
 
   // Structured clone
   bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const;
   bool ReadStructuredClone(JSStructuredCloneReader* aReader);
 
   // Extract various forms of derived information
   CK_MECHANISM_TYPE Mechanism() const;
   nsString JwkAlg() const;
@@ -124,25 +104,14 @@ struct KeyAlgorithmProxy
   void
   MakeEc(const nsString& aName, const nsString& aNamedCurve)
   {
     mType = EC;
     mName = aName;
     mEc.mName = aName;
     mEc.mNamedCurve = aNamedCurve;
   }
-
-  void
-  MakeDh(const nsString& aName, const CryptoBuffer& aPrime,
-         const CryptoBuffer& aGenerator)
-  {
-    mType = DH;
-    mName = aName;
-    mDh.mName = aName;
-    mDh.mPrime.Assign(aPrime);
-    mDh.mGenerator.Assign(aGenerator);
-  }
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_KeyAlgorithmProxy_h
--- a/dom/crypto/WebCryptoCommon.h
+++ b/dom/crypto/WebCryptoCommon.h
@@ -23,17 +23,16 @@
 #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_RSASSA_PKCS1  "RSASSA-PKCS1-v1_5"
 #define WEBCRYPTO_ALG_RSA_OAEP      "RSA-OAEP"
 #define WEBCRYPTO_ALG_ECDH          "ECDH"
 #define WEBCRYPTO_ALG_ECDSA         "ECDSA"
-#define WEBCRYPTO_ALG_DH            "DH"
 
 // 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
@@ -97,24 +96,16 @@
 // 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) };
 
-// python security/pkix/tools/DottedOIDToCode.py dhKeyAgreement 1.2.840.113549.1.3.1
-static const uint8_t dhKeyAgreement[] = {
-  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x03, 0x01
-};
-const SECItem SEC_OID_DATA_DH_KEY_AGREEMENT = { siBuffer,
-                                                (unsigned char*)dhKeyAgreement,
-                                                PR_ARRAY_SIZE(dhKeyAgreement) };
-
 namespace mozilla {
 namespace dom {
 
 // Helper functions for structured cloning
 inline bool
 ReadString(JSStructuredCloneReader* aReader, nsString& aString)
 {
   bool read;
@@ -195,18 +186,16 @@ MapAlgorithmNameToMechanism(const nsStri
   } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
     mechanism = CKM_PKCS5_PBKD2;
   } 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;
-  } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
-    mechanism = CKM_DH_PKCS_DERIVE;
   }
 
   return mechanism;
 }
 
 #define NORMALIZED_EQUALS(aTest, aConst) \
         nsContentUtils::EqualsIgnoreASCIICase(aTest, NS_LITERAL_STRING(aConst))
 
@@ -237,18 +226,16 @@ NormalizeToken(const nsString& aName, ns
   } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSASSA_PKCS1)) {
     aDest.AssignLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1);
   } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSA_OAEP)) {
     aDest.AssignLiteral(WEBCRYPTO_ALG_RSA_OAEP);
   } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDH)) {
     aDest.AssignLiteral(WEBCRYPTO_ALG_ECDH);
   } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDSA)) {
     aDest.AssignLiteral(WEBCRYPTO_ALG_ECDSA);
-  } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_DH)) {
-    aDest.AssignLiteral(WEBCRYPTO_ALG_DH);
   // Named curve values
   } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P256)) {
     aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P256);
   } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P384)) {
     aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P384);
   } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P521)) {
     aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P521);
   } else {
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -75,18 +75,19 @@ enum TelemetryAlgorithm {
 // OOM-safe CryptoBuffer initialization, suitable for constructors
 #define ATTEMPT_BUFFER_INIT(dst, src) \
   if (!dst.Assign(src)) { \
     mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR; \
     return; \
   }
 
 // OOM-safe CryptoBuffer-to-SECItem copy, suitable for DoCrypto
-#define ATTEMPT_BUFFER_TO_SECITEM(arena, dst, src) \
-  if (!src.ToSECItem(arena, dst)) { \
+#define ATTEMPT_BUFFER_TO_SECITEM(dst, src) \
+  dst = src.ToSECItem(); \
+  if (!dst) { \
     return NS_ERROR_DOM_UNKNOWN_ERR; \
   }
 
 // OOM-safe CryptoBuffer copy, suitable for DoCrypto
 #define ATTEMPT_BUFFER_ASSIGN(dst, src) \
   if (!dst.Assign(src)) { \
     return NS_ERROR_DOM_UNKNOWN_ERR; \
   }
@@ -505,28 +506,25 @@ private:
   virtual nsresult DoCrypto() MOZ_OVERRIDE
   {
     nsresult rv;
 
     if (!mDataIsSet) {
       return NS_ERROR_DOM_OPERATION_ERR;
     }
 
-    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-    if (!arena) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
-
     // Construct the parameters object depending on algorithm
-    SECItem param = { siBuffer, nullptr, 0 };
+    SECItem param;
+    ScopedSECItem cbcParam;
     CK_AES_CTR_PARAMS ctrParams;
     CK_GCM_PARAMS gcmParams;
     switch (mMechanism) {
       case CKM_AES_CBC_PAD:
-        ATTEMPT_BUFFER_TO_SECITEM(arena, &param, mIv);
+        ATTEMPT_BUFFER_TO_SECITEM(cbcParam, mIv);
+        param = *cbcParam;
         break;
       case CKM_AES_CTR:
         ctrParams.ulCounterBits = mCounterLength;
         MOZ_ASSERT(mIv.Length() == 16);
         memcpy(&ctrParams.cb, mIv.Elements(), 16);
         param.type = siBuffer;
         param.data = (unsigned char*) &ctrParams;
         param.len  = sizeof(ctrParams);
@@ -541,22 +539,22 @@ private:
         param.data = (unsigned char*) &gcmParams;
         param.len  = sizeof(gcmParams);
         break;
       default:
         return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     }
 
     // Import the key
-    SECItem keyItem = { siBuffer, nullptr, 0 };
-    ATTEMPT_BUFFER_TO_SECITEM(arena, &keyItem, mSymKey);
+    ScopedSECItem keyItem;
+    ATTEMPT_BUFFER_TO_SECITEM(keyItem, mSymKey);
     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
     MOZ_ASSERT(slot.get());
     ScopedPK11SymKey symKey(PK11_ImportSymKey(slot, mMechanism, PK11_OriginUnwrap,
-                                              CKA_ENCRYPT, &keyItem, nullptr));
+                                              CKA_ENCRYPT, keyItem.get(), nullptr));
     if (!symKey) {
       return NS_ERROR_DOM_INVALID_ACCESS_ERR;
     }
 
     // Initialize the output buffer (enough space for padding / a full tag)
     uint32_t dataLen = mData.Length();
     uint32_t maxLen = dataLen + 16;
     if (!mResult.SetLength(maxLen)) {
@@ -643,45 +641,40 @@ private:
       return NS_ERROR_DOM_OPERATION_ERR;
     }
 
     // Check that the input is a multiple of 64 bits long
     if (mData.Length() == 0 || mData.Length() % 8 != 0) {
       return NS_ERROR_DOM_DATA_ERR;
     }
 
-    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-    if (!arena) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
-
     // Import the key
-    SECItem keyItem = { siBuffer, nullptr, 0 };
-    ATTEMPT_BUFFER_TO_SECITEM(arena, &keyItem, mSymKey);
+    ScopedSECItem keyItem;
+    ATTEMPT_BUFFER_TO_SECITEM(keyItem, mSymKey);
     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
     MOZ_ASSERT(slot.get());
     ScopedPK11SymKey symKey(PK11_ImportSymKey(slot, mMechanism, PK11_OriginUnwrap,
-                                              CKA_WRAP, &keyItem, nullptr));
+                                              CKA_WRAP, keyItem.get(), nullptr));
     if (!symKey) {
       return NS_ERROR_DOM_INVALID_ACCESS_ERR;
     }
 
     // Import the data to a SECItem
-    SECItem dataItem = { siBuffer, nullptr, 0 };
-    ATTEMPT_BUFFER_TO_SECITEM(arena, &dataItem, mData);
+    ScopedSECItem dataItem;
+    ATTEMPT_BUFFER_TO_SECITEM(dataItem, mData);
 
     // Parameters for the fake keys
     CK_MECHANISM_TYPE fakeMechanism = CKM_SHA_1_HMAC;
     CK_ATTRIBUTE_TYPE fakeOperation = CKA_SIGN;
 
     if (mEncrypt) {
       // Import the data into a fake PK11SymKey structure
       ScopedPK11SymKey keyToWrap(PK11_ImportSymKey(slot, fakeMechanism,
                                                    PK11_OriginUnwrap, fakeOperation,
-                                                   &dataItem, nullptr));
+                                                   dataItem.get(), nullptr));
       if (!keyToWrap) {
         return NS_ERROR_DOM_OPERATION_ERR;
       }
 
       // Encrypt and return the wrapped key
       // AES-KW encryption results in a wrapped key 64 bits longer
       if (!mResult.SetLength(mData.Length() + 8)) {
         return NS_ERROR_DOM_OPERATION_ERR;
@@ -691,17 +684,17 @@ private:
       rv = MapSECStatus(PK11_WrapSymKey(mMechanism, nullptr, symKey.get(),
                                         keyToWrap.get(), &resultItem));
       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
     } else {
       // Decrypt the ciphertext into a temporary PK11SymKey
       // Unwrapped key should be 64 bits shorter
       int keySize = mData.Length() - 8;
       ScopedPK11SymKey unwrappedKey(PK11_UnwrapSymKey(symKey, mMechanism, nullptr,
-                                                 &dataItem, fakeMechanism,
+                                                 dataItem.get(), fakeMechanism,
                                                  fakeOperation, keySize));
       if (!unwrappedKey) {
         return NS_ERROR_DOM_OPERATION_ERR;
       }
 
       // Export the key to get the cleartext
       rv = MapSECStatus(PK11_ExtractKeyValue(unwrappedKey));
       if (NS_FAILED(rv)) {
@@ -903,30 +896,25 @@ private:
   bool mSign;
 
   virtual nsresult DoCrypto() MOZ_OVERRIDE
   {
     // Initialize the output buffer
     if (!mResult.SetLength(HASH_LENGTH_MAX)) {
       return NS_ERROR_DOM_UNKNOWN_ERR;
     }
-
-    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-    if (!arena) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
+    uint32_t outLen;
 
     // Import the key
-    uint32_t outLen;
-    SECItem keyItem = { siBuffer, nullptr, 0 };
-    ATTEMPT_BUFFER_TO_SECITEM(arena, &keyItem, mSymKey);
+    ScopedSECItem keyItem;
+    ATTEMPT_BUFFER_TO_SECITEM(keyItem, mSymKey);
     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
     MOZ_ASSERT(slot.get());
     ScopedPK11SymKey symKey(PK11_ImportSymKey(slot, mMechanism, PK11_OriginUnwrap,
-                                              CKA_SIGN, &keyItem, nullptr));
+                                              CKA_SIGN, keyItem.get(), nullptr));
     if (!symKey) {
       return NS_ERROR_DOM_INVALID_ACCESS_ERR;
     }
 
     // Compute the MAC
     SECItem param = { siBuffer, nullptr, 0 };
     ScopedPK11Context ctx(PK11_CreateContextBySymKey(mMechanism, CKA_SIGN,
                                                      symKey.get(), &param));
@@ -1076,17 +1064,17 @@ private:
   bool mSign;
   bool mVerified;
   bool mEcdsa;
 
   virtual nsresult DoCrypto() MOZ_OVERRIDE
   {
     nsresult rv;
     if (mSign) {
-      ScopedSECItem signature(::SECITEM_AllocItem(nullptr, nullptr, 0));
+      ScopedSECItem signature((SECItem*) PORT_Alloc(sizeof(SECItem)));
       ScopedSGNContext ctx(SGN_NewContext(mOidTag, mPrivKey));
       if (!signature.get() || !ctx.get()) {
         return NS_ERROR_DOM_OPERATION_ERR;
       }
 
       rv = MapSECStatus(SEC_SignData(signature, mData.Elements(),
                                      mData.Length(), mPrivKey, mOidTag));
 
@@ -1100,33 +1088,37 @@ private:
         }
 
         ATTEMPT_BUFFER_ASSIGN(mSignature, rawSignature);
       } else {
         ATTEMPT_BUFFER_ASSIGN(mSignature, signature);
       }
 
     } else {
-      ScopedSECItem signature(::SECITEM_AllocItem(nullptr, nullptr, 0));
-      if (!signature.get()) {
-        return NS_ERROR_DOM_UNKNOWN_ERR;
-      }
+      ScopedSECItem signature;
 
       if (mEcdsa) {
         // DER-encode the signature
-        ScopedSECItem rawSignature(::SECITEM_AllocItem(nullptr, nullptr, 0));
-        if (!rawSignature || !mSignature.ToSECItem(nullptr, rawSignature)) {
+        ScopedSECItem rawSignature(mSignature.ToSECItem());
+        if (!rawSignature.get()) {
           return NS_ERROR_DOM_UNKNOWN_ERR;
         }
 
+        signature = (SECItem*) PORT_Alloc(sizeof(SECItem));
+        if (!signature.get()) {
+          return NS_ERROR_DOM_UNKNOWN_ERR;
+        }
         rv = MapSECStatus(DSAU_EncodeDerSigWithLen(signature, rawSignature,
                                                    rawSignature->len));
         NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
-      } else if (!mSignature.ToSECItem(nullptr, signature)) {
-        return NS_ERROR_DOM_UNKNOWN_ERR;
+      } else {
+        signature = mSignature.ToSECItem();
+        if (!signature) {
+          return NS_ERROR_DOM_UNKNOWN_ERR;
+        }
       }
 
       rv = MapSECStatus(VFY_VerifyData(mData.Elements(), mData.Length(),
                                        mPubKey, signature, mOidTag, nullptr));
       mVerified = NS_SUCCEEDED(rv);
     }
 
     return NS_OK;
@@ -1749,113 +1741,16 @@ private:
     if (mDataIsJwk && !JwkCompatible(mJwk, mKey)) {
       return NS_ERROR_DOM_DATA_ERR;
     }
 
     return NS_OK;
   }
 };
 
-class ImportDhKeyTask : public ImportKeyTask
-{
-public:
-  ImportDhKeyTask(JSContext* aCx, const nsAString& aFormat,
-                  const ObjectOrString& aAlgorithm, bool aExtractable,
-                  const Sequence<nsString>& aKeyUsages)
-  {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
-  }
-
-  ImportDhKeyTask(JSContext* aCx, const nsAString& aFormat,
-                  JS::Handle<JSObject*> aKeyData,
-                  const ObjectOrString& aAlgorithm, bool aExtractable,
-                  const Sequence<nsString>& aKeyUsages)
-  {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
-    if (NS_SUCCEEDED(mEarlyRv)) {
-      SetKeyData(aCx, aKeyData);
-    }
-  }
-
-  void Init(JSContext* aCx, const nsAString& aFormat,
-            const ObjectOrString& aAlgorithm, bool aExtractable,
-            const Sequence<nsString>& aKeyUsages)
-  {
-    ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
-    if (NS_FAILED(mEarlyRv)) {
-      return;
-    }
-
-    if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
-      RootedDictionary<DhImportKeyParams> params(aCx);
-      mEarlyRv = Coerce(aCx, params, aAlgorithm);
-      if (NS_FAILED(mEarlyRv)) {
-        mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
-        return;
-      }
-
-      CryptoBuffer prime;
-      ATTEMPT_BUFFER_INIT(mPrime, params.mPrime);
-
-      CryptoBuffer generator;
-      ATTEMPT_BUFFER_INIT(mGenerator, params.mGenerator);
-    }
-  }
-
-private:
-  CryptoBuffer mPrime;
-  CryptoBuffer mGenerator;
-
-  virtual nsresult DoCrypto() MOZ_OVERRIDE
-  {
-    // Import the key data itself
-    ScopedSECKEYPublicKey pubKey;
-
-    nsNSSShutDownPreventionLock locker;
-    if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW) ||
-        mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) {
-      // Public key import
-      if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
-        pubKey = CryptoKey::PublicDhKeyFromRaw(mKeyData, mPrime, mGenerator, locker);
-      } else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) {
-        pubKey = CryptoKey::PublicKeyFromSpki(mKeyData, locker);
-      } else {
-        MOZ_ASSERT(false);
-      }
-
-      if (!pubKey) {
-        return NS_ERROR_DOM_DATA_ERR;
-      }
-
-      if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) {
-        ATTEMPT_BUFFER_ASSIGN(mPrime, &pubKey->u.dh.prime);
-        ATTEMPT_BUFFER_ASSIGN(mGenerator, &pubKey->u.dh.base);
-      }
-
-      mKey->SetPublicKey(pubKey.get());
-      mKey->SetType(CryptoKey::PUBLIC);
-    } else {
-      return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
-    }
-
-    return NS_OK;
-  }
-
-  virtual nsresult AfterCrypto() MOZ_OVERRIDE
-  {
-    // Check permissions for the requested operation
-    if (mKey->HasUsageOtherThan(CryptoKey::DERIVEBITS | CryptoKey::DERIVEKEY)) {
-      return NS_ERROR_DOM_DATA_ERR;
-    }
-
-    mKey->Algorithm().MakeDh(mAlgName, mPrime, mGenerator);
-    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())
@@ -1886,24 +1781,16 @@ private:
     mPublicKey.dispose();
   }
 
   virtual nsresult DoCrypto() MOZ_OVERRIDE
   {
     nsNSSShutDownPreventionLock locker;
 
     if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
-      if (mPublicKey && mPublicKey->keyType == dhKey) {
-        nsresult rv = CryptoKey::PublicDhKeyToRaw(mPublicKey, mResult, locker);
-        if (NS_FAILED(rv)) {
-          return NS_ERROR_DOM_OPERATION_ERR;
-        }
-        return NS_OK;
-      }
-
       mResult = mSymKey;
       if (mResult.Length() == 0) {
         return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
       }
 
       return NS_OK;
     } else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_PKCS8)) {
       if (!mPrivateKey) {
@@ -2116,22 +2003,16 @@ public:
       const Sequence<nsString>& aKeyUsages)
   {
     nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
     if (!global) {
       mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
       return;
     }
 
-    mArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (!mArena) {
-      mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
-      return;
-    }
-
     // Create an empty key and set easy attributes
     mKeyPair.mPrivateKey = new CryptoKey(global);
     mKeyPair.mPublicKey  = new CryptoKey(global);
 
     // Extract algorithm name
     nsString algName;
     mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
     if (NS_FAILED(mEarlyRv)) {
@@ -2192,56 +2073,30 @@ public:
         mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
         return;
       }
 
       // Create algorithm.
       mKeyPair.mPublicKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
       mKeyPair.mPrivateKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
       mMechanism = CKM_EC_KEY_PAIR_GEN;
-    } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
-      RootedDictionary<DhKeyGenParams> params(aCx);
-      mEarlyRv = Coerce(aCx, params, aAlgorithm);
-      if (NS_FAILED(mEarlyRv)) {
-        mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
-        return;
-      }
-
-      CryptoBuffer prime;
-      ATTEMPT_BUFFER_INIT(prime, params.mPrime);
-
-      CryptoBuffer generator;
-      ATTEMPT_BUFFER_INIT(generator, params.mGenerator);
-
-      // Set up params.
-      if (!prime.ToSECItem(mArena, &mDhParams.prime) ||
-          !generator.ToSECItem(mArena, &mDhParams.base)) {
-        mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
-        return;
-      }
-
-      // Create algorithm.
-      mKeyPair.mPublicKey.get()->Algorithm().MakeDh(algName, prime, generator);
-      mKeyPair.mPrivateKey.get()->Algorithm().MakeDh(algName, prime, generator);
-      mMechanism = CKM_DH_PKCS_KEY_PAIR_GEN;
     } else {
       mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
       return;
     }
 
     // Set key usages.
     if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
         algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
       privateAllowedUsages = CryptoKey::SIGN;
       publicAllowedUsages = CryptoKey::VERIFY;
     } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
       privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY;
       publicAllowedUsages = CryptoKey::ENCRYPT | CryptoKey::WRAPKEY;
-    } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) ||
-               algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
+    } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
       privateAllowedUsages = CryptoKey::DERIVEKEY | CryptoKey::DERIVEBITS;
       publicAllowedUsages = 0;
     }
 
     mKeyPair.mPrivateKey.get()->SetExtractable(aExtractable);
     mKeyPair.mPrivateKey.get()->SetType(CryptoKey::PRIVATE);
 
     mKeyPair.mPublicKey.get()->SetExtractable(true);
@@ -2267,46 +2122,48 @@ public:
     if (!mKeyPair.mPrivateKey.get()->HasAnyUsage() ||
         !mKeyPair.mPrivateKey.get()->HasAnyUsage()) {
       mEarlyRv = NS_ERROR_DOM_DATA_ERR;
       return;
     }
   }
 
 private:
-  ScopedPLArenaPool mArena;
   CryptoKeyPair mKeyPair;
   CK_MECHANISM_TYPE mMechanism;
   PK11RSAGenParams mRsaParams;
-  SECKEYDHParams mDhParams;
   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_DH_PKCS_KEY_PAIR_GEN:
-        param = &mDhParams;
-        break;
       case CKM_EC_KEY_PAIR_GEN: {
-        param = CreateECParamsForCurve(mNamedCurve, mArena);
+        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;
     }
@@ -2404,45 +2261,40 @@ private:
   size_t mLength;
   size_t mIterations;
   CryptoBuffer mSalt;
   CryptoBuffer mSymKey;
   SECOidTag mHashOidTag;
 
   virtual nsresult DoCrypto() MOZ_OVERRIDE
   {
-    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-    if (!arena) {
-      return NS_ERROR_DOM_OPERATION_ERR;
-    }
-
-    SECItem salt = { siBuffer, nullptr, 0 };
-    ATTEMPT_BUFFER_TO_SECITEM(arena, &salt, mSalt);
+    ScopedSECItem salt;
+    ATTEMPT_BUFFER_TO_SECITEM(salt, mSalt);
 
     // Always pass in cipherAlg=SEC_OID_HMAC_SHA1 (i.e. PBMAC1) as this
     // parameter is unused for key generation. It is currently only used
     // for PBKDF2 authentication or key (un)wrapping when specifying an
     // encryption algorithm (PBES2).
     ScopedSECAlgorithmID alg_id(PK11_CreatePBEV2AlgorithmID(
       SEC_OID_PKCS5_PBKDF2, SEC_OID_HMAC_SHA1, mHashOidTag,
-      mLength, mIterations, &salt));
+      mLength, mIterations, salt));
 
     if (!alg_id.get()) {
       return NS_ERROR_DOM_OPERATION_ERR;
     }
 
     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
     if (!slot.get()) {
       return NS_ERROR_DOM_OPERATION_ERR;
     }
 
-    SECItem keyItem = { siBuffer, nullptr, 0 };
-    ATTEMPT_BUFFER_TO_SECITEM(arena, &keyItem, mSymKey);
-
-    ScopedPK11SymKey symKey(PK11_PBEKeyGen(slot, alg_id, &keyItem, false, nullptr));
+    ScopedSECItem keyItem;
+    ATTEMPT_BUFFER_TO_SECITEM(keyItem, mSymKey);
+
+    ScopedPK11SymKey symKey(PK11_PBEKeyGen(slot, alg_id, keyItem, false, 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;
     }
@@ -2564,120 +2416,19 @@ public:
 
 private:
   size_t mLength;
   ScopedSECKEYPrivateKey mPrivKey;
   ScopedSECKEYPublicKey mPubKey;
 
   virtual nsresult DoCrypto() MOZ_OVERRIDE
   {
-    // CKM_SHA512_HMAC and CKA_SIGN are key type and usage attributes of the
-    // derived symmetric key and don't matter because we ignore them anyway.
     ScopedPK11SymKey symKey(PK11_PubDeriveWithKDF(
       mPrivKey, mPubKey, PR_FALSE, nullptr, nullptr, CKM_ECDH1_DERIVE,
-      CKM_SHA512_HMAC, CKA_SIGN, 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;
-  }
-};
-
-class DeriveDhBitsTask : public ReturnArrayBufferViewTask
-{
-public:
-  DeriveDhBitsTask(JSContext* aCx,
-      const ObjectOrString& aAlgorithm, CryptoKey& aKey, uint32_t aLength)
-    : mLength(aLength),
-      mPrivKey(aKey.GetPrivateKey())
-  {
-    Init(aCx, aAlgorithm, aKey);
-  }
-
-  DeriveDhBitsTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
-                   CryptoKey& aKey, const ObjectOrString& aTargetAlgorithm)
-    : mPrivKey(aKey.GetPrivateKey())
-  {
-    mEarlyRv = GetKeyLengthForAlgorithm(aCx, aTargetAlgorithm, mLength);
-    if (NS_SUCCEEDED(mEarlyRv)) {
-      Init(aCx, aAlgorithm, aKey);
-    }
-  }
-
-  void Init(JSContext* aCx, const ObjectOrString& aAlgorithm, CryptoKey& aKey)
-  {
-    CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_DH);
-
-    // Check that we have a private key.
-    if (!mPrivKey) {
-      mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
-      return;
-    }
-
-    mLength = mLength >> 3; // bits to bytes
-
-    // Retrieve the peer's public key.
-    RootedDictionary<DhKeyDeriveParams> params(aCx);
-    mEarlyRv = Coerce(aCx, params, aAlgorithm);
-    if (NS_FAILED(mEarlyRv)) {
-      mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
-      return;
-    }
-
-    CryptoKey* publicKey = params.mPublic;
-    mPubKey = publicKey->GetPublicKey();
-    if (!mPubKey) {
-      mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
-      return;
-    }
-
-    KeyAlgorithmProxy alg1 = publicKey->Algorithm();
-    CHECK_KEY_ALGORITHM(alg1, WEBCRYPTO_ALG_DH);
-
-    // Both keys must use the same prime and generator.
-    KeyAlgorithmProxy alg2 = aKey.Algorithm();
-    if (alg1.mDh.mPrime != alg2.mDh.mPrime ||
-        alg1.mDh.mGenerator != alg2.mDh.mGenerator) {
-      mEarlyRv = NS_ERROR_DOM_DATA_ERR;
-      return;
-    }
-  }
-
-private:
-  size_t mLength;
-  ScopedSECKEYPrivateKey mPrivKey;
-  ScopedSECKEYPublicKey mPubKey;
-
-  virtual nsresult DoCrypto() MOZ_OVERRIDE
-  {
-    // CKM_SHA512_HMAC and CKA_SIGN are key type and usage attributes of the
-    // derived symmetric key and don't matter because we ignore them anyway.
-    ScopedPK11SymKey symKey(PK11_PubDeriveWithKDF(
-      mPrivKey, mPubKey, PR_FALSE, nullptr, nullptr, CKM_DH_PKCS_DERIVE,
-      CKM_SHA512_HMAC, CKA_SIGN, 0, CKD_NULL, nullptr, nullptr));
+      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;
@@ -2938,19 +2689,16 @@ WebCryptoTask::CreateImportKeyTask(JSCon
   } else if (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) ||
              algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
     return new ImportEcKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
                                aExtractable, aKeyUsages);
-  } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
-    return new ImportDhKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
-                               aExtractable, aKeyUsages);
   } else {
     return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   }
 }
 
 WebCryptoTask*
 WebCryptoTask::CreateExportKeyTask(const nsAString& aFormat,
                                    CryptoKey& aKey)
@@ -2977,18 +2725,17 @@ WebCryptoTask::CreateExportKeyTask(const
   if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP) ||
-      algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) ||
-      algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
+      algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
     return new ExportKeyTask(aFormat, aKey);
   }
 
   return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 }
 
 WebCryptoTask*
 WebCryptoTask::CreateGenerateKeyTask(JSContext* aCx,
@@ -3016,18 +2763,17 @@ WebCryptoTask::CreateGenerateKeyTask(JSC
       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_RSASSA_PKCS1) ||
              algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
              algName.EqualsASCII(WEBCRYPTO_ALG_ECDH) ||
-             algName.EqualsASCII(WEBCRYPTO_ALG_ECDSA) ||
-             algName.EqualsASCII(WEBCRYPTO_ALG_DH)) {
+             algName.EqualsASCII(WEBCRYPTO_ALG_ECDSA)) {
     return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
   } else {
     return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   }
 }
 
 WebCryptoTask*
 WebCryptoTask::CreateDeriveKeyTask(JSContext* aCx,
@@ -3092,20 +2838,16 @@ WebCryptoTask::CreateDeriveBitsTask(JSCo
   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);
   }
 
-  if (algName.EqualsASCII(WEBCRYPTO_ALG_DH)) {
-    return new DeriveDhBitsTask(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/test/mochitest.ini
+++ b/dom/crypto/test/mochitest.ini
@@ -3,13 +3,12 @@
 skip-if = (buildapp == 'b2g')
 support-files =
   test-array.js
   test-vectors.js
   test_WebCrypto.css
   util.js
 
 [test_WebCrypto.html]
-[test_WebCrypto_DH.html]
 [test_WebCrypto_ECDH.html]
 [test_WebCrypto_JWK.html]
 [test_WebCrypto_PBKDF2.html]
 [test_WebCrypto_RSA_OAEP.html]
--- a/dom/crypto/test/test-vectors.js
+++ b/dom/crypto/test/test-vectors.js
@@ -652,68 +652,10 @@ tv = {
     pub_jwk: {
       "kty": "EC",
       "crv": "P-521",
       "x": "BhOH_WuVkU6IX5Eu37tfsnRlUCfyFsQJHKg-GTNnQP2B" +
            "rt_gR_UbQr32gWESEBPg1VsRehTkMD-SbI3rt3p_2q0B",
       "y": "AUNouOdGgHsraPNhXNeNdhpGTd15GPyN9R0iWWL98ePc" +
            "JD4mUQD/DsEzNZ4zLkTdSa/Y5fOP6GEzVzQy0zwC+goD"
     }
-  },
-
-  // RFC 2409 <http://tools.ietf.org/html/rfc2409#section-6.1>
-  dh: {
-    prime: util.hex2abv(
-      "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" +
-      "020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" +
-      "4fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"
-    ),
-
-    prime2: util.hex2abv(
-      "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" +
-      "020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" +
-      "4fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed" +
-      "ee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"
-    ),
-  },
-
-  // KASValidityTest_FFCStatic_NOKC_ZZOnly_resp.fax [FA]
-  // <http://csrc.nist.gov/groups/STM/cavp/documents/keymgmt/kastestvectors.zip>
-  dh_nist: {
-    prime: util.hex2abv(
-      "8b79f180cbd3f282de92e8b8f2d092674ffda61f01ed961f8ef04a1b7a3709ff" +
-      "748c2abf6226cf0c4538e48838193da456e92ee530ef7aa703e741585e475b26" +
-      "cd64fa97819181cef27de2449cd385c49c9b030f89873b5b7eaf063a788f00db" +
-      "3cb670c73846bc4f76af062d672bde8f29806b81548411ab48b99aebfd9c2d09"
-    ),
-
-    gen: util.hex2abv(
-      "029843c81d0ea285c41a49b1a2f8e11a56a4b39040dfbc5ec040150c16f72f87" +
-      "4152f9c44c659d86f7717b2425b62597e9a453b13da327a31cde2cced6009152" +
-      "52d30262d1e54f4f864ace0e484f98abdbb37ebb0ba4106af5f0935b744677fa" +
-      "2f7f3826dcef3a1586956105ebea805d871f34c46c25bc30fc66b2db26cb0a93"
-    ),
-
-    raw: util.hex2abv(
-      "4fc9904887ac7fabff87f054003547c2d9458c1f6f584c140d7271f8b266bb39" +
-      "0af7e3f625a629bec9c6a057a4cbe1a556d5e3eb2ff1c6ff677a08b0c7c50911" +
-      "0b9e7c6dbc961ca4360362d3dbcffc5bf2bb7207e0a5922f77cf5464b316aa49" +
-      "fb62b338ebcdb30bf573d07b663bb7777b69d6317df0a4f636ba3d9acbf9e8ac"
-    ),
-
-    spki: util.hex2abv(
-      "308201a33082011806092a864886f70d01030130820109028181008b79f180cb" +
-      "d3f282de92e8b8f2d092674ffda61f01ed961f8ef04a1b7a3709ff748c2abf62" +
-      "26cf0c4538e48838193da456e92ee530ef7aa703e741585e475b26cd64fa9781" +
-      "9181cef27de2449cd385c49c9b030f89873b5b7eaf063a788f00db3cb670c738" +
-      "46bc4f76af062d672bde8f29806b81548411ab48b99aebfd9c2d090281800298" +
-      "43c81d0ea285c41a49b1a2f8e11a56a4b39040dfbc5ec040150c16f72f874152" +
-      "f9c44c659d86f7717b2425b62597e9a453b13da327a31cde2cced600915252d3" +
-      "0262d1e54f4f864ace0e484f98abdbb37ebb0ba4106af5f0935b744677fa2f7f" +
-      "3826dcef3a1586956105ebea805d871f34c46c25bc30fc66b2db26cb0a930000" +
-      "038184000281804fc9904887ac7fabff87f054003547c2d9458c1f6f584c140d" +
-      "7271f8b266bb390af7e3f625a629bec9c6a057a4cbe1a556d5e3eb2ff1c6ff67" +
-      "7a08b0c7c509110b9e7c6dbc961ca4360362d3dbcffc5bf2bb7207e0a5922f77" +
-      "cf5464b316aa49fb62b338ebcdb30bf573d07b663bb7777b69d6317df0a4f636" +
-      "ba3d9acbf9e8ac"
-    )
-  },
+  }
 }
deleted file mode 100644
--- a/dom/crypto/test/test_WebCrypto_DH.html
+++ /dev/null
@@ -1,284 +0,0 @@
-<!DOCTYPE html>
-<html>
-
-<head>
-<title>WebCrypto Test Suite</title>
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-<link rel="stylesheet" href="./test_WebCrypto.css"/>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-
-<!-- Utilities for manipulating ABVs -->
-<script src="util.js"></script>
-
-<!-- A simple wrapper around IndexedDB -->
-<script src="simpledb.js"></script>
-
-<!-- Test vectors drawn from the literature -->
-<script src="./test-vectors.js"></script>
-
-<!-- General testing framework -->
-<script src="./test-array.js"></script>
-
-<script>/*<![CDATA[*/
-"use strict";
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Generate a DH key",
-  function() {
-    var that = this;
-    var alg = {
-      name: "DH",
-      prime: tv.dh.prime,
-      generator: new Uint8Array([0x02])
-    };
-    crypto.subtle.generateKey(alg, false, ["deriveKey", "deriveBits"]).then(
-      complete(that, function(x) {
-        return exists(x.publicKey) &&
-               (x.publicKey.algorithm.name == alg.name) &&
-               util.memcmp(x.publicKey.algorithm.prime, alg.prime) &&
-               util.memcmp(x.publicKey.algorithm.generator, alg.generator) &&
-               (x.publicKey.type == "public") &&
-               x.publicKey.extractable &&
-               (x.publicKey.usages.length == 0) &&
-               exists(x.privateKey) &&
-               (x.privateKey.algorithm.name == alg.name) &&
-               util.memcmp(x.privateKey.algorithm.prime, alg.prime) &&
-               util.memcmp(x.privateKey.algorithm.generator, alg.generator) &&
-               (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(
-  "Derive bits from a DH key",
-  function() {
-    var that = this;
-    var alg = {
-      name: "DH",
-      prime: tv.dh.prime,
-      generator: new Uint8Array([0x02])
-    };
-
-    function doDerive(x) {
-      var alg = {
-        name: "DH",
-        public: x.publicKey
-      };
-      return crypto.subtle.deriveBits(alg, x.privateKey, 128);
-    }
-
-    crypto.subtle.generateKey(alg, false, ["deriveBits"])
-      .then(doDerive, error(that))
-      .then(complete(that, function (x) {
-        return x.byteLength == 16;
-      }), error(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Test that DH deriveBits() fails when the public key is not a DH key",
-  function() {
-    var that = this;
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x.publicKey; }
-    function setPriv(x) { privKey = x.privateKey; }
-
-    function doGenerateDH() {
-      var alg = {
-        name: "DH",
-        prime: tv.dh.prime,
-        generator: new Uint8Array([0x02])
-      };
-      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: "DH", public: pubKey};
-      return crypto.subtle.deriveBits(alg, privKey, 128);
-    }
-
-    doGenerateDH()
-      .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 DH deriveBits() fails when the given keys' primes or bases don't match",
-  function() {
-    var that = this;
-    var pubKey, privKey;
-    function setPub(x) { pubKey = x.publicKey; }
-    function setPriv(x) { privKey = x.privateKey; }
-
-    function doGenerateDH() {
-      var alg = {
-        name: "DH",
-        prime: tv.dh.prime,
-        generator: new Uint8Array([0x02])
-      };
-      return crypto.subtle.generateKey(alg, false, ["deriveBits"]);
-    }
-
-    function doGenerateDH2() {
-      var alg = {
-        name: "DH",
-        prime: tv.dh.prime2,
-        generator: new Uint8Array([0x02])
-      };
-      return crypto.subtle.generateKey(alg, false, ["deriveBits"]);
-    }
-
-    function doGenerateDH3() {
-      var alg = {
-        name: "DH",
-        prime: tv.dh.prime,
-        generator: new Uint8Array([0x03])
-      };
-      return crypto.subtle.generateKey(alg, false, ["deriveBits"]);
-    }
-
-    function doDerive() {
-      var alg = {name: "DH", public: pubKey};
-      return crypto.subtle.deriveBits(alg, privKey, 128);
-    }
-
-    doGenerateDH()
-      .then(setPriv, error(that))
-      .then(doGenerateDH2, error(that))
-      .then(setPub, error(that))
-      .then(doDerive, error(that))
-      .then(error(that), doGenerateDH3)
-      .then(setPub, error(that))
-      .then(doDerive, error(that))
-      .then(error(that), complete(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Raw import/export of a public DH key",
-  function () {
-    var that = this;
-    var alg = {
-      name: "DH",
-      prime: tv.dh_nist.prime,
-      generator: tv.dh_nist.gen
-    };
-
-    function doExport(x) {
-      return crypto.subtle.exportKey("raw", x);
-    }
-
-    crypto.subtle.importKey("raw", tv.dh_nist.raw, alg, true, ["deriveBits"])
-      .then(doExport)
-      .then(memcmp_complete(that, tv.dh_nist.raw), error(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "Derive bits from an imported public and a generated private DH key",
-  function() {
-    var that = this;
-    var alg = {
-      name: "DH",
-      prime: tv.dh_nist.prime,
-      generator: tv.dh_nist.gen
-    };
-
-    var privKey;
-    function setPriv(x) { privKey = x.privateKey; }
-
-    function doImport() {
-      return crypto.subtle.importKey("raw", tv.dh_nist.raw, alg, true, ["deriveBits"]);
-    }
-
-    function doDerive(pubKey) {
-      var alg = {name: "DH", public: pubKey};
-      return crypto.subtle.deriveBits(alg, privKey, 128);
-    }
-
-    crypto.subtle.generateKey(alg, false, ["deriveBits"])
-      .then(setPriv, error(that))
-      .then(doImport, error(that))
-      .then(doDerive, error(that))
-      .then(complete(that, function (x) {
-        return x.byteLength == 16;
-      }), error(that));
-  }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
-  "SPKI import/export of a public DH key",
-  function() {
-    var that = this;
-
-    function doExport(x) {
-      return crypto.subtle.exportKey("spki", x);
-    }
-
-    crypto.subtle.importKey("spki", tv.dh_nist.spki, "DH", true, ["deriveBits"])
-      .then(doExport, error(that))
-      .then(memcmp_complete(that, tv.dh_nist.spki), error(that));
-  }
-);
-/*]]>*/</script>
-</head>
-
-<body>
-
-<div id="content">
-	<div id="head">
-		<b>Web</b>Crypto<br>
-	</div>
-
-    <div id="start" onclick="start();">RUN ALL</div>
-
-    <div id="resultDiv" class="content">
-    Summary:
-    <span class="pass"><span id="passN">0</span> passed, </span>
-    <span class="fail"><span id="failN">0</span> failed, </span>
-    <span class="pending"><span id="pendingN">0</span> pending.</span>
-    <br/>
-    <br/>
-
-    <table id="results">
-        <tr>
-            <th>Test</th>
-            <th>Result</th>
-            <th>Time</th>
-        </tr>
-    </table>
-
-    </div>
-
-    <div id="foot"></div>
-</div>
-
-</body>
-</html>
--- a/dom/webidl/KeyAlgorithm.webidl
+++ b/dom/webidl/KeyAlgorithm.webidl
@@ -25,13 +25,8 @@ dictionary HmacKeyAlgorithm : KeyAlgorit
 };
 
 dictionary RsaHashedKeyAlgorithm : KeyAlgorithm {
   required unsigned short modulusLength;
   required Uint8Array publicExponent;
   required KeyAlgorithm hash;
 };
 
-dictionary DhKeyAlgorithm : KeyAlgorithm {
-  required Uint8Array prime;
-  required Uint8Array generator;
-};
-
--- a/dom/webidl/SubtleCrypto.webidl
+++ b/dom/webidl/SubtleCrypto.webidl
@@ -82,25 +82,16 @@ dictionary AesDerivedKeyParams : Algorit
 dictionary HmacDerivedKeyParams : HmacImportParams {
   [EnforceRange] unsigned long length;
 };
 
 dictionary EcdhKeyDeriveParams : Algorithm {
   required CryptoKey public;
 };
 
-dictionary DhKeyDeriveParams : Algorithm {
-  required CryptoKey public;
-};
-
-dictionary DhImportKeyParams : Algorithm {
-  required BigInteger prime;
-  required BigInteger generator;
-};
-
 dictionary EcdsaParams : Algorithm {
   required AlgorithmIdentifier hash;
 };
 
 /***** JWK *****/
 
 dictionary RsaOtherPrimesInfo {
   // The following fields are defined in Section 6.3.2.7 of JSON Web Algorithms