EncryptingOutputStream.h (3851B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_quota_EncryptingOutputStream_h 8 #define mozilla_dom_quota_EncryptingOutputStream_h 9 10 // Local includes 11 #include "EncryptedBlock.h" // for EncryptedBlock 12 13 // Global includes 14 #include <cstddef> 15 #include <cstdint> 16 17 #include "ErrorList.h" 18 #include "mozilla/InitializedOnce.h" 19 #include "mozilla/Maybe.h" 20 #include "mozilla/NotNull.h" 21 #include "nsCOMPtr.h" 22 #include "nsIOutputStream.h" 23 #include "nsISupports.h" 24 #include "nsTArray.h" 25 #include "nscore.h" 26 27 class nsIInputStream; 28 class nsIRandomGenerator; 29 30 namespace mozilla::dom::quota { 31 class EncryptingOutputStreamBase : public nsIOutputStream { 32 public: 33 NS_DECL_THREADSAFE_ISUPPORTS 34 35 NS_IMETHOD Write(const char* aBuf, uint32_t aCount, uint32_t* _retval) final; 36 NS_IMETHOD WriteFrom(nsIInputStream* aFromStream, uint32_t aCount, 37 uint32_t* _retval) final; 38 NS_IMETHOD IsNonBlocking(bool* _retval) final; 39 40 protected: 41 EncryptingOutputStreamBase(nsCOMPtr<nsIOutputStream> aBaseStream, 42 size_t aBlockSize); 43 44 virtual ~EncryptingOutputStreamBase() = default; 45 46 nsresult WriteAll(const char* aBuf, uint32_t aCount, 47 uint32_t* aBytesWrittenOut); 48 49 InitializedOnce<const NotNull<nsCOMPtr<nsIOutputStream>>> mBaseStream; 50 const size_t mBlockSize; 51 }; 52 53 // Wraps another nsIOutputStream using the CipherStrategy to encrypt it a 54 // page-based manner. Essentially, the CipherStrategy is not actually 55 // necessarily doing encryption, but any transformation to a page requiring some 56 // fixed-size reserved size per page. 57 // 58 // Paired with DecryptingInputStream which can be used to read the data written 59 // to the underlying stream, using the same (or more generally, a compatible) 60 // CipherStrategy, when created with the same key (assuming a symmetric cipher 61 // is being used; in principle, an asymmetric cipher would probably also work). 62 template <typename CipherStrategy> 63 class EncryptingOutputStream final : public EncryptingOutputStreamBase { 64 public: 65 // Construct a new blocking output stream to encrypt data to 66 // the given base stream. The base stream must also be blocking. 67 // The encryption block size may optionally be set to a value 68 // up to kMaxBlockSize. 69 explicit EncryptingOutputStream(nsCOMPtr<nsIOutputStream> aBaseStream, 70 size_t aBlockSize, 71 typename CipherStrategy::KeyType aKey); 72 73 private: 74 ~EncryptingOutputStream(); 75 76 nsresult FlushToBaseStream(); 77 78 bool EnsureBuffers(); 79 80 CipherStrategy mCipherStrategy; 81 82 // Buffer holding copied plain data. This must be copied here 83 // so that the encryption can be performed on a single flat buffer. 84 // XXX This is only necessary if the data written doesn't contain a portion of 85 // effective block size at a block boundary. 86 nsTArray<uint8_t> mBuffer; 87 88 nsCOMPtr<nsIRandomGenerator> mRandomGenerator; 89 90 // The next byte in the plain data to copy incoming data to. 91 size_t mNextByte = 0; 92 93 // Buffer holding the resulting encrypted data. 94 using EncryptedBlockType = EncryptedBlock<CipherStrategy::BlockPrefixLength, 95 CipherStrategy::BasicBlockSize>; 96 Maybe<EncryptedBlockType> mEncryptedBlock; 97 98 public: 99 NS_IMETHOD Close() override; 100 NS_IMETHOD Flush() override; 101 NS_IMETHOD StreamStatus() override; 102 NS_IMETHOD WriteSegments(nsReadSegmentFun aReader, void* aClosure, 103 uint32_t aCount, uint32_t* _retval) override; 104 }; 105 106 } // namespace mozilla::dom::quota 107 108 #endif