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