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