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