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