deleted file mode 100644
--- a/dom/crypto/AesKeyAlgorithm.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/AesKeyAlgorithm.h"
-#include "mozilla/dom/SubtleCryptoBinding.h"
-#include "mozilla/dom/WebCryptoCommon.h"
-
-namespace mozilla {
-namespace dom {
-
-JSObject*
-AesKeyAlgorithm::WrapObject(JSContext* aCx)
-{
- return AesKeyAlgorithmBinding::Wrap(aCx, this);
-}
-
-nsString
-AesKeyAlgorithm::ToJwkAlg() const
-{
- if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
- switch (mLength) {
- case 128: return NS_LITERAL_STRING(JWK_ALG_A128CBC);
- case 192: return NS_LITERAL_STRING(JWK_ALG_A192CBC);
- case 256: return NS_LITERAL_STRING(JWK_ALG_A256CBC);
- }
- }
-
- if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
- switch (mLength) {
- case 128: return NS_LITERAL_STRING(JWK_ALG_A128CTR);
- case 192: return NS_LITERAL_STRING(JWK_ALG_A192CTR);
- case 256: return NS_LITERAL_STRING(JWK_ALG_A256CTR);
- }
- }
-
- if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
- switch (mLength) {
- case 128: return NS_LITERAL_STRING(JWK_ALG_A128GCM);
- case 192: return NS_LITERAL_STRING(JWK_ALG_A192GCM);
- case 256: return NS_LITERAL_STRING(JWK_ALG_A256GCM);
- }
- }
-
- if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
- switch (mLength) {
- case 128: return NS_LITERAL_STRING(JWK_ALG_A128KW);
- case 192: return NS_LITERAL_STRING(JWK_ALG_A192KW);
- case 256: return NS_LITERAL_STRING(JWK_ALG_A256KW);
- }
- }
-
- return nsString();
-}
-
-bool
-AesKeyAlgorithm::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
-{
- return JS_WriteUint32Pair(aWriter, SCTAG_AESKEYALG, 0) &&
- JS_WriteUint32Pair(aWriter, mLength, 0) &&
- WriteString(aWriter, mName);
-}
-
-KeyAlgorithm*
-AesKeyAlgorithm::Create(nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader)
-{
- uint32_t length, zero;
- nsString name;
- bool read = JS_ReadUint32Pair(aReader, &length, &zero) &&
- ReadString(aReader, name);
- if (!read) {
- return nullptr;
- }
-
- return new AesKeyAlgorithm(aGlobal, name, length);
-}
-
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/crypto/AesKeyAlgorithm.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_AesKeyAlgorithm_h
-#define mozilla_dom_AesKeyAlgorithm_h
-
-#include "mozilla/dom/BasicSymmetricKeyAlgorithm.h"
-#include "js/TypeDecls.h"
-
-namespace mozilla {
-namespace dom {
-
-class AesKeyAlgorithm MOZ_FINAL : public BasicSymmetricKeyAlgorithm
-{
-public:
- AesKeyAlgorithm(nsIGlobalObject* aGlobal, const nsString& aName, uint16_t aLength)
- : BasicSymmetricKeyAlgorithm(aGlobal, aName, aLength)
- {}
-
- ~AesKeyAlgorithm()
- {}
-
- virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
-
- virtual nsString ToJwkAlg() const MOZ_OVERRIDE;
-
- virtual bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const MOZ_OVERRIDE;
- static KeyAlgorithm* Create(nsIGlobalObject* aGlobal,
- JSStructuredCloneReader* aReader);
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_AesKeyAlgorithm_h
deleted file mode 100644
--- a/dom/crypto/BasicSymmetricKeyAlgorithm.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_BasicSymmetricKeyAlgorithm_h
-#define mozilla_dom_BasicSymmetricKeyAlgorithm_h
-
-#include "mozilla/dom/KeyAlgorithm.h"
-
-namespace mozilla {
-namespace dom {
-
-class BasicSymmetricKeyAlgorithm : public KeyAlgorithm
-{
-public:
- BasicSymmetricKeyAlgorithm(nsIGlobalObject* aGlobal, const nsString& aName, uint16_t aLength)
- : KeyAlgorithm(aGlobal, aName)
- , mLength(aLength)
- {}
-
- ~BasicSymmetricKeyAlgorithm()
- {}
-
- uint16_t Length() const
- {
- return mLength;
- }
-
-protected:
- uint16_t mLength;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_BasicSymmetricKeyAlgorithm_h
--- a/dom/crypto/CryptoBuffer.cpp
+++ b/dom/crypto/CryptoBuffer.cpp
@@ -156,16 +156,23 @@ CryptoBuffer::ToSECItem() const
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());
+}
+
+
// "BigInt" comes from the WebCrypto spec
// ("unsigned long" isn't very "big", of course)
// Likewise, the spec calls for big-endian ints
bool
CryptoBuffer::GetBigIntValue(unsigned long& aRetVal)
{
if (Length() > sizeof(aRetVal)) {
return false;
--- a/dom/crypto/CryptoBuffer.h
+++ b/dom/crypto/CryptoBuffer.h
@@ -35,16 +35,17 @@ public:
{
aArray.ComputeLengthAndData();
return Assign(aArray.Data(), aArray.Length());
}
nsresult FromJwkBase64(const nsString& aBase64);
nsresult ToJwkBase64(nsString& aBase64);
SECItem* ToSECItem() const;
+ JSObject* ToUint8Array(JSContext* aCx) const;
bool GetBigIntValue(unsigned long& aRetVal);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_CryptoBuffer_h
--- a/dom/crypto/CryptoKey.cpp
+++ b/dom/crypto/CryptoKey.cpp
@@ -5,21 +5,22 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#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"
namespace mozilla {
namespace dom {
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CryptoKey, mGlobal, mAlgorithm)
+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
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
nsresult
@@ -85,20 +86,45 @@ CryptoKey::GetType(nsString& aRetVal) co
}
bool
CryptoKey::Extractable() const
{
return (mAttributes & EXTRACTABLE);
}
-KeyAlgorithm*
-CryptoKey::Algorithm() const
+void
+CryptoKey::GetAlgorithm(JSContext* cx, JS::MutableHandle<JSObject*> aRetVal,
+ ErrorResult& aRv) const
{
- return mAlgorithm;
+ bool converted = false;
+ JS::RootedValue val(cx);
+ switch (mAlgorithm.mType) {
+ case KeyAlgorithmProxy::AES:
+ converted = ToJSValue(cx, mAlgorithm.mAes, &val);
+ break;
+ case KeyAlgorithmProxy::HMAC:
+ converted = ToJSValue(cx, mAlgorithm.mHmac, &val);
+ break;
+ case KeyAlgorithmProxy::RSA: {
+ 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;
+ }
+ if (!converted) {
+ aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
+ return;
+ }
+
+ aRetVal.set(&val.toObject());
}
void
CryptoKey::GetUsages(nsTArray<nsString>& aRetVal) const
{
if (mAttributes & ENCRYPT) {
aRetVal.AppendElement(NS_LITERAL_STRING(WEBCRYPTO_KEY_USAGE_ENCRYPT));
}
@@ -120,16 +146,28 @@ CryptoKey::GetUsages(nsTArray<nsString>&
if (mAttributes & WRAPKEY) {
aRetVal.AppendElement(NS_LITERAL_STRING(WEBCRYPTO_KEY_USAGE_WRAPKEY));
}
if (mAttributes & UNWRAPKEY) {
aRetVal.AppendElement(NS_LITERAL_STRING(WEBCRYPTO_KEY_USAGE_UNWRAPKEY));
}
}
+KeyAlgorithmProxy&
+CryptoKey::Algorithm()
+{
+ return mAlgorithm;
+}
+
+const KeyAlgorithmProxy&
+CryptoKey::Algorithm() const
+{
+ return mAlgorithm;
+}
+
CryptoKey::KeyType
CryptoKey::GetKeyType() const
{
return static_cast<CryptoKey::KeyType>(mAttributes & TYPE_MASK);
}
nsresult
CryptoKey::SetType(const nsString& aType)
@@ -161,22 +199,16 @@ CryptoKey::SetExtractable(bool aExtracta
{
mAttributes &= CLEAR_EXTRACTABLE;
if (aExtractable) {
mAttributes |= EXTRACTABLE;
}
}
void
-CryptoKey::SetAlgorithm(KeyAlgorithm* aAlgorithm)
-{
- mAlgorithm = aAlgorithm;
-}
-
-void
CryptoKey::ClearUsages()
{
mAttributes &= CLEAR_USAGES;
}
nsresult
CryptoKey::AddUsage(const nsString& aUsage)
{
@@ -201,27 +233,52 @@ CryptoKey::AddUsageIntersecting(const ns
void
CryptoKey::AddUsage(CryptoKey::KeyUsage aUsage)
{
mAttributes |= aUsage;
}
bool
+CryptoKey::HasAnyUsage()
+{
+ return !!(mAttributes & USAGES_MASK);
+}
+
+bool
CryptoKey::HasUsage(CryptoKey::KeyUsage aUsage)
{
return !!(mAttributes & aUsage);
}
bool
CryptoKey::HasUsageOtherThan(uint32_t aUsages)
{
return !!(mAttributes & USAGES_MASK & ~aUsages);
}
+bool
+CryptoKey::IsRecognizedUsage(const nsString& aUsage)
+{
+ KeyUsage dummy;
+ nsresult rv = StringToUsage(aUsage, dummy);
+ return NS_SUCCEEDED(rv);
+}
+
+bool
+CryptoKey::AllUsagesRecognized(const Sequence<nsString>& aUsages)
+{
+ for (uint32_t i = 0; i < aUsages.Length(); ++i) {
+ if (!IsRecognizedUsage(aUsages[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
void CryptoKey::SetSymKey(const CryptoBuffer& aSymKey)
{
mSymKey = aSymKey;
}
void
CryptoKey::SetPrivateKey(SECKEYPrivateKey* aPrivateKey)
{
@@ -436,35 +493,31 @@ PrivateKeyFromPrivateKeyTemplate(SECItem
return SECKEY_CopyPrivateKey(privKey.get());
}
SECKEYPrivateKey*
CryptoKey::PrivateKeyFromJwk(const JsonWebKey& aJwk,
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
{
- if (!aJwk.mKty.WasPassed()) {
- return nullptr;
- }
-
CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY;
CK_BBOOL falseValue = CK_FALSE;
- if (aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_EC)) {
+ if (aJwk.mKty.EqualsLiteral(JWK_TYPE_EC)) {
// Verify that all of the required parameters are present
CryptoBuffer x, y, d;
if (!aJwk.mCrv.WasPassed() ||
!aJwk.mX.WasPassed() || NS_FAILED(x.FromJwkBase64(aJwk.mX.Value())) ||
!aJwk.mY.WasPassed() || NS_FAILED(y.FromJwkBase64(aJwk.mY.Value())) ||
!aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value()))) {
return nullptr;
}
nsString namedCurve;
- if (!NormalizeNamedCurveValue(aJwk.mCrv.Value(), namedCurve)) {
+ if (!NormalizeToken(aJwk.mCrv.Value(), namedCurve)) {
return nullptr;
}
ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
if (!arena) {
return nullptr;
}
@@ -499,17 +552,17 @@ CryptoKey::PrivateKeyFromJwk(const JsonW
{ CKA_EC_POINT, ecPoint->data, ecPoint->len },
{ CKA_VALUE, (void*) d.Elements(), d.Length() },
};
return PrivateKeyFromPrivateKeyTemplate(objID, keyTemplate,
PR_ARRAY_SIZE(keyTemplate));
}
- if (aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_RSA)) {
+ if (aJwk.mKty.EqualsLiteral(JWK_TYPE_RSA)) {
// Verify that all of the required parameters are present
CryptoBuffer n, e, d, p, q, dp, dq, qi;
if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) ||
!aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value())) ||
!aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value())) ||
!aJwk.mP.WasPassed() || NS_FAILED(p.FromJwkBase64(aJwk.mP.Value())) ||
!aJwk.mQ.WasPassed() || NS_FAILED(q.FromJwkBase64(aJwk.mQ.Value())) ||
!aJwk.mDp.WasPassed() || NS_FAILED(dp.FromJwkBase64(aJwk.mDp.Value())) ||
@@ -638,17 +691,17 @@ ECKeyToJwk(const PK11ObjectType aKeyType
memcpy(ecPointY->data, aPublicValue->data + 1 + flen, flen);
CryptoBuffer x, y;
if (!x.Assign(ecPointX) || NS_FAILED(x.ToJwkBase64(aRetVal.mX.Value())) ||
!y.Assign(ecPointY) || NS_FAILED(y.ToJwkBase64(aRetVal.mY.Value()))) {
return false;
}
- aRetVal.mKty.Construct(NS_LITERAL_STRING(JWK_TYPE_EC));
+ aRetVal.mKty = NS_LITERAL_STRING(JWK_TYPE_EC);
return true;
}
nsresult
CryptoKey::PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey,
JsonWebKey& aRetVal,
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
{
@@ -669,17 +722,17 @@ CryptoKey::PrivateKeyToJwk(SECKEYPrivate
!ReadAndEncodeAttribute(aPrivKey, CKA_PRIME_1, aRetVal.mP) ||
!ReadAndEncodeAttribute(aPrivKey, CKA_PRIME_2, aRetVal.mQ) ||
!ReadAndEncodeAttribute(aPrivKey, CKA_EXPONENT_1, aRetVal.mDp) ||
!ReadAndEncodeAttribute(aPrivKey, CKA_EXPONENT_2, aRetVal.mDq) ||
!ReadAndEncodeAttribute(aPrivKey, CKA_COEFFICIENT, aRetVal.mQi)) {
return NS_ERROR_DOM_OPERATION_ERR;
}
- aRetVal.mKty.Construct(NS_LITERAL_STRING(JWK_TYPE_RSA));
+ aRetVal.mKty = NS_LITERAL_STRING(JWK_TYPE_RSA);
return NS_OK;
}
case ecKey: {
// Read EC params.
ScopedSECItem params(::SECITEM_AllocItem(nullptr, nullptr, 0));
SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, aPrivKey,
CKA_EC_PARAMS, params);
if (rv != SECSuccess) {
@@ -711,21 +764,17 @@ CryptoKey::PrivateKeyToJwk(SECKEYPrivate
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
}
SECKEYPublicKey*
CryptoKey::PublicKeyFromJwk(const JsonWebKey& aJwk,
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
{
- if (!aJwk.mKty.WasPassed()) {
- return nullptr;
- }
-
- if (aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_RSA)) {
+ if (aJwk.mKty.EqualsLiteral(JWK_TYPE_RSA)) {
// Verify that all of the required parameters are present
CryptoBuffer n, e;
if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) ||
!aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value()))) {
return nullptr;
}
// Transcode to a DER RSAPublicKey structure
@@ -748,17 +797,17 @@ CryptoKey::PublicKeyFromJwk(const JsonWe
rsaPublicKeyTemplate));
if (!pkDer.get()) {
return nullptr;
}
return SECKEY_ImportDERPublicKey(pkDer.get(), CKK_RSA);
}
- if (aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_EC)) {
+ if (aJwk.mKty.EqualsLiteral(JWK_TYPE_EC)) {
// Verify that all of the required parameters are present
CryptoBuffer x, y;
if (!aJwk.mCrv.WasPassed() ||
!aJwk.mX.WasPassed() || NS_FAILED(x.FromJwkBase64(aJwk.mX.Value())) ||
!aJwk.mY.WasPassed() || NS_FAILED(y.FromJwkBase64(aJwk.mY.Value()))) {
return nullptr;
}
@@ -772,17 +821,17 @@ CryptoKey::PublicKeyFromJwk(const JsonWe
return nullptr;
}
key->keyType = ecKey;
key->pkcs11Slot = nullptr;
key->pkcs11ID = CK_INVALID_HANDLE;
nsString namedCurve;
- if (!NormalizeNamedCurveValue(aJwk.mCrv.Value(), namedCurve)) {
+ if (!NormalizeToken(aJwk.mCrv.Value(), namedCurve)) {
return nullptr;
}
// Create parameters.
SECItem* params = CreateECParamsForCurve(namedCurve, arena.get());
if (!params) {
return nullptr;
}
@@ -814,17 +863,17 @@ CryptoKey::PublicKeyToJwk(SECKEYPublicKe
if (!n.Assign(&aPubKey->u.rsa.modulus) ||
!e.Assign(&aPubKey->u.rsa.publicExponent) ||
NS_FAILED(n.ToJwkBase64(aRetVal.mN.Value())) ||
NS_FAILED(e.ToJwkBase64(aRetVal.mE.Value()))) {
return NS_ERROR_DOM_OPERATION_ERR;
}
- aRetVal.mKty.Construct(NS_LITERAL_STRING(JWK_TYPE_RSA));
+ aRetVal.mKty = NS_LITERAL_STRING(JWK_TYPE_RSA);
return NS_OK;
}
case ecKey:
if (!ECKeyToJwk(PK11_TypePubKey, aPubKey, &aPubKey->u.ec.DEREncodedParams,
&aPubKey->u.ec.publicValue, aRetVal)) {
return NS_ERROR_DOM_OPERATION_ERR;
}
return NS_OK;
@@ -852,54 +901,53 @@ CryptoKey::WriteStructuredClone(JSStruct
if (mPrivateKey) {
CryptoKey::PrivateKeyToPkcs8(mPrivateKey, priv, locker);
}
if (mPublicKey) {
CryptoKey::PublicKeyToSpki(mPublicKey, pub, locker);
}
- return JS_WriteUint32Pair(aWriter, mAttributes, 0) &&
+ return JS_WriteUint32Pair(aWriter, mAttributes, CRYPTOKEY_SC_VERSION) &&
WriteBuffer(aWriter, mSymKey) &&
WriteBuffer(aWriter, priv) &&
WriteBuffer(aWriter, pub) &&
- mAlgorithm->WriteStructuredClone(aWriter);
+ mAlgorithm.WriteStructuredClone(aWriter);
}
bool
CryptoKey::ReadStructuredClone(JSStructuredCloneReader* aReader)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return false;
}
- uint32_t zero;
+ uint32_t version;
CryptoBuffer sym, priv, pub;
- nsRefPtr<KeyAlgorithm> algorithm;
- bool read = JS_ReadUint32Pair(aReader, &mAttributes, &zero) &&
+ bool read = JS_ReadUint32Pair(aReader, &mAttributes, &version) &&
+ (version == CRYPTOKEY_SC_VERSION) &&
ReadBuffer(aReader, sym) &&
ReadBuffer(aReader, priv) &&
ReadBuffer(aReader, pub) &&
- (algorithm = KeyAlgorithm::Create(mGlobal, aReader));
+ mAlgorithm.ReadStructuredClone(aReader);
if (!read) {
return false;
}
if (sym.Length() > 0) {
mSymKey = sym;
}
if (priv.Length() > 0) {
mPrivateKey = CryptoKey::PrivateKeyFromPkcs8(priv, locker);
}
if (pub.Length() > 0) {
mPublicKey = CryptoKey::PublicKeyFromSpki(pub, locker);
}
- mAlgorithm = algorithm;
// Ensure that what we've read is consistent
// If the attributes indicate a key type, should have a key of that type
if (!((GetKeyType() == SECRET && mSymKey.Length() > 0) ||
(GetKeyType() == PRIVATE && mPrivateKey) ||
(GetKeyType() == PUBLIC && mPublicKey))) {
return false;
}
--- a/dom/crypto/CryptoKey.h
+++ b/dom/crypto/CryptoKey.h
@@ -9,21 +9,24 @@
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "nsIGlobalObject.h"
#include "nsNSSShutDown.h"
#include "pk11pub.h"
#include "keyhi.h"
#include "ScopedNSSTypes.h"
-#include "mozilla/dom/KeyAlgorithm.h"
+#include "mozilla/ErrorResult.h"
#include "mozilla/dom/CryptoBuffer.h"
+#include "mozilla/dom/KeyAlgorithmProxy.h"
#include "js/StructuredClone.h"
#include "js/TypeDecls.h"
+#define CRYPTOKEY_SC_VERSION 0x00000001
+
class nsIGlobalObject;
namespace mozilla {
namespace dom {
/*
The internal structure of keys is dictated by the need for cloning.
@@ -95,33 +98,38 @@ public:
return mGlobal;
}
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL methods
void GetType(nsString& aRetVal) const;
bool Extractable() const;
- KeyAlgorithm* Algorithm() const;
+ void GetAlgorithm(JSContext* cx, JS::MutableHandle<JSObject*> aRetVal,
+ ErrorResult& aRv) const;
void GetUsages(nsTArray<nsString>& aRetVal) const;
// The below methods are not exposed to JS, but C++ can use
// them to manipulate the object
+ KeyAlgorithmProxy& Algorithm();
+ const KeyAlgorithmProxy& Algorithm() const;
KeyType GetKeyType() const;
nsresult SetType(const nsString& aType);
void SetType(KeyType aType);
void SetExtractable(bool aExtractable);
- void SetAlgorithm(KeyAlgorithm* aAlgorithm);
void ClearUsages();
nsresult AddUsage(const nsString& aUsage);
nsresult AddUsageIntersecting(const nsString& aUsage, uint32_t aUsageMask);
void AddUsage(KeyUsage aUsage);
+ bool HasAnyUsage();
bool HasUsage(KeyUsage aUsage);
bool HasUsageOtherThan(uint32_t aUsages);
+ static bool IsRecognizedUsage(const nsString& aUsage);
+ static bool AllUsagesRecognized(const Sequence<nsString>& aUsages);
void SetSymKey(const CryptoBuffer& aSymKey);
void SetPrivateKey(SECKEYPrivateKey* aPrivateKey);
void SetPublicKey(SECKEYPublicKey* aPublicKey);
// Accessors for the keys themselves
// Note: GetPrivateKey and GetPublicKey return copies of the internal
// key handles, which the caller must free with SECKEY_DestroyPrivateKey
@@ -167,17 +175,17 @@ public:
bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const;
bool ReadStructuredClone(JSStructuredCloneReader* aReader);
private:
~CryptoKey();
nsRefPtr<nsIGlobalObject> mGlobal;
uint32_t mAttributes; // see above
- nsRefPtr<KeyAlgorithm> mAlgorithm;
+ KeyAlgorithmProxy mAlgorithm;
// Only one key handle should be set, according to the KeyType
CryptoBuffer mSymKey;
ScopedSECKEYPrivateKey mPrivateKey;
ScopedSECKEYPublicKey mPublicKey;
};
} // namespace dom
deleted file mode 100644
--- a/dom/crypto/CryptoKeyPair.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/CryptoKeyPair.h"
-#include "mozilla/dom/SubtleCryptoBinding.h"
-#include "nsContentUtils.h"
-
-namespace mozilla {
-namespace dom {
-
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CryptoKeyPair, mGlobal, mPublicKey, mPrivateKey)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(CryptoKeyPair)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(CryptoKeyPair)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CryptoKeyPair)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-JSObject*
-CryptoKeyPair::WrapObject(JSContext* aCx)
-{
- return CryptoKeyPairBinding::Wrap(aCx, this);
-}
-
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/crypto/CryptoKeyPair.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_CryptoKeyPair_h
-#define mozilla_dom_CryptoKeyPair_h
-
-#include "nsCycleCollectionParticipant.h"
-#include "nsWrapperCache.h"
-#include "nsIGlobalObject.h"
-#include "mozilla/dom/CryptoKey.h"
-#include "js/TypeDecls.h"
-
-namespace mozilla {
-namespace dom {
-
-class CryptoKeyPair MOZ_FINAL : public nsISupports,
- public nsWrapperCache
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CryptoKeyPair)
-
-public:
- explicit CryptoKeyPair(nsIGlobalObject* aGlobal)
- : mGlobal(aGlobal)
- , mPublicKey(new CryptoKey(aGlobal))
- , mPrivateKey(new CryptoKey(aGlobal))
- {
- SetIsDOMBinding();
- }
-
- nsIGlobalObject* GetParentObject() const
- {
- return mGlobal;
- }
-
- virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
-
- CryptoKey* PublicKey() const
- {
- return mPublicKey;
- }
-
- CryptoKey* PrivateKey() const
- {
- return mPrivateKey;
- }
-
-private:
- ~CryptoKeyPair() {}
-
- nsRefPtr<nsIGlobalObject> mGlobal;
- nsRefPtr<CryptoKey> mPublicKey;
- nsRefPtr<CryptoKey> mPrivateKey;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_CryptoKeyPair_h
deleted file mode 100644
--- a/dom/crypto/EcKeyAlgorithm.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/EcKeyAlgorithm.h"
-#include "mozilla/dom/SubtleCryptoBinding.h"
-#include "mozilla/dom/WebCryptoCommon.h"
-
-namespace mozilla {
-namespace dom {
-
-JSObject*
-EcKeyAlgorithm::WrapObject(JSContext* aCx)
-{
- return EcKeyAlgorithmBinding::Wrap(aCx, this);
-}
-
-bool
-EcKeyAlgorithm::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
-{
- return JS_WriteUint32Pair(aWriter, SCTAG_ECKEYALG, 0) &&
- WriteString(aWriter, mNamedCurve) &&
- WriteString(aWriter, mName);
-}
-
-KeyAlgorithm*
-EcKeyAlgorithm::Create(nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader)
-{
- nsString name;
- nsString namedCurve;
- bool read = ReadString(aReader, namedCurve) &&
- ReadString(aReader, name);
- if (!read) {
- return nullptr;
- }
-
- return new EcKeyAlgorithm(aGlobal, name, namedCurve);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/crypto/EcKeyAlgorithm.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_EcKeyAlgorithm_h
-#define mozilla_dom_EcKeyAlgorithm_h
-
-#include "mozilla/ErrorResult.h"
-#include "mozilla/dom/KeyAlgorithm.h"
-#include "js/TypeDecls.h"
-
-namespace mozilla {
-namespace dom {
-
-class EcKeyAlgorithm : public KeyAlgorithm
-{
-public:
- EcKeyAlgorithm(nsIGlobalObject* aGlobal,
- const nsString& aName,
- const nsString& aNamedCurve)
- : KeyAlgorithm(aGlobal, aName)
- , mNamedCurve(aNamedCurve)
- {}
-
- ~EcKeyAlgorithm()
- {}
-
- virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
-
- void GetNamedCurve(nsString& aRetVal) const
- {
- aRetVal.Assign(mNamedCurve);
- }
-
- virtual bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const MOZ_OVERRIDE;
- static KeyAlgorithm* Create(nsIGlobalObject* aGlobal,
- JSStructuredCloneReader* aReader);
-
-protected:
- nsString mNamedCurve;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_EcKeyAlgorithm_h
deleted file mode 100644
--- a/dom/crypto/HmacKeyAlgorithm.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/HmacKeyAlgorithm.h"
-#include "mozilla/dom/SubtleCryptoBinding.h"
-
-namespace mozilla {
-namespace dom {
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(HmacKeyAlgorithm, KeyAlgorithm, mHash)
-NS_IMPL_ADDREF_INHERITED(HmacKeyAlgorithm, KeyAlgorithm)
-NS_IMPL_RELEASE_INHERITED(HmacKeyAlgorithm, KeyAlgorithm)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HmacKeyAlgorithm)
-NS_INTERFACE_MAP_END_INHERITING(KeyAlgorithm)
-
-JSObject*
-HmacKeyAlgorithm::WrapObject(JSContext* aCx)
-{
- return HmacKeyAlgorithmBinding::Wrap(aCx, this);
-}
-
-nsString
-HmacKeyAlgorithm::ToJwkAlg() const
-{
- switch (mMechanism) {
- case CKM_SHA_1_HMAC: return NS_LITERAL_STRING(JWK_ALG_HS1);
- case CKM_SHA256_HMAC: return NS_LITERAL_STRING(JWK_ALG_HS256);
- case CKM_SHA384_HMAC: return NS_LITERAL_STRING(JWK_ALG_HS384);
- case CKM_SHA512_HMAC: return NS_LITERAL_STRING(JWK_ALG_HS512);
- }
- return nsString();
-}
-
-bool
-HmacKeyAlgorithm::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
-{
- nsString hashName;
- mHash->GetName(hashName);
- return JS_WriteUint32Pair(aWriter, SCTAG_HMACKEYALG, 0) &&
- JS_WriteUint32Pair(aWriter, mLength, 0) &&
- WriteString(aWriter, hashName) &&
- WriteString(aWriter, mName);
-}
-
-KeyAlgorithm*
-HmacKeyAlgorithm::Create(nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader)
-{
- uint32_t length, zero;
- nsString hash, name;
- bool read = JS_ReadUint32Pair(aReader, &length, &zero) &&
- ReadString(aReader, hash) &&
- ReadString(aReader, name);
- if (!read) {
- return nullptr;
- }
-
- return new HmacKeyAlgorithm(aGlobal, name, length, hash);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/crypto/HmacKeyAlgorithm.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_HmacKeyAlgorithm_h
-#define mozilla_dom_HmacKeyAlgorithm_h
-
-#include "nsCycleCollectionParticipant.h"
-#include "nsWrapperCache.h"
-#include "nsAutoPtr.h"
-#include "mozilla/dom/KeyAlgorithm.h"
-#include "mozilla/dom/WebCryptoCommon.h"
-#include "js/TypeDecls.h"
-
-namespace mozilla {
-namespace dom {
-
-class HmacKeyAlgorithm MOZ_FINAL : public KeyAlgorithm
-{
-public:
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HmacKeyAlgorithm, KeyAlgorithm)
-
- HmacKeyAlgorithm(nsIGlobalObject* aGlobal,
- const nsString& aName,
- uint32_t aLength,
- const nsString& aHash)
- : KeyAlgorithm(aGlobal, aName)
- , mHash(new KeyAlgorithm(aGlobal, aHash))
- , mLength(aLength)
- {
- switch (mHash->Mechanism()) {
- case CKM_SHA_1: mMechanism = CKM_SHA_1_HMAC; break;
- case CKM_SHA256: mMechanism = CKM_SHA256_HMAC; break;
- case CKM_SHA384: mMechanism = CKM_SHA384_HMAC; break;
- case CKM_SHA512: mMechanism = CKM_SHA512_HMAC; break;
- default: mMechanism = UNKNOWN_CK_MECHANISM; break;
- }
- }
-
- virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
-
- KeyAlgorithm* Hash() const
- {
- return mHash;
- }
-
- uint32_t Length() const
- {
- return mLength;
- }
-
- virtual nsString ToJwkAlg() const MOZ_OVERRIDE;
-
- virtual bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const MOZ_OVERRIDE;
- static KeyAlgorithm* Create(nsIGlobalObject* aGlobal,
- JSStructuredCloneReader* aReader);
-
-protected:
- ~HmacKeyAlgorithm()
- {}
-
- nsRefPtr<KeyAlgorithm> mHash;
- uint32_t mLength;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_HmacKeyAlgorithm_h
deleted file mode 100644
--- a/dom/crypto/KeyAlgorithm.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/KeyAlgorithm.h"
-#include "mozilla/dom/WebCryptoCommon.h"
-#include "mozilla/dom/AesKeyAlgorithm.h"
-#include "mozilla/dom/EcKeyAlgorithm.h"
-#include "mozilla/dom/HmacKeyAlgorithm.h"
-#include "mozilla/dom/RsaKeyAlgorithm.h"
-#include "mozilla/dom/RsaHashedKeyAlgorithm.h"
-#include "mozilla/dom/SubtleCryptoBinding.h"
-#include "mozilla/dom/WebCryptoCommon.h"
-
-namespace mozilla {
-namespace dom {
-
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(KeyAlgorithm, mGlobal)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(KeyAlgorithm)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(KeyAlgorithm)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(KeyAlgorithm)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-KeyAlgorithm::KeyAlgorithm(nsIGlobalObject* aGlobal, const nsString& aName)
- : mGlobal(aGlobal)
- , mName(aName)
-{
- SetIsDOMBinding();
-
- // Set mechanism based on algorithm name
- mMechanism = MapAlgorithmNameToMechanism(aName);
-
- // HMAC not handled here, since it requires extra info
-}
-
-KeyAlgorithm::~KeyAlgorithm()
-{
-}
-
-JSObject*
-KeyAlgorithm::WrapObject(JSContext* aCx)
-{
- return KeyAlgorithmBinding::Wrap(aCx, this);
-}
-
-nsString
-KeyAlgorithm::ToJwkAlg() const
-{
- return nsString();
-}
-
-void
-KeyAlgorithm::GetName(nsString& aRetVal) const
-{
- aRetVal.Assign(mName);
-}
-
-bool
-KeyAlgorithm::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
-{
- return WriteString(aWriter, mName);
-}
-
-KeyAlgorithm*
-KeyAlgorithm::Create(nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader)
-{
- uint32_t tag, zero;
- bool read = JS_ReadUint32Pair( aReader, &tag, &zero );
- if (!read) {
- return nullptr;
- }
-
- KeyAlgorithm* algorithm = nullptr;
- switch (tag) {
- case SCTAG_KEYALG: {
- nsString name;
- read = ReadString(aReader, name);
- if (!read) {
- return nullptr;
- }
- algorithm = new KeyAlgorithm(aGlobal, name);
- break;
- }
- case SCTAG_AESKEYALG: {
- algorithm = AesKeyAlgorithm::Create(aGlobal, aReader);
- break;
- }
- case SCTAG_ECKEYALG: {
- algorithm = EcKeyAlgorithm::Create(aGlobal, aReader);
- break;
- }
- case SCTAG_HMACKEYALG: {
- algorithm = HmacKeyAlgorithm::Create(aGlobal, aReader);
- break;
- }
- case SCTAG_RSAKEYALG: {
- algorithm = RsaKeyAlgorithm::Create(aGlobal, aReader);
- break;
- }
- case SCTAG_RSAHASHEDKEYALG: {
- algorithm = RsaHashedKeyAlgorithm::Create(aGlobal, aReader);
- break;
- }
- // No default, algorithm is already nullptr
- }
-
- return algorithm;
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/crypto/KeyAlgorithm.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_KeyAlgorithm_h
-#define mozilla_dom_KeyAlgorithm_h
-
-#include "nsCycleCollectionParticipant.h"
-#include "nsIGlobalObject.h"
-#include "nsWrapperCache.h"
-#include "pk11pub.h"
-#include "mozilla/dom/CryptoBuffer.h"
-#include "js/StructuredClone.h"
-#include "js/TypeDecls.h"
-
-namespace mozilla {
-namespace dom {
-
-class CryptoKey;
-class KeyAlgorithm;
-
-enum KeyAlgorithmStructuredCloneTags {
- SCTAG_KEYALG,
- SCTAG_AESKEYALG,
- SCTAG_ECKEYALG,
- SCTAG_HMACKEYALG,
- SCTAG_RSAKEYALG,
- SCTAG_RSAHASHEDKEYALG
-};
-
-}
-
-namespace dom {
-
-class KeyAlgorithm : public nsISupports,
- public nsWrapperCache
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(KeyAlgorithm)
-
-public:
- KeyAlgorithm(nsIGlobalObject* aGlobal, const nsString& aName);
-
- nsIGlobalObject* GetParentObject() const
- {
- return mGlobal;
- }
-
- virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
-
- void GetName(nsString& aRetVal) const;
-
- virtual nsString ToJwkAlg() const;
-
- // Structured clone support methods
- virtual bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const;
- static KeyAlgorithm* Create(nsIGlobalObject* aGlobal,
- JSStructuredCloneReader* aReader);
-
- // Helper method to look up NSS methods
- // Sub-classes should assign mMechanism on constructor
- CK_MECHANISM_TYPE Mechanism() const {
- return mMechanism;
- }
-
-protected:
- virtual ~KeyAlgorithm();
-
- nsRefPtr<nsIGlobalObject> mGlobal;
- nsString mName;
- CK_MECHANISM_TYPE mMechanism;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_KeyAlgorithm_h
new file mode 100644
--- /dev/null
+++ b/dom/crypto/KeyAlgorithmProxy.cpp
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/KeyAlgorithmProxy.h"
+#include "mozilla/dom/WebCryptoCommon.h"
+
+namespace mozilla {
+namespace dom {
+
+bool
+KeyAlgorithmProxy::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
+{
+ if (!WriteString(aWriter, mName) ||
+ !JS_WriteUint32Pair(aWriter, mType, KEY_ALGORITHM_SC_VERSION)) {
+ return false;
+ }
+
+ switch (mType) {
+ case AES:
+ return JS_WriteUint32Pair(aWriter, mAes.mLength, 0);
+ case HMAC:
+ return JS_WriteUint32Pair(aWriter, mHmac.mLength, 0) &&
+ 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);
+ }
+
+ return false;
+}
+
+bool
+KeyAlgorithmProxy::ReadStructuredClone(JSStructuredCloneReader* aReader)
+{
+ uint32_t type, version, dummy;
+ if (!ReadString(aReader, mName) ||
+ !JS_ReadUint32Pair(aReader, &type, &version)) {
+ return false;
+ }
+
+ if (version != KEY_ALGORITHM_SC_VERSION) {
+ return false;
+ }
+
+ mType = (KeyAlgorithmType) type;
+ switch (mType) {
+ case AES: {
+ uint32_t length;
+ if (!JS_ReadUint32Pair(aReader, &length, &dummy)) {
+ return false;
+ }
+
+ mAes.mLength = length;
+ mAes.mName = mName;
+ return true;
+ }
+ case HMAC: {
+ if (!JS_ReadUint32Pair(aReader, &mHmac.mLength, &dummy) ||
+ !ReadString(aReader, mHmac.mHash.mName)) {
+ return false;
+ }
+
+ mHmac.mName = mName;
+ return true;
+ }
+ case RSA: {
+ uint32_t modulusLength;
+ nsString hashName;
+ if (!JS_ReadUint32Pair(aReader, &modulusLength, &dummy) ||
+ !ReadBuffer(aReader, mRsa.mPublicExponent) ||
+ !ReadString(aReader, mRsa.mHash.mName)) {
+ return false;
+ }
+
+ mRsa.mModulusLength = modulusLength;
+ mRsa.mName = mName;
+ return true;
+ }
+ case EC: {
+ nsString namedCurve;
+ if (!ReadString(aReader, mEc.mNamedCurve)) {
+ return false;
+ }
+
+ mEc.mName = mName;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+CK_MECHANISM_TYPE
+KeyAlgorithmProxy::Mechanism() const
+{
+ if (mType == HMAC) {
+ return GetMechanism(mHmac);
+ }
+ return MapAlgorithmNameToMechanism(mName);
+}
+
+nsString
+KeyAlgorithmProxy::JwkAlg() const
+{
+ if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
+ switch (mAes.mLength) {
+ case 128: return NS_LITERAL_STRING(JWK_ALG_A128CBC);
+ case 192: return NS_LITERAL_STRING(JWK_ALG_A192CBC);
+ case 256: return NS_LITERAL_STRING(JWK_ALG_A256CBC);
+ }
+ }
+
+ if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
+ switch (mAes.mLength) {
+ case 128: return NS_LITERAL_STRING(JWK_ALG_A128CTR);
+ case 192: return NS_LITERAL_STRING(JWK_ALG_A192CTR);
+ case 256: return NS_LITERAL_STRING(JWK_ALG_A256CTR);
+ }
+ }
+
+ if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
+ switch (mAes.mLength) {
+ case 128: return NS_LITERAL_STRING(JWK_ALG_A128GCM);
+ case 192: return NS_LITERAL_STRING(JWK_ALG_A192GCM);
+ case 256: return NS_LITERAL_STRING(JWK_ALG_A256GCM);
+ }
+ }
+
+ if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
+ switch (mAes.mLength) {
+ case 128: return NS_LITERAL_STRING(JWK_ALG_A128KW);
+ case 192: return NS_LITERAL_STRING(JWK_ALG_A192KW);
+ case 256: return NS_LITERAL_STRING(JWK_ALG_A256KW);
+ }
+ }
+
+ if (mName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
+ nsString hashName = mHmac.mHash.mName;
+ if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
+ return NS_LITERAL_STRING(JWK_ALG_HS1);
+ } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
+ return NS_LITERAL_STRING(JWK_ALG_HS256);
+ } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
+ return NS_LITERAL_STRING(JWK_ALG_HS384);
+ } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
+ return NS_LITERAL_STRING(JWK_ALG_HS512);
+ }
+ }
+
+ if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
+ nsString hashName = mRsa.mHash.mName;
+ if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
+ return NS_LITERAL_STRING(JWK_ALG_RS1);
+ } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
+ return NS_LITERAL_STRING(JWK_ALG_RS256);
+ } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
+ return NS_LITERAL_STRING(JWK_ALG_RS384);
+ } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
+ return NS_LITERAL_STRING(JWK_ALG_RS512);
+ }
+ }
+
+ if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
+ nsString hashName = mRsa.mHash.mName;
+ if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
+ return NS_LITERAL_STRING(JWK_ALG_RSA_OAEP);
+ } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
+ return NS_LITERAL_STRING(JWK_ALG_RSA_OAEP_256);
+ } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
+ return NS_LITERAL_STRING(JWK_ALG_RSA_OAEP_384);
+ } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
+ return NS_LITERAL_STRING(JWK_ALG_RSA_OAEP_512);
+ }
+ }
+
+ return nsString();
+}
+
+CK_MECHANISM_TYPE
+KeyAlgorithmProxy::GetMechanism(const KeyAlgorithm& aAlgorithm)
+{
+ // For everything but HMAC, the name determines the mechanism
+ // HMAC is handled by the specialization below
+ return MapAlgorithmNameToMechanism(aAlgorithm.mName);
+}
+
+CK_MECHANISM_TYPE
+KeyAlgorithmProxy::GetMechanism(const HmacKeyAlgorithm& aAlgorithm)
+{
+ // The use of HmacKeyAlgorithm doesn't completely prevent this
+ // method from being called with dictionaries that don't really
+ // represent HMAC key algorithms.
+ MOZ_ASSERT(aAlgorithm.mName.EqualsLiteral(WEBCRYPTO_ALG_HMAC));
+
+ CK_MECHANISM_TYPE hashMech;
+ hashMech = MapAlgorithmNameToMechanism(aAlgorithm.mHash.mName);
+
+ switch (hashMech) {
+ case CKM_SHA_1: return CKM_SHA_1_HMAC;
+ case CKM_SHA256: return CKM_SHA256_HMAC;
+ case CKM_SHA384: return CKM_SHA384_HMAC;
+ case CKM_SHA512: return CKM_SHA512_HMAC;
+ }
+ return UNKNOWN_CK_MECHANISM;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/crypto/KeyAlgorithmProxy.h
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_KeyAlgorithmProxy_h
+#define mozilla_dom_KeyAlgorithmProxy_h
+
+#include "pk11pub.h"
+#include "js/StructuredClone.h"
+#include "mozilla/dom/KeyAlgorithmBinding.h"
+#include "mozilla/dom/WebCryptoCommon.h"
+
+#define KEY_ALGORITHM_SC_VERSION 0x00000001
+
+namespace mozilla {
+namespace dom {
+
+// A heap-safe variant of RsaHashedKeyAlgorithm
+// The only difference is that it uses CryptoBuffer instead of Uint8Array
+struct RsaHashedKeyAlgorithmStorage {
+ nsString mName;
+ KeyAlgorithm mHash;
+ uint16_t mModulusLength;
+ CryptoBuffer mPublicExponent;
+
+ void
+ ToKeyAlgorithm(JSContext* aCx, RsaHashedKeyAlgorithm& aRsa) const
+ {
+ aRsa.mName = mName;
+ aRsa.mModulusLength = mModulusLength;
+ aRsa.mHash.mName = mHash.mName;
+ aRsa.mPublicExponent.Init(mPublicExponent.ToUint8Array(aCx));
+ aRsa.mPublicExponent.ComputeLengthAndData();
+ }
+};
+
+// This class encapuslates a KeyAlgorithm object, and adds several
+// methods that make WebCrypto operations simpler.
+struct KeyAlgorithmProxy
+{
+ enum KeyAlgorithmType {
+ AES,
+ HMAC,
+ RSA,
+ 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;
+
+ // 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;
+
+ // And in static form for calling on raw KeyAlgorithm dictionaries
+ static CK_MECHANISM_TYPE GetMechanism(const KeyAlgorithm& aAlgorithm);
+ static CK_MECHANISM_TYPE GetMechanism(const HmacKeyAlgorithm& aAlgorithm);
+ static nsString GetJwkAlg(const KeyAlgorithm& aAlgorithm);
+
+ // Construction of the various algorithm types
+ void
+ MakeAes(const nsString& aName, uint32_t aLength)
+ {
+ mType = AES;
+ mName = aName;
+ mAes.mName = aName;
+ mAes.mLength = aLength;
+ }
+
+ void
+ MakeHmac(uint32_t aLength, const nsString& aHashName)
+ {
+ mType = HMAC;
+ mName = NS_LITERAL_STRING(WEBCRYPTO_ALG_HMAC);
+ mHmac.mName = NS_LITERAL_STRING(WEBCRYPTO_ALG_HMAC);
+ mHmac.mLength = aLength;
+ mHmac.mHash.mName = aHashName;
+ }
+
+ void
+ MakeRsa(const nsString& aName, uint32_t aModulusLength,
+ const CryptoBuffer& aPublicExponent, const nsString& aHashName)
+ {
+ mType = RSA;
+ mName = aName;
+ mRsa.mName = aName;
+ mRsa.mModulusLength = aModulusLength;
+ mRsa.mHash.mName = aHashName;
+ mRsa.mPublicExponent.Assign(aPublicExponent);
+ }
+
+ void
+ MakeEc(const nsString& aName, const nsString& aNamedCurve)
+ {
+ mType = EC;
+ mName = aName;
+ mEc.mName = aName;
+ mEc.mNamedCurve = aNamedCurve;
+ }
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_KeyAlgorithmProxy_h
deleted file mode 100644
--- a/dom/crypto/RsaHashedKeyAlgorithm.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/RsaHashedKeyAlgorithm.h"
-#include "mozilla/dom/SubtleCryptoBinding.h"
-#include "mozilla/dom/WebCryptoCommon.h"
-
-namespace mozilla {
-namespace dom {
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(RsaHashedKeyAlgorithm, RsaKeyAlgorithm, mHash)
-NS_IMPL_ADDREF_INHERITED(RsaHashedKeyAlgorithm, RsaKeyAlgorithm)
-NS_IMPL_RELEASE_INHERITED(RsaHashedKeyAlgorithm, RsaKeyAlgorithm)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RsaHashedKeyAlgorithm)
-NS_INTERFACE_MAP_END_INHERITING(RsaKeyAlgorithm)
-
-JSObject*
-RsaHashedKeyAlgorithm::WrapObject(JSContext* aCx)
-{
- return RsaHashedKeyAlgorithmBinding::Wrap(aCx, this);
-}
-
-nsString
-RsaHashedKeyAlgorithm::ToJwkAlg() const
-{
- if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
- switch (mHash->Mechanism()) {
- case CKM_SHA_1: return NS_LITERAL_STRING(JWK_ALG_RS1);
- case CKM_SHA256: return NS_LITERAL_STRING(JWK_ALG_RS256);
- case CKM_SHA384: return NS_LITERAL_STRING(JWK_ALG_RS384);
- case CKM_SHA512: return NS_LITERAL_STRING(JWK_ALG_RS512);
- }
- }
-
- if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
- switch(mHash->Mechanism()) {
- case CKM_SHA_1: return NS_LITERAL_STRING(JWK_ALG_RSA_OAEP);
- case CKM_SHA256: return NS_LITERAL_STRING(JWK_ALG_RSA_OAEP_256);
- case CKM_SHA384: return NS_LITERAL_STRING(JWK_ALG_RSA_OAEP_256);
- case CKM_SHA512: return NS_LITERAL_STRING(JWK_ALG_RSA_OAEP_512);
- }
- }
-
- return nsString();
-}
-
-bool
-RsaHashedKeyAlgorithm::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
-{
- nsString hashName;
- mHash->GetName(hashName);
- return JS_WriteUint32Pair(aWriter, SCTAG_RSAHASHEDKEYALG, 0) &&
- JS_WriteUint32Pair(aWriter, mModulusLength, 0) &&
- WriteBuffer(aWriter, mPublicExponent) &&
- WriteString(aWriter, hashName) &&
- WriteString(aWriter, mName);
-}
-
-KeyAlgorithm*
-RsaHashedKeyAlgorithm::Create(nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader) {
- uint32_t modulusLength, zero;
- CryptoBuffer publicExponent;
- nsString name, hash;
-
- bool read = JS_ReadUint32Pair(aReader, &modulusLength, &zero) &&
- ReadBuffer(aReader, publicExponent) &&
- ReadString(aReader, hash) &&
- ReadString(aReader, name);
- if (!read) {
- return nullptr;
- }
-
- return new RsaHashedKeyAlgorithm(aGlobal, name, modulusLength, publicExponent, hash);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/crypto/RsaHashedKeyAlgorithm.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_RsaHashedKeyAlgorithm_h
-#define mozilla_dom_RsaHashedKeyAlgorithm_h
-
-#include "nsAutoPtr.h"
-#include "mozilla/dom/RsaKeyAlgorithm.h"
-
-namespace mozilla {
-namespace dom {
-
-class RsaHashedKeyAlgorithm MOZ_FINAL : public RsaKeyAlgorithm
-{
-public:
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(RsaHashedKeyAlgorithm, RsaKeyAlgorithm)
-
- RsaHashedKeyAlgorithm(nsIGlobalObject* aGlobal,
- const nsString& aName,
- uint32_t aModulusLength,
- const CryptoBuffer& aPublicExponent,
- const nsString& aHashName)
- : RsaKeyAlgorithm(aGlobal, aName, aModulusLength, aPublicExponent)
- , mHash(new KeyAlgorithm(aGlobal, aHashName))
- {}
-
- virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
-
- virtual nsString ToJwkAlg() const MOZ_OVERRIDE;
-
- KeyAlgorithm* Hash() const
- {
- return mHash;
- }
-
- virtual bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const MOZ_OVERRIDE;
- static KeyAlgorithm* Create(nsIGlobalObject* aGlobal,
- JSStructuredCloneReader* aReader);
-
-private:
- ~RsaHashedKeyAlgorithm() {}
-
- nsRefPtr<KeyAlgorithm> mHash;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_RsaHashedKeyAlgorithm_h
deleted file mode 100644
--- a/dom/crypto/RsaKeyAlgorithm.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/RsaKeyAlgorithm.h"
-#include "mozilla/dom/SubtleCryptoBinding.h"
-#include "mozilla/dom/WebCryptoCommon.h"
-
-namespace mozilla {
-namespace dom {
-
-JSObject*
-RsaKeyAlgorithm::WrapObject(JSContext* aCx)
-{
- return RsaKeyAlgorithmBinding::Wrap(aCx, this);
-}
-
-bool
-RsaKeyAlgorithm::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
-{
- return JS_WriteUint32Pair(aWriter, SCTAG_RSAKEYALG, 0) &&
- JS_WriteUint32Pair(aWriter, mModulusLength, 0) &&
- WriteBuffer(aWriter, mPublicExponent) &&
- WriteString(aWriter, mName);
-}
-
-KeyAlgorithm*
-RsaKeyAlgorithm::Create(nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader)
-{
- uint32_t modulusLength, zero;
- CryptoBuffer publicExponent;
- nsString name;
- bool read = JS_ReadUint32Pair(aReader, &modulusLength, &zero) &&
- ReadBuffer(aReader, publicExponent) &&
- ReadString(aReader, name);
- if (!read) {
- return nullptr;
- }
-
- return new RsaKeyAlgorithm(aGlobal, name, modulusLength, publicExponent);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/crypto/RsaKeyAlgorithm.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_RsaKeyAlgorithm_h
-#define mozilla_dom_RsaKeyAlgorithm_h
-
-#include "mozilla/ErrorResult.h"
-#include "mozilla/dom/KeyAlgorithm.h"
-#include "js/TypeDecls.h"
-
-namespace mozilla {
-namespace dom {
-
-class RsaKeyAlgorithm : public KeyAlgorithm
-{
-public:
- RsaKeyAlgorithm(nsIGlobalObject* aGlobal,
- const nsString& aName,
- uint32_t aModulusLength,
- const CryptoBuffer& aPublicExponent)
- : KeyAlgorithm(aGlobal, aName)
- , mModulusLength(aModulusLength)
- , mPublicExponent(aPublicExponent)
- {}
-
- ~RsaKeyAlgorithm()
- {}
-
- virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
-
- uint32_t ModulusLength() const
- {
- return mModulusLength;
- }
-
- void GetPublicExponent(JSContext* cx, JS::MutableHandle<JSObject*> aRetval,
- ErrorResult& aError) const
- {
- TypedArrayCreator<Uint8Array> creator(mPublicExponent);
- JSObject* retval = creator.Create(cx);
- if (!retval) {
- aError.Throw(NS_ERROR_OUT_OF_MEMORY);
- } else {
- aRetval.set(retval);
- }
- }
-
- virtual bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const MOZ_OVERRIDE;
- static KeyAlgorithm* Create(nsIGlobalObject* aGlobal,
- JSStructuredCloneReader* aReader);
-
-protected:
- uint32_t mModulusLength;
- CryptoBuffer mPublicExponent;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_RsaKeyAlgorithm_h
--- a/dom/crypto/WebCryptoCommon.h
+++ b/dom/crypto/WebCryptoCommon.h
@@ -4,31 +4,31 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_WebCryptoCommon_h
#define mozilla_dom_WebCryptoCommon_h
#include "pk11pub.h"
#include "nsString.h"
+#include "nsContentUtils.h"
#include "mozilla/dom/CryptoBuffer.h"
#include "js/StructuredClone.h"
// WebCrypto algorithm names
#define WEBCRYPTO_ALG_AES_CBC "AES-CBC"
#define WEBCRYPTO_ALG_AES_CTR "AES-CTR"
#define WEBCRYPTO_ALG_AES_GCM "AES-GCM"
#define WEBCRYPTO_ALG_AES_KW "AES-KW"
#define WEBCRYPTO_ALG_SHA1 "SHA-1"
#define WEBCRYPTO_ALG_SHA256 "SHA-256"
#define WEBCRYPTO_ALG_SHA384 "SHA-384"
#define WEBCRYPTO_ALG_SHA512 "SHA-512"
#define WEBCRYPTO_ALG_HMAC "HMAC"
#define WEBCRYPTO_ALG_PBKDF2 "PBKDF2"
-#define WEBCRYPTO_ALG_RSAES_PKCS1 "RSAES-PKCS1-v1_5"
#define WEBCRYPTO_ALG_RSASSA_PKCS1 "RSASSA-PKCS1-v1_5"
#define WEBCRYPTO_ALG_RSA_OAEP "RSA-OAEP"
#define WEBCRYPTO_ALG_ECDH "ECDH"
// WebCrypto key formats
#define WEBCRYPTO_KEY_FORMAT_RAW "raw"
#define WEBCRYPTO_KEY_FORMAT_PKCS8 "pkcs8"
#define WEBCRYPTO_KEY_FORMAT_SPKI "spki"
@@ -176,37 +176,66 @@ MapAlgorithmNameToMechanism(const nsStri
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
mechanism = CKM_SHA256;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
mechanism = CKM_SHA384;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
mechanism = CKM_SHA512;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
mechanism = CKM_PKCS5_PBKD2;
- } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
- mechanism = CKM_RSA_PKCS;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
mechanism = CKM_RSA_PKCS;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
mechanism = CKM_RSA_PKCS_OAEP;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
mechanism = CKM_ECDH1_DERIVE;
}
return mechanism;
}
+#define NORMALIZED_EQUALS(aTest, aConst) \
+ nsContentUtils::EqualsIgnoreASCIICase(aTest, NS_LITERAL_STRING(aConst))
+
inline bool
-NormalizeNamedCurveValue(const nsString& aNamedCurve, nsString& aDest)
+NormalizeToken(const nsString& aName, nsString& aDest)
{
- if (aNamedCurve.EqualsIgnoreCase(WEBCRYPTO_NAMED_CURVE_P256)) {
+ // Algorithm names
+ if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_CBC)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_AES_CBC);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_CTR)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_AES_CTR);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_GCM)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_AES_GCM);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_KW)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_AES_KW);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA1)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_SHA1);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA256)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_SHA256);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA384)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_SHA384);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA512)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_SHA512);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_HMAC)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_HMAC);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_PBKDF2)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_PBKDF2);
+ } 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);
+ // Named curve values
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P256)) {
aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P256);
- } else if (aNamedCurve.EqualsIgnoreCase(WEBCRYPTO_NAMED_CURVE_P384)) {
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P384)) {
aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P384);
- } else if (aNamedCurve.EqualsIgnoreCase(WEBCRYPTO_NAMED_CURVE_P521)) {
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P521)) {
aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P521);
} else {
return false;
}
return true;
}
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -6,26 +6,19 @@
#include "pk11pub.h"
#include "cryptohi.h"
#include "secerr.h"
#include "ScopedNSSTypes.h"
#include "jsapi.h"
#include "mozilla/Telemetry.h"
-#include "mozilla/dom/AesKeyAlgorithm.h"
#include "mozilla/dom/CryptoBuffer.h"
#include "mozilla/dom/CryptoKey.h"
-#include "mozilla/dom/CryptoKeyPair.h"
-#include "mozilla/dom/EcKeyAlgorithm.h"
-#include "mozilla/dom/HmacKeyAlgorithm.h"
-#include "mozilla/dom/KeyAlgorithm.h"
-#include "mozilla/dom/RsaHashedKeyAlgorithm.h"
-#include "mozilla/dom/RsaKeyAlgorithm.h"
-#include "mozilla/dom/ToJSValue.h"
+#include "mozilla/dom/KeyAlgorithmProxy.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/WebCryptoCommon.h"
#include "mozilla/dom/WebCryptoTask.h"
namespace mozilla {
namespace dom {
// Pre-defined identifiers for telemetry histograms
@@ -49,17 +42,17 @@ enum TelemetryAlgorithm {
// Please make additions at the end of the list,
// to preserve comparability of histograms over time
TA_UNKNOWN = 0,
// encrypt / decrypt
TA_AES_CBC = 1,
TA_AES_CFB = 2,
TA_AES_CTR = 3,
TA_AES_GCM = 4,
- TA_RSAES_PKCS1 = 5,
+ TA_RSAES_PKCS1 = 5, // NB: This algorithm has been removed
TA_RSA_OAEP = 6,
// sign/verify
TA_RSASSA_PKCS1 = 7,
TA_RSA_PSS = 8,
TA_HMAC_SHA_1 = 9,
TA_HMAC_SHA_224 = 10,
TA_HMAC_SHA_256 = 11,
TA_HMAC_SHA_384 = 12,
@@ -94,19 +87,17 @@ enum TelemetryAlgorithm {
#define ATTEMPT_BUFFER_ASSIGN(dst, src) \
if (!dst.Assign(src)) { \
return NS_ERROR_DOM_UNKNOWN_ERR; \
}
// Safety check for algorithms that use keys, suitable for constructors
#define CHECK_KEY_ALGORITHM(keyAlg, algName) \
{ \
- nsString keyAlgName; \
- keyAlg->GetName(keyAlgName); \
- if (!keyAlgName.EqualsLiteral(algName)) { \
+ if (!NORMALIZED_EQUALS(keyAlg.mName, algName)) { \
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR; \
return; \
} \
}
class ClearException
{
public:
@@ -132,52 +123,25 @@ GetAlgorithmName(JSContext* aCx, const O
if (aAlgorithm.IsString()) {
// If string, then treat as algorithm name
aName.Assign(aAlgorithm.GetAsString());
} else {
// Coerce to algorithm and extract name
JS::RootedValue value(aCx, JS::ObjectValue(*aAlgorithm.GetAsObject()));
Algorithm alg;
- if (!alg.Init(aCx, value) || !alg.mName.WasPassed()) {
+ if (!alg.Init(aCx, value)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
- aName.Assign(alg.mName.Value());
+ aName = alg.mName;
}
- // Normalize algorithm names.
- if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_AES_CBC)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_AES_CBC);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_AES_CTR)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_AES_CTR);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_AES_GCM)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_AES_GCM);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_AES_KW)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_AES_KW);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_SHA1)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_SHA1);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_SHA256)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_SHA256);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_SHA384)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_SHA384);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_SHA512)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_SHA512);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_HMAC)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_HMAC);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_PBKDF2)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_PBKDF2);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_RSAES_PKCS1)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_RSAES_PKCS1);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_RSA_OAEP)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_RSA_OAEP);
- } else if (aName.EqualsIgnoreCase(WEBCRYPTO_ALG_ECDH)) {
- aName.AssignLiteral(WEBCRYPTO_ALG_ECDH);
+ if (!NormalizeToken(aName, aName)) {
+ return NS_ERROR_DOM_SYNTAX_ERR;
}
return NS_OK;
}
template<class T, class OOS>
static nsresult
Coerce(JSContext* aCx, T& aTarget, const OOS& aAlgorithm)
@@ -225,47 +189,46 @@ GetKeyLengthForAlgorithm(JSContext* aCx,
}
// Read AES key length from given algorithm object.
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)) {
RootedDictionary<AesDerivedKeyParams> params(aCx);
- if (NS_FAILED(Coerce(aCx, params, aAlgorithm)) ||
- !params.mLength.WasPassed()) {
+ if (NS_FAILED(Coerce(aCx, params, aAlgorithm))) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
- size_t length = params.mLength.Value();
- if (length != 128 && length != 192 && length != 256) {
+ if (params.mLength != 128 &&
+ params.mLength != 192 &&
+ params.mLength != 256) {
return NS_ERROR_DOM_DATA_ERR;
}
- aLength = length;
+ aLength = params.mLength;
return NS_OK;
}
// Read HMAC key length from given algorithm object or
// determine key length as the block size of the given hash.
if (algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
RootedDictionary<HmacDerivedKeyParams> params(aCx);
- if (NS_FAILED(Coerce(aCx, params, aAlgorithm)) ||
- !params.mHash.WasPassed()) {
+ if (NS_FAILED(Coerce(aCx, params, aAlgorithm))) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
// Return the passed length, if any.
if (params.mLength.WasPassed()) {
aLength = params.mLength.Value();
return NS_OK;
}
nsString hashName;
- if (NS_FAILED(GetAlgorithmName(aCx, params.mHash.Value(), hashName))) {
+ if (NS_FAILED(GetAlgorithmName(aCx, params.mHash, hashName))) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
// Return the given hash algorithm's block size as the key length.
size_t length = MapHashAlgorithmNameToBlockSize(hashName);
if (length == 0) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
@@ -313,17 +276,16 @@ CloneData(JSContext* aCx, CryptoBuffer&
RootedTypedArray<ArrayBufferView> abv(aCx);
if (abv.Init(aSrc)) {
return !!aDst.Assign(abv);
}
return false;
}
-
// Implementation of WebCryptoTask methods
void
WebCryptoTask::FailWithError(nsresult aRv)
{
MOZ_ASSERT(NS_IsMainThread());
Telemetry::Accumulate(Telemetry::WEBCRYPTO_RESOLVED, false);
@@ -459,59 +421,58 @@ public:
TelemetryAlgorithm telemetryAlg;
if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_AES_CBC);
mMechanism = CKM_AES_CBC_PAD;
telemetryAlg = TA_AES_CBC;
AesCbcParams params;
nsresult rv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(rv) || !params.mIv.WasPassed()) {
+ if (NS_FAILED(rv)) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
- ATTEMPT_BUFFER_INIT(mIv, params.mIv.Value())
+ ATTEMPT_BUFFER_INIT(mIv, params.mIv)
if (mIv.Length() != 16) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
}
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_AES_CTR);
mMechanism = CKM_AES_CTR;
telemetryAlg = TA_AES_CTR;
AesCtrParams params;
nsresult rv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(rv) || !params.mCounter.WasPassed() ||
- !params.mLength.WasPassed()) {
+ if (NS_FAILED(rv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
- ATTEMPT_BUFFER_INIT(mIv, params.mCounter.Value())
+ ATTEMPT_BUFFER_INIT(mIv, params.mCounter)
if (mIv.Length() != 16) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
}
- mCounterLength = params.mLength.Value();
+ mCounterLength = params.mLength;
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_AES_GCM);
mMechanism = CKM_AES_GCM;
telemetryAlg = TA_AES_GCM;
AesGcmParams params;
nsresult rv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(rv) || !params.mIv.WasPassed()) {
+ if (NS_FAILED(rv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
- ATTEMPT_BUFFER_INIT(mIv, params.mIv.Value())
+ ATTEMPT_BUFFER_INIT(mIv, params.mIv)
if (params.mAdditionalData.WasPassed()) {
ATTEMPT_BUFFER_INIT(mAad, params.mAdditionalData.Value())
}
// 32, 64, 96, 104, 112, 120 or 128
mTagLength = 128;
if (params.mTagLength.WasPassed()) {
@@ -738,114 +699,16 @@ private:
}
ATTEMPT_BUFFER_ASSIGN(mResult, PK11_GetKeyData(unwrappedKey));
}
return rv;
}
};
-class RsaesPkcs1Task : public ReturnArrayBufferViewTask,
- public DeferredData
-{
-public:
- RsaesPkcs1Task(JSContext* aCx, const ObjectOrString& aAlgorithm,
- CryptoKey& aKey, bool aEncrypt)
- : mPrivKey(aKey.GetPrivateKey())
- , mPubKey(aKey.GetPublicKey())
- , mEncrypt(aEncrypt)
- {
- Init(aCx, aAlgorithm, aKey, aEncrypt);
- }
-
- RsaesPkcs1Task(JSContext* aCx, const ObjectOrString& aAlgorithm,
- CryptoKey& aKey, const CryptoOperationData& aData,
- bool aEncrypt)
- : mPrivKey(aKey.GetPrivateKey())
- , mPubKey(aKey.GetPublicKey())
- , mEncrypt(aEncrypt)
- {
- Init(aCx, aAlgorithm, aKey, aEncrypt);
- SetData(aData);
- }
-
- void Init(JSContext* aCx, const ObjectOrString& aAlgorithm,
- CryptoKey& aKey, bool aEncrypt)
- {
-
- Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_RSAES_PKCS1);
-
- CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_RSAES_PKCS1);
-
- if (mEncrypt) {
- if (!mPubKey) {
- mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
- return;
- }
- mStrength = SECKEY_PublicKeyStrength(mPubKey);
- } else {
- if (!mPrivKey) {
- mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
- return;
- }
- mStrength = PK11_GetPrivateModulusLen(mPrivKey);
- }
- }
-
-private:
- ScopedSECKEYPrivateKey mPrivKey;
- ScopedSECKEYPublicKey mPubKey;
- uint32_t mStrength;
- bool mEncrypt;
-
- virtual nsresult BeforeCrypto() MOZ_OVERRIDE
- {
- if (!mDataIsSet) {
- return NS_ERROR_DOM_OPERATION_ERR;
- }
-
- // Verify that the data input is not too big
- // (as required by PKCS#1 / RFC 3447, Section 7.2)
- // http://tools.ietf.org/html/rfc3447#section-7.2
- if (mEncrypt && mData.Length() > mStrength - 11) {
- return NS_ERROR_DOM_DATA_ERR;
- }
-
- return NS_OK;
- }
-
- virtual nsresult DoCrypto() MOZ_OVERRIDE
- {
- nsresult rv;
-
- // Ciphertext is an integer mod the modulus, so it will be
- // no longer than mStrength octets
- if (!mResult.SetLength(mStrength)) {
- return NS_ERROR_DOM_UNKNOWN_ERR;
- }
-
- if (mEncrypt) {
- rv = MapSECStatus(PK11_PubEncryptPKCS1(
- mPubKey.get(), mResult.Elements(),
- mData.Elements(), mData.Length(),
- nullptr));
- } else {
- uint32_t outLen;
- rv = MapSECStatus(PK11_PrivDecryptPKCS1(
- mPrivKey.get(), mResult.Elements(),
- &outLen, mResult.Length(),
- mData.Elements(), mData.Length()));
- mResult.SetLength(outLen);
- }
-
- NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
- return NS_OK;
- }
-};
-
class RsaOaepTask : public ReturnArrayBufferViewTask,
public DeferredData
{
public:
RsaOaepTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
CryptoKey& aKey, bool aEncrypt)
: mPrivKey(aKey.GetPrivateKey())
, mPubKey(aKey.GetPublicKey())
@@ -891,30 +754,27 @@ public:
if (!aAlgorithm.IsString()) {
RootedDictionary<RsaOaepParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
- if (params.mLabel.WasPassed() && !params.mLabel.Value().IsNull()) {
- ATTEMPT_BUFFER_INIT(mLabel, params.mLabel.Value().Value());
+ if (params.mLabel.WasPassed()) {
+ ATTEMPT_BUFFER_INIT(mLabel, params.mLabel.Value());
}
}
// Otherwise mLabel remains the empty octet string, as intended
// Look up the MGF based on the KeyAlgorithm.
// static_cast is safe because we only get here if the algorithm name
// is RSA-OAEP, and that only happens if we've constructed
// an RsaHashedKeyAlgorithm.
- // TODO: Add As* methods to KeyAlgorithm (Bug 1036734)
- nsRefPtr<RsaHashedKeyAlgorithm> rsaAlg =
- static_cast<RsaHashedKeyAlgorithm*>(aKey.Algorithm());
- mHashMechanism = rsaAlg->Hash()->Mechanism();
+ mHashMechanism = KeyAlgorithmProxy::GetMechanism(aKey.Algorithm().mRsa.mHash);
switch (mHashMechanism) {
case CKM_SHA_1:
mMgfMechanism = CKG_MGF1_SHA1; break;
case CKM_SHA256:
mMgfMechanism = CKG_MGF1_SHA256; break;
case CKM_SHA384:
mMgfMechanism = CKG_MGF1_SHA384; break;
@@ -991,17 +851,17 @@ private:
class HmacTask : public WebCryptoTask
{
public:
HmacTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
CryptoKey& aKey,
const CryptoOperationData& aSignature,
const CryptoOperationData& aData,
bool aSign)
- : mMechanism(aKey.Algorithm()->Mechanism())
+ : mMechanism(aKey.Algorithm().Mechanism())
, mSymKey(aKey.GetSymKey())
, mSign(aSign)
{
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_HMAC);
ATTEMPT_BUFFER_INIT(mData, aData);
if (!aSign) {
ATTEMPT_BUFFER_INIT(mSignature, aSignature);
@@ -1115,20 +975,20 @@ public:
if (!aSign) {
ATTEMPT_BUFFER_INIT(mSignature, aSignature);
}
// Look up the SECOidTag based on the KeyAlgorithm
// static_cast is safe because we only get here if the algorithm name
// is RSASSA-PKCS1-v1_5, and that only happens if we've constructed
// an RsaHashedKeyAlgorithm
- nsRefPtr<RsaHashedKeyAlgorithm> rsaAlg = static_cast<RsaHashedKeyAlgorithm*>(aKey.Algorithm());
- nsRefPtr<KeyAlgorithm> hashAlg = rsaAlg->Hash();
-
- switch (hashAlg->Mechanism()) {
+ CK_MECHANISM_TYPE mech;
+ mech = KeyAlgorithmProxy::GetMechanism(aKey.Algorithm().mRsa.mHash);
+
+ switch (mech) {
case CKM_SHA_1:
mOidTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; break;
case CKM_SHA256:
mOidTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; break;
case CKM_SHA384:
mOidTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; break;
case CKM_SHA512:
mOidTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; break;
@@ -1315,17 +1175,17 @@ public:
// Check 'ext'
if (aKey->Extractable() &&
aJwk.mExt.WasPassed() && !aJwk.mExt.Value()) {
return false;
}
// Check 'alg'
if (aJwk.mAlg.WasPassed() &&
- aJwk.mAlg.Value() != aKey->Algorithm()->ToJwkAlg()) {
+ aJwk.mAlg.Value() != aKey->Algorithm().JwkAlg()) {
return false;
}
// Check 'key_ops'
if (aJwk.mKey_ops.WasPassed()) {
nsTArray<nsString> usages;
aKey->GetUsages(usages);
for (size_t i = 0; i < usages.Length(); ++i) {
@@ -1344,16 +1204,17 @@ public:
// and if that fails, try to initialize a JWK
if (CloneData(aCx, mKeyData, aKeyData)) {
mDataIsJwk = false;
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
SetJwkFromKeyData();
}
} else {
+ ClearException ce(aCx);
JS::RootedValue value(aCx, JS::ObjectValue(*aKeyData));
if (!mJwk.Init(aCx, value)) {
return;
}
mDataIsJwk = true;
}
}
@@ -1424,37 +1285,41 @@ public:
const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
SetKeyData(aCx, aKeyData);
+ if (mDataIsJwk && !mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
+ mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
+ return;
+ }
}
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 this is an HMAC key, import the hash name
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
RootedDictionary<HmacImportParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(mEarlyRv) || !params.mHash.WasPassed()) {
+ if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
- mEarlyRv = GetAlgorithmName(aCx, params.mHash.Value(), mHashName);
+ mEarlyRv = GetAlgorithmName(aCx, params.mHash, mHashName);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
}
}
virtual nsresult BeforeCrypto() MOZ_OVERRIDE
@@ -1476,18 +1341,16 @@ public:
// Check that we have valid key data.
if (mKeyData.Length() == 0) {
return NS_ERROR_DOM_DATA_ERR;
}
// Construct an appropriate KeyAlorithm,
// and verify that usages are appropriate
- nsRefPtr<KeyAlgorithm> algorithm;
- nsIGlobalObject* global = mKey->GetParentObject();
uint32_t length = 8 * mKeyData.Length(); // bytes to bits
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
if (mKey->HasUsageOtherThan(CryptoKey::ENCRYPT | CryptoKey::DECRYPT |
CryptoKey::WRAPKEY | CryptoKey::UNWRAPKEY)) {
return NS_ERROR_DOM_DATA_ERR;
@@ -1496,62 +1359,59 @@ public:
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW) &&
mKey->HasUsageOtherThan(CryptoKey::WRAPKEY | CryptoKey::UNWRAPKEY)) {
return NS_ERROR_DOM_DATA_ERR;
}
if ( (length != 128) && (length != 192) && (length != 256) ) {
return NS_ERROR_DOM_DATA_ERR;
}
- algorithm = new AesKeyAlgorithm(global, mAlgName, length);
+ mKey->Algorithm().MakeAes(mAlgName, length);
if (mDataIsJwk && mJwk.mUse.WasPassed() &&
!mJwk.mUse.Value().EqualsLiteral(JWK_USE_ENC)) {
return NS_ERROR_DOM_DATA_ERR;
}
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
- if (mKey->HasUsageOtherThan(CryptoKey::DERIVEKEY)) {
+ if (mKey->HasUsageOtherThan(CryptoKey::DERIVEKEY | CryptoKey::DERIVEBITS)) {
return NS_ERROR_DOM_DATA_ERR;
}
- algorithm = new BasicSymmetricKeyAlgorithm(global, mAlgName, length);
+ mKey->Algorithm().MakeAes(mAlgName, length);
if (mDataIsJwk && mJwk.mUse.WasPassed()) {
// There is not a 'use' value consistent with PBKDF
return NS_ERROR_DOM_DATA_ERR;
};
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
if (mKey->HasUsageOtherThan(CryptoKey::SIGN | CryptoKey::VERIFY)) {
return NS_ERROR_DOM_DATA_ERR;
}
- algorithm = new HmacKeyAlgorithm(global, mAlgName, length, mHashName);
- if (algorithm->Mechanism() == UNKNOWN_CK_MECHANISM) {
+ mKey->Algorithm().MakeHmac(length, mHashName);
+
+ if (mKey->Algorithm().Mechanism() == UNKNOWN_CK_MECHANISM) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (mDataIsJwk && mJwk.mUse.WasPassed() &&
!mJwk.mUse.Value().EqualsLiteral(JWK_USE_SIG)) {
return NS_ERROR_DOM_DATA_ERR;
}
} else {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
- mKey->SetAlgorithm(algorithm);
mKey->SetSymKey(mKeyData);
mKey->SetType(CryptoKey::SECRET);
- mEarlyComplete = true;
- return NS_OK;
- }
-
- nsresult AfterCrypto() MOZ_OVERRIDE
- {
+
if (mDataIsJwk && !JwkCompatible(mJwk, mKey)) {
return NS_ERROR_DOM_DATA_ERR;
}
+
+ mEarlyComplete = true;
return NS_OK;
}
private:
nsString mHashName;
};
class ImportRsaKeyTask : public ImportKeyTask
@@ -1571,16 +1431,20 @@ public:
const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
SetKeyData(aCx, aKeyData);
+ if (mDataIsJwk && !mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
+ mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
+ return;
+ }
}
void Init(JSContext* aCx,
const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
@@ -1588,26 +1452,34 @@ public:
return;
}
// If this is RSA with a hash, cache the hash name
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
RootedDictionary<RsaHashedImportParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(mEarlyRv) || !params.mHash.WasPassed()) {
- mEarlyRv = NS_ERROR_DOM_DATA_ERR;
- return;
- }
-
- mEarlyRv = GetAlgorithmName(aCx, params.mHash.Value(), mHashName);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
}
+
+ mEarlyRv = GetAlgorithmName(aCx, params.mHash, mHashName);
+ if (NS_FAILED(mEarlyRv)) {
+ mEarlyRv = NS_ERROR_DOM_DATA_ERR;
+ return;
+ }
+ }
+
+ // Check support for the algorithm and hash names
+ CK_MECHANISM_TYPE mech1 = MapAlgorithmNameToMechanism(mAlgName);
+ CK_MECHANISM_TYPE mech2 = MapAlgorithmNameToMechanism(mHashName);
+ if ((mech1 == UNKNOWN_CK_MECHANISM) || (mech2 == UNKNOWN_CK_MECHANISM)) {
+ mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+ return;
}
}
private:
nsString mHashName;
uint32_t mModulusLength;
CryptoBuffer mPublicExponent;
@@ -1664,51 +1536,35 @@ private:
mPublicExponent.Assign(&pubKey->u.rsa.publicExponent);
return NS_OK;
}
virtual nsresult AfterCrypto() MOZ_OVERRIDE
{
// Check permissions for the requested operation
- nsIGlobalObject* global = mKey->GetParentObject();
- if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
- mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
+ if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
if ((mKey->GetKeyType() == CryptoKey::PUBLIC &&
mKey->HasUsageOtherThan(CryptoKey::ENCRYPT | CryptoKey::WRAPKEY)) ||
(mKey->GetKeyType() == CryptoKey::PRIVATE &&
mKey->HasUsageOtherThan(CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY))) {
return NS_ERROR_DOM_DATA_ERR;
}
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
if ((mKey->GetKeyType() == CryptoKey::PUBLIC &&
mKey->HasUsageOtherThan(CryptoKey::VERIFY)) ||
(mKey->GetKeyType() == CryptoKey::PRIVATE &&
mKey->HasUsageOtherThan(CryptoKey::SIGN))) {
return NS_ERROR_DOM_DATA_ERR;
}
}
- // Construct an appropriate KeyAlgorithm
- if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
- mKey->SetAlgorithm(new RsaKeyAlgorithm(global, mAlgName, mModulusLength, mPublicExponent));
- } else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
- mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
- nsRefPtr<RsaHashedKeyAlgorithm> algorithm =
- new RsaHashedKeyAlgorithm(global, mAlgName,
- mModulusLength, mPublicExponent, mHashName);
- if (algorithm->Mechanism() == UNKNOWN_CK_MECHANISM) {
- return NS_ERROR_DOM_SYNTAX_ERR;
- }
-
- if (algorithm->Hash()->Mechanism() == UNKNOWN_CK_MECHANISM) {
- return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
- }
- mKey->SetAlgorithm(algorithm);
- }
+ // Set an appropriate KeyAlgorithm
+ mKey->Algorithm().MakeRsa(mAlgName, mModulusLength,
+ mPublicExponent, mHashName);
if (mDataIsJwk && !JwkCompatible(mJwk, mKey)) {
return NS_ERROR_DOM_DATA_ERR;
}
return NS_OK;
}
};
@@ -1788,34 +1644,33 @@ private:
mKey->SetPublicKey(pubKey.get());
mKey->SetType(CryptoKey::PUBLIC);
} else {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
// Extract 'crv' parameter from JWKs.
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
- if (!NormalizeNamedCurveValue(mJwk.mCrv.Value(), mNamedCurve)) {
+ if (!NormalizeToken(mJwk.mCrv.Value(), mNamedCurve)) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
}
return NS_OK;
}
virtual nsresult AfterCrypto() MOZ_OVERRIDE
{
// Check permissions for the requested operation
if (mKey->GetKeyType() == CryptoKey::PRIVATE &&
mKey->HasUsageOtherThan(CryptoKey::DERIVEBITS | CryptoKey::DERIVEKEY)) {
return NS_ERROR_DOM_DATA_ERR;
}
- nsIGlobalObject* global = mKey->GetParentObject();
- mKey->SetAlgorithm(new EcKeyAlgorithm(global, mAlgName, mNamedCurve));
+ mKey->Algorithm().MakeEc(mAlgName, mNamedCurve);
if (mDataIsJwk && !JwkCompatible(mJwk, mKey)) {
return NS_ERROR_DOM_DATA_ERR;
}
return NS_OK;
}
};
@@ -1825,23 +1680,18 @@ class ExportKeyTask : public WebCryptoTa
public:
ExportKeyTask(const nsAString& aFormat, CryptoKey& aKey)
: mFormat(aFormat)
, mSymKey(aKey.GetSymKey())
, mPrivateKey(aKey.GetPrivateKey())
, mPublicKey(aKey.GetPublicKey())
, mKeyType(aKey.GetKeyType())
, mExtractable(aKey.Extractable())
- , mAlg(aKey.Algorithm()->ToJwkAlg())
+ , mAlg(aKey.Algorithm().JwkAlg())
{
- if (!aKey.Extractable()) {
- mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
- return;
- }
-
aKey.GetUsages(mKeyUsages);
}
protected:
nsString mFormat;
CryptoBuffer mSymKey;
ScopedSECKEYPrivateKey mPrivateKey;
@@ -1892,17 +1742,17 @@ private:
} else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
if (mKeyType == CryptoKey::SECRET) {
nsString k;
nsresult rv = mSymKey.ToJwkBase64(k);
if (NS_FAILED(rv)) {
return NS_ERROR_DOM_OPERATION_ERR;
}
mJwk.mK.Construct(k);
- mJwk.mKty.Construct(NS_LITERAL_STRING(JWK_TYPE_SYMMETRIC));
+ mJwk.mKty = NS_LITERAL_STRING(JWK_TYPE_SYMMETRIC);
} else if (mKeyType == CryptoKey::PUBLIC) {
if (!mPublicKey) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
nsresult rv = CryptoKey::PublicKeyToJwk(mPublicKey, mJwk, locker);
if (NS_FAILED(rv)) {
return NS_ERROR_DOM_OPERATION_ERR;
@@ -1970,74 +1820,73 @@ public:
nsString algName;
mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// Construct an appropriate KeyAlorithm
- nsRefPtr<KeyAlgorithm> algorithm;
uint32_t allowedUsages = 0;
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)) {
mEarlyRv = GetKeyLengthForAlgorithm(aCx, aAlgorithm, mLength);
if (NS_FAILED(mEarlyRv)) {
return;
}
- algorithm = new AesKeyAlgorithm(global, algName, mLength);
+ mKey->Algorithm().MakeAes(algName, mLength);
+
allowedUsages = CryptoKey::ENCRYPT | CryptoKey::DECRYPT |
CryptoKey::WRAPKEY | CryptoKey::UNWRAPKEY;
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
RootedDictionary<HmacKeyGenParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(mEarlyRv) || !params.mHash.WasPassed()) {
+ if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
nsString hashName;
- mEarlyRv = GetAlgorithmName(aCx, params.mHash.Value(), hashName);
+ mEarlyRv = GetAlgorithmName(aCx, params.mHash, hashName);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
if (params.mLength.WasPassed()) {
mLength = params.mLength.Value();
} else {
mLength = MapHashAlgorithmNameToBlockSize(hashName);
}
if (mLength == 0) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
}
- algorithm = new HmacKeyAlgorithm(global, algName, mLength, hashName);
+ mKey->Algorithm().MakeHmac(mLength, hashName);
allowedUsages = CryptoKey::SIGN | CryptoKey::VERIFY;
} else {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
// Add key usages
mKey->ClearUsages();
for (uint32_t i = 0; i < aKeyUsages.Length(); ++i) {
mEarlyRv = mKey->AddUsageIntersecting(aKeyUsages[i], allowedUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
}
mLength = mLength >> 3; // bits to bytes
- mMechanism = algorithm->Mechanism();
- mKey->SetAlgorithm(algorithm);
+ mMechanism = mKey->Algorithm().Mechanism();
// SetSymKey done in Resolve, after we've done the keygen
}
private:
nsRefPtr<CryptoKey> mKey;
size_t mLength;
CK_MECHANISM_TYPE mMechanism;
CryptoBuffer mKeyData;
@@ -2084,154 +1933,133 @@ public:
{
nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
if (!global) {
mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
return;
}
// Create an empty key and set easy attributes
- mKeyPair = new CryptoKeyPair(global);
+ mKeyPair.mPrivateKey = new CryptoKey(global);
+ mKeyPair.mPublicKey = new CryptoKey(global);
// Extract algorithm name
nsString algName;
mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// Construct an appropriate KeyAlorithm
- KeyAlgorithm* algorithm;
uint32_t privateAllowedUsages = 0, publicAllowedUsages = 0;
if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
RootedDictionary<RsaHashedKeyGenParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(mEarlyRv) || !params.mModulusLength.WasPassed() ||
- !params.mPublicExponent.WasPassed() ||
- !params.mHash.WasPassed()) {
+ if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// Pull relevant info
- uint32_t modulusLength = params.mModulusLength.Value();
+ uint32_t modulusLength = params.mModulusLength;
CryptoBuffer publicExponent;
- ATTEMPT_BUFFER_INIT(publicExponent, params.mPublicExponent.Value());
+ ATTEMPT_BUFFER_INIT(publicExponent, params.mPublicExponent);
nsString hashName;
- mEarlyRv = GetAlgorithmName(aCx, params.mHash.Value(), hashName);
+ mEarlyRv = GetAlgorithmName(aCx, params.mHash, hashName);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// Create algorithm
- algorithm = new RsaHashedKeyAlgorithm(global, algName, modulusLength,
- publicExponent, hashName);
- mKeyPair->PublicKey()->SetAlgorithm(algorithm);
- mKeyPair->PrivateKey()->SetAlgorithm(algorithm);
- mMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
-
- // Set up params struct
- mRsaParams.keySizeInBits = modulusLength;
- bool converted = publicExponent.GetBigIntValue(mRsaParams.pe);
- if (!converted) {
- mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
- return;
- }
- } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
- RootedDictionary<RsaKeyGenParams> params(aCx);
- mEarlyRv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(mEarlyRv) || !params.mModulusLength.WasPassed() ||
- !params.mPublicExponent.WasPassed()) {
- mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
- return;
- }
-
- // Pull relevant info
- uint32_t modulusLength = params.mModulusLength.Value();
- CryptoBuffer publicExponent;
- ATTEMPT_BUFFER_INIT(publicExponent, params.mPublicExponent.Value());
-
- // Create algorithm and note the mechanism
- algorithm = new RsaKeyAlgorithm(global, algName, modulusLength,
- publicExponent);
- mKeyPair->PublicKey()->SetAlgorithm(algorithm);
- mKeyPair->PrivateKey()->SetAlgorithm(algorithm);
+ mKeyPair.mPublicKey.get()->Algorithm().MakeRsa(algName,
+ modulusLength,
+ publicExponent,
+ hashName);
+ mKeyPair.mPrivateKey.get()->Algorithm().MakeRsa(algName,
+ modulusLength,
+ publicExponent,
+ hashName);
mMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
// Set up params struct
mRsaParams.keySizeInBits = modulusLength;
bool converted = publicExponent.GetBigIntValue(mRsaParams.pe);
if (!converted) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
RootedDictionary<EcKeyGenParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(mEarlyRv) || !params.mNamedCurve.WasPassed()) {
+ if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
- if (!NormalizeNamedCurveValue(params.mNamedCurve.Value(), mNamedCurve)) {
+ if (!NormalizeToken(params.mNamedCurve, mNamedCurve)) {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
// Create algorithm.
- algorithm = new EcKeyAlgorithm(global, algName, mNamedCurve);
- mKeyPair->PublicKey()->SetAlgorithm(algorithm);
- mKeyPair->PrivateKey()->SetAlgorithm(algorithm);
+ mKeyPair.mPublicKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
+ mKeyPair.mPrivateKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
mMechanism = CKM_EC_KEY_PAIR_GEN;
} else {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
// Set key usages.
if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
privateAllowedUsages = CryptoKey::SIGN;
publicAllowedUsages = CryptoKey::VERIFY;
- } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
- algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
+ } 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)) {
privateAllowedUsages = CryptoKey::DERIVEKEY | CryptoKey::DERIVEBITS;
publicAllowedUsages = 0;
}
- mKeyPair->PrivateKey()->SetExtractable(aExtractable);
- mKeyPair->PrivateKey()->SetType(CryptoKey::PRIVATE);
-
- mKeyPair->PublicKey()->SetExtractable(true);
- mKeyPair->PublicKey()->SetType(CryptoKey::PUBLIC);
-
- mKeyPair->PrivateKey()->ClearUsages();
- mKeyPair->PublicKey()->ClearUsages();
+ mKeyPair.mPrivateKey.get()->SetExtractable(aExtractable);
+ mKeyPair.mPrivateKey.get()->SetType(CryptoKey::PRIVATE);
+
+ mKeyPair.mPublicKey.get()->SetExtractable(true);
+ mKeyPair.mPublicKey.get()->SetType(CryptoKey::PUBLIC);
+
+ mKeyPair.mPrivateKey.get()->ClearUsages();
+ mKeyPair.mPublicKey.get()->ClearUsages();
for (uint32_t i=0; i < aKeyUsages.Length(); ++i) {
- mEarlyRv = mKeyPair->PrivateKey()->AddUsageIntersecting(aKeyUsages[i],
- privateAllowedUsages);
+ mEarlyRv = mKeyPair.mPrivateKey.get()->AddUsageIntersecting(aKeyUsages[i],
+ privateAllowedUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
- mEarlyRv = mKeyPair->PublicKey()->AddUsageIntersecting(aKeyUsages[i],
- publicAllowedUsages);
+ mEarlyRv = mKeyPair.mPublicKey.get()->AddUsageIntersecting(aKeyUsages[i],
+ publicAllowedUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
}
+
+ // If no usages ended up being allowed, DataError
+ if (!mKeyPair.mPrivateKey.get()->HasAnyUsage() ||
+ !mKeyPair.mPrivateKey.get()->HasAnyUsage()) {
+ mEarlyRv = NS_ERROR_DOM_DATA_ERR;
+ return;
+ }
}
private:
- nsRefPtr<CryptoKeyPair> mKeyPair;
+ CryptoKeyPair mKeyPair;
CK_MECHANISM_TYPE mMechanism;
PK11RSAGenParams mRsaParams;
ScopedSECKEYPublicKey mPublicKey;
ScopedSECKEYPrivateKey mPrivateKey;
nsString mNamedCurve;
virtual void ReleaseNSSResources() MOZ_OVERRIDE
{
@@ -2270,30 +2098,25 @@ private:
SECKEYPublicKey* pubKey = nullptr;
mPrivateKey = PK11_GenerateKeyPair(slot.get(), mMechanism, param, &pubKey,
PR_FALSE, PR_FALSE, nullptr);
mPublicKey = pubKey;
if (!mPrivateKey.get() || !mPublicKey.get()) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
- mKeyPair->PrivateKey()->SetPrivateKey(mPrivateKey);
- mKeyPair->PublicKey()->SetPublicKey(mPublicKey);
+ mKeyPair.mPrivateKey.get()->SetPrivateKey(mPrivateKey);
+ mKeyPair.mPublicKey.get()->SetPublicKey(mPublicKey);
return NS_OK;
}
virtual void Resolve() MOZ_OVERRIDE
{
mResultPromise->MaybeResolve(mKeyPair);
}
-
- virtual void Cleanup() MOZ_OVERRIDE
- {
- mKeyPair = nullptr;
- }
};
class DerivePbkdfBitsTask : public ReturnArrayBufferViewTask
{
public:
DerivePbkdfBitsTask(JSContext* aCx,
const ObjectOrString& aAlgorithm, CryptoKey& aKey, uint32_t aLength)
: mSymKey(aKey.GetSymKey())
@@ -2321,50 +2144,49 @@ public:
// Check that we got a symmetric key
if (mSymKey.Length() == 0) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
RootedDictionary<Pbkdf2Params> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(mEarlyRv) || !params.mHash.WasPassed() ||
- !params.mIterations.WasPassed() || !params.mSalt.WasPassed()) {
+ if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// length must be a multiple of 8 bigger than zero.
if (aLength == 0 || aLength % 8) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
}
// Extract the hash algorithm.
nsString hashName;
- mEarlyRv = GetAlgorithmName(aCx, params.mHash.Value(), hashName);
+ mEarlyRv = GetAlgorithmName(aCx, params.mHash, hashName);
if (NS_FAILED(mEarlyRv)) {
return;
}
// Check the given hash algorithm.
switch (MapAlgorithmNameToMechanism(hashName)) {
case CKM_SHA_1: mHashOidTag = SEC_OID_HMAC_SHA1; break;
case CKM_SHA256: mHashOidTag = SEC_OID_HMAC_SHA256; break;
case CKM_SHA384: mHashOidTag = SEC_OID_HMAC_SHA384; break;
case CKM_SHA512: mHashOidTag = SEC_OID_HMAC_SHA512; break;
default: {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
}
- ATTEMPT_BUFFER_INIT(mSalt, params.mSalt.Value())
+ ATTEMPT_BUFFER_INIT(mSalt, params.mSalt)
mLength = aLength >> 3; // bits to bytes
- mIterations = params.mIterations.Value();
+ mIterations = params.mIterations;
}
private:
size_t mLength;
size_t mIterations;
CryptoBuffer mSalt;
CryptoBuffer mSymKey;
SECOidTag mHashOidTag;
@@ -2489,35 +2311,33 @@ public:
return;
}
mLength = mLength >> 3; // bits to bytes
// Retrieve the peer's public key.
RootedDictionary<EcdhKeyDeriveParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
- if (NS_FAILED(mEarlyRv) || !params.mPublic.WasPassed()) {
+ if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
- CryptoKey* publicKey = params.mPublic.Value();
+ CryptoKey* publicKey = params.mPublic;
mPubKey = publicKey->GetPublicKey();
if (!mPubKey) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
- nsRefPtr<KeyAlgorithm> publicAlgorithm = publicKey->Algorithm();
- CHECK_KEY_ALGORITHM(publicAlgorithm, WEBCRYPTO_ALG_ECDH);
+ CHECK_KEY_ALGORITHM(publicKey->Algorithm(), WEBCRYPTO_ALG_ECDH);
// Both keys must use the same named curve.
- nsString curve1, curve2;
- static_cast<EcKeyAlgorithm*>(aKey.Algorithm())->GetNamedCurve(curve1);
- static_cast<EcKeyAlgorithm*>(publicAlgorithm.get())->GetNamedCurve(curve2);
+ nsString curve1 = aKey.Algorithm().mEc.mNamedCurve;
+ nsString curve2 = publicKey->Algorithm().mEc.mNamedCurve;
if (!curve1.Equals(curve2)) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
}
}
private:
@@ -2640,182 +2460,268 @@ private:
mTask->Skip();
}
mTask = nullptr;
}
};
// Task creation methods for WebCryptoTask
+// Note: We do not perform algorithm normalization as a monolithic process,
+// as described in the spec. Instead:
+// * Each method handles its slice of the supportedAlgorithms structure
+// * Task constructors take care of:
+// * Coercing the algorithm to the proper concrete type
+// * Cloning subordinate data items
+// * Cloning input data as needed
+//
+// Thus, support for different algorithms is determined by the if-statements
+// below, rather than a data structure.
+//
+// This results in algorithm normalization coming after some other checks,
+// and thus slightly more steps being done synchronously than the spec calls
+// for. But none of these steps is especially time-consuming.
+
WebCryptoTask*
WebCryptoTask::CreateEncryptDecryptTask(JSContext* aCx,
- const ObjectOrString& aAlgorithm,
- CryptoKey& aKey,
- const CryptoOperationData& aData,
- bool aEncrypt)
+ const ObjectOrString& aAlgorithm,
+ CryptoKey& aKey,
+ const CryptoOperationData& aData,
+ bool aEncrypt)
{
TelemetryMethod method = (aEncrypt)? TM_ENCRYPT : TM_DECRYPT;
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, method);
Telemetry::Accumulate(Telemetry::WEBCRYPTO_EXTRACTABLE_ENC, aKey.Extractable());
+ // Ensure key is usable for this operation
+ if ((aEncrypt && !aKey.HasUsage(CryptoKey::ENCRYPT)) ||
+ (!aEncrypt && !aKey.HasUsage(CryptoKey::DECRYPT))) {
+ return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+ }
+
nsString algName;
nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
- // Ensure key is usable for this operation
- if ((aEncrypt && !aKey.HasUsage(CryptoKey::ENCRYPT)) ||
- (!aEncrypt && !aKey.HasUsage(CryptoKey::DECRYPT))) {
- return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
- }
-
if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
return new AesTask(aCx, aAlgorithm, aKey, aData, aEncrypt);
- } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
- return new RsaesPkcs1Task(aCx, aAlgorithm, aKey, aData, aEncrypt);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
return new RsaOaepTask(aCx, aAlgorithm, aKey, aData, aEncrypt);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
WebCryptoTask*
WebCryptoTask::CreateSignVerifyTask(JSContext* aCx,
- const ObjectOrString& aAlgorithm,
- CryptoKey& aKey,
- const CryptoOperationData& aSignature,
- const CryptoOperationData& aData,
- bool aSign)
+ const ObjectOrString& aAlgorithm,
+ CryptoKey& aKey,
+ const CryptoOperationData& aSignature,
+ const CryptoOperationData& aData,
+ bool aSign)
{
TelemetryMethod method = (aSign)? TM_SIGN : TM_VERIFY;
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, method);
Telemetry::Accumulate(Telemetry::WEBCRYPTO_EXTRACTABLE_SIG, aKey.Extractable());
+ // Ensure key is usable for this operation
+ if ((aSign && !aKey.HasUsage(CryptoKey::SIGN)) ||
+ (!aSign && !aKey.HasUsage(CryptoKey::VERIFY))) {
+ return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+ }
+
nsString algName;
nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
- // Ensure key is usable for this operation
- if ((aSign && !aKey.HasUsage(CryptoKey::SIGN)) ||
- (!aSign && !aKey.HasUsage(CryptoKey::VERIFY))) {
- return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
- }
-
if (algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
return new HmacTask(aCx, aAlgorithm, aKey, aSignature, aData, aSign);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
return new RsassaPkcs1Task(aCx, aAlgorithm, aKey, aSignature, aData, aSign);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
WebCryptoTask*
WebCryptoTask::CreateDigestTask(JSContext* aCx,
- const ObjectOrString& aAlgorithm,
- const CryptoOperationData& aData)
+ const ObjectOrString& aAlgorithm,
+ const CryptoOperationData& aData)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_DIGEST);
- return new DigestTask(aCx, aAlgorithm, aData);
-}
-
-WebCryptoTask*
-WebCryptoTask::CreateImportKeyTask(JSContext* aCx,
- const nsAString& aFormat,
- JS::Handle<JSObject*> aKeyData,
- const ObjectOrString& aAlgorithm,
- bool aExtractable,
- const Sequence<nsString>& aKeyUsages)
-{
- Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_IMPORTKEY);
- Telemetry::Accumulate(Telemetry::WEBCRYPTO_EXTRACTABLE_IMPORT, aExtractable);
nsString algName;
nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
+ if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA1) ||
+ algName.EqualsLiteral(WEBCRYPTO_ALG_SHA256) ||
+ algName.EqualsLiteral(WEBCRYPTO_ALG_SHA384) ||
+ algName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
+ return new DigestTask(aCx, aAlgorithm, aData);
+ }
+
+ return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+}
+
+WebCryptoTask*
+WebCryptoTask::CreateImportKeyTask(JSContext* aCx,
+ const nsAString& aFormat,
+ JS::Handle<JSObject*> aKeyData,
+ const ObjectOrString& aAlgorithm,
+ bool aExtractable,
+ const Sequence<nsString>& aKeyUsages)
+{
+ Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_IMPORTKEY);
+ Telemetry::Accumulate(Telemetry::WEBCRYPTO_EXTRACTABLE_IMPORT, aExtractable);
+
+ // Verify that the format is recognized
+ if (!aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW) &&
+ !aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI) &&
+ !aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_PKCS8) &&
+ !aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
+ return new FailureTask(NS_ERROR_DOM_SYNTAX_ERR);
+ }
+
+ // Verify that aKeyUsages does not contain an unrecognized value
+ if (!CryptoKey::AllUsagesRecognized(aKeyUsages)) {
+ return new FailureTask(NS_ERROR_DOM_SYNTAX_ERR);
+ }
+
+ nsString algName;
+ nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
+ if (NS_FAILED(rv)) {
+ return new FailureTask(rv);
+ }
+
+ // SPEC-BUG: PBKDF2 is not supposed to be supported for this operation.
+ // However, the spec should be updated to allow it.
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)) {
return new ImportSymmetricKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
- } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
- algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
+ } 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)) {
return new ImportEcKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else {
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
}
WebCryptoTask*
WebCryptoTask::CreateExportKeyTask(const nsAString& aFormat,
- CryptoKey& aKey)
+ CryptoKey& aKey)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_EXPORTKEY);
- return new ExportKeyTask(aFormat, aKey);
+ // Verify that the format is recognized
+ if (!aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW) &&
+ !aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI) &&
+ !aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_PKCS8) &&
+ !aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
+ return new FailureTask(NS_ERROR_DOM_SYNTAX_ERR);
+ }
+
+ // Verify that the key is extractable
+ if (!aKey.Extractable()) {
+ return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+ }
+
+ // Verify that the algorithm supports export
+ // SPEC-BUG: PBKDF2 is not supposed to be supported for this operation.
+ // However, the spec should be updated to allow it.
+ nsString algName = aKey.Algorithm().mName;
+ 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)) {
+ return new ExportKeyTask(aFormat, aKey);
+ }
+
+ return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
WebCryptoTask*
WebCryptoTask::CreateGenerateKeyTask(JSContext* aCx,
- const ObjectOrString& aAlgorithm,
- bool aExtractable,
- const Sequence<nsString>& aKeyUsages)
+ const ObjectOrString& aAlgorithm,
+ bool aExtractable,
+ const Sequence<nsString>& aKeyUsages)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_GENERATEKEY);
Telemetry::Accumulate(Telemetry::WEBCRYPTO_EXTRACTABLE_GENERATE, aExtractable);
+ // Verify that aKeyUsages does not contain an unrecognized value
+ // SPEC-BUG: Spec says that this should be InvalidAccessError, but that
+ // is inconsistent with other analogous points in the spec
+ if (!CryptoKey::AllUsagesRecognized(aKeyUsages)) {
+ return new FailureTask(NS_ERROR_DOM_SYNTAX_ERR);
+ }
+
nsString algName;
nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_AES_CBC) ||
algName.EqualsASCII(WEBCRYPTO_ALG_AES_CTR) ||
algName.EqualsASCII(WEBCRYPTO_ALG_AES_GCM) ||
algName.EqualsASCII(WEBCRYPTO_ALG_AES_KW) ||
algName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) {
return new GenerateSymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
- } else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSAES_PKCS1) ||
- algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
+ } else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
algName.EqualsASCII(WEBCRYPTO_ALG_ECDH)) {
return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
} else {
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
}
WebCryptoTask*
WebCryptoTask::CreateDeriveKeyTask(JSContext* aCx,
- const ObjectOrString& aAlgorithm,
- CryptoKey& aBaseKey,
- const ObjectOrString& aDerivedKeyType,
- bool aExtractable,
- const Sequence<nsString>& aKeyUsages)
+ const ObjectOrString& aAlgorithm,
+ CryptoKey& aBaseKey,
+ const ObjectOrString& aDerivedKeyType,
+ bool aExtractable,
+ const Sequence<nsString>& aKeyUsages)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_DERIVEKEY);
+ // Ensure baseKey is usable for this operation
+ if (!aBaseKey.HasUsage(CryptoKey::DERIVEKEY)) {
+ return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+ }
+
+ // Verify that aKeyUsages does not contain an unrecognized value
+ if (!CryptoKey::AllUsagesRecognized(aKeyUsages)) {
+ return new FailureTask(NS_ERROR_DOM_SYNTAX_ERR);
+ }
+
nsString algName;
nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_PBKDF2)) {
return new DeriveKeyTask<DerivePbkdfBitsTask>(aCx, aAlgorithm, aBaseKey,
@@ -2829,22 +2735,27 @@ WebCryptoTask::CreateDeriveKeyTask(JSCon
aKeyUsages);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
WebCryptoTask*
WebCryptoTask::CreateDeriveBitsTask(JSContext* aCx,
- const ObjectOrString& aAlgorithm,
- CryptoKey& aKey,
- uint32_t aLength)
+ const ObjectOrString& aAlgorithm,
+ CryptoKey& aKey,
+ uint32_t aLength)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_DERIVEBITS);
+ // Ensure baseKey is usable for this operation
+ if (!aKey.HasUsage(CryptoKey::DERIVEBITS)) {
+ return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+ }
+
nsString algName;
nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_PBKDF2)) {
return new DerivePbkdfBitsTask(aCx, aAlgorithm, aKey, aLength);
@@ -2854,87 +2765,101 @@ WebCryptoTask::CreateDeriveBitsTask(JSCo
return new DeriveEcdhBitsTask(aCx, aAlgorithm, aKey, aLength);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
WebCryptoTask*
WebCryptoTask::CreateWrapKeyTask(JSContext* aCx,
- const nsAString& aFormat,
- CryptoKey& aKey,
- CryptoKey& aWrappingKey,
- const ObjectOrString& aWrapAlgorithm)
+ const nsAString& aFormat,
+ CryptoKey& aKey,
+ CryptoKey& aWrappingKey,
+ const ObjectOrString& aWrapAlgorithm)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_WRAPKEY);
- // Ensure key is usable for this operation
+ // Verify that the format is recognized
+ if (!aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW) &&
+ !aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI) &&
+ !aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_PKCS8) &&
+ !aFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
+ return new FailureTask(NS_ERROR_DOM_SYNTAX_ERR);
+ }
+
+ // Ensure wrappingKey is usable for this operation
if (!aWrappingKey.HasUsage(CryptoKey::WRAPKEY)) {
return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
}
+ // Ensure key is extractable
+ if (!aKey.Extractable()) {
+ return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+ }
+
nsString wrapAlgName;
nsresult rv = GetAlgorithmName(aCx, aWrapAlgorithm, wrapAlgName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
if (wrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
wrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
wrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
return new WrapKeyTask<AesTask>(aCx, aFormat, aKey,
aWrappingKey, aWrapAlgorithm);
} else if (wrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
return new WrapKeyTask<AesKwTask>(aCx, aFormat, aKey,
aWrappingKey, aWrapAlgorithm);
- } else if (wrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
- return new WrapKeyTask<RsaesPkcs1Task>(aCx, aFormat, aKey,
- aWrappingKey, aWrapAlgorithm);
} else if (wrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
return new WrapKeyTask<RsaOaepTask>(aCx, aFormat, aKey,
aWrappingKey, aWrapAlgorithm);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
WebCryptoTask*
WebCryptoTask::CreateUnwrapKeyTask(JSContext* aCx,
- const nsAString& aFormat,
- const ArrayBufferViewOrArrayBuffer& aWrappedKey,
- CryptoKey& aUnwrappingKey,
- const ObjectOrString& aUnwrapAlgorithm,
- const ObjectOrString& aUnwrappedKeyAlgorithm,
- bool aExtractable,
- const Sequence<nsString>& aKeyUsages)
+ const nsAString& aFormat,
+ const ArrayBufferViewOrArrayBuffer& aWrappedKey,
+ CryptoKey& aUnwrappingKey,
+ const ObjectOrString& aUnwrapAlgorithm,
+ const ObjectOrString& aUnwrappedKeyAlgorithm,
+ bool aExtractable,
+ const Sequence<nsString>& aKeyUsages)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_UNWRAPKEY);
// Ensure key is usable for this operation
if (!aUnwrappingKey.HasUsage(CryptoKey::UNWRAPKEY)) {
return new FailureTask(NS_ERROR_DOM_INVALID_ACCESS_ERR);
}
+ // Verify that aKeyUsages does not contain an unrecognized value
+ if (!CryptoKey::AllUsagesRecognized(aKeyUsages)) {
+ return new FailureTask(NS_ERROR_DOM_SYNTAX_ERR);
+ }
+
nsString keyAlgName;
nsresult rv = GetAlgorithmName(aCx, aUnwrappedKeyAlgorithm, keyAlgName);
if (NS_FAILED(rv)) {
return new FailureTask(rv);
}
CryptoOperationData dummy;
nsRefPtr<ImportKeyTask> importTask;
if (keyAlgName.EqualsASCII(WEBCRYPTO_ALG_AES_CBC) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_AES_CTR) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_AES_GCM) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) {
importTask = new ImportSymmetricKeyTask(aCx, aFormat,
aUnwrappedKeyAlgorithm,
aExtractable, aKeyUsages);
- } else if (keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSAES_PKCS1) ||
- keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
+ } else if (keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP)) {
importTask = new ImportRsaKeyTask(aCx, aFormat,
aUnwrappedKeyAlgorithm,
aExtractable, aKeyUsages);
} else {
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
@@ -2948,20 +2873,16 @@ WebCryptoTask::CreateUnwrapKeyTask(JSCon
unwrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
return new UnwrapKeyTask<AesTask>(aCx, aWrappedKey,
aUnwrappingKey, aUnwrapAlgorithm,
importTask);
} else if (unwrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
return new UnwrapKeyTask<AesKwTask>(aCx, aWrappedKey,
aUnwrappingKey, aUnwrapAlgorithm,
importTask);
- } else if (unwrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
- return new UnwrapKeyTask<RsaesPkcs1Task>(aCx, aWrappedKey,
- aUnwrappingKey, aUnwrapAlgorithm,
- importTask);
} else if (unwrapAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
return new UnwrapKeyTask<RsaOaepTask>(aCx, aWrappedKey,
aUnwrappingKey, aUnwrapAlgorithm,
importTask);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
--- a/dom/crypto/moz.build
+++ b/dom/crypto/moz.build
@@ -1,39 +1,26 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom += [
- 'AesKeyAlgorithm.h',
- 'BasicSymmetricKeyAlgorithm.h',
'CryptoBuffer.h',
'CryptoKey.h',
- 'CryptoKeyPair.h',
- 'EcKeyAlgorithm.h',
- 'HmacKeyAlgorithm.h',
- 'KeyAlgorithm.h',
- 'RsaHashedKeyAlgorithm.h',
- 'RsaKeyAlgorithm.h',
+ 'KeyAlgorithmProxy.h',
'WebCryptoCommon.h',
'WebCryptoTask.h',
]
UNIFIED_SOURCES += [
- 'AesKeyAlgorithm.cpp',
'CryptoBuffer.cpp',
'CryptoKey.cpp',
- 'CryptoKeyPair.cpp',
- 'EcKeyAlgorithm.cpp',
- 'HmacKeyAlgorithm.cpp',
- 'KeyAlgorithm.cpp',
- 'RsaHashedKeyAlgorithm.cpp',
- 'RsaKeyAlgorithm.cpp',
+ 'KeyAlgorithmProxy.cpp',
'WebCryptoTask.cpp',
]
FAIL_ON_WARNINGS = True
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
--- a/dom/crypto/test/test_WebCrypto.html
+++ b/dom/crypto/test/test_WebCrypto.html
@@ -66,31 +66,30 @@ TestArray.addTest(
TestArray.addTest(
"Import / export round-trip with 'raw'",
function() {
var that = this;
var alg = "AES-GCM";
function doExport(x) {
if (!hasKeyFields(x)) {
- window.result = x;
throw "Invalid key; missing field(s)";
} else if ((x.algorithm.name != alg) ||
(x.algorithm.length != 8 * tv.raw.length) ||
(x.type != "secret") ||
(!x.extractable) ||
(x.usages.length != 1) ||
(x.usages[0] != 'encrypt')){
throw "Invalid key: incorrect key data";
}
return crypto.subtle.exportKey("raw", x);
}
crypto.subtle.importKey("raw", tv.raw, alg, true, ["encrypt"])
- .then(doExport, error(that))
+ .then(doExport)
.then(
memcmp_complete(that, tv.raw),
error(that)
);
}
);
// -----------------------------------------------------------------------------
@@ -148,17 +147,17 @@ TestArray.addTest(
(x.usages.length != 1) ||
(x.usages[0] != 'sign')){
throw "Invalid key: incorrect key data";
}
return crypto.subtle.exportKey("pkcs8", x);
}
crypto.subtle.importKey("pkcs8", tv.pkcs8, alg, true, ["sign"])
- .then(doExport, error(that))
+ .then(doExport)
.then(
memcmp_complete(that, tv.pkcs8),
error(that)
);
}
);
// -----------------------------------------------------------------------------
@@ -173,48 +172,54 @@ TestArray.addTest(
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Import / export round-trip with 'spki'",
function() {
var that = this;
- var alg = "RSAES-PKCS1-v1_5";
+ var alg = {
+ name: "RSASSA-PKCS1-v1_5",
+ hash: "SHA-256"
+ };
function doExport(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
- } else if ((x.algorithm.name != alg) ||
+ } else if ((x.algorithm.name != alg.name) ||
(x.algorithm.modulusLength != 1024) ||
(x.algorithm.publicExponent.byteLength != 3) ||
(x.type != "public") ||
(!x.extractable) ||
(x.usages.length != 1) ||
- (x.usages[0] != 'encrypt')){
+ (x.usages[0] != 'verify')){
throw "Invalid key: incorrect key data";
}
return crypto.subtle.exportKey("spki", x);
}
- crypto.subtle.importKey("spki", tv.spki, alg, true, ["encrypt"])
+ crypto.subtle.importKey("spki", tv.spki, alg, true, ["verify"])
.then(doExport, error(that))
.then(
memcmp_complete(that, tv.spki),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Import failure with format 'spki'",
function() {
var that = this;
- var alg = "RSAES-PKCS1-v1_5";
+ var alg = {
+ name: "RSASSA-PKCS1-v1_5",
+ hash: "SHA-256"
+ };
crypto.subtle.importKey("spki", tv.negative_spki, alg, true, ["encrypt"])
.then(error(that), complete(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
@@ -377,54 +382,56 @@ TestArray.addTest(
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Generate a 1024-bit RSA key",
function() {
var that = this;
var alg = {
- name: "RSAES-PKCS1-v1_5",
+ name: "RSASSA-PKCS1-v1_5",
+ hash: "SHA-256",
modulusLength: 1024,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
- crypto.subtle.generateKey(alg, false, ["encrypt", "decrypt"]).then(
+ crypto.subtle.generateKey(alg, false, ["sign", "verify"]).then(
complete(that, function(x) {
return exists(x.publicKey) &&
(x.publicKey.algorithm.name == alg.name) &&
(x.publicKey.algorithm.modulusLength == alg.modulusLength) &&
(x.publicKey.type == "public") &&
x.publicKey.extractable &&
(x.publicKey.usages.length == 1) &&
- (x.publicKey.usages[0] == "encrypt") &&
+ (x.publicKey.usages[0] == "verify") &&
exists(x.privateKey) &&
(x.privateKey.algorithm.name == alg.name) &&
(x.privateKey.algorithm.modulusLength == alg.modulusLength) &&
(x.privateKey.type == "private") &&
!x.privateKey.extractable &&
(x.privateKey.usages.length == 1) &&
- (x.privateKey.usages[0] == "decrypt");
+ (x.privateKey.usages[0] == "sign");
}),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Fail cleanly when NSS refuses to generate a key pair",
function() {
var that = this;
var alg = {
- name: "RSAES-PKCS1-v1_5",
+ name: "RSASSA-PKCS1-v1_5",
+ hash: "SHA-256",
modulusLength: 2299, // NSS does not like this key length
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
- crypto.subtle.generateKey(alg, false, ["encrypt"])
+ crypto.subtle.generateKey(alg, false, ["sign"])
.then( error(that), complete(that) );
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"SHA-256 digest",
function() {
@@ -450,17 +457,16 @@ TestArray.addTest(
// -----------------------------------------------------------------------------
TestArray.addTest(
"AES-CBC encrypt",
function () {
var that = this;
function doEncrypt(x) {
- console.log(x);
return crypto.subtle.encrypt(
{ name: "AES-CBC", iv: tv.aes_cbc_enc.iv },
x, tv.aes_cbc_enc.data);
}
crypto.subtle.importKey("raw", tv.aes_cbc_enc.key, "AES-CBC", false, ['encrypt'])
.then(doEncrypt)
.then(
@@ -472,17 +478,16 @@ TestArray.addTest(
// -----------------------------------------------------------------------------
TestArray.addTest(
"AES-CBC encrypt with wrong IV size",
function () {
var that = this;
function encrypt(x, iv) {
- console.log(x);
return crypto.subtle.encrypt(
{ name: "AES-CBC", iv: iv },
x, tv.aes_cbc_enc.data);
}
function doEncrypt(x) {
return encrypt(x, new Uint8Array(15))
.then(
@@ -819,187 +824,125 @@ TestArray.addTest(
error(that),
complete(that, function(x) { return true; })
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
- "RSAES-PKCS#1 encrypt/decrypt round-trip",
- function () {
- var that = this;
- var privKey, pubKey;
- var alg = {name:"RSAES-PKCS1-v1_5"};
-
- var privKey, pubKey, data, ct, pt;
- function setPriv(x) { privKey = x; }
- function setPub(x) { pubKey = x; }
- function doEncrypt() {
- return crypto.subtle.encrypt(alg.name, pubKey, tv.rsaes.data);
- }
- function doDecrypt(x) {
- return crypto.subtle.decrypt(alg.name, privKey, x);
- }
-
- function fail() { error(that); }
-
- Promise.all([
- crypto.subtle.importKey("pkcs8", tv.rsaes.pkcs8, alg, false, ['decrypt'])
- .then(setPriv, error(that)),
- crypto.subtle.importKey("spki", tv.rsaes.spki, alg, false, ['encrypt'])
- .then(setPub, error(that))
- ]).then(doEncrypt, error(that))
- .then(doDecrypt, error(that))
- .then(
- memcmp_complete(that, tv.rsaes.data),
- error(that)
- );
- }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
- "RSAES-PKCS#1 decryption known answer",
- function () {
- var that = this;
- var alg = {name:"RSAES-PKCS1-v1_5"};
-
- function doDecrypt(x) {
- return crypto.subtle.decrypt(alg.name, x, tv.rsaes.result);
- }
- function fail() { error(that); }
-
- crypto.subtle.importKey("pkcs8", tv.rsaes.pkcs8, alg, false, ['decrypt'])
- .then( doDecrypt, fail )
- .then( memcmp_complete(that, tv.rsaes.data), fail );
- }
-);
-
-// -----------------------------------------------------------------------------
-TestArray.addTest(
"RSASSA/SHA-1 signature",
function () {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" };
function doSign(x) {
- console.log("sign");
- console.log(x);
return crypto.subtle.sign(alg.name, x, tv.rsassa.data);
}
- function fail() { console.log("fail"); error(that); }
crypto.subtle.importKey("pkcs8", tv.rsassa.pkcs8, alg, false, ['sign'])
- .then( doSign, fail )
- .then( memcmp_complete(that, tv.rsassa.sig1), fail );
+ .then( doSign )
+ .then( memcmp_complete(that, tv.rsassa.sig1), error(that) );
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSASSA verification (SHA-1)",
function () {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" };
function doVerify(x) {
return crypto.subtle.verify(alg.name, x, tv.rsassa.sig1, tv.rsassa.data);
}
- function fail(x) { error(that); }
crypto.subtle.importKey("spki", tv.rsassa.spki, alg, false, ['verify'])
- .then( doVerify, fail )
+ .then( doVerify )
.then(
complete(that, function(x) { return x; }),
- fail
+ error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSASSA verification (SHA-1), failing verification",
function () {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" };
function doVerify(x) {
return crypto.subtle.verify(alg.name, x, tv.rsassa.sig_fail, tv.rsassa.data);
}
- function fail(x) { error(that); }
crypto.subtle.importKey("spki", tv.rsassa.spki, alg, false, ['verify'])
- .then( doVerify, fail )
+ .then( doVerify )
.then(
complete(that, function(x) { return !x; }),
- fail
+ error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSASSA/SHA-256 signature",
function () {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
function doSign(x) {
return crypto.subtle.sign(alg.name, x, tv.rsassa.data);
}
- function fail(x) { console.log(x); error(that); }
crypto.subtle.importKey("pkcs8", tv.rsassa.pkcs8, alg, false, ['sign'])
- .then( doSign, fail )
- .then( memcmp_complete(that, tv.rsassa.sig256), fail );
+ .then( doSign )
+ .then( memcmp_complete(that, tv.rsassa.sig256), error(that) );
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSASSA verification (SHA-256)",
function () {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
function doVerify(x) {
return crypto.subtle.verify(alg.name, x, tv.rsassa.sig256, tv.rsassa.data);
}
- function fail(x) { error(that); }
crypto.subtle.importKey("spki", tv.rsassa.spki, alg, false, ['verify'])
- .then( doVerify, fail )
+ .then( doVerify )
.then(
complete(that, function(x) { return x; }),
- fail
+ error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSASSA verification (SHA-256), failing verification",
function () {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
var use = ['sign', 'verify'];
function doVerify(x) {
- console.log("verifying")
return crypto.subtle.verify(alg.name, x, tv.rsassa.sig_fail, tv.rsassa.data);
}
- function fail(x) { console.log("failing"); error(that)(x); }
- console.log("running")
crypto.subtle.importKey("spki", tv.rsassa.spki, alg, false, ['verify'])
- .then( doVerify, fail )
+ .then( doVerify )
.then(
complete(that, function(x) { return !x; }),
- fail
+ error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Key wrap known answer, using AES-GCM",
function () {
@@ -1170,30 +1113,28 @@ TestArray.addTest(
return crypto.subtle.wrapKey("jwk", originalKey, wrapKey, wrapAlg);
}
function doUnwrap(wrappedKey) {
return crypto.subtle.unwrapKey("jwk", wrappedKey, wrapKey, wrapAlg,
{ name: "HMAC", hash: "SHA-384"},
true, ['sign', 'verify']);
}
- function temperr(x) { return function(y) { console.log("error in "+x); console.log(y); } }
-
Promise.all([
crypto.subtle.importKey("jwk", tv.aes_gcm_enc.key_jwk,
"AES-GCM", false, ['wrapKey','unwrapKey'])
- .then(function(x) { console.log("wrapKey"); wrapKey = x; }),
+ .then(function(x) { wrapKey = x; }),
crypto.subtle.generateKey(genAlg, true, ['sign', 'verify'])
- .then(function(x) { console.log("originalKey"); originalKey = x; return x; })
+ .then(function(x) { originalKey = x; return x; })
.then(doExport)
.then(function(x) { originalKeyJwk = x; })
])
- .then(doWrap, temperr("initial phase"))
- .then(doUnwrap, temperr("wrap"))
- .then(doExport, temperr("unwrap"))
+ .then(doWrap)
+ .then(doUnwrap)
+ .then(doExport)
.then(
complete(that, function(x) {
return exists(x.k) && x.k == originalKeyJwk.k;
}),
error(that)
);
}
);
@@ -1264,19 +1205,19 @@ TestArray.addTest(
return crypto.subtle.unwrapKey("raw", wrappedKey, wrapKey,
"AES-KW", { name: "HMAC", hash: "SHA-384"},
true, ['sign', 'verify']);
}
Promise.all([
crypto.subtle.importKey("jwk", tv.aes_kw.wrapping_key,
"AES-KW", false, ['wrapKey','unwrapKey'])
- .then(function(x) { console.log("wrapKey"); wrapKey = x; }),
+ .then(function(x) { wrapKey = x; }),
crypto.subtle.generateKey(genAlg, true, ['sign'])
- .then(function(x) { console.log("originalKey"); originalKey = x; return x; })
+ .then(function(x) { originalKey = x; return x; })
.then(doExport)
.then(function(x) { originalKeyJwk = x; })
])
.then(doWrap)
.then(doUnwrap)
.then(doExport)
.then(
complete(that, function(x) {
@@ -1327,17 +1268,17 @@ TestArray.addTest(
function doGenerateRsaOaepKey() {
var alg = {
name: "rsa-OAEP",
hash: "sha-1",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
- return crypto.subtle.generateKey(alg, false, ["encrypt"]);
+ return crypto.subtle.generateKey(alg, false, ["encrypt", "decrypt"]);
}
function doGenerateRsaSsaPkcs1Key() {
var alg = { name: "RSASSA-pkcs1-V1_5", hash: "SHA-1" };
return crypto.subtle.importKey("pkcs8", tv.pkcs8, alg, true, ["sign"]);
}
crypto.subtle.generateKey(alg, false, ["sign"])
@@ -1359,34 +1300,17 @@ TestArray.addTest(
function doSign(x) {
return crypto.subtle.sign("RSASSA-PKCS1-v1_5", x, new Uint8Array());
}
return crypto.subtle.generateKey(alg, false, ["sign"]).then(doSign);
}
- function doCheckRSAES() {
- var alg = {
- name: "RSAES-PKCS1-v1_5",
- modulusLength: 1024,
- publicExponent: new Uint8Array([0x01, 0x00, 0x01])
- };
-
- function doEncrypt(x) {
- var alg = {name: "RSA-OAEP", hash: "SHA-1"};
- return crypto.subtle.encrypt(alg, x.publicKey, new Uint8Array());
- }
-
- return crypto.subtle.generateKey(alg, false, ["encrypt"]).then(doEncrypt);
- }
-
- doCheckRSASSA().then(error(that), function () {
- doCheckRSAES().then(error(that), complete(that));
- });
+ doCheckRSASSA().then(error(that), complete(that));
}
);
/*]]>*/</script>
</head>
<body>
<div id="content">
--- a/dom/crypto/test/test_WebCrypto_ECDH.html
+++ b/dom/crypto/test/test_WebCrypto_ECDH.html
@@ -98,17 +98,17 @@ TestArray.addTest(
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"])
+ return crypto.subtle.generateKey(alg, false, ["encrypt", "decrypt"])
}
function doDerive() {
var alg = { name: "ECDH", public: pubKey };
return crypto.subtle.deriveBits(alg, privKey, 16);
}
doGenerateP256()
@@ -331,22 +331,22 @@ TestArray.addTest(
var data = crypto.getRandomValues(new Uint8Array(1024));
return crypto.subtle.sign("HMAC", x, data)
.then(function (sig) {
return crypto.subtle.verify("HMAC", x, sig, data);
});
}
Promise.all([
- crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_priv, alg, false, ["deriveBits"])
- .then(setPriv, error(that)),
- crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_pub, alg, false, ["deriveBits"])
- .then(setPub, error(that))
- ]).then(doDerive, error(that))
- .then(doSignAndVerify, error(that))
+ crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_priv, alg, false, ["deriveKey"])
+ .then(setPriv),
+ crypto.subtle.importKey("jwk", tv.ecdh_p521.jwk_pub, alg, false, ["deriveKey"])
+ .then(setPub)
+ ]).then(doDerive)
+ .then(doSignAndVerify)
.then(complete(that), error(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"SPKI import/export of public ECDH keys (P-256)",
function () {
--- a/dom/crypto/test/test_WebCrypto_JWK.html
+++ b/dom/crypto/test/test_WebCrypto_JWK.html
@@ -187,18 +187,16 @@ TestArray.addTest(
function doExport(k) {
return crypto.subtle.exportKey("jwk", k);
}
crypto.subtle.importKey("jwk", jwk, alg, true, ['sign'])
.then(doExport)
.then(
complete(that, function(x) {
- window.jwk_priv = x;
- console.log(JSON.stringify(x));
return hasBaseJwkFields(x) &&
hasFields(x, ['n', 'e', 'd', 'p', 'q', 'dp', 'dq', 'qi']) &&
x.kty == 'RSA' &&
x.alg == 'RS256' &&
x.ext &&
shallowArrayEquals(x.key_ops, ['sign']) &&
x.n == jwk.n &&
x.e == jwk.e &&
--- a/dom/crypto/test/test_WebCrypto_PBKDF2.html
+++ b/dom/crypto/test/test_WebCrypto_PBKDF2.html
@@ -41,47 +41,45 @@ TestArray.addTest(
TestArray.addTest(
"Import raw PBKDF2 key and derive bits using HMAC-SHA-1",
function() {
var that = this;
var alg = "PBKDF2";
var key = tv.pbkdf2_sha1.password;
function doDerive(x) {
- console.log("deriving");
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
}
var alg = {
name: "PBKDF2",
hash: "SHA-1",
salt: tv.pbkdf2_sha1.salt,
iterations: tv.pbkdf2_sha1.iterations
};
return crypto.subtle.deriveBits(alg, x, tv.pbkdf2_sha1.length);
}
function fail(x) { console.log("failing"); error(that)(x); }
- crypto.subtle.importKey("raw", key, alg, false, ["deriveKey"])
+ crypto.subtle.importKey("raw", key, alg, false, ["deriveBits"])
.then( doDerive, fail )
.then( memcmp_complete(that, tv.pbkdf2_sha1.derived), fail );
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Import raw PBKDF2 key and derive a new key using HMAC-SHA-1",
function() {
var that = this;
var alg = "PBKDF2";
var key = tv.pbkdf2_sha1.password;
function doDerive(x) {
- console.log("deriving");
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
}
var alg = {
name: "PBKDF2",
hash: "SHA-1",
salt: tv.pbkdf2_sha1.salt,
@@ -156,17 +154,16 @@ TestArray.addTest(
/*TestArray.addTest(
"Import raw PBKDF2 key and derive bits using HMAC-SHA-256",
function() {
var that = this;
var alg = "PBKDF2";
var key = tv.pbkdf2_sha256.password;
function doDerive(x) {
- console.log("deriving");
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
}
var alg = {
name: "PBKDF2",
hash: "SHA-256",
salt: tv.pbkdf2_sha256.salt,
--- a/dom/crypto/test/test_WebCrypto_RSA_OAEP.html
+++ b/dom/crypto/test/test_WebCrypto_RSA_OAEP.html
@@ -115,22 +115,23 @@ TestArray.addTest(
hash: "SHA-1",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
var privKey, pubKey;
function setKey(x) { pubKey = x.publicKey; privKey = x.privateKey; }
function doEncrypt(n) {
+ console.log("entered encrypt("+ n +")");
return function () {
return crypto.subtle.encrypt(alg, pubKey, new Uint8Array(n));
}
}
- crypto.subtle.generateKey(alg, false, ['encrypt'])
+ crypto.subtle.generateKey(alg, false, ['encrypt', 'decrypt'])
.then(setKey, error(that))
.then(doEncrypt(214), error(that))
.then(doEncrypt(215), error(that))
.then(error(that), complete(that));
}
);
// -----------------------------------------------------------------------------
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -240,18 +240,16 @@ var interfaceNamesInGlobalScope =
"Controllers",
// IMPORTANT: Do not change this list without review from a DOM peer!
"ConvolverNode",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Crypto",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "CryptoKey", pref: "dom.webcrypto.enabled"},
// IMPORTANT: Do not change this list without review from a DOM peer!
- {name: "CryptoKeyPair", pref: "dom.webcrypto.enabled"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
"CSS",
// IMPORTANT: Do not change this list without review from a DOM peer!
"CSS2Properties",
// IMPORTANT: Do not change this list without review from a DOM peer!
"CSSCharsetRule",
// IMPORTANT: Do not change this list without review from a DOM peer!
"CSSConditionRule",
// IMPORTANT: Do not change this list without review from a DOM peer!
new file mode 100644
--- /dev/null
+++ b/dom/webidl/KeyAlgorithm.webidl
@@ -0,0 +1,32 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/TR/WebCryptoAPI/
+ */
+
+dictionary KeyAlgorithm {
+ required DOMString name;
+};
+
+dictionary AesKeyAlgorithm : KeyAlgorithm {
+ required unsigned short length;
+};
+
+dictionary EcKeyAlgorithm : KeyAlgorithm {
+ required DOMString namedCurve;
+};
+
+dictionary HmacKeyAlgorithm : KeyAlgorithm {
+ required KeyAlgorithm hash;
+ required unsigned long length;
+};
+
+dictionary RsaHashedKeyAlgorithm : KeyAlgorithm {
+ required unsigned short modulusLength;
+ required Uint8Array publicExponent;
+ required KeyAlgorithm hash;
+};
+
--- a/dom/webidl/SubtleCrypto.webidl
+++ b/dom/webidl/SubtleCrypto.webidl
@@ -4,146 +4,107 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://www.w3.org/TR/WebCryptoAPI/
*/
typedef DOMString KeyType;
typedef DOMString KeyUsage;
+typedef DOMString NamedCurve;
typedef Uint8Array BigInteger;
-/***** KeyAlgorithm interfaces *****/
-
-[NoInterfaceObject]
-interface KeyAlgorithm {
- readonly attribute DOMString name;
-};
-
-[NoInterfaceObject]
-interface AesKeyAlgorithm : KeyAlgorithm {
- readonly attribute unsigned short length;
-};
-
-[NoInterfaceObject]
-interface HmacKeyAlgorithm : KeyAlgorithm {
- readonly attribute KeyAlgorithm hash;
- readonly attribute unsigned long length;
-};
-
-[NoInterfaceObject]
-interface RsaKeyAlgorithm : KeyAlgorithm {
- readonly attribute unsigned long modulusLength;
- [Throws]
- readonly attribute BigInteger publicExponent;
-};
-
-[NoInterfaceObject]
-interface RsaHashedKeyAlgorithm : RsaKeyAlgorithm {
- readonly attribute KeyAlgorithm hash;
-};
-
-[NoInterfaceObject]
-interface EcKeyAlgorithm : KeyAlgorithm {
- readonly attribute NamedCurve namedCurve;
-};
-
-
/***** Algorithm dictionaries *****/
dictionary Algorithm {
- DOMString name;
+ required DOMString name;
};
dictionary AesCbcParams : Algorithm {
- CryptoOperationData iv;
+ required CryptoOperationData iv;
};
dictionary AesCtrParams : Algorithm {
- CryptoOperationData counter;
- [EnforceRange] octet length;
+ required CryptoOperationData counter;
+ [EnforceRange] required octet length;
};
dictionary AesGcmParams : Algorithm {
- CryptoOperationData iv;
+ required CryptoOperationData iv;
CryptoOperationData additionalData;
[EnforceRange] octet tagLength;
};
dictionary HmacImportParams : Algorithm {
- AlgorithmIdentifier hash;
+ required AlgorithmIdentifier hash;
};
dictionary Pbkdf2Params : Algorithm {
- CryptoOperationData salt;
- [EnforceRange] unsigned long iterations;
- AlgorithmIdentifier hash;
+ required CryptoOperationData salt;
+ [EnforceRange] required unsigned long iterations;
+ required AlgorithmIdentifier hash;
};
dictionary RsaHashedImportParams {
- AlgorithmIdentifier hash;
+ required AlgorithmIdentifier hash;
};
dictionary AesKeyGenParams : Algorithm {
- [EnforceRange] unsigned short length;
+ [EnforceRange] required unsigned short length;
};
dictionary HmacKeyGenParams : Algorithm {
- AlgorithmIdentifier hash;
+ required AlgorithmIdentifier hash;
[EnforceRange] unsigned long length;
};
-dictionary RsaKeyGenParams : Algorithm {
- [EnforceRange] unsigned long modulusLength;
- BigInteger publicExponent;
-};
-
-dictionary RsaHashedKeyGenParams : RsaKeyGenParams {
- AlgorithmIdentifier hash;
+dictionary RsaHashedKeyGenParams : Algorithm {
+ [EnforceRange] required unsigned long modulusLength;
+ required BigInteger publicExponent;
+ required AlgorithmIdentifier hash;
};
dictionary RsaOaepParams : Algorithm {
- CryptoOperationData? label;
+ CryptoOperationData label;
};
dictionary DhKeyGenParams : Algorithm {
- BigInteger prime;
- BigInteger generator;
+ required BigInteger prime;
+ required BigInteger generator;
};
-typedef DOMString NamedCurve;
dictionary EcKeyGenParams : Algorithm {
- NamedCurve namedCurve;
+ required NamedCurve namedCurve;
};
dictionary AesDerivedKeyParams : Algorithm {
- [EnforceRange] unsigned long length;
+ [EnforceRange] required unsigned long length;
};
dictionary HmacDerivedKeyParams : HmacImportParams {
[EnforceRange] unsigned long length;
};
dictionary EcdhKeyDeriveParams : Algorithm {
- CryptoKey public;
+ required CryptoKey public;
};
/***** JWK *****/
dictionary RsaOtherPrimesInfo {
// The following fields are defined in Section 6.3.2.7 of JSON Web Algorithms
- DOMString r;
- DOMString d;
- DOMString t;
+ required DOMString r;
+ required DOMString d;
+ required DOMString t;
};
dictionary JsonWebKey {
// The following fields are defined in Section 3.1 of JSON Web Key
- DOMString kty;
+ required DOMString kty;
DOMString use;
sequence<DOMString> key_ops;
DOMString alg;
// The following fields are defined in JSON Web Key Parameters Registration
boolean ext;
// The following fields are defined in Section 6 of JSON Web Algorithms
@@ -164,24 +125,23 @@ dictionary JsonWebKey {
/***** The Main API *****/
[Pref="dom.webcrypto.enabled"]
interface CryptoKey {
readonly attribute KeyType type;
readonly attribute boolean extractable;
- readonly attribute KeyAlgorithm algorithm;
+ [Cached, Constant, Throws] readonly attribute object algorithm;
[Cached, Constant, Frozen] readonly attribute sequence<KeyUsage> usages;
};
-[Pref="dom.webcrypto.enabled"]
-interface CryptoKeyPair {
- readonly attribute CryptoKey publicKey;
- readonly attribute CryptoKey privateKey;
+dictionary CryptoKeyPair {
+ required CryptoKey publicKey;
+ required CryptoKey privateKey;
};
typedef DOMString KeyFormat;
typedef (ArrayBufferView or ArrayBuffer) CryptoOperationData;
typedef (object or DOMString) AlgorithmIdentifier;
[Pref="dom.webcrypto.enabled"]
interface SubtleCrypto {
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -233,16 +233,17 @@ WEBIDL_FILES = [
'InputEvent.webidl',
'InputMethod.webidl',
'InspectorUtils.webidl',
'InstallEvent.webidl',
'InstallPhaseEvent.webidl',
'InterAppConnection.webidl',
'InterAppConnectionRequest.webidl',
'InterAppMessagePort.webidl',
+ 'KeyAlgorithm.webidl',
'KeyboardEvent.webidl',
'KeyEvent.webidl',
'LegacyQueryInterface.webidl',
'LinkStyle.webidl',
'LocalMediaStream.webidl',
'Location.webidl',
'MediaElementAudioSourceNode.webidl',
'MediaError.webidl',