524 lines
20 KiB
C++
524 lines
20 KiB
C++
// Copyright 2021 The Pigweed Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
// use this file except in compliance with the License. You may obtain a copy of
|
|
// the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
// License for the specific language governing permissions and limitations under
|
|
// the License.
|
|
|
|
#include <array>
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "pw_kvs/fake_flash_memory.h"
|
|
#include "pw_kvs/test_key_value_store.h"
|
|
#include "pw_software_update/bundled_update_backend.h"
|
|
#include "pw_software_update/update_bundle_accessor.h"
|
|
#include "pw_stream/memory_stream.h"
|
|
#include "test_bundles.h"
|
|
|
|
#define ASSERT_OK(status) ASSERT_EQ(OkStatus(), status)
|
|
#define ASSERT_FAIL(status) ASSERT_NE(OkStatus(), status)
|
|
|
|
namespace pw::software_update {
|
|
namespace {
|
|
|
|
constexpr size_t kBufferSize = 256;
|
|
static constexpr size_t kFlashAlignment = 16;
|
|
constexpr size_t kSectorSize = 2048;
|
|
constexpr size_t kSectorCount = 2;
|
|
constexpr size_t kMetadataBufferSize =
|
|
blob_store::BlobStore::BlobWriter::RequiredMetadataBufferSize(0);
|
|
|
|
class TestBundledUpdateBackend final : public BundledUpdateBackend {
|
|
public:
|
|
TestBundledUpdateBackend()
|
|
: manifest_reader_({}), trusted_root_memory_reader_({}) {}
|
|
|
|
Status ApplyReboot() override { return Status::Unimplemented(); }
|
|
Status PostRebootFinalize() override { return OkStatus(); }
|
|
|
|
Status ApplyTargetFile(std::string_view, stream::Reader&, size_t) override {
|
|
return OkStatus();
|
|
}
|
|
|
|
Result<uint32_t> EnableBundleTransferHandler(std::string_view) override {
|
|
return 0;
|
|
}
|
|
|
|
void DisableBundleTransferHandler() override {}
|
|
|
|
void SetTrustedRoot(ConstByteSpan trusted_root) {
|
|
trusted_root_memory_reader_ = stream::MemoryReader(trusted_root);
|
|
trusted_root_reader_ = stream::IntervalReader(
|
|
trusted_root_memory_reader_,
|
|
0,
|
|
trusted_root_memory_reader_.ConservativeReadLimit());
|
|
}
|
|
|
|
void SetCurrentManifest(ConstByteSpan current_manifest) {
|
|
manifest_reader_ = stream::MemoryReader(current_manifest);
|
|
}
|
|
|
|
void SetManifestWriter(stream::Writer* writer) { manifest_writer_ = writer; }
|
|
|
|
virtual Result<stream::SeekableReader*> GetRootMetadataReader() override {
|
|
return &trusted_root_reader_;
|
|
};
|
|
|
|
Status BeforeManifestRead() override {
|
|
before_manifest_read_called_ = true;
|
|
if (manifest_reader_.ConservativeReadLimit() > 0) {
|
|
return OkStatus();
|
|
}
|
|
return Status::NotFound();
|
|
};
|
|
|
|
bool BeforeManifestReadCalled() { return before_manifest_read_called_; }
|
|
|
|
Result<stream::SeekableReader*> GetManifestReader() override {
|
|
return &manifest_reader_;
|
|
}
|
|
|
|
Status BeforeManifestWrite() override {
|
|
before_manifest_write_called_ = true;
|
|
return (manifest_writer_) ? OkStatus() : Status::NotFound();
|
|
}
|
|
|
|
bool BeforeManifestWriteCalled() { return before_manifest_write_called_; }
|
|
|
|
Status AfterManifestWrite() override {
|
|
after_manifest_write_called_ = true;
|
|
return OkStatus();
|
|
}
|
|
|
|
bool AfterManifestWriteCalled() { return after_manifest_write_called_; }
|
|
|
|
Result<stream::Writer*> GetManifestWriter() override {
|
|
return manifest_writer_;
|
|
}
|
|
|
|
virtual Status SafelyPersistRootMetadata(
|
|
[[maybe_unused]] stream::IntervalReader root_metadata) override {
|
|
new_root_persisted_ = true;
|
|
trusted_root_reader_ = root_metadata;
|
|
return OkStatus();
|
|
};
|
|
|
|
bool IsNewRootPersisted() const { return new_root_persisted_; }
|
|
|
|
private:
|
|
stream::IntervalReader trusted_root_reader_;
|
|
stream::MemoryReader manifest_reader_;
|
|
stream::Writer* manifest_writer_ = nullptr;
|
|
bool before_manifest_read_called_ = false;
|
|
bool before_manifest_write_called_ = false;
|
|
bool after_manifest_write_called_ = false;
|
|
bool new_root_persisted_ = false;
|
|
size_t backend_verified_files_ = 0;
|
|
|
|
// A memory reader for buffer passed by SetTrustedRoot(). This will be used
|
|
// to back `trusted_root_reader_`
|
|
stream::MemoryReader trusted_root_memory_reader_;
|
|
};
|
|
|
|
class UpdateBundleTest : public testing::Test {
|
|
public:
|
|
UpdateBundleTest()
|
|
: blob_flash_(kFlashAlignment),
|
|
blob_partition_(&blob_flash_),
|
|
bundle_blob_("TestBundle",
|
|
blob_partition_,
|
|
nullptr,
|
|
kvs::TestKvs(),
|
|
kBufferSize) {}
|
|
|
|
blob_store::BlobStoreBuffer<kBufferSize>& bundle_blob() {
|
|
return bundle_blob_;
|
|
}
|
|
|
|
TestBundledUpdateBackend& backend() { return backend_; }
|
|
|
|
void StageTestBundle(ConstByteSpan bundle_data) {
|
|
ASSERT_OK(bundle_blob_.Init());
|
|
blob_store::BlobStore::BlobWriter blob_writer(bundle_blob(),
|
|
metadata_buffer_);
|
|
ASSERT_OK(blob_writer.Open());
|
|
ASSERT_OK(blob_writer.Write(bundle_data));
|
|
ASSERT_OK(blob_writer.Close());
|
|
}
|
|
|
|
// A helper to verify that all bundle operations are disallowed because
|
|
// the bundle is not open or verified.
|
|
void VerifyAllBundleOperationsDisallowed(
|
|
UpdateBundleAccessor& update_bundle) {
|
|
// We need to check specificially that failure is due to rejecting
|
|
// unverified/unopen bundle, not anything else.
|
|
ASSERT_EQ(update_bundle.GetManifest().status(),
|
|
Status::FailedPrecondition());
|
|
ASSERT_EQ(update_bundle.GetTargetPayload("any").status(),
|
|
Status::FailedPrecondition());
|
|
ASSERT_EQ(update_bundle.GetTargetPayload(protobuf::String({})).status(),
|
|
Status::FailedPrecondition());
|
|
ASSERT_EQ(update_bundle.PersistManifest(), Status::FailedPrecondition());
|
|
ASSERT_EQ(update_bundle.GetTotalPayloadSize().status(),
|
|
Status::FailedPrecondition());
|
|
}
|
|
|
|
// A helper to verify that UpdateBundleAccessor::OpenAndVerify() fails and
|
|
// that all bundle operations are disallowed as a result. Also check whether
|
|
// root metadata should be expected to be persisted.
|
|
void CheckOpenAndVerifyFail(UpdateBundleAccessor& update_bundle,
|
|
bool expect_new_root_persisted) {
|
|
ASSERT_FALSE(backend().IsNewRootPersisted());
|
|
ASSERT_FAIL(update_bundle.OpenAndVerify());
|
|
ASSERT_EQ(backend().IsNewRootPersisted(), expect_new_root_persisted);
|
|
VerifyAllBundleOperationsDisallowed(update_bundle);
|
|
|
|
ASSERT_OK(update_bundle.Close());
|
|
VerifyAllBundleOperationsDisallowed(update_bundle);
|
|
}
|
|
|
|
private:
|
|
kvs::FakeFlashMemoryBuffer<kSectorSize, kSectorCount> blob_flash_;
|
|
kvs::FlashPartition blob_partition_;
|
|
blob_store::BlobStoreBuffer<kBufferSize> bundle_blob_;
|
|
std::array<std::byte, kMetadataBufferSize> metadata_buffer_;
|
|
TestBundledUpdateBackend backend_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
TEST_F(UpdateBundleTest, GetTargetPayload) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
StageTestBundle(kTestDevBundle);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
|
|
{
|
|
stream::IntervalReader res = update_bundle.GetTargetPayload("file1");
|
|
ASSERT_OK(res.status());
|
|
|
|
const char kExpectedContent[] = "file 1 content";
|
|
char read_buffer[sizeof(kExpectedContent) + 1] = {0};
|
|
ASSERT_TRUE(res.Read(read_buffer, sizeof(kExpectedContent)).ok());
|
|
ASSERT_STREQ(read_buffer, kExpectedContent);
|
|
}
|
|
|
|
{
|
|
stream::IntervalReader res = update_bundle.GetTargetPayload("file2");
|
|
ASSERT_OK(res.status());
|
|
|
|
const char kExpectedContent[] = "file 2 content";
|
|
char read_buffer[sizeof(kExpectedContent) + 1] = {0};
|
|
ASSERT_TRUE(res.Read(read_buffer, sizeof(kExpectedContent)).ok());
|
|
ASSERT_STREQ(read_buffer, kExpectedContent);
|
|
}
|
|
|
|
{
|
|
stream::IntervalReader res = update_bundle.GetTargetPayload("non-exist");
|
|
ASSERT_EQ(res.status(), Status::NotFound());
|
|
}
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, PersistManifest) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
StageTestBundle(kTestDevBundle);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
|
|
std::byte manifest_buffer[sizeof(kTestBundleManifest)] = {};
|
|
stream::MemoryWriter manifest_writer(manifest_buffer);
|
|
backend().SetManifestWriter(&manifest_writer);
|
|
ASSERT_FALSE(backend().BeforeManifestWriteCalled());
|
|
ASSERT_FALSE(backend().AfterManifestWriteCalled());
|
|
ASSERT_OK(update_bundle.PersistManifest());
|
|
ASSERT_TRUE(backend().BeforeManifestWriteCalled());
|
|
ASSERT_TRUE(backend().AfterManifestWriteCalled());
|
|
|
|
ASSERT_EQ(
|
|
memcmp(manifest_buffer, kTestBundleManifest, sizeof(kTestBundleManifest)),
|
|
0);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, PersistManifestFailIfNotVerified) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
StageTestBundle(kTestBadProdSignature);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
|
|
ASSERT_FAIL(update_bundle.OpenAndVerify());
|
|
|
|
std::byte manifest_buffer[sizeof(kTestBundleManifest)];
|
|
stream::MemoryWriter manifest_writer(manifest_buffer);
|
|
backend().SetManifestWriter(&manifest_writer);
|
|
ASSERT_FALSE(backend().BeforeManifestWriteCalled());
|
|
ASSERT_FALSE(backend().AfterManifestWriteCalled());
|
|
ASSERT_FAIL(update_bundle.PersistManifest());
|
|
ASSERT_FALSE(backend().BeforeManifestWriteCalled());
|
|
ASSERT_FALSE(backend().AfterManifestWriteCalled());
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, SelfVerificationWithIncomingRoot) {
|
|
StageTestBundle(kTestDevBundleWithRoot);
|
|
UpdateBundleAccessor update_bundle(
|
|
bundle_blob(), backend(), /* disable_verification = */ true);
|
|
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
// Self verification must not persist anything.
|
|
ASSERT_FALSE(backend().IsNewRootPersisted());
|
|
|
|
// Manifest persisting should be allowed as well.
|
|
std::byte manifest_buffer[sizeof(kTestBundleManifest)];
|
|
stream::MemoryWriter manifest_writer(manifest_buffer);
|
|
backend().SetManifestWriter(&manifest_writer);
|
|
ASSERT_OK(update_bundle.PersistManifest());
|
|
|
|
ASSERT_EQ(
|
|
memcmp(manifest_buffer, kTestBundleManifest, sizeof(kTestBundleManifest)),
|
|
0);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, SelfVerificationWithoutIncomingRoot) {
|
|
StageTestBundle(kTestDevBundle);
|
|
UpdateBundleAccessor update_bundle(
|
|
bundle_blob(), backend(), /* disable_verification = */ true);
|
|
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, SelfVerificationWithMessedUpRoot) {
|
|
StageTestBundle(kTestDevBundleWithProdRoot);
|
|
UpdateBundleAccessor update_bundle(
|
|
bundle_blob(), backend(), /* disable_verification = */ true);
|
|
|
|
ASSERT_FAIL(update_bundle.OpenAndVerify());
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, SelfVerificationChecksMissingHashes) {
|
|
StageTestBundle(kTestBundleMissingTargetHashFile0);
|
|
UpdateBundleAccessor update_bundle(
|
|
bundle_blob(), backend(), /* disable_verification = */ true);
|
|
|
|
ASSERT_FAIL(update_bundle.OpenAndVerify());
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, SelfVerificationChecksBadHashes) {
|
|
StageTestBundle(kTestBundleMismatchedTargetHashFile0);
|
|
UpdateBundleAccessor update_bundle(
|
|
bundle_blob(), backend(), /* disable_verification = */ true);
|
|
|
|
ASSERT_FAIL(update_bundle.OpenAndVerify());
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, SelfVerificationIgnoresUnsignedBundle) {
|
|
StageTestBundle(kTestUnsignedBundleWithRoot);
|
|
UpdateBundleAccessor update_bundle(
|
|
bundle_blob(), backend(), /* disable_verification = */ true);
|
|
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifySucceedsWithAllVerification) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
StageTestBundle(kTestProdBundle);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
|
|
ASSERT_FALSE(backend().IsNewRootPersisted());
|
|
ASSERT_FALSE(backend().BeforeManifestReadCalled());
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
ASSERT_TRUE(backend().IsNewRootPersisted());
|
|
ASSERT_TRUE(backend().BeforeManifestReadCalled());
|
|
|
|
ASSERT_OK(update_bundle.Close());
|
|
VerifyAllBundleOperationsDisallowed(update_bundle);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest,
|
|
OpenAndVerifyWithoutIncomingRootSucceedsWithAllVerification) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// kTestDevBundle does not contain an incoming root. See
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py for
|
|
// detail of generation.
|
|
StageTestBundle(kTestDevBundle);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
|
|
ASSERT_FALSE(backend().IsNewRootPersisted());
|
|
ASSERT_FALSE(backend().BeforeManifestReadCalled());
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
ASSERT_FALSE(backend().IsNewRootPersisted());
|
|
ASSERT_TRUE(backend().BeforeManifestReadCalled());
|
|
|
|
ASSERT_OK(update_bundle.Close());
|
|
VerifyAllBundleOperationsDisallowed(update_bundle);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedRootKeyAndSignature) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// kTestMismatchedRootKeyAndSignature has a dev root metadata that is
|
|
// prod signed. The root metadata will not be able to verify itself.
|
|
// See pw_software_update/py/pw_software_update/generate_test_bundle.py for
|
|
// detail of generation.
|
|
StageTestBundle(kTestMismatchedRootKeyAndSignature);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, false);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnBadProdSignature) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
StageTestBundle(kTestBadProdSignature);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, false);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnBadTargetsSignature) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
StageTestBundle(kTestBadTargetsSignature);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, true);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnBadTargetsRollBack) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
StageTestBundle(kTestTargetsRollback);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, true);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifySucceedsWithoutExistingManifest) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
StageTestBundle(kTestProdBundle);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
|
|
ASSERT_FALSE(backend().IsNewRootPersisted());
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
ASSERT_TRUE(backend().IsNewRootPersisted());
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnRootRollback) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
StageTestBundle(kTestRootRollback);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, false);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedTargetHashFile0) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// `kTestBundleMismatchedTargetHashFile0` is auto generated by
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py.
|
|
// The hash value for file 0 in the targets metadata is made incorrect.
|
|
StageTestBundle(kTestBundleMismatchedTargetHashFile0);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, true);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedTargetHashFile1) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// `kTestBundleMismatchedTargetHashFile1` is auto generated by
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py
|
|
// The hash value for file 1 in the targets metadata is made incorrect.
|
|
StageTestBundle(kTestBundleMismatchedTargetHashFile1);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, true);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMissingTargetHashFile0) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// `kTestBundleMismatchedTargetHashFile0` is auto generated by
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py.
|
|
// The hash value for file 0 is removed.
|
|
StageTestBundle(kTestBundleMissingTargetHashFile0);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, true);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMissingTargetHashFile1) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// `kTestBundleMismatchedTargetHashFile1` is auto generated by
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py
|
|
// The hash value for file 1 is removed.
|
|
StageTestBundle(kTestBundleMissingTargetHashFile1);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, true);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedTargetLengthFile0) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// `kTestBundleMismatchedTargetLengthFile0` is auto generated by
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py.
|
|
// The length value for file 0 in the targets metadata is made incorrect (1).
|
|
StageTestBundle(kTestBundleMismatchedTargetLengthFile0);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, true);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedTargetLengthFile1) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// `kTestBundleMismatchedTargetLengthFile1` is auto generated by
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py.
|
|
// The length value for file 0 in the targets metadata is made incorrect (1).
|
|
StageTestBundle(kTestBundleMismatchedTargetLengthFile1);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
CheckOpenAndVerifyFail(update_bundle, true);
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifySucceedsWithPersonalizedOutFile0) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// `kTestBundlePersonalizedOutFile0` is auto generated by
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py
|
|
// The payload for file 0 is removed from the bundle to emulate being
|
|
// personalized out.
|
|
StageTestBundle(kTestBundlePersonalizedOutFile0);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest, OpenAndVerifySucceedsWithPersonalizedOutFile1) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
backend().SetCurrentManifest(kTestBundleManifest);
|
|
// `kTestBundlePersonalizedOutFile1` is auto generated by
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py
|
|
// The payload for file 1 is removed from the bundle to emulate being
|
|
// personalized out.
|
|
StageTestBundle(kTestBundlePersonalizedOutFile1);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
|
|
ASSERT_OK(update_bundle.OpenAndVerify());
|
|
}
|
|
|
|
TEST_F(UpdateBundleTest,
|
|
PersonalizationVerificationFailsWithoutDeviceManifest) {
|
|
backend().SetTrustedRoot(kDevSignedRoot);
|
|
// `kTestBundlePersonalizedOutFile0` is auto generated by
|
|
// pw_software_update/py/pw_software_update/generate_test_bundle.py
|
|
// The payload for file 0 is removed from the bundle to emulate being
|
|
// personalized out.
|
|
StageTestBundle(kTestBundlePersonalizedOutFile0);
|
|
UpdateBundleAccessor update_bundle(bundle_blob(), backend());
|
|
|
|
ASSERT_FAIL(update_bundle.OpenAndVerify());
|
|
}
|
|
|
|
} // namespace pw::software_update
|