• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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