blob: accf00a4416dd32a936181e2ef72832d05e7ae4c [file] [log] [blame]
David Zeuthen21e95262016-07-27 17:58:40 -04001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
David Zeuthenc612e2e2016-09-16 16:44:08 -04004 * 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:
David Zeuthen21e95262016-07-27 17:58:40 -040011 *
David Zeuthenc612e2e2016-09-16 16:44:08 -040012 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
David Zeuthen21e95262016-07-27 17:58:40 -040014 *
David Zeuthenc612e2e2016-09-16 16:44:08 -040015 * 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.
David Zeuthen21e95262016-07-27 17:58:40 -040023 */
24
25#include <iostream>
26
David Zeuthen21e95262016-07-27 17:58:40 -040027#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"
David Zeuthen8b6973b2016-09-20 12:39:49 -040032#include "fake_avb_ops.h"
David Zeuthen21e95262016-07-27 17:58:40 -040033
34class AvbSlotVerifyTest : public BaseAvbToolTest {
35 public:
36 AvbSlotVerifyTest() {}
37
38 virtual void SetUp() override {
39 BaseAvbToolTest::SetUp();
40 ops_.set_partition_dir(testdir_);
41 ops_.set_stored_rollback_indexes({0, 0, 0, 0});
42 ops_.set_stored_is_device_unlocked(false);
43 }
44
David Zeuthen8b6973b2016-09-20 12:39:49 -040045 FakeAvbOps ops_;
David Zeuthen21e95262016-07-27 17:58:40 -040046};
47
48TEST_F(AvbSlotVerifyTest, Basic) {
49 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 0,
50 base::FilePath("test/data/testkey_rsa2048.pem"));
51
52 ops_.set_expected_public_key(
53 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
54
55 AvbSlotVerifyData* slot_data = NULL;
56 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
57 avb_slot_verify(ops_.avb_ops(), "_a", &slot_data));
58 EXPECT_NE(nullptr, slot_data);
59 EXPECT_EQ(
60 "androidboot.slot_suffix=_a androidboot.vbmeta.device_state=locked "
61 "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1408 "
David Zeuthen88b13e12016-10-03 17:24:55 -040062 "androidboot.vbmeta.digest="
63 "22cda7342f5ba915f41662975f96f0810ba097399d9d4d4d3847f59c1fe8dfc9",
David Zeuthen21e95262016-07-27 17:58:40 -040064 std::string(slot_data->cmdline));
65 avb_slot_verify_data_free(slot_data);
66}
67
68TEST_F(AvbSlotVerifyTest, BasicSha512) {
69 GenerateVBMetaImage("vbmeta_a.img", "SHA512_RSA2048", 0,
70 base::FilePath("test/data/testkey_rsa2048.pem"));
71
72 ops_.set_expected_public_key(
73 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
74
75 AvbSlotVerifyData* slot_data = NULL;
76 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
77 avb_slot_verify(ops_.avb_ops(), "_a", &slot_data));
78 EXPECT_NE(nullptr, slot_data);
79 EXPECT_EQ(
80 "androidboot.slot_suffix=_a androidboot.vbmeta.device_state=locked "
81 "androidboot.vbmeta.hash_alg=sha512 androidboot.vbmeta.size=1472 "
82 "androidboot.vbmeta.digest="
David Zeuthen88b13e12016-10-03 17:24:55 -040083 "125592a19a266efe6683de1afee53e2585ccfcf33adb5d6485e6fbfeabccf57134aa8365"
84 "aa949a5c6b253bf34956b80e304b7668ee599d207047c8d1bf9574d9",
David Zeuthen21e95262016-07-27 17:58:40 -040085 std::string(slot_data->cmdline));
86 avb_slot_verify_data_free(slot_data);
87}
88
89TEST_F(AvbSlotVerifyTest, BasicUnlocked) {
90 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 0,
91 base::FilePath("test/data/testkey_rsa2048.pem"));
92
93 ops_.set_expected_public_key(
94 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
95
96 ops_.set_stored_is_device_unlocked(true);
97
98 AvbSlotVerifyData* slot_data = NULL;
99 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
100 avb_slot_verify(ops_.avb_ops(), "_a", &slot_data));
101 EXPECT_NE(nullptr, slot_data);
102 EXPECT_EQ(
103 "androidboot.slot_suffix=_a androidboot.vbmeta.device_state=unlocked "
104 "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1408 "
David Zeuthen88b13e12016-10-03 17:24:55 -0400105 "androidboot.vbmeta.digest="
106 "22cda7342f5ba915f41662975f96f0810ba097399d9d4d4d3847f59c1fe8dfc9",
David Zeuthen21e95262016-07-27 17:58:40 -0400107 std::string(slot_data->cmdline));
108 avb_slot_verify_data_free(slot_data);
109}
110
111TEST_F(AvbSlotVerifyTest, SlotDataIsCorrect) {
112 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 0,
113 base::FilePath("test/data/testkey_rsa2048.pem"));
114
115 ops_.set_expected_public_key(
116 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
117
118 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
119 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
120}
121
122TEST_F(AvbSlotVerifyTest, WrongPublicKey) {
123 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 0,
124 base::FilePath("test/data/testkey_rsa2048.pem"));
125
126 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
127 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
128}
129
130TEST_F(AvbSlotVerifyTest, NoImage) {
131 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_IO,
132 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
133}
134
135TEST_F(AvbSlotVerifyTest, UnsignedVBMeta) {
136 GenerateVBMetaImage("vbmeta_a.img", "", 0, base::FilePath(""));
137
138 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
139 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
140}
141
142TEST_F(AvbSlotVerifyTest, CorruptedImage) {
143 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 0,
144 base::FilePath("test/data/testkey_rsa2048.pem"));
145
146 // Corrupt four bytes of data in the end of the image. Since the aux
147 // data is at the end and this data is signed, this will change the
148 // value of the computed hash.
149 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
150 EXPECT_EQ(AVB_IO_RESULT_OK, ops_.avb_ops()->write_to_partition(
151 ops_.avb_ops(), "vbmeta_a",
152 -sizeof corrupt_data, // offset from end
153 sizeof corrupt_data, corrupt_data));
154
155 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
156 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
157}
158
159TEST_F(AvbSlotVerifyTest, RollbackIndex) {
160 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 42,
161 base::FilePath("test/data/testkey_rsa2048.pem"));
162
163 ops_.set_expected_public_key(
164 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
165
166 // First try with 42 as the stored rollback index - this should
167 // succeed since the image rollback index is 42 (as set above).
168 ops_.set_stored_rollback_indexes({42});
169 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
170 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
171
172 // Then try with 43 for the stored rollback index - this should fail
173 // because the image has rollback index 42 which is less than 43.
174 ops_.set_stored_rollback_indexes({43});
175 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
176 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
177}
178
179TEST_F(AvbSlotVerifyTest, HashDescriptorInVBMeta) {
180 const size_t boot_partition_size = 16 * 1024 * 1024;
181 const size_t boot_image_size = 5 * 1024 * 1024;
182 base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
183
184 EXPECT_COMMAND(
185 0,
186 "./avbtool add_hash_footer"
187 " --image %s"
188 " --rollback_index 0"
189 " --partition_name boot"
190 " --partition_size %zd"
191 " --kernel_cmdline 'cmdline in hash footer $(ANDROID_SYSTEM_PARTUUID)'"
192 " --salt deadbeef",
193 boot_path.value().c_str(), boot_partition_size);
194
195 GenerateVBMetaImage(
196 "vbmeta_a.img", "SHA256_RSA2048", 4,
197 base::FilePath("test/data/testkey_rsa2048.pem"),
198 base::StringPrintf(
199 "--include_descriptors_from_image %s"
200 " --kernel_cmdline 'cmdline in vbmeta $(ANDROID_BOOT_PARTUUID)'",
201 boot_path.value().c_str()));
202
203 EXPECT_EQ(
204 "VBMeta image version: 1.0\n"
205 "Header Block: 256 bytes\n"
206 "Authentication Block: 576 bytes\n"
207 "Auxiliary Block: 768 bytes\n"
208 "Algorithm: SHA256_RSA2048\n"
209 "Rollback Index: 4\n"
210 "Descriptors:\n"
211 " Kernel Cmdline descriptor:\n"
212 " Kernel Cmdline: 'cmdline in vbmeta "
213 "$(ANDROID_BOOT_PARTUUID)'\n"
214 " Hash descriptor:\n"
215 " Image Size: 5242880 bytes\n"
216 " Hash Algorithm: sha256\n"
217 " Partition Name: boot\n"
218 " Salt: deadbeef\n"
219 " Digest: "
220 "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n"
221 " Kernel Cmdline descriptor:\n"
222 " Kernel Cmdline: 'cmdline in hash footer "
223 "$(ANDROID_SYSTEM_PARTUUID)'\n",
224 InfoImage(vbmeta_image_path_));
225
226 EXPECT_COMMAND(0,
227 "./avbtool erase_footer"
228 " --image %s",
229 boot_path.value().c_str());
230
231 // With no footer, 'avbtool info_image' should fail (exit status 1).
232 EXPECT_COMMAND(1, "./avbtool info_image --image %s",
233 boot_path.value().c_str());
234
235 ops_.set_expected_public_key(
236 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
237
238 AvbSlotVerifyData* slot_data = NULL;
239 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
240 avb_slot_verify(ops_.avb_ops(), "_a", &slot_data));
241 EXPECT_NE(nullptr, slot_data);
242
243 // Now verify the slot data. The vbmeta data should match our
244 // vbmeta_image_ member.
245 EXPECT_EQ(slot_data->vbmeta_size, vbmeta_image_.size());
246 EXPECT_EQ(0, memcmp(vbmeta_image_.data(), slot_data->vbmeta_data,
247 slot_data->vbmeta_size));
248
249 // The boot image data should match what is generated above with
250 // GenerateImage().
251 EXPECT_EQ(boot_image_size, slot_data->boot_size);
252 for (size_t n = 0; n < slot_data->boot_size; n++) {
253 EXPECT_EQ(slot_data->boot_data[n], uint8_t(n));
254 }
255
256 // This should match the two cmdlines with a space (U+0020) between
257 // them and the $(ANDROID_SYSTEM_PARTUUID) and
258 // $(ANDROID_BOOT_PARTUUID) variables replaced.
259 EXPECT_EQ(
260 "cmdline in vbmeta 1234-fake-guid-for:boot_a "
261 "cmdline in hash footer 1234-fake-guid-for:system_a "
262 "androidboot.slot_suffix=_a "
263 "androidboot.vbmeta.device_state=locked "
264 "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=1600 "
David Zeuthen88b13e12016-10-03 17:24:55 -0400265 "androidboot.vbmeta.digest="
266 "844308149e43d5db7b14cd5747def40aadf2f0e4716d6435242f90aac9d883d6",
David Zeuthen21e95262016-07-27 17:58:40 -0400267 std::string(slot_data->cmdline));
268 EXPECT_EQ(4UL, slot_data->rollback_indexes[0]);
269 for (size_t n = 1; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; n++) {
270 EXPECT_EQ(0UL, slot_data->rollback_indexes[n]);
271 }
272 avb_slot_verify_data_free(slot_data);
273}
274
275TEST_F(AvbSlotVerifyTest, HashDescriptorInVBMetaCorruptBoot) {
276 size_t boot_partition_size = 16 * 1024 * 1024;
277 base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
278
279 EXPECT_COMMAND(0,
280 "./avbtool add_hash_footer"
281 " --image %s"
282 " --rollback_index 0"
283 " --partition_name boot"
284 " --partition_size %zd"
285 " --salt deadbeef",
286 boot_path.value().c_str(), boot_partition_size);
287
288 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 0,
289 base::FilePath("test/data/testkey_rsa2048.pem"),
290 base::StringPrintf("--include_descriptors_from_image %s",
291 boot_path.value().c_str()));
292
293 EXPECT_COMMAND(0,
294 "./avbtool erase_footer"
295 " --image %s",
296 boot_path.value().c_str());
297
298 ops_.set_expected_public_key(
299 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
300
301 // So far, so good.
302 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
303 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
304
305 // Now corrupt boot_a.img and expect verification error.
306 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
307 EXPECT_EQ(AVB_IO_RESULT_OK, ops_.avb_ops()->write_to_partition(
308 ops_.avb_ops(), "boot_a",
309 1024 * 1024, // offset: 1 MiB
310 sizeof corrupt_data, corrupt_data));
311
312 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
313 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
314}
315
316TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartition) {
317 size_t boot_partition_size = 16 * 1024 * 1024;
318 const size_t boot_image_size = 5 * 1024 * 1024;
319 base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
320
321 EXPECT_COMMAND(0,
322 "./avbtool add_hash_footer"
323 " --image %s"
324 " --kernel_cmdline 'cmdline2 in hash footer'"
325 " --rollback_index 12"
326 " --partition_name boot"
327 " --partition_size %zd"
328 " --algorithm SHA256_RSA4096"
329 " --key test/data/testkey_rsa4096.pem"
330 " --salt deadbeef",
331 boot_path.value().c_str(), boot_partition_size);
332
333 base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
334 EXPECT_COMMAND(
335 0,
336 "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
337 " --output %s",
338 pk_path.value().c_str());
339
340 GenerateVBMetaImage(
341 "vbmeta_a.img", "SHA256_RSA2048", 11,
342 base::FilePath("test/data/testkey_rsa2048.pem"),
343 base::StringPrintf("--chain_partition boot:1:%s"
344 " --kernel_cmdline 'cmdline2 in vbmeta'",
345 pk_path.value().c_str()));
346
347 EXPECT_EQ(
348 "VBMeta image version: 1.0\n"
349 "Header Block: 256 bytes\n"
350 "Authentication Block: 576 bytes\n"
351 "Auxiliary Block: 1664 bytes\n"
352 "Algorithm: SHA256_RSA2048\n"
353 "Rollback Index: 11\n"
354 "Descriptors:\n"
355 " Chain Partition descriptor:\n"
356 " Partition Name: boot\n"
357 " Rollback Index Slot: 1\n"
358 " Public key (sha1): 2597c218aae470a130f61162feaae70afd97f011\n"
359 " Kernel Cmdline descriptor:\n"
360 " Kernel Cmdline: 'cmdline2 in vbmeta'\n",
361 InfoImage(vbmeta_image_path_));
362
363 ops_.set_expected_public_key(
364 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
365
366 AvbSlotVerifyData* slot_data = NULL;
367 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
368 avb_slot_verify(ops_.avb_ops(), "_a", &slot_data));
369 EXPECT_NE(nullptr, slot_data);
370
371 // Now verify the slot data. The vbmeta data should match our
372 // vbmeta_image_ member.
373 EXPECT_EQ(slot_data->vbmeta_size, vbmeta_image_.size());
374 EXPECT_EQ(0, memcmp(vbmeta_image_.data(), slot_data->vbmeta_data,
375 slot_data->vbmeta_size));
376
377 // The boot image data should match what is generated above with
378 // GenerateImage().
379 EXPECT_EQ(boot_image_size, slot_data->boot_size);
380 for (size_t n = 0; n < slot_data->boot_size; n++) {
381 EXPECT_EQ(slot_data->boot_data[n], uint8_t(n));
382 }
383
384 // This should match the two cmdlines with a space (U+0020) between them.
385 EXPECT_EQ(
386 "cmdline2 in hash footer cmdline2 in vbmeta "
387 "androidboot.slot_suffix=_a "
388 "androidboot.vbmeta.device_state=locked "
389 "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=2496 "
David Zeuthen88b13e12016-10-03 17:24:55 -0400390 "androidboot.vbmeta.digest="
391 "3924a4e4cdf9a4e6e77b0d87e6e9b4648621e43c2a20988a86c1eb9a56bef338",
David Zeuthen21e95262016-07-27 17:58:40 -0400392 std::string(slot_data->cmdline));
393 EXPECT_EQ(11UL, slot_data->rollback_indexes[0]);
394 EXPECT_EQ(12UL, slot_data->rollback_indexes[1]);
395 for (size_t n = 2; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; n++) {
396 EXPECT_EQ(0UL, slot_data->rollback_indexes[n]);
397 }
398 avb_slot_verify_data_free(slot_data);
399}
400
401TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartitionCorruptBoot) {
402 size_t boot_partition_size = 16 * 1024 * 1024;
403 base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
404
405 EXPECT_COMMAND(0,
406 "./avbtool add_hash_footer"
407 " --image %s"
408 " --rollback_index 0"
409 " --partition_name boot"
410 " --partition_size %zd"
411 " --algorithm SHA256_RSA4096"
412 " --key test/data/testkey_rsa4096.pem"
413 " --salt deadbeef",
414 boot_path.value().c_str(), boot_partition_size);
415
416 base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
417 EXPECT_COMMAND(
418 0,
419 "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
420 " --output %s",
421 pk_path.value().c_str());
422
423 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 0,
424 base::FilePath("test/data/testkey_rsa2048.pem"),
425 base::StringPrintf("--chain_partition boot:1:%s",
426 pk_path.value().c_str()));
427
428 ops_.set_expected_public_key(
429 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
430
431 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
432 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
433
434 // Now corrupt boot_a.img and expect verification error.
435 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
436 EXPECT_EQ(AVB_IO_RESULT_OK, ops_.avb_ops()->write_to_partition(
437 ops_.avb_ops(), "boot_a",
438 1024 * 1024, // offset: 1 MiB
439 sizeof corrupt_data, corrupt_data));
440
441 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
442 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
443}
444
445TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartitionKeyMismatch) {
446 size_t boot_partition_size = 16 * 1024 * 1024;
447 base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
448
449 // Use different key to sign vbmeta in boot_a (we use the 8192 bit
450 // key) than what's in the chained partition descriptor (which is
451 // the 4096 bit key) and expect
452 // AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED.
453
454 EXPECT_COMMAND(0,
455 "./avbtool add_hash_footer"
456 " --image %s"
457 " --rollback_index 0"
458 " --partition_name boot"
459 " --partition_size %zd"
460 " --algorithm SHA256_RSA8192"
461 " --key test/data/testkey_rsa8192.pem"
462 " --salt deadbeef",
463 boot_path.value().c_str(), boot_partition_size);
464
465 base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
466 EXPECT_COMMAND(
467 0,
468 "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
469 " --output %s",
470 pk_path.value().c_str());
471
472 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 0,
473 base::FilePath("test/data/testkey_rsa2048.pem"),
474 base::StringPrintf("--chain_partition boot:1:%s",
475 pk_path.value().c_str()));
476
477 ops_.set_expected_public_key(
478 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
479
480 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
481 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
482}
483
484TEST_F(AvbSlotVerifyTest, HashDescriptorInChainedPartitionRollbackIndexFail) {
485 size_t boot_partition_size = 16 * 1024 * 1024;
486 base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
487
488 EXPECT_COMMAND(0,
489 "./avbtool add_hash_footer"
490 " --image %s"
491 " --rollback_index 10"
492 " --partition_name boot"
493 " --partition_size %zd"
494 " --algorithm SHA256_RSA4096"
495 " --key test/data/testkey_rsa4096.pem"
496 " --salt deadbeef",
497 boot_path.value().c_str(), boot_partition_size);
498
499 base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
500 EXPECT_COMMAND(
501 0,
502 "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
503 " --output %s",
504 pk_path.value().c_str());
505
506 GenerateVBMetaImage("vbmeta_a.img", "SHA256_RSA2048", 110,
507 base::FilePath("test/data/testkey_rsa2048.pem"),
508 base::StringPrintf("--chain_partition boot:1:%s",
509 pk_path.value().c_str()));
510
511 ops_.set_expected_public_key(
512 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
513
514 // Both images (vbmeta_a and boot_a) have rollback index 10 and 11
515 // so it should work if the stored rollback indexes are 0 and 0.
516 ops_.set_stored_rollback_indexes({0, 0});
517 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
518 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
519
520 // Check failure if we set the stored rollback index of the chained
521 // partition to 20 (see AvbSlotVerifyTest.RollbackIndex above
522 // where we test rollback index checks for the vbmeta partition).
523 ops_.set_stored_rollback_indexes({0, 20});
524 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
525 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
526
527 // Check failure if there is no rollback index slot 1 - in that case
528 // we expect an I/O error since ops->read_rollback_index() will
529 // fail.
530 ops_.set_stored_rollback_indexes({0});
531 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_IO,
532 avb_slot_verify(ops_.avb_ops(), "_a", NULL));
533}
534
535TEST_F(AvbSlotVerifyTest, ChainedPartitionNoSlots) {
536 size_t boot_partition_size = 16 * 1024 * 1024;
537 const size_t boot_image_size = 5 * 1024 * 1024;
538 base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
539
540 EXPECT_COMMAND(0,
541 "./avbtool add_hash_footer"
542 " --image %s"
543 " --kernel_cmdline 'cmdline2 in hash footer'"
544 " --rollback_index 12"
545 " --partition_name boot"
546 " --partition_size %zd"
547 " --algorithm SHA256_RSA4096"
548 " --key test/data/testkey_rsa4096.pem"
549 " --salt deadbeef",
550 boot_path.value().c_str(), boot_partition_size);
551
552 base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
553 EXPECT_COMMAND(
554 0,
555 "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
556 " --output %s",
557 pk_path.value().c_str());
558
559 GenerateVBMetaImage(
560 "vbmeta.img", "SHA256_RSA2048", 11,
561 base::FilePath("test/data/testkey_rsa2048.pem"),
562 base::StringPrintf("--chain_partition boot:1:%s"
563 " --kernel_cmdline 'cmdline2 in vbmeta'",
564 pk_path.value().c_str()));
565
566 EXPECT_EQ(
567 "VBMeta image version: 1.0\n"
568 "Header Block: 256 bytes\n"
569 "Authentication Block: 576 bytes\n"
570 "Auxiliary Block: 1664 bytes\n"
571 "Algorithm: SHA256_RSA2048\n"
572 "Rollback Index: 11\n"
573 "Descriptors:\n"
574 " Chain Partition descriptor:\n"
575 " Partition Name: boot\n"
576 " Rollback Index Slot: 1\n"
577 " Public key (sha1): 2597c218aae470a130f61162feaae70afd97f011\n"
578 " Kernel Cmdline descriptor:\n"
579 " Kernel Cmdline: 'cmdline2 in vbmeta'\n",
580 InfoImage(vbmeta_image_path_));
581
582 ops_.set_expected_public_key(
583 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
584
585 AvbSlotVerifyData* slot_data = NULL;
586 EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
587 avb_slot_verify(ops_.avb_ops(), "", &slot_data));
588 EXPECT_NE(nullptr, slot_data);
589
590 // Now verify the slot data. The vbmeta data should match our
591 // vbmeta_image_ member.
592 EXPECT_EQ(slot_data->vbmeta_size, vbmeta_image_.size());
593 EXPECT_EQ(0, memcmp(vbmeta_image_.data(), slot_data->vbmeta_data,
594 slot_data->vbmeta_size));
595
596 // The boot image data should match what is generated above with
597 // GenerateImage().
598 EXPECT_EQ(boot_image_size, slot_data->boot_size);
599 for (size_t n = 0; n < slot_data->boot_size; n++) {
600 EXPECT_EQ(slot_data->boot_data[n], uint8_t(n));
601 }
602
603 // This should match the two cmdlines with a space (U+0020) between
604 // them - note that androidboot.slot_suffix is not set since we
605 // don't have any slots in this setup.
606 EXPECT_EQ(
607 "cmdline2 in hash footer cmdline2 in vbmeta "
608 "androidboot.vbmeta.device_state=locked "
609 "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=2496 "
David Zeuthen88b13e12016-10-03 17:24:55 -0400610 "androidboot.vbmeta.digest="
611 "3924a4e4cdf9a4e6e77b0d87e6e9b4648621e43c2a20988a86c1eb9a56bef338",
David Zeuthen21e95262016-07-27 17:58:40 -0400612 std::string(slot_data->cmdline));
613 EXPECT_EQ(11UL, slot_data->rollback_indexes[0]);
614 EXPECT_EQ(12UL, slot_data->rollback_indexes[1]);
615 for (size_t n = 2; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; n++) {
616 EXPECT_EQ(0UL, slot_data->rollback_indexes[n]);
617 }
618 avb_slot_verify_data_free(slot_data);
619}