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 <iostream> 26 27 #include <endian.h> 28 #include <errno.h> 29 #include <inttypes.h> 30 #include <string.h> 31 32 #include <fcntl.h> 33 #include <sys/stat.h> 34 #include <sys/types.h> 35 #include <unistd.h> 36 37 #include <base/files/file_util.h> 38 #include <base/strings/string_util.h> 39 #include <base/strings/stringprintf.h> 40 #include <openssl/rand.h> 41 #include <openssl/sha.h> 42 43 #include "fake_avb_ops.h" 44 45 namespace avb { 46 47 std::set<std::string> FakeAvbOps::get_partition_names_read_from() { 48 return partition_names_read_from_; 49 } 50 51 bool FakeAvbOps::preload_partition(const std::string& partition, 52 const base::FilePath& path) { 53 if (preloaded_partitions_.count(partition) > 0) { 54 fprintf(stderr, "Partition '%s' already preloaded\n", partition.c_str()); 55 return false; 56 } 57 58 int64_t file_size; 59 if (!base::GetFileSize(path, &file_size)) { 60 fprintf(stderr, "Error getting size of file '%s'\n", path.value().c_str()); 61 return false; 62 } 63 64 int fd = open(path.value().c_str(), O_RDONLY); 65 if (fd < 0) { 66 fprintf(stderr, 67 "Error opening file '%s': %s\n", 68 path.value().c_str(), 69 strerror(errno)); 70 return false; 71 } 72 73 uint8_t* buffer = static_cast<uint8_t*>(malloc(file_size)); 74 ssize_t num_read = read(fd, buffer, file_size); 75 if (num_read != file_size) { 76 fprintf(stderr, 77 "Error reading %zd bytes from file '%s': %s\n", 78 file_size, 79 path.value().c_str(), 80 strerror(errno)); 81 free(buffer); 82 return false; 83 } 84 close(fd); 85 86 preloaded_partitions_[partition] = buffer; 87 return true; 88 } 89 90 AvbIOResult FakeAvbOps::read_from_partition(const char* partition, 91 int64_t offset, 92 size_t num_bytes, 93 void* buffer, 94 size_t* out_num_read) { 95 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) { 96 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 97 } 98 99 base::FilePath path = 100 partition_dir_.Append(std::string(partition)).AddExtension("img"); 101 102 partition_names_read_from_.insert(partition); 103 104 if (offset < 0) { 105 int64_t file_size; 106 if (!base::GetFileSize(path, &file_size)) { 107 fprintf( 108 stderr, "Error getting size of file '%s'\n", path.value().c_str()); 109 return AVB_IO_RESULT_ERROR_IO; 110 } 111 offset = file_size - (-offset); 112 } 113 114 int fd = open(path.value().c_str(), O_RDONLY); 115 if (fd < 0) { 116 fprintf(stderr, 117 "Error opening file '%s': %s\n", 118 path.value().c_str(), 119 strerror(errno)); 120 if (errno == ENOENT) { 121 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 122 } else { 123 return AVB_IO_RESULT_ERROR_IO; 124 } 125 } 126 if (lseek(fd, offset, SEEK_SET) != offset) { 127 fprintf(stderr, 128 "Error seeking to pos %zd in file %s: %s\n", 129 offset, 130 path.value().c_str(), 131 strerror(errno)); 132 close(fd); 133 return AVB_IO_RESULT_ERROR_IO; 134 } 135 ssize_t num_read = read(fd, buffer, num_bytes); 136 if (num_read < 0) { 137 fprintf(stderr, 138 "Error reading %zd bytes from pos %" PRId64 " in file %s: %s\n", 139 num_bytes, 140 offset, 141 path.value().c_str(), 142 strerror(errno)); 143 close(fd); 144 return AVB_IO_RESULT_ERROR_IO; 145 } 146 close(fd); 147 148 if (out_num_read != NULL) { 149 *out_num_read = num_read; 150 } 151 152 return AVB_IO_RESULT_OK; 153 } 154 155 AvbIOResult FakeAvbOps::get_preloaded_partition( 156 const char* partition, 157 size_t num_bytes, 158 uint8_t** out_pointer, 159 size_t* out_num_bytes_preloaded) { 160 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) { 161 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 162 } 163 std::map<std::string, uint8_t*>::iterator it = 164 preloaded_partitions_.find(std::string(partition)); 165 if (it == preloaded_partitions_.end()) { 166 *out_pointer = NULL; 167 *out_num_bytes_preloaded = 0; 168 return AVB_IO_RESULT_OK; 169 } 170 171 uint64_t size; 172 AvbIOResult result = get_size_of_partition(avb_ops(), partition, &size); 173 if (result != AVB_IO_RESULT_OK) { 174 return result; 175 } 176 if (size != num_bytes) { 177 return AVB_IO_RESULT_ERROR_IO; 178 } 179 180 *out_num_bytes_preloaded = num_bytes; 181 *out_pointer = it->second; 182 return AVB_IO_RESULT_OK; 183 } 184 185 AvbIOResult FakeAvbOps::write_to_partition(const char* partition, 186 int64_t offset, 187 size_t num_bytes, 188 const void* buffer) { 189 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) { 190 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 191 } 192 193 base::FilePath path = 194 partition_dir_.Append(std::string(partition)).AddExtension("img"); 195 196 if (offset < 0) { 197 int64_t file_size; 198 if (!base::GetFileSize(path, &file_size)) { 199 fprintf( 200 stderr, "Error getting size of file '%s'\n", path.value().c_str()); 201 return AVB_IO_RESULT_ERROR_IO; 202 } 203 offset = file_size - (-offset); 204 } 205 206 int fd = open(path.value().c_str(), O_WRONLY); 207 if (fd < 0) { 208 fprintf(stderr, 209 "Error opening file '%s': %s\n", 210 path.value().c_str(), 211 strerror(errno)); 212 if (errno == ENOENT) { 213 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 214 } else { 215 return AVB_IO_RESULT_ERROR_IO; 216 } 217 } 218 if (lseek(fd, offset, SEEK_SET) != offset) { 219 fprintf(stderr, 220 "Error seeking to pos %zd in file %s: %s\n", 221 offset, 222 path.value().c_str(), 223 strerror(errno)); 224 close(fd); 225 return AVB_IO_RESULT_ERROR_IO; 226 } 227 ssize_t num_written = write(fd, buffer, num_bytes); 228 if (num_written < 0) { 229 fprintf(stderr, 230 "Error writing %zd bytes at pos %" PRId64 " in file %s: %s\n", 231 num_bytes, 232 offset, 233 path.value().c_str(), 234 strerror(errno)); 235 close(fd); 236 return AVB_IO_RESULT_ERROR_IO; 237 } 238 close(fd); 239 240 return AVB_IO_RESULT_OK; 241 } 242 243 AvbIOResult FakeAvbOps::validate_vbmeta_public_key( 244 AvbOps* ops, 245 const uint8_t* public_key_data, 246 size_t public_key_length, 247 const uint8_t* public_key_metadata, 248 size_t public_key_metadata_length, 249 bool* out_key_is_trusted) { 250 if (out_key_is_trusted != NULL) { 251 bool pk_matches = (public_key_length == expected_public_key_.size() && 252 (memcmp(expected_public_key_.c_str(), 253 public_key_data, 254 public_key_length) == 0)); 255 bool pkmd_matches = 256 (public_key_metadata_length == expected_public_key_metadata_.size() && 257 (memcmp(expected_public_key_metadata_.c_str(), 258 public_key_metadata, 259 public_key_metadata_length) == 0)); 260 *out_key_is_trusted = pk_matches && pkmd_matches; 261 } 262 return AVB_IO_RESULT_OK; 263 } 264 265 AvbIOResult FakeAvbOps::read_rollback_index(AvbOps* ops, 266 size_t rollback_index_location, 267 uint64_t* out_rollback_index) { 268 if (stored_rollback_indexes_.count(rollback_index_location) == 0) { 269 fprintf(stderr, 270 "No rollback index for location %zd (has %zd locations).\n", 271 rollback_index_location, 272 stored_rollback_indexes_.size()); 273 return AVB_IO_RESULT_ERROR_IO; 274 } 275 *out_rollback_index = stored_rollback_indexes_[rollback_index_location]; 276 return AVB_IO_RESULT_OK; 277 } 278 279 AvbIOResult FakeAvbOps::write_rollback_index(AvbOps* ops, 280 size_t rollback_index_location, 281 uint64_t rollback_index) { 282 if (stored_rollback_indexes_.count(rollback_index_location) == 0) { 283 fprintf(stderr, 284 "No rollback index for location %zd (has %zd locations).\n", 285 rollback_index_location, 286 stored_rollback_indexes_.size()); 287 return AVB_IO_RESULT_ERROR_IO; 288 } 289 stored_rollback_indexes_[rollback_index_location] = rollback_index; 290 return AVB_IO_RESULT_OK; 291 } 292 293 AvbIOResult FakeAvbOps::read_is_device_unlocked(AvbOps* ops, 294 bool* out_is_device_unlocked) { 295 *out_is_device_unlocked = stored_is_device_unlocked_ ? 1 : 0; 296 return AVB_IO_RESULT_OK; 297 } 298 299 AvbIOResult FakeAvbOps::get_unique_guid_for_partition(AvbOps* ops, 300 const char* partition, 301 char* guid_buf, 302 size_t guid_buf_size) { 303 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) { 304 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 305 } 306 // This is faking it a bit but makes testing easy. It works 307 // because avb_slot_verify.c doesn't check that the returned GUID 308 // is wellformed. 309 snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition); 310 return AVB_IO_RESULT_OK; 311 } 312 313 AvbIOResult FakeAvbOps::get_size_of_partition(AvbOps* ops, 314 const char* partition, 315 uint64_t* out_size) { 316 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) { 317 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 318 } 319 320 base::FilePath path = 321 partition_dir_.Append(std::string(partition)).AddExtension("img"); 322 323 int64_t file_size; 324 if (!base::GetFileSize(path, &file_size)) { 325 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 326 } 327 *out_size = file_size; 328 return AVB_IO_RESULT_OK; 329 } 330 331 AvbIOResult FakeAvbOps::read_persistent_value(const char* name, 332 size_t buffer_size, 333 uint8_t* out_buffer, 334 size_t* out_num_bytes_read) { 335 if (out_buffer == NULL && buffer_size > 0) { 336 return AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE; 337 } 338 if (stored_values_.count(name) == 0) { 339 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; 340 } 341 if (stored_values_[name].size() > buffer_size) { 342 *out_num_bytes_read = stored_values_[name].size(); 343 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE; 344 } 345 memcpy(out_buffer, stored_values_[name].data(), stored_values_[name].size()); 346 *out_num_bytes_read = stored_values_[name].size(); 347 return AVB_IO_RESULT_OK; 348 } 349 350 AvbIOResult FakeAvbOps::write_persistent_value(const char* name, 351 size_t value_size, 352 const uint8_t* value) { 353 stored_values_[name] = 354 std::string(reinterpret_cast<const char*>(value), value_size); 355 return AVB_IO_RESULT_OK; 356 } 357 358 AvbIOResult FakeAvbOps::read_permanent_attributes( 359 AvbAtxPermanentAttributes* attributes) { 360 *attributes = permanent_attributes_; 361 return AVB_IO_RESULT_OK; 362 } 363 364 AvbIOResult FakeAvbOps::read_permanent_attributes_hash( 365 uint8_t hash[AVB_SHA256_DIGEST_SIZE]) { 366 if (permanent_attributes_hash_.empty()) { 367 SHA256(reinterpret_cast<const unsigned char*>(&permanent_attributes_), 368 sizeof(AvbAtxPermanentAttributes), 369 hash); 370 return AVB_IO_RESULT_OK; 371 } 372 memset(hash, 0, AVB_SHA256_DIGEST_SIZE); 373 permanent_attributes_hash_.copy(reinterpret_cast<char*>(hash), 374 AVB_SHA256_DIGEST_SIZE); 375 return AVB_IO_RESULT_OK; 376 } 377 378 void FakeAvbOps::set_key_version(size_t rollback_index_location, 379 uint64_t key_version) { 380 verified_rollback_indexes_[rollback_index_location] = key_version; 381 } 382 383 AvbIOResult FakeAvbOps::get_random(size_t num_bytes, uint8_t* output) { 384 if (!RAND_bytes(output, num_bytes)) { 385 return AVB_IO_RESULT_ERROR_IO; 386 } 387 return AVB_IO_RESULT_OK; 388 } 389 390 static AvbIOResult my_ops_read_from_partition(AvbOps* ops, 391 const char* partition, 392 int64_t offset, 393 size_t num_bytes, 394 void* buffer, 395 size_t* out_num_read) { 396 return FakeAvbOps::GetInstanceFromAvbOps(ops) 397 ->delegate() 398 ->read_from_partition(partition, offset, num_bytes, buffer, out_num_read); 399 } 400 401 static AvbIOResult my_ops_get_preloaded_partition( 402 AvbOps* ops, 403 const char* partition, 404 size_t num_bytes, 405 uint8_t** out_pointer, 406 size_t* out_num_bytes_preloaded) { 407 return FakeAvbOps::GetInstanceFromAvbOps(ops) 408 ->delegate() 409 ->get_preloaded_partition( 410 partition, num_bytes, out_pointer, out_num_bytes_preloaded); 411 } 412 413 static AvbIOResult my_ops_write_to_partition(AvbOps* ops, 414 const char* partition, 415 int64_t offset, 416 size_t num_bytes, 417 const void* buffer) { 418 return FakeAvbOps::GetInstanceFromAvbOps(ops)->delegate()->write_to_partition( 419 partition, offset, num_bytes, buffer); 420 } 421 422 static AvbIOResult my_ops_validate_vbmeta_public_key( 423 AvbOps* ops, 424 const uint8_t* public_key_data, 425 size_t public_key_length, 426 const uint8_t* public_key_metadata, 427 size_t public_key_metadata_length, 428 bool* out_key_is_trusted) { 429 return FakeAvbOps::GetInstanceFromAvbOps(ops) 430 ->delegate() 431 ->validate_vbmeta_public_key(ops, 432 public_key_data, 433 public_key_length, 434 public_key_metadata, 435 public_key_metadata_length, 436 out_key_is_trusted); 437 } 438 439 static AvbIOResult my_ops_read_rollback_index(AvbOps* ops, 440 size_t rollback_index_location, 441 uint64_t* out_rollback_index) { 442 return FakeAvbOps::GetInstanceFromAvbOps(ops) 443 ->delegate() 444 ->read_rollback_index(ops, rollback_index_location, out_rollback_index); 445 } 446 447 static AvbIOResult my_ops_write_rollback_index(AvbOps* ops, 448 size_t rollback_index_location, 449 uint64_t rollback_index) { 450 return FakeAvbOps::GetInstanceFromAvbOps(ops) 451 ->delegate() 452 ->write_rollback_index(ops, rollback_index_location, rollback_index); 453 } 454 455 static AvbIOResult my_ops_read_is_device_unlocked( 456 AvbOps* ops, bool* out_is_device_unlocked) { 457 return FakeAvbOps::GetInstanceFromAvbOps(ops) 458 ->delegate() 459 ->read_is_device_unlocked(ops, out_is_device_unlocked); 460 } 461 462 static AvbIOResult my_ops_get_unique_guid_for_partition(AvbOps* ops, 463 const char* partition, 464 char* guid_buf, 465 size_t guid_buf_size) { 466 return FakeAvbOps::GetInstanceFromAvbOps(ops) 467 ->delegate() 468 ->get_unique_guid_for_partition(ops, partition, guid_buf, guid_buf_size); 469 } 470 471 static AvbIOResult my_ops_get_size_of_partition(AvbOps* ops, 472 const char* partition, 473 uint64_t* out_size) { 474 return FakeAvbOps::GetInstanceFromAvbOps(ops) 475 ->delegate() 476 ->get_size_of_partition(ops, partition, out_size); 477 } 478 479 static AvbIOResult my_ops_read_persistent_value(AvbOps* ops, 480 const char* name, 481 size_t buffer_size, 482 uint8_t* out_buffer, 483 size_t* out_num_bytes_read) { 484 return FakeAvbOps::GetInstanceFromAvbOps(ops) 485 ->delegate() 486 ->read_persistent_value( 487 name, buffer_size, out_buffer, out_num_bytes_read); 488 } 489 490 static AvbIOResult my_ops_write_persistent_value(AvbOps* ops, 491 const char* name, 492 size_t value_size, 493 const uint8_t* value) { 494 return FakeAvbOps::GetInstanceFromAvbOps(ops) 495 ->delegate() 496 ->write_persistent_value(name, value_size, value); 497 } 498 499 static AvbIOResult my_ops_read_permanent_attributes( 500 AvbAtxOps* atx_ops, AvbAtxPermanentAttributes* attributes) { 501 return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops) 502 ->delegate() 503 ->read_permanent_attributes(attributes); 504 } 505 506 static AvbIOResult my_ops_read_permanent_attributes_hash( 507 AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]) { 508 return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops) 509 ->delegate() 510 ->read_permanent_attributes_hash(hash); 511 } 512 513 static void my_ops_set_key_version(AvbAtxOps* atx_ops, 514 size_t rollback_index_location, 515 uint64_t key_version) { 516 return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops) 517 ->delegate() 518 ->set_key_version(rollback_index_location, key_version); 519 } 520 521 static AvbIOResult my_ops_get_random(AvbAtxOps* atx_ops, 522 size_t num_bytes, 523 uint8_t* output) { 524 return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops) 525 ->delegate() 526 ->get_random(num_bytes, output); 527 } 528 529 FakeAvbOps::FakeAvbOps() { 530 memset(&avb_ops_, 0, sizeof(avb_ops_)); 531 avb_ops_.ab_ops = &avb_ab_ops_; 532 avb_ops_.atx_ops = &avb_atx_ops_; 533 avb_ops_.user_data = this; 534 avb_ops_.read_from_partition = my_ops_read_from_partition; 535 avb_ops_.write_to_partition = my_ops_write_to_partition; 536 avb_ops_.validate_vbmeta_public_key = my_ops_validate_vbmeta_public_key; 537 avb_ops_.read_rollback_index = my_ops_read_rollback_index; 538 avb_ops_.write_rollback_index = my_ops_write_rollback_index; 539 avb_ops_.read_is_device_unlocked = my_ops_read_is_device_unlocked; 540 avb_ops_.get_unique_guid_for_partition = my_ops_get_unique_guid_for_partition; 541 avb_ops_.get_size_of_partition = my_ops_get_size_of_partition; 542 avb_ops_.read_persistent_value = my_ops_read_persistent_value; 543 avb_ops_.write_persistent_value = my_ops_write_persistent_value; 544 545 // Just use the built-in A/B metadata read/write routines. 546 avb_ab_ops_.ops = &avb_ops_; 547 avb_ab_ops_.read_ab_metadata = avb_ab_data_read; 548 avb_ab_ops_.write_ab_metadata = avb_ab_data_write; 549 550 avb_atx_ops_.ops = &avb_ops_; 551 avb_atx_ops_.read_permanent_attributes = my_ops_read_permanent_attributes; 552 avb_atx_ops_.read_permanent_attributes_hash = 553 my_ops_read_permanent_attributes_hash; 554 avb_atx_ops_.set_key_version = my_ops_set_key_version; 555 avb_atx_ops_.get_random = my_ops_get_random; 556 557 delegate_ = this; 558 } 559 560 FakeAvbOps::~FakeAvbOps() { 561 std::map<std::string, uint8_t*>::iterator it; 562 for (it = preloaded_partitions_.begin(); it != preloaded_partitions_.end(); 563 it++) { 564 free(it->second); 565 } 566 } 567 568 void FakeAvbOps::enable_get_preloaded_partition() { 569 avb_ops_.get_preloaded_partition = my_ops_get_preloaded_partition; 570 } 571 572 } // namespace avb 573