tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WebCryptoTask.h (7558B)


      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 
     17 namespace mozilla::dom {
     18 
     19 class ThreadSafeWorkerRef;
     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    return;                  \
     58  }
     59 
     60 class WebCryptoTask : public CancelableRunnable {
     61 public:
     62  virtual void DispatchWithPromise(Promise* aResultPromise);
     63 
     64 protected:
     65  static WebCryptoTask* CreateEncryptDecryptTask(
     66      JSContext* aCx, const ObjectOrString& aAlgorithm, CryptoKey& aKey,
     67      const CryptoOperationData& aData, bool aEncrypt);
     68 
     69  static WebCryptoTask* CreateSignVerifyTask(
     70      JSContext* aCx, const ObjectOrString& aAlgorithm, CryptoKey& aKey,
     71      const CryptoOperationData& aSignature, const CryptoOperationData& aData,
     72      bool aSign);
     73 
     74 public:
     75  static WebCryptoTask* CreateEncryptTask(JSContext* aCx,
     76                                          const ObjectOrString& aAlgorithm,
     77                                          CryptoKey& aKey,
     78                                          const CryptoOperationData& aData) {
     79    return CreateEncryptDecryptTask(aCx, aAlgorithm, aKey, aData, true);
     80  }
     81 
     82  static WebCryptoTask* CreateDecryptTask(JSContext* aCx,
     83                                          const ObjectOrString& aAlgorithm,
     84                                          CryptoKey& aKey,
     85                                          const CryptoOperationData& aData) {
     86    return CreateEncryptDecryptTask(aCx, aAlgorithm, aKey, aData, false);
     87  }
     88 
     89  static WebCryptoTask* CreateSignTask(JSContext* aCx,
     90                                       const ObjectOrString& aAlgorithm,
     91                                       CryptoKey& aKey,
     92                                       const CryptoOperationData& aData) {
     93    CryptoOperationData dummy;
     94    (void)dummy.SetAsArrayBuffer(aCx);
     95    return CreateSignVerifyTask(aCx, aAlgorithm, aKey, dummy, aData, true);
     96  }
     97 
     98  static WebCryptoTask* CreateVerifyTask(JSContext* aCx,
     99                                         const ObjectOrString& aAlgorithm,
    100                                         CryptoKey& aKey,
    101                                         const CryptoOperationData& aSignature,
    102                                         const CryptoOperationData& aData) {
    103    return CreateSignVerifyTask(aCx, aAlgorithm, aKey, aSignature, aData,
    104                                false);
    105  }
    106 
    107  static WebCryptoTask* CreateDigestTask(JSContext* aCx,
    108                                         const ObjectOrString& aAlgorithm,
    109                                         const CryptoOperationData& aData);
    110 
    111  static WebCryptoTask* CreateImportKeyTask(
    112      nsIGlobalObject* aGlobal, JSContext* aCx, const nsAString& aFormat,
    113      JS::Handle<JSObject*> aKeyData, const ObjectOrString& aAlgorithm,
    114      bool aExtractable, const Sequence<nsString>& aKeyUsages);
    115  static WebCryptoTask* CreateExportKeyTask(const nsAString& aFormat,
    116                                            CryptoKey& aKey);
    117  static WebCryptoTask* CreateGenerateKeyTask(
    118      nsIGlobalObject* aGlobal, JSContext* aCx,
    119      const ObjectOrString& aAlgorithm, bool aExtractable,
    120      const Sequence<nsString>& aKeyUsages);
    121 
    122  static WebCryptoTask* CreateDeriveKeyTask(
    123      nsIGlobalObject* aGlobal, JSContext* aCx,
    124      const ObjectOrString& aAlgorithm, CryptoKey& aBaseKey,
    125      const ObjectOrString& aDerivedKeyType, bool extractable,
    126      const Sequence<nsString>& aKeyUsages);
    127  static WebCryptoTask* CreateDeriveBitsTask(JSContext* aCx,
    128                                             const ObjectOrString& aAlgorithm,
    129                                             CryptoKey& aKey,
    130                                             const Nullable<uint32_t>& aLength);
    131 
    132  static WebCryptoTask* CreateWrapKeyTask(JSContext* aCx,
    133                                          const nsAString& aFormat,
    134                                          CryptoKey& aKey,
    135                                          CryptoKey& aWrappingKey,
    136                                          const ObjectOrString& aWrapAlgorithm);
    137  static WebCryptoTask* CreateUnwrapKeyTask(
    138      nsIGlobalObject* aGlobal, JSContext* aCx, const nsAString& aFormat,
    139      const ArrayBufferViewOrArrayBuffer& aWrappedKey,
    140      CryptoKey& aUnwrappingKey, const ObjectOrString& aUnwrapAlgorithm,
    141      const ObjectOrString& aUnwrappedKeyAlgorithm, bool aExtractable,
    142      const Sequence<nsString>& aKeyUsages);
    143 
    144 protected:
    145  RefPtr<Promise> mResultPromise;
    146  nsresult mEarlyRv;
    147  bool mEarlyComplete;
    148 
    149  WebCryptoTask();
    150  virtual ~WebCryptoTask();
    151 
    152  bool IsOnOriginalThread() {
    153    return !mOriginalEventTarget || mOriginalEventTarget->IsOnCurrentThread();
    154  }
    155 
    156  // For things that need to happen on the main thread
    157  // either before or after CalculateResult
    158  virtual nsresult BeforeCrypto() { return NS_OK; }
    159  virtual nsresult DoCrypto() { return NS_OK; }
    160  virtual nsresult AfterCrypto() { return NS_OK; }
    161  virtual void Resolve() {}
    162  virtual void Cleanup() {}
    163 
    164  void FailWithError(nsresult aRv);
    165 
    166  nsresult CalculateResult();
    167 
    168  void CallCallback(nsresult rv);
    169 
    170 private:
    171  NS_IMETHOD Run() final;
    172  nsresult Cancel() final;
    173 
    174  nsCOMPtr<nsISerialEventTarget> mOriginalEventTarget;
    175  RefPtr<ThreadSafeWorkerRef> mWorkerRef;
    176  nsresult mRv;
    177 };
    178 
    179 // XXX This class is declared here (unlike others) to enable reuse by WebRTC.
    180 class GenerateAsymmetricKeyTask : public WebCryptoTask {
    181 public:
    182  GenerateAsymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
    183                            const ObjectOrString& aAlgorithm, bool aExtractable,
    184                            const Sequence<nsString>& aKeyUsages);
    185 
    186 protected:
    187  UniquePLArenaPool mArena;
    188  UniquePtr<CryptoKeyPair> mKeyPair;
    189  nsString mAlgName;
    190  CK_MECHANISM_TYPE mMechanism;
    191  PK11RSAGenParams mRsaParams;
    192  SECKEYDHParams mDhParams;
    193  nsString mNamedCurve;
    194 
    195  virtual nsresult DoCrypto() override;
    196  virtual void Resolve() override;
    197  virtual void Cleanup() override;
    198 
    199 private:
    200  UniqueSECKEYPublicKey mPublicKey;
    201  UniqueSECKEYPrivateKey mPrivateKey;
    202 };
    203 
    204 }  // namespace mozilla::dom
    205 
    206 #endif  // mozilla_dom_WebCryptoTask_h