| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- /*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
- #include "avb_user_verification.h"
- /* Maximum allow length (in bytes) of a partition name, including
- * ab_suffix.
- */
- #define AVB_PART_NAME_MAX_SIZE 32
- /* Loads the toplevel AvbVBMetaImageHeader from the slot denoted by
- * |ab_suffix| into |vbmeta_image|. No validation, verification, or
- * byteswapping is performed.
- *
- * If successful, |true| is returned and the partition it was loaded
- * from is returned in |out_partition_name| and the offset on said
- * partition is returned in |out_vbmeta_offset|.
- */
- static bool load_top_level_vbmeta_header(
- AvbOps* ops,
- const char* ab_suffix,
- uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE],
- char out_partition_name[AVB_PART_NAME_MAX_SIZE],
- uint64_t* out_vbmeta_offset) {
- uint64_t vbmeta_offset = 0;
- size_t num_read;
- bool ret = false;
- AvbIOResult io_res;
- /* Construct full partition name. */
- if (!avb_str_concat(out_partition_name,
- AVB_PART_NAME_MAX_SIZE,
- "vbmeta",
- 6,
- ab_suffix,
- avb_strlen(ab_suffix))) {
- avb_error("Partition name and suffix does not fit.\n");
- goto out;
- }
- /* Only read the header, not the entire struct. */
- io_res = ops->read_from_partition(ops,
- out_partition_name,
- vbmeta_offset,
- AVB_VBMETA_IMAGE_HEADER_SIZE,
- vbmeta_image,
- &num_read);
- if (io_res == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
- AvbFooter footer;
- /* Try looking for the vbmeta struct in 'boot' via the footer. */
- if (!avb_str_concat(out_partition_name,
- AVB_PART_NAME_MAX_SIZE,
- "boot",
- 4,
- ab_suffix,
- avb_strlen(ab_suffix))) {
- avb_error("Partition name and suffix does not fit.\n");
- goto out;
- }
- io_res = ops->read_from_partition(ops,
- out_partition_name,
- -AVB_FOOTER_SIZE,
- AVB_FOOTER_SIZE,
- &footer,
- &num_read);
- if (io_res != AVB_IO_RESULT_OK) {
- avb_errorv("Error loading footer from partition '",
- out_partition_name,
- "'\n",
- NULL);
- goto out;
- }
- if (avb_memcmp(footer.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) != 0) {
- avb_errorv("Data from '",
- out_partition_name,
- "' does not look like a vbmeta footer.\n",
- NULL);
- goto out;
- }
- vbmeta_offset = avb_be64toh(footer.vbmeta_offset);
- io_res = ops->read_from_partition(ops,
- out_partition_name,
- vbmeta_offset,
- AVB_VBMETA_IMAGE_HEADER_SIZE,
- vbmeta_image,
- &num_read);
- }
- if (io_res != AVB_IO_RESULT_OK) {
- avb_errorv(
- "Error loading from partition '", out_partition_name, "'\n", NULL);
- goto out;
- }
- if (out_vbmeta_offset != NULL) {
- *out_vbmeta_offset = vbmeta_offset;
- }
- ret = true;
- out:
- return ret;
- }
- bool avb_user_verification_get(AvbOps* ops,
- const char* ab_suffix,
- bool* out_verification_enabled) {
- uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
- char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
- AvbVBMetaImageHeader* header;
- uint32_t flags;
- bool ret = false;
- if (!load_top_level_vbmeta_header(
- ops, ab_suffix, vbmeta_image, partition_name, NULL)) {
- goto out;
- }
- if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
- avb_errorv("Data from '",
- partition_name,
- "' does not look like a vbmeta header.\n",
- NULL);
- goto out;
- }
- /* Set/clear the VERIFICATION_DISABLED bit, as requested. */
- header = (AvbVBMetaImageHeader*)vbmeta_image;
- flags = avb_be32toh(header->flags);
- if (out_verification_enabled != NULL) {
- *out_verification_enabled =
- !(flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
- }
- ret = true;
- out:
- return ret;
- }
- bool avb_user_verification_set(AvbOps* ops,
- const char* ab_suffix,
- bool enable_verification) {
- uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
- char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
- uint64_t vbmeta_offset;
- AvbIOResult io_res;
- AvbVBMetaImageHeader* header;
- uint32_t flags;
- bool ret = false;
- if (!load_top_level_vbmeta_header(
- ops, ab_suffix, vbmeta_image, partition_name, &vbmeta_offset)) {
- goto out;
- }
- if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
- avb_errorv("Data from '",
- partition_name,
- "' does not look like a vbmeta header.\n",
- NULL);
- goto out;
- }
- /* Set/clear the VERIFICATION_DISABLED bit, as requested. */
- header = (AvbVBMetaImageHeader*)vbmeta_image;
- flags = avb_be32toh(header->flags);
- flags &= ~AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
- if (!enable_verification) {
- flags |= AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
- }
- header->flags = avb_htobe32(flags);
- /* Write the header. */
- io_res = ops->write_to_partition(ops,
- partition_name,
- vbmeta_offset,
- AVB_VBMETA_IMAGE_HEADER_SIZE,
- vbmeta_image);
- if (io_res != AVB_IO_RESULT_OK) {
- avb_errorv("Error writing to partition '", partition_name, "'\n", NULL);
- goto out;
- }
- ret = true;
- out:
- return ret;
- }
|