diff options
Diffstat (limited to 'dom/crypto/CryptoKey.h')
-rw-r--r-- | dom/crypto/CryptoKey.h | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/dom/crypto/CryptoKey.h b/dom/crypto/CryptoKey.h new file mode 100644 index 0000000000..d09d2cd66c --- /dev/null +++ b/dom/crypto/CryptoKey.h @@ -0,0 +1,200 @@ +/* -*- 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 <cstdint> +#include "ErrorList.h" +#include "ScopedNSSTypes.h" +#include "js/RootingAPI.h" +#include "keythi.h" +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Assertions.h" +#include "mozilla/RefPtr.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/CryptoBuffer.h" +#include "mozilla/dom/KeyAlgorithmProxy.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIGlobalObject.h" +#include "nsISupports.h" +#include "nsStringFwd.h" +#include "nsTArrayForwardDeclare.h" +#include "nsWrapperCache.h" + +#define CRYPTOKEY_SC_VERSION 0x00000001 + +class JSObject; +class nsIGlobalObject; +struct JSContext; +struct JSStructuredCloneReader; +struct JSStructuredCloneWriter; + +namespace mozilla { + +class ErrorResult; + +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: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_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 AddAllowedUsage(const nsString& aUsage, const nsString& aAlgorithm); + nsresult AddAllowedUsageIntersecting(const nsString& aUsage, + const nsString& aAlgorithm, + uint32_t aUsageMask = USAGES_MASK); + 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); + static uint32_t GetAllowedUsagesForAlgorithm(const nsString& aAlgorithm); + + nsresult SetSymKey(const CryptoBuffer& aSymKey); + nsresult SetPrivateKey(SECKEYPrivateKey* aPrivateKey); + nsresult SetPublicKey(SECKEYPublicKey* aPublicKey); + + // Accessors for the keys themselves + const CryptoBuffer& GetSymKey() const; + UniqueSECKEYPrivateKey GetPrivateKey() const; + UniqueSECKEYPublicKey GetPublicKey() const; + + // 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 UniqueSECKEYPrivateKey PrivateKeyFromPkcs8(CryptoBuffer& aKeyData); + static nsresult PrivateKeyToPkcs8(SECKEYPrivateKey* aPrivKey, + CryptoBuffer& aRetVal); + + static UniqueSECKEYPublicKey PublicKeyFromSpki(CryptoBuffer& aKeyData); + static nsresult PublicKeyToSpki(SECKEYPublicKey* aPubKey, + CryptoBuffer& aRetVal); + + static UniqueSECKEYPrivateKey PrivateKeyFromJwk(const JsonWebKey& aJwk); + static nsresult PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey, + JsonWebKey& aRetVal); + + static UniqueSECKEYPublicKey PublicKeyFromJwk(const JsonWebKey& aKeyData); + static nsresult PublicKeyToJwk(SECKEYPublicKey* aPubKey, JsonWebKey& aRetVal); + + static UniqueSECKEYPublicKey PublicECKeyFromRaw(CryptoBuffer& aKeyData, + const nsString& aNamedCurve); + static nsresult PublicECKeyToRaw(SECKEYPublicKey* aPubKey, + CryptoBuffer& aRetVal); + + static bool PublicKeyValid(SECKEYPublicKey* aPubKey); + + // Structured clone methods use these to clone keys + bool WriteStructuredClone(JSContext* aCx, + JSStructuredCloneWriter* aWriter) const; + static already_AddRefed<CryptoKey> ReadStructuredClone( + JSContext* aCx, nsIGlobalObject* aGlobal, + JSStructuredCloneReader* aReader); + + private: + ~CryptoKey() = default; + + RefPtr<nsIGlobalObject> mGlobal; + uint32_t mAttributes; // see above + KeyAlgorithmProxy mAlgorithm; + + // Only one key handle should be set, according to the KeyType + CryptoBuffer mSymKey; + UniqueSECKEYPrivateKey mPrivateKey; + UniqueSECKEYPublicKey mPublicKey; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_CryptoKey_h |