• 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 
read_from_partition(const char * partition,int64_t offset,size_t num_bytes,void * buffer,size_t * out_num_read)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 
get_preloaded_partition(const char * partition,size_t num_bytes,uint8_t ** out_pointer,size_t * out_num_bytes_preloaded)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 
write_to_partition(const char * partition,int64_t offset,size_t num_bytes,const void * buffer)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 
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)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 
read_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t * out_rollback_index)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 
write_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t rollback_index)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 
read_is_device_unlocked(AvbOps * ops,bool * out_is_device_unlocked)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 
get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)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 
get_size_of_partition(AvbOps * ops,const char * partition,uint64_t * out_size)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 
read_persistent_value(const char * name,size_t buffer_size,uint8_t * out_buffer,size_t * out_num_bytes_read)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 
write_persistent_value(const char * name,size_t value_size,const uint8_t * value)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 
read_permanent_attributes(AvbAtxPermanentAttributes * attributes)358 AvbIOResult FakeAvbOps::read_permanent_attributes(
359     AvbAtxPermanentAttributes* attributes) {
360   *attributes = permanent_attributes_;
361   return AVB_IO_RESULT_OK;
362 }
363 
read_permanent_attributes_hash(uint8_t hash[AVB_SHA256_DIGEST_SIZE])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 
set_key_version(size_t rollback_index_location,uint64_t key_version)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 
get_random(size_t num_bytes,uint8_t * output)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 
my_ops_read_from_partition(AvbOps * ops,const char * partition,int64_t offset,size_t num_bytes,void * buffer,size_t * out_num_read)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 
my_ops_get_preloaded_partition(AvbOps * ops,const char * partition,size_t num_bytes,uint8_t ** out_pointer,size_t * out_num_bytes_preloaded)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 
my_ops_write_to_partition(AvbOps * ops,const char * partition,int64_t offset,size_t num_bytes,const void * buffer)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 
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)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 
my_ops_read_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t * out_rollback_index)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 
my_ops_write_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t rollback_index)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 
my_ops_read_is_device_unlocked(AvbOps * ops,bool * out_is_device_unlocked)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 
my_ops_get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)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 
my_ops_get_size_of_partition(AvbOps * ops,const char * partition,uint64_t * out_size)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 
my_ops_read_persistent_value(AvbOps * ops,const char * name,size_t buffer_size,uint8_t * out_buffer,size_t * out_num_bytes_read)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 
my_ops_write_persistent_value(AvbOps * ops,const char * name,size_t value_size,const uint8_t * value)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 
my_ops_read_permanent_attributes(AvbAtxOps * atx_ops,AvbAtxPermanentAttributes * attributes)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 
my_ops_read_permanent_attributes_hash(AvbAtxOps * atx_ops,uint8_t hash[AVB_SHA256_DIGEST_SIZE])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 
my_ops_set_key_version(AvbAtxOps * atx_ops,size_t rollback_index_location,uint64_t key_version)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 
my_ops_get_random(AvbAtxOps * atx_ops,size_t num_bytes,uint8_t * output)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 
FakeAvbOps()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 
~FakeAvbOps()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 
enable_get_preloaded_partition()568 void FakeAvbOps::enable_get_preloaded_partition() {
569   avb_ops_.get_preloaded_partition = my_ops_get_preloaded_partition;
570 }
571 
572 }  // namespace avb
573