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