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