blob: 6d3e64f7c695b52c33ae4558858af476ff401181 [file] [log] [blame]
Monika Singhb15747d2017-09-25 14:01:13 +05301/*
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 "avb_slot_verify.h"
26#include "avb_chain_partition_descriptor.h"
27#include "avb_footer.h"
28#include "avb_hash_descriptor.h"
29#include "avb_kernel_cmdline_descriptor.h"
30#include "avb_sha.h"
31#include "avb_util.h"
32#include "avb_vbmeta_image.h"
33#include "avb_version.h"
34
35/* Maximum allow length (in bytes) of a partition name, including
36 * ab_suffix.
37 */
38#define PART_NAME_MAX_SIZE 32
39
40/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
41#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
42
43/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
44#define MAX_NUMBER_OF_VBMETA_IMAGES 32
45
46/* Maximum size of a vbmeta image - 64 KiB. */
47#define VBMETA_MAX_SIZE (64 * 1024)
48
49/* Helper function to see if we should continue with verification in
50 * allow_verification_error=true mode if something goes wrong. See the
51 * comments for the avb_slot_verify() function for more information.
52 */
53static inline bool result_should_continue(AvbSlotVerifyResult result) {
54 switch (result) {
55 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
56 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
57 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
58 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
59 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
60 return false;
61
62 case AVB_SLOT_VERIFY_RESULT_OK:
63 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
64 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
65 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
66 return true;
67 }
68
69 return false;
70}
71
72static AvbSlotVerifyResult load_and_verify_hash_partition(
73 AvbOps* ops,
74 const char* const* requested_partitions,
75 const char* ab_suffix,
76 bool allow_verification_error,
77 const AvbDescriptor* descriptor,
78 AvbSlotVerifyData* slot_data) {
79 AvbHashDescriptor hash_desc;
80 const uint8_t* desc_partition_name = NULL;
81 const uint8_t* desc_salt;
82 const uint8_t* desc_digest;
83 char part_name[PART_NAME_MAX_SIZE];
84 AvbSlotVerifyResult ret;
85 AvbIOResult io_ret;
86 uint8_t* image_buf = NULL;
87 size_t part_num_read;
88 uint8_t* digest = NULL;
89 size_t digest_len;
90 const char* found = NULL;
91 uint64_t image_size;
92
93 if (!avb_hash_descriptor_validate_and_byteswap(
94 (const AvbHashDescriptor*)descriptor, &hash_desc)) {
95 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
96 goto out;
97 }
98 desc_partition_name =
99 ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
100 desc_salt = desc_partition_name + hash_desc.partition_name_len;
101 desc_digest = desc_salt + hash_desc.salt_len;
102
103 if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
104 avb_error("Partition name is not valid UTF-8.\n");
105 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
106 goto out;
107 }
108
109 /* Don't bother loading or validating unless the partition was
110 * requested in the first place.
111 */
112 found = avb_strv_find_str(requested_partitions,
113 (const char*)desc_partition_name,
114 hash_desc.partition_name_len);
115 if (found == NULL) {
116 ret = AVB_SLOT_VERIFY_RESULT_OK;
117 goto out;
118 }
119
120 if (!avb_str_concat(part_name,
121 sizeof part_name,
122 (const char*)desc_partition_name,
123 hash_desc.partition_name_len,
124 ab_suffix,
125 avb_strlen(ab_suffix))) {
126 avb_error("Partition name and suffix does not fit.\n");
127 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
128 goto out;
129 }
130
131 /* If we're allowing verification errors then hash_desc.image_size
132 * may no longer match what's in the partition... so in this case
133 * just load the entire partition.
134 *
135 * For example, this can happen if a developer does 'fastboot flash
136 * boot /path/to/new/and/bigger/boot.img'. We want this to work
137 * since it's such a common workflow.
138 */
139 image_size = hash_desc.image_size;
140 if (allow_verification_error) {
141 if (ops->get_size_of_partition == NULL) {
142 avb_errorv(part_name,
143 ": The get_size_of_partition() operation is "
144 "not implemented so we may not load the entire partition. "
145 "Please implement.",
146 NULL);
147 } else {
148 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
149 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
150 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
151 goto out;
152 } else if (io_ret != AVB_IO_RESULT_OK) {
153 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
154 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
155 goto out;
156 }
157 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
158 }
159 }
160
Monika Singh7a5c2ed2018-08-30 15:57:24 +0530161 if (!strncmp(part_name, "boot", strlen("boot"))) {
162 image_size = hash_desc.image_size;
163 }
164
165 io_ret = ops->read_from_partition(
166 ops, part_name, 0 /* offset */, image_size, &image_buf, &part_num_read);
167
Monika Singhb15747d2017-09-25 14:01:13 +0530168 if (image_buf == NULL) {
169 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
170 goto out;
171 }
Monika Singhb15747d2017-09-25 14:01:13 +0530172 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
173 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
174 goto out;
175 } else if (io_ret != AVB_IO_RESULT_OK) {
176 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
177 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
178 goto out;
179 }
Monika Singh7a5c2ed2018-08-30 15:57:24 +0530180 if (part_num_read < image_size) {
Monika Singhb15747d2017-09-25 14:01:13 +0530181 avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
182 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
183 goto out;
184 }
185
186 if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
187 uint32_t complete_len = hash_desc.salt_len + hash_desc.image_size;
Monika Singhb15747d2017-09-25 14:01:13 +0530188 digest = avb_malloc(AVB_SHA256_DIGEST_SIZE);
Monika Singh08d26892018-09-10 15:58:07 +0530189 if(digest == NULL || hash_desc.salt_len > SALT_BUFF_OFFSET )
Monika Singh0f7bfc82018-04-16 23:14:29 +0530190 {
191 avb_errorv(part_name, ": Failed to allocate memory\n", NULL);
192 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
193 goto out;
194 }
Monika Singh08d26892018-09-10 15:58:07 +0530195 image_buf = ADD_SALT_BUFF_OFFSET(image_buf) - hash_desc.salt_len;
196 avb_memcpy(image_buf, desc_salt, hash_desc.salt_len);
197 hash_find(image_buf, complete_len, digest, CRYPTO_AUTH_ALG_SHA256);
Monika Singh871d4b12018-10-08 00:06:18 +0530198 image_buf = SUB_SALT_BUFF_OFFSET(image_buf) + hash_desc.salt_len;
Monika Singhb15747d2017-09-25 14:01:13 +0530199 digest_len = AVB_SHA256_DIGEST_SIZE;
200 } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
201 AvbSHA512Ctx sha512_ctx;
202 uint8_t *dig;
203 digest = avb_malloc(AVB_SHA512_DIGEST_SIZE);
Monika Singh0f7bfc82018-04-16 23:14:29 +0530204 if(digest == NULL)
205 {
206 avb_errorv(part_name, ": Failed to allocate memory\n", NULL);
207 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
208 goto out;
209 }
Monika Singhb15747d2017-09-25 14:01:13 +0530210 avb_sha512_init(&sha512_ctx);
211 avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
212 avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
213 dig = avb_sha512_final(&sha512_ctx);
214 digest_len = AVB_SHA512_DIGEST_SIZE;
215 avb_memcpy(digest, dig, AVB_SHA512_DIGEST_SIZE);
216 } else {
217 avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
218 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
219 goto out;
220 }
221
222 if (digest_len != hash_desc.digest_len) {
223 avb_errorv(
224 part_name, ": Digest in descriptor not of expected size.\n", NULL);
225 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
226 goto out;
227 }
228
229 if (avb_safe_memcmp(digest, desc_digest, digest_len) != 0) {
230 avb_errorv(part_name,
231 ": Hash of data does not match digest in descriptor.\n",
232 NULL);
233 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
234 goto out;
235 }
236
237 ret = AVB_SLOT_VERIFY_RESULT_OK;
238
239out:
240 if (digest)
241 avb_free(digest);
242 /* If it worked and something was loaded, copy to slot_data. */
243 if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
244 image_buf != NULL) {
245 AvbPartitionData* loaded_partition;
246 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
247 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
248 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
249 goto fail;
250 }
251 loaded_partition =
252 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
253 loaded_partition->partition_name = avb_strdup(found);
254 loaded_partition->data_size = image_size;
255 loaded_partition->data = image_buf;
256 image_buf = NULL;
257 }
258
259fail:
260 //remove avb_free() as memory allocated from scratch region
261 return ret;
262}
263
264static AvbSlotVerifyResult load_requested_partitions(
265 AvbOps* ops,
266 const char* const* requested_partitions,
267 const char* ab_suffix,
268 AvbSlotVerifyData* slot_data) {
269 AvbSlotVerifyResult ret;
270 uint8_t* image_buf = NULL;
271 size_t n;
272
273 if (ops->get_size_of_partition == NULL) {
274 avb_error("get_size_of_partition() not implemented.\n");
275 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
276 goto out;
277 }
278
279 for (n = 0; requested_partitions[n] != NULL; n++) {
280 char part_name[PART_NAME_MAX_SIZE];
281 AvbIOResult io_ret;
282 uint64_t image_size;
283 size_t part_num_read;
284 AvbPartitionData* loaded_partition;
285
286 if (!avb_str_concat(part_name,
287 sizeof part_name,
288 requested_partitions[n],
289 avb_strlen(requested_partitions[n]),
290 ab_suffix,
291 avb_strlen(ab_suffix))) {
292 avb_error("Partition name and suffix does not fit.\n");
293 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
294 goto out;
295 }
296
297 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
298 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
299 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
300 goto out;
301 } else if (io_ret != AVB_IO_RESULT_OK) {
302 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
303 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
304 goto out;
305 }
306 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
307
308 image_buf = avb_malloc(image_size);
309 if (image_buf == NULL) {
310 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
311 goto out;
312 }
313
314 io_ret = ops->read_from_partition(
315 ops, part_name, 0 /* offset */, image_size, image_buf, &part_num_read);
316 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
317 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
318 goto out;
319 } else if (io_ret != AVB_IO_RESULT_OK) {
320 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
321 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
322 goto out;
323 }
324 if (part_num_read != image_size) {
325 avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
326 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
327 goto out;
328 }
329
330 /* Move to slot_data. */
331 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
332 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
333 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
334 goto out;
335 }
336 loaded_partition =
337 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
338 loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
339 if (loaded_partition->partition_name == NULL) {
340 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
341 goto out;
342 }
343 loaded_partition->data_size = image_size;
344 loaded_partition->data = image_buf;
345 image_buf = NULL;
346 }
347
348 ret = AVB_SLOT_VERIFY_RESULT_OK;
349
350out:
351 if (image_buf != NULL) {
352 avb_free(image_buf);
353 }
354 return ret;
355}
356
357static AvbSlotVerifyResult load_and_verify_vbmeta(
358 AvbOps* ops,
359 const char* const* requested_partitions,
360 const char* ab_suffix,
361 bool allow_verification_error,
362 AvbVBMetaImageFlags toplevel_vbmeta_flags,
363 int rollback_index_location,
364 const char* partition_name,
365 size_t partition_name_len,
366 const uint8_t* expected_public_key,
367 size_t expected_public_key_length,
368 AvbSlotVerifyData* slot_data,
369 AvbAlgorithmType* out_algorithm_type) {
370 char full_partition_name[PART_NAME_MAX_SIZE];
371 AvbSlotVerifyResult ret;
372 AvbIOResult io_ret;
Monika Singh5c317dc2018-09-25 11:09:55 +0530373 UINTN vbmeta_offset;
Monika Singhb15747d2017-09-25 14:01:13 +0530374 size_t vbmeta_size;
375 uint8_t* vbmeta_buf = NULL;
376 size_t vbmeta_num_read;
377 AvbVBMetaVerifyResult vbmeta_ret;
378 const uint8_t* pk_data;
379 size_t pk_len;
380 AvbVBMetaImageHeader vbmeta_header;
381 uint64_t stored_rollback_index;
382 const AvbDescriptor** descriptors = NULL;
383 size_t num_descriptors;
384 size_t n;
385 bool is_main_vbmeta;
386 bool is_vbmeta_partition;
387 AvbVBMetaData* vbmeta_image_data = NULL;
388
389 ret = AVB_SLOT_VERIFY_RESULT_OK;
390
391 avb_assert(slot_data != NULL);
392
393 /* Since we allow top-level vbmeta in 'boot', use
394 * rollback_index_location to determine whether we're the main
395 * vbmeta struct.
396 */
397 is_main_vbmeta = (rollback_index_location == 0);
398 is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
399
400 if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
401 avb_error("Partition name is not valid UTF-8.\n");
402 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
403 goto out;
404 }
405
406 /* Construct full partition name. */
407 if (!avb_str_concat(full_partition_name,
408 sizeof full_partition_name,
409 partition_name,
410 partition_name_len,
411 ab_suffix,
412 avb_strlen(ab_suffix))) {
413 avb_error("Partition name and suffix does not fit.\n");
414 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
415 goto out;
416 }
417
418 avb_debugv("Loading vbmeta struct from partition '",
419 full_partition_name,
420 "'.\n",
421 NULL);
422
423 /* If we're loading from the main vbmeta partition, the vbmeta
424 * struct is in the beginning. Otherwise we have to locate it via a
425 * footer.
426 */
427 if (is_vbmeta_partition) {
428 vbmeta_offset = 0;
429 vbmeta_size = VBMETA_MAX_SIZE;
430 } else {
431 uint8_t footer_buf[AVB_FOOTER_SIZE];
432 size_t footer_num_read;
433 AvbFooter footer;
434
435 io_ret = ops->read_from_partition(ops,
436 full_partition_name,
437 -AVB_FOOTER_SIZE,
438 AVB_FOOTER_SIZE,
439 footer_buf,
440 &footer_num_read);
441 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
442 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
443 goto out;
444 } else if (io_ret != AVB_IO_RESULT_OK) {
445 avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
446 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
447 goto out;
448 }
449 avb_assert(footer_num_read == AVB_FOOTER_SIZE);
450
451 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
452 &footer)) {
453 avb_errorv(full_partition_name, ": Error validating footer.\n", NULL);
454 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
455 goto out;
456 }
457
458 /* Basic footer sanity check since the data is untrusted. */
459 if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
460 avb_errorv(
461 full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
462 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
463 goto out;
464 }
Monika Singhb15747d2017-09-25 14:01:13 +0530465 vbmeta_offset = footer.vbmeta_offset;
466 vbmeta_size = footer.vbmeta_size;
467 }
468
Monika Singh5c317dc2018-09-25 11:09:55 +0530469 if (avb_strcmp(full_partition_name, "vbmeta") == 0) {
470 io_ret = ops->read_from_partition(ops,
Monika Singh7a5c2ed2018-08-30 15:57:24 +0530471 full_partition_name,
472 vbmeta_offset,
473 vbmeta_size,
474 &vbmeta_buf,
475 &vbmeta_num_read);
Monika Singh5c317dc2018-09-25 11:09:55 +0530476 } else { // for chain partitions
477 vbmeta_buf = avb_malloc(vbmeta_size);
478 if (vbmeta_buf == NULL) {
479 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
480 goto out;
481 }
482 io_ret = ops->read_from_partition(ops,
483 full_partition_name,
484 vbmeta_offset,
485 vbmeta_size,
486 vbmeta_buf,
487 &vbmeta_num_read);
488 }
Monika Singhb15747d2017-09-25 14:01:13 +0530489 if (vbmeta_buf == NULL) {
490 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
491 goto out;
492 }
493
Monika Singhb15747d2017-09-25 14:01:13 +0530494 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
495 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
496 goto out;
497 } else if (io_ret != AVB_IO_RESULT_OK) {
498 /* If we're looking for 'vbmeta' but there is no such partition,
499 * go try to get it from the boot partition instead.
500 */
501 if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
502 is_vbmeta_partition) {
503 avb_debugv(full_partition_name,
504 ": No such partition. Trying 'boot' instead.\n",
505 NULL);
506 ret = load_and_verify_vbmeta(ops,
507 requested_partitions,
508 ab_suffix,
509 allow_verification_error,
510 0 /* toplevel_vbmeta_flags */,
511 0 /* rollback_index_location */,
512 "boot",
513 avb_strlen("boot"),
514 NULL /* expected_public_key */,
515 0 /* expected_public_key_length */,
516 slot_data,
517 out_algorithm_type);
518 goto out;
519 } else {
520 avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
521 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
522 goto out;
523 }
524 }
525 avb_assert(vbmeta_num_read <= vbmeta_size);
526
527 /* Check if the image is properly signed and get the public key used
528 * to sign the image.
529 */
530 vbmeta_ret =
531 avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
532 switch (vbmeta_ret) {
533 case AVB_VBMETA_VERIFY_RESULT_OK:
534 avb_assert(pk_data != NULL && pk_len > 0);
535 break;
536
537 case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
538 case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
539 case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
540 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
541 avb_errorv(full_partition_name,
542 ": Error verifying vbmeta image: ",
543 avb_vbmeta_verify_result_to_string(vbmeta_ret),
544 "\n",
545 NULL);
546 if (!allow_verification_error) {
547 goto out;
548 }
549 break;
550
551 case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
552 /* No way to continue this case. */
553 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
554 avb_errorv(full_partition_name,
555 ": Error verifying vbmeta image: invalid vbmeta header\n",
556 NULL);
557 goto out;
558
559 case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
560 /* No way to continue this case. */
561 ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
562 avb_errorv(full_partition_name,
563 ": Error verifying vbmeta image: unsupported AVB version\n",
564 NULL);
565 goto out;
566 }
567
568 /* Byteswap the header. */
569 avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
570 &vbmeta_header);
571
572 /* If we're the toplevel, assign flags so they'll be passed down. */
573 if (is_main_vbmeta) {
574 toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
575 } else {
576 if (vbmeta_header.flags != 0) {
577 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
578 avb_errorv(full_partition_name,
579 ": chained vbmeta image has non-zero flags\n",
580 NULL);
581 goto out;
582 }
583 }
584
585 /* Check if key used to make signature matches what is expected. */
586 if (pk_data != NULL) {
587 if (expected_public_key != NULL) {
588 avb_assert(!is_main_vbmeta);
589 if (expected_public_key_length != pk_len ||
590 avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
591 avb_errorv(full_partition_name,
592 ": Public key used to sign data does not match key in chain "
593 "partition descriptor.\n",
594 NULL);
595 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
596 if (!allow_verification_error) {
597 goto out;
598 }
599 }
600 } else {
601 bool key_is_trusted = false;
602 const uint8_t* pk_metadata = NULL;
603 size_t pk_metadata_len = 0;
604
605 if (vbmeta_header.public_key_metadata_size > 0) {
606 pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
607 vbmeta_header.authentication_data_block_size +
608 vbmeta_header.public_key_metadata_offset;
609 pk_metadata_len = vbmeta_header.public_key_metadata_size;
610 }
611
612 avb_assert(is_main_vbmeta);
613 io_ret = ops->validate_vbmeta_public_key(
614 ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
615 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
616 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
617 goto out;
618 } else if (io_ret != AVB_IO_RESULT_OK) {
619 avb_errorv(full_partition_name,
620 ": Error while checking public key used to sign data.\n",
621 NULL);
622 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
623 goto out;
624 }
625 if (!key_is_trusted) {
626 avb_errorv(full_partition_name,
627 ": Public key used to sign data rejected.\n",
628 NULL);
629 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
630 if (!allow_verification_error) {
631 goto out;
632 }
633 }
634 }
635 }
636
637 /* Check rollback index. */
638 io_ret = ops->read_rollback_index(
639 ops, rollback_index_location, &stored_rollback_index);
640 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
641 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
642 goto out;
643 } else if (io_ret != AVB_IO_RESULT_OK) {
644 avb_errorv(full_partition_name,
645 ": Error getting rollback index for location.\n",
646 NULL);
647 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
648 goto out;
649 }
650 if (vbmeta_header.rollback_index < stored_rollback_index) {
651 avb_errorv(
652 full_partition_name,
653 ": Image rollback index is less than the stored rollback index.\n",
654 NULL);
655 ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
656 if (!allow_verification_error) {
657 goto out;
658 }
659 }
660
Monika Singh2c9d2b82018-05-01 12:24:59 +0530661 if (stored_rollback_index < vbmeta_header.rollback_index) {
662 io_ret = ops->write_rollback_index(
663 ops, rollback_index_location, vbmeta_header.rollback_index);
664 if (io_ret != AVB_IO_RESULT_OK) {
665 avb_errorv(full_partition_name,
666 ": Error storing rollback index for location.\n",
667 NULL);
668 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
669 goto out;
670 }
671 }
672
Monika Singhb15747d2017-09-25 14:01:13 +0530673 /* Copy vbmeta to vbmeta_images before recursing. */
674 if (is_main_vbmeta) {
675 avb_assert(slot_data->num_vbmeta_images == 0);
676 } else {
677 avb_assert(slot_data->num_vbmeta_images > 0);
678 }
679 if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
680 avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
681 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
682 goto out;
683 }
684 vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
685 vbmeta_image_data->partition_name = avb_strdup(partition_name);
686 vbmeta_image_data->vbmeta_data = vbmeta_buf;
687 /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
688 * and this includes data past the end of the image. Pass the
689 * actual size of the vbmeta image. Also, no need to use
690 * avb_safe_add() since the header has already been verified.
691 */
692 vbmeta_image_data->vbmeta_size =
693 sizeof(AvbVBMetaImageHeader) +
694 vbmeta_header.authentication_data_block_size +
695 vbmeta_header.auxiliary_data_block_size;
696 vbmeta_image_data->verify_result = vbmeta_ret;
697
698 /* If verification has been disabled by setting a bit in the image,
699 * we're done... except that we need to load the entirety of the
700 * requested partitions.
701 */
702 if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
703 AvbSlotVerifyResult sub_ret;
704 avb_debugv(
705 full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
706 /* If load_requested_partitions() fail it is always a fatal
707 * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
708 * than recoverable (e.g. one where result_should_continue()
709 * returns true) and we want to convey that error.
710 */
711 sub_ret = load_requested_partitions(
712 ops, requested_partitions, ab_suffix, slot_data);
713 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
714 ret = sub_ret;
715 }
716 goto out;
717 }
718
719 /* Now go through all descriptors and take the appropriate action:
720 *
721 * - hash descriptor: Load data from partition, calculate hash, and
722 * checks that it matches what's in the hash descriptor.
723 *
724 * - hashtree descriptor: Do nothing since verification happens
725 * on-the-fly from within the OS.
726 *
727 * - chained partition descriptor: Load the footer, load the vbmeta
728 * image, verify vbmeta image (includes rollback checks, hash
729 * checks, bail on chained partitions).
730 */
731 descriptors =
732 avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
Firoz Khan6f6d59e2018-09-19 14:24:13 +0530733 if (descriptors == NULL) {
734 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
735 goto out;
736 }
737
Monika Singhb15747d2017-09-25 14:01:13 +0530738 for (n = 0; n < num_descriptors; n++) {
739 AvbDescriptor desc;
740
741 if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
742 avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
743 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
744 goto out;
745 }
746
747 switch (desc.tag) {
748 case AVB_DESCRIPTOR_TAG_HASH: {
749 AvbSlotVerifyResult sub_ret;
750 sub_ret = load_and_verify_hash_partition(ops,
751 requested_partitions,
752 ab_suffix,
753 allow_verification_error,
754 descriptors[n],
755 slot_data);
756 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
757 ret = sub_ret;
758 if (!allow_verification_error || !result_should_continue(ret)) {
759 goto out;
760 }
761 }
762 } break;
763
764 case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
765 AvbSlotVerifyResult sub_ret;
766 AvbChainPartitionDescriptor chain_desc;
767 const uint8_t* chain_partition_name;
768 const uint8_t* chain_public_key;
769
770 /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
771 if (!is_main_vbmeta) {
772 avb_errorv(full_partition_name,
773 ": Encountered chain descriptor not in main image.\n",
774 NULL);
775 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
776 goto out;
777 }
778
779 if (!avb_chain_partition_descriptor_validate_and_byteswap(
780 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
781 avb_errorv(full_partition_name,
782 ": Chain partition descriptor is invalid.\n",
783 NULL);
784 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
785 goto out;
786 }
787
788 if (chain_desc.rollback_index_location == 0) {
789 avb_errorv(full_partition_name,
790 ": Chain partition has invalid "
791 "rollback_index_location field.\n",
792 NULL);
793 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
794 goto out;
795 }
796
797 chain_partition_name = ((const uint8_t*)descriptors[n]) +
798 sizeof(AvbChainPartitionDescriptor);
799 chain_public_key = chain_partition_name + chain_desc.partition_name_len;
800
801 sub_ret = load_and_verify_vbmeta(ops,
802 requested_partitions,
803 ab_suffix,
804 allow_verification_error,
805 toplevel_vbmeta_flags,
806 chain_desc.rollback_index_location,
807 (const char*)chain_partition_name,
808 chain_desc.partition_name_len,
809 chain_public_key,
810 chain_desc.public_key_len,
811 slot_data,
812 NULL /* out_algorithm_type */);
813 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
814 ret = sub_ret;
815 if (!result_should_continue(ret)) {
816 goto out;
817 }
818 }
819 } break;
820
821 case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
822 const uint8_t* kernel_cmdline;
823 AvbKernelCmdlineDescriptor kernel_cmdline_desc;
824 bool apply_cmdline;
825
826 if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
827 (AvbKernelCmdlineDescriptor*)descriptors[n],
828 &kernel_cmdline_desc)) {
829 avb_errorv(full_partition_name,
830 ": Kernel cmdline descriptor is invalid.\n",
831 NULL);
832 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
833 goto out;
834 }
835
836 kernel_cmdline = ((const uint8_t*)descriptors[n]) +
837 sizeof(AvbKernelCmdlineDescriptor);
838
839 if (!avb_validate_utf8(kernel_cmdline,
840 kernel_cmdline_desc.kernel_cmdline_length)) {
841 avb_errorv(full_partition_name,
842 ": Kernel cmdline is not valid UTF-8.\n",
843 NULL);
844 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
845 goto out;
846 }
847
848 /* Compare the flags for top-level VBMeta struct with flags in
849 * the command-line descriptor so command-line snippets only
850 * intended for a certain mode (dm-verity enabled/disabled)
851 * are skipped if applicable.
852 */
853 apply_cmdline = true;
854 if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
855 if (kernel_cmdline_desc.flags &
856 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
857 apply_cmdline = false;
858 }
859 } else {
860 if (kernel_cmdline_desc.flags &
861 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
862 apply_cmdline = false;
863 }
864 }
865
866 if (apply_cmdline) {
867 if (slot_data->cmdline == NULL) {
868 slot_data->cmdline =
869 avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
870 if (slot_data->cmdline == NULL) {
871 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
872 goto out;
873 }
874 avb_memcpy(slot_data->cmdline,
875 kernel_cmdline,
876 kernel_cmdline_desc.kernel_cmdline_length);
877 } else {
878 /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
879 size_t orig_size = avb_strlen(slot_data->cmdline);
880 size_t new_size =
881 orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
882 char* new_cmdline = avb_calloc(new_size);
883 if (new_cmdline == NULL) {
884 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
885 goto out;
886 }
887 avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
888 new_cmdline[orig_size] = ' ';
889 avb_memcpy(new_cmdline + orig_size + 1,
890 kernel_cmdline,
891 kernel_cmdline_desc.kernel_cmdline_length);
892 avb_free(slot_data->cmdline);
893 slot_data->cmdline = new_cmdline;
894 }
895 }
896 } break;
897
898 /* Explicit fall-through */
899 case AVB_DESCRIPTOR_TAG_PROPERTY:
900 case AVB_DESCRIPTOR_TAG_HASHTREE:
901 /* Do nothing. */
902 break;
903 }
904 }
905
906 if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
907 avb_errorv(
908 full_partition_name, ": Invalid rollback_index_location.\n", NULL);
909 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
910 goto out;
911 }
912
913 slot_data->rollback_indexes[rollback_index_location] =
914 vbmeta_header.rollback_index;
915
916 if (out_algorithm_type != NULL) {
917 *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
918 }
919
920out:
921 /* If |vbmeta_image_data| isn't NULL it means that it adopted
922 * |vbmeta_buf| so in that case don't free it here.
923 */
924
925 /* remove avb_free() as memory allocated from scratch region */
926
927 if (descriptors != NULL) {
928 avb_free(descriptors);
929 }
930 return ret;
931}
932
933#define NUM_GUIDS 3
934
935/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
936 * values. Returns NULL on OOM, otherwise the cmdline with values
937 * replaced.
938 */
939static char* sub_cmdline(AvbOps* ops,
940 const char* cmdline,
941 const char* ab_suffix,
942 bool using_boot_for_vbmeta) {
943 const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
944 const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
945 "$(ANDROID_BOOT_PARTUUID)",
946 "$(ANDROID_VBMETA_PARTUUID)"};
947 char* ret = NULL;
948 AvbIOResult io_ret;
949
950 /* Special-case for when the top-level vbmeta struct is in the boot
951 * partition.
952 */
953 if (using_boot_for_vbmeta) {
954 part_name_str[2] = "boot";
955 }
956
957 /* Replace unique partition GUIDs */
958 for (size_t n = 0; n < NUM_GUIDS; n++) {
959 char part_name[PART_NAME_MAX_SIZE];
960 char guid_buf[37];
961
962 if (!avb_str_concat(part_name,
963 sizeof part_name,
964 part_name_str[n],
965 avb_strlen(part_name_str[n]),
966 ab_suffix,
967 avb_strlen(ab_suffix))) {
968 avb_error("Partition name and suffix does not fit.\n");
969 goto fail;
970 }
971
972 io_ret = ops->get_unique_guid_for_partition(
973 ops, part_name, guid_buf, sizeof guid_buf);
974 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
975 return NULL;
976 } else if (io_ret != AVB_IO_RESULT_OK) {
977 avb_error("Error getting unique GUID for partition.\n");
978 goto fail;
979 }
980
981 if (ret == NULL) {
982 ret = avb_replace(cmdline, replace_str[n], guid_buf);
983 } else {
984 char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
985 avb_free(ret);
986 ret = new_ret;
987 }
988 if (ret == NULL) {
989 goto fail;
990 }
991 }
992
993 return ret;
994
995fail:
996 if (ret != NULL) {
997 avb_free(ret);
998 }
999 return NULL;
1000}
1001
1002static int cmdline_append_option(AvbSlotVerifyData* slot_data,
1003 const char* key,
1004 const char* value) {
1005 size_t offset, key_len, value_len;
1006 char* new_cmdline;
1007
1008 key_len = avb_strlen(key);
1009 value_len = avb_strlen(value);
1010
1011 offset = 0;
1012 if (slot_data->cmdline != NULL) {
1013 offset = avb_strlen(slot_data->cmdline);
1014 if (offset > 0) {
1015 offset += 1;
1016 }
1017 }
1018
1019 new_cmdline = avb_calloc(offset + key_len + value_len + 2);
1020 if (new_cmdline == NULL) {
1021 return 0;
1022 }
1023 if (offset > 0) {
1024 avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
1025 new_cmdline[offset - 1] = ' ';
1026 }
1027 avb_memcpy(new_cmdline + offset, key, key_len);
1028 new_cmdline[offset + key_len] = '=';
1029 avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
1030 if (slot_data->cmdline != NULL) {
1031 avb_free(slot_data->cmdline);
1032 }
1033 slot_data->cmdline = new_cmdline;
1034
1035 return 1;
1036}
1037
1038#define AVB_MAX_DIGITS_UINT64 32
1039
1040/* Writes |value| to |digits| in base 10 followed by a NUL byte.
1041 * Returns number of characters written excluding the NUL byte.
1042 */
1043static size_t uint64_to_base10(uint64_t value,
1044 char digits[AVB_MAX_DIGITS_UINT64]) {
1045 char rev_digits[AVB_MAX_DIGITS_UINT64];
1046 size_t n, num_digits;
1047
1048 for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
1049 rev_digits[num_digits++] = (value % 10) + '0';
1050 value /= 10;
1051 if (value == 0) {
1052 break;
1053 }
1054 }
1055
1056 for (n = 0; n < num_digits; n++) {
1057 digits[n] = rev_digits[num_digits - 1 - n];
1058 }
1059 digits[n] = '\0';
1060 return n;
1061}
1062
1063static int cmdline_append_version(AvbSlotVerifyData* slot_data,
1064 const char* key,
1065 uint64_t major_version,
1066 uint64_t minor_version) {
1067 char major_digits[AVB_MAX_DIGITS_UINT64];
1068 char minor_digits[AVB_MAX_DIGITS_UINT64];
1069 char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
1070 size_t num_major_digits, num_minor_digits;
1071
1072 num_major_digits = uint64_to_base10(major_version, major_digits);
1073 num_minor_digits = uint64_to_base10(minor_version, minor_digits);
1074 avb_memcpy(combined, major_digits, num_major_digits);
1075 combined[num_major_digits] = '.';
1076 avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
1077 combined[num_major_digits + 1 + num_minor_digits] = '\0';
1078
1079 return cmdline_append_option(slot_data, key, combined);
1080}
1081
1082static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
1083 const char* key,
1084 uint64_t value) {
1085 char digits[AVB_MAX_DIGITS_UINT64];
1086 uint64_to_base10(value, digits);
1087 return cmdline_append_option(slot_data, key, digits);
1088}
1089
1090static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
1091 const char* key,
1092 const uint8_t* data,
1093 size_t data_len) {
1094 char hex_digits[17] = "0123456789abcdef";
1095 char* hex_data;
1096 int ret;
1097 size_t n;
1098
1099 hex_data = avb_malloc(data_len * 2 + 1);
1100 if (hex_data == NULL) {
1101 return 0;
1102 }
1103
1104 for (n = 0; n < data_len; n++) {
1105 hex_data[n * 2] = hex_digits[data[n] >> 4];
1106 hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
1107 }
1108 hex_data[n * 2] = '\0';
1109
1110 ret = cmdline_append_option(slot_data, key, hex_data);
1111 avb_free(hex_data);
1112 return ret;
1113}
1114
1115static AvbSlotVerifyResult append_options(
1116 AvbOps* ops,
1117 AvbSlotVerifyData* slot_data,
1118 AvbVBMetaImageHeader* toplevel_vbmeta,
1119 AvbAlgorithmType algorithm_type,
1120 AvbHashtreeErrorMode hashtree_error_mode) {
1121 AvbSlotVerifyResult ret;
1122 const char* verity_mode = NULL;
1123 bool is_device_unlocked;
1124 AvbIOResult io_ret;
1125
1126 /* Add androidboot.vbmeta.device option. */
1127 if (!cmdline_append_option(slot_data,
1128 "androidboot.vbmeta.device",
1129 "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
1130 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1131 goto out;
1132 }
1133
1134 /* Add androidboot.vbmeta.avb_version option. */
1135 if (!cmdline_append_version(slot_data,
1136 "androidboot.vbmeta.avb_version",
1137 AVB_VERSION_MAJOR,
1138 AVB_VERSION_MINOR)) {
1139 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1140 goto out;
1141 }
1142
1143 /* Set androidboot.avb.device_state to "locked" or "unlocked". */
1144 io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
1145 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
1146 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1147 goto out;
1148 } else if (io_ret != AVB_IO_RESULT_OK) {
1149 avb_error("Error getting device state.\n");
1150 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1151 goto out;
1152 }
1153 if (!cmdline_append_option(slot_data,
1154 "androidboot.vbmeta.device_state",
1155 is_device_unlocked ? "unlocked" : "locked")) {
1156 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1157 goto out;
1158 }
1159
1160 /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
1161 * function as is used to sign vbmeta.
1162 */
1163 switch (algorithm_type) {
1164 /* Explicit fallthrough. */
1165 case AVB_ALGORITHM_TYPE_NONE:
1166 case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
1167 case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
1168 case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
1169 size_t n, prev_sz = 0, total_size = 0;
1170 uint8_t* digest = NULL;
1171 uint8_t* tbuf = NULL;
1172
1173 digest = avb_malloc(AVB_SHA256_DIGEST_SIZE);
Monika Singh0f7bfc82018-04-16 23:14:29 +05301174 if(digest == NULL)
1175 {
1176 avb_error("Failed to allocate memory\n");
1177 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1178 goto out;
1179 }
Monika Singhb15747d2017-09-25 14:01:13 +05301180 for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1181 total_size += slot_data->vbmeta_images[n].vbmeta_size;
1182 }
1183 tbuf = avb_malloc(total_size);
1184
1185 for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1186 avb_memcpy(tbuf + prev_sz, slot_data->vbmeta_images[n].vbmeta_data,
1187 slot_data->vbmeta_images[n].vbmeta_size);
1188 prev_sz = slot_data->vbmeta_images[n].vbmeta_size;
1189 }
1190 hash_find((unsigned char *)tbuf, total_size, digest, CRYPTO_AUTH_ALG_SHA256);
1191 avb_free(tbuf);
1192
1193 if (!cmdline_append_option(
1194 slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
1195 !cmdline_append_uint64_base10(
1196 slot_data, "androidboot.vbmeta.size", total_size) ||
1197 !cmdline_append_hex(slot_data,
1198 "androidboot.vbmeta.digest",
1199 digest,
1200 AVB_SHA256_DIGEST_SIZE)) {
1201 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1202 if (digest)
1203 avb_free(digest);
1204 goto out;
1205 }
1206 if (digest)
1207 avb_free(digest);
1208 } break;
1209 /* Explicit fallthrough. */
1210 case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
1211 case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
1212 case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
1213 AvbSHA512Ctx ctx;
1214 size_t n, total_size = 0;
1215 avb_sha512_init(&ctx);
1216 for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1217 avb_sha512_update(&ctx,
1218 slot_data->vbmeta_images[n].vbmeta_data,
1219 slot_data->vbmeta_images[n].vbmeta_size);
1220 total_size += slot_data->vbmeta_images[n].vbmeta_size;
1221 }
1222 if (!cmdline_append_option(
1223 slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
1224 !cmdline_append_uint64_base10(
1225 slot_data, "androidboot.vbmeta.size", total_size) ||
1226 !cmdline_append_hex(slot_data,
1227 "androidboot.vbmeta.digest",
1228 avb_sha512_final(&ctx),
1229 AVB_SHA512_DIGEST_SIZE)) {
1230 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1231 goto out;
1232 }
1233 } break;
1234 case _AVB_ALGORITHM_NUM_TYPES:
1235 avb_assert_not_reached();
1236 break;
1237 }
1238
1239 /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
1240 if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
1241 verity_mode = "disabled";
1242 } else {
1243 const char* dm_verity_mode = NULL;
1244 char* new_ret;
1245
1246 switch (hashtree_error_mode) {
1247 case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
1248 if (!cmdline_append_option(
1249 slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
1250 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1251 goto out;
1252 }
1253 verity_mode = "enforcing";
1254 dm_verity_mode = "restart_on_corruption";
1255 break;
1256 case AVB_HASHTREE_ERROR_MODE_RESTART:
1257 verity_mode = "enforcing";
1258 dm_verity_mode = "restart_on_corruption";
1259 break;
1260 case AVB_HASHTREE_ERROR_MODE_EIO:
1261 verity_mode = "eio";
1262 /* For now there's no option to specify the EIO mode. So
1263 * just use 'ignore_zero_blocks' since that's already set
1264 * and dm-verity-target.c supports specifying this multiple
1265 * times.
1266 */
1267 dm_verity_mode = "ignore_zero_blocks";
1268 break;
1269 case AVB_HASHTREE_ERROR_MODE_LOGGING:
1270 verity_mode = "logging";
1271 dm_verity_mode = "ignore_corruption";
1272 break;
1273 }
1274 new_ret = avb_replace(
1275 slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
1276 avb_free(slot_data->cmdline);
1277 slot_data->cmdline = new_ret;
1278 if (slot_data->cmdline == NULL) {
1279 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1280 goto out;
1281 }
1282 }
1283 if (!cmdline_append_option(
1284 slot_data, "androidboot.veritymode", verity_mode)) {
1285 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1286 goto out;
1287 }
1288
1289 ret = AVB_SLOT_VERIFY_RESULT_OK;
1290
1291out:
1292
1293 return ret;
1294}
1295
1296AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
1297 const char* const* requested_partitions,
1298 const char* ab_suffix,
1299 AvbSlotVerifyFlags flags,
1300 AvbHashtreeErrorMode hashtree_error_mode,
1301 AvbSlotVerifyData** out_data) {
1302 AvbSlotVerifyResult ret;
1303 AvbSlotVerifyData* slot_data = NULL;
1304 AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
1305 bool using_boot_for_vbmeta = false;
1306 AvbVBMetaImageHeader toplevel_vbmeta;
1307 bool allow_verification_error =
1308 (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
1309
1310 /* Fail early if we're missing the AvbOps needed for slot verification.
1311 *
1312 * For now, handle get_size_of_partition() not being implemented. In
1313 * a later release we may change that.
1314 */
1315 avb_assert(ops->read_is_device_unlocked != NULL);
1316 avb_assert(ops->read_from_partition != NULL);
1317 avb_assert(ops->validate_vbmeta_public_key != NULL);
1318 avb_assert(ops->read_rollback_index != NULL);
1319 avb_assert(ops->get_unique_guid_for_partition != NULL);
1320 /* avb_assert(ops->get_size_of_partition != NULL); */
1321
1322 if (out_data != NULL) {
1323 *out_data = NULL;
1324 }
1325
1326 /* Allowing dm-verity errors defeats the purpose of verified boot so
1327 * only allow this if set up to allow verification errors
1328 * (e.g. typically only UNLOCKED mode).
1329 */
1330 if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
1331 !allow_verification_error) {
1332 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1333 goto fail;
1334 }
1335
1336 slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
1337 if (slot_data == NULL) {
1338 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1339 goto fail;
1340 }
1341 slot_data->vbmeta_images =
1342 avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
1343 if (slot_data->vbmeta_images == NULL) {
1344 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1345 goto fail;
1346 }
1347 slot_data->loaded_partitions =
1348 avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
1349 if (slot_data->loaded_partitions == NULL) {
1350 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1351 goto fail;
1352 }
1353
1354 ret = load_and_verify_vbmeta(ops,
1355 requested_partitions,
1356 ab_suffix,
1357 allow_verification_error,
1358 0 /* toplevel_vbmeta_flags */,
1359 0 /* rollback_index_location */,
1360 "vbmeta",
1361 avb_strlen("vbmeta"),
1362 NULL /* expected_public_key */,
1363 0 /* expected_public_key_length */,
1364 slot_data,
1365 &algorithm_type);
1366 if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1367 goto fail;
1368 }
1369
1370 /* If things check out, mangle the kernel command-line as needed. */
1371 if (result_should_continue(ret)) {
1372 if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
1373 avb_assert(
1374 avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
1375 using_boot_for_vbmeta = true;
1376 }
1377
1378 /* Byteswap top-level vbmeta header since we'll need it below. */
1379 avb_vbmeta_image_header_to_host_byte_order(
1380 (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
1381 &toplevel_vbmeta);
1382
1383 /* Fill in |ab_suffix| field. */
1384 slot_data->ab_suffix = avb_strdup(ab_suffix);
1385 if (slot_data->ab_suffix == NULL) {
1386 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1387 goto fail;
1388 }
1389
1390 /* If verification is disabled, we are done ... we specifically
1391 * don't want to add any androidboot.* options since verification
1392 * is disabled.
1393 */
1394 if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
1395 /* Since verification is disabled we didn't process any
1396 * descriptors and thus there's no cmdline... so set root= such
1397 * that the system partition is mounted.
1398 */
1399 avb_assert(slot_data->cmdline == NULL);
1400 slot_data->cmdline =
1401 avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
1402 if (slot_data->cmdline == NULL) {
1403 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1404 goto fail;
1405 }
1406 } else {
1407 /* Add options - any failure in append_options() is either an
1408 * I/O or OOM error.
1409 */
1410 AvbSlotVerifyResult sub_ret = append_options(ops,
1411 slot_data,
1412 &toplevel_vbmeta,
1413 algorithm_type,
1414 hashtree_error_mode);
1415 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1416 ret = sub_ret;
1417 goto fail;
1418 }
1419 }
1420
1421 /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1422 if (slot_data->cmdline != NULL) {
1423 char* new_cmdline;
1424 new_cmdline = sub_cmdline(
1425 ops, slot_data->cmdline, ab_suffix, using_boot_for_vbmeta);
1426 if (new_cmdline == NULL) {
1427 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1428 goto fail;
1429 }
1430 avb_free(slot_data->cmdline);
1431 slot_data->cmdline = new_cmdline;
1432 }
1433
1434 if (out_data != NULL) {
1435 *out_data = slot_data;
1436 } else {
1437 avb_slot_verify_data_free(slot_data);
1438 }
1439 }
1440
1441 if (!allow_verification_error) {
1442 avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1443 }
1444
1445 return ret;
1446
1447fail:
1448 if (slot_data != NULL) {
1449 avb_slot_verify_data_free(slot_data);
1450 }
1451 return ret;
1452}
1453
1454void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1455 if (data->ab_suffix != NULL) {
1456 avb_free(data->ab_suffix);
1457 }
1458 if (data->cmdline != NULL) {
1459 avb_free(data->cmdline);
1460 }
1461 if (data->vbmeta_images != NULL) {
1462 size_t n;
1463 for (n = 0; n < data->num_vbmeta_images; n++) {
1464 AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
1465 if (vbmeta_image->partition_name != NULL) {
1466 avb_free(vbmeta_image->partition_name);
1467 }
1468 if (vbmeta_image->vbmeta_data != NULL) {
1469 vbmeta_image->vbmeta_data = NULL;
1470 }
1471 }
1472 avb_free(data->vbmeta_images);
1473 }
1474 if (data->loaded_partitions != NULL) {
1475 size_t n;
1476 for (n = 0; n < data->num_loaded_partitions; n++) {
1477 AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1478 if (loaded_partition->partition_name != NULL) {
1479 avb_free(loaded_partition->partition_name);
1480 }
1481 if (loaded_partition->data != NULL) {
1482 if (data->num_loaded_partitions == 1)
1483 loaded_partition->data = NULL;
1484 }
1485 }
1486 avb_free(data->loaded_partitions);
1487 }
1488 avb_free(data);
1489}
1490
1491const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
1492 const char* ret = NULL;
1493
1494 switch (result) {
1495 case AVB_SLOT_VERIFY_RESULT_OK:
1496 ret = "OK";
1497 break;
1498 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
1499 ret = "ERROR_OOM";
1500 break;
1501 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
1502 ret = "ERROR_IO";
1503 break;
1504 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
1505 ret = "ERROR_VERIFICATION";
1506 break;
1507 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
1508 ret = "ERROR_ROLLBACK_INDEX";
1509 break;
1510 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
1511 ret = "ERROR_PUBLIC_KEY_REJECTED";
1512 break;
1513 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
1514 ret = "ERROR_INVALID_METADATA";
1515 break;
1516 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1517 ret = "ERROR_UNSUPPORTED_VERSION";
1518 break;
1519 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
1520 ret = "ERROR_INVALID_ARGUMENT";
1521 break;
1522 /* Do not add a 'default:' case here because of -Wswitch. */
1523 }
1524
1525 if (ret == NULL) {
1526 avb_error("Unknown AvbSlotVerifyResult value.\n");
1527 ret = "(unknown)";
1528 }
1529
1530 return ret;
1531}