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