1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <android-base/file.h>
26 #include <gtest/gtest.h>
27 #include <libavb_ab/libavb_ab.h>
28 #include <string.h>
29
30 #include <map>
31 #include <vector>
32
33 #include "avb_unittest_util.h"
34 #include "fake_avb_ops.h"
35
36 namespace avb {
37
38 static_assert(sizeof(AvbABSlotData) == 4, "AvbABSlotData has wrong size");
39 static_assert(sizeof(AvbABData) == AVB_AB_DATA_SIZE,
40 "AvbABData has wrong size");
41 static_assert(offsetof(AvbABData, slots) % 8 == 0,
42 "AvbABData slots member has wrong offset");
43
44 // Subclass BaseAvbToolTest to check for memory leaks.
45 class ABTest : public BaseAvbToolTest {
46 public:
ABTest()47 ABTest() {}
48 };
49
TEST_F(ABTest,InitData)50 TEST_F(ABTest, InitData) {
51 AvbABData data;
52 avb_ab_data_init(&data);
53 EXPECT_EQ(0,
54 strncmp(reinterpret_cast<const char*>(data.magic),
55 AVB_AB_MAGIC,
56 AVB_AB_MAGIC_LEN));
57 EXPECT_EQ(AVB_AB_MAX_PRIORITY, data.slots[0].priority);
58 EXPECT_EQ(AVB_AB_MAX_TRIES_REMAINING, data.slots[0].tries_remaining);
59 EXPECT_EQ(0, data.slots[0].successful_boot);
60 EXPECT_EQ(AVB_AB_MAX_PRIORITY - 1, data.slots[1].priority);
61 EXPECT_EQ(AVB_AB_MAX_TRIES_REMAINING, data.slots[1].tries_remaining);
62 EXPECT_EQ(0, data.slots[1].successful_boot);
63 EXPECT_EQ(uint32_t(0), data.crc32);
64 }
65
TEST_F(ABTest,DataSerialization)66 TEST_F(ABTest, DataSerialization) {
67 AvbABData data;
68 AvbABData serialized;
69 AvbABData restored;
70
71 avb_ab_data_init(&data);
72 EXPECT_EQ(uint32_t(0), data.crc32);
73 avb_ab_data_update_crc_and_byteswap(&data, &serialized);
74 EXPECT_NE(uint32_t(0), serialized.crc32);
75 EXPECT_TRUE(avb_ab_data_verify_and_byteswap(&serialized, &restored));
76 EXPECT_EQ(std::string(reinterpret_cast<const char*>(data.magic), 4),
77 std::string(reinterpret_cast<const char*>(restored.magic), 4));
78 EXPECT_EQ(data.version_major, restored.version_major);
79 EXPECT_EQ(data.version_minor, restored.version_minor);
80 EXPECT_EQ(0,
81 memcmp(reinterpret_cast<void*>(data.slots),
82 reinterpret_cast<void*>(restored.slots),
83 sizeof(AvbABSlotData) * 2));
84 }
85
TEST_F(ABTest,CatchBadCRC)86 TEST_F(ABTest, CatchBadCRC) {
87 AvbABData data;
88 AvbABData serialized;
89 AvbABData restored;
90
91 avb_ab_data_init(&data);
92 avb_ab_data_update_crc_and_byteswap(&data, &serialized);
93 serialized.crc32 += 1;
94 EXPECT_FALSE(avb_ab_data_verify_and_byteswap(&serialized, &restored));
95 }
96
TEST_F(ABTest,CatchUnsupportedMajorVersion)97 TEST_F(ABTest, CatchUnsupportedMajorVersion) {
98 AvbABData data;
99 AvbABData serialized;
100 AvbABData restored;
101
102 avb_ab_data_init(&data);
103 data.version_major += 1;
104 avb_ab_data_update_crc_and_byteswap(&data, &serialized);
105 EXPECT_FALSE(avb_ab_data_verify_and_byteswap(&serialized, &restored));
106 }
107
TEST_F(ABTest,SupportSameMajorFutureMinorVersion)108 TEST_F(ABTest, SupportSameMajorFutureMinorVersion) {
109 AvbABData data;
110 AvbABData serialized;
111 AvbABData restored;
112
113 avb_ab_data_init(&data);
114 data.version_minor += 1;
115 avb_ab_data_update_crc_and_byteswap(&data, &serialized);
116 EXPECT_TRUE(avb_ab_data_verify_and_byteswap(&serialized, &restored));
117 }
118
119 #define MISC_PART_SIZE 8 * 1024
120
121 // These values are kept short since they are used in SetMD() and it's
122 // helpful if the information for a slot fits in one 80-character
123 // line.
124 enum SlotValidity {
125 SV_OK, // Slot is valid and verified.
126 SV_INV, // Slot is invalid.
127 SV_UNV, // Slot is valid but unverified.
128 };
129
130 class AvbABFlowTest : public BaseAvbToolTest {
131 public:
AvbABFlowTest()132 AvbABFlowTest() {}
133
SetUp()134 virtual void SetUp() override {
135 BaseAvbToolTest::SetUp();
136 ops_.set_partition_dir(testdir_);
137 ops_.set_stored_rollback_indexes({{0, 0}, {1, 0}, {2, 0}, {3, 0}});
138 ops_.set_stored_is_device_unlocked(false);
139
140 // Create large enough 'misc' partition and initialize it with
141 // zeroes.
142 std::vector<uint8_t> misc;
143 misc.resize(MISC_PART_SIZE);
144 std::filesystem::path misc_path = testdir_ / "misc.img";
145 EXPECT_EQ(misc.size(),
146 static_cast<const size_t>(
147 base::WriteFile(base::FilePath(misc_path.c_str()),
148 reinterpret_cast<const char*>(misc.data()),
149 misc.size())));
150
151 // We're going to use this key for all images.
152 ops_.set_expected_public_key(PublicKeyAVB("test/data/testkey_rsa2048.pem"));
153 }
154
GenerateSlot(unsigned int slot_number,SlotValidity slot_validity,uint64_t rollback_boot,uint64_t rollback_odm)155 void GenerateSlot(unsigned int slot_number,
156 SlotValidity slot_validity,
157 uint64_t rollback_boot,
158 uint64_t rollback_odm) {
159 std::string boot_name = "boot_a.img";
160 std::string vbmeta_name = "vbmeta_a.img";
161 std::string odm_name = "odm_a.img";
162 if (slot_number > 0) {
163 boot_name = "boot_b.img";
164 vbmeta_name = "vbmeta_b.img";
165 odm_name = "odm_b.img";
166 }
167
168 // If asked to make an invalid slot, just generate 1MiB garbage
169 // for each the three images in the slot.
170 if (slot_validity == SV_INV) {
171 GenerateImage(boot_name, 1024 * 1024);
172 GenerateImage(vbmeta_name, 1024 * 1024);
173 GenerateImage(odm_name, 1024 * 1024);
174 return;
175 }
176
177 const size_t boot_partition_size = 16 * 1024 * 1024;
178 const size_t boot_image_size = 5 * 1024 * 1024;
179 std::string boot_path = GenerateImage(boot_name, boot_image_size);
180 EXPECT_COMMAND(0,
181 "./avbtool.py add_hash_footer"
182 " --image %s"
183 " --rollback_index %" PRIu64
184 " --partition_name boot"
185 " --partition_size %zd"
186 " --salt deadbeef",
187 boot_path.c_str(),
188 rollback_boot,
189 boot_partition_size);
190
191 const size_t odm_partition_size = 512 * 1024;
192 const size_t odm_image_size = 80 * 1024;
193 std::string odm_path = GenerateImage(odm_name, odm_image_size);
194 EXPECT_COMMAND(0,
195 "./avbtool.py add_hashtree_footer"
196 " --image %s"
197 " --rollback_index %" PRIu64
198 " --partition_name odm"
199 " --partition_size %zd"
200 " --salt deadbeef"
201 " --algorithm SHA512_RSA4096 "
202 " --key test/data/testkey_rsa4096.pem"
203 " --do_not_generate_fec",
204 odm_path.c_str(),
205 rollback_odm,
206 odm_partition_size);
207
208 std::string pk_path = (testdir_ / "testkey_rsa4096.avbpubkey").string();
209 EXPECT_COMMAND(
210 0,
211 "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
212 " --output %s",
213 pk_path.c_str());
214
215 // If requested to make the image unverified, just use another key
216 // in the chain_partition descriptor since this will cause
217 // avb_slot_verify() to return ERROR_PUBLIC_KEY_REJECTED.
218 if (slot_validity == SV_UNV) {
219 pk_path = GenerateImage("dummy.avbpubkey", 32);
220 }
221
222 GenerateVBMetaImage(
223 vbmeta_name,
224 "SHA256_RSA2048",
225 rollback_boot,
226 "test/data/testkey_rsa2048.pem",
227 android::base::StringPrintf("--include_descriptors_from_image %s"
228 " --chain_partition odm:1:%s",
229 boot_path.c_str(),
230 pk_path.c_str()));
231 }
232
SetMD(int a_pri,int a_tries,bool a_success,SlotValidity a_slot_validity,uint64_t a_rollback_boot,uint64_t a_rollback_odm,int b_pri,int b_tries,bool b_success,SlotValidity b_slot_validity,uint64_t b_rollback_boot,uint64_t b_rollback_odm,const std::map<size_t,uint64_t> & stored_rollback_indexes)233 void SetMD(int a_pri,
234 int a_tries,
235 bool a_success,
236 SlotValidity a_slot_validity,
237 uint64_t a_rollback_boot,
238 uint64_t a_rollback_odm,
239 int b_pri,
240 int b_tries,
241 bool b_success,
242 SlotValidity b_slot_validity,
243 uint64_t b_rollback_boot,
244 uint64_t b_rollback_odm,
245 const std::map<size_t, uint64_t>& stored_rollback_indexes) {
246 AvbABData data;
247 avb_ab_data_init(&data);
248 data.slots[0].priority = a_pri;
249 data.slots[0].tries_remaining = a_tries;
250 data.slots[0].successful_boot = (a_success ? 1 : 0);
251 data.slots[1].priority = b_pri;
252 data.slots[1].tries_remaining = b_tries;
253 data.slots[1].successful_boot = (b_success ? 1 : 0);
254 EXPECT_EQ(AVB_IO_RESULT_OK,
255 ops_.avb_ab_ops()->write_ab_metadata(ops_.avb_ab_ops(), &data));
256 GenerateSlot(0, a_slot_validity, a_rollback_boot, a_rollback_odm);
257 GenerateSlot(1, b_slot_validity, b_rollback_boot, b_rollback_odm);
258 ops_.set_stored_rollback_indexes(stored_rollback_indexes);
259 }
260
MakeRollbackIndexes(uint64_t slot_0_value,uint64_t slot_1_value)261 std::map<size_t, uint64_t> MakeRollbackIndexes(uint64_t slot_0_value,
262 uint64_t slot_1_value) {
263 return std::map<size_t, uint64_t>{{0, slot_0_value}, {1, slot_1_value}};
264 }
265
266 FakeAvbOps ops_;
267 };
268
269 #define ExpMD(a_pri, \
270 a_tries, \
271 a_success, \
272 b_pri, \
273 b_tries, \
274 b_success, \
275 stored_rollback_indexes) \
276 do { \
277 AvbABData data; \
278 EXPECT_EQ(AVB_IO_RESULT_OK, \
279 ops_.avb_ab_ops()->read_ab_metadata(ops_.avb_ab_ops(), &data)); \
280 EXPECT_EQ(a_pri, data.slots[0].priority); \
281 EXPECT_EQ(a_tries, data.slots[0].tries_remaining); \
282 EXPECT_EQ(a_success ? 1 : 0, data.slots[0].successful_boot); \
283 EXPECT_EQ(b_pri, data.slots[1].priority); \
284 EXPECT_EQ(b_tries, data.slots[1].tries_remaining); \
285 EXPECT_EQ(b_success ? 1 : 0, data.slots[1].successful_boot); \
286 EXPECT_EQ(stored_rollback_indexes, ops_.get_stored_rollback_indexes()); \
287 } while (0);
288
TEST_F(AvbABFlowTest,MetadataReadAndWrite)289 TEST_F(AvbABFlowTest, MetadataReadAndWrite) {
290 AvbABData data;
291 AvbABData loaded;
292
293 // First load from an uninitialized 'misc' partition. This should
294 // not fail and just returned initialized data.
295 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_read(ops_.avb_ab_ops(), &loaded));
296 EXPECT_EQ(AVB_AB_MAX_PRIORITY, loaded.slots[0].priority);
297 EXPECT_EQ(AVB_AB_MAX_TRIES_REMAINING, loaded.slots[0].tries_remaining);
298 EXPECT_EQ(0, loaded.slots[0].successful_boot);
299 EXPECT_EQ(AVB_AB_MAX_PRIORITY - 1, loaded.slots[1].priority);
300 EXPECT_EQ(AVB_AB_MAX_TRIES_REMAINING, loaded.slots[1].tries_remaining);
301 EXPECT_EQ(0, loaded.slots[1].successful_boot);
302
303 // Then initialize and save well-known A/B metadata and check we
304 // read back the same thing.
305 avb_ab_data_init(&data);
306 data.slots[0].priority = 2;
307 data.slots[0].tries_remaining = 3;
308 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_write(ops_.avb_ab_ops(), &data));
309 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_read(ops_.avb_ab_ops(), &loaded));
310 EXPECT_EQ(2, loaded.slots[0].priority);
311 EXPECT_EQ(3, loaded.slots[0].tries_remaining);
312 }
313
TEST_F(AvbABFlowTest,EverythingIsValid)314 TEST_F(AvbABFlowTest, EverythingIsValid) {
315 AvbSlotVerifyData* data;
316 const char* requested_partitions[] = {"boot", NULL};
317
318 SetMD(14,
319 0,
320 1,
321 SV_OK,
322 0,
323 0, // A: pri, tries, success, slot_validity, RIs
324 15,
325 0,
326 1,
327 SV_OK,
328 0,
329 0, // B: pri, tries, success, slot_validity, RIs
330 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
331 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
332 avb_ab_flow(ops_.avb_ab_ops(),
333 requested_partitions,
334 AVB_SLOT_VERIFY_FLAGS_NONE,
335 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
336 &data));
337 ExpMD(14,
338 0,
339 1, // A: pri, tries, successful
340 15,
341 0,
342 1, // B: pri, tries, successful
343 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
344 ASSERT_NE(nullptr, data);
345 EXPECT_EQ("_b", std::string(data->ab_suffix));
346 avb_slot_verify_data_free(data);
347
348 // Also check the other slot.
349 SetMD(15,
350 0,
351 1,
352 SV_OK,
353 0,
354 0, // A: pri, tries, success, slot_validity, RIs
355 14,
356 0,
357 1,
358 SV_OK,
359 0,
360 0, // B: pri, tries, success, slot_validity, RIs
361 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
362 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
363 avb_ab_flow(ops_.avb_ab_ops(),
364 requested_partitions,
365 AVB_SLOT_VERIFY_FLAGS_NONE,
366 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
367 &data));
368 ExpMD(15,
369 0,
370 1, // A: pri, tries, successful
371 14,
372 0,
373 1, // B: pri, tries, successful
374 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
375 ASSERT_NE(nullptr, data);
376 EXPECT_EQ("_a", std::string(data->ab_suffix));
377 avb_slot_verify_data_free(data);
378 }
379
TEST_F(AvbABFlowTest,NoBootableSlots)380 TEST_F(AvbABFlowTest, NoBootableSlots) {
381 AvbSlotVerifyData* data;
382 const char* requested_partitions[] = {"boot", NULL};
383
384 SetMD(0,
385 0,
386 0,
387 SV_OK,
388 0,
389 0, // A: pri, tries, success, slot_validity, RIs
390 0,
391 0,
392 0,
393 SV_OK,
394 0,
395 0, // B: pri, tries, success, slot_validity, RIs
396 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
397 EXPECT_EQ(AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
398 avb_ab_flow(ops_.avb_ab_ops(),
399 requested_partitions,
400 AVB_SLOT_VERIFY_FLAGS_NONE,
401 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
402 &data));
403 ExpMD(0,
404 0,
405 0, // A: pri, tries, successful
406 0,
407 0,
408 0, // B: pri, tries, successful
409 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
410 ASSERT_EQ(nullptr, data);
411 }
412
TEST_F(AvbABFlowTest,TriesRemainingDecreasing)413 TEST_F(AvbABFlowTest, TriesRemainingDecreasing) {
414 AvbSlotVerifyData* data;
415 const char* requested_partitions[] = {"boot", NULL};
416
417 SetMD(15,
418 3,
419 0,
420 SV_OK,
421 0,
422 0, // A: pri, tries, success, slot_validity, RIs
423 0,
424 0,
425 0,
426 SV_OK,
427 0,
428 0, // B: pri, tries, success, slot_validity, RIs
429 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
430
431 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
432 avb_ab_flow(ops_.avb_ab_ops(),
433 requested_partitions,
434 AVB_SLOT_VERIFY_FLAGS_NONE,
435 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
436 &data));
437 ExpMD(15,
438 2,
439 0, // A: pri, tries, successful
440 0,
441 0,
442 0, // B: pri, tries, successful
443 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
444 ASSERT_NE(nullptr, data);
445 EXPECT_EQ("_a", std::string(data->ab_suffix));
446 avb_slot_verify_data_free(data);
447
448 // Keep counting down...
449 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
450 avb_ab_flow(ops_.avb_ab_ops(),
451 requested_partitions,
452 AVB_SLOT_VERIFY_FLAGS_NONE,
453 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
454 &data));
455 ExpMD(15,
456 1,
457 0, // A: pri, tries, successful
458 0,
459 0,
460 0, // B: pri, tries, successful
461 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
462 ASSERT_NE(nullptr, data);
463 EXPECT_EQ("_a", std::string(data->ab_suffix));
464 avb_slot_verify_data_free(data);
465
466 // Last try...
467 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
468 avb_ab_flow(ops_.avb_ab_ops(),
469 requested_partitions,
470 AVB_SLOT_VERIFY_FLAGS_NONE,
471 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
472 &data));
473 ExpMD(15,
474 0,
475 0, // A: pri, tries, successful
476 0,
477 0,
478 0, // B: pri, tries, successful
479 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
480 ASSERT_NE(nullptr, data);
481 EXPECT_EQ("_a", std::string(data->ab_suffix));
482 avb_slot_verify_data_free(data);
483
484 // And we're out of tries. At this point, (15, 0, 0) is normalized
485 // to (0, 0, 0) so expect that.
486 EXPECT_EQ(AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
487 avb_ab_flow(ops_.avb_ab_ops(),
488 requested_partitions,
489 AVB_SLOT_VERIFY_FLAGS_NONE,
490 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
491 &data));
492 ExpMD(0,
493 0,
494 0, // A: pri, tries, successful
495 0,
496 0,
497 0, // B: pri, tries, successful
498 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
499 ASSERT_EQ(nullptr, data);
500 }
501
TEST_F(AvbABFlowTest,TryingThenFallback)502 TEST_F(AvbABFlowTest, TryingThenFallback) {
503 AvbSlotVerifyData* data;
504 const char* requested_partitions[] = {"boot", NULL};
505
506 SetMD(15,
507 2,
508 0,
509 SV_OK,
510 0,
511 0, // A: pri, tries, success, slot_validity, RIs
512 14,
513 0,
514 1,
515 SV_OK,
516 0,
517 0, // B: pri, tries, success, slot_validity, RIs
518 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
519 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
520 avb_ab_flow(ops_.avb_ab_ops(),
521 requested_partitions,
522 AVB_SLOT_VERIFY_FLAGS_NONE,
523 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
524 &data));
525 ExpMD(15,
526 1,
527 0, // A: pri, tries, successful
528 14,
529 0,
530 1, // B: pri, tries, successful
531 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
532 ASSERT_NE(nullptr, data);
533 EXPECT_EQ("_a", std::string(data->ab_suffix));
534 avb_slot_verify_data_free(data);
535
536 // Last try...
537 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
538 avb_ab_flow(ops_.avb_ab_ops(),
539 requested_partitions,
540 AVB_SLOT_VERIFY_FLAGS_NONE,
541 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
542 &data));
543 ExpMD(15,
544 0,
545 0, // A: pri, tries, successful
546 14,
547 0,
548 1, // B: pri, tries, successful
549 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
550 ASSERT_NE(nullptr, data);
551 EXPECT_EQ("_a", std::string(data->ab_suffix));
552 avb_slot_verify_data_free(data);
553
554 // And we're out of tries. Check we fall back to slot B.
555 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
556 avb_ab_flow(ops_.avb_ab_ops(),
557 requested_partitions,
558 AVB_SLOT_VERIFY_FLAGS_NONE,
559 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
560 &data));
561 ExpMD(0,
562 0,
563 0, // A: pri, tries, successful
564 14,
565 0,
566 1, // B: pri, tries, successful
567 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
568 ASSERT_NE(nullptr, data);
569 EXPECT_EQ("_b", std::string(data->ab_suffix));
570 avb_slot_verify_data_free(data);
571 }
572
TEST_F(AvbABFlowTest,TriesRemainingNotDecreasingIfNotPriority)573 TEST_F(AvbABFlowTest, TriesRemainingNotDecreasingIfNotPriority) {
574 AvbSlotVerifyData* data;
575 const char* requested_partitions[] = {"boot", NULL};
576
577 SetMD(15,
578 0,
579 1,
580 SV_OK,
581 0,
582 0, // A: pri, tries, success, slot_validity, RIs
583 14,
584 7,
585 0,
586 SV_OK,
587 0,
588 0, // B: pri, tries, success, slot_validity, RIs
589 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
590 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
591 avb_ab_flow(ops_.avb_ab_ops(),
592 requested_partitions,
593 AVB_SLOT_VERIFY_FLAGS_NONE,
594 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
595 &data));
596 ExpMD(15,
597 0,
598 1, // A: pri, tries, successful
599 14,
600 7,
601 0, // B: pri, tries, successful
602 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
603 ASSERT_NE(nullptr, data);
604 EXPECT_EQ("_a", std::string(data->ab_suffix));
605 avb_slot_verify_data_free(data);
606 }
607
TEST_F(AvbABFlowTest,InvalidSlotIsMarkedAsSuch)608 TEST_F(AvbABFlowTest, InvalidSlotIsMarkedAsSuch) {
609 AvbSlotVerifyData* data;
610 const char* requested_partitions[] = {"boot", NULL};
611
612 // Slot A is invalid.
613 SetMD(15,
614 0,
615 1,
616 SV_INV,
617 0,
618 0, // A: pri, tries, success, slot_validity, RIs
619 14,
620 0,
621 1,
622 SV_OK,
623 0,
624 0, // B: pri, tries, success, slot_validity, RIs
625 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
626 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
627 avb_ab_flow(ops_.avb_ab_ops(),
628 requested_partitions,
629 AVB_SLOT_VERIFY_FLAGS_NONE,
630 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
631 &data));
632 ExpMD(0,
633 0,
634 0, // A: pri, tries, successful
635 14,
636 0,
637 1, // B: pri, tries, successful
638 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
639 ASSERT_NE(nullptr, data);
640 EXPECT_EQ("_b", std::string(data->ab_suffix));
641 avb_slot_verify_data_free(data);
642
643 // Slot B is invalid.
644 SetMD(15,
645 0,
646 1,
647 SV_OK,
648 0,
649 0, // A: pri, tries, success, slot_validity, RIs
650 14,
651 0,
652 1,
653 SV_INV,
654 0,
655 0, // B: pri, tries, success, slot_validity, RIs
656 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
657 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
658 avb_ab_flow(ops_.avb_ab_ops(),
659 requested_partitions,
660 AVB_SLOT_VERIFY_FLAGS_NONE,
661 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
662 &data));
663 ExpMD(15,
664 0,
665 1, // A: pri, tries, successful
666 0,
667 0,
668 0, // B: pri, tries, successful
669 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
670 ASSERT_NE(nullptr, data);
671 EXPECT_EQ("_a", std::string(data->ab_suffix));
672 avb_slot_verify_data_free(data);
673
674 // Both slots are invalid.
675 SetMD(15,
676 0,
677 1,
678 SV_INV,
679 0,
680 0, // A: pri, tries, success, slot_validity, RIs
681 14,
682 0,
683 1,
684 SV_INV,
685 0,
686 0, // B: pri, tries, success, slot_validity, RIs
687 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
688 EXPECT_EQ(AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
689 avb_ab_flow(ops_.avb_ab_ops(),
690 requested_partitions,
691 AVB_SLOT_VERIFY_FLAGS_NONE,
692 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
693 &data));
694 ExpMD(0,
695 0,
696 0, // A: pri, tries, successful
697 0,
698 0,
699 0, // B: pri, tries, successful
700 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
701 ASSERT_EQ(nullptr, data);
702 }
703
TEST_F(AvbABFlowTest,UnverifiedSlotIsMarkedAsSuch)704 TEST_F(AvbABFlowTest, UnverifiedSlotIsMarkedAsSuch) {
705 AvbSlotVerifyData* data;
706 const char* requested_partitions[] = {"boot", NULL};
707
708 // Slot A fails verification.
709 SetMD(15,
710 0,
711 1,
712 SV_UNV,
713 0,
714 0, // A: pri, tries, success, slot_validity, RIs
715 14,
716 0,
717 1,
718 SV_OK,
719 0,
720 0, // B: pri, tries, success, slot_validity, RIs
721 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
722 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
723 avb_ab_flow(ops_.avb_ab_ops(),
724 requested_partitions,
725 AVB_SLOT_VERIFY_FLAGS_NONE,
726 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
727 &data));
728 ExpMD(0,
729 0,
730 0, // A: pri, tries, successful
731 14,
732 0,
733 1, // B: pri, tries, successful
734 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
735 ASSERT_NE(nullptr, data);
736 EXPECT_EQ("_b", std::string(data->ab_suffix));
737 avb_slot_verify_data_free(data);
738
739 // Slot B fails verification.
740 SetMD(15,
741 0,
742 1,
743 SV_OK,
744 0,
745 0, // A: pri, tries, success, slot_validity, RIs
746 14,
747 0,
748 1,
749 SV_UNV,
750 0,
751 0, // B: pri, tries, success, slot_validity, RIs
752 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
753 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
754 avb_ab_flow(ops_.avb_ab_ops(),
755 requested_partitions,
756 AVB_SLOT_VERIFY_FLAGS_NONE,
757 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
758 &data));
759 ExpMD(15,
760 0,
761 1, // A: pri, tries, successful
762 0,
763 0,
764 0, // B: pri, tries, successful
765 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
766 ASSERT_NE(nullptr, data);
767 EXPECT_EQ("_a", std::string(data->ab_suffix));
768 avb_slot_verify_data_free(data);
769
770 // Both slots fail verification.
771 SetMD(15,
772 0,
773 1,
774 SV_UNV,
775 0,
776 0, // A: pri, tries, success, slot_validity, RIs
777 14,
778 0,
779 1,
780 SV_UNV,
781 0,
782 0, // B: pri, tries, success, slot_validity, RIs
783 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
784 EXPECT_EQ(AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
785 avb_ab_flow(ops_.avb_ab_ops(),
786 requested_partitions,
787 AVB_SLOT_VERIFY_FLAGS_NONE,
788 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
789 &data));
790 ExpMD(0,
791 0,
792 0, // A: pri, tries, successful
793 0,
794 0,
795 0, // B: pri, tries, successful
796 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
797 ASSERT_EQ(nullptr, data);
798 }
799
TEST_F(AvbABFlowTest,RollbackIndexFailures)800 TEST_F(AvbABFlowTest, RollbackIndexFailures) {
801 AvbSlotVerifyData* data;
802 const char* requested_partitions[] = {"boot", NULL};
803
804 // Slot A rollback index failure for 'boot'.
805 SetMD(15,
806 0,
807 1,
808 SV_OK,
809 0,
810 2, // A: pri, tries, success, slot_validity, RIs
811 14,
812 0,
813 1,
814 SV_OK,
815 2,
816 2, // B: pri, tries, success, slot_validity, RIs
817 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
818 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
819 avb_ab_flow(ops_.avb_ab_ops(),
820 requested_partitions,
821 AVB_SLOT_VERIFY_FLAGS_NONE,
822 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
823 &data));
824 ExpMD(0,
825 0,
826 0, // A: pri, tries, successful
827 14,
828 0,
829 1, // B: pri, tries, successful
830 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
831 ASSERT_NE(nullptr, data);
832 EXPECT_EQ("_b", std::string(data->ab_suffix));
833 avb_slot_verify_data_free(data);
834
835 // Slot A rollback index failure for 'odm'.
836 SetMD(15,
837 0,
838 1,
839 SV_OK,
840 2,
841 0, // A: pri, tries, success, slot_validity, RIs
842 14,
843 0,
844 1,
845 SV_OK,
846 2,
847 2, // B: pri, tries, success, slot_validity, RIs
848 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
849 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
850 avb_ab_flow(ops_.avb_ab_ops(),
851 requested_partitions,
852 AVB_SLOT_VERIFY_FLAGS_NONE,
853 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
854 &data));
855 ExpMD(0,
856 0,
857 0, // A: pri, tries, successful
858 14,
859 0,
860 1, // B: pri, tries, successful
861 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
862 ASSERT_NE(nullptr, data);
863 EXPECT_EQ("_b", std::string(data->ab_suffix));
864 avb_slot_verify_data_free(data);
865 }
866
TEST_F(AvbABFlowTest,StoredRollbackIndexBumped)867 TEST_F(AvbABFlowTest, StoredRollbackIndexBumped) {
868 AvbSlotVerifyData* data;
869 const char* requested_partitions[] = {"boot", NULL};
870
871 SetMD(15,
872 0,
873 1,
874 SV_OK,
875 3,
876 3, // A: pri, tries, success, slot_validity, RIs
877 14,
878 0,
879 1,
880 SV_OK,
881 3,
882 3, // B: pri, tries, success, slot_validity, RIs
883 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
884 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
885 avb_ab_flow(ops_.avb_ab_ops(),
886 requested_partitions,
887 AVB_SLOT_VERIFY_FLAGS_NONE,
888 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
889 &data));
890 ExpMD(15,
891 0,
892 1, // A: pri, tries, successful
893 14,
894 0,
895 1, // B: pri, tries, successful
896 MakeRollbackIndexes(3, 3)); // stored_rollback_indexes
897 ASSERT_NE(nullptr, data);
898 EXPECT_EQ("_a", std::string(data->ab_suffix));
899 avb_slot_verify_data_free(data);
900
901 // The case where different partitions have different rollback
902 // index values.
903 SetMD(15,
904 0,
905 1,
906 SV_OK,
907 4,
908 9, // A: pri, tries, success, slot_validity, RIs
909 14,
910 0,
911 1,
912 SV_OK,
913 5,
914 7, // B: pri, tries, success, slot_validity, RIs
915 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
916 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
917 avb_ab_flow(ops_.avb_ab_ops(),
918 requested_partitions,
919 AVB_SLOT_VERIFY_FLAGS_NONE,
920 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
921 &data));
922 ExpMD(15,
923 0,
924 1, // A: pri, tries, successful
925 14,
926 0,
927 1, // B: pri, tries, successful
928 MakeRollbackIndexes(4, 7)); // stored_rollback_indexes
929 ASSERT_NE(nullptr, data);
930 EXPECT_EQ("_a", std::string(data->ab_suffix));
931 avb_slot_verify_data_free(data);
932
933 // If the slot with the low RI fails verification (or is invalid),
934 // check that these low Rollback Indexs are not taken into account
935 // after marking it as unbootable.
936 SetMD(15,
937 0,
938 1,
939 SV_INV,
940 4,
941 9, // A: pri, tries, success, slot_validity, RIs
942 14,
943 0,
944 1,
945 SV_OK,
946 5,
947 7, // B: pri, tries, success, slot_validity, RIs
948 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
949 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
950 avb_ab_flow(ops_.avb_ab_ops(),
951 requested_partitions,
952 AVB_SLOT_VERIFY_FLAGS_NONE,
953 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
954 &data));
955 ExpMD(0,
956 0,
957 0, // A: pri, tries, successful
958 14,
959 0,
960 1, // B: pri, tries, successful
961 MakeRollbackIndexes(5, 7)); // stored_rollback_indexes
962 ASSERT_NE(nullptr, data);
963 EXPECT_EQ("_b", std::string(data->ab_suffix));
964 avb_slot_verify_data_free(data);
965 }
966
TEST_F(AvbABFlowTest,MarkSlotActive)967 TEST_F(AvbABFlowTest, MarkSlotActive) {
968 SetMD(15,
969 0,
970 1,
971 SV_INV,
972 0,
973 0, // A: pri, tries, success, slot_validity, RIs
974 11,
975 0,
976 1,
977 SV_OK,
978 0,
979 0, // B: pri, tries, success, slot_validity, RIs
980 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
981 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_active(ops_.avb_ab_ops(), 0));
982 ExpMD(15,
983 7,
984 0, // A: pri, tries, successful
985 11,
986 0,
987 1, // B: pri, tries, successful
988 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
989
990 // Note how priority of slot A is altered to make room for newly
991 // activated slot.
992 SetMD(15,
993 0,
994 1,
995 SV_INV,
996 0,
997 0, // A: pri, tries, success, slot_validity, RIs
998 14,
999 0,
1000 1,
1001 SV_OK,
1002 0,
1003 0, // B: pri, tries, success, slot_validity, RIs
1004 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1005 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_active(ops_.avb_ab_ops(), 1));
1006 ExpMD(14,
1007 0,
1008 1, // A: pri, tries, successful
1009 15,
1010 7,
1011 0, // B: pri, tries, successful
1012 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1013 }
1014
TEST_F(AvbABFlowTest,MarkSlotUnbootable)1015 TEST_F(AvbABFlowTest, MarkSlotUnbootable) {
1016 SetMD(15,
1017 0,
1018 1,
1019 SV_INV,
1020 0,
1021 0, // A: pri, tries, success, slot_validity, RIs
1022 11,
1023 0,
1024 1,
1025 SV_OK,
1026 0,
1027 0, // B: pri, tries, success, slot_validity, RIs
1028 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1029 EXPECT_EQ(AVB_IO_RESULT_OK,
1030 avb_ab_mark_slot_unbootable(ops_.avb_ab_ops(), 0));
1031 ExpMD(0,
1032 0,
1033 0, // A: pri, tries, successful
1034 11,
1035 0,
1036 1, // B: pri, tries, successful
1037 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1038
1039 SetMD(15,
1040 0,
1041 1,
1042 SV_INV,
1043 0,
1044 0, // A: pri, tries, success, slot_validity, RIs
1045 14,
1046 0,
1047 1,
1048 SV_OK,
1049 0,
1050 0, // B: pri, tries, success, slot_validity, RIs
1051 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1052 EXPECT_EQ(AVB_IO_RESULT_OK,
1053 avb_ab_mark_slot_unbootable(ops_.avb_ab_ops(), 1));
1054 ExpMD(15,
1055 0,
1056 1, // A: pri, tries, successful
1057 0,
1058 0,
1059 0, // B: pri, tries, successful
1060 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1061 }
1062
TEST_F(AvbABFlowTest,MarkSlotSuccessful)1063 TEST_F(AvbABFlowTest, MarkSlotSuccessful) {
1064 SetMD(15,
1065 5,
1066 0,
1067 SV_INV,
1068 0,
1069 0, // A: pri, tries, success, slot_validity, RIs
1070 11,
1071 3,
1072 0,
1073 SV_OK,
1074 0,
1075 0, // B: pri, tries, success, slot_validity, RIs
1076 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1077 EXPECT_EQ(AVB_IO_RESULT_OK,
1078 avb_ab_mark_slot_successful(ops_.avb_ab_ops(), 0));
1079 ExpMD(15,
1080 0,
1081 1, // A: pri, tries, successful
1082 11,
1083 3,
1084 0, // B: pri, tries, successful
1085 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1086
1087 SetMD(15,
1088 5,
1089 0,
1090 SV_INV,
1091 0,
1092 0, // A: pri, tries, success, slot_validity, RIs
1093 14,
1094 0,
1095 1,
1096 SV_OK,
1097 0,
1098 0, // B: pri, tries, success, slot_validity, RIs
1099 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1100 EXPECT_EQ(AVB_IO_RESULT_OK,
1101 avb_ab_mark_slot_successful(ops_.avb_ab_ops(), 1));
1102 ExpMD(15,
1103 5,
1104 0, // A: pri, tries, successful
1105 14,
1106 0,
1107 1, // B: pri, tries, successful
1108 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1109
1110 // Marking an unbootable slot (A) as successful won't work (it's a
1111 // programmer error to do so)... notice however that the unbootable
1112 // slot is normalized in the process.
1113 SetMD(0,
1114 3,
1115 2,
1116 SV_INV,
1117 0,
1118 0, // A: pri, tries, success, slot_validity, RIs
1119 14,
1120 0,
1121 1,
1122 SV_OK,
1123 0,
1124 0, // B: pri, tries, success, slot_validity, RIs
1125 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1126 EXPECT_EQ(AVB_IO_RESULT_OK,
1127 avb_ab_mark_slot_successful(ops_.avb_ab_ops(), 0));
1128 ExpMD(0,
1129 0,
1130 0, // A: pri, tries, successful
1131 14,
1132 0,
1133 1, // B: pri, tries, successful
1134 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1135 }
1136
1137 static AvbABData my_serialized_data;
1138
my_write_ab_metadata(AvbABOps * ops,const struct AvbABData * data)1139 static AvbIOResult my_write_ab_metadata(AvbABOps* ops,
1140 const struct AvbABData* data) {
1141 avb_ab_data_update_crc_and_byteswap(data, &my_serialized_data);
1142 return AVB_IO_RESULT_OK;
1143 }
1144
my_read_ab_metadata(AvbABOps * ops,struct AvbABData * data)1145 static AvbIOResult my_read_ab_metadata(AvbABOps* ops, struct AvbABData* data) {
1146 if (!avb_ab_data_verify_and_byteswap(&my_serialized_data, data)) {
1147 avb_error(
1148 "Error validating A/B metadata from persistent storage. "
1149 "Resetting and writing new A/B metadata to persistent storage.\n");
1150 avb_ab_data_init(data);
1151 return my_write_ab_metadata(ops, data);
1152 }
1153 return AVB_IO_RESULT_OK;
1154 }
1155
TEST_F(AvbABFlowTest,OtherMetadataStorage)1156 TEST_F(AvbABFlowTest, OtherMetadataStorage) {
1157 AvbSlotVerifyData* data;
1158 const char* requested_partitions[] = {"boot", NULL};
1159
1160 // Use our own A/B storage routines (see above).
1161 ops_.avb_ab_ops()->read_ab_metadata = my_read_ab_metadata;
1162 ops_.avb_ab_ops()->write_ab_metadata = my_write_ab_metadata;
1163
1164 SetMD(14,
1165 0,
1166 1,
1167 SV_OK,
1168 0,
1169 0, // A: pri, tries, success, slot_validity, RIs
1170 15,
1171 0,
1172 1,
1173 SV_OK,
1174 0,
1175 0, // B: pri, tries, success, slot_validity, RIs
1176 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1177 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
1178 avb_ab_flow(ops_.avb_ab_ops(),
1179 requested_partitions,
1180 AVB_SLOT_VERIFY_FLAGS_NONE,
1181 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1182 &data));
1183 ExpMD(14,
1184 0,
1185 1, // A: pri, tries, successful
1186 15,
1187 0,
1188 1, // B: pri, tries, successful
1189 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1190 ASSERT_NE(nullptr, data);
1191 EXPECT_EQ("_b", std::string(data->ab_suffix));
1192 avb_slot_verify_data_free(data);
1193
1194 // Also check the other slot.
1195 SetMD(15,
1196 0,
1197 1,
1198 SV_OK,
1199 0,
1200 0, // A: pri, tries, success, slot_validity, RIs
1201 14,
1202 0,
1203 1,
1204 SV_OK,
1205 0,
1206 0, // B: pri, tries, success, slot_validity, RIs
1207 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1208 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
1209 avb_ab_flow(ops_.avb_ab_ops(),
1210 requested_partitions,
1211 AVB_SLOT_VERIFY_FLAGS_NONE,
1212 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1213 &data));
1214 ExpMD(15,
1215 0,
1216 1, // A: pri, tries, successful
1217 14,
1218 0,
1219 1, // B: pri, tries, successful
1220 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1221 ASSERT_NE(nullptr, data);
1222 EXPECT_EQ("_a", std::string(data->ab_suffix));
1223 avb_slot_verify_data_free(data);
1224
1225 // Check that 'misc' hasn't been written to at all.
1226 std::string misc_data;
1227 std::filesystem::path misc_path = testdir_ / "misc.img";
1228 ASSERT_TRUE(android::base::ReadFileToString(misc_path.string(), &misc_data));
1229 EXPECT_EQ(size_t(MISC_PART_SIZE), misc_data.size());
1230 for (size_t n = 0; n < misc_data.size(); n++) {
1231 ASSERT_EQ(uint8_t(misc_data[n]), 0);
1232 }
1233 }
1234
TEST_F(AvbABFlowTest,UnlockedUnverifiedSlot)1235 TEST_F(AvbABFlowTest, UnlockedUnverifiedSlot) {
1236 AvbSlotVerifyData* data;
1237 const char* requested_partitions[] = {"boot", NULL};
1238
1239 SetMD(14,
1240 0,
1241 1,
1242 SV_OK,
1243 0,
1244 0, // A: pri, tries, success, slot_validity, RIs
1245 15,
1246 0,
1247 1,
1248 SV_UNV,
1249 0,
1250 0, // B: pri, tries, success, slot_validity, RIs
1251 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1252 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR,
1253 avb_ab_flow(ops_.avb_ab_ops(),
1254 requested_partitions,
1255 AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
1256 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1257 &data));
1258 ExpMD(14,
1259 0,
1260 1, // A: pri, tries, successful
1261 15,
1262 0,
1263 1, // B: pri, tries, successful
1264 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1265 ASSERT_NE(nullptr, data);
1266 EXPECT_EQ("_b", std::string(data->ab_suffix));
1267 avb_slot_verify_data_free(data);
1268
1269 // Also check the other slot.
1270 SetMD(15,
1271 0,
1272 1,
1273 SV_UNV,
1274 0,
1275 0, // A: pri, tries, success, slot_validity, RIs
1276 14,
1277 0,
1278 1,
1279 SV_OK,
1280 0,
1281 0, // B: pri, tries, success, slot_validity, RIs
1282 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1283 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR,
1284 avb_ab_flow(ops_.avb_ab_ops(),
1285 requested_partitions,
1286 AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
1287 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1288 &data));
1289 ExpMD(15,
1290 0,
1291 1, // A: pri, tries, successful
1292 14,
1293 0,
1294 1, // B: pri, tries, successful
1295 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1296 ASSERT_NE(nullptr, data);
1297 EXPECT_EQ("_a", std::string(data->ab_suffix));
1298 avb_slot_verify_data_free(data);
1299 }
1300
TEST_F(AvbABFlowTest,AvbtoolMetadataGeneratorEmptyFile)1301 TEST_F(AvbABFlowTest, AvbtoolMetadataGeneratorEmptyFile) {
1302 AvbABData data;
1303
1304 std::filesystem::path misc_path = testdir_ / "misc.img";
1305 EXPECT_COMMAND(0,
1306 "./avbtool.py set_ab_metadata"
1307 " --misc_image %s"
1308 " --slot_data 13:3:0:11:2:1",
1309 misc_path.c_str());
1310
1311 EXPECT_EQ(AVB_IO_RESULT_OK,
1312 ops_.avb_ab_ops()->read_ab_metadata(ops_.avb_ab_ops(), &data));
1313 EXPECT_EQ(13, data.slots[0].priority);
1314 EXPECT_EQ(3, data.slots[0].tries_remaining);
1315 EXPECT_EQ(0, data.slots[0].successful_boot);
1316 EXPECT_EQ(11, data.slots[1].priority);
1317 EXPECT_EQ(2, data.slots[1].tries_remaining);
1318 EXPECT_EQ(1, data.slots[1].successful_boot);
1319 }
1320
TEST_F(AvbABFlowTest,AvbtoolMetadataGeneratorExistingFile)1321 TEST_F(AvbABFlowTest, AvbtoolMetadataGeneratorExistingFile) {
1322 AvbABData data;
1323 size_t n;
1324
1325 size_t misc_size = 1024 * 1024;
1326 std::string misc_path = GenerateImage("misc.img", misc_size);
1327 EXPECT_COMMAND(0,
1328 "./avbtool.py set_ab_metadata"
1329 " --misc_image %s"
1330 " --slot_data 12:2:1:10:5:0",
1331 misc_path.c_str());
1332
1333 EXPECT_EQ(AVB_IO_RESULT_OK,
1334 ops_.avb_ab_ops()->read_ab_metadata(ops_.avb_ab_ops(), &data));
1335 EXPECT_EQ(12, data.slots[0].priority);
1336 EXPECT_EQ(2, data.slots[0].tries_remaining);
1337 EXPECT_EQ(1, data.slots[0].successful_boot);
1338 EXPECT_EQ(10, data.slots[1].priority);
1339 EXPECT_EQ(5, data.slots[1].tries_remaining);
1340 EXPECT_EQ(0, data.slots[1].successful_boot);
1341
1342 std::string misc_data;
1343 ASSERT_TRUE(android::base::ReadFileToString(misc_path, &misc_data));
1344 EXPECT_EQ(misc_size, misc_data.size());
1345 for (n = 0; n < 2048; n++) {
1346 ASSERT_EQ(uint8_t(misc_data[n]), uint8_t(n));
1347 }
1348 for (n = 2048 + 32; n < misc_data.size(); n++) {
1349 ASSERT_EQ(uint8_t(misc_data[n]), uint8_t(n));
1350 }
1351 }
1352
1353 } // namespace avb
1354