diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 2 | ||||
| -rw-r--r-- | lib/efi_loader/efi_capsule.c | 7 | ||||
| -rw-r--r-- | lib/efi_loader/efi_gop.c | 7 | ||||
| -rw-r--r-- | lib/efi_loader/efi_signature.c | 10 | ||||
| -rw-r--r-- | lib/fwu_updates/fwu.c | 4 | ||||
| -rw-r--r-- | lib/gunzip.c | 10 | ||||
| -rw-r--r-- | lib/libavb/avb_chain_partition_descriptor.c | 1 | ||||
| -rw-r--r-- | lib/libavb/avb_chain_partition_descriptor.h | 16 | ||||
| -rw-r--r-- | lib/libavb/avb_cmdline.c | 42 | ||||
| -rw-r--r-- | lib/libavb/avb_descriptor.c | 62 | ||||
| -rw-r--r-- | lib/libavb/avb_hashtree_descriptor.h | 3 | ||||
| -rw-r--r-- | lib/libavb/avb_property_descriptor.h | 8 | ||||
| -rw-r--r-- | lib/libavb/avb_rsa.c | 6 | ||||
| -rw-r--r-- | lib/libavb/avb_slot_verify.c | 311 | ||||
| -rw-r--r-- | lib/libavb/avb_slot_verify.h | 6 | ||||
| -rw-r--r-- | lib/libavb/avb_util.c | 46 | ||||
| -rw-r--r-- | lib/libavb/avb_util.h | 140 | ||||
| -rw-r--r-- | lib/libavb/avb_vbmeta_image.c | 1 | ||||
| -rw-r--r-- | lib/libavb/avb_vbmeta_image.h | 8 | ||||
| -rw-r--r-- | lib/libavb/avb_version.h | 2 | ||||
| -rw-r--r-- | lib/lmb.c | 6 | ||||
| -rw-r--r-- | lib/lwip/u-boot/lwipopts.h | 11 | ||||
| -rw-r--r-- | lib/string.c | 70 | ||||
| -rw-r--r-- | lib/uuid.c | 2 |
24 files changed, 448 insertions, 333 deletions
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 8c9a9b5eb56..8938b214ceb 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -934,6 +934,7 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi efi_status_t ret = EFI_SUCCESS; u16 *delete_index_list = NULL, *p; efi_uintn_t buf_size; + efi_guid_t guid; buf_size = 128; var_name16 = malloc(buf_size); @@ -943,7 +944,6 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi var_name16[0] = 0; for (;;) { int index; - efi_guid_t guid; efi_uintn_t tmp; ret = efi_next_variable_name(&buf_size, &var_name16, &guid); diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 52887f7c274..a77810fa15c 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -860,7 +860,11 @@ static efi_status_t get_dp_device(u16 *boot_var, if (!buf) return EFI_NOT_FOUND; - efi_deserialize_load_option(&lo, buf, &size); + ret = efi_deserialize_load_option(&lo, buf, &size); + if (ret != EFI_SUCCESS) { + log_err("Invalid load option %ls\n", boot_var); + goto out; + } if (lo.attributes & LOAD_OPTION_ACTIVE) { efi_dp_split_file_path(lo.file_path, device_dp, &file_dp); @@ -871,6 +875,7 @@ static efi_status_t get_dp_device(u16 *boot_var, ret = EFI_NOT_FOUND; } +out: free(buf); return ret; diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index 9403e09691e..ae44d140289 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -471,7 +471,7 @@ efi_status_t efi_gop_register(void) { struct efi_gop_obj *gopobj; u32 bpix, format, col, row; - u64 fb_base, fb_size; + u64 fb_size; efi_status_t ret; struct udevice *vdev; struct video_priv *priv; @@ -490,7 +490,6 @@ efi_status_t efi_gop_register(void) row = video_get_ysize(vdev); plat = dev_get_uclass_plat(vdev); - fb_base = IS_ENABLED(CONFIG_VIDEO_COPY) ? plat->copy_base : plat->base; fb_size = plat->size; switch (bpix) { @@ -528,7 +527,7 @@ efi_status_t efi_gop_register(void) gopobj->mode.info = &gopobj->info; gopobj->mode.info_size = sizeof(gopobj->info); - gopobj->mode.fb_base = fb_base; + gopobj->mode.fb_base = (uintptr_t)priv->fb; gopobj->mode.fb_size = fb_size; gopobj->info.version = 0; @@ -553,7 +552,7 @@ efi_status_t efi_gop_register(void) } gopobj->info.pixels_per_scanline = col; gopobj->bpix = bpix; - gopobj->fb = map_sysmem(fb_base, fb_size); + gopobj->fb = priv->fb; gopobj->vdev = vdev; return EFI_SUCCESS; diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c index f99a0c29d2b..c2be5cb61b3 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -647,7 +647,7 @@ static struct efi_signature_store * efi_sigstore_parse_siglist(struct efi_signature_list *esl) { struct efi_signature_store *siglist = NULL; - struct efi_sig_data *sig_data, *sig_data_next; + struct efi_sig_data *sig_data; struct efi_signature_data *esd; size_t left; @@ -690,7 +690,6 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl) memcpy(&siglist->sig_type, &esl->signature_type, sizeof(efi_guid_t)); /* Go through the list */ - sig_data_next = NULL; left = esl->signature_list_size - (sizeof(*esl) + esl->signature_header_size); esd = (struct efi_signature_data *) @@ -709,6 +708,9 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl) goto err; } + sig_data->next = siglist->sig_data_list; + siglist->sig_data_list = sig_data; + /* Append signature data */ memcpy(&sig_data->owner, &esd->signature_owner, sizeof(efi_guid_t)); @@ -721,15 +723,11 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl) } memcpy(sig_data->data, esd->signature_data, sig_data->size); - sig_data->next = sig_data_next; - sig_data_next = sig_data; - /* Next */ esd = (struct efi_signature_data *) ((u8 *)esd + esl->signature_size); left -= esl->signature_size; } - siglist->sig_data_list = sig_data_next; return siglist; diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c index 2b11e5da061..e9bb1b4fc65 100644 --- a/lib/fwu_updates/fwu.c +++ b/lib/fwu_updates/fwu.c @@ -759,7 +759,7 @@ static int fwu_boottime_checks(void) ret = uclass_first_device_err(UCLASS_FWU_MDATA, &g_dev); if (ret) { - log_debug("Cannot find fwu device\n"); + log_err("Cannot find fwu device\n"); return ret; } @@ -771,7 +771,7 @@ static int fwu_boottime_checks(void) ret = fwu_init(); if (ret) { - log_debug("fwu_init() failed\n"); + log_err("fwu_init() failed\n"); return ret; } diff --git a/lib/gunzip.c b/lib/gunzip.c index 20cc14f9688..b30cbfc34ef 100644 --- a/lib/gunzip.c +++ b/lib/gunzip.c @@ -246,6 +246,16 @@ int gzwrite(unsigned char *src, size_t len, struct blk_desc *dev, s.next_out = writebuf; } r = inflate(&s, Z_SYNC_FLUSH); + if (r == Z_BUF_ERROR && !s.avail_in && payload_size) { + /* + * The input chunk was exhausted at exactly + * the same time as the write buffer filled + * up, so no progress was possible. This is + * not fatal, let the outer loop refill the + * input chunk. + */ + break; + } if ((r != Z_OK) && (r != Z_STREAM_END)) { printf("Error: inflate() returned %d\n", r); diff --git a/lib/libavb/avb_chain_partition_descriptor.c b/lib/libavb/avb_chain_partition_descriptor.c index e2993063103..0354276c64a 100644 --- a/lib/libavb/avb_chain_partition_descriptor.c +++ b/lib/libavb/avb_chain_partition_descriptor.c @@ -24,6 +24,7 @@ bool avb_chain_partition_descriptor_validate_and_byteswap( dest->rollback_index_location = avb_be32toh(dest->rollback_index_location); dest->partition_name_len = avb_be32toh(dest->partition_name_len); dest->public_key_len = avb_be32toh(dest->public_key_len); + dest->flags = avb_be32toh(dest->flags); if (dest->rollback_index_location < 1) { avb_error("Invalid rollback index location value.\n"); diff --git a/lib/libavb/avb_chain_partition_descriptor.h b/lib/libavb/avb_chain_partition_descriptor.h index 80e2271782e..31c7298d1df 100644 --- a/lib/libavb/avb_chain_partition_descriptor.h +++ b/lib/libavb/avb_chain_partition_descriptor.h @@ -16,6 +16,16 @@ extern "C" { #endif +/* Flags for chain descriptors. + * + * AVB_CHAIN_PARTITION_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B + * partition logic to this partition. This is intentionally a negative boolean + * because A/B should be both the default and most used in practice. + */ +typedef enum { + AVB_CHAIN_PARTITION_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0), +} AvbChainPartitionDescriptorFlags; + /* A descriptor containing a pointer to signed integrity data stored * on another partition. The descriptor contains the partition name in * question (without the A/B suffix), the public key used to sign the @@ -28,13 +38,17 @@ extern "C" { * * The |reserved| field is for future expansion and must be set to NUL * bytes. + * + * Changes in v1.3: + * - flags field is added which supports AVB_CHAIN_PARTITION_DESCRIPTOR_FLAGS_DO_NOT_USE_AB */ typedef struct AvbChainPartitionDescriptor { AvbDescriptor parent_descriptor; uint32_t rollback_index_location; uint32_t partition_name_len; uint32_t public_key_len; - uint8_t reserved[64]; + uint32_t flags; + uint8_t reserved[60]; } AVB_ATTR_PACKED AvbChainPartitionDescriptor; /* Copies |src| to |dest| and validates, byte-swapping fields in the diff --git a/lib/libavb/avb_cmdline.c b/lib/libavb/avb_cmdline.c index a58ce6c48c0..842629abe0e 100644 --- a/lib/libavb/avb_cmdline.c +++ b/lib/libavb/avb_cmdline.c @@ -7,8 +7,6 @@ #include "avb_sha.h" #include "avb_util.h" #include "avb_version.h" -#include <log.h> -#include <malloc.h> #define NUM_GUIDS 3 @@ -149,30 +147,6 @@ static int cmdline_append_option(AvbSlotVerifyData* slot_data, return 1; } -#define AVB_MAX_DIGITS_UINT64 32 - -/* Writes |value| to |digits| in base 10 followed by a NUL byte. - * Returns number of characters written excluding the NUL byte. - */ -static size_t uint64_to_base10(uint64_t value, - char digits[AVB_MAX_DIGITS_UINT64]) { - char rev_digits[AVB_MAX_DIGITS_UINT64]; - size_t n, num_digits; - - for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) { - rev_digits[num_digits++] = avb_div_by_10(&value) + '0'; - if (value == 0) { - break; - } - } - - for (n = 0; n < num_digits; n++) { - digits[n] = rev_digits[num_digits - 1 - n]; - } - digits[n] = '\0'; - return n; -} - static int cmdline_append_version(AvbSlotVerifyData* slot_data, const char* key, uint64_t major_version, @@ -182,8 +156,8 @@ static int cmdline_append_version(AvbSlotVerifyData* slot_data, char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1]; size_t num_major_digits, num_minor_digits; - num_major_digits = uint64_to_base10(major_version, major_digits); - num_minor_digits = uint64_to_base10(minor_version, minor_digits); + num_major_digits = avb_uint64_to_base10(major_version, major_digits); + num_minor_digits = avb_uint64_to_base10(minor_version, minor_digits); avb_memcpy(combined, major_digits, num_major_digits); combined[num_major_digits] = '.'; avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits); @@ -196,7 +170,7 @@ static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data, const char* key, uint64_t value) { char digits[AVB_MAX_DIGITS_UINT64]; - uint64_to_base10(value, digits); + avb_uint64_to_base10(value, digits); return cmdline_append_option(slot_data, key, digits); } @@ -359,11 +333,11 @@ AvbSlotVerifyResult avb_append_options( // Should never get here because MANAGED_RESTART_AND_EIO is // remapped by avb_manage_hashtree_error_mode(). avb_assert_not_reached(); - ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT; - goto out; - default: - ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT; - goto out; + break; + case AVB_HASHTREE_ERROR_MODE_PANIC: + verity_mode = "panicking"; + dm_verity_mode = "panic_on_corruption"; + break; } new_ret = avb_replace( slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode); diff --git a/lib/libavb/avb_descriptor.c b/lib/libavb/avb_descriptor.c index 56a3a91fc23..f4ff16694e6 100644 --- a/lib/libavb/avb_descriptor.c +++ b/lib/libavb/avb_descriptor.c @@ -6,8 +6,6 @@ #include "avb_descriptor.h" #include "avb_util.h" #include "avb_vbmeta_image.h" -#include <log.h> -#include <malloc.h> bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src, AvbDescriptor* dest) { @@ -31,6 +29,8 @@ bool avb_descriptor_foreach(const uint8_t* image_data, const uint8_t* desc_start; const uint8_t* desc_end; const uint8_t* p; + uint64_t desc_offset = 0; + uint64_t desc_size = 0; if (image_data == NULL) { avb_error("image_data is NULL\n."); @@ -42,6 +42,9 @@ bool avb_descriptor_foreach(const uint8_t* image_data, goto out; } + /* The data is supposed to have been cryptographically verified at this point, + * This check is just adding defense in depth. + */ if (image_size < sizeof(AvbVBMetaImageHeader)) { avb_error("Length is smaller than header.\n"); goto out; @@ -58,23 +61,53 @@ bool avb_descriptor_foreach(const uint8_t* image_data, header = (const AvbVBMetaImageHeader*)image_data; image_end = image_data + image_size; - desc_start = image_data + sizeof(AvbVBMetaImageHeader) + - avb_be64toh(header->authentication_data_block_size) + - avb_be64toh(header->descriptors_offset); + /* Since the data is supposed to have been cryptographically verified at this + * point, being overflow-safe is just for defense. + * The following lines are overflow-safe version of: + * desc_offset = sizeof(AvbVBMetaImageHeader) + + * avb_be64toh(header->authentication_data_block_size)) + + * avb_be64toh(header->descriptors_offset) + */ + if (!avb_safe_add(&desc_offset, + sizeof(AvbVBMetaImageHeader), + avb_be64toh(header->authentication_data_block_size))) { + avb_error("Invalid authentication data block size.\n"); + goto out; + } + if (!avb_safe_add_to(&desc_offset, avb_be64toh(header->descriptors_offset))) { + avb_error("Invalid descriptors offset.\n"); + goto out; + } + + if (desc_offset > (uint64_t)(image_end - image_data)) { + avb_error("Descriptors not inside passed-in data.\n"); + goto out; + } - desc_end = desc_start + avb_be64toh(header->descriptors_size); + desc_start = image_data + desc_offset; - if (desc_start < image_data || desc_start > image_end || - desc_end < image_data || desc_end > image_end || desc_end < desc_start) { + desc_size = avb_be64toh(header->descriptors_size); + if (desc_size > (uint64_t)(image_end - desc_start)) { avb_error("Descriptors not inside passed-in data.\n"); goto out; } + desc_end = desc_start + desc_size; + for (p = desc_start; p < desc_end;) { - const AvbDescriptor* dh = (const AvbDescriptor*)p; - avb_assert_aligned(dh); - uint64_t nb_following = avb_be64toh(dh->num_bytes_following); + uint64_t nb_following; uint64_t nb_total = 0; + const AvbDescriptor* dh; + + if (sizeof(AvbDescriptor) > (size_t)(desc_end - p)) { + avb_error("Invalid descriptor length.\n"); + goto out; + } + + dh = (const AvbDescriptor*)p; + avb_assert_aligned(dh); + nb_following = avb_be64toh(dh->num_bytes_following); + if (!avb_safe_add(&nb_total, sizeof(AvbDescriptor), nb_following)) { avb_error("Invalid descriptor length.\n"); goto out; @@ -85,7 +118,7 @@ bool avb_descriptor_foreach(const uint8_t* image_data, goto out; } - if (nb_total + p < desc_start || nb_total + p > desc_end) { + if (nb_total > (uint64_t)(desc_end - p)) { avb_error("Invalid data in descriptors array.\n"); goto out; } @@ -94,10 +127,7 @@ bool avb_descriptor_foreach(const uint8_t* image_data, goto out; } - if (!avb_safe_add_to((uint64_t*)(&p), nb_total)) { - avb_error("Invalid descriptor length.\n"); - goto out; - } + p += nb_total; } ret = true; diff --git a/lib/libavb/avb_hashtree_descriptor.h b/lib/libavb/avb_hashtree_descriptor.h index d7f3eb501a3..5f74c465fed 100644 --- a/lib/libavb/avb_hashtree_descriptor.h +++ b/lib/libavb/avb_hashtree_descriptor.h @@ -21,9 +21,12 @@ extern "C" { * AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B * partition logic to this partition. This is intentionally a negative boolean * because A/B should be both the default and most used in practice. + * AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE: supports to validate hashes + * at most once in DM-Verity. */ typedef enum { AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0), + AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE = (1 << 1), } AvbHashtreeDescriptorFlags; /* A descriptor containing information about a dm-verity hashtree. diff --git a/lib/libavb/avb_property_descriptor.h b/lib/libavb/avb_property_descriptor.h index 917c58f9fea..b4df1c433a6 100644 --- a/lib/libavb/avb_property_descriptor.h +++ b/lib/libavb/avb_property_descriptor.h @@ -18,10 +18,10 @@ extern "C" { /* A descriptor for properties (free-form key/value pairs). * - * Following this struct are |key_num_bytes| bytes of key data, - * followed by a NUL byte, then |value_num_bytes| bytes of value data, - * followed by a NUL byte and then enough padding to make the combined - * size a multiple of 8. + * Following this struct are |key_num_bytes| bytes of key data encoded + * as UTF-8, followed by a NUL byte, then |value_num_bytes| bytes of + * value data, followed by a NUL byte and then enough padding to make + * the combined size a multiple of 8. */ typedef struct AvbPropertyDescriptor { AvbDescriptor parent_descriptor; diff --git a/lib/libavb/avb_rsa.c b/lib/libavb/avb_rsa.c index d7bf8905be2..b64749980c0 100644 --- a/lib/libavb/avb_rsa.c +++ b/lib/libavb/avb_rsa.c @@ -3,6 +3,11 @@ * Copyright (C) 2016 The Android Open Source Project */ +/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + /* Implementation of RSA signature verification which uses a pre-processed * key for computation. The code extends libmincrypt RSA verification code to * support multiple RSA key lengths and hash digest algorithms. @@ -12,7 +17,6 @@ #include "avb_sha.h" #include "avb_util.h" #include "avb_vbmeta_image.h" -#include <malloc.h> typedef struct IAvbKey { unsigned int len; /* Length of n[] in number of uint32_t */ diff --git a/lib/libavb/avb_slot_verify.c b/lib/libavb/avb_slot_verify.c index ae8e1dffa4c..d37ffed0148 100644 --- a/lib/libavb/avb_slot_verify.c +++ b/lib/libavb/avb_slot_verify.c @@ -14,8 +14,6 @@ #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 @@ -26,6 +24,9 @@ /* 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, @@ -72,7 +73,7 @@ static AvbSlotVerifyResult load_full_partition(AvbOps* ops, /* 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; } @@ -83,16 +84,16 @@ static AvbSlotVerifyResult load_full_partition(AvbOps* ops, 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; } } @@ -112,11 +113,11 @@ static AvbSlotVerifyResult load_full_partition(AvbOps* ops, 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; } } @@ -150,7 +151,7 @@ static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops, 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 = @@ -187,19 +188,17 @@ static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops, } 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; @@ -225,23 +224,21 @@ static AvbSlotVerifyResult initialize_persistent_digest( } 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; } @@ -251,9 +248,8 @@ static AvbSlotVerifyResult initialize_persistent_digest( // 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; } @@ -356,11 +352,11 @@ static AvbSlotVerifyResult load_and_verify_hash_partition( 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( @@ -392,14 +388,14 @@ static AvbSlotVerifyResult load_and_verify_hash_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)); @@ -418,16 +414,14 @@ static AvbSlotVerifyResult load_and_verify_hash_partition( } 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; } @@ -441,7 +435,7 @@ 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; } @@ -451,6 +445,7 @@ out: loaded_partition->data_size = image_size; loaded_partition->data = image_buf; loaded_partition->preloaded = image_preloaded; + loaded_partition->verify_result = ret; image_buf = NULL; } @@ -493,11 +488,11 @@ static AvbSlotVerifyResult load_requested_partitions( 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); @@ -507,7 +502,7 @@ static AvbSlotVerifyResult load_requested_partitions( /* 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; } @@ -544,18 +539,19 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; @@ -599,17 +595,27 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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 @@ -635,7 +641,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; } @@ -643,43 +649,67 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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); - } + 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); + 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; @@ -689,9 +719,8 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( */ 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, @@ -705,10 +734,11 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; } @@ -729,11 +759,10 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; } @@ -742,17 +771,15 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; } @@ -766,14 +793,16 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( } 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) { @@ -781,10 +810,9 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; @@ -827,16 +855,14 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; @@ -852,17 +878,15 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; @@ -878,7 +902,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( } } 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; } @@ -902,8 +926,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( */ 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() @@ -936,7 +959,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; } @@ -966,31 +989,32 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( /* 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; @@ -1009,7 +1033,8 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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)) { @@ -1026,9 +1051,8 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; } @@ -1038,9 +1062,8 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; } @@ -1100,8 +1123,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( 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; } @@ -1155,7 +1177,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( "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; } @@ -1188,15 +1210,14 @@ static AvbSlotVerifyResult load_and_verify_vbmeta( } } - 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) { @@ -1315,7 +1336,7 @@ out: 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; @@ -1348,7 +1369,7 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops, 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; @@ -1456,7 +1477,8 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops, 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; } @@ -1477,7 +1499,8 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops, 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; } @@ -1686,7 +1709,7 @@ const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) { 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; diff --git a/lib/libavb/avb_slot_verify.h b/lib/libavb/avb_slot_verify.h index 8d0fa536935..b86c96cbd06 100644 --- a/lib/libavb/avb_slot_verify.h +++ b/lib/libavb/avb_slot_verify.h @@ -69,7 +69,8 @@ typedef enum { AVB_HASHTREE_ERROR_MODE_RESTART, AVB_HASHTREE_ERROR_MODE_EIO, AVB_HASHTREE_ERROR_MODE_LOGGING, - AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO + AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO, + AVB_HASHTREE_ERROR_MODE_PANIC } AvbHashtreeErrorMode; /* Flags that influence how avb_slot_verify() works. @@ -138,6 +139,7 @@ typedef struct { uint8_t* data; size_t data_size; bool preloaded; + AvbSlotVerifyResult verify_result; } AvbPartitionData; /* AvbVBMetaData contains a vbmeta struct loaded from a partition when @@ -291,7 +293,7 @@ typedef struct { * in |out_digest| which must be large enough to hold a digest * of the requested type. */ -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); diff --git a/lib/libavb/avb_util.c b/lib/libavb/avb_util.c index 8719ede15a7..25af46075a7 100644 --- a/lib/libavb/avb_util.c +++ b/lib/libavb/avb_util.c @@ -4,11 +4,17 @@ */ #include "avb_util.h" -#include <log.h> -#include <malloc.h> #include <stdarg.h> +uint16_t avb_be16toh(uint16_t in) { + uint8_t* d = (uint8_t*)∈ + uint16_t ret; + ret = ((uint16_t)d[0]) << 8; + ret |= ((uint16_t)d[1]); + return ret; +} + uint32_t avb_be32toh(uint32_t in) { uint8_t* d = (uint8_t*)∈ uint32_t ret; @@ -33,6 +39,17 @@ uint64_t avb_be64toh(uint64_t in) { return ret; } +/* Converts a 16-bit unsigned integer from host to big-endian byte order. */ +uint16_t avb_htobe16(uint16_t in) { + union { + uint16_t word; + uint8_t bytes[2]; + } ret; + ret.bytes[0] = (in >> 8) & 0xff; + ret.bytes[1] = in & 0xff; + return ret.word; +} + /* Converts a 32-bit unsigned integer from host to big-endian byte order. */ uint32_t avb_htobe32(uint32_t in) { union { @@ -159,6 +176,12 @@ bool avb_str_concat(char* buf, size_t str2_len) { uint64_t combined_len; + // Doesn't make sense to pass 0 for buf_size since there's + // no room for the terminating NUL byte. + if (buf_size == 0) { + return false; + } + if (!avb_safe_add(&combined_len, str1_len, str2_len)) { avb_error("Overflow when adding string sizes.\n"); return false; @@ -411,3 +434,22 @@ char* avb_bin2hex(const uint8_t* data, size_t data_len) { hex_data[n * 2] = '\0'; return hex_data; } + +size_t avb_uint64_to_base10(uint64_t value, + char digits[AVB_MAX_DIGITS_UINT64]) { + char rev_digits[AVB_MAX_DIGITS_UINT64]; + size_t n, num_digits; + + for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) { + rev_digits[num_digits++] = avb_div_by_10(&value) + '0'; + if (value == 0) { + break; + } + } + + for (n = 0; n < num_digits; n++) { + digits[n] = rev_digits[num_digits - 1 - n]; + } + digits[n] = '\0'; + return n; +} diff --git a/lib/libavb/avb_util.h b/lib/libavb/avb_util.h index 26dc6b045ac..d0612cc97f3 100644 --- a/lib/libavb/avb_util.h +++ b/lib/libavb/avb_util.h @@ -16,9 +16,44 @@ 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. * @@ -30,21 +65,28 @@ extern "C" { 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. @@ -54,85 +96,42 @@ extern "C" { #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; @@ -261,6 +260,11 @@ void avb_uppercase(char* str); */ 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 diff --git a/lib/libavb/avb_vbmeta_image.c b/lib/libavb/avb_vbmeta_image.c index 384f5ac19e5..44d75fda322 100644 --- a/lib/libavb/avb_vbmeta_image.c +++ b/lib/libavb/avb_vbmeta_image.c @@ -254,6 +254,7 @@ void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src, dest->rollback_index = avb_be64toh(dest->rollback_index); dest->flags = avb_be32toh(dest->flags); + dest->rollback_index_location = avb_be32toh(dest->rollback_index_location); } const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) { diff --git a/lib/libavb/avb_vbmeta_image.h b/lib/libavb/avb_vbmeta_image.h index 24f8519ff60..221ccd1d383 100644 --- a/lib/libavb/avb_vbmeta_image.h +++ b/lib/libavb/avb_vbmeta_image.h @@ -157,10 +157,12 @@ typedef struct AvbVBMetaImageHeader { */ uint32_t flags; - /* 124: Reserved to ensure |release_string| start on a 16-byte - * boundary. Must be set to zeroes. + /* 124: The location of the rollback index defined in this header. + * Only valid for the main vbmeta. For chained partitions, the rollback + * index location must be specified in the AvbChainPartitionDescriptor + * and this value must be set to 0. */ - uint8_t reserved0[4]; + uint32_t rollback_index_location; /* 128: The release string from avbtool, e.g. "avbtool 1.0.0" or * "avbtool 1.0.0 xyz_board Git-234abde89". Is guaranteed to be NUL diff --git a/lib/libavb/avb_version.h b/lib/libavb/avb_version.h index 57c6ece851c..e6f7798769d 100644 --- a/lib/libavb/avb_version.h +++ b/lib/libavb/avb_version.h @@ -18,7 +18,7 @@ extern "C" { /* The version number of AVB - keep in sync with avbtool. */ #define AVB_VERSION_MAJOR 1 -#define AVB_VERSION_MINOR 1 +#define AVB_VERSION_MINOR 3 #define AVB_VERSION_SUB 0 /* Returns a NUL-terminated string for the libavb version in use. The diff --git a/lib/lmb.c b/lib/lmb.c index 77440a48486..ca00047f624 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -286,7 +286,7 @@ static long _lmb_free(struct alist *lmb_rgn_lst, phys_addr_t base, /* Didn't find the region */ if (i == lmb_rgn_lst->count) - return -1; + return -EFAULT; /* Check to see if we are removing entire region */ if (rgnbegin == base && rgnend == end) { @@ -752,9 +752,11 @@ static int _lmb_alloc_addr(phys_addr_t base, phys_size_t size, u32 flags) base + size - 1, 1)) /* ok, reserve the memory */ return lmb_reserve(base, size, flags); + + return -EINVAL; } - return -EINVAL; + return -EFAULT; } int lmb_alloc_mem(enum lmb_mem_type type, u64 align, phys_addr_t *addr, diff --git a/lib/lwip/u-boot/lwipopts.h b/lib/lwip/u-boot/lwipopts.h index 8dae004f1a2..1c1adc57c6b 100644 --- a/lib/lwip/u-boot/lwipopts.h +++ b/lib/lwip/u-boot/lwipopts.h @@ -72,6 +72,17 @@ #define PBUF_POOL_RESERVE 4 #define TFTP_BLOCKSIZE_THRESHOLD 4096 +/* + * Match the legacy U-Boot TFTP filename buffer. The legacy + * CONFIG_TFTP_FILE_NAME_MAX_LEN value is a buffer size including the trailing + * NUL, while lwIP's TFTP_MAX_FILENAME_LEN is the usable string length. + */ +#ifdef CONFIG_TFTP_FILE_NAME_MAX_LEN +#define TFTP_MAX_FILENAME_LEN (CONFIG_TFTP_FILE_NAME_MAX_LEN - 1) +#else +#define TFTP_MAX_FILENAME_LEN 127 +#endif + #if defined(CONFIG_TFTP_BLOCKSIZE) && (CONFIG_TFTP_BLOCKSIZE > TFTP_BLOCKSIZE_THRESHOLD) #define PBUF_POOL_SIZE (((CONFIG_TFTP_BLOCKSIZE + (IP_FRAG_MTU_USABLE - 1)) / \ IP_FRAG_MTU_USABLE) + PBUF_POOL_HEADROOM) diff --git a/lib/string.c b/lib/string.c index 37ea8c29561..dbf2ce340df 100644 --- a/lib/string.c +++ b/lib/string.c @@ -263,12 +263,12 @@ char * strchr(const char * s, int c) } #endif -const char *strchrnul(const char *s, int c) +char *strchrnul(const char *s, int c) { for (; *s != (char)c; ++s) if (*s == '\0') break; - return s; + return (char *)s; } #ifndef __HAVE_ARCH_STRRCHR @@ -399,7 +399,6 @@ void kfree_const(const void *x) } -#ifndef __HAVE_ARCH_STRSPN /** * strspn - Calculate the length of the initial substring of @s which only * contain letters in @accept @@ -424,9 +423,7 @@ size_t strspn(const char *s, const char *accept) return count; } -#endif -#ifndef __HAVE_ARCH_STRPBRK /** * strpbrk - Find the first occurrence of a set of characters * @cs: The string to be searched @@ -444,9 +441,7 @@ char * strpbrk(const char * cs,const char * ct) } return NULL; } -#endif -#ifndef __HAVE_ARCH_STRTOK /** * strtok - Split a string into tokens * @s: The string to be searched @@ -473,9 +468,7 @@ char * strtok(char * s,const char * ct) ___strtok = send; return (sbegin); } -#endif -#ifndef __HAVE_ARCH_STRSEP /** * strsep - Split a string into tokens * @s: The string to be searched @@ -501,35 +494,6 @@ char * strsep(char **s, const char *ct) return sbegin; } -#endif - -#ifndef __HAVE_ARCH_STRSWAB -/** - * strswab - swap adjacent even and odd bytes in %NUL-terminated string - * s: address of the string - * - * returns the address of the swapped string or NULL on error. If - * string length is odd, last byte is untouched. - */ -char *strswab(const char *s) -{ - char *p, *q; - - if ((NULL == s) || ('\0' == *s)) { - return (NULL); - } - - for (p=(char *)s, q=p+1; (*p != '\0') && (*q != '\0'); p+=2, q+=2) { - char tmp; - - tmp = *p; - *p = *q; - *q = tmp; - } - - return (char *) s; -} -#endif #ifndef __HAVE_ARCH_MEMSET /** @@ -702,7 +666,7 @@ void *memdup(const void *src, size_t len) * * @s1: string to be searched * @s2: string to search for - * @len: maximum number of characters in s2 to consider + * @len: maximum number of characters in s1 to consider * * Return: pointer to the first occurrence or NULL */ @@ -728,7 +692,6 @@ char *strnstr(const char *s1, const char *s2, size_t len) * * @s1: string to be searched * @s2: string to search for - * @len: maximum number of characters in s2 to consider * * Return: pointer to the first occurrence or NULL */ @@ -738,6 +701,33 @@ char *strstr(const char *s1, const char *s2) } #endif +/** + * strcasestr() - Case insensitive substring search + * + * @haystack: string to be searched + * @needle: string to search for + * + * Return: pointer to the first occurrence or NULL + * + * The case of both strings are ignored. + */ +char *strcasestr(const char *haystack, const char *needle) +{ + size_t l1, l2; + + l1 = strlen(haystack); + l2 = strlen(needle); + + while (l1 >= l2) { + if (!strncasecmp(haystack, needle, l2)) + return (char *)haystack; + haystack++; + l1--; + } + + return NULL; +} + #ifndef __HAVE_ARCH_MEMCHR /** * memchr - Find a character in an area of memory. diff --git a/lib/uuid.c b/lib/uuid.c index d7c164ea06b..16ca8f37751 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -95,6 +95,7 @@ static const struct { "system", "EFI System Partition", PARTITION_SYSTEM_GUID, }, +#endif /* EFI_PARTITION */ #if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI_CLIENT) { NULL, "Device Path", @@ -304,7 +305,6 @@ static const struct { { "EFI_MEM_STATUS_CODE_REC", NULL, EFI_MEM_STATUS_CODE_REC }, { "EFI_GUID_EFI_ACPI1", NULL, EFI_GUID_EFI_ACPI1 }, #endif -#endif /* EFI_PARTITION */ #endif /* !USE_HOSTCC */ }; |
