DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (441520899d5f)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Generic key store implementation for platforms that we don't support with OS
// specific implementations.

#ifndef OSKeyStore_h
#define OSKeyStore_h

#include "nsIOSKeyStore.h"
#include "nsString.h"

#include <memory>

class AbstractOSKeyStore {
 public:
  // Retrieve a secret with the given label.
  virtual nsresult RetrieveSecret(const nsACString& aLabel,
                                  /* out */ nsACString& aSecret) = 0;
  // Store a new secret with the given label.
  virtual nsresult StoreSecret(const nsACString& secret,
                               const nsACString& label) = 0;
  // Delete the secret with the given label.
  virtual nsresult DeleteSecret(const nsACString& label) = 0;
  // Lock the key store.
  virtual nsresult Lock() = 0;
  // Unlock the key store.
  virtual nsresult Unlock() = 0;
  virtual ~AbstractOSKeyStore() {}

  // Returns true if the secret with the given label is available in the key
  // store, false otherwise.
  virtual bool SecretAvailable(const nsACString& label);
  // Perform encryption or decryption operation with the given secret and input
  // bytes. The output is written in outBytes. This function can make use of the
  // AesGcm class to use NSS for encryption and decryption.
  virtual nsresult EncryptDecrypt(const nsACString& label,
                                  const std::vector<uint8_t>& inBytes,
                                  std::vector<uint8_t>& outBytes, bool encrypt);

  size_t GetKeyByteLength() { return mKeyByteLength; }

 protected:
  /* These helper functions are implemented in OSKeyStore.cpp and implement
   * common functionality of the abstract key store to encrypt and decrypt.
   */
  nsresult DoCipher(const UniquePK11SymKey& aSymKey,
                    const std::vector<uint8_t>& inBytes,
                    std::vector<uint8_t>& outBytes, bool aEncrypt);
  nsresult BuildAesGcmKey(std::vector<uint8_t> keyBytes,
                          /* out */ UniquePK11SymKey& aKey);

 private:
  const size_t mKeyByteLength = 16;
  const size_t mIVLength = 12;
};

#define NS_OSKEYSTORE_CONTRACTID "@mozilla.org/security/oskeystore;1"
#define NS_OSKEYSTORE_CID                            \
  {                                                  \
    0x57972956, 0x5718, 0x42d2, {                    \
      0x80, 0x70, 0xb3, 0xfc, 0x72, 0x21, 0x2e, 0xaf \
    }                                                \
  }

nsresult GetPromise(JSContext* aCx,
                    /* out */ RefPtr<mozilla::dom::Promise>& aPromise);

class OSKeyStore final : public nsIOSKeyStore, public nsIObserver {
 public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSIOBSERVER
  NS_DECL_NSIOSKEYSTORE

  OSKeyStore();
  nsresult GenerateSecret(const nsACString& aLabel,
                          /* out */ nsACString& aRecoveryPhrase);
  nsresult SecretAvailable(const nsACString& aLabel,
                           /* out */ bool* aAvailable);
  nsresult RecoverSecret(const nsACString& aLabel,
                         const nsACString& aRecoveryPhrase);
  nsresult DeleteSecret(const nsACString& aLabel);
  nsresult EncryptBytes(const nsACString& aLabel, uint32_t inLen,
                        uint8_t* inBytes,
                        /*out*/ nsACString& aEncryptedBase64Text);
  nsresult DecryptBytes(const nsACString& aLabel,
                        const nsACString& aEncryptedBase64Text,
                        /*out*/ uint32_t* outLen,
                        /*out*/ uint8_t** outBytes);
  nsresult Lock();
  nsresult Unlock();

 private:
  ~OSKeyStore() = default;

  // Thread safety for OSKeyStore:
  // * mKsThread is only accessed on the main thread
  // * mKsThread is shut down on the main thread when OSKeyStore receives the
  //   "xpcom-shutdown" notification
  // * mKs is created and destroyed on the main thread, but is only accessed on
  //   mKsThread
  // * XPCOM notifies "xpcom-shutdown" before shutting down the component
  //   manager, so mKsThread is shut down before mKs is destroyed
  // Essentially, the lifetime of mKsThread is contained by the lifetime of mKs.
  // Since the value of mKs never changes while mKsThread is alive and any uses
  // of it are serial, there shouldn't be any memory safety issues.
  std::unique_ptr<AbstractOSKeyStore> mKs;
  nsCOMPtr<nsIThread> mKsThread;

  bool mKsIsNSSKeyStore;
  const nsCString mLabelPrefix =
      NS_LITERAL_CSTRING("org.mozilla.nss.keystore.");
};

#endif  // OSKeyStore_h