avb_slot_verify.c revision 4b6a634e48353da1e119ebe0287299f7b919d778
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 "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 34/* Maximum allow length (in bytes) of a partition name, including 35 * ab_suffix. 36 */ 37#define PART_NAME_MAX_SIZE 32 38 39/* Maximum number of partitions that can be loaded with avb_slot_verify(). */ 40#define MAX_NUMBER_OF_LOADED_PARTITIONS 32 41 42/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */ 43#define MAX_NUMBER_OF_VBMETA_IMAGES 32 44 45/* Maximum size of a vbmeta image - 64 KiB. */ 46#define VBMETA_MAX_SIZE (64 * 1024) 47 48/* Helper function to see if we should continue with verification in 49 * allow_verification_error=true mode if something goes wrong. See the 50 * comments for the avb_slot_verify() function for more information. 51 */ 52static inline bool result_should_continue(AvbSlotVerifyResult result) { 53 switch (result) { 54 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM: 55 case AVB_SLOT_VERIFY_RESULT_ERROR_IO: 56 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA: 57 return false; 58 59 case AVB_SLOT_VERIFY_RESULT_OK: 60 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: 61 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX: 62 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED: 63 return true; 64 } 65 66 return false; 67} 68 69static AvbSlotVerifyResult load_and_verify_hash_partition( 70 AvbOps* ops, 71 const char* const* requested_partitions, 72 const char* ab_suffix, 73 bool allow_verification_error, 74 const AvbDescriptor* descriptor, 75 AvbSlotVerifyData* slot_data) { 76 AvbHashDescriptor hash_desc; 77 const uint8_t* desc_partition_name = NULL; 78 const uint8_t* desc_salt; 79 const uint8_t* desc_digest; 80 char part_name[PART_NAME_MAX_SIZE]; 81 AvbSlotVerifyResult ret; 82 AvbIOResult io_ret; 83 uint8_t* image_buf = NULL; 84 size_t part_num_read; 85 uint8_t* digest; 86 size_t digest_len; 87 const char* found; 88 89 if (!avb_hash_descriptor_validate_and_byteswap( 90 (const AvbHashDescriptor*)descriptor, &hash_desc)) { 91 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 92 goto out; 93 } 94 95 desc_partition_name = 96 ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor); 97 desc_salt = desc_partition_name + hash_desc.partition_name_len; 98 desc_digest = desc_salt + hash_desc.salt_len; 99 100 if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) { 101 avb_error("Partition name is not valid UTF-8.\n"); 102 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 103 goto out; 104 } 105 106 if (!avb_str_concat(part_name, 107 sizeof part_name, 108 (const char*)desc_partition_name, 109 hash_desc.partition_name_len, 110 ab_suffix, 111 avb_strlen(ab_suffix))) { 112 avb_error("Partition name and suffix does not fit.\n"); 113 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 114 goto out; 115 } 116 117 image_buf = avb_malloc(hash_desc.image_size); 118 if (image_buf == NULL) { 119 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 120 goto out; 121 } 122 123 io_ret = ops->read_from_partition(ops, 124 part_name, 125 0 /* offset */, 126 hash_desc.image_size, 127 image_buf, 128 &part_num_read); 129 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 130 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 131 goto out; 132 } else if (io_ret != AVB_IO_RESULT_OK) { 133 avb_errorv(part_name, ": Error loading data from partition.\n", NULL); 134 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; 135 goto out; 136 } 137 if (part_num_read != hash_desc.image_size) { 138 avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL); 139 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; 140 goto out; 141 } 142 143 if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) { 144 AvbSHA256Ctx sha256_ctx; 145 avb_sha256_init(&sha256_ctx); 146 avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len); 147 avb_sha256_update(&sha256_ctx, image_buf, hash_desc.image_size); 148 digest = avb_sha256_final(&sha256_ctx); 149 digest_len = AVB_SHA256_DIGEST_SIZE; 150 } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) { 151 AvbSHA512Ctx sha512_ctx; 152 avb_sha512_init(&sha512_ctx); 153 avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len); 154 avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size); 155 digest = avb_sha512_final(&sha512_ctx); 156 digest_len = AVB_SHA512_DIGEST_SIZE; 157 } else { 158 avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL); 159 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 160 goto out; 161 } 162 163 if (digest_len != hash_desc.digest_len) { 164 avb_errorv( 165 part_name, ": Digest in descriptor not of expected size.\n", NULL); 166 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 167 goto out; 168 } 169 170 if (avb_safe_memcmp(digest, desc_digest, digest_len) != 0) { 171 avb_errorv(part_name, 172 ": Hash of data does not match digest in descriptor.\n", 173 NULL); 174 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION; 175 goto out; 176 } 177 178 ret = AVB_SLOT_VERIFY_RESULT_OK; 179 180out: 181 182 if (ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) { 183 /* If this is the requested partition, copy to slot_data. */ 184 found = avb_strv_find_str(requested_partitions, 185 (const char*)desc_partition_name, 186 hash_desc.partition_name_len); 187 if (found != NULL) { 188 AvbPartitionData* loaded_partition; 189 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) { 190 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL); 191 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 192 goto fail; 193 } 194 loaded_partition = 195 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++]; 196 loaded_partition->partition_name = avb_strdup(found); 197 loaded_partition->data_size = hash_desc.image_size; 198 loaded_partition->data = image_buf; 199 image_buf = NULL; 200 } 201 } 202 203fail: 204 if (image_buf != NULL) { 205 avb_free(image_buf); 206 } 207 return ret; 208} 209 210static AvbSlotVerifyResult load_and_verify_vbmeta( 211 AvbOps* ops, 212 const char* const* requested_partitions, 213 const char* ab_suffix, 214 bool allow_verification_error, 215 AvbVBMetaImageFlags toplevel_vbmeta_flags, 216 int rollback_index_location, 217 const char* partition_name, 218 size_t partition_name_len, 219 const uint8_t* expected_public_key, 220 size_t expected_public_key_length, 221 AvbSlotVerifyData* slot_data, 222 AvbAlgorithmType* out_algorithm_type) { 223 char full_partition_name[PART_NAME_MAX_SIZE]; 224 AvbSlotVerifyResult ret; 225 AvbIOResult io_ret; 226 size_t vbmeta_offset; 227 size_t vbmeta_size; 228 uint8_t* vbmeta_buf = NULL; 229 size_t vbmeta_num_read; 230 AvbVBMetaVerifyResult vbmeta_ret; 231 const uint8_t* pk_data; 232 size_t pk_len; 233 AvbVBMetaImageHeader vbmeta_header; 234 uint64_t stored_rollback_index; 235 const AvbDescriptor** descriptors = NULL; 236 size_t num_descriptors; 237 size_t n; 238 int is_main_vbmeta; 239 AvbVBMetaData* vbmeta_image_data = NULL; 240 241 ret = AVB_SLOT_VERIFY_RESULT_OK; 242 243 avb_assert(slot_data != NULL); 244 245 is_main_vbmeta = (avb_strcmp(partition_name, "vbmeta") == 0); 246 247 if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) { 248 avb_error("Partition name is not valid UTF-8.\n"); 249 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 250 goto out; 251 } 252 253 /* Construct full partition name. */ 254 if (!avb_str_concat(full_partition_name, 255 sizeof full_partition_name, 256 partition_name, 257 partition_name_len, 258 ab_suffix, 259 avb_strlen(ab_suffix))) { 260 avb_error("Partition name and suffix does not fit.\n"); 261 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 262 goto out; 263 } 264 265 avb_debugv("Loading vbmeta struct from partition '", 266 full_partition_name, 267 "'.\n", 268 NULL); 269 270 /* If we're loading from the main vbmeta partition, the vbmeta 271 * struct is in the beginning. Otherwise we have to locate it via a 272 * footer. 273 */ 274 if (is_main_vbmeta) { 275 vbmeta_offset = 0; 276 vbmeta_size = VBMETA_MAX_SIZE; 277 } else { 278 uint8_t footer_buf[AVB_FOOTER_SIZE]; 279 size_t footer_num_read; 280 AvbFooter footer; 281 282 io_ret = ops->read_from_partition(ops, 283 full_partition_name, 284 -AVB_FOOTER_SIZE, 285 AVB_FOOTER_SIZE, 286 footer_buf, 287 &footer_num_read); 288 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 289 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 290 goto out; 291 } else if (io_ret != AVB_IO_RESULT_OK) { 292 avb_errorv(full_partition_name, ": Error loading footer.\n", NULL); 293 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; 294 goto out; 295 } 296 avb_assert(footer_num_read == AVB_FOOTER_SIZE); 297 298 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf, 299 &footer)) { 300 avb_errorv(full_partition_name, ": Error validating footer.\n", NULL); 301 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 302 goto out; 303 } 304 305 /* Basic footer sanity check since the data is untrusted. */ 306 if (footer.vbmeta_size > VBMETA_MAX_SIZE) { 307 avb_errorv( 308 full_partition_name, ": Invalid vbmeta size in footer.\n", NULL); 309 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 310 goto out; 311 } 312 313 vbmeta_offset = footer.vbmeta_offset; 314 vbmeta_size = footer.vbmeta_size; 315 } 316 317 vbmeta_buf = avb_malloc(vbmeta_size); 318 if (vbmeta_buf == NULL) { 319 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 320 goto out; 321 } 322 323 io_ret = ops->read_from_partition(ops, 324 full_partition_name, 325 vbmeta_offset, 326 vbmeta_size, 327 vbmeta_buf, 328 &vbmeta_num_read); 329 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 330 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 331 goto out; 332 } else if (io_ret != AVB_IO_RESULT_OK) { 333 avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL); 334 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; 335 goto out; 336 } 337 avb_assert(vbmeta_num_read <= vbmeta_size); 338 339 /* Check if the image is properly signed and get the public key used 340 * to sign the image. 341 */ 342 vbmeta_ret = 343 avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len); 344 switch (vbmeta_ret) { 345 case AVB_VBMETA_VERIFY_RESULT_OK: 346 avb_assert(pk_data != NULL && pk_len > 0); 347 break; 348 349 case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED: 350 case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH: 351 case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH: 352 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION; 353 avb_errorv(full_partition_name, 354 ": Error verifying vbmeta image: ", 355 avb_vbmeta_verify_result_to_string(vbmeta_ret), 356 "\n", 357 NULL); 358 if (!allow_verification_error) { 359 goto out; 360 } 361 break; 362 363 case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER: 364 /* No way to continue this case. */ 365 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 366 avb_errorv(full_partition_name, 367 ": Error verifying vbmeta image: invalid vbmeta header\n", 368 NULL); 369 goto out; 370 } 371 372 /* Byteswap the header. */ 373 avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf, 374 &vbmeta_header); 375 376 /* If we're the toplevel, assign flags so they'll be passed down. */ 377 if (is_main_vbmeta) { 378 toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags; 379 } else { 380 if (vbmeta_header.flags != 0) { 381 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 382 avb_errorv(full_partition_name, 383 ": chained vbmeta image has non-zero flags\n", 384 NULL); 385 goto out; 386 } 387 } 388 389 /* Check if key used to make signature matches what is expected. */ 390 if (pk_data != NULL) { 391 if (expected_public_key != NULL) { 392 avb_assert(!is_main_vbmeta); 393 if (expected_public_key_length != pk_len || 394 avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) { 395 avb_errorv(full_partition_name, 396 ": Public key used to sign data does not match key in chain " 397 "partition descriptor.\n", 398 NULL); 399 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED; 400 if (!allow_verification_error) { 401 goto out; 402 } 403 } 404 } else { 405 bool key_is_trusted = false; 406 const uint8_t* pk_metadata = NULL; 407 size_t pk_metadata_len = 0; 408 409 if (vbmeta_header.public_key_metadata_size > 0) { 410 pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) + 411 vbmeta_header.authentication_data_block_size + 412 vbmeta_header.public_key_metadata_offset; 413 pk_metadata_len = vbmeta_header.public_key_metadata_size; 414 } 415 416 avb_assert(is_main_vbmeta); 417 io_ret = ops->validate_vbmeta_public_key( 418 ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted); 419 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 420 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 421 goto out; 422 } else if (io_ret != AVB_IO_RESULT_OK) { 423 avb_errorv(full_partition_name, 424 ": Error while checking public key used to sign data.\n", 425 NULL); 426 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; 427 goto out; 428 } 429 if (!key_is_trusted) { 430 avb_errorv(full_partition_name, 431 ": Public key used to sign data rejected.\n", 432 NULL); 433 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED; 434 if (!allow_verification_error) { 435 goto out; 436 } 437 } 438 } 439 } 440 441 /* Check rollback index. */ 442 io_ret = ops->read_rollback_index( 443 ops, rollback_index_location, &stored_rollback_index); 444 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 445 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 446 goto out; 447 } else if (io_ret != AVB_IO_RESULT_OK) { 448 avb_errorv(full_partition_name, 449 ": Error getting rollback index for location.\n", 450 NULL); 451 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; 452 goto out; 453 } 454 if (vbmeta_header.rollback_index < stored_rollback_index) { 455 avb_errorv( 456 full_partition_name, 457 ": Image rollback index is less than the stored rollback index.\n", 458 NULL); 459 ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX; 460 if (!allow_verification_error) { 461 goto out; 462 } 463 } 464 465 /* Copy vbmeta to vbmeta_images before recursing. */ 466 if (is_main_vbmeta) { 467 avb_assert(slot_data->num_vbmeta_images == 0); 468 } else { 469 avb_assert(slot_data->num_vbmeta_images > 0); 470 } 471 if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) { 472 avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL); 473 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 474 goto out; 475 } 476 vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++]; 477 vbmeta_image_data->partition_name = avb_strdup(partition_name); 478 vbmeta_image_data->vbmeta_data = vbmeta_buf; 479 /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long 480 * and this includes data past the end of the image. Pass the 481 * actual size of the vbmeta image. Also, no need to use 482 * avb_safe_add() since the header has already been verified. 483 */ 484 vbmeta_image_data->vbmeta_size = 485 sizeof(AvbVBMetaImageHeader) + 486 vbmeta_header.authentication_data_block_size + 487 vbmeta_header.auxiliary_data_block_size; 488 vbmeta_image_data->verify_result = vbmeta_ret; 489 490 /* Now go through all descriptors and take the appropriate action: 491 * 492 * - hash descriptor: Load data from partition, calculate hash, and 493 * checks that it matches what's in the hash descriptor. 494 * 495 * - hashtree descriptor: Do nothing since verification happens 496 * on-the-fly from within the OS. 497 * 498 * - chained partition descriptor: Load the footer, load the vbmeta 499 * image, verify vbmeta image (includes rollback checks, hash 500 * checks, bail on chained partitions). 501 */ 502 descriptors = 503 avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors); 504 for (n = 0; n < num_descriptors; n++) { 505 AvbDescriptor desc; 506 507 if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) { 508 avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL); 509 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 510 goto out; 511 } 512 513 switch (desc.tag) { 514 case AVB_DESCRIPTOR_TAG_HASH: { 515 AvbSlotVerifyResult sub_ret; 516 sub_ret = load_and_verify_hash_partition(ops, 517 requested_partitions, 518 ab_suffix, 519 allow_verification_error, 520 descriptors[n], 521 slot_data); 522 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) { 523 ret = sub_ret; 524 if (!allow_verification_error || !result_should_continue(ret)) { 525 goto out; 526 } 527 } 528 } break; 529 530 case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: { 531 AvbSlotVerifyResult sub_ret; 532 AvbChainPartitionDescriptor chain_desc; 533 const uint8_t* chain_partition_name; 534 const uint8_t* chain_public_key; 535 536 /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */ 537 if (!is_main_vbmeta) { 538 avb_errorv(full_partition_name, 539 ": Encountered chain descriptor not in main image.\n", 540 NULL); 541 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 542 goto out; 543 } 544 545 if (!avb_chain_partition_descriptor_validate_and_byteswap( 546 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) { 547 avb_errorv(full_partition_name, 548 ": Chain partition descriptor is invalid.\n", 549 NULL); 550 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 551 goto out; 552 } 553 554 chain_partition_name = ((const uint8_t*)descriptors[n]) + 555 sizeof(AvbChainPartitionDescriptor); 556 chain_public_key = chain_partition_name + chain_desc.partition_name_len; 557 558 sub_ret = load_and_verify_vbmeta(ops, 559 requested_partitions, 560 ab_suffix, 561 allow_verification_error, 562 toplevel_vbmeta_flags, 563 chain_desc.rollback_index_location, 564 (const char*)chain_partition_name, 565 chain_desc.partition_name_len, 566 chain_public_key, 567 chain_desc.public_key_len, 568 slot_data, 569 NULL /* out_algorithm_type */); 570 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) { 571 ret = sub_ret; 572 if (!result_should_continue(ret)) { 573 goto out; 574 } 575 } 576 } break; 577 578 case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: { 579 const uint8_t* kernel_cmdline; 580 AvbKernelCmdlineDescriptor kernel_cmdline_desc; 581 bool apply_cmdline; 582 583 if (!avb_kernel_cmdline_descriptor_validate_and_byteswap( 584 (AvbKernelCmdlineDescriptor*)descriptors[n], 585 &kernel_cmdline_desc)) { 586 avb_errorv(full_partition_name, 587 ": Kernel cmdline descriptor is invalid.\n", 588 NULL); 589 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 590 goto out; 591 } 592 593 kernel_cmdline = ((const uint8_t*)descriptors[n]) + 594 sizeof(AvbKernelCmdlineDescriptor); 595 596 if (!avb_validate_utf8(kernel_cmdline, 597 kernel_cmdline_desc.kernel_cmdline_length)) { 598 avb_errorv(full_partition_name, 599 ": Kernel cmdline is not valid UTF-8.\n", 600 NULL); 601 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 602 goto out; 603 } 604 605 /* Compare the flags for top-level VBMeta struct with flags in 606 * the command-line descriptor so command-line snippets only 607 * intended for a certain mode (dm-verity enabled/disabled) 608 * are skipped if applicable. 609 */ 610 apply_cmdline = true; 611 if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) { 612 if (kernel_cmdline_desc.flags & 613 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) { 614 apply_cmdline = false; 615 } 616 } else { 617 if (kernel_cmdline_desc.flags & 618 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) { 619 apply_cmdline = false; 620 } 621 } 622 623 if (apply_cmdline) { 624 if (slot_data->cmdline == NULL) { 625 slot_data->cmdline = 626 avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1); 627 if (slot_data->cmdline == NULL) { 628 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 629 goto out; 630 } 631 avb_memcpy(slot_data->cmdline, 632 kernel_cmdline, 633 kernel_cmdline_desc.kernel_cmdline_length); 634 } else { 635 /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */ 636 size_t orig_size = avb_strlen(slot_data->cmdline); 637 size_t new_size = 638 orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1; 639 char* new_cmdline = avb_calloc(new_size); 640 if (new_cmdline == NULL) { 641 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 642 goto out; 643 } 644 avb_memcpy(new_cmdline, slot_data->cmdline, orig_size); 645 new_cmdline[orig_size] = ' '; 646 avb_memcpy(new_cmdline + orig_size + 1, 647 kernel_cmdline, 648 kernel_cmdline_desc.kernel_cmdline_length); 649 avb_free(slot_data->cmdline); 650 slot_data->cmdline = new_cmdline; 651 } 652 } 653 } break; 654 655 /* Explicit fall-through */ 656 case AVB_DESCRIPTOR_TAG_PROPERTY: 657 case AVB_DESCRIPTOR_TAG_HASHTREE: 658 /* Do nothing. */ 659 break; 660 } 661 } 662 663 if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) { 664 avb_errorv( 665 full_partition_name, ": Invalid rollback_index_location.\n", NULL); 666 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; 667 goto out; 668 } 669 670 slot_data->rollback_indexes[rollback_index_location] = 671 vbmeta_header.rollback_index; 672 673 if (out_algorithm_type != NULL) { 674 *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type; 675 } 676 677out: 678 /* If |vbmeta_image_data| isn't NULL it means that it adopted 679 * |vbmeta_buf| so in that case don't free it here. 680 */ 681 if (vbmeta_image_data == NULL) { 682 if (vbmeta_buf != NULL) { 683 avb_free(vbmeta_buf); 684 } 685 } 686 if (descriptors != NULL) { 687 avb_free(descriptors); 688 } 689 return ret; 690} 691 692#define NUM_GUIDS 3 693 694/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with 695 * values. Returns NULL on OOM, otherwise the cmdline with values 696 * replaced. 697 */ 698static char* sub_cmdline(AvbOps* ops, 699 const char* cmdline, 700 const char* ab_suffix) { 701 const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"}; 702 const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)", 703 "$(ANDROID_BOOT_PARTUUID)", 704 "$(ANDROID_VBMETA_PARTUUID)"}; 705 char* ret = NULL; 706 AvbIOResult io_ret; 707 708 /* Replace unique partition GUIDs */ 709 for (size_t n = 0; n < NUM_GUIDS; n++) { 710 char part_name[PART_NAME_MAX_SIZE]; 711 char guid_buf[37]; 712 char* new_ret; 713 714 if (!avb_str_concat(part_name, 715 sizeof part_name, 716 part_name_str[n], 717 avb_strlen(part_name_str[n]), 718 ab_suffix, 719 avb_strlen(ab_suffix))) { 720 avb_error("Partition name and suffix does not fit.\n"); 721 goto fail; 722 } 723 724 io_ret = ops->get_unique_guid_for_partition( 725 ops, part_name, guid_buf, sizeof guid_buf); 726 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 727 return NULL; 728 } else if (io_ret != AVB_IO_RESULT_OK) { 729 avb_error("Error getting unique GUID for partition.\n"); 730 goto fail; 731 } 732 733 if (ret == NULL) { 734 new_ret = avb_replace(cmdline, replace_str[n], guid_buf); 735 } else { 736 new_ret = avb_replace(ret, replace_str[n], guid_buf); 737 } 738 if (new_ret == NULL) { 739 goto fail; 740 } 741 ret = new_ret; 742 } 743 744 return ret; 745 746fail: 747 if (ret != NULL) { 748 avb_free(ret); 749 } 750 return NULL; 751} 752 753static int cmdline_append_option(AvbSlotVerifyData* slot_data, 754 const char* key, 755 const char* value) { 756 size_t offset, key_len, value_len; 757 char* new_cmdline; 758 759 key_len = avb_strlen(key); 760 value_len = avb_strlen(value); 761 762 offset = 0; 763 if (slot_data->cmdline != NULL) { 764 offset = avb_strlen(slot_data->cmdline); 765 if (offset > 0) { 766 offset += 1; 767 } 768 } 769 770 new_cmdline = avb_calloc(offset + key_len + value_len + 2); 771 if (new_cmdline == NULL) { 772 return 0; 773 } 774 if (offset > 0) { 775 avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1); 776 new_cmdline[offset - 1] = ' '; 777 } 778 avb_memcpy(new_cmdline + offset, key, key_len); 779 new_cmdline[offset + key_len] = '='; 780 avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len); 781 if (slot_data->cmdline != NULL) { 782 avb_free(slot_data->cmdline); 783 } 784 slot_data->cmdline = new_cmdline; 785 786 return 1; 787} 788 789static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data, 790 const char* key, 791 uint64_t value) { 792 const int MAX_DIGITS = 32; 793 char rev_digits[MAX_DIGITS]; 794 char digits[MAX_DIGITS]; 795 size_t n, num_digits; 796 797 for (num_digits = 0; num_digits < MAX_DIGITS - 1;) { 798 rev_digits[num_digits++] = (value % 10) + '0'; 799 value /= 10; 800 if (value == 0) { 801 break; 802 } 803 } 804 805 for (n = 0; n < num_digits; n++) { 806 digits[n] = rev_digits[num_digits - 1 - n]; 807 } 808 digits[n] = '\0'; 809 810 return cmdline_append_option(slot_data, key, digits); 811} 812 813static int cmdline_append_hex(AvbSlotVerifyData* slot_data, 814 const char* key, 815 const uint8_t* data, 816 size_t data_len) { 817 char hex_digits[17] = "0123456789abcdef"; 818 char* hex_data; 819 int ret; 820 size_t n; 821 822 hex_data = avb_malloc(data_len * 2 + 1); 823 if (hex_data == NULL) { 824 return 0; 825 } 826 827 for (n = 0; n < data_len; n++) { 828 hex_data[n * 2] = hex_digits[data[n] >> 4]; 829 hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f]; 830 } 831 hex_data[n * 2] = '\0'; 832 833 ret = cmdline_append_option(slot_data, key, hex_data); 834 avb_free(hex_data); 835 return ret; 836} 837 838AvbSlotVerifyResult avb_slot_verify(AvbOps* ops, 839 const char* const* requested_partitions, 840 const char* ab_suffix, 841 bool allow_verification_error, 842 AvbSlotVerifyData** out_data) { 843 AvbSlotVerifyResult ret; 844 AvbSlotVerifyData* slot_data = NULL; 845 AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE; 846 AvbIOResult io_ret; 847 848 if (out_data != NULL) { 849 *out_data = NULL; 850 } 851 852 slot_data = avb_calloc(sizeof(AvbSlotVerifyData)); 853 if (slot_data == NULL) { 854 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 855 goto fail; 856 } 857 slot_data->vbmeta_images = 858 avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES); 859 if (slot_data->vbmeta_images == NULL) { 860 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 861 goto fail; 862 } 863 slot_data->loaded_partitions = 864 avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS); 865 if (slot_data->loaded_partitions == NULL) { 866 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 867 goto fail; 868 } 869 870 ret = load_and_verify_vbmeta(ops, 871 requested_partitions, 872 ab_suffix, 873 allow_verification_error, 874 0, /* toplevel_vbmeta_flags */ 875 0 /* rollback_index_location */, 876 "vbmeta", 877 avb_strlen("vbmeta"), 878 NULL /* expected_public_key */, 879 0 /* expected_public_key_length */, 880 slot_data, 881 &algorithm_type); 882 if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) { 883 goto fail; 884 } 885 886 /* If things check out, mangle the kernel command-line as needed. */ 887 if (result_should_continue(ret)) { 888 /* Fill in |ab_suffix| field. */ 889 slot_data->ab_suffix = avb_strdup(ab_suffix); 890 if (slot_data->ab_suffix == NULL) { 891 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 892 goto fail; 893 } 894 895 /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */ 896 if (slot_data->cmdline != NULL) { 897 char* new_cmdline = sub_cmdline(ops, slot_data->cmdline, ab_suffix); 898 if (new_cmdline == NULL) { 899 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 900 goto fail; 901 } 902 avb_free(slot_data->cmdline); 903 slot_data->cmdline = new_cmdline; 904 } 905 906 /* Add androidboot.slot_suffix, if applicable. */ 907 if (avb_strlen(ab_suffix) > 0) { 908 if (!cmdline_append_option( 909 slot_data, "androidboot.slot_suffix", ab_suffix)) { 910 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 911 goto fail; 912 } 913 } 914 915 /* Set androidboot.avb.device_state to "locked" or "unlocked". */ 916 bool is_device_unlocked; 917 io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked); 918 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 919 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 920 goto fail; 921 } else if (io_ret != AVB_IO_RESULT_OK) { 922 avb_error("Error getting device state.\n"); 923 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; 924 goto fail; 925 } 926 if (!cmdline_append_option(slot_data, 927 "androidboot.vbmeta.device_state", 928 is_device_unlocked ? "unlocked" : "locked")) { 929 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 930 goto fail; 931 } 932 933 /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash 934 * function as is used to sign vbmeta. 935 */ 936 switch (algorithm_type) { 937 /* Explicit fallthrough. */ 938 case AVB_ALGORITHM_TYPE_NONE: 939 case AVB_ALGORITHM_TYPE_SHA256_RSA2048: 940 case AVB_ALGORITHM_TYPE_SHA256_RSA4096: 941 case AVB_ALGORITHM_TYPE_SHA256_RSA8192: { 942 AvbSHA256Ctx ctx; 943 size_t n, total_size = 0; 944 avb_sha256_init(&ctx); 945 for (n = 0; n < slot_data->num_vbmeta_images; n++) { 946 avb_sha256_update(&ctx, 947 slot_data->vbmeta_images[n].vbmeta_data, 948 slot_data->vbmeta_images[n].vbmeta_size); 949 total_size += slot_data->vbmeta_images[n].vbmeta_size; 950 } 951 if (!cmdline_append_option( 952 slot_data, "androidboot.vbmeta.hash_alg", "sha256") || 953 !cmdline_append_uint64_base10( 954 slot_data, "androidboot.vbmeta.size", total_size) || 955 !cmdline_append_hex(slot_data, 956 "androidboot.vbmeta.digest", 957 avb_sha256_final(&ctx), 958 AVB_SHA256_DIGEST_SIZE)) { 959 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 960 goto fail; 961 } 962 } break; 963 /* Explicit fallthrough. */ 964 case AVB_ALGORITHM_TYPE_SHA512_RSA2048: 965 case AVB_ALGORITHM_TYPE_SHA512_RSA4096: 966 case AVB_ALGORITHM_TYPE_SHA512_RSA8192: { 967 AvbSHA512Ctx ctx; 968 size_t n, total_size = 0; 969 ; 970 avb_sha512_init(&ctx); 971 for (n = 0; n < slot_data->num_vbmeta_images; n++) { 972 avb_sha512_update(&ctx, 973 slot_data->vbmeta_images[n].vbmeta_data, 974 slot_data->vbmeta_images[n].vbmeta_size); 975 total_size += slot_data->vbmeta_images[n].vbmeta_size; 976 } 977 if (!cmdline_append_option( 978 slot_data, "androidboot.vbmeta.hash_alg", "sha512") || 979 !cmdline_append_uint64_base10( 980 slot_data, "androidboot.vbmeta.size", total_size) || 981 !cmdline_append_hex(slot_data, 982 "androidboot.vbmeta.digest", 983 avb_sha512_final(&ctx), 984 AVB_SHA512_DIGEST_SIZE)) { 985 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; 986 goto fail; 987 } 988 } break; 989 case _AVB_ALGORITHM_NUM_TYPES: 990 avb_assert_not_reached(); 991 break; 992 } 993 994 if (out_data != NULL) { 995 *out_data = slot_data; 996 } else { 997 avb_slot_verify_data_free(slot_data); 998 } 999 } 1000 1001 if (!allow_verification_error) { 1002 avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK); 1003 } 1004 1005 return ret; 1006 1007fail: 1008 if (slot_data != NULL) { 1009 avb_slot_verify_data_free(slot_data); 1010 } 1011 return ret; 1012} 1013 1014void avb_slot_verify_data_free(AvbSlotVerifyData* data) { 1015 if (data->ab_suffix != NULL) { 1016 avb_free(data->ab_suffix); 1017 } 1018 if (data->cmdline != NULL) { 1019 avb_free(data->cmdline); 1020 } 1021 if (data->vbmeta_images != NULL) { 1022 size_t n; 1023 for (n = 0; n < data->num_vbmeta_images; n++) { 1024 AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n]; 1025 if (vbmeta_image->partition_name != NULL) { 1026 avb_free(vbmeta_image->partition_name); 1027 } 1028 if (vbmeta_image->vbmeta_data != NULL) { 1029 avb_free(vbmeta_image->vbmeta_data); 1030 } 1031 } 1032 avb_free(data->vbmeta_images); 1033 } 1034 if (data->loaded_partitions != NULL) { 1035 size_t n; 1036 for (n = 0; n < data->num_loaded_partitions; n++) { 1037 AvbPartitionData* loaded_partition = &data->loaded_partitions[n]; 1038 if (loaded_partition->partition_name != NULL) { 1039 avb_free(loaded_partition->partition_name); 1040 } 1041 if (loaded_partition->data != NULL) { 1042 avb_free(loaded_partition->data); 1043 } 1044 } 1045 avb_free(data->loaded_partitions); 1046 } 1047 avb_free(data); 1048} 1049 1050const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) { 1051 const char* ret = NULL; 1052 1053 switch (result) { 1054 case AVB_SLOT_VERIFY_RESULT_OK: 1055 ret = "OK"; 1056 break; 1057 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM: 1058 ret = "ERROR_OOM"; 1059 break; 1060 case AVB_SLOT_VERIFY_RESULT_ERROR_IO: 1061 ret = "ERROR_IO"; 1062 break; 1063 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: 1064 ret = "ERROR_VERIFICATION"; 1065 break; 1066 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX: 1067 ret = "ERROR_ROLLBACK_INDEX"; 1068 break; 1069 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED: 1070 ret = "ERROR_PUBLIC_KEY_REJECTED"; 1071 break; 1072 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA: 1073 ret = "ERROR_INVALID_METADATA"; 1074 break; 1075 /* Do not add a 'default:' case here because of -Wswitch. */ 1076 } 1077 1078 if (ret == NULL) { 1079 avb_error("Unknown AvbSlotVerifyResult value.\n"); 1080 ret = "(unknown)"; 1081 } 1082 1083 return ret; 1084} 1085