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