• 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 <iostream>
26 
27 #include <base/files/file_util.h>
28 #include <base/strings/string_util.h>
29 #include <base/strings/stringprintf.h>
30 
31 #include "avb_unittest_util.h"
32 #include "fake_avb_ops.h"
33 
34 namespace avb {
35 
36 class AvbSlotVerifyTest : public BaseAvbToolTest {
37  public:
AvbSlotVerifyTest()38   AvbSlotVerifyTest() {}
39 
SetUp()40   virtual void SetUp() override {
41     BaseAvbToolTest::SetUp();
42     ops_.set_partition_dir(testdir_);
43     ops_.set_stored_rollback_indexes({{0, 0}, {1, 0}, {2, 0}, {3, 0}});
44     ops_.set_stored_is_device_unlocked(false);
45   }
46 
47   void CmdlineWithHashtreeVerification(bool hashtree_verification_on);
48   void CmdlineWithChainedHashtreeVerification(bool hashtree_verification_on);
49   void VerificationDisabled(bool use_avbctl);
50 
51   FakeAvbOps ops_;
52 };
53 
TEST_F(AvbSlotVerifyTest,Basic)54 TEST_F(AvbSlotVerifyTest, Basic) {
55   GenerateVBMetaImage("vbmeta_a.img",
56                       "SHA256_RSA2048",
57                       0,
58                       base::FilePath("test/data/testkey_rsa2048.pem"),
59                       "--internal_release_string \"\"");
60 
61   ops_.set_expected_public_key(
62       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
63 
64   AvbSlotVerifyData* slot_data = NULL;
65   const char* requested_partitions[] = {"boot", NULL};
66   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
67             avb_slot_verify(ops_.avb_ops(),
68                             requested_partitions,
69                             "_a",
70                             AVB_SLOT_VERIFY_FLAGS_NONE,
71                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
72                             &slot_data));
73   EXPECT_NE(nullptr, slot_data);
74   EXPECT_EQ(
75       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
76       "androidboot.vbmeta.avb_version=1.0 "
77       "androidboot.vbmeta.device_state=locked "
78       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1152 "
79       "androidboot.vbmeta.digest="
80       "4161a7e655eabe16c3fe714de5d43736e7c0a190cf08d36c946d2509ce071e4d "
81       "androidboot.vbmeta.invalidate_on_error=yes "
82       "androidboot.veritymode=enforcing",
83       std::string(slot_data->cmdline));
84   avb_slot_verify_data_free(slot_data);
85 }
86 
TEST_F(AvbSlotVerifyTest,BasicSha512)87 TEST_F(AvbSlotVerifyTest, BasicSha512) {
88   GenerateVBMetaImage("vbmeta_a.img",
89                       "SHA512_RSA2048",
90                       0,
91                       base::FilePath("test/data/testkey_rsa2048.pem"),
92                       "--internal_release_string \"\"");
93 
94   ops_.set_expected_public_key(
95       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
96 
97   AvbSlotVerifyData* slot_data = NULL;
98   const char* requested_partitions[] = {"boot", NULL};
99   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
100             avb_slot_verify(ops_.avb_ops(),
101                             requested_partitions,
102                             "_a",
103                             AVB_SLOT_VERIFY_FLAGS_NONE,
104                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
105                             &slot_data));
106   EXPECT_NE(nullptr, slot_data);
107   EXPECT_EQ(
108       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
109       "androidboot.vbmeta.avb_version=1.0 "
110       "androidboot.vbmeta.device_state=locked "
111       "androidboot.vbmeta.hash_alg=sha512 androidboot.vbmeta.size=1152 "
112       "androidboot.vbmeta.digest="
113       "cb913d2f1a884f4e04c1db5bb181f3133fd16ac02fb367a20ef0776c0b07b3656ad1f081"
114       "e01932cf70f38b8960877470b448f1588dff022808387cc52fa77e77 "
115       "androidboot.vbmeta.invalidate_on_error=yes "
116       "androidboot.veritymode=enforcing",
117       std::string(slot_data->cmdline));
118   avb_slot_verify_data_free(slot_data);
119 }
120 
TEST_F(AvbSlotVerifyTest,BasicUnlocked)121 TEST_F(AvbSlotVerifyTest, BasicUnlocked) {
122   GenerateVBMetaImage("vbmeta_a.img",
123                       "SHA256_RSA2048",
124                       0,
125                       base::FilePath("test/data/testkey_rsa2048.pem"),
126                       "--internal_release_string \"\"");
127 
128   ops_.set_expected_public_key(
129       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
130 
131   ops_.set_stored_is_device_unlocked(true);
132 
133   AvbSlotVerifyData* slot_data = NULL;
134   const char* requested_partitions[] = {"boot", NULL};
135   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
136             avb_slot_verify(ops_.avb_ops(),
137                             requested_partitions,
138                             "_a",
139                             AVB_SLOT_VERIFY_FLAGS_NONE,
140                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
141                             &slot_data));
142   EXPECT_NE(nullptr, slot_data);
143   EXPECT_EQ(
144       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
145       "androidboot.vbmeta.avb_version=1.0 "
146       "androidboot.vbmeta.device_state=unlocked "
147       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1152 "
148       "androidboot.vbmeta.digest="
149       "4161a7e655eabe16c3fe714de5d43736e7c0a190cf08d36c946d2509ce071e4d "
150       "androidboot.vbmeta.invalidate_on_error=yes "
151       "androidboot.veritymode=enforcing",
152       std::string(slot_data->cmdline));
153   avb_slot_verify_data_free(slot_data);
154 }
155 
TEST_F(AvbSlotVerifyTest,SlotDataIsCorrect)156 TEST_F(AvbSlotVerifyTest, SlotDataIsCorrect) {
157   GenerateVBMetaImage("vbmeta_a.img",
158                       "SHA256_RSA2048",
159                       0,
160                       base::FilePath("test/data/testkey_rsa2048.pem"),
161                       "--internal_release_string \"\"");
162 
163   ops_.set_expected_public_key(
164       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
165 
166   AvbSlotVerifyData* slot_data = NULL;
167   const char* requested_partitions[] = {"boot", NULL};
168   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
169             avb_slot_verify(ops_.avb_ops(),
170                             requested_partitions,
171                             "_a",
172                             AVB_SLOT_VERIFY_FLAGS_NONE,
173                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
174                             &slot_data));
175   EXPECT_NE(nullptr, slot_data);
176   avb_slot_verify_data_free(slot_data);
177 }
178 
TEST_F(AvbSlotVerifyTest,WrongPublicKey)179 TEST_F(AvbSlotVerifyTest, WrongPublicKey) {
180   GenerateVBMetaImage("vbmeta_a.img",
181                       "SHA256_RSA2048",
182                       0,
183                       base::FilePath("test/data/testkey_rsa2048.pem"),
184                       "--internal_release_string \"\"");
185 
186   AvbSlotVerifyData* slot_data = NULL;
187   const char* requested_partitions[] = {"boot", NULL};
188   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
189             avb_slot_verify(ops_.avb_ops(),
190                             requested_partitions,
191                             "_a",
192                             AVB_SLOT_VERIFY_FLAGS_NONE,
193                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
194                             &slot_data));
195   EXPECT_EQ(nullptr, slot_data);
196   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
197             avb_slot_verify(ops_.avb_ops(),
198                             requested_partitions,
199                             "_a",
200                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
201                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
202                             &slot_data));
203   EXPECT_NE(nullptr, slot_data);
204   avb_slot_verify_data_free(slot_data);
205 }
206 
TEST_F(AvbSlotVerifyTest,NoImage)207 TEST_F(AvbSlotVerifyTest, NoImage) {
208   const char* requested_partitions[] = {"boot", NULL};
209   AvbSlotVerifyData* slot_data = NULL;
210   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_IO,
211             avb_slot_verify(ops_.avb_ops(),
212                             requested_partitions,
213                             "_a",
214                             AVB_SLOT_VERIFY_FLAGS_NONE,
215                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
216                             &slot_data));
217   EXPECT_EQ(nullptr, slot_data);
218 }
219 
TEST_F(AvbSlotVerifyTest,UnsignedVBMeta)220 TEST_F(AvbSlotVerifyTest, UnsignedVBMeta) {
221   GenerateVBMetaImage("vbmeta_a.img",
222                       "",
223                       0,
224                       base::FilePath(""),
225                       "--internal_release_string \"\"");
226 
227   AvbSlotVerifyData* slot_data = NULL;
228   const char* requested_partitions[] = {"boot", NULL};
229   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
230             avb_slot_verify(ops_.avb_ops(),
231                             requested_partitions,
232                             "_a",
233                             AVB_SLOT_VERIFY_FLAGS_NONE,
234                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
235                             &slot_data));
236   EXPECT_EQ(nullptr, slot_data);
237   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
238             avb_slot_verify(ops_.avb_ops(),
239                             requested_partitions,
240                             "_a",
241                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
242                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
243                             &slot_data));
244   EXPECT_NE(nullptr, slot_data);
245   avb_slot_verify_data_free(slot_data);
246 }
247 
TEST_F(AvbSlotVerifyTest,CorruptedImage)248 TEST_F(AvbSlotVerifyTest, CorruptedImage) {
249   GenerateVBMetaImage("vbmeta_a.img",
250                       "SHA256_RSA2048",
251                       0,
252                       base::FilePath("test/data/testkey_rsa2048.pem"),
253                       "--internal_release_string \"\"");
254 
255   // Corrupt four bytes of data in the end of the image. Since the aux
256   // data is at the end and this data is signed, this will change the
257   // value of the computed hash.
258   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
259   EXPECT_EQ(AVB_IO_RESULT_OK,
260             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
261                                                "vbmeta_a",
262                                                -4,  // offset from end
263                                                sizeof corrupt_data,
264                                                corrupt_data));
265 
266   AvbSlotVerifyData* slot_data = NULL;
267   const char* requested_partitions[] = {"boot", NULL};
268   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
269             avb_slot_verify(ops_.avb_ops(),
270                             requested_partitions,
271                             "_a",
272                             AVB_SLOT_VERIFY_FLAGS_NONE,
273                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
274                             &slot_data));
275   EXPECT_EQ(nullptr, slot_data);
276   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
277             avb_slot_verify(ops_.avb_ops(),
278                             requested_partitions,
279                             "_a",
280                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
281                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
282                             &slot_data));
283   EXPECT_NE(nullptr, slot_data);
284   avb_slot_verify_data_free(slot_data);
285 }
286 
TEST_F(AvbSlotVerifyTest,CorruptedMetadata)287 TEST_F(AvbSlotVerifyTest, CorruptedMetadata) {
288   GenerateVBMetaImage("vbmeta_a.img",
289                       "SHA256_RSA2048",
290                       0,
291                       base::FilePath("test/data/testkey_rsa2048.pem"),
292                       "--internal_release_string \"\"");
293 
294   // Corrupt four bytes of data in the beginning of the image. Unlike
295   // the CorruptedImage test-case above (which is valid metadata) this
296   // will make the metadata invalid and render the slot unbootable
297   // even if the device is unlocked. Specifically no AvbSlotVerifyData
298   // is returned.
299   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
300   EXPECT_EQ(AVB_IO_RESULT_OK,
301             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
302                                                "vbmeta_a",
303                                                0,  // offset: beginning
304                                                sizeof corrupt_data,
305                                                corrupt_data));
306 
307   AvbSlotVerifyData* slot_data = NULL;
308   const char* requested_partitions[] = {"boot", NULL};
309   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
310             avb_slot_verify(ops_.avb_ops(),
311                             requested_partitions,
312                             "_a",
313                             AVB_SLOT_VERIFY_FLAGS_NONE,
314                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
315                             &slot_data));
316   EXPECT_EQ(nullptr, slot_data);
317 }
318 
TEST_F(AvbSlotVerifyTest,RollbackIndex)319 TEST_F(AvbSlotVerifyTest, RollbackIndex) {
320   GenerateVBMetaImage("vbmeta_a.img",
321                       "SHA256_RSA2048",
322                       42,
323                       base::FilePath("test/data/testkey_rsa2048.pem"),
324                       "--internal_release_string \"\"");
325 
326   ops_.set_expected_public_key(
327       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
328 
329   AvbSlotVerifyData* slot_data = NULL;
330   const char* requested_partitions[] = {"boot", NULL};
331 
332   // First try with 42 as the stored rollback index - this should
333   // succeed since the image rollback index is 42 (as set above).
334   ops_.set_stored_rollback_indexes({{0, 42}});
335   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
336             avb_slot_verify(ops_.avb_ops(),
337                             requested_partitions,
338                             "_a",
339                             AVB_SLOT_VERIFY_FLAGS_NONE,
340                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
341                             &slot_data));
342   EXPECT_NE(nullptr, slot_data);
343   avb_slot_verify_data_free(slot_data);
344 
345   // Then try with 43 for the stored rollback index - this should fail
346   // because the image has rollback index 42 which is less than 43.
347   ops_.set_stored_rollback_indexes({{0, 43}});
348   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
349             avb_slot_verify(ops_.avb_ops(),
350                             requested_partitions,
351                             "_a",
352                             AVB_SLOT_VERIFY_FLAGS_NONE,
353                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
354                             &slot_data));
355   EXPECT_EQ(nullptr, slot_data);
356   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
357             avb_slot_verify(ops_.avb_ops(),
358                             requested_partitions,
359                             "_a",
360                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
361                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
362                             &slot_data));
363   EXPECT_NE(nullptr, slot_data);
364   avb_slot_verify_data_free(slot_data);
365 }
366 
TEST_F(AvbSlotVerifyTest,LoadEntirePartitionIfAllowingVerificationError)367 TEST_F(AvbSlotVerifyTest, LoadEntirePartitionIfAllowingVerificationError) {
368   const size_t boot_partition_size = 16 * 1024 * 1024;
369   const size_t boot_image_size = 5 * 1024 * 1024;
370   const size_t new_boot_image_size = 10 * 1024 * 1024;
371   base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
372 
373   // If we're allowing verification errors then check that the whole
374   // partition is loaded. This is needed because in this mode for
375   // example the "boot" partition might be flashed with another
376   // boot.img that is larger than what the HashDescriptor in vbmeta
377   // says.
378   EXPECT_COMMAND(
379       0,
380       "./avbtool add_hash_footer"
381       " --image %s"
382       " --rollback_index 0"
383       " --partition_name boot"
384       " --partition_size %zd"
385       " --kernel_cmdline 'cmdline in hash footer $(ANDROID_SYSTEM_PARTUUID)'"
386       " --salt deadbeef"
387       " --internal_release_string \"\"",
388       boot_path.value().c_str(),
389       boot_partition_size);
390 
391   GenerateVBMetaImage(
392       "vbmeta_a.img",
393       "SHA256_RSA2048",
394       4,
395       base::FilePath("test/data/testkey_rsa2048.pem"),
396       base::StringPrintf(
397           "--include_descriptors_from_image %s"
398           " --kernel_cmdline 'cmdline in vbmeta $(ANDROID_BOOT_PARTUUID)'"
399           " --internal_release_string \"\"",
400           boot_path.value().c_str()));
401 
402   // Now replace the boot partition with something bigger and
403   // different. Because FakeOps's get_size_of_partition() operation
404   // just returns the file size it means that this is what is returned
405   // by get_size_of_partition().
406   //
407   // Also make sure this image will return a different digest by using
408   // a non-standard starting byte. This is to force avb_slot_verify()
409   // to return ERROR_VERIFICATION below.
410   GenerateImage("boot_a.img", new_boot_image_size, 1 /* start_byte */);
411 
412   ops_.set_expected_public_key(
413       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
414 
415   AvbSlotVerifyData* slot_data = NULL;
416   const char* requested_partitions[] = {"boot", NULL};
417   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
418             avb_slot_verify(ops_.avb_ops(),
419                             requested_partitions,
420                             "_a",
421                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
422                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
423                             &slot_data));
424   EXPECT_NE(nullptr, slot_data);
425 
426   // Check that the loaded partition is actually
427   // |new_boot_image_size|.
428   EXPECT_EQ(size_t(1), slot_data->num_loaded_partitions);
429   EXPECT_EQ("boot",
430             std::string(slot_data->loaded_partitions[0].partition_name));
431   EXPECT_EQ(new_boot_image_size, slot_data->loaded_partitions[0].data_size);
432   avb_slot_verify_data_free(slot_data);
433 }
434 
TEST_F(AvbSlotVerifyTest,HashDescriptorInVBMeta)435 TEST_F(AvbSlotVerifyTest, HashDescriptorInVBMeta) {
436   const size_t boot_partition_size = 16 * 1024 * 1024;
437   const size_t boot_image_size = 5 * 1024 * 1024;
438   base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
439 
440   EXPECT_COMMAND(
441       0,
442       "./avbtool add_hash_footer"
443       " --image %s"
444       " --rollback_index 0"
445       " --partition_name boot"
446       " --partition_size %zd"
447       " --kernel_cmdline 'cmdline in hash footer $(ANDROID_SYSTEM_PARTUUID)'"
448       " --salt deadbeef"
449       " --internal_release_string \"\"",
450       boot_path.value().c_str(),
451       boot_partition_size);
452 
453   GenerateVBMetaImage(
454       "vbmeta_a.img",
455       "SHA256_RSA2048",
456       4,
457       base::FilePath("test/data/testkey_rsa2048.pem"),
458       base::StringPrintf(
459           "--include_descriptors_from_image %s"
460           " --kernel_cmdline 'cmdline in vbmeta $(ANDROID_BOOT_PARTUUID)'"
461           " --internal_release_string \"\"",
462           boot_path.value().c_str()));
463 
464   EXPECT_EQ(
465       "Minimum libavb version:   1.0\n"
466       "Header Block:             256 bytes\n"
467       "Authentication Block:     320 bytes\n"
468       "Auxiliary Block:          896 bytes\n"
469       "Algorithm:                SHA256_RSA2048\n"
470       "Rollback Index:           4\n"
471       "Flags:                    0\n"
472       "Release String:           ''\n"
473       "Descriptors:\n"
474       "    Kernel Cmdline descriptor:\n"
475       "      Flags:                 0\n"
476       "      Kernel Cmdline:        'cmdline in vbmeta "
477       "$(ANDROID_BOOT_PARTUUID)'\n"
478       "    Hash descriptor:\n"
479       "      Image Size:            5242880 bytes\n"
480       "      Hash Algorithm:        sha256\n"
481       "      Partition Name:        boot\n"
482       "      Salt:                  deadbeef\n"
483       "      Digest:                "
484       "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n"
485       "    Kernel Cmdline descriptor:\n"
486       "      Flags:                 0\n"
487       "      Kernel Cmdline:        'cmdline in hash footer "
488       "$(ANDROID_SYSTEM_PARTUUID)'\n",
489       InfoImage(vbmeta_image_path_));
490 
491   EXPECT_COMMAND(0,
492                  "./avbtool erase_footer"
493                  " --image %s",
494                  boot_path.value().c_str());
495 
496   // With no footer, 'avbtool info_image' should fail (exit status 1).
497   EXPECT_COMMAND(
498       1, "./avbtool info_image --image %s", boot_path.value().c_str());
499 
500   ops_.set_expected_public_key(
501       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
502 
503   AvbSlotVerifyData* slot_data = NULL;
504   const char* requested_partitions[] = {"boot", NULL};
505   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
506             avb_slot_verify(ops_.avb_ops(),
507                             requested_partitions,
508                             "_a",
509                             AVB_SLOT_VERIFY_FLAGS_NONE,
510                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
511                             &slot_data));
512   EXPECT_NE(nullptr, slot_data);
513 
514   // Now verify the slot data. The vbmeta data should match our
515   // vbmeta_image_ member.
516   EXPECT_EQ(size_t(1), slot_data->num_vbmeta_images);
517   EXPECT_EQ("vbmeta", std::string(slot_data->vbmeta_images[0].partition_name));
518   EXPECT_EQ(slot_data->vbmeta_images[0].vbmeta_size, vbmeta_image_.size());
519   EXPECT_EQ(0,
520             memcmp(vbmeta_image_.data(),
521                    slot_data->vbmeta_images[0].vbmeta_data,
522                    slot_data->vbmeta_images[0].vbmeta_size));
523 
524   // The boot image data should match what is generated above with
525   // GenerateImage().
526   EXPECT_EQ(size_t(1), slot_data->num_loaded_partitions);
527   EXPECT_EQ("boot",
528             std::string(slot_data->loaded_partitions[0].partition_name));
529   EXPECT_EQ(boot_image_size, slot_data->loaded_partitions[0].data_size);
530   for (size_t n = 0; n < slot_data->loaded_partitions[0].data_size; n++) {
531     EXPECT_EQ(slot_data->loaded_partitions[0].data[n], uint8_t(n));
532   }
533 
534   // This should match the two cmdlines with a space (U+0020) between
535   // them and the $(ANDROID_SYSTEM_PARTUUID) and
536   // $(ANDROID_BOOT_PARTUUID) variables replaced.
537   EXPECT_EQ(
538       "cmdline in vbmeta 1234-fake-guid-for:boot_a cmdline in hash footer "
539       "1234-fake-guid-for:system_a "
540       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
541       "androidboot.vbmeta.avb_version=1.0 "
542       "androidboot.vbmeta.device_state=locked "
543       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1472 "
544       "androidboot.vbmeta.digest="
545       "34cdb59b955aa35d4da97701f304fabf7392eecca8c50ff1a0b7b6e1c9aaa1b8 "
546       "androidboot.vbmeta.invalidate_on_error=yes "
547       "androidboot.veritymode=enforcing",
548       std::string(slot_data->cmdline));
549   EXPECT_EQ(4UL, slot_data->rollback_indexes[0]);
550   for (size_t n = 1; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
551     EXPECT_EQ(0UL, slot_data->rollback_indexes[n]);
552   }
553   avb_slot_verify_data_free(slot_data);
554 }
555 
TEST_F(AvbSlotVerifyTest,HashDescriptorInVBMetaCorruptBoot)556 TEST_F(AvbSlotVerifyTest, HashDescriptorInVBMetaCorruptBoot) {
557   size_t boot_partition_size = 16 * 1024 * 1024;
558   base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
559   const char* requested_partitions[] = {"boot", NULL};
560 
561   EXPECT_COMMAND(0,
562                  "./avbtool add_hash_footer"
563                  " --image %s"
564                  " --rollback_index 0"
565                  " --partition_name boot"
566                  " --partition_size %zd"
567                  " --salt deadbeef"
568                  " --internal_release_string \"\"",
569                  boot_path.value().c_str(),
570                  boot_partition_size);
571 
572   GenerateVBMetaImage("vbmeta_a.img",
573                       "SHA256_RSA2048",
574                       0,
575                       base::FilePath("test/data/testkey_rsa2048.pem"),
576                       base::StringPrintf("--include_descriptors_from_image %s"
577                                          " --internal_release_string \"\"",
578                                          boot_path.value().c_str()));
579 
580   EXPECT_COMMAND(0,
581                  "./avbtool erase_footer"
582                  " --image %s",
583                  boot_path.value().c_str());
584 
585   ops_.set_expected_public_key(
586       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
587 
588   // So far, so good.
589   AvbSlotVerifyData* slot_data = NULL;
590   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
591             avb_slot_verify(ops_.avb_ops(),
592                             requested_partitions,
593                             "_a",
594                             AVB_SLOT_VERIFY_FLAGS_NONE,
595                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
596                             &slot_data));
597   EXPECT_NE(nullptr, slot_data);
598   avb_slot_verify_data_free(slot_data);
599 
600   // Now corrupt boot_a.img and expect verification error.
601   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
602   EXPECT_EQ(AVB_IO_RESULT_OK,
603             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
604                                                "boot_a",
605                                                1024 * 1024,  // offset: 1 MiB
606                                                sizeof corrupt_data,
607                                                corrupt_data));
608 
609   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
610             avb_slot_verify(ops_.avb_ops(),
611                             requested_partitions,
612                             "_a",
613                             AVB_SLOT_VERIFY_FLAGS_NONE,
614                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
615                             &slot_data));
616   EXPECT_EQ(nullptr, slot_data);
617   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
618             avb_slot_verify(ops_.avb_ops(),
619                             requested_partitions,
620                             "_a",
621                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
622                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
623                             &slot_data));
624   EXPECT_NE(nullptr, slot_data);
625   avb_slot_verify_data_free(slot_data);
626 }
627 
TEST_F(AvbSlotVerifyTest,HashDescriptorInChainedPartition)628 TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartition) {
629   size_t boot_partition_size = 16 * 1024 * 1024;
630   const size_t boot_image_size = 5 * 1024 * 1024;
631   base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
632   const char* requested_partitions[] = {"boot", NULL};
633 
634   EXPECT_COMMAND(0,
635                  "./avbtool add_hash_footer"
636                  " --image %s"
637                  " --kernel_cmdline 'cmdline2 in hash footer'"
638                  " --rollback_index 12"
639                  " --partition_name boot"
640                  " --partition_size %zd"
641                  " --algorithm SHA256_RSA4096"
642                  " --key test/data/testkey_rsa4096.pem"
643                  " --salt deadbeef"
644                  " --internal_release_string \"\"",
645                  boot_path.value().c_str(),
646                  boot_partition_size);
647 
648   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
649   EXPECT_COMMAND(
650       0,
651       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
652       " --output %s",
653       pk_path.value().c_str());
654 
655   GenerateVBMetaImage(
656       "vbmeta_a.img",
657       "SHA256_RSA2048",
658       11,
659       base::FilePath("test/data/testkey_rsa2048.pem"),
660       base::StringPrintf("--chain_partition boot:1:%s"
661                          " --kernel_cmdline 'cmdline2 in vbmeta'"
662                          " --internal_release_string \"\"",
663                          pk_path.value().c_str()));
664 
665   EXPECT_EQ(
666       "Minimum libavb version:   1.0\n"
667       "Header Block:             256 bytes\n"
668       "Authentication Block:     320 bytes\n"
669       "Auxiliary Block:          1728 bytes\n"
670       "Algorithm:                SHA256_RSA2048\n"
671       "Rollback Index:           11\n"
672       "Flags:                    0\n"
673       "Release String:           ''\n"
674       "Descriptors:\n"
675       "    Chain Partition descriptor:\n"
676       "      Partition Name:          boot\n"
677       "      Rollback Index Location: 1\n"
678       "      Public key (sha1):       "
679       "2597c218aae470a130f61162feaae70afd97f011\n"
680       "    Kernel Cmdline descriptor:\n"
681       "      Flags:                 0\n"
682       "      Kernel Cmdline:        'cmdline2 in vbmeta'\n",
683       InfoImage(vbmeta_image_path_));
684 
685   EXPECT_EQ(
686       "Footer version:           1.0\n"
687       "Image size:               16777216 bytes\n"
688       "Original image size:      5242880 bytes\n"
689       "VBMeta offset:            5242880\n"
690       "VBMeta size:              2112 bytes\n"
691       "--\n"
692       "Minimum libavb version:   1.0\n"
693       "Header Block:             256 bytes\n"
694       "Authentication Block:     576 bytes\n"
695       "Auxiliary Block:          1280 bytes\n"
696       "Algorithm:                SHA256_RSA4096\n"
697       "Rollback Index:           12\n"
698       "Flags:                    0\n"
699       "Release String:           ''\n"
700       "Descriptors:\n"
701       "    Hash descriptor:\n"
702       "      Image Size:            5242880 bytes\n"
703       "      Hash Algorithm:        sha256\n"
704       "      Partition Name:        boot\n"
705       "      Salt:                  deadbeef\n"
706       "      Digest:                "
707       "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n"
708       "    Kernel Cmdline descriptor:\n"
709       "      Flags:                 0\n"
710       "      Kernel Cmdline:        'cmdline2 in hash footer'\n",
711       InfoImage(boot_path));
712 
713   ops_.set_expected_public_key(
714       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
715 
716   AvbSlotVerifyData* slot_data = NULL;
717   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
718             avb_slot_verify(ops_.avb_ops(),
719                             requested_partitions,
720                             "_a",
721                             AVB_SLOT_VERIFY_FLAGS_NONE,
722                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
723                             &slot_data));
724   EXPECT_NE(nullptr, slot_data);
725 
726   // Now verify the slot data. We should have two vbmeta
727   // structs. Verify both of them. Note that the A/B suffix isn't
728   // appended.
729   EXPECT_EQ(size_t(2), slot_data->num_vbmeta_images);
730   EXPECT_EQ("vbmeta", std::string(slot_data->vbmeta_images[0].partition_name));
731   EXPECT_EQ(slot_data->vbmeta_images[0].vbmeta_size, vbmeta_image_.size());
732   EXPECT_EQ(0,
733             memcmp(vbmeta_image_.data(),
734                    slot_data->vbmeta_images[0].vbmeta_data,
735                    slot_data->vbmeta_images[0].vbmeta_size));
736   // And for the second vbmeta struct we check that the descriptors
737   // match the info_image output from above.
738   EXPECT_EQ("boot", std::string(slot_data->vbmeta_images[1].partition_name));
739   const AvbDescriptor** descriptors =
740       avb_descriptor_get_all(slot_data->vbmeta_images[1].vbmeta_data,
741                              slot_data->vbmeta_images[1].vbmeta_size,
742                              NULL);
743   EXPECT_NE(nullptr, descriptors);
744   AvbHashDescriptor hash_desc;
745   EXPECT_EQ(true,
746             avb_hash_descriptor_validate_and_byteswap(
747                 ((AvbHashDescriptor*)descriptors[0]), &hash_desc));
748   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
749                             sizeof(AvbHashDescriptor);
750   uint64_t o = 0;
751   EXPECT_EQ("boot",
752             std::string(reinterpret_cast<const char*>(desc_end + o),
753                         hash_desc.partition_name_len));
754   o += hash_desc.partition_name_len;
755   EXPECT_EQ("deadbeef", mem_to_hexstring(desc_end + o, hash_desc.salt_len));
756   o += hash_desc.salt_len;
757   EXPECT_EQ("184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d",
758             mem_to_hexstring(desc_end + o, hash_desc.digest_len));
759   AvbKernelCmdlineDescriptor cmdline_desc;
760   EXPECT_EQ(true,
761             avb_kernel_cmdline_descriptor_validate_and_byteswap(
762                 ((AvbKernelCmdlineDescriptor*)descriptors[1]), &cmdline_desc));
763   desc_end = reinterpret_cast<const uint8_t*>(descriptors[1]) +
764              sizeof(AvbKernelCmdlineDescriptor);
765   EXPECT_EQ("cmdline2 in hash footer",
766             std::string(reinterpret_cast<const char*>(desc_end),
767                         cmdline_desc.kernel_cmdline_length));
768   avb_free(descriptors);
769 
770   // The boot image data should match what is generated above with
771   // GenerateImage().
772   EXPECT_EQ(size_t(1), slot_data->num_loaded_partitions);
773   EXPECT_EQ("boot",
774             std::string(slot_data->loaded_partitions[0].partition_name));
775   EXPECT_EQ(boot_image_size, slot_data->loaded_partitions[0].data_size);
776   for (size_t n = 0; n < slot_data->loaded_partitions[0].data_size; n++) {
777     EXPECT_EQ(slot_data->loaded_partitions[0].data[n], uint8_t(n));
778   }
779 
780   // This should match the two cmdlines with a space (U+0020) between them.
781   EXPECT_EQ(
782       "cmdline2 in hash footer cmdline2 in vbmeta "
783       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
784       "androidboot.vbmeta.avb_version=1.0 "
785       "androidboot.vbmeta.device_state=locked "
786       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=4416 "
787       "androidboot.vbmeta.digest="
788       "4a45faa9adfeb94e9154fe682c11fef1a1a3d829b67cbf1a12ac7f0aa4f8e2e4 "
789       "androidboot.vbmeta.invalidate_on_error=yes "
790       "androidboot.veritymode=enforcing",
791       std::string(slot_data->cmdline));
792   EXPECT_EQ(11UL, slot_data->rollback_indexes[0]);
793   EXPECT_EQ(12UL, slot_data->rollback_indexes[1]);
794   for (size_t n = 2; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
795     EXPECT_EQ(0UL, slot_data->rollback_indexes[n]);
796   }
797   avb_slot_verify_data_free(slot_data);
798 }
799 
TEST_F(AvbSlotVerifyTest,HashDescriptorInChainedPartitionCorruptBoot)800 TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartitionCorruptBoot) {
801   size_t boot_partition_size = 16 * 1024 * 1024;
802   base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
803   const char* requested_partitions[] = {"boot", NULL};
804 
805   EXPECT_COMMAND(0,
806                  "./avbtool add_hash_footer"
807                  " --image %s"
808                  " --rollback_index 0"
809                  " --partition_name boot"
810                  " --partition_size %zd"
811                  " --algorithm SHA256_RSA4096"
812                  " --key test/data/testkey_rsa4096.pem"
813                  " --salt deadbeef"
814                  " --internal_release_string \"\"",
815                  boot_path.value().c_str(),
816                  boot_partition_size);
817 
818   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
819   EXPECT_COMMAND(
820       0,
821       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
822       " --output %s",
823       pk_path.value().c_str());
824 
825   GenerateVBMetaImage("vbmeta_a.img",
826                       "SHA256_RSA2048",
827                       0,
828                       base::FilePath("test/data/testkey_rsa2048.pem"),
829                       base::StringPrintf("--chain_partition boot:1:%s"
830                                          " --internal_release_string \"\"",
831                                          pk_path.value().c_str()));
832 
833   ops_.set_expected_public_key(
834       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
835 
836   AvbSlotVerifyData* slot_data = NULL;
837   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
838             avb_slot_verify(ops_.avb_ops(),
839                             requested_partitions,
840                             "_a",
841                             AVB_SLOT_VERIFY_FLAGS_NONE,
842                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
843                             &slot_data));
844   EXPECT_NE(nullptr, slot_data);
845   avb_slot_verify_data_free(slot_data);
846 
847   // Now corrupt boot_a.img and expect verification error.
848   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
849   EXPECT_EQ(AVB_IO_RESULT_OK,
850             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
851                                                "boot_a",
852                                                1024 * 1024,  // offset: 1 MiB
853                                                sizeof corrupt_data,
854                                                corrupt_data));
855 
856   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
857             avb_slot_verify(ops_.avb_ops(),
858                             requested_partitions,
859                             "_a",
860                             AVB_SLOT_VERIFY_FLAGS_NONE,
861                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
862                             &slot_data));
863   EXPECT_EQ(nullptr, slot_data);
864   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
865             avb_slot_verify(ops_.avb_ops(),
866                             requested_partitions,
867                             "_a",
868                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
869                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
870                             &slot_data));
871   EXPECT_NE(nullptr, slot_data);
872   avb_slot_verify_data_free(slot_data);
873 }
874 
TEST_F(AvbSlotVerifyTest,HashDescriptorInChainedPartitionKeyMismatch)875 TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartitionKeyMismatch) {
876   size_t boot_partition_size = 16 * 1024 * 1024;
877   base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
878   const char* requested_partitions[] = {"boot", NULL};
879 
880   // Use different key to sign vbmeta in boot_a (we use the 8192 bit
881   // key) than what's in the chained partition descriptor (which is
882   // the 4096 bit key) and expect
883   // AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED.
884 
885   EXPECT_COMMAND(0,
886                  "./avbtool add_hash_footer"
887                  " --image %s"
888                  " --rollback_index 0"
889                  " --partition_name boot"
890                  " --partition_size %zd"
891                  " --algorithm SHA256_RSA8192"
892                  " --key test/data/testkey_rsa8192.pem"
893                  " --salt deadbeef"
894                  " --internal_release_string \"\"",
895                  boot_path.value().c_str(),
896                  boot_partition_size);
897 
898   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
899   EXPECT_COMMAND(
900       0,
901       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
902       " --output %s",
903       pk_path.value().c_str());
904 
905   GenerateVBMetaImage("vbmeta_a.img",
906                       "SHA256_RSA2048",
907                       0,
908                       base::FilePath("test/data/testkey_rsa2048.pem"),
909                       base::StringPrintf("--chain_partition boot:1:%s"
910                                          " --internal_release_string \"\"",
911                                          pk_path.value().c_str()));
912 
913   ops_.set_expected_public_key(
914       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
915 
916   AvbSlotVerifyData* slot_data = NULL;
917   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
918             avb_slot_verify(ops_.avb_ops(),
919                             requested_partitions,
920                             "_a",
921                             AVB_SLOT_VERIFY_FLAGS_NONE,
922                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
923                             &slot_data));
924   EXPECT_EQ(nullptr, slot_data);
925   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
926             avb_slot_verify(ops_.avb_ops(),
927                             requested_partitions,
928                             "_a",
929                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
930                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
931                             &slot_data));
932   EXPECT_NE(nullptr, slot_data);
933   avb_slot_verify_data_free(slot_data);
934 }
935 
TEST_F(AvbSlotVerifyTest,HashDescriptorInChainedPartitionRollbackIndexFail)936 TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartitionRollbackIndexFail) {
937   size_t boot_partition_size = 16 * 1024 * 1024;
938   base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
939   const char* requested_partitions[] = {"boot", NULL};
940 
941   EXPECT_COMMAND(0,
942                  "./avbtool add_hash_footer"
943                  " --image %s"
944                  " --rollback_index 10"
945                  " --partition_name boot"
946                  " --partition_size %zd"
947                  " --algorithm SHA256_RSA4096"
948                  " --key test/data/testkey_rsa4096.pem"
949                  " --salt deadbeef"
950                  " --internal_release_string \"\"",
951                  boot_path.value().c_str(),
952                  boot_partition_size);
953 
954   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
955   EXPECT_COMMAND(
956       0,
957       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
958       " --output %s",
959       pk_path.value().c_str());
960 
961   GenerateVBMetaImage("vbmeta_a.img",
962                       "SHA256_RSA2048",
963                       110,
964                       base::FilePath("test/data/testkey_rsa2048.pem"),
965                       base::StringPrintf("--chain_partition boot:1:%s"
966                                          " --internal_release_string \"\"",
967                                          pk_path.value().c_str()));
968 
969   ops_.set_expected_public_key(
970       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
971 
972   AvbSlotVerifyData* slot_data = NULL;
973 
974   // Both images (vbmeta_a and boot_a) have rollback index 10 and 11
975   // so it should work if the stored rollback indexes are 0 and 0.
976   ops_.set_stored_rollback_indexes({{0, 0}, {1, 0}});
977   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
978             avb_slot_verify(ops_.avb_ops(),
979                             requested_partitions,
980                             "_a",
981                             AVB_SLOT_VERIFY_FLAGS_NONE,
982                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
983                             &slot_data));
984   EXPECT_NE(nullptr, slot_data);
985   avb_slot_verify_data_free(slot_data);
986 
987   // Check failure if we set the stored rollback index of the chained
988   // partition to 20 (see AvbSlotVerifyTest.RollbackIndex above
989   // where we test rollback index checks for the vbmeta partition).
990   ops_.set_stored_rollback_indexes({{0, 0}, {1, 20}});
991   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
992             avb_slot_verify(ops_.avb_ops(),
993                             requested_partitions,
994                             "_a",
995                             AVB_SLOT_VERIFY_FLAGS_NONE,
996                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
997                             &slot_data));
998   EXPECT_EQ(nullptr, slot_data);
999   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
1000             avb_slot_verify(ops_.avb_ops(),
1001                             requested_partitions,
1002                             "_a",
1003                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
1004                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1005                             &slot_data));
1006   EXPECT_NE(nullptr, slot_data);
1007   avb_slot_verify_data_free(slot_data);
1008 
1009   // Check failure if there is no rollback index slot 1 - in that case
1010   // we expect an I/O error since ops->read_rollback_index() will
1011   // fail.
1012   ops_.set_stored_rollback_indexes({{0, 0}});
1013   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_IO,
1014             avb_slot_verify(ops_.avb_ops(),
1015                             requested_partitions,
1016                             "_a",
1017                             AVB_SLOT_VERIFY_FLAGS_NONE,
1018                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1019                             &slot_data));
1020   EXPECT_EQ(nullptr, slot_data);
1021 }
1022 
TEST_F(AvbSlotVerifyTest,ChainedPartitionNoSlots)1023 TEST_F(AvbSlotVerifyTest, ChainedPartitionNoSlots) {
1024   size_t boot_partition_size = 16 * 1024 * 1024;
1025   const size_t boot_image_size = 5 * 1024 * 1024;
1026   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
1027   const char* requested_partitions[] = {"boot", NULL};
1028 
1029   EXPECT_COMMAND(0,
1030                  "./avbtool add_hash_footer"
1031                  " --image %s"
1032                  " --kernel_cmdline 'cmdline2 in hash footer'"
1033                  " --rollback_index 12"
1034                  " --partition_name boot"
1035                  " --partition_size %zd"
1036                  " --algorithm SHA256_RSA4096"
1037                  " --key test/data/testkey_rsa4096.pem"
1038                  " --salt deadbeef"
1039                  " --internal_release_string \"\"",
1040                  boot_path.value().c_str(),
1041                  boot_partition_size);
1042 
1043   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
1044   EXPECT_COMMAND(
1045       0,
1046       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
1047       " --output %s",
1048       pk_path.value().c_str());
1049 
1050   GenerateVBMetaImage(
1051       "vbmeta.img",
1052       "SHA256_RSA2048",
1053       11,
1054       base::FilePath("test/data/testkey_rsa2048.pem"),
1055       base::StringPrintf("--chain_partition boot:1:%s"
1056                          " --kernel_cmdline 'cmdline2 in vbmeta'"
1057                          " --internal_release_string \"\"",
1058                          pk_path.value().c_str()));
1059 
1060   EXPECT_EQ(
1061       "Minimum libavb version:   1.0\n"
1062       "Header Block:             256 bytes\n"
1063       "Authentication Block:     320 bytes\n"
1064       "Auxiliary Block:          1728 bytes\n"
1065       "Algorithm:                SHA256_RSA2048\n"
1066       "Rollback Index:           11\n"
1067       "Flags:                    0\n"
1068       "Release String:           ''\n"
1069       "Descriptors:\n"
1070       "    Chain Partition descriptor:\n"
1071       "      Partition Name:          boot\n"
1072       "      Rollback Index Location: 1\n"
1073       "      Public key (sha1):       "
1074       "2597c218aae470a130f61162feaae70afd97f011\n"
1075       "    Kernel Cmdline descriptor:\n"
1076       "      Flags:                 0\n"
1077       "      Kernel Cmdline:        'cmdline2 in vbmeta'\n",
1078       InfoImage(vbmeta_image_path_));
1079 
1080   ops_.set_expected_public_key(
1081       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1082 
1083   AvbSlotVerifyData* slot_data = NULL;
1084   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1085             avb_slot_verify(ops_.avb_ops(),
1086                             requested_partitions,
1087                             "",
1088                             AVB_SLOT_VERIFY_FLAGS_NONE,
1089                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1090                             &slot_data));
1091   EXPECT_NE(nullptr, slot_data);
1092 
1093   // Now verify the slot data. The first vbmeta data should match our
1094   // vbmeta_image_ member and the second one should be for the 'boot'
1095   // partition.
1096   EXPECT_EQ(size_t(2), slot_data->num_vbmeta_images);
1097   EXPECT_EQ("vbmeta", std::string(slot_data->vbmeta_images[0].partition_name));
1098   EXPECT_EQ(slot_data->vbmeta_images[0].vbmeta_size, vbmeta_image_.size());
1099   EXPECT_EQ(0,
1100             memcmp(vbmeta_image_.data(),
1101                    slot_data->vbmeta_images[0].vbmeta_data,
1102                    slot_data->vbmeta_images[0].vbmeta_size));
1103   EXPECT_EQ("boot", std::string(slot_data->vbmeta_images[1].partition_name));
1104 
1105   // The boot image data should match what is generated above with
1106   // GenerateImage().
1107   EXPECT_EQ(size_t(1), slot_data->num_loaded_partitions);
1108   EXPECT_EQ("boot",
1109             std::string(slot_data->loaded_partitions[0].partition_name));
1110   EXPECT_EQ(boot_image_size, slot_data->loaded_partitions[0].data_size);
1111   for (size_t n = 0; n < slot_data->loaded_partitions[0].data_size; n++) {
1112     EXPECT_EQ(slot_data->loaded_partitions[0].data[n], uint8_t(n));
1113   }
1114 
1115   // This should match the two cmdlines with a space (U+0020) between
1116   // them.
1117   EXPECT_EQ(
1118       "cmdline2 in hash footer cmdline2 in vbmeta "
1119       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta "
1120       "androidboot.vbmeta.avb_version=1.0 "
1121       "androidboot.vbmeta.device_state=locked "
1122       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=4416 "
1123       "androidboot.vbmeta.digest="
1124       "4a45faa9adfeb94e9154fe682c11fef1a1a3d829b67cbf1a12ac7f0aa4f8e2e4 "
1125       "androidboot.vbmeta.invalidate_on_error=yes "
1126       "androidboot.veritymode=enforcing",
1127       std::string(slot_data->cmdline));
1128   EXPECT_EQ(11UL, slot_data->rollback_indexes[0]);
1129   EXPECT_EQ(12UL, slot_data->rollback_indexes[1]);
1130   for (size_t n = 2; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
1131     EXPECT_EQ(0UL, slot_data->rollback_indexes[n]);
1132   }
1133   avb_slot_verify_data_free(slot_data);
1134 }
1135 
TEST_F(AvbSlotVerifyTest,PartitionsOtherThanBoot)1136 TEST_F(AvbSlotVerifyTest, PartitionsOtherThanBoot) {
1137   const size_t foo_partition_size = 16 * 1024 * 1024;
1138   const size_t bar_partition_size = 32 * 1024 * 1024;
1139   const size_t foo_image_size = 5 * 1024 * 1024;
1140   const size_t bar_image_size = 10 * 1024 * 1024;
1141   base::FilePath foo_path = GenerateImage("foo_a.img", foo_image_size);
1142   base::FilePath bar_path = GenerateImage("bar_a.img", bar_image_size);
1143 
1144   EXPECT_COMMAND(0,
1145                  "./avbtool add_hash_footer"
1146                  " --image %s"
1147                  " --partition_name foo"
1148                  " --partition_size %zd"
1149                  " --salt deadbeef"
1150                  " --internal_release_string \"\"",
1151                  foo_path.value().c_str(),
1152                  foo_partition_size);
1153 
1154   EXPECT_COMMAND(0,
1155                  "./avbtool add_hash_footer"
1156                  " --image %s"
1157                  " --partition_name bar"
1158                  " --partition_size %zd"
1159                  " --salt deadbeef"
1160                  " --internal_release_string \"\"",
1161                  bar_path.value().c_str(),
1162                  bar_partition_size);
1163 
1164   GenerateVBMetaImage("vbmeta_a.img",
1165                       "SHA256_RSA2048",
1166                       4,
1167                       base::FilePath("test/data/testkey_rsa2048.pem"),
1168                       base::StringPrintf("--include_descriptors_from_image %s"
1169                                          " --include_descriptors_from_image %s"
1170                                          " --internal_release_string \"\"",
1171                                          foo_path.value().c_str(),
1172                                          bar_path.value().c_str()));
1173 
1174   EXPECT_EQ(
1175       "Minimum libavb version:   1.0\n"
1176       "Header Block:             256 bytes\n"
1177       "Authentication Block:     320 bytes\n"
1178       "Auxiliary Block:          896 bytes\n"
1179       "Algorithm:                SHA256_RSA2048\n"
1180       "Rollback Index:           4\n"
1181       "Flags:                    0\n"
1182       "Release String:           ''\n"
1183       "Descriptors:\n"
1184       "    Hash descriptor:\n"
1185       "      Image Size:            5242880 bytes\n"
1186       "      Hash Algorithm:        sha256\n"
1187       "      Partition Name:        foo\n"
1188       "      Salt:                  deadbeef\n"
1189       "      Digest:                "
1190       "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n"
1191       "    Hash descriptor:\n"
1192       "      Image Size:            10485760 bytes\n"
1193       "      Hash Algorithm:        sha256\n"
1194       "      Partition Name:        bar\n"
1195       "      Salt:                  deadbeef\n"
1196       "      Digest:                "
1197       "baea4bbd261d0edf4d1fe5e6e5a36976c291eeba66b6a46fa81dba691327a727\n",
1198       InfoImage(vbmeta_image_path_));
1199 
1200   ops_.set_expected_public_key(
1201       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1202 
1203   AvbSlotVerifyData* slot_data = NULL;
1204   const char* requested_partitions[] = {"foo", "bar", NULL};
1205   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1206             avb_slot_verify(ops_.avb_ops(),
1207                             requested_partitions,
1208                             "_a",
1209                             AVB_SLOT_VERIFY_FLAGS_NONE,
1210                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1211                             &slot_data));
1212   EXPECT_NE(nullptr, slot_data);
1213 
1214   // Now verify the slot data. The vbmeta data should match our
1215   // vbmeta_image_ member.
1216   EXPECT_EQ(size_t(1), slot_data->num_vbmeta_images);
1217   EXPECT_EQ("vbmeta", std::string(slot_data->vbmeta_images[0].partition_name));
1218   EXPECT_EQ(slot_data->vbmeta_images[0].vbmeta_size, vbmeta_image_.size());
1219   EXPECT_EQ(0,
1220             memcmp(vbmeta_image_.data(),
1221                    slot_data->vbmeta_images[0].vbmeta_data,
1222                    slot_data->vbmeta_images[0].vbmeta_size));
1223 
1224   // The 'foo' and 'bar' image data should match what is generated
1225   // above with GenerateImage().
1226   EXPECT_EQ(size_t(2), slot_data->num_loaded_partitions);
1227   EXPECT_EQ("foo", std::string(slot_data->loaded_partitions[0].partition_name));
1228   EXPECT_EQ(foo_image_size, slot_data->loaded_partitions[0].data_size);
1229   for (size_t n = 0; n < slot_data->loaded_partitions[0].data_size; n++) {
1230     EXPECT_EQ(slot_data->loaded_partitions[0].data[n], uint8_t(n));
1231   }
1232   EXPECT_EQ("bar", std::string(slot_data->loaded_partitions[1].partition_name));
1233   EXPECT_EQ(bar_image_size, slot_data->loaded_partitions[1].data_size);
1234   for (size_t n = 0; n < slot_data->loaded_partitions[1].data_size; n++) {
1235     EXPECT_EQ(slot_data->loaded_partitions[1].data[n], uint8_t(n));
1236   }
1237   avb_slot_verify_data_free(slot_data);
1238 
1239   // Check that we loaded vbmeta_a, foo_a, and bar_a.
1240   std::set<std::string> partitions = ops_.get_partition_names_read_from();
1241   EXPECT_EQ(size_t(3), partitions.size());
1242   EXPECT_TRUE(partitions.find("vbmeta_a") != partitions.end());
1243   EXPECT_TRUE(partitions.find("foo_a") != partitions.end());
1244   EXPECT_TRUE(partitions.find("bar_a") != partitions.end());
1245 }
1246 
TEST_F(AvbSlotVerifyTest,OnlyLoadWhatHasBeenRequested)1247 TEST_F(AvbSlotVerifyTest, OnlyLoadWhatHasBeenRequested) {
1248   const size_t foo_partition_size = 16 * 1024 * 1024;
1249   const size_t bar_partition_size = 32 * 1024 * 1024;
1250   const size_t foo_image_size = 5 * 1024 * 1024;
1251   const size_t bar_image_size = 10 * 1024 * 1024;
1252   base::FilePath foo_path = GenerateImage("foo_a.img", foo_image_size);
1253   base::FilePath bar_path = GenerateImage("bar_a.img", bar_image_size);
1254 
1255   EXPECT_COMMAND(0,
1256                  "./avbtool add_hash_footer"
1257                  " --image %s"
1258                  " --partition_name foo"
1259                  " --partition_size %zd"
1260                  " --salt deadbeef"
1261                  " --internal_release_string \"\"",
1262                  foo_path.value().c_str(),
1263                  foo_partition_size);
1264 
1265   EXPECT_COMMAND(0,
1266                  "./avbtool add_hash_footer"
1267                  " --image %s"
1268                  " --partition_name bar"
1269                  " --partition_size %zd"
1270                  " --salt deadbeef"
1271                  " --internal_release_string \"\"",
1272                  bar_path.value().c_str(),
1273                  bar_partition_size);
1274 
1275   GenerateVBMetaImage("vbmeta_a.img",
1276                       "SHA256_RSA2048",
1277                       4,
1278                       base::FilePath("test/data/testkey_rsa2048.pem"),
1279                       base::StringPrintf("--include_descriptors_from_image %s"
1280                                          " --include_descriptors_from_image %s"
1281                                          " --internal_release_string \"\"",
1282                                          foo_path.value().c_str(),
1283                                          bar_path.value().c_str()));
1284 
1285   EXPECT_EQ(
1286       "Minimum libavb version:   1.0\n"
1287       "Header Block:             256 bytes\n"
1288       "Authentication Block:     320 bytes\n"
1289       "Auxiliary Block:          896 bytes\n"
1290       "Algorithm:                SHA256_RSA2048\n"
1291       "Rollback Index:           4\n"
1292       "Flags:                    0\n"
1293       "Release String:           ''\n"
1294       "Descriptors:\n"
1295       "    Hash descriptor:\n"
1296       "      Image Size:            5242880 bytes\n"
1297       "      Hash Algorithm:        sha256\n"
1298       "      Partition Name:        foo\n"
1299       "      Salt:                  deadbeef\n"
1300       "      Digest:                "
1301       "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n"
1302       "    Hash descriptor:\n"
1303       "      Image Size:            10485760 bytes\n"
1304       "      Hash Algorithm:        sha256\n"
1305       "      Partition Name:        bar\n"
1306       "      Salt:                  deadbeef\n"
1307       "      Digest:                "
1308       "baea4bbd261d0edf4d1fe5e6e5a36976c291eeba66b6a46fa81dba691327a727\n",
1309       InfoImage(vbmeta_image_path_));
1310 
1311   ops_.set_expected_public_key(
1312       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1313   AvbSlotVerifyData* slot_data = NULL;
1314   const char* requested_partitions[] = {"foo", NULL};
1315   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1316             avb_slot_verify(ops_.avb_ops(),
1317                             requested_partitions,
1318                             "_a",
1319                             AVB_SLOT_VERIFY_FLAGS_NONE,
1320                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1321                             &slot_data));
1322   EXPECT_NE(nullptr, slot_data);
1323   EXPECT_EQ(size_t(1), slot_data->num_loaded_partitions);
1324   EXPECT_EQ("foo", std::string(slot_data->loaded_partitions[0].partition_name));
1325   avb_slot_verify_data_free(slot_data);
1326 
1327   // Check that we loaded vbmeta_a, foo_a but not bar_a.
1328   std::set<std::string> partitions = ops_.get_partition_names_read_from();
1329   EXPECT_EQ(size_t(2), partitions.size());
1330   EXPECT_TRUE(partitions.find("vbmeta_a") != partitions.end());
1331   EXPECT_TRUE(partitions.find("foo_a") != partitions.end());
1332   EXPECT_TRUE(partitions.find("bar_a") == partitions.end());
1333 }
1334 
TEST_F(AvbSlotVerifyTest,PublicKeyMetadata)1335 TEST_F(AvbSlotVerifyTest, PublicKeyMetadata) {
1336   base::FilePath md_path = GenerateImage("md.bin", 1536);
1337 
1338   GenerateVBMetaImage("vbmeta_a.img",
1339                       "SHA256_RSA2048",
1340                       0,
1341                       base::FilePath("test/data/testkey_rsa2048.pem"),
1342                       base::StringPrintf("--public_key_metadata %s"
1343                                          " --internal_release_string \"\"",
1344                                          md_path.value().c_str()));
1345 
1346   ops_.set_expected_public_key(
1347       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1348 
1349   std::string md_data;
1350   ASSERT_TRUE(base::ReadFileToString(md_path, &md_data));
1351   ops_.set_expected_public_key_metadata(md_data);
1352 
1353   AvbSlotVerifyData* slot_data = NULL;
1354   const char* requested_partitions[] = {"boot", NULL};
1355   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1356             avb_slot_verify(ops_.avb_ops(),
1357                             requested_partitions,
1358                             "_a",
1359                             AVB_SLOT_VERIFY_FLAGS_NONE,
1360                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1361                             &slot_data));
1362   EXPECT_NE(nullptr, slot_data);
1363   EXPECT_EQ(
1364       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
1365       "androidboot.vbmeta.avb_version=1.0 "
1366       "androidboot.vbmeta.device_state=locked "
1367       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=2688 "
1368       "androidboot.vbmeta.digest="
1369       "5edcaa54f40382ee6a2fc3b86cdf383348b35ed07955e83ea32d84b69a97eaa0 "
1370       "androidboot.vbmeta.invalidate_on_error=yes "
1371       "androidboot.veritymode=enforcing",
1372       std::string(slot_data->cmdline));
1373   avb_slot_verify_data_free(slot_data);
1374 }
1375 
CmdlineWithHashtreeVerification(bool hashtree_verification_on)1376 void AvbSlotVerifyTest::CmdlineWithHashtreeVerification(
1377     bool hashtree_verification_on) {
1378   const size_t rootfs_size = 1028 * 1024;
1379   const size_t partition_size = 1536 * 1024;
1380 
1381   // Generate a 1028 KiB file with known content.
1382   std::vector<uint8_t> rootfs;
1383   rootfs.resize(rootfs_size);
1384   for (size_t n = 0; n < rootfs_size; n++)
1385     rootfs[n] = uint8_t(n);
1386   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
1387   EXPECT_EQ(rootfs_size,
1388             static_cast<const size_t>(
1389                 base::WriteFile(rootfs_path,
1390                                 reinterpret_cast<const char*>(rootfs.data()),
1391                                 rootfs.size())));
1392 
1393   EXPECT_COMMAND(0,
1394                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1395                  "--partition_size %d --partition_name foobar "
1396                  "--algorithm SHA256_RSA2048 "
1397                  "--key test/data/testkey_rsa2048.pem "
1398                  "--internal_release_string \"\" "
1399                  "--do_not_generate_fec",
1400                  rootfs_path.value().c_str(),
1401                  (int)partition_size);
1402 
1403   // Check that we correctly generate dm-verity kernel cmdline
1404   // snippets, if requested.
1405   GenerateVBMetaImage(
1406       "vbmeta_a.img",
1407       "SHA256_RSA2048",
1408       4,
1409       base::FilePath("test/data/testkey_rsa2048.pem"),
1410       base::StringPrintf("--setup_rootfs_from_kernel %s "
1411                          "--kernel_cmdline should_be_in_both=1 "
1412                          "--algorithm SHA256_RSA2048 "
1413                          "--flags %d "
1414                          "--internal_release_string \"\"",
1415                          rootfs_path.value().c_str(),
1416                          hashtree_verification_on
1417                              ? 0
1418                              : AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED));
1419 
1420   EXPECT_EQ(
1421       base::StringPrintf(
1422           "Minimum libavb version:   1.0\n"
1423           "Header Block:             256 bytes\n"
1424           "Authentication Block:     320 bytes\n"
1425           "Auxiliary Block:          960 bytes\n"
1426           "Algorithm:                SHA256_RSA2048\n"
1427           "Rollback Index:           4\n"
1428           "Flags:                    %d\n"
1429           "Release String:           ''\n"
1430           "Descriptors:\n"
1431           "    Kernel Cmdline descriptor:\n"
1432           "      Flags:                 1\n"
1433           "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity "
1434           "1 PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1435           "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) 4096 4096 257 257 sha1 "
1436           "e811611467dcd6e8dc4324e45f706c2bdd51db67 d00df00d 2 "
1437           "$(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n"
1438           "    Kernel Cmdline descriptor:\n"
1439           "      Flags:                 2\n"
1440           "      Kernel Cmdline:        "
1441           "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n"
1442           "    Kernel Cmdline descriptor:\n"
1443           "      Flags:                 0\n"
1444           "      Kernel Cmdline:        'should_be_in_both=1'\n",
1445           hashtree_verification_on ? 0
1446                                    : AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED),
1447       InfoImage(vbmeta_image_path_));
1448 
1449   ops_.set_expected_public_key(
1450       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1451 
1452   // Check that avb_slot_verify() picks the cmdline decsriptors based
1453   // on their flags value.
1454   AvbSlotVerifyData* slot_data = NULL;
1455   const char* requested_partitions[] = {"boot", NULL};
1456   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1457             avb_slot_verify(ops_.avb_ops(),
1458                             requested_partitions,
1459                             "_a",
1460                             AVB_SLOT_VERIFY_FLAGS_NONE,
1461                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1462                             &slot_data));
1463   EXPECT_NE(nullptr, slot_data);
1464   if (hashtree_verification_on) {
1465     EXPECT_EQ(
1466         "dm=\"1 vroot none ro 1,0 2056 verity 1 "
1467         "PARTUUID=1234-fake-guid-for:system_a "
1468         "PARTUUID=1234-fake-guid-for:system_a 4096 4096 257 257 sha1 "
1469         "e811611467dcd6e8dc4324e45f706c2bdd51db67 d00df00d 2 "
1470         "restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0 "
1471         "should_be_in_both=1 "
1472         "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
1473         "androidboot.vbmeta.avb_version=1.0 "
1474         "androidboot.vbmeta.device_state=locked "
1475         "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1536 "
1476         "androidboot.vbmeta.digest="
1477         "946996b4cd78f2c060f6bb062b94054b809cbfbe9bf4425df263a0e55395ceea "
1478         "androidboot.vbmeta.invalidate_on_error=yes "
1479         "androidboot.veritymode=enforcing",
1480         std::string(slot_data->cmdline));
1481   } else {
1482     // NOTE: androidboot.veritymode is 'disabled', not 'enforcing' and
1483     // androidboot.vbmeta.invalidate_on_error isn't set.
1484     EXPECT_EQ(
1485         "root=PARTUUID=1234-fake-guid-for:system_a should_be_in_both=1 "
1486         "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
1487         "androidboot.vbmeta.avb_version=1.0 "
1488         "androidboot.vbmeta.device_state=locked "
1489         "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1536 "
1490         "androidboot.vbmeta.digest="
1491         "c74338b2b366f7f774d264abb4ac06c997cbaacbf5edd70a6ef1a552f744076b "
1492         "androidboot.veritymode=disabled",
1493         std::string(slot_data->cmdline));
1494   }
1495   avb_slot_verify_data_free(slot_data);
1496 }
1497 
TEST_F(AvbSlotVerifyTest,CmdlineWithHashtreeVerificationOff)1498 TEST_F(AvbSlotVerifyTest, CmdlineWithHashtreeVerificationOff) {
1499   CmdlineWithHashtreeVerification(false);
1500 }
1501 
TEST_F(AvbSlotVerifyTest,CmdlineWithHashtreeVerificationOn)1502 TEST_F(AvbSlotVerifyTest, CmdlineWithHashtreeVerificationOn) {
1503   CmdlineWithHashtreeVerification(true);
1504 }
1505 
CmdlineWithChainedHashtreeVerification(bool hashtree_verification_on)1506 void AvbSlotVerifyTest::CmdlineWithChainedHashtreeVerification(
1507     bool hashtree_verification_on) {
1508   const size_t system_size = 1028 * 1024;
1509   const size_t system_partition_size = 1536 * 1024;
1510 
1511   // Generate a 1028 KiB file with known content.
1512   std::vector<uint8_t> contents;
1513   contents.resize(system_size);
1514   for (size_t n = 0; n < system_size; n++)
1515     contents[n] = uint8_t(n);
1516   base::FilePath system_path = testdir_.Append("system_a.img");
1517   EXPECT_EQ(system_size,
1518             static_cast<const size_t>(
1519                 base::WriteFile(system_path,
1520                                 reinterpret_cast<const char*>(contents.data()),
1521                                 contents.size())));
1522 
1523   // Check that we correctly generate dm-verity kernel cmdline
1524   // snippets, if requested.
1525   EXPECT_COMMAND(0,
1526                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1527                  "--partition_size %d --partition_name foobar "
1528                  "--algorithm SHA256_RSA2048 "
1529                  "--key test/data/testkey_rsa2048.pem "
1530                  "--internal_release_string \"\" "
1531                  "--do_not_generate_fec "
1532                  "--setup_as_rootfs_from_kernel",
1533                  system_path.value().c_str(),
1534                  (int)system_partition_size);
1535 
1536   EXPECT_EQ(
1537       "Footer version:           1.0\n"
1538       "Image size:               1572864 bytes\n"
1539       "Original image size:      1052672 bytes\n"
1540       "VBMeta offset:            1069056\n"
1541       "VBMeta size:              1664 bytes\n"
1542       "--\n"
1543       "Minimum libavb version:   1.0\n"
1544       "Header Block:             256 bytes\n"
1545       "Authentication Block:     320 bytes\n"
1546       "Auxiliary Block:          1088 bytes\n"
1547       "Algorithm:                SHA256_RSA2048\n"
1548       "Rollback Index:           0\n"
1549       "Flags:                    0\n"
1550       "Release String:           ''\n"
1551       "Descriptors:\n"
1552       "    Hashtree descriptor:\n"
1553       "      Version of dm-verity:  1\n"
1554       "      Image Size:            1052672 bytes\n"
1555       "      Tree Offset:           1052672\n"
1556       "      Tree Size:             16384 bytes\n"
1557       "      Data Block Size:       4096 bytes\n"
1558       "      Hash Block Size:       4096 bytes\n"
1559       "      FEC num roots:         0\n"
1560       "      FEC offset:            0\n"
1561       "      FEC size:              0 bytes\n"
1562       "      Hash Algorithm:        sha1\n"
1563       "      Partition Name:        foobar\n"
1564       "      Salt:                  d00df00d\n"
1565       "      Root Digest:           e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
1566       "    Kernel Cmdline descriptor:\n"
1567       "      Flags:                 1\n"
1568       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1569       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1570       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1571       "d00df00d 2 $(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n"
1572       "    Kernel Cmdline descriptor:\n"
1573       "      Flags:                 2\n"
1574       "      Kernel Cmdline:        "
1575       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1576       InfoImage(system_path));
1577 
1578   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1579   EXPECT_COMMAND(
1580       0,
1581       "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1582       " --output %s",
1583       pk_path.value().c_str());
1584 
1585   GenerateVBMetaImage(
1586       "vbmeta_a.img",
1587       "SHA256_RSA2048",
1588       4,
1589       base::FilePath("test/data/testkey_rsa2048.pem"),
1590       base::StringPrintf("--kernel_cmdline should_be_in_both=1 "
1591                          "--algorithm SHA256_RSA2048 "
1592                          "--flags %d "
1593                          "--chain_partition system:1:%s "
1594                          "--internal_release_string \"\"",
1595                          hashtree_verification_on
1596                              ? 0
1597                              : AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED,
1598                          pk_path.value().c_str()));
1599 
1600   EXPECT_EQ(
1601       base::StringPrintf("Minimum libavb version:   1.0\n"
1602                          "Header Block:             256 bytes\n"
1603                          "Authentication Block:     320 bytes\n"
1604                          "Auxiliary Block:          1216 bytes\n"
1605                          "Algorithm:                SHA256_RSA2048\n"
1606                          "Rollback Index:           4\n"
1607                          "Flags:                    %d\n"
1608                          "Release String:           ''\n"
1609                          "Descriptors:\n"
1610                          "    Chain Partition descriptor:\n"
1611                          "      Partition Name:          system\n"
1612                          "      Rollback Index Location: 1\n"
1613                          "      Public key (sha1):       "
1614                          "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1615                          "    Kernel Cmdline descriptor:\n"
1616                          "      Flags:                 0\n"
1617                          "      Kernel Cmdline:        'should_be_in_both=1'\n",
1618                          hashtree_verification_on
1619                              ? 0
1620                              : AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED),
1621       InfoImage(vbmeta_image_path_));
1622 
1623   ops_.set_expected_public_key(
1624       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1625 
1626   // Check that avb_slot_verify() picks the cmdline descriptors based
1627   // on their flags value... note that these descriptors are in the
1628   // 'system' partition.
1629   AvbSlotVerifyData* slot_data = NULL;
1630   const char* requested_partitions[] = {"boot", NULL};
1631   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1632             avb_slot_verify(ops_.avb_ops(),
1633                             requested_partitions,
1634                             "_a",
1635                             AVB_SLOT_VERIFY_FLAGS_NONE,
1636                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1637                             &slot_data));
1638   EXPECT_NE(nullptr, slot_data);
1639   if (hashtree_verification_on) {
1640     EXPECT_EQ(
1641         "dm=\"1 vroot none ro 1,0 2056 verity 1 "
1642         "PARTUUID=1234-fake-guid-for:system_a "
1643         "PARTUUID=1234-fake-guid-for:system_a 4096 4096 257 257 sha1 "
1644         "e811611467dcd6e8dc4324e45f706c2bdd51db67 d00df00d 2 "
1645         "restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0 "
1646         "should_be_in_both=1 "
1647         "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
1648         "androidboot.vbmeta.avb_version=1.0 "
1649         "androidboot.vbmeta.device_state=locked "
1650         "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=3456 "
1651         "androidboot.vbmeta.digest="
1652         "5ee1669b112625322657b83ec932c73dad9b0222011b5aa3e8273f4e0ee025dc "
1653         "androidboot.vbmeta.invalidate_on_error=yes "
1654         "androidboot.veritymode=enforcing",
1655         std::string(slot_data->cmdline));
1656   } else {
1657     // NOTE: androidboot.veritymode is 'disabled', not 'enforcing' and
1658     // androidboot.vbmeta.invalidate_on_error isn't set.
1659     EXPECT_EQ(
1660         "root=PARTUUID=1234-fake-guid-for:system_a should_be_in_both=1 "
1661         "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
1662         "androidboot.vbmeta.avb_version=1.0 "
1663         "androidboot.vbmeta.device_state=locked "
1664         "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=3456 "
1665         "androidboot.vbmeta.digest="
1666         "ae792c45a9d898b532ff9625b60043a8d9eae7e6106b9cba31837d50ba40f81c "
1667         "androidboot.veritymode=disabled",
1668         std::string(slot_data->cmdline));
1669   }
1670   avb_slot_verify_data_free(slot_data);
1671 }
1672 
TEST_F(AvbSlotVerifyTest,CmdlineWithChainedHashtreeVerificationOff)1673 TEST_F(AvbSlotVerifyTest, CmdlineWithChainedHashtreeVerificationOff) {
1674   CmdlineWithChainedHashtreeVerification(false);
1675 }
1676 
TEST_F(AvbSlotVerifyTest,CmdlineWithChainedHashtreeVerificationOn)1677 TEST_F(AvbSlotVerifyTest, CmdlineWithChainedHashtreeVerificationOn) {
1678   CmdlineWithChainedHashtreeVerification(true);
1679 }
1680 
VerificationDisabled(bool use_avbctl)1681 void AvbSlotVerifyTest::VerificationDisabled(bool use_avbctl) {
1682   const size_t boot_part_size = 32 * 1024 * 1024;
1683   const size_t dtbo_part_size = 4 * 1024 * 1024;
1684   const size_t rootfs_size = 1028 * 1024;
1685   const size_t partition_size = 1536 * 1024;
1686 
1687   // Generate boot_a.img and dtbo_a.img since avb_slot_verify() will
1688   // attempt to load them upon encountering the VERIFICATION_DISABLED
1689   // flag.
1690   base::FilePath boot_path = GenerateImage("boot_a.img", boot_part_size);
1691   const size_t DTBO_DATA_OFFSET = 42;
1692   base::FilePath dtbo_path =
1693       GenerateImage("dtbo_a.img", dtbo_part_size, DTBO_DATA_OFFSET);
1694 
1695   // Generate a 1028 KiB file with known content.
1696   std::vector<uint8_t> rootfs;
1697   rootfs.resize(rootfs_size);
1698   for (size_t n = 0; n < rootfs_size; n++)
1699     rootfs[n] = uint8_t(n);
1700   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
1701   EXPECT_EQ(rootfs_size,
1702             static_cast<const size_t>(
1703                 base::WriteFile(rootfs_path,
1704                                 reinterpret_cast<const char*>(rootfs.data()),
1705                                 rootfs.size())));
1706 
1707   EXPECT_COMMAND(0,
1708                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1709                  "--partition_size %d --partition_name foobar "
1710                  "--algorithm SHA256_RSA2048 "
1711                  "--key test/data/testkey_rsa2048.pem "
1712                  "--internal_release_string \"\" "
1713                  "--do_not_generate_fec",
1714                  rootfs_path.value().c_str(),
1715                  (int)partition_size);
1716 
1717   // Check that we correctly generate dm-verity kernel cmdline
1718   // snippets, if requested.
1719   GenerateVBMetaImage(
1720       "vbmeta_a.img",
1721       "SHA256_RSA2048",
1722       4,
1723       base::FilePath("test/data/testkey_rsa2048.pem"),
1724       base::StringPrintf(
1725           "--setup_rootfs_from_kernel %s "
1726           "--kernel_cmdline should_be_in_both=1 "
1727           "--algorithm SHA256_RSA2048 "
1728           "--flags %d "
1729           "--internal_release_string \"\"",
1730           rootfs_path.value().c_str(),
1731           use_avbctl ? 0 : AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED));
1732 
1733   EXPECT_EQ(
1734       base::StringPrintf(
1735           "Minimum libavb version:   1.0\n"
1736           "Header Block:             256 bytes\n"
1737           "Authentication Block:     320 bytes\n"
1738           "Auxiliary Block:          960 bytes\n"
1739           "Algorithm:                SHA256_RSA2048\n"
1740           "Rollback Index:           4\n"
1741           "Flags:                    %d\n"
1742           "Release String:           ''\n"
1743           "Descriptors:\n"
1744           "    Kernel Cmdline descriptor:\n"
1745           "      Flags:                 1\n"
1746           "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity "
1747           "1 PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1748           "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) 4096 4096 257 257 sha1 "
1749           "e811611467dcd6e8dc4324e45f706c2bdd51db67 d00df00d 2 "
1750           "$(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n"
1751           "    Kernel Cmdline descriptor:\n"
1752           "      Flags:                 2\n"
1753           "      Kernel Cmdline:        "
1754           "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n"
1755           "    Kernel Cmdline descriptor:\n"
1756           "      Flags:                 0\n"
1757           "      Kernel Cmdline:        'should_be_in_both=1'\n",
1758           use_avbctl ? 0 : AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED),
1759       InfoImage(vbmeta_image_path_));
1760 
1761   ops_.set_expected_public_key(
1762       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1763 
1764   // Manually set the flag the same way 'avbctl disable-verification'
1765   // would do it.
1766   if (use_avbctl) {
1767     uint32_t flags_data;
1768     flags_data = avb_htobe32(AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
1769     EXPECT_EQ(AVB_IO_RESULT_OK,
1770               ops_.avb_ops()->write_to_partition(
1771                   ops_.avb_ops(),
1772                   "vbmeta_a",
1773                   offsetof(AvbVBMetaImageHeader, flags),
1774                   sizeof flags_data,
1775                   &flags_data));
1776   }
1777 
1778   // Check that avb_slot_verify() doesn't return any of the
1779   // descriptors and instead return a kernel command-line with
1780   // root=PARTUUID=<whatever_for_system_a> and none of the
1781   // androidboot.vbmeta.* options are set. Also ensure all the
1782   // requested partitions are loaded.
1783   //
1784   // Also if we modified via avbctl we should expect
1785   // ERROR_VERIFICATION instead of OK.
1786   //
1787   AvbSlotVerifyResult expected_result = AVB_SLOT_VERIFY_RESULT_OK;
1788   if (use_avbctl) {
1789     expected_result = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
1790   }
1791   AvbSlotVerifyData* slot_data = NULL;
1792   const char* requested_partitions[] = {"boot", "dtbo", NULL};
1793   EXPECT_EQ(expected_result,
1794             avb_slot_verify(ops_.avb_ops(),
1795                             requested_partitions,
1796                             "_a",
1797                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
1798                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1799                             &slot_data));
1800   EXPECT_NE(nullptr, slot_data);
1801   EXPECT_EQ("root=PARTUUID=1234-fake-guid-for:system_a",
1802             std::string(slot_data->cmdline));
1803   // Also make sure that it actually loads the boot and dtbo partitions.
1804   EXPECT_EQ(size_t(2), slot_data->num_loaded_partitions);
1805   EXPECT_EQ("boot",
1806             std::string(slot_data->loaded_partitions[0].partition_name));
1807   EXPECT_EQ(boot_part_size, slot_data->loaded_partitions[0].data_size);
1808   for (size_t n = 0; n < boot_part_size; n++) {
1809     EXPECT_EQ(uint8_t(n), slot_data->loaded_partitions[0].data[n]);
1810   }
1811   EXPECT_EQ("dtbo",
1812             std::string(slot_data->loaded_partitions[1].partition_name));
1813   EXPECT_EQ(dtbo_part_size, slot_data->loaded_partitions[1].data_size);
1814   for (size_t n = 0; n < dtbo_part_size; n++) {
1815     EXPECT_EQ(uint8_t(n + DTBO_DATA_OFFSET),
1816               slot_data->loaded_partitions[1].data[n]);
1817   }
1818   avb_slot_verify_data_free(slot_data);
1819 }
1820 
TEST_F(AvbSlotVerifyTest,VerificationDisabledUnmodified)1821 TEST_F(AvbSlotVerifyTest, VerificationDisabledUnmodified) {
1822   VerificationDisabled(false);  // use_avbctl
1823 }
1824 
TEST_F(AvbSlotVerifyTest,VerificationDisabledModified)1825 TEST_F(AvbSlotVerifyTest, VerificationDisabledModified) {
1826   VerificationDisabled(true);  // use_avbctl
1827 }
1828 
1829 // In the event that there's no vbmeta partition, we treat the vbmeta
1830 // struct from 'boot' as the top-level partition. Check that this
1831 // works.
TEST_F(AvbSlotVerifyTest,NoVBMetaPartition)1832 TEST_F(AvbSlotVerifyTest, NoVBMetaPartition) {
1833   const size_t MiB = 1024 * 1024;
1834   const size_t boot_size = 6 * MiB;
1835   const size_t boot_part_size = 8 * MiB;
1836   const size_t system_size = 16 * MiB;
1837   const size_t system_part_size = 32 * MiB;
1838   const size_t foobar_size = 8 * MiB;
1839   const size_t foobar_part_size = 16 * MiB;
1840   const size_t bazboo_size = 4 * MiB;
1841   const size_t bazboo_part_size = 8 * MiB;
1842   base::FilePath boot_path = GenerateImage("boot.img", boot_size);
1843   base::FilePath system_path = GenerateImage("system.img", system_size);
1844   base::FilePath foobar_path = GenerateImage("foobar.img", foobar_size);
1845   base::FilePath bazboo_path = GenerateImage("bazboo.img", bazboo_size);
1846 
1847   EXPECT_COMMAND(0,
1848                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1849                  "--partition_size %d --partition_name system "
1850                  "--algorithm SHA256_RSA2048 "
1851                  "--key test/data/testkey_rsa2048.pem "
1852                  "--internal_release_string \"\" "
1853                  "--do_not_generate_fec",
1854                  system_path.value().c_str(),
1855                  (int)system_part_size);
1856 
1857   EXPECT_COMMAND(0,
1858                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1859                  "--partition_size %d --partition_name foobar "
1860                  "--algorithm SHA256_RSA2048 "
1861                  "--key test/data/testkey_rsa2048.pem "
1862                  "--internal_release_string \"\" "
1863                  "--do_not_generate_fec",
1864                  foobar_path.value().c_str(),
1865                  (int)foobar_part_size);
1866 
1867   EXPECT_COMMAND(0,
1868                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1869                  "--partition_size %d --partition_name bazboo "
1870                  "--algorithm SHA512_RSA4096 "
1871                  "--key test/data/testkey_rsa4096.pem "
1872                  "--internal_release_string \"\" "
1873                  "--do_not_generate_fec",
1874                  bazboo_path.value().c_str(),
1875                  (int)bazboo_part_size);
1876 
1877   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
1878   EXPECT_COMMAND(
1879       0,
1880       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
1881       " --output %s",
1882       pk_path.value().c_str());
1883 
1884   // Explicitly pass "--flags 2147483648" (i.e. 1<<31) to check that
1885   // boot.img is treated as top-level. Note the corresponding "Flags:"
1886   // field below in the avbtool info_image output.
1887   EXPECT_COMMAND(0,
1888                  "./avbtool add_hash_footer --salt d00df00d "
1889                  "--hash_algorithm sha256 --image %s "
1890                  "--partition_size %d --partition_name boot "
1891                  "--algorithm SHA256_RSA2048 "
1892                  "--key test/data/testkey_rsa2048.pem "
1893                  "--internal_release_string \"\" "
1894                  "--include_descriptors_from_image %s "
1895                  "--include_descriptors_from_image %s "
1896                  "--setup_rootfs_from_kernel %s "
1897                  "--chain_partition bazboo:1:%s "
1898                  "--flags 2147483648",
1899                  boot_path.value().c_str(),
1900                  (int)boot_part_size,
1901                  system_path.value().c_str(),
1902                  foobar_path.value().c_str(),
1903                  system_path.value().c_str(),
1904                  pk_path.value().c_str());
1905 
1906   ASSERT_EQ(
1907       "Footer version:           1.0\n"
1908       "Image size:               8388608 bytes\n"
1909       "Original image size:      6291456 bytes\n"
1910       "VBMeta offset:            6291456\n"
1911       "VBMeta size:              3200 bytes\n"
1912       "--\n"
1913       "Minimum libavb version:   1.0\n"
1914       "Header Block:             256 bytes\n"
1915       "Authentication Block:     320 bytes\n"
1916       "Auxiliary Block:          2624 bytes\n"
1917       "Algorithm:                SHA256_RSA2048\n"
1918       "Rollback Index:           0\n"
1919       "Flags:                    2147483648\n"
1920       "Release String:           ''\n"
1921       "Descriptors:\n"
1922       "    Hash descriptor:\n"
1923       "      Image Size:            6291456 bytes\n"
1924       "      Hash Algorithm:        sha256\n"
1925       "      Partition Name:        boot\n"
1926       "      Salt:                  d00df00d\n"
1927       "      Digest:                "
1928       "4c109399b20e476bab15363bff55740add83e1c1e97e0b132f5c713ddd8c7868\n"
1929       "    Chain Partition descriptor:\n"
1930       "      Partition Name:          bazboo\n"
1931       "      Rollback Index Location: 1\n"
1932       "      Public key (sha1):       "
1933       "2597c218aae470a130f61162feaae70afd97f011\n"
1934       "    Kernel Cmdline descriptor:\n"
1935       "      Flags:                 1\n"
1936       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 32768 verity 1 "
1937       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1938       "4096 4096 4096 4096 sha1 c9ffc3bfae5000269a55a56621547fd1fcf819df "
1939       "d00df00d 2 $(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n"
1940       "    Kernel Cmdline descriptor:\n"
1941       "      Flags:                 2\n"
1942       "      Kernel Cmdline:        "
1943       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n"
1944       "    Hashtree descriptor:\n"
1945       "      Version of dm-verity:  1\n"
1946       "      Image Size:            16777216 bytes\n"
1947       "      Tree Offset:           16777216\n"
1948       "      Tree Size:             135168 bytes\n"
1949       "      Data Block Size:       4096 bytes\n"
1950       "      Hash Block Size:       4096 bytes\n"
1951       "      FEC num roots:         0\n"
1952       "      FEC offset:            0\n"
1953       "      FEC size:              0 bytes\n"
1954       "      Hash Algorithm:        sha1\n"
1955       "      Partition Name:        system\n"
1956       "      Salt:                  d00df00d\n"
1957       "      Root Digest:           c9ffc3bfae5000269a55a56621547fd1fcf819df\n"
1958       "    Hashtree descriptor:\n"
1959       "      Version of dm-verity:  1\n"
1960       "      Image Size:            8388608 bytes\n"
1961       "      Tree Offset:           8388608\n"
1962       "      Tree Size:             69632 bytes\n"
1963       "      Data Block Size:       4096 bytes\n"
1964       "      Hash Block Size:       4096 bytes\n"
1965       "      FEC num roots:         0\n"
1966       "      FEC offset:            0\n"
1967       "      FEC size:              0 bytes\n"
1968       "      Hash Algorithm:        sha1\n"
1969       "      Partition Name:        foobar\n"
1970       "      Salt:                  d00df00d\n"
1971       "      Root Digest:           d52d93c988d336a79abe1c05240ae9a79a9b7d61\n",
1972       InfoImage(boot_path));
1973 
1974   ops_.set_expected_public_key(
1975       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1976 
1977   // Now check that libavb will fall back to reading from 'boot'
1978   // instead of 'vbmeta' when encountering
1979   // AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION on trying to read from
1980   // 'vbmeta'.
1981   AvbSlotVerifyData* slot_data = NULL;
1982   const char* requested_partitions[] = {"boot", NULL};
1983   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1984             avb_slot_verify(ops_.avb_ops(),
1985                             requested_partitions,
1986                             "",
1987                             AVB_SLOT_VERIFY_FLAGS_NONE,
1988                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
1989                             &slot_data));
1990   EXPECT_NE(nullptr, slot_data);
1991   // Note 'boot' in the value androidboot.vbmeta.device since we've
1992   // read from 'boot' and not 'vbmeta'.
1993   EXPECT_EQ(
1994       "dm=\"1 vroot none ro 1,0 32768 verity 1 "
1995       "PARTUUID=1234-fake-guid-for:system PARTUUID=1234-fake-guid-for:system "
1996       "4096 4096 4096 4096 sha1 c9ffc3bfae5000269a55a56621547fd1fcf819df "
1997       "d00df00d 2 restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0 "
1998       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:boot "
1999       "androidboot.vbmeta.avb_version=1.0 "
2000       "androidboot.vbmeta.device_state=locked "
2001       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=5312 "
2002       "androidboot.vbmeta.digest="
2003       "6b06719a940e5d8fa53ffef91eb4f0517ff0dda9833b90be1c9624ab3a5261d2 "
2004       "androidboot.vbmeta.invalidate_on_error=yes "
2005       "androidboot.veritymode=enforcing",
2006       std::string(slot_data->cmdline));
2007   avb_slot_verify_data_free(slot_data);
2008 }
2009 
2010 // Check that non-zero flags in chained partition are caught in
2011 // avb_slot_verify().
TEST_F(AvbSlotVerifyTest,ChainedPartitionEnforceFlagsZero)2012 TEST_F(AvbSlotVerifyTest, ChainedPartitionEnforceFlagsZero) {
2013   size_t boot_partition_size = 16 * 1024 * 1024;
2014   const size_t boot_image_size = 5 * 1024 * 1024;
2015   base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
2016   const char* requested_partitions[] = {"boot", NULL};
2017 
2018   EXPECT_COMMAND(0,
2019                  "./avbtool add_hash_footer"
2020                  " --image %s"
2021                  " --kernel_cmdline 'cmdline2 in hash footer'"
2022                  " --rollback_index 12"
2023                  " --partition_name boot"
2024                  " --partition_size %zd"
2025                  " --algorithm SHA256_RSA4096"
2026                  " --key test/data/testkey_rsa4096.pem"
2027                  " --salt deadbeef"
2028                  " --flags 1"
2029                  " --internal_release_string \"\"",
2030                  boot_path.value().c_str(),
2031                  boot_partition_size);
2032 
2033   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
2034   EXPECT_COMMAND(
2035       0,
2036       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
2037       " --output %s",
2038       pk_path.value().c_str());
2039 
2040   GenerateVBMetaImage(
2041       "vbmeta_a.img",
2042       "SHA256_RSA2048",
2043       11,
2044       base::FilePath("test/data/testkey_rsa2048.pem"),
2045       base::StringPrintf("--chain_partition boot:1:%s"
2046                          " --kernel_cmdline 'cmdline2 in vbmeta'"
2047                          " --internal_release_string \"\"",
2048                          pk_path.value().c_str()));
2049 
2050   ops_.set_expected_public_key(
2051       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
2052 
2053   AvbSlotVerifyData* slot_data = NULL;
2054   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
2055             avb_slot_verify(ops_.avb_ops(),
2056                             requested_partitions,
2057                             "_a",
2058                             AVB_SLOT_VERIFY_FLAGS_NONE,
2059                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
2060                             &slot_data));
2061   EXPECT_EQ(nullptr, slot_data);
2062 }
2063 
2064 // Check that chain descriptors in chained partitions are caught in
2065 // avb_slot_verify().
TEST_F(AvbSlotVerifyTest,ChainedPartitionEnforceNoChainPartitions)2066 TEST_F(AvbSlotVerifyTest, ChainedPartitionEnforceNoChainPartitions) {
2067   size_t boot_partition_size = 16 * 1024 * 1024;
2068   const size_t boot_image_size = 5 * 1024 * 1024;
2069   base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
2070   const char* requested_partitions[] = {"boot", NULL};
2071 
2072   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
2073   EXPECT_COMMAND(
2074       0,
2075       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
2076       " --output %s",
2077       pk_path.value().c_str());
2078 
2079   EXPECT_COMMAND(0,
2080                  "./avbtool add_hash_footer"
2081                  " --image %s"
2082                  " --kernel_cmdline 'cmdline2 in hash footer'"
2083                  " --rollback_index 12"
2084                  " --partition_name boot"
2085                  " --partition_size %zd"
2086                  " --algorithm SHA256_RSA4096"
2087                  " --key test/data/testkey_rsa4096.pem"
2088                  " --salt deadbeef"
2089                  " --chain_partition other:2:%s"
2090                  " --internal_release_string \"\"",
2091                  boot_path.value().c_str(),
2092                  boot_partition_size,
2093                  pk_path.value().c_str());
2094 
2095   GenerateVBMetaImage(
2096       "vbmeta_a.img",
2097       "SHA256_RSA2048",
2098       11,
2099       base::FilePath("test/data/testkey_rsa2048.pem"),
2100       base::StringPrintf("--chain_partition boot:1:%s"
2101                          " --kernel_cmdline 'cmdline2 in vbmeta'"
2102                          " --internal_release_string \"\"",
2103                          pk_path.value().c_str()));
2104 
2105   ops_.set_expected_public_key(
2106       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
2107 
2108   AvbSlotVerifyData* slot_data = NULL;
2109   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
2110             avb_slot_verify(ops_.avb_ops(),
2111                             requested_partitions,
2112                             "_a",
2113                             AVB_SLOT_VERIFY_FLAGS_NONE,
2114                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
2115                             &slot_data));
2116   EXPECT_EQ(nullptr, slot_data);
2117 }
2118 
TEST_F(AvbSlotVerifyTest,HashtreeErrorModes)2119 TEST_F(AvbSlotVerifyTest, HashtreeErrorModes) {
2120   const size_t MiB = 1024 * 1024;
2121   const size_t system_size = 16 * MiB;
2122   const size_t system_part_size = 32 * MiB;
2123   base::FilePath system_path = GenerateImage("system.img", system_size);
2124 
2125   EXPECT_COMMAND(0,
2126                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
2127                  "--partition_size %d --partition_name system "
2128                  "--algorithm SHA256_RSA2048 "
2129                  "--key test/data/testkey_rsa2048.pem "
2130                  "--internal_release_string \"\" "
2131                  "--do_not_generate_fec",
2132                  system_path.value().c_str(),
2133                  (int)system_part_size);
2134 
2135   GenerateVBMetaImage("vbmeta.img",
2136                       "SHA256_RSA2048",
2137                       0,
2138                       base::FilePath("test/data/testkey_rsa2048.pem"),
2139                       base::StringPrintf("--setup_rootfs_from_kernel %s "
2140                                          "--include_descriptors_from_image %s"
2141                                          " --internal_release_string \"\"",
2142                                          system_path.value().c_str(),
2143                                          system_path.value().c_str()));
2144 
2145   ops_.set_expected_public_key(
2146       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
2147 
2148   AvbSlotVerifyData* slot_data = NULL;
2149   const char* requested_partitions[] = {"boot", NULL};
2150 
2151   // For AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE we should get
2152   // androidboot.vbmeta.invalidate_on_error=yes and
2153   // androidboot.veritymode=enforcing. We should get
2154   // 'restart_on_corruption' in the dm="..." string.
2155   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
2156             avb_slot_verify(ops_.avb_ops(),
2157                             requested_partitions,
2158                             "",
2159                             AVB_SLOT_VERIFY_FLAGS_NONE,
2160                             AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
2161                             &slot_data));
2162   EXPECT_NE(nullptr, slot_data);
2163   EXPECT_EQ(
2164       "dm=\"1 vroot none ro 1,0 32768 verity 1 "
2165       "PARTUUID=1234-fake-guid-for:system "
2166       "PARTUUID=1234-fake-guid-for:system 4096 4096 4096 4096 sha1 "
2167       "c9ffc3bfae5000269a55a56621547fd1fcf819df d00df00d 2 "
2168       "restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0 "
2169       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta "
2170       "androidboot.vbmeta.avb_version=1.0 "
2171       "androidboot.vbmeta.device_state=locked "
2172       "androidboot.vbmeta.hash_alg=sha256 "
2173       "androidboot.vbmeta.size=1664 "
2174       "androidboot.vbmeta.digest="
2175       "e6c8c7d819f6b05ec0ebf7f73ee3b09f8d395e70ee040fe34f8fa6bccc8df798 "
2176       "androidboot.vbmeta.invalidate_on_error=yes "
2177       "androidboot.veritymode=enforcing",
2178       std::string(slot_data->cmdline));
2179   avb_slot_verify_data_free(slot_data);
2180 
2181   // For AVB_HASHTREE_ERROR_MODE_RESTART we should get
2182   // androidboot.veritymode=enforcing and
2183   // androidboot.vbmeta.invalidate_on_error should be unset. We should
2184   // get 'restart_on_corruption' in the dm="..." string.
2185   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
2186             avb_slot_verify(ops_.avb_ops(),
2187                             requested_partitions,
2188                             "",
2189                             AVB_SLOT_VERIFY_FLAGS_NONE,
2190                             AVB_HASHTREE_ERROR_MODE_RESTART,
2191                             &slot_data));
2192   EXPECT_NE(nullptr, slot_data);
2193   EXPECT_EQ(
2194       "dm=\"1 vroot none ro 1,0 32768 verity 1 "
2195       "PARTUUID=1234-fake-guid-for:system "
2196       "PARTUUID=1234-fake-guid-for:system 4096 4096 4096 4096 sha1 "
2197       "c9ffc3bfae5000269a55a56621547fd1fcf819df d00df00d 2 "
2198       "restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0 "
2199       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta "
2200       "androidboot.vbmeta.avb_version=1.0 "
2201       "androidboot.vbmeta.device_state=locked "
2202       "androidboot.vbmeta.hash_alg=sha256 "
2203       "androidboot.vbmeta.size=1664 "
2204       "androidboot.vbmeta.digest="
2205       "e6c8c7d819f6b05ec0ebf7f73ee3b09f8d395e70ee040fe34f8fa6bccc8df798 "
2206       "androidboot.veritymode=enforcing",
2207       std::string(slot_data->cmdline));
2208   avb_slot_verify_data_free(slot_data);
2209 
2210   // For AVB_HASHTREE_ERROR_MODE_EIO we should get
2211   // androidboot.veritymode=eio and
2212   // androidboot.vbmeta.invalidate_on_error should be unset. We should
2213   // get 'ignore_zero_blocks' in the dm="..." string.
2214   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
2215             avb_slot_verify(ops_.avb_ops(),
2216                             requested_partitions,
2217                             "",
2218                             AVB_SLOT_VERIFY_FLAGS_NONE,
2219                             AVB_HASHTREE_ERROR_MODE_EIO,
2220                             &slot_data));
2221   EXPECT_NE(nullptr, slot_data);
2222   EXPECT_EQ(
2223       "dm=\"1 vroot none ro 1,0 32768 verity 1 "
2224       "PARTUUID=1234-fake-guid-for:system "
2225       "PARTUUID=1234-fake-guid-for:system 4096 4096 4096 4096 sha1 "
2226       "c9ffc3bfae5000269a55a56621547fd1fcf819df d00df00d 2 "
2227       "ignore_zero_blocks ignore_zero_blocks\" root=/dev/dm-0 "
2228       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta "
2229       "androidboot.vbmeta.avb_version=1.0 "
2230       "androidboot.vbmeta.device_state=locked "
2231       "androidboot.vbmeta.hash_alg=sha256 "
2232       "androidboot.vbmeta.size=1664 "
2233       "androidboot.vbmeta.digest="
2234       "e6c8c7d819f6b05ec0ebf7f73ee3b09f8d395e70ee040fe34f8fa6bccc8df798 "
2235       "androidboot.veritymode=eio",
2236       std::string(slot_data->cmdline));
2237   avb_slot_verify_data_free(slot_data);
2238 
2239   // For AVB_HASHTREE_ERROR_MODE_LOGGING we should get
2240   // androidboot.veritymode=logging and
2241   // androidboot.vbmeta.invalidate_on_error should be unset. We should
2242   // get 'ignore_corruption' in the dm="..." string.
2243   //
2244   // Check AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT is returned
2245   // unless we pass AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
2246   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT,
2247             avb_slot_verify(ops_.avb_ops(),
2248                             requested_partitions,
2249                             "",
2250                             AVB_SLOT_VERIFY_FLAGS_NONE,
2251                             AVB_HASHTREE_ERROR_MODE_LOGGING,
2252                             &slot_data));
2253   EXPECT_EQ(nullptr, slot_data);
2254   // --
2255   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
2256             avb_slot_verify(ops_.avb_ops(),
2257                             requested_partitions,
2258                             "",
2259                             AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
2260                             AVB_HASHTREE_ERROR_MODE_LOGGING,
2261                             &slot_data));
2262   EXPECT_NE(nullptr, slot_data);
2263   EXPECT_EQ(
2264       "dm=\"1 vroot none ro 1,0 32768 verity 1 "
2265       "PARTUUID=1234-fake-guid-for:system "
2266       "PARTUUID=1234-fake-guid-for:system 4096 4096 4096 4096 sha1 "
2267       "c9ffc3bfae5000269a55a56621547fd1fcf819df d00df00d 2 "
2268       "ignore_corruption ignore_zero_blocks\" root=/dev/dm-0 "
2269       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta "
2270       "androidboot.vbmeta.avb_version=1.0 "
2271       "androidboot.vbmeta.device_state=locked "
2272       "androidboot.vbmeta.hash_alg=sha256 "
2273       "androidboot.vbmeta.size=1664 "
2274       "androidboot.vbmeta.digest="
2275       "e6c8c7d819f6b05ec0ebf7f73ee3b09f8d395e70ee040fe34f8fa6bccc8df798 "
2276       "androidboot.veritymode=logging",
2277       std::string(slot_data->cmdline));
2278   avb_slot_verify_data_free(slot_data);
2279 
2280   // Check we'll get androidboot.veritymode=disabled for any
2281   // |hashtree_error_mode| if dm-verity is disabled.
2282   GenerateVBMetaImage("vbmeta.img",
2283                       "SHA256_RSA2048",
2284                       0,
2285                       base::FilePath("test/data/testkey_rsa2048.pem"),
2286                       base::StringPrintf("--setup_rootfs_from_kernel %s "
2287                                          "--include_descriptors_from_image %s "
2288                                          "--set_hashtree_disabled_flag "
2289                                          "--internal_release_string \"\"",
2290                                          system_path.value().c_str(),
2291                                          system_path.value().c_str()));
2292   for (int n = 0; n < 4; n++) {
2293     AvbHashtreeErrorMode modes[4] = {
2294         AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
2295         AVB_HASHTREE_ERROR_MODE_RESTART,
2296         AVB_HASHTREE_ERROR_MODE_EIO,
2297         AVB_HASHTREE_ERROR_MODE_LOGGING};
2298     EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
2299               avb_slot_verify(ops_.avb_ops(),
2300                               requested_partitions,
2301                               "",
2302                               AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
2303                               modes[n],
2304                               &slot_data));
2305     EXPECT_NE(nullptr, slot_data);
2306     EXPECT_EQ(
2307         "root=PARTUUID=1234-fake-guid-for:system "
2308         "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta "
2309         "androidboot.vbmeta.avb_version=1.0 "
2310         "androidboot.vbmeta.device_state=locked "
2311         "androidboot.vbmeta.hash_alg=sha256 "
2312         "androidboot.vbmeta.size=1664 "
2313         "androidboot.vbmeta.digest="
2314         "e73a466d63f451dcf5c051ff12a32c006ba282a34b37420c0d563f0282cad703 "
2315         "androidboot.veritymode=disabled",
2316         std::string(slot_data->cmdline));
2317     avb_slot_verify_data_free(slot_data);
2318   }
2319 }
2320 
2321 }  // namespace avb
2322