Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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_DecryptingInputStream_h
#define mozilla_dom_quota_DecryptingInputStream_h
// Local includes
#include "EncryptedBlock.h"
// Global includes
#include <cstddef>
#include <cstdint>
#include "ErrorList.h"
#include "mozilla/InitializedOnce.h"
#include "mozilla/Maybe.h"
#include "mozilla/NotNull.h"
#include "mozilla/ipc/InputStreamParams.h"
#include "nsCOMPtr.h"
#include "nsICloneableInputStream.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsIInputStream.h"
#include "nsISeekableStream.h"
#include "nsISupports.h"
#include "nsITellableStream.h"
#include "nsTArray.h"
#include "nscore.h"
template <class T>
class nsCOMPtr;
namespace mozilla::dom::quota {
class DecryptingInputStreamBase : public nsIInputStream,
public nsISeekableStream,
public nsICloneableInputStream,
public nsIIPCSerializableInputStream {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD Read(char* aBuf, uint32_t aCount, uint32_t* _retval) final;
NS_IMETHOD IsNonBlocking(bool* _retval) final;
NS_IMETHOD SetEOF() final;
using nsICloneableInputStream::GetCloneable;
NS_IMETHOD GetCloneable(bool* aCloneable) final;
void SerializedComplexity(uint32_t aMaxSize, uint32_t* aSizeUsed,
uint32_t* aPipes,
uint32_t* aTransferables) override;
protected:
DecryptingInputStreamBase(MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream,
size_t aBlockSize);
// For deserialization only.
DecryptingInputStreamBase() = default;
virtual ~DecryptingInputStreamBase() = default;
void Init(MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream,
size_t aBlockSize);
// Convenience routine to determine how many bytes of plain data
// we currently have in our plain buffer.
size_t PlainLength() const;
size_t EncryptedBufferLength() const;
LazyInitializedOnceEarlyDestructible<const NotNull<nsCOMPtr<nsIInputStream>>>
mBaseStream;
LazyInitializedOnce<const NotNull<nsISeekableStream*>> mBaseSeekableStream;
LazyInitializedOnce<const NotNull<nsICloneableInputStream*>>
mBaseCloneableInputStream;
LazyInitializedOnce<const NotNull<nsIIPCSerializableInputStream*>>
mBaseIPCSerializableInputStream;
// Number of bytes of plain data in mPlainBuffer.
size_t mPlainBytes = 0;
// Next byte of mPlainBuffer to return in ReadSegments().
size_t mNextByte = 0;
LazyInitializedOnceNotNull<const size_t> mBlockSize;
};
// Wraps another nsIInputStream which contains data written using
// EncryptingOutputStream with a compatible CipherStategy and key. See the
// remarks on EncryptingOutputStream.
template <typename CipherStrategy>
class DecryptingInputStream final : public DecryptingInputStreamBase {
public:
// Construct a new blocking stream to decrypt the given base stream. The
// base stream must also be blocking. The base stream does not have to be
// buffered.
DecryptingInputStream(MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream,
size_t aBlockSize,
typename CipherStrategy::KeyType aKey);
// For deserialization only.
explicit DecryptingInputStream();
nsresult BaseStreamStatus();
NS_IMETHOD Close() override;
NS_IMETHOD Available(uint64_t* _retval) override;
NS_IMETHOD StreamStatus() override;
NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t* _retval) override;
NS_DECL_NSITELLABLESTREAM
NS_IMETHOD Seek(int32_t aWhence, int64_t aOffset) override;
NS_IMETHOD Clone(nsIInputStream** _retval) override;
void Serialize(mozilla::ipc::InputStreamParams& aParams, uint32_t aMaxSize,
uint32_t* aSizeUsed) override;
bool Deserialize(const mozilla::ipc::InputStreamParams& aParams) override;
private:
~DecryptingInputStream();
// Parse the next chunk of data. This populates mPlainBuffer (until the
// stream position is at EOF).
nsresult ParseNextChunk(bool aCheckAvailableBytes, uint32_t* aBytesReadOut);
// Convenience routine to Read() from the base stream until we get
// the given number of bytes or reach EOF.
//
// aBuf - The buffer to write the bytes into.
// aCount - Max number of bytes to read. If the stream closes
// fewer bytes my be read.
// aMinValidCount - A minimum expected number of bytes. If we find
// fewer than this many bytes, then return
// NS_ERROR_CORRUPTED_CONTENT. If nothing was read
// due due to EOF (aBytesReadOut == 0), then NS_OK is
// returned.
// aCheckAvailableBytes - boolean flag controlling whether ReadAll should
// check available bytes before calling underlying
// Read method.
// aBytesReadOut - An out parameter indicating how many bytes were
// read.
nsresult ReadAll(char* aBuf, uint32_t aCount, uint32_t aMinValidCount,
bool aCheckAvailableBytes, uint32_t* aBytesReadOut);
bool EnsureBuffers();
// This method may change the current position in the stream.
nsresult EnsureDecryptedStreamSize();
CipherStrategy mCipherStrategy;
LazyInitializedOnce<const typename CipherStrategy::KeyType> mKey;
// Buffer to hold encrypted data. Must copy here since we need a
// flat buffer to run the decryption process on.
using EncryptedBlockType = EncryptedBlock<CipherStrategy::BlockPrefixLength,
CipherStrategy::BasicBlockSize>;
Maybe<EncryptedBlockType> mEncryptedBlock;
// Buffer storing the resulting plain data.
nsTArray<uint8_t> mPlainBuffer;
LazyInitializedOnce<const int64_t> mDecryptedStreamSize;
};
} // namespace mozilla::dom::quota
#endif