1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include <array>
16
17 #include "pw_blob_store/blob_store.h"
18 #include "pw_kvs/fake_flash_memory.h"
19 #include "pw_kvs/test_key_value_store.h"
20 #include "pw_software_update/blob_store_openable_reader.h"
21 #include "pw_software_update/bundled_update_backend.h"
22 #include "pw_software_update/update_bundle_accessor.h"
23 #include "pw_stream/memory_stream.h"
24 #include "pw_unit_test/framework.h"
25 #include "test_bundles.h"
26
27 #define ASSERT_OK(status) ASSERT_EQ(OkStatus(), status)
28 #define ASSERT_FAIL(status) ASSERT_NE(OkStatus(), status)
29
30 namespace pw::software_update {
31 namespace {
32
33 constexpr size_t kBufferSize = 256;
34 static constexpr size_t kFlashAlignment = 16;
35 constexpr size_t kSectorSize = 2048;
36 constexpr size_t kSectorCount = 2;
37 constexpr size_t kMetadataBufferSize =
38 blob_store::BlobStore::BlobWriter::RequiredMetadataBufferSize(0);
39
40 class TestBundledUpdateBackend final : public BundledUpdateBackend {
41 public:
TestBundledUpdateBackend()42 TestBundledUpdateBackend()
43 : manifest_reader_({}), trusted_root_memory_reader_({}) {}
44
ApplyReboot()45 Status ApplyReboot() override { return Status::Unimplemented(); }
PostRebootFinalize()46 Status PostRebootFinalize() override { return OkStatus(); }
47
ApplyTargetFile(std::string_view,stream::SeekableReader &,size_t)48 Status ApplyTargetFile(std::string_view,
49 stream::SeekableReader&,
50 size_t) override {
51 return OkStatus();
52 }
53
EnableBundleTransferHandler(std::string_view)54 Result<uint32_t> EnableBundleTransferHandler(std::string_view) override {
55 return 0;
56 }
57
DisableBundleTransferHandler()58 void DisableBundleTransferHandler() override {}
59
SetTrustedRoot(ConstByteSpan trusted_root)60 void SetTrustedRoot(ConstByteSpan trusted_root) {
61 trusted_root_memory_reader_ = stream::MemoryReader(trusted_root);
62 trusted_root_reader_ = stream::IntervalReader(
63 trusted_root_memory_reader_,
64 0,
65 trusted_root_memory_reader_.ConservativeReadLimit());
66 }
67
SetCurrentManifest(ConstByteSpan current_manifest)68 void SetCurrentManifest(ConstByteSpan current_manifest) {
69 manifest_reader_ = stream::MemoryReader(current_manifest);
70 }
71
SetManifestWriter(stream::Writer * writer)72 void SetManifestWriter(stream::Writer* writer) { manifest_writer_ = writer; }
73
GetRootMetadataReader()74 Result<stream::SeekableReader*> GetRootMetadataReader() override {
75 return &trusted_root_reader_;
76 }
77
BeforeManifestRead()78 Status BeforeManifestRead() override {
79 before_manifest_read_called_ = true;
80 if (manifest_reader_.ConservativeReadLimit() > 0) {
81 return OkStatus();
82 }
83 return Status::NotFound();
84 }
85
BeforeManifestReadCalled()86 bool BeforeManifestReadCalled() { return before_manifest_read_called_; }
87
GetManifestReader()88 Result<stream::SeekableReader*> GetManifestReader() override {
89 return &manifest_reader_;
90 }
91
BeforeManifestWrite()92 Status BeforeManifestWrite() override {
93 before_manifest_write_called_ = true;
94 return (manifest_writer_) ? OkStatus() : Status::NotFound();
95 }
96
BeforeManifestWriteCalled()97 bool BeforeManifestWriteCalled() { return before_manifest_write_called_; }
98
AfterManifestWrite()99 Status AfterManifestWrite() override {
100 after_manifest_write_called_ = true;
101 return OkStatus();
102 }
103
AfterManifestWriteCalled()104 bool AfterManifestWriteCalled() { return after_manifest_write_called_; }
105
GetManifestWriter()106 Result<stream::Writer*> GetManifestWriter() override {
107 return manifest_writer_;
108 }
109
SafelyPersistRootMetadata(stream::IntervalReader root_metadata)110 Status SafelyPersistRootMetadata(
111 [[maybe_unused]] stream::IntervalReader root_metadata) override {
112 new_root_persisted_ = true;
113 trusted_root_reader_ = root_metadata;
114 return OkStatus();
115 }
116
IsNewRootPersisted() const117 bool IsNewRootPersisted() const { return new_root_persisted_; }
118
119 private:
120 stream::IntervalReader trusted_root_reader_;
121 stream::MemoryReader manifest_reader_;
122 stream::Writer* manifest_writer_ = nullptr;
123 bool before_manifest_read_called_ = false;
124 bool before_manifest_write_called_ = false;
125 bool after_manifest_write_called_ = false;
126 bool new_root_persisted_ = false;
127
128 // A memory reader for buffer passed by SetTrustedRoot(). This will be used
129 // to back `trusted_root_reader_`
130 stream::MemoryReader trusted_root_memory_reader_;
131 };
132
133 class UpdateBundleTest : public testing::Test {
134 public:
UpdateBundleTest()135 UpdateBundleTest()
136 : blob_flash_(kFlashAlignment),
137 blob_partition_(&blob_flash_),
138 bundle_blob_("TestBundle",
139 blob_partition_,
140 nullptr,
141 kvs::TestKvs(),
142 kBufferSize),
143 blob_reader_(bundle_blob_) {}
144
bundle_blob()145 blob_store::BlobStoreBuffer<kBufferSize>& bundle_blob() {
146 return bundle_blob_;
147 }
148
blob_reader()149 BlobStoreOpenableReader& blob_reader() { return blob_reader_; }
150
backend()151 TestBundledUpdateBackend& backend() { return backend_; }
152
StageTestBundle(ConstByteSpan bundle_data)153 void StageTestBundle(ConstByteSpan bundle_data) {
154 ASSERT_OK(bundle_blob_.Init());
155 blob_store::BlobStore::BlobWriter blob_writer(bundle_blob(),
156 metadata_buffer_);
157 ASSERT_OK(blob_writer.Open());
158 ASSERT_OK(blob_writer.Write(bundle_data));
159 ASSERT_OK(blob_writer.Close());
160 }
161
162 // A helper to verify that all bundle operations are disallowed because
163 // the bundle is not open or verified.
VerifyAllBundleOperationsDisallowed(UpdateBundleAccessor & update_bundle)164 void VerifyAllBundleOperationsDisallowed(
165 UpdateBundleAccessor& update_bundle) {
166 // We need to check specificially that failure is due to rejecting
167 // unverified/unopen bundle, not anything else.
168 ASSERT_EQ(update_bundle.GetManifest().status(),
169 Status::FailedPrecondition());
170 ASSERT_EQ(update_bundle.GetTargetPayload("any").status(),
171 Status::FailedPrecondition());
172 ASSERT_EQ(update_bundle.GetTargetPayload(protobuf::String({})).status(),
173 Status::FailedPrecondition());
174 ASSERT_EQ(update_bundle.PersistManifest(), Status::FailedPrecondition());
175 ASSERT_EQ(update_bundle.GetTotalPayloadSize().status(),
176 Status::FailedPrecondition());
177 }
178
179 // A helper to verify that UpdateBundleAccessor::OpenAndVerify() fails and
180 // that all bundle operations are disallowed as a result. Also check whether
181 // root metadata should be expected to be persisted.
CheckOpenAndVerifyFail(UpdateBundleAccessor & update_bundle,bool expect_new_root_persisted)182 void CheckOpenAndVerifyFail(UpdateBundleAccessor& update_bundle,
183 bool expect_new_root_persisted) {
184 ASSERT_FALSE(backend().IsNewRootPersisted());
185 ASSERT_FAIL(update_bundle.OpenAndVerify());
186 ASSERT_EQ(backend().IsNewRootPersisted(), expect_new_root_persisted);
187 VerifyAllBundleOperationsDisallowed(update_bundle);
188
189 ASSERT_OK(update_bundle.Close());
190 VerifyAllBundleOperationsDisallowed(update_bundle);
191 }
192
193 private:
194 kvs::FakeFlashMemoryBuffer<kSectorSize, kSectorCount> blob_flash_;
195 kvs::FlashPartition blob_partition_;
196 blob_store::BlobStoreBuffer<kBufferSize> bundle_blob_;
197 BlobStoreOpenableReader blob_reader_;
198 std::array<std::byte, kMetadataBufferSize> metadata_buffer_;
199 TestBundledUpdateBackend backend_;
200 };
201
202 } // namespace
203
TEST_F(UpdateBundleTest,GetTargetPayload)204 TEST_F(UpdateBundleTest, GetTargetPayload) {
205 backend().SetTrustedRoot(kDevSignedRoot);
206 StageTestBundle(kTestDevBundle);
207 UpdateBundleAccessor update_bundle(blob_reader(), backend());
208
209 ASSERT_OK(update_bundle.OpenAndVerify());
210
211 {
212 stream::IntervalReader res = update_bundle.GetTargetPayload("file1");
213 ASSERT_OK(res.status());
214
215 const char kExpectedContent[] = "file 1 content";
216 char read_buffer[sizeof(kExpectedContent) + 1] = {0};
217 ASSERT_TRUE(res.Read(read_buffer, sizeof(kExpectedContent)).ok());
218 ASSERT_STREQ(read_buffer, kExpectedContent);
219 }
220
221 {
222 stream::IntervalReader res = update_bundle.GetTargetPayload("file2");
223 ASSERT_OK(res.status());
224
225 const char kExpectedContent[] = "file 2 content";
226 char read_buffer[sizeof(kExpectedContent) + 1] = {0};
227 ASSERT_TRUE(res.Read(read_buffer, sizeof(kExpectedContent)).ok());
228 ASSERT_STREQ(read_buffer, kExpectedContent);
229 }
230
231 {
232 stream::IntervalReader res = update_bundle.GetTargetPayload("non-exist");
233 ASSERT_EQ(res.status(), Status::NotFound());
234 }
235 }
236
TEST_F(UpdateBundleTest,PersistManifest)237 TEST_F(UpdateBundleTest, PersistManifest) {
238 backend().SetTrustedRoot(kDevSignedRoot);
239 StageTestBundle(kTestDevBundle);
240 UpdateBundleAccessor update_bundle(blob_reader(), backend());
241
242 ASSERT_OK(update_bundle.OpenAndVerify());
243
244 std::byte manifest_buffer[sizeof(kTestBundleManifest)] = {};
245 stream::MemoryWriter manifest_writer(manifest_buffer);
246 backend().SetManifestWriter(&manifest_writer);
247 ASSERT_FALSE(backend().BeforeManifestWriteCalled());
248 ASSERT_FALSE(backend().AfterManifestWriteCalled());
249 ASSERT_OK(update_bundle.PersistManifest());
250 ASSERT_TRUE(backend().BeforeManifestWriteCalled());
251 ASSERT_TRUE(backend().AfterManifestWriteCalled());
252
253 ASSERT_EQ(
254 memcmp(manifest_buffer, kTestBundleManifest, sizeof(kTestBundleManifest)),
255 0);
256 }
257
TEST_F(UpdateBundleTest,PersistManifestFailIfNotVerified)258 TEST_F(UpdateBundleTest, PersistManifestFailIfNotVerified) {
259 backend().SetTrustedRoot(kDevSignedRoot);
260 StageTestBundle(kTestBadProdSignature);
261 UpdateBundleAccessor update_bundle(blob_reader(), backend());
262
263 ASSERT_FAIL(update_bundle.OpenAndVerify());
264
265 std::byte manifest_buffer[sizeof(kTestBundleManifest)];
266 stream::MemoryWriter manifest_writer(manifest_buffer);
267 backend().SetManifestWriter(&manifest_writer);
268 ASSERT_FALSE(backend().BeforeManifestWriteCalled());
269 ASSERT_FALSE(backend().AfterManifestWriteCalled());
270 ASSERT_FAIL(update_bundle.PersistManifest());
271 ASSERT_FALSE(backend().BeforeManifestWriteCalled());
272 ASSERT_FALSE(backend().AfterManifestWriteCalled());
273 }
274
TEST_F(UpdateBundleTest,SelfVerificationWithIncomingRoot)275 TEST_F(UpdateBundleTest, SelfVerificationWithIncomingRoot) {
276 StageTestBundle(kTestDevBundleWithRoot);
277 UpdateBundleAccessor update_bundle(
278 blob_reader(), backend(), /* self_verification = */ true);
279
280 ASSERT_OK(update_bundle.OpenAndVerify());
281 // Self verification must not persist anything.
282 ASSERT_FALSE(backend().IsNewRootPersisted());
283
284 // Manifest persisting should be allowed as well.
285 std::byte manifest_buffer[sizeof(kTestBundleManifest)];
286 stream::MemoryWriter manifest_writer(manifest_buffer);
287 backend().SetManifestWriter(&manifest_writer);
288 ASSERT_OK(update_bundle.PersistManifest());
289
290 ASSERT_EQ(
291 memcmp(manifest_buffer, kTestBundleManifest, sizeof(kTestBundleManifest)),
292 0);
293 }
294
TEST_F(UpdateBundleTest,SelfVerificationWithoutIncomingRoot)295 TEST_F(UpdateBundleTest, SelfVerificationWithoutIncomingRoot) {
296 StageTestBundle(kTestDevBundle);
297 UpdateBundleAccessor update_bundle(
298 blob_reader(), backend(), /* self_verification = */ true);
299
300 ASSERT_OK(update_bundle.OpenAndVerify());
301 }
302
TEST_F(UpdateBundleTest,SelfVerificationWithMessedUpRoot)303 TEST_F(UpdateBundleTest, SelfVerificationWithMessedUpRoot) {
304 StageTestBundle(kTestDevBundleWithProdRoot);
305 UpdateBundleAccessor update_bundle(
306 blob_reader(), backend(), /* self_verification = */ true);
307
308 ASSERT_FAIL(update_bundle.OpenAndVerify());
309 }
310
TEST_F(UpdateBundleTest,SelfVerificationChecksMissingHashes)311 TEST_F(UpdateBundleTest, SelfVerificationChecksMissingHashes) {
312 StageTestBundle(kTestBundleMissingTargetHashFile0);
313 UpdateBundleAccessor update_bundle(
314 blob_reader(), backend(), /* self_verification = */ true);
315
316 ASSERT_FAIL(update_bundle.OpenAndVerify());
317 }
318
TEST_F(UpdateBundleTest,SelfVerificationChecksBadHashes)319 TEST_F(UpdateBundleTest, SelfVerificationChecksBadHashes) {
320 StageTestBundle(kTestBundleMismatchedTargetHashFile0);
321 UpdateBundleAccessor update_bundle(
322 blob_reader(), backend(), /* self_verification = */ true);
323
324 ASSERT_FAIL(update_bundle.OpenAndVerify());
325 }
326
TEST_F(UpdateBundleTest,SelfVerificationIgnoresUnsignedBundle)327 TEST_F(UpdateBundleTest, SelfVerificationIgnoresUnsignedBundle) {
328 StageTestBundle(kTestUnsignedBundleWithRoot);
329 UpdateBundleAccessor update_bundle(
330 blob_reader(), backend(), /* self_verification = */ true);
331
332 ASSERT_OK(update_bundle.OpenAndVerify());
333 }
334
TEST_F(UpdateBundleTest,OpenAndVerifySucceedsWithAllVerification)335 TEST_F(UpdateBundleTest, OpenAndVerifySucceedsWithAllVerification) {
336 backend().SetTrustedRoot(kDevSignedRoot);
337 backend().SetCurrentManifest(kTestBundleManifest);
338 StageTestBundle(kTestProdBundle);
339 UpdateBundleAccessor update_bundle(blob_reader(), backend());
340
341 ASSERT_FALSE(backend().IsNewRootPersisted());
342 ASSERT_FALSE(backend().BeforeManifestReadCalled());
343 ASSERT_OK(update_bundle.OpenAndVerify());
344 ASSERT_TRUE(backend().IsNewRootPersisted());
345 ASSERT_TRUE(backend().BeforeManifestReadCalled());
346
347 ASSERT_OK(update_bundle.Close());
348 VerifyAllBundleOperationsDisallowed(update_bundle);
349 }
350
TEST_F(UpdateBundleTest,OpenAndVerifyWithoutIncomingRootSucceedsWithAllVerification)351 TEST_F(UpdateBundleTest,
352 OpenAndVerifyWithoutIncomingRootSucceedsWithAllVerification) {
353 backend().SetTrustedRoot(kDevSignedRoot);
354 backend().SetCurrentManifest(kTestBundleManifest);
355 // kTestDevBundle does not contain an incoming root. See
356 // pw_software_update/py/pw_software_update/generate_test_bundle.py for
357 // detail of generation.
358 StageTestBundle(kTestDevBundle);
359 UpdateBundleAccessor update_bundle(blob_reader(), backend());
360
361 ASSERT_FALSE(backend().IsNewRootPersisted());
362 ASSERT_FALSE(backend().BeforeManifestReadCalled());
363 ASSERT_OK(update_bundle.OpenAndVerify());
364 ASSERT_FALSE(backend().IsNewRootPersisted());
365 ASSERT_TRUE(backend().BeforeManifestReadCalled());
366
367 ASSERT_OK(update_bundle.Close());
368 VerifyAllBundleOperationsDisallowed(update_bundle);
369 }
370
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnMismatchedRootKeyAndSignature)371 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedRootKeyAndSignature) {
372 backend().SetTrustedRoot(kDevSignedRoot);
373 backend().SetCurrentManifest(kTestBundleManifest);
374 // kTestMismatchedRootKeyAndSignature has a dev root metadata that is
375 // prod signed. The root metadata will not be able to verify itself.
376 // See pw_software_update/py/pw_software_update/generate_test_bundle.py for
377 // detail of generation.
378 StageTestBundle(kTestMismatchedRootKeyAndSignature);
379 UpdateBundleAccessor update_bundle(blob_reader(), backend());
380 CheckOpenAndVerifyFail(update_bundle, false);
381 }
382
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnBadProdSignature)383 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnBadProdSignature) {
384 backend().SetTrustedRoot(kDevSignedRoot);
385 backend().SetCurrentManifest(kTestBundleManifest);
386 StageTestBundle(kTestBadProdSignature);
387 UpdateBundleAccessor update_bundle(blob_reader(), backend());
388 CheckOpenAndVerifyFail(update_bundle, false);
389 }
390
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnBadTargetsSignature)391 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnBadTargetsSignature) {
392 backend().SetTrustedRoot(kDevSignedRoot);
393 backend().SetCurrentManifest(kTestBundleManifest);
394 StageTestBundle(kTestBadTargetsSignature);
395 UpdateBundleAccessor update_bundle(blob_reader(), backend());
396 CheckOpenAndVerifyFail(update_bundle, true);
397 }
398
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnBadTargetsRollBack)399 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnBadTargetsRollBack) {
400 backend().SetTrustedRoot(kDevSignedRoot);
401 backend().SetCurrentManifest(kTestBundleManifest);
402 StageTestBundle(kTestTargetsRollback);
403 UpdateBundleAccessor update_bundle(blob_reader(), backend());
404 CheckOpenAndVerifyFail(update_bundle, true);
405 }
406
TEST_F(UpdateBundleTest,OpenAndVerifySucceedsWithoutExistingManifest)407 TEST_F(UpdateBundleTest, OpenAndVerifySucceedsWithoutExistingManifest) {
408 backend().SetTrustedRoot(kDevSignedRoot);
409 StageTestBundle(kTestProdBundle);
410 UpdateBundleAccessor update_bundle(blob_reader(), backend());
411
412 ASSERT_FALSE(backend().IsNewRootPersisted());
413 ASSERT_OK(update_bundle.OpenAndVerify());
414 ASSERT_TRUE(backend().IsNewRootPersisted());
415 }
416
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnRootRollback)417 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnRootRollback) {
418 backend().SetTrustedRoot(kDevSignedRoot);
419 backend().SetCurrentManifest(kTestBundleManifest);
420 StageTestBundle(kTestRootRollback);
421 UpdateBundleAccessor update_bundle(blob_reader(), backend());
422 CheckOpenAndVerifyFail(update_bundle, false);
423 }
424
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnMismatchedTargetHashFile0)425 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedTargetHashFile0) {
426 backend().SetTrustedRoot(kDevSignedRoot);
427 backend().SetCurrentManifest(kTestBundleManifest);
428 // `kTestBundleMismatchedTargetHashFile0` is auto generated by
429 // pw_software_update/py/pw_software_update/generate_test_bundle.py.
430 // The hash value for file 0 in the targets metadata is made incorrect.
431 StageTestBundle(kTestBundleMismatchedTargetHashFile0);
432 UpdateBundleAccessor update_bundle(blob_reader(), backend());
433 CheckOpenAndVerifyFail(update_bundle, true);
434 }
435
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnMismatchedTargetHashFile1)436 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedTargetHashFile1) {
437 backend().SetTrustedRoot(kDevSignedRoot);
438 backend().SetCurrentManifest(kTestBundleManifest);
439 // `kTestBundleMismatchedTargetHashFile1` is auto generated by
440 // pw_software_update/py/pw_software_update/generate_test_bundle.py
441 // The hash value for file 1 in the targets metadata is made incorrect.
442 StageTestBundle(kTestBundleMismatchedTargetHashFile1);
443 UpdateBundleAccessor update_bundle(blob_reader(), backend());
444 CheckOpenAndVerifyFail(update_bundle, true);
445 }
446
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnMissingTargetHashFile0)447 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMissingTargetHashFile0) {
448 backend().SetTrustedRoot(kDevSignedRoot);
449 backend().SetCurrentManifest(kTestBundleManifest);
450 // `kTestBundleMismatchedTargetHashFile0` is auto generated by
451 // pw_software_update/py/pw_software_update/generate_test_bundle.py.
452 // The hash value for file 0 is removed.
453 StageTestBundle(kTestBundleMissingTargetHashFile0);
454 UpdateBundleAccessor update_bundle(blob_reader(), backend());
455 CheckOpenAndVerifyFail(update_bundle, true);
456 }
457
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnMissingTargetHashFile1)458 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMissingTargetHashFile1) {
459 backend().SetTrustedRoot(kDevSignedRoot);
460 backend().SetCurrentManifest(kTestBundleManifest);
461 // `kTestBundleMismatchedTargetHashFile1` is auto generated by
462 // pw_software_update/py/pw_software_update/generate_test_bundle.py
463 // The hash value for file 1 is removed.
464 StageTestBundle(kTestBundleMissingTargetHashFile1);
465 UpdateBundleAccessor update_bundle(blob_reader(), backend());
466 CheckOpenAndVerifyFail(update_bundle, true);
467 }
468
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnMismatchedTargetLengthFile0)469 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedTargetLengthFile0) {
470 backend().SetTrustedRoot(kDevSignedRoot);
471 backend().SetCurrentManifest(kTestBundleManifest);
472 // `kTestBundleMismatchedTargetLengthFile0` is auto generated by
473 // pw_software_update/py/pw_software_update/generate_test_bundle.py.
474 // The length value for file 0 in the targets metadata is made incorrect (1).
475 StageTestBundle(kTestBundleMismatchedTargetLengthFile0);
476 UpdateBundleAccessor update_bundle(blob_reader(), backend());
477 CheckOpenAndVerifyFail(update_bundle, true);
478 }
479
TEST_F(UpdateBundleTest,OpenAndVerifyFailsOnMismatchedTargetLengthFile1)480 TEST_F(UpdateBundleTest, OpenAndVerifyFailsOnMismatchedTargetLengthFile1) {
481 backend().SetTrustedRoot(kDevSignedRoot);
482 backend().SetCurrentManifest(kTestBundleManifest);
483 // `kTestBundleMismatchedTargetLengthFile1` is auto generated by
484 // pw_software_update/py/pw_software_update/generate_test_bundle.py.
485 // The length value for file 0 in the targets metadata is made incorrect (1).
486 StageTestBundle(kTestBundleMismatchedTargetLengthFile1);
487 UpdateBundleAccessor update_bundle(blob_reader(), backend());
488 CheckOpenAndVerifyFail(update_bundle, true);
489 }
490
TEST_F(UpdateBundleTest,OpenAndVerifySucceedsWithPersonalizedOutFile0)491 TEST_F(UpdateBundleTest, OpenAndVerifySucceedsWithPersonalizedOutFile0) {
492 backend().SetTrustedRoot(kDevSignedRoot);
493 backend().SetCurrentManifest(kTestBundleManifest);
494 // `kTestBundlePersonalizedOutFile0` is auto generated by
495 // pw_software_update/py/pw_software_update/generate_test_bundle.py
496 // The payload for file 0 is removed from the bundle to emulate being
497 // personalized out.
498 StageTestBundle(kTestBundlePersonalizedOutFile0);
499 UpdateBundleAccessor update_bundle(blob_reader(), backend());
500
501 ASSERT_OK(update_bundle.OpenAndVerify());
502 }
503
TEST_F(UpdateBundleTest,OpenAndVerifySucceedsWithPersonalizedOutFile1)504 TEST_F(UpdateBundleTest, OpenAndVerifySucceedsWithPersonalizedOutFile1) {
505 backend().SetTrustedRoot(kDevSignedRoot);
506 backend().SetCurrentManifest(kTestBundleManifest);
507 // `kTestBundlePersonalizedOutFile1` is auto generated by
508 // pw_software_update/py/pw_software_update/generate_test_bundle.py
509 // The payload for file 1 is removed from the bundle to emulate being
510 // personalized out.
511 StageTestBundle(kTestBundlePersonalizedOutFile1);
512 UpdateBundleAccessor update_bundle(blob_reader(), backend());
513
514 ASSERT_OK(update_bundle.OpenAndVerify());
515 }
516
TEST_F(UpdateBundleTest,PersonalizationVerificationFailsWithoutDeviceManifest)517 TEST_F(UpdateBundleTest,
518 PersonalizationVerificationFailsWithoutDeviceManifest) {
519 backend().SetTrustedRoot(kDevSignedRoot);
520 // `kTestBundlePersonalizedOutFile0` is auto generated by
521 // pw_software_update/py/pw_software_update/generate_test_bundle.py
522 // The payload for file 0 is removed from the bundle to emulate being
523 // personalized out.
524 StageTestBundle(kTestBundlePersonalizedOutFile0);
525 UpdateBundleAccessor update_bundle(blob_reader(), backend());
526
527 ASSERT_FAIL(update_bundle.OpenAndVerify());
528 }
529
530 } // namespace pw::software_update
531