author | J.C. Jones <jjones@mozilla.com> |
Mon, 11 Nov 2019 21:17:47 +0000 | |
changeset 501771 | 5d93cdf79d2796c10ea902470cab90b9f903b159 |
parent 501770 | d65ec56af99764c4370edc565668ce1ec638ee01 |
child 501772 | 35f2efaaeff6d8c617498ba1958a2409efe1c92c |
push id | 100418 |
push user | jjones@mozilla.com |
push date | Wed, 13 Nov 2019 15:48:34 +0000 |
treeherder | autoland@35f2efaaeff6 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | kjacobs, bzbarsky, keeler |
bugs | 1564509, 1034856, 1539578 |
milestone | 72.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/crypto/CryptoKey.cpp +++ b/dom/crypto/CryptoKey.cpp @@ -8,42 +8,16 @@ #include "cryptohi.h" #include "mozilla/ArrayUtils.h" #include "mozilla/dom/SubtleCryptoBinding.h" #include "mozilla/dom/ToJSValue.h" #include "nsNSSComponent.h" #include "pk11pub.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 @@ -201,24 +175,16 @@ void CryptoKey::GetAlgorithm(JSContext* if (converted) { converted = ToJSValue(cx, rsa, &val); } break; } case KeyAlgorithmProxy::EC: converted = ToJSValue(cx, mAlgorithm.mEc, &val); break; - case KeyAlgorithmProxy::DH: { - RootedDictionary<DhKeyAlgorithm> dh(cx); - converted = mAlgorithm.mDh.ToKeyAlgorithm(cx, dh); - if (converted) { - converted = ToJSValue(cx, dh, &val); - } - break; - } } if (!converted) { aRv.Throw(NS_ERROR_DOM_OPERATION_ERR); return; } aRetVal.set(&val.toObject()); } @@ -478,32 +444,22 @@ UniqueSECKEYPublicKey CryptoKey::PublicK UniqueCERTSubjectPublicKeyInfo spki( SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem)); 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); - } + // Check for |id-ecDH|. Per the WebCrypto spec we must + // support this OID but NSS does unfortunately not know it. Let's + // change the algorithm to |id-ecPublicKey| to make NSS happy. + if (isECDHAlgorithm) { + SECOidTag oid = SEC_OID_ANSIX962_EC_PUBLIC_KEY; SECOidData* oidData = SECOID_FindOIDByTag(oid); if (!oidData) { return nullptr; } SECStatus rv = SECITEM_CopyItem(spki->arena, &spki->algorithm.algorithm, &oidData->oid); @@ -527,96 +483,31 @@ nsresult CryptoKey::PrivateKeyToPkcs8(SE return NS_ERROR_DOM_INVALID_ACCESS_ERR; } if (!aRetVal.Assign(pkcs8Item.get())) { return NS_ERROR_DOM_OPERATION_ERR; } return NS_OK; } -nsresult PublicDhKeyToSpki(SECKEYPublicKey* aPubKey, - CERTSubjectPublicKeyInfo* aSpki) { - 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) { - 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) { UniqueCERTSubjectPublicKeyInfo 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. - UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); - if (!arena) { - return NS_ERROR_DOM_OPERATION_ERR; - } - - spki.reset(PORT_ArenaZNew(arena.get(), 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.release(); - - nsresult rv = PublicDhKeyToSpki(aPubKey, spki.get()); - NS_ENSURE_SUCCESS(rv, rv); - } else { - spki.reset(SECKEY_CreateSubjectPublicKeyInfo(aPubKey)); - if (!spki) { - return NS_ERROR_DOM_OPERATION_ERR; - } + spki.reset(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 this 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); - } - - SECStatus rv = - SECITEM_CopyItem(spki->arena, &spki->algorithm.algorithm, oidData); + 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); UniqueSECItem spkiItem(SEC_ASN1EncodeItem(nullptr, nullptr, spki.get(), tpl)); @@ -1031,55 +922,16 @@ nsresult CryptoKey::PublicKeyToJwk(SECKE return NS_ERROR_DOM_OPERATION_ERR; } return NS_OK; default: return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } } -UniqueSECKEYPublicKey CryptoKey::PublicDhKeyFromRaw( - CryptoBuffer& aKeyData, const CryptoBuffer& aPrime, - const CryptoBuffer& aGenerator) { - UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); - if (!arena) { - return nullptr; - } - - SECKEYPublicKey* key = PORT_ArenaZNew(arena.get(), 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.get(), &key->u.dh.prime) || - !aGenerator.ToSECItem(arena.get(), &key->u.dh.base) || - !aKeyData.ToSECItem(arena.get(), &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 UniqueSECKEYPublicKey(SECKEY_CopyPublicKey(key)); -} - -nsresult CryptoKey::PublicDhKeyToRaw(SECKEYPublicKey* aPubKey, - CryptoBuffer& aRetVal) { - if (!aRetVal.Assign(&aPubKey->u.dh.publicValue)) { - return NS_ERROR_DOM_OPERATION_ERR; - } - return NS_OK; -} - UniqueSECKEYPublicKey CryptoKey::PublicECKeyFromRaw( CryptoBuffer& aKeyData, const nsString& aNamedCurve) { UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { return nullptr; } SECItem rawItem = {siBuffer, nullptr, 0};
--- a/dom/crypto/CryptoKey.h +++ b/dom/crypto/CryptoKey.h @@ -145,22 +145,16 @@ class CryptoKey final : public nsISuppor static UniqueSECKEYPrivateKey PrivateKeyFromJwk(const JsonWebKey& aJwk); static nsresult PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey, JsonWebKey& aRetVal); static UniqueSECKEYPublicKey PublicKeyFromJwk(const JsonWebKey& aKeyData); static nsresult PublicKeyToJwk(SECKEYPublicKey* aPubKey, JsonWebKey& aRetVal); - static UniqueSECKEYPublicKey PublicDhKeyFromRaw( - CryptoBuffer& aKeyData, const CryptoBuffer& aPrime, - const CryptoBuffer& aGenerator); - static nsresult PublicDhKeyToRaw(SECKEYPublicKey* aPubKey, - CryptoBuffer& aRetVal); - static UniqueSECKEYPublicKey PublicECKeyFromRaw(CryptoBuffer& aKeyData, const nsString& aNamedCurve); static nsresult PublicECKeyToRaw(SECKEYPublicKey* aPubKey, CryptoBuffer& aRetVal); static bool PublicKeyValid(SECKEYPublicKey* aPubKey); // Structured clone methods use these to clone keys
--- a/dom/crypto/KeyAlgorithmProxy.cpp +++ b/dom/crypto/KeyAlgorithmProxy.cpp @@ -26,20 +26,16 @@ bool KeyAlgorithmProxy::WriteStructuredC StructuredCloneHolder::WriteString(aWriter, mHmac.mHash.mName); case RSA: { return JS_WriteUint32Pair(aWriter, mRsa.mModulusLength, 0) && WriteBuffer(aWriter, mRsa.mPublicExponent) && StructuredCloneHolder::WriteString(aWriter, mRsa.mHash.mName); } case EC: return StructuredCloneHolder::WriteString(aWriter, mEc.mNamedCurve); - case DH: { - return WriteBuffer(aWriter, mDh.mPrime) && - WriteBuffer(aWriter, mDh.mGenerator); - } } return false; } bool KeyAlgorithmProxy::ReadStructuredClone(JSStructuredCloneReader* aReader) { uint32_t type, version, dummy; if (!StructuredCloneHolder::ReadString(aReader, mName) || @@ -89,25 +85,16 @@ bool KeyAlgorithmProxy::ReadStructuredCl nsString namedCurve; if (!StructuredCloneHolder::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 { if (mType == HMAC) {
--- a/dom/crypto/KeyAlgorithmProxy.h +++ b/dom/crypto/KeyAlgorithmProxy.h @@ -36,64 +36,34 @@ struct RsaHashedKeyAlgorithmStorage { aRsa.mHash.mName = mHash.mName; aRsa.mPublicExponent.Init(exponent); aRsa.mPublicExponent.ComputeLengthAndData(); return true; } }; -// 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; - - bool ToKeyAlgorithm(JSContext* aCx, DhKeyAlgorithm& aDh) const { - JS::Rooted<JSObject*> prime(aCx, mPrime.ToUint8Array(aCx)); - if (!prime) { - return false; - } - - JS::Rooted<JSObject*> generator(aCx, mGenerator.ToUint8Array(aCx)); - if (!generator) { - return false; - } - - aDh.mName = mName; - aDh.mPrime.Init(prime); - aDh.mPrime.ComputeLengthAndData(); - aDh.mGenerator.Init(generator); - aDh.mGenerator.ComputeLengthAndData(); - - return true; - } -}; - // This class encapuslates a KeyAlgorithm object, and adds several // methods that make WebCrypto operations simpler. struct KeyAlgorithmProxy { enum KeyAlgorithmType { AES, HMAC, RSA, EC, - DH, }; 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; @@ -133,28 +103,14 @@ struct KeyAlgorithmProxy { } void MakeEc(const nsString& aName, const nsString& aNamedCurve) { mType = EC; mName = aName; mEc.mName = aName; mEc.mNamedCurve = aNamedCurve; } - - bool MakeDh(const nsString& aName, const CryptoBuffer& aPrime, - const CryptoBuffer& aGenerator) { - mType = DH; - mName = aName; - mDh.mName = aName; - if (!mDh.mPrime.Assign(aPrime)) { - return false; - } - if (!mDh.mGenerator.Assign(aGenerator)) { - return false; - } - return true; - } }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_KeyAlgorithmProxy_h
--- a/dom/crypto/WebCryptoCommon.h +++ b/dom/crypto/WebCryptoCommon.h @@ -26,17 +26,16 @@ #define WEBCRYPTO_ALG_HMAC "HMAC" #define WEBCRYPTO_ALG_HKDF "HKDF" #define WEBCRYPTO_ALG_PBKDF2 "PBKDF2" #define WEBCRYPTO_ALG_RSASSA_PKCS1 "RSASSA-PKCS1-v1_5" #define WEBCRYPTO_ALG_RSA_OAEP "RSA-OAEP" #define WEBCRYPTO_ALG_RSA_PSS "RSA-PSS" #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 @@ -105,25 +104,16 @@ #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, static_cast<unsigned int>(mozilla::ArrayLength(id_ecDH))}; -// clang-format off -// python security/pkix/tools/DottedOIDToCode.py dhKeyAgreement 1.2.840.113549.1.3.1 -// clang-format on -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, - static_cast<unsigned int>(mozilla::ArrayLength(dhKeyAgreement))}; - namespace mozilla { namespace dom { inline bool ReadBuffer(JSStructuredCloneReader* aReader, CryptoBuffer& aBuffer) { uint32_t length, zero; bool ret = JS_ReadUint32Pair(aReader, &length, &zero); if (!ret) { @@ -178,18 +168,16 @@ inline CK_MECHANISM_TYPE MapAlgorithmNam } 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_RSA_PSS)) { mechanism = CKM_RSA_PKCS_PSS; } 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)) @@ -222,18 +210,16 @@ inline bool NormalizeToken(const nsStrin } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSA_OAEP)) { aDest.AssignLiteral(WEBCRYPTO_ALG_RSA_OAEP); } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSA_PSS)) { aDest.AssignLiteral(WEBCRYPTO_ALG_RSA_PSS); } 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 @@ -1875,113 +1875,16 @@ class ImportEcKeyTask : public ImportKey if (mDataIsJwk && !JwkCompatible(mJwk, mKey)) { return NS_ERROR_DOM_DATA_ERR; } return NS_OK; } }; -class ImportDhKeyTask : public ImportKeyTask { - public: - ImportDhKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx, - const nsAString& aFormat, const ObjectOrString& aAlgorithm, - bool aExtractable, const Sequence<nsString>& aKeyUsages) { - Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages); - } - - ImportDhKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx, - const nsAString& aFormat, JS::Handle<JSObject*> aKeyData, - const ObjectOrString& aAlgorithm, bool aExtractable, - const Sequence<nsString>& aKeyUsages) { - Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages); - if (NS_SUCCEEDED(mEarlyRv)) { - SetKeyData(aCx, aKeyData); - NS_ENSURE_SUCCESS_VOID(mEarlyRv); - } - } - - void Init(nsIGlobalObject* aGlobal, JSContext* aCx, const nsAString& aFormat, - const ObjectOrString& aAlgorithm, bool aExtractable, - const Sequence<nsString>& aKeyUsages) { - ImportKeyTask::Init(aGlobal, 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() override { - // Import the key data itself - UniqueSECKEYPublicKey pubKey; - - 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); - } else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) { - pubKey = CryptoKey::PublicKeyFromSpki(mKeyData); - } 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); - } - - if (NS_FAILED(mKey->SetPublicKey(pubKey.get()))) { - return NS_ERROR_DOM_OPERATION_ERR; - } - - mKey->SetType(CryptoKey::PUBLIC); - } else { - return NS_ERROR_DOM_NOT_SUPPORTED_ERR; - } - - return NS_OK; - } - - virtual nsresult AfterCrypto() override { - // Check permissions for the requested operation - if (mKey->HasUsageOtherThan(CryptoKey::DERIVEBITS | CryptoKey::DERIVEKEY)) { - return NS_ERROR_DOM_DATA_ERR; - } - - if (!mKey->Algorithm().MakeDh(mAlgName, mPrime, mGenerator)) { - return NS_ERROR_DOM_OPERATION_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()), mKeyType(aKey.GetKeyType()), @@ -2001,21 +1904,17 @@ class ExportKeyTask : public WebCryptoTa nsTArray<nsString> mKeyUsages; CryptoBuffer mResult; JsonWebKey mJwk; private: virtual nsresult DoCrypto() override { if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) { if (mPublicKey && mPublicKey->keyType == dhKey) { - nsresult rv = CryptoKey::PublicDhKeyToRaw(mPublicKey.get(), mResult); - if (NS_FAILED(rv)) { - return NS_ERROR_DOM_OPERATION_ERR; - } - return NS_OK; + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } if (mPublicKey && mPublicKey->keyType == ecKey) { nsresult rv = CryptoKey::PublicECKeyToRaw(mPublicKey.get(), mResult); if (NS_FAILED(rv)) { return NS_ERROR_DOM_OPERATION_ERR; } return NS_OK; @@ -2302,65 +2201,31 @@ GenerateAsymmetricKeyTask::GenerateAsymm mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR; return; } // Create algorithm. mKeyPair->mPublicKey.get()->Algorithm().MakeEc(mAlgName, mNamedCurve); mKeyPair->mPrivateKey.get()->Algorithm().MakeEc(mAlgName, mNamedCurve); mMechanism = CKM_EC_KEY_PAIR_GEN; - } else if (mAlgName.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.get(), &mDhParams.prime) || - !generator.ToSECItem(mArena.get(), &mDhParams.base)) { - mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR; - return; - } - - // Create algorithm. - if (!mKeyPair->mPublicKey.get()->Algorithm().MakeDh(mAlgName, prime, - generator)) { - mEarlyRv = NS_ERROR_DOM_OPERATION_ERR; - return; - } - if (!mKeyPair->mPrivateKey.get()->Algorithm().MakeDh(mAlgName, prime, - generator)) { - mEarlyRv = NS_ERROR_DOM_OPERATION_ERR; - return; - } - mMechanism = CKM_DH_PKCS_KEY_PAIR_GEN; } else { mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR; return; } // Set key usages. if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) || mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS) || mAlgName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) { privateAllowedUsages = CryptoKey::SIGN; publicAllowedUsages = CryptoKey::VERIFY; } else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) { privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY; publicAllowedUsages = CryptoKey::ENCRYPT | CryptoKey::WRAPKEY; - } else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) || - mAlgName.EqualsLiteral(WEBCRYPTO_ALG_DH)) { + } else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) { privateAllowedUsages = CryptoKey::DERIVEKEY | CryptoKey::DERIVEBITS; publicAllowedUsages = 0; } else { MOZ_ASSERT(false); // This shouldn't happen. } mKeyPair->mPrivateKey.get()->SetExtractable(aExtractable); mKeyPair->mPrivateKey.get()->SetType(CryptoKey::PRIVATE); @@ -2867,111 +2732,16 @@ class DeriveEcdhBitsTask : public Return if (!mResult.SetLength(mLength, fallible)) { 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) { - Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_DH); - 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; - UniqueSECKEYPrivateKey mPrivKey; - UniqueSECKEYPublicKey mPubKey; - - virtual nsresult DoCrypto() 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. - UniquePK11SymKey symKey( - PK11_PubDeriveWithKDF(mPrivKey.get(), mPubKey.get(), PR_FALSE, nullptr, - nullptr, CKM_DH_PKCS_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.get())); - 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.get())); - - if (mLength > mResult.Length()) { - return NS_ERROR_DOM_DATA_ERR; - } - - if (!mResult.SetLength(mLength, fallible)) { - 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, const ObjectOrString& aWrapAlgorithm) : ExportKeyTask(aFormat, aKey) { if (NS_FAILED(mEarlyRv)) { return; @@ -3172,19 +2942,16 @@ WebCryptoTask* WebCryptoTask::CreateImpo algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP) || algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) { return new ImportRsaKeyTask(aGlobal, aCx, aFormat, aKeyData, aAlgorithm, aExtractable, aKeyUsages); } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) || algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) { return new ImportEcKeyTask(aGlobal, aCx, aFormat, aKeyData, aAlgorithm, aExtractable, aKeyUsages); - } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) { - return new ImportDhKeyTask(aGlobal, aCx, aFormat, aKeyData, aAlgorithm, - aExtractable, aKeyUsages); } else { return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR); } } WebCryptoTask* WebCryptoTask::CreateExportKeyTask(const nsAString& aFormat, CryptoKey& aKey) { Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_EXPORTKEY); @@ -3211,18 +2978,17 @@ WebCryptoTask* WebCryptoTask::CreateExpo 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_RSA_PSS) || algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA) || - 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( nsIGlobalObject* aGlobal, JSContext* aCx, const ObjectOrString& aAlgorithm, @@ -3250,18 +3016,17 @@ WebCryptoTask* WebCryptoTask::CreateGene algName.EqualsASCII(WEBCRYPTO_ALG_AES_KW) || algName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) { return new GenerateSymmetricKeyTask(aGlobal, aCx, aAlgorithm, aExtractable, aKeyUsages); } else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) || algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) || algName.EqualsASCII(WEBCRYPTO_ALG_RSA_PSS) || algName.EqualsASCII(WEBCRYPTO_ALG_ECDH) || - algName.EqualsASCII(WEBCRYPTO_ALG_ECDSA) || - algName.EqualsASCII(WEBCRYPTO_ALG_DH)) { + algName.EqualsASCII(WEBCRYPTO_ALG_ECDSA)) { return new GenerateAsymmetricKeyTask(aGlobal, aCx, aAlgorithm, aExtractable, aKeyUsages); } else { return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR); } } WebCryptoTask* WebCryptoTask::CreateDeriveKeyTask( @@ -3326,20 +3091,16 @@ WebCryptoTask* WebCryptoTask::CreateDeri 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); - } - if (algName.EqualsASCII(WEBCRYPTO_ALG_HKDF)) { return new DeriveHkdfBitsTask(aCx, aAlgorithm, aKey, aLength); } return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR); } WebCryptoTask* WebCryptoTask::CreateWrapKeyTask(
--- a/dom/crypto/test/browser/browser_WebCrypto_telemetry.js +++ b/dom/crypto/test/browser/browser_WebCrypto_telemetry.js @@ -27,31 +27,8 @@ add_task(async function ecdh_key() { { name: "ECDH", public: x.publicKey }, x.privateKey, 128 ); is(data.byteLength, 128 / 8, "Should be 16 bytes derived"); TelemetryTestUtils.assertHistogram(hist, 20, 1); }); - -add_task(async function dh_key() { - let hist = TelemetryTestUtils.getAndClearHistogram(WEBCRYPTO_ALG_PROBE); - - let alg = { - name: "DH", - prime: tv.dh.prime, - generator: new Uint8Array([0x02]), - }; - - let x = await crypto.subtle.generateKey(alg, false, [ - "deriveKey", - "deriveBits", - ]); - let data = await crypto.subtle.deriveBits( - { name: "DH", public: x.publicKey }, - x.privateKey, - 128 - ); - is(data.byteLength, 128 / 8, "Should be 16 bytes derived"); - - TelemetryTestUtils.assertHistogram(hist, 24, 1); -});
--- a/dom/crypto/test/test-vectors.js +++ b/dom/crypto/test/test-vectors.js @@ -746,30 +746,51 @@ let tv = { iterations: 1, derived: util.hex2abv( "1635fa0f0542cc84f51207ff6cad5284aee3b0264faa55868eca95a7efd2335c" ), }, broken_pkcs8: { - // A DH key with parameters p and g, and a private value. - // This currently fails the key import due to the missing public value. - // <https://stackoverflow.com/questions/6032675/diffie-hellman-test-vectors> - dh: util.hex2abv( - "308201340201003082011506072a8648ce3e02013082010802818100da3a8085" + - "d372437805de95b88b675122f575df976610c6a844de99f1df82a06848bf7a42" + - "f18895c97402e81118e01a00d0855d51922f434c022350861d58ddf60d65bc69" + - "41fc6064b147071a4c30426d82fc90d888f94990267c64beef8c304a4b2b26fb" + - "93724d6a9472fa16bc50c5b9b8b59afb62cfe9ea3ba042c73a6ade3502818100" + - "a51883e9ac0539859df3d25c716437008bb4bd8ec4786eb4bc643299daef5e3e" + - "5af5863a6ac40a597b83a27583f6a658d408825105b16d31b6ed088fc623f648" + - "fd6d95e9cefcb0745763cddf564c87bcf4ba7928e74fd6a3080481f588d535e4" + - "c026b58a21e1e5ec412ff241b436043e29173f1dc6cb943c09742de989547288" + - "0416021442c6ee70beb7465928a1efe692d2281b8f7b53d6" + // An RSA key that's missing the prime1 value. This currently fails the key + // import due that missing value. See this gist for the construction: + // <https://gist.github.com/jcjones/79efe5a6fe2aad3145e1d5e6be765893> + rsa: util.hex2abv( + "30820438020100300d06092a864886f70d0101010500048204223082041e0201000282" + + "010100cd5286bf0558a0829d0218ae2912bb1ffb1c0533d42a419076dd777652b6fc61" + + "c2deeb0dcb60cbcdce530ebdd0952fef6fb4086575a70318dfa9099284ccb99e0c789c" + + "f1f006d371fc2a5644ab5dd3928aaf2b7b046968d3db2b5018c21a56f10f83646f34bc" + + "f4bc898e6847d6848e51891f9ff8524aee3e3683a8efe437861db3c0671fa994980774" + + "de555ffb70c30bd4341b2c2efe0b5624af52ff371bc11b092309b46fecc428c04e1d10" + + "b11c678256c76ef9b3a6aee79b2e795496a31c363454c4fdf239d43b759ac321647a3b" + + "4b7c76fe5575183a463cd9ebca2da17a6caac74ac9430ee6fef4cb24ca01d3da7321b1" + + "972b97cda536a5e392f64d0cb04902030100010282010036599619928cb7505bc76649" + + "13ce45825db2391e53172c6bd54b22884bb4ec71e467a5c8ed011e71c81fec530a97b3" + + "2caa60f9a801d0c7dd19b761354bb9f59884ac98bee24eac420c0218fbec70d5c480b9" + + "85c4f6920091b3fe6f215ea0224b8553be8e416393552504714e32d6bbe5916ab1a9c5" + + "fed7b9d82c59d7c68d7c0e7ed37123e64176aa7d24a52972859b91fee93f25c263f900" + + "a1c38764798d0396294c775b65e5563e8d8a6fc519307d14c49bd11a36dcbd05a120d9" + + "6e05e47da12051311b4e8b027cce5016b411072927f3846a662b8019cd275430f80646" + + "7d531dc595bb4af64136c8aadd9cf3f6c123b0aec69c040a0beb4ee2f023beab915102" + + "818100d0e82ca2cd42a550f66b8ebaa6fe0fd51e204a15418a4fc97a8106c4106aee61" + + "0b72f794a7e65eea45a44a9e844c36a75436c825349c94c8608b243d54a6835013bd77" + + "56f386ea25102398bcbda264f1fea9dc5b415d8d71ee3d4e2c67b0e0c6abc1029bb94b" + + "6d70b19cb4cea401dc4a9fdc351463666b8ac43c821672551b9f02818052b9f12d0b99" + + "cae194fcb8abc8f21cab920453aded0789ec4f92bdb2b1c0c073d6cb29c089c9ac000a" + + "afe2df7633741acea7ff216b4aa5f0c299ede0f713a0bd07a5a1001e730013efdc81c9" + + "984d8aba957c5c175a7dff3b17c6e0725604f4c91bd867544f20c2b5f6dd39280a9800" + + "4308ef55f20be709e5ebeab4c0dc879fc90281800fa02e26873fe2e9a964e62a23ef80" + + "f3a9eb345f5ea59fce2c319675f7dc67b42e8d0ce3bba3499a305757957fc3cb9abc7b" + + "d480a3ecca5c2a8c7dcb70977bdef37b0a80207b08ec78c690d81d3f1659db788d18ee" + + "4cb715bc822d64b8e4cc0b503181a67037aa19f1cf0cdf1ff95ba6e14a31563311281e" + + "1b0b83977639d3750281807759c93656b00d794f68388928309c380b0cfd075baf76c2" + + "e37b5bc55409027ed02eb1bb3a2cb12d4fc43a84fdadd5b80216b88545d71559caa3a0" + + "1267a3cd07c58230ee477d69a71053a6b6a81e5083f7f0cbc28c3d1eae8a3ceeaf8a75" + + "651d0f52db8c79cff223edf4b1d412071b1bedf0d9b05348f39e0b2a89c692886ef3" ), }, // KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.fax [EC] // <http://csrc.nist.gov/groups/STM/cavp/documents/keymgmt/kastestvectors.zip> ecdh_p256: { jwk_pub: { kty: "EC", @@ -989,23 +1010,16 @@ let tv = { // RFC 2409 <http://tools.ietf.org/html/rfc2409#section-6.2> dh: { prime: util.hex2abv( "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" + "020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" + "4fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed" + "ee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff" ), - - prime2: util.hex2abv( - "8b79f180cbd3f282de92e8b8f2d092674ffda61f01ed961f8ef04a1b7a3709ff" + - "748c2abf6226cf0c4538e48838193da456e92ee530ef7aa703e741585e475b26" + - "cd64fa97819181cef27de2449cd385c49c9b030f89873b5b7eaf063a788f00db" + - "3cb670c73846bc4f76af062d672bde8f29806b81548411ab48b99aebfd9c2d09" - ), }, // 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" +
--- a/dom/crypto/test/test_WebCrypto.html +++ b/dom/crypto/test/test_WebCrypto.html @@ -1025,20 +1025,19 @@ TestArray.addTest( } ); // ----------------------------------------------------------------------------- TestArray.addTest( "Ensure that importing an invalid key doesn't crash", function() { var that = this; - // TODO Change the algorithm to "DH" once we support it. var alg = {name: "RSA-OAEP", hash: "SHA-1"}; - crypto.subtle.importKey("pkcs8", tv.broken_pkcs8.dh, alg, false, ["decrypt"]) + crypto.subtle.importKey("pkcs8", tv.broken_pkcs8.rsa, alg, false, ["decrypt"]) .then(error(that), complete(that)); } ); // ----------------------------------------------------------------------------- TestArray.addTest( "Test that we check keys before using them for encryption/signatures", function() {
--- a/dom/crypto/test/test_WebCrypto_DH.html +++ b/dom/crypto/test/test_WebCrypto_DH.html @@ -16,234 +16,56 @@ <!-- 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"; +// DH is not permitted, so ensure all entry point methods error // ----------------------------------------------------------------------------- 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) { - return crypto.subtle.deriveBits({ name: "DH", public: x.publicKey }, 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)) + crypto.subtle.generateKey(alg, false, ["deriveKey", "deriveBits"]) .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) { - return crypto.subtle.deriveBits({name: "DH", public: pubKey}, 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)); + .then(error(that), complete(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)); + .then(error(that), complete(that)); } ); /* ]]>*/</script> </head> <body> <div id="content">
--- a/dom/webidl/SubtleCrypto.webidl +++ b/dom/webidl/SubtleCrypto.webidl @@ -75,22 +75,16 @@ dictionary RsaOaepParams : Algorithm { }; [GenerateInit] dictionary RsaPssParams : Algorithm { required [EnforceRange] unsigned long saltLength; }; [GenerateInit] -dictionary DhKeyGenParams : Algorithm { - required BigInteger prime; - required BigInteger generator; -}; - -[GenerateInit] dictionary EcKeyGenParams : Algorithm { required NamedCurve namedCurve; }; [GenerateInit] dictionary AesDerivedKeyParams : Algorithm { required [EnforceRange] unsigned long length; }; @@ -101,21 +95,16 @@ dictionary HmacDerivedKeyParams : HmacIm }; [GenerateInit] dictionary EcdhKeyDeriveParams : Algorithm { required CryptoKey public; }; [GenerateInit] -dictionary DhKeyDeriveParams : Algorithm { - required CryptoKey public; -}; - -[GenerateInit] dictionary DhImportKeyParams : Algorithm { required BigInteger prime; required BigInteger generator; }; [GenerateInit] dictionary EcdsaParams : Algorithm { required AlgorithmIdentifier hash;