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_WebCryptoTask_h
8 : #define mozilla_dom_WebCryptoTask_h
9 :
10 : #include "ScopedNSSTypes.h"
11 : #include "mozilla/dom/CryptoKey.h"
12 : #include "mozilla/dom/DOMException.h"
13 : #include "mozilla/dom/Promise.h"
14 : #include "mozilla/dom/SubtleCryptoBinding.h"
15 : #include "nsIGlobalObject.h"
16 : #include "nsNSSShutDown.h"
17 :
18 : namespace mozilla {
19 : namespace dom {
20 :
21 : typedef ArrayBufferViewOrArrayBuffer CryptoOperationData;
22 : typedef ArrayBufferViewOrArrayBuffer KeyData;
23 :
24 : /*
25 :
26 : The execution of a WebCryptoTask happens in several phases
27 :
28 : 1. Constructor
29 : 2. BeforeCrypto
30 : 3. CalculateResult -> DoCrypto
31 : 4. AfterCrypto
32 : 5. Resolve or FailWithError
33 : 6. Cleanup
34 :
35 : If any of these steps produces an error (setting mEarlyRv), then
36 : subsequent steps will not proceed. If the constructor or BeforeCrypto
37 : sets mEarlyComplete to true, then we will skip step 3, saving the
38 : thread overhead.
39 :
40 : In general, the constructor should handle any parsing steps that
41 : require JS context, and otherwise just cache information for later
42 : steps to use.
43 :
44 : All steps besides step 3 occur on the main thread, so they should
45 : avoid blocking operations.
46 :
47 : Only step 3 is guarded to ensure that NSS has not been shutdown,
48 : so all NSS interactions should occur in DoCrypto
49 :
50 : Cleanup should execute regardless of what else happens.
51 :
52 : */
53 :
54 : #define MAYBE_EARLY_FAIL(rv) \
55 : if (NS_FAILED(rv)) { \
56 : FailWithError(rv); \
57 : Skip(); \
58 : return; \
59 : }
60 :
61 : class WebCryptoTask : public CancelableRunnable,
62 : public nsNSSShutDownObject
63 : {
64 : public:
65 : virtual void DispatchWithPromise(Promise* aResultPromise);
66 :
67 0 : void Skip()
68 : {
69 0 : virtualDestroyNSSReference();
70 0 : }
71 :
72 : protected:
73 : static WebCryptoTask* CreateEncryptDecryptTask(JSContext* aCx,
74 : const ObjectOrString& aAlgorithm,
75 : CryptoKey& aKey,
76 : const CryptoOperationData& aData,
77 : bool aEncrypt);
78 :
79 : static WebCryptoTask* CreateSignVerifyTask(JSContext* aCx,
80 : const ObjectOrString& aAlgorithm,
81 : CryptoKey& aKey,
82 : const CryptoOperationData& aSignature,
83 : const CryptoOperationData& aData,
84 : bool aSign);
85 :
86 : public:
87 0 : static WebCryptoTask* CreateEncryptTask(JSContext* aCx,
88 : const ObjectOrString& aAlgorithm,
89 : CryptoKey& aKey,
90 : const CryptoOperationData& aData)
91 : {
92 0 : return CreateEncryptDecryptTask(aCx, aAlgorithm, aKey, aData, true);
93 : }
94 :
95 0 : static WebCryptoTask* CreateDecryptTask(JSContext* aCx,
96 : const ObjectOrString& aAlgorithm,
97 : CryptoKey& aKey,
98 : const CryptoOperationData& aData)
99 : {
100 0 : return CreateEncryptDecryptTask(aCx, aAlgorithm, aKey, aData, false);
101 : }
102 :
103 0 : static WebCryptoTask* CreateSignTask(JSContext* aCx,
104 : const ObjectOrString& aAlgorithm,
105 : CryptoKey& aKey,
106 : const CryptoOperationData& aData)
107 : {
108 0 : CryptoOperationData dummy;
109 0 : dummy.SetAsArrayBuffer(aCx);
110 0 : return CreateSignVerifyTask(aCx, aAlgorithm, aKey, dummy, aData, true);
111 : }
112 :
113 0 : static WebCryptoTask* CreateVerifyTask(JSContext* aCx,
114 : const ObjectOrString& aAlgorithm,
115 : CryptoKey& aKey,
116 : const CryptoOperationData& aSignature,
117 : const CryptoOperationData& aData)
118 : {
119 0 : return CreateSignVerifyTask(aCx, aAlgorithm, aKey, aSignature, aData, false);
120 : }
121 :
122 : static WebCryptoTask* CreateDigestTask(JSContext* aCx,
123 : const ObjectOrString& aAlgorithm,
124 : const CryptoOperationData& aData);
125 :
126 : static WebCryptoTask* CreateImportKeyTask(nsIGlobalObject* aGlobal,
127 : JSContext* aCx,
128 : const nsAString& aFormat,
129 : JS::Handle<JSObject*> aKeyData,
130 : const ObjectOrString& aAlgorithm,
131 : bool aExtractable,
132 : const Sequence<nsString>& aKeyUsages);
133 : static WebCryptoTask* CreateExportKeyTask(const nsAString& aFormat,
134 : CryptoKey& aKey);
135 : static WebCryptoTask* CreateGenerateKeyTask(nsIGlobalObject* aGlobal,
136 : JSContext* aCx,
137 : const ObjectOrString& aAlgorithm,
138 : bool aExtractable,
139 : const Sequence<nsString>& aKeyUsages);
140 :
141 : static WebCryptoTask* CreateDeriveKeyTask(nsIGlobalObject* aGlobal,
142 : JSContext* aCx,
143 : const ObjectOrString& aAlgorithm,
144 : CryptoKey& aBaseKey,
145 : const ObjectOrString& aDerivedKeyType,
146 : bool extractable,
147 : const Sequence<nsString>& aKeyUsages);
148 : static WebCryptoTask* CreateDeriveBitsTask(JSContext* aCx,
149 : const ObjectOrString& aAlgorithm,
150 : CryptoKey& aKey,
151 : uint32_t aLength);
152 :
153 : static WebCryptoTask* CreateWrapKeyTask(JSContext* aCx,
154 : const nsAString& aFormat,
155 : CryptoKey& aKey,
156 : CryptoKey& aWrappingKey,
157 : const ObjectOrString& aWrapAlgorithm);
158 : static WebCryptoTask* CreateUnwrapKeyTask(nsIGlobalObject* aGlobal,
159 : JSContext* aCx,
160 : const nsAString& aFormat,
161 : const ArrayBufferViewOrArrayBuffer& aWrappedKey,
162 : CryptoKey& aUnwrappingKey,
163 : const ObjectOrString& aUnwrapAlgorithm,
164 : const ObjectOrString& aUnwrappedKeyAlgorithm,
165 : bool aExtractable,
166 : const Sequence<nsString>& aKeyUsages);
167 :
168 : protected:
169 : RefPtr<Promise> mResultPromise;
170 : nsresult mEarlyRv;
171 : bool mEarlyComplete;
172 :
173 : WebCryptoTask();
174 : virtual ~WebCryptoTask();
175 :
176 0 : bool IsOnOriginalThread() {
177 0 : return !mOriginalEventTarget || mOriginalEventTarget->IsOnCurrentThread();
178 : }
179 :
180 : // For things that need to happen on the main thread
181 : // either before or after CalculateResult
182 0 : virtual nsresult BeforeCrypto() { return NS_OK; }
183 0 : virtual nsresult DoCrypto() { return NS_OK; }
184 0 : virtual nsresult AfterCrypto() { return NS_OK; }
185 0 : virtual void Resolve() {}
186 0 : virtual void Cleanup() {}
187 :
188 : void FailWithError(nsresult aRv);
189 :
190 : // Subclasses should override this method if they keep references to
191 : // any NSS objects, e.g., SECKEYPrivateKey or PK11SymKey.
192 0 : virtual void ReleaseNSSResources() {}
193 :
194 : virtual nsresult CalculateResult() final;
195 :
196 : virtual void CallCallback(nsresult rv) final;
197 :
198 : private:
199 : NS_IMETHOD Run() override final;
200 : nsresult Cancel() override final;
201 :
202 : virtual void
203 0 : virtualDestroyNSSReference() override final
204 : {
205 0 : MOZ_ASSERT(IsOnOriginalThread());
206 :
207 0 : if (!mReleasedNSSResources) {
208 0 : mReleasedNSSResources = true;
209 0 : ReleaseNSSResources();
210 : }
211 0 : }
212 :
213 : class InternalWorkerHolder;
214 :
215 : nsCOMPtr<nsISerialEventTarget> mOriginalEventTarget;
216 : RefPtr<InternalWorkerHolder> mWorkerHolder;
217 : bool mReleasedNSSResources;
218 : nsresult mRv;
219 : };
220 :
221 : // XXX This class is declared here (unlike others) to enable reuse by WebRTC.
222 0 : class GenerateAsymmetricKeyTask : public WebCryptoTask
223 : {
224 : public:
225 : GenerateAsymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
226 : const ObjectOrString& aAlgorithm, bool aExtractable,
227 : const Sequence<nsString>& aKeyUsages);
228 : protected:
229 : UniquePLArenaPool mArena;
230 : UniquePtr<CryptoKeyPair> mKeyPair;
231 : nsString mAlgName;
232 : CK_MECHANISM_TYPE mMechanism;
233 : PK11RSAGenParams mRsaParams;
234 : SECKEYDHParams mDhParams;
235 : nsString mNamedCurve;
236 :
237 : virtual void ReleaseNSSResources() override;
238 : virtual nsresult DoCrypto() override;
239 : virtual void Resolve() override;
240 : virtual void Cleanup() override;
241 :
242 : private:
243 : UniqueSECKEYPublicKey mPublicKey;
244 : UniqueSECKEYPrivateKey mPrivateKey;
245 : };
246 :
247 : } // namespace dom
248 : } // namespace mozilla
249 :
250 : #endif // mozilla_dom_WebCryptoTask_h
|