mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1634436 - Make DecryptingInputStream implement nsIIPCSerializableInputStream. r=baku
Differential Revision: https://phabricator.services.mozilla.com/D75913
This commit is contained in:
parent
ea360db963
commit
43fe271d3f
@ -17,12 +17,22 @@ NS_INTERFACE_MAP_BEGIN(DecryptingInputStreamBase)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
|
||||
mBaseCloneableInputStream || !mBaseStream)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(
|
||||
nsIIPCSerializableInputStream,
|
||||
mBaseIPCSerializableInputStream || !mBaseStream)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
DecryptingInputStreamBase::DecryptingInputStreamBase(
|
||||
MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream, size_t aBlockSize)
|
||||
: mBaseStream(std::move(aBaseStream)), mBlockSize(aBlockSize) {
|
||||
MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream, size_t aBlockSize) {
|
||||
Init(std::move(aBaseStream), aBlockSize);
|
||||
}
|
||||
|
||||
void DecryptingInputStreamBase::Init(
|
||||
MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream, size_t aBlockSize) {
|
||||
mBlockSize.init(aBlockSize);
|
||||
mBaseStream.init(std::move(aBaseStream));
|
||||
|
||||
const nsCOMPtr<nsISeekableStream> seekableStream =
|
||||
do_QueryInterface(mBaseStream->get());
|
||||
MOZ_ASSERT(seekableStream &&
|
||||
@ -35,6 +45,14 @@ DecryptingInputStreamBase::DecryptingInputStreamBase(
|
||||
SameCOMIdentity(mBaseStream->get(), cloneableInputStream)) {
|
||||
mBaseCloneableInputStream.init(WrapNotNullUnchecked(cloneableInputStream));
|
||||
}
|
||||
|
||||
const nsCOMPtr<nsIIPCSerializableInputStream> ipcSerializeInputStream =
|
||||
do_QueryInterface(mBaseStream->get());
|
||||
if (ipcSerializeInputStream &&
|
||||
SameCOMIdentity(mBaseStream->get(), ipcSerializeInputStream)) {
|
||||
mBaseIPCSerializableInputStream.init(
|
||||
WrapNotNullUnchecked(ipcSerializeInputStream));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DecryptingInputStreamBase::Read(char* aBuf, uint32_t aCount,
|
||||
@ -58,13 +76,21 @@ NS_IMETHODIMP DecryptingInputStreamBase::GetCloneable(bool* aCloneable) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void DecryptingInputStreamBase::Serialize(
|
||||
mozilla::ipc::InputStreamParams& aParams,
|
||||
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
|
||||
uint32_t aMaxSize, uint32_t* aSizeUsed,
|
||||
mozilla::ipc::ChildToParentStreamActorManager* aManager) {
|
||||
MOZ_CRASH("Not implemented");
|
||||
}
|
||||
|
||||
size_t DecryptingInputStreamBase::PlainLength() const {
|
||||
MOZ_ASSERT(mNextByte <= mPlainBytes);
|
||||
return mPlainBytes - mNextByte;
|
||||
}
|
||||
|
||||
size_t DecryptingInputStreamBase::EncryptedBufferLength() const {
|
||||
return mBlockSize;
|
||||
return *mBlockSize;
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom::quota
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICloneableInputStream.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIIPCSerializableInputStream.h"
|
||||
#include "nsISeekableStream.h"
|
||||
|
||||
#include "EncryptedBlock.h"
|
||||
@ -19,7 +20,8 @@ namespace mozilla::dom::quota {
|
||||
|
||||
class DecryptingInputStreamBase : public nsIInputStream,
|
||||
public nsISeekableStream,
|
||||
public nsICloneableInputStream {
|
||||
public nsICloneableInputStream,
|
||||
public nsIIPCSerializableInputStream {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
@ -31,22 +33,37 @@ class DecryptingInputStreamBase : public nsIInputStream,
|
||||
using nsICloneableInputStream::GetCloneable;
|
||||
NS_IMETHOD GetCloneable(bool* aCloneable) final;
|
||||
|
||||
using nsIIPCSerializableInputStream::Serialize;
|
||||
void Serialize(mozilla::ipc::InputStreamParams& aParams,
|
||||
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
|
||||
uint32_t aMaxSize, uint32_t* aSizeUsed,
|
||||
mozilla::ipc::ChildToParentStreamActorManager* aManager) final;
|
||||
|
||||
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 buffer.
|
||||
size_t PlainLength() const;
|
||||
|
||||
size_t EncryptedBufferLength() const;
|
||||
|
||||
InitializedOnce<const NotNull<nsCOMPtr<nsIInputStream>>> mBaseStream;
|
||||
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 mBuffer.
|
||||
size_t mPlainBytes = 0;
|
||||
@ -54,7 +71,7 @@ class DecryptingInputStreamBase : public nsIInputStream,
|
||||
// Next byte of mBuffer to return in ReadSegments().
|
||||
size_t mNextByte = 0;
|
||||
|
||||
const size_t mBlockSize;
|
||||
LazyInitializedOnceNotNull<const size_t> mBlockSize;
|
||||
|
||||
size_t mLastBlockLength = 0;
|
||||
};
|
||||
@ -72,6 +89,9 @@ class DecryptingInputStream final : public DecryptingInputStreamBase {
|
||||
size_t aBlockSize, CipherStrategy aCipherStrategy,
|
||||
typename CipherStrategy::KeyType aKey);
|
||||
|
||||
// For deserialization only.
|
||||
explicit DecryptingInputStream(CipherStrategy aCipherStrategy);
|
||||
|
||||
NS_IMETHOD Close() override;
|
||||
NS_IMETHOD Available(uint64_t* _retval) override;
|
||||
NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
|
||||
@ -83,6 +103,16 @@ class DecryptingInputStream final : public DecryptingInputStreamBase {
|
||||
|
||||
NS_IMETHOD Clone(nsIInputStream** _retval) override;
|
||||
|
||||
using DecryptingInputStreamBase::Serialize;
|
||||
void Serialize(
|
||||
mozilla::ipc::InputStreamParams& aParams,
|
||||
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
|
||||
uint32_t aMaxSize, uint32_t* aSizeUsed,
|
||||
mozilla::ipc::ParentToChildStreamActorManager* aManager) override;
|
||||
|
||||
bool Deserialize(const mozilla::ipc::InputStreamParams& aParams,
|
||||
const FileDescriptorArray& aFileDescriptors) override;
|
||||
|
||||
private:
|
||||
~DecryptingInputStream();
|
||||
|
||||
@ -108,7 +138,7 @@ class DecryptingInputStream final : public DecryptingInputStreamBase {
|
||||
bool EnsureBuffers();
|
||||
|
||||
const CipherStrategy mCipherStrategy;
|
||||
const typename CipherStrategy::KeyType mKey;
|
||||
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.
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "CipherStrategy.h"
|
||||
|
||||
#include "mozilla/ipc/InputStreamParams.h"
|
||||
#include "nsFileStreams.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsStreamUtils.h"
|
||||
|
||||
@ -38,6 +40,12 @@ DecryptingInputStream<CipherStrategy>::~DecryptingInputStream() {
|
||||
Close();
|
||||
}
|
||||
|
||||
template <typename CipherStrategy>
|
||||
DecryptingInputStream<CipherStrategy>::DecryptingInputStream(
|
||||
CipherStrategy aCipherStrategy)
|
||||
: DecryptingInputStreamBase{},
|
||||
mCipherStrategy(std::move(aCipherStrategy)) {}
|
||||
|
||||
template <typename CipherStrategy>
|
||||
NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::Close() {
|
||||
if (!mBaseStream) {
|
||||
@ -183,7 +191,7 @@ nsresult DecryptingInputStream<CipherStrategy>::ParseNextChunk(
|
||||
|
||||
// XXX Do we need to know the actual decrypted size?
|
||||
rv = mCipherStrategy.Cipher(
|
||||
CipherMode::Decrypt, mKey, mEncryptedBlock->MutableCipherPrefix(),
|
||||
CipherMode::Decrypt, *mKey, mEncryptedBlock->MutableCipherPrefix(),
|
||||
mEncryptedBlock->Payload(), AsWritableBytes(Span{mPlainBuffer}));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
@ -238,7 +246,7 @@ bool DecryptingInputStream<CipherStrategy>::EnsureBuffers() {
|
||||
// until the stream is closed.
|
||||
if (!mEncryptedBlock) {
|
||||
// XXX Do we need to do this fallible (as the comment above suggests)?
|
||||
mEncryptedBlock.emplace(mBlockSize);
|
||||
mEncryptedBlock.emplace(*mBlockSize);
|
||||
|
||||
MOZ_ASSERT(mPlainBuffer.IsEmpty());
|
||||
if (NS_WARN_IF(!mPlainBuffer.SetLength(mEncryptedBlock->MaxPayloadLength(),
|
||||
@ -269,8 +277,8 @@ NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::Tell(
|
||||
return rv;
|
||||
}
|
||||
|
||||
const auto fullBlocks = basePosition / mBlockSize;
|
||||
MOZ_ASSERT(0 == basePosition % mBlockSize);
|
||||
const auto fullBlocks = basePosition / *mBlockSize;
|
||||
MOZ_ASSERT(0 == basePosition % *mBlockSize);
|
||||
|
||||
*aRetval = (fullBlocks - ((mPlainBytes || mLastBlockLength) ? 1 : 0)) *
|
||||
mEncryptedBlock->MaxPayloadLength() +
|
||||
@ -331,7 +339,7 @@ NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::Seek(const int32_t aWhence,
|
||||
|
||||
nsresult rv =
|
||||
(*mBaseSeekableStream)
|
||||
->Seek(NS_SEEK_END, -static_cast<int64_t>(mBlockSize));
|
||||
->Seek(NS_SEEK_END, -static_cast<int64_t>(*mBlockSize));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return Err(rv);
|
||||
}
|
||||
@ -377,7 +385,7 @@ NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::Seek(const int32_t aWhence,
|
||||
|
||||
// XXX If we remain in the same block as before, we can skip this.
|
||||
nsresult rv =
|
||||
(*mBaseSeekableStream)->Seek(NS_SEEK_SET, baseBlocksOffset * mBlockSize);
|
||||
(*mBaseSeekableStream)->Seek(NS_SEEK_SET, baseBlocksOffset * *mBlockSize);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -400,7 +408,7 @@ NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::Seek(const int32_t aWhence,
|
||||
return aOffset == 0 ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
nsresult rv = (*mBaseSeekableStream)->Seek(NS_SEEK_CUR, -mBlockSize);
|
||||
nsresult rv = (*mBaseSeekableStream)->Seek(NS_SEEK_CUR, -*mBlockSize);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -438,12 +446,65 @@ NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::Clone(
|
||||
|
||||
*_retval =
|
||||
MakeAndAddRef<DecryptingInputStream>(WrapNotNull(std::move(clonedStream)),
|
||||
mBlockSize, mCipherStrategy, mKey)
|
||||
*mBlockSize, mCipherStrategy, *mKey)
|
||||
.take();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
template <typename CipherStrategy>
|
||||
void DecryptingInputStream<CipherStrategy>::Serialize(
|
||||
mozilla::ipc::InputStreamParams& aParams,
|
||||
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
|
||||
uint32_t aMaxSize, uint32_t* aSizeUsed,
|
||||
mozilla::ipc::ParentToChildStreamActorManager* aManager) {
|
||||
MOZ_ASSERT(mBaseStream);
|
||||
MOZ_ASSERT(mBaseIPCSerializableInputStream);
|
||||
|
||||
mozilla::ipc::InputStreamParams baseStreamParams;
|
||||
(*mBaseIPCSerializableInputStream)
|
||||
->Serialize(baseStreamParams, aFileDescriptors, aDelayedStart, aMaxSize,
|
||||
aSizeUsed, aManager);
|
||||
|
||||
MOZ_ASSERT(baseStreamParams.type() ==
|
||||
mozilla::ipc::InputStreamParams::TFileInputStreamParams);
|
||||
|
||||
mozilla::ipc::EncryptedFileInputStreamParams encryptedFileInputStreamParams;
|
||||
encryptedFileInputStreamParams.fileInputStreamParams() =
|
||||
std::move(baseStreamParams);
|
||||
encryptedFileInputStreamParams.key().AppendElements(
|
||||
mCipherStrategy.SerializeKey(*mKey));
|
||||
encryptedFileInputStreamParams.blockSize() = *mBlockSize;
|
||||
|
||||
aParams = std::move(encryptedFileInputStreamParams);
|
||||
}
|
||||
|
||||
template <typename CipherStrategy>
|
||||
bool DecryptingInputStream<CipherStrategy>::Deserialize(
|
||||
const mozilla::ipc::InputStreamParams& aParams,
|
||||
const FileDescriptorArray& aFileDescriptors) {
|
||||
MOZ_ASSERT(aParams.type() ==
|
||||
mozilla::ipc::InputStreamParams::TEncryptedFileInputStreamParams);
|
||||
const auto& params = aParams.get_EncryptedFileInputStreamParams();
|
||||
|
||||
nsCOMPtr<nsIFileInputStream> stream;
|
||||
nsFileInputStream::Create(nullptr, NS_GET_IID(nsIFileInputStream),
|
||||
getter_AddRefs(stream));
|
||||
nsCOMPtr<nsIIPCSerializableInputStream> baseSerializable =
|
||||
do_QueryInterface(stream);
|
||||
|
||||
if (NS_WARN_IF(!baseSerializable->Deserialize(params.fileInputStreamParams(),
|
||||
aFileDescriptors))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Init(WrapNotNull<nsCOMPtr<nsIInputStream>>(std::move(stream)),
|
||||
params.blockSize());
|
||||
mKey.init(mCipherStrategy.DeserializeKey(params.key()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom::quota
|
||||
|
||||
#endif
|
||||
|
16
dom/quota/IPCStreamCipherStrategy.h
Normal file
16
dom/quota/IPCStreamCipherStrategy.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* -*- 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_IPCStreamCipherStrategy_h
|
||||
#define mozilla_dom_quota_IPCStreamCipherStrategy_h
|
||||
|
||||
#include "mozilla/dom/quota/DummyCipherStrategy.h"
|
||||
|
||||
namespace mozilla::dom::quota {
|
||||
using IPCStreamCipherStrategy = DummyCipherStrategy;
|
||||
}
|
||||
|
||||
#endif
|
@ -35,6 +35,7 @@ EXPORTS.mozilla.dom.quota += [
|
||||
'EncryptingOutputStream_impl.h',
|
||||
'FileStreams.h',
|
||||
'InitializationTypes.h',
|
||||
'IPCStreamCipherStrategy.h',
|
||||
'MemoryOutputStream.h',
|
||||
'OriginScope.h',
|
||||
'PersistenceType.h',
|
||||
|
@ -92,6 +92,14 @@ union InputStreamParams
|
||||
IPCBlobInputStreamParams;
|
||||
InputStreamLengthWrapperParams;
|
||||
IPCRemoteStreamParams;
|
||||
EncryptedFileInputStreamParams;
|
||||
};
|
||||
|
||||
struct EncryptedFileInputStreamParams
|
||||
{
|
||||
FileInputStreamParams fileInputStreamParams;
|
||||
uint8_t[] key;
|
||||
uint32_t blockSize;
|
||||
};
|
||||
|
||||
struct BufferedInputStreamParams
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "mozilla/dom/IPCBlobInputStream.h"
|
||||
#include "mozilla/dom/IPCBlobInputStreamChild.h"
|
||||
#include "mozilla/dom/IPCBlobInputStreamStorage.h"
|
||||
#include "mozilla/dom/quota/DecryptingInputStream_impl.h"
|
||||
#include "mozilla/dom/quota/IPCStreamCipherStrategy.h"
|
||||
#include "mozilla/ipc/IPCStreamDestination.h"
|
||||
#include "mozilla/ipc/IPCStreamSource.h"
|
||||
#include "mozilla/InputStreamLengthHelper.h"
|
||||
@ -249,6 +251,9 @@ void InputStreamHelper::PostSerializationActivation(InputStreamParams& aParams,
|
||||
case InputStreamParams::TIPCBlobInputStreamParams:
|
||||
break;
|
||||
|
||||
case InputStreamParams::TEncryptedFileInputStreamParams:
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH(
|
||||
"A new stream? Should decide if it must be processed recursively or "
|
||||
@ -361,6 +366,12 @@ already_AddRefed<nsIInputStream> InputStreamHelper::DeserializeInputStream(
|
||||
serializable = new InputStreamLengthWrapper();
|
||||
break;
|
||||
|
||||
case InputStreamParams::TEncryptedFileInputStreamParams:
|
||||
serializable = new dom::quota::DecryptingInputStream<
|
||||
dom::quota::IPCStreamCipherStrategy>(
|
||||
dom::quota::IPCStreamCipherStrategy{});
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unknown params!");
|
||||
return nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user