/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ #ifndef mozilla_dom_quota_EncryptingOutputStream_h #define mozilla_dom_quota_EncryptingOutputStream_h // Local includes #include "EncryptedBlock.h" // for EncryptedBlock // Global includes #include #include #include "ErrorList.h" #include "mozilla/InitializedOnce.h" #include "mozilla/Maybe.h" #include "mozilla/NotNull.h" #include "nsCOMPtr.h" #include "nsIOutputStream.h" #include "nsISupports.h" #include "nsTArray.h" #include "nscore.h" class nsIInputStream; class nsIRandomGenerator; namespace mozilla::dom::quota { class EncryptingOutputStreamBase : public nsIOutputStream { public: NS_DECL_THREADSAFE_ISUPPORTS NS_IMETHOD Write(const char* aBuf, uint32_t aCount, uint32_t* _retval) final; NS_IMETHOD WriteFrom(nsIInputStream* aFromStream, uint32_t aCount, uint32_t* _retval) final; NS_IMETHOD IsNonBlocking(bool* _retval) final; protected: EncryptingOutputStreamBase(nsCOMPtr aBaseStream, size_t aBlockSize); virtual ~EncryptingOutputStreamBase() = default; nsresult WriteAll(const char* aBuf, uint32_t aCount, uint32_t* aBytesWrittenOut); InitializedOnce>> mBaseStream; const size_t mBlockSize; }; // Wraps another nsIOutputStream using the CipherStrategy to encrypt it a // page-based manner. Essentially, the CipherStrategy is not actually // necessarily doing encryption, but any transformation to a page requiring some // fixed-size reserved size per page. // // Paired with DecryptingInputStream which can be used to read the data written // to the underlying stream, using the same (or more generally, a compatible) // CipherStrategy, when created with the same key (assuming a symmetric cipher // is being used; in principle, an asymmetric cipher would probably also work). template class EncryptingOutputStream final : public EncryptingOutputStreamBase { public: // Construct a new blocking output stream to encrypt data to // the given base stream. The base stream must also be blocking. // The encryption block size may optionally be set to a value // up to kMaxBlockSize. explicit EncryptingOutputStream(nsCOMPtr aBaseStream, size_t aBlockSize, typename CipherStrategy::KeyType aKey); private: ~EncryptingOutputStream(); nsresult FlushToBaseStream(); bool EnsureBuffers(); CipherStrategy mCipherStrategy; // Buffer holding copied plain data. This must be copied here // so that the encryption can be performed on a single flat buffer. // XXX This is only necessary if the data written doesn't contain a portion of // effective block size at a block boundary. nsTArray mBuffer; nsCOMPtr mRandomGenerator; // The next byte in the plain data to copy incoming data to. size_t mNextByte = 0; // Buffer holding the resulting encrypted data. using EncryptedBlockType = EncryptedBlock; Maybe mEncryptedBlock; public: NS_IMETHOD Close() override; NS_IMETHOD Flush() override; NS_IMETHOD StreamStatus() override; NS_IMETHOD WriteSegments(nsReadSegmentFun aReader, void* aClosure, uint32_t aCount, uint32_t* _retval) override; }; } // namespace mozilla::dom::quota #endif