CipherKeyManager.h (3195B)
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 DOM_QUOTA_CIPHERKEYMANAGER_H_ 8 #define DOM_QUOTA_CIPHERKEYMANAGER_H_ 9 10 #include "mozilla/DataMutex.h" 11 #include "mozilla/dom/FlippedOnce.h" 12 #include "mozilla/dom/quota/QuotaCommon.h" 13 #include "nsTHashMap.h" 14 15 namespace mozilla::dom::quota { 16 17 using mozilla::FlippedOnce; 18 19 template <typename CipherStrategy> 20 class CipherKeyManager { 21 // This helper class is used by quota clients to store/retrieve cipher 22 // keys in private browsing mode. All data in private mode must be encrypted 23 // using a cipher key and unique IV (Initialization Vector). 24 25 // This class uses hashmap (represented by mCipherKeys) to store cipher keys 26 // and is currently used by IndexedDB and Cache quota clients. At any given 27 // time, IndexedDB may contain multiple instances of this class where each is 28 // used to cipherkeys relevant to a particular database. Unlike IndexedDB, 29 // CacheAPI only has one physical sqlite db per origin, so all cipher keys 30 // corresponding to an origin in cacheAPI gets stored together in this 31 // hashmap. 32 33 // Bug1859558: It could be better if QuotaManager owns cipherKeys for 34 // all the quota clients and exposes, methods like 35 // GetOrCreateCipherManager(aOrigin, aDatabaseName, aClientType) for 36 // clients to access their respective cipherKeys scoped. 37 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CipherKeyManager) 38 39 using CipherKey = typename CipherStrategy::KeyType; 40 41 public: 42 explicit CipherKeyManager(const char* aName) : mCipherKeys(aName) {}; 43 44 Maybe<CipherKey> Get(const nsACString& aKeyId = "default"_ns) { 45 auto lockedCipherKeys = mCipherKeys.Lock(); 46 47 MOZ_ASSERT(!mInvalidated); 48 49 return lockedCipherKeys->MaybeGet(aKeyId); 50 } 51 52 CipherKey Ensure(const nsACString& aKeyId = "default"_ns) { 53 auto lockedCipherKeys = mCipherKeys.Lock(); 54 55 MOZ_ASSERT(!mInvalidated); 56 57 return lockedCipherKeys->LookupOrInsertWith(aKeyId, [] { 58 // Generate a new key if one corresponding to keyStoreId does not exist 59 // already. 60 61 QM_TRY_RETURN(CipherStrategy::GenerateKey(), [](const auto&) { 62 // Bug1800110 Propagate the error to the caller rather than asserting. 63 MOZ_RELEASE_ASSERT(false); 64 65 return CipherKey{}; 66 }); 67 }); 68 } 69 70 bool Invalidated() { 71 auto lockedCipherKeys = mCipherKeys.Lock(); 72 73 return mInvalidated; 74 } 75 76 // After calling this method, callers should not call any more methods on this 77 // class. 78 void Invalidate() { 79 auto lockedCipherKeys = mCipherKeys.Lock(); 80 81 mInvalidated.Flip(); 82 83 lockedCipherKeys->Clear(); 84 } 85 86 private: 87 ~CipherKeyManager() = default; 88 // XXX Maybe we can avoid a mutex here by moving all accesses to the 89 // background thread. 90 DataMutex<nsTHashMap<nsCStringHashKey, CipherKey>> mCipherKeys; 91 92 FlippedOnce<false> mInvalidated; 93 }; 94 95 } // namespace mozilla::dom::quota 96 97 #endif // DOM_QUOTA_CIPHERKEYMANAGER_H_