1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_CryptoKey_h 8 #define mozilla_dom_CryptoKey_h 9 10 #include <cstdint> 11 #include "ErrorList.h" 12 #include "ScopedNSSTypes.h" 13 #include "js/RootingAPI.h" 14 #include "keythi.h" 15 #include "mozilla/AlreadyAddRefed.h" 16 #include "mozilla/Assertions.h" 17 #include "mozilla/RefPtr.h" 18 #include "mozilla/dom/BindingDeclarations.h" 19 #include "mozilla/dom/CryptoBuffer.h" 20 #include "mozilla/dom/KeyAlgorithmProxy.h" 21 #include "nsCycleCollectionParticipant.h" 22 #include "nsIGlobalObject.h" 23 #include "nsISupports.h" 24 #include "nsStringFwd.h" 25 #include "nsTArrayForwardDeclare.h" 26 #include "nsWrapperCache.h" 27 28 #define CRYPTOKEY_SC_VERSION 0x00000001 29 30 class JSObject; 31 class nsIGlobalObject; 32 struct JSContext; 33 struct JSStructuredCloneReader; 34 struct JSStructuredCloneWriter; 35 36 namespace mozilla { 37 38 class ErrorResult; 39 40 namespace dom { 41 42 /* 43 44 The internal structure of keys is dictated by the need for cloning. 45 We store everything besides the key data itself in a 32-bit bitmask, 46 with the following structure (byte-aligned for simplicity, in order 47 from least to most significant): 48 49 Bits Usage 50 0 Extractable 51 1-7 [reserved] 52 8-15 KeyType 53 16-23 KeyUsage 54 24-31 [reserved] 55 56 In the order of a hex value for a uint32_t 57 58 3 2 1 0 59 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 60 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 61 |~~~~~~~~~~~~~~~| Usage | Type |~~~~~~~~~~~~~|E| 62 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 63 64 Thus, internally, a key has the following fields: 65 * uint32_t - flags for extractable, usage, type 66 * KeyAlgorithm - the algorithm (which must serialize/deserialize itself) 67 * The actual keys (which the CryptoKey must serialize) 68 69 */ 70 71 struct JsonWebKey; 72 73 class CryptoKey final : public nsISupports, public nsWrapperCache { 74 public: 75 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 76 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CryptoKey) 77 78 static const uint32_t CLEAR_EXTRACTABLE = 0xFFFFFFE; 79 static const uint32_t EXTRACTABLE = 0x00000001; 80 81 static const uint32_t CLEAR_TYPE = 0xFFFF00FF; 82 static const uint32_t TYPE_MASK = 0x0000FF00; 83 enum KeyType { 84 UNKNOWN = 0x00000000, 85 SECRET = 0x00000100, 86 PUBLIC = 0x00000200, 87 PRIVATE = 0x00000300 88 }; 89 90 static const uint32_t CLEAR_USAGES = 0xFF00FFFF; 91 static const uint32_t USAGES_MASK = 0x00FF0000; 92 enum KeyUsage { 93 ENCRYPT = 0x00010000, 94 DECRYPT = 0x00020000, 95 SIGN = 0x00040000, 96 VERIFY = 0x00080000, 97 DERIVEKEY = 0x00100000, 98 DERIVEBITS = 0x00200000, 99 WRAPKEY = 0x00400000, 100 UNWRAPKEY = 0x00800000 101 }; 102 103 explicit CryptoKey(nsIGlobalObject* aWindow); 104 GetParentObject()105 nsIGlobalObject* GetParentObject() const { return mGlobal; } 106 107 virtual JSObject* WrapObject(JSContext* aCx, 108 JS::Handle<JSObject*> aGivenProto) override; 109 110 // WebIDL methods 111 void GetType(nsString& aRetVal) const; 112 bool Extractable() const; 113 void GetAlgorithm(JSContext* cx, JS::MutableHandle<JSObject*> aRetVal, 114 ErrorResult& aRv) const; 115 void GetUsages(nsTArray<nsString>& aRetVal) const; 116 117 // The below methods are not exposed to JS, but C++ can use 118 // them to manipulate the object 119 120 KeyAlgorithmProxy& Algorithm(); 121 const KeyAlgorithmProxy& Algorithm() const; 122 KeyType GetKeyType() const; 123 nsresult SetType(const nsString& aType); 124 void SetType(KeyType aType); 125 void SetExtractable(bool aExtractable); 126 nsresult AddPublicKeyData(SECKEYPublicKey* point); 127 void ClearUsages(); 128 nsresult AddUsage(const nsString& aUsage); 129 nsresult AddAllowedUsage(const nsString& aUsage, const nsString& aAlgorithm); 130 nsresult AddAllowedUsageIntersecting(const nsString& aUsage, 131 const nsString& aAlgorithm, 132 uint32_t aUsageMask = USAGES_MASK); 133 void AddUsage(KeyUsage aUsage); 134 bool HasAnyUsage(); 135 bool HasUsage(KeyUsage aUsage); 136 bool HasUsageOtherThan(uint32_t aUsages); 137 static bool IsRecognizedUsage(const nsString& aUsage); 138 static bool AllUsagesRecognized(const Sequence<nsString>& aUsages); 139 static uint32_t GetAllowedUsagesForAlgorithm(const nsString& aAlgorithm); 140 141 nsresult SetSymKey(const CryptoBuffer& aSymKey); 142 nsresult SetPrivateKey(SECKEYPrivateKey* aPrivateKey); 143 nsresult SetPublicKey(SECKEYPublicKey* aPublicKey); 144 145 // Accessors for the keys themselves 146 const CryptoBuffer& GetSymKey() const; 147 UniqueSECKEYPrivateKey GetPrivateKey() const; 148 UniqueSECKEYPublicKey GetPublicKey() const; 149 150 // Serialization and deserialization convenience methods 151 // Note: 152 // 1. The inputs aKeyData are non-const only because the NSS import 153 // functions lack the const modifier. They should not be modified. 154 // 2. All of the NSS key objects returned need to be freed by the caller. 155 static UniqueSECKEYPrivateKey PrivateKeyFromPkcs8(CryptoBuffer& aKeyData); 156 static nsresult PrivateKeyToPkcs8(SECKEYPrivateKey* aPrivKey, 157 CryptoBuffer& aRetVal); 158 159 static UniqueSECKEYPublicKey PublicKeyFromSpki(CryptoBuffer& aKeyData); 160 static nsresult PublicKeyToSpki(SECKEYPublicKey* aPubKey, 161 CryptoBuffer& aRetVal); 162 163 static UniqueSECKEYPrivateKey PrivateKeyFromJwk(const JsonWebKey& aJwk); 164 static nsresult PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey, 165 JsonWebKey& aRetVal); 166 167 static UniqueSECKEYPublicKey PublicKeyFromJwk(const JsonWebKey& aKeyData); 168 static nsresult PublicKeyToJwk(SECKEYPublicKey* aPubKey, JsonWebKey& aRetVal); 169 170 static UniqueSECKEYPublicKey PublicECKeyFromRaw(CryptoBuffer& aKeyData, 171 const nsString& aNamedCurve); 172 static nsresult PublicECKeyToRaw(SECKEYPublicKey* aPubKey, 173 CryptoBuffer& aRetVal); 174 175 static bool PublicKeyValid(SECKEYPublicKey* aPubKey); 176 177 // Structured clone methods use these to clone keys 178 bool WriteStructuredClone(JSContext* aCx, 179 JSStructuredCloneWriter* aWriter) const; 180 static already_AddRefed<CryptoKey> ReadStructuredClone( 181 JSContext* aCx, nsIGlobalObject* aGlobal, 182 JSStructuredCloneReader* aReader); 183 184 private: 185 ~CryptoKey() = default; 186 187 RefPtr<nsIGlobalObject> mGlobal; 188 uint32_t mAttributes; // see above 189 KeyAlgorithmProxy mAlgorithm; 190 191 // Only one key handle should be set, according to the KeyType 192 CryptoBuffer mSymKey; 193 UniqueSECKEYPrivateKey mPrivateKey; 194 UniqueSECKEYPublicKey mPublicKey; 195 }; 196 197 } // namespace dom 198 } // namespace mozilla 199 200 #endif // mozilla_dom_CryptoKey_h 201