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