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/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