DecryptingInputStream.h (6343B)
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_DecryptingInputStream_h 8 #define mozilla_dom_quota_DecryptingInputStream_h 9 10 // Local includes 11 #include "EncryptedBlock.h" 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 "mozilla/ipc/InputStreamParams.h" 22 #include "nsCOMPtr.h" 23 #include "nsICloneableInputStream.h" 24 #include "nsIIPCSerializableInputStream.h" 25 #include "nsIInputStream.h" 26 #include "nsISeekableStream.h" 27 #include "nsISupports.h" 28 #include "nsITellableStream.h" 29 #include "nsTArray.h" 30 #include "nscore.h" 31 32 template <class T> 33 class nsCOMPtr; 34 35 namespace mozilla::dom::quota { 36 37 class DecryptingInputStreamBase : public nsIInputStream, 38 public nsISeekableStream, 39 public nsICloneableInputStream, 40 public nsIIPCSerializableInputStream { 41 public: 42 NS_DECL_THREADSAFE_ISUPPORTS 43 44 NS_IMETHOD Read(char* aBuf, uint32_t aCount, uint32_t* _retval) final; 45 NS_IMETHOD IsNonBlocking(bool* _retval) final; 46 47 NS_IMETHOD SetEOF() final; 48 49 using nsICloneableInputStream::GetCloneable; 50 NS_IMETHOD GetCloneable(bool* aCloneable) final; 51 52 void SerializedComplexity(uint32_t aMaxSize, uint32_t* aSizeUsed, 53 uint32_t* aPipes, 54 uint32_t* aTransferables) override; 55 56 protected: 57 DecryptingInputStreamBase(MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream, 58 size_t aBlockSize); 59 60 // For deserialization only. 61 DecryptingInputStreamBase() = default; 62 63 virtual ~DecryptingInputStreamBase() = default; 64 65 void Init(MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream, 66 size_t aBlockSize); 67 68 // Convenience routine to determine how many bytes of plain data 69 // we currently have in our plain buffer. 70 size_t PlainLength() const; 71 72 size_t EncryptedBufferLength() const; 73 74 LazyInitializedOnceEarlyDestructible<const NotNull<nsCOMPtr<nsIInputStream>>> 75 mBaseStream; 76 LazyInitializedOnce<const NotNull<nsISeekableStream*>> mBaseSeekableStream; 77 LazyInitializedOnce<const NotNull<nsICloneableInputStream*>> 78 mBaseCloneableInputStream; 79 LazyInitializedOnce<const NotNull<nsIIPCSerializableInputStream*>> 80 mBaseIPCSerializableInputStream; 81 82 // Number of bytes of plain data in mPlainBuffer. 83 size_t mPlainBytes = 0; 84 85 // Next byte of mPlainBuffer to return in ReadSegments(). 86 size_t mNextByte = 0; 87 88 LazyInitializedOnceNotNull<const size_t> mBlockSize; 89 }; 90 91 // Wraps another nsIInputStream which contains data written using 92 // EncryptingOutputStream with a compatible CipherStategy and key. See the 93 // remarks on EncryptingOutputStream. 94 template <typename CipherStrategy> 95 class DecryptingInputStream final : public DecryptingInputStreamBase { 96 public: 97 // Construct a new blocking stream to decrypt the given base stream. The 98 // base stream must also be blocking. The base stream does not have to be 99 // buffered. 100 DecryptingInputStream(MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream, 101 size_t aBlockSize, 102 typename CipherStrategy::KeyType aKey); 103 104 // For deserialization only. 105 explicit DecryptingInputStream(); 106 107 nsresult BaseStreamStatus(); 108 109 NS_IMETHOD Close() override; 110 NS_IMETHOD Available(uint64_t* _retval) override; 111 NS_IMETHOD StreamStatus() override; 112 NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, 113 uint32_t aCount, uint32_t* _retval) override; 114 115 NS_DECL_NSITELLABLESTREAM 116 117 NS_IMETHOD Seek(int32_t aWhence, int64_t aOffset) override; 118 119 NS_IMETHOD Clone(nsIInputStream** _retval) override; 120 121 void Serialize(mozilla::ipc::InputStreamParams& aParams, uint32_t aMaxSize, 122 uint32_t* aSizeUsed) override; 123 124 bool Deserialize(const mozilla::ipc::InputStreamParams& aParams) override; 125 126 private: 127 ~DecryptingInputStream(); 128 129 // Parse the next chunk of data. This populates mPlainBuffer (until the 130 // stream position is at EOF). 131 nsresult ParseNextChunk(bool aCheckAvailableBytes, uint32_t* aBytesReadOut); 132 133 // Convenience routine to Read() from the base stream until we get 134 // the given number of bytes or reach EOF. 135 // 136 // aBuf - The buffer to write the bytes into. 137 // aCount - Max number of bytes to read. If the stream closes 138 // fewer bytes my be read. 139 // aMinValidCount - A minimum expected number of bytes. If we find 140 // fewer than this many bytes, then return 141 // NS_ERROR_CORRUPTED_CONTENT. If nothing was read 142 // due due to EOF (aBytesReadOut == 0), then NS_OK is 143 // returned. 144 // aCheckAvailableBytes - boolean flag controlling whether ReadAll should 145 // check available bytes before calling underlying 146 // Read method. 147 // aBytesReadOut - An out parameter indicating how many bytes were 148 // read. 149 nsresult ReadAll(char* aBuf, uint32_t aCount, uint32_t aMinValidCount, 150 bool aCheckAvailableBytes, uint32_t* aBytesReadOut); 151 152 bool EnsureBuffers(); 153 154 // This method may change the current position in the stream. 155 nsresult EnsureDecryptedStreamSize(); 156 157 CipherStrategy mCipherStrategy; 158 LazyInitializedOnce<const typename CipherStrategy::KeyType> mKey; 159 160 // Buffer to hold encrypted data. Must copy here since we need a 161 // flat buffer to run the decryption process on. 162 using EncryptedBlockType = EncryptedBlock<CipherStrategy::BlockPrefixLength, 163 CipherStrategy::BasicBlockSize>; 164 Maybe<EncryptedBlockType> mEncryptedBlock; 165 166 // Buffer storing the resulting plain data. 167 nsTArray<uint8_t> mPlainBuffer; 168 169 LazyInitializedOnce<const int64_t> mDecryptedStreamSize; 170 }; 171 172 } // namespace mozilla::dom::quota 173 174 #endif