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 
49   FakeAvbOps ops_;
50 };
51 
TEST_F(AvbSlotVerifyTest,Basic)52 TEST_F(AvbSlotVerifyTest, Basic) {
53   GenerateVBMetaImage("vbmeta_a.img",
54                       "SHA256_RSA2048",
55                       0,
56                       base::FilePath("test/data/testkey_rsa2048.pem"),
57                       "--internal_release_string \"\"");
58 
59   ops_.set_expected_public_key(
60       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
61 
62   AvbSlotVerifyData* slot_data = NULL;
63   const char* requested_partitions[] = {"boot", NULL};
64   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
65             avb_slot_verify(ops_.avb_ops(),
66                             requested_partitions,
67                             "_a",
68                             false /* allow_verification_error */,
69                             &slot_data));
70   EXPECT_NE(nullptr, slot_data);
71   EXPECT_EQ(
72       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
73       "androidboot.vbmeta.avb_version=1.0 "
74       "androidboot.vbmeta.device_state=locked "
75       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1152 "
76       "androidboot.vbmeta.digest="
77       "4161a7e655eabe16c3fe714de5d43736e7c0a190cf08d36c946d2509ce071e4d",
78       std::string(slot_data->cmdline));
79   avb_slot_verify_data_free(slot_data);
80 }
81 
TEST_F(AvbSlotVerifyTest,BasicSha512)82 TEST_F(AvbSlotVerifyTest, BasicSha512) {
83   GenerateVBMetaImage("vbmeta_a.img",
84                       "SHA512_RSA2048",
85                       0,
86                       base::FilePath("test/data/testkey_rsa2048.pem"),
87                       "--internal_release_string \"\"");
88 
89   ops_.set_expected_public_key(
90       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
91 
92   AvbSlotVerifyData* slot_data = NULL;
93   const char* requested_partitions[] = {"boot", NULL};
94   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
95             avb_slot_verify(ops_.avb_ops(),
96                             requested_partitions,
97                             "_a",
98                             false /* allow_verification_error */,
99                             &slot_data));
100   EXPECT_NE(nullptr, slot_data);
101   EXPECT_EQ(
102       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
103       "androidboot.vbmeta.avb_version=1.0 "
104       "androidboot.vbmeta.device_state=locked "
105       "androidboot.vbmeta.hash_alg=sha512 androidboot.vbmeta.size=1152 "
106       "androidboot.vbmeta.digest="
107       "cb913d2f1a884f4e04c1db5bb181f3133fd16ac02fb367a20ef0776c0b07b3656ad1f081"
108       "e01932cf70f38b8960877470b448f1588dff022808387cc52fa77e77",
109       std::string(slot_data->cmdline));
110   avb_slot_verify_data_free(slot_data);
111 }
112 
TEST_F(AvbSlotVerifyTest,BasicUnlocked)113 TEST_F(AvbSlotVerifyTest, BasicUnlocked) {
114   GenerateVBMetaImage("vbmeta_a.img",
115                       "SHA256_RSA2048",
116                       0,
117                       base::FilePath("test/data/testkey_rsa2048.pem"),
118                       "--internal_release_string \"\"");
119 
120   ops_.set_expected_public_key(
121       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
122 
123   ops_.set_stored_is_device_unlocked(true);
124 
125   AvbSlotVerifyData* slot_data = NULL;
126   const char* requested_partitions[] = {"boot", NULL};
127   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
128             avb_slot_verify(ops_.avb_ops(),
129                             requested_partitions,
130                             "_a",
131                             false /* allow_verification_error */,
132                             &slot_data));
133   EXPECT_NE(nullptr, slot_data);
134   EXPECT_EQ(
135       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
136       "androidboot.vbmeta.avb_version=1.0 "
137       "androidboot.vbmeta.device_state=unlocked "
138       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1152 "
139       "androidboot.vbmeta.digest="
140       "4161a7e655eabe16c3fe714de5d43736e7c0a190cf08d36c946d2509ce071e4d",
141       std::string(slot_data->cmdline));
142   avb_slot_verify_data_free(slot_data);
143 }
144 
TEST_F(AvbSlotVerifyTest,SlotDataIsCorrect)145 TEST_F(AvbSlotVerifyTest, SlotDataIsCorrect) {
146   GenerateVBMetaImage("vbmeta_a.img",
147                       "SHA256_RSA2048",
148                       0,
149                       base::FilePath("test/data/testkey_rsa2048.pem"),
150                       "--internal_release_string \"\"");
151 
152   ops_.set_expected_public_key(
153       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
154 
155   AvbSlotVerifyData* slot_data = NULL;
156   const char* requested_partitions[] = {"boot", NULL};
157   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
158             avb_slot_verify(ops_.avb_ops(),
159                             requested_partitions,
160                             "_a",
161                             false /* allow_verification_error */,
162                             &slot_data));
163   EXPECT_NE(nullptr, slot_data);
164   avb_slot_verify_data_free(slot_data);
165 }
166 
TEST_F(AvbSlotVerifyTest,WrongPublicKey)167 TEST_F(AvbSlotVerifyTest, WrongPublicKey) {
168   GenerateVBMetaImage("vbmeta_a.img",
169                       "SHA256_RSA2048",
170                       0,
171                       base::FilePath("test/data/testkey_rsa2048.pem"),
172                       "--internal_release_string \"\"");
173 
174   AvbSlotVerifyData* slot_data = NULL;
175   const char* requested_partitions[] = {"boot", NULL};
176   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
177             avb_slot_verify(ops_.avb_ops(),
178                             requested_partitions,
179                             "_a",
180                             false /* allow_verification_error */,
181                             &slot_data));
182   EXPECT_EQ(nullptr, slot_data);
183   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
184             avb_slot_verify(ops_.avb_ops(),
185                             requested_partitions,
186                             "_a",
187                             true /* allow_verification_error */,
188                             &slot_data));
189   EXPECT_NE(nullptr, slot_data);
190   avb_slot_verify_data_free(slot_data);
191 }
192 
TEST_F(AvbSlotVerifyTest,NoImage)193 TEST_F(AvbSlotVerifyTest, NoImage) {
194   const char* requested_partitions[] = {"boot", NULL};
195   AvbSlotVerifyData* slot_data = NULL;
196   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_IO,
197             avb_slot_verify(ops_.avb_ops(),
198                             requested_partitions,
199                             "_a",
200                             false /* allow_verification_error */,
201                             &slot_data));
202   EXPECT_EQ(nullptr, slot_data);
203 }
204 
TEST_F(AvbSlotVerifyTest,UnsignedVBMeta)205 TEST_F(AvbSlotVerifyTest, UnsignedVBMeta) {
206   GenerateVBMetaImage("vbmeta_a.img",
207                       "",
208                       0,
209                       base::FilePath(""),
210                       "--internal_release_string \"\"");
211 
212   AvbSlotVerifyData* slot_data = NULL;
213   const char* requested_partitions[] = {"boot", NULL};
214   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
215             avb_slot_verify(ops_.avb_ops(),
216                             requested_partitions,
217                             "_a",
218                             false /* allow_verification_error */,
219                             &slot_data));
220   EXPECT_EQ(nullptr, slot_data);
221   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
222             avb_slot_verify(ops_.avb_ops(),
223                             requested_partitions,
224                             "_a",
225                             true /* allow_verification_error */,
226                             &slot_data));
227   EXPECT_NE(nullptr, slot_data);
228   avb_slot_verify_data_free(slot_data);
229 }
230 
TEST_F(AvbSlotVerifyTest,CorruptedImage)231 TEST_F(AvbSlotVerifyTest, CorruptedImage) {
232   GenerateVBMetaImage("vbmeta_a.img",
233                       "SHA256_RSA2048",
234                       0,
235                       base::FilePath("test/data/testkey_rsa2048.pem"),
236                       "--internal_release_string \"\"");
237 
238   // Corrupt four bytes of data in the end of the image. Since the aux
239   // data is at the end and this data is signed, this will change the
240   // value of the computed hash.
241   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
242   EXPECT_EQ(AVB_IO_RESULT_OK,
243             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
244                                                "vbmeta_a",
245                                                -4,  // offset from end
246                                                sizeof corrupt_data,
247                                                corrupt_data));
248 
249   AvbSlotVerifyData* slot_data = NULL;
250   const char* requested_partitions[] = {"boot", NULL};
251   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
252             avb_slot_verify(ops_.avb_ops(),
253                             requested_partitions,
254                             "_a",
255                             false /* allow_verification_error */,
256                             &slot_data));
257   EXPECT_EQ(nullptr, slot_data);
258   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
259             avb_slot_verify(ops_.avb_ops(),
260                             requested_partitions,
261                             "_a",
262                             true /* allow_verification_error */,
263                             &slot_data));
264   EXPECT_NE(nullptr, slot_data);
265   avb_slot_verify_data_free(slot_data);
266 }
267 
TEST_F(AvbSlotVerifyTest,CorruptedMetadata)268 TEST_F(AvbSlotVerifyTest, CorruptedMetadata) {
269   GenerateVBMetaImage("vbmeta_a.img",
270                       "SHA256_RSA2048",
271                       0,
272                       base::FilePath("test/data/testkey_rsa2048.pem"),
273                       "--internal_release_string \"\"");
274 
275   // Corrupt four bytes of data in the beginning of the image. Unlike
276   // the CorruptedImage test-case above (which is valid metadata) this
277   // will make the metadata invalid and render the slot unbootable
278   // even if the device is unlocked. Specifically no AvbSlotVerifyData
279   // is returned.
280   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
281   EXPECT_EQ(AVB_IO_RESULT_OK,
282             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
283                                                "vbmeta_a",
284                                                0,  // offset: beginning
285                                                sizeof corrupt_data,
286                                                corrupt_data));
287 
288   AvbSlotVerifyData* slot_data = NULL;
289   const char* requested_partitions[] = {"boot", NULL};
290   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
291             avb_slot_verify(ops_.avb_ops(),
292                             requested_partitions,
293                             "_a",
294                             false /* allow_verification_error */,
295                             &slot_data));
296   EXPECT_EQ(nullptr, slot_data);
297 }
298 
TEST_F(AvbSlotVerifyTest,RollbackIndex)299 TEST_F(AvbSlotVerifyTest, RollbackIndex) {
300   GenerateVBMetaImage("vbmeta_a.img",
301                       "SHA256_RSA2048",
302                       42,
303                       base::FilePath("test/data/testkey_rsa2048.pem"),
304                       "--internal_release_string \"\"");
305 
306   ops_.set_expected_public_key(
307       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
308 
309   AvbSlotVerifyData* slot_data = NULL;
310   const char* requested_partitions[] = {"boot", NULL};
311 
312   // First try with 42 as the stored rollback index - this should
313   // succeed since the image rollback index is 42 (as set above).
314   ops_.set_stored_rollback_indexes({{0, 42}});
315   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
316             avb_slot_verify(ops_.avb_ops(),
317                             requested_partitions,
318                             "_a",
319                             false /* allow_verification_error */,
320                             &slot_data));
321   EXPECT_NE(nullptr, slot_data);
322   avb_slot_verify_data_free(slot_data);
323 
324   // Then try with 43 for the stored rollback index - this should fail
325   // because the image has rollback index 42 which is less than 43.
326   ops_.set_stored_rollback_indexes({{0, 43}});
327   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
328             avb_slot_verify(ops_.avb_ops(),
329                             requested_partitions,
330                             "_a",
331                             false /* allow_verification_error */,
332                             &slot_data));
333   EXPECT_EQ(nullptr, slot_data);
334   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
335             avb_slot_verify(ops_.avb_ops(),
336                             requested_partitions,
337                             "_a",
338                             true /* allow_verification_error */,
339                             &slot_data));
340   EXPECT_NE(nullptr, slot_data);
341   avb_slot_verify_data_free(slot_data);
342 }
343 
TEST_F(AvbSlotVerifyTest,HashDescriptorInVBMeta)344 TEST_F(AvbSlotVerifyTest, HashDescriptorInVBMeta) {
345   const size_t boot_partition_size = 16 * 1024 * 1024;
346   const size_t boot_image_size = 5 * 1024 * 1024;
347   base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
348 
349   EXPECT_COMMAND(
350       0,
351       "./avbtool add_hash_footer"
352       " --image %s"
353       " --rollback_index 0"
354       " --partition_name boot"
355       " --partition_size %zd"
356       " --kernel_cmdline 'cmdline in hash footer $(ANDROID_SYSTEM_PARTUUID)'"
357       " --salt deadbeef"
358       " --internal_release_string \"\"",
359       boot_path.value().c_str(),
360       boot_partition_size);
361 
362   GenerateVBMetaImage(
363       "vbmeta_a.img",
364       "SHA256_RSA2048",
365       4,
366       base::FilePath("test/data/testkey_rsa2048.pem"),
367       base::StringPrintf(
368           "--include_descriptors_from_image %s"
369           " --kernel_cmdline 'cmdline in vbmeta $(ANDROID_BOOT_PARTUUID)'"
370           " --internal_release_string \"\"",
371           boot_path.value().c_str()));
372 
373   EXPECT_EQ(
374       "Minimum libavb version:   1.0\n"
375       "Header Block:             256 bytes\n"
376       "Authentication Block:     320 bytes\n"
377       "Auxiliary Block:          896 bytes\n"
378       "Algorithm:                SHA256_RSA2048\n"
379       "Rollback Index:           4\n"
380       "Flags:                    0\n"
381       "Release String:           ''\n"
382       "Descriptors:\n"
383       "    Kernel Cmdline descriptor:\n"
384       "      Flags:                 0\n"
385       "      Kernel Cmdline:        'cmdline in vbmeta "
386       "$(ANDROID_BOOT_PARTUUID)'\n"
387       "    Hash descriptor:\n"
388       "      Image Size:            5242880 bytes\n"
389       "      Hash Algorithm:        sha256\n"
390       "      Partition Name:        boot\n"
391       "      Salt:                  deadbeef\n"
392       "      Digest:                "
393       "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n"
394       "    Kernel Cmdline descriptor:\n"
395       "      Flags:                 0\n"
396       "      Kernel Cmdline:        'cmdline in hash footer "
397       "$(ANDROID_SYSTEM_PARTUUID)'\n",
398       InfoImage(vbmeta_image_path_));
399 
400   EXPECT_COMMAND(0,
401                  "./avbtool erase_footer"
402                  " --image %s",
403                  boot_path.value().c_str());
404 
405   // With no footer, 'avbtool info_image' should fail (exit status 1).
406   EXPECT_COMMAND(
407       1, "./avbtool info_image --image %s", boot_path.value().c_str());
408 
409   ops_.set_expected_public_key(
410       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
411 
412   AvbSlotVerifyData* slot_data = NULL;
413   const char* requested_partitions[] = {"boot", NULL};
414   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
415             avb_slot_verify(ops_.avb_ops(),
416                             requested_partitions,
417                             "_a",
418                             false /* allow_verification_error */,
419                             &slot_data));
420   EXPECT_NE(nullptr, slot_data);
421 
422   // Now verify the slot data. The vbmeta data should match our
423   // vbmeta_image_ member.
424   EXPECT_EQ(size_t(1), slot_data->num_vbmeta_images);
425   EXPECT_EQ("vbmeta", std::string(slot_data->vbmeta_images[0].partition_name));
426   EXPECT_EQ(slot_data->vbmeta_images[0].vbmeta_size, vbmeta_image_.size());
427   EXPECT_EQ(0,
428             memcmp(vbmeta_image_.data(),
429                    slot_data->vbmeta_images[0].vbmeta_data,
430                    slot_data->vbmeta_images[0].vbmeta_size));
431 
432   // The boot image data should match what is generated above with
433   // GenerateImage().
434   EXPECT_EQ(size_t(1), slot_data->num_loaded_partitions);
435   EXPECT_EQ("boot",
436             std::string(slot_data->loaded_partitions[0].partition_name));
437   EXPECT_EQ(boot_image_size, slot_data->loaded_partitions[0].data_size);
438   for (size_t n = 0; n < slot_data->loaded_partitions[0].data_size; n++) {
439     EXPECT_EQ(slot_data->loaded_partitions[0].data[n], uint8_t(n));
440   }
441 
442   // This should match the two cmdlines with a space (U+0020) between
443   // them and the $(ANDROID_SYSTEM_PARTUUID) and
444   // $(ANDROID_BOOT_PARTUUID) variables replaced.
445   EXPECT_EQ(
446       "cmdline in vbmeta 1234-fake-guid-for:boot_a cmdline in hash footer "
447       "1234-fake-guid-for:system_a "
448       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
449       "androidboot.vbmeta.avb_version=1.0 "
450       "androidboot.vbmeta.device_state=locked "
451       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1472 "
452       "androidboot.vbmeta.digest="
453       "34cdb59b955aa35d4da97701f304fabf7392eecca8c50ff1a0b7b6e1c9aaa1b8",
454       std::string(slot_data->cmdline));
455   EXPECT_EQ(4UL, slot_data->rollback_indexes[0]);
456   for (size_t n = 1; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
457     EXPECT_EQ(0UL, slot_data->rollback_indexes[n]);
458   }
459   avb_slot_verify_data_free(slot_data);
460 }
461 
TEST_F(AvbSlotVerifyTest,HashDescriptorInVBMetaCorruptBoot)462 TEST_F(AvbSlotVerifyTest, HashDescriptorInVBMetaCorruptBoot) {
463   size_t boot_partition_size = 16 * 1024 * 1024;
464   base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
465   const char* requested_partitions[] = {"boot", NULL};
466 
467   EXPECT_COMMAND(0,
468                  "./avbtool add_hash_footer"
469                  " --image %s"
470                  " --rollback_index 0"
471                  " --partition_name boot"
472                  " --partition_size %zd"
473                  " --salt deadbeef"
474                  " --internal_release_string \"\"",
475                  boot_path.value().c_str(),
476                  boot_partition_size);
477 
478   GenerateVBMetaImage("vbmeta_a.img",
479                       "SHA256_RSA2048",
480                       0,
481                       base::FilePath("test/data/testkey_rsa2048.pem"),
482                       base::StringPrintf("--include_descriptors_from_image %s"
483                                          " --internal_release_string \"\"",
484                                          boot_path.value().c_str()));
485 
486   EXPECT_COMMAND(0,
487                  "./avbtool erase_footer"
488                  " --image %s",
489                  boot_path.value().c_str());
490 
491   ops_.set_expected_public_key(
492       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
493 
494   // So far, so good.
495   AvbSlotVerifyData* slot_data = NULL;
496   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
497             avb_slot_verify(ops_.avb_ops(),
498                             requested_partitions,
499                             "_a",
500                             false /* allow_verification_error */,
501                             &slot_data));
502   EXPECT_NE(nullptr, slot_data);
503   avb_slot_verify_data_free(slot_data);
504 
505   // Now corrupt boot_a.img and expect verification error.
506   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
507   EXPECT_EQ(AVB_IO_RESULT_OK,
508             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
509                                                "boot_a",
510                                                1024 * 1024,  // offset: 1 MiB
511                                                sizeof corrupt_data,
512                                                corrupt_data));
513 
514   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
515             avb_slot_verify(ops_.avb_ops(),
516                             requested_partitions,
517                             "_a",
518                             false /* allow_verification_error */,
519                             &slot_data));
520   EXPECT_EQ(nullptr, slot_data);
521   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
522             avb_slot_verify(ops_.avb_ops(),
523                             requested_partitions,
524                             "_a",
525                             true /* allow_verification_error */,
526                             &slot_data));
527   EXPECT_NE(nullptr, slot_data);
528   avb_slot_verify_data_free(slot_data);
529 }
530 
TEST_F(AvbSlotVerifyTest,HashDescriptorInChainedPartition)531 TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartition) {
532   size_t boot_partition_size = 16 * 1024 * 1024;
533   const size_t boot_image_size = 5 * 1024 * 1024;
534   base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
535   const char* requested_partitions[] = {"boot", NULL};
536 
537   EXPECT_COMMAND(0,
538                  "./avbtool add_hash_footer"
539                  " --image %s"
540                  " --kernel_cmdline 'cmdline2 in hash footer'"
541                  " --rollback_index 12"
542                  " --partition_name boot"
543                  " --partition_size %zd"
544                  " --algorithm SHA256_RSA4096"
545                  " --key test/data/testkey_rsa4096.pem"
546                  " --salt deadbeef"
547                  " --internal_release_string \"\"",
548                  boot_path.value().c_str(),
549                  boot_partition_size);
550 
551   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
552   EXPECT_COMMAND(
553       0,
554       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
555       " --output %s",
556       pk_path.value().c_str());
557 
558   GenerateVBMetaImage(
559       "vbmeta_a.img",
560       "SHA256_RSA2048",
561       11,
562       base::FilePath("test/data/testkey_rsa2048.pem"),
563       base::StringPrintf("--chain_partition boot:1:%s"
564                          " --kernel_cmdline 'cmdline2 in vbmeta'"
565                          " --internal_release_string \"\"",
566                          pk_path.value().c_str()));
567 
568   EXPECT_EQ(
569       "Minimum libavb version:   1.0\n"
570       "Header Block:             256 bytes\n"
571       "Authentication Block:     320 bytes\n"
572       "Auxiliary Block:          1728 bytes\n"
573       "Algorithm:                SHA256_RSA2048\n"
574       "Rollback Index:           11\n"
575       "Flags:                    0\n"
576       "Release String:           ''\n"
577       "Descriptors:\n"
578       "    Chain Partition descriptor:\n"
579       "      Partition Name:          boot\n"
580       "      Rollback Index Location: 1\n"
581       "      Public key (sha1):       "
582       "2597c218aae470a130f61162feaae70afd97f011\n"
583       "    Kernel Cmdline descriptor:\n"
584       "      Flags:                 0\n"
585       "      Kernel Cmdline:        'cmdline2 in vbmeta'\n",
586       InfoImage(vbmeta_image_path_));
587 
588   EXPECT_EQ(
589       "Footer version:           1.0\n"
590       "Image size:               16777216 bytes\n"
591       "Original image size:      5242880 bytes\n"
592       "VBMeta offset:            5242880\n"
593       "VBMeta size:              2112 bytes\n"
594       "--\n"
595       "Minimum libavb version:   1.0\n"
596       "Header Block:             256 bytes\n"
597       "Authentication Block:     576 bytes\n"
598       "Auxiliary Block:          1280 bytes\n"
599       "Algorithm:                SHA256_RSA4096\n"
600       "Rollback Index:           12\n"
601       "Flags:                    0\n"
602       "Release String:           ''\n"
603       "Descriptors:\n"
604       "    Hash descriptor:\n"
605       "      Image Size:            5242880 bytes\n"
606       "      Hash Algorithm:        sha256\n"
607       "      Partition Name:        boot\n"
608       "      Salt:                  deadbeef\n"
609       "      Digest:                "
610       "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n"
611       "    Kernel Cmdline descriptor:\n"
612       "      Flags:                 0\n"
613       "      Kernel Cmdline:        'cmdline2 in hash footer'\n",
614       InfoImage(boot_path));
615 
616   ops_.set_expected_public_key(
617       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
618 
619   AvbSlotVerifyData* slot_data = NULL;
620   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
621             avb_slot_verify(ops_.avb_ops(),
622                             requested_partitions,
623                             "_a",
624                             false /* allow_verification_error */,
625                             &slot_data));
626   EXPECT_NE(nullptr, slot_data);
627 
628   // Now verify the slot data. We should have two vbmeta
629   // structs. Verify both of them. Note that the A/B suffix isn't
630   // appended.
631   EXPECT_EQ(size_t(2), slot_data->num_vbmeta_images);
632   EXPECT_EQ("vbmeta", std::string(slot_data->vbmeta_images[0].partition_name));
633   EXPECT_EQ(slot_data->vbmeta_images[0].vbmeta_size, vbmeta_image_.size());
634   EXPECT_EQ(0,
635             memcmp(vbmeta_image_.data(),
636                    slot_data->vbmeta_images[0].vbmeta_data,
637                    slot_data->vbmeta_images[0].vbmeta_size));
638   // And for the second vbmeta struct we check that the descriptors
639   // match the info_image output from above.
640   EXPECT_EQ("boot", std::string(slot_data->vbmeta_images[1].partition_name));
641   const AvbDescriptor** descriptors =
642       avb_descriptor_get_all(slot_data->vbmeta_images[1].vbmeta_data,
643                              slot_data->vbmeta_images[1].vbmeta_size,
644                              NULL);
645   EXPECT_NE(nullptr, descriptors);
646   AvbHashDescriptor hash_desc;
647   EXPECT_EQ(true,
648             avb_hash_descriptor_validate_and_byteswap(
649                 ((AvbHashDescriptor*)descriptors[0]), &hash_desc));
650   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
651                             sizeof(AvbHashDescriptor);
652   uint64_t o = 0;
653   EXPECT_EQ("boot",
654             std::string(reinterpret_cast<const char*>(desc_end + o),
655                         hash_desc.partition_name_len));
656   o += hash_desc.partition_name_len;
657   EXPECT_EQ("deadbeef", mem_to_hexstring(desc_end + o, hash_desc.salt_len));
658   o += hash_desc.salt_len;
659   EXPECT_EQ("184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d",
660             mem_to_hexstring(desc_end + o, hash_desc.digest_len));
661   AvbKernelCmdlineDescriptor cmdline_desc;
662   EXPECT_EQ(true,
663             avb_kernel_cmdline_descriptor_validate_and_byteswap(
664                 ((AvbKernelCmdlineDescriptor*)descriptors[1]), &cmdline_desc));
665   desc_end = reinterpret_cast<const uint8_t*>(descriptors[1]) +
666              sizeof(AvbKernelCmdlineDescriptor);
667   EXPECT_EQ("cmdline2 in hash footer",
668             std::string(reinterpret_cast<const char*>(desc_end),
669                         cmdline_desc.kernel_cmdline_length));
670   avb_free(descriptors);
671 
672   // The boot image data should match what is generated above with
673   // GenerateImage().
674   EXPECT_EQ(size_t(1), slot_data->num_loaded_partitions);
675   EXPECT_EQ("boot",
676             std::string(slot_data->loaded_partitions[0].partition_name));
677   EXPECT_EQ(boot_image_size, slot_data->loaded_partitions[0].data_size);
678   for (size_t n = 0; n < slot_data->loaded_partitions[0].data_size; n++) {
679     EXPECT_EQ(slot_data->loaded_partitions[0].data[n], uint8_t(n));
680   }
681 
682   // This should match the two cmdlines with a space (U+0020) between them.
683   EXPECT_EQ(
684       "cmdline2 in hash footer cmdline2 in vbmeta "
685       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
686       "androidboot.vbmeta.avb_version=1.0 "
687       "androidboot.vbmeta.device_state=locked "
688       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=4416 "
689       "androidboot.vbmeta.digest="
690       "4a45faa9adfeb94e9154fe682c11fef1a1a3d829b67cbf1a12ac7f0aa4f8e2e4",
691       std::string(slot_data->cmdline));
692   EXPECT_EQ(11UL, slot_data->rollback_indexes[0]);
693   EXPECT_EQ(12UL, slot_data->rollback_indexes[1]);
694   for (size_t n = 2; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
695     EXPECT_EQ(0UL, slot_data->rollback_indexes[n]);
696   }
697   avb_slot_verify_data_free(slot_data);
698 }
699 
TEST_F(AvbSlotVerifyTest,HashDescriptorInChainedPartitionCorruptBoot)700 TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartitionCorruptBoot) {
701   size_t boot_partition_size = 16 * 1024 * 1024;
702   base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
703   const char* requested_partitions[] = {"boot", NULL};
704 
705   EXPECT_COMMAND(0,
706                  "./avbtool add_hash_footer"
707                  " --image %s"
708                  " --rollback_index 0"
709                  " --partition_name boot"
710                  " --partition_size %zd"
711                  " --algorithm SHA256_RSA4096"
712                  " --key test/data/testkey_rsa4096.pem"
713                  " --salt deadbeef"
714                  " --internal_release_string \"\"",
715                  boot_path.value().c_str(),
716                  boot_partition_size);
717 
718   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
719   EXPECT_COMMAND(
720       0,
721       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
722       " --output %s",
723       pk_path.value().c_str());
724 
725   GenerateVBMetaImage("vbmeta_a.img",
726                       "SHA256_RSA2048",
727                       0,
728                       base::FilePath("test/data/testkey_rsa2048.pem"),
729                       base::StringPrintf("--chain_partition boot:1:%s"
730                                          " --internal_release_string \"\"",
731                                          pk_path.value().c_str()));
732 
733   ops_.set_expected_public_key(
734       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
735 
736   AvbSlotVerifyData* slot_data = NULL;
737   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
738             avb_slot_verify(ops_.avb_ops(),
739                             requested_partitions,
740                             "_a",
741                             false /* allow_verification_error */,
742                             &slot_data));
743   EXPECT_NE(nullptr, slot_data);
744   avb_slot_verify_data_free(slot_data);
745 
746   // Now corrupt boot_a.img and expect verification error.
747   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
748   EXPECT_EQ(AVB_IO_RESULT_OK,
749             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
750                                                "boot_a",
751                                                1024 * 1024,  // offset: 1 MiB
752                                                sizeof corrupt_data,
753                                                corrupt_data));
754 
755   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
756             avb_slot_verify(ops_.avb_ops(),
757                             requested_partitions,
758                             "_a",
759                             false /* allow_verification_error */,
760                             &slot_data));
761   EXPECT_EQ(nullptr, slot_data);
762   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
763             avb_slot_verify(ops_.avb_ops(),
764                             requested_partitions,
765                             "_a",
766                             true /* allow_verification_error */,
767                             &slot_data));
768   EXPECT_NE(nullptr, slot_data);
769   avb_slot_verify_data_free(slot_data);
770 }
771 
TEST_F(AvbSlotVerifyTest,HashDescriptorInChainedPartitionKeyMismatch)772 TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartitionKeyMismatch) {
773   size_t boot_partition_size = 16 * 1024 * 1024;
774   base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
775   const char* requested_partitions[] = {"boot", NULL};
776 
777   // Use different key to sign vbmeta in boot_a (we use the 8192 bit
778   // key) than what's in the chained partition descriptor (which is
779   // the 4096 bit key) and expect
780   // AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED.
781 
782   EXPECT_COMMAND(0,
783                  "./avbtool add_hash_footer"
784                  " --image %s"
785                  " --rollback_index 0"
786                  " --partition_name boot"
787                  " --partition_size %zd"
788                  " --algorithm SHA256_RSA8192"
789                  " --key test/data/testkey_rsa8192.pem"
790                  " --salt deadbeef"
791                  " --internal_release_string \"\"",
792                  boot_path.value().c_str(),
793                  boot_partition_size);
794 
795   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
796   EXPECT_COMMAND(
797       0,
798       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
799       " --output %s",
800       pk_path.value().c_str());
801 
802   GenerateVBMetaImage("vbmeta_a.img",
803                       "SHA256_RSA2048",
804                       0,
805                       base::FilePath("test/data/testkey_rsa2048.pem"),
806                       base::StringPrintf("--chain_partition boot:1:%s"
807                                          " --internal_release_string \"\"",
808                                          pk_path.value().c_str()));
809 
810   ops_.set_expected_public_key(
811       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
812 
813   AvbSlotVerifyData* slot_data = NULL;
814   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
815             avb_slot_verify(ops_.avb_ops(),
816                             requested_partitions,
817                             "_a",
818                             false /* allow_verification_error */,
819                             &slot_data));
820   EXPECT_EQ(nullptr, slot_data);
821   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
822             avb_slot_verify(ops_.avb_ops(),
823                             requested_partitions,
824                             "_a",
825                             true /* allow_verification_error */,
826                             &slot_data));
827   EXPECT_NE(nullptr, slot_data);
828   avb_slot_verify_data_free(slot_data);
829 }
830 
TEST_F(AvbSlotVerifyTest,HashDescriptorInChainedPartitionRollbackIndexFail)831 TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartitionRollbackIndexFail) {
832   size_t boot_partition_size = 16 * 1024 * 1024;
833   base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
834   const char* requested_partitions[] = {"boot", NULL};
835 
836   EXPECT_COMMAND(0,
837                  "./avbtool add_hash_footer"
838                  " --image %s"
839                  " --rollback_index 10"
840                  " --partition_name boot"
841                  " --partition_size %zd"
842                  " --algorithm SHA256_RSA4096"
843                  " --key test/data/testkey_rsa4096.pem"
844                  " --salt deadbeef"
845                  " --internal_release_string \"\"",
846                  boot_path.value().c_str(),
847                  boot_partition_size);
848 
849   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
850   EXPECT_COMMAND(
851       0,
852       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
853       " --output %s",
854       pk_path.value().c_str());
855 
856   GenerateVBMetaImage("vbmeta_a.img",
857                       "SHA256_RSA2048",
858                       110,
859                       base::FilePath("test/data/testkey_rsa2048.pem"),
860                       base::StringPrintf("--chain_partition boot:1:%s"
861                                          " --internal_release_string \"\"",
862                                          pk_path.value().c_str()));
863 
864   ops_.set_expected_public_key(
865       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
866 
867   AvbSlotVerifyData* slot_data = NULL;
868 
869   // Both images (vbmeta_a and boot_a) have rollback index 10 and 11
870   // so it should work if the stored rollback indexes are 0 and 0.
871   ops_.set_stored_rollback_indexes({{0, 0}, {1, 0}});
872   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
873             avb_slot_verify(ops_.avb_ops(),
874                             requested_partitions,
875                             "_a",
876                             false /* allow_verification_error */,
877                             &slot_data));
878   EXPECT_NE(nullptr, slot_data);
879   avb_slot_verify_data_free(slot_data);
880 
881   // Check failure if we set the stored rollback index of the chained
882   // partition to 20 (see AvbSlotVerifyTest.RollbackIndex above
883   // where we test rollback index checks for the vbmeta partition).
884   ops_.set_stored_rollback_indexes({{0, 0}, {1, 20}});
885   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
886             avb_slot_verify(ops_.avb_ops(),
887                             requested_partitions,
888                             "_a",
889                             false /* allow_verification_error */,
890                             &slot_data));
891   EXPECT_EQ(nullptr, slot_data);
892   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
893             avb_slot_verify(ops_.avb_ops(),
894                             requested_partitions,
895                             "_a",
896                             true /* allow_verification_error */,
897                             &slot_data));
898   EXPECT_NE(nullptr, slot_data);
899   avb_slot_verify_data_free(slot_data);
900 
901   // Check failure if there is no rollback index slot 1 - in that case
902   // we expect an I/O error since ops->read_rollback_index() will
903   // fail.
904   ops_.set_stored_rollback_indexes({{0, 0}});
905   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_IO,
906             avb_slot_verify(ops_.avb_ops(),
907                             requested_partitions,
908                             "_a",
909                             false /* allow_verification_error */,
910                             &slot_data));
911   EXPECT_EQ(nullptr, slot_data);
912 }
913 
TEST_F(AvbSlotVerifyTest,ChainedPartitionNoSlots)914 TEST_F(AvbSlotVerifyTest, ChainedPartitionNoSlots) {
915   size_t boot_partition_size = 16 * 1024 * 1024;
916   const size_t boot_image_size = 5 * 1024 * 1024;
917   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
918   const char* requested_partitions[] = {"boot", NULL};
919 
920   EXPECT_COMMAND(0,
921                  "./avbtool add_hash_footer"
922                  " --image %s"
923                  " --kernel_cmdline 'cmdline2 in hash footer'"
924                  " --rollback_index 12"
925                  " --partition_name boot"
926                  " --partition_size %zd"
927                  " --algorithm SHA256_RSA4096"
928                  " --key test/data/testkey_rsa4096.pem"
929                  " --salt deadbeef"
930                  " --internal_release_string \"\"",
931                  boot_path.value().c_str(),
932                  boot_partition_size);
933 
934   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
935   EXPECT_COMMAND(
936       0,
937       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
938       " --output %s",
939       pk_path.value().c_str());
940 
941   GenerateVBMetaImage(
942       "vbmeta.img",
943       "SHA256_RSA2048",
944       11,
945       base::FilePath("test/data/testkey_rsa2048.pem"),
946       base::StringPrintf("--chain_partition boot:1:%s"
947                          " --kernel_cmdline 'cmdline2 in vbmeta'"
948                          " --internal_release_string \"\"",
949                          pk_path.value().c_str()));
950 
951   EXPECT_EQ(
952       "Minimum libavb version:   1.0\n"
953       "Header Block:             256 bytes\n"
954       "Authentication Block:     320 bytes\n"
955       "Auxiliary Block:          1728 bytes\n"
956       "Algorithm:                SHA256_RSA2048\n"
957       "Rollback Index:           11\n"
958       "Flags:                    0\n"
959       "Release String:           ''\n"
960       "Descriptors:\n"
961       "    Chain Partition descriptor:\n"
962       "      Partition Name:          boot\n"
963       "      Rollback Index Location: 1\n"
964       "      Public key (sha1):       "
965       "2597c218aae470a130f61162feaae70afd97f011\n"
966       "    Kernel Cmdline descriptor:\n"
967       "      Flags:                 0\n"
968       "      Kernel Cmdline:        'cmdline2 in vbmeta'\n",
969       InfoImage(vbmeta_image_path_));
970 
971   ops_.set_expected_public_key(
972       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
973 
974   AvbSlotVerifyData* slot_data = NULL;
975   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
976             avb_slot_verify(ops_.avb_ops(),
977                             requested_partitions,
978                             "",
979                             false /* allow_verification_error */,
980                             &slot_data));
981   EXPECT_NE(nullptr, slot_data);
982 
983   // Now verify the slot data. The first vbmeta data should match our
984   // vbmeta_image_ member and the second one should be for the 'boot'
985   // partition.
986   EXPECT_EQ(size_t(2), slot_data->num_vbmeta_images);
987   EXPECT_EQ("vbmeta", std::string(slot_data->vbmeta_images[0].partition_name));
988   EXPECT_EQ(slot_data->vbmeta_images[0].vbmeta_size, vbmeta_image_.size());
989   EXPECT_EQ(0,
990             memcmp(vbmeta_image_.data(),
991                    slot_data->vbmeta_images[0].vbmeta_data,
992                    slot_data->vbmeta_images[0].vbmeta_size));
993   EXPECT_EQ("boot", std::string(slot_data->vbmeta_images[1].partition_name));
994 
995   // The boot image data should match what is generated above with
996   // GenerateImage().
997   EXPECT_EQ(size_t(1), slot_data->num_loaded_partitions);
998   EXPECT_EQ("boot",
999             std::string(slot_data->loaded_partitions[0].partition_name));
1000   EXPECT_EQ(boot_image_size, slot_data->loaded_partitions[0].data_size);
1001   for (size_t n = 0; n < slot_data->loaded_partitions[0].data_size; n++) {
1002     EXPECT_EQ(slot_data->loaded_partitions[0].data[n], uint8_t(n));
1003   }
1004 
1005   // This should match the two cmdlines with a space (U+0020) between
1006   // them.
1007   EXPECT_EQ(
1008       "cmdline2 in hash footer cmdline2 in vbmeta "
1009       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta "
1010       "androidboot.vbmeta.avb_version=1.0 "
1011       "androidboot.vbmeta.device_state=locked "
1012       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=4416 "
1013       "androidboot.vbmeta.digest="
1014       "4a45faa9adfeb94e9154fe682c11fef1a1a3d829b67cbf1a12ac7f0aa4f8e2e4",
1015       std::string(slot_data->cmdline));
1016   EXPECT_EQ(11UL, slot_data->rollback_indexes[0]);
1017   EXPECT_EQ(12UL, slot_data->rollback_indexes[1]);
1018   for (size_t n = 2; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
1019     EXPECT_EQ(0UL, slot_data->rollback_indexes[n]);
1020   }
1021   avb_slot_verify_data_free(slot_data);
1022 }
1023 
TEST_F(AvbSlotVerifyTest,PartitionsOtherThanBoot)1024 TEST_F(AvbSlotVerifyTest, PartitionsOtherThanBoot) {
1025   const size_t foo_partition_size = 16 * 1024 * 1024;
1026   const size_t bar_partition_size = 32 * 1024 * 1024;
1027   const size_t foo_image_size = 5 * 1024 * 1024;
1028   const size_t bar_image_size = 10 * 1024 * 1024;
1029   base::FilePath foo_path = GenerateImage("foo_a.img", foo_image_size);
1030   base::FilePath bar_path = GenerateImage("bar_a.img", bar_image_size);
1031 
1032   EXPECT_COMMAND(0,
1033                  "./avbtool add_hash_footer"
1034                  " --image %s"
1035                  " --partition_name foo"
1036                  " --partition_size %zd"
1037                  " --salt deadbeef"
1038                  " --internal_release_string \"\"",
1039                  foo_path.value().c_str(),
1040                  foo_partition_size);
1041 
1042   EXPECT_COMMAND(0,
1043                  "./avbtool add_hash_footer"
1044                  " --image %s"
1045                  " --partition_name bar"
1046                  " --partition_size %zd"
1047                  " --salt deadbeef"
1048                  " --internal_release_string \"\"",
1049                  bar_path.value().c_str(),
1050                  bar_partition_size);
1051 
1052   GenerateVBMetaImage("vbmeta_a.img",
1053                       "SHA256_RSA2048",
1054                       4,
1055                       base::FilePath("test/data/testkey_rsa2048.pem"),
1056                       base::StringPrintf("--include_descriptors_from_image %s"
1057                                          " --include_descriptors_from_image %s"
1058                                          " --internal_release_string \"\"",
1059                                          foo_path.value().c_str(),
1060                                          bar_path.value().c_str()));
1061 
1062   EXPECT_EQ(
1063       "Minimum libavb version:   1.0\n"
1064       "Header Block:             256 bytes\n"
1065       "Authentication Block:     320 bytes\n"
1066       "Auxiliary Block:          896 bytes\n"
1067       "Algorithm:                SHA256_RSA2048\n"
1068       "Rollback Index:           4\n"
1069       "Flags:                    0\n"
1070       "Release String:           ''\n"
1071       "Descriptors:\n"
1072       "    Hash descriptor:\n"
1073       "      Image Size:            5242880 bytes\n"
1074       "      Hash Algorithm:        sha256\n"
1075       "      Partition Name:        foo\n"
1076       "      Salt:                  deadbeef\n"
1077       "      Digest:                "
1078       "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n"
1079       "    Hash descriptor:\n"
1080       "      Image Size:            10485760 bytes\n"
1081       "      Hash Algorithm:        sha256\n"
1082       "      Partition Name:        bar\n"
1083       "      Salt:                  deadbeef\n"
1084       "      Digest:                "
1085       "baea4bbd261d0edf4d1fe5e6e5a36976c291eeba66b6a46fa81dba691327a727\n",
1086       InfoImage(vbmeta_image_path_));
1087 
1088   ops_.set_expected_public_key(
1089       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1090 
1091   AvbSlotVerifyData* slot_data = NULL;
1092   const char* requested_partitions[] = {"foo", "bar", NULL};
1093   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1094             avb_slot_verify(ops_.avb_ops(),
1095                             requested_partitions,
1096                             "_a",
1097                             false /* allow_verification_error */,
1098                             &slot_data));
1099   EXPECT_NE(nullptr, slot_data);
1100 
1101   // Now verify the slot data. The vbmeta data should match our
1102   // vbmeta_image_ member.
1103   EXPECT_EQ(size_t(1), slot_data->num_vbmeta_images);
1104   EXPECT_EQ("vbmeta", std::string(slot_data->vbmeta_images[0].partition_name));
1105   EXPECT_EQ(slot_data->vbmeta_images[0].vbmeta_size, vbmeta_image_.size());
1106   EXPECT_EQ(0,
1107             memcmp(vbmeta_image_.data(),
1108                    slot_data->vbmeta_images[0].vbmeta_data,
1109                    slot_data->vbmeta_images[0].vbmeta_size));
1110 
1111   // The 'foo' and 'bar' image data should match what is generated
1112   // above with GenerateImage().
1113   EXPECT_EQ(size_t(2), slot_data->num_loaded_partitions);
1114   EXPECT_EQ("foo", std::string(slot_data->loaded_partitions[0].partition_name));
1115   EXPECT_EQ(foo_image_size, slot_data->loaded_partitions[0].data_size);
1116   for (size_t n = 0; n < slot_data->loaded_partitions[0].data_size; n++) {
1117     EXPECT_EQ(slot_data->loaded_partitions[0].data[n], uint8_t(n));
1118   }
1119   EXPECT_EQ("bar", std::string(slot_data->loaded_partitions[1].partition_name));
1120   EXPECT_EQ(bar_image_size, slot_data->loaded_partitions[1].data_size);
1121   for (size_t n = 0; n < slot_data->loaded_partitions[1].data_size; n++) {
1122     EXPECT_EQ(slot_data->loaded_partitions[1].data[n], uint8_t(n));
1123   }
1124 
1125   avb_slot_verify_data_free(slot_data);
1126 }
1127 
TEST_F(AvbSlotVerifyTest,PublicKeyMetadata)1128 TEST_F(AvbSlotVerifyTest, PublicKeyMetadata) {
1129   base::FilePath md_path = GenerateImage("md.bin", 1536);
1130 
1131   GenerateVBMetaImage("vbmeta_a.img",
1132                       "SHA256_RSA2048",
1133                       0,
1134                       base::FilePath("test/data/testkey_rsa2048.pem"),
1135                       base::StringPrintf("--public_key_metadata %s"
1136                                          " --internal_release_string \"\"",
1137                                          md_path.value().c_str()));
1138 
1139   ops_.set_expected_public_key(
1140       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1141 
1142   std::string md_data;
1143   ASSERT_TRUE(base::ReadFileToString(md_path, &md_data));
1144   ops_.set_expected_public_key_metadata(md_data);
1145 
1146   AvbSlotVerifyData* slot_data = NULL;
1147   const char* requested_partitions[] = {"boot", NULL};
1148   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1149             avb_slot_verify(ops_.avb_ops(),
1150                             requested_partitions,
1151                             "_a",
1152                             false /* allow_verification_error */,
1153                             &slot_data));
1154   EXPECT_NE(nullptr, slot_data);
1155   EXPECT_EQ(
1156       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
1157       "androidboot.vbmeta.avb_version=1.0 "
1158       "androidboot.vbmeta.device_state=locked "
1159       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=2688 "
1160       "androidboot.vbmeta.digest="
1161       "5edcaa54f40382ee6a2fc3b86cdf383348b35ed07955e83ea32d84b69a97eaa0",
1162       std::string(slot_data->cmdline));
1163   avb_slot_verify_data_free(slot_data);
1164 }
1165 
CmdlineWithHashtreeVerification(bool hashtree_verification_on)1166 void AvbSlotVerifyTest::CmdlineWithHashtreeVerification(
1167     bool hashtree_verification_on) {
1168   const size_t rootfs_size = 1028 * 1024;
1169   const size_t partition_size = 1536 * 1024;
1170 
1171   // Generate a 1028 KiB file with known content.
1172   std::vector<uint8_t> rootfs;
1173   rootfs.resize(rootfs_size);
1174   for (size_t n = 0; n < rootfs_size; n++)
1175     rootfs[n] = uint8_t(n);
1176   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
1177   EXPECT_EQ(rootfs_size,
1178             static_cast<const size_t>(
1179                 base::WriteFile(rootfs_path,
1180                                 reinterpret_cast<const char*>(rootfs.data()),
1181                                 rootfs.size())));
1182 
1183   EXPECT_COMMAND(0,
1184                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1185                  "--partition_size %d --partition_name foobar "
1186                  "--algorithm SHA256_RSA2048 "
1187                  "--key test/data/testkey_rsa2048.pem "
1188                  "--internal_release_string \"\"",
1189                  rootfs_path.value().c_str(),
1190                  (int)partition_size);
1191 
1192   // Check that we correctly generate dm-verity kernel cmdline
1193   // snippets, if requested.
1194   GenerateVBMetaImage(
1195       "vbmeta_a.img",
1196       "SHA256_RSA2048",
1197       4,
1198       base::FilePath("test/data/testkey_rsa2048.pem"),
1199       base::StringPrintf("--setup_rootfs_from_kernel %s "
1200                          "--kernel_cmdline should_be_in_both=1 "
1201                          "--algorithm SHA256_RSA2048 "
1202                          "--flags %d "
1203                          "--internal_release_string \"\"",
1204                          rootfs_path.value().c_str(),
1205                          hashtree_verification_on
1206                              ? 0
1207                              : AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED));
1208 
1209   EXPECT_EQ(
1210       base::StringPrintf(
1211           "Minimum libavb version:   1.0\n"
1212           "Header Block:             256 bytes\n"
1213           "Authentication Block:     320 bytes\n"
1214           "Auxiliary Block:          960 bytes\n"
1215           "Algorithm:                SHA256_RSA2048\n"
1216           "Rollback Index:           4\n"
1217           "Flags:                    %d\n"
1218           "Release String:           ''\n"
1219           "Descriptors:\n"
1220           "    Kernel Cmdline descriptor:\n"
1221           "      Flags:                 1\n"
1222           "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity "
1223           "1 PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1224           "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) 4096 4096 257 257 sha1 "
1225           "e811611467dcd6e8dc4324e45f706c2bdd51db67 d00df00d 2 "
1226           "restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0'\n"
1227           "    Kernel Cmdline descriptor:\n"
1228           "      Flags:                 2\n"
1229           "      Kernel Cmdline:        "
1230           "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n"
1231           "    Kernel Cmdline descriptor:\n"
1232           "      Flags:                 0\n"
1233           "      Kernel Cmdline:        'should_be_in_both=1'\n",
1234           hashtree_verification_on ? 0
1235                                    : AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED),
1236       InfoImage(vbmeta_image_path_));
1237 
1238   ops_.set_expected_public_key(
1239       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1240 
1241   // Check that avb_slot_verify() picks the cmdline decsriptors based
1242   // on their flags value.
1243   AvbSlotVerifyData* slot_data = NULL;
1244   const char* requested_partitions[] = {"boot", NULL};
1245   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1246             avb_slot_verify(ops_.avb_ops(),
1247                             requested_partitions,
1248                             "_a",
1249                             false /* allow_verification_error */,
1250                             &slot_data));
1251   EXPECT_NE(nullptr, slot_data);
1252   if (hashtree_verification_on) {
1253     EXPECT_EQ(
1254         "dm=\"1 vroot none ro 1,0 2056 verity 1 "
1255         "PARTUUID=1234-fake-guid-for:system_a "
1256         "PARTUUID=1234-fake-guid-for:system_a 4096 4096 257 257 sha1 "
1257         "e811611467dcd6e8dc4324e45f706c2bdd51db67 d00df00d 2 "
1258         "restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0 "
1259         "should_be_in_both=1 "
1260         "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
1261         "androidboot.vbmeta.avb_version=1.0 "
1262         "androidboot.vbmeta.device_state=locked "
1263         "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1536 "
1264         "androidboot.vbmeta.digest="
1265         "51ea1638d8cc19a7a15b2bade22d155fb5150a6e376171ea1a89b7d6c89d6f17",
1266         std::string(slot_data->cmdline));
1267   } else {
1268     EXPECT_EQ(
1269         "root=PARTUUID=1234-fake-guid-for:system_a should_be_in_both=1 "
1270         "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:vbmeta_a "
1271         "androidboot.vbmeta.avb_version=1.0 "
1272         "androidboot.vbmeta.device_state=locked "
1273         "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1536 "
1274         "androidboot.vbmeta.digest="
1275         "877daa21c04df1d9e1776bc6169c98de947ce44b1b34b545021bb3f34e287da6",
1276         std::string(slot_data->cmdline));
1277   }
1278   avb_slot_verify_data_free(slot_data);
1279 }
1280 
TEST_F(AvbSlotVerifyTest,CmdlineWithHashtreeVerificationOff)1281 TEST_F(AvbSlotVerifyTest, CmdlineWithHashtreeVerificationOff) {
1282   CmdlineWithHashtreeVerification(false);
1283 }
1284 
TEST_F(AvbSlotVerifyTest,CmdlineWithHashtreeVerificationOn)1285 TEST_F(AvbSlotVerifyTest, CmdlineWithHashtreeVerificationOn) {
1286   CmdlineWithHashtreeVerification(true);
1287 }
1288 
1289 // In the event that there's no vbmeta partition, we treat the vbmeta
1290 // struct from 'boot' as the top-level partition. Check that this
1291 // works.
TEST_F(AvbSlotVerifyTest,NoVBMetaPartition)1292 TEST_F(AvbSlotVerifyTest, NoVBMetaPartition) {
1293   const size_t MiB = 1024 * 1024;
1294   const size_t boot_size = 6 * MiB;
1295   const size_t boot_part_size = 8 * MiB;
1296   const size_t system_size = 16 * MiB;
1297   const size_t system_part_size = 32 * MiB;
1298   const size_t foobar_size = 8 * MiB;
1299   const size_t foobar_part_size = 16 * MiB;
1300   const size_t bazboo_size = 4 * MiB;
1301   const size_t bazboo_part_size = 8 * MiB;
1302   base::FilePath boot_path = GenerateImage("boot.img", boot_size);
1303   base::FilePath system_path = GenerateImage("system.img", system_size);
1304   base::FilePath foobar_path = GenerateImage("foobar.img", foobar_size);
1305   base::FilePath bazboo_path = GenerateImage("bazboo.img", bazboo_size);
1306 
1307   EXPECT_COMMAND(0,
1308                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1309                  "--partition_size %d --partition_name system "
1310                  "--algorithm SHA256_RSA2048 "
1311                  "--key test/data/testkey_rsa2048.pem "
1312                  "--internal_release_string \"\"",
1313                  system_path.value().c_str(),
1314                  (int)system_part_size);
1315 
1316   EXPECT_COMMAND(0,
1317                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1318                  "--partition_size %d --partition_name foobar "
1319                  "--algorithm SHA256_RSA2048 "
1320                  "--key test/data/testkey_rsa2048.pem "
1321                  "--internal_release_string \"\"",
1322                  foobar_path.value().c_str(),
1323                  (int)foobar_part_size);
1324 
1325   EXPECT_COMMAND(0,
1326                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1327                  "--partition_size %d --partition_name bazboo "
1328                  "--algorithm SHA512_RSA4096 "
1329                  "--key test/data/testkey_rsa4096.pem "
1330                  "--internal_release_string \"\"",
1331                  bazboo_path.value().c_str(),
1332                  (int)bazboo_part_size);
1333 
1334   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
1335   EXPECT_COMMAND(
1336       0,
1337       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
1338       " --output %s",
1339       pk_path.value().c_str());
1340 
1341   // Explicitly pass "--flags 2147483648" (i.e. 1<<31) to check that
1342   // boot.img is treated as top-level. Note the corresponding "Flags:"
1343   // field below in the avbtool info_image output.
1344   EXPECT_COMMAND(0,
1345                  "./avbtool add_hash_footer --salt d00df00d "
1346                  "--hash_algorithm sha256 --image %s "
1347                  "--partition_size %d --partition_name boot "
1348                  "--algorithm SHA256_RSA2048 "
1349                  "--key test/data/testkey_rsa2048.pem "
1350                  "--internal_release_string \"\" "
1351                  "--include_descriptors_from_image %s "
1352                  "--include_descriptors_from_image %s "
1353                  "--setup_rootfs_from_kernel %s "
1354                  "--chain_partition bazboo:1:%s "
1355                  "--flags 2147483648",
1356                  boot_path.value().c_str(),
1357                  (int)boot_part_size,
1358                  system_path.value().c_str(),
1359                  foobar_path.value().c_str(),
1360                  system_path.value().c_str(),
1361                  pk_path.value().c_str());
1362 
1363   ASSERT_EQ(
1364       "Footer version:           1.0\n"
1365       "Image size:               8388608 bytes\n"
1366       "Original image size:      6291456 bytes\n"
1367       "VBMeta offset:            6291456\n"
1368       "VBMeta size:              3200 bytes\n"
1369       "--\n"
1370       "Minimum libavb version:   1.0\n"
1371       "Header Block:             256 bytes\n"
1372       "Authentication Block:     320 bytes\n"
1373       "Auxiliary Block:          2624 bytes\n"
1374       "Algorithm:                SHA256_RSA2048\n"
1375       "Rollback Index:           0\n"
1376       "Flags:                    2147483648\n"
1377       "Release String:           ''\n"
1378       "Descriptors:\n"
1379       "    Hash descriptor:\n"
1380       "      Image Size:            6291456 bytes\n"
1381       "      Hash Algorithm:        sha256\n"
1382       "      Partition Name:        boot\n"
1383       "      Salt:                  d00df00d\n"
1384       "      Digest:                "
1385       "4c109399b20e476bab15363bff55740add83e1c1e97e0b132f5c713ddd8c7868\n"
1386       "    Chain Partition descriptor:\n"
1387       "      Partition Name:          bazboo\n"
1388       "      Rollback Index Location: 1\n"
1389       "      Public key (sha1):       "
1390       "2597c218aae470a130f61162feaae70afd97f011\n"
1391       "    Kernel Cmdline descriptor:\n"
1392       "      Flags:                 1\n"
1393       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 32768 verity 1 "
1394       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1395       "4096 4096 4096 4096 sha1 c9ffc3bfae5000269a55a56621547fd1fcf819df "
1396       "d00df00d 2 restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0'\n"
1397       "    Kernel Cmdline descriptor:\n"
1398       "      Flags:                 2\n"
1399       "      Kernel Cmdline:        "
1400       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n"
1401       "    Hashtree descriptor:\n"
1402       "      Version of dm-verity:  1\n"
1403       "      Image Size:            16777216 bytes\n"
1404       "      Tree Offset:           16777216\n"
1405       "      Tree Size:             135168 bytes\n"
1406       "      Data Block Size:       4096 bytes\n"
1407       "      Hash Block Size:       4096 bytes\n"
1408       "      FEC num roots:         0\n"
1409       "      FEC offset:            0\n"
1410       "      FEC size:              0 bytes\n"
1411       "      Hash Algorithm:        sha1\n"
1412       "      Partition Name:        system\n"
1413       "      Salt:                  d00df00d\n"
1414       "      Root Digest:           c9ffc3bfae5000269a55a56621547fd1fcf819df\n"
1415       "    Hashtree descriptor:\n"
1416       "      Version of dm-verity:  1\n"
1417       "      Image Size:            8388608 bytes\n"
1418       "      Tree Offset:           8388608\n"
1419       "      Tree Size:             69632 bytes\n"
1420       "      Data Block Size:       4096 bytes\n"
1421       "      Hash Block Size:       4096 bytes\n"
1422       "      FEC num roots:         0\n"
1423       "      FEC offset:            0\n"
1424       "      FEC size:              0 bytes\n"
1425       "      Hash Algorithm:        sha1\n"
1426       "      Partition Name:        foobar\n"
1427       "      Salt:                  d00df00d\n"
1428       "      Root Digest:           d52d93c988d336a79abe1c05240ae9a79a9b7d61\n",
1429       InfoImage(boot_path));
1430 
1431   ops_.set_expected_public_key(
1432       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1433 
1434   // Now check that libavb will fall back to reading from 'boot'
1435   // instead of 'vbmeta' when encountering
1436   // AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION on trying to read from
1437   // 'vbmeta'.
1438   AvbSlotVerifyData* slot_data = NULL;
1439   const char* requested_partitions[] = {"boot", NULL};
1440   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
1441             avb_slot_verify(ops_.avb_ops(),
1442                             requested_partitions,
1443                             "",
1444                             false /* allow_verification_error */,
1445                             &slot_data));
1446   EXPECT_NE(nullptr, slot_data);
1447   // Note 'boot' in the value androidboot.vbmeta.device since we've
1448   // read from 'boot' and not 'vbmeta'.
1449   EXPECT_EQ(
1450       "dm=\"1 vroot none ro 1,0 32768 verity 1 "
1451       "PARTUUID=1234-fake-guid-for:system PARTUUID=1234-fake-guid-for:system "
1452       "4096 4096 4096 4096 sha1 c9ffc3bfae5000269a55a56621547fd1fcf819df "
1453       "d00df00d 2 restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0 "
1454       "androidboot.vbmeta.device=PARTUUID=1234-fake-guid-for:boot "
1455       "androidboot.vbmeta.avb_version=1.0 "
1456       "androidboot.vbmeta.device_state=locked "
1457       "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=5312 "
1458       "androidboot.vbmeta.digest="
1459       "87bf39949a560f93d54aa0a5e9d158439110141246e40fb103f131633a3ca456",
1460       std::string(slot_data->cmdline));
1461   avb_slot_verify_data_free(slot_data);
1462 }
1463 
1464 // Check that non-zero flags in chained partition are caught in
1465 // avb_slot_verify().
TEST_F(AvbSlotVerifyTest,ChainedPartitionEnforceFlagsZero)1466 TEST_F(AvbSlotVerifyTest, ChainedPartitionEnforceFlagsZero) {
1467   size_t boot_partition_size = 16 * 1024 * 1024;
1468   const size_t boot_image_size = 5 * 1024 * 1024;
1469   base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
1470   const char* requested_partitions[] = {"boot", NULL};
1471 
1472   EXPECT_COMMAND(0,
1473                  "./avbtool add_hash_footer"
1474                  " --image %s"
1475                  " --kernel_cmdline 'cmdline2 in hash footer'"
1476                  " --rollback_index 12"
1477                  " --partition_name boot"
1478                  " --partition_size %zd"
1479                  " --algorithm SHA256_RSA4096"
1480                  " --key test/data/testkey_rsa4096.pem"
1481                  " --salt deadbeef"
1482                  " --flags 1"
1483                  " --internal_release_string \"\"",
1484                  boot_path.value().c_str(),
1485                  boot_partition_size);
1486 
1487   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
1488   EXPECT_COMMAND(
1489       0,
1490       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
1491       " --output %s",
1492       pk_path.value().c_str());
1493 
1494   GenerateVBMetaImage(
1495       "vbmeta_a.img",
1496       "SHA256_RSA2048",
1497       11,
1498       base::FilePath("test/data/testkey_rsa2048.pem"),
1499       base::StringPrintf("--chain_partition boot:1:%s"
1500                          " --kernel_cmdline 'cmdline2 in vbmeta'"
1501                          " --internal_release_string \"\"",
1502                          pk_path.value().c_str()));
1503 
1504   ops_.set_expected_public_key(
1505       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1506 
1507   AvbSlotVerifyData* slot_data = NULL;
1508   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
1509             avb_slot_verify(ops_.avb_ops(),
1510                             requested_partitions,
1511                             "_a",
1512                             false /* allow_verification_error */,
1513                             &slot_data));
1514   EXPECT_EQ(nullptr, slot_data);
1515 }
1516 
1517 // Check that chain descriptors in chained partitions are caught in
1518 // avb_slot_verify().
TEST_F(AvbSlotVerifyTest,ChainedPartitionEnforceNoChainPartitions)1519 TEST_F(AvbSlotVerifyTest, ChainedPartitionEnforceNoChainPartitions) {
1520   size_t boot_partition_size = 16 * 1024 * 1024;
1521   const size_t boot_image_size = 5 * 1024 * 1024;
1522   base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
1523   const char* requested_partitions[] = {"boot", NULL};
1524 
1525   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
1526   EXPECT_COMMAND(
1527       0,
1528       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
1529       " --output %s",
1530       pk_path.value().c_str());
1531 
1532   EXPECT_COMMAND(0,
1533                  "./avbtool add_hash_footer"
1534                  " --image %s"
1535                  " --kernel_cmdline 'cmdline2 in hash footer'"
1536                  " --rollback_index 12"
1537                  " --partition_name boot"
1538                  " --partition_size %zd"
1539                  " --algorithm SHA256_RSA4096"
1540                  " --key test/data/testkey_rsa4096.pem"
1541                  " --salt deadbeef"
1542                  " --chain_partition other:2:%s"
1543                  " --internal_release_string \"\"",
1544                  boot_path.value().c_str(),
1545                  boot_partition_size,
1546                  pk_path.value().c_str());
1547 
1548   GenerateVBMetaImage(
1549       "vbmeta_a.img",
1550       "SHA256_RSA2048",
1551       11,
1552       base::FilePath("test/data/testkey_rsa2048.pem"),
1553       base::StringPrintf("--chain_partition boot:1:%s"
1554                          " --kernel_cmdline 'cmdline2 in vbmeta'"
1555                          " --internal_release_string \"\"",
1556                          pk_path.value().c_str()));
1557 
1558   ops_.set_expected_public_key(
1559       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
1560 
1561   AvbSlotVerifyData* slot_data = NULL;
1562   EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
1563             avb_slot_verify(ops_.avb_ops(),
1564                             requested_partitions,
1565                             "_a",
1566                             false /* allow_verification_error */,
1567                             &slot_data));
1568   EXPECT_EQ(nullptr, slot_data);
1569 }
1570 
1571 }  // namespace avb
1572