/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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_CryptoKey_h #define mozilla_dom_CryptoKey_h #include "nsCycleCollectionParticipant.h" #include "nsWrapperCache.h" #include "nsIGlobalObject.h" #include "nsNSSShutDown.h" #include "pk11pub.h" #include "keyhi.h" #include "ScopedNSSTypes.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. We store everything besides the key data itself in a 32-bit bitmask, with the following structure (byte-aligned for simplicity, in order from least to most significant): Bits Usage 0 Extractable 1-7 [reserved] 8-15 KeyType 16-23 KeyUsage 24-31 [reserved] In the order of a hex value for a uint32_t 3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |~~~~~~~~~~~~~~~| Usage | Type |~~~~~~~~~~~~~|E| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Thus, internally, a key has the following fields: * uint32_t - flags for extractable, usage, type * KeyAlgorithm - the algorithm (which must serialize/deserialize itself) * The actual keys (which the CryptoKey must serialize) */ struct JsonWebKey; class CryptoKey final : public nsISupports, public nsWrapperCache, public nsNSSShutDownObject { public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CryptoKey) static const uint32_t CLEAR_EXTRACTABLE = 0xFFFFFFE; static const uint32_t EXTRACTABLE = 0x00000001; static const uint32_t CLEAR_TYPE = 0xFFFF00FF; static const uint32_t TYPE_MASK = 0x0000FF00; enum KeyType { UNKNOWN = 0x00000000, SECRET = 0x00000100, PUBLIC = 0x00000200, PRIVATE = 0x00000300 }; static const uint32_t CLEAR_USAGES = 0xFF00FFFF; static const uint32_t USAGES_MASK = 0x00FF0000; enum KeyUsage { ENCRYPT = 0x00010000, DECRYPT = 0x00020000, SIGN = 0x00040000, VERIFY = 0x00080000, DERIVEKEY = 0x00100000, DERIVEBITS = 0x00200000, WRAPKEY = 0x00400000, UNWRAPKEY = 0x00800000 }; explicit CryptoKey(nsIGlobalObject* aWindow); nsIGlobalObject* GetParentObject() const { return mGlobal; } virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; // WebIDL methods void GetType(nsString& aRetVal) const; bool Extractable() 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); nsresult AddPublicKeyData(SECKEYPublicKey* point); 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); nsresult SetSymKey(const CryptoBuffer& aSymKey); nsresult SetPrivateKey(SECKEYPrivateKey* aPrivateKey); nsresult 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 // or SECKEY_DestroyPublicKey. const CryptoBuffer& GetSymKey() const; SECKEYPrivateKey* GetPrivateKey() const; SECKEYPublicKey* GetPublicKey() const; // For nsNSSShutDownObject virtual void virtualDestroyNSSReference() override; void destructorSafeDestroyNSSReference(); // Serialization and deserialization convenience methods // Note: // 1. The inputs aKeyData are non-const only because the NSS import // functions lack the const modifier. They should not be modified. // 2. All of the NSS key objects returned need to be freed by the caller. static SECKEYPrivateKey* PrivateKeyFromPkcs8(CryptoBuffer& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static nsresult PrivateKeyToPkcs8(SECKEYPrivateKey* aPrivKey, CryptoBuffer& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static SECKEYPublicKey* PublicKeyFromSpki(CryptoBuffer& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static nsresult PublicKeyToSpki(SECKEYPublicKey* aPubKey, CryptoBuffer& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static SECKEYPrivateKey* PrivateKeyFromJwk(const JsonWebKey& aJwk, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static nsresult PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey, JsonWebKey& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static SECKEYPublicKey* PublicKeyFromJwk(const JsonWebKey& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static nsresult PublicKeyToJwk(SECKEYPublicKey* aPubKey, JsonWebKey& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static SECKEYPublicKey* PublicDhKeyFromRaw(CryptoBuffer& aKeyData, const CryptoBuffer& aPrime, const CryptoBuffer& aGenerator, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static nsresult PublicDhKeyToRaw(SECKEYPublicKey* aPubKey, CryptoBuffer& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static SECKEYPublicKey* PublicECKeyFromRaw(CryptoBuffer& aKeyData, const nsString& aNamedCurve, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static nsresult PublicECKeyToRaw(SECKEYPublicKey* aPubKey, CryptoBuffer& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static bool PublicKeyValid(SECKEYPublicKey* aPubKey); // Structured clone methods use these to clone keys bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const; bool ReadStructuredClone(JSStructuredCloneReader* aReader); private: ~CryptoKey(); RefPtr<nsIGlobalObject> mGlobal; uint32_t mAttributes; // see above KeyAlgorithmProxy mAlgorithm; // Only one key handle should be set, according to the KeyType CryptoBuffer mSymKey; ScopedSECKEYPrivateKey mPrivateKey; ScopedSECKEYPublicKey mPublicKey; }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_CryptoKey_h