#include "avb_util.h"
#include "avb_vbmeta_image.h"
#include "avb_version.h"
-#include <log.h>
-#include <malloc.h>
/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
/* Maximum size of a vbmeta image - 64 KiB. */
#define VBMETA_MAX_SIZE (64 * 1024)
+/* Test buffer used to check the existence of a partition. */
+#define TEST_BUFFER_SIZE 1
+
static AvbSlotVerifyResult initialize_persistent_digest(
AvbOps* ops,
const char* part_name,
/* We are going to implicitly cast image_size from uint64_t to size_t in the
* following code, so we need to make sure that the cast is safe. */
if (image_size != (size_t)(image_size)) {
- avb_errorv(part_name, ": Partition size too large to load.\n", NULL);
+ avb_error(part_name, ": Partition size too large to load.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
}
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
} else if (io_ret != AVB_IO_RESULT_OK) {
- avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
+ avb_error(part_name, ": Error loading data from partition.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
}
if (*out_image_buf != NULL) {
+ *out_image_preloaded = true;
if (part_num_read != image_size) {
- avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
+ avb_error(part_name, ": Read incorrect number of bytes.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
}
- *out_image_preloaded = true;
}
}
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
} else if (io_ret != AVB_IO_RESULT_OK) {
- avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
+ avb_error(part_name, ": Error loading data from partition.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
}
if (part_num_read != image_size) {
- avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
+ avb_error(part_name, ": Read incorrect number of bytes.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
}
}
size_t stored_digest_size = 0;
if (ops->read_persistent_value == NULL) {
- avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
+ avb_error(part_name, ": Persistent values are not implemented.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
}
persistent_value_name =
} else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
// Treat a missing persistent value as a verification error, which is
// ignoreable, rather than a metadata error which is not.
- avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
+ avb_error(part_name, ": Persistent digest does not exist.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
} else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE) {
- avb_errorv(
- part_name, ": Persistent digest is not of expected size.\n", NULL);
+ avb_error(part_name, ": Persistent digest is not of expected size.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
} else if (io_ret != AVB_IO_RESULT_OK) {
- avb_errorv(part_name, ": Error reading persistent digest.\n", NULL);
+ avb_error(part_name, ": Error reading persistent digest.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
} else if (expected_digest_size != stored_digest_size) {
- avb_errorv(
- part_name, ": Persistent digest is not of expected size.\n", NULL);
+ avb_error(part_name, ": Persistent digest is not of expected size.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
}
return AVB_SLOT_VERIFY_RESULT_OK;
}
if (is_device_unlocked) {
- avb_debugv(part_name,
- ": Digest does not exist, device unlocked so not initializing "
- "digest.\n",
- NULL);
+ avb_debug(part_name,
+ ": Digest does not exist, device unlocked so not initializing "
+ "digest.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
}
// Device locked; initialize digest with given initial value.
- avb_debugv(part_name,
- ": Digest does not exist, initializing persistent digest.\n",
- NULL);
+ avb_debug(part_name,
+ ": Digest does not exist, initializing persistent digest.\n");
io_ret = ops->write_persistent_value(
ops, persistent_value_name, digest_size, initial_digest);
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
} else if (io_ret != AVB_IO_RESULT_OK) {
- avb_errorv(part_name, ": Error initializing persistent digest.\n", NULL);
+ avb_error(part_name, ": Error initializing persistent digest.\n");
return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
}
// initial_digest ensures that this will not recurse again.
ret = read_persistent_digest(ops, part_name, digest_size, NULL, out_digest);
if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
- avb_errorv(part_name,
- ": Reading back initialized persistent digest failed!\n",
- NULL);
+ avb_error(part_name,
+ ": Reading back initialized persistent digest failed!\n");
}
return ret;
}
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
} else if (io_ret != AVB_IO_RESULT_OK) {
- avb_errorv(part_name, ": Error determining partition size.\n", NULL);
+ avb_error(part_name, ": Error determining partition size.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
}
- avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+ avb_debug(part_name, ": Loading entire partition.\n");
}
ret = load_full_partition(
digest = avb_sha512_final(&sha512_ctx);
digest_len = AVB_SHA512_DIGEST_SIZE;
} else {
- avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
+ avb_error(part_name, ": Unsupported hash algorithm.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
if (hash_desc.digest_len == 0) {
/* Expect a match to a persistent digest. */
- avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
+ avb_debug(part_name, ": No digest, using persistent digest.\n");
expected_digest_len = digest_len;
expected_digest = expected_digest_buf;
avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
}
if (digest_len != expected_digest_len) {
- avb_errorv(
- part_name, ": Digest in descriptor not of expected size.\n", NULL);
+ avb_error(part_name, ": Digest in descriptor not of expected size.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
- avb_errorv(part_name,
- ": Hash of data does not match digest in descriptor.\n",
- NULL);
+ avb_error(part_name,
+ ": Hash of data does not match digest in descriptor.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
goto out;
}
image_buf != NULL) {
AvbPartitionData* loaded_partition;
if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
- avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
+ avb_error(part_name, ": Too many loaded partitions.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto fail;
}
loaded_partition->data_size = image_size;
loaded_partition->data = image_buf;
loaded_partition->preloaded = image_preloaded;
+ loaded_partition->verify_result = ret;
image_buf = NULL;
}
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
} else if (io_ret != AVB_IO_RESULT_OK) {
- avb_errorv(part_name, ": Error determining partition size.\n", NULL);
+ avb_error(part_name, ": Error determining partition size.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
}
- avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+ avb_debug(part_name, ": Loading entire partition.\n");
ret = load_full_partition(
ops, part_name, image_size, &image_buf, &image_preloaded);
/* Move to slot_data. */
if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
- avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
+ avb_error(part_name, ": Too many loaded partitions.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}
AvbSlotVerifyFlags flags,
bool allow_verification_error,
AvbVBMetaImageFlags toplevel_vbmeta_flags,
- int rollback_index_location,
+ uint32_t rollback_index_location,
const char* partition_name,
size_t partition_name_len,
const uint8_t* expected_public_key,
size_t expected_public_key_length,
AvbSlotVerifyData* slot_data,
AvbAlgorithmType* out_algorithm_type,
- AvbCmdlineSubstList* out_additional_cmdline_subst) {
+ AvbCmdlineSubstList* out_additional_cmdline_subst,
+ bool use_ab_suffix) {
char full_partition_name[AVB_PART_NAME_MAX_SIZE];
AvbSlotVerifyResult ret;
AvbIOResult io_ret;
- size_t vbmeta_offset;
+ uint64_t vbmeta_offset;
size_t vbmeta_size;
uint8_t* vbmeta_buf = NULL;
size_t vbmeta_num_read;
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
-
- /* Construct full partition name e.g. system_a. */
- if (!avb_str_concat(full_partition_name,
+ if (!use_ab_suffix) {
+ /*No ab_suffix, just copy the partition name as is.*/
+ if (partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
+ avb_error("Partition name does not fit.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+ avb_memcpy(full_partition_name, partition_name, partition_name_len);
+ full_partition_name[partition_name_len] = '\0';
+ }else{
+ /* Construct full partition name e.g. system_a. */
+ if (!avb_str_concat(full_partition_name,
sizeof full_partition_name,
partition_name,
partition_name_len,
ab_suffix,
avb_strlen(ab_suffix))) {
- avb_error("Partition name and suffix does not fit.\n");
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
+ avb_error("Partition name and suffix does not fit.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
}
/* If we're loading from the main vbmeta partition, the vbmeta struct is in
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
} else if (io_ret != AVB_IO_RESULT_OK) {
- avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
+ avb_error(full_partition_name, ": Error loading footer.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
}
if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
&footer)) {
- avb_debugv(full_partition_name, ": No footer detected.\n", NULL);
+ avb_debug(full_partition_name, ": No footer detected.\n");
} else {
/* Basic footer sanity check since the data is untrusted. */
if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
- avb_errorv(
- full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
+ avb_error(full_partition_name, ": Invalid vbmeta size in footer.\n");
} else {
vbmeta_offset = footer.vbmeta_offset;
vbmeta_size = footer.vbmeta_size;
}
}
+ } else {
+ uint64_t partition_size = 0;
+ io_ret =
+ ops->get_size_of_partition(ops, full_partition_name, &partition_size);
+ if (io_ret == AVB_IO_RESULT_OK) {
+ if (partition_size < vbmeta_size && partition_size > 0) {
+ avb_debug(full_partition_name,
+ ": Using partition size as vbmeta size\n");
+ vbmeta_size = partition_size;
+ }
+ } else {
+ avb_debug(full_partition_name, ": Failed to get partition size\n");
+ // libavb might fall back to other partitions if current vbmeta partition
+ // isn't found. So AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is recoverable,
+ // but other errors are not.
+ if (io_ret != AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ }
}
- vbmeta_buf = avb_malloc(vbmeta_size);
- if (vbmeta_buf == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
+ /* Use result from previous I/O operation to check the existence of the
+ * partition before allocating the big chunk of memory on heap
+ * for vbmeta later. `io_ret` will be used later to decide whether
+ * to fallback on the `boot` partition.
+ */
+ if (io_ret != AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
+ vbmeta_buf = avb_malloc(vbmeta_size);
+ if (vbmeta_buf == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
- if (vbmeta_offset != 0) {
- avb_debugv("Loading vbmeta struct in footer from partition '",
- full_partition_name,
- "'.\n",
- NULL);
- } else {
- avb_debugv("Loading vbmeta struct from partition '",
- full_partition_name,
- "'.\n",
- NULL);
- }
-
- io_ret = ops->read_from_partition(ops,
- full_partition_name,
- vbmeta_offset,
- vbmeta_size,
- vbmeta_buf,
- &vbmeta_num_read);
+ if (vbmeta_offset != 0) {
+ avb_debug("Loading vbmeta struct in footer from partition '",
+ full_partition_name,
+ "'.\n");
+ } else {
+ avb_debug("Loading vbmeta struct from partition '",
+ full_partition_name,
+ "'.\n");
+ }
+
+ io_ret = ops->read_from_partition(ops,
+ full_partition_name,
+ vbmeta_offset,
+ vbmeta_size,
+ vbmeta_buf,
+ &vbmeta_num_read);
+ }
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
*/
if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
!look_for_vbmeta_footer) {
- avb_debugv(full_partition_name,
- ": No such partition. Trying 'boot' instead.\n",
- NULL);
+ avb_debug(full_partition_name,
+ ": No such partition. Trying 'boot' instead.\n");
ret = load_and_verify_vbmeta(ops,
requested_partitions,
ab_suffix,
0 /* expected_public_key_length */,
slot_data,
out_algorithm_type,
- out_additional_cmdline_subst);
+ out_additional_cmdline_subst,
+ use_ab_suffix);
goto out;
} else {
- avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
+ avb_error(full_partition_name, ": Error loading vbmeta data.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
}
case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
- avb_errorv(full_partition_name,
- ": Error verifying vbmeta image: ",
- avb_vbmeta_verify_result_to_string(vbmeta_ret),
- "\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Error verifying vbmeta image: ",
+ avb_vbmeta_verify_result_to_string(vbmeta_ret),
+ "\n");
if (!allow_verification_error) {
goto out;
}
case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
/* No way to continue this case. */
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- avb_errorv(full_partition_name,
- ": Error verifying vbmeta image: invalid vbmeta header\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Error verifying vbmeta image: invalid vbmeta header\n");
goto out;
case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
/* No way to continue this case. */
ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
- avb_errorv(full_partition_name,
- ": Error verifying vbmeta image: unsupported AVB version\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Error verifying vbmeta image: unsupported AVB version\n");
goto out;
}
} else {
if (vbmeta_header.flags != 0) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- avb_errorv(full_partition_name,
- ": chained vbmeta image has non-zero flags\n",
- NULL);
+ avb_error(full_partition_name,
+ ": chained vbmeta image has non-zero flags\n");
goto out;
}
}
uint32_t rollback_index_location_to_use = rollback_index_location;
+ if (is_main_vbmeta) {
+ rollback_index_location_to_use = vbmeta_header.rollback_index_location;
+ }
/* Check if key used to make signature matches what is expected. */
if (pk_data != NULL) {
avb_assert(!is_main_vbmeta);
if (expected_public_key_length != pk_len ||
avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
- avb_errorv(full_partition_name,
- ": Public key used to sign data does not match key in chain "
- "partition descriptor.\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Public key used to sign data does not match key in chain "
+ "partition descriptor.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
if (!allow_verification_error) {
goto out;
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
} else if (io_ret != AVB_IO_RESULT_OK) {
- avb_errorv(full_partition_name,
- ": Error while checking public key used to sign data.\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Error while checking public key used to sign data.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
}
if (!key_is_trusted) {
- avb_errorv(full_partition_name,
- ": Public key used to sign data rejected.\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Public key used to sign data rejected.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
if (!allow_verification_error) {
goto out;
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
} else if (io_ret != AVB_IO_RESULT_OK) {
- avb_errorv(full_partition_name,
- ": Error getting rollback index for location.\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Error getting rollback index for location.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
}
if (vbmeta_header.rollback_index < stored_rollback_index) {
- avb_errorv(
+ avb_error(
full_partition_name,
- ": Image rollback index is less than the stored rollback index.\n",
- NULL);
+ ": Image rollback index is less than the stored rollback index.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
if (!allow_verification_error) {
goto out;
}
}
if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
- avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
+ avb_error(full_partition_name, ": Too many vbmeta images.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}
*/
if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
AvbSlotVerifyResult sub_ret;
- avb_debugv(
- full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
+ avb_debug(full_partition_name, ": VERIFICATION_DISABLED bit is set.\n");
/* If load_requested_partitions() fail it is always a fatal
* failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
* than recoverable (e.g. one where result_should_continue()
AvbDescriptor desc;
if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
- avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
+ avb_error(full_partition_name, ": Descriptor is invalid.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
/* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
if (!is_main_vbmeta) {
- avb_errorv(full_partition_name,
- ": Encountered chain descriptor not in main image.\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Encountered chain descriptor not in main image.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
if (!avb_chain_partition_descriptor_validate_and_byteswap(
(AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
- avb_errorv(full_partition_name,
- ": Chain partition descriptor is invalid.\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Chain partition descriptor is invalid.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
if (chain_desc.rollback_index_location == 0) {
- avb_errorv(full_partition_name,
- ": Chain partition has invalid "
- "rollback_index_location field.\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Chain partition has invalid "
+ "rollback_index_location field.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
-
+ if ((chain_desc.flags & AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) != 0){
+ use_ab_suffix = false;
+ }else{
+ use_ab_suffix = true;
+ }
chain_partition_name = ((const uint8_t*)descriptors[n]) +
sizeof(AvbChainPartitionDescriptor);
chain_public_key = chain_partition_name + chain_desc.partition_name_len;
chain_desc.public_key_len,
slot_data,
NULL, /* out_algorithm_type */
- NULL /* out_additional_cmdline_subst */);
+ NULL, /* out_additional_cmdline_subst */
+ use_ab_suffix);
if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
ret = sub_ret;
if (!result_should_continue(ret)) {
if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
(AvbKernelCmdlineDescriptor*)descriptors[n],
&kernel_cmdline_desc)) {
- avb_errorv(full_partition_name,
- ": Kernel cmdline descriptor is invalid.\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Kernel cmdline descriptor is invalid.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
if (!avb_validate_utf8(kernel_cmdline,
kernel_cmdline_desc.kernel_cmdline_length)) {
- avb_errorv(full_partition_name,
- ": Kernel cmdline is not valid UTF-8.\n",
- NULL);
+ avb_error(full_partition_name,
+ ": Kernel cmdline is not valid UTF-8.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
if (!avb_hashtree_descriptor_validate_and_byteswap(
(AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
- avb_errorv(
- full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
+ avb_error(full_partition_name, ": Hashtree descriptor is invalid.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
"sha512") == 0) {
digest_len = AVB_SHA512_DIGEST_SIZE;
} else {
- avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
+ avb_error(part_name, ": Unsupported hash algorithm.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
}
}
- if (rollback_index_location < 0 ||
- rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
- avb_errorv(
- full_partition_name, ": Invalid rollback_index_location.\n", NULL);
+ if (rollback_index_location_to_use >=
+ AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
+ avb_error(full_partition_name, ": Invalid rollback_index_location.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
goto out;
}
- slot_data->rollback_indexes[rollback_index_location] =
+ slot_data->rollback_indexes[rollback_index_location_to_use] =
vbmeta_header.rollback_index;
if (out_algorithm_type != NULL) {
static bool has_system_partition(AvbOps* ops, const char* ab_suffix) {
char part_name[AVB_PART_NAME_MAX_SIZE];
- char* system_part_name = "system";
+ const char* system_part_name = "system";
char guid_buf[37];
AvbIOResult io_ret;
AvbSlotVerifyFlags flags,
AvbHashtreeErrorMode hashtree_error_mode,
AvbSlotVerifyData** out_data) {
- AvbSlotVerifyResult ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ AvbSlotVerifyResult ret;
AvbSlotVerifyData* slot_data = NULL;
AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
bool using_boot_for_vbmeta = false;
0 /* expected_public_key_length */,
slot_data,
&algorithm_type,
- additional_cmdline_subst);
+ additional_cmdline_subst,
+ true /*use_ab_suffix*/);
if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
goto fail;
}
0 /* expected_public_key_length */,
slot_data,
&algorithm_type,
- additional_cmdline_subst);
+ additional_cmdline_subst,
+ true /*use_ab_suffix*/);
if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
goto fail;
}
return ret;
}
-void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
+void avb_slot_verify_data_calculate_vbmeta_digest(const AvbSlotVerifyData* data,
AvbDigestType digest_type,
uint8_t* out_digest) {
bool ret = false;
extern "C" {
#endif
+#define AVB_CONCAT(x, y) x##y
#define AVB_STRINGIFY(x) #x
#define AVB_TO_STRING(x) AVB_STRINGIFY(x)
+#define AVB__COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, x, ...) x
+#define AVB_COUNT_ARGS(...) \
+ AVB__COUNT_ARGS(, ##__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define AVB__REPEAT0(x)
+#define AVB__REPEAT1(x) x
+#define AVB__REPEAT2(x) AVB__REPEAT1(x) x
+#define AVB__REPEAT3(x) AVB__REPEAT2(x) x
+#define AVB__REPEAT4(x) AVB__REPEAT3(x) x
+#define AVB__REPEAT5(x) AVB__REPEAT4(x) x
+#define AVB__REPEAT6(x) AVB__REPEAT5(x) x
+#define AVB__REPEAT7(x) AVB__REPEAT6(x) x
+#define AVB__REPEAT(n, x) AVB_CONCAT(AVB__REPEAT, n)(x)
+#define AVB_REPEAT(n, x) AVB__REPEAT(n, x)
+
+#ifdef AVB_USE_PRINTF_LOGS
+#define AVB_LOG(level, message, ...) \
+ avb_printf("%s:%d: " level \
+ ": " AVB_REPEAT(AVB_COUNT_ARGS(message, ##__VA_ARGS__), "%s"), \
+ avb_basename(__FILE__), \
+ __LINE__, \
+ message, \
+ ##__VA_ARGS__)
+#else
+#define AVB_LOG(level, message, ...) \
+ avb_printv(avb_basename(__FILE__), \
+ ":", \
+ AVB_TO_STRING(__LINE__), \
+ ": " level ": ", \
+ message, \
+ ##__VA_ARGS__, \
+ NULL)
+#endif
+
#ifdef AVB_ENABLE_DEBUG
/* Aborts the program if |expr| is false.
*
avb_fatal("assert fail: " #expr "\n"); \
} \
} while (0)
-#else
-#define avb_assert(expr)
-#endif
/* Aborts the program if reached.
*
* This has no effect unless AVB_ENABLE_DEBUG is defined.
*/
-#ifdef AVB_ENABLE_DEBUG
#define avb_assert_not_reached() \
do { \
avb_fatal("assert_not_reached()\n"); \
} while (0)
+
+/* Print functions, used for diagnostics.
+ *
+ * These have no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#define avb_debug(message, ...) \
+ do { \
+ AVB_LOG("DEBUG", message, ##__VA_ARGS__); \
+ } while (0)
#else
+#define avb_assert(expr)
#define avb_assert_not_reached()
+#define avb_debug(message, ...)
#endif
/* Aborts the program if |addr| is not word-aligned.
#define avb_assert_aligned(addr) \
avb_assert((((uintptr_t)addr) & (AVB_ALIGNMENT_SIZE - 1)) == 0)
-#ifdef AVB_ENABLE_DEBUG
-/* Print functions, used for diagnostics.
- *
- * These have no effect unless AVB_ENABLE_DEBUG is defined.
- */
-#define avb_debug(message) \
- do { \
- avb_printv(avb_basename(__FILE__), \
- ":", \
- AVB_TO_STRING(__LINE__), \
- ": DEBUG: ", \
- message, \
- NULL); \
- } while (0)
-#define avb_debugv(message, ...) \
- do { \
- avb_printv(avb_basename(__FILE__), \
- ":", \
- AVB_TO_STRING(__LINE__), \
- ": DEBUG: ", \
- message, \
- ##__VA_ARGS__); \
- } while (0)
-#else
-#define avb_debug(message)
-#define avb_debugv(message, ...)
-#endif
-
/* Prints out a message. This is typically used if a runtime-error
* occurs.
*/
-#define avb_error(message) \
- do { \
- avb_printv(avb_basename(__FILE__), \
- ":", \
- AVB_TO_STRING(__LINE__), \
- ": ERROR: ", \
- message, \
- NULL); \
- } while (0)
-#define avb_errorv(message, ...) \
- do { \
- avb_printv(avb_basename(__FILE__), \
- ":", \
- AVB_TO_STRING(__LINE__), \
- ": ERROR: ", \
- message, \
- ##__VA_ARGS__); \
+#define avb_error(message, ...) \
+ do { \
+ AVB_LOG("ERROR", message, ##__VA_ARGS__); \
} while (0)
/* Prints out a message and calls avb_abort().
*/
-#define avb_fatal(message) \
- do { \
- avb_printv(avb_basename(__FILE__), \
- ":", \
- AVB_TO_STRING(__LINE__), \
- ": FATAL: ", \
- message, \
- NULL); \
- avb_abort(); \
- } while (0)
-#define avb_fatalv(message, ...) \
- do { \
- avb_printv(avb_basename(__FILE__), \
- ":", \
- AVB_TO_STRING(__LINE__), \
- ": FATAL: ", \
- message, \
- ##__VA_ARGS__); \
- avb_abort(); \
+#define avb_fatal(message, ...) \
+ do { \
+ AVB_LOG("FATAL", message, ##__VA_ARGS__); \
+ avb_abort(); \
} while (0)
+#ifndef AVB_USE_PRINTF_LOGS
+/* Deprecated legacy logging functions -- kept for client compatibility.
+ */
+#define avb_debugv(message, ...) avb_debug(message, ##__VA_ARGS__)
+#define avb_errorv(message, ...) avb_error(message, ##__VA_ARGS__)
+#define avb_fatalv(message, ...) avb_fatal(message, ##__VA_ARGS__)
+#endif
+
+/* Converts a 16-bit unsigned integer from big-endian to host byte order. */
+uint16_t avb_be16toh(uint16_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
/* Converts a 32-bit unsigned integer from big-endian to host byte order. */
uint32_t avb_be32toh(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
/* Converts a 64-bit unsigned integer from big-endian to host byte order. */
uint64_t avb_be64toh(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+/* Converts a 16-bit unsigned integer from host to big-endian byte order. */
+uint16_t avb_htobe16(uint16_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
uint32_t avb_htobe32(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
*/
char* avb_bin2hex(const uint8_t* data, size_t data_len);
+/* Writes |value| to |digits| in base 10 followed by a NUL byte.
+ * Returns number of characters written excluding the NUL byte.
+ */
+#define AVB_MAX_DIGITS_UINT64 32
+size_t avb_uint64_to_base10(uint64_t value, char digits[AVB_MAX_DIGITS_UINT64]);
#ifdef __cplusplus
}
#endif