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 <android_avb/avb_ab_flow.h> 26 27 bool avb_ab_data_verify_and_byteswap(const AvbABData* src, AvbABData* dest) { 28 /* Ensure magic is correct. */ 29 if (avb_safe_memcmp(src->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) { 30 avb_error("Magic is incorrect.\n"); 31 return false; 32 } 33 34 avb_memcpy(dest, src, sizeof(AvbABData)); 35 dest->crc32 = avb_be32toh(dest->crc32); 36 37 /* Ensure we don't attempt to access any fields if the major version 38 * is not supported. 39 */ 40 if (dest->version_major > AVB_AB_MAJOR_VERSION) { 41 avb_error("No support for given major version.\n"); 42 return false; 43 } 44 45 /* Bail if CRC32 doesn't match. */ 46 if (dest->crc32 != 47 avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))) { 48 avb_error("CRC32 does not match.\n"); 49 return false; 50 } 51 52 return true; 53 } 54 55 void avb_ab_data_update_crc_and_byteswap(const AvbABData* src, 56 AvbABData* dest) { 57 avb_memcpy(dest, src, sizeof(AvbABData)); 58 dest->crc32 = avb_htobe32( 59 avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))); 60 } 61 62 void avb_ab_data_init(AvbABData* data) { 63 avb_memset(data, '\0', sizeof(AvbABData)); 64 avb_memcpy(data->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN); 65 data->version_major = AVB_AB_MAJOR_VERSION; 66 data->version_minor = AVB_AB_MINOR_VERSION; 67 data->last_boot = 0; 68 data->slots[0].priority = AVB_AB_MAX_PRIORITY; 69 data->slots[0].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; 70 data->slots[0].successful_boot = 0; 71 data->slots[1].priority = AVB_AB_MAX_PRIORITY - 1; 72 data->slots[1].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; 73 data->slots[1].successful_boot = 0; 74 } 75 76 /* The AvbABData struct is stored 2048 bytes into the 'misc' partition 77 * following the 'struct bootloader_message' field. The struct is 78 * compatible with the guidelines in bootable/recovery/bootloader.h - 79 * e.g. it is stored in the |slot_suffix| field, starts with a 80 * NUL-byte, and is 32 bytes long. 81 */ 82 #define AB_METADATA_MISC_PARTITION_OFFSET 2048 83 84 AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data) { 85 AvbOps* ops = ab_ops->ops; 86 AvbABData serialized; 87 AvbIOResult io_ret; 88 size_t num_bytes_read; 89 90 io_ret = ops->read_from_partition(ops, 91 "misc", 92 AB_METADATA_MISC_PARTITION_OFFSET, 93 sizeof(AvbABData), 94 &serialized, 95 &num_bytes_read); 96 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 97 return AVB_IO_RESULT_ERROR_OOM; 98 } else if (io_ret != AVB_IO_RESULT_OK || 99 num_bytes_read != sizeof(AvbABData)) { 100 avb_error("Error reading A/B metadata.\n"); 101 return AVB_IO_RESULT_ERROR_IO; 102 } 103 104 if (!avb_ab_data_verify_and_byteswap(&serialized, data)) { 105 avb_error( 106 "Error validating A/B metadata from disk. " 107 "Resetting and writing new A/B metadata to disk.\n"); 108 avb_ab_data_init(data); 109 return avb_ab_data_write(ab_ops, data); 110 } 111 112 return AVB_IO_RESULT_OK; 113 } 114 115 AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data) { 116 AvbOps* ops = ab_ops->ops; 117 AvbABData serialized; 118 AvbIOResult io_ret; 119 120 avb_ab_data_update_crc_and_byteswap(data, &serialized); 121 io_ret = ops->write_to_partition(ops, 122 "misc", 123 AB_METADATA_MISC_PARTITION_OFFSET, 124 sizeof(AvbABData), 125 &serialized); 126 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 127 return AVB_IO_RESULT_ERROR_OOM; 128 } else if (io_ret != AVB_IO_RESULT_OK) { 129 avb_error("Error writing A/B metadata.\n"); 130 return AVB_IO_RESULT_ERROR_IO; 131 } 132 return AVB_IO_RESULT_OK; 133 } 134 135 static bool slot_is_bootable(AvbABSlotData* slot) { 136 return slot->priority > 0 && 137 (slot->successful_boot || (slot->tries_remaining > 0)); 138 } 139 140 static void slot_set_unbootable(AvbABSlotData* slot) { 141 slot->priority = 0; 142 slot->tries_remaining = 0; 143 slot->successful_boot = 0; 144 } 145 146 /* Ensure all unbootable and/or illegal states are marked as the 147 * canonical 'unbootable' state, e.g. priority=0, tries_remaining=0, 148 * and successful_boot=0. 149 */ 150 static void slot_normalize(AvbABSlotData* slot) { 151 if (slot->priority > 0) { 152 if (slot->tries_remaining == 0 && !slot->successful_boot) { 153 /* We've exhausted all tries -> unbootable. */ 154 slot_set_unbootable(slot); 155 } 156 if (slot->tries_remaining > 0 && slot->successful_boot) { 157 /* Illegal state - avb_ab_mark_slot_successful() will clear 158 * tries_remaining when setting successful_boot. 159 */ 160 slot_set_unbootable(slot); 161 } 162 } else { 163 slot_set_unbootable(slot); 164 } 165 } 166 167 static const char* slot_suffixes[2] = {"_a", "_b"}; 168 169 /* Helper function to load metadata - returns AVB_IO_RESULT_OK on 170 * success, error code otherwise. 171 */ 172 AvbIOResult load_metadata(AvbABOps* ab_ops, 173 AvbABData* ab_data, 174 AvbABData* ab_data_orig) { 175 AvbIOResult io_ret; 176 177 io_ret = ab_ops->read_ab_metadata(ab_ops, ab_data); 178 if (io_ret != AVB_IO_RESULT_OK) { 179 avb_error("I/O error while loading A/B metadata.\n"); 180 return io_ret; 181 } 182 *ab_data_orig = *ab_data; 183 184 /* Ensure data is normalized, e.g. illegal states will be marked as 185 * unbootable and all unbootable states are represented with 186 * (priority=0, tries_remaining=0, successful_boot=0). 187 */ 188 slot_normalize(&ab_data->slots[0]); 189 slot_normalize(&ab_data->slots[1]); 190 return AVB_IO_RESULT_OK; 191 } 192 193 /* Writes A/B metadata to disk only if it has changed - returns 194 * AVB_IO_RESULT_OK on success, error code otherwise. 195 */ 196 AvbIOResult save_metadata_if_changed(AvbABOps* ab_ops, 197 AvbABData* ab_data, 198 AvbABData* ab_data_orig) { 199 if (avb_safe_memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) { 200 avb_debug("Writing A/B metadata to disk.\n"); 201 return ab_ops->write_ab_metadata(ab_ops, ab_data); 202 } 203 return AVB_IO_RESULT_OK; 204 } 205 206 AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops, 207 const char* const* requested_partitions, 208 AvbSlotVerifyFlags flags, 209 AvbHashtreeErrorMode hashtree_error_mode, 210 AvbSlotVerifyData** out_data) { 211 AvbOps* ops = ab_ops->ops; 212 AvbSlotVerifyData* slot_data[2] = {NULL, NULL}; 213 AvbSlotVerifyData* data = NULL; 214 AvbABFlowResult ret; 215 AvbABData ab_data, ab_data_orig; 216 size_t slot_index_to_boot, n; 217 AvbIOResult io_ret; 218 bool saw_and_allowed_verification_error = false; 219 220 io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); 221 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 222 ret = AVB_AB_FLOW_RESULT_ERROR_OOM; 223 goto out; 224 } else if (io_ret != AVB_IO_RESULT_OK) { 225 ret = AVB_AB_FLOW_RESULT_ERROR_IO; 226 goto out; 227 } 228 229 /* Validate all bootable slots. */ 230 for (n = 0; n < 2; n++) { 231 if (slot_is_bootable(&ab_data.slots[n])) { 232 AvbSlotVerifyResult verify_result; 233 bool set_slot_unbootable = false; 234 235 verify_result = avb_slot_verify(ops, 236 requested_partitions, 237 slot_suffixes[n], 238 flags, 239 hashtree_error_mode, 240 &slot_data[n]); 241 switch (verify_result) { 242 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM: 243 ret = AVB_AB_FLOW_RESULT_ERROR_OOM; 244 goto out; 245 246 case AVB_SLOT_VERIFY_RESULT_ERROR_IO: 247 ret = AVB_AB_FLOW_RESULT_ERROR_IO; 248 goto out; 249 250 case AVB_SLOT_VERIFY_RESULT_OK: 251 break; 252 253 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA: 254 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION: 255 /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR 256 * these mean game over. 257 */ 258 set_slot_unbootable = true; 259 break; 260 261 /* explicit fallthrough. */ 262 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: 263 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX: 264 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED: 265 if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) { 266 /* Do nothing since we allow this. */ 267 avb_debugv("Allowing slot ", 268 slot_suffixes[n], 269 " which verified " 270 "with result ", 271 avb_slot_verify_result_to_string(verify_result), 272 " because " 273 "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR " 274 "is set.\n", 275 NULL); 276 saw_and_allowed_verification_error = true; 277 } else { 278 set_slot_unbootable = true; 279 } 280 break; 281 282 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT: 283 ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT; 284 goto out; 285 /* Do not add a 'default:' case here because of -Wswitch. */ 286 } 287 288 if (set_slot_unbootable) { 289 avb_errorv("Error verifying slot ", 290 slot_suffixes[n], 291 " with result ", 292 avb_slot_verify_result_to_string(verify_result), 293 " - setting unbootable.\n", 294 NULL); 295 slot_set_unbootable(&ab_data.slots[n]); 296 } 297 } 298 } 299 300 if (slot_is_bootable(&ab_data.slots[0]) && 301 slot_is_bootable(&ab_data.slots[1])) { 302 if (ab_data.slots[1].priority > ab_data.slots[0].priority) { 303 slot_index_to_boot = 1; 304 } else { 305 slot_index_to_boot = 0; 306 } 307 } else if (slot_is_bootable(&ab_data.slots[0])) { 308 slot_index_to_boot = 0; 309 } else if (slot_is_bootable(&ab_data.slots[1])) { 310 slot_index_to_boot = 1; 311 } else { 312 /* No bootable slots! */ 313 avb_error("No bootable slots found.\n"); 314 ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS; 315 goto out; 316 } 317 318 /* Update stored rollback index such that the stored rollback index 319 * is the largest value supporting all currently bootable slots. Do 320 * this for every rollback index location. 321 */ 322 for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) { 323 uint64_t rollback_index_value = 0; 324 325 if (slot_data[0] != NULL && slot_data[1] != NULL) { 326 uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n]; 327 uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n]; 328 rollback_index_value = 329 (a_rollback_index < b_rollback_index ? a_rollback_index 330 : b_rollback_index); 331 } else if (slot_data[0] != NULL) { 332 rollback_index_value = slot_data[0]->rollback_indexes[n]; 333 } else if (slot_data[1] != NULL) { 334 rollback_index_value = slot_data[1]->rollback_indexes[n]; 335 } 336 337 if (rollback_index_value != 0) { 338 uint64_t current_rollback_index_value; 339 io_ret = ops->read_rollback_index(ops, n, ¤t_rollback_index_value); 340 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 341 ret = AVB_AB_FLOW_RESULT_ERROR_OOM; 342 goto out; 343 } else if (io_ret != AVB_IO_RESULT_OK) { 344 avb_error("Error getting rollback index for slot.\n"); 345 ret = AVB_AB_FLOW_RESULT_ERROR_IO; 346 goto out; 347 } 348 if (current_rollback_index_value != rollback_index_value) { 349 io_ret = ops->write_rollback_index(ops, n, rollback_index_value); 350 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 351 ret = AVB_AB_FLOW_RESULT_ERROR_OOM; 352 goto out; 353 } else if (io_ret != AVB_IO_RESULT_OK) { 354 avb_error("Error setting stored rollback index.\n"); 355 ret = AVB_AB_FLOW_RESULT_ERROR_IO; 356 goto out; 357 } 358 } 359 } 360 } 361 362 /* Finally, select this slot. */ 363 avb_assert(slot_data[slot_index_to_boot] != NULL); 364 data = slot_data[slot_index_to_boot]; 365 slot_data[slot_index_to_boot] = NULL; 366 if (saw_and_allowed_verification_error) { 367 avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR); 368 ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR; 369 } else { 370 ret = AVB_AB_FLOW_RESULT_OK; 371 } 372 373 /* ... and decrement tries remaining, if applicable. */ 374 if (!ab_data.slots[slot_index_to_boot].successful_boot && 375 ab_data.slots[slot_index_to_boot].tries_remaining > 0) { 376 ab_data.slots[slot_index_to_boot].tries_remaining -= 1; 377 } 378 379 out: 380 io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); 381 if (io_ret != AVB_IO_RESULT_OK) { 382 if (io_ret == AVB_IO_RESULT_ERROR_OOM) { 383 ret = AVB_AB_FLOW_RESULT_ERROR_OOM; 384 } else { 385 ret = AVB_AB_FLOW_RESULT_ERROR_IO; 386 } 387 if (data != NULL) { 388 avb_slot_verify_data_free(data); 389 data = NULL; 390 } 391 } 392 393 for (n = 0; n < 2; n++) { 394 if (slot_data[n] != NULL) { 395 avb_slot_verify_data_free(slot_data[n]); 396 } 397 } 398 399 if (out_data != NULL) { 400 *out_data = data; 401 } else { 402 if (data != NULL) { 403 avb_slot_verify_data_free(data); 404 } 405 } 406 407 return ret; 408 } 409 410 AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops, 411 unsigned int slot_number) { 412 AvbABData ab_data, ab_data_orig; 413 unsigned int other_slot_number; 414 AvbIOResult ret; 415 416 avb_assert(slot_number < 2); 417 418 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); 419 if (ret != AVB_IO_RESULT_OK) { 420 goto out; 421 } 422 423 /* Make requested slot top priority, unsuccessful, and with max tries. */ 424 ab_data.slots[slot_number].priority = AVB_AB_MAX_PRIORITY; 425 ab_data.slots[slot_number].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; 426 ab_data.slots[slot_number].successful_boot = 0; 427 428 /* Ensure other slot doesn't have as high a priority. */ 429 other_slot_number = 1 - slot_number; 430 if (ab_data.slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) { 431 ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1; 432 } 433 434 ret = AVB_IO_RESULT_OK; 435 436 out: 437 if (ret == AVB_IO_RESULT_OK) { 438 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); 439 } 440 return ret; 441 } 442 443 AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops, 444 unsigned int slot_number) { 445 AvbABData ab_data, ab_data_orig; 446 AvbIOResult ret; 447 448 avb_assert(slot_number < 2); 449 450 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); 451 if (ret != AVB_IO_RESULT_OK) { 452 goto out; 453 } 454 455 slot_set_unbootable(&ab_data.slots[slot_number]); 456 457 ret = AVB_IO_RESULT_OK; 458 459 out: 460 if (ret == AVB_IO_RESULT_OK) { 461 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); 462 } 463 return ret; 464 } 465 466 AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops, 467 unsigned int slot_number) { 468 AvbABData ab_data, ab_data_orig; 469 AvbIOResult ret; 470 471 avb_assert(slot_number < 2); 472 473 ret = load_metadata(ab_ops, &ab_data, &ab_data_orig); 474 if (ret != AVB_IO_RESULT_OK) { 475 goto out; 476 } 477 478 if (!slot_is_bootable(&ab_data.slots[slot_number])) { 479 avb_error("Cannot mark unbootable slot as successful.\n"); 480 ret = AVB_IO_RESULT_OK; 481 goto out; 482 } 483 484 ab_data.slots[slot_number].tries_remaining = 0; 485 ab_data.slots[slot_number].successful_boot = 1; 486 487 ret = AVB_IO_RESULT_OK; 488 489 out: 490 if (ret == AVB_IO_RESULT_OK) { 491 ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig); 492 } 493 return ret; 494 } 495 496 const char* avb_ab_flow_result_to_string(AvbABFlowResult result) { 497 const char* ret = NULL; 498 499 switch (result) { 500 case AVB_AB_FLOW_RESULT_OK: 501 ret = "OK"; 502 break; 503 504 case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR: 505 ret = "OK_WITH_VERIFICATION_ERROR"; 506 break; 507 508 case AVB_AB_FLOW_RESULT_ERROR_OOM: 509 ret = "ERROR_OOM"; 510 break; 511 512 case AVB_AB_FLOW_RESULT_ERROR_IO: 513 ret = "ERROR_IO"; 514 break; 515 516 case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS: 517 ret = "ERROR_NO_BOOTABLE_SLOTS"; 518 break; 519 520 case AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT: 521 ret = "ERROR_INVALID_ARGUMENT"; 522 break; 523 /* Do not add a 'default:' case here because of -Wswitch. */ 524 } 525 526 if (ret == NULL) { 527 avb_error("Unknown AvbABFlowResult value.\n"); 528 ret = "(unknown)"; 529 } 530 531 return ret; 532 } 533