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