aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md14
-rw-r--r--libavb/avb_cmdline.c27
-rw-r--r--libavb/avb_cmdline.h1
-rw-r--r--libavb/avb_ops.h23
-rw-r--r--libavb/avb_slot_verify.c133
-rw-r--r--libavb/avb_slot_verify.h16
-rw-r--r--test/avb_slot_verify_unittest.cc109
-rw-r--r--test/fake_avb_ops.cc47
-rw-r--r--test/fake_avb_ops.h53
9 files changed, 388 insertions, 35 deletions
diff --git a/README.md b/README.md
index f64c6de..62072bf 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,7 @@ Verified Boot 2.0. Usually AVB is used to refer to this codebase.
+ [Persistent Digests](#Persistent-Digests)
+ [Updating Stored Rollback Indexes](#Updating-Stored-Rollback-Indexes)
+ [Recommended Bootflow](#Recommended-Bootflow)
+ + [Booting Into Recovery](#Booting-Into-Recovery)
+ [Handling dm-verity Errors](#Handling-dm_verity-Errors)
+ [Android Specific Integration](#Android-Specific-Integration)
+ [Device Specific Notes](#Device-Specific-Notes)
@@ -917,6 +918,19 @@ Notes:
be used to convey that the device is UNLOCKED (lightbars, LEDs,
etc.).
+### Booting Into Recovery
+
+On Android devices not using A/B, the `recovery` partition usually isn't
+updated along with other partitions and therefore can't be referenced
+from the main `vbmeta` partition.
+
+It's still possible to use AVB to protect this partition (and others)
+by signing these partitions and passing the
+`AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION` flag to `avb_slot_verify()`.
+In this mode, the key used to sign each requested partition is verified
+by the `validate_public_key_for_partition()` operation which is also
+used to return the rollback index location to be used.
+
## Handling dm-verity Errors
By design, hashtree verification errors are detected by the HLOS and
diff --git a/libavb/avb_cmdline.c b/libavb/avb_cmdline.c
index bf10865..f87e18c 100644
--- a/libavb/avb_cmdline.c
+++ b/libavb/avb_cmdline.c
@@ -97,7 +97,15 @@ char* avb_sub_cmdline(AvbOps* ops,
}
}
- avb_assert(ret != NULL);
+ /* It's possible there is no _PARTUUID for replacement above.
+ * Duplicate cmdline to ret for additional substitutions below.
+ */
+ if (ret == NULL) {
+ ret = avb_strdup(cmdline);
+ if (ret == NULL) {
+ goto fail;
+ }
+ }
/* Replace any additional substitutions. */
if (additional_substitutions != NULL) {
@@ -225,6 +233,7 @@ static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
AvbSlotVerifyResult avb_append_options(
AvbOps* ops,
+ AvbSlotVerifyFlags flags,
AvbSlotVerifyData* slot_data,
AvbVBMetaImageHeader* toplevel_vbmeta,
AvbAlgorithmType algorithm_type,
@@ -235,12 +244,16 @@ AvbSlotVerifyResult avb_append_options(
bool is_device_unlocked;
AvbIOResult io_ret;
- /* Add androidboot.vbmeta.device option. */
- if (!cmdline_append_option(slot_data,
- "androidboot.vbmeta.device",
- "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
+ /* Add androidboot.vbmeta.device option... except if not using a vbmeta
+ * partition since it doesn't make sense in that case.
+ */
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ if (!cmdline_append_option(slot_data,
+ "androidboot.vbmeta.device",
+ "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
}
/* Add androidboot.vbmeta.avb_version option. */
diff --git a/libavb/avb_cmdline.h b/libavb/avb_cmdline.h
index e1f5b1b..377783f 100644
--- a/libavb/avb_cmdline.h
+++ b/libavb/avb_cmdline.h
@@ -62,6 +62,7 @@ char* avb_sub_cmdline(AvbOps* ops,
AvbSlotVerifyResult avb_append_options(
AvbOps* ops,
+ AvbSlotVerifyFlags flags,
AvbSlotVerifyData* slot_data,
AvbVBMetaImageHeader* toplevel_vbmeta,
AvbAlgorithmType algorithm_type,
diff --git a/libavb/avb_ops.h b/libavb/avb_ops.h
index 7f86386..dec163d 100644
--- a/libavb/avb_ops.h
+++ b/libavb/avb_ops.h
@@ -191,6 +191,10 @@ struct AvbOps {
*
* If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
* true if trusted or false if untrusted.
+ *
+ * NOTE: If AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is passed to
+ * avb_slot_verify() then this operation is never used. Instead, the
+ * validate_public_key_for_partition() operation is used
*/
AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
const uint8_t* public_key_data,
@@ -308,6 +312,25 @@ struct AvbOps {
const char* name,
size_t value_size,
const uint8_t* value);
+
+ /* Like validate_vbmeta_public_key() but for when the flag
+ * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is being used. The name of the
+ * partition to get the public key for is passed in |partition_name|.
+ *
+ * Also returns the rollback index location to use for the partition, in
+ * |out_rollback_index_location|.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ */
+ AvbIOResult (*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_is_trusted,
+ uint32_t* out_rollback_index_location);
};
#ifdef __cplusplus
diff --git a/libavb/avb_slot_verify.c b/libavb/avb_slot_verify.c
index 9124b24..30faac8 100644
--- a/libavb/avb_slot_verify.c
+++ b/libavb/avb_slot_verify.c
@@ -558,6 +558,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
AvbOps* ops,
const char* const* requested_partitions,
const char* ab_suffix,
+ AvbSlotVerifyFlags flags,
bool allow_verification_error,
AvbVBMetaImageFlags toplevel_vbmeta_flags,
int rollback_index_location,
@@ -595,7 +596,12 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
* rollback_index_location to determine whether we're the main
* vbmeta struct.
*/
- is_main_vbmeta = (rollback_index_location == 0);
+ is_main_vbmeta = false;
+ if (rollback_index_location == 0) {
+ if ((flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) == 0) {
+ is_main_vbmeta = true;
+ }
+ }
/* Don't use footers for vbmeta partitions ('vbmeta' or
* 'vbmeta_<partition_name>').
@@ -706,6 +712,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
ret = load_and_verify_vbmeta(ops,
requested_partitions,
ab_suffix,
+ flags,
allow_verification_error,
0 /* toplevel_vbmeta_flags */,
0 /* rollback_index_location */,
@@ -783,6 +790,8 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
}
}
+ uint32_t rollback_index_location_to_use = rollback_index_location;
+
/* Check if key used to make signature matches what is expected. */
if (pk_data != NULL) {
if (expected_public_key != NULL) {
@@ -810,9 +819,27 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
pk_metadata_len = vbmeta_header.public_key_metadata_size;
}
- avb_assert(is_main_vbmeta);
- io_ret = ops->validate_vbmeta_public_key(
- ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
+ // If we're not using a vbmeta partition, need to use another AvbOps...
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ io_ret = ops->validate_public_key_for_partition(
+ ops,
+ full_partition_name,
+ pk_data,
+ pk_len,
+ pk_metadata,
+ pk_metadata_len,
+ &key_is_trusted,
+ &rollback_index_location_to_use);
+ } else {
+ avb_assert(is_main_vbmeta);
+ io_ret = ops->validate_vbmeta_public_key(ops,
+ pk_data,
+ pk_len,
+ pk_metadata,
+ pk_metadata_len,
+ &key_is_trusted);
+ }
+
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
@@ -837,7 +864,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
/* Check rollback index. */
io_ret = ops->read_rollback_index(
- ops, rollback_index_location, &stored_rollback_index);
+ ops, rollback_index_location_to_use, &stored_rollback_index);
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
@@ -863,7 +890,9 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
if (is_main_vbmeta) {
avb_assert(slot_data->num_vbmeta_images == 0);
} else {
- avb_assert(slot_data->num_vbmeta_images > 0);
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ avb_assert(slot_data->num_vbmeta_images > 0);
+ }
}
if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
@@ -987,6 +1016,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
load_and_verify_vbmeta(ops,
requested_partitions,
ab_suffix,
+ flags,
allow_verification_error,
toplevel_vbmeta_flags,
chain_desc.rollback_index_location,
@@ -1348,7 +1378,6 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
avb_assert(ops->read_is_device_unlocked != NULL);
avb_assert(ops->read_from_partition != NULL);
avb_assert(ops->get_size_of_partition != NULL);
- avb_assert(ops->validate_vbmeta_public_key != NULL);
avb_assert(ops->read_rollback_index != NULL);
avb_assert(ops->get_unique_guid_for_partition != NULL);
@@ -1381,6 +1410,21 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
}
}
+ /* Make sure passed-in AvbOps support verifying public keys and getting
+ * rollback index location if not using a vbmeta partition.
+ */
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ if (ops->validate_public_key_for_partition == NULL) {
+ avb_error(
+ "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION was passed but the "
+ "validate_public_key_for_partition() operation isn't implemented.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+ } else {
+ avb_assert(ops->validate_vbmeta_public_key != NULL);
+ }
+
slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
if (slot_data == NULL) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
@@ -1405,21 +1449,55 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
goto fail;
}
- ret = load_and_verify_vbmeta(ops,
- requested_partitions,
- ab_suffix,
- allow_verification_error,
- 0 /* toplevel_vbmeta_flags */,
- 0 /* rollback_index_location */,
- "vbmeta",
- avb_strlen("vbmeta"),
- NULL /* expected_public_key */,
- 0 /* expected_public_key_length */,
- slot_data,
- &algorithm_type,
- additional_cmdline_subst);
- if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
- goto fail;
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ if (requested_partitions == NULL || requested_partitions[0] == NULL) {
+ avb_fatal(
+ "Requested partitions cannot be empty when using "
+ "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+
+ /* No vbmeta partition, go through each of the requested partitions... */
+ for (size_t n = 0; requested_partitions[n] != NULL; n++) {
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ requested_partitions[n],
+ avb_strlen(requested_partitions[n]),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ &algorithm_type,
+ additional_cmdline_subst);
+ if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto fail;
+ }
+ }
+
+ } else {
+ /* Usual path, load "vbmeta"... */
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ "vbmeta",
+ avb_strlen("vbmeta"),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ &algorithm_type,
+ additional_cmdline_subst);
+ if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto fail;
+ }
}
if (!result_should_continue(ret)) {
@@ -1427,10 +1505,12 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
}
/* If things check out, mangle the kernel command-line as needed. */
- if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
- avb_assert(
- avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
- using_boot_for_vbmeta = true;
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
+ avb_assert(
+ avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
+ using_boot_for_vbmeta = true;
+ }
}
/* Byteswap top-level vbmeta header since we'll need it below. */
@@ -1490,6 +1570,7 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
/* Add options... */
AvbSlotVerifyResult sub_ret;
sub_ret = avb_append_options(ops,
+ flags,
slot_data,
&toplevel_vbmeta,
algorithm_type,
diff --git a/libavb/avb_slot_verify.h b/libavb/avb_slot_verify.h
index d42d64c..a2c98f4 100644
--- a/libavb/avb_slot_verify.h
+++ b/libavb/avb_slot_verify.h
@@ -117,11 +117,21 @@ typedef enum {
* should be set if using AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
* and the reason the boot loader is running is because the device
* was restarted by the dm-verity driver.
+ *
+ * If the AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION flag is set then
+ * data won't be loaded from the "vbmeta" partition and the
+ * |validate_vbmeta_public_key| operation is never called. Instead, the
+ * vbmeta structs in |requested_partitions| are loaded and processed and the
+ * |validate_public_key_for_partition| operation is called for each of these
+ * vbmeta structs. This flag is useful when booting into recovery on a device
+ * not using A/B - see section "Booting into recovery" in README.md for
+ * more information.
*/
typedef enum {
AVB_SLOT_VERIFY_FLAGS_NONE = 0,
AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0),
- AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION = (1 << 1)
+ AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION = (1 << 1),
+ AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION = (1 << 2),
} AvbSlotVerifyFlags;
/* Get a textual representation of |result|. */
@@ -245,7 +255,9 @@ typedef struct {
* PARTUUID=$(ANDROID_VBMETA_PARTUUID) before substitution so it
* will end up pointing to the vbmeta partition for the verified
* slot. If there is no vbmeta partition it will point to the boot
- * partition of the verified slot.
+ * partition of the verified slot. If the flag
+ * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is used, this is not
+ * set.
*
* androidboot.vbmeta.avb_version: This is set to the decimal value
* of AVB_VERSION_MAJOR followed by a dot followed by the decimal
diff --git a/test/avb_slot_verify_unittest.cc b/test/avb_slot_verify_unittest.cc
index d27e6e0..28ec151 100644
--- a/test/avb_slot_verify_unittest.cc
+++ b/test/avb_slot_verify_unittest.cc
@@ -1728,6 +1728,115 @@ TEST_F(AvbSlotVerifyTest, OnlyLoadWhatHasBeenRequested) {
EXPECT_TRUE(partitions.find("bar_a") == partitions.end());
}
+TEST_F(AvbSlotVerifyTest, NoVBMetaPartitionFlag) {
+ const size_t foo_partition_size = 16 * 1024 * 1024;
+ const size_t bar_partition_size = 32 * 1024 * 1024;
+ const size_t foo_image_size = 5 * 1024 * 1024;
+ const size_t bar_image_size = 10 * 1024 * 1024;
+ base::FilePath foo_path = GenerateImage("foo_a.img", foo_image_size);
+ base::FilePath bar_path = GenerateImage("bar_a.img", bar_image_size);
+
+ EXPECT_COMMAND(0,
+ "./avbtool add_hash_footer"
+ " --image %s"
+ " --kernel_cmdline 'this is=5 from foo=42'"
+ " --partition_name foo"
+ " --partition_size %zd"
+ " --salt deadbeef"
+ " --internal_release_string \"\""
+ " --algorithm SHA256_RSA4096"
+ " --salt deadbeef"
+ " --key test/data/testkey_rsa4096.pem"
+ " --rollback_index 42",
+ foo_path.value().c_str(),
+ foo_partition_size);
+
+ EXPECT_COMMAND(0,
+ "./avbtool add_hash_footer"
+ " --image %s"
+ " --kernel_cmdline 'and=43 from bar'"
+ " --partition_name bar"
+ " --partition_size %zd"
+ " --salt deadbeef"
+ " --internal_release_string \"\""
+ " --algorithm SHA256_RSA2048"
+ " --salt deadbeef"
+ " --key test/data/testkey_rsa2048.pem"
+ " --rollback_index 43",
+ bar_path.value().c_str(),
+ bar_partition_size);
+
+ ops_.set_expected_public_key_for_partition(
+ "foo_a",
+ PublicKeyAVB(base::FilePath("test/data/testkey_rsa4096.pem")),
+ 1);
+ ops_.set_expected_public_key_for_partition(
+ "bar_a",
+ PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")),
+ 2);
+ ops_.set_stored_rollback_indexes({{0, 1000}, {1, 10}, {2, 11}});
+ AvbSlotVerifyData* slot_data = NULL;
+ const char* requested_partitions[] = {"foo", "bar", NULL};
+
+ // Without AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION, this should fail because
+ // vbmeta_a (or boot_a) cannot not be found.
+ EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_IO,
+ avb_slot_verify(ops_.avb_ops(),
+ requested_partitions,
+ "_a",
+ AVB_SLOT_VERIFY_FLAGS_NONE,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+ &slot_data));
+
+ // However, with this flag it should succeed (note that rollback indexes in
+ // the images exceed the stored rollback indexes)
+ EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
+ avb_slot_verify(ops_.avb_ops(),
+ requested_partitions,
+ "_a",
+ AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+ &slot_data));
+ EXPECT_NE(nullptr, slot_data);
+ EXPECT_EQ(size_t(2), slot_data->num_loaded_partitions);
+ EXPECT_EQ("foo", std::string(slot_data->loaded_partitions[0].partition_name));
+ EXPECT_EQ("bar", std::string(slot_data->loaded_partitions[1].partition_name));
+ // Note the absence of 'androidboot.vbmeta.device'
+ EXPECT_EQ(
+ "this is=5 from foo=42 and=43 from bar "
+ "androidboot.vbmeta.avb_version=1.1 "
+ "androidboot.vbmeta.device_state=locked "
+ "androidboot.vbmeta.hash_alg=sha256 "
+ "androidboot.vbmeta.size=3456 "
+ "androidboot.vbmeta.digest="
+ "b5dbfb1743073f9a4cb45f94d1d849f89ca9777d158a2a06d09517c79ffd86cd "
+ "androidboot.vbmeta.invalidate_on_error=yes "
+ "androidboot.veritymode=enforcing",
+ std::string(slot_data->cmdline));
+ avb_slot_verify_data_free(slot_data);
+
+ // Check that rollback protection works if we increase the stored rollback
+ // indexes to exceed that of the image... do a check for each location.
+ ops_.set_stored_rollback_indexes({{0, 1000}, {1, 10}, {2, 100}});
+ EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
+ avb_slot_verify(ops_.avb_ops(),
+ requested_partitions,
+ "_a",
+ AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+ &slot_data));
+ EXPECT_EQ(nullptr, slot_data);
+ ops_.set_stored_rollback_indexes({{0, 1000}, {1, 100}, {2, 10}});
+ EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
+ avb_slot_verify(ops_.avb_ops(),
+ requested_partitions,
+ "_a",
+ AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+ &slot_data));
+ EXPECT_EQ(nullptr, slot_data);
+}
+
TEST_F(AvbSlotVerifyTest, PublicKeyMetadata) {
base::FilePath md_path = GenerateImage("md.bin", 1536);
diff --git a/test/fake_avb_ops.cc b/test/fake_avb_ops.cc
index 2fdba10..6e8ab8c 100644
--- a/test/fake_avb_ops.cc
+++ b/test/fake_avb_ops.cc
@@ -262,6 +262,30 @@ AvbIOResult FakeAvbOps::validate_vbmeta_public_key(
return AVB_IO_RESULT_OK;
}
+AvbIOResult FakeAvbOps::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) {
+ std::string expected_public_key =
+ expected_public_key_for_partition_map_[partition];
+ uint32_t rollback_index_location =
+ rollback_index_location_for_partition_map_[partition];
+ if (out_key_is_trusted != NULL) {
+ bool pk_matches = (public_key_length == expected_public_key.size() &&
+ (memcmp(expected_public_key.c_str(),
+ public_key_data,
+ public_key_length) == 0));
+ *out_key_is_trusted = pk_matches;
+ *out_rollback_index_location = rollback_index_location;
+ }
+ return AVB_IO_RESULT_OK;
+}
+
AvbIOResult FakeAvbOps::read_rollback_index(AvbOps* ops,
size_t rollback_index_location,
uint64_t* out_rollback_index) {
@@ -436,6 +460,27 @@ static AvbIOResult my_ops_validate_vbmeta_public_key(
out_key_is_trusted);
}
+static AvbIOResult 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) {
+ return FakeAvbOps::GetInstanceFromAvbOps(ops)
+ ->delegate()
+ ->validate_public_key_for_partition(ops,
+ partition,
+ public_key_data,
+ public_key_length,
+ public_key_metadata,
+ public_key_metadata_length,
+ out_key_is_trusted,
+ out_rollback_index_location);
+}
+
static AvbIOResult my_ops_read_rollback_index(AvbOps* ops,
size_t rollback_index_location,
uint64_t* out_rollback_index) {
@@ -541,6 +586,8 @@ FakeAvbOps::FakeAvbOps() {
avb_ops_.get_size_of_partition = my_ops_get_size_of_partition;
avb_ops_.read_persistent_value = my_ops_read_persistent_value;
avb_ops_.write_persistent_value = my_ops_write_persistent_value;
+ avb_ops_.validate_public_key_for_partition =
+ my_ops_validate_public_key_for_partition;
// Just use the built-in A/B metadata read/write routines.
avb_ab_ops_.ops = &avb_ops_;
diff --git a/test/fake_avb_ops.h b/test/fake_avb_ops.h
index 935dbf4..2cc12d8 100644
--- a/test/fake_avb_ops.h
+++ b/test/fake_avb_ops.h
@@ -95,6 +95,16 @@ class FakeAvbOpsDelegate {
size_t value_size,
const uint8_t* value) = 0;
+ virtual AvbIOResult 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_is_trusted,
+ uint32_t* out_rollback_index_location) = 0;
+
virtual AvbIOResult read_permanent_attributes(
AvbAtxPermanentAttributes* attributes) = 0;
@@ -150,6 +160,16 @@ class FakeAvbOps : public FakeAvbOpsDelegate {
expected_public_key_ = expected_public_key;
}
+ void set_expected_public_key_for_partition(
+ const std::string& partition_name,
+ const std::string& expected_public_key,
+ uint32_t rollback_index_location) {
+ expected_public_key_for_partition_map_[partition_name] =
+ expected_public_key;
+ rollback_index_location_for_partition_map_[partition_name] =
+ rollback_index_location;
+ }
+
void set_expected_public_key_metadata(
const std::string& expected_public_key_metadata) {
expected_public_key_metadata_ = expected_public_key_metadata;
@@ -248,6 +268,16 @@ class FakeAvbOps : public FakeAvbOpsDelegate {
size_t value_size,
const uint8_t* value) override;
+ AvbIOResult 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_is_trusted,
+ uint32_t* out_rollback_index_location) override;
+
AvbIOResult read_permanent_attributes(
AvbAtxPermanentAttributes* attributes) override;
@@ -271,6 +301,10 @@ class FakeAvbOps : public FakeAvbOpsDelegate {
std::string expected_public_key_;
std::string expected_public_key_metadata_;
+ std::map<std::string, std::string> expected_public_key_for_partition_map_;
+
+ std::map<std::string, uint32_t> rollback_index_location_for_partition_map_;
+
std::map<size_t, uint64_t> stored_rollback_indexes_;
std::map<size_t, uint64_t> verified_rollback_indexes_;
@@ -328,6 +362,25 @@ class FakeAvbOpsDelegateWithDefaults : public FakeAvbOpsDelegate {
out_key_is_trusted);
}
+ AvbIOResult 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) override {
+ return ops_.validate_public_key_for_partition(ops,
+ partition,
+ public_key_data,
+ public_key_length,
+ public_key_metadata,
+ public_key_metadata_length,
+ out_key_is_trusted,
+ out_rollback_index_location);
+ }
+
AvbIOResult read_rollback_index(AvbOps* ops,
size_t rollback_index_slot,
uint64_t* out_rollback_index) override {