summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zhu <jason.zhu@rock-chips.com>2018-06-13 14:27:58 +0800
committerTreeHugger Robot <treehugger-gerrit@google.com>2018-07-06 21:38:24 +0000
commit234a3aae025c3eae57c9267bb10c9ba6d531fdd8 (patch)
treea9c4503c5b921021fac9bf9331ff304c411a5272
parentc0e73e5f326c9e9bc75e47d0aa58962e099d45aa (diff)
downloadrk-u-boot-234a3aae025c3eae57c9267bb10c9ba6d531fdd8.tar.gz
lib: avb: update lib avb
1.put the (.c&.h) file together according to google. 2. update the lib avb to support more feature. The commit ID: 44e07124afb1f46af0d745d83481f49c482900b1 Change-Id: I59dbb5319285a587241e0147db7b0418142d1195 Signed-off-by: Jason Zhu <jason.zhu@rock-chips.com>
-rw-r--r--cmd/boot_android.c6
-rw-r--r--common/android_bootloader.c1
-rw-r--r--drivers/usb/gadget/f_fastboot.c1
-rw-r--r--include/android_avb/rk_avb_ops_user.h38
-rw-r--r--lib/Kconfig1
-rw-r--r--lib/Makefile1
-rw-r--r--lib/avb/libavb/Makefile2
-rw-r--r--lib/avb/libavb/avb_chain_partition_descriptor.c128
-rw-r--r--lib/avb/libavb/avb_chain_partition_descriptor.h (renamed from include/android_avb/avb_chain_partition_descriptor.h)146
-rw-r--r--lib/avb/libavb/avb_cmdline.c811
-rw-r--r--lib/avb/libavb/avb_cmdline.h (renamed from include/android_avb/avb_cmdline.h)152
-rw-r--r--lib/avb/libavb/avb_crc32.c228
-rw-r--r--lib/avb/libavb/avb_crypto.c744
-rw-r--r--lib/avb/libavb/avb_crypto.h (renamed from include/android_avb/avb_crypto.h)341
-rw-r--r--lib/avb/libavb/avb_descriptor.c320
-rw-r--r--lib/avb/libavb/avb_descriptor.h (renamed from include/android_avb/avb_descriptor.h)264
-rw-r--r--lib/avb/libavb/avb_footer.c108
-rw-r--r--lib/avb/libavb/avb_footer.h (renamed from include/android_avb/avb_footer.h)174
-rw-r--r--lib/avb/libavb/avb_hash_descriptor.c123
-rw-r--r--lib/avb/libavb/avb_hash_descriptor.h (renamed from include/android_avb/avb_hash_descriptor.h)163
-rw-r--r--lib/avb/libavb/avb_hashtree_descriptor.c139
-rw-r--r--lib/avb/libavb/avb_hashtree_descriptor.h (renamed from include/android_avb/avb_hashtree_descriptor.h)183
-rw-r--r--lib/avb/libavb/avb_kernel_cmdline_descriptor.c116
-rw-r--r--lib/avb/libavb/avb_kernel_cmdline_descriptor.h (renamed from include/android_avb/avb_kernel_cmdline_descriptor.h)164
-rw-r--r--lib/avb/libavb/avb_ops.h (renamed from include/android_avb/avb_ops.h)567
-rw-r--r--lib/avb/libavb/avb_property_descriptor.c370
-rw-r--r--lib/avb/libavb/avb_property_descriptor.h (renamed from include/android_avb/avb_property_descriptor.h)216
-rw-r--r--lib/avb/libavb/avb_rsa.c598
-rw-r--r--lib/avb/libavb/avb_rsa.h (renamed from include/android_avb/avb_rsa.h)150
-rw-r--r--lib/avb/libavb/avb_sha.h (renamed from include/android_avb/avb_sha.h)182
-rw-r--r--lib/avb/libavb/avb_sha256.c780
-rw-r--r--lib/avb/libavb/avb_sha512.c776
-rw-r--r--lib/avb/libavb/avb_slot_verify.c2540
-rw-r--r--lib/avb/libavb/avb_slot_verify.h (renamed from include/android_avb/avb_slot_verify.h)711
-rw-r--r--lib/avb/libavb/avb_sysdeps.h (renamed from include/android_avb/avb_sysdeps.h)258
-rw-r--r--lib/avb/libavb/avb_sysdeps_posix.c171
-rw-r--r--lib/avb/libavb/avb_util.c833
-rw-r--r--lib/avb/libavb/avb_util.h (renamed from include/android_avb/avb_util.h)566
-rw-r--r--lib/avb/libavb/avb_vbmeta_image.c616
-rw-r--r--lib/avb/libavb/avb_vbmeta_image.h (renamed from include/android_avb/avb_vbmeta_image.h)590
-rw-r--r--lib/avb/libavb/avb_version.c68
-rw-r--r--lib/avb/libavb/avb_version.h (renamed from include/android_avb/avb_version.h)120
-rw-r--r--lib/avb/libavb/libavb.h (renamed from include/android_avb/libavb.h)100
-rw-r--r--lib/avb/libavb_ab/Makefile1
-rw-r--r--lib/avb/libavb_ab/avb_ab_flow.c1062
-rw-r--r--lib/avb/libavb_ab/avb_ab_flow.h (renamed from include/android_avb/avb_ab_flow.h)524
-rw-r--r--lib/avb/libavb_ab/avb_ab_ops.h (renamed from include/android_avb/avb_ab_ops.h)160
-rw-r--r--lib/avb/libavb_ab/libavb_ab.h (renamed from include/android_avb/libavb_ab.h)105
-rw-r--r--lib/avb/libavb_atx/Makefile1
-rw-r--r--lib/avb/libavb_atx/avb_atx_ops.h (renamed from include/android_avb/avb_atx_ops.h)161
-rw-r--r--lib/avb/libavb_atx/avb_atx_types.h (renamed from include/android_avb/avb_atx_types.h)176
-rw-r--r--lib/avb/libavb_atx/avb_atx_validate.c657
-rw-r--r--lib/avb/libavb_atx/avb_atx_validate.h (renamed from include/android_avb/avb_atx_validate.h)170
-rw-r--r--lib/avb/libavb_atx/libavb_atx.h (renamed from include/android_avb/libavb_atx.h)82
-rw-r--r--lib/avb/libavb_user/Makefile1
-rw-r--r--lib/avb/libavb_user/avb_ops_user.c396
-rw-r--r--lib/avb/libavb_user/avb_ops_user.cpp347
-rw-r--r--lib/avb/libavb_user/avb_ops_user.h (renamed from include/android_avb/avb_ops_user.h)139
-rw-r--r--lib/avb/libavb_user/avb_user_verification.c428
-rw-r--r--lib/avb/libavb_user/avb_user_verification.h (renamed from include/android_avb/avb_user_verification.h)126
-rw-r--r--lib/avb/libavb_user/avb_user_verity.c426
-rw-r--r--lib/avb/libavb_user/avb_user_verity.h (renamed from include/android_avb/avb_user_verity.h)126
-rw-r--r--lib/avb/libavb_user/libavb_user.h (renamed from include/android_avb/libavb_user.h)82
-rw-r--r--lib/avb/rk_avb_user/Makefile2
-rw-r--r--lib/avb/rk_avb_user/rk_avb_ops_user.c370
-rw-r--r--lib/avb/rk_avb_user/rk_avb_sysdeps_uboot.c83
66 files changed, 10606 insertions, 9585 deletions
diff --git a/cmd/boot_android.c b/cmd/boot_android.c
index f29a21c5ee..6319db6f63 100644
--- a/cmd/boot_android.c
+++ b/cmd/boot_android.c
@@ -5,9 +5,7 @@
*/
#include <android_bootloader.h>
-#include <android_avb/avb_version.h>
-#include <android_avb/avb_ab_flow.h>
-#include <android_avb/avb_ops_user.h>
+#include <libavb/libavb.h>
#include <android_cmds.h>
#include <malloc.h>
#include <common.h>
@@ -199,7 +197,7 @@ int do_avb_flow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (ops->read_is_device_unlocked(ops, &unlocked) != AVB_IO_RESULT_OK) {
printf("Error determining whether device is unlocked.\n");
unlocked = ANDROID_VBOOT_UNLOCK;
- if (ops->write_is_device_unlocked(ops, &unlocked) != AVB_IO_RESULT_OK) {
+ if (write_is_device_unlocked(ops, &unlocked) != AVB_IO_RESULT_OK) {
printf("Can not write lock state!\n");
unlocked = ANDROID_VBOOT_LOCK;
}
diff --git a/common/android_bootloader.c b/common/android_bootloader.c
index 2e4fb26e72..a4186b7ab2 100644
--- a/common/android_bootloader.c
+++ b/common/android_bootloader.c
@@ -6,7 +6,6 @@
#include <android_bootloader.h>
#include <android_bootloader_message.h>
-#include <android_avb/avb_ops_user.h>
#include <android_avb/rk_avb_ops_user.h>
#include <cli.h>
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 05a2fb2d96..b7294a3c61 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -24,7 +24,6 @@
#include <version.h>
#include <g_dnl.h>
#include <fs.h>
-#include <android_avb/avb_ops_user.h>
#include <android_avb/rk_avb_ops_user.h>
#include <dm/uclass.h>
#include <power/fuel_gauge.h>
diff --git a/include/android_avb/rk_avb_ops_user.h b/include/android_avb/rk_avb_ops_user.h
index 51197a0bf1..f2b06d9edc 100644
--- a/include/android_avb/rk_avb_ops_user.h
+++ b/include/android_avb/rk_avb_ops_user.h
@@ -7,7 +7,10 @@
#ifndef RK_AVB_OPS_USER_H_
#define RK_AVB_OPS_USER_H_
-#include <android_avb/avb_atx_validate.h>
+#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
+#include <libavb/libavb.h>
+#include <libavb_ab/libavb_ab.h>
+#include <libavb_atx/libavb_atx.h>
#ifdef __cplusplus
extern "C" {
@@ -34,6 +37,37 @@ extern "C" {
#define UBOOT_RB_INDEX_OFFSET 24
#define TRUST_RB_INDEX_OFFSET 28
+/* Allocates an AvbOps instance suitable for use in Android userspace
+ * on the device. Returns NULL on OOM.
+ *
+ * The returned AvbOps has the following characteristics:
+ *
+ * - The read_from_partition(), write_to_partition(), and
+ * get_size_of_partition() operations are implemented, however for
+ * these operations to work the fstab file on the device must have a
+ * /misc entry using a by-name device file scheme and the containing
+ * by-name/ subdirectory must have files for other partitions.
+ *
+ * - The remaining operations are implemented and never fails and
+ * return the following values:
+ * - validate_vbmeta_public_key(): always returns |true|.
+ * - read_rollback_index(): returns 0 for any roolback index.
+ * - write_rollback_index(): no-op.
+ * - read_is_device_unlocked(): always returns |true|.
+ * - get_unique_guid_for_partition(): always returns the empty string.
+ *
+ * - The |ab_ops| member will point to a valid AvbABOps instance
+ * implemented via libavb_ab/. This should only be used if the AVB
+ * A/B stack is used on the device. This is what is used in
+ * bootctrl.avb boot control implementation.
+ *
+ * Free with avb_ops_user_free().
+ */
+AvbOps* avb_ops_user_new(void);
+
+/* Frees an AvbOps instance previously allocated with avb_ops_device_new(). */
+void avb_ops_user_free(AvbOps* ops);
+
/**
* Provided to fastboot to read how many slot in this system.
*
@@ -259,6 +293,8 @@ void rk_set_key_version(AvbAtxOps* atx_ops,
size_t rollback_index_location,
uint64_t key_version);
+AvbIOResult write_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/Kconfig b/lib/Kconfig
index 76b1acd096..b43fcd2f30 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -271,7 +271,6 @@ source lib/efi_loader/Kconfig
source lib/avb/libavb/Kconfig
source lib/avb/libavb_ab/Kconfig
source lib/avb/libavb_atx/Kconfig
-source lib/avb/libavb_user/Kconfig
source lib/avb/rk_avb_user/Kconfig
source lib/optee_clientApi/Kconfig
diff --git a/lib/Makefile b/lib/Makefile
index 151e588908..b17b55144b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -49,7 +49,6 @@ endif
obj-$(CONFIG_$(SPL_TPL_)AVB_LIBAVB) += avb/libavb/
obj-$(CONFIG_$(SPL_TPL_)AVB_LIBAVB_AB) += avb/libavb_ab/
obj-$(CONFIG_$(SPL_TPL_)AVB_LIBAVB_ATX) += avb/libavb_atx/
-obj-$(CONFIG_$(SPL_TPL_)AVB_LIBAVB_USER) += avb/libavb_user/
obj-$(CONFIG_$(SPL_TPL_)RK_AVB_LIBAVB_USER) += avb/rk_avb_user/
obj-$(CONFIG_RSA) += rsa/
diff --git a/lib/avb/libavb/Makefile b/lib/avb/libavb/Makefile
index 7b3d37b052..00fa9b1690 100644
--- a/lib/avb/libavb/Makefile
+++ b/lib/avb/libavb/Makefile
@@ -1,3 +1,4 @@
+ccflags-y += -DAVB_COMPILATION
obj-y += avb_chain_partition_descriptor.o
obj-y += avb_cmdline.o
obj-y += avb_crc32.o
@@ -11,7 +12,6 @@ obj-y += avb_property_descriptor.o
obj-y += avb_rsa.o
obj-y += avb_sha256.o
obj-y += avb_sha512.o
-obj-y += avb_sysdeps_posix.o
obj-y += avb_slot_verify.o
obj-y += avb_util.o
obj-y += avb_vbmeta_image.o
diff --git a/lib/avb/libavb/avb_chain_partition_descriptor.c b/lib/avb/libavb/avb_chain_partition_descriptor.c
index c325f7daf3..3f14232593 100644
--- a/lib/avb/libavb/avb_chain_partition_descriptor.c
+++ b/lib/avb/libavb/avb_chain_partition_descriptor.c
@@ -1,64 +1,64 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_chain_partition_descriptor.h>
-#include <android_avb/avb_util.h>
-
-bool avb_chain_partition_descriptor_validate_and_byteswap(
- const AvbChainPartitionDescriptor* src, AvbChainPartitionDescriptor* dest) {
- uint64_t expected_size;
-
- avb_memcpy(dest, src, sizeof(AvbChainPartitionDescriptor));
-
- if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
- (AvbDescriptor*)dest))
- return false;
-
- if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_CHAIN_PARTITION) {
- avb_error("Invalid tag for chain partition descriptor.\n");
- return false;
- }
-
- 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);
-
- if (dest->rollback_index_location < 1) {
- avb_error("Invalid rollback index location value.\n");
- return false;
- }
-
- /* Check that partition_name and public_key are fully contained. */
- expected_size = sizeof(AvbChainPartitionDescriptor) - sizeof(AvbDescriptor);
- if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
- !avb_safe_add_to(&expected_size, dest->public_key_len)) {
- avb_error("Overflow while adding up sizes.\n");
- return false;
- }
- if (expected_size > dest->parent_descriptor.num_bytes_following) {
- avb_error("Descriptor payload size overflow.\n");
- return false;
- }
- return true;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_chain_partition_descriptor.h"
+#include "avb_util.h"
+
+bool avb_chain_partition_descriptor_validate_and_byteswap(
+ const AvbChainPartitionDescriptor* src, AvbChainPartitionDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbChainPartitionDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_CHAIN_PARTITION) {
+ avb_error("Invalid tag for chain partition descriptor.\n");
+ return false;
+ }
+
+ 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);
+
+ if (dest->rollback_index_location < 1) {
+ avb_error("Invalid rollback index location value.\n");
+ return false;
+ }
+
+ /* Check that partition_name and public_key are fully contained. */
+ expected_size = sizeof(AvbChainPartitionDescriptor) - sizeof(AvbDescriptor);
+ if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
+ !avb_safe_add_to(&expected_size, dest->public_key_len)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+ return true;
+}
diff --git a/include/android_avb/avb_chain_partition_descriptor.h b/lib/avb/libavb/avb_chain_partition_descriptor.h
index 2c0a38d58a..f2c9250156 100644
--- a/include/android_avb/avb_chain_partition_descriptor.h
+++ b/lib/avb/libavb/avb_chain_partition_descriptor.h
@@ -1,74 +1,72 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_CHAIN_PARTITION_DESCRIPTOR_H_
-#define AVB_CHAIN_PARTITION_DESCRIPTOR_H_
-
-#include <android_avb/avb_descriptor.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* 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
- * integrity data, and rollback index location to use for rollback
- * protection.
- *
- * Following this struct are |partition_name_len| bytes of the
- * partition name (UTF-8 encoded) and |public_key_len| bytes of the
- * public key.
- *
- * The |reserved| field is for future expansion and must be set to NUL
- * bytes.
- */
-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];
-} AVB_ATTR_PACKED AvbChainPartitionDescriptor;
-
-/* Copies |src| to |dest| and validates, byte-swapping fields in the
- * process if needed. Returns true if valid, false if invalid.
- *
- * Data following the struct is not validated nor copied.
- */
-bool avb_chain_partition_descriptor_validate_and_byteswap(
- const AvbChainPartitionDescriptor* src,
- AvbChainPartitionDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_CHAIN_PARTITION_DESCRIPTOR_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_CHAIN_PARTITION_DESCRIPTOR_H_
+#define AVB_CHAIN_PARTITION_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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
+ * integrity data, and rollback index location to use for rollback
+ * protection.
+ *
+ * Following this struct are |partition_name_len| bytes of the
+ * partition name (UTF-8 encoded) and |public_key_len| bytes of the
+ * public key.
+ *
+ * The |reserved| field is for future expansion and must be set to NUL
+ * bytes.
+ */
+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];
+} AVB_ATTR_PACKED AvbChainPartitionDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_chain_partition_descriptor_validate_and_byteswap(
+ const AvbChainPartitionDescriptor* src,
+ AvbChainPartitionDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_CHAIN_PARTITION_DESCRIPTOR_H_ */
diff --git a/lib/avb/libavb/avb_cmdline.c b/lib/avb/libavb/avb_cmdline.c
index ecf582ebd9..3f4b99ace9 100644
--- a/lib/avb/libavb/avb_cmdline.c
+++ b/lib/avb/libavb/avb_cmdline.c
@@ -1,371 +1,440 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_cmdline.h>
-#include <android_avb/avb_sha.h>
-#include <android_avb/avb_util.h>
-#include <android_avb/avb_version.h>
-
-#define NUM_GUIDS 3
-
-/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
- * values. Returns NULL on OOM, otherwise the cmdline with values
- * replaced.
- */
-char* avb_sub_cmdline(AvbOps* ops, const char* cmdline, const char* ab_suffix,
- bool using_boot_for_vbmeta) {
- const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
- const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
- "$(ANDROID_BOOT_PARTUUID)",
- "$(ANDROID_VBMETA_PARTUUID)"};
- char* ret = NULL;
- AvbIOResult io_ret;
- size_t n;
-
- /* Special-case for when the top-level vbmeta struct is in the boot
- * partition.
- */
- if (using_boot_for_vbmeta) {
- part_name_str[2] = "boot";
- }
-
- /* Replace unique partition GUIDs */
- for (n = 0; n < NUM_GUIDS; n++) {
- char part_name[AVB_PART_NAME_MAX_SIZE];
- char guid_buf[37];
-
- if (!avb_str_concat(part_name,
- sizeof part_name,
- part_name_str[n],
- avb_strlen(part_name_str[n]),
- ab_suffix,
- avb_strlen(ab_suffix))) {
- avb_error("Partition name and suffix does not fit.\n");
- goto fail;
- }
-
- io_ret = ops->get_unique_guid_for_partition(
- ops, part_name, guid_buf, sizeof guid_buf);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- return NULL;
- } else if (io_ret != AVB_IO_RESULT_OK) {
- avb_error("Error getting unique GUID for partition.\n");
- goto fail;
- }
-
- if (ret == NULL) {
- ret = avb_replace(cmdline, replace_str[n], guid_buf);
- } else {
- char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
- avb_free(ret);
- ret = new_ret;
- }
- if (ret == NULL) {
- goto fail;
- }
- }
-
- return ret;
-
-fail:
- if (ret != NULL) {
- avb_free(ret);
- }
- return NULL;
-}
-
-static int cmdline_append_option(AvbSlotVerifyData* slot_data,
- const char* key,
- const char* value) {
- size_t offset, key_len, value_len;
- char* new_cmdline;
-
- key_len = avb_strlen(key);
- value_len = avb_strlen(value);
-
- offset = 0;
- if (slot_data->cmdline != NULL) {
- offset = avb_strlen(slot_data->cmdline);
- if (offset > 0) {
- offset += 1;
- }
- }
-
- new_cmdline = avb_calloc(offset + key_len + value_len + 2);
- if (new_cmdline == NULL) {
- return 0;
- }
- if (offset > 0) {
- avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
- new_cmdline[offset - 1] = ' ';
- }
- avb_memcpy(new_cmdline + offset, key, key_len);
- new_cmdline[offset + key_len] = '=';
- avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
- if (slot_data->cmdline != NULL) {
- avb_free(slot_data->cmdline);
- }
- slot_data->cmdline = new_cmdline;
-
- 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,
- uint64_t minor_version) {
- char major_digits[AVB_MAX_DIGITS_UINT64];
- char minor_digits[AVB_MAX_DIGITS_UINT64];
- 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);
- avb_memcpy(combined, major_digits, num_major_digits);
- combined[num_major_digits] = '.';
- avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
- combined[num_major_digits + 1 + num_minor_digits] = '\0';
-
- return cmdline_append_option(slot_data, key, combined);
-}
-
-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);
- return cmdline_append_option(slot_data, key, digits);
-}
-
-static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
- const char* key,
- const uint8_t* data,
- size_t data_len) {
- char hex_digits[17] = "0123456789abcdef";
- char* hex_data;
- int ret;
- size_t n;
-
- hex_data = avb_malloc(data_len * 2 + 1);
- if (hex_data == NULL) {
- return 0;
- }
-
- for (n = 0; n < data_len; n++) {
- hex_data[n * 2] = hex_digits[data[n] >> 4];
- hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
- }
- hex_data[n * 2] = '\0';
-
- ret = cmdline_append_option(slot_data, key, hex_data);
- avb_free(hex_data);
- return ret;
-}
-
-AvbSlotVerifyResult avb_append_options(
- AvbOps* ops,
- AvbSlotVerifyData* slot_data,
- AvbVBMetaImageHeader* toplevel_vbmeta,
- AvbAlgorithmType algorithm_type,
- AvbHashtreeErrorMode hashtree_error_mode) {
- AvbSlotVerifyResult ret;
- const char* verity_mode = NULL;
- 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.avb_version option. */
- if (!cmdline_append_version(slot_data,
- "androidboot.vbmeta.avb_version",
- AVB_VERSION_MAJOR,
- AVB_VERSION_MINOR)) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
-
- /* Set androidboot.avb.device_state to "locked" or "unlocked". */
- io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- } else if (io_ret != AVB_IO_RESULT_OK) {
- avb_error("Error getting device state.\n");
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- goto out;
- }
- if (!cmdline_append_option(slot_data,
- "androidboot.vbmeta.device_state",
- is_device_unlocked ? "unlocked" : "locked")) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
-
- /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
- * function as is used to sign vbmeta.
- */
- switch (algorithm_type) {
- /* Explicit fallthrough. */
- case AVB_ALGORITHM_TYPE_NONE:
- case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
- case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
- case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
- AvbSHA256Ctx ctx;
- size_t n, total_size = 0;
- avb_sha256_init(&ctx);
- for (n = 0; n < slot_data->num_vbmeta_images; n++) {
- avb_sha256_update(&ctx,
- slot_data->vbmeta_images[n].vbmeta_data,
- slot_data->vbmeta_images[n].vbmeta_size);
- total_size += slot_data->vbmeta_images[n].vbmeta_size;
- }
- if (!cmdline_append_option(
- slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
- !cmdline_append_uint64_base10(
- slot_data, "androidboot.vbmeta.size", total_size) ||
- !cmdline_append_hex(slot_data,
- "androidboot.vbmeta.digest",
- avb_sha256_final(&ctx),
- AVB_SHA256_DIGEST_SIZE)) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
- } break;
- /* Explicit fallthrough. */
- case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
- case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
- case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
- AvbSHA512Ctx ctx;
- size_t n, total_size = 0;
- avb_sha512_init(&ctx);
- for (n = 0; n < slot_data->num_vbmeta_images; n++) {
- avb_sha512_update(&ctx,
- slot_data->vbmeta_images[n].vbmeta_data,
- slot_data->vbmeta_images[n].vbmeta_size);
- total_size += slot_data->vbmeta_images[n].vbmeta_size;
- }
- if (!cmdline_append_option(
- slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
- !cmdline_append_uint64_base10(
- slot_data, "androidboot.vbmeta.size", total_size) ||
- !cmdline_append_hex(slot_data,
- "androidboot.vbmeta.digest",
- avb_sha512_final(&ctx),
- AVB_SHA512_DIGEST_SIZE)) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
- } break;
- case _AVB_ALGORITHM_NUM_TYPES:
- avb_assert_not_reached();
- break;
- }
-
- /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
- if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
- verity_mode = "disabled";
- } else {
- const char* dm_verity_mode = NULL;
- char* new_ret;
-
- switch (hashtree_error_mode) {
- case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
- if (!cmdline_append_option(
- slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
- verity_mode = "enforcing";
- dm_verity_mode = "restart_on_corruption";
- break;
- case AVB_HASHTREE_ERROR_MODE_RESTART:
- verity_mode = "enforcing";
- dm_verity_mode = "restart_on_corruption";
- break;
- case AVB_HASHTREE_ERROR_MODE_EIO:
- verity_mode = "eio";
- /* For now there's no option to specify the EIO mode. So
- * just use 'ignore_zero_blocks' since that's already set
- * and dm-verity-target.c supports specifying this multiple
- * times.
- */
- dm_verity_mode = "ignore_zero_blocks";
- break;
- case AVB_HASHTREE_ERROR_MODE_LOGGING:
- verity_mode = "logging";
- dm_verity_mode = "ignore_corruption";
- break;
- }
- new_ret = avb_replace(
- slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
- avb_free(slot_data->cmdline);
- slot_data->cmdline = new_ret;
- if (slot_data->cmdline == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
- }
- if (!cmdline_append_option(
- slot_data, "androidboot.veritymode", verity_mode)) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
-
- ret = AVB_SLOT_VERIFY_RESULT_OK;
-
-out:
-
- return ret;
-}
-
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_cmdline.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_version.h"
+
+#define NUM_GUIDS 3
+
+/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
+ * values. Returns NULL on OOM, otherwise the cmdline with values
+ * replaced.
+ */
+char* avb_sub_cmdline(AvbOps* ops,
+ const char* cmdline,
+ const char* ab_suffix,
+ bool using_boot_for_vbmeta,
+ const AvbCmdlineSubstList* additional_substitutions) {
+ const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
+ const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
+ "$(ANDROID_BOOT_PARTUUID)",
+ "$(ANDROID_VBMETA_PARTUUID)"};
+ char* ret = NULL;
+ AvbIOResult io_ret;
+ size_t n;
+
+ /* Special-case for when the top-level vbmeta struct is in the boot
+ * partition.
+ */
+ if (using_boot_for_vbmeta) {
+ part_name_str[2] = "boot";
+ }
+
+ /* Replace unique partition GUIDs */
+ for (n = 0; n < NUM_GUIDS; n++) {
+ char part_name[AVB_PART_NAME_MAX_SIZE];
+ char guid_buf[37];
+
+ if (!avb_str_concat(part_name,
+ sizeof part_name,
+ part_name_str[n],
+ avb_strlen(part_name_str[n]),
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("Partition name and suffix does not fit.\n");
+ goto fail;
+ }
+
+ io_ret = ops->get_unique_guid_for_partition(
+ ops, part_name, guid_buf, sizeof guid_buf);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ goto fail;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error getting unique GUID for partition.\n");
+ goto fail;
+ }
+
+ if (ret == NULL) {
+ ret = avb_replace(cmdline, replace_str[n], guid_buf);
+ } else {
+ char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
+ avb_free(ret);
+ ret = new_ret;
+ }
+ if (ret == NULL) {
+ goto fail;
+ }
+ }
+
+ avb_assert(ret != NULL);
+
+ /* Replace any additional substitutions. */
+ if (additional_substitutions != NULL) {
+ for (n = 0; n < additional_substitutions->size; ++n) {
+ char* new_ret = avb_replace(ret,
+ additional_substitutions->tokens[n],
+ additional_substitutions->values[n]);
+ avb_free(ret);
+ ret = new_ret;
+ if (ret == NULL) {
+ goto fail;
+ }
+ }
+ }
+
+ return ret;
+
+fail:
+ if (ret != NULL) {
+ avb_free(ret);
+ }
+ return NULL;
+}
+
+static int cmdline_append_option(AvbSlotVerifyData* slot_data,
+ const char* key,
+ const char* value) {
+ size_t offset, key_len, value_len;
+ char* new_cmdline;
+
+ key_len = avb_strlen(key);
+ value_len = avb_strlen(value);
+
+ offset = 0;
+ if (slot_data->cmdline != NULL) {
+ offset = avb_strlen(slot_data->cmdline);
+ if (offset > 0) {
+ offset += 1;
+ }
+ }
+
+ new_cmdline = avb_calloc(offset + key_len + value_len + 2);
+ if (new_cmdline == NULL) {
+ return 0;
+ }
+ if (offset > 0) {
+ avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
+ new_cmdline[offset - 1] = ' ';
+ }
+ avb_memcpy(new_cmdline + offset, key, key_len);
+ new_cmdline[offset + key_len] = '=';
+ avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
+ if (slot_data->cmdline != NULL) {
+ avb_free(slot_data->cmdline);
+ }
+ slot_data->cmdline = new_cmdline;
+
+ 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,
+ uint64_t minor_version) {
+ char major_digits[AVB_MAX_DIGITS_UINT64];
+ char minor_digits[AVB_MAX_DIGITS_UINT64];
+ 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);
+ avb_memcpy(combined, major_digits, num_major_digits);
+ combined[num_major_digits] = '.';
+ avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
+ combined[num_major_digits + 1 + num_minor_digits] = '\0';
+
+ return cmdline_append_option(slot_data, key, combined);
+}
+
+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);
+ return cmdline_append_option(slot_data, key, digits);
+}
+
+static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
+ const char* key,
+ const uint8_t* data,
+ size_t data_len) {
+ int ret;
+ char* hex_data = avb_bin2hex(data, data_len);
+ if (hex_data == NULL) {
+ return 0;
+ }
+ ret = cmdline_append_option(slot_data, key, hex_data);
+ avb_free(hex_data);
+ return ret;
+}
+
+AvbSlotVerifyResult avb_append_options(
+ AvbOps* ops,
+ AvbSlotVerifyData* slot_data,
+ AvbVBMetaImageHeader* toplevel_vbmeta,
+ AvbAlgorithmType algorithm_type,
+ AvbHashtreeErrorMode hashtree_error_mode) {
+ AvbSlotVerifyResult ret;
+ const char* verity_mode;
+ 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.avb_version option. */
+ if (!cmdline_append_version(slot_data,
+ "androidboot.vbmeta.avb_version",
+ AVB_VERSION_MAJOR,
+ AVB_VERSION_MINOR)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+
+ /* Set androidboot.avb.device_state to "locked" or "unlocked". */
+ io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error getting device state.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (!cmdline_append_option(slot_data,
+ "androidboot.vbmeta.device_state",
+ is_device_unlocked ? "unlocked" : "locked")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+
+ /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
+ * function as is used to sign vbmeta.
+ */
+ switch (algorithm_type) {
+ /* Explicit fallthrough. */
+ case AVB_ALGORITHM_TYPE_NONE:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
+ size_t n, total_size = 0;
+ uint8_t vbmeta_digest[AVB_SHA256_DIGEST_SIZE];
+ avb_slot_verify_data_calculate_vbmeta_digest(
+ slot_data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest);
+ for (n = 0; n < slot_data->num_vbmeta_images; n++) {
+ total_size += slot_data->vbmeta_images[n].vbmeta_size;
+ }
+ if (!cmdline_append_option(
+ slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
+ !cmdline_append_uint64_base10(
+ slot_data, "androidboot.vbmeta.size", total_size) ||
+ !cmdline_append_hex(slot_data,
+ "androidboot.vbmeta.digest",
+ vbmeta_digest,
+ AVB_SHA256_DIGEST_SIZE)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ } break;
+ /* Explicit fallthrough. */
+ case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
+ case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
+ case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
+ size_t n, total_size = 0;
+ uint8_t vbmeta_digest[AVB_SHA512_DIGEST_SIZE];
+ avb_slot_verify_data_calculate_vbmeta_digest(
+ slot_data, AVB_DIGEST_TYPE_SHA512, vbmeta_digest);
+ for (n = 0; n < slot_data->num_vbmeta_images; n++) {
+ total_size += slot_data->vbmeta_images[n].vbmeta_size;
+ }
+ if (!cmdline_append_option(
+ slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
+ !cmdline_append_uint64_base10(
+ slot_data, "androidboot.vbmeta.size", total_size) ||
+ !cmdline_append_hex(slot_data,
+ "androidboot.vbmeta.digest",
+ vbmeta_digest,
+ AVB_SHA512_DIGEST_SIZE)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ } break;
+ case _AVB_ALGORITHM_NUM_TYPES:
+ avb_assert_not_reached();
+ break;
+ }
+
+ /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
+ if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
+ verity_mode = "disabled";
+ } else {
+ const char* dm_verity_mode;
+ char* new_ret;
+
+ switch (hashtree_error_mode) {
+ case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
+ if (!cmdline_append_option(
+ slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ verity_mode = "enforcing";
+ dm_verity_mode = "restart_on_corruption";
+ break;
+ case AVB_HASHTREE_ERROR_MODE_RESTART:
+ verity_mode = "enforcing";
+ dm_verity_mode = "restart_on_corruption";
+ break;
+ case AVB_HASHTREE_ERROR_MODE_EIO:
+ verity_mode = "eio";
+ /* For now there's no option to specify the EIO mode. So
+ * just use 'ignore_zero_blocks' since that's already set
+ * and dm-verity-target.c supports specifying this multiple
+ * times.
+ */
+ dm_verity_mode = "ignore_zero_blocks";
+ break;
+ case AVB_HASHTREE_ERROR_MODE_LOGGING:
+ verity_mode = "logging";
+ dm_verity_mode = "ignore_corruption";
+ break;
+ }
+ new_ret = avb_replace(
+ slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
+ avb_free(slot_data->cmdline);
+ slot_data->cmdline = new_ret;
+ if (slot_data->cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ }
+ if (!cmdline_append_option(
+ slot_data, "androidboot.veritymode", verity_mode)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+out:
+
+ return ret;
+}
+
+AvbCmdlineSubstList* avb_new_cmdline_subst_list() {
+ return (AvbCmdlineSubstList*)avb_calloc(sizeof(AvbCmdlineSubstList));
+}
+
+void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst) {
+ size_t i;
+ for (i = 0; i < cmdline_subst->size; ++i) {
+ avb_free(cmdline_subst->tokens[i]);
+ avb_free(cmdline_subst->values[i]);
+ }
+ cmdline_subst->size = 0;
+ avb_free(cmdline_subst);
+}
+
+AvbSlotVerifyResult avb_add_root_digest_substitution(
+ const char* part_name,
+ const uint8_t* digest,
+ size_t digest_size,
+ AvbCmdlineSubstList* out_cmdline_subst) {
+ const char* kDigestSubPrefix = "$(AVB_";
+ const char* kDigestSubSuffix = "_ROOT_DIGEST)";
+ size_t part_name_len = avb_strlen(part_name);
+ size_t list_index = out_cmdline_subst->size;
+
+ avb_assert(part_name_len < AVB_PART_NAME_MAX_SIZE);
+ avb_assert(digest_size <= AVB_SHA512_DIGEST_SIZE);
+ if (part_name_len >= AVB_PART_NAME_MAX_SIZE ||
+ digest_size > AVB_SHA512_DIGEST_SIZE) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ }
+
+ if (out_cmdline_subst->size >= AVB_MAX_NUM_CMDLINE_SUBST) {
+ /* The list is full. Currently dynamic growth of this list is not supported.
+ */
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ }
+
+ /* Construct the token to replace in the command line based on the partition
+ * name. For partition 'foo', this will be '$(AVB_FOO_ROOT_DIGEST)'.
+ */
+ out_cmdline_subst->tokens[list_index] =
+ avb_strdupv(kDigestSubPrefix, part_name, kDigestSubSuffix, NULL);
+ if (out_cmdline_subst->tokens[list_index] == NULL) {
+ goto fail;
+ }
+ avb_uppercase(out_cmdline_subst->tokens[list_index]);
+
+ /* The digest value is hex encoded when inserted in the command line. */
+ out_cmdline_subst->values[list_index] = avb_bin2hex(digest, digest_size);
+ if (out_cmdline_subst->values[list_index] == NULL) {
+ goto fail;
+ }
+
+ out_cmdline_subst->size++;
+ return AVB_SLOT_VERIFY_RESULT_OK;
+
+fail:
+ if (out_cmdline_subst->tokens[list_index]) {
+ avb_free(out_cmdline_subst->tokens[list_index]);
+ }
+ if (out_cmdline_subst->values[list_index]) {
+ avb_free(out_cmdline_subst->values[list_index]);
+ }
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+}
diff --git a/include/android_avb/avb_cmdline.h b/lib/avb/libavb/avb_cmdline.h
index 717381a3f4..996535d088 100644
--- a/include/android_avb/avb_cmdline.h
+++ b/lib/avb/libavb/avb_cmdline.h
@@ -1,62 +1,90 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#ifdef AVB_INSIDE_LIBAVB_H
-#error "You can't include avb_sha.h in the public header libavb.h."
-#endif
-*/
-
-/*
-#ifndef AVB_COMPILATION
-#error "Never include this file, it may only be used from internal avb code."
-#endif
-*/
-
-#ifndef AVB_CMDLINE_H_
-#define AVB_CMDLINE_H_
-
-#include <android_avb/avb_ops.h>
-#include <android_avb/avb_slot_verify.h>
-
-/* Maximum allow length (in bytes) of a partition name, including
- * ab_suffix.
- */
-#define AVB_PART_NAME_MAX_SIZE 32
-
-/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
- * values. Returns NULL on OOM, otherwise the cmdline with values
- * replaced.
- */
-char* avb_sub_cmdline(AvbOps* ops, const char* cmdline, const char* ab_suffix,
- bool using_boot_for_vbmeta);
-
-AvbSlotVerifyResult avb_append_options(
- AvbOps* ops,
- AvbSlotVerifyData* slot_data,
- AvbVBMetaImageHeader* toplevel_vbmeta,
- AvbAlgorithmType algorithm_type,
- AvbHashtreeErrorMode hashtree_error_mode);
-
-#endif
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef AVB_INSIDE_LIBAVB_H
+#error "You can't include avb_sha.h in the public header libavb.h."
+#endif
+
+#ifndef AVB_COMPILATION
+#error "Never include this file, it may only be used from internal avb code."
+#endif
+
+#ifndef AVB_CMDLINE_H_
+#define AVB_CMDLINE_H_
+
+#include "avb_ops.h"
+#include "avb_slot_verify.h"
+
+/* Maximum allow length (in bytes) of a partition name, including
+ * ab_suffix.
+ */
+#define AVB_PART_NAME_MAX_SIZE 32
+
+#define AVB_MAX_NUM_CMDLINE_SUBST 10
+
+/* Holds information about command-line substitutions. */
+typedef struct AvbCmdlineSubstList {
+ size_t size;
+ char* tokens[AVB_MAX_NUM_CMDLINE_SUBST];
+ char* values[AVB_MAX_NUM_CMDLINE_SUBST];
+} AvbCmdlineSubstList;
+
+/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
+ * values. Returns NULL on OOM, otherwise the cmdline with values
+ * replaced.
+ */
+char* avb_sub_cmdline(AvbOps* ops,
+ const char* cmdline,
+ const char* ab_suffix,
+ bool using_boot_for_vbmeta,
+ const AvbCmdlineSubstList* additional_substitutions);
+
+AvbSlotVerifyResult avb_append_options(
+ AvbOps* ops,
+ AvbSlotVerifyData* slot_data,
+ AvbVBMetaImageHeader* toplevel_vbmeta,
+ AvbAlgorithmType algorithm_type,
+ AvbHashtreeErrorMode hashtree_error_mode);
+
+/* Allocates and initializes a new command line substitution list. Free with
+ * |avb_free_cmdline_subst_list|.
+ */
+AvbCmdlineSubstList* avb_new_cmdline_subst_list(void);
+
+/* Use this instead of |avb_free| to deallocate a AvbCmdlineSubstList. */
+void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst);
+
+/* Adds a hashtree root digest to be substituted in $(AVB_*_ROOT_DIGEST)
+ * variables. The partition name differentiates the variable. For example, if
+ * |part_name| is "foo" then $(AVB_FOO_ROOT_DIGEST) will be substituted with the
+ * hex encoding of the digest. The substitution will be added to
+ * |out_cmdline_subst|. Returns AVB_SLOT_VERIFY_RESULT_OK on success.
+ */
+AvbSlotVerifyResult avb_add_root_digest_substitution(
+ const char* part_name,
+ const uint8_t* digest,
+ size_t digest_size,
+ AvbCmdlineSubstList* out_cmdline_subst);
+
+#endif
diff --git a/lib/avb/libavb/avb_crc32.c b/lib/avb/libavb/avb_crc32.c
index 8629eb627b..7d4cb09035 100644
--- a/lib/avb/libavb/avb_crc32.c
+++ b/lib/avb/libavb/avb_crc32.c
@@ -1,114 +1,114 @@
-/*-
- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
- * code or tables extracted from it, as desired without restriction.
- */
-
-/*
- * First, the polynomial itself and its table of feedback terms. The
- * polynomial is
- * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
- *
- * Note that we take it "backwards" and put the highest-order term in
- * the lowest-order bit. The X^32 term is "implied"; the LSB is the
- * X^31 term, etc. The X^0 term (usually shown as "+1") results in
- * the MSB being 1
- *
- * Note that the usual hardware shift register implementation, which
- * is what we're using (we're merely optimizing it by doing eight-bit
- * chunks at a time) shifts bits into the lowest-order term. In our
- * implementation, that means shifting towards the right. Why do we
- * do it this way? Because the calculated CRC must be transmitted in
- * order from highest-order term to lowest-order term. UARTs transmit
- * characters in order from LSB to MSB. By storing the CRC this way
- * we hand it to the UART in the order low-byte to high-byte; the UART
- * sends each low-bit to hight-bit; and the result is transmission bit
- * by bit from highest- to lowest-order term without requiring any bit
- * shuffling on our part. Reception works similarly
- *
- * The feedback terms table consists of 256, 32-bit entries. Notes
- *
- * The table can be generated at runtime if desired; code to do so
- * is shown later. It might not be obvious, but the feedback
- * terms simply represent the results of eight shift/xor opera
- * tions for all combinations of data and CRC register values
- *
- * The values must be right-shifted by eight bits by the "updcrc
- * logic; the shift must be unsigned (bring in zeroes). On some
- * hardware you could probably optimize the shift in assembler by
- * using byte-swap instructions
- * polynomial $edb88320
- *
- *
- * CRC32 code derived from work by Gary S. Brown.
- */
-
-#include <android_avb/avb_sysdeps.h>
-#include <android_avb/avb_util.h>
-
-/* Code taken from FreeBSD 8 */
-
-static uint32_t iavb_crc32_tab[] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
-
-/*
- * A function that calculates the CRC-32 based on the table above is
- * given below for documentation purposes. An equivalent implementation
- * of this function that's actually used in the kernel can be found
- * in sys/libkern.h, where it can be inlined.
- */
-
-static uint32_t iavb_crc32(uint32_t crc_in, const uint8_t* buf, int size) {
- const uint8_t* p = buf;
- uint32_t crc;
-
- crc = crc_in ^ ~0U;
- while (size--)
- crc = iavb_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
- return crc ^ ~0U;
-}
-
-uint32_t avb_crc32(const uint8_t* buf, size_t size) {
- return iavb_crc32(0, buf, size);
-}
+/*-
+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ */
+
+/*
+ * First, the polynomial itself and its table of feedback terms. The
+ * polynomial is
+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
+ *
+ * Note that we take it "backwards" and put the highest-order term in
+ * the lowest-order bit. The X^32 term is "implied"; the LSB is the
+ * X^31 term, etc. The X^0 term (usually shown as "+1") results in
+ * the MSB being 1
+ *
+ * Note that the usual hardware shift register implementation, which
+ * is what we're using (we're merely optimizing it by doing eight-bit
+ * chunks at a time) shifts bits into the lowest-order term. In our
+ * implementation, that means shifting towards the right. Why do we
+ * do it this way? Because the calculated CRC must be transmitted in
+ * order from highest-order term to lowest-order term. UARTs transmit
+ * characters in order from LSB to MSB. By storing the CRC this way
+ * we hand it to the UART in the order low-byte to high-byte; the UART
+ * sends each low-bit to hight-bit; and the result is transmission bit
+ * by bit from highest- to lowest-order term without requiring any bit
+ * shuffling on our part. Reception works similarly
+ *
+ * The feedback terms table consists of 256, 32-bit entries. Notes
+ *
+ * The table can be generated at runtime if desired; code to do so
+ * is shown later. It might not be obvious, but the feedback
+ * terms simply represent the results of eight shift/xor opera
+ * tions for all combinations of data and CRC register values
+ *
+ * The values must be right-shifted by eight bits by the "updcrc
+ * logic; the shift must be unsigned (bring in zeroes). On some
+ * hardware you could probably optimize the shift in assembler by
+ * using byte-swap instructions
+ * polynomial $edb88320
+ *
+ *
+ * CRC32 code derived from work by Gary S. Brown.
+ */
+
+#include "avb_sysdeps.h"
+#include "avb_util.h"
+
+/* Code taken from FreeBSD 8 */
+
+static uint32_t iavb_crc32_tab[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
+
+/*
+ * A function that calculates the CRC-32 based on the table above is
+ * given below for documentation purposes. An equivalent implementation
+ * of this function that's actually used in the kernel can be found
+ * in sys/libkern.h, where it can be inlined.
+ */
+
+static uint32_t iavb_crc32(uint32_t crc_in, const uint8_t* buf, int size) {
+ const uint8_t* p = buf;
+ uint32_t crc;
+
+ crc = crc_in ^ ~0U;
+ while (size--)
+ crc = iavb_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
+ return crc ^ ~0U;
+}
+
+uint32_t avb_crc32(const uint8_t* buf, size_t size) {
+ return iavb_crc32(0, buf, size);
+}
diff --git a/lib/avb/libavb/avb_crypto.c b/lib/avb/libavb/avb_crypto.c
index a99979a622..a99ff80d65 100644
--- a/lib/avb/libavb/avb_crypto.c
+++ b/lib/avb/libavb/avb_crypto.c
@@ -1,372 +1,372 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_crypto.h>
-#include <android_avb/avb_rsa.h>
-#include <android_avb/avb_sha.h>
-#include <android_avb/avb_util.h>
-
-/* NOTE: The PKC1-v1.5 padding is a blob of binary DER of ASN.1 and is
- * obtained from section 5.2.2 of RFC 4880.
- */
-
-static const uint8_t
- padding_RSA2048_SHA256[AVB_RSA2048_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
- 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
- 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
-
-static const uint8_t
- padding_RSA4096_SHA256[AVB_RSA4096_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
- 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
- 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
-
-static const uint8_t
- padding_RSA8192_SHA256[AVB_RSA8192_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
- 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
- 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
-
-static const uint8_t
- padding_RSA2048_SHA512[AVB_RSA2048_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
- 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
- 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
-
-static const uint8_t
- padding_RSA4096_SHA512[AVB_RSA4096_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
- 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30,
- 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
- 0x05, 0x00, 0x04, 0x40};
-
-static const uint8_t
- padding_RSA8192_SHA512[AVB_RSA8192_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
- 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
- 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
-
-static AvbAlgorithmData algorithm_data[_AVB_ALGORITHM_NUM_TYPES] = {
- /* AVB_ALGORITHM_TYPE_NONE */
- {.padding = NULL, .padding_len = 0, .hash_len = 0},
- /* AVB_ALGORITHM_TYPE_SHA256_RSA2048 */
- {.padding = padding_RSA2048_SHA256,
- .padding_len = sizeof(padding_RSA2048_SHA256),
- .hash_len = AVB_SHA256_DIGEST_SIZE},
- /* AVB_ALGORITHM_TYPE_SHA256_RSA4096 */
- {.padding = padding_RSA4096_SHA256,
- .padding_len = sizeof(padding_RSA4096_SHA256),
- .hash_len = AVB_SHA256_DIGEST_SIZE},
- /* AVB_ALGORITHM_TYPE_SHA256_RSA8192 */
- {.padding = padding_RSA8192_SHA256,
- .padding_len = sizeof(padding_RSA8192_SHA256),
- .hash_len = AVB_SHA256_DIGEST_SIZE},
- /* AVB_ALGORITHM_TYPE_SHA512_RSA2048 */
- {.padding = padding_RSA2048_SHA512,
- .padding_len = sizeof(padding_RSA2048_SHA512),
- .hash_len = AVB_SHA512_DIGEST_SIZE},
- /* AVB_ALGORITHM_TYPE_SHA512_RSA4096 */
- {.padding = padding_RSA4096_SHA512,
- .padding_len = sizeof(padding_RSA4096_SHA512),
- .hash_len = AVB_SHA512_DIGEST_SIZE},
- /* AVB_ALGORITHM_TYPE_SHA512_RSA8192 */
- {.padding = padding_RSA8192_SHA512,
- .padding_len = sizeof(padding_RSA8192_SHA512),
- .hash_len = AVB_SHA512_DIGEST_SIZE},
-};
-
-const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm) {
- if ((size_t)algorithm < _AVB_ALGORITHM_NUM_TYPES) {
- return &algorithm_data[algorithm];
- }
- return NULL;
-}
-
-bool avb_rsa_public_key_header_validate_and_byteswap(
- const AvbRSAPublicKeyHeader* src, AvbRSAPublicKeyHeader* dest) {
- avb_memcpy(dest, src, sizeof(AvbRSAPublicKeyHeader));
-
- dest->key_num_bits = avb_be32toh(dest->key_num_bits);
- dest->n0inv = avb_be32toh(dest->n0inv);
-
- return true;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_crypto.h"
+#include "avb_rsa.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+
+/* NOTE: The PKC1-v1.5 padding is a blob of binary DER of ASN.1 and is
+ * obtained from section 5.2.2 of RFC 4880.
+ */
+
+static const uint8_t
+ padding_RSA2048_SHA256[AVB_RSA2048_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+ 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+
+static const uint8_t
+ padding_RSA4096_SHA256[AVB_RSA4096_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+
+static const uint8_t
+ padding_RSA8192_SHA256[AVB_RSA8192_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+ 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+
+static const uint8_t
+ padding_RSA2048_SHA512[AVB_RSA2048_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
+
+static const uint8_t
+ padding_RSA4096_SHA512[AVB_RSA4096_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30,
+ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+ 0x05, 0x00, 0x04, 0x40};
+
+static const uint8_t
+ padding_RSA8192_SHA512[AVB_RSA8192_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
+
+static AvbAlgorithmData algorithm_data[_AVB_ALGORITHM_NUM_TYPES] = {
+ /* AVB_ALGORITHM_TYPE_NONE */
+ {.padding = NULL, .padding_len = 0, .hash_len = 0},
+ /* AVB_ALGORITHM_TYPE_SHA256_RSA2048 */
+ {.padding = padding_RSA2048_SHA256,
+ .padding_len = sizeof(padding_RSA2048_SHA256),
+ .hash_len = AVB_SHA256_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA256_RSA4096 */
+ {.padding = padding_RSA4096_SHA256,
+ .padding_len = sizeof(padding_RSA4096_SHA256),
+ .hash_len = AVB_SHA256_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA256_RSA8192 */
+ {.padding = padding_RSA8192_SHA256,
+ .padding_len = sizeof(padding_RSA8192_SHA256),
+ .hash_len = AVB_SHA256_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA512_RSA2048 */
+ {.padding = padding_RSA2048_SHA512,
+ .padding_len = sizeof(padding_RSA2048_SHA512),
+ .hash_len = AVB_SHA512_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA512_RSA4096 */
+ {.padding = padding_RSA4096_SHA512,
+ .padding_len = sizeof(padding_RSA4096_SHA512),
+ .hash_len = AVB_SHA512_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA512_RSA8192 */
+ {.padding = padding_RSA8192_SHA512,
+ .padding_len = sizeof(padding_RSA8192_SHA512),
+ .hash_len = AVB_SHA512_DIGEST_SIZE},
+};
+
+const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm) {
+ if ((size_t)algorithm < _AVB_ALGORITHM_NUM_TYPES) {
+ return &algorithm_data[algorithm];
+ }
+ return NULL;
+}
+
+bool avb_rsa_public_key_header_validate_and_byteswap(
+ const AvbRSAPublicKeyHeader* src, AvbRSAPublicKeyHeader* dest) {
+ avb_memcpy(dest, src, sizeof(AvbRSAPublicKeyHeader));
+
+ dest->key_num_bits = avb_be32toh(dest->key_num_bits);
+ dest->n0inv = avb_be32toh(dest->n0inv);
+
+ return true;
+}
diff --git a/include/android_avb/avb_crypto.h b/lib/avb/libavb/avb_crypto.h
index b99a905d70..30c1e4b989 100644
--- a/include/android_avb/avb_crypto.h
+++ b/lib/avb/libavb/avb_crypto.h
@@ -1,167 +1,174 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_CRYPTO_H_
-#define AVB_CRYPTO_H_
-
-#include <android_avb/avb_sysdeps.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Size of a RSA-2048 signature. */
-#define AVB_RSA2048_NUM_BYTES 256
-
-/* Size of a RSA-4096 signature. */
-#define AVB_RSA4096_NUM_BYTES 512
-
-/* Size of a RSA-8192 signature. */
-#define AVB_RSA8192_NUM_BYTES 1024
-
-/* Size in bytes of a SHA-256 digest. */
-#define AVB_SHA256_DIGEST_SIZE 32
-
-/* Size in bytes of a SHA-512 digest. */
-#define AVB_SHA512_DIGEST_SIZE 64
-
-/* Algorithms that can be used in the vbmeta image for
- * verification. An algorithm consists of a hash type and a signature
- * type.
- *
- * The data used to calculate the hash is the three blocks mentioned
- * in the documentation for |AvbVBMetaImageHeader| except for the data
- * in the "Authentication data" block.
- *
- * For signatures with RSA keys, PKCS v1.5 padding is used. The public
- * key data is stored in the auxiliary data block, see
- * |AvbRSAPublicKeyHeader| for the serialization format.
- *
- * Each algorithm type is described below:
- *
- * AVB_ALGORITHM_TYPE_NONE: There is no hash, no signature of the
- * data, and no public key. The data cannot be verified. The fields
- * |hash_size|, |signature_size|, and |public_key_size| must be zero.
- *
- * AVB_ALGORITHM_TYPE_SHA256_RSA2048: The hash function used is
- * SHA-256, resulting in 32 bytes of hash digest data. This hash is
- * signed with a 2048-bit RSA key. The field |hash_size| must be 32,
- * |signature_size| must be 256, and the public key data must have
- * |key_num_bits| set to 2048.
- *
- * AVB_ALGORITHM_TYPE_SHA256_RSA4096: Like above, but only with
- * a 4096-bit RSA key and |signature_size| set to 512.
- *
- * AVB_ALGORITHM_TYPE_SHA256_RSA8192: Like above, but only with
- * a 8192-bit RSA key and |signature_size| set to 1024.
- *
- * AVB_ALGORITHM_TYPE_SHA512_RSA2048: The hash function used is
- * SHA-512, resulting in 64 bytes of hash digest data. This hash is
- * signed with a 2048-bit RSA key. The field |hash_size| must be 64,
- * |signature_size| must be 256, and the public key data must have
- * |key_num_bits| set to 2048.
- *
- * AVB_ALGORITHM_TYPE_SHA512_RSA4096: Like above, but only with
- * a 4096-bit RSA key and |signature_size| set to 512.
- *
- * AVB_ALGORITHM_TYPE_SHA512_RSA8192: Like above, but only with
- * a 8192-bit RSA key and |signature_size| set to 1024.
- */
-typedef enum {
- AVB_ALGORITHM_TYPE_NONE,
- AVB_ALGORITHM_TYPE_SHA256_RSA2048,
- AVB_ALGORITHM_TYPE_SHA256_RSA4096,
- AVB_ALGORITHM_TYPE_SHA256_RSA8192,
- AVB_ALGORITHM_TYPE_SHA512_RSA2048,
- AVB_ALGORITHM_TYPE_SHA512_RSA4096,
- AVB_ALGORITHM_TYPE_SHA512_RSA8192,
- _AVB_ALGORITHM_NUM_TYPES
-} AvbAlgorithmType;
-
-/* Holds algorithm-specific data. The |padding| is needed by avb_rsa_verify. */
-typedef struct {
- const uint8_t* padding;
- size_t padding_len;
- size_t hash_len;
-} AvbAlgorithmData;
-
-/* Provides algorithm-specific data for a given |algorithm|. Returns NULL if
- * |algorithm| is invalid.
- */
-const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm)
- AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* The header for a serialized RSA public key.
- *
- * The size of the key is given by |key_num_bits|, for example 2048
- * for a RSA-2048 key. By definition, a RSA public key is the pair (n,
- * e) where |n| is the modulus (which can be represented in
- * |key_num_bits| bits) and |e| is the public exponent. The exponent
- * is not stored since it's assumed to always be 65537.
- *
- * To optimize verification, the key block includes two precomputed
- * values, |n0inv| (fits in 32 bits) and |rr| and can always be
- * represented in |key_num_bits|.
-
- * The value |n0inv| is the value -1/n[0] (mod 2^32). The value |rr|
- * is (2^key_num_bits)^2 (mod n).
- *
- * Following this header is |key_num_bits| bits of |n|, then
- * |key_num_bits| bits of |rr|. Both values are stored with most
- * significant bit first. Each serialized number takes up
- * |key_num_bits|/8 bytes.
- *
- * All fields in this struct are stored in network byte order when
- * serialized. To generate a copy with fields swapped to native byte
- * order, use the function avb_rsa_public_key_header_validate_and_byteswap().
- *
- * The avb_rsa_verify() function expects a key in this serialized
- * format.
- *
- * The 'avbtool extract_public_key' command can be used to generate a
- * serialized RSA public key.
- */
-typedef struct AvbRSAPublicKeyHeader {
- uint32_t key_num_bits;
- uint32_t n0inv;
-} AVB_ATTR_PACKED AvbRSAPublicKeyHeader;
-
-/* Copies |src| to |dest| and validates, byte-swapping fields in the
- * process if needed. Returns true if valid, false if invalid.
- */
-bool avb_rsa_public_key_header_validate_and_byteswap(
- const AvbRSAPublicKeyHeader* src,
- AvbRSAPublicKeyHeader* dest) AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_CRYPTO_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_CRYPTO_H_
+#define AVB_CRYPTO_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Size of a RSA-2048 signature. */
+#define AVB_RSA2048_NUM_BYTES 256
+
+/* Size of a RSA-4096 signature. */
+#define AVB_RSA4096_NUM_BYTES 512
+
+/* Size of a RSA-8192 signature. */
+#define AVB_RSA8192_NUM_BYTES 1024
+
+/* Size in bytes of a SHA-1 digest. */
+#define AVB_SHA1_DIGEST_SIZE 20
+
+/* Size in bytes of a SHA-256 digest. */
+#define AVB_SHA256_DIGEST_SIZE 32
+
+/* Size in bytes of a SHA-512 digest. */
+#define AVB_SHA512_DIGEST_SIZE 64
+
+/* Possible digest types supported by libavb routines. */
+typedef enum {
+ AVB_DIGEST_TYPE_SHA256,
+ AVB_DIGEST_TYPE_SHA512,
+} AvbDigestType;
+
+/* Algorithms that can be used in the vbmeta image for
+ * verification. An algorithm consists of a hash type and a signature
+ * type.
+ *
+ * The data used to calculate the hash is the three blocks mentioned
+ * in the documentation for |AvbVBMetaImageHeader| except for the data
+ * in the "Authentication data" block.
+ *
+ * For signatures with RSA keys, PKCS v1.5 padding is used. The public
+ * key data is stored in the auxiliary data block, see
+ * |AvbRSAPublicKeyHeader| for the serialization format.
+ *
+ * Each algorithm type is described below:
+ *
+ * AVB_ALGORITHM_TYPE_NONE: There is no hash, no signature of the
+ * data, and no public key. The data cannot be verified. The fields
+ * |hash_size|, |signature_size|, and |public_key_size| must be zero.
+ *
+ * AVB_ALGORITHM_TYPE_SHA256_RSA2048: The hash function used is
+ * SHA-256, resulting in 32 bytes of hash digest data. This hash is
+ * signed with a 2048-bit RSA key. The field |hash_size| must be 32,
+ * |signature_size| must be 256, and the public key data must have
+ * |key_num_bits| set to 2048.
+ *
+ * AVB_ALGORITHM_TYPE_SHA256_RSA4096: Like above, but only with
+ * a 4096-bit RSA key and |signature_size| set to 512.
+ *
+ * AVB_ALGORITHM_TYPE_SHA256_RSA8192: Like above, but only with
+ * a 8192-bit RSA key and |signature_size| set to 1024.
+ *
+ * AVB_ALGORITHM_TYPE_SHA512_RSA2048: The hash function used is
+ * SHA-512, resulting in 64 bytes of hash digest data. This hash is
+ * signed with a 2048-bit RSA key. The field |hash_size| must be 64,
+ * |signature_size| must be 256, and the public key data must have
+ * |key_num_bits| set to 2048.
+ *
+ * AVB_ALGORITHM_TYPE_SHA512_RSA4096: Like above, but only with
+ * a 4096-bit RSA key and |signature_size| set to 512.
+ *
+ * AVB_ALGORITHM_TYPE_SHA512_RSA8192: Like above, but only with
+ * a 8192-bit RSA key and |signature_size| set to 1024.
+ */
+typedef enum {
+ AVB_ALGORITHM_TYPE_NONE,
+ AVB_ALGORITHM_TYPE_SHA256_RSA2048,
+ AVB_ALGORITHM_TYPE_SHA256_RSA4096,
+ AVB_ALGORITHM_TYPE_SHA256_RSA8192,
+ AVB_ALGORITHM_TYPE_SHA512_RSA2048,
+ AVB_ALGORITHM_TYPE_SHA512_RSA4096,
+ AVB_ALGORITHM_TYPE_SHA512_RSA8192,
+ _AVB_ALGORITHM_NUM_TYPES
+} AvbAlgorithmType;
+
+/* Holds algorithm-specific data. The |padding| is needed by avb_rsa_verify. */
+typedef struct {
+ const uint8_t* padding;
+ size_t padding_len;
+ size_t hash_len;
+} AvbAlgorithmData;
+
+/* Provides algorithm-specific data for a given |algorithm|. Returns NULL if
+ * |algorithm| is invalid.
+ */
+const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* The header for a serialized RSA public key.
+ *
+ * The size of the key is given by |key_num_bits|, for example 2048
+ * for a RSA-2048 key. By definition, a RSA public key is the pair (n,
+ * e) where |n| is the modulus (which can be represented in
+ * |key_num_bits| bits) and |e| is the public exponent. The exponent
+ * is not stored since it's assumed to always be 65537.
+ *
+ * To optimize verification, the key block includes two precomputed
+ * values, |n0inv| (fits in 32 bits) and |rr| and can always be
+ * represented in |key_num_bits|.
+
+ * The value |n0inv| is the value -1/n[0] (mod 2^32). The value |rr|
+ * is (2^key_num_bits)^2 (mod n).
+ *
+ * Following this header is |key_num_bits| bits of |n|, then
+ * |key_num_bits| bits of |rr|. Both values are stored with most
+ * significant bit first. Each serialized number takes up
+ * |key_num_bits|/8 bytes.
+ *
+ * All fields in this struct are stored in network byte order when
+ * serialized. To generate a copy with fields swapped to native byte
+ * order, use the function avb_rsa_public_key_header_validate_and_byteswap().
+ *
+ * The avb_rsa_verify() function expects a key in this serialized
+ * format.
+ *
+ * The 'avbtool extract_public_key' command can be used to generate a
+ * serialized RSA public key.
+ */
+typedef struct AvbRSAPublicKeyHeader {
+ uint32_t key_num_bits;
+ uint32_t n0inv;
+} AVB_ATTR_PACKED AvbRSAPublicKeyHeader;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ */
+bool avb_rsa_public_key_header_validate_and_byteswap(
+ const AvbRSAPublicKeyHeader* src,
+ AvbRSAPublicKeyHeader* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_CRYPTO_H_ */
diff --git a/lib/avb/libavb/avb_descriptor.c b/lib/avb/libavb/avb_descriptor.c
index c90b2d94fd..4f8e92534e 100644
--- a/lib/avb/libavb/avb_descriptor.c
+++ b/lib/avb/libavb/avb_descriptor.c
@@ -1,160 +1,160 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_descriptor.h>
-#include <android_avb/avb_util.h>
-#include <android_avb/avb_vbmeta_image.h>
-
-bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src,
- AvbDescriptor* dest) {
- dest->tag = avb_be64toh(src->tag);
- dest->num_bytes_following = avb_be64toh(src->num_bytes_following);
-
- if ((dest->num_bytes_following & 0x07) != 0) {
- avb_error("Descriptor size is not divisible by 8.\n");
- return false;
- }
- return true;
-}
-
-bool avb_descriptor_foreach(const uint8_t* image_data,
- size_t image_size,
- AvbDescriptorForeachFunc foreach_func,
- void* user_data) {
- const AvbVBMetaImageHeader* header = NULL;
- bool ret = false;
- const uint8_t* image_end;
- const uint8_t* desc_start;
- const uint8_t* desc_end;
- const uint8_t* p;
-
- if (image_data == NULL) {
- avb_error("image_data is NULL\n.");
- goto out;
- }
-
- if (foreach_func == NULL) {
- avb_error("foreach_func is NULL\n.");
- goto out;
- }
-
- if (image_size < sizeof(AvbVBMetaImageHeader)) {
- avb_error("Length is smaller than header.\n");
- goto out;
- }
-
- /* Ensure magic is correct. */
- if (avb_memcmp(image_data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
- avb_error("Magic is incorrect.\n");
- goto out;
- }
-
- /* Careful, not byteswapped - also ensure it's aligned properly. */
- avb_assert_aligned(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);
-
- desc_end = desc_start + avb_be64toh(header->descriptors_size);
-
- if (desc_start < image_data || desc_start > image_end ||
- desc_end < image_data || desc_end > image_end || desc_end < desc_start) {
- avb_error("Descriptors not inside passed-in data.\n");
- goto out;
- }
-
- 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_total = sizeof(AvbDescriptor) + nb_following;
-
- if ((nb_total & 7) != 0) {
- avb_error("Invalid descriptor length.\n");
- goto out;
- }
-
- if (nb_total + p < desc_start || nb_total + p > desc_end) {
- avb_error("Invalid data in descriptors array.\n");
- goto out;
- }
-
- if (foreach_func(dh, user_data) == 0) {
- goto out;
- }
-
- p += nb_total;
- }
-
- ret = true;
-
-out:
- return ret;
-}
-
-static bool count_descriptors(const AvbDescriptor* descriptor,
- void* user_data) {
- size_t* num_descriptors = user_data;
- *num_descriptors += 1;
- return true;
-}
-
-typedef struct {
- size_t descriptor_number;
- const AvbDescriptor** descriptors;
-} SetDescriptorData;
-
-static bool set_descriptors(const AvbDescriptor* descriptor, void* user_data) {
- SetDescriptorData* data = user_data;
- data->descriptors[data->descriptor_number++] = descriptor;
- return true;
-}
-
-const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
- size_t image_size,
- size_t* out_num_descriptors) {
- size_t num_descriptors = 0;
- SetDescriptorData data;
-
- avb_descriptor_foreach(
- image_data, image_size, count_descriptors, &num_descriptors);
-
- data.descriptor_number = 0;
- data.descriptors =
- avb_calloc(sizeof(const AvbDescriptor*) * (num_descriptors + 1));
- if (data.descriptors == NULL) {
- return NULL;
- }
- avb_descriptor_foreach(image_data, image_size, set_descriptors, &data);
- avb_assert(data.descriptor_number == num_descriptors);
-
- if (out_num_descriptors != NULL) {
- *out_num_descriptors = num_descriptors;
- }
-
- return data.descriptors;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_descriptor.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+
+bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src,
+ AvbDescriptor* dest) {
+ dest->tag = avb_be64toh(src->tag);
+ dest->num_bytes_following = avb_be64toh(src->num_bytes_following);
+
+ if ((dest->num_bytes_following & 0x07) != 0) {
+ avb_error("Descriptor size is not divisible by 8.\n");
+ return false;
+ }
+ return true;
+}
+
+bool avb_descriptor_foreach(const uint8_t* image_data,
+ size_t image_size,
+ AvbDescriptorForeachFunc foreach_func,
+ void* user_data) {
+ const AvbVBMetaImageHeader* header = NULL;
+ bool ret = false;
+ const uint8_t* image_end;
+ const uint8_t* desc_start;
+ const uint8_t* desc_end;
+ const uint8_t* p;
+
+ if (image_data == NULL) {
+ avb_error("image_data is NULL\n.");
+ goto out;
+ }
+
+ if (foreach_func == NULL) {
+ avb_error("foreach_func is NULL\n.");
+ goto out;
+ }
+
+ if (image_size < sizeof(AvbVBMetaImageHeader)) {
+ avb_error("Length is smaller than header.\n");
+ goto out;
+ }
+
+ /* Ensure magic is correct. */
+ if (avb_memcmp(image_data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+ avb_error("Magic is incorrect.\n");
+ goto out;
+ }
+
+ /* Careful, not byteswapped - also ensure it's aligned properly. */
+ avb_assert_aligned(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);
+
+ desc_end = desc_start + avb_be64toh(header->descriptors_size);
+
+ if (desc_start < image_data || desc_start > image_end ||
+ desc_end < image_data || desc_end > image_end || desc_end < desc_start) {
+ avb_error("Descriptors not inside passed-in data.\n");
+ goto out;
+ }
+
+ 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_total = sizeof(AvbDescriptor) + nb_following;
+
+ if ((nb_total & 7) != 0) {
+ avb_error("Invalid descriptor length.\n");
+ goto out;
+ }
+
+ if (nb_total + p < desc_start || nb_total + p > desc_end) {
+ avb_error("Invalid data in descriptors array.\n");
+ goto out;
+ }
+
+ if (foreach_func(dh, user_data) == 0) {
+ goto out;
+ }
+
+ p += nb_total;
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
+
+static bool count_descriptors(const AvbDescriptor* descriptor,
+ void* user_data) {
+ size_t* num_descriptors = user_data;
+ *num_descriptors += 1;
+ return true;
+}
+
+typedef struct {
+ size_t descriptor_number;
+ const AvbDescriptor** descriptors;
+} SetDescriptorData;
+
+static bool set_descriptors(const AvbDescriptor* descriptor, void* user_data) {
+ SetDescriptorData* data = user_data;
+ data->descriptors[data->descriptor_number++] = descriptor;
+ return true;
+}
+
+const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
+ size_t image_size,
+ size_t* out_num_descriptors) {
+ size_t num_descriptors = 0;
+ SetDescriptorData data;
+
+ avb_descriptor_foreach(
+ image_data, image_size, count_descriptors, &num_descriptors);
+
+ data.descriptor_number = 0;
+ data.descriptors =
+ avb_calloc(sizeof(const AvbDescriptor*) * (num_descriptors + 1));
+ if (data.descriptors == NULL) {
+ return NULL;
+ }
+ avb_descriptor_foreach(image_data, image_size, set_descriptors, &data);
+ avb_assert(data.descriptor_number == num_descriptors);
+
+ if (out_num_descriptors != NULL) {
+ *out_num_descriptors = num_descriptors;
+ }
+
+ return data.descriptors;
+}
diff --git a/include/android_avb/avb_descriptor.h b/lib/avb/libavb/avb_descriptor.h
index 2af9f5a5c2..5d0f0c699f 100644
--- a/include/android_avb/avb_descriptor.h
+++ b/lib/avb/libavb/avb_descriptor.h
@@ -1,133 +1,131 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_DESCRIPTOR_H_
-#define AVB_DESCRIPTOR_H_
-
-#include <android_avb/avb_sysdeps.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Well-known descriptor tags.
- *
- * AVB_DESCRIPTOR_TAG_PROPERTY: see |AvbPropertyDescriptor| struct.
- * AVB_DESCRIPTOR_TAG_HASHTREE: see |AvbHashtreeDescriptor| struct.
- * AVB_DESCRIPTOR_TAG_HASH: see |AvbHashDescriptor| struct.
- * AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: see |AvbKernelCmdlineDescriptor| struct.
- * AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: see |AvbChainPartitionDescriptor| struct.
- */
-typedef enum {
- AVB_DESCRIPTOR_TAG_PROPERTY,
- AVB_DESCRIPTOR_TAG_HASHTREE,
- AVB_DESCRIPTOR_TAG_HASH,
- AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
- AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
-} AvbDescriptorTag;
-
-/* The header for a serialized descriptor.
- *
- * A descriptor always have two fields, a |tag| (denoting its type,
- * see the |AvbDescriptorTag| enumeration) and the size of the bytes
- * following, |num_bytes_following|.
- *
- * For padding, |num_bytes_following| is always a multiple of 8.
- */
-typedef struct AvbDescriptor {
- uint64_t tag;
- uint64_t num_bytes_following;
-} AVB_ATTR_PACKED AvbDescriptor;
-
-/* Copies |src| to |dest| and validates, byte-swapping fields in the
- * process if needed. Returns true if valid, false if invalid.
- *
- * Data following the struct is not validated nor copied.
- */
-bool avb_descriptor_validate_and_byteswap(
- const AvbDescriptor* src, AvbDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Signature for callback function used in avb_descriptor_foreach().
- * The passed in descriptor is given by |descriptor| and the
- * |user_data| passed to avb_descriptor_foreach() function is in
- * |user_data|. Return true to continue iterating, false to stop
- * iterating.
- *
- * Note that |descriptor| points into the image passed to
- * avb_descriptor_foreach() - all fields need to be byteswapped!
- */
-typedef bool AvbDescriptorForeachFunc(const AvbDescriptor* descriptor,
- void* user_data);
-
-/* Convenience function to iterate over all descriptors in an vbmeta
- * image.
- *
- * The function given by |foreach_func| will be called for each
- * descriptor. The given function should return true to continue
- * iterating, false to stop.
- *
- * The |user_data| parameter will be passed to |foreach_func|.
- *
- * Returns false if the iteration was short-circuited, that is if
- * an invocation of |foreach_func| returned false.
- *
- * Before using this function, you MUST verify |image_data| with
- * avb_vbmeta_image_verify() and reject it unless it's signed by a known
- * good public key. Additionally, |image_data| must be word-aligned.
- */
-bool avb_descriptor_foreach(const uint8_t* image_data,
- size_t image_size,
- AvbDescriptorForeachFunc foreach_func,
- void* user_data);
-
-/* Gets all descriptors in a vbmeta image.
- *
- * The return value is a NULL-pointer terminated array of
- * AvbDescriptor pointers. Free with avb_free() when you are done with
- * it. If |out_num_descriptors| is non-NULL, the number of descriptors
- * will be returned there.
- *
- * Note that each AvbDescriptor pointer in the array points into
- * |image_data| - all fields need to be byteswapped!
- *
- * Before using this function, you MUST verify |image_data| with
- * avb_vbmeta_image_verify() and reject it unless it's signed by a known
- * good public key. Additionally, |image_data| must be word-aligned.
- */
-const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
- size_t image_size,
- size_t* out_num_descriptors)
- AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_DESCRIPTOR_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_DESCRIPTOR_H_
+#define AVB_DESCRIPTOR_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Well-known descriptor tags.
+ *
+ * AVB_DESCRIPTOR_TAG_PROPERTY: see |AvbPropertyDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_HASHTREE: see |AvbHashtreeDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_HASH: see |AvbHashDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: see |AvbKernelCmdlineDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: see |AvbChainPartitionDescriptor| struct.
+ */
+typedef enum {
+ AVB_DESCRIPTOR_TAG_PROPERTY,
+ AVB_DESCRIPTOR_TAG_HASHTREE,
+ AVB_DESCRIPTOR_TAG_HASH,
+ AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
+ AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
+} AvbDescriptorTag;
+
+/* The header for a serialized descriptor.
+ *
+ * A descriptor always have two fields, a |tag| (denoting its type,
+ * see the |AvbDescriptorTag| enumeration) and the size of the bytes
+ * following, |num_bytes_following|.
+ *
+ * For padding, |num_bytes_following| is always a multiple of 8.
+ */
+typedef struct AvbDescriptor {
+ uint64_t tag;
+ uint64_t num_bytes_following;
+} AVB_ATTR_PACKED AvbDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_descriptor_validate_and_byteswap(
+ const AvbDescriptor* src, AvbDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Signature for callback function used in avb_descriptor_foreach().
+ * The passed in descriptor is given by |descriptor| and the
+ * |user_data| passed to avb_descriptor_foreach() function is in
+ * |user_data|. Return true to continue iterating, false to stop
+ * iterating.
+ *
+ * Note that |descriptor| points into the image passed to
+ * avb_descriptor_foreach() - all fields need to be byteswapped!
+ */
+typedef bool AvbDescriptorForeachFunc(const AvbDescriptor* descriptor,
+ void* user_data);
+
+/* Convenience function to iterate over all descriptors in an vbmeta
+ * image.
+ *
+ * The function given by |foreach_func| will be called for each
+ * descriptor. The given function should return true to continue
+ * iterating, false to stop.
+ *
+ * The |user_data| parameter will be passed to |foreach_func|.
+ *
+ * Returns false if the iteration was short-circuited, that is if
+ * an invocation of |foreach_func| returned false.
+ *
+ * Before using this function, you MUST verify |image_data| with
+ * avb_vbmeta_image_verify() and reject it unless it's signed by a known
+ * good public key. Additionally, |image_data| must be word-aligned.
+ */
+bool avb_descriptor_foreach(const uint8_t* image_data,
+ size_t image_size,
+ AvbDescriptorForeachFunc foreach_func,
+ void* user_data);
+
+/* Gets all descriptors in a vbmeta image.
+ *
+ * The return value is a NULL-pointer terminated array of
+ * AvbDescriptor pointers. Free with avb_free() when you are done with
+ * it. If |out_num_descriptors| is non-NULL, the number of descriptors
+ * will be returned there.
+ *
+ * Note that each AvbDescriptor pointer in the array points into
+ * |image_data| - all fields need to be byteswapped!
+ *
+ * Before using this function, you MUST verify |image_data| with
+ * avb_vbmeta_image_verify() and reject it unless it's signed by a known
+ * good public key. Additionally, |image_data| must be word-aligned.
+ */
+const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
+ size_t image_size,
+ size_t* out_num_descriptors)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_DESCRIPTOR_H_ */
diff --git a/lib/avb/libavb/avb_footer.c b/lib/avb/libavb/avb_footer.c
index f3fd95dcf0..b8b8211501 100644
--- a/lib/avb/libavb/avb_footer.c
+++ b/lib/avb/libavb/avb_footer.c
@@ -1,54 +1,54 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_footer.h>
-#include <android_avb/avb_util.h>
-
-bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest) {
- avb_memcpy(dest, src, sizeof(AvbFooter));
-
- dest->version_major = avb_be32toh(dest->version_major);
- dest->version_minor = avb_be32toh(dest->version_minor);
-
- dest->original_image_size = avb_be64toh(dest->original_image_size);
- dest->vbmeta_offset = avb_be64toh(dest->vbmeta_offset);
- dest->vbmeta_size = avb_be64toh(dest->vbmeta_size);
-
- /* Check that magic is correct. */
- if (avb_safe_memcmp(dest->magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) !=
- 0) {
- avb_error("Footer magic is incorrect.\n");
- return false;
- }
-
- /* Ensure we don't attempt to access any fields if the footer major
- * version is not supported.
- */
- if (dest->version_major > AVB_FOOTER_VERSION_MAJOR) {
- avb_error("No support for footer version.\n");
- return false;
- }
-
- return true;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_footer.h"
+#include "avb_util.h"
+
+bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest) {
+ avb_memcpy(dest, src, sizeof(AvbFooter));
+
+ dest->version_major = avb_be32toh(dest->version_major);
+ dest->version_minor = avb_be32toh(dest->version_minor);
+
+ dest->original_image_size = avb_be64toh(dest->original_image_size);
+ dest->vbmeta_offset = avb_be64toh(dest->vbmeta_offset);
+ dest->vbmeta_size = avb_be64toh(dest->vbmeta_size);
+
+ /* Check that magic is correct. */
+ if (avb_safe_memcmp(dest->magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) !=
+ 0) {
+ avb_error("Footer magic is incorrect.\n");
+ return false;
+ }
+
+ /* Ensure we don't attempt to access any fields if the footer major
+ * version is not supported.
+ */
+ if (dest->version_major > AVB_FOOTER_VERSION_MAJOR) {
+ avb_error("No support for footer version.\n");
+ return false;
+ }
+
+ return true;
+}
diff --git a/include/android_avb/avb_footer.h b/lib/avb/libavb/avb_footer.h
index 668d553adb..e84826fa8f 100644
--- a/include/android_avb/avb_footer.h
+++ b/lib/avb/libavb/avb_footer.h
@@ -1,88 +1,86 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_FOOTER_H_
-#define AVB_FOOTER_H_
-
-#include <android_avb/avb_sysdeps.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Magic for the footer. */
-#define AVB_FOOTER_MAGIC "AVBf"
-#define AVB_FOOTER_MAGIC_LEN 4
-
-/* Size of the footer. */
-#define AVB_FOOTER_SIZE 64
-
-/* The current footer version used - keep in sync with avbtool. */
-#define AVB_FOOTER_VERSION_MAJOR 1
-#define AVB_FOOTER_VERSION_MINOR 0
-
-/* The struct used as a footer used on partitions, used to find the
- * AvbVBMetaImageHeader struct. This struct is always stored at the
- * end of a partition.
- */
-typedef struct AvbFooter {
- /* 0: Four bytes equal to "AVBf" (AVB_FOOTER_MAGIC). */
- uint8_t magic[AVB_FOOTER_MAGIC_LEN];
- /* 4: The major version of the footer struct. */
- uint32_t version_major;
- /* 8: The minor version of the footer struct. */
- uint32_t version_minor;
-
- /* 12: The original size of the image on the partition. */
- uint64_t original_image_size;
-
- /* 20: The offset of the |AvbVBMetaImageHeader| struct. */
- uint64_t vbmeta_offset;
-
- /* 28: The size of the vbmeta block (header + auth + aux blocks). */
- uint64_t vbmeta_size;
-
- /* 36: Padding to ensure struct is size AVB_FOOTER_SIZE bytes. This
- * must be set to zeroes.
- */
- uint8_t reserved[28];
-} AVB_ATTR_PACKED AvbFooter;
-
-/* Copies |src| to |dest| and validates, byte-swapping fields in the
- * process if needed. Returns true if valid, false if invalid.
- */
-bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest)
- AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_FOOTER_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_FOOTER_H_
+#define AVB_FOOTER_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Magic for the footer. */
+#define AVB_FOOTER_MAGIC "AVBf"
+#define AVB_FOOTER_MAGIC_LEN 4
+
+/* Size of the footer. */
+#define AVB_FOOTER_SIZE 64
+
+/* The current footer version used - keep in sync with avbtool. */
+#define AVB_FOOTER_VERSION_MAJOR 1
+#define AVB_FOOTER_VERSION_MINOR 0
+
+/* The struct used as a footer used on partitions, used to find the
+ * AvbVBMetaImageHeader struct. This struct is always stored at the
+ * end of a partition.
+ */
+typedef struct AvbFooter {
+ /* 0: Four bytes equal to "AVBf" (AVB_FOOTER_MAGIC). */
+ uint8_t magic[AVB_FOOTER_MAGIC_LEN];
+ /* 4: The major version of the footer struct. */
+ uint32_t version_major;
+ /* 8: The minor version of the footer struct. */
+ uint32_t version_minor;
+
+ /* 12: The original size of the image on the partition. */
+ uint64_t original_image_size;
+
+ /* 20: The offset of the |AvbVBMetaImageHeader| struct. */
+ uint64_t vbmeta_offset;
+
+ /* 28: The size of the vbmeta block (header + auth + aux blocks). */
+ uint64_t vbmeta_size;
+
+ /* 36: Padding to ensure struct is size AVB_FOOTER_SIZE bytes. This
+ * must be set to zeroes.
+ */
+ uint8_t reserved[28];
+} AVB_ATTR_PACKED AvbFooter;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ */
+bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_FOOTER_H_ */
diff --git a/lib/avb/libavb/avb_hash_descriptor.c b/lib/avb/libavb/avb_hash_descriptor.c
index 294f3d648e..3a6b8c8809 100644
--- a/lib/avb/libavb/avb_hash_descriptor.c
+++ b/lib/avb/libavb/avb_hash_descriptor.c
@@ -1,61 +1,62 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_hash_descriptor.h>
-#include <android_avb/avb_util.h>
-
-bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
- AvbHashDescriptor* dest) {
- uint64_t expected_size;
-
- avb_memcpy(dest, src, sizeof(AvbHashDescriptor));
-
- if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
- (AvbDescriptor*)dest))
- return false;
-
- if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASH) {
- avb_error("Invalid tag for hash descriptor.\n");
- return false;
- }
-
- dest->image_size = avb_be64toh(dest->image_size);
- dest->partition_name_len = avb_be32toh(dest->partition_name_len);
- dest->salt_len = avb_be32toh(dest->salt_len);
- dest->digest_len = avb_be32toh(dest->digest_len);
-
- /* Check that partition_name, salt, and digest are fully contained. */
- expected_size = sizeof(AvbHashDescriptor) - sizeof(AvbDescriptor);
- if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
- !avb_safe_add_to(&expected_size, dest->salt_len) ||
- !avb_safe_add_to(&expected_size, dest->digest_len)) {
- avb_error("Overflow while adding up sizes.\n");
- return false;
- }
- if (expected_size > dest->parent_descriptor.num_bytes_following) {
- avb_error("Descriptor payload size overflow.\n");
- return false;
- }
- return true;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_hash_descriptor.h"
+#include "avb_util.h"
+
+bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
+ AvbHashDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbHashDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASH) {
+ avb_error("Invalid tag for hash descriptor.\n");
+ return false;
+ }
+
+ dest->image_size = avb_be64toh(dest->image_size);
+ dest->partition_name_len = avb_be32toh(dest->partition_name_len);
+ dest->salt_len = avb_be32toh(dest->salt_len);
+ dest->digest_len = avb_be32toh(dest->digest_len);
+ dest->flags = avb_be32toh(dest->flags);
+
+ /* Check that partition_name, salt, and digest are fully contained. */
+ expected_size = sizeof(AvbHashDescriptor) - sizeof(AvbDescriptor);
+ if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
+ !avb_safe_add_to(&expected_size, dest->salt_len) ||
+ !avb_safe_add_to(&expected_size, dest->digest_len)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+ return true;
+}
diff --git a/include/android_avb/avb_hash_descriptor.h b/lib/avb/libavb/avb_hash_descriptor.h
index ef3f27117a..9ee8997123 100644
--- a/include/android_avb/avb_hash_descriptor.h
+++ b/lib/avb/libavb/avb_hash_descriptor.h
@@ -1,75 +1,88 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_HASH_DESCRIPTOR_H_
-#define AVB_HASH_DESCRIPTOR_H_
-
-#include <android_avb/avb_descriptor.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* A descriptor containing information about hash for an image.
- *
- * This descriptor is typically used for boot partitions to verify the
- * entire kernel+initramfs image before executing it.
- *
- * Following this struct are |partition_name_len| bytes of the
- * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
- * |digest_len| bytes of the digest.
- *
- * The |reserved| field is for future expansion and must be set to NUL
- * bytes.
- */
-typedef struct AvbHashDescriptor {
- AvbDescriptor parent_descriptor;
- uint64_t image_size;
- uint8_t hash_algorithm[32];
- uint32_t partition_name_len;
- uint32_t salt_len;
- uint32_t digest_len;
- uint8_t reserved[64];
-} AVB_ATTR_PACKED AvbHashDescriptor;
-
-/* Copies |src| to |dest| and validates, byte-swapping fields in the
- * process if needed. Returns true if valid, false if invalid.
- *
- * Data following the struct is not validated nor copied.
- */
-bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
- AvbHashDescriptor* dest)
- AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_HASH_DESCRIPTOR_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_HASH_DESCRIPTOR_H_
+#define AVB_HASH_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Flags for hash descriptors.
+ *
+ * AVB_HASH_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_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
+} AvbHashDescriptorFlags;
+
+/* A descriptor containing information about hash for an image.
+ *
+ * This descriptor is typically used for boot partitions to verify the
+ * entire kernel+initramfs image before executing it.
+ *
+ * Following this struct are |partition_name_len| bytes of the
+ * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
+ * |digest_len| bytes of the digest.
+ *
+ * The |reserved| field is for future expansion and must be set to NUL
+ * bytes.
+ *
+ * Changes in v1.1:
+ * - flags field is added which supports AVB_HASH_DESCRIPTOR_FLAGS_USE_AB
+ * - digest_len may be zero, which indicates the use of a persistent digest
+ */
+typedef struct AvbHashDescriptor {
+ AvbDescriptor parent_descriptor;
+ uint64_t image_size;
+ uint8_t hash_algorithm[32];
+ uint32_t partition_name_len;
+ uint32_t salt_len;
+ uint32_t digest_len;
+ uint32_t flags;
+ uint8_t reserved[60];
+} AVB_ATTR_PACKED AvbHashDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
+ AvbHashDescriptor* dest)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_HASH_DESCRIPTOR_H_ */
diff --git a/lib/avb/libavb/avb_hashtree_descriptor.c b/lib/avb/libavb/avb_hashtree_descriptor.c
index 0e95e8762d..0822458f84 100644
--- a/lib/avb/libavb/avb_hashtree_descriptor.c
+++ b/lib/avb/libavb/avb_hashtree_descriptor.c
@@ -1,69 +1,70 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_hashtree_descriptor.h>
-#include <android_avb/avb_util.h>
-
-bool avb_hashtree_descriptor_validate_and_byteswap(
- const AvbHashtreeDescriptor* src, AvbHashtreeDescriptor* dest) {
- uint64_t expected_size;
-
- avb_memcpy(dest, src, sizeof(AvbHashtreeDescriptor));
-
- if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
- (AvbDescriptor*)dest))
- return false;
-
- if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASHTREE) {
- avb_error("Invalid tag for hashtree descriptor.\n");
- return false;
- }
-
- dest->dm_verity_version = avb_be32toh(dest->dm_verity_version);
- dest->image_size = avb_be64toh(dest->image_size);
- dest->tree_offset = avb_be64toh(dest->tree_offset);
- dest->tree_size = avb_be64toh(dest->tree_size);
- dest->data_block_size = avb_be32toh(dest->data_block_size);
- dest->hash_block_size = avb_be32toh(dest->hash_block_size);
- dest->fec_num_roots = avb_be32toh(dest->fec_num_roots);
- dest->fec_offset = avb_be64toh(dest->fec_offset);
- dest->fec_size = avb_be64toh(dest->fec_size);
- dest->partition_name_len = avb_be32toh(dest->partition_name_len);
- dest->salt_len = avb_be32toh(dest->salt_len);
- dest->root_digest_len = avb_be32toh(dest->root_digest_len);
-
- /* Check that partition_name, salt, and root_digest are fully contained. */
- expected_size = sizeof(AvbHashtreeDescriptor) - sizeof(AvbDescriptor);
- if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
- !avb_safe_add_to(&expected_size, dest->salt_len) ||
- !avb_safe_add_to(&expected_size, dest->root_digest_len)) {
- avb_error("Overflow while adding up sizes.\n");
- return false;
- }
- if (expected_size > dest->parent_descriptor.num_bytes_following) {
- avb_error("Descriptor payload size overflow.\n");
- return false;
- }
- return true;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_hashtree_descriptor.h"
+#include "avb_util.h"
+
+bool avb_hashtree_descriptor_validate_and_byteswap(
+ const AvbHashtreeDescriptor* src, AvbHashtreeDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbHashtreeDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASHTREE) {
+ avb_error("Invalid tag for hashtree descriptor.\n");
+ return false;
+ }
+
+ dest->dm_verity_version = avb_be32toh(dest->dm_verity_version);
+ dest->image_size = avb_be64toh(dest->image_size);
+ dest->tree_offset = avb_be64toh(dest->tree_offset);
+ dest->tree_size = avb_be64toh(dest->tree_size);
+ dest->data_block_size = avb_be32toh(dest->data_block_size);
+ dest->hash_block_size = avb_be32toh(dest->hash_block_size);
+ dest->fec_num_roots = avb_be32toh(dest->fec_num_roots);
+ dest->fec_offset = avb_be64toh(dest->fec_offset);
+ dest->fec_size = avb_be64toh(dest->fec_size);
+ dest->partition_name_len = avb_be32toh(dest->partition_name_len);
+ dest->salt_len = avb_be32toh(dest->salt_len);
+ dest->root_digest_len = avb_be32toh(dest->root_digest_len);
+ dest->flags = avb_be32toh(dest->flags);
+
+ /* Check that partition_name, salt, and root_digest are fully contained. */
+ expected_size = sizeof(AvbHashtreeDescriptor) - sizeof(AvbDescriptor);
+ if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
+ !avb_safe_add_to(&expected_size, dest->salt_len) ||
+ !avb_safe_add_to(&expected_size, dest->root_digest_len)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+ return true;
+}
diff --git a/include/android_avb/avb_hashtree_descriptor.h b/lib/avb/libavb/avb_hashtree_descriptor.h
index d579275e73..d0f7e2c288 100644
--- a/include/android_avb/avb_hashtree_descriptor.h
+++ b/lib/avb/libavb/avb_hashtree_descriptor.h
@@ -1,85 +1,98 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_HASHTREE_DESCRIPTOR_H_
-#define AVB_HASHTREE_DESCRIPTOR_H_
-
-#include <android_avb/avb_descriptor.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* A descriptor containing information about a dm-verity hashtree.
- *
- * Hash-trees are used to verify large partitions typically containing
- * file systems. See
- * https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for more
- * information about dm-verity.
- *
- * Following this struct are |partition_name_len| bytes of the
- * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
- * |root_digest_len| bytes of the root digest.
- *
- * The |reserved| field is for future expansion and must be set to NUL
- * bytes.
- */
-typedef struct AvbHashtreeDescriptor {
- AvbDescriptor parent_descriptor;
- uint32_t dm_verity_version;
- uint64_t image_size;
- uint64_t tree_offset;
- uint64_t tree_size;
- uint32_t data_block_size;
- uint32_t hash_block_size;
- uint32_t fec_num_roots;
- uint64_t fec_offset;
- uint64_t fec_size;
- uint8_t hash_algorithm[32];
- uint32_t partition_name_len;
- uint32_t salt_len;
- uint32_t root_digest_len;
- uint8_t reserved[64];
-} AVB_ATTR_PACKED AvbHashtreeDescriptor;
-
-/* Copies |src| to |dest| and validates, byte-swapping fields in the
- * process if needed. Returns true if valid, false if invalid.
- *
- * Data following the struct is not validated nor copied.
- */
-bool avb_hashtree_descriptor_validate_and_byteswap(
- const AvbHashtreeDescriptor* src,
- AvbHashtreeDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_HASHTREE_DESCRIPTOR_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_HASHTREE_DESCRIPTOR_H_
+#define AVB_HASHTREE_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Flags for hashtree descriptors.
+ *
+ * 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.
+ */
+typedef enum {
+ AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
+} AvbHashtreeDescriptorFlags;
+
+/* A descriptor containing information about a dm-verity hashtree.
+ *
+ * Hash-trees are used to verify large partitions typically containing
+ * file systems. See
+ * https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for more
+ * information about dm-verity.
+ *
+ * Following this struct are |partition_name_len| bytes of the
+ * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
+ * |root_digest_len| bytes of the root digest.
+ *
+ * The |reserved| field is for future expansion and must be set to NUL
+ * bytes.
+ *
+ * Changes in v1.1:
+ * - flags field is added which supports AVB_HASHTREE_DESCRIPTOR_FLAGS_USE_AB
+ * - digest_len may be zero, which indicates the use of a persistent digest
+ */
+typedef struct AvbHashtreeDescriptor {
+ AvbDescriptor parent_descriptor;
+ uint32_t dm_verity_version;
+ uint64_t image_size;
+ uint64_t tree_offset;
+ uint64_t tree_size;
+ uint32_t data_block_size;
+ uint32_t hash_block_size;
+ uint32_t fec_num_roots;
+ uint64_t fec_offset;
+ uint64_t fec_size;
+ uint8_t hash_algorithm[32];
+ uint32_t partition_name_len;
+ uint32_t salt_len;
+ uint32_t root_digest_len;
+ uint32_t flags;
+ uint8_t reserved[60];
+} AVB_ATTR_PACKED AvbHashtreeDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_hashtree_descriptor_validate_and_byteswap(
+ const AvbHashtreeDescriptor* src,
+ AvbHashtreeDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_HASHTREE_DESCRIPTOR_H_ */
diff --git a/lib/avb/libavb/avb_kernel_cmdline_descriptor.c b/lib/avb/libavb/avb_kernel_cmdline_descriptor.c
index 9f3187c439..67521f231a 100644
--- a/lib/avb/libavb/avb_kernel_cmdline_descriptor.c
+++ b/lib/avb/libavb/avb_kernel_cmdline_descriptor.c
@@ -1,58 +1,58 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_kernel_cmdline_descriptor.h>
-#include <android_avb/avb_util.h>
-
-bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
- const AvbKernelCmdlineDescriptor* src, AvbKernelCmdlineDescriptor* dest) {
- uint64_t expected_size;
-
- avb_memcpy(dest, src, sizeof(AvbKernelCmdlineDescriptor));
-
- if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
- (AvbDescriptor*)dest))
- return false;
-
- if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE) {
- avb_error("Invalid tag for kernel cmdline descriptor.\n");
- return false;
- }
-
- dest->flags = avb_be32toh(dest->flags);
- dest->kernel_cmdline_length = avb_be32toh(dest->kernel_cmdline_length);
-
- /* Check that kernel_cmdline is fully contained. */
- expected_size = sizeof(AvbKernelCmdlineDescriptor) - sizeof(AvbDescriptor);
- if (!avb_safe_add_to(&expected_size, dest->kernel_cmdline_length)) {
- avb_error("Overflow while adding up sizes.\n");
- return false;
- }
- if (expected_size > dest->parent_descriptor.num_bytes_following) {
- avb_error("Descriptor payload size overflow.\n");
- return false;
- }
-
- return true;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_kernel_cmdline_descriptor.h"
+#include "avb_util.h"
+
+bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
+ const AvbKernelCmdlineDescriptor* src, AvbKernelCmdlineDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbKernelCmdlineDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE) {
+ avb_error("Invalid tag for kernel cmdline descriptor.\n");
+ return false;
+ }
+
+ dest->flags = avb_be32toh(dest->flags);
+ dest->kernel_cmdline_length = avb_be32toh(dest->kernel_cmdline_length);
+
+ /* Check that kernel_cmdline is fully contained. */
+ expected_size = sizeof(AvbKernelCmdlineDescriptor) - sizeof(AvbDescriptor);
+ if (!avb_safe_add_to(&expected_size, dest->kernel_cmdline_length)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+
+ return true;
+}
diff --git a/include/android_avb/avb_kernel_cmdline_descriptor.h b/lib/avb/libavb/avb_kernel_cmdline_descriptor.h
index af9bba2f66..6908b3b19d 100644
--- a/include/android_avb/avb_kernel_cmdline_descriptor.h
+++ b/lib/avb/libavb/avb_kernel_cmdline_descriptor.h
@@ -1,83 +1,81 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_KERNEL_CMDLINE_DESCRIPTOR_H_
-#define AVB_KERNEL_CMDLINE_DESCRIPTOR_H_
-
-#include <android_avb/avb_descriptor.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Flags for kernel command-line descriptors.
- *
- * AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED: The
- * cmdline will only be applied if hashtree verification is not
- * disabled (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
- *
- * AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED: The cmdline
- * will only be applied if hashtree verification is disabled
- * (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
- */
-typedef enum {
- AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED = (1 << 0),
- AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED = (1 << 1)
-} AvbKernelCmdlineFlags;
-
-/* A descriptor containing information to be appended to the kernel
- * command-line.
- *
- * The |flags| field contains flags from the AvbKernelCmdlineFlags
- * enumeration.
- *
- * Following this struct are |kernel_cmdline_len| bytes with the
- * kernel command-line (UTF-8 encoded).
- */
-typedef struct AvbKernelCmdlineDescriptor {
- AvbDescriptor parent_descriptor;
- uint32_t flags;
- uint32_t kernel_cmdline_length;
-} AVB_ATTR_PACKED AvbKernelCmdlineDescriptor;
-
-/* Copies |src| to |dest| and validates, byte-swapping fields in the
- * process if needed. Returns true if valid, false if invalid.
- *
- * Data following the struct is not validated nor copied.
- */
-bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
- const AvbKernelCmdlineDescriptor* src,
- AvbKernelCmdlineDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_KERNEL_CMDLINE_DESCRIPTOR_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_KERNEL_CMDLINE_DESCRIPTOR_H_
+#define AVB_KERNEL_CMDLINE_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Flags for kernel command-line descriptors.
+ *
+ * AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED: The
+ * cmdline will only be applied if hashtree verification is not
+ * disabled (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
+ *
+ * AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED: The cmdline
+ * will only be applied if hashtree verification is disabled
+ * (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
+ */
+typedef enum {
+ AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED = (1 << 0),
+ AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED = (1 << 1)
+} AvbKernelCmdlineFlags;
+
+/* A descriptor containing information to be appended to the kernel
+ * command-line.
+ *
+ * The |flags| field contains flags from the AvbKernelCmdlineFlags
+ * enumeration.
+ *
+ * Following this struct are |kernel_cmdline_len| bytes with the
+ * kernel command-line (UTF-8 encoded).
+ */
+typedef struct AvbKernelCmdlineDescriptor {
+ AvbDescriptor parent_descriptor;
+ uint32_t flags;
+ uint32_t kernel_cmdline_length;
+} AVB_ATTR_PACKED AvbKernelCmdlineDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
+ const AvbKernelCmdlineDescriptor* src,
+ AvbKernelCmdlineDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_KERNEL_CMDLINE_DESCRIPTOR_H_ */
diff --git a/include/android_avb/avb_ops.h b/lib/avb/libavb/avb_ops.h
index 2a418454d4..77f7ec3c12 100644
--- a/include/android_avb/avb_ops.h
+++ b/lib/avb/libavb/avb_ops.h
@@ -1,256 +1,311 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_OPS_H_
-#define AVB_OPS_H_
-
-#include <android_avb/avb_sysdeps.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Return codes used for I/O operations.
- *
- * AVB_IO_RESULT_OK is returned if the requested operation was
- * successful.
- *
- * AVB_IO_RESULT_ERROR_IO is returned if the underlying hardware (disk
- * or other subsystem) encountered an I/O error.
- *
- * AVB_IO_RESULT_ERROR_OOM is returned if unable to allocate memory.
- *
- * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is returned if the requested
- * partition does not exist.
- *
- * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the
- * range of bytes requested to be read or written is outside the range
- * of the partition.
- */
-typedef enum {
- AVB_IO_RESULT_OK,
- AVB_IO_RESULT_ERROR_OOM,
- AVB_IO_RESULT_ERROR_IO,
- AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
- AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION
-} AvbIOResult;
-
-struct AvbOps;
-typedef struct AvbOps AvbOps;
-
-/* Forward-declaration of operations in libavb_ab. */
-struct AvbABOps;
-
-/* Forward-declaration of operations in libavb_atx. */
-struct AvbAtxOps;
-
-/* High-level operations/functions/methods that are platform
- * dependent.
- *
- * Operations may be added in the future so when implementing it
- * always make sure to zero out sizeof(AvbOps) bytes of the struct to
- * ensure that unimplemented operations are set to NULL.
- */
-struct AvbOps {
- /* This pointer can be used by the application/bootloader using
- * libavb and is typically used in each operation to get a pointer
- * to platform-specific resources. It cannot be used by libraries.
- */
- void* user_data;
-
- /* If libavb_ab is used, this should point to the
- * AvbABOps. Otherwise it must be set to NULL.
- */
- struct AvbABOps* ab_ops;
-
- /* If libavb_atx is used, this should point to the
- * AvbAtxOps. Otherwise it must be set to NULL.
- */
- struct AvbAtxOps* atx_ops;
-
- /* Reads |num_bytes| from offset |offset| from partition with name
- * |partition| (NUL-terminated UTF-8 string). If |offset| is
- * negative, its absolute value should be interpreted as the number
- * of bytes from the end of the partition.
- *
- * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
- * there is no partition with the given name,
- * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
- * |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if
- * there was an I/O error from the underlying I/O subsystem. If the
- * operation succeeds as requested AVB_IO_RESULT_OK is returned and
- * the data is available in |buffer|.
- *
- * The only time partial I/O may occur is if reading beyond the end
- * of the partition. In this case the value returned in
- * |out_num_read| may be smaller than |num_bytes|.
- */
- AvbIOResult (*read_from_partition)(AvbOps* ops,
- const char* partition,
- int64_t offset,
- size_t num_bytes,
- void* buffer,
- size_t* out_num_read);
-
- /* Gets the starting pointer of a partition that is pre-loaded in memory, and
- * save it to |out_pointer|. The preloaded partition is expected to be
- * |num_bytes|, where the actual preloaded byte count is returned in
- * |out_num_bytes_preloaded|. |out_num_bytes_preloaded| must be no larger than
- * |num_bytes|.
- *
- * This provides an alternative way to access a partition that is preloaded
- * into memory without a full memory copy. When this function pointer is not
- * set (has value NULL), or when the |out_pointer| is set to NULL as a result,
- * |read_from_partition| will be used as the fallback. This function is mainly
- * used for accessing the entire partition content to calculate its hash.
- *
- * Preloaded partition data must outlive the lifespan of the
- * |AvbSlotVerifyData| structure that |avb_slot_verify| outputs.
- */
- AvbIOResult (*get_preloaded_partition)(AvbOps* ops,
- const char* partition,
- size_t num_bytes,
- uint8_t** out_pointer,
- size_t* out_num_bytes_preloaded);
-
- /* Writes |num_bytes| from |bffer| at offset |offset| to partition
- * with name |partition| (NUL-terminated UTF-8 string). If |offset|
- * is negative, its absolute value should be interpreted as the
- * number of bytes from the end of the partition.
- *
- * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
- * there is no partition with the given name,
- * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
- * byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO
- * if there was an I/O error from the underlying I/O subsystem. If
- * the operation succeeds as requested AVB_IO_RESULT_OK is
- * returned.
- *
- * This function never does any partial I/O, it either transfers all
- * of the requested bytes or returns an error.
- */
- AvbIOResult (*write_to_partition)(AvbOps* ops,
- const char* partition,
- int64_t offset,
- size_t num_bytes,
- const void* buffer);
-
- /* Checks if the given public key used to sign the 'vbmeta'
- * partition is trusted. Boot loaders typically compare this with
- * embedded key material generated with 'avbtool
- * extract_public_key'.
- *
- * The public key is in the array pointed to by |public_key_data|
- * and is of |public_key_length| bytes.
- *
- * If there is no public key metadata (set with the avbtool option
- * --public_key_metadata) then |public_key_metadata| will be set to
- * NULL. Otherwise this field points to the data which is
- * |public_key_metadata_length| bytes long.
- *
- * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
- * true if trusted or false if untrusted.
- */
- AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
- const uint8_t* public_key_data,
- size_t public_key_length,
- const uint8_t* public_key_metadata,
- size_t public_key_metadata_length,
- bool* out_is_trusted);
-
- /* Gets the rollback index corresponding to the location given by
- * |rollback_index_location|. The value is returned in
- * |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback
- * index was retrieved, otherwise an error code.
- *
- * A device may have a limited amount of rollback index locations (say,
- * one or four) so may error out if |rollback_index_location| exceeds
- * this number.
- */
- AvbIOResult (*read_rollback_index)(AvbOps* ops,
- size_t rollback_index_location,
- uint64_t* out_rollback_index);
-
- /* Sets the rollback index corresponding to the location given by
- * |rollback_index_location| to |rollback_index|. Returns
- * AVB_IO_RESULT_OK if the rollback index was set, otherwise an
- * error code.
- *
- * A device may have a limited amount of rollback index locations (say,
- * one or four) so may error out if |rollback_index_location| exceeds
- * this number.
- */
- AvbIOResult (*write_rollback_index)(AvbOps* ops,
- size_t rollback_index_location,
- uint64_t rollback_index);
-
- /* Gets whether the device is unlocked. The value is returned in
- * |out_is_unlocked| (true if unlocked, false otherwise). Returns
- * AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
- * code.
- */
- AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
-
- /* write the device lock flag. Returns
- * AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
- * code.
- */
- AvbIOResult (*write_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
- /* Gets the unique partition GUID for a partition with name in
- * |partition| (NUL-terminated UTF-8 string). The GUID is copied as
- * a string into |guid_buf| of size |guid_buf_size| and will be NUL
- * terminated. The string must be lower-case and properly
- * hyphenated. For example:
- *
- * 527c1c6d-6361-4593-8842-3c78fcd39219
- *
- * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
- */
- AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops,
- const char* partition,
- char* guid_buf,
- size_t guid_buf_size);
-
- /* Gets the size of a partition with the name in |partition|
- * (NUL-terminated UTF-8 string). Returns the value in
- * |out_size_num_bytes|.
- *
- * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
- */
- AvbIOResult (*get_size_of_partition)(AvbOps* ops,
- const char* partition,
- uint64_t* out_size_num_bytes);
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_OPS_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_OPS_H_
+#define AVB_OPS_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Well-known names of named persistent values. */
+#define AVB_NPV_PERSISTENT_DIGEST_PREFIX "avb.persistent_digest."
+
+/* Return codes used for I/O operations.
+ *
+ * AVB_IO_RESULT_OK is returned if the requested operation was
+ * successful.
+ *
+ * AVB_IO_RESULT_ERROR_IO is returned if the underlying hardware (disk
+ * or other subsystem) encountered an I/O error.
+ *
+ * AVB_IO_RESULT_ERROR_OOM is returned if unable to allocate memory.
+ *
+ * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is returned if the requested
+ * partition does not exist.
+ *
+ * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the
+ * range of bytes requested to be read or written is outside the range
+ * of the partition.
+ *
+ * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE is returned if a named persistent value
+ * does not exist.
+ *
+ * AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE is returned if a named persistent
+ * value size is not supported or does not match the expected size.
+ *
+ * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned if a buffer is too small
+ * for the requested operation.
+ */
+typedef enum {
+ AVB_IO_RESULT_OK,
+ AVB_IO_RESULT_ERROR_OOM,
+ AVB_IO_RESULT_ERROR_IO,
+ AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
+ AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION,
+ AVB_IO_RESULT_ERROR_NO_SUCH_VALUE,
+ AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE,
+ AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE,
+} AvbIOResult;
+
+struct AvbOps;
+typedef struct AvbOps AvbOps;
+
+/* Forward-declaration of operations in libavb_ab. */
+struct AvbABOps;
+
+/* Forward-declaration of operations in libavb_atx. */
+struct AvbAtxOps;
+
+/* High-level operations/functions/methods that are platform
+ * dependent.
+ *
+ * Operations may be added in the future so when implementing it
+ * always make sure to zero out sizeof(AvbOps) bytes of the struct to
+ * ensure that unimplemented operations are set to NULL.
+ */
+struct AvbOps {
+ /* This pointer can be used by the application/bootloader using
+ * libavb and is typically used in each operation to get a pointer
+ * to platform-specific resources. It cannot be used by libraries.
+ */
+ void* user_data;
+
+ /* If libavb_ab is used, this should point to the
+ * AvbABOps. Otherwise it must be set to NULL.
+ */
+ struct AvbABOps* ab_ops;
+
+ /* If libavb_atx is used, this should point to the
+ * AvbAtxOps. Otherwise it must be set to NULL.
+ */
+ struct AvbAtxOps* atx_ops;
+
+ /* Reads |num_bytes| from offset |offset| from partition with name
+ * |partition| (NUL-terminated UTF-8 string). If |offset| is
+ * negative, its absolute value should be interpreted as the number
+ * of bytes from the end of the partition.
+ *
+ * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
+ * there is no partition with the given name,
+ * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
+ * |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if
+ * there was an I/O error from the underlying I/O subsystem. If the
+ * operation succeeds as requested AVB_IO_RESULT_OK is returned and
+ * the data is available in |buffer|.
+ *
+ * The only time partial I/O may occur is if reading beyond the end
+ * of the partition. In this case the value returned in
+ * |out_num_read| may be smaller than |num_bytes|.
+ */
+ AvbIOResult (*read_from_partition)(AvbOps* ops,
+ const char* partition,
+ int64_t offset,
+ size_t num_bytes,
+ void* buffer,
+ size_t* out_num_read);
+
+ /* Gets the starting pointer of a partition that is pre-loaded in memory, and
+ * save it to |out_pointer|. The preloaded partition is expected to be
+ * |num_bytes|, where the actual preloaded byte count is returned in
+ * |out_num_bytes_preloaded|. |out_num_bytes_preloaded| must be no larger than
+ * |num_bytes|.
+ *
+ * This provides an alternative way to access a partition that is preloaded
+ * into memory without a full memory copy. When this function pointer is not
+ * set (has value NULL), or when the |out_pointer| is set to NULL as a result,
+ * |read_from_partition| will be used as the fallback. This function is mainly
+ * used for accessing the entire partition content to calculate its hash.
+ *
+ * Preloaded partition data must outlive the lifespan of the
+ * |AvbSlotVerifyData| structure that |avb_slot_verify| outputs.
+ */
+ AvbIOResult (*get_preloaded_partition)(AvbOps* ops,
+ const char* partition,
+ size_t num_bytes,
+ uint8_t** out_pointer,
+ size_t* out_num_bytes_preloaded);
+
+ /* Writes |num_bytes| from |bffer| at offset |offset| to partition
+ * with name |partition| (NUL-terminated UTF-8 string). If |offset|
+ * is negative, its absolute value should be interpreted as the
+ * number of bytes from the end of the partition.
+ *
+ * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
+ * there is no partition with the given name,
+ * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
+ * byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO
+ * if there was an I/O error from the underlying I/O subsystem. If
+ * the operation succeeds as requested AVB_IO_RESULT_OK is
+ * returned.
+ *
+ * This function never does any partial I/O, it either transfers all
+ * of the requested bytes or returns an error.
+ */
+ AvbIOResult (*write_to_partition)(AvbOps* ops,
+ const char* partition,
+ int64_t offset,
+ size_t num_bytes,
+ const void* buffer);
+
+ /* Checks if the given public key used to sign the 'vbmeta'
+ * partition is trusted. Boot loaders typically compare this with
+ * embedded key material generated with 'avbtool
+ * extract_public_key'.
+ *
+ * The public key is in the array pointed to by |public_key_data|
+ * and is of |public_key_length| bytes.
+ *
+ * If there is no public key metadata (set with the avbtool option
+ * --public_key_metadata) then |public_key_metadata| will be set to
+ * NULL. Otherwise this field points to the data which is
+ * |public_key_metadata_length| bytes long.
+ *
+ * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
+ * true if trusted or false if untrusted.
+ */
+ AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ const uint8_t* public_key_metadata,
+ size_t public_key_metadata_length,
+ bool* out_is_trusted);
+
+ /* Gets the rollback index corresponding to the location given by
+ * |rollback_index_location|. The value is returned in
+ * |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback
+ * index was retrieved, otherwise an error code.
+ *
+ * A device may have a limited amount of rollback index locations (say,
+ * one or four) so may error out if |rollback_index_location| exceeds
+ * this number.
+ */
+ AvbIOResult (*read_rollback_index)(AvbOps* ops,
+ size_t rollback_index_location,
+ uint64_t* out_rollback_index);
+
+ /* Sets the rollback index corresponding to the location given by
+ * |rollback_index_location| to |rollback_index|. Returns
+ * AVB_IO_RESULT_OK if the rollback index was set, otherwise an
+ * error code.
+ *
+ * A device may have a limited amount of rollback index locations (say,
+ * one or four) so may error out if |rollback_index_location| exceeds
+ * this number.
+ */
+ AvbIOResult (*write_rollback_index)(AvbOps* ops,
+ size_t rollback_index_location,
+ uint64_t rollback_index);
+
+ /* Gets whether the device is unlocked. The value is returned in
+ * |out_is_unlocked| (true if unlocked, false otherwise). Returns
+ * AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
+ * code.
+ */
+ AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
+
+ /* Gets the unique partition GUID for a partition with name in
+ * |partition| (NUL-terminated UTF-8 string). The GUID is copied as
+ * a string into |guid_buf| of size |guid_buf_size| and will be NUL
+ * terminated. The string must be lower-case and properly
+ * hyphenated. For example:
+ *
+ * 527c1c6d-6361-4593-8842-3c78fcd39219
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ */
+ AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops,
+ const char* partition,
+ char* guid_buf,
+ size_t guid_buf_size);
+
+ /* Gets the size of a partition with the name in |partition|
+ * (NUL-terminated UTF-8 string). Returns the value in
+ * |out_size_num_bytes|.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ */
+ AvbIOResult (*get_size_of_partition)(AvbOps* ops,
+ const char* partition,
+ uint64_t* out_size_num_bytes);
+
+ /* Reads a persistent value corresponding to the given |name|. The value is
+ * returned in |out_buffer| which must point to |buffer_size| bytes. On
+ * success |out_num_bytes_read| contains the number of bytes read into
+ * |out_buffer|. If AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned,
+ * |out_num_bytes_read| contains the number of bytes that would have been read
+ * which can be used to allocate a buffer.
+ *
+ * The |buffer_size| may be zero and the |out_buffer| may be NULL, but if
+ * |out_buffer| is NULL then |buffer_size| *must* be zero.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ *
+ * If the value does not exist, is not supported, or is not populated, returns
+ * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If |buffer_size| is smaller than the
+ * size of the stored value, returns AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE.
+ *
+ * This operation is currently only used to support persistent digests. If a
+ * device does not use persistent digests this function pointer can be set to
+ * NULL.
+ */
+ AvbIOResult (*read_persistent_value)(AvbOps* ops,
+ const char* name,
+ size_t buffer_size,
+ uint8_t* out_buffer,
+ size_t* out_num_bytes_read);
+
+ /* Writes a persistent value corresponding to the given |name|. The value is
+ * supplied in |value| which must point to |value_size| bytes. Any existing
+ * value with the same name is overwritten. If |value_size| is zero, future
+ * calls to |read_persistent_value| will return
+ * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ *
+ * If the value |name| is not supported, returns
+ * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If the |value_size| is not supported,
+ * returns AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE.
+ *
+ * This operation is currently only used to support persistent digests. If a
+ * device does not use persistent digests this function pointer can be set to
+ * NULL.
+ */
+ AvbIOResult (*write_persistent_value)(AvbOps* ops,
+ const char* name,
+ size_t value_size,
+ const uint8_t* value);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_OPS_H_ */
diff --git a/lib/avb/libavb/avb_property_descriptor.c b/lib/avb/libavb/avb_property_descriptor.c
index e039433334..7eba2c00b0 100644
--- a/lib/avb/libavb/avb_property_descriptor.c
+++ b/lib/avb/libavb/avb_property_descriptor.c
@@ -1,185 +1,185 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_property_descriptor.h>
-#include <android_avb/avb_util.h>
-
-bool avb_property_descriptor_validate_and_byteswap(
- const AvbPropertyDescriptor* src, AvbPropertyDescriptor* dest) {
- uint64_t expected_size;
-
- avb_memcpy(dest, src, sizeof(AvbPropertyDescriptor));
-
- if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
- (AvbDescriptor*)dest))
- return false;
-
- if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
- avb_error("Invalid tag for property descriptor.\n");
- return false;
- }
-
- dest->key_num_bytes = avb_be64toh(dest->key_num_bytes);
- dest->value_num_bytes = avb_be64toh(dest->value_num_bytes);
-
- /* Check that key and value are fully contained. */
- expected_size = sizeof(AvbPropertyDescriptor) - sizeof(AvbDescriptor) + 2;
- if (!avb_safe_add_to(&expected_size, dest->key_num_bytes) ||
- !avb_safe_add_to(&expected_size, dest->value_num_bytes)) {
- avb_error("Overflow while adding up sizes.\n");
- return false;
- }
- if (expected_size > dest->parent_descriptor.num_bytes_following) {
- avb_error("Descriptor payload size overflow.\n");
- return false;
- }
-
- return true;
-}
-
-typedef struct {
- const char* key;
- size_t key_size;
- const char* ret_value;
- size_t ret_value_size;
-} PropertyIteratorData;
-
-static bool property_lookup_desc_foreach(const AvbDescriptor* header,
- void* user_data) {
- PropertyIteratorData* data = (PropertyIteratorData*)user_data;
- AvbPropertyDescriptor prop_desc;
- const uint8_t* p;
- bool ret = true;
-
- if (header->tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
- goto out;
- }
-
- if (!avb_property_descriptor_validate_and_byteswap(
- (const AvbPropertyDescriptor*)header, &prop_desc)) {
- goto out;
- }
-
- p = (const uint8_t*)header;
- if (p[sizeof(AvbPropertyDescriptor) + prop_desc.key_num_bytes] != 0) {
- avb_error("No terminating NUL byte in key.\n");
- goto out;
- }
-
- if (data->key_size == prop_desc.key_num_bytes) {
- if (avb_memcmp(p + sizeof(AvbPropertyDescriptor),
- data->key,
- data->key_size) == 0) {
- data->ret_value = (const char*)(p + sizeof(AvbPropertyDescriptor) +
- prop_desc.key_num_bytes + 1);
- data->ret_value_size = prop_desc.value_num_bytes;
- /* Stop iterating. */
- ret = false;
- goto out;
- }
- }
-
-out:
- return ret;
-}
-
-const char* avb_property_lookup(const uint8_t* image_data,
- size_t image_size,
- const char* key,
- size_t key_size,
- size_t* out_value_size) {
- PropertyIteratorData data;
-
- if (key_size == 0) {
- key_size = avb_strlen(key);
- }
-
- data.key = key;
- data.key_size = key_size;
-
- if (avb_descriptor_foreach(
- image_data, image_size, property_lookup_desc_foreach, &data) == 0) {
- if (out_value_size != NULL) {
- *out_value_size = data.ret_value_size;
- }
- return data.ret_value;
- }
-
- if (out_value_size != NULL) {
- *out_value_size = 0;
- }
- return NULL;
-}
-
-bool avb_property_lookup_uint64(const uint8_t* image_data,
- size_t image_size,
- const char* key,
- size_t key_size,
- uint64_t* out_value) {
- const char* value;
- bool ret = false;
- uint64_t parsed_val;
- int base;
- int n;
-
- value = avb_property_lookup(image_data, image_size, key, key_size, NULL);
- if (value == NULL) {
- goto out;
- }
-
- base = 10;
- if (avb_memcmp(value, "0x", 2) == 0) {
- base = 16;
- value += 2;
- }
-
- parsed_val = 0;
- for (n = 0; value[n] != '\0'; n++) {
- int c = value[n];
- int digit;
-
- parsed_val *= base;
-
- if (c >= '0' && c <= '9') {
- digit = c - '0';
- } else if (base == 16 && c >= 'a' && c <= 'f') {
- digit = c - 'a' + 10;
- } else if (base == 16 && c >= 'A' && c <= 'F') {
- digit = c - 'A' + 10;
- } else {
- avb_error("Invalid digit.\n");
- goto out;
- }
-
- parsed_val += digit;
- }
-
- ret = true;
- if (out_value != NULL) {
- *out_value = parsed_val;
- }
-
-out:
- return ret;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_property_descriptor.h"
+#include "avb_util.h"
+
+bool avb_property_descriptor_validate_and_byteswap(
+ const AvbPropertyDescriptor* src, AvbPropertyDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbPropertyDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
+ avb_error("Invalid tag for property descriptor.\n");
+ return false;
+ }
+
+ dest->key_num_bytes = avb_be64toh(dest->key_num_bytes);
+ dest->value_num_bytes = avb_be64toh(dest->value_num_bytes);
+
+ /* Check that key and value are fully contained. */
+ expected_size = sizeof(AvbPropertyDescriptor) - sizeof(AvbDescriptor) + 2;
+ if (!avb_safe_add_to(&expected_size, dest->key_num_bytes) ||
+ !avb_safe_add_to(&expected_size, dest->value_num_bytes)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+
+ return true;
+}
+
+typedef struct {
+ const char* key;
+ size_t key_size;
+ const char* ret_value;
+ size_t ret_value_size;
+} PropertyIteratorData;
+
+static bool property_lookup_desc_foreach(const AvbDescriptor* header,
+ void* user_data) {
+ PropertyIteratorData* data = (PropertyIteratorData*)user_data;
+ AvbPropertyDescriptor prop_desc;
+ const uint8_t* p;
+ bool ret = true;
+
+ if (header->tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
+ goto out;
+ }
+
+ if (!avb_property_descriptor_validate_and_byteswap(
+ (const AvbPropertyDescriptor*)header, &prop_desc)) {
+ goto out;
+ }
+
+ p = (const uint8_t*)header;
+ if (p[sizeof(AvbPropertyDescriptor) + prop_desc.key_num_bytes] != 0) {
+ avb_error("No terminating NUL byte in key.\n");
+ goto out;
+ }
+
+ if (data->key_size == prop_desc.key_num_bytes) {
+ if (avb_memcmp(p + sizeof(AvbPropertyDescriptor),
+ data->key,
+ data->key_size) == 0) {
+ data->ret_value = (const char*)(p + sizeof(AvbPropertyDescriptor) +
+ prop_desc.key_num_bytes + 1);
+ data->ret_value_size = prop_desc.value_num_bytes;
+ /* Stop iterating. */
+ ret = false;
+ goto out;
+ }
+ }
+
+out:
+ return ret;
+}
+
+const char* avb_property_lookup(const uint8_t* image_data,
+ size_t image_size,
+ const char* key,
+ size_t key_size,
+ size_t* out_value_size) {
+ PropertyIteratorData data;
+
+ if (key_size == 0) {
+ key_size = avb_strlen(key);
+ }
+
+ data.key = key;
+ data.key_size = key_size;
+
+ if (avb_descriptor_foreach(
+ image_data, image_size, property_lookup_desc_foreach, &data) == 0) {
+ if (out_value_size != NULL) {
+ *out_value_size = data.ret_value_size;
+ }
+ return data.ret_value;
+ }
+
+ if (out_value_size != NULL) {
+ *out_value_size = 0;
+ }
+ return NULL;
+}
+
+bool avb_property_lookup_uint64(const uint8_t* image_data,
+ size_t image_size,
+ const char* key,
+ size_t key_size,
+ uint64_t* out_value) {
+ const char* value;
+ bool ret = false;
+ uint64_t parsed_val;
+ int base;
+ int n;
+
+ value = avb_property_lookup(image_data, image_size, key, key_size, NULL);
+ if (value == NULL) {
+ goto out;
+ }
+
+ base = 10;
+ if (avb_memcmp(value, "0x", 2) == 0) {
+ base = 16;
+ value += 2;
+ }
+
+ parsed_val = 0;
+ for (n = 0; value[n] != '\0'; n++) {
+ int c = value[n];
+ int digit;
+
+ parsed_val *= base;
+
+ if (c >= '0' && c <= '9') {
+ digit = c - '0';
+ } else if (base == 16 && c >= 'a' && c <= 'f') {
+ digit = c - 'a' + 10;
+ } else if (base == 16 && c >= 'A' && c <= 'F') {
+ digit = c - 'A' + 10;
+ } else {
+ avb_error("Invalid digit.\n");
+ goto out;
+ }
+
+ parsed_val += digit;
+ }
+
+ ret = true;
+ if (out_value != NULL) {
+ *out_value = parsed_val;
+ }
+
+out:
+ return ret;
+}
diff --git a/include/android_avb/avb_property_descriptor.h b/lib/avb/libavb/avb_property_descriptor.h
index 28c35cb560..a2fef696a9 100644
--- a/include/android_avb/avb_property_descriptor.h
+++ b/lib/avb/libavb/avb_property_descriptor.h
@@ -1,109 +1,107 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_PROPERTY_DESCRIPTOR_H_
-#define AVB_PROPERTY_DESCRIPTOR_H_
-
-#include <android_avb/avb_descriptor.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* 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.
- */
-typedef struct AvbPropertyDescriptor {
- AvbDescriptor parent_descriptor;
- uint64_t key_num_bytes;
- uint64_t value_num_bytes;
-} AVB_ATTR_PACKED AvbPropertyDescriptor;
-
-/* Copies |src| to |dest| and validates, byte-swapping fields in the
- * process if needed. Returns true if valid, false if invalid.
- *
- * Data following the struct is not validated nor copied.
- */
-bool avb_property_descriptor_validate_and_byteswap(
- const AvbPropertyDescriptor* src,
- AvbPropertyDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Convenience function for looking up the value for a property with
- * name |key| in a vbmeta image. If |key_size| is 0, |key| must be
- * NUL-terminated.
- *
- * The |image_data| parameter must be a pointer to a vbmeta image of
- * size |image_size|.
- *
- * This function returns a pointer to the value inside the passed-in
- * image or NULL if not found. Note that the value is always
- * guaranteed to be followed by a NUL byte.
- *
- * If the value was found and |out_value_size| is not NULL, the size
- * of the value is returned there.
- *
- * This function is O(n) in number of descriptors so if you need to
- * look up a lot of values, you may want to build a more efficient
- * lookup-table by manually walking all descriptors using
- * avb_descriptor_foreach().
- *
- * Before using this function, you MUST verify |image_data| with
- * avb_vbmeta_image_verify() and reject it unless it's signed by a
- * known good public key.
- */
-const char* avb_property_lookup(const uint8_t* image_data,
- size_t image_size,
- const char* key,
- size_t key_size,
- size_t* out_value_size)
- AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Like avb_property_lookup() but parses the intial portions of the
- * value as an unsigned 64-bit integer. Both decimal and hexadecimal
- * representations (e.g. "0x2a") are supported. Returns false on
- * failure and true on success. On success, the parsed value is
- * returned in |out_value|.
- */
-bool avb_property_lookup_uint64(const uint8_t* image_data,
- size_t image_size,
- const char* key,
- size_t key_size,
- uint64_t* out_value)
- AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_PROPERTY_DESCRIPTOR_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_PROPERTY_DESCRIPTOR_H_
+#define AVB_PROPERTY_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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.
+ */
+typedef struct AvbPropertyDescriptor {
+ AvbDescriptor parent_descriptor;
+ uint64_t key_num_bytes;
+ uint64_t value_num_bytes;
+} AVB_ATTR_PACKED AvbPropertyDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_property_descriptor_validate_and_byteswap(
+ const AvbPropertyDescriptor* src,
+ AvbPropertyDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Convenience function for looking up the value for a property with
+ * name |key| in a vbmeta image. If |key_size| is 0, |key| must be
+ * NUL-terminated.
+ *
+ * The |image_data| parameter must be a pointer to a vbmeta image of
+ * size |image_size|.
+ *
+ * This function returns a pointer to the value inside the passed-in
+ * image or NULL if not found. Note that the value is always
+ * guaranteed to be followed by a NUL byte.
+ *
+ * If the value was found and |out_value_size| is not NULL, the size
+ * of the value is returned there.
+ *
+ * This function is O(n) in number of descriptors so if you need to
+ * look up a lot of values, you may want to build a more efficient
+ * lookup-table by manually walking all descriptors using
+ * avb_descriptor_foreach().
+ *
+ * Before using this function, you MUST verify |image_data| with
+ * avb_vbmeta_image_verify() and reject it unless it's signed by a
+ * known good public key.
+ */
+const char* avb_property_lookup(const uint8_t* image_data,
+ size_t image_size,
+ const char* key,
+ size_t key_size,
+ size_t* out_value_size)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Like avb_property_lookup() but parses the intial portions of the
+ * value as an unsigned 64-bit integer. Both decimal and hexadecimal
+ * representations (e.g. "0x2a") are supported. Returns false on
+ * failure and true on success. On success, the parsed value is
+ * returned in |out_value|.
+ */
+bool avb_property_lookup_uint64(const uint8_t* image_data,
+ size_t image_size,
+ const char* key,
+ size_t key_size,
+ uint64_t* out_value)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_PROPERTY_DESCRIPTOR_H_ */
diff --git a/lib/avb/libavb/avb_rsa.c b/lib/avb/libavb/avb_rsa.c
index c018e2be39..f4cb322b9e 100644
--- a/lib/avb/libavb/avb_rsa.c
+++ b/lib/avb/libavb/avb_rsa.c
@@ -1,299 +1,299 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* 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.
- */
-
-#include <android_avb/avb_rsa.h>
-#include <android_avb/avb_sha.h>
-#include <android_avb/avb_util.h>
-#include <android_avb/avb_vbmeta_image.h>
-
-typedef struct IAvbKey {
- unsigned int len; /* Length of n[] in number of uint32_t */
- uint32_t n0inv; /* -1 / n[0] mod 2^32 */
- uint32_t* n; /* modulus as array (host-byte order) */
- uint32_t* rr; /* R^2 as array (host-byte order) */
-} IAvbKey;
-
-static IAvbKey* iavb_parse_key_data(const uint8_t* data, size_t length) {
- AvbRSAPublicKeyHeader h;
- IAvbKey* key = NULL;
- size_t expected_length;
- unsigned int i;
- const uint8_t* n;
- const uint8_t* rr;
-
- if (!avb_rsa_public_key_header_validate_and_byteswap(
- (const AvbRSAPublicKeyHeader*)data, &h)) {
- avb_error("Invalid key.\n");
- goto fail;
- }
-
- if (!(h.key_num_bits == 2048 || h.key_num_bits == 4096 ||
- h.key_num_bits == 8192)) {
- avb_error("Unexpected key length.\n");
- goto fail;
- }
-
- expected_length = sizeof(AvbRSAPublicKeyHeader) + 2 * h.key_num_bits / 8;
- if (length != expected_length) {
- avb_error("Key does not match expected length.\n");
- goto fail;
- }
-
- n = data + sizeof(AvbRSAPublicKeyHeader);
- rr = data + sizeof(AvbRSAPublicKeyHeader) + h.key_num_bits / 8;
-
- /* Store n and rr following the key header so we only have to do one
- * allocation.
- */
- key = (IAvbKey*)(avb_malloc(sizeof(IAvbKey) + 2 * h.key_num_bits / 8));
- if (key == NULL) {
- goto fail;
- }
-
- key->len = h.key_num_bits / 32;
- key->n0inv = h.n0inv;
- key->n = (uint32_t*)(key + 1); /* Skip ahead sizeof(IAvbKey) bytes. */
- key->rr = key->n + key->len;
-
- /* Crypto-code below (modpowF4() and friends) expects the key in
- * little-endian format (rather than the format we're storing the
- * key in), so convert it.
- */
- for (i = 0; i < key->len; i++) {
- key->n[i] = avb_be32toh(((uint32_t*)n)[key->len - i - 1]);
- key->rr[i] = avb_be32toh(((uint32_t*)rr)[key->len - i - 1]);
- }
- return key;
-
-fail:
- if (key != NULL) {
- avb_free(key);
- }
- return NULL;
-}
-
-static void iavb_free_parsed_key(IAvbKey* key) {
- avb_free(key);
-}
-
-/* a[] -= mod */
-static void subM(const IAvbKey* key, uint32_t* a) {
- int64_t A = 0;
- uint32_t i;
- for (i = 0; i < key->len; ++i) {
- A += (uint64_t)a[i] - key->n[i];
- a[i] = (uint32_t)A;
- A >>= 32;
- }
-}
-
-/* return a[] >= mod */
-static int geM(const IAvbKey* key, uint32_t* a) {
- uint32_t i;
- for (i = key->len; i;) {
- --i;
- if (a[i] < key->n[i]) {
- return 0;
- }
- if (a[i] > key->n[i]) {
- return 1;
- }
- }
- return 1; /* equal */
-}
-
-/* montgomery c[] += a * b[] / R % mod */
-static void montMulAdd(const IAvbKey* key,
- uint32_t* c,
- const uint32_t a,
- const uint32_t* b) {
- uint64_t A = (uint64_t)a * b[0] + c[0];
- uint32_t d0 = (uint32_t)A * key->n0inv;
- uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
- uint32_t i;
-
- for (i = 1; i < key->len; ++i) {
- A = (A >> 32) + (uint64_t)a * b[i] + c[i];
- B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
- c[i - 1] = (uint32_t)B;
- }
-
- A = (A >> 32) + (B >> 32);
-
- c[i - 1] = (uint32_t)A;
-
- if (A >> 32) {
- subM(key, c);
- }
-}
-
-/* montgomery c[] = a[] * b[] / R % mod */
-static void montMul(const IAvbKey* key, uint32_t* c, uint32_t* a, uint32_t* b) {
- uint32_t i;
- for (i = 0; i < key->len; ++i) {
- c[i] = 0;
- }
- for (i = 0; i < key->len; ++i) {
- montMulAdd(key, c, a[i], b);
- }
-}
-
-/* In-place public exponentiation. (65537}
- * Input and output big-endian byte array in inout.
- */
-static void modpowF4(const IAvbKey* key, uint8_t* inout) {
- uint32_t* a = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
- uint32_t* aR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
- uint32_t* aaR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
- if (a == NULL || aR == NULL || aaR == NULL) {
- goto out;
- }
-
- uint32_t* aaa = aaR; /* Re-use location. */
- int i;
-
- /* Convert from big endian byte array to little endian word array. */
- for (i = 0; i < (int)key->len; ++i) {
- uint32_t tmp = (inout[((key->len - 1 - i) * 4) + 0] << 24) |
- (inout[((key->len - 1 - i) * 4) + 1] << 16) |
- (inout[((key->len - 1 - i) * 4) + 2] << 8) |
- (inout[((key->len - 1 - i) * 4) + 3] << 0);
- a[i] = tmp;
- }
-
- montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
- for (i = 0; i < 16; i += 2) {
- montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
- montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */
- }
- montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */
-
- /* Make sure aaa < mod; aaa is at most 1x mod too large. */
- if (geM(key, aaa)) {
- subM(key, aaa);
- }
-
- /* Convert to bigendian byte array */
- for (i = (int)key->len - 1; i >= 0; --i) {
- uint32_t tmp = aaa[i];
- *inout++ = (uint8_t)(tmp >> 24);
- *inout++ = (uint8_t)(tmp >> 16);
- *inout++ = (uint8_t)(tmp >> 8);
- *inout++ = (uint8_t)(tmp >> 0);
- }
-
-out:
- if (a != NULL) {
- avb_free(a);
- }
- if (aR != NULL) {
- avb_free(aR);
- }
- if (aaR != NULL) {
- avb_free(aaR);
- }
-}
-
-/* Verify a RSA PKCS1.5 signature against an expected hash.
- * Returns false on failure, true on success.
- */
-bool avb_rsa_verify(const uint8_t* key,
- size_t key_num_bytes,
- const uint8_t* sig,
- size_t sig_num_bytes,
- const uint8_t* hash,
- size_t hash_num_bytes,
- const uint8_t* padding,
- size_t padding_num_bytes) {
- uint8_t* buf = NULL;
- IAvbKey* parsed_key = NULL;
- bool success = false;
-
- if (key == NULL || sig == NULL || hash == NULL || padding == NULL) {
- avb_error("Invalid input.\n");
- goto out;
- }
-
- parsed_key = iavb_parse_key_data(key, key_num_bytes);
- if (parsed_key == NULL) {
- avb_error("Error parsing key.\n");
- goto out;
- }
-
- if (sig_num_bytes != (parsed_key->len * sizeof(uint32_t))) {
- avb_error("Signature length does not match key length.\n");
- goto out;
- }
-
- if (padding_num_bytes != sig_num_bytes - hash_num_bytes) {
- avb_error("Padding length does not match hash and signature lengths.\n");
- goto out;
- }
-
- buf = (uint8_t*)avb_malloc(sig_num_bytes);
- if (buf == NULL) {
- avb_error("Error allocating memory.\n");
- goto out;
- }
- avb_memcpy(buf, sig, sig_num_bytes);
-
- modpowF4(parsed_key, buf);
-
- /* Check padding bytes.
- *
- * Even though there are probably no timing issues here, we use
- * avb_safe_memcmp() just to be on the safe side.
- */
- if (avb_safe_memcmp(buf, padding, padding_num_bytes)) {
- avb_error("Padding check failed.\n");
- goto out;
- }
-
- /* Check hash. */
- if (avb_safe_memcmp(buf + padding_num_bytes, hash, hash_num_bytes)) {
- avb_error("Hash check failed.\n");
- goto out;
- }
-
- success = true;
-
-out:
- if (parsed_key != NULL) {
- iavb_free_parsed_key(parsed_key);
- }
- if (buf != NULL) {
- avb_free(buf);
- }
- return success;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* 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.
+ */
+
+#include "avb_rsa.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+
+typedef struct IAvbKey {
+ unsigned int len; /* Length of n[] in number of uint32_t */
+ uint32_t n0inv; /* -1 / n[0] mod 2^32 */
+ uint32_t* n; /* modulus as array (host-byte order) */
+ uint32_t* rr; /* R^2 as array (host-byte order) */
+} IAvbKey;
+
+static IAvbKey* iavb_parse_key_data(const uint8_t* data, size_t length) {
+ AvbRSAPublicKeyHeader h;
+ IAvbKey* key = NULL;
+ size_t expected_length;
+ unsigned int i;
+ const uint8_t* n;
+ const uint8_t* rr;
+
+ if (!avb_rsa_public_key_header_validate_and_byteswap(
+ (const AvbRSAPublicKeyHeader*)data, &h)) {
+ avb_error("Invalid key.\n");
+ goto fail;
+ }
+
+ if (!(h.key_num_bits == 2048 || h.key_num_bits == 4096 ||
+ h.key_num_bits == 8192)) {
+ avb_error("Unexpected key length.\n");
+ goto fail;
+ }
+
+ expected_length = sizeof(AvbRSAPublicKeyHeader) + 2 * h.key_num_bits / 8;
+ if (length != expected_length) {
+ avb_error("Key does not match expected length.\n");
+ goto fail;
+ }
+
+ n = data + sizeof(AvbRSAPublicKeyHeader);
+ rr = data + sizeof(AvbRSAPublicKeyHeader) + h.key_num_bits / 8;
+
+ /* Store n and rr following the key header so we only have to do one
+ * allocation.
+ */
+ key = (IAvbKey*)(avb_malloc(sizeof(IAvbKey) + 2 * h.key_num_bits / 8));
+ if (key == NULL) {
+ goto fail;
+ }
+
+ key->len = h.key_num_bits / 32;
+ key->n0inv = h.n0inv;
+ key->n = (uint32_t*)(key + 1); /* Skip ahead sizeof(IAvbKey) bytes. */
+ key->rr = key->n + key->len;
+
+ /* Crypto-code below (modpowF4() and friends) expects the key in
+ * little-endian format (rather than the format we're storing the
+ * key in), so convert it.
+ */
+ for (i = 0; i < key->len; i++) {
+ key->n[i] = avb_be32toh(((uint32_t*)n)[key->len - i - 1]);
+ key->rr[i] = avb_be32toh(((uint32_t*)rr)[key->len - i - 1]);
+ }
+ return key;
+
+fail:
+ if (key != NULL) {
+ avb_free(key);
+ }
+ return NULL;
+}
+
+static void iavb_free_parsed_key(IAvbKey* key) {
+ avb_free(key);
+}
+
+/* a[] -= mod */
+static void subM(const IAvbKey* key, uint32_t* a) {
+ int64_t A = 0;
+ uint32_t i;
+ for (i = 0; i < key->len; ++i) {
+ A += (uint64_t)a[i] - key->n[i];
+ a[i] = (uint32_t)A;
+ A >>= 32;
+ }
+}
+
+/* return a[] >= mod */
+static int geM(const IAvbKey* key, uint32_t* a) {
+ uint32_t i;
+ for (i = key->len; i;) {
+ --i;
+ if (a[i] < key->n[i]) {
+ return 0;
+ }
+ if (a[i] > key->n[i]) {
+ return 1;
+ }
+ }
+ return 1; /* equal */
+}
+
+/* montgomery c[] += a * b[] / R % mod */
+static void montMulAdd(const IAvbKey* key,
+ uint32_t* c,
+ const uint32_t a,
+ const uint32_t* b) {
+ uint64_t A = (uint64_t)a * b[0] + c[0];
+ uint32_t d0 = (uint32_t)A * key->n0inv;
+ uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
+ uint32_t i;
+
+ for (i = 1; i < key->len; ++i) {
+ A = (A >> 32) + (uint64_t)a * b[i] + c[i];
+ B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
+ c[i - 1] = (uint32_t)B;
+ }
+
+ A = (A >> 32) + (B >> 32);
+
+ c[i - 1] = (uint32_t)A;
+
+ if (A >> 32) {
+ subM(key, c);
+ }
+}
+
+/* montgomery c[] = a[] * b[] / R % mod */
+static void montMul(const IAvbKey* key, uint32_t* c, uint32_t* a, uint32_t* b) {
+ uint32_t i;
+ for (i = 0; i < key->len; ++i) {
+ c[i] = 0;
+ }
+ for (i = 0; i < key->len; ++i) {
+ montMulAdd(key, c, a[i], b);
+ }
+}
+
+/* In-place public exponentiation. (65537}
+ * Input and output big-endian byte array in inout.
+ */
+static void modpowF4(const IAvbKey* key, uint8_t* inout) {
+ uint32_t* a = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
+ uint32_t* aR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
+ uint32_t* aaR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
+ if (a == NULL || aR == NULL || aaR == NULL) {
+ goto out;
+ }
+
+ uint32_t* aaa = aaR; /* Re-use location. */
+ int i;
+
+ /* Convert from big endian byte array to little endian word array. */
+ for (i = 0; i < (int)key->len; ++i) {
+ uint32_t tmp = (inout[((key->len - 1 - i) * 4) + 0] << 24) |
+ (inout[((key->len - 1 - i) * 4) + 1] << 16) |
+ (inout[((key->len - 1 - i) * 4) + 2] << 8) |
+ (inout[((key->len - 1 - i) * 4) + 3] << 0);
+ a[i] = tmp;
+ }
+
+ montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
+ for (i = 0; i < 16; i += 2) {
+ montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
+ montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */
+ }
+ montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */
+
+ /* Make sure aaa < mod; aaa is at most 1x mod too large. */
+ if (geM(key, aaa)) {
+ subM(key, aaa);
+ }
+
+ /* Convert to bigendian byte array */
+ for (i = (int)key->len - 1; i >= 0; --i) {
+ uint32_t tmp = aaa[i];
+ *inout++ = (uint8_t)(tmp >> 24);
+ *inout++ = (uint8_t)(tmp >> 16);
+ *inout++ = (uint8_t)(tmp >> 8);
+ *inout++ = (uint8_t)(tmp >> 0);
+ }
+
+out:
+ if (a != NULL) {
+ avb_free(a);
+ }
+ if (aR != NULL) {
+ avb_free(aR);
+ }
+ if (aaR != NULL) {
+ avb_free(aaR);
+ }
+}
+
+/* Verify a RSA PKCS1.5 signature against an expected hash.
+ * Returns false on failure, true on success.
+ */
+bool avb_rsa_verify(const uint8_t* key,
+ size_t key_num_bytes,
+ const uint8_t* sig,
+ size_t sig_num_bytes,
+ const uint8_t* hash,
+ size_t hash_num_bytes,
+ const uint8_t* padding,
+ size_t padding_num_bytes) {
+ uint8_t* buf = NULL;
+ IAvbKey* parsed_key = NULL;
+ bool success = false;
+
+ if (key == NULL || sig == NULL || hash == NULL || padding == NULL) {
+ avb_error("Invalid input.\n");
+ goto out;
+ }
+
+ parsed_key = iavb_parse_key_data(key, key_num_bytes);
+ if (parsed_key == NULL) {
+ avb_error("Error parsing key.\n");
+ goto out;
+ }
+
+ if (sig_num_bytes != (parsed_key->len * sizeof(uint32_t))) {
+ avb_error("Signature length does not match key length.\n");
+ goto out;
+ }
+
+ if (padding_num_bytes != sig_num_bytes - hash_num_bytes) {
+ avb_error("Padding length does not match hash and signature lengths.\n");
+ goto out;
+ }
+
+ buf = (uint8_t*)avb_malloc(sig_num_bytes);
+ if (buf == NULL) {
+ avb_error("Error allocating memory.\n");
+ goto out;
+ }
+ avb_memcpy(buf, sig, sig_num_bytes);
+
+ modpowF4(parsed_key, buf);
+
+ /* Check padding bytes.
+ *
+ * Even though there are probably no timing issues here, we use
+ * avb_safe_memcmp() just to be on the safe side.
+ */
+ if (avb_safe_memcmp(buf, padding, padding_num_bytes)) {
+ avb_error("Padding check failed.\n");
+ goto out;
+ }
+
+ /* Check hash. */
+ if (avb_safe_memcmp(buf + padding_num_bytes, hash, hash_num_bytes)) {
+ avb_error("Hash check failed.\n");
+ goto out;
+ }
+
+ success = true;
+
+out:
+ if (parsed_key != NULL) {
+ iavb_free_parsed_key(parsed_key);
+ }
+ if (buf != NULL) {
+ avb_free(buf);
+ }
+ return success;
+}
diff --git a/include/android_avb/avb_rsa.h b/lib/avb/libavb/avb_rsa.h
index e8b0c50e71..c2dcf4715c 100644
--- a/include/android_avb/avb_rsa.h
+++ b/lib/avb/libavb/avb_rsa.h
@@ -1,77 +1,73 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* 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.
- */
-
-/*
-#ifdef AVB_INSIDE_LIBAVB_H
-#error "You can't include avb_rsa.h in the public header libavb.h."
-#endif
-*/
-
-/*
-#ifndef AVB_COMPILATION
-#error "Never include this file, it may only be used from internal avb code."
-#endif
-*/
-
-#ifndef AVB_RSA_H_
-#define AVB_RSA_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <android_avb/avb_crypto.h>
-#include <android_avb/avb_sysdeps.h>
-
-/* Using the key given by |key|, verify a RSA signature |sig| of
- * length |sig_num_bytes| against an expected |hash| of length
- * |hash_num_bytes|. The padding to expect must be passed in using
- * |padding| of length |padding_num_bytes|.
- *
- * The data in |key| must match the format defined in
- * |AvbRSAPublicKeyHeader|, including the two large numbers
- * following. The |key_num_bytes| must be the size of the entire
- * serialized key.
- *
- * Returns false if verification fails, true otherwise.
- */
-bool avb_rsa_verify(const uint8_t* key,
- size_t key_num_bytes,
- const uint8_t* sig,
- size_t sig_num_bytes,
- const uint8_t* hash,
- size_t hash_num_bytes,
- const uint8_t* padding,
- size_t padding_num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_RSA_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* 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.
+ */
+
+#ifdef AVB_INSIDE_LIBAVB_H
+#error "You can't include avb_rsa.h in the public header libavb.h."
+#endif
+
+#ifndef AVB_COMPILATION
+#error "Never include this file, it may only be used from internal avb code."
+#endif
+
+#ifndef AVB_RSA_H_
+#define AVB_RSA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avb_crypto.h"
+#include "avb_sysdeps.h"
+
+/* Using the key given by |key|, verify a RSA signature |sig| of
+ * length |sig_num_bytes| against an expected |hash| of length
+ * |hash_num_bytes|. The padding to expect must be passed in using
+ * |padding| of length |padding_num_bytes|.
+ *
+ * The data in |key| must match the format defined in
+ * |AvbRSAPublicKeyHeader|, including the two large numbers
+ * following. The |key_num_bytes| must be the size of the entire
+ * serialized key.
+ *
+ * Returns false if verification fails, true otherwise.
+ */
+bool avb_rsa_verify(const uint8_t* key,
+ size_t key_num_bytes,
+ const uint8_t* sig,
+ size_t sig_num_bytes,
+ const uint8_t* hash,
+ size_t hash_num_bytes,
+ const uint8_t* padding,
+ size_t padding_num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_RSA_H_ */
diff --git a/include/android_avb/avb_sha.h b/lib/avb/libavb/avb_sha.h
index c4b7c7705e..c5a6a4c706 100644
--- a/include/android_avb/avb_sha.h
+++ b/lib/avb/libavb/avb_sha.h
@@ -1,92 +1,90 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#ifdef AVB_INSIDE_LIBAVB_H
-#error "You can't include avb_sha.h in the public header libavb.h."
-#endif
-
-#ifndef AVB_COMPILATION
-#error "Never include this file, it may only be used from internal avb code."
-#endif
-*/
-
-#ifndef AVB_SHA_H_
-#define AVB_SHA_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <android_avb/avb_crypto.h>
-#include <android_avb/avb_sysdeps.h>
-
-/* Block size in bytes of a SHA-256 digest. */
-#define AVB_SHA256_BLOCK_SIZE 64
-
-
-/* Block size in bytes of a SHA-512 digest. */
-#define AVB_SHA512_BLOCK_SIZE 128
-
-/* Data structure used for SHA-256. */
-typedef struct {
- uint32_t h[8];
- uint32_t tot_len;
- uint32_t len;
- uint8_t block[2 * AVB_SHA256_BLOCK_SIZE];
- uint8_t buf[AVB_SHA256_DIGEST_SIZE]; /* Used for storing the final digest. */
-} AvbSHA256Ctx;
-
-/* Data structure used for SHA-512. */
-typedef struct {
- uint64_t h[8];
- uint32_t tot_len;
- uint32_t len;
- uint8_t block[2 * AVB_SHA512_BLOCK_SIZE];
- uint8_t buf[AVB_SHA512_DIGEST_SIZE]; /* Used for storing the final digest. */
-} AvbSHA512Ctx;
-
-/* Initializes the SHA-256 context. */
-void avb_sha256_init(AvbSHA256Ctx* ctx);
-
-/* Updates the SHA-256 context with |len| bytes from |data|. */
-void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len);
-
-/* Returns the SHA-256 digest. */
-uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Initializes the SHA-512 context. */
-void avb_sha512_init(AvbSHA512Ctx* ctx);
-
-/* Updates the SHA-512 context with |len| bytes from |data|. */
-void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, uint32_t len);
-
-/* Returns the SHA-512 digest. */
-uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_SHA_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef AVB_INSIDE_LIBAVB_H
+#error "You can't include avb_sha.h in the public header libavb.h."
+#endif
+
+#ifndef AVB_COMPILATION
+#error "Never include this file, it may only be used from internal avb code."
+#endif
+
+#ifndef AVB_SHA_H_
+#define AVB_SHA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avb_crypto.h"
+#include "avb_sysdeps.h"
+
+/* Block size in bytes of a SHA-256 digest. */
+#define AVB_SHA256_BLOCK_SIZE 64
+
+
+/* Block size in bytes of a SHA-512 digest. */
+#define AVB_SHA512_BLOCK_SIZE 128
+
+/* Data structure used for SHA-256. */
+typedef struct {
+ uint32_t h[8];
+ uint32_t tot_len;
+ uint32_t len;
+ uint8_t block[2 * AVB_SHA256_BLOCK_SIZE];
+ uint8_t buf[AVB_SHA256_DIGEST_SIZE]; /* Used for storing the final digest. */
+} AvbSHA256Ctx;
+
+/* Data structure used for SHA-512. */
+typedef struct {
+ uint64_t h[8];
+ uint32_t tot_len;
+ uint32_t len;
+ uint8_t block[2 * AVB_SHA512_BLOCK_SIZE];
+ uint8_t buf[AVB_SHA512_DIGEST_SIZE]; /* Used for storing the final digest. */
+} AvbSHA512Ctx;
+
+/* Initializes the SHA-256 context. */
+void avb_sha256_init(AvbSHA256Ctx* ctx);
+
+/* Updates the SHA-256 context with |len| bytes from |data|. */
+void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len);
+
+/* Returns the SHA-256 digest. */
+uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Initializes the SHA-512 context. */
+void avb_sha512_init(AvbSHA512Ctx* ctx);
+
+/* Updates the SHA-512 context with |len| bytes from |data|. */
+void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, uint32_t len);
+
+/* Returns the SHA-512 digest. */
+uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_SHA_H_ */
diff --git a/lib/avb/libavb/avb_sha256.c b/lib/avb/libavb/avb_sha256.c
index b567643f9b..cdd143a93f 100644
--- a/lib/avb/libavb/avb_sha256.c
+++ b/lib/avb/libavb/avb_sha256.c
@@ -1,390 +1,390 @@
-/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
- * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
- */
-
-/*
- * FIPS 180-2 SHA-224/256/384/512 implementation
- * Last update: 02/02/2007
- * Issue date: 04/30/2005
- *
- * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <android_avb/avb_sha.h>
-
-#define SHFR(x, n) (x >> n)
-#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
-#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
-#define CH(x, y, z) ((x & y) ^ (~x & z))
-#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
-
-#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
-#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
-#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
-#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
-
-#define UNPACK32(x, str) \
- { \
- *((str) + 3) = (uint8_t)((x)); \
- *((str) + 2) = (uint8_t)((x) >> 8); \
- *((str) + 1) = (uint8_t)((x) >> 16); \
- *((str) + 0) = (uint8_t)((x) >> 24); \
- }
-
-#define PACK32(str, x) \
- { \
- *(x) = ((uint32_t) * ((str) + 3)) | ((uint32_t) * ((str) + 2) << 8) | \
- ((uint32_t) * ((str) + 1) << 16) | \
- ((uint32_t) * ((str) + 0) << 24); \
- }
-
-/* Macros used for loops unrolling */
-
-#define SHA256_SCR(i) \
- { w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16]; }
-
-#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
- { \
- t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha256_k[j] + \
- w[j]; \
- t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
- wv[d] += t1; \
- wv[h] = t1 + t2; \
- }
-
-static const uint32_t sha256_h0[8] = {0x6a09e667,
- 0xbb67ae85,
- 0x3c6ef372,
- 0xa54ff53a,
- 0x510e527f,
- 0x9b05688c,
- 0x1f83d9ab,
- 0x5be0cd19};
-
-static const uint32_t sha256_k[64] = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
- 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
- 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
- 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
- 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
- 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
-
-/* SHA-256 implementation */
-void avb_sha256_init(AvbSHA256Ctx* ctx) {
-#ifndef UNROLL_LOOPS
- int i;
- for (i = 0; i < 8; i++) {
- ctx->h[i] = sha256_h0[i];
- }
-#else
- ctx->h[0] = sha256_h0[0];
- ctx->h[1] = sha256_h0[1];
- ctx->h[2] = sha256_h0[2];
- ctx->h[3] = sha256_h0[3];
- ctx->h[4] = sha256_h0[4];
- ctx->h[5] = sha256_h0[5];
- ctx->h[6] = sha256_h0[6];
- ctx->h[7] = sha256_h0[7];
-#endif /* !UNROLL_LOOPS */
-
- ctx->len = 0;
- ctx->tot_len = 0;
-}
-
-static void SHA256_transform(AvbSHA256Ctx* ctx,
- const uint8_t* message,
- unsigned int block_nb) {
- uint32_t w[64];
- uint32_t wv[8];
- uint32_t t1, t2;
- const unsigned char* sub_block;
- int i;
-
-#ifndef UNROLL_LOOPS
- int j;
-#endif
-
- for (i = 0; i < (int)block_nb; i++) {
- sub_block = message + (i << 6);
-
-#ifndef UNROLL_LOOPS
- for (j = 0; j < 16; j++) {
- PACK32(&sub_block[j << 2], &w[j]);
- }
-
- for (j = 16; j < 64; j++) {
- SHA256_SCR(j);
- }
-
- for (j = 0; j < 8; j++) {
- wv[j] = ctx->h[j];
- }
-
- for (j = 0; j < 64; j++) {
- t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] +
- w[j];
- t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
- wv[7] = wv[6];
- wv[6] = wv[5];
- wv[5] = wv[4];
- wv[4] = wv[3] + t1;
- wv[3] = wv[2];
- wv[2] = wv[1];
- wv[1] = wv[0];
- wv[0] = t1 + t2;
- }
-
- for (j = 0; j < 8; j++) {
- ctx->h[j] += wv[j];
- }
-#else
- PACK32(&sub_block[0], &w[0]);
- PACK32(&sub_block[4], &w[1]);
- PACK32(&sub_block[8], &w[2]);
- PACK32(&sub_block[12], &w[3]);
- PACK32(&sub_block[16], &w[4]);
- PACK32(&sub_block[20], &w[5]);
- PACK32(&sub_block[24], &w[6]);
- PACK32(&sub_block[28], &w[7]);
- PACK32(&sub_block[32], &w[8]);
- PACK32(&sub_block[36], &w[9]);
- PACK32(&sub_block[40], &w[10]);
- PACK32(&sub_block[44], &w[11]);
- PACK32(&sub_block[48], &w[12]);
- PACK32(&sub_block[52], &w[13]);
- PACK32(&sub_block[56], &w[14]);
- PACK32(&sub_block[60], &w[15]);
-
- SHA256_SCR(16);
- SHA256_SCR(17);
- SHA256_SCR(18);
- SHA256_SCR(19);
- SHA256_SCR(20);
- SHA256_SCR(21);
- SHA256_SCR(22);
- SHA256_SCR(23);
- SHA256_SCR(24);
- SHA256_SCR(25);
- SHA256_SCR(26);
- SHA256_SCR(27);
- SHA256_SCR(28);
- SHA256_SCR(29);
- SHA256_SCR(30);
- SHA256_SCR(31);
- SHA256_SCR(32);
- SHA256_SCR(33);
- SHA256_SCR(34);
- SHA256_SCR(35);
- SHA256_SCR(36);
- SHA256_SCR(37);
- SHA256_SCR(38);
- SHA256_SCR(39);
- SHA256_SCR(40);
- SHA256_SCR(41);
- SHA256_SCR(42);
- SHA256_SCR(43);
- SHA256_SCR(44);
- SHA256_SCR(45);
- SHA256_SCR(46);
- SHA256_SCR(47);
- SHA256_SCR(48);
- SHA256_SCR(49);
- SHA256_SCR(50);
- SHA256_SCR(51);
- SHA256_SCR(52);
- SHA256_SCR(53);
- SHA256_SCR(54);
- SHA256_SCR(55);
- SHA256_SCR(56);
- SHA256_SCR(57);
- SHA256_SCR(58);
- SHA256_SCR(59);
- SHA256_SCR(60);
- SHA256_SCR(61);
- SHA256_SCR(62);
- SHA256_SCR(63);
-
- wv[0] = ctx->h[0];
- wv[1] = ctx->h[1];
- wv[2] = ctx->h[2];
- wv[3] = ctx->h[3];
- wv[4] = ctx->h[4];
- wv[5] = ctx->h[5];
- wv[6] = ctx->h[6];
- wv[7] = ctx->h[7];
-
- SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0);
- SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1);
- SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2);
- SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3);
- SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4);
- SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5);
- SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6);
- SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7);
- SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8);
- SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9);
- SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10);
- SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11);
- SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12);
- SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13);
- SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14);
- SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15);
- SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16);
- SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17);
- SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18);
- SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19);
- SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20);
- SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21);
- SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22);
- SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23);
- SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24);
- SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25);
- SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26);
- SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27);
- SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28);
- SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29);
- SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30);
- SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31);
- SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32);
- SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33);
- SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34);
- SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35);
- SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36);
- SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37);
- SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38);
- SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39);
- SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40);
- SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41);
- SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42);
- SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43);
- SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44);
- SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45);
- SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46);
- SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47);
- SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48);
- SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49);
- SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50);
- SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51);
- SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52);
- SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53);
- SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54);
- SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55);
- SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56);
- SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57);
- SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58);
- SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59);
- SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60);
- SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 61);
- SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 62);
- SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 63);
-
- ctx->h[0] += wv[0];
- ctx->h[1] += wv[1];
- ctx->h[2] += wv[2];
- ctx->h[3] += wv[3];
- ctx->h[4] += wv[4];
- ctx->h[5] += wv[5];
- ctx->h[6] += wv[6];
- ctx->h[7] += wv[7];
-#endif /* !UNROLL_LOOPS */
- }
-}
-
-void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len) {
- unsigned int block_nb;
- unsigned int new_len, rem_len, tmp_len;
- const uint8_t* shifted_data;
-
- tmp_len = AVB_SHA256_BLOCK_SIZE - ctx->len;
- rem_len = len < tmp_len ? len : tmp_len;
-
- avb_memcpy(&ctx->block[ctx->len], data, rem_len);
-
- if (ctx->len + len < AVB_SHA256_BLOCK_SIZE) {
- ctx->len += len;
- return;
- }
-
- new_len = len - rem_len;
- block_nb = new_len / AVB_SHA256_BLOCK_SIZE;
-
- shifted_data = data + rem_len;
-
- SHA256_transform(ctx, ctx->block, 1);
- SHA256_transform(ctx, shifted_data, block_nb);
-
- rem_len = new_len % AVB_SHA256_BLOCK_SIZE;
-
- avb_memcpy(ctx->block, &shifted_data[block_nb << 6], rem_len);
-
- ctx->len = rem_len;
- ctx->tot_len += (block_nb + 1) << 6;
-}
-
-uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) {
- unsigned int block_nb;
- unsigned int pm_len;
- unsigned int len_b;
-#ifndef UNROLL_LOOPS
- int i;
-#endif
-
- block_nb =
- (1 + ((AVB_SHA256_BLOCK_SIZE - 9) < (ctx->len % AVB_SHA256_BLOCK_SIZE)));
-
- len_b = (ctx->tot_len + ctx->len) << 3;
- pm_len = block_nb << 6;
-
- avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
- ctx->block[ctx->len] = 0x80;
- UNPACK32(len_b, ctx->block + pm_len - 4);
-
- SHA256_transform(ctx, ctx->block, block_nb);
-
-#ifndef UNROLL_LOOPS
- for (i = 0; i < 8; i++) {
- UNPACK32(ctx->h[i], &ctx->buf[i << 2]);
- }
-#else
- UNPACK32(ctx->h[0], &ctx->buf[0]);
- UNPACK32(ctx->h[1], &ctx->buf[4]);
- UNPACK32(ctx->h[2], &ctx->buf[8]);
- UNPACK32(ctx->h[3], &ctx->buf[12]);
- UNPACK32(ctx->h[4], &ctx->buf[16]);
- UNPACK32(ctx->h[5], &ctx->buf[20]);
- UNPACK32(ctx->h[6], &ctx->buf[24]);
- UNPACK32(ctx->h[7], &ctx->buf[28]);
-#endif /* !UNROLL_LOOPS */
-
- return ctx->buf;
-}
+/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
+ * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
+ */
+
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "avb_sha.h"
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define UNPACK32(x, str) \
+ { \
+ *((str) + 3) = (uint8_t)((x)); \
+ *((str) + 2) = (uint8_t)((x) >> 8); \
+ *((str) + 1) = (uint8_t)((x) >> 16); \
+ *((str) + 0) = (uint8_t)((x) >> 24); \
+ }
+
+#define PACK32(str, x) \
+ { \
+ *(x) = ((uint32_t) * ((str) + 3)) | ((uint32_t) * ((str) + 2) << 8) | \
+ ((uint32_t) * ((str) + 1) << 16) | \
+ ((uint32_t) * ((str) + 0) << 24); \
+ }
+
+/* Macros used for loops unrolling */
+
+#define SHA256_SCR(i) \
+ { w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16]; }
+
+#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
+ { \
+ t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha256_k[j] + \
+ w[j]; \
+ t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+ }
+
+static const uint32_t sha256_h0[8] = {0x6a09e667,
+ 0xbb67ae85,
+ 0x3c6ef372,
+ 0xa54ff53a,
+ 0x510e527f,
+ 0x9b05688c,
+ 0x1f83d9ab,
+ 0x5be0cd19};
+
+static const uint32_t sha256_k[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
+
+/* SHA-256 implementation */
+void avb_sha256_init(AvbSHA256Ctx* ctx) {
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha256_h0[i];
+ }
+#else
+ ctx->h[0] = sha256_h0[0];
+ ctx->h[1] = sha256_h0[1];
+ ctx->h[2] = sha256_h0[2];
+ ctx->h[3] = sha256_h0[3];
+ ctx->h[4] = sha256_h0[4];
+ ctx->h[5] = sha256_h0[5];
+ ctx->h[6] = sha256_h0[6];
+ ctx->h[7] = sha256_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+static void SHA256_transform(AvbSHA256Ctx* ctx,
+ const uint8_t* message,
+ unsigned int block_nb) {
+ uint32_t w[64];
+ uint32_t wv[8];
+ uint32_t t1, t2;
+ const unsigned char* sub_block;
+ int i;
+
+#ifndef UNROLL_LOOPS
+ int j;
+#endif
+
+ for (i = 0; i < (int)block_nb; i++) {
+ sub_block = message + (i << 6);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ PACK32(&sub_block[j << 2], &w[j]);
+ }
+
+ for (j = 16; j < 64; j++) {
+ SHA256_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 64; j++) {
+ t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] +
+ w[j];
+ t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ PACK32(&sub_block[0], &w[0]);
+ PACK32(&sub_block[4], &w[1]);
+ PACK32(&sub_block[8], &w[2]);
+ PACK32(&sub_block[12], &w[3]);
+ PACK32(&sub_block[16], &w[4]);
+ PACK32(&sub_block[20], &w[5]);
+ PACK32(&sub_block[24], &w[6]);
+ PACK32(&sub_block[28], &w[7]);
+ PACK32(&sub_block[32], &w[8]);
+ PACK32(&sub_block[36], &w[9]);
+ PACK32(&sub_block[40], &w[10]);
+ PACK32(&sub_block[44], &w[11]);
+ PACK32(&sub_block[48], &w[12]);
+ PACK32(&sub_block[52], &w[13]);
+ PACK32(&sub_block[56], &w[14]);
+ PACK32(&sub_block[60], &w[15]);
+
+ SHA256_SCR(16);
+ SHA256_SCR(17);
+ SHA256_SCR(18);
+ SHA256_SCR(19);
+ SHA256_SCR(20);
+ SHA256_SCR(21);
+ SHA256_SCR(22);
+ SHA256_SCR(23);
+ SHA256_SCR(24);
+ SHA256_SCR(25);
+ SHA256_SCR(26);
+ SHA256_SCR(27);
+ SHA256_SCR(28);
+ SHA256_SCR(29);
+ SHA256_SCR(30);
+ SHA256_SCR(31);
+ SHA256_SCR(32);
+ SHA256_SCR(33);
+ SHA256_SCR(34);
+ SHA256_SCR(35);
+ SHA256_SCR(36);
+ SHA256_SCR(37);
+ SHA256_SCR(38);
+ SHA256_SCR(39);
+ SHA256_SCR(40);
+ SHA256_SCR(41);
+ SHA256_SCR(42);
+ SHA256_SCR(43);
+ SHA256_SCR(44);
+ SHA256_SCR(45);
+ SHA256_SCR(46);
+ SHA256_SCR(47);
+ SHA256_SCR(48);
+ SHA256_SCR(49);
+ SHA256_SCR(50);
+ SHA256_SCR(51);
+ SHA256_SCR(52);
+ SHA256_SCR(53);
+ SHA256_SCR(54);
+ SHA256_SCR(55);
+ SHA256_SCR(56);
+ SHA256_SCR(57);
+ SHA256_SCR(58);
+ SHA256_SCR(59);
+ SHA256_SCR(60);
+ SHA256_SCR(61);
+ SHA256_SCR(62);
+ SHA256_SCR(63);
+
+ wv[0] = ctx->h[0];
+ wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2];
+ wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4];
+ wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6];
+ wv[7] = ctx->h[7];
+
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 61);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 62);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 63);
+
+ ctx->h[0] += wv[0];
+ ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2];
+ ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4];
+ ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6];
+ ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len) {
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const uint8_t* shifted_data;
+
+ tmp_len = AVB_SHA256_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ avb_memcpy(&ctx->block[ctx->len], data, rem_len);
+
+ if (ctx->len + len < AVB_SHA256_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / AVB_SHA256_BLOCK_SIZE;
+
+ shifted_data = data + rem_len;
+
+ SHA256_transform(ctx, ctx->block, 1);
+ SHA256_transform(ctx, shifted_data, block_nb);
+
+ rem_len = new_len % AVB_SHA256_BLOCK_SIZE;
+
+ avb_memcpy(ctx->block, &shifted_data[block_nb << 6], rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) {
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb =
+ (1 + ((AVB_SHA256_BLOCK_SIZE - 9) < (ctx->len % AVB_SHA256_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ SHA256_transform(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0; i < 8; i++) {
+ UNPACK32(ctx->h[i], &ctx->buf[i << 2]);
+ }
+#else
+ UNPACK32(ctx->h[0], &ctx->buf[0]);
+ UNPACK32(ctx->h[1], &ctx->buf[4]);
+ UNPACK32(ctx->h[2], &ctx->buf[8]);
+ UNPACK32(ctx->h[3], &ctx->buf[12]);
+ UNPACK32(ctx->h[4], &ctx->buf[16]);
+ UNPACK32(ctx->h[5], &ctx->buf[20]);
+ UNPACK32(ctx->h[6], &ctx->buf[24]);
+ UNPACK32(ctx->h[7], &ctx->buf[28]);
+#endif /* !UNROLL_LOOPS */
+
+ return ctx->buf;
+}
diff --git a/lib/avb/libavb/avb_sha512.c b/lib/avb/libavb/avb_sha512.c
index 020e9c9019..8df63193c9 100644
--- a/lib/avb/libavb/avb_sha512.c
+++ b/lib/avb/libavb/avb_sha512.c
@@ -1,388 +1,388 @@
-/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
- * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
- */
-
-/*
- * FIPS 180-2 SHA-224/256/384/512 implementation
- * Last update: 02/02/2007
- * Issue date: 04/30/2005
- *
- * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <android_avb/avb_sha.h>
-
-#define SHFR(x, n) (x >> n)
-#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
-#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
-#define CH(x, y, z) ((x & y) ^ (~x & z))
-#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
-
-#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
-#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
-#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
-#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
-
-#define UNPACK32(x, str) \
- { \
- *((str) + 3) = (uint8_t)((x)); \
- *((str) + 2) = (uint8_t)((x) >> 8); \
- *((str) + 1) = (uint8_t)((x) >> 16); \
- *((str) + 0) = (uint8_t)((x) >> 24); \
- }
-
-#define UNPACK64(x, str) \
- { \
- *((str) + 7) = (uint8_t)x; \
- *((str) + 6) = (uint8_t)((uint64_t)x >> 8); \
- *((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
- *((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
- *((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
- *((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
- *((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
- *((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
- }
-
-#define PACK64(str, x) \
- { \
- *(x) = \
- ((uint64_t) * ((str) + 7)) | ((uint64_t) * ((str) + 6) << 8) | \
- ((uint64_t) * ((str) + 5) << 16) | ((uint64_t) * ((str) + 4) << 24) | \
- ((uint64_t) * ((str) + 3) << 32) | ((uint64_t) * ((str) + 2) << 40) | \
- ((uint64_t) * ((str) + 1) << 48) | ((uint64_t) * ((str) + 0) << 56); \
- }
-
-/* Macros used for loops unrolling */
-
-#define SHA512_SCR(i) \
- { w[i] = SHA512_F4(w[i - 2]) + w[i - 7] + SHA512_F3(w[i - 15]) + w[i - 16]; }
-
-#define SHA512_EXP(a, b, c, d, e, f, g, h, j) \
- { \
- t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha512_k[j] + \
- w[j]; \
- t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
- wv[d] += t1; \
- wv[h] = t1 + t2; \
- }
-
-static const uint64_t sha512_h0[8] = {0x6a09e667f3bcc908ULL,
- 0xbb67ae8584caa73bULL,
- 0x3c6ef372fe94f82bULL,
- 0xa54ff53a5f1d36f1ULL,
- 0x510e527fade682d1ULL,
- 0x9b05688c2b3e6c1fULL,
- 0x1f83d9abfb41bd6bULL,
- 0x5be0cd19137e2179ULL};
-
-static const uint64_t sha512_k[80] = {
- 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
- 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
- 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
- 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
- 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
- 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
- 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
- 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
- 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
- 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
- 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
- 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
- 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
- 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
- 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
- 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
- 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
- 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
- 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
- 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
- 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
- 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
- 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
- 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
- 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
- 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
- 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
-
-/* SHA-512 implementation */
-
-void avb_sha512_init(AvbSHA512Ctx* ctx) {
-#ifdef UNROLL_LOOPS_SHA512
- ctx->h[0] = sha512_h0[0];
- ctx->h[1] = sha512_h0[1];
- ctx->h[2] = sha512_h0[2];
- ctx->h[3] = sha512_h0[3];
- ctx->h[4] = sha512_h0[4];
- ctx->h[5] = sha512_h0[5];
- ctx->h[6] = sha512_h0[6];
- ctx->h[7] = sha512_h0[7];
-#else
- int i;
-
- for (i = 0; i < 8; i++)
- ctx->h[i] = sha512_h0[i];
-#endif /* UNROLL_LOOPS_SHA512 */
-
- ctx->len = 0;
- ctx->tot_len = 0;
-}
-
-static void SHA512_transform(AvbSHA512Ctx* ctx,
- const uint8_t* message,
- unsigned int block_nb) {
- uint64_t w[80];
- uint64_t wv[8];
- uint64_t t1, t2;
- const uint8_t* sub_block;
- int i, j;
-
- for (i = 0; i < (int)block_nb; i++) {
- sub_block = message + (i << 7);
-
-#ifdef UNROLL_LOOPS_SHA512
- PACK64(&sub_block[0], &w[0]);
- PACK64(&sub_block[8], &w[1]);
- PACK64(&sub_block[16], &w[2]);
- PACK64(&sub_block[24], &w[3]);
- PACK64(&sub_block[32], &w[4]);
- PACK64(&sub_block[40], &w[5]);
- PACK64(&sub_block[48], &w[6]);
- PACK64(&sub_block[56], &w[7]);
- PACK64(&sub_block[64], &w[8]);
- PACK64(&sub_block[72], &w[9]);
- PACK64(&sub_block[80], &w[10]);
- PACK64(&sub_block[88], &w[11]);
- PACK64(&sub_block[96], &w[12]);
- PACK64(&sub_block[104], &w[13]);
- PACK64(&sub_block[112], &w[14]);
- PACK64(&sub_block[120], &w[15]);
-
- SHA512_SCR(16);
- SHA512_SCR(17);
- SHA512_SCR(18);
- SHA512_SCR(19);
- SHA512_SCR(20);
- SHA512_SCR(21);
- SHA512_SCR(22);
- SHA512_SCR(23);
- SHA512_SCR(24);
- SHA512_SCR(25);
- SHA512_SCR(26);
- SHA512_SCR(27);
- SHA512_SCR(28);
- SHA512_SCR(29);
- SHA512_SCR(30);
- SHA512_SCR(31);
- SHA512_SCR(32);
- SHA512_SCR(33);
- SHA512_SCR(34);
- SHA512_SCR(35);
- SHA512_SCR(36);
- SHA512_SCR(37);
- SHA512_SCR(38);
- SHA512_SCR(39);
- SHA512_SCR(40);
- SHA512_SCR(41);
- SHA512_SCR(42);
- SHA512_SCR(43);
- SHA512_SCR(44);
- SHA512_SCR(45);
- SHA512_SCR(46);
- SHA512_SCR(47);
- SHA512_SCR(48);
- SHA512_SCR(49);
- SHA512_SCR(50);
- SHA512_SCR(51);
- SHA512_SCR(52);
- SHA512_SCR(53);
- SHA512_SCR(54);
- SHA512_SCR(55);
- SHA512_SCR(56);
- SHA512_SCR(57);
- SHA512_SCR(58);
- SHA512_SCR(59);
- SHA512_SCR(60);
- SHA512_SCR(61);
- SHA512_SCR(62);
- SHA512_SCR(63);
- SHA512_SCR(64);
- SHA512_SCR(65);
- SHA512_SCR(66);
- SHA512_SCR(67);
- SHA512_SCR(68);
- SHA512_SCR(69);
- SHA512_SCR(70);
- SHA512_SCR(71);
- SHA512_SCR(72);
- SHA512_SCR(73);
- SHA512_SCR(74);
- SHA512_SCR(75);
- SHA512_SCR(76);
- SHA512_SCR(77);
- SHA512_SCR(78);
- SHA512_SCR(79);
-
- wv[0] = ctx->h[0];
- wv[1] = ctx->h[1];
- wv[2] = ctx->h[2];
- wv[3] = ctx->h[3];
- wv[4] = ctx->h[4];
- wv[5] = ctx->h[5];
- wv[6] = ctx->h[6];
- wv[7] = ctx->h[7];
-
- j = 0;
-
- do {
- SHA512_EXP(0, 1, 2, 3, 4, 5, 6, 7, j);
- j++;
- SHA512_EXP(7, 0, 1, 2, 3, 4, 5, 6, j);
- j++;
- SHA512_EXP(6, 7, 0, 1, 2, 3, 4, 5, j);
- j++;
- SHA512_EXP(5, 6, 7, 0, 1, 2, 3, 4, j);
- j++;
- SHA512_EXP(4, 5, 6, 7, 0, 1, 2, 3, j);
- j++;
- SHA512_EXP(3, 4, 5, 6, 7, 0, 1, 2, j);
- j++;
- SHA512_EXP(2, 3, 4, 5, 6, 7, 0, 1, j);
- j++;
- SHA512_EXP(1, 2, 3, 4, 5, 6, 7, 0, j);
- j++;
- } while (j < 80);
-
- ctx->h[0] += wv[0];
- ctx->h[1] += wv[1];
- ctx->h[2] += wv[2];
- ctx->h[3] += wv[3];
- ctx->h[4] += wv[4];
- ctx->h[5] += wv[5];
- ctx->h[6] += wv[6];
- ctx->h[7] += wv[7];
-#else
- for (j = 0; j < 16; j++) {
- PACK64(&sub_block[j << 3], &w[j]);
- }
-
- for (j = 16; j < 80; j++) {
- SHA512_SCR(j);
- }
-
- for (j = 0; j < 8; j++) {
- wv[j] = ctx->h[j];
- }
-
- for (j = 0; j < 80; j++) {
- t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha512_k[j] +
- w[j];
- t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
- wv[7] = wv[6];
- wv[6] = wv[5];
- wv[5] = wv[4];
- wv[4] = wv[3] + t1;
- wv[3] = wv[2];
- wv[2] = wv[1];
- wv[1] = wv[0];
- wv[0] = t1 + t2;
- }
-
- for (j = 0; j < 8; j++)
- ctx->h[j] += wv[j];
-#endif /* UNROLL_LOOPS_SHA512 */
- }
-}
-
-void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, uint32_t len) {
- unsigned int block_nb;
- unsigned int new_len, rem_len, tmp_len;
- const uint8_t* shifted_data;
-
- tmp_len = AVB_SHA512_BLOCK_SIZE - ctx->len;
- rem_len = len < tmp_len ? len : tmp_len;
-
- avb_memcpy(&ctx->block[ctx->len], data, rem_len);
-
- if (ctx->len + len < AVB_SHA512_BLOCK_SIZE) {
- ctx->len += len;
- return;
- }
-
- new_len = len - rem_len;
- block_nb = new_len / AVB_SHA512_BLOCK_SIZE;
-
- shifted_data = data + rem_len;
-
- SHA512_transform(ctx, ctx->block, 1);
- SHA512_transform(ctx, shifted_data, block_nb);
-
- rem_len = new_len % AVB_SHA512_BLOCK_SIZE;
-
- avb_memcpy(ctx->block, &shifted_data[block_nb << 7], rem_len);
-
- ctx->len = rem_len;
- ctx->tot_len += (block_nb + 1) << 7;
-}
-
-uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) {
- unsigned int block_nb;
- unsigned int pm_len;
- unsigned int len_b;
-
-#ifndef UNROLL_LOOPS_SHA512
- int i;
-#endif
-
- block_nb =
- 1 + ((AVB_SHA512_BLOCK_SIZE - 17) < (ctx->len % AVB_SHA512_BLOCK_SIZE));
-
- len_b = (ctx->tot_len + ctx->len) << 3;
- pm_len = block_nb << 7;
-
- avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
- ctx->block[ctx->len] = 0x80;
- UNPACK32(len_b, ctx->block + pm_len - 4);
-
- SHA512_transform(ctx, ctx->block, block_nb);
-
-#ifdef UNROLL_LOOPS_SHA512
- UNPACK64(ctx->h[0], &ctx->buf[0]);
- UNPACK64(ctx->h[1], &ctx->buf[8]);
- UNPACK64(ctx->h[2], &ctx->buf[16]);
- UNPACK64(ctx->h[3], &ctx->buf[24]);
- UNPACK64(ctx->h[4], &ctx->buf[32]);
- UNPACK64(ctx->h[5], &ctx->buf[40]);
- UNPACK64(ctx->h[6], &ctx->buf[48]);
- UNPACK64(ctx->h[7], &ctx->buf[56]);
-#else
- for (i = 0; i < 8; i++)
- UNPACK64(ctx->h[i], &ctx->buf[i << 3]);
-#endif /* UNROLL_LOOPS_SHA512 */
-
- return ctx->buf;
-}
+/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
+ * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
+ */
+
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "avb_sha.h"
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
+#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
+
+#define UNPACK32(x, str) \
+ { \
+ *((str) + 3) = (uint8_t)((x)); \
+ *((str) + 2) = (uint8_t)((x) >> 8); \
+ *((str) + 1) = (uint8_t)((x) >> 16); \
+ *((str) + 0) = (uint8_t)((x) >> 24); \
+ }
+
+#define UNPACK64(x, str) \
+ { \
+ *((str) + 7) = (uint8_t)x; \
+ *((str) + 6) = (uint8_t)((uint64_t)x >> 8); \
+ *((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
+ *((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
+ *((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
+ *((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
+ *((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
+ *((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
+ }
+
+#define PACK64(str, x) \
+ { \
+ *(x) = \
+ ((uint64_t) * ((str) + 7)) | ((uint64_t) * ((str) + 6) << 8) | \
+ ((uint64_t) * ((str) + 5) << 16) | ((uint64_t) * ((str) + 4) << 24) | \
+ ((uint64_t) * ((str) + 3) << 32) | ((uint64_t) * ((str) + 2) << 40) | \
+ ((uint64_t) * ((str) + 1) << 48) | ((uint64_t) * ((str) + 0) << 56); \
+ }
+
+/* Macros used for loops unrolling */
+
+#define SHA512_SCR(i) \
+ { w[i] = SHA512_F4(w[i - 2]) + w[i - 7] + SHA512_F3(w[i - 15]) + w[i - 16]; }
+
+#define SHA512_EXP(a, b, c, d, e, f, g, h, j) \
+ { \
+ t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha512_k[j] + \
+ w[j]; \
+ t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+ }
+
+static const uint64_t sha512_h0[8] = {0x6a09e667f3bcc908ULL,
+ 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL,
+ 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL,
+ 0x5be0cd19137e2179ULL};
+
+static const uint64_t sha512_k[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+ 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+ 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+ 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+ 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+ 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+ 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+ 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+ 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+ 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+ 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+ 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+ 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+ 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
+
+/* SHA-512 implementation */
+
+void avb_sha512_init(AvbSHA512Ctx* ctx) {
+#ifdef UNROLL_LOOPS_SHA512
+ ctx->h[0] = sha512_h0[0];
+ ctx->h[1] = sha512_h0[1];
+ ctx->h[2] = sha512_h0[2];
+ ctx->h[3] = sha512_h0[3];
+ ctx->h[4] = sha512_h0[4];
+ ctx->h[5] = sha512_h0[5];
+ ctx->h[6] = sha512_h0[6];
+ ctx->h[7] = sha512_h0[7];
+#else
+ int i;
+
+ for (i = 0; i < 8; i++)
+ ctx->h[i] = sha512_h0[i];
+#endif /* UNROLL_LOOPS_SHA512 */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+static void SHA512_transform(AvbSHA512Ctx* ctx,
+ const uint8_t* message,
+ unsigned int block_nb) {
+ uint64_t w[80];
+ uint64_t wv[8];
+ uint64_t t1, t2;
+ const uint8_t* sub_block;
+ int i, j;
+
+ for (i = 0; i < (int)block_nb; i++) {
+ sub_block = message + (i << 7);
+
+#ifdef UNROLL_LOOPS_SHA512
+ PACK64(&sub_block[0], &w[0]);
+ PACK64(&sub_block[8], &w[1]);
+ PACK64(&sub_block[16], &w[2]);
+ PACK64(&sub_block[24], &w[3]);
+ PACK64(&sub_block[32], &w[4]);
+ PACK64(&sub_block[40], &w[5]);
+ PACK64(&sub_block[48], &w[6]);
+ PACK64(&sub_block[56], &w[7]);
+ PACK64(&sub_block[64], &w[8]);
+ PACK64(&sub_block[72], &w[9]);
+ PACK64(&sub_block[80], &w[10]);
+ PACK64(&sub_block[88], &w[11]);
+ PACK64(&sub_block[96], &w[12]);
+ PACK64(&sub_block[104], &w[13]);
+ PACK64(&sub_block[112], &w[14]);
+ PACK64(&sub_block[120], &w[15]);
+
+ SHA512_SCR(16);
+ SHA512_SCR(17);
+ SHA512_SCR(18);
+ SHA512_SCR(19);
+ SHA512_SCR(20);
+ SHA512_SCR(21);
+ SHA512_SCR(22);
+ SHA512_SCR(23);
+ SHA512_SCR(24);
+ SHA512_SCR(25);
+ SHA512_SCR(26);
+ SHA512_SCR(27);
+ SHA512_SCR(28);
+ SHA512_SCR(29);
+ SHA512_SCR(30);
+ SHA512_SCR(31);
+ SHA512_SCR(32);
+ SHA512_SCR(33);
+ SHA512_SCR(34);
+ SHA512_SCR(35);
+ SHA512_SCR(36);
+ SHA512_SCR(37);
+ SHA512_SCR(38);
+ SHA512_SCR(39);
+ SHA512_SCR(40);
+ SHA512_SCR(41);
+ SHA512_SCR(42);
+ SHA512_SCR(43);
+ SHA512_SCR(44);
+ SHA512_SCR(45);
+ SHA512_SCR(46);
+ SHA512_SCR(47);
+ SHA512_SCR(48);
+ SHA512_SCR(49);
+ SHA512_SCR(50);
+ SHA512_SCR(51);
+ SHA512_SCR(52);
+ SHA512_SCR(53);
+ SHA512_SCR(54);
+ SHA512_SCR(55);
+ SHA512_SCR(56);
+ SHA512_SCR(57);
+ SHA512_SCR(58);
+ SHA512_SCR(59);
+ SHA512_SCR(60);
+ SHA512_SCR(61);
+ SHA512_SCR(62);
+ SHA512_SCR(63);
+ SHA512_SCR(64);
+ SHA512_SCR(65);
+ SHA512_SCR(66);
+ SHA512_SCR(67);
+ SHA512_SCR(68);
+ SHA512_SCR(69);
+ SHA512_SCR(70);
+ SHA512_SCR(71);
+ SHA512_SCR(72);
+ SHA512_SCR(73);
+ SHA512_SCR(74);
+ SHA512_SCR(75);
+ SHA512_SCR(76);
+ SHA512_SCR(77);
+ SHA512_SCR(78);
+ SHA512_SCR(79);
+
+ wv[0] = ctx->h[0];
+ wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2];
+ wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4];
+ wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6];
+ wv[7] = ctx->h[7];
+
+ j = 0;
+
+ do {
+ SHA512_EXP(0, 1, 2, 3, 4, 5, 6, 7, j);
+ j++;
+ SHA512_EXP(7, 0, 1, 2, 3, 4, 5, 6, j);
+ j++;
+ SHA512_EXP(6, 7, 0, 1, 2, 3, 4, 5, j);
+ j++;
+ SHA512_EXP(5, 6, 7, 0, 1, 2, 3, 4, j);
+ j++;
+ SHA512_EXP(4, 5, 6, 7, 0, 1, 2, 3, j);
+ j++;
+ SHA512_EXP(3, 4, 5, 6, 7, 0, 1, 2, j);
+ j++;
+ SHA512_EXP(2, 3, 4, 5, 6, 7, 0, 1, j);
+ j++;
+ SHA512_EXP(1, 2, 3, 4, 5, 6, 7, 0, j);
+ j++;
+ } while (j < 80);
+
+ ctx->h[0] += wv[0];
+ ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2];
+ ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4];
+ ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6];
+ ctx->h[7] += wv[7];
+#else
+ for (j = 0; j < 16; j++) {
+ PACK64(&sub_block[j << 3], &w[j]);
+ }
+
+ for (j = 16; j < 80; j++) {
+ SHA512_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 80; j++) {
+ t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha512_k[j] +
+ w[j];
+ t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++)
+ ctx->h[j] += wv[j];
+#endif /* UNROLL_LOOPS_SHA512 */
+ }
+}
+
+void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, uint32_t len) {
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const uint8_t* shifted_data;
+
+ tmp_len = AVB_SHA512_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ avb_memcpy(&ctx->block[ctx->len], data, rem_len);
+
+ if (ctx->len + len < AVB_SHA512_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / AVB_SHA512_BLOCK_SIZE;
+
+ shifted_data = data + rem_len;
+
+ SHA512_transform(ctx, ctx->block, 1);
+ SHA512_transform(ctx, shifted_data, block_nb);
+
+ rem_len = new_len % AVB_SHA512_BLOCK_SIZE;
+
+ avb_memcpy(ctx->block, &shifted_data[block_nb << 7], rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) {
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS_SHA512
+ int i;
+#endif
+
+ block_nb =
+ 1 + ((AVB_SHA512_BLOCK_SIZE - 17) < (ctx->len % AVB_SHA512_BLOCK_SIZE));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ SHA512_transform(ctx, ctx->block, block_nb);
+
+#ifdef UNROLL_LOOPS_SHA512
+ UNPACK64(ctx->h[0], &ctx->buf[0]);
+ UNPACK64(ctx->h[1], &ctx->buf[8]);
+ UNPACK64(ctx->h[2], &ctx->buf[16]);
+ UNPACK64(ctx->h[3], &ctx->buf[24]);
+ UNPACK64(ctx->h[4], &ctx->buf[32]);
+ UNPACK64(ctx->h[5], &ctx->buf[40]);
+ UNPACK64(ctx->h[6], &ctx->buf[48]);
+ UNPACK64(ctx->h[7], &ctx->buf[56]);
+#else
+ for (i = 0; i < 8; i++)
+ UNPACK64(ctx->h[i], &ctx->buf[i << 3]);
+#endif /* UNROLL_LOOPS_SHA512 */
+
+ return ctx->buf;
+}
diff --git a/lib/avb/libavb/avb_slot_verify.c b/lib/avb/libavb/avb_slot_verify.c
index 972fda0e9c..64e2666643 100644
--- a/lib/avb/libavb/avb_slot_verify.c
+++ b/lib/avb/libavb/avb_slot_verify.c
@@ -1,1155 +1,1385 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_slot_verify.h>
-#include <android_avb/avb_chain_partition_descriptor.h>
-#include <android_avb/avb_cmdline.h>
-#include <android_avb/avb_footer.h>
-#include <android_avb/avb_hash_descriptor.h>
-#include <android_avb/avb_kernel_cmdline_descriptor.h>
-#include <android_avb/avb_sha.h>
-#include <android_avb/avb_util.h>
-#include <android_avb/avb_vbmeta_image.h>
-#include <android_avb/avb_version.h>
-
-/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
-#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
-
-/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
-#define MAX_NUMBER_OF_VBMETA_IMAGES 32
-
-/* Maximum size of a vbmeta image - 64 KiB. */
-#define VBMETA_MAX_SIZE (64 * 1024)
-
-/* Helper function to see if we should continue with verification in
- * allow_verification_error=true mode if something goes wrong. See the
- * comments for the avb_slot_verify() function for more information.
- */
-static inline bool result_should_continue(AvbSlotVerifyResult result) {
- switch (result) {
- case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
- case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
- case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
- case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
- case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
- return false;
-
- case AVB_SLOT_VERIFY_RESULT_OK:
- case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
- case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
- case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
- return true;
- }
-
- return false;
-}
-
-static AvbSlotVerifyResult load_full_partition(
- AvbOps* ops, const char* part_name,
- uint64_t image_size, uint8_t** out_image_buf,
- bool* out_image_preloaded) {
- size_t part_num_read;
- AvbIOResult io_ret;
-
- /* Make sure that we do not overwrite existing data. */
- avb_assert(*out_image_buf == NULL);
- avb_assert(!*out_image_preloaded);
-
- /* 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);
- return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- }
-
- /* Try use a preloaded one. */
- if (ops->get_preloaded_partition != NULL) {
- io_ret = ops->get_preloaded_partition(
- ops, part_name, image_size, out_image_buf, &part_num_read);
- 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);
- return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- }
-
- if (*out_image_buf != NULL) {
- if (part_num_read != image_size) {
- avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
- return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- }
- *out_image_preloaded = true;
- }
- }
-
- /* Allocate and copy the partition. */
- if (!*out_image_preloaded) {
- *out_image_buf = avb_malloc(image_size);
- if (*out_image_buf == NULL) {
- return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- }
-
- io_ret = ops->read_from_partition(
- ops, part_name, 0 /* offset */, image_size, *out_image_buf,
- &part_num_read);
- 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);
- return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- }
- if (part_num_read != image_size) {
- avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
- return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- }
- }
-
- return AVB_SLOT_VERIFY_RESULT_OK;
-}
-
-static AvbSlotVerifyResult load_and_verify_hash_partition(
- AvbOps* ops,
- const char* const* requested_partitions,
- const char* ab_suffix,
- bool allow_verification_error,
- const AvbDescriptor* descriptor,
- AvbSlotVerifyData* slot_data) {
- AvbHashDescriptor hash_desc;
- const uint8_t* desc_partition_name = NULL;
- const uint8_t* desc_salt;
- const uint8_t* desc_digest;
- char part_name[AVB_PART_NAME_MAX_SIZE];
- AvbSlotVerifyResult ret;
- AvbIOResult io_ret;
- uint8_t* image_buf = NULL;
- bool image_preloaded = false;
- uint8_t* digest;
- size_t digest_len;
- const char* found;
- uint64_t image_size = 0;
-
- if (!avb_hash_descriptor_validate_and_byteswap(
- (const AvbHashDescriptor*)descriptor, &hash_desc)) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- desc_partition_name =
- ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
- desc_salt = desc_partition_name + hash_desc.partition_name_len;
- desc_digest = desc_salt + hash_desc.salt_len;
-
- if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
- avb_error("Partition name is not valid UTF-8.\n");
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- /* Don't bother loading or validating unless the partition was
- * requested in the first place.
- */
- found = avb_strv_find_str(requested_partitions,
- (const char*)desc_partition_name,
- hash_desc.partition_name_len);
- if (found == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_OK;
- goto out;
- }
-
- if (!avb_str_concat(part_name,
- sizeof part_name,
- (const char*)desc_partition_name,
- hash_desc.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;
- }
-
- /* If we're allowing verification errors then hash_desc.image_size
- * may no longer match what's in the partition... so in this case
- * just load the entire partition.
- *
- * For example, this can happen if a developer does 'fastboot flash
- * boot /path/to/new/and/bigger/boot.img'. We want this to work
- * since it's such a common workflow.
- */
- image_size = hash_desc.image_size;
- if (0) {
- if (ops->get_size_of_partition == NULL) {
- avb_errorv(part_name,
- ": The get_size_of_partition() operation is "
- "not implemented so we may not load the entire partition. "
- "Please implement.",
- NULL);
- } else {
- io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- goto out;
- }
- avb_debugv(part_name, ": Loading entire partition.\n", NULL);
- }
- }
-
- ret = load_full_partition(
- ops, part_name, image_size, &image_buf, &image_preloaded);
- if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
- goto out;
- }
-
- if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
- AvbSHA256Ctx sha256_ctx;
- avb_sha256_init(&sha256_ctx);
- avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
- avb_sha256_update(&sha256_ctx, image_buf, hash_desc.image_size);
- digest = avb_sha256_final(&sha256_ctx);
- digest_len = AVB_SHA256_DIGEST_SIZE;
- } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
- AvbSHA512Ctx sha512_ctx;
- avb_sha512_init(&sha512_ctx);
- avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
- avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
- digest = avb_sha512_final(&sha512_ctx);
- digest_len = AVB_SHA512_DIGEST_SIZE;
- } else {
- avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- if (digest_len != hash_desc.digest_len) {
- avb_errorv(
- part_name, ": Digest in descriptor not of expected size.\n", NULL);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- if (avb_safe_memcmp(digest, desc_digest, digest_len) != 0) {
- avb_errorv(part_name,
- ": Hash of data does not match digest in descriptor.\n",
- NULL);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
- goto out;
- }
-
- ret = AVB_SLOT_VERIFY_RESULT_OK;
-
-out:
-
- /* If it worked and something was loaded, copy to slot_data. */
- if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto fail;
- }
- loaded_partition =
- &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
- loaded_partition->partition_name = avb_strdup(found);
- loaded_partition->data_size = image_size;
- loaded_partition->data = image_buf;
- loaded_partition->preloaded = image_preloaded;
- image_buf = NULL;
- }
-
-fail:
- if (image_buf != NULL && !image_preloaded) {
- avb_free(image_buf);
- }
- return ret;
-}
-
-static AvbSlotVerifyResult load_requested_partitions(
- AvbOps* ops,
- const char* const* requested_partitions,
- const char* ab_suffix,
- AvbSlotVerifyData* slot_data) {
- AvbSlotVerifyResult ret;
- uint8_t* image_buf = NULL;
- bool image_preloaded = false;
- size_t n;
-
- if (ops->get_size_of_partition == NULL) {
- avb_error("get_size_of_partition() not implemented.\n");
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
- goto out;
- }
-
- for (n = 0; requested_partitions[n] != NULL; n++) {
- char part_name[AVB_PART_NAME_MAX_SIZE];
- AvbIOResult io_ret;
- uint64_t image_size;
- AvbPartitionData* loaded_partition;
-
- if (!avb_str_concat(part_name,
- sizeof part_name,
- requested_partitions[n],
- avb_strlen(requested_partitions[n]),
- 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;
- }
-
- io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- goto out;
- }
- avb_debugv(part_name, ": Loading entire partition.\n", NULL);
-
- ret = load_full_partition(
- ops, part_name, image_size, &image_buf, &image_preloaded);
- if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
- goto out;
- }
-
- /* 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
- loaded_partition =
- &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
- loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
- if (loaded_partition->partition_name == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
- loaded_partition->data_size = image_size;
- loaded_partition->data = image_buf; /* Transferring the owner. */
- loaded_partition->preloaded = image_preloaded;
- image_buf = NULL;
- image_preloaded = false;
- }
-
- ret = AVB_SLOT_VERIFY_RESULT_OK;
-
-out:
- /* Free the current buffer if any. */
- if (image_buf != NULL && !image_preloaded) {
- avb_free(image_buf);
- }
- /* Buffers that are already saved in slot_data will be handled by the caller
- * even on failure. */
- return ret;
-}
-
-static AvbSlotVerifyResult load_and_verify_vbmeta(
- AvbOps* ops,
- const char* const* requested_partitions,
- const char* ab_suffix,
- bool allow_verification_error,
- AvbVBMetaImageFlags toplevel_vbmeta_flags,
- int 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) {
- char full_partition_name[AVB_PART_NAME_MAX_SIZE];
- AvbSlotVerifyResult ret;
- AvbIOResult io_ret;
- size_t vbmeta_offset;
- size_t vbmeta_size;
- uint8_t* vbmeta_buf = NULL;
- size_t vbmeta_num_read;
- AvbVBMetaVerifyResult vbmeta_ret;
- const uint8_t* pk_data;
- size_t pk_len;
- AvbVBMetaImageHeader vbmeta_header;
- uint64_t stored_rollback_index;
- const AvbDescriptor** descriptors = NULL;
- size_t num_descriptors;
- size_t n;
- bool is_main_vbmeta;
- bool is_vbmeta_partition;
- AvbVBMetaData* vbmeta_image_data = NULL;
-
- ret = AVB_SLOT_VERIFY_RESULT_OK;
-
- avb_assert(slot_data != NULL);
-
- /* Since we allow top-level vbmeta in 'boot', use
- * rollback_index_location to determine whether we're the main
- * vbmeta struct.
- */
- is_main_vbmeta = (rollback_index_location == 0);
- is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
-
- if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
- avb_error("Partition name is not valid UTF-8.\n");
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- /* Construct full partition name. */
- 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_debugv("Loading vbmeta struct from partition '",
- full_partition_name,
- "'.\n",
- NULL);
-
- /* If we're loading from the main vbmeta partition, the vbmeta
- * struct is in the beginning. Otherwise we have to locate it via a
- * footer.
- */
- if (is_vbmeta_partition) {
- vbmeta_offset = 0;
- vbmeta_size = VBMETA_MAX_SIZE;
- } else {
- uint8_t footer_buf[AVB_FOOTER_SIZE];
- size_t footer_num_read;
- AvbFooter footer;
-
- io_ret = ops->read_from_partition(ops,
- full_partition_name,
- -AVB_FOOTER_SIZE,
- AVB_FOOTER_SIZE,
- footer_buf,
- &footer_num_read);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- goto out;
- }
- avb_assert(footer_num_read == AVB_FOOTER_SIZE);
-
- if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
- &footer)) {
- avb_errorv(full_partition_name, ": Error validating footer.\n", NULL);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- /* 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- vbmeta_offset = footer.vbmeta_offset;
- vbmeta_size = footer.vbmeta_size;
- }
-
- vbmeta_buf = avb_malloc(vbmeta_size);
- if (vbmeta_buf == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
-
- 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;
- } else if (io_ret != AVB_IO_RESULT_OK) {
- /* If we're looking for 'vbmeta' but there is no such partition,
- * go try to get it from the boot partition instead.
- */
- if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
- is_vbmeta_partition) {
- avb_debugv(full_partition_name,
- ": No such partition. Trying 'boot' instead.\n",
- NULL);
- ret = load_and_verify_vbmeta(ops,
- requested_partitions,
- ab_suffix,
- allow_verification_error,
- 0 /* toplevel_vbmeta_flags */,
- 0 /* rollback_index_location */,
- "boot",
- avb_strlen("boot"),
- NULL /* expected_public_key */,
- 0 /* expected_public_key_length */,
- slot_data,
- out_algorithm_type);
- goto out;
- } else {
- avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- goto out;
- }
- }
- avb_assert(vbmeta_num_read <= vbmeta_size);
-
- /* Check if the image is properly signed and get the public key used
- * to sign the image.
- */
- vbmeta_ret =
- avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
- switch (vbmeta_ret) {
- case AVB_VBMETA_VERIFY_RESULT_OK:
- avb_assert(pk_data != NULL && pk_len > 0);
- break;
-
- case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
- 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);
- if (!allow_verification_error) {
- goto out;
- }
- break;
-
- 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);
- 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);
- goto out;
- }
-
- /* Byteswap the header. */
- avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
- &vbmeta_header);
-
- /* If we're the toplevel, assign flags so they'll be passed down. */
- if (is_main_vbmeta) {
- toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
- } 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);
- goto out;
- }
- }
-
- /* Check if key used to make signature matches what is expected. */
- if (pk_data != NULL) {
- if (expected_public_key != 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
- if (!allow_verification_error) {
- goto out;
- }
- }
- } else {
- bool key_is_trusted = false;
- const uint8_t* pk_metadata = NULL;
- size_t pk_metadata_len = 0;
-
- if (vbmeta_header.public_key_metadata_size > 0) {
- pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
- vbmeta_header.authentication_data_block_size +
- vbmeta_header.public_key_metadata_offset;
- 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 (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- 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);
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
- if (!allow_verification_error) {
- goto out;
- }
- }
- }
- }
-
- /* Check rollback index. */
- io_ret = ops->read_rollback_index(
- ops, rollback_index_location, &stored_rollback_index);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- goto out;
- }
- if (vbmeta_header.rollback_index < stored_rollback_index) {
- avb_errorv(
- full_partition_name,
- ": Image rollback index is less than the stored rollback index.\n",
- NULL);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
- if (!allow_verification_error) {
- goto out;
- }
- }
-
- /* Copy vbmeta to vbmeta_images before recursing. */
- if (is_main_vbmeta) {
- avb_assert(slot_data->num_vbmeta_images == 0);
- } else {
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
- vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
- vbmeta_image_data->partition_name = avb_strdup(partition_name);
- vbmeta_image_data->vbmeta_data = vbmeta_buf;
- /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
- * and this includes data past the end of the image. Pass the
- * actual size of the vbmeta image. Also, no need to use
- * avb_safe_add() since the header has already been verified.
- */
- vbmeta_image_data->vbmeta_size =
- sizeof(AvbVBMetaImageHeader) +
- vbmeta_header.authentication_data_block_size +
- vbmeta_header.auxiliary_data_block_size;
- vbmeta_image_data->verify_result = vbmeta_ret;
-
- /* If verification has been disabled by setting a bit in the image,
- * we're done... except that we need to load the entirety of the
- * requested partitions.
- */
- 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);
- /* 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()
- * returns true) and we want to convey that error.
- */
- sub_ret = load_requested_partitions(
- ops, requested_partitions, ab_suffix, slot_data);
- if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
- ret = sub_ret;
- }
- goto out;
- }
-
- /* Now go through all descriptors and take the appropriate action:
- *
- * - hash descriptor: Load data from partition, calculate hash, and
- * checks that it matches what's in the hash descriptor.
- *
- * - hashtree descriptor: Do nothing since verification happens
- * on-the-fly from within the OS.
- *
- * - chained partition descriptor: Load the footer, load the vbmeta
- * image, verify vbmeta image (includes rollback checks, hash
- * checks, bail on chained partitions).
- */
- descriptors =
- avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
- for (n = 0; n < num_descriptors; n++) {
- AvbDescriptor desc;
-
- if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
- avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- switch (desc.tag) {
- case AVB_DESCRIPTOR_TAG_HASH: {
- AvbSlotVerifyResult sub_ret;
- sub_ret = load_and_verify_hash_partition(ops,
- requested_partitions,
- ab_suffix,
- allow_verification_error,
- descriptors[n],
- slot_data);
- if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
- ret = sub_ret;
- if (!allow_verification_error || !result_should_continue(ret)) {
- goto out;
- }
- }
- } break;
-
- case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
- AvbSlotVerifyResult sub_ret;
- AvbChainPartitionDescriptor chain_desc;
- const uint8_t* chain_partition_name;
- const uint8_t* chain_public_key;
-
- /* 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);
- 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);
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- chain_partition_name = ((const uint8_t*)descriptors[n]) +
- sizeof(AvbChainPartitionDescriptor);
- chain_public_key = chain_partition_name + chain_desc.partition_name_len;
-
- sub_ret = load_and_verify_vbmeta(ops,
- requested_partitions,
- ab_suffix,
- allow_verification_error,
- toplevel_vbmeta_flags,
- chain_desc.rollback_index_location,
- (const char*)chain_partition_name,
- chain_desc.partition_name_len,
- chain_public_key,
- chain_desc.public_key_len,
- slot_data,
- NULL /* out_algorithm_type */);
- if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
- ret = sub_ret;
- if (!result_should_continue(ret)) {
- goto out;
- }
- }
- } break;
-
- case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
- const uint8_t* kernel_cmdline;
- AvbKernelCmdlineDescriptor kernel_cmdline_desc;
- bool apply_cmdline;
-
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- kernel_cmdline = ((const uint8_t*)descriptors[n]) +
- sizeof(AvbKernelCmdlineDescriptor);
-
- 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);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- /* Compare the flags for top-level VBMeta struct with flags in
- * the command-line descriptor so command-line snippets only
- * intended for a certain mode (dm-verity enabled/disabled)
- * are skipped if applicable.
- */
- apply_cmdline = true;
- if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
- if (kernel_cmdline_desc.flags &
- AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
- apply_cmdline = false;
- }
- } else {
- if (kernel_cmdline_desc.flags &
- AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
- apply_cmdline = false;
- }
- }
-
- if (apply_cmdline) {
- if (slot_data->cmdline == NULL) {
- slot_data->cmdline =
- avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
- if (slot_data->cmdline == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
- avb_memcpy(slot_data->cmdline,
- kernel_cmdline,
- kernel_cmdline_desc.kernel_cmdline_length);
- } else {
- /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
- size_t orig_size = avb_strlen(slot_data->cmdline);
- size_t new_size =
- orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
- char* new_cmdline = avb_calloc(new_size);
- if (new_cmdline == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
- avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
- new_cmdline[orig_size] = ' ';
- avb_memcpy(new_cmdline + orig_size + 1,
- kernel_cmdline,
- kernel_cmdline_desc.kernel_cmdline_length);
- avb_free(slot_data->cmdline);
- slot_data->cmdline = new_cmdline;
- }
- }
- } break;
-
- /* Explicit fall-through */
- case AVB_DESCRIPTOR_TAG_PROPERTY:
- case AVB_DESCRIPTOR_TAG_HASHTREE:
- /* Do nothing. */
- break;
- }
- }
-
- if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
- avb_errorv(
- full_partition_name, ": Invalid rollback_index_location.\n", NULL);
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
- goto out;
- }
-
- slot_data->rollback_indexes[rollback_index_location] =
- vbmeta_header.rollback_index;
-
- if (out_algorithm_type != NULL) {
- *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
- }
-
-out:
- /* If |vbmeta_image_data| isn't NULL it means that it adopted
- * |vbmeta_buf| so in that case don't free it here.
- */
- if (vbmeta_image_data == NULL) {
- if (vbmeta_buf != NULL) {
- avb_free(vbmeta_buf);
- }
- }
- if (descriptors != NULL) {
- avb_free(descriptors);
- }
- return ret;
-}
-
-AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
- const char* const* requested_partitions,
- const char* ab_suffix,
- AvbSlotVerifyFlags flags,
- AvbHashtreeErrorMode hashtree_error_mode,
- AvbSlotVerifyData** out_data) {
- AvbSlotVerifyResult ret;
- AvbSlotVerifyData* slot_data = NULL;
- AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
- bool using_boot_for_vbmeta = false;
- AvbVBMetaImageHeader toplevel_vbmeta;
- bool allow_verification_error =
- (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
-
- /* Fail early if we're missing the AvbOps needed for slot verification.
- *
- * For now, handle get_size_of_partition() not being implemented. In
- * a later release we may change that.
- */
- avb_assert(ops->read_is_device_unlocked != NULL);
- avb_assert(ops->read_from_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);
-
- if (out_data != NULL) {
- *out_data = NULL;
- }
-
- /* Allowing dm-verity errors defeats the purpose of verified boot so
- * only allow this if set up to allow verification errors
- * (e.g. typically only UNLOCKED mode).
- */
- if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
- !allow_verification_error) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
- goto fail;
- }
-
- slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
- if (slot_data == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto fail;
- }
- slot_data->vbmeta_images =
- avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
- if (slot_data->vbmeta_images == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto fail;
- }
- slot_data->loaded_partitions =
- avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
- if (slot_data->loaded_partitions == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- 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);
- if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
- goto fail;
- }
-
- /* If things check out, mangle the kernel command-line as needed. */
- if (result_should_continue(ret)) {
- 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. */
- avb_vbmeta_image_header_to_host_byte_order(
- (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
- &toplevel_vbmeta);
-
- /* Fill in |ab_suffix| field. */
- slot_data->ab_suffix = avb_strdup(ab_suffix);
- if (slot_data->ab_suffix == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto fail;
- }
-
- /* If verification is disabled, we are done ... we specifically
- * don't want to add any androidboot.* options since verification
- * is disabled.
- */
- if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
- /* Since verification is disabled we didn't process any
- * descriptors and thus there's no cmdline... so set root= such
- * that the system partition is mounted.
- */
- avb_assert(slot_data->cmdline == NULL);
- slot_data->cmdline =
- avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
- if (slot_data->cmdline == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto fail;
- }
- } else {
- /* Add options - any failure in avb_append_options() is either an
- * I/O or OOM error.
- */
- AvbSlotVerifyResult sub_ret = avb_append_options(
- ops, slot_data, &toplevel_vbmeta, algorithm_type,
- hashtree_error_mode);
- if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
- ret = sub_ret;
- goto fail;
- }
- }
-
- /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
- if (slot_data->cmdline != NULL) {
- char* new_cmdline;
- new_cmdline = avb_sub_cmdline(
- ops, slot_data->cmdline, ab_suffix, using_boot_for_vbmeta);
- if (new_cmdline != slot_data->cmdline) {
- if (new_cmdline == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto fail;
- }
- avb_free(slot_data->cmdline);
- slot_data->cmdline = new_cmdline;
- }
- }
-
- if (out_data != NULL) {
- *out_data = slot_data;
- } else {
- avb_slot_verify_data_free(slot_data);
- }
- }
-
- if (!allow_verification_error) {
- avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
- }
-
- return ret;
-
-fail:
- if (slot_data != NULL) {
- avb_slot_verify_data_free(slot_data);
- }
- return ret;
-}
-
-void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
- if (data->ab_suffix != NULL) {
- avb_free(data->ab_suffix);
- }
- if (data->cmdline != NULL) {
- avb_free(data->cmdline);
- }
- if (data->vbmeta_images != NULL) {
- size_t n;
- for (n = 0; n < data->num_vbmeta_images; n++) {
- AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
- if (vbmeta_image->partition_name != NULL) {
- avb_free(vbmeta_image->partition_name);
- }
- if (vbmeta_image->vbmeta_data != NULL) {
- avb_free(vbmeta_image->vbmeta_data);
- }
- }
- avb_free(data->vbmeta_images);
- }
- if (data->loaded_partitions != NULL) {
- size_t n;
- for (n = 0; n < data->num_loaded_partitions; n++) {
- AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
- if (loaded_partition->partition_name != NULL) {
- avb_free(loaded_partition->partition_name);
- }
- if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
- avb_free(loaded_partition->data);
- }
- }
- avb_free(data->loaded_partitions);
- }
- avb_free(data);
-}
-
-const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
- const char* ret = NULL;
-
- switch (result) {
- case AVB_SLOT_VERIFY_RESULT_OK:
- ret = "OK";
- break;
- case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
- ret = "ERROR_OOM";
- break;
- case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
- ret = "ERROR_IO";
- break;
- case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
- ret = "ERROR_VERIFICATION";
- break;
- case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
- ret = "ERROR_ROLLBACK_INDEX";
- break;
- case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
- ret = "ERROR_PUBLIC_KEY_REJECTED";
- break;
- case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
- ret = "ERROR_INVALID_METADATA";
- break;
- case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
- ret = "ERROR_UNSUPPORTED_VERSION";
- break;
- case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
- ret = "ERROR_INVALID_ARGUMENT";
- break;
- /* Do not add a 'default:' case here because of -Wswitch. */
- }
-
- if (ret == NULL) {
- avb_error("Unknown AvbSlotVerifyResult value.\n");
- ret = "(unknown)";
- }
-
- return ret;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_slot_verify.h"
+#include "avb_chain_partition_descriptor.h"
+#include "avb_cmdline.h"
+#include "avb_footer.h"
+#include "avb_hash_descriptor.h"
+#include "avb_hashtree_descriptor.h"
+#include "avb_kernel_cmdline_descriptor.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+#include "avb_version.h"
+
+/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
+#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
+
+/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
+#define MAX_NUMBER_OF_VBMETA_IMAGES 32
+
+/* Maximum size of a vbmeta image - 64 KiB. */
+#define VBMETA_MAX_SIZE (64 * 1024)
+
+/* Helper function to see if we should continue with verification in
+ * allow_verification_error=true mode if something goes wrong. See the
+ * comments for the avb_slot_verify() function for more information.
+ */
+static inline bool result_should_continue(AvbSlotVerifyResult result) {
+ switch (result) {
+ case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+ return false;
+
+ case AVB_SLOT_VERIFY_RESULT_OK:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+ return true;
+ }
+
+ return false;
+}
+
+static AvbSlotVerifyResult load_full_partition(AvbOps* ops,
+ const char* part_name,
+ uint64_t image_size,
+ uint8_t** out_image_buf,
+ bool* out_image_preloaded) {
+ size_t part_num_read;
+ AvbIOResult io_ret;
+
+ /* Make sure that we do not overwrite existing data. */
+ avb_assert(*out_image_buf == NULL);
+ avb_assert(!*out_image_preloaded);
+
+ /* 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);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ }
+
+ /* Try use a preloaded one. */
+ if (ops->get_preloaded_partition != NULL) {
+ io_ret = ops->get_preloaded_partition(
+ ops, part_name, image_size, out_image_buf, &part_num_read);
+ 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);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+
+ if (*out_image_buf != NULL) {
+ if (part_num_read != image_size) {
+ avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+ *out_image_preloaded = true;
+ }
+ }
+
+ /* Allocate and copy the partition. */
+ if (!*out_image_preloaded) {
+ *out_image_buf = avb_malloc(image_size);
+ if (*out_image_buf == NULL) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ }
+
+ io_ret = ops->read_from_partition(ops,
+ part_name,
+ 0 /* offset */,
+ image_size,
+ *out_image_buf,
+ &part_num_read);
+ 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);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+ if (part_num_read != image_size) {
+ avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+ }
+
+ return AVB_SLOT_VERIFY_RESULT_OK;
+}
+
+static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops,
+ const char* part_name,
+ size_t expected_digest_size,
+ uint8_t* out_digest) {
+ char* persistent_value_name = NULL;
+ AvbIOResult io_ret = AVB_IO_RESULT_OK;
+ size_t stored_digest_size = 0;
+
+ if (ops->read_persistent_value == NULL) {
+ avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ }
+ persistent_value_name =
+ avb_strdupv(AVB_NPV_PERSISTENT_DIGEST_PREFIX, part_name, NULL);
+ if (persistent_value_name == NULL) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ }
+ io_ret = ops->read_persistent_value(ops,
+ persistent_value_name,
+ expected_digest_size,
+ out_digest,
+ &stored_digest_size);
+ avb_free(persistent_value_name);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ } else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
+ avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ } else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
+ io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE ||
+ expected_digest_size != stored_digest_size) {
+ avb_errorv(
+ part_name, ": Persistent digest is not of expected size.\n", NULL);
+ 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);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+ return AVB_SLOT_VERIFY_RESULT_OK;
+}
+
+static AvbSlotVerifyResult load_and_verify_hash_partition(
+ AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ bool allow_verification_error,
+ const AvbDescriptor* descriptor,
+ AvbSlotVerifyData* slot_data) {
+ AvbHashDescriptor hash_desc;
+ const uint8_t* desc_partition_name = NULL;
+ const uint8_t* desc_salt;
+ const uint8_t* desc_digest;
+ char part_name[AVB_PART_NAME_MAX_SIZE];
+ AvbSlotVerifyResult ret;
+ AvbIOResult io_ret;
+ uint8_t* image_buf = NULL;
+ bool image_preloaded = false;
+ uint8_t* digest;
+ size_t digest_len;
+ const char* found;
+ uint64_t image_size;
+ size_t expected_digest_len = 0;
+ uint8_t expected_digest_buf[AVB_SHA512_DIGEST_SIZE];
+ const uint8_t* expected_digest = NULL;
+
+ if (!avb_hash_descriptor_validate_and_byteswap(
+ (const AvbHashDescriptor*)descriptor, &hash_desc)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ desc_partition_name =
+ ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
+ desc_salt = desc_partition_name + hash_desc.partition_name_len;
+ desc_digest = desc_salt + hash_desc.salt_len;
+
+ if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
+ avb_error("Partition name is not valid UTF-8.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* Don't bother loading or validating unless the partition was
+ * requested in the first place.
+ */
+ found = avb_strv_find_str(requested_partitions,
+ (const char*)desc_partition_name,
+ hash_desc.partition_name_len);
+ if (found == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+ goto out;
+ }
+
+ if ((hash_desc.flags & AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) != 0) {
+ /* No ab_suffix, just copy the partition name as is. */
+ if (hash_desc.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(part_name, desc_partition_name, hash_desc.partition_name_len);
+ part_name[hash_desc.partition_name_len] = '\0';
+ } else if (hash_desc.digest_len == 0 && avb_strlen(ab_suffix) != 0) {
+ /* No ab_suffix allowed for partitions without a digest in the descriptor
+ * because these partitions hold data unique to this device and are not
+ * updated using an A/B scheme.
+ */
+ avb_error("Cannot use A/B with a persistent digest.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ } else {
+ /* Add ab_suffix to the partition name. */
+ if (!avb_str_concat(part_name,
+ sizeof part_name,
+ (const char*)desc_partition_name,
+ hash_desc.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;
+ }
+ }
+
+ /* If we're allowing verification errors then hash_desc.image_size
+ * may no longer match what's in the partition... so in this case
+ * just load the entire partition.
+ *
+ * For example, this can happen if a developer does 'fastboot flash
+ * boot /path/to/new/and/bigger/boot.img'. We want this to work
+ * since it's such a common workflow.
+ */
+ image_size = hash_desc.image_size;
+ if (allow_verification_error) {
+ if (ops->get_size_of_partition == NULL) {
+ avb_errorv(part_name,
+ ": The get_size_of_partition() operation is "
+ "not implemented so we may not load the entire partition. "
+ "Please implement.",
+ NULL);
+ } else {
+ io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+ }
+ }
+
+ ret = load_full_partition(
+ ops, part_name, image_size, &image_buf, &image_preloaded);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+
+ if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
+ AvbSHA256Ctx sha256_ctx;
+ avb_sha256_init(&sha256_ctx);
+ avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
+ avb_sha256_update(&sha256_ctx, image_buf, hash_desc.image_size);
+ digest = avb_sha256_final(&sha256_ctx);
+ digest_len = AVB_SHA256_DIGEST_SIZE;
+ } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
+ AvbSHA512Ctx sha512_ctx;
+ avb_sha512_init(&sha512_ctx);
+ avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
+ avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
+ digest = avb_sha512_final(&sha512_ctx);
+ digest_len = AVB_SHA512_DIGEST_SIZE;
+ } else {
+ avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
+ 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);
+ expected_digest_len = digest_len;
+ expected_digest = expected_digest_buf;
+ avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
+ ret =
+ read_persistent_digest(ops, part_name, digest_len, expected_digest_buf);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+ } else {
+ // Expect a match to the digest in the descriptor.
+ expected_digest_len = hash_desc.digest_len;
+ expected_digest = desc_digest;
+ }
+
+ if (digest_len != expected_digest_len) {
+ avb_errorv(
+ part_name, ": Digest in descriptor not of expected size.\n", NULL);
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+ goto out;
+ }
+
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+out:
+
+ /* If it worked and something was loaded, copy to slot_data. */
+ if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ loaded_partition =
+ &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
+ loaded_partition->partition_name = avb_strdup(found);
+ loaded_partition->data_size = image_size;
+ loaded_partition->data = image_buf;
+ loaded_partition->preloaded = image_preloaded;
+ image_buf = NULL;
+ }
+
+fail:
+ if (image_buf != NULL && !image_preloaded) {
+ avb_free(image_buf);
+ }
+ return ret;
+}
+
+static AvbSlotVerifyResult load_requested_partitions(
+ AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ AvbSlotVerifyData* slot_data) {
+ AvbSlotVerifyResult ret;
+ uint8_t* image_buf = NULL;
+ bool image_preloaded = false;
+ size_t n;
+
+ if (ops->get_size_of_partition == NULL) {
+ avb_error("get_size_of_partition() not implemented.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ for (n = 0; requested_partitions[n] != NULL; n++) {
+ char part_name[AVB_PART_NAME_MAX_SIZE];
+ AvbIOResult io_ret;
+ uint64_t image_size;
+ AvbPartitionData* loaded_partition;
+
+ if (!avb_str_concat(part_name,
+ sizeof part_name,
+ requested_partitions[n],
+ avb_strlen(requested_partitions[n]),
+ 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;
+ }
+
+ io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+
+ ret = load_full_partition(
+ ops, part_name, image_size, &image_buf, &image_preloaded);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+
+ /* 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ loaded_partition =
+ &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
+ loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
+ if (loaded_partition->partition_name == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ loaded_partition->data_size = image_size;
+ loaded_partition->data = image_buf; /* Transferring the owner. */
+ loaded_partition->preloaded = image_preloaded;
+ image_buf = NULL;
+ image_preloaded = false;
+ }
+
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+out:
+ /* Free the current buffer if any. */
+ if (image_buf != NULL && !image_preloaded) {
+ avb_free(image_buf);
+ }
+ /* Buffers that are already saved in slot_data will be handled by the caller
+ * even on failure. */
+ return ret;
+}
+
+static AvbSlotVerifyResult load_and_verify_vbmeta(
+ AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ bool allow_verification_error,
+ AvbVBMetaImageFlags toplevel_vbmeta_flags,
+ int 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) {
+ char full_partition_name[AVB_PART_NAME_MAX_SIZE];
+ AvbSlotVerifyResult ret;
+ AvbIOResult io_ret;
+ size_t vbmeta_offset;
+ size_t vbmeta_size;
+ uint8_t* vbmeta_buf = NULL;
+ size_t vbmeta_num_read;
+ AvbVBMetaVerifyResult vbmeta_ret;
+ const uint8_t* pk_data;
+ size_t pk_len;
+ AvbVBMetaImageHeader vbmeta_header;
+ uint64_t stored_rollback_index;
+ const AvbDescriptor** descriptors = NULL;
+ size_t num_descriptors;
+ size_t n;
+ bool is_main_vbmeta;
+ bool is_vbmeta_partition;
+ AvbVBMetaData* vbmeta_image_data = NULL;
+
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+ avb_assert(slot_data != NULL);
+
+ /* Since we allow top-level vbmeta in 'boot', use
+ * rollback_index_location to determine whether we're the main
+ * vbmeta struct.
+ */
+ is_main_vbmeta = (rollback_index_location == 0);
+ is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
+
+ if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
+ avb_error("Partition name is not valid UTF-8.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* Construct full partition name. */
+ 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_debugv("Loading vbmeta struct from partition '",
+ full_partition_name,
+ "'.\n",
+ NULL);
+
+ /* If we're loading from the main vbmeta partition, the vbmeta
+ * struct is in the beginning. Otherwise we have to locate it via a
+ * footer.
+ */
+ if (is_vbmeta_partition) {
+ vbmeta_offset = 0;
+ vbmeta_size = VBMETA_MAX_SIZE;
+ } else {
+ uint8_t footer_buf[AVB_FOOTER_SIZE];
+ size_t footer_num_read;
+ AvbFooter footer;
+
+ io_ret = ops->read_from_partition(ops,
+ full_partition_name,
+ -AVB_FOOTER_SIZE,
+ AVB_FOOTER_SIZE,
+ footer_buf,
+ &footer_num_read);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ avb_assert(footer_num_read == AVB_FOOTER_SIZE);
+
+ if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
+ &footer)) {
+ avb_errorv(full_partition_name, ": Error validating footer.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ vbmeta_offset = footer.vbmeta_offset;
+ vbmeta_size = footer.vbmeta_size;
+ }
+
+ vbmeta_buf = avb_malloc(vbmeta_size);
+ if (vbmeta_buf == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+
+ 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;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ /* If we're looking for 'vbmeta' but there is no such partition,
+ * go try to get it from the boot partition instead.
+ */
+ if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
+ is_vbmeta_partition) {
+ avb_debugv(full_partition_name,
+ ": No such partition. Trying 'boot' instead.\n",
+ NULL);
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ "boot",
+ avb_strlen("boot"),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ out_algorithm_type,
+ out_additional_cmdline_subst);
+ goto out;
+ } else {
+ avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ }
+ avb_assert(vbmeta_num_read <= vbmeta_size);
+
+ /* Check if the image is properly signed and get the public key used
+ * to sign the image.
+ */
+ vbmeta_ret =
+ avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
+ switch (vbmeta_ret) {
+ case AVB_VBMETA_VERIFY_RESULT_OK:
+ avb_assert(pk_data != NULL && pk_len > 0);
+ break;
+
+ case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
+ 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);
+ if (!allow_verification_error) {
+ goto out;
+ }
+ break;
+
+ 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);
+ 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);
+ goto out;
+ }
+
+ /* Byteswap the header. */
+ avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
+ &vbmeta_header);
+
+ /* If we're the toplevel, assign flags so they'll be passed down. */
+ if (is_main_vbmeta) {
+ toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
+ } 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);
+ goto out;
+ }
+ }
+
+ /* Check if key used to make signature matches what is expected. */
+ if (pk_data != NULL) {
+ if (expected_public_key != 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
+ if (!allow_verification_error) {
+ goto out;
+ }
+ }
+ } else {
+ bool key_is_trusted = false;
+ const uint8_t* pk_metadata = NULL;
+ size_t pk_metadata_len = 0;
+
+ if (vbmeta_header.public_key_metadata_size > 0) {
+ pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
+ vbmeta_header.authentication_data_block_size +
+ vbmeta_header.public_key_metadata_offset;
+ 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 (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ 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);
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
+ if (!allow_verification_error) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ /* Check rollback index. */
+ io_ret = ops->read_rollback_index(
+ ops, rollback_index_location, &stored_rollback_index);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (vbmeta_header.rollback_index < stored_rollback_index) {
+ avb_errorv(
+ full_partition_name,
+ ": Image rollback index is less than the stored rollback index.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
+ if (!allow_verification_error) {
+ goto out;
+ }
+ }
+
+ /* Copy vbmeta to vbmeta_images before recursing. */
+ if (is_main_vbmeta) {
+ avb_assert(slot_data->num_vbmeta_images == 0);
+ } else {
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
+ vbmeta_image_data->partition_name = avb_strdup(partition_name);
+ vbmeta_image_data->vbmeta_data = vbmeta_buf;
+ /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
+ * and this includes data past the end of the image. Pass the
+ * actual size of the vbmeta image. Also, no need to use
+ * avb_safe_add() since the header has already been verified.
+ */
+ vbmeta_image_data->vbmeta_size =
+ sizeof(AvbVBMetaImageHeader) +
+ vbmeta_header.authentication_data_block_size +
+ vbmeta_header.auxiliary_data_block_size;
+ vbmeta_image_data->verify_result = vbmeta_ret;
+
+ /* If verification has been disabled by setting a bit in the image,
+ * we're done... except that we need to load the entirety of the
+ * requested partitions.
+ */
+ 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);
+ /* 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()
+ * returns true) and we want to convey that error.
+ */
+ sub_ret = load_requested_partitions(
+ ops, requested_partitions, ab_suffix, slot_data);
+ if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ ret = sub_ret;
+ }
+ goto out;
+ }
+
+ /* Now go through all descriptors and take the appropriate action:
+ *
+ * - hash descriptor: Load data from partition, calculate hash, and
+ * checks that it matches what's in the hash descriptor.
+ *
+ * - hashtree descriptor: Do nothing since verification happens
+ * on-the-fly from within the OS. (Unless the descriptor uses a
+ * persistent digest, in which case we need to find it).
+ *
+ * - chained partition descriptor: Load the footer, load the vbmeta
+ * image, verify vbmeta image (includes rollback checks, hash
+ * checks, bail on chained partitions).
+ */
+ descriptors =
+ avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
+ for (n = 0; n < num_descriptors; n++) {
+ AvbDescriptor desc;
+
+ if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
+ avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ switch (desc.tag) {
+ case AVB_DESCRIPTOR_TAG_HASH: {
+ AvbSlotVerifyResult sub_ret;
+ sub_ret = load_and_verify_hash_partition(ops,
+ requested_partitions,
+ ab_suffix,
+ allow_verification_error,
+ descriptors[n],
+ slot_data);
+ if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ ret = sub_ret;
+ if (!allow_verification_error || !result_should_continue(ret)) {
+ goto out;
+ }
+ }
+ } break;
+
+ case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
+ AvbSlotVerifyResult sub_ret;
+ AvbChainPartitionDescriptor chain_desc;
+ const uint8_t* chain_partition_name;
+ const uint8_t* chain_public_key;
+
+ /* 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);
+ 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);
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ chain_partition_name = ((const uint8_t*)descriptors[n]) +
+ sizeof(AvbChainPartitionDescriptor);
+ chain_public_key = chain_partition_name + chain_desc.partition_name_len;
+
+ sub_ret =
+ load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ allow_verification_error,
+ toplevel_vbmeta_flags,
+ chain_desc.rollback_index_location,
+ (const char*)chain_partition_name,
+ chain_desc.partition_name_len,
+ chain_public_key,
+ chain_desc.public_key_len,
+ slot_data,
+ NULL, /* out_algorithm_type */
+ NULL /* out_additional_cmdline_subst */);
+ if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ ret = sub_ret;
+ if (!result_should_continue(ret)) {
+ goto out;
+ }
+ }
+ } break;
+
+ case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
+ const uint8_t* kernel_cmdline;
+ AvbKernelCmdlineDescriptor kernel_cmdline_desc;
+ bool apply_cmdline;
+
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ kernel_cmdline = ((const uint8_t*)descriptors[n]) +
+ sizeof(AvbKernelCmdlineDescriptor);
+
+ 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);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* Compare the flags for top-level VBMeta struct with flags in
+ * the command-line descriptor so command-line snippets only
+ * intended for a certain mode (dm-verity enabled/disabled)
+ * are skipped if applicable.
+ */
+ apply_cmdline = true;
+ if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
+ if (kernel_cmdline_desc.flags &
+ AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
+ apply_cmdline = false;
+ }
+ } else {
+ if (kernel_cmdline_desc.flags &
+ AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
+ apply_cmdline = false;
+ }
+ }
+
+ if (apply_cmdline) {
+ if (slot_data->cmdline == NULL) {
+ slot_data->cmdline =
+ avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
+ if (slot_data->cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ avb_memcpy(slot_data->cmdline,
+ kernel_cmdline,
+ kernel_cmdline_desc.kernel_cmdline_length);
+ } else {
+ /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
+ size_t orig_size = avb_strlen(slot_data->cmdline);
+ size_t new_size =
+ orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
+ char* new_cmdline = avb_calloc(new_size);
+ if (new_cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
+ new_cmdline[orig_size] = ' ';
+ avb_memcpy(new_cmdline + orig_size + 1,
+ kernel_cmdline,
+ kernel_cmdline_desc.kernel_cmdline_length);
+ avb_free(slot_data->cmdline);
+ slot_data->cmdline = new_cmdline;
+ }
+ }
+ } break;
+
+ case AVB_DESCRIPTOR_TAG_HASHTREE: {
+ AvbHashtreeDescriptor hashtree_desc;
+
+ if (!avb_hashtree_descriptor_validate_and_byteswap(
+ (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
+ avb_errorv(
+ full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* We only need to continue when there is no digest in the descriptor.
+ * This is because the only processing here is to find the digest and
+ * make it available on the kernel command line.
+ */
+ if (hashtree_desc.root_digest_len == 0) {
+ char part_name[AVB_PART_NAME_MAX_SIZE];
+ size_t digest_len = 0;
+ uint8_t digest_buf[AVB_SHA512_DIGEST_SIZE];
+ const uint8_t* desc_partition_name =
+ ((const uint8_t*)descriptors[n]) + sizeof(AvbHashtreeDescriptor);
+
+ if (!avb_validate_utf8(desc_partition_name,
+ hashtree_desc.partition_name_len)) {
+ avb_error("Partition name is not valid UTF-8.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* No ab_suffix for partitions without a digest in the descriptor
+ * because these partitions hold data unique to this device and are
+ * not updated using an A/B scheme.
+ */
+ if ((hashtree_desc.flags &
+ AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) == 0 &&
+ avb_strlen(ab_suffix) != 0) {
+ avb_error("Cannot use A/B with a persistent root digest.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+ if (hashtree_desc.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(
+ part_name, desc_partition_name, hashtree_desc.partition_name_len);
+ part_name[hashtree_desc.partition_name_len] = '\0';
+
+ /* Determine the expected digest size from the hash algorithm. */
+ if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
+ 0) {
+ digest_len = AVB_SHA1_DIGEST_SIZE;
+ } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
+ "sha256") == 0) {
+ digest_len = AVB_SHA256_DIGEST_SIZE;
+ } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
+ "sha512") == 0) {
+ digest_len = AVB_SHA512_DIGEST_SIZE;
+ } else {
+ avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ ret = read_persistent_digest(ops, part_name, digest_len, digest_buf);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+
+ if (out_additional_cmdline_subst) {
+ ret =
+ avb_add_root_digest_substitution(part_name,
+ digest_buf,
+ digest_len,
+ out_additional_cmdline_subst);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+ }
+ }
+ } break;
+
+ case AVB_DESCRIPTOR_TAG_PROPERTY:
+ /* Do nothing. */
+ break;
+ }
+ }
+
+ if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
+ avb_errorv(
+ full_partition_name, ": Invalid rollback_index_location.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ slot_data->rollback_indexes[rollback_index_location] =
+ vbmeta_header.rollback_index;
+
+ if (out_algorithm_type != NULL) {
+ *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
+ }
+
+out:
+ /* If |vbmeta_image_data| isn't NULL it means that it adopted
+ * |vbmeta_buf| so in that case don't free it here.
+ */
+ if (vbmeta_image_data == NULL) {
+ if (vbmeta_buf != NULL) {
+ avb_free(vbmeta_buf);
+ }
+ }
+ if (descriptors != NULL) {
+ avb_free(descriptors);
+ }
+ return ret;
+}
+
+AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ AvbSlotVerifyFlags flags,
+ AvbHashtreeErrorMode hashtree_error_mode,
+ AvbSlotVerifyData** out_data) {
+ AvbSlotVerifyResult ret;
+ AvbSlotVerifyData* slot_data = NULL;
+ AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
+ bool using_boot_for_vbmeta = false;
+ AvbVBMetaImageHeader toplevel_vbmeta;
+ bool allow_verification_error =
+ (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
+ AvbCmdlineSubstList* additional_cmdline_subst = NULL;
+
+ /* Fail early if we're missing the AvbOps needed for slot verification.
+ *
+ * For now, handle get_size_of_partition() not being implemented. In
+ * a later release we may change that.
+ */
+ avb_assert(ops->read_is_device_unlocked != NULL);
+ avb_assert(ops->read_from_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);
+
+ if (out_data != NULL) {
+ *out_data = NULL;
+ }
+
+ /* Allowing dm-verity errors defeats the purpose of verified boot so
+ * only allow this if set up to allow verification errors
+ * (e.g. typically only UNLOCKED mode).
+ */
+ if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
+ !allow_verification_error) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+
+ slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
+ if (slot_data == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ slot_data->vbmeta_images =
+ avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
+ if (slot_data->vbmeta_images == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ slot_data->loaded_partitions =
+ avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
+ if (slot_data->loaded_partitions == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+
+ additional_cmdline_subst = avb_new_cmdline_subst_list();
+ if (additional_cmdline_subst == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ 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 things check out, mangle the kernel command-line as needed. */
+ if (result_should_continue(ret)) {
+ 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. */
+ avb_vbmeta_image_header_to_host_byte_order(
+ (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
+ &toplevel_vbmeta);
+
+ /* Fill in |ab_suffix| field. */
+ slot_data->ab_suffix = avb_strdup(ab_suffix);
+ if (slot_data->ab_suffix == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+
+ /* If verification is disabled, we are done ... we specifically
+ * don't want to add any androidboot.* options since verification
+ * is disabled.
+ */
+ if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
+ /* Since verification is disabled we didn't process any
+ * descriptors and thus there's no cmdline... so set root= such
+ * that the system partition is mounted.
+ */
+ avb_assert(slot_data->cmdline == NULL);
+ slot_data->cmdline =
+ avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
+ if (slot_data->cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ } else {
+ /* Add options - any failure in avb_append_options() is either an
+ * I/O or OOM error.
+ */
+ AvbSlotVerifyResult sub_ret = avb_append_options(ops,
+ slot_data,
+ &toplevel_vbmeta,
+ algorithm_type,
+ hashtree_error_mode);
+ if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ ret = sub_ret;
+ goto fail;
+ }
+ }
+
+ /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
+ if (slot_data->cmdline != NULL) {
+ char* new_cmdline;
+ new_cmdline = avb_sub_cmdline(ops,
+ slot_data->cmdline,
+ ab_suffix,
+ using_boot_for_vbmeta,
+ additional_cmdline_subst);
+ if (new_cmdline != slot_data->cmdline) {
+ if (new_cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ avb_free(slot_data->cmdline);
+ slot_data->cmdline = new_cmdline;
+ }
+ }
+
+ if (out_data != NULL) {
+ *out_data = slot_data;
+ } else {
+ avb_slot_verify_data_free(slot_data);
+ }
+ }
+
+ avb_free_cmdline_subst_list(additional_cmdline_subst);
+ additional_cmdline_subst = NULL;
+
+ if (!allow_verification_error) {
+ avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
+ }
+
+ return ret;
+
+fail:
+ if (slot_data != NULL) {
+ avb_slot_verify_data_free(slot_data);
+ }
+ if (additional_cmdline_subst != NULL) {
+ avb_free_cmdline_subst_list(additional_cmdline_subst);
+ }
+ return ret;
+}
+
+void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
+ if (data->ab_suffix != NULL) {
+ avb_free(data->ab_suffix);
+ }
+ if (data->cmdline != NULL) {
+ avb_free(data->cmdline);
+ }
+ if (data->vbmeta_images != NULL) {
+ size_t n;
+ for (n = 0; n < data->num_vbmeta_images; n++) {
+ AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
+ if (vbmeta_image->partition_name != NULL) {
+ avb_free(vbmeta_image->partition_name);
+ }
+ if (vbmeta_image->vbmeta_data != NULL) {
+ avb_free(vbmeta_image->vbmeta_data);
+ }
+ }
+ avb_free(data->vbmeta_images);
+ }
+ if (data->loaded_partitions != NULL) {
+ size_t n;
+ for (n = 0; n < data->num_loaded_partitions; n++) {
+ AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
+ if (loaded_partition->partition_name != NULL) {
+ avb_free(loaded_partition->partition_name);
+ }
+ if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
+ avb_free(loaded_partition->data);
+ }
+ }
+ avb_free(data->loaded_partitions);
+ }
+ avb_free(data);
+}
+
+const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
+ const char* ret = NULL;
+
+ switch (result) {
+ case AVB_SLOT_VERIFY_RESULT_OK:
+ ret = "OK";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+ ret = "ERROR_OOM";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+ ret = "ERROR_IO";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+ ret = "ERROR_VERIFICATION";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+ ret = "ERROR_ROLLBACK_INDEX";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+ ret = "ERROR_PUBLIC_KEY_REJECTED";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+ ret = "ERROR_INVALID_METADATA";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+ ret = "ERROR_UNSUPPORTED_VERSION";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+ ret = "ERROR_INVALID_ARGUMENT";
+ break;
+ /* Do not add a 'default:' case here because of -Wswitch. */
+ }
+
+ if (ret == NULL) {
+ avb_error("Unknown AvbSlotVerifyResult value.\n");
+ ret = "(unknown)";
+ }
+
+ return ret;
+}
+
+void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
+ AvbDigestType digest_type,
+ uint8_t* out_digest) {
+ bool ret = false;
+ size_t n;
+
+ switch (digest_type) {
+ case AVB_DIGEST_TYPE_SHA256: {
+ AvbSHA256Ctx ctx;
+ avb_sha256_init(&ctx);
+ for (n = 0; n < data->num_vbmeta_images; n++) {
+ avb_sha256_update(&ctx,
+ data->vbmeta_images[n].vbmeta_data,
+ data->vbmeta_images[n].vbmeta_size);
+ }
+ avb_memcpy(out_digest, avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE);
+ ret = true;
+ } break;
+
+ case AVB_DIGEST_TYPE_SHA512: {
+ AvbSHA512Ctx ctx;
+ avb_sha512_init(&ctx);
+ for (n = 0; n < data->num_vbmeta_images; n++) {
+ avb_sha512_update(&ctx,
+ data->vbmeta_images[n].vbmeta_data,
+ data->vbmeta_images[n].vbmeta_size);
+ }
+ avb_memcpy(out_digest, avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE);
+ ret = true;
+ } break;
+
+ /* Do not add a 'default:' case here because of -Wswitch. */
+ }
+
+ if (!ret) {
+ avb_fatal("Unknown digest type");
+ }
+}
diff --git a/include/android_avb/avb_slot_verify.h b/lib/avb/libavb/avb_slot_verify.h
index 1b7932496c..375db3da31 100644
--- a/include/android_avb/avb_slot_verify.h
+++ b/lib/avb/libavb/avb_slot_verify.h
@@ -1,352 +1,359 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_SLOT_VERIFY_H_
-#define AVB_SLOT_VERIFY_H_
-
-#include <android_avb/avb_ops.h>
-#include <android_avb/avb_vbmeta_image.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Return codes used in avb_slot_verify(), see that function for
- * documentation for each field.
- *
- * Use avb_slot_verify_result_to_string() to get a textual
- * representation usable for error/debug output.
- */
-typedef enum {
- AVB_SLOT_VERIFY_RESULT_OK,
- AVB_SLOT_VERIFY_RESULT_ERROR_OOM,
- AVB_SLOT_VERIFY_RESULT_ERROR_IO,
- AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
- AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
- AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
- AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
- AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION,
- AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
-} AvbSlotVerifyResult;
-
-/* Various error handling modes for when verification fails using a
- * hashtree at runtime inside the HLOS.
- *
- * AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE means that the OS
- * will invalidate the current slot and restart.
- *
- * AVB_HASHTREE_ERROR_MODE_RESTART means that the OS will restart.
- *
- * AVB_HASHTREE_ERROR_MODE_EIO means that an EIO error will be
- * returned to applications.
- *
- * AVB_HASHTREE_ERROR_MODE_LOGGING means that errors will be logged
- * and corrupt data may be returned to applications. This mode should
- * be used ONLY for diagnostics and debugging. It cannot be used
- * unless AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is also
- * used.
- */
-typedef enum {
- AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
- AVB_HASHTREE_ERROR_MODE_RESTART,
- AVB_HASHTREE_ERROR_MODE_EIO,
- AVB_HASHTREE_ERROR_MODE_LOGGING
-} AvbHashtreeErrorMode;
-
-/* Flags that influence how avb_slot_verify() works.
- *
- * If AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is NOT set then
- * avb_slot_verify() will bail out as soon as an error is encountered
- * and |out_data| is set only if AVB_SLOT_VERIFY_RESULT_OK is
- * returned.
- *
- * Otherwise if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set
- * avb_slot_verify() will continue verification efforts and |out_data|
- * is also set if AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
- * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
- * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned. It is
- * undefined which error is returned if more than one distinct error
- * is encountered. It is guaranteed that AVB_SLOT_VERIFY_RESULT_OK is
- * returned if, and only if, there are no errors. This mode is needed
- * to boot valid but unverified slots when the device is unlocked.
- *
- * Also, if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set the
- * contents loaded from |requested_partition| will be the contents of
- * the entire partition instead of just the size specified in the hash
- * descriptor.
- */
-typedef enum {
- AVB_SLOT_VERIFY_FLAGS_NONE = 0,
- AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0)
-} AvbSlotVerifyFlags;
-
-/* Get a textual representation of |result|. */
-const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result);
-
-/* Maximum number of rollback index locations supported. */
-#define AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS 32
-
-/* AvbPartitionData contains data loaded from partitions when using
- * avb_slot_verify(). The |partition_name| field contains the name of
- * the partition (without A/B suffix), |data| points to the loaded
- * data which is |data_size| bytes long. If |preloaded| is set to true,
- * this structure dose not own |data|. The caller of |avb_slot_verify|
- * needs to make sure that the preloaded data outlives this
- * |AvbPartitionData| structure.
- *
- * Note that this is strictly less than the partition size - it's only
- * the image stored there, not the entire partition nor any of the
- * metadata.
- */
-typedef struct {
- char* partition_name;
- uint8_t* data;
- size_t data_size;
- bool preloaded;
-} AvbPartitionData;
-
-/* AvbVBMetaData contains a vbmeta struct loaded from a partition when
- * using avb_slot_verify(). The |partition_name| field contains the
- * name of the partition (without A/B suffix), |vbmeta_data| points to
- * the loaded data which is |vbmeta_size| bytes long.
- *
- * The |verify_result| field contains the result of
- * avb_vbmeta_image_verify() on the data. This is guaranteed to be
- * AVB_VBMETA_VERIFY_RESULT_OK for all vbmeta images if
- * avb_slot_verify() returns AVB_SLOT_VERIFY_RESULT_OK.
- *
- * You can use avb_descriptor_get_all(), avb_descriptor_foreach(), and
- * avb_vbmeta_image_header_to_host_byte_order() with this data.
- */
-typedef struct {
- char* partition_name;
- uint8_t* vbmeta_data;
- size_t vbmeta_size;
- AvbVBMetaVerifyResult verify_result;
-} AvbVBMetaData;
-
-/* AvbSlotVerifyData contains data needed to boot a particular slot
- * and is returned by avb_slot_verify() if partitions in a slot are
- * successfully verified.
- *
- * All data pointed to by this struct - including data in each item in
- * the |partitions| array - will be freed when the
- * avb_slot_verify_data_free() function is called.
- *
- * The |ab_suffix| field is the copy of the of |ab_suffix| field
- * passed to avb_slot_verify(). It is the A/B suffix of the slot. This
- * value includes the leading underscore - typical values are "" (if
- * no slots are in use), "_a" (for the first slot), and "_b" (for the
- * second slot).
- *
- * The VBMeta images that were checked are available in the
- * |vbmeta_images| field. The field |num_vbmeta_images| contains the
- * number of elements in this array. The first element -
- * vbmeta_images[0] - is guaranteed to be from the partition with the
- * top-level vbmeta struct. This is usually the "vbmeta" partition in
- * the requested slot but if there is no "vbmeta" partition it can
- * also be the "boot" partition.
- *
- * The partitions loaded and verified from from the slot are
- * accessible in the |loaded_partitions| array. The field
- * |num_loaded_partitions| contains the number of elements in this
- * array. The order of partitions in this array may not necessarily be
- * the same order as in the passed-in |requested_partitions| array.
- *
- * Rollback indexes for the verified slot are stored in the
- * |rollback_indexes| field. Note that avb_slot_verify() will NEVER
- * modify stored_rollback_index[n] locations e.g. it will never use
- * the write_rollback_index() AvbOps operation. Instead it is the job
- * of the caller of avb_slot_verify() to do this based on e.g. A/B
- * policy and other factors. See libavb_ab/avb_ab_flow.c for an
- * example of how to do this.
- *
- * The |cmdline| field is a NUL-terminated string in UTF-8 resulting
- * from concatenating all |AvbKernelCmdlineDescriptor| and then
- * performing proper substitution of the variables
- * $(ANDROID_SYSTEM_PARTUUID), $(ANDROID_BOOT_PARTUUID), and
- * $(ANDROID_VBMETA_PARTUUID) using the
- * get_unique_guid_for_partition() operation in |AvbOps|. Additionally
- * $(ANDROID_VERITY_MODE) will be replaced with the proper dm-verity
- * option depending on the value of |hashtree_error_mode|.
- *
- * Additionally, the |cmdline| field will have the following kernel
- * command-line options set (unless verification is disabled, see
- * below):
- *
- * androidboot.veritymode: This is set to 'disabled' if the
- * AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED flag is set in top-level
- * vbmeta struct. Otherwise it is set to 'enforcing' if the
- * passed-in hashtree error mode is AVB_HASHTREE_ERROR_MODE_RESTART
- * or AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 'eio' if it's
- * set to AVB_HASHTREE_ERROR_MODE_EIO, and 'logging' if it's set to
- * AVB_HASHTREE_ERROR_MODE_LOGGING.
- *
- * androidboot.vbmeta.invalidate_on_error: This is set to 'yes' only
- * if hashtree validation isn't disabled and the passed-in hashtree
- * error mode is AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE.
- *
- * androidboot.vbmeta.device_state: set to "locked" or "unlocked"
- * depending on the result of the result of AvbOps's
- * read_is_unlocked() function.
- *
- * androidboot.vbmeta.{hash_alg, size, digest}: Will be set to
- * the digest of all images in |vbmeta_images|.
- *
- * androidboot.vbmeta.device: This is set to the value
- * 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.
- *
- * androidboot.vbmeta.avb_version: This is set to the decimal value
- * of AVB_VERSION_MAJOR followed by a dot followed by the decimal
- * value of AVB_VERSION_MINOR, for example "1.0" or "1.4". This
- * version number represents the vbmeta file format version
- * supported by libavb copy used in the boot loader. This is not
- * necessarily the same version number of the on-disk metadata for
- * the slot that was verified.
- *
- * Note that androidboot.slot_suffix is not set in the |cmdline| field
- * in |AvbSlotVerifyData| - you will have to set this yourself.
- *
- * If the |AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED| flag is set
- * in the top-level vbmeta struct then only the top-level vbmeta
- * struct is verified and descriptors will not processed. The return
- * value will be set accordingly (if this flag is set via 'avbctl
- * disable-verification' then the return value will be
- * |AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION|) and
- * |AvbSlotVerifyData| is returned. Additionally all partitions in the
- * |requested_partitions| are loaded and the |cmdline| field is set to
- * "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)" and the GUID for the
- * appropriate system partition is substituted in. Note that none of
- * the androidboot.* options mentioned above will be set.
- *
- * This struct may grow in the future without it being considered an
- * ABI break.
- */
-typedef struct {
- char* ab_suffix;
- AvbVBMetaData* vbmeta_images;
- size_t num_vbmeta_images;
- AvbPartitionData* loaded_partitions;
- size_t num_loaded_partitions;
- char* cmdline;
- uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
-} AvbSlotVerifyData;
-
-/* Frees a |AvbSlotVerifyData| including all data it points to. */
-void avb_slot_verify_data_free(AvbSlotVerifyData* data);
-
-/* Performs a full verification of the slot identified by |ab_suffix|
- * and load and verify the contents of the partitions whose name is in
- * the NULL-terminated string array |requested_partitions| (each
- * partition must use hash verification). If not using A/B, pass an
- * empty string (e.g. "", not NULL) for |ab_suffix|. This parameter
- * must include the leading underscore, for example "_a" should be
- * used to refer to the first slot.
- *
- * Typically the |requested_partitions| array only contains a single
- * item for the boot partition, 'boot'.
- *
- * Verification includes loading and verifying data from the 'vbmeta',
- * the requested hash partitions, and possibly other partitions (with
- * |ab_suffix| appended), inspecting rollback indexes, and checking if
- * the public key used to sign the data is acceptable. The functions
- * in |ops| will be used to do this.
- *
- * If |out_data| is not NULL, it will be set to a newly allocated
- * |AvbSlotVerifyData| struct containing all the data needed to
- * actually boot the slot. This data structure should be freed with
- * avb_slot_verify_data_free() when you are done with it. See below
- * for when this is returned.
- *
- * The |flags| parameter is used to influence the semantics of
- * avb_slot_verify() - for example the
- * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag can be used to
- * ignore verification errors which is something needed in the
- * UNLOCKED state. See the AvbSlotVerifyFlags enumeration for details.
- *
- * The |hashtree_error_mode| parameter should be set to the desired
- * error handling mode when hashtree validation fails inside the
- * HLOS. This value isn't used by libavb per se - it is forwarded to
- * the HLOS through the androidboot.veritymode and
- * androidboot.vbmeta.invalidate_on_error cmdline parameters. See the
- * AvbHashtreeErrorMode enumeration for details.
- *
- * Also note that |out_data| is never set if
- * AVB_SLOT_VERIFY_RESULT_ERROR_OOM, AVB_SLOT_VERIFY_RESULT_ERROR_IO,
- * or AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned.
- *
- * AVB_SLOT_VERIFY_RESULT_OK is returned if everything is verified
- * correctly and all public keys are accepted.
- *
- * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED is returned if
- * everything is verified correctly out but one or more public keys
- * are not accepted. This includes the case where integrity data is
- * not signed.
- *
- * AVB_SLOT_VERIFY_RESULT_ERROR_OOM is returned if unable to
- * allocate memory.
- *
- * AVB_SLOT_VERIFY_RESULT_ERROR_IO is returned if an I/O error
- * occurred while trying to load data or get a rollback index.
- *
- * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION is returned if the data
- * did not verify, e.g. the digest didn't match or signature checks
- * failed.
- *
- * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned if a
- * rollback index was less than its stored value.
- *
- * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned if some
- * of the metadata is invalid or inconsistent.
- *
- * AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION is returned if
- * some of the metadata requires a newer version of libavb than what
- * is in use.
- *
- * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT is returned if the
- * caller passed invalid parameters, for example trying to use
- * AVB_HASHTREE_ERROR_MODE_LOGGING without
- * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
- */
-AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
- const char* const* requested_partitions,
- const char* ab_suffix,
- AvbSlotVerifyFlags flags,
- AvbHashtreeErrorMode hashtree_error_mode,
- AvbSlotVerifyData** out_data);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_SLOT_VERIFY_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_SLOT_VERIFY_H_
+#define AVB_SLOT_VERIFY_H_
+
+#include "avb_ops.h"
+#include "avb_vbmeta_image.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return codes used in avb_slot_verify(), see that function for
+ * documentation for each field.
+ *
+ * Use avb_slot_verify_result_to_string() to get a textual
+ * representation usable for error/debug output.
+ */
+typedef enum {
+ AVB_SLOT_VERIFY_RESULT_OK,
+ AVB_SLOT_VERIFY_RESULT_ERROR_OOM,
+ AVB_SLOT_VERIFY_RESULT_ERROR_IO,
+ AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
+ AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
+ AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
+ AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
+ AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION,
+ AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
+} AvbSlotVerifyResult;
+
+/* Various error handling modes for when verification fails using a
+ * hashtree at runtime inside the HLOS.
+ *
+ * AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE means that the OS
+ * will invalidate the current slot and restart.
+ *
+ * AVB_HASHTREE_ERROR_MODE_RESTART means that the OS will restart.
+ *
+ * AVB_HASHTREE_ERROR_MODE_EIO means that an EIO error will be
+ * returned to applications.
+ *
+ * AVB_HASHTREE_ERROR_MODE_LOGGING means that errors will be logged
+ * and corrupt data may be returned to applications. This mode should
+ * be used ONLY for diagnostics and debugging. It cannot be used
+ * unless AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is also
+ * used.
+ */
+typedef enum {
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+ AVB_HASHTREE_ERROR_MODE_RESTART,
+ AVB_HASHTREE_ERROR_MODE_EIO,
+ AVB_HASHTREE_ERROR_MODE_LOGGING
+} AvbHashtreeErrorMode;
+
+/* Flags that influence how avb_slot_verify() works.
+ *
+ * If AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is NOT set then
+ * avb_slot_verify() will bail out as soon as an error is encountered
+ * and |out_data| is set only if AVB_SLOT_VERIFY_RESULT_OK is
+ * returned.
+ *
+ * Otherwise if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set
+ * avb_slot_verify() will continue verification efforts and |out_data|
+ * is also set if AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
+ * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
+ * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned. It is
+ * undefined which error is returned if more than one distinct error
+ * is encountered. It is guaranteed that AVB_SLOT_VERIFY_RESULT_OK is
+ * returned if, and only if, there are no errors. This mode is needed
+ * to boot valid but unverified slots when the device is unlocked.
+ *
+ * Also, if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set the
+ * contents loaded from |requested_partition| will be the contents of
+ * the entire partition instead of just the size specified in the hash
+ * descriptor.
+ */
+typedef enum {
+ AVB_SLOT_VERIFY_FLAGS_NONE = 0,
+ AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0)
+} AvbSlotVerifyFlags;
+
+/* Get a textual representation of |result|. */
+const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result);
+
+/* Maximum number of rollback index locations supported. */
+#define AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS 32
+
+/* AvbPartitionData contains data loaded from partitions when using
+ * avb_slot_verify(). The |partition_name| field contains the name of
+ * the partition (without A/B suffix), |data| points to the loaded
+ * data which is |data_size| bytes long. If |preloaded| is set to true,
+ * this structure dose not own |data|. The caller of |avb_slot_verify|
+ * needs to make sure that the preloaded data outlives this
+ * |AvbPartitionData| structure.
+ *
+ * Note that this is strictly less than the partition size - it's only
+ * the image stored there, not the entire partition nor any of the
+ * metadata.
+ */
+typedef struct {
+ char* partition_name;
+ uint8_t* data;
+ size_t data_size;
+ bool preloaded;
+} AvbPartitionData;
+
+/* AvbVBMetaData contains a vbmeta struct loaded from a partition when
+ * using avb_slot_verify(). The |partition_name| field contains the
+ * name of the partition (without A/B suffix), |vbmeta_data| points to
+ * the loaded data which is |vbmeta_size| bytes long.
+ *
+ * The |verify_result| field contains the result of
+ * avb_vbmeta_image_verify() on the data. This is guaranteed to be
+ * AVB_VBMETA_VERIFY_RESULT_OK for all vbmeta images if
+ * avb_slot_verify() returns AVB_SLOT_VERIFY_RESULT_OK.
+ *
+ * You can use avb_descriptor_get_all(), avb_descriptor_foreach(), and
+ * avb_vbmeta_image_header_to_host_byte_order() with this data.
+ */
+typedef struct {
+ char* partition_name;
+ uint8_t* vbmeta_data;
+ size_t vbmeta_size;
+ AvbVBMetaVerifyResult verify_result;
+} AvbVBMetaData;
+
+/* AvbSlotVerifyData contains data needed to boot a particular slot
+ * and is returned by avb_slot_verify() if partitions in a slot are
+ * successfully verified.
+ *
+ * All data pointed to by this struct - including data in each item in
+ * the |partitions| array - will be freed when the
+ * avb_slot_verify_data_free() function is called.
+ *
+ * The |ab_suffix| field is the copy of the of |ab_suffix| field
+ * passed to avb_slot_verify(). It is the A/B suffix of the slot. This
+ * value includes the leading underscore - typical values are "" (if
+ * no slots are in use), "_a" (for the first slot), and "_b" (for the
+ * second slot).
+ *
+ * The VBMeta images that were checked are available in the
+ * |vbmeta_images| field. The field |num_vbmeta_images| contains the
+ * number of elements in this array. The first element -
+ * vbmeta_images[0] - is guaranteed to be from the partition with the
+ * top-level vbmeta struct. This is usually the "vbmeta" partition in
+ * the requested slot but if there is no "vbmeta" partition it can
+ * also be the "boot" partition.
+ *
+ * The partitions loaded and verified from from the slot are
+ * accessible in the |loaded_partitions| array. The field
+ * |num_loaded_partitions| contains the number of elements in this
+ * array. The order of partitions in this array may not necessarily be
+ * the same order as in the passed-in |requested_partitions| array.
+ *
+ * Rollback indexes for the verified slot are stored in the
+ * |rollback_indexes| field. Note that avb_slot_verify() will NEVER
+ * modify stored_rollback_index[n] locations e.g. it will never use
+ * the write_rollback_index() AvbOps operation. Instead it is the job
+ * of the caller of avb_slot_verify() to do this based on e.g. A/B
+ * policy and other factors. See libavb_ab/avb_ab_flow.c for an
+ * example of how to do this.
+ *
+ * The |cmdline| field is a NUL-terminated string in UTF-8 resulting
+ * from concatenating all |AvbKernelCmdlineDescriptor| and then
+ * performing proper substitution of the variables
+ * $(ANDROID_SYSTEM_PARTUUID), $(ANDROID_BOOT_PARTUUID), and
+ * $(ANDROID_VBMETA_PARTUUID) using the
+ * get_unique_guid_for_partition() operation in |AvbOps|. Additionally
+ * $(ANDROID_VERITY_MODE) will be replaced with the proper dm-verity
+ * option depending on the value of |hashtree_error_mode|.
+ *
+ * Additionally, the |cmdline| field will have the following kernel
+ * command-line options set (unless verification is disabled, see
+ * below):
+ *
+ * androidboot.veritymode: This is set to 'disabled' if the
+ * AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED flag is set in top-level
+ * vbmeta struct. Otherwise it is set to 'enforcing' if the
+ * passed-in hashtree error mode is AVB_HASHTREE_ERROR_MODE_RESTART
+ * or AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 'eio' if it's
+ * set to AVB_HASHTREE_ERROR_MODE_EIO, and 'logging' if it's set to
+ * AVB_HASHTREE_ERROR_MODE_LOGGING.
+ *
+ * androidboot.vbmeta.invalidate_on_error: This is set to 'yes' only
+ * if hashtree validation isn't disabled and the passed-in hashtree
+ * error mode is AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE.
+ *
+ * androidboot.vbmeta.device_state: set to "locked" or "unlocked"
+ * depending on the result of the result of AvbOps's
+ * read_is_unlocked() function.
+ *
+ * androidboot.vbmeta.{hash_alg, size, digest}: Will be set to
+ * the digest of all images in |vbmeta_images|.
+ *
+ * androidboot.vbmeta.device: This is set to the value
+ * 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.
+ *
+ * androidboot.vbmeta.avb_version: This is set to the decimal value
+ * of AVB_VERSION_MAJOR followed by a dot followed by the decimal
+ * value of AVB_VERSION_MINOR, for example "1.0" or "1.4". This
+ * version number represents the vbmeta file format version
+ * supported by libavb copy used in the boot loader. This is not
+ * necessarily the same version number of the on-disk metadata for
+ * the slot that was verified.
+ *
+ * Note that androidboot.slot_suffix is not set in the |cmdline| field
+ * in |AvbSlotVerifyData| - you will have to set this yourself.
+ *
+ * If the |AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED| flag is set
+ * in the top-level vbmeta struct then only the top-level vbmeta
+ * struct is verified and descriptors will not processed. The return
+ * value will be set accordingly (if this flag is set via 'avbctl
+ * disable-verification' then the return value will be
+ * |AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION|) and
+ * |AvbSlotVerifyData| is returned. Additionally all partitions in the
+ * |requested_partitions| are loaded and the |cmdline| field is set to
+ * "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)" and the GUID for the
+ * appropriate system partition is substituted in. Note that none of
+ * the androidboot.* options mentioned above will be set.
+ *
+ * This struct may grow in the future without it being considered an
+ * ABI break.
+ */
+typedef struct {
+ char* ab_suffix;
+ AvbVBMetaData* vbmeta_images;
+ size_t num_vbmeta_images;
+ AvbPartitionData* loaded_partitions;
+ size_t num_loaded_partitions;
+ char* cmdline;
+ uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
+} AvbSlotVerifyData;
+
+/* Calculates a digest of all vbmeta images in |data| using
+ * the digest indicated by |digest_type|. Stores the result
+ * 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,
+ AvbDigestType digest_type,
+ uint8_t* out_digest);
+
+/* Frees a |AvbSlotVerifyData| including all data it points to. */
+void avb_slot_verify_data_free(AvbSlotVerifyData* data);
+
+/* Performs a full verification of the slot identified by |ab_suffix|
+ * and load and verify the contents of the partitions whose name is in
+ * the NULL-terminated string array |requested_partitions| (each
+ * partition must use hash verification). If not using A/B, pass an
+ * empty string (e.g. "", not NULL) for |ab_suffix|. This parameter
+ * must include the leading underscore, for example "_a" should be
+ * used to refer to the first slot.
+ *
+ * Typically the |requested_partitions| array only contains a single
+ * item for the boot partition, 'boot'.
+ *
+ * Verification includes loading and verifying data from the 'vbmeta',
+ * the requested hash partitions, and possibly other partitions (with
+ * |ab_suffix| appended), inspecting rollback indexes, and checking if
+ * the public key used to sign the data is acceptable. The functions
+ * in |ops| will be used to do this.
+ *
+ * If |out_data| is not NULL, it will be set to a newly allocated
+ * |AvbSlotVerifyData| struct containing all the data needed to
+ * actually boot the slot. This data structure should be freed with
+ * avb_slot_verify_data_free() when you are done with it. See below
+ * for when this is returned.
+ *
+ * The |flags| parameter is used to influence the semantics of
+ * avb_slot_verify() - for example the
+ * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag can be used to
+ * ignore verification errors which is something needed in the
+ * UNLOCKED state. See the AvbSlotVerifyFlags enumeration for details.
+ *
+ * The |hashtree_error_mode| parameter should be set to the desired
+ * error handling mode when hashtree validation fails inside the
+ * HLOS. This value isn't used by libavb per se - it is forwarded to
+ * the HLOS through the androidboot.veritymode and
+ * androidboot.vbmeta.invalidate_on_error cmdline parameters. See the
+ * AvbHashtreeErrorMode enumeration for details.
+ *
+ * Also note that |out_data| is never set if
+ * AVB_SLOT_VERIFY_RESULT_ERROR_OOM, AVB_SLOT_VERIFY_RESULT_ERROR_IO,
+ * or AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned.
+ *
+ * AVB_SLOT_VERIFY_RESULT_OK is returned if everything is verified
+ * correctly and all public keys are accepted.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED is returned if
+ * everything is verified correctly out but one or more public keys
+ * are not accepted. This includes the case where integrity data is
+ * not signed.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_OOM is returned if unable to
+ * allocate memory.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_IO is returned if an I/O error
+ * occurred while trying to load data or get a rollback index.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION is returned if the data
+ * did not verify, e.g. the digest didn't match or signature checks
+ * failed.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned if a
+ * rollback index was less than its stored value.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned if some
+ * of the metadata is invalid or inconsistent.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION is returned if
+ * some of the metadata requires a newer version of libavb than what
+ * is in use.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT is returned if the
+ * caller passed invalid parameters, for example trying to use
+ * AVB_HASHTREE_ERROR_MODE_LOGGING without
+ * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
+ */
+AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ AvbSlotVerifyFlags flags,
+ AvbHashtreeErrorMode hashtree_error_mode,
+ AvbSlotVerifyData** out_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_SLOT_VERIFY_H_ */
diff --git a/include/android_avb/avb_sysdeps.h b/lib/avb/libavb/avb_sysdeps.h
index b2ba7f8321..e68019cfbc 100644
--- a/include/android_avb/avb_sysdeps.h
+++ b/lib/avb/libavb/avb_sysdeps.h
@@ -1,130 +1,128 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_SYSDEPS_H_
-#define AVB_SYSDEPS_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Change these includes to match your platform to bring in the
- * equivalent types available in a normal C runtime. At least things
- * like uint8_t, uint64_t, and bool (with |false|, |true| keywords)
- * must be present.
- */
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stddef.h>
-#ifdef CONFIG_USE_STDINT
-/* Provided by gcc. */
-#include <stdint.h>
-#else
-/* Type for `void *' pointers. */
-typedef unsigned long int uintptr_t;
-#endif
-
-/* If you don't have gcc or clang, these attribute macros may need to
- * be adjusted.
- */
-#define AVB_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#define AVB_ATTR_PACKED __attribute__((packed))
-#define AVB_ATTR_NO_RETURN __attribute__((noreturn))
-#define AVB_ATTR_SENTINEL __attribute__((__sentinel__))
-
-/* Size in bytes used for alignment. */
-#ifdef __LP64__
-#define AVB_ALIGNMENT_SIZE 8
-#else
-#define AVB_ALIGNMENT_SIZE 4
-#endif
-
-/* Compare |n| bytes in |src1| and |src2|.
- *
- * Returns an integer less than, equal to, or greater than zero if the
- * first |n| bytes of |src1| is found, respectively, to be less than,
- * to match, or be greater than the first |n| bytes of |src2|. */
-int avb_memcmp(const void* src1,
- const void* src2,
- size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Compare two strings.
- *
- * Return an integer less than, equal to, or greater than zero if |s1|
- * is found, respectively, to be less than, to match, or be greater
- * than |s2|.
- */
-int avb_strcmp(const char* s1, const char* s2);
-
-/* Copy |n| bytes from |src| to |dest|. */
-void* avb_memcpy(void* dest, const void* src, size_t n);
-
-/* Set |n| bytes starting at |s| to |c|. Returns |dest|. */
-void* avb_memset(void* dest, const int c, size_t n);
-
-/* Prints out a message. The string passed must be a NUL-terminated
- * UTF-8 string.
- */
-void avb_print(const char* message);
-
-/* Prints out a vector of strings. Each argument must point to a
- * NUL-terminated UTF-8 string and NULL should be the last argument.
- */
-void avb_printv(const char* message, ...) AVB_ATTR_SENTINEL;
-
-/* Aborts the program or reboots the device. */
-void avb_abort(void);
-
-/* Allocates |size| bytes. Returns NULL if no memory is available,
- * otherwise a pointer to the allocated memory.
- *
- * The memory is not initialized.
- *
- * The pointer returned is guaranteed to be word-aligned.
- *
- * The memory should be freed with avb_free() when you are done with it.
- */
-void* avb_malloc_(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Frees memory previously allocated with avb_malloc(). */
-void avb_free(void* ptr);
-
-/* Returns the lenght of |str|, excluding the terminating NUL-byte. */
-size_t avb_strlen(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Divide the |dividend| by 10 and saves back to the pointer. Return the
- * remainder. */
-uint32_t avb_div_by_10(uint64_t* dividend);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_SYSDEPS_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_SYSDEPS_H_
+#define AVB_SYSDEPS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Change these includes to match your platform to bring in the
+ * equivalent types available in a normal C runtime. At least things
+ * like uint8_t, uint64_t, and bool (with |false|, |true| keywords)
+ * must be present.
+ */
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stddef.h>
+#ifdef CONFIG_USE_STDINT
+/* Provided by gcc. */
+#include <stdint.h>
+#else
+/* Type for `void *' pointers. */
+typedef unsigned long int uintptr_t;
+#endif
+
+/* If you don't have gcc or clang, these attribute macros may need to
+ * be adjusted.
+ */
+#define AVB_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#define AVB_ATTR_PACKED __attribute__((packed))
+#define AVB_ATTR_NO_RETURN __attribute__((noreturn))
+#define AVB_ATTR_SENTINEL __attribute__((__sentinel__))
+
+/* Size in bytes used for alignment. */
+#ifdef __LP64__
+#define AVB_ALIGNMENT_SIZE 8
+#else
+#define AVB_ALIGNMENT_SIZE 4
+#endif
+
+/* Compare |n| bytes in |src1| and |src2|.
+ *
+ * Returns an integer less than, equal to, or greater than zero if the
+ * first |n| bytes of |src1| is found, respectively, to be less than,
+ * to match, or be greater than the first |n| bytes of |src2|. */
+int avb_memcmp(const void* src1,
+ const void* src2,
+ size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Compare two strings.
+ *
+ * Return an integer less than, equal to, or greater than zero if |s1|
+ * is found, respectively, to be less than, to match, or be greater
+ * than |s2|.
+ */
+int avb_strcmp(const char* s1, const char* s2);
+
+/* Copy |n| bytes from |src| to |dest|. */
+void* avb_memcpy(void* dest, const void* src, size_t n);
+
+/* Set |n| bytes starting at |s| to |c|. Returns |dest|. */
+void* avb_memset(void* dest, const int c, size_t n);
+
+/* Prints out a message. The string passed must be a NUL-terminated
+ * UTF-8 string.
+ */
+void avb_print(const char* message);
+
+/* Prints out a vector of strings. Each argument must point to a
+ * NUL-terminated UTF-8 string and NULL should be the last argument.
+ */
+void avb_printv(const char* message, ...) AVB_ATTR_SENTINEL;
+
+/* Aborts the program or reboots the device. */
+void avb_abort(void) AVB_ATTR_NO_RETURN;
+
+/* Allocates |size| bytes. Returns NULL if no memory is available,
+ * otherwise a pointer to the allocated memory.
+ *
+ * The memory is not initialized.
+ *
+ * The pointer returned is guaranteed to be word-aligned.
+ *
+ * The memory should be freed with avb_free() when you are done with it.
+ */
+void* avb_malloc_(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Frees memory previously allocated with avb_malloc(). */
+void avb_free(void* ptr);
+
+/* Returns the lenght of |str|, excluding the terminating NUL-byte. */
+size_t avb_strlen(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Divide the |dividend| by 10 and saves back to the pointer. Return the
+ * remainder. */
+uint32_t avb_div_by_10(uint64_t* dividend);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_SYSDEPS_H_ */
diff --git a/lib/avb/libavb/avb_sysdeps_posix.c b/lib/avb/libavb/avb_sysdeps_posix.c
index 9df018f7c8..0cbabee06c 100644
--- a/lib/avb/libavb/avb_sysdeps_posix.c
+++ b/lib/avb/libavb/avb_sysdeps_posix.c
@@ -1,87 +1,84 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <common.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <errno.h>
-#include <asm/io.h>
-
-#include <android_avb/avb_sysdeps.h>
-
-void abort(void);
-
-int avb_memcmp(const void* src1, const void* src2, size_t n) {
- return memcmp(src1, src2, n);
-}
-
-void* avb_memcpy(void* dest, const void* src, size_t n) {
- return memcpy(dest, src, n);
-}
-
-void* avb_memset(void* dest, const int c, size_t n) {
- return memset(dest, c, n);
-}
-
-int avb_strcmp(const char* s1, const char* s2) {
- return strcmp(s1, s2);
-}
-
-size_t avb_strlen(const char* str) {
- return strlen(str);
-}
-
-void avb_abort(void) {
- abort();
-}
-
-void avb_print(const char* message) {
- fprintf(stderr, "%s", message);
-}
-
-void avb_printv(const char* message, ...) {
- va_list ap;
- const char* m;
-
- va_start(ap, message);
- for (m = message; m != NULL; m = va_arg(ap, const char*)) {
- fprintf(stderr, "%s", m);
- }
- va_end(ap);
-}
-
-void* avb_malloc_(size_t size) {
- return malloc(size);
-}
-
-void avb_free(void* ptr) {
- free(ptr);
-}
-
-uint32_t avb_div_by_10(uint64_t* dividend) {
- uint32_t rem = (uint32_t)(*dividend % 10);
- *dividend /= 10;
- return rem;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <endian.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avb_sysdeps.h"
+
+int avb_memcmp(const void* src1, const void* src2, size_t n) {
+ return memcmp(src1, src2, n);
+}
+
+void* avb_memcpy(void* dest, const void* src, size_t n) {
+ return memcpy(dest, src, n);
+}
+
+void* avb_memset(void* dest, const int c, size_t n) {
+ return memset(dest, c, n);
+}
+
+int avb_strcmp(const char* s1, const char* s2) {
+ return strcmp(s1, s2);
+}
+
+size_t avb_strlen(const char* str) {
+ return strlen(str);
+}
+
+void avb_abort(void) {
+ abort();
+}
+
+void avb_print(const char* message) {
+ fprintf(stderr, "%s", message);
+}
+
+void avb_printv(const char* message, ...) {
+ va_list ap;
+ const char* m;
+
+ va_start(ap, message);
+ for (m = message; m != NULL; m = va_arg(ap, const char*)) {
+ fprintf(stderr, "%s", m);
+ }
+ va_end(ap);
+}
+
+void* avb_malloc_(size_t size) {
+ return malloc(size);
+}
+
+void avb_free(void* ptr) {
+ free(ptr);
+}
+
+uint32_t avb_div_by_10(uint64_t* dividend) {
+ uint32_t rem = (uint32_t)(*dividend % 10);
+ *dividend /= 10;
+ return rem;
+}
diff --git a/lib/avb/libavb/avb_util.c b/lib/avb/libavb/avb_util.c
index 434cb39e2b..c04c79ae71 100644
--- a/lib/avb/libavb/avb_util.c
+++ b/lib/avb/libavb/avb_util.c
@@ -1,403 +1,430 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_util.h>
-
-#include <stdarg.h>
-
-uint32_t avb_be32toh(uint32_t in) {
- uint8_t* d = (uint8_t*)&in;
- uint32_t ret;
- ret = ((uint32_t)d[0]) << 24;
- ret |= ((uint32_t)d[1]) << 16;
- ret |= ((uint32_t)d[2]) << 8;
- ret |= ((uint32_t)d[3]);
- return ret;
-}
-
-uint64_t avb_be64toh(uint64_t in) {
- uint8_t* d = (uint8_t*)&in;
- uint64_t ret;
- ret = ((uint64_t)d[0]) << 56;
- ret |= ((uint64_t)d[1]) << 48;
- ret |= ((uint64_t)d[2]) << 40;
- ret |= ((uint64_t)d[3]) << 32;
- ret |= ((uint64_t)d[4]) << 24;
- ret |= ((uint64_t)d[5]) << 16;
- ret |= ((uint64_t)d[6]) << 8;
- ret |= ((uint64_t)d[7]);
- return ret;
-}
-
-/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
-uint32_t avb_htobe32(uint32_t in) {
- union {
- uint32_t word;
- uint8_t bytes[4];
- } ret;
- ret.bytes[0] = (in >> 24) & 0xff;
- ret.bytes[1] = (in >> 16) & 0xff;
- ret.bytes[2] = (in >> 8) & 0xff;
- ret.bytes[3] = in & 0xff;
- return ret.word;
-}
-
-/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
-uint64_t avb_htobe64(uint64_t in) {
- union {
- uint64_t word;
- uint8_t bytes[8];
- } ret;
- ret.bytes[0] = (in >> 56) & 0xff;
- ret.bytes[1] = (in >> 48) & 0xff;
- ret.bytes[2] = (in >> 40) & 0xff;
- ret.bytes[3] = (in >> 32) & 0xff;
- ret.bytes[4] = (in >> 24) & 0xff;
- ret.bytes[5] = (in >> 16) & 0xff;
- ret.bytes[6] = (in >> 8) & 0xff;
- ret.bytes[7] = in & 0xff;
- return ret.word;
-}
-
-int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
- const unsigned char* us1 = s1;
- const unsigned char* us2 = s2;
- int result = 0;
-
- if (0 == n) {
- return 0;
- }
-
- /*
- * Code snippet without data-dependent branch due to Nate Lawson
- * (nate@root.org) of Root Labs.
- */
- while (n--) {
- result |= *us1++ ^ *us2++;
- }
-
- return result != 0;
-}
-
-bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
- uint64_t original_value;
-
- avb_assert(value != NULL);
-
- original_value = *value;
-
- *value += value_to_add;
- if (*value < original_value) {
- avb_error("Overflow when adding values.\n");
- return false;
- }
-
- return true;
-}
-
-bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
- uint64_t dummy;
- if (out_result == NULL) {
- out_result = &dummy;
- }
- *out_result = a;
- return avb_safe_add_to(out_result, b);
-}
-
-bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
- size_t n;
- unsigned int num_cc;
-
- for (n = 0, num_cc = 0; n < num_bytes; n++) {
- uint8_t c = data[n];
-
- if (num_cc > 0) {
- if ((c & (0x80 | 0x40)) == 0x80) {
- /* 10xx xxxx */
- } else {
- goto fail;
- }
- num_cc--;
- } else {
- if (c < 0x80) {
- num_cc = 0;
- } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
- /* 110x xxxx */
- num_cc = 1;
- } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
- /* 1110 xxxx */
- num_cc = 2;
- } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
- (0x80 | 0x40 | 0x20 | 0x10)) {
- /* 1111 0xxx */
- num_cc = 3;
- } else {
- goto fail;
- }
- }
- }
-
- if (num_cc != 0) {
- goto fail;
- }
-
- return true;
-
-fail:
- return false;
-}
-
-bool avb_str_concat(char* buf,
- size_t buf_size,
- const char* str1,
- size_t str1_len,
- const char* str2,
- size_t str2_len) {
- uint64_t combined_len;
-
- if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
- avb_error("Overflow when adding string sizes.\n");
- return false;
- }
-
- if (combined_len > buf_size - 1) {
- avb_error("Insufficient buffer space.\n");
- return false;
- }
-
- avb_memcpy(buf, str1, str1_len);
- avb_memcpy(buf + str1_len, str2, str2_len);
- buf[combined_len] = '\0';
-
- return true;
-}
-
-void* avb_malloc(size_t size) {
- void* ret = avb_malloc_(size);
- if (ret == NULL) {
- avb_error("Failed to allocate memory.\n");
- return NULL;
- }
- return ret;
-}
-
-void* avb_calloc(size_t size) {
- void* ret = avb_malloc(size);
- if (ret == NULL) {
- return NULL;
- }
-
- avb_memset(ret, '\0', size);
- return ret;
-}
-
-char* avb_strdup(const char* str) {
- size_t len = avb_strlen(str);
- char* ret = avb_malloc(len + 1);
- if (ret == NULL) {
- return NULL;
- }
-
- avb_memcpy(ret, str, len);
- ret[len] = '\0';
-
- return ret;
-}
-
-const char* avb_strstr(const char* haystack, const char* needle) {
- size_t n, m;
-
- /* Look through |haystack| and check if the first character of
- * |needle| matches. If so, check the rest of |needle|.
- */
- for (n = 0; haystack[n] != '\0'; n++) {
- if (haystack[n] != needle[0]) {
- continue;
- }
-
- for (m = 1;; m++) {
- if (needle[m] == '\0') {
- return haystack + n;
- }
-
- if (haystack[n + m] != needle[m]) {
- break;
- }
- }
- }
-
- return NULL;
-}
-
-const char* avb_strv_find_str(const char* const* strings,
- const char* str,
- size_t str_size) {
- size_t n;
- for (n = 0; strings[n] != NULL; n++) {
- if (avb_strlen(strings[n]) == str_size &&
- avb_memcmp(strings[n], str, str_size) == 0) {
- return strings[n];
- }
- }
- return NULL;
-}
-
-char* avb_replace(const char* str, const char* search, const char* replace) {
- char* ret = NULL;
- size_t ret_len = 0;
- size_t search_len, replace_len;
- const char* str_after_last_replace;
-
- search_len = avb_strlen(search);
- replace_len = avb_strlen(replace);
-
- str_after_last_replace = str;
- while (*str != '\0') {
- const char* s;
- size_t num_before;
- size_t num_new;
-
- s = avb_strstr(str, search);
- if (s == NULL) {
- break;
- }
-
- num_before = s - str;
-
- if (ret == NULL) {
- num_new = num_before + replace_len + 1;
- ret = avb_malloc(num_new);
- if (ret == NULL) {
- goto out;
- }
- avb_memcpy(ret, str, num_before);
- avb_memcpy(ret + num_before, replace, replace_len);
- ret[num_new - 1] = '\0';
- ret_len = num_new - 1;
- } else {
- char* new_str;
- num_new = ret_len + num_before + replace_len + 1;
- new_str = avb_malloc(num_new);
- if (new_str == NULL) {
- goto out;
- }
- avb_memcpy(new_str, ret, ret_len);
- avb_memcpy(new_str + ret_len, str, num_before);
- avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
- new_str[num_new - 1] = '\0';
- avb_free(ret);
- ret = new_str;
- ret_len = num_new - 1;
- }
-
- str = s + search_len;
- str_after_last_replace = str;
- }
-
- if (ret == NULL) {
- ret = avb_strdup(str_after_last_replace);
- if (ret == NULL) {
- goto out;
- }
- } else {
- size_t num_remaining = avb_strlen(str_after_last_replace);
- size_t num_new = ret_len + num_remaining + 1;
- char* new_str = avb_malloc(num_new);
- if (new_str == NULL) {
- goto out;
- }
- avb_memcpy(new_str, ret, ret_len);
- avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
- new_str[num_new - 1] = '\0';
- avb_free(ret);
- ret = new_str;
- ret_len = num_new - 1;
- }
-
-out:
- return ret;
-}
-
-/* We only support a limited amount of strings in avb_strdupv(). */
-#define AVB_STRDUPV_MAX_NUM_STRINGS 32
-
-char* avb_strdupv(const char* str, ...) {
- va_list ap;
- const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
- size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
- size_t num_strings, n;
- uint64_t total_length;
- char *ret = NULL, *dest;
-
- num_strings = 0;
- total_length = 0;
- va_start(ap, str);
- do {
- size_t str_len = avb_strlen(str);
- strings[num_strings] = str;
- lengths[num_strings] = str_len;
- if (!avb_safe_add_to(&total_length, str_len)) {
- avb_fatal("Overflow while determining total length.\n");
- break;
- }
- num_strings++;
- if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
- avb_fatal("Too many strings passed.\n");
- break;
- }
- str = va_arg(ap, const char*);
- } while (str != NULL);
- va_end(ap);
-
- ret = avb_malloc(total_length + 1);
- if (ret == NULL) {
- goto out;
- }
-
- dest = ret;
- for (n = 0; n < num_strings; n++) {
- avb_memcpy(dest, strings[n], lengths[n]);
- dest += lengths[n];
- }
- *dest = '\0';
- avb_assert(dest == ret + total_length);
-
-out:
- return ret;
-}
-
-const char* avb_basename(const char* str) {
- int64_t n;
- size_t len;
-
- len = avb_strlen(str);
- if (len >= 2) {
- for (n = len - 2; n >= 0; n--) {
- if (str[n] == '/') {
- return str + n + 1;
- }
- }
- }
- return str;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_util.h"
+
+#include <stdarg.h>
+
+uint32_t avb_be32toh(uint32_t in) {
+ uint8_t* d = (uint8_t*)&in;
+ uint32_t ret;
+ ret = ((uint32_t)d[0]) << 24;
+ ret |= ((uint32_t)d[1]) << 16;
+ ret |= ((uint32_t)d[2]) << 8;
+ ret |= ((uint32_t)d[3]);
+ return ret;
+}
+
+uint64_t avb_be64toh(uint64_t in) {
+ uint8_t* d = (uint8_t*)&in;
+ uint64_t ret;
+ ret = ((uint64_t)d[0]) << 56;
+ ret |= ((uint64_t)d[1]) << 48;
+ ret |= ((uint64_t)d[2]) << 40;
+ ret |= ((uint64_t)d[3]) << 32;
+ ret |= ((uint64_t)d[4]) << 24;
+ ret |= ((uint64_t)d[5]) << 16;
+ ret |= ((uint64_t)d[6]) << 8;
+ ret |= ((uint64_t)d[7]);
+ return ret;
+}
+
+/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
+uint32_t avb_htobe32(uint32_t in) {
+ union {
+ uint32_t word;
+ uint8_t bytes[4];
+ } ret;
+ ret.bytes[0] = (in >> 24) & 0xff;
+ ret.bytes[1] = (in >> 16) & 0xff;
+ ret.bytes[2] = (in >> 8) & 0xff;
+ ret.bytes[3] = in & 0xff;
+ return ret.word;
+}
+
+/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
+uint64_t avb_htobe64(uint64_t in) {
+ union {
+ uint64_t word;
+ uint8_t bytes[8];
+ } ret;
+ ret.bytes[0] = (in >> 56) & 0xff;
+ ret.bytes[1] = (in >> 48) & 0xff;
+ ret.bytes[2] = (in >> 40) & 0xff;
+ ret.bytes[3] = (in >> 32) & 0xff;
+ ret.bytes[4] = (in >> 24) & 0xff;
+ ret.bytes[5] = (in >> 16) & 0xff;
+ ret.bytes[6] = (in >> 8) & 0xff;
+ ret.bytes[7] = in & 0xff;
+ return ret.word;
+}
+
+int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
+ const unsigned char* us1 = s1;
+ const unsigned char* us2 = s2;
+ int result = 0;
+
+ if (0 == n) {
+ return 0;
+ }
+
+ /*
+ * Code snippet without data-dependent branch due to Nate Lawson
+ * (nate@root.org) of Root Labs.
+ */
+ while (n--) {
+ result |= *us1++ ^ *us2++;
+ }
+
+ return result != 0;
+}
+
+bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
+ uint64_t original_value;
+
+ avb_assert(value != NULL);
+
+ original_value = *value;
+
+ *value += value_to_add;
+ if (*value < original_value) {
+ avb_error("Overflow when adding values.\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
+ uint64_t dummy;
+ if (out_result == NULL) {
+ out_result = &dummy;
+ }
+ *out_result = a;
+ return avb_safe_add_to(out_result, b);
+}
+
+bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
+ size_t n;
+ unsigned int num_cc;
+
+ for (n = 0, num_cc = 0; n < num_bytes; n++) {
+ uint8_t c = data[n];
+
+ if (num_cc > 0) {
+ if ((c & (0x80 | 0x40)) == 0x80) {
+ /* 10xx xxxx */
+ } else {
+ goto fail;
+ }
+ num_cc--;
+ } else {
+ if (c < 0x80) {
+ num_cc = 0;
+ } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
+ /* 110x xxxx */
+ num_cc = 1;
+ } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
+ /* 1110 xxxx */
+ num_cc = 2;
+ } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
+ (0x80 | 0x40 | 0x20 | 0x10)) {
+ /* 1111 0xxx */
+ num_cc = 3;
+ } else {
+ goto fail;
+ }
+ }
+ }
+
+ if (num_cc != 0) {
+ goto fail;
+ }
+
+ return true;
+
+fail:
+ return false;
+}
+
+bool avb_str_concat(char* buf,
+ size_t buf_size,
+ const char* str1,
+ size_t str1_len,
+ const char* str2,
+ size_t str2_len) {
+ uint64_t combined_len;
+
+ if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
+ avb_error("Overflow when adding string sizes.\n");
+ return false;
+ }
+
+ if (combined_len > buf_size - 1) {
+ avb_error("Insufficient buffer space.\n");
+ return false;
+ }
+
+ avb_memcpy(buf, str1, str1_len);
+ avb_memcpy(buf + str1_len, str2, str2_len);
+ buf[combined_len] = '\0';
+
+ return true;
+}
+
+void* avb_malloc(size_t size) {
+ void* ret = avb_malloc_(size);
+ if (ret == NULL) {
+ avb_error("Failed to allocate memory.\n");
+ return NULL;
+ }
+ return ret;
+}
+
+void* avb_calloc(size_t size) {
+ void* ret = avb_malloc(size);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ avb_memset(ret, '\0', size);
+ return ret;
+}
+
+char* avb_strdup(const char* str) {
+ size_t len = avb_strlen(str);
+ char* ret = avb_malloc(len + 1);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ avb_memcpy(ret, str, len);
+ ret[len] = '\0';
+
+ return ret;
+}
+
+const char* avb_strstr(const char* haystack, const char* needle) {
+ size_t n, m;
+
+ /* Look through |haystack| and check if the first character of
+ * |needle| matches. If so, check the rest of |needle|.
+ */
+ for (n = 0; haystack[n] != '\0'; n++) {
+ if (haystack[n] != needle[0]) {
+ continue;
+ }
+
+ for (m = 1;; m++) {
+ if (needle[m] == '\0') {
+ return haystack + n;
+ }
+
+ if (haystack[n + m] != needle[m]) {
+ break;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+const char* avb_strv_find_str(const char* const* strings,
+ const char* str,
+ size_t str_size) {
+ size_t n;
+ for (n = 0; strings[n] != NULL; n++) {
+ if (avb_strlen(strings[n]) == str_size &&
+ avb_memcmp(strings[n], str, str_size) == 0) {
+ return strings[n];
+ }
+ }
+ return NULL;
+}
+
+char* avb_replace(const char* str, const char* search, const char* replace) {
+ char* ret = NULL;
+ size_t ret_len = 0;
+ size_t search_len, replace_len;
+ const char* str_after_last_replace;
+
+ search_len = avb_strlen(search);
+ replace_len = avb_strlen(replace);
+
+ str_after_last_replace = str;
+ while (*str != '\0') {
+ const char* s;
+ size_t num_before;
+ size_t num_new;
+
+ s = avb_strstr(str, search);
+ if (s == NULL) {
+ break;
+ }
+
+ num_before = s - str;
+
+ if (ret == NULL) {
+ num_new = num_before + replace_len + 1;
+ ret = avb_malloc(num_new);
+ if (ret == NULL) {
+ goto out;
+ }
+ avb_memcpy(ret, str, num_before);
+ avb_memcpy(ret + num_before, replace, replace_len);
+ ret[num_new - 1] = '\0';
+ ret_len = num_new - 1;
+ } else {
+ char* new_str;
+ num_new = ret_len + num_before + replace_len + 1;
+ new_str = avb_malloc(num_new);
+ if (new_str == NULL) {
+ goto out;
+ }
+ avb_memcpy(new_str, ret, ret_len);
+ avb_memcpy(new_str + ret_len, str, num_before);
+ avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
+ new_str[num_new - 1] = '\0';
+ avb_free(ret);
+ ret = new_str;
+ ret_len = num_new - 1;
+ }
+
+ str = s + search_len;
+ str_after_last_replace = str;
+ }
+
+ if (ret == NULL) {
+ ret = avb_strdup(str_after_last_replace);
+ if (ret == NULL) {
+ goto out;
+ }
+ } else {
+ size_t num_remaining = avb_strlen(str_after_last_replace);
+ size_t num_new = ret_len + num_remaining + 1;
+ char* new_str = avb_malloc(num_new);
+ if (new_str == NULL) {
+ goto out;
+ }
+ avb_memcpy(new_str, ret, ret_len);
+ avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
+ new_str[num_new - 1] = '\0';
+ avb_free(ret);
+ ret = new_str;
+ ret_len = num_new - 1;
+ }
+
+out:
+ return ret;
+}
+
+/* We only support a limited amount of strings in avb_strdupv(). */
+#define AVB_STRDUPV_MAX_NUM_STRINGS 32
+
+char* avb_strdupv(const char* str, ...) {
+ va_list ap;
+ const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
+ size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
+ size_t num_strings, n;
+ uint64_t total_length;
+ char *ret = NULL, *dest;
+
+ num_strings = 0;
+ total_length = 0;
+ va_start(ap, str);
+ do {
+ size_t str_len = avb_strlen(str);
+ strings[num_strings] = str;
+ lengths[num_strings] = str_len;
+ if (!avb_safe_add_to(&total_length, str_len)) {
+ avb_fatal("Overflow while determining total length.\n");
+ break;
+ }
+ num_strings++;
+ if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
+ avb_fatal("Too many strings passed.\n");
+ break;
+ }
+ str = va_arg(ap, const char*);
+ } while (str != NULL);
+ va_end(ap);
+
+ ret = avb_malloc(total_length + 1);
+ if (ret == NULL) {
+ goto out;
+ }
+
+ dest = ret;
+ for (n = 0; n < num_strings; n++) {
+ avb_memcpy(dest, strings[n], lengths[n]);
+ dest += lengths[n];
+ }
+ *dest = '\0';
+ avb_assert(dest == ret + total_length);
+
+out:
+ return ret;
+}
+
+const char* avb_basename(const char* str) {
+ int64_t n;
+ size_t len;
+
+ len = avb_strlen(str);
+ if (len >= 2) {
+ for (n = len - 2; n >= 0; n--) {
+ if (str[n] == '/') {
+ return str + n + 1;
+ }
+ }
+ }
+ return str;
+}
+
+void avb_uppercase(char* str) {
+ size_t i;
+ for (i = 0; str[i] != '\0'; ++i) {
+ if (str[i] <= 0x7A && str[i] >= 0x61) {
+ str[i] -= 0x20;
+ }
+ }
+}
+
+char* avb_bin2hex(const uint8_t* data, size_t data_len) {
+ const char hex_digits[17] = "0123456789abcdef";
+ char* hex_data;
+ size_t n;
+
+ hex_data = avb_malloc(data_len * 2 + 1);
+ if (hex_data == NULL) {
+ return NULL;
+ }
+
+ for (n = 0; n < data_len; n++) {
+ hex_data[n * 2] = hex_digits[data[n] >> 4];
+ hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
+ }
+ hex_data[n * 2] = '\0';
+ return hex_data;
+}
diff --git a/include/android_avb/avb_util.h b/lib/avb/libavb/avb_util.h
index d23c961e10..be1b3c9b21 100644
--- a/include/android_avb/avb_util.h
+++ b/lib/avb/libavb/avb_util.h
@@ -1,279 +1,287 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_UTIL_H_
-#define AVB_UTIL_H_
-
-#include <android_avb/avb_sysdeps.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define AVB_STRINGIFY(x) #x
-#define AVB_TO_STRING(x) AVB_STRINGIFY(x)
-
-#ifdef AVB_ENABLE_DEBUG
-/* Aborts the program if |expr| is false.
- *
- * This has no effect unless AVB_ENABLE_DEBUG is defined.
- */
-#define avb_assert(expr) \
- do { \
- if (!(expr)) { \
- 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)
-#else
-#define avb_assert_not_reached()
-#endif
-
-/* Aborts the program if |addr| is not word-aligned.
- *
- * This has no effect unless AVB_ENABLE_DEBUG is defined.
- */
-#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__); \
- } 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(); \
- } while (0)
-
-/* 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 32-bit unsigned integer from host to big-endian byte order. */
-uint32_t avb_htobe32(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
-uint64_t avb_htobe64(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Compare |n| bytes starting at |s1| with |s2| and return 0 if they
- * match, 1 if they don't. Returns 0 if |n|==0, since no bytes
- * mismatched.
- *
- * Time taken to perform the comparison is only dependent on |n| and
- * not on the relationship of the match between |s1| and |s2|.
- *
- * Note that unlike avb_memcmp(), this only indicates inequality, not
- * whether |s1| is less than or greater than |s2|.
- */
-int avb_safe_memcmp(const void* s1,
- const void* s2,
- size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Adds |value_to_add| to |value| with overflow protection.
- *
- * Returns false if the addition overflows, true otherwise. In either
- * case, |value| is always modified.
- */
-bool avb_safe_add_to(uint64_t* value,
- uint64_t value_to_add) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Adds |a| and |b| with overflow protection, returning the value in
- * |out_result|.
- *
- * It's permissible to pass NULL for |out_result| if you just want to
- * check that the addition would not overflow.
- *
- * Returns false if the addition overflows, true otherwise.
- */
-bool avb_safe_add(uint64_t* out_result,
- uint64_t a,
- uint64_t b) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Checks if |num_bytes| data at |data| is a valid UTF-8
- * string. Returns true if valid UTF-8, false otherwise.
- */
-bool avb_validate_utf8(const uint8_t* data,
- size_t num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Concatenates |str1| (of |str1_len| bytes) and |str2| (of |str2_len|
- * bytes) and puts the result in |buf| which holds |buf_size|
- * bytes. The result is also guaranteed to be NUL terminated. Fail if
- * there is not enough room in |buf| for the resulting string plus
- * terminating NUL byte.
- *
- * Returns true if the operation succeeds, false otherwise.
- */
-bool avb_str_concat(char* buf,
- size_t buf_size,
- const char* str1,
- size_t str1_len,
- const char* str2,
- size_t str2_len);
-
-/* Like avb_malloc_() but prints a error using avb_error() if memory
- * allocation fails.
- */
-void* avb_malloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Like avb_malloc() but sets the memory with zeroes. */
-void* avb_calloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Duplicates a NUL-terminated string. Returns NULL on OOM. */
-char* avb_strdup(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Duplicates a NULL-terminated array of NUL-terminated strings by
- * concatenating them. The returned string will be
- * NUL-terminated. Returns NULL on OOM.
- */
-char* avb_strdupv(const char* str,
- ...) AVB_ATTR_WARN_UNUSED_RESULT AVB_ATTR_SENTINEL;
-
-/* Finds the first occurrence of |needle| in the string |haystack|
- * where both strings are NUL-terminated strings. The terminating NUL
- * bytes are not compared.
- *
- * Returns NULL if not found, otherwise points into |haystack| for the
- * first occurrence of |needle|.
- */
-const char* avb_strstr(const char* haystack,
- const char* needle) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Finds the first occurrence of |str| in the NULL-terminated string
- * array |strings|. Each element in |strings| must be
- * NUL-terminated. The string given by |str| need not be
- * NUL-terminated but its size must be given in |str_size|.
- *
- * Returns NULL if not found, otherwise points into |strings| for the
- * first occurrence of |str|.
- */
-const char* avb_strv_find_str(const char* const* strings,
- const char* str,
- size_t str_size);
-
-/* Replaces all occurrences of |search| with |replace| in |str|.
- *
- * Returns a newly allocated string or NULL if out of memory.
- */
-char* avb_replace(const char* str,
- const char* search,
- const char* replace) AVB_ATTR_WARN_UNUSED_RESULT;
-
-/* Calculates the CRC-32 for data in |buf| of size |buf_size|. */
-uint32_t avb_crc32(const uint8_t* buf, size_t buf_size);
-
-/* Returns the basename of |str|. This is defined as the last path
- * component, assuming the normal POSIX separator '/'. If there are no
- * separators, returns |str|.
- */
-const char* avb_basename(const char* str);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_UTIL_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_UTIL_H_
+#define AVB_UTIL_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AVB_STRINGIFY(x) #x
+#define AVB_TO_STRING(x) AVB_STRINGIFY(x)
+
+#ifdef AVB_ENABLE_DEBUG
+/* Aborts the program if |expr| is false.
+ *
+ * This has no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#define avb_assert(expr) \
+ do { \
+ if (!(expr)) { \
+ 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)
+#else
+#define avb_assert_not_reached()
+#endif
+
+/* Aborts the program if |addr| is not word-aligned.
+ *
+ * This has no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#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__); \
+ } 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(); \
+ } while (0)
+
+/* 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 32-bit unsigned integer from host to big-endian byte order. */
+uint32_t avb_htobe32(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
+uint64_t avb_htobe64(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Compare |n| bytes starting at |s1| with |s2| and return 0 if they
+ * match, 1 if they don't. Returns 0 if |n|==0, since no bytes
+ * mismatched.
+ *
+ * Time taken to perform the comparison is only dependent on |n| and
+ * not on the relationship of the match between |s1| and |s2|.
+ *
+ * Note that unlike avb_memcmp(), this only indicates inequality, not
+ * whether |s1| is less than or greater than |s2|.
+ */
+int avb_safe_memcmp(const void* s1,
+ const void* s2,
+ size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Adds |value_to_add| to |value| with overflow protection.
+ *
+ * Returns false if the addition overflows, true otherwise. In either
+ * case, |value| is always modified.
+ */
+bool avb_safe_add_to(uint64_t* value,
+ uint64_t value_to_add) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Adds |a| and |b| with overflow protection, returning the value in
+ * |out_result|.
+ *
+ * It's permissible to pass NULL for |out_result| if you just want to
+ * check that the addition would not overflow.
+ *
+ * Returns false if the addition overflows, true otherwise.
+ */
+bool avb_safe_add(uint64_t* out_result,
+ uint64_t a,
+ uint64_t b) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Checks if |num_bytes| data at |data| is a valid UTF-8
+ * string. Returns true if valid UTF-8, false otherwise.
+ */
+bool avb_validate_utf8(const uint8_t* data,
+ size_t num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Concatenates |str1| (of |str1_len| bytes) and |str2| (of |str2_len|
+ * bytes) and puts the result in |buf| which holds |buf_size|
+ * bytes. The result is also guaranteed to be NUL terminated. Fail if
+ * there is not enough room in |buf| for the resulting string plus
+ * terminating NUL byte.
+ *
+ * Returns true if the operation succeeds, false otherwise.
+ */
+bool avb_str_concat(char* buf,
+ size_t buf_size,
+ const char* str1,
+ size_t str1_len,
+ const char* str2,
+ size_t str2_len);
+
+/* Like avb_malloc_() but prints a error using avb_error() if memory
+ * allocation fails.
+ */
+void* avb_malloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Like avb_malloc() but sets the memory with zeroes. */
+void* avb_calloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Duplicates a NUL-terminated string. Returns NULL on OOM. */
+char* avb_strdup(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Duplicates a NULL-terminated array of NUL-terminated strings by
+ * concatenating them. The returned string will be
+ * NUL-terminated. Returns NULL on OOM.
+ */
+char* avb_strdupv(const char* str,
+ ...) AVB_ATTR_WARN_UNUSED_RESULT AVB_ATTR_SENTINEL;
+
+/* Finds the first occurrence of |needle| in the string |haystack|
+ * where both strings are NUL-terminated strings. The terminating NUL
+ * bytes are not compared.
+ *
+ * Returns NULL if not found, otherwise points into |haystack| for the
+ * first occurrence of |needle|.
+ */
+const char* avb_strstr(const char* haystack,
+ const char* needle) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Finds the first occurrence of |str| in the NULL-terminated string
+ * array |strings|. Each element in |strings| must be
+ * NUL-terminated. The string given by |str| need not be
+ * NUL-terminated but its size must be given in |str_size|.
+ *
+ * Returns NULL if not found, otherwise points into |strings| for the
+ * first occurrence of |str|.
+ */
+const char* avb_strv_find_str(const char* const* strings,
+ const char* str,
+ size_t str_size);
+
+/* Replaces all occurrences of |search| with |replace| in |str|.
+ *
+ * Returns a newly allocated string or NULL if out of memory.
+ */
+char* avb_replace(const char* str,
+ const char* search,
+ const char* replace) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Calculates the CRC-32 for data in |buf| of size |buf_size|. */
+uint32_t avb_crc32(const uint8_t* buf, size_t buf_size);
+
+/* Returns the basename of |str|. This is defined as the last path
+ * component, assuming the normal POSIX separator '/'. If there are no
+ * separators, returns |str|.
+ */
+const char* avb_basename(const char* str);
+
+/* Converts any ascii lowercase characters in |str| to uppercase in-place.
+ * |str| must be NUL-terminated and valid UTF-8.
+ */
+void avb_uppercase(char* str);
+
+/* Converts |data_len| bytes of |data| to hex and returns the result. Returns
+ * NULL on OOM. Caller must free the returned string with avb_free.
+ */
+char* avb_bin2hex(const uint8_t* data, size_t data_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_UTIL_H_ */
diff --git a/lib/avb/libavb/avb_vbmeta_image.c b/lib/avb/libavb/avb_vbmeta_image.c
index 3f6d33e90b..21bbf9295d 100644
--- a/lib/avb/libavb/avb_vbmeta_image.c
+++ b/lib/avb/libavb/avb_vbmeta_image.c
@@ -1,308 +1,308 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_vbmeta_image.h>
-#include <android_avb/avb_crypto.h>
-#include <android_avb/avb_rsa.h>
-#include <android_avb/avb_sha.h>
-#include <android_avb/avb_util.h>
-#include <android_avb/avb_version.h>
-
-AvbVBMetaVerifyResult avb_vbmeta_image_verify(
- const uint8_t* data,
- size_t length,
- const uint8_t** out_public_key_data,
- size_t* out_public_key_length) {
- AvbVBMetaVerifyResult ret;
- AvbVBMetaImageHeader h;
- uint8_t* computed_hash;
- const AvbAlgorithmData* algorithm;
- AvbSHA256Ctx sha256_ctx;
- AvbSHA512Ctx sha512_ctx;
- const uint8_t* header_block;
- const uint8_t* authentication_block;
- const uint8_t* auxiliary_block;
- int verification_result;
-
- ret = AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER;
-
- if (out_public_key_data != NULL) {
- *out_public_key_data = NULL;
- }
- if (out_public_key_length != NULL) {
- *out_public_key_length = 0;
- }
-
- /* Ensure magic is correct. */
- if (avb_safe_memcmp(data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
- avb_error("Magic is incorrect.\n");
- goto out;
- }
-
- /* Before we byteswap, ensure length is long enough. */
- if (length < sizeof(AvbVBMetaImageHeader)) {
- avb_error("Length is smaller than header.\n");
- goto out;
- }
- avb_vbmeta_image_header_to_host_byte_order((const AvbVBMetaImageHeader*)data,
- &h);
-
- /* Ensure we don't attempt to access any fields if we do not meet
- * the specified minimum version of libavb.
- */
- if ((h.required_libavb_version_major != AVB_VERSION_MAJOR) ||
- (h.required_libavb_version_minor > AVB_VERSION_MINOR)) {
- avb_error("Mismatch between image version and libavb version.\n");
- ret = AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION;
- goto out;
- }
-
- /* Ensure |release_string| ends with a NUL byte. */
- if (h.release_string[AVB_RELEASE_STRING_SIZE - 1] != '\0') {
- avb_error("Release string does not end with a NUL byte.\n");
- goto out;
- }
-
- /* Ensure inner block sizes are multiple of 64. */
- if ((h.authentication_data_block_size & 0x3f) != 0 ||
- (h.auxiliary_data_block_size & 0x3f) != 0) {
- avb_error("Block size is not a multiple of 64.\n");
- goto out;
- }
-
- /* Ensure block sizes all add up to at most |length|. */
- uint64_t block_total = sizeof(AvbVBMetaImageHeader);
- if (!avb_safe_add_to(&block_total, h.authentication_data_block_size) ||
- !avb_safe_add_to(&block_total, h.auxiliary_data_block_size)) {
- avb_error("Overflow while computing size of boot image.\n");
- goto out;
- }
- if (block_total > length) {
- avb_error("Block sizes add up to more than given length.\n");
- goto out;
- }
-
- uintptr_t data_ptr = (uintptr_t)data;
- /* Ensure passed in memory doesn't wrap. */
- if (!avb_safe_add(NULL, (uint64_t)data_ptr, length)) {
- avb_error("Boot image location and length mismatch.\n");
- goto out;
- }
-
- /* Ensure hash and signature are entirely in the Authentication data block. */
- uint64_t hash_end;
- if (!avb_safe_add(&hash_end, h.hash_offset, h.hash_size) ||
- hash_end > h.authentication_data_block_size) {
- avb_error("Hash is not entirely in its block.\n");
- goto out;
- }
- uint64_t signature_end;
- if (!avb_safe_add(&signature_end, h.signature_offset, h.signature_size) ||
- signature_end > h.authentication_data_block_size) {
- avb_error("Signature is not entirely in its block.\n");
- goto out;
- }
-
- /* Ensure public key is entirely in the Auxiliary data block. */
- uint64_t pubkey_end;
- if (!avb_safe_add(&pubkey_end, h.public_key_offset, h.public_key_size) ||
- pubkey_end > h.auxiliary_data_block_size) {
- avb_error("Public key is not entirely in its block.\n");
- goto out;
- }
-
- /* Ensure public key metadata (if set) is entirely in the Auxiliary
- * data block. */
- if (h.public_key_metadata_size > 0) {
- uint64_t pubkey_md_end;
- if (!avb_safe_add(&pubkey_md_end,
- h.public_key_metadata_offset,
- h.public_key_metadata_size) ||
- pubkey_md_end > h.auxiliary_data_block_size) {
- avb_error("Public key metadata is not entirely in its block.\n");
- goto out;
- }
- }
-
- /* Bail early if there's no hash or signature. */
- if (h.algorithm_type == AVB_ALGORITHM_TYPE_NONE) {
- ret = AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED;
- goto out;
- }
-
- /* Ensure algorithm field is supported. */
- algorithm = avb_get_algorithm_data(h.algorithm_type);
- if (!algorithm) {
- avb_error("Invalid or unknown algorithm.\n");
- goto out;
- }
-
- /* Bail if the embedded hash size doesn't match the chosen algorithm. */
- if (h.hash_size != algorithm->hash_len) {
- avb_error("Embedded hash has wrong size.\n");
- goto out;
- }
-
- /* No overflow checks needed from here-on after since all block
- * sizes and offsets have been verified above.
- */
-
- header_block = data;
- authentication_block = header_block + sizeof(AvbVBMetaImageHeader);
- auxiliary_block = authentication_block + h.authentication_data_block_size;
-
- switch (h.algorithm_type) {
- /* Explicit fall-through: */
- case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
- case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
- case AVB_ALGORITHM_TYPE_SHA256_RSA8192:
- avb_sha256_init(&sha256_ctx);
- avb_sha256_update(
- &sha256_ctx, header_block, sizeof(AvbVBMetaImageHeader));
- avb_sha256_update(
- &sha256_ctx, auxiliary_block, h.auxiliary_data_block_size);
- computed_hash = avb_sha256_final(&sha256_ctx);
- break;
- /* Explicit fall-through: */
- case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
- case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
- case AVB_ALGORITHM_TYPE_SHA512_RSA8192:
- avb_sha512_init(&sha512_ctx);
- avb_sha512_update(
- &sha512_ctx, header_block, sizeof(AvbVBMetaImageHeader));
- avb_sha512_update(
- &sha512_ctx, auxiliary_block, h.auxiliary_data_block_size);
- computed_hash = avb_sha512_final(&sha512_ctx);
- break;
- default:
- avb_error("Unknown algorithm.\n");
- goto out;
- }
-
- if (avb_safe_memcmp(authentication_block + h.hash_offset,
- computed_hash,
- h.hash_size) != 0) {
- avb_error("Hash does not match!\n");
- ret = AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH;
- goto out;
- }
-
- verification_result =
- avb_rsa_verify(auxiliary_block + h.public_key_offset,
- h.public_key_size,
- authentication_block + h.signature_offset,
- h.signature_size,
- authentication_block + h.hash_offset,
- h.hash_size,
- algorithm->padding,
- algorithm->padding_len);
-
- if (verification_result == 0) {
- ret = AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH;
- goto out;
- }
-
- if (h.public_key_size > 0) {
- if (out_public_key_data != NULL) {
- *out_public_key_data = auxiliary_block + h.public_key_offset;
- }
- if (out_public_key_length != NULL) {
- *out_public_key_length = h.public_key_size;
- }
- }
-
- ret = AVB_VBMETA_VERIFY_RESULT_OK;
-
-out:
- return ret;
-}
-
-void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
- AvbVBMetaImageHeader* dest) {
- avb_memcpy(dest, src, sizeof(AvbVBMetaImageHeader));
-
- dest->required_libavb_version_major =
- avb_be32toh(dest->required_libavb_version_major);
- dest->required_libavb_version_minor =
- avb_be32toh(dest->required_libavb_version_minor);
-
- dest->authentication_data_block_size =
- avb_be64toh(dest->authentication_data_block_size);
- dest->auxiliary_data_block_size =
- avb_be64toh(dest->auxiliary_data_block_size);
-
- dest->algorithm_type = avb_be32toh(dest->algorithm_type);
-
- dest->hash_offset = avb_be64toh(dest->hash_offset);
- dest->hash_size = avb_be64toh(dest->hash_size);
-
- dest->signature_offset = avb_be64toh(dest->signature_offset);
- dest->signature_size = avb_be64toh(dest->signature_size);
-
- dest->public_key_offset = avb_be64toh(dest->public_key_offset);
- dest->public_key_size = avb_be64toh(dest->public_key_size);
-
- dest->public_key_metadata_offset =
- avb_be64toh(dest->public_key_metadata_offset);
- dest->public_key_metadata_size = avb_be64toh(dest->public_key_metadata_size);
-
- dest->descriptors_offset = avb_be64toh(dest->descriptors_offset);
- dest->descriptors_size = avb_be64toh(dest->descriptors_size);
-
- dest->rollback_index = avb_be64toh(dest->rollback_index);
- dest->flags = avb_be32toh(dest->flags);
-}
-
-const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) {
- const char* ret = NULL;
-
- switch (result) {
- case AVB_VBMETA_VERIFY_RESULT_OK:
- ret = "OK";
- break;
- case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
- ret = "OK_NOT_SIGNED";
- break;
- case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
- ret = "INVALID_VBMETA_HEADER";
- break;
- case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
- ret = "UNSUPPORTED_VERSION";
- break;
- case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
- ret = "HASH_MISMATCH";
- break;
- case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
- ret = "SIGNATURE_MISMATCH";
- break;
- /* Do not add a 'default:' case here because of -Wswitch. */
- }
-
- if (ret == NULL) {
- avb_error("Unknown AvbVBMetaVerifyResult value.\n");
- ret = "(unknown)";
- }
-
- return ret;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_vbmeta_image.h"
+#include "avb_crypto.h"
+#include "avb_rsa.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_version.h"
+
+AvbVBMetaVerifyResult avb_vbmeta_image_verify(
+ const uint8_t* data,
+ size_t length,
+ const uint8_t** out_public_key_data,
+ size_t* out_public_key_length) {
+ AvbVBMetaVerifyResult ret;
+ AvbVBMetaImageHeader h;
+ uint8_t* computed_hash;
+ const AvbAlgorithmData* algorithm;
+ AvbSHA256Ctx sha256_ctx;
+ AvbSHA512Ctx sha512_ctx;
+ const uint8_t* header_block;
+ const uint8_t* authentication_block;
+ const uint8_t* auxiliary_block;
+ int verification_result;
+
+ ret = AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER;
+
+ if (out_public_key_data != NULL) {
+ *out_public_key_data = NULL;
+ }
+ if (out_public_key_length != NULL) {
+ *out_public_key_length = 0;
+ }
+
+ /* Ensure magic is correct. */
+ if (avb_safe_memcmp(data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+ avb_error("Magic is incorrect.\n");
+ goto out;
+ }
+
+ /* Before we byteswap, ensure length is long enough. */
+ if (length < sizeof(AvbVBMetaImageHeader)) {
+ avb_error("Length is smaller than header.\n");
+ goto out;
+ }
+ avb_vbmeta_image_header_to_host_byte_order((const AvbVBMetaImageHeader*)data,
+ &h);
+
+ /* Ensure we don't attempt to access any fields if we do not meet
+ * the specified minimum version of libavb.
+ */
+ if ((h.required_libavb_version_major != AVB_VERSION_MAJOR) ||
+ (h.required_libavb_version_minor > AVB_VERSION_MINOR)) {
+ avb_error("Mismatch between image version and libavb version.\n");
+ ret = AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION;
+ goto out;
+ }
+
+ /* Ensure |release_string| ends with a NUL byte. */
+ if (h.release_string[AVB_RELEASE_STRING_SIZE - 1] != '\0') {
+ avb_error("Release string does not end with a NUL byte.\n");
+ goto out;
+ }
+
+ /* Ensure inner block sizes are multiple of 64. */
+ if ((h.authentication_data_block_size & 0x3f) != 0 ||
+ (h.auxiliary_data_block_size & 0x3f) != 0) {
+ avb_error("Block size is not a multiple of 64.\n");
+ goto out;
+ }
+
+ /* Ensure block sizes all add up to at most |length|. */
+ uint64_t block_total = sizeof(AvbVBMetaImageHeader);
+ if (!avb_safe_add_to(&block_total, h.authentication_data_block_size) ||
+ !avb_safe_add_to(&block_total, h.auxiliary_data_block_size)) {
+ avb_error("Overflow while computing size of boot image.\n");
+ goto out;
+ }
+ if (block_total > length) {
+ avb_error("Block sizes add up to more than given length.\n");
+ goto out;
+ }
+
+ uintptr_t data_ptr = (uintptr_t)data;
+ /* Ensure passed in memory doesn't wrap. */
+ if (!avb_safe_add(NULL, (uint64_t)data_ptr, length)) {
+ avb_error("Boot image location and length mismatch.\n");
+ goto out;
+ }
+
+ /* Ensure hash and signature are entirely in the Authentication data block. */
+ uint64_t hash_end;
+ if (!avb_safe_add(&hash_end, h.hash_offset, h.hash_size) ||
+ hash_end > h.authentication_data_block_size) {
+ avb_error("Hash is not entirely in its block.\n");
+ goto out;
+ }
+ uint64_t signature_end;
+ if (!avb_safe_add(&signature_end, h.signature_offset, h.signature_size) ||
+ signature_end > h.authentication_data_block_size) {
+ avb_error("Signature is not entirely in its block.\n");
+ goto out;
+ }
+
+ /* Ensure public key is entirely in the Auxiliary data block. */
+ uint64_t pubkey_end;
+ if (!avb_safe_add(&pubkey_end, h.public_key_offset, h.public_key_size) ||
+ pubkey_end > h.auxiliary_data_block_size) {
+ avb_error("Public key is not entirely in its block.\n");
+ goto out;
+ }
+
+ /* Ensure public key metadata (if set) is entirely in the Auxiliary
+ * data block. */
+ if (h.public_key_metadata_size > 0) {
+ uint64_t pubkey_md_end;
+ if (!avb_safe_add(&pubkey_md_end,
+ h.public_key_metadata_offset,
+ h.public_key_metadata_size) ||
+ pubkey_md_end > h.auxiliary_data_block_size) {
+ avb_error("Public key metadata is not entirely in its block.\n");
+ goto out;
+ }
+ }
+
+ /* Bail early if there's no hash or signature. */
+ if (h.algorithm_type == AVB_ALGORITHM_TYPE_NONE) {
+ ret = AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED;
+ goto out;
+ }
+
+ /* Ensure algorithm field is supported. */
+ algorithm = avb_get_algorithm_data(h.algorithm_type);
+ if (!algorithm) {
+ avb_error("Invalid or unknown algorithm.\n");
+ goto out;
+ }
+
+ /* Bail if the embedded hash size doesn't match the chosen algorithm. */
+ if (h.hash_size != algorithm->hash_len) {
+ avb_error("Embedded hash has wrong size.\n");
+ goto out;
+ }
+
+ /* No overflow checks needed from here-on after since all block
+ * sizes and offsets have been verified above.
+ */
+
+ header_block = data;
+ authentication_block = header_block + sizeof(AvbVBMetaImageHeader);
+ auxiliary_block = authentication_block + h.authentication_data_block_size;
+
+ switch (h.algorithm_type) {
+ /* Explicit fall-through: */
+ case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA8192:
+ avb_sha256_init(&sha256_ctx);
+ avb_sha256_update(
+ &sha256_ctx, header_block, sizeof(AvbVBMetaImageHeader));
+ avb_sha256_update(
+ &sha256_ctx, auxiliary_block, h.auxiliary_data_block_size);
+ computed_hash = avb_sha256_final(&sha256_ctx);
+ break;
+ /* Explicit fall-through: */
+ case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
+ case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
+ case AVB_ALGORITHM_TYPE_SHA512_RSA8192:
+ avb_sha512_init(&sha512_ctx);
+ avb_sha512_update(
+ &sha512_ctx, header_block, sizeof(AvbVBMetaImageHeader));
+ avb_sha512_update(
+ &sha512_ctx, auxiliary_block, h.auxiliary_data_block_size);
+ computed_hash = avb_sha512_final(&sha512_ctx);
+ break;
+ default:
+ avb_error("Unknown algorithm.\n");
+ goto out;
+ }
+
+ if (avb_safe_memcmp(authentication_block + h.hash_offset,
+ computed_hash,
+ h.hash_size) != 0) {
+ avb_error("Hash does not match!\n");
+ ret = AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH;
+ goto out;
+ }
+
+ verification_result =
+ avb_rsa_verify(auxiliary_block + h.public_key_offset,
+ h.public_key_size,
+ authentication_block + h.signature_offset,
+ h.signature_size,
+ authentication_block + h.hash_offset,
+ h.hash_size,
+ algorithm->padding,
+ algorithm->padding_len);
+
+ if (verification_result == 0) {
+ ret = AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH;
+ goto out;
+ }
+
+ if (h.public_key_size > 0) {
+ if (out_public_key_data != NULL) {
+ *out_public_key_data = auxiliary_block + h.public_key_offset;
+ }
+ if (out_public_key_length != NULL) {
+ *out_public_key_length = h.public_key_size;
+ }
+ }
+
+ ret = AVB_VBMETA_VERIFY_RESULT_OK;
+
+out:
+ return ret;
+}
+
+void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
+ AvbVBMetaImageHeader* dest) {
+ avb_memcpy(dest, src, sizeof(AvbVBMetaImageHeader));
+
+ dest->required_libavb_version_major =
+ avb_be32toh(dest->required_libavb_version_major);
+ dest->required_libavb_version_minor =
+ avb_be32toh(dest->required_libavb_version_minor);
+
+ dest->authentication_data_block_size =
+ avb_be64toh(dest->authentication_data_block_size);
+ dest->auxiliary_data_block_size =
+ avb_be64toh(dest->auxiliary_data_block_size);
+
+ dest->algorithm_type = avb_be32toh(dest->algorithm_type);
+
+ dest->hash_offset = avb_be64toh(dest->hash_offset);
+ dest->hash_size = avb_be64toh(dest->hash_size);
+
+ dest->signature_offset = avb_be64toh(dest->signature_offset);
+ dest->signature_size = avb_be64toh(dest->signature_size);
+
+ dest->public_key_offset = avb_be64toh(dest->public_key_offset);
+ dest->public_key_size = avb_be64toh(dest->public_key_size);
+
+ dest->public_key_metadata_offset =
+ avb_be64toh(dest->public_key_metadata_offset);
+ dest->public_key_metadata_size = avb_be64toh(dest->public_key_metadata_size);
+
+ dest->descriptors_offset = avb_be64toh(dest->descriptors_offset);
+ dest->descriptors_size = avb_be64toh(dest->descriptors_size);
+
+ dest->rollback_index = avb_be64toh(dest->rollback_index);
+ dest->flags = avb_be32toh(dest->flags);
+}
+
+const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) {
+ const char* ret = NULL;
+
+ switch (result) {
+ case AVB_VBMETA_VERIFY_RESULT_OK:
+ ret = "OK";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
+ ret = "OK_NOT_SIGNED";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
+ ret = "INVALID_VBMETA_HEADER";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
+ ret = "UNSUPPORTED_VERSION";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
+ ret = "HASH_MISMATCH";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
+ ret = "SIGNATURE_MISMATCH";
+ break;
+ /* Do not add a 'default:' case here because of -Wswitch. */
+ }
+
+ if (ret == NULL) {
+ avb_error("Unknown AvbVBMetaVerifyResult value.\n");
+ ret = "(unknown)";
+ }
+
+ return ret;
+}
diff --git a/include/android_avb/avb_vbmeta_image.h b/lib/avb/libavb/avb_vbmeta_image.h
index fbd82ff65b..d0c9f15376 100644
--- a/include/android_avb/avb_vbmeta_image.h
+++ b/lib/avb/libavb/avb_vbmeta_image.h
@@ -1,296 +1,294 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_VBMETA_IMAGE_H_
-#define AVB_VBMETA_IMAGE_H_
-
-#include <android_avb/avb_sysdeps.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "avb_crypto.h"
-#include "avb_descriptor.h"
-
-/* Size of the vbmeta image header. */
-#define AVB_VBMETA_IMAGE_HEADER_SIZE 256
-
-/* Magic for the vbmeta image header. */
-#define AVB_MAGIC "AVB0"
-#define AVB_MAGIC_LEN 4
-
-/* Maximum size of the release string including the terminating NUL byte. */
-#define AVB_RELEASE_STRING_SIZE 48
-
-/* Flags for the vbmeta image.
- *
- * AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED: If this flag is set,
- * hashtree image verification will be disabled.
- *
- * AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: If this flag is set,
- * verification will be disabled and descriptors will not be parsed.
- */
-typedef enum {
- AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = (1 << 0),
- AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED = (1 << 1)
-} AvbVBMetaImageFlags;
-
-/* Binary format for header of the vbmeta image.
- *
- * The vbmeta image consists of three blocks:
- *
- * +-----------------------------------------+
- * | Header data - fixed size |
- * +-----------------------------------------+
- * | Authentication data - variable size |
- * +-----------------------------------------+
- * | Auxiliary data - variable size |
- * +-----------------------------------------+
- *
- * The "Header data" block is described by this struct and is always
- * |AVB_VBMETA_IMAGE_HEADER_SIZE| bytes long.
- *
- * The "Authentication data" block is |authentication_data_block_size|
- * bytes long and contains the hash and signature used to authenticate
- * the vbmeta image. The type of the hash and signature is defined by
- * the |algorithm_type| field.
- *
- * The "Auxiliary data" is |auxiliary_data_block_size| bytes long and
- * contains the auxiliary data including the public key used to make
- * the signature and descriptors.
- *
- * The public key is at offset |public_key_offset| with size
- * |public_key_size| in this block. The size of the public key data is
- * defined by the |algorithm_type| field. The format of the public key
- * data is described in the |AvbRSAPublicKeyHeader| struct.
- *
- * The descriptors starts at |descriptors_offset| from the beginning
- * of the "Auxiliary Data" block and take up |descriptors_size|
- * bytes. Each descriptor is stored as a |AvbDescriptor| with tag and
- * number of bytes following. The number of descriptors can be
- * determined by walking this data until |descriptors_size| is
- * exhausted.
- *
- * The size of each of the "Authentication data" and "Auxiliary data"
- * blocks must be divisible by 64. This is to ensure proper alignment.
- *
- * Descriptors are free-form blocks stored in a part of the vbmeta
- * image subject to the same integrity checks as the rest of the
- * image. See the documentation for |AvbDescriptor| for well-known
- * descriptors. See avb_descriptor_foreach() for a convenience
- * function to iterate over descriptors.
- *
- * This struct is versioned, see the |required_libavb_version_major|
- * and |required_libavb_version_minor| fields. This represents the
- * minimum version of libavb required to verify the header and depends
- * on the features (e.g. algorithms, descriptors) used. Note that this
- * may be 1.0 even if generated by an avbtool from 1.4 but where no
- * features introduced after 1.0 has been used. See the "Versioning
- * and compatibility" section in the README.md file for more details.
- *
- * All fields are stored in network byte order when serialized. To
- * generate a copy with fields swapped to native byte order, use the
- * function avb_vbmeta_image_header_to_host_byte_order().
- *
- * Before reading and/or using any of this data, you MUST verify it
- * using avb_vbmeta_image_verify() and reject it unless it's signed by
- * a known good public key.
- */
-typedef struct AvbVBMetaImageHeader {
- /* 0: Four bytes equal to "AVB0" (AVB_MAGIC). */
- uint8_t magic[AVB_MAGIC_LEN];
-
- /* 4: The major version of libavb required for this header. */
- uint32_t required_libavb_version_major;
- /* 8: The minor version of libavb required for this header. */
- uint32_t required_libavb_version_minor;
-
- /* 12: The size of the signature block. */
- uint64_t authentication_data_block_size;
- /* 20: The size of the auxiliary data block. */
- uint64_t auxiliary_data_block_size;
-
- /* 28: The verification algorithm used, see |AvbAlgorithmType| enum. */
- uint32_t algorithm_type;
-
- /* 32: Offset into the "Authentication data" block of hash data. */
- uint64_t hash_offset;
- /* 40: Length of the hash data. */
- uint64_t hash_size;
-
- /* 48: Offset into the "Authentication data" block of signature data. */
- uint64_t signature_offset;
- /* 56: Length of the signature data. */
- uint64_t signature_size;
-
- /* 64: Offset into the "Auxiliary data" block of public key data. */
- uint64_t public_key_offset;
- /* 72: Length of the public key data. */
- uint64_t public_key_size;
-
- /* 80: Offset into the "Auxiliary data" block of public key metadata. */
- uint64_t public_key_metadata_offset;
- /* 88: Length of the public key metadata. Must be set to zero if there
- * is no public key metadata.
- */
- uint64_t public_key_metadata_size;
-
- /* 96: Offset into the "Auxiliary data" block of descriptor data. */
- uint64_t descriptors_offset;
- /* 104: Length of descriptor data. */
- uint64_t descriptors_size;
-
- /* 112: The rollback index which can be used to prevent rollback to
- * older versions.
- */
- uint64_t rollback_index;
-
- /* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be
- * set to zero if the vbmeta image is not a top-level image.
- */
- uint32_t flags;
-
- /* 124: Reserved to ensure |release_string| start on a 16-byte
- * boundary. Must be set to zeroes.
- */
- uint8_t reserved0[4];
-
- /* 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
- * terminated. Applications must not make assumptions about how this
- * string is formatted.
- */
- uint8_t release_string[AVB_RELEASE_STRING_SIZE];
-
- /* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
- * bytes. This must be set to zeroes.
- */
- uint8_t reserved[80];
-} AVB_ATTR_PACKED AvbVBMetaImageHeader;
-
-/* Copies |src| to |dest|, byte-swapping fields in the process.
- *
- * Make sure you've verified |src| using avb_vbmeta_image_verify()
- * before accessing the data and/or using this function.
- */
-void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
- AvbVBMetaImageHeader* dest);
-
-/* Return codes used in avb_vbmeta_image_verify().
- *
- * AVB_VBMETA_VERIFY_RESULT_OK is returned if the vbmeta image header
- * is valid, the hash is correct and the signature is correct. Keep in
- * mind that you still need to check that you know the public key used
- * to sign the image, see avb_vbmeta_image_verify() for details.
- *
- * AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED is returned if the vbmeta
- * image header is valid but there is no signature or hash.
- *
- * AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER is returned if the
- * header of the vbmeta image is invalid, for example, invalid magic
- * or inconsistent data.
- *
- * AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION is returned if a) the
- * vbmeta image requires a minimum version of libavb which exceeds the
- * version of libavb used; or b) the vbmeta image major version
- * differs from the major version of libavb in use.
- *
- * AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH is returned if the hash
- * stored in the "Authentication data" block does not match the
- * calculated hash.
- *
- * AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH is returned if the
- * signature stored in the "Authentication data" block is invalid or
- * doesn't match the public key stored in the vbmeta image.
- */
-typedef enum {
- AVB_VBMETA_VERIFY_RESULT_OK,
- AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED,
- AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
- AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION,
- AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH,
- AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH,
-} AvbVBMetaVerifyResult;
-
-/* Get a textual representation of |result|. */
-const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result);
-
-/* Checks that vbmeta image at |data| of size |length| is a valid
- * vbmeta image. The complete contents of the vbmeta image must be
- * passed in. It's fine if |length| is bigger than the actual image,
- * typically callers of this function will load the entire contents of
- * the 'vbmeta_a' or 'vbmeta_b' partition and pass in its length (for
- * example, 1 MiB).
- *
- * See the |AvbVBMetaImageHeader| struct for information about the
- * three blocks (header, authentication, auxiliary) that make up a
- * vbmeta image.
- *
- * If the function returns |AVB_VBMETA_VERIFY_RESULT_OK| and
- * |out_public_key_data| is non-NULL, it will be set to point inside
- * |data| for where the serialized public key data is stored and
- * |out_public_key_length|, if non-NULL, will be set to the length of
- * the public key data. If there is no public key in the metadata then
- * |out_public_key_data| is set to NULL.
- *
- * See the |AvbVBMetaVerifyResult| enum for possible return values.
- *
- * VERY IMPORTANT:
- *
- * 1. Even if |AVB_VBMETA_VERIFY_RESULT_OK| is returned, you still
- * need to check that the public key embedded in the image
- * matches a known key! You can use 'avbtool extract_public_key'
- * to extract the key (at build time, then store it along your
- * code) and compare it to what is returned in
- * |out_public_key_data|.
- *
- * 2. You need to check the |rollback_index| field against a stored
- * value in NVRAM and reject the vbmeta image if the value in
- * NVRAM is bigger than |rollback_index|. You must also update
- * the value stored in NVRAM to the smallest value of
- * |rollback_index| field from boot images in all bootable and
- * authentic slots marked as GOOD.
- *
- * This is a low-level function to only verify the vbmeta data - you
- * are likely looking for avb_slot_verify() instead for verifying
- * integrity data for a whole set of partitions.
- */
-AvbVBMetaVerifyResult avb_vbmeta_image_verify(
- const uint8_t* data,
- size_t length,
- const uint8_t** out_public_key_data,
- size_t* out_public_key_length) AVB_ATTR_WARN_UNUSED_RESULT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_VBMETA_IMAGE_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_VBMETA_IMAGE_H_
+#define AVB_VBMETA_IMAGE_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avb_crypto.h"
+#include "avb_descriptor.h"
+
+/* Size of the vbmeta image header. */
+#define AVB_VBMETA_IMAGE_HEADER_SIZE 256
+
+/* Magic for the vbmeta image header. */
+#define AVB_MAGIC "AVB0"
+#define AVB_MAGIC_LEN 4
+
+/* Maximum size of the release string including the terminating NUL byte. */
+#define AVB_RELEASE_STRING_SIZE 48
+
+/* Flags for the vbmeta image.
+ *
+ * AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED: If this flag is set,
+ * hashtree image verification will be disabled.
+ *
+ * AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: If this flag is set,
+ * verification will be disabled and descriptors will not be parsed.
+ */
+typedef enum {
+ AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = (1 << 0),
+ AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED = (1 << 1)
+} AvbVBMetaImageFlags;
+
+/* Binary format for header of the vbmeta image.
+ *
+ * The vbmeta image consists of three blocks:
+ *
+ * +-----------------------------------------+
+ * | Header data - fixed size |
+ * +-----------------------------------------+
+ * | Authentication data - variable size |
+ * +-----------------------------------------+
+ * | Auxiliary data - variable size |
+ * +-----------------------------------------+
+ *
+ * The "Header data" block is described by this struct and is always
+ * |AVB_VBMETA_IMAGE_HEADER_SIZE| bytes long.
+ *
+ * The "Authentication data" block is |authentication_data_block_size|
+ * bytes long and contains the hash and signature used to authenticate
+ * the vbmeta image. The type of the hash and signature is defined by
+ * the |algorithm_type| field.
+ *
+ * The "Auxiliary data" is |auxiliary_data_block_size| bytes long and
+ * contains the auxiliary data including the public key used to make
+ * the signature and descriptors.
+ *
+ * The public key is at offset |public_key_offset| with size
+ * |public_key_size| in this block. The size of the public key data is
+ * defined by the |algorithm_type| field. The format of the public key
+ * data is described in the |AvbRSAPublicKeyHeader| struct.
+ *
+ * The descriptors starts at |descriptors_offset| from the beginning
+ * of the "Auxiliary Data" block and take up |descriptors_size|
+ * bytes. Each descriptor is stored as a |AvbDescriptor| with tag and
+ * number of bytes following. The number of descriptors can be
+ * determined by walking this data until |descriptors_size| is
+ * exhausted.
+ *
+ * The size of each of the "Authentication data" and "Auxiliary data"
+ * blocks must be divisible by 64. This is to ensure proper alignment.
+ *
+ * Descriptors are free-form blocks stored in a part of the vbmeta
+ * image subject to the same integrity checks as the rest of the
+ * image. See the documentation for |AvbDescriptor| for well-known
+ * descriptors. See avb_descriptor_foreach() for a convenience
+ * function to iterate over descriptors.
+ *
+ * This struct is versioned, see the |required_libavb_version_major|
+ * and |required_libavb_version_minor| fields. This represents the
+ * minimum version of libavb required to verify the header and depends
+ * on the features (e.g. algorithms, descriptors) used. Note that this
+ * may be 1.0 even if generated by an avbtool from 1.4 but where no
+ * features introduced after 1.0 has been used. See the "Versioning
+ * and compatibility" section in the README.md file for more details.
+ *
+ * All fields are stored in network byte order when serialized. To
+ * generate a copy with fields swapped to native byte order, use the
+ * function avb_vbmeta_image_header_to_host_byte_order().
+ *
+ * Before reading and/or using any of this data, you MUST verify it
+ * using avb_vbmeta_image_verify() and reject it unless it's signed by
+ * a known good public key.
+ */
+typedef struct AvbVBMetaImageHeader {
+ /* 0: Four bytes equal to "AVB0" (AVB_MAGIC). */
+ uint8_t magic[AVB_MAGIC_LEN];
+
+ /* 4: The major version of libavb required for this header. */
+ uint32_t required_libavb_version_major;
+ /* 8: The minor version of libavb required for this header. */
+ uint32_t required_libavb_version_minor;
+
+ /* 12: The size of the signature block. */
+ uint64_t authentication_data_block_size;
+ /* 20: The size of the auxiliary data block. */
+ uint64_t auxiliary_data_block_size;
+
+ /* 28: The verification algorithm used, see |AvbAlgorithmType| enum. */
+ uint32_t algorithm_type;
+
+ /* 32: Offset into the "Authentication data" block of hash data. */
+ uint64_t hash_offset;
+ /* 40: Length of the hash data. */
+ uint64_t hash_size;
+
+ /* 48: Offset into the "Authentication data" block of signature data. */
+ uint64_t signature_offset;
+ /* 56: Length of the signature data. */
+ uint64_t signature_size;
+
+ /* 64: Offset into the "Auxiliary data" block of public key data. */
+ uint64_t public_key_offset;
+ /* 72: Length of the public key data. */
+ uint64_t public_key_size;
+
+ /* 80: Offset into the "Auxiliary data" block of public key metadata. */
+ uint64_t public_key_metadata_offset;
+ /* 88: Length of the public key metadata. Must be set to zero if there
+ * is no public key metadata.
+ */
+ uint64_t public_key_metadata_size;
+
+ /* 96: Offset into the "Auxiliary data" block of descriptor data. */
+ uint64_t descriptors_offset;
+ /* 104: Length of descriptor data. */
+ uint64_t descriptors_size;
+
+ /* 112: The rollback index which can be used to prevent rollback to
+ * older versions.
+ */
+ uint64_t rollback_index;
+
+ /* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be
+ * set to zero if the vbmeta image is not a top-level image.
+ */
+ uint32_t flags;
+
+ /* 124: Reserved to ensure |release_string| start on a 16-byte
+ * boundary. Must be set to zeroes.
+ */
+ uint8_t reserved0[4];
+
+ /* 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
+ * terminated. Applications must not make assumptions about how this
+ * string is formatted.
+ */
+ uint8_t release_string[AVB_RELEASE_STRING_SIZE];
+
+ /* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
+ * bytes. This must be set to zeroes.
+ */
+ uint8_t reserved[80];
+} AVB_ATTR_PACKED AvbVBMetaImageHeader;
+
+/* Copies |src| to |dest|, byte-swapping fields in the process.
+ *
+ * Make sure you've verified |src| using avb_vbmeta_image_verify()
+ * before accessing the data and/or using this function.
+ */
+void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
+ AvbVBMetaImageHeader* dest);
+
+/* Return codes used in avb_vbmeta_image_verify().
+ *
+ * AVB_VBMETA_VERIFY_RESULT_OK is returned if the vbmeta image header
+ * is valid, the hash is correct and the signature is correct. Keep in
+ * mind that you still need to check that you know the public key used
+ * to sign the image, see avb_vbmeta_image_verify() for details.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED is returned if the vbmeta
+ * image header is valid but there is no signature or hash.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER is returned if the
+ * header of the vbmeta image is invalid, for example, invalid magic
+ * or inconsistent data.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION is returned if a) the
+ * vbmeta image requires a minimum version of libavb which exceeds the
+ * version of libavb used; or b) the vbmeta image major version
+ * differs from the major version of libavb in use.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH is returned if the hash
+ * stored in the "Authentication data" block does not match the
+ * calculated hash.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH is returned if the
+ * signature stored in the "Authentication data" block is invalid or
+ * doesn't match the public key stored in the vbmeta image.
+ */
+typedef enum {
+ AVB_VBMETA_VERIFY_RESULT_OK,
+ AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED,
+ AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
+ AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION,
+ AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH,
+ AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH,
+} AvbVBMetaVerifyResult;
+
+/* Get a textual representation of |result|. */
+const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result);
+
+/* Checks that vbmeta image at |data| of size |length| is a valid
+ * vbmeta image. The complete contents of the vbmeta image must be
+ * passed in. It's fine if |length| is bigger than the actual image,
+ * typically callers of this function will load the entire contents of
+ * the 'vbmeta_a' or 'vbmeta_b' partition and pass in its length (for
+ * example, 1 MiB).
+ *
+ * See the |AvbVBMetaImageHeader| struct for information about the
+ * three blocks (header, authentication, auxiliary) that make up a
+ * vbmeta image.
+ *
+ * If the function returns |AVB_VBMETA_VERIFY_RESULT_OK| and
+ * |out_public_key_data| is non-NULL, it will be set to point inside
+ * |data| for where the serialized public key data is stored and
+ * |out_public_key_length|, if non-NULL, will be set to the length of
+ * the public key data. If there is no public key in the metadata then
+ * |out_public_key_data| is set to NULL.
+ *
+ * See the |AvbVBMetaVerifyResult| enum for possible return values.
+ *
+ * VERY IMPORTANT:
+ *
+ * 1. Even if |AVB_VBMETA_VERIFY_RESULT_OK| is returned, you still
+ * need to check that the public key embedded in the image
+ * matches a known key! You can use 'avbtool extract_public_key'
+ * to extract the key (at build time, then store it along your
+ * code) and compare it to what is returned in
+ * |out_public_key_data|.
+ *
+ * 2. You need to check the |rollback_index| field against a stored
+ * value in NVRAM and reject the vbmeta image if the value in
+ * NVRAM is bigger than |rollback_index|. You must also update
+ * the value stored in NVRAM to the smallest value of
+ * |rollback_index| field from boot images in all bootable and
+ * authentic slots marked as GOOD.
+ *
+ * This is a low-level function to only verify the vbmeta data - you
+ * are likely looking for avb_slot_verify() instead for verifying
+ * integrity data for a whole set of partitions.
+ */
+AvbVBMetaVerifyResult avb_vbmeta_image_verify(
+ const uint8_t* data,
+ size_t length,
+ const uint8_t** out_public_key_data,
+ size_t* out_public_key_length) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_VBMETA_IMAGE_H_ */
diff --git a/lib/avb/libavb/avb_version.c b/lib/avb/libavb/avb_version.c
index 915e3c8388..31f5fa6bf1 100644
--- a/lib/avb/libavb/avb_version.c
+++ b/lib/avb/libavb/avb_version.c
@@ -1,34 +1,34 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_version.h>
-
-#define AVB_QUOTE(str) #str
-#define AVB_EXPAND_AND_QUOTE(str) AVB_QUOTE(str)
-
-/* Keep in sync with get_release_string() in avbtool. */
-const char* avb_version_string(void) {
- return AVB_EXPAND_AND_QUOTE(AVB_VERSION_MAJOR) "." AVB_EXPAND_AND_QUOTE(
- AVB_VERSION_MINOR) "." AVB_EXPAND_AND_QUOTE(AVB_VERSION_SUB);
-}
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_version.h"
+
+#define AVB_QUOTE(str) #str
+#define AVB_EXPAND_AND_QUOTE(str) AVB_QUOTE(str)
+
+/* Keep in sync with get_release_string() in avbtool. */
+const char* avb_version_string(void) {
+ return AVB_EXPAND_AND_QUOTE(AVB_VERSION_MAJOR) "." AVB_EXPAND_AND_QUOTE(
+ AVB_VERSION_MINOR) "." AVB_EXPAND_AND_QUOTE(AVB_VERSION_SUB);
+}
diff --git a/include/android_avb/avb_version.h b/lib/avb/libavb/avb_version.h
index 48e11705a9..ce4313604e 100644
--- a/include/android_avb/avb_version.h
+++ b/lib/avb/libavb/avb_version.h
@@ -1,61 +1,59 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb.h instead."
-#endif
-*/
-
-#ifndef AVB_VERSION_H_
-#define AVB_VERSION_H_
-
-#include <android_avb/avb_sysdeps.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* The version number of AVB - keep in sync with avbtool. */
-#define AVB_VERSION_MAJOR 1
-#define AVB_VERSION_MINOR 0
-#define AVB_VERSION_SUB 0
-
-/* Returns a NUL-terminated string for the libavb version in use. The
- * returned string usually looks like "%d.%d.%d". Applications must
- * not make assumptions about the content of this string.
- *
- * Boot loaders should display this string in debug/diagnostics output
- * to aid with debugging.
- *
- * This is similar to the string put in the |release_string| string
- * field in the VBMeta struct by avbtool.
- */
-const char* avb_version_string(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_VERSION_H_ */
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_VERSION_H_
+#define AVB_VERSION_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The version number of AVB - keep in sync with avbtool. */
+#define AVB_VERSION_MAJOR 1
+#define AVB_VERSION_MINOR 1
+#define AVB_VERSION_SUB 0
+
+/* Returns a NUL-terminated string for the libavb version in use. The
+ * returned string usually looks like "%d.%d.%d". Applications must
+ * not make assumptions about the content of this string.
+ *
+ * Boot loaders should display this string in debug/diagnostics output
+ * to aid with debugging.
+ *
+ * This is similar to the string put in the |release_string| string
+ * field in the VBMeta struct by avbtool.
+ */
+const char* avb_version_string(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_VERSION_H_ */
diff --git a/include/android_avb/libavb.h b/lib/avb/libavb/libavb.h
index 0e2b9c7cac..d511584653 100644
--- a/include/android_avb/libavb.h
+++ b/lib/avb/libavb/libavb.h
@@ -1,50 +1,50 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef LIBAVB_H_
-#define LIBAVB_H_
-
-/* The AVB_INSIDE_LIBAVB_H preprocessor symbol is used to enforce
- * library users to include only this file. All public interfaces, and
- * only public interfaces, must be included here.
- */
-
-#define AVB_INSIDE_LIBAVB_H
-#include <android_avb/avb_chain_partition_descriptor.h>
-#include <android_avb/avb_crypto.h>
-#include <android_avb/avb_descriptor.h>
-#include <android_avb/avb_footer.h>
-#include <android_avb/avb_hash_descriptor.h>
-#include <android_avb/avb_hashtree_descriptor.h>
-#include <android_avb/avb_kernel_cmdline_descriptor.h>
-#include <android_avb/avb_ops.h>
-#include <android_avb/avb_property_descriptor.h>
-#include <android_avb/avb_slot_verify.h>
-#include <android_avb/avb_sysdeps.h>
-#include <android_avb/avb_util.h>
-#include <android_avb/avb_vbmeta_image.h>
-#include <android_avb/avb_version.h>
-#undef AVB_INSIDE_LIBAVB_H
-
-#endif /* LIBAVB_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef LIBAVB_H_
+#define LIBAVB_H_
+
+/* The AVB_INSIDE_LIBAVB_H preprocessor symbol is used to enforce
+ * library users to include only this file. All public interfaces, and
+ * only public interfaces, must be included here.
+ */
+
+#define AVB_INSIDE_LIBAVB_H
+#include "avb_chain_partition_descriptor.h"
+#include "avb_crypto.h"
+#include "avb_descriptor.h"
+#include "avb_footer.h"
+#include "avb_hash_descriptor.h"
+#include "avb_hashtree_descriptor.h"
+#include "avb_kernel_cmdline_descriptor.h"
+#include "avb_ops.h"
+#include "avb_property_descriptor.h"
+#include "avb_slot_verify.h"
+#include "avb_sysdeps.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+#include "avb_version.h"
+#undef AVB_INSIDE_LIBAVB_H
+
+#endif /* LIBAVB_H_ */
diff --git a/lib/avb/libavb_ab/Makefile b/lib/avb/libavb_ab/Makefile
index 9b1aa04880..66e813ff74 100644
--- a/lib/avb/libavb_ab/Makefile
+++ b/lib/avb/libavb_ab/Makefile
@@ -1 +1,2 @@
+ccflags-y += -DAVB_COMPILATION
obj-y += avb_ab_flow.o
diff --git a/lib/avb/libavb_ab/avb_ab_flow.c b/lib/avb/libavb_ab/avb_ab_flow.c
index 55f0a04065..bf6eab1542 100644
--- a/lib/avb/libavb_ab/avb_ab_flow.c
+++ b/lib/avb/libavb_ab/avb_ab_flow.c
@@ -1,531 +1,531 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_ab_flow.h>
-
-bool avb_ab_data_verify_and_byteswap(const AvbABData* src, AvbABData* dest) {
- /* Ensure magic is correct. */
- if (avb_safe_memcmp(src->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
- avb_error("Magic is incorrect.\n");
- return false;
- }
-
- avb_memcpy(dest, src, sizeof(AvbABData));
- dest->crc32 = avb_be32toh(dest->crc32);
-
- /* Ensure we don't attempt to access any fields if the major version
- * is not supported.
- */
- if (dest->version_major > AVB_AB_MAJOR_VERSION) {
- avb_error("No support for given major version.\n");
- return false;
- }
-
- /* Bail if CRC32 doesn't match. */
- if (dest->crc32 !=
- avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))) {
- avb_error("CRC32 does not match.\n");
- return false;
- }
-
- return true;
-}
-
-void avb_ab_data_update_crc_and_byteswap(const AvbABData* src,
- AvbABData* dest) {
- avb_memcpy(dest, src, sizeof(AvbABData));
- dest->crc32 = avb_htobe32(
- avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t)));
-}
-
-void avb_ab_data_init(AvbABData* data) {
- avb_memset(data, '\0', sizeof(AvbABData));
- avb_memcpy(data->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN);
- data->version_major = AVB_AB_MAJOR_VERSION;
- data->version_minor = AVB_AB_MINOR_VERSION;
- data->slots[0].priority = AVB_AB_MAX_PRIORITY;
- data->slots[0].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
- data->slots[0].successful_boot = 0;
- data->slots[1].priority = AVB_AB_MAX_PRIORITY - 1;
- data->slots[1].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
- data->slots[1].successful_boot = 0;
-}
-
-/* The AvbABData struct is stored 2048 bytes into the 'misc' partition
- * following the 'struct bootloader_message' field. The struct is
- * compatible with the guidelines in bootable/recovery/bootloader.h -
- * e.g. it is stored in the |slot_suffix| field, starts with a
- * NUL-byte, and is 32 bytes long.
- */
-#define AB_METADATA_MISC_PARTITION_OFFSET 2048
-
-AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data) {
- AvbOps* ops = ab_ops->ops;
- AvbABData serialized;
- AvbIOResult io_ret;
- size_t num_bytes_read;
-
- io_ret = ops->read_from_partition(ops,
- "misc",
- AB_METADATA_MISC_PARTITION_OFFSET,
- sizeof(AvbABData),
- &serialized,
- &num_bytes_read);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- return AVB_IO_RESULT_ERROR_OOM;
- } else if (io_ret != AVB_IO_RESULT_OK ||
- num_bytes_read != sizeof(AvbABData)) {
- avb_error("Error reading A/B metadata.\n");
- return AVB_IO_RESULT_ERROR_IO;
- }
-
- if (!avb_ab_data_verify_and_byteswap(&serialized, data)) {
- avb_error(
- "Error validating A/B metadata from disk. "
- "Resetting and writing new A/B metadata to disk.\n");
- avb_ab_data_init(data);
- return avb_ab_data_write(ab_ops, data);
- }
-
- return AVB_IO_RESULT_OK;
-}
-
-AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data) {
- AvbOps* ops = ab_ops->ops;
- AvbABData serialized;
- AvbIOResult io_ret;
-
- avb_ab_data_update_crc_and_byteswap(data, &serialized);
- io_ret = ops->write_to_partition(ops,
- "misc",
- AB_METADATA_MISC_PARTITION_OFFSET,
- sizeof(AvbABData),
- &serialized);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- return AVB_IO_RESULT_ERROR_OOM;
- } else if (io_ret != AVB_IO_RESULT_OK) {
- avb_error("Error writing A/B metadata.\n");
- return AVB_IO_RESULT_ERROR_IO;
- }
- return AVB_IO_RESULT_OK;
-}
-
-static bool slot_is_bootable(AvbABSlotData* slot) {
- return slot->priority > 0 &&
- (slot->successful_boot || (slot->tries_remaining > 0));
-}
-
-static void slot_set_unbootable(AvbABSlotData* slot) {
- slot->priority = 0;
- slot->tries_remaining = 0;
- slot->successful_boot = 0;
-}
-
-/* Ensure all unbootable and/or illegal states are marked as the
- * canonical 'unbootable' state, e.g. priority=0, tries_remaining=0,
- * and successful_boot=0.
- */
-static void slot_normalize(AvbABSlotData* slot) {
- if (slot->priority > 0) {
- if (slot->tries_remaining == 0 && !slot->successful_boot) {
- /* We've exhausted all tries -> unbootable. */
- slot_set_unbootable(slot);
- }
- if (slot->tries_remaining > 0 && slot->successful_boot) {
- /* Illegal state - avb_ab_mark_slot_successful() will clear
- * tries_remaining when setting successful_boot.
- */
- slot_set_unbootable(slot);
- }
- } else {
- slot_set_unbootable(slot);
- }
-}
-
-static const char* slot_suffixes[2] = {"_a", "_b"};
-
-/* Helper function to load metadata - returns AVB_IO_RESULT_OK on
- * success, error code otherwise.
- */
-static AvbIOResult load_metadata(AvbABOps* ab_ops,
- AvbABData* ab_data,
- AvbABData* ab_data_orig) {
- AvbIOResult io_ret;
-
- io_ret = ab_ops->read_ab_metadata(ab_ops, ab_data);
- if (io_ret != AVB_IO_RESULT_OK) {
- avb_error("I/O error while loading A/B metadata.\n");
- return io_ret;
- }
- *ab_data_orig = *ab_data;
-
- /* Ensure data is normalized, e.g. illegal states will be marked as
- * unbootable and all unbootable states are represented with
- * (priority=0, tries_remaining=0, successful_boot=0).
- */
- slot_normalize(&ab_data->slots[0]);
- slot_normalize(&ab_data->slots[1]);
- return AVB_IO_RESULT_OK;
-}
-
-/* Writes A/B metadata to disk only if it has changed - returns
- * AVB_IO_RESULT_OK on success, error code otherwise.
- */
-static AvbIOResult save_metadata_if_changed(AvbABOps* ab_ops,
- AvbABData* ab_data,
- AvbABData* ab_data_orig) {
- if (avb_safe_memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) {
- avb_debug("Writing A/B metadata to disk.\n");
- return ab_ops->write_ab_metadata(ab_ops, ab_data);
- }
- return AVB_IO_RESULT_OK;
-}
-
-AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
- const char* const* requested_partitions,
- AvbSlotVerifyFlags flags,
- AvbHashtreeErrorMode hashtree_error_mode,
- AvbSlotVerifyData** out_data) {
- AvbOps* ops = ab_ops->ops;
- AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
- AvbSlotVerifyData* data = NULL;
- AvbABFlowResult ret;
- AvbABData ab_data, ab_data_orig;
- size_t slot_index_to_boot, n;
- AvbIOResult io_ret;
- bool saw_and_allowed_verification_error = false;
-
- io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
- goto out;
- } else if (io_ret != AVB_IO_RESULT_OK) {
- ret = AVB_AB_FLOW_RESULT_ERROR_IO;
- goto out;
- }
-
- /* Validate all bootable slots. */
- for (n = 0; n < 2; n++) {
- if (slot_is_bootable(&ab_data.slots[n])) {
- AvbSlotVerifyResult verify_result;
- bool set_slot_unbootable = false;
-
- verify_result = avb_slot_verify(ops,
- requested_partitions,
- slot_suffixes[n],
- flags,
- hashtree_error_mode,
- &slot_data[n]);
- switch (verify_result) {
- case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
- ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
- goto out;
-
- case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
- ret = AVB_AB_FLOW_RESULT_ERROR_IO;
- goto out;
-
- case AVB_SLOT_VERIFY_RESULT_OK:
- break;
-
- case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
- case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
- /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
- * these mean game over.
- */
- set_slot_unbootable = true;
- break;
-
- /* explicit fallthrough. */
- case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
- case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
- case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
- if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
- /* Do nothing since we allow this. */
- avb_debugv("Allowing slot ",
- slot_suffixes[n],
- " which verified "
- "with result ",
- avb_slot_verify_result_to_string(verify_result),
- " because "
- "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
- "is set.\n",
- NULL);
- saw_and_allowed_verification_error = true;
- } else {
- set_slot_unbootable = true;
- }
- break;
-
- case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
- ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
- goto out;
- /* Do not add a 'default:' case here because of -Wswitch. */
- }
-
- if (set_slot_unbootable) {
- avb_errorv("Error verifying slot ",
- slot_suffixes[n],
- " with result ",
- avb_slot_verify_result_to_string(verify_result),
- " - setting unbootable.\n",
- NULL);
- slot_set_unbootable(&ab_data.slots[n]);
- }
- }
- }
-
- if (slot_is_bootable(&ab_data.slots[0]) &&
- slot_is_bootable(&ab_data.slots[1])) {
- if (ab_data.slots[1].priority > ab_data.slots[0].priority) {
- slot_index_to_boot = 1;
- } else {
- slot_index_to_boot = 0;
- }
- } else if (slot_is_bootable(&ab_data.slots[0])) {
- slot_index_to_boot = 0;
- } else if (slot_is_bootable(&ab_data.slots[1])) {
- slot_index_to_boot = 1;
- } else {
- /* No bootable slots! */
- avb_error("No bootable slots found.\n");
- ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
- goto out;
- }
-
- /* Update stored rollback index such that the stored rollback index
- * is the largest value supporting all currently bootable slots. Do
- * this for every rollback index location.
- */
- for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
- uint64_t rollback_index_value = 0;
-
- if (slot_data[0] != NULL && slot_data[1] != NULL) {
- uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n];
- uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n];
- rollback_index_value =
- (a_rollback_index < b_rollback_index ? a_rollback_index
- : b_rollback_index);
- } else if (slot_data[0] != NULL) {
- rollback_index_value = slot_data[0]->rollback_indexes[n];
- } else if (slot_data[1] != NULL) {
- rollback_index_value = slot_data[1]->rollback_indexes[n];
- }
-
- if (rollback_index_value != 0) {
- uint64_t current_rollback_index_value;
- io_ret = ops->read_rollback_index(ops, n, &current_rollback_index_value);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
- goto out;
- } else if (io_ret != AVB_IO_RESULT_OK) {
- avb_error("Error getting rollback index for slot.\n");
- ret = AVB_AB_FLOW_RESULT_ERROR_IO;
- goto out;
- }
- if (current_rollback_index_value != rollback_index_value) {
- io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
- goto out;
- } else if (io_ret != AVB_IO_RESULT_OK) {
- avb_error("Error setting stored rollback index.\n");
- ret = AVB_AB_FLOW_RESULT_ERROR_IO;
- goto out;
- }
- }
- }
- }
-
- /* Finally, select this slot. */
- avb_assert(slot_data[slot_index_to_boot] != NULL);
- data = slot_data[slot_index_to_boot];
- slot_data[slot_index_to_boot] = NULL;
- if (saw_and_allowed_verification_error) {
- avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
- ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
- } else {
- ret = AVB_AB_FLOW_RESULT_OK;
- }
-
- /* ... and decrement tries remaining, if applicable. */
- if (!ab_data.slots[slot_index_to_boot].successful_boot &&
- ab_data.slots[slot_index_to_boot].tries_remaining > 0) {
- ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
- }
-
-out:
- io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
- if (io_ret != AVB_IO_RESULT_OK) {
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
- } else {
- ret = AVB_AB_FLOW_RESULT_ERROR_IO;
- }
- if (data != NULL) {
- avb_slot_verify_data_free(data);
- data = NULL;
- }
- }
-
- for (n = 0; n < 2; n++) {
- if (slot_data[n] != NULL) {
- avb_slot_verify_data_free(slot_data[n]);
- }
- }
-
- if (out_data != NULL) {
- *out_data = data;
- } else {
- if (data != NULL) {
- avb_slot_verify_data_free(data);
- }
- }
-
- return ret;
-}
-
-AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops,
- unsigned int slot_number) {
- AvbABData ab_data, ab_data_orig;
- unsigned int other_slot_number;
- AvbIOResult ret;
-
- avb_assert(slot_number < 2);
-
- ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
- if (ret != AVB_IO_RESULT_OK) {
- goto out;
- }
-
- /* Make requested slot top priority, unsuccessful, and with max tries. */
- ab_data.slots[slot_number].priority = AVB_AB_MAX_PRIORITY;
- ab_data.slots[slot_number].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
- ab_data.slots[slot_number].successful_boot = 0;
-
- /* Ensure other slot doesn't have as high a priority. */
- other_slot_number = 1 - slot_number;
- if (ab_data.slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) {
- ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1;
- }
-
- ret = AVB_IO_RESULT_OK;
-
-out:
- if (ret == AVB_IO_RESULT_OK) {
- ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
- }
- return ret;
-}
-
-AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops,
- unsigned int slot_number) {
- AvbABData ab_data, ab_data_orig;
- AvbIOResult ret;
-
- avb_assert(slot_number < 2);
-
- ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
- if (ret != AVB_IO_RESULT_OK) {
- goto out;
- }
-
- slot_set_unbootable(&ab_data.slots[slot_number]);
-
- ret = AVB_IO_RESULT_OK;
-
-out:
- if (ret == AVB_IO_RESULT_OK) {
- ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
- }
- return ret;
-}
-
-AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops,
- unsigned int slot_number) {
- AvbABData ab_data, ab_data_orig;
- AvbIOResult ret;
-
- avb_assert(slot_number < 2);
-
- ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
- if (ret != AVB_IO_RESULT_OK) {
- goto out;
- }
-
- if (!slot_is_bootable(&ab_data.slots[slot_number])) {
- avb_error("Cannot mark unbootable slot as successful.\n");
- ret = AVB_IO_RESULT_OK;
- goto out;
- }
-
- ab_data.slots[slot_number].tries_remaining = 0;
- ab_data.slots[slot_number].successful_boot = 1;
-
- ret = AVB_IO_RESULT_OK;
-
-out:
- if (ret == AVB_IO_RESULT_OK) {
- ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
- }
- return ret;
-}
-
-const char* avb_ab_flow_result_to_string(AvbABFlowResult result) {
- const char* ret = NULL;
-
- switch (result) {
- case AVB_AB_FLOW_RESULT_OK:
- ret = "OK";
- break;
-
- case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR:
- ret = "OK_WITH_VERIFICATION_ERROR";
- break;
-
- case AVB_AB_FLOW_RESULT_ERROR_OOM:
- ret = "ERROR_OOM";
- break;
-
- case AVB_AB_FLOW_RESULT_ERROR_IO:
- ret = "ERROR_IO";
- break;
-
- case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS:
- ret = "ERROR_NO_BOOTABLE_SLOTS";
- break;
-
- case AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT:
- ret = "ERROR_INVALID_ARGUMENT";
- break;
- /* Do not add a 'default:' case here because of -Wswitch. */
- }
-
- if (ret == NULL) {
- avb_error("Unknown AvbABFlowResult value.\n");
- ret = "(unknown)";
- }
-
- return ret;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_ab_flow.h"
+
+bool avb_ab_data_verify_and_byteswap(const AvbABData* src, AvbABData* dest) {
+ /* Ensure magic is correct. */
+ if (avb_safe_memcmp(src->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
+ avb_error("Magic is incorrect.\n");
+ return false;
+ }
+
+ avb_memcpy(dest, src, sizeof(AvbABData));
+ dest->crc32 = avb_be32toh(dest->crc32);
+
+ /* Ensure we don't attempt to access any fields if the major version
+ * is not supported.
+ */
+ if (dest->version_major > AVB_AB_MAJOR_VERSION) {
+ avb_error("No support for given major version.\n");
+ return false;
+ }
+
+ /* Bail if CRC32 doesn't match. */
+ if (dest->crc32 !=
+ avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))) {
+ avb_error("CRC32 does not match.\n");
+ return false;
+ }
+
+ return true;
+}
+
+void avb_ab_data_update_crc_and_byteswap(const AvbABData* src,
+ AvbABData* dest) {
+ avb_memcpy(dest, src, sizeof(AvbABData));
+ dest->crc32 = avb_htobe32(
+ avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t)));
+}
+
+void avb_ab_data_init(AvbABData* data) {
+ avb_memset(data, '\0', sizeof(AvbABData));
+ avb_memcpy(data->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN);
+ data->version_major = AVB_AB_MAJOR_VERSION;
+ data->version_minor = AVB_AB_MINOR_VERSION;
+ data->slots[0].priority = AVB_AB_MAX_PRIORITY;
+ data->slots[0].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
+ data->slots[0].successful_boot = 0;
+ data->slots[1].priority = AVB_AB_MAX_PRIORITY - 1;
+ data->slots[1].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
+ data->slots[1].successful_boot = 0;
+}
+
+/* The AvbABData struct is stored 2048 bytes into the 'misc' partition
+ * following the 'struct bootloader_message' field. The struct is
+ * compatible with the guidelines in bootable/recovery/bootloader.h -
+ * e.g. it is stored in the |slot_suffix| field, starts with a
+ * NUL-byte, and is 32 bytes long.
+ */
+#define AB_METADATA_MISC_PARTITION_OFFSET 2048
+
+AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data) {
+ AvbOps* ops = ab_ops->ops;
+ AvbABData serialized;
+ AvbIOResult io_ret;
+ size_t num_bytes_read;
+
+ io_ret = ops->read_from_partition(ops,
+ "misc",
+ AB_METADATA_MISC_PARTITION_OFFSET,
+ sizeof(AvbABData),
+ &serialized,
+ &num_bytes_read);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_IO_RESULT_ERROR_OOM;
+ } else if (io_ret != AVB_IO_RESULT_OK ||
+ num_bytes_read != sizeof(AvbABData)) {
+ avb_error("Error reading A/B metadata.\n");
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ if (!avb_ab_data_verify_and_byteswap(&serialized, data)) {
+ avb_error(
+ "Error validating A/B metadata from disk. "
+ "Resetting and writing new A/B metadata to disk.\n");
+ avb_ab_data_init(data);
+ return avb_ab_data_write(ab_ops, data);
+ }
+
+ return AVB_IO_RESULT_OK;
+}
+
+AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data) {
+ AvbOps* ops = ab_ops->ops;
+ AvbABData serialized;
+ AvbIOResult io_ret;
+
+ avb_ab_data_update_crc_and_byteswap(data, &serialized);
+ io_ret = ops->write_to_partition(ops,
+ "misc",
+ AB_METADATA_MISC_PARTITION_OFFSET,
+ sizeof(AvbABData),
+ &serialized);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_IO_RESULT_ERROR_OOM;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error writing A/B metadata.\n");
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ return AVB_IO_RESULT_OK;
+}
+
+static bool slot_is_bootable(AvbABSlotData* slot) {
+ return slot->priority > 0 &&
+ (slot->successful_boot || (slot->tries_remaining > 0));
+}
+
+static void slot_set_unbootable(AvbABSlotData* slot) {
+ slot->priority = 0;
+ slot->tries_remaining = 0;
+ slot->successful_boot = 0;
+}
+
+/* Ensure all unbootable and/or illegal states are marked as the
+ * canonical 'unbootable' state, e.g. priority=0, tries_remaining=0,
+ * and successful_boot=0.
+ */
+static void slot_normalize(AvbABSlotData* slot) {
+ if (slot->priority > 0) {
+ if (slot->tries_remaining == 0 && !slot->successful_boot) {
+ /* We've exhausted all tries -> unbootable. */
+ slot_set_unbootable(slot);
+ }
+ if (slot->tries_remaining > 0 && slot->successful_boot) {
+ /* Illegal state - avb_ab_mark_slot_successful() will clear
+ * tries_remaining when setting successful_boot.
+ */
+ slot_set_unbootable(slot);
+ }
+ } else {
+ slot_set_unbootable(slot);
+ }
+}
+
+static const char* slot_suffixes[2] = {"_a", "_b"};
+
+/* Helper function to load metadata - returns AVB_IO_RESULT_OK on
+ * success, error code otherwise.
+ */
+static AvbIOResult load_metadata(AvbABOps* ab_ops,
+ AvbABData* ab_data,
+ AvbABData* ab_data_orig) {
+ AvbIOResult io_ret;
+
+ io_ret = ab_ops->read_ab_metadata(ab_ops, ab_data);
+ if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("I/O error while loading A/B metadata.\n");
+ return io_ret;
+ }
+ *ab_data_orig = *ab_data;
+
+ /* Ensure data is normalized, e.g. illegal states will be marked as
+ * unbootable and all unbootable states are represented with
+ * (priority=0, tries_remaining=0, successful_boot=0).
+ */
+ slot_normalize(&ab_data->slots[0]);
+ slot_normalize(&ab_data->slots[1]);
+ return AVB_IO_RESULT_OK;
+}
+
+/* Writes A/B metadata to disk only if it has changed - returns
+ * AVB_IO_RESULT_OK on success, error code otherwise.
+ */
+static AvbIOResult save_metadata_if_changed(AvbABOps* ab_ops,
+ AvbABData* ab_data,
+ AvbABData* ab_data_orig) {
+ if (avb_safe_memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) {
+ avb_debug("Writing A/B metadata to disk.\n");
+ return ab_ops->write_ab_metadata(ab_ops, ab_data);
+ }
+ return AVB_IO_RESULT_OK;
+}
+
+AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
+ const char* const* requested_partitions,
+ AvbSlotVerifyFlags flags,
+ AvbHashtreeErrorMode hashtree_error_mode,
+ AvbSlotVerifyData** out_data) {
+ AvbOps* ops = ab_ops->ops;
+ AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
+ AvbSlotVerifyData* data = NULL;
+ AvbABFlowResult ret;
+ AvbABData ab_data, ab_data_orig;
+ size_t slot_index_to_boot, n;
+ AvbIOResult io_ret;
+ bool saw_and_allowed_verification_error = false;
+
+ io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+ goto out;
+ }
+
+ /* Validate all bootable slots. */
+ for (n = 0; n < 2; n++) {
+ if (slot_is_bootable(&ab_data.slots[n])) {
+ AvbSlotVerifyResult verify_result;
+ bool set_slot_unbootable = false;
+
+ verify_result = avb_slot_verify(ops,
+ requested_partitions,
+ slot_suffixes[n],
+ flags,
+ hashtree_error_mode,
+ &slot_data[n]);
+ switch (verify_result) {
+ case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+ ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+ goto out;
+
+ case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+ ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+ goto out;
+
+ case AVB_SLOT_VERIFY_RESULT_OK:
+ break;
+
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+ /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
+ * these mean game over.
+ */
+ set_slot_unbootable = true;
+ break;
+
+ /* explicit fallthrough. */
+ case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+ if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
+ /* Do nothing since we allow this. */
+ avb_debugv("Allowing slot ",
+ slot_suffixes[n],
+ " which verified "
+ "with result ",
+ avb_slot_verify_result_to_string(verify_result),
+ " because "
+ "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
+ "is set.\n",
+ NULL);
+ saw_and_allowed_verification_error = true;
+ } else {
+ set_slot_unbootable = true;
+ }
+ break;
+
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+ ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
+ goto out;
+ /* Do not add a 'default:' case here because of -Wswitch. */
+ }
+
+ if (set_slot_unbootable) {
+ avb_errorv("Error verifying slot ",
+ slot_suffixes[n],
+ " with result ",
+ avb_slot_verify_result_to_string(verify_result),
+ " - setting unbootable.\n",
+ NULL);
+ slot_set_unbootable(&ab_data.slots[n]);
+ }
+ }
+ }
+
+ if (slot_is_bootable(&ab_data.slots[0]) &&
+ slot_is_bootable(&ab_data.slots[1])) {
+ if (ab_data.slots[1].priority > ab_data.slots[0].priority) {
+ slot_index_to_boot = 1;
+ } else {
+ slot_index_to_boot = 0;
+ }
+ } else if (slot_is_bootable(&ab_data.slots[0])) {
+ slot_index_to_boot = 0;
+ } else if (slot_is_bootable(&ab_data.slots[1])) {
+ slot_index_to_boot = 1;
+ } else {
+ /* No bootable slots! */
+ avb_error("No bootable slots found.\n");
+ ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
+ goto out;
+ }
+
+ /* Update stored rollback index such that the stored rollback index
+ * is the largest value supporting all currently bootable slots. Do
+ * this for every rollback index location.
+ */
+ for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
+ uint64_t rollback_index_value = 0;
+
+ if (slot_data[0] != NULL && slot_data[1] != NULL) {
+ uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n];
+ uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n];
+ rollback_index_value =
+ (a_rollback_index < b_rollback_index ? a_rollback_index
+ : b_rollback_index);
+ } else if (slot_data[0] != NULL) {
+ rollback_index_value = slot_data[0]->rollback_indexes[n];
+ } else if (slot_data[1] != NULL) {
+ rollback_index_value = slot_data[1]->rollback_indexes[n];
+ }
+
+ if (rollback_index_value != 0) {
+ uint64_t current_rollback_index_value;
+ io_ret = ops->read_rollback_index(ops, n, &current_rollback_index_value);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error getting rollback index for slot.\n");
+ ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (current_rollback_index_value != rollback_index_value) {
+ io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error setting stored rollback index.\n");
+ ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+ goto out;
+ }
+ }
+ }
+ }
+
+ /* Finally, select this slot. */
+ avb_assert(slot_data[slot_index_to_boot] != NULL);
+ data = slot_data[slot_index_to_boot];
+ slot_data[slot_index_to_boot] = NULL;
+ if (saw_and_allowed_verification_error) {
+ avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
+ ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
+ } else {
+ ret = AVB_AB_FLOW_RESULT_OK;
+ }
+
+ /* ... and decrement tries remaining, if applicable. */
+ if (!ab_data.slots[slot_index_to_boot].successful_boot &&
+ ab_data.slots[slot_index_to_boot].tries_remaining > 0) {
+ ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
+ }
+
+out:
+ io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
+ if (io_ret != AVB_IO_RESULT_OK) {
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+ } else {
+ ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+ }
+ if (data != NULL) {
+ avb_slot_verify_data_free(data);
+ data = NULL;
+ }
+ }
+
+ for (n = 0; n < 2; n++) {
+ if (slot_data[n] != NULL) {
+ avb_slot_verify_data_free(slot_data[n]);
+ }
+ }
+
+ if (out_data != NULL) {
+ *out_data = data;
+ } else {
+ if (data != NULL) {
+ avb_slot_verify_data_free(data);
+ }
+ }
+
+ return ret;
+}
+
+AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops,
+ unsigned int slot_number) {
+ AvbABData ab_data, ab_data_orig;
+ unsigned int other_slot_number;
+ AvbIOResult ret;
+
+ avb_assert(slot_number < 2);
+
+ ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
+ if (ret != AVB_IO_RESULT_OK) {
+ goto out;
+ }
+
+ /* Make requested slot top priority, unsuccessful, and with max tries. */
+ ab_data.slots[slot_number].priority = AVB_AB_MAX_PRIORITY;
+ ab_data.slots[slot_number].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
+ ab_data.slots[slot_number].successful_boot = 0;
+
+ /* Ensure other slot doesn't have as high a priority. */
+ other_slot_number = 1 - slot_number;
+ if (ab_data.slots[other_slot_number].priority == AVB_AB_MAX_PRIORITY) {
+ ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1;
+ }
+
+ ret = AVB_IO_RESULT_OK;
+
+out:
+ if (ret == AVB_IO_RESULT_OK) {
+ ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
+ }
+ return ret;
+}
+
+AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops,
+ unsigned int slot_number) {
+ AvbABData ab_data, ab_data_orig;
+ AvbIOResult ret;
+
+ avb_assert(slot_number < 2);
+
+ ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
+ if (ret != AVB_IO_RESULT_OK) {
+ goto out;
+ }
+
+ slot_set_unbootable(&ab_data.slots[slot_number]);
+
+ ret = AVB_IO_RESULT_OK;
+
+out:
+ if (ret == AVB_IO_RESULT_OK) {
+ ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
+ }
+ return ret;
+}
+
+AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops,
+ unsigned int slot_number) {
+ AvbABData ab_data, ab_data_orig;
+ AvbIOResult ret;
+
+ avb_assert(slot_number < 2);
+
+ ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
+ if (ret != AVB_IO_RESULT_OK) {
+ goto out;
+ }
+
+ if (!slot_is_bootable(&ab_data.slots[slot_number])) {
+ avb_error("Cannot mark unbootable slot as successful.\n");
+ ret = AVB_IO_RESULT_OK;
+ goto out;
+ }
+
+ ab_data.slots[slot_number].tries_remaining = 0;
+ ab_data.slots[slot_number].successful_boot = 1;
+
+ ret = AVB_IO_RESULT_OK;
+
+out:
+ if (ret == AVB_IO_RESULT_OK) {
+ ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
+ }
+ return ret;
+}
+
+const char* avb_ab_flow_result_to_string(AvbABFlowResult result) {
+ const char* ret = NULL;
+
+ switch (result) {
+ case AVB_AB_FLOW_RESULT_OK:
+ ret = "OK";
+ break;
+
+ case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR:
+ ret = "OK_WITH_VERIFICATION_ERROR";
+ break;
+
+ case AVB_AB_FLOW_RESULT_ERROR_OOM:
+ ret = "ERROR_OOM";
+ break;
+
+ case AVB_AB_FLOW_RESULT_ERROR_IO:
+ ret = "ERROR_IO";
+ break;
+
+ case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS:
+ ret = "ERROR_NO_BOOTABLE_SLOTS";
+ break;
+
+ case AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT:
+ ret = "ERROR_INVALID_ARGUMENT";
+ break;
+ /* Do not add a 'default:' case here because of -Wswitch. */
+ }
+
+ if (ret == NULL) {
+ avb_error("Unknown AvbABFlowResult value.\n");
+ ret = "(unknown)";
+ }
+
+ return ret;
+}
diff --git a/include/android_avb/avb_ab_flow.h b/lib/avb/libavb_ab/avb_ab_flow.h
index f6aca9b0fa..588026d5a5 100644
--- a/include/android_avb/avb_ab_flow.h
+++ b/lib/avb/libavb_ab/avb_ab_flow.h
@@ -1,263 +1,261 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_AB_H) && !defined(AVB_COMPILATION)
-#error \
- "Never include this file directly, include libavb_ab/libavb_ab.h instead."
-#endif
-*/
-
-#ifndef AVB_AB_FLOW_H_
-#define AVB_AB_FLOW_H_
-
-#include <android_avb/avb_ab_ops.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Magic for the A/B struct when serialized. */
-#define AVB_AB_MAGIC "\0AB0"
-#define AVB_AB_MAGIC_LEN 4
-
-/* Versioning for the on-disk A/B metadata - keep in sync with avbtool. */
-#define AVB_AB_MAJOR_VERSION 1
-#define AVB_AB_MINOR_VERSION 0
-
-/* Size of AvbABData struct. */
-#define AVB_AB_DATA_SIZE 32
-
-/* Maximum values for slot data */
-#define AVB_AB_MAX_PRIORITY 15
-#define AVB_AB_MAX_TRIES_REMAINING 7
-
-/* Struct used for recording per-slot metadata.
- *
- * When serialized, data is stored in network byte-order.
- */
-typedef struct AvbABSlotData {
- /* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY,
- * both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY
- * being the highest. The special value 0 is used to indicate the
- * slot is unbootable.
- */
- uint8_t priority;
-
- /* Number of times left attempting to boot this slot ranging from 0
- * to AVB_AB_MAX_TRIES_REMAINING.
- */
- uint8_t tries_remaining;
-
- /* Non-zero if this slot has booted successfully, 0 otherwise. */
- uint8_t successful_boot;
-
- /* Reserved for future use. */
- uint8_t reserved[1];
-} AVB_ATTR_PACKED AvbABSlotData;
-
-/* Struct used for recording A/B metadata.
- *
- * When serialized, data is stored in network byte-order.
- */
-typedef struct AvbABData {
- /* Magic number used for identification - see AVB_AB_MAGIC. */
- uint8_t magic[AVB_AB_MAGIC_LEN];
-
- /* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */
- uint8_t version_major;
- uint8_t version_minor;
-
- /* Padding to ensure |slots| field start eight bytes in. */
- uint8_t reserved1[2];
-
- /* Per-slot metadata. */
- AvbABSlotData slots[2];
-
- /* Reserved for future use. */
- uint8_t reserved2[12];
-
- /* CRC32 of all 28 bytes preceding this field. */
- uint32_t crc32;
-} AVB_ATTR_PACKED AvbABData;
-
-/* Copies |src| to |dest|, byte-swapping fields in the
- * process. Returns false if the data is invalid (e.g. wrong magic,
- * wrong CRC32 etc.), true otherwise.
- */
-bool avb_ab_data_verify_and_byteswap(const AvbABData* src, AvbABData* dest);
-
-/* Copies |src| to |dest|, byte-swapping fields in the process. Also
- * updates the |crc32| field in |dest|.
- */
-void avb_ab_data_update_crc_and_byteswap(const AvbABData* src, AvbABData* dest);
-
-/* Initializes |data| such that it has two slots and both slots have
- * maximum tries remaining. The CRC is not set.
- */
-void avb_ab_data_init(AvbABData* data);
-
-/* Reads A/B metadata from the 'misc' partition using |ops|. Returned
- * data is properly byteswapped. Returns AVB_IO_RESULT_OK on
- * success, error code otherwise.
- *
- * If the data read from disk is invalid (e.g. wrong magic or CRC
- * checksum failure), the metadata will be reset using
- * avb_ab_data_init() and then written to disk.
- */
-AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data);
-
-/* Writes A/B metadata to the 'misc' partition using |ops|. This will
- * byteswap and update the CRC as needed. Returns AVB_IO_RESULT_OK on
- * success, error code otherwise.
- */
-AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data);
-
-/* Return codes used in avb_ab_flow(), see that function for
- * documentation of each value.
- */
-typedef enum {
- AVB_AB_FLOW_RESULT_OK,
- AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR,
- AVB_AB_FLOW_RESULT_ERROR_OOM,
- AVB_AB_FLOW_RESULT_ERROR_IO,
- AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
- AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT
-} AvbABFlowResult;
-
-/* Get a textual representation of |result|. */
-const char* avb_ab_flow_result_to_string(AvbABFlowResult result);
-
-/* High-level function to select a slot to boot. The following
- * algorithm is used:
- *
- * 1. A/B metadata is loaded and validated using the
- * read_ab_metadata() operation. Typically this means it's read from
- * the 'misc' partition and if it's invalid then it's reset using
- * avb_ab_data_init() and this reset metadata is returned.
- *
- * 2. All bootable slots listed in the A/B metadata are verified using
- * avb_slot_verify(). If a slot is invalid or if it fails verification
- * (and AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is not set, see
- * below), it will be marked as unbootable in the A/B metadata and the
- * metadata will be saved to disk before returning.
- *
- * 3. If there are no bootable slots, the value
- * AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS is returned.
- *
- * 4. For each bootable slot, the Stored Rollback Indexes are updated
- * such that for each rollback index location, the Stored Rollback
- * Index is the largest number smaller than or equal to the Rollback
- * Index of each slot.
- *
- * 5. The bootable slot with the highest priority is selected and
- * returned in |out_data|. If this slot is already marked as
- * successful, the A/B metadata is not modified. However, if the slot
- * is not marked as bootable its |tries_remaining| count is
- * decremented and the A/B metadata is saved to disk before returning.
- * In either case the value AVB_AB_FLOW_RESULT_OK is returning.
- *
- * The partitions to load is given in |requested_partitions| as a
- * NULL-terminated array of NUL-terminated strings. Typically the
- * |requested_partitions| array only contains a single item for the
- * boot partition, 'boot'.
- *
- * If the device is unlocked (and _only_ if it's unlocked), the
- * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag should be set
- * in the |flags| parameter. This will allow considering slots as
- * verified even when avb_slot_verify() returns
- * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
- * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
- * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX for the slot in
- * question.
- *
- * Note that neither androidboot.slot_suffix nor androidboot.slot are
- * set in the |cmdline| field in |AvbSlotVerifyData| - you will have
- * to pass these yourself.
- *
- * If a slot was selected and it verified then AVB_AB_FLOW_RESULT_OK
- * is returned.
- *
- * If a slot was selected but it didn't verify then
- * AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR is returned. This can
- * only happen when the AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
- * flag is set.
- *
- * If an I/O operation - such as loading/saving metadata or checking
- * rollback indexes - fail, the value AVB_AB_FLOW_RESULT_ERROR_IO is
- * returned.
- *
- * If memory allocation fails, AVB_AB_FLOW_RESULT_ERROR_OOM is
- * returned.
- *
- * If invalid arguments are passed,
- * AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT is returned. For example
- * this can happen if using AVB_HASHTREE_ERROR_MODE_LOGGING without
- * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
- *
- * Reasonable behavior for handling AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS
- * is to initiate device repair (which is device-dependent).
- */
-AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
- const char* const* requested_partitions,
- AvbSlotVerifyFlags flags,
- AvbHashtreeErrorMode hashtree_error_mode,
- AvbSlotVerifyData** out_data);
-
-/* Marks the slot with the given slot number as active. Returns
- * AVB_IO_RESULT_OK on success, error code otherwise.
- *
- * This function is typically used by the OS updater when completing
- * an update. It can also used by the firmware for implementing the
- * "set_active" command.
- */
-AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops, unsigned int slot_number);
-
-/* Marks the slot with the given slot number as unbootable. Returns
- * AVB_IO_RESULT_OK on success, error code otherwise.
- *
- * This function is typically used by the OS updater before writing to
- * a slot.
- */
-AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops,
- unsigned int slot_number);
-
-/* Marks the slot with the given slot number as having booted
- * successfully. Returns AVB_IO_RESULT_OK on success, error code
- * otherwise.
- *
- * Calling this on an unbootable slot is an error - AVB_IO_RESULT_OK
- * will be returned yet the function will have no side-effects.
- *
- * This function is typically used by the OS updater after having
- * confirmed that the slot works as intended.
- */
-AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops,
- unsigned int slot_number);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_AB_FLOW_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_AB_H) && !defined(AVB_COMPILATION)
+#error \
+ "Never include this file directly, include libavb_ab/libavb_ab.h instead."
+#endif
+
+#ifndef AVB_AB_FLOW_H_
+#define AVB_AB_FLOW_H_
+
+#include "avb_ab_ops.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Magic for the A/B struct when serialized. */
+#define AVB_AB_MAGIC "\0AB0"
+#define AVB_AB_MAGIC_LEN 4
+
+/* Versioning for the on-disk A/B metadata - keep in sync with avbtool. */
+#define AVB_AB_MAJOR_VERSION 1
+#define AVB_AB_MINOR_VERSION 0
+
+/* Size of AvbABData struct. */
+#define AVB_AB_DATA_SIZE 32
+
+/* Maximum values for slot data */
+#define AVB_AB_MAX_PRIORITY 15
+#define AVB_AB_MAX_TRIES_REMAINING 7
+
+/* Struct used for recording per-slot metadata.
+ *
+ * When serialized, data is stored in network byte-order.
+ */
+typedef struct AvbABSlotData {
+ /* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY,
+ * both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY
+ * being the highest. The special value 0 is used to indicate the
+ * slot is unbootable.
+ */
+ uint8_t priority;
+
+ /* Number of times left attempting to boot this slot ranging from 0
+ * to AVB_AB_MAX_TRIES_REMAINING.
+ */
+ uint8_t tries_remaining;
+
+ /* Non-zero if this slot has booted successfully, 0 otherwise. */
+ uint8_t successful_boot;
+
+ /* Reserved for future use. */
+ uint8_t reserved[1];
+} AVB_ATTR_PACKED AvbABSlotData;
+
+/* Struct used for recording A/B metadata.
+ *
+ * When serialized, data is stored in network byte-order.
+ */
+typedef struct AvbABData {
+ /* Magic number used for identification - see AVB_AB_MAGIC. */
+ uint8_t magic[AVB_AB_MAGIC_LEN];
+
+ /* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */
+ uint8_t version_major;
+ uint8_t version_minor;
+
+ /* Padding to ensure |slots| field start eight bytes in. */
+ uint8_t reserved1[2];
+
+ /* Per-slot metadata. */
+ AvbABSlotData slots[2];
+
+ /* Reserved for future use. */
+ uint8_t reserved2[12];
+
+ /* CRC32 of all 28 bytes preceding this field. */
+ uint32_t crc32;
+} AVB_ATTR_PACKED AvbABData;
+
+/* Copies |src| to |dest|, byte-swapping fields in the
+ * process. Returns false if the data is invalid (e.g. wrong magic,
+ * wrong CRC32 etc.), true otherwise.
+ */
+bool avb_ab_data_verify_and_byteswap(const AvbABData* src, AvbABData* dest);
+
+/* Copies |src| to |dest|, byte-swapping fields in the process. Also
+ * updates the |crc32| field in |dest|.
+ */
+void avb_ab_data_update_crc_and_byteswap(const AvbABData* src, AvbABData* dest);
+
+/* Initializes |data| such that it has two slots and both slots have
+ * maximum tries remaining. The CRC is not set.
+ */
+void avb_ab_data_init(AvbABData* data);
+
+/* Reads A/B metadata from the 'misc' partition using |ops|. Returned
+ * data is properly byteswapped. Returns AVB_IO_RESULT_OK on
+ * success, error code otherwise.
+ *
+ * If the data read from disk is invalid (e.g. wrong magic or CRC
+ * checksum failure), the metadata will be reset using
+ * avb_ab_data_init() and then written to disk.
+ */
+AvbIOResult avb_ab_data_read(AvbABOps* ab_ops, AvbABData* data);
+
+/* Writes A/B metadata to the 'misc' partition using |ops|. This will
+ * byteswap and update the CRC as needed. Returns AVB_IO_RESULT_OK on
+ * success, error code otherwise.
+ */
+AvbIOResult avb_ab_data_write(AvbABOps* ab_ops, const AvbABData* data);
+
+/* Return codes used in avb_ab_flow(), see that function for
+ * documentation of each value.
+ */
+typedef enum {
+ AVB_AB_FLOW_RESULT_OK,
+ AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR,
+ AVB_AB_FLOW_RESULT_ERROR_OOM,
+ AVB_AB_FLOW_RESULT_ERROR_IO,
+ AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
+ AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT
+} AvbABFlowResult;
+
+/* Get a textual representation of |result|. */
+const char* avb_ab_flow_result_to_string(AvbABFlowResult result);
+
+/* High-level function to select a slot to boot. The following
+ * algorithm is used:
+ *
+ * 1. A/B metadata is loaded and validated using the
+ * read_ab_metadata() operation. Typically this means it's read from
+ * the 'misc' partition and if it's invalid then it's reset using
+ * avb_ab_data_init() and this reset metadata is returned.
+ *
+ * 2. All bootable slots listed in the A/B metadata are verified using
+ * avb_slot_verify(). If a slot is invalid or if it fails verification
+ * (and AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is not set, see
+ * below), it will be marked as unbootable in the A/B metadata and the
+ * metadata will be saved to disk before returning.
+ *
+ * 3. If there are no bootable slots, the value
+ * AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS is returned.
+ *
+ * 4. For each bootable slot, the Stored Rollback Indexes are updated
+ * such that for each rollback index location, the Stored Rollback
+ * Index is the largest number smaller than or equal to the Rollback
+ * Index of each slot.
+ *
+ * 5. The bootable slot with the highest priority is selected and
+ * returned in |out_data|. If this slot is already marked as
+ * successful, the A/B metadata is not modified. However, if the slot
+ * is not marked as bootable its |tries_remaining| count is
+ * decremented and the A/B metadata is saved to disk before returning.
+ * In either case the value AVB_AB_FLOW_RESULT_OK is returning.
+ *
+ * The partitions to load is given in |requested_partitions| as a
+ * NULL-terminated array of NUL-terminated strings. Typically the
+ * |requested_partitions| array only contains a single item for the
+ * boot partition, 'boot'.
+ *
+ * If the device is unlocked (and _only_ if it's unlocked), the
+ * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag should be set
+ * in the |flags| parameter. This will allow considering slots as
+ * verified even when avb_slot_verify() returns
+ * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
+ * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
+ * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX for the slot in
+ * question.
+ *
+ * Note that neither androidboot.slot_suffix nor androidboot.slot are
+ * set in the |cmdline| field in |AvbSlotVerifyData| - you will have
+ * to pass these yourself.
+ *
+ * If a slot was selected and it verified then AVB_AB_FLOW_RESULT_OK
+ * is returned.
+ *
+ * If a slot was selected but it didn't verify then
+ * AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR is returned. This can
+ * only happen when the AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
+ * flag is set.
+ *
+ * If an I/O operation - such as loading/saving metadata or checking
+ * rollback indexes - fail, the value AVB_AB_FLOW_RESULT_ERROR_IO is
+ * returned.
+ *
+ * If memory allocation fails, AVB_AB_FLOW_RESULT_ERROR_OOM is
+ * returned.
+ *
+ * If invalid arguments are passed,
+ * AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT is returned. For example
+ * this can happen if using AVB_HASHTREE_ERROR_MODE_LOGGING without
+ * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
+ *
+ * Reasonable behavior for handling AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS
+ * is to initiate device repair (which is device-dependent).
+ */
+AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
+ const char* const* requested_partitions,
+ AvbSlotVerifyFlags flags,
+ AvbHashtreeErrorMode hashtree_error_mode,
+ AvbSlotVerifyData** out_data);
+
+/* Marks the slot with the given slot number as active. Returns
+ * AVB_IO_RESULT_OK on success, error code otherwise.
+ *
+ * This function is typically used by the OS updater when completing
+ * an update. It can also used by the firmware for implementing the
+ * "set_active" command.
+ */
+AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops, unsigned int slot_number);
+
+/* Marks the slot with the given slot number as unbootable. Returns
+ * AVB_IO_RESULT_OK on success, error code otherwise.
+ *
+ * This function is typically used by the OS updater before writing to
+ * a slot.
+ */
+AvbIOResult avb_ab_mark_slot_unbootable(AvbABOps* ab_ops,
+ unsigned int slot_number);
+
+/* Marks the slot with the given slot number as having booted
+ * successfully. Returns AVB_IO_RESULT_OK on success, error code
+ * otherwise.
+ *
+ * Calling this on an unbootable slot is an error - AVB_IO_RESULT_OK
+ * will be returned yet the function will have no side-effects.
+ *
+ * This function is typically used by the OS updater after having
+ * confirmed that the slot works as intended.
+ */
+AvbIOResult avb_ab_mark_slot_successful(AvbABOps* ab_ops,
+ unsigned int slot_number);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_AB_FLOW_H_ */
diff --git a/include/android_avb/avb_ab_ops.h b/lib/avb/libavb_ab/avb_ab_ops.h
index 60e9a497b6..8d8fde7aa9 100644
--- a/include/android_avb/avb_ab_ops.h
+++ b/lib/avb/libavb_ab/avb_ab_ops.h
@@ -1,81 +1,79 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_AB_H) && !defined(AVB_COMPILATION)
-#error \
- "Never include this file directly, include libavb_ab/libavb_ab.h instead."
-#endif
-*/
-
-#ifndef AVB_AB_OPS_H_
-#define AVB_AB_OPS_H_
-
-#include <android_avb/libavb.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct AvbABOps;
-typedef struct AvbABOps AvbABOps;
-
-struct AvbABData;
-
-/* High-level operations/functions/methods for A/B that are platform
- * dependent.
- */
-struct AvbABOps {
- /* Operations from libavb. */
- AvbOps* ops;
-
- /* Reads A/B metadata from persistent storage. Returned data is
- * properly byteswapped. Returns AVB_IO_RESULT_OK on success, error
- * code otherwise.
- *
- * If the data read is invalid (e.g. wrong magic or CRC checksum
- * failure), the metadata shoule be reset using avb_ab_data_init()
- * and then written to persistent storage.
- *
- * Implementations will typically want to use avb_ab_data_read()
- * here to use the 'misc' partition for persistent storage.
- */
- AvbIOResult (*read_ab_metadata)(AvbABOps* ab_ops, struct AvbABData* data);
-
- /* Writes A/B metadata to persistent storage. This will byteswap and
- * update the CRC as needed. Returns AVB_IO_RESULT_OK on success,
- * error code otherwise.
- *
- * Implementations will typically want to use avb_ab_data_write()
- * here to use the 'misc' partition for persistent storage.
- */
- AvbIOResult (*write_ab_metadata)(AvbABOps* ab_ops,
- const struct AvbABData* data);
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_AB_OPS_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_AB_H) && !defined(AVB_COMPILATION)
+#error \
+ "Never include this file directly, include libavb_ab/libavb_ab.h instead."
+#endif
+
+#ifndef AVB_AB_OPS_H_
+#define AVB_AB_OPS_H_
+
+#include <libavb/libavb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct AvbABOps;
+typedef struct AvbABOps AvbABOps;
+
+struct AvbABData;
+
+/* High-level operations/functions/methods for A/B that are platform
+ * dependent.
+ */
+struct AvbABOps {
+ /* Operations from libavb. */
+ AvbOps* ops;
+
+ /* Reads A/B metadata from persistent storage. Returned data is
+ * properly byteswapped. Returns AVB_IO_RESULT_OK on success, error
+ * code otherwise.
+ *
+ * If the data read is invalid (e.g. wrong magic or CRC checksum
+ * failure), the metadata shoule be reset using avb_ab_data_init()
+ * and then written to persistent storage.
+ *
+ * Implementations will typically want to use avb_ab_data_read()
+ * here to use the 'misc' partition for persistent storage.
+ */
+ AvbIOResult (*read_ab_metadata)(AvbABOps* ab_ops, struct AvbABData* data);
+
+ /* Writes A/B metadata to persistent storage. This will byteswap and
+ * update the CRC as needed. Returns AVB_IO_RESULT_OK on success,
+ * error code otherwise.
+ *
+ * Implementations will typically want to use avb_ab_data_write()
+ * here to use the 'misc' partition for persistent storage.
+ */
+ AvbIOResult (*write_ab_metadata)(AvbABOps* ab_ops,
+ const struct AvbABData* data);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_AB_OPS_H_ */
diff --git a/include/android_avb/libavb_ab.h b/lib/avb/libavb_ab/libavb_ab.h
index 562cee1fa7..654ff5e771 100644
--- a/include/android_avb/libavb_ab.h
+++ b/lib/avb/libavb_ab/libavb_ab.h
@@ -1,54 +1,51 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef LIBAVB_AB_H_
-#define LIBAVB_AB_H_
-
-#include <android_avb/libavb.h>
-
-/* The libavb_ab/ and boot_control/ code has been marked for some time
- * as experimental in anticipation of being removed in the future. It
- * is now deprecated and to continue using it you must define
- * AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED. It will be removed Jun
- * 1 2018.
- */
-
-/*
-#ifndef AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
-#error \
- "You must define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED to use this library."
-#endif
-*/
-
-/* The AVB_INSIDE_LIBAVB_AB_H preprocessor symbol is used to enforce
- * library users to include only this file. All public interfaces, and
- * only public interfaces, must be included here.
- */
-
-#define AVB_INSIDE_LIBAVB_AB_H
-#include <android_avb/avb_ab_flow.h>
-#include <android_avb/avb_ab_ops.h>
-#undef AVB_INSIDE_LIBAVB_AB_H
-
-#endif /* LIBAVB_AB_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef LIBAVB_AB_H_
+#define LIBAVB_AB_H_
+
+#include <libavb/libavb.h>
+
+/* The libavb_ab/ and boot_control/ code has been marked for some time
+ * as experimental in anticipation of being removed in the future. It
+ * is now deprecated and to continue using it you must define
+ * AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED. It will be removed Jun
+ * 1 2018.
+ */
+#ifndef AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
+#error \
+ "You must define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED to use this library."
+#endif
+
+/* The AVB_INSIDE_LIBAVB_AB_H preprocessor symbol is used to enforce
+ * library users to include only this file. All public interfaces, and
+ * only public interfaces, must be included here.
+ */
+
+#define AVB_INSIDE_LIBAVB_AB_H
+#include "avb_ab_flow.h"
+#include "avb_ab_ops.h"
+#undef AVB_INSIDE_LIBAVB_AB_H
+
+#endif /* LIBAVB_AB_H_ */
diff --git a/lib/avb/libavb_atx/Makefile b/lib/avb/libavb_atx/Makefile
index 3ffa57a0b1..43acf11d81 100644
--- a/lib/avb/libavb_atx/Makefile
+++ b/lib/avb/libavb_atx/Makefile
@@ -1 +1,2 @@
+ccflags-y += -DAVB_COMPILATION
obj-y += avb_atx_validate.o
diff --git a/include/android_avb/avb_atx_ops.h b/lib/avb/libavb_atx/avb_atx_ops.h
index 726dd6a8a1..53c898d623 100644
--- a/include/android_avb/avb_atx_ops.h
+++ b/lib/avb/libavb_atx/avb_atx_ops.h
@@ -1,77 +1,84 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_ATX_H) && !defined(AVB_COMPILATION)
-#error \
- "Never include this file directly, include libavb_atx/libavb_atx.h instead."
-#endif
-*/
-
-#ifndef AVB_ATX_OPS_H_
-#define AVB_ATX_OPS_H_
-
-#include <android_avb/libavb.h>
-
-#include <android_avb/avb_atx_types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct AvbAtxOps;
-typedef struct AvbAtxOps AvbAtxOps;
-
-/* An extension to AvbOps required by avb_atx_validate_vbmeta_public_key(). */
-struct AvbAtxOps {
- /* Operations from libavb. */
- AvbOps* ops;
-
- /* Reads permanent |attributes| data. There are no restrictions on where this
- * data is stored. On success, returns AVB_IO_RESULT_OK and populates
- * |attributes|.
- */
- AvbIOResult (*read_permanent_attributes)(
- AvbAtxOps* atx_ops, AvbAtxPermanentAttributes* attributes);
-
- /* Reads a |hash| of permanent attributes. This hash MUST be retrieved from a
- * permanently read-only location (e.g. fuses) when a device is LOCKED. On
- * success, returned AVB_IO_RESULT_OK and populates |hash|.
- */
- AvbIOResult (*read_permanent_attributes_hash)(
- AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]);
-
- /* Provides the key version of a key used during verification. This may be
- * useful for managing the minimum key version.
- */
- void (*set_key_version)(AvbAtxOps* atx_ops,
- size_t rollback_index_location,
- uint64_t key_version);
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_ATX_OPS_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_ATX_H) && !defined(AVB_COMPILATION)
+#error \
+ "Never include this file directly, include libavb_atx/libavb_atx.h instead."
+#endif
+
+#ifndef AVB_ATX_OPS_H_
+#define AVB_ATX_OPS_H_
+
+#include <libavb/libavb.h>
+
+#include "avb_atx_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct AvbAtxOps;
+typedef struct AvbAtxOps AvbAtxOps;
+
+/* An extension to AvbOps required by avb_atx_validate_vbmeta_public_key(). */
+struct AvbAtxOps {
+ /* Operations from libavb. */
+ AvbOps* ops;
+
+ /* Reads permanent |attributes| data. There are no restrictions on where this
+ * data is stored. On success, returns AVB_IO_RESULT_OK and populates
+ * |attributes|.
+ */
+ AvbIOResult (*read_permanent_attributes)(
+ AvbAtxOps* atx_ops, AvbAtxPermanentAttributes* attributes);
+
+ /* Reads a |hash| of permanent attributes. This hash MUST be retrieved from a
+ * permanently read-only location (e.g. fuses) when a device is LOCKED. On
+ * success, returned AVB_IO_RESULT_OK and populates |hash|.
+ */
+ AvbIOResult (*read_permanent_attributes_hash)(
+ AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]);
+
+ /* Provides the key version of a key used during verification. This may be
+ * useful for managing the minimum key version.
+ */
+ void (*set_key_version)(AvbAtxOps* atx_ops,
+ size_t rollback_index_location,
+ uint64_t key_version);
+
+ /* Generates |num_bytes| random bytes and stores them in |output|,
+ * which must point to a buffer large enough to store the bytes.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ */
+ AvbIOResult (*get_random)(AvbAtxOps* atx_ops,
+ size_t num_bytes,
+ uint8_t* output);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_ATX_OPS_H_ */
diff --git a/include/android_avb/avb_atx_types.h b/lib/avb/libavb_atx/avb_atx_types.h
index 9b1c36a3c3..e78bbfa78c 100644
--- a/include/android_avb/avb_atx_types.h
+++ b/lib/avb/libavb_atx/avb_atx_types.h
@@ -1,80 +1,96 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_ATX_H) && !defined(AVB_COMPILATION)
-#error \
- "Never include this file directly, include libavb_atx/libavb_atx.h instead."
-#endif
-*/
-
-#ifndef AVB_ATX_TYPES_H_
-#define AVB_ATX_TYPES_H_
-
-#include <android_avb/libavb.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Size in bytes of an Android Things product ID. */
-#define AVB_ATX_PRODUCT_ID_SIZE 16
-
-/* Size in bytes of a serialized public key with a 4096-bit modulus. */
-#define AVB_ATX_PUBLIC_KEY_SIZE (sizeof(AvbRSAPublicKeyHeader) + 1024)
-
-/* Data structure of Android Things permanent attributes. */
-typedef struct AvbAtxPermanentAttributes {
- uint32_t version;
- uint8_t product_root_public_key[AVB_ATX_PUBLIC_KEY_SIZE];
- uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE];
-} AVB_ATTR_PACKED AvbAtxPermanentAttributes;
-
-/* Data structure of signed fields in an Android Things certificate. */
-typedef struct AvbAtxCertificateSignedData {
- uint32_t version;
- uint8_t public_key[AVB_ATX_PUBLIC_KEY_SIZE];
- uint8_t subject[AVB_SHA256_DIGEST_SIZE];
- uint8_t usage[AVB_SHA256_DIGEST_SIZE];
- uint64_t key_version;
-} AVB_ATTR_PACKED AvbAtxCertificateSignedData;
-
-/* Data structure of an Android Things certificate. */
-typedef struct AvbAtxCertificate {
- AvbAtxCertificateSignedData signed_data;
- uint8_t signature[AVB_RSA4096_NUM_BYTES];
-} AVB_ATTR_PACKED AvbAtxCertificate;
-
-/* Data structure of Android Things public key metadata in vbmeta. */
-typedef struct AvbAtxPublicKeyMetadata {
- uint32_t version;
- AvbAtxCertificate product_intermediate_key_certificate;
- AvbAtxCertificate product_signing_key_certificate;
-} AVB_ATTR_PACKED AvbAtxPublicKeyMetadata;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_ATX_TYPES_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_ATX_H) && !defined(AVB_COMPILATION)
+#error \
+ "Never include this file directly, include libavb_atx/libavb_atx.h instead."
+#endif
+
+#ifndef AVB_ATX_TYPES_H_
+#define AVB_ATX_TYPES_H_
+
+#include <libavb/libavb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Size in bytes of an Android Things product ID. */
+#define AVB_ATX_PRODUCT_ID_SIZE 16
+
+/* Size in bytes of an Android Things unlock challenge. */
+#define AVB_ATX_UNLOCK_CHALLENGE_SIZE 16
+
+/* Size in bytes of a serialized public key with a 4096-bit modulus. */
+#define AVB_ATX_PUBLIC_KEY_SIZE (sizeof(AvbRSAPublicKeyHeader) + 1024)
+
+/* Data structure of Android Things permanent attributes. */
+typedef struct AvbAtxPermanentAttributes {
+ uint32_t version;
+ uint8_t product_root_public_key[AVB_ATX_PUBLIC_KEY_SIZE];
+ uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE];
+} AVB_ATTR_PACKED AvbAtxPermanentAttributes;
+
+/* Data structure of signed fields in an Android Things certificate. */
+typedef struct AvbAtxCertificateSignedData {
+ uint32_t version;
+ uint8_t public_key[AVB_ATX_PUBLIC_KEY_SIZE];
+ uint8_t subject[AVB_SHA256_DIGEST_SIZE];
+ uint8_t usage[AVB_SHA256_DIGEST_SIZE];
+ uint64_t key_version;
+} AVB_ATTR_PACKED AvbAtxCertificateSignedData;
+
+/* Data structure of an Android Things certificate. */
+typedef struct AvbAtxCertificate {
+ AvbAtxCertificateSignedData signed_data;
+ uint8_t signature[AVB_RSA4096_NUM_BYTES];
+} AVB_ATTR_PACKED AvbAtxCertificate;
+
+/* Data structure of Android Things public key metadata in vbmeta. */
+typedef struct AvbAtxPublicKeyMetadata {
+ uint32_t version;
+ AvbAtxCertificate product_intermediate_key_certificate;
+ AvbAtxCertificate product_signing_key_certificate;
+} AVB_ATTR_PACKED AvbAtxPublicKeyMetadata;
+
+/* Data structure of an Android Things unlock challenge. */
+typedef struct AvbAtxUnlockChallenge {
+ uint32_t version;
+ uint8_t product_id_hash[AVB_SHA256_DIGEST_SIZE];
+ uint8_t challenge[AVB_ATX_UNLOCK_CHALLENGE_SIZE];
+} AVB_ATTR_PACKED AvbAtxUnlockChallenge;
+
+/* Data structure of an Android Things unlock credential. */
+typedef struct AvbAtxUnlockCredential {
+ uint32_t version;
+ AvbAtxCertificate product_intermediate_key_certificate;
+ AvbAtxCertificate product_unlock_key_certificate;
+ uint8_t challenge_signature[AVB_RSA4096_NUM_BYTES];
+} AVB_ATTR_PACKED AvbAtxUnlockCredential;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_ATX_TYPES_H_ */
diff --git a/lib/avb/libavb_atx/avb_atx_validate.c b/lib/avb/libavb_atx/avb_atx_validate.c
index e0f205a728..f3c1d96841 100644
--- a/lib/avb/libavb_atx/avb_atx_validate.c
+++ b/lib/avb/libavb_atx/avb_atx_validate.c
@@ -1,256 +1,401 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_atx_validate.h>
-
-#include <android_avb/avb_rsa.h>
-#include <android_avb/avb_sha.h>
-#include <android_avb/avb_sysdeps.h>
-#include <android_avb/avb_util.h>
-
-/* Computes the SHA256 |hash| of |length| bytes of |data|. */
-static void sha256(const uint8_t* data,
- uint32_t length,
- uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
- AvbSHA256Ctx context;
- avb_sha256_init(&context);
- avb_sha256_update(&context, data, length);
- uint8_t* tmp = avb_sha256_final(&context);
- avb_memcpy(hash, tmp, AVB_SHA256_DIGEST_SIZE);
-}
-
-/* Computes the SHA512 |hash| of |length| bytes of |data|. */
-static void sha512(const uint8_t* data,
- uint32_t length,
- uint8_t hash[AVB_SHA512_DIGEST_SIZE]) {
- AvbSHA512Ctx context;
- avb_sha512_init(&context);
- avb_sha512_update(&context, data, length);
- uint8_t* tmp = avb_sha512_final(&context);
- avb_memcpy(hash, tmp, AVB_SHA512_DIGEST_SIZE);
-}
-
-/* Computes the SHA256 |hash| of a NUL-terminated |str|. */
-static void sha256_str(const char* str, uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
- sha256((const uint8_t*)str, avb_strlen(str), hash);
-}
-
-/* Verifies structure and |expected_hash| of permanent |attributes|. */
-static bool verify_permanent_attributes(
- const AvbAtxPermanentAttributes* attributes,
- uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE]) {
- uint8_t hash[AVB_SHA256_DIGEST_SIZE];
-
- if (attributes->version != 1) {
- avb_error("Unsupported permanent attributes version.\n");
- return false;
- }
- sha256((const uint8_t*)attributes, sizeof(AvbAtxPermanentAttributes), hash);
- if (0 != avb_safe_memcmp(hash, expected_hash, AVB_SHA256_DIGEST_SIZE)) {
- avb_error("Invalid permanent attributes.\n");
- return false;
- }
- return true;
-}
-
-/* Verifies the format, key version, usage, and signature of a certificate. */
-static bool verify_certificate(AvbAtxCertificate* certificate,
- uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
- uint64_t minimum_key_version,
- uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]) {
- const AvbAlgorithmData* algorithm_data;
- uint8_t certificate_hash[AVB_SHA512_DIGEST_SIZE];
-
- if (certificate->signed_data.version != 1) {
- avb_error("Unsupported certificate format.\n");
- return false;
- }
- algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
- sha512((const uint8_t*)&certificate->signed_data,
- sizeof(AvbAtxCertificateSignedData),
- certificate_hash);
- if (!avb_rsa_verify(authority,
- AVB_ATX_PUBLIC_KEY_SIZE,
- certificate->signature,
- AVB_RSA4096_NUM_BYTES,
- certificate_hash,
- AVB_SHA512_DIGEST_SIZE,
- algorithm_data->padding,
- algorithm_data->padding_len)) {
- avb_error("Invalid certificate signature.\n");
- return false;
- }
- if (certificate->signed_data.key_version < minimum_key_version) {
- avb_error("Key rollback detected.\n");
- return false;
- }
- if (0 != avb_safe_memcmp(certificate->signed_data.usage,
- expected_usage,
- AVB_SHA256_DIGEST_SIZE)) {
- avb_error("Invalid certificate usage.\n");
- return false;
- }
- return true;
-}
-
-/* Verifies signature and fields of a PIK certificate. */
-static bool verify_pik_certificate(AvbAtxCertificate* certificate,
- uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
- uint64_t minimum_version) {
- uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
-
- sha256_str("com.google.android.things.vboot.ca", expected_usage);
- if (!verify_certificate(
- certificate, authority, minimum_version, expected_usage)) {
- avb_error("Invalid PIK certificate.\n");
- return false;
- }
- return true;
-}
-
-/* Verifies signature and fields of a PSK certificate. */
-static bool verify_psk_certificate(
- AvbAtxCertificate* certificate,
- uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
- uint64_t minimum_version,
- uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
- uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
- uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
-
- sha256_str("com.google.android.things.vboot", expected_usage);
- if (!verify_certificate(
- certificate, authority, minimum_version, expected_usage)) {
- avb_error("Invalid PSK certificate.\n");
- return false;
- }
- sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject);
- if (0 != avb_safe_memcmp(certificate->signed_data.subject,
- expected_subject,
- AVB_SHA256_DIGEST_SIZE)) {
- avb_error("Product ID mismatch.\n");
- return false;
- }
- return true;
-}
-
-AvbIOResult avb_atx_validate_vbmeta_public_key(
- AvbOps* ops,
- const uint8_t* public_key_data,
- size_t public_key_length,
- const uint8_t* public_key_metadata,
- size_t public_key_metadata_length,
- bool* out_is_trusted) {
- AvbIOResult result = AVB_IO_RESULT_OK;
- AvbAtxPermanentAttributes permanent_attributes;
- uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
- AvbAtxPublicKeyMetadata metadata;
- uint64_t minimum_version;
-
- /* Be pessimistic so we can exit early without having to remember to clear.
- */
- *out_is_trusted = false;
-
- /* Read and verify permanent attributes. */
- result = ops->atx_ops->read_permanent_attributes(ops->atx_ops,
- &permanent_attributes);
- if (result != AVB_IO_RESULT_OK) {
- avb_error("Failed to read permanent attributes.\n");
- return result;
- }
- result = ops->atx_ops->read_permanent_attributes_hash(
- ops->atx_ops, permanent_attributes_hash);
- if (result != AVB_IO_RESULT_OK) {
- avb_error("Failed to read permanent attributes hash.\n");
- return result;
- }
- if (!verify_permanent_attributes(&permanent_attributes,
- permanent_attributes_hash)) {
- return AVB_IO_RESULT_OK;
- }
-
- /* Sanity check public key metadata. */
- if (public_key_metadata_length != sizeof(AvbAtxPublicKeyMetadata)) {
- avb_error("Invalid public key metadata.\n");
- return AVB_IO_RESULT_OK;
- }
- avb_memcpy(&metadata, public_key_metadata, sizeof(AvbAtxPublicKeyMetadata));
- if (metadata.version != 1) {
- avb_error("Unsupported public key metadata.\n");
- return AVB_IO_RESULT_OK;
- }
-
- /* Verify the PIK certificate. */
- result = ops->read_rollback_index(
- ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version);
- if (result != AVB_IO_RESULT_OK) {
- avb_error("Failed to read PIK minimum version.\n");
- return result;
- }
- if (!verify_pik_certificate(&metadata.product_intermediate_key_certificate,
- permanent_attributes.product_root_public_key,
- minimum_version)) {
- return AVB_IO_RESULT_OK;
- }
-
- /* Verify the PSK certificate. */
- result = ops->read_rollback_index(
- ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version);
- if (result != AVB_IO_RESULT_OK) {
- avb_error("Failed to read PSK minimum version.\n");
- return result;
- }
- if (!verify_psk_certificate(
- &metadata.product_signing_key_certificate,
- metadata.product_intermediate_key_certificate.signed_data.public_key,
- minimum_version,
- permanent_attributes.product_id)) {
- return AVB_IO_RESULT_OK;
- }
-
- /* Verify the PSK is the same key that verified vbmeta. */
- if (public_key_length != AVB_ATX_PUBLIC_KEY_SIZE) {
- avb_error("Public key length mismatch.\n");
- return AVB_IO_RESULT_OK;
- }
- if (0 != avb_safe_memcmp(
- metadata.product_signing_key_certificate.signed_data.public_key,
- public_key_data,
- AVB_ATX_PUBLIC_KEY_SIZE)) {
- avb_error("Public key mismatch.\n");
- return AVB_IO_RESULT_OK;
- }
-
- /* Report the key versions used during verification. */
- ops->atx_ops->set_key_version(
- ops->atx_ops,
- AVB_ATX_PIK_VERSION_LOCATION,
- metadata.product_intermediate_key_certificate.signed_data.key_version);
- ops->atx_ops->set_key_version(
- ops->atx_ops,
- AVB_ATX_PSK_VERSION_LOCATION,
- metadata.product_signing_key_certificate.signed_data.key_version);
-
- *out_is_trusted = true;
- return AVB_IO_RESULT_OK;
-}
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_atx_validate.h"
+
+#include <libavb/avb_rsa.h>
+#include <libavb/avb_sha.h>
+#include <libavb/avb_sysdeps.h>
+#include <libavb/avb_util.h>
+
+/* The most recent unlock challenge generated. */
+static uint8_t last_unlock_challenge[AVB_ATX_UNLOCK_CHALLENGE_SIZE];
+
+/* Computes the SHA256 |hash| of |length| bytes of |data|. */
+static void sha256(const uint8_t* data,
+ uint32_t length,
+ uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
+ AvbSHA256Ctx context;
+ avb_sha256_init(&context);
+ avb_sha256_update(&context, data, length);
+ uint8_t* tmp = avb_sha256_final(&context);
+ avb_memcpy(hash, tmp, AVB_SHA256_DIGEST_SIZE);
+}
+
+/* Computes the SHA512 |hash| of |length| bytes of |data|. */
+static void sha512(const uint8_t* data,
+ uint32_t length,
+ uint8_t hash[AVB_SHA512_DIGEST_SIZE]) {
+ AvbSHA512Ctx context;
+ avb_sha512_init(&context);
+ avb_sha512_update(&context, data, length);
+ uint8_t* tmp = avb_sha512_final(&context);
+ avb_memcpy(hash, tmp, AVB_SHA512_DIGEST_SIZE);
+}
+
+/* Computes the SHA256 |hash| of a NUL-terminated |str|. */
+static void sha256_str(const char* str, uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
+ sha256((const uint8_t*)str, avb_strlen(str), hash);
+}
+
+/* Verifies structure and |expected_hash| of permanent |attributes|. */
+static bool verify_permanent_attributes(
+ const AvbAtxPermanentAttributes* attributes,
+ const uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE]) {
+ uint8_t hash[AVB_SHA256_DIGEST_SIZE];
+
+ if (attributes->version != 1) {
+ avb_error("Unsupported permanent attributes version.\n");
+ return false;
+ }
+ sha256((const uint8_t*)attributes, sizeof(AvbAtxPermanentAttributes), hash);
+ if (0 != avb_safe_memcmp(hash, expected_hash, AVB_SHA256_DIGEST_SIZE)) {
+ avb_error("Invalid permanent attributes.\n");
+ return false;
+ }
+ return true;
+}
+
+/* Verifies the format, key version, usage, and signature of a certificate. */
+static bool verify_certificate(
+ const AvbAtxCertificate* certificate,
+ const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
+ uint64_t minimum_key_version,
+ const uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]) {
+ const AvbAlgorithmData* algorithm_data;
+ uint8_t certificate_hash[AVB_SHA512_DIGEST_SIZE];
+
+ if (certificate->signed_data.version != 1) {
+ avb_error("Unsupported certificate format.\n");
+ return false;
+ }
+ algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
+ sha512((const uint8_t*)&certificate->signed_data,
+ sizeof(AvbAtxCertificateSignedData),
+ certificate_hash);
+ if (!avb_rsa_verify(authority,
+ AVB_ATX_PUBLIC_KEY_SIZE,
+ certificate->signature,
+ AVB_RSA4096_NUM_BYTES,
+ certificate_hash,
+ AVB_SHA512_DIGEST_SIZE,
+ algorithm_data->padding,
+ algorithm_data->padding_len)) {
+ avb_error("Invalid certificate signature.\n");
+ return false;
+ }
+ if (certificate->signed_data.key_version < minimum_key_version) {
+ avb_error("Key rollback detected.\n");
+ return false;
+ }
+ if (0 != avb_safe_memcmp(certificate->signed_data.usage,
+ expected_usage,
+ AVB_SHA256_DIGEST_SIZE)) {
+ avb_error("Invalid certificate usage.\n");
+ return false;
+ }
+ return true;
+}
+
+/* Verifies signature and fields of a PIK certificate. */
+static bool verify_pik_certificate(
+ const AvbAtxCertificate* certificate,
+ const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
+ uint64_t minimum_version) {
+ uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
+
+ sha256_str("com.google.android.things.vboot.ca", expected_usage);
+ if (!verify_certificate(
+ certificate, authority, minimum_version, expected_usage)) {
+ avb_error("Invalid PIK certificate.\n");
+ return false;
+ }
+ return true;
+}
+
+/* Verifies signature and fields of a PSK certificate. */
+static bool verify_psk_certificate(
+ const AvbAtxCertificate* certificate,
+ const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
+ uint64_t minimum_version,
+ const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
+ uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
+ uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
+
+ sha256_str("com.google.android.things.vboot", expected_usage);
+ if (!verify_certificate(
+ certificate, authority, minimum_version, expected_usage)) {
+ avb_error("Invalid PSK certificate.\n");
+ return false;
+ }
+ sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject);
+ if (0 != avb_safe_memcmp(certificate->signed_data.subject,
+ expected_subject,
+ AVB_SHA256_DIGEST_SIZE)) {
+ avb_error("PSK: Product ID mismatch.\n");
+ return false;
+ }
+ return true;
+}
+
+/* Verifies signature and fields of a PUK certificate. */
+static bool verify_puk_certificate(
+ const AvbAtxCertificate* certificate,
+ const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
+ uint64_t minimum_version,
+ const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
+ uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
+ uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
+
+ sha256_str("com.google.android.things.vboot.unlock", expected_usage);
+ if (!verify_certificate(
+ certificate, authority, minimum_version, expected_usage)) {
+ avb_error("Invalid PUK certificate.\n");
+ return false;
+ }
+ sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject);
+ if (0 != avb_safe_memcmp(certificate->signed_data.subject,
+ expected_subject,
+ AVB_SHA256_DIGEST_SIZE)) {
+ avb_error("PUK: Product ID mismatch.\n");
+ return false;
+ }
+ return true;
+}
+
+AvbIOResult avb_atx_validate_vbmeta_public_key(
+ AvbOps* ops,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ const uint8_t* public_key_metadata,
+ size_t public_key_metadata_length,
+ bool* out_is_trusted) {
+ AvbIOResult result = AVB_IO_RESULT_OK;
+ AvbAtxPermanentAttributes permanent_attributes;
+ uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
+ AvbAtxPublicKeyMetadata metadata;
+ uint64_t minimum_version;
+
+ /* Be pessimistic so we can exit early without having to remember to clear.
+ */
+ *out_is_trusted = false;
+
+ /* Read and verify permanent attributes. */
+ result = ops->atx_ops->read_permanent_attributes(ops->atx_ops,
+ &permanent_attributes);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to read permanent attributes.\n");
+ return result;
+ }
+ result = ops->atx_ops->read_permanent_attributes_hash(
+ ops->atx_ops, permanent_attributes_hash);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to read permanent attributes hash.\n");
+ return result;
+ }
+ if (!verify_permanent_attributes(&permanent_attributes,
+ permanent_attributes_hash)) {
+ return AVB_IO_RESULT_OK;
+ }
+
+ /* Sanity check public key metadata. */
+ if (public_key_metadata_length != sizeof(AvbAtxPublicKeyMetadata)) {
+ avb_error("Invalid public key metadata.\n");
+ return AVB_IO_RESULT_OK;
+ }
+ avb_memcpy(&metadata, public_key_metadata, sizeof(AvbAtxPublicKeyMetadata));
+ if (metadata.version != 1) {
+ avb_error("Unsupported public key metadata.\n");
+ return AVB_IO_RESULT_OK;
+ }
+
+ /* Verify the PIK certificate. */
+ result = ops->read_rollback_index(
+ ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to read PIK minimum version.\n");
+ return result;
+ }
+ if (!verify_pik_certificate(&metadata.product_intermediate_key_certificate,
+ permanent_attributes.product_root_public_key,
+ minimum_version)) {
+ return AVB_IO_RESULT_OK;
+ }
+
+ /* Verify the PSK certificate. */
+ result = ops->read_rollback_index(
+ ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to read PSK minimum version.\n");
+ return result;
+ }
+ if (!verify_psk_certificate(
+ &metadata.product_signing_key_certificate,
+ metadata.product_intermediate_key_certificate.signed_data.public_key,
+ minimum_version,
+ permanent_attributes.product_id)) {
+ return AVB_IO_RESULT_OK;
+ }
+
+ /* Verify the PSK is the same key that verified vbmeta. */
+ if (public_key_length != AVB_ATX_PUBLIC_KEY_SIZE) {
+ avb_error("Public key length mismatch.\n");
+ return AVB_IO_RESULT_OK;
+ }
+ if (0 != avb_safe_memcmp(
+ metadata.product_signing_key_certificate.signed_data.public_key,
+ public_key_data,
+ AVB_ATX_PUBLIC_KEY_SIZE)) {
+ avb_error("Public key mismatch.\n");
+ return AVB_IO_RESULT_OK;
+ }
+
+ /* Report the key versions used during verification. */
+ ops->atx_ops->set_key_version(
+ ops->atx_ops,
+ AVB_ATX_PIK_VERSION_LOCATION,
+ metadata.product_intermediate_key_certificate.signed_data.key_version);
+ ops->atx_ops->set_key_version(
+ ops->atx_ops,
+ AVB_ATX_PSK_VERSION_LOCATION,
+ metadata.product_signing_key_certificate.signed_data.key_version);
+
+ *out_is_trusted = true;
+ return AVB_IO_RESULT_OK;
+}
+
+AvbIOResult avb_atx_generate_unlock_challenge(
+ AvbAtxOps* atx_ops, AvbAtxUnlockChallenge* out_unlock_challenge) {
+ AvbIOResult result = AVB_IO_RESULT_OK;
+ AvbAtxPermanentAttributes permanent_attributes;
+
+ /* We need the permanent attributes to compute the product_id_hash. */
+ result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to read permanent attributes.\n");
+ return result;
+ }
+ result = atx_ops->get_random(
+ atx_ops, AVB_ATX_UNLOCK_CHALLENGE_SIZE, last_unlock_challenge);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to generate random challenge.\n");
+ return result;
+ }
+ out_unlock_challenge->version = 1;
+ sha256(permanent_attributes.product_id,
+ AVB_ATX_PRODUCT_ID_SIZE,
+ out_unlock_challenge->product_id_hash);
+ avb_memcpy(out_unlock_challenge->challenge,
+ last_unlock_challenge,
+ AVB_ATX_UNLOCK_CHALLENGE_SIZE);
+ return result;
+}
+
+AvbIOResult avb_atx_validate_unlock_credential(
+ AvbAtxOps* atx_ops,
+ const AvbAtxUnlockCredential* unlock_credential,
+ bool* out_is_trusted) {
+ AvbIOResult result = AVB_IO_RESULT_OK;
+ AvbAtxPermanentAttributes permanent_attributes;
+ uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
+ uint64_t minimum_version;
+ const AvbAlgorithmData* algorithm_data;
+ uint8_t challenge_hash[AVB_SHA512_DIGEST_SIZE];
+
+ /* Be pessimistic so we can exit early without having to remember to clear.
+ */
+ *out_is_trusted = false;
+
+ /* Sanity check the credential. */
+ if (unlock_credential->version != 1) {
+ avb_error("Unsupported unlock credential format.\n");
+ return AVB_IO_RESULT_OK;
+ }
+
+ /* Read and verify permanent attributes. */
+ result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to read permanent attributes.\n");
+ return result;
+ }
+ result = atx_ops->read_permanent_attributes_hash(atx_ops,
+ permanent_attributes_hash);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to read permanent attributes hash.\n");
+ return result;
+ }
+ if (!verify_permanent_attributes(&permanent_attributes,
+ permanent_attributes_hash)) {
+ return AVB_IO_RESULT_OK;
+ }
+
+ /* Verify the PIK certificate. */
+ result = atx_ops->ops->read_rollback_index(
+ atx_ops->ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to read PIK minimum version.\n");
+ return result;
+ }
+ if (!verify_pik_certificate(
+ &unlock_credential->product_intermediate_key_certificate,
+ permanent_attributes.product_root_public_key,
+ minimum_version)) {
+ return AVB_IO_RESULT_OK;
+ }
+
+ /* Verify the PUK certificate. The minimum version is shared with the PSK. */
+ result = atx_ops->ops->read_rollback_index(
+ atx_ops->ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version);
+ if (result != AVB_IO_RESULT_OK) {
+ avb_error("Failed to read PSK minimum version.\n");
+ return result;
+ }
+ if (!verify_puk_certificate(
+ &unlock_credential->product_unlock_key_certificate,
+ unlock_credential->product_intermediate_key_certificate.signed_data
+ .public_key,
+ minimum_version,
+ permanent_attributes.product_id)) {
+ return AVB_IO_RESULT_OK;
+ }
+
+ /* Verify the challenge signature. */
+ algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
+ sha512(last_unlock_challenge, AVB_ATX_UNLOCK_CHALLENGE_SIZE, challenge_hash);
+ if (!avb_rsa_verify(unlock_credential->product_unlock_key_certificate
+ .signed_data.public_key,
+ AVB_ATX_PUBLIC_KEY_SIZE,
+ unlock_credential->challenge_signature,
+ AVB_RSA4096_NUM_BYTES,
+ challenge_hash,
+ AVB_SHA512_DIGEST_SIZE,
+ algorithm_data->padding,
+ algorithm_data->padding_len)) {
+ avb_error("Invalid unlock challenge signature.\n");
+ return AVB_IO_RESULT_OK;
+ }
+
+ *out_is_trusted = true;
+ return AVB_IO_RESULT_OK;
+}
diff --git a/include/android_avb/avb_atx_validate.h b/lib/avb/libavb_atx/avb_atx_validate.h
index 9989bb1ddb..1a0690d491 100644
--- a/include/android_avb/avb_atx_validate.h
+++ b/lib/avb/libavb_atx/avb_atx_validate.h
@@ -1,79 +1,91 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
-#if !defined(AVB_INSIDE_LIBAVB_ATX_H) && !defined(AVB_COMPILATION)
-#error \
- "Never include this file directly, include libavb_atx/libavb_atx.h instead."
-#endif
-*/
-
-#ifndef AVB_ATX_VALIDATE_H_
-#define AVB_ATX_VALIDATE_H_
-
-#include <android_avb/avb_atx_ops.h>
-#include <android_avb/avb_atx_types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Rollback index locations for Android Things key versions. */
-#define AVB_ATX_PIK_VERSION_LOCATION 0x1000
-#define AVB_ATX_PSK_VERSION_LOCATION 0x1001
-
-/* An implementation of validate_vbmeta_public_key for Android Things. See
- * libavb/avb_ops.h for details on validate_vbmeta_public_key in general. This
- * implementation uses the metadata expected with Android Things vbmeta images
- * to perform validation on the public key. The ATX ops must be implemented.
- * That is, |ops->atx_ops| must be valid.
- *
- * There are a multiple values that need verification:
- * - Permanent Product Attributes: A hash of these attributes is fused into
- * hardware. Consistency is checked.
- * - Product Root Key (PRK): This key is provided in permanent attributes and
- * is the root authority for all Android Things
- * products.
- * - Product Intermediate Key (PIK): This key is a rotated intermediary. It is
- * certified by the PRK.
- * - Product Signing Key (PSK): This key is a rotated authority for a specific
- * Android Things product. It is certified by a
- * PIK and must match |public_key_data|.
- * - Product ID: This value is provided in permanent attributes and is unique
- * to a specific Android Things product. This value must match
- * the subject of the PSK certificate.
- */
-AvbIOResult avb_atx_validate_vbmeta_public_key(
- AvbOps* ops,
- const uint8_t* public_key_data,
- size_t public_key_length,
- const uint8_t* public_key_metadata,
- size_t public_key_metadata_length,
- bool* out_is_trusted);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_ATX_VALIDATE_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_ATX_H) && !defined(AVB_COMPILATION)
+#error \
+ "Never include this file directly, include libavb_atx/libavb_atx.h instead."
+#endif
+
+#ifndef AVB_ATX_VALIDATE_H_
+#define AVB_ATX_VALIDATE_H_
+
+#include "avb_atx_ops.h"
+#include "avb_atx_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Rollback index locations for Android Things key versions. */
+#define AVB_ATX_PIK_VERSION_LOCATION 0x1000
+#define AVB_ATX_PSK_VERSION_LOCATION 0x1001
+
+/* An implementation of validate_vbmeta_public_key for Android Things. See
+ * libavb/avb_ops.h for details on validate_vbmeta_public_key in general. This
+ * implementation uses the metadata expected with Android Things vbmeta images
+ * to perform validation on the public key. The ATX ops must be implemented.
+ * That is, |ops->atx_ops| must be valid.
+ *
+ * There are a multiple values that need verification:
+ * - Permanent Product Attributes: A hash of these attributes is fused into
+ * hardware. Consistency is checked.
+ * - Product Root Key (PRK): This key is provided in permanent attributes and
+ * is the root authority for all Android Things
+ * products.
+ * - Product Intermediate Key (PIK): This key is a rotated intermediary. It is
+ * certified by the PRK.
+ * - Product Signing Key (PSK): This key is a rotated authority for a specific
+ * Android Things product. It is certified by a
+ * PIK and must match |public_key_data|.
+ * - Product ID: This value is provided in permanent attributes and is unique
+ * to a specific Android Things product. This value must match
+ * the subject of the PSK certificate.
+ */
+AvbIOResult avb_atx_validate_vbmeta_public_key(
+ AvbOps* ops,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ const uint8_t* public_key_metadata,
+ size_t public_key_metadata_length,
+ bool* out_is_trusted);
+
+/* Generates a challenge which can be used to create an unlock credential. */
+AvbIOResult avb_atx_generate_unlock_challenge(
+ AvbAtxOps* atx_ops, AvbAtxUnlockChallenge* out_unlock_challenge);
+
+/* Validates an unlock credential. The certificate validation is very similar to
+ * the validation of public key metadata except in place of the PSK is a Product
+ * Unlock Key (PUK) and the certificate usage field identifies it as such. The
+ * challenge signature field is verified against this PUK.
+ */
+AvbIOResult avb_atx_validate_unlock_credential(
+ AvbAtxOps* atx_ops,
+ const AvbAtxUnlockCredential* unlock_credential,
+ bool* out_is_trusted);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_ATX_VALIDATE_H_ */
diff --git a/include/android_avb/libavb_atx.h b/lib/avb/libavb_atx/libavb_atx.h
index 36ae6daa59..839c0afa98 100644
--- a/include/android_avb/libavb_atx.h
+++ b/lib/avb/libavb_atx/libavb_atx.h
@@ -1,41 +1,41 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef LIBAVB_ATX_H_
-#define LIBAVB_ATX_H_
-
-#include <android_avb/libavb.h>
-
-/* The AVB_INSIDE_LIBAVB_ATX_H preprocessor symbol is used to enforce
- * library users to include only this file. All public interfaces, and
- * only public interfaces, must be included here.
- */
-
-#define AVB_INSIDE_LIBAVB_ATX_H
-#include <android_avb/avb_atx_ops.h>
-#include <android_avb/avb_atx_types.h>
-#include <android_avb/avb_atx_validate.h>
-#undef AVB_INSIDE_LIBAVB_ATX_H
-
-#endif /* LIBAVB_ATX_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef LIBAVB_ATX_H_
+#define LIBAVB_ATX_H_
+
+#include <libavb/libavb.h>
+
+/* The AVB_INSIDE_LIBAVB_ATX_H preprocessor symbol is used to enforce
+ * library users to include only this file. All public interfaces, and
+ * only public interfaces, must be included here.
+ */
+
+#define AVB_INSIDE_LIBAVB_ATX_H
+#include "avb_atx_ops.h"
+#include "avb_atx_types.h"
+#include "avb_atx_validate.h"
+#undef AVB_INSIDE_LIBAVB_ATX_H
+
+#endif /* LIBAVB_ATX_H_ */
diff --git a/lib/avb/libavb_user/Makefile b/lib/avb/libavb_user/Makefile
index fe634018e3..1e2062d4c6 100644
--- a/lib/avb/libavb_user/Makefile
+++ b/lib/avb/libavb_user/Makefile
@@ -1,3 +1,4 @@
+ccflags-y += -DAVB_COMPILATION
obj-y += avb_ops_user.o
obj-y += avb_user_verification.o
obj-y += avb_user_verity.o
diff --git a/lib/avb/libavb_user/avb_ops_user.c b/lib/avb/libavb_user/avb_ops_user.c
deleted file mode 100644
index 2c4937485f..0000000000
--- a/lib/avb/libavb_user/avb_ops_user.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <common.h>
-#include <image.h>
-#include <android_image.h>
-#include <malloc.h>
-#include <mapmem.h>
-#include <errno.h>
-#include <command.h>
-#include <mmc.h>
-#include <blk.h>
-#include <part.h>
-#include <android_avb/avb_ops_user.h>
-#include <android_avb/libavb_ab.h>
-#include <android_avb/avb_atx_validate.h>
-#include <android_avb/avb_atx_types.h>
-#include <optee_include/OpteeClientInterface.h>
-#include <optee_include/tee_api_defines.h>
-#include <android_avb/avb_vbmeta_image.h>
-#include <android_avb/avb_atx_validate.h>
-#include <android_avb/rk_avb_ops_user.h>
-
-static void byte_to_block(int64_t *offset,
- size_t *num_bytes,
- lbaint_t *offset_blk,
- lbaint_t *blkcnt)
-{
- *offset_blk = (lbaint_t)(*offset / 512);
- if (*num_bytes % 512 == 0) {
- if (*offset % 512 == 0) {
- *blkcnt = (lbaint_t)(*num_bytes / 512);
- } else {
- *blkcnt = (lbaint_t)(*num_bytes / 512) + 1;
- }
- } else {
- if (*offset % 512 == 0) {
- *blkcnt = (lbaint_t)(*num_bytes / 512) + 1;
- } else {
- if ((*offset % 512) + (*num_bytes % 512) < 512 ||
- (*offset % 512) + (*num_bytes % 512) == 512) {
- *blkcnt = (lbaint_t)(*num_bytes / 512) + 1;
- } else {
- *blkcnt = (lbaint_t)(*num_bytes / 512) + 2;
- }
- }
- }
-}
-
-static AvbIOResult read_from_partition(AvbOps* ops,
- const char* partition,
- int64_t offset,
- size_t num_bytes,
- void* buffer,
- size_t* out_num_read)
-{
- char *dev_iface = "mmc";
- int dev_num = 0;
- struct blk_desc *dev_desc;
- lbaint_t offset_blk, blkcnt;
- disk_partition_t part_info;
-
- byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt);
- dev_desc = blk_get_dev(dev_iface, dev_num);
- if (!dev_desc) {
- printf("Could not find %s %d\n", dev_iface, dev_num);
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
-
- if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
- printf("Could not find \"%s\" partition\n", partition);
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
-
- if((offset % 512 == 0) && (num_bytes % 512 == 0)) {
- blk_dread(dev_desc, part_info.start + offset_blk, blkcnt, buffer);
- *out_num_read = blkcnt * 512;
- } else {
- char *buffer_temp;
- buffer_temp = malloc(512 * blkcnt);
- if (buffer_temp == NULL) {
- printf("malloc error!\n");
- return AVB_IO_RESULT_ERROR_OOM;
- }
- blk_dread(dev_desc, part_info.start + offset_blk, blkcnt, buffer_temp);
- memcpy(buffer, buffer_temp + (offset % 512), num_bytes);
- *out_num_read = num_bytes;
- free(buffer_temp);
- }
-
- return AVB_IO_RESULT_OK;
-}
-
-static AvbIOResult write_to_partition(AvbOps* ops,
- const char* partition,
- int64_t offset,
- size_t num_bytes,
- const void* buffer)
-{
- const char *dev_iface = "mmc";
- int dev_num = 0;
- struct blk_desc *dev_desc;
- char *buffer_temp;
- disk_partition_t part_info;
- lbaint_t offset_blk, blkcnt;
-
- byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt);
- buffer_temp = malloc(512 * blkcnt);
- if (buffer_temp == NULL) {
- printf("malloc error!\n");
- return AVB_IO_RESULT_ERROR_OOM;
- }
- memset(buffer_temp, 0, 512 * blkcnt);
- dev_desc = blk_get_dev(dev_iface, dev_num);
- if (!dev_desc) {
- printf("Could not find %s %d\n", dev_iface, dev_num);
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
-
- if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
- printf("Could not find \"%s\" partition\n", partition);
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
-
- if ((offset % 512 != 0) && (num_bytes % 512) != 0) {
- blk_dread(dev_desc, part_info.start + offset_blk, blkcnt, buffer_temp);
- }
-
- memcpy(buffer_temp, buffer + (offset % 512), num_bytes);
- blk_dwrite(dev_desc, part_info.start + offset_blk, blkcnt, buffer);
- free(buffer_temp);
-
- return AVB_IO_RESULT_OK;
-}
-
-static AvbIOResult validate_vbmeta_public_key(
- AvbOps *ops,
- const uint8_t *public_key_data,
- size_t public_key_length,
- const uint8_t *public_key_metadata,
- size_t public_key_metadata_length,
- bool *out_is_trusted)
-{
-#ifdef AVB_VBMETA_PUBLIC_KEY_VALIDATE
- if (out_is_trusted != NULL) {
- avb_atx_validate_vbmeta_public_key(ops,
- public_key_data,
- public_key_length,
- public_key_metadata,
- public_key_metadata_length,
- out_is_trusted);
- }
-#else
- if (out_is_trusted != NULL) {
- *out_is_trusted = true;
- }
-#endif
- return AVB_IO_RESULT_OK;
-}
-
-static AvbIOResult read_rollback_index(AvbOps *ops,
- size_t rollback_index_location,
- uint64_t *out_rollback_index)
-{
- if (out_rollback_index != NULL) {
-#ifdef CONFIG_OPTEE_CLIENT
- int ret;
- ret = trusty_read_rollback_index(rollback_index_location,
- out_rollback_index);
- if (ret == TEE_ERROR_GENERIC) {
- *out_rollback_index = 0;
- ret = trusty_write_rollback_index(rollback_index_location,
- *out_rollback_index);
- if (ret != 0) {
- printf("%s: init rollback index error\n", __FILE__);
- return AVB_IO_RESULT_ERROR_IO;
- }
- ret = trusty_read_rollback_index(rollback_index_location,
- out_rollback_index);
- if (ret == 0)
- return AVB_IO_RESULT_OK;
- } else if (ret == 0) {
- return AVB_IO_RESULT_OK;
- } else {
- printf("trusty_read_rollback_index ret = %x\n", ret);
- return AVB_IO_RESULT_ERROR_IO;
- }
-#endif
- }
- return AVB_IO_RESULT_ERROR_IO;
-}
-
-static AvbIOResult write_rollback_index(AvbOps *ops,
- size_t rollback_index_location,
- uint64_t rollback_index)
-{
-#ifdef CONFIG_OPTEE_CLIENT
- if (trusty_write_rollback_index(rollback_index_location, rollback_index)) {
- printf("%s: Fail to write rollback index\n", __FILE__);
- return AVB_IO_RESULT_ERROR_IO;
- }
- return AVB_IO_RESULT_OK;
-#endif
- return AVB_IO_RESULT_ERROR_IO;
-}
-
-static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
-{
- if (out_is_unlocked != NULL) {
-#ifdef CONFIG_OPTEE_CLIENT
- int ret;
-
- ret = trusty_read_lock_state((uint8_t *)out_is_unlocked);
- if (ret == TEE_ERROR_GENERIC) {
- *out_is_unlocked = 1;
- if (trusty_write_lock_state(*out_is_unlocked)) {
- printf("%s: init lock state error\n", __FILE__);
- return AVB_IO_RESULT_ERROR_IO;
- }
-
- ret = trusty_read_lock_state((uint8_t *)out_is_unlocked);
- if(ret == 0)
- return 0;
- } else if (ret == 0) {
- return AVB_IO_RESULT_OK;
- } else {
- printf("read_is_device_unlocked ret = %x\n", ret);
- return AVB_IO_RESULT_ERROR_IO;
- }
-#endif
- }
- return AVB_IO_RESULT_ERROR_IO;
-}
-
-static AvbIOResult write_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
-{
- if (out_is_unlocked != NULL) {
-#ifdef CONFIG_OPTEE_CLIENT
- if (trusty_write_lock_state(*out_is_unlocked)) {
- printf("%s: Fail to write lock state\n", __FILE__);
- return AVB_IO_RESULT_ERROR_IO;
- }
- return AVB_IO_RESULT_OK;
-#endif
- }
- return AVB_IO_RESULT_ERROR_IO;
-}
-
-static AvbIOResult get_size_of_partition(AvbOps *ops,
- const char *partition,
- uint64_t *out_size_in_bytes)
-{
- const char *dev_iface = "mmc";
- int dev_num = 0;
- struct blk_desc *dev_desc;
- disk_partition_t part_info;
-
- dev_desc = blk_get_dev(dev_iface, dev_num);
- if (!dev_desc) {
- printf("Could not find %s %d\n", dev_iface, dev_num);
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
-
- if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
- printf("Could not find \"%s\" partition\n", partition);
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
- *out_size_in_bytes = (part_info.size) * 512;
- return AVB_IO_RESULT_OK;
-}
-
-static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
- const char *partition,
- char *guid_buf,
- size_t guid_buf_size)
-{
- const char *dev_iface = "mmc";
- int dev_num = 0;
- struct blk_desc *dev_desc;
- disk_partition_t part_info;
- dev_desc = blk_get_dev(dev_iface, dev_num);
- if (!dev_desc) {
- printf("Could not find %s %d\n", dev_iface, dev_num);
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
-
- if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
- printf("Could not find \"%s\" partition\n", partition);
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
- if (guid_buf != NULL && guid_buf_size > 0) {
- memcpy(guid_buf, part_info.uuid, guid_buf_size);
- }
- return AVB_IO_RESULT_OK;
-}
-
-/* read permanent attributes from rpmb */
-AvbIOResult avb_read_perm_attr(AvbAtxOps* atx_ops,
- AvbAtxPermanentAttributes* attributes)
-{
- if (attributes != NULL) {
-#ifdef CONFIG_OPTEE_CLIENT
- trusty_read_permanent_attributes((uint8_t *)attributes,
- sizeof(struct AvbAtxPermanentAttributes));
- return AVB_IO_RESULT_OK;
-#endif
- }
-
- return -1;
-}
-
-/*read permanent attributes hash from efuse */
-AvbIOResult avb_read_perm_attr_hash(AvbAtxOps* atx_ops,
- uint8_t hash[AVB_SHA256_DIGEST_SIZE])
-{
-#ifdef CONFIG_OPTEE_CLIENT
- if (trusty_read_attribute_hash((uint32_t *)hash, AVB_SHA256_DIGEST_SIZE / 4))
- return -1;
-#else
- avb_error("Please open the macro!\n");
- return -1;
-#endif
- return AVB_IO_RESULT_OK;
-}
-
-AvbOps* avb_ops_user_new(void) {
- AvbOps* ops;
-
- ops = calloc(1, sizeof(AvbOps));
- if (ops == NULL) {
- avb_error("Error allocating memory for AvbOps.\n");
- goto out;
- }
-
- ops->ab_ops = calloc(1, sizeof(AvbABOps));
- if (ops->ab_ops == NULL) {
- avb_error("Error allocating memory for AvbABOps.\n");
- free(ops);
- goto out;
- }
-
- ops->atx_ops = calloc(1, sizeof(AvbAtxOps));
- if (ops->atx_ops == NULL) {
- avb_error("Error allocating memory for AvbAtxOps.\n");
- free(ops->ab_ops);
- free(ops);
- goto out;
- }
- ops->ab_ops->ops = ops;
- ops->atx_ops->ops = ops;
-
- ops->read_from_partition = read_from_partition;
- ops->write_to_partition = write_to_partition;
- ops->validate_vbmeta_public_key = validate_vbmeta_public_key;
- ops->read_rollback_index = read_rollback_index;
- ops->write_rollback_index = write_rollback_index;
- ops->read_is_device_unlocked = read_is_device_unlocked;
- ops->write_is_device_unlocked = write_is_device_unlocked;
- ops->get_unique_guid_for_partition = get_unique_guid_for_partition;
- ops->get_size_of_partition = get_size_of_partition;
- ops->ab_ops->read_ab_metadata = avb_ab_data_read;
- ops->ab_ops->write_ab_metadata = avb_ab_data_write;
- ops->atx_ops->read_permanent_attributes = avb_read_perm_attr;
- ops->atx_ops->read_permanent_attributes_hash = avb_read_perm_attr_hash;
-
-out:
- return ops;
-}
-
-
-void avb_ops_user_free(AvbOps* ops) {
- free(ops->ab_ops);
- free(ops->atx_ops);
- free(ops);
-}
diff --git a/lib/avb/libavb_user/avb_ops_user.cpp b/lib/avb/libavb_user/avb_ops_user.cpp
new file mode 100644
index 0000000000..3600248ab4
--- /dev/null
+++ b/lib/avb/libavb_user/avb_ops_user.cpp
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_ops_user.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <fs_mgr.h>
+
+#include <libavb_ab/libavb_ab.h>
+
+/* Open the appropriate fstab file and fallback to /fstab.device if
+ * that's what's being used.
+ */
+static struct fstab* open_fstab(void) {
+#if 0
+ struct fstab* fstab = fs_mgr_read_fstab_default();
+#else
+ char propbuf[PROPERTY_VALUE_MAX];
+ char fstab_name[PROPERTY_VALUE_MAX + 32];
+ struct fstab* fstab;
+
+ property_get("ro.hardware", propbuf, "");
+ snprintf(fstab_name, sizeof(fstab_name), "/fstab.%s", propbuf);
+ fstab = fs_mgr_read_fstab(fstab_name);
+#endif
+
+ if (fstab != NULL) {
+ return fstab;
+ }
+
+ fstab = fs_mgr_read_fstab("/fstab.device");
+ return fstab;
+}
+
+static int open_partition(const char* name, int flags) {
+ char* path;
+ int fd;
+ struct fstab* fstab;
+ struct fstab_rec* record;
+
+ /* We can't use fs_mgr to look up |name| because fstab doesn't list
+ * every slot partition (it uses the slotselect option to mask the
+ * suffix) and |slot| is expected to be of that form, e.g. boot_a.
+ *
+ * We can however assume that there's an entry for the /misc mount
+ * point and use that to get the device file for the misc
+ * partition. From there we'll assume that a by-name scheme is used
+ * so we can just replace the trailing "misc" by the given |name|,
+ * e.g.
+ *
+ * /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
+ * /dev/block/platform/soc.0/7824900.sdhci/by-name/boot_a
+ *
+ * If needed, it's possible to relax this assumption in the future
+ * by trawling /sys/block looking for the appropriate sibling of
+ * misc and then finding an entry in /dev matching the sysfs entry.
+ */
+
+ fstab = open_fstab();
+ if (fstab == NULL) {
+ return -1;
+ }
+ record = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
+ if (record == NULL) {
+ fs_mgr_free_fstab(fstab);
+ return -1;
+ }
+ if (strcmp(name, "misc") == 0) {
+ path = strdup(record->blk_device);
+ } else {
+ size_t trimmed_len, name_len;
+ const char* end_slash = strrchr(record->blk_device, '/');
+ if (end_slash == NULL) {
+ fs_mgr_free_fstab(fstab);
+ return -1;
+ }
+ trimmed_len = end_slash - record->blk_device + 1;
+ name_len = strlen(name);
+ path = static_cast<char*>(calloc(trimmed_len + name_len + 1, 1));
+ strncpy(path, record->blk_device, trimmed_len);
+ strncpy(path + trimmed_len, name, name_len);
+ }
+ fs_mgr_free_fstab(fstab);
+
+ fd = open(path, flags);
+ free(path);
+
+ return fd;
+}
+
+static AvbIOResult read_from_partition(AvbOps* ops,
+ const char* partition,
+ int64_t offset,
+ size_t num_bytes,
+ void* buffer,
+ size_t* out_num_read) {
+ int fd;
+ off_t where;
+ ssize_t num_read;
+ AvbIOResult ret;
+
+ fd = open_partition(partition, O_RDONLY);
+ if (fd == -1) {
+ ret = AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ goto out;
+ }
+
+ if (offset < 0) {
+ uint64_t partition_size;
+ if (ioctl(fd, BLKGETSIZE64, &partition_size) != 0) {
+ avb_errorv(
+ "Error getting size of \"", partition, "\" partition.\n", NULL);
+ ret = AVB_IO_RESULT_ERROR_IO;
+ goto out;
+ }
+ offset = partition_size - (-offset);
+ }
+
+ where = lseek(fd, offset, SEEK_SET);
+ if (where == -1) {
+ avb_error("Error seeking to offset.\n");
+ ret = AVB_IO_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (where != offset) {
+ avb_error("Error seeking to offset.\n");
+ ret = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+ goto out;
+ }
+
+ /* On Linux, we never get partial reads from block devices (except
+ * for EOF).
+ */
+ num_read = read(fd, buffer, num_bytes);
+ if (num_read == -1) {
+ avb_error("Error reading data.\n");
+ ret = AVB_IO_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (out_num_read != NULL) {
+ *out_num_read = num_read;
+ }
+
+ ret = AVB_IO_RESULT_OK;
+
+out:
+ if (fd != -1) {
+ if (close(fd) != 0) {
+ avb_error("Error closing file descriptor.\n");
+ }
+ }
+ return ret;
+}
+
+static AvbIOResult write_to_partition(AvbOps* ops,
+ const char* partition,
+ int64_t offset,
+ size_t num_bytes,
+ const void* buffer) {
+ int fd;
+ off_t where;
+ ssize_t num_written;
+ AvbIOResult ret;
+
+ fd = open_partition(partition, O_WRONLY);
+ if (fd == -1) {
+ avb_errorv("Error opening \"", partition, "\" partition.\n", NULL);
+ ret = AVB_IO_RESULT_ERROR_IO;
+ goto out;
+ }
+
+ where = lseek(fd, offset, SEEK_SET);
+ if (where == -1) {
+ avb_error("Error seeking to offset.\n");
+ ret = AVB_IO_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (where != offset) {
+ avb_error("Error seeking to offset.\n");
+ ret = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
+ goto out;
+ }
+
+ /* On Linux, we never get partial writes on block devices. */
+ num_written = write(fd, buffer, num_bytes);
+ if (num_written == -1) {
+ avb_error("Error writing data.\n");
+ ret = AVB_IO_RESULT_ERROR_IO;
+ goto out;
+ }
+
+ ret = AVB_IO_RESULT_OK;
+
+out:
+ if (fd != -1) {
+ if (close(fd) != 0) {
+ avb_error("Error closing file descriptor.\n");
+ }
+ }
+ return ret;
+}
+
+static AvbIOResult validate_vbmeta_public_key(
+ AvbOps* ops,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ const uint8_t* public_key_metadata,
+ size_t public_key_metadata_length,
+ bool* out_is_trusted) {
+ if (out_is_trusted != NULL) {
+ *out_is_trusted = true;
+ }
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult read_rollback_index(AvbOps* ops,
+ size_t rollback_index_location,
+ uint64_t* out_rollback_index) {
+ if (out_rollback_index != NULL) {
+ *out_rollback_index = 0;
+ }
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult write_rollback_index(AvbOps* ops,
+ size_t rollback_index_location,
+ uint64_t rollback_index) {
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked) {
+ if (out_is_unlocked != NULL) {
+ *out_is_unlocked = true;
+ }
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult get_size_of_partition(AvbOps* ops,
+ const char* partition,
+ uint64_t* out_size_in_bytes) {
+ int fd;
+ AvbIOResult ret;
+
+ fd = open_partition(partition, O_WRONLY);
+ if (fd == -1) {
+ avb_errorv("Error opening \"", partition, "\" partition.\n", NULL);
+ ret = AVB_IO_RESULT_ERROR_IO;
+ goto out;
+ }
+
+ if (out_size_in_bytes != NULL) {
+ if (ioctl(fd, BLKGETSIZE64, out_size_in_bytes) != 0) {
+ avb_errorv(
+ "Error getting size of \"", partition, "\" partition.\n", NULL);
+ ret = AVB_IO_RESULT_ERROR_IO;
+ goto out;
+ }
+ }
+
+ ret = AVB_IO_RESULT_OK;
+
+out:
+ if (fd != -1) {
+ if (close(fd) != 0) {
+ avb_error("Error closing file descriptor.\n");
+ }
+ }
+ return ret;
+}
+
+static AvbIOResult get_unique_guid_for_partition(AvbOps* ops,
+ const char* partition,
+ char* guid_buf,
+ size_t guid_buf_size) {
+ if (guid_buf != NULL && guid_buf_size > 0) {
+ guid_buf[0] = '\0';
+ }
+ return AVB_IO_RESULT_OK;
+}
+
+AvbOps* avb_ops_user_new(void) {
+ AvbOps* ops;
+
+ ops = static_cast<AvbOps*>(calloc(1, sizeof(AvbOps)));
+ if (ops == NULL) {
+ avb_error("Error allocating memory for AvbOps.\n");
+ goto out;
+ }
+
+ ops->ab_ops = static_cast<AvbABOps*>(calloc(1, sizeof(AvbABOps)));
+ if (ops->ab_ops == NULL) {
+ avb_error("Error allocating memory for AvbABOps.\n");
+ free(ops);
+ goto out;
+ }
+ ops->ab_ops->ops = ops;
+
+ ops->read_from_partition = read_from_partition;
+ ops->write_to_partition = write_to_partition;
+ ops->validate_vbmeta_public_key = validate_vbmeta_public_key;
+ ops->read_rollback_index = read_rollback_index;
+ ops->write_rollback_index = write_rollback_index;
+ ops->read_is_device_unlocked = read_is_device_unlocked;
+ ops->get_unique_guid_for_partition = get_unique_guid_for_partition;
+ ops->get_size_of_partition = get_size_of_partition;
+ ops->ab_ops->read_ab_metadata = avb_ab_data_read;
+ ops->ab_ops->write_ab_metadata = avb_ab_data_write;
+
+out:
+ return ops;
+}
+
+void avb_ops_user_free(AvbOps* ops) {
+ free(ops->ab_ops);
+ free(ops);
+}
diff --git a/include/android_avb/avb_ops_user.h b/lib/avb/libavb_user/avb_ops_user.h
index 36a98da08e..95a56b6181 100644
--- a/include/android_avb/avb_ops_user.h
+++ b/lib/avb/libavb_user/avb_ops_user.h
@@ -1,70 +1,69 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef AVB_OPS_USER_H_
-#define AVB_OPS_USER_H_
-
-#include <android_avb/libavb.h>
-#include <android_avb/avb_ab_flow.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Allocates an AvbOps instance suitable for use in Android userspace
- * on the device. Returns NULL on OOM.
- *
- * The returned AvbOps has the following characteristics:
- *
- * - The read_from_partition(), write_to_partition(), and
- * get_size_of_partition() operations are implemented, however for
- * these operations to work the fstab file on the device must have a
- * /misc entry using a by-name device file scheme and the containing
- * by-name/ subdirectory must have files for other partitions.
- *
- * - The remaining operations are implemented and never fails and
- * return the following values:
- * - validate_vbmeta_public_key(): always returns |true|.
- * - read_rollback_index(): returns 0 for any roolback index.
- * - write_rollback_index(): no-op.
- * - read_is_device_unlocked(): always returns |true|.
- * - get_unique_guid_for_partition(): always returns the empty string.
- *
- * - The |ab_ops| member will point to a valid AvbABOps instance
- * implemented via libavb_ab/. This should only be used if the AVB
- * A/B stack is used on the device. This is what is used in
- * bootctrl.avb boot control implementation.
- *
- * Free with avb_ops_user_free().
- */
-AvbOps* avb_ops_user_new(void);
-
-/* Frees an AvbOps instance previously allocated with avb_ops_device_new(). */
-void avb_ops_user_free(AvbOps* ops);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_OPS_USER_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef AVB_OPS_USER_H_
+#define AVB_OPS_USER_H_
+
+#include <libavb/libavb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Allocates an AvbOps instance suitable for use in Android userspace
+ * on the device. Returns NULL on OOM.
+ *
+ * The returned AvbOps has the following characteristics:
+ *
+ * - The read_from_partition(), write_to_partition(), and
+ * get_size_of_partition() operations are implemented, however for
+ * these operations to work the fstab file on the device must have a
+ * /misc entry using a by-name device file scheme and the containing
+ * by-name/ subdirectory must have files for other partitions.
+ *
+ * - The remaining operations are implemented and never fails and
+ * return the following values:
+ * - validate_vbmeta_public_key(): always returns |true|.
+ * - read_rollback_index(): returns 0 for any roolback index.
+ * - write_rollback_index(): no-op.
+ * - read_is_device_unlocked(): always returns |true|.
+ * - get_unique_guid_for_partition(): always returns the empty string.
+ *
+ * - The |ab_ops| member will point to a valid AvbABOps instance
+ * implemented via libavb_ab/. This should only be used if the AVB
+ * A/B stack is used on the device. This is what is used in
+ * bootctrl.avb boot control implementation.
+ *
+ * Free with avb_ops_user_free().
+ */
+AvbOps* avb_ops_user_new(void);
+
+/* Frees an AvbOps instance previously allocated with avb_ops_device_new(). */
+void avb_ops_user_free(AvbOps* ops);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_OPS_USER_H_ */
diff --git a/lib/avb/libavb_user/avb_user_verification.c b/lib/avb/libavb_user/avb_user_verification.c
index 9b0e69d401..f572128da3 100644
--- a/lib/avb/libavb_user/avb_user_verification.c
+++ b/lib/avb/libavb_user/avb_user_verification.c
@@ -1,214 +1,214 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_user_verification.h>
-
-/* Maximum allow length (in bytes) of a partition name, including
- * ab_suffix.
- */
-#define AVB_PART_NAME_MAX_SIZE 32
-
-/* Loads the toplevel AvbVBMetaImageHeader from the slot denoted by
- * |ab_suffix| into |vbmeta_image|. No validation, verification, or
- * byteswapping is performed.
- *
- * If successful, |true| is returned and the partition it was loaded
- * from is returned in |out_partition_name| and the offset on said
- * partition is returned in |out_vbmeta_offset|.
- */
-static bool load_top_level_vbmeta_header(
- AvbOps* ops,
- const char* ab_suffix,
- uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE],
- char out_partition_name[AVB_PART_NAME_MAX_SIZE],
- uint64_t* out_vbmeta_offset) {
- uint64_t vbmeta_offset = 0;
- size_t num_read;
- bool ret = false;
- AvbIOResult io_res;
-
- /* Construct full partition name. */
- if (!avb_str_concat(out_partition_name,
- AVB_PART_NAME_MAX_SIZE,
- "vbmeta",
- 6,
- ab_suffix,
- avb_strlen(ab_suffix))) {
- avb_error("Partition name and suffix does not fit.\n");
- goto out;
- }
-
- /* Only read the header, not the entire struct. */
- io_res = ops->read_from_partition(ops,
- out_partition_name,
- vbmeta_offset,
- AVB_VBMETA_IMAGE_HEADER_SIZE,
- vbmeta_image,
- &num_read);
- if (io_res == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
- AvbFooter footer;
-
- /* Try looking for the vbmeta struct in 'boot' via the footer. */
- if (!avb_str_concat(out_partition_name,
- AVB_PART_NAME_MAX_SIZE,
- "boot",
- 4,
- ab_suffix,
- avb_strlen(ab_suffix))) {
- avb_error("Partition name and suffix does not fit.\n");
- goto out;
- }
- io_res = ops->read_from_partition(ops,
- out_partition_name,
- -AVB_FOOTER_SIZE,
- AVB_FOOTER_SIZE,
- &footer,
- &num_read);
- if (io_res != AVB_IO_RESULT_OK) {
- avb_errorv("Error loading footer from partition '",
- out_partition_name,
- "'\n",
- NULL);
- goto out;
- }
-
- if (avb_memcmp(footer.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) != 0) {
- avb_errorv("Data from '",
- out_partition_name,
- "' does not look like a vbmeta footer.\n",
- NULL);
- goto out;
- }
-
- vbmeta_offset = avb_be64toh(footer.vbmeta_offset);
- io_res = ops->read_from_partition(ops,
- out_partition_name,
- vbmeta_offset,
- AVB_VBMETA_IMAGE_HEADER_SIZE,
- vbmeta_image,
- &num_read);
- }
-
- if (io_res != AVB_IO_RESULT_OK) {
- avb_errorv(
- "Error loading from partition '", out_partition_name, "'\n", NULL);
- goto out;
- }
-
- if (out_vbmeta_offset != NULL) {
- *out_vbmeta_offset = vbmeta_offset;
- }
-
- ret = true;
-
-out:
- return ret;
-}
-
-bool avb_user_verification_get(AvbOps* ops,
- const char* ab_suffix,
- bool* out_verification_enabled) {
- uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
- char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
- AvbVBMetaImageHeader* header;
- uint32_t flags;
- bool ret = false;
-
- if (!load_top_level_vbmeta_header(
- ops, ab_suffix, vbmeta_image, partition_name, NULL)) {
- goto out;
- }
-
- if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
- avb_errorv("Data from '",
- partition_name,
- "' does not look like a vbmeta header.\n",
- NULL);
- goto out;
- }
-
- /* Set/clear the VERIFICATION_DISABLED bit, as requested. */
- header = (AvbVBMetaImageHeader*)vbmeta_image;
- flags = avb_be32toh(header->flags);
-
- if (out_verification_enabled != NULL) {
- *out_verification_enabled =
- !(flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
- }
-
- ret = true;
-
-out:
- return ret;
-}
-
-bool avb_user_verification_set(AvbOps* ops,
- const char* ab_suffix,
- bool enable_verification) {
- uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
- char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
- uint64_t vbmeta_offset;
- AvbIOResult io_res;
- AvbVBMetaImageHeader* header;
- uint32_t flags;
- bool ret = false;
-
- if (!load_top_level_vbmeta_header(
- ops, ab_suffix, vbmeta_image, partition_name, &vbmeta_offset)) {
- goto out;
- }
-
- if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
- avb_errorv("Data from '",
- partition_name,
- "' does not look like a vbmeta header.\n",
- NULL);
- goto out;
- }
-
- /* Set/clear the VERIFICATION_DISABLED bit, as requested. */
- header = (AvbVBMetaImageHeader*)vbmeta_image;
- flags = avb_be32toh(header->flags);
- flags &= ~AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
- if (!enable_verification) {
- flags |= AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
- }
- header->flags = avb_htobe32(flags);
-
- /* Write the header. */
- io_res = ops->write_to_partition(ops,
- partition_name,
- vbmeta_offset,
- AVB_VBMETA_IMAGE_HEADER_SIZE,
- vbmeta_image);
- if (io_res != AVB_IO_RESULT_OK) {
- avb_errorv("Error writing to partition '", partition_name, "'\n", NULL);
- goto out;
- }
-
- ret = true;
-
-out:
- return ret;
-}
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_user_verification.h"
+
+/* Maximum allow length (in bytes) of a partition name, including
+ * ab_suffix.
+ */
+#define AVB_PART_NAME_MAX_SIZE 32
+
+/* Loads the toplevel AvbVBMetaImageHeader from the slot denoted by
+ * |ab_suffix| into |vbmeta_image|. No validation, verification, or
+ * byteswapping is performed.
+ *
+ * If successful, |true| is returned and the partition it was loaded
+ * from is returned in |out_partition_name| and the offset on said
+ * partition is returned in |out_vbmeta_offset|.
+ */
+static bool load_top_level_vbmeta_header(
+ AvbOps* ops,
+ const char* ab_suffix,
+ uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE],
+ char out_partition_name[AVB_PART_NAME_MAX_SIZE],
+ uint64_t* out_vbmeta_offset) {
+ uint64_t vbmeta_offset = 0;
+ size_t num_read;
+ bool ret = false;
+ AvbIOResult io_res;
+
+ /* Construct full partition name. */
+ if (!avb_str_concat(out_partition_name,
+ AVB_PART_NAME_MAX_SIZE,
+ "vbmeta",
+ 6,
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("Partition name and suffix does not fit.\n");
+ goto out;
+ }
+
+ /* Only read the header, not the entire struct. */
+ io_res = ops->read_from_partition(ops,
+ out_partition_name,
+ vbmeta_offset,
+ AVB_VBMETA_IMAGE_HEADER_SIZE,
+ vbmeta_image,
+ &num_read);
+ if (io_res == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
+ AvbFooter footer;
+
+ /* Try looking for the vbmeta struct in 'boot' via the footer. */
+ if (!avb_str_concat(out_partition_name,
+ AVB_PART_NAME_MAX_SIZE,
+ "boot",
+ 4,
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("Partition name and suffix does not fit.\n");
+ goto out;
+ }
+ io_res = ops->read_from_partition(ops,
+ out_partition_name,
+ -AVB_FOOTER_SIZE,
+ AVB_FOOTER_SIZE,
+ &footer,
+ &num_read);
+ if (io_res != AVB_IO_RESULT_OK) {
+ avb_errorv("Error loading footer from partition '",
+ out_partition_name,
+ "'\n",
+ NULL);
+ goto out;
+ }
+
+ if (avb_memcmp(footer.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) != 0) {
+ avb_errorv("Data from '",
+ out_partition_name,
+ "' does not look like a vbmeta footer.\n",
+ NULL);
+ goto out;
+ }
+
+ vbmeta_offset = avb_be64toh(footer.vbmeta_offset);
+ io_res = ops->read_from_partition(ops,
+ out_partition_name,
+ vbmeta_offset,
+ AVB_VBMETA_IMAGE_HEADER_SIZE,
+ vbmeta_image,
+ &num_read);
+ }
+
+ if (io_res != AVB_IO_RESULT_OK) {
+ avb_errorv(
+ "Error loading from partition '", out_partition_name, "'\n", NULL);
+ goto out;
+ }
+
+ if (out_vbmeta_offset != NULL) {
+ *out_vbmeta_offset = vbmeta_offset;
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
+
+bool avb_user_verification_get(AvbOps* ops,
+ const char* ab_suffix,
+ bool* out_verification_enabled) {
+ uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
+ char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
+ AvbVBMetaImageHeader* header;
+ uint32_t flags;
+ bool ret = false;
+
+ if (!load_top_level_vbmeta_header(
+ ops, ab_suffix, vbmeta_image, partition_name, NULL)) {
+ goto out;
+ }
+
+ if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+ avb_errorv("Data from '",
+ partition_name,
+ "' does not look like a vbmeta header.\n",
+ NULL);
+ goto out;
+ }
+
+ /* Set/clear the VERIFICATION_DISABLED bit, as requested. */
+ header = (AvbVBMetaImageHeader*)vbmeta_image;
+ flags = avb_be32toh(header->flags);
+
+ if (out_verification_enabled != NULL) {
+ *out_verification_enabled =
+ !(flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
+
+bool avb_user_verification_set(AvbOps* ops,
+ const char* ab_suffix,
+ bool enable_verification) {
+ uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
+ char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
+ uint64_t vbmeta_offset;
+ AvbIOResult io_res;
+ AvbVBMetaImageHeader* header;
+ uint32_t flags;
+ bool ret = false;
+
+ if (!load_top_level_vbmeta_header(
+ ops, ab_suffix, vbmeta_image, partition_name, &vbmeta_offset)) {
+ goto out;
+ }
+
+ if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+ avb_errorv("Data from '",
+ partition_name,
+ "' does not look like a vbmeta header.\n",
+ NULL);
+ goto out;
+ }
+
+ /* Set/clear the VERIFICATION_DISABLED bit, as requested. */
+ header = (AvbVBMetaImageHeader*)vbmeta_image;
+ flags = avb_be32toh(header->flags);
+ flags &= ~AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
+ if (!enable_verification) {
+ flags |= AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
+ }
+ header->flags = avb_htobe32(flags);
+
+ /* Write the header. */
+ io_res = ops->write_to_partition(ops,
+ partition_name,
+ vbmeta_offset,
+ AVB_VBMETA_IMAGE_HEADER_SIZE,
+ vbmeta_image);
+ if (io_res != AVB_IO_RESULT_OK) {
+ avb_errorv("Error writing to partition '", partition_name, "'\n", NULL);
+ goto out;
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
diff --git a/include/android_avb/avb_user_verification.h b/lib/avb/libavb_user/avb_user_verification.h
index a0077cbe17..7a33c8da42 100644
--- a/include/android_avb/avb_user_verification.h
+++ b/lib/avb/libavb_user/avb_user_verification.h
@@ -1,63 +1,63 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef AVB_USER_VERIFICATION_H_
-#define AVB_USER_VERIFICATION_H_
-
-#include <android_avb/libavb.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Function to enable or disable verification for an entire slot. The
- * passed in |ops| should be obtained via avb_ops_user_new(). The
- * |ab_suffix| parameter should specify the slot to modify including
- * the leading underscore (e.g. "_a" or "_b"). The
- * |enable_verification| parameter should be set to |true| to enable
- * dm-verification and |false| to disable.
- *
- * Returns |true| if the operation succeeded, otherwise |false|.
- */
-bool avb_user_verification_set(AvbOps* ops,
- const char* ab_suffix,
- bool enable_verification);
-
-/* Gets whether verification is enabled for an entire slot. The passed
- * in |ops| should be obtained via avb_ops_user_new(). The |ab_suffix|
- * parameter should specify the slot to query including the leading
- * underscore (e.g. "_a" or "_b"). The result is returned in the
- * |out_verification_enabled| parameter.
- *
- * Returns |true| if the operation succeeded, otherwise |false|.
- */
-bool avb_user_verification_get(AvbOps* ops,
- const char* ab_suffix,
- bool* out_verification_enabled);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_USER_VERIFICATION_H_ */
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef AVB_USER_VERIFICATION_H_
+#define AVB_USER_VERIFICATION_H_
+
+#include <libavb/libavb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function to enable or disable verification for an entire slot. The
+ * passed in |ops| should be obtained via avb_ops_user_new(). The
+ * |ab_suffix| parameter should specify the slot to modify including
+ * the leading underscore (e.g. "_a" or "_b"). The
+ * |enable_verification| parameter should be set to |true| to enable
+ * dm-verification and |false| to disable.
+ *
+ * Returns |true| if the operation succeeded, otherwise |false|.
+ */
+bool avb_user_verification_set(AvbOps* ops,
+ const char* ab_suffix,
+ bool enable_verification);
+
+/* Gets whether verification is enabled for an entire slot. The passed
+ * in |ops| should be obtained via avb_ops_user_new(). The |ab_suffix|
+ * parameter should specify the slot to query including the leading
+ * underscore (e.g. "_a" or "_b"). The result is returned in the
+ * |out_verification_enabled| parameter.
+ *
+ * Returns |true| if the operation succeeded, otherwise |false|.
+ */
+bool avb_user_verification_get(AvbOps* ops,
+ const char* ab_suffix,
+ bool* out_verification_enabled);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_USER_VERIFICATION_H_ */
diff --git a/lib/avb/libavb_user/avb_user_verity.c b/lib/avb/libavb_user/avb_user_verity.c
index e3f1a4d554..ecf0043c93 100644
--- a/lib/avb/libavb_user/avb_user_verity.c
+++ b/lib/avb/libavb_user/avb_user_verity.c
@@ -1,213 +1,213 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <android_avb/avb_user_verity.h>
-
-/* Maximum allow length (in bytes) of a partition name, including
- * ab_suffix.
- */
-#define AVB_PART_NAME_MAX_SIZE 32
-
-/* Loads the toplevel AvbVBMetaImageHeader from the slot denoted by
- * |ab_suffix| into |vbmeta_image|. No validation, verification, or
- * byteswapping is performed.
- *
- * If successful, |true| is returned and the partition it was loaded
- * from is returned in |out_partition_name| and the offset on said
- * partition is returned in |out_vbmeta_offset|.
- */
-static bool load_top_level_vbmeta_header(
- AvbOps* ops,
- const char* ab_suffix,
- uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE],
- char out_partition_name[AVB_PART_NAME_MAX_SIZE],
- uint64_t* out_vbmeta_offset) {
- uint64_t vbmeta_offset = 0;
- size_t num_read;
- bool ret = false;
- AvbIOResult io_res;
-
- /* Construct full partition name. */
- if (!avb_str_concat(out_partition_name,
- AVB_PART_NAME_MAX_SIZE,
- "vbmeta",
- 6,
- ab_suffix,
- avb_strlen(ab_suffix))) {
- avb_error("Partition name and suffix does not fit.\n");
- goto out;
- }
-
- /* Only read the header, not the entire struct. */
- io_res = ops->read_from_partition(ops,
- out_partition_name,
- vbmeta_offset,
- AVB_VBMETA_IMAGE_HEADER_SIZE,
- vbmeta_image,
- &num_read);
- if (io_res == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
- AvbFooter footer;
-
- /* Try looking for the vbmeta struct in 'boot' via the footer. */
- if (!avb_str_concat(out_partition_name,
- AVB_PART_NAME_MAX_SIZE,
- "boot",
- 4,
- ab_suffix,
- avb_strlen(ab_suffix))) {
- avb_error("Partition name and suffix does not fit.\n");
- goto out;
- }
- io_res = ops->read_from_partition(ops,
- out_partition_name,
- -AVB_FOOTER_SIZE,
- AVB_FOOTER_SIZE,
- &footer,
- &num_read);
- if (io_res != AVB_IO_RESULT_OK) {
- avb_errorv("Error loading footer from partition '",
- out_partition_name,
- "'\n",
- NULL);
- goto out;
- }
-
- if (avb_memcmp(footer.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) != 0) {
- avb_errorv("Data from '",
- out_partition_name,
- "' does not look like a vbmeta footer.\n",
- NULL);
- goto out;
- }
-
- vbmeta_offset = avb_be64toh(footer.vbmeta_offset);
- io_res = ops->read_from_partition(ops,
- out_partition_name,
- vbmeta_offset,
- AVB_VBMETA_IMAGE_HEADER_SIZE,
- vbmeta_image,
- &num_read);
- }
-
- if (io_res != AVB_IO_RESULT_OK) {
- avb_errorv(
- "Error loading from partition '", out_partition_name, "'\n", NULL);
- goto out;
- }
-
- if (out_vbmeta_offset != NULL) {
- *out_vbmeta_offset = vbmeta_offset;
- }
-
- ret = true;
-
-out:
- return ret;
-}
-
-bool avb_user_verity_get(AvbOps* ops,
- const char* ab_suffix,
- bool* out_verity_enabled) {
- uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
- char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
- AvbVBMetaImageHeader* header;
- uint32_t flags;
- bool ret = false;
-
- if (!load_top_level_vbmeta_header(
- ops, ab_suffix, vbmeta_image, partition_name, NULL)) {
- goto out;
- }
-
- if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
- avb_errorv("Data from '",
- partition_name,
- "' does not look like a vbmeta header.\n",
- NULL);
- goto out;
- }
-
- /* Set/clear the HASHTREE_DISABLED bit, as requested. */
- header = (AvbVBMetaImageHeader*)vbmeta_image;
- flags = avb_be32toh(header->flags);
-
- if (out_verity_enabled != NULL) {
- *out_verity_enabled = !(flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
- }
-
- ret = true;
-
-out:
- return ret;
-}
-
-bool avb_user_verity_set(AvbOps* ops,
- const char* ab_suffix,
- bool enable_verity) {
- uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
- char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
- uint64_t vbmeta_offset;
- AvbIOResult io_res;
- AvbVBMetaImageHeader* header;
- uint32_t flags;
- bool ret = false;
-
- if (!load_top_level_vbmeta_header(
- ops, ab_suffix, vbmeta_image, partition_name, &vbmeta_offset)) {
- goto out;
- }
-
- if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
- avb_errorv("Data from '",
- partition_name,
- "' does not look like a vbmeta header.\n",
- NULL);
- goto out;
- }
-
- /* Set/clear the HASHTREE_DISABLED bit, as requested. */
- header = (AvbVBMetaImageHeader*)vbmeta_image;
- flags = avb_be32toh(header->flags);
- flags &= ~AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED;
- if (!enable_verity) {
- flags |= AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED;
- }
- header->flags = avb_htobe32(flags);
-
- /* Write the header. */
- io_res = ops->write_to_partition(ops,
- partition_name,
- vbmeta_offset,
- AVB_VBMETA_IMAGE_HEADER_SIZE,
- vbmeta_image);
- if (io_res != AVB_IO_RESULT_OK) {
- avb_errorv("Error writing to partition '", partition_name, "'\n", NULL);
- goto out;
- }
-
- ret = true;
-
-out:
- return ret;
-}
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "avb_user_verity.h"
+
+/* Maximum allow length (in bytes) of a partition name, including
+ * ab_suffix.
+ */
+#define AVB_PART_NAME_MAX_SIZE 32
+
+/* Loads the toplevel AvbVBMetaImageHeader from the slot denoted by
+ * |ab_suffix| into |vbmeta_image|. No validation, verification, or
+ * byteswapping is performed.
+ *
+ * If successful, |true| is returned and the partition it was loaded
+ * from is returned in |out_partition_name| and the offset on said
+ * partition is returned in |out_vbmeta_offset|.
+ */
+static bool load_top_level_vbmeta_header(
+ AvbOps* ops,
+ const char* ab_suffix,
+ uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE],
+ char out_partition_name[AVB_PART_NAME_MAX_SIZE],
+ uint64_t* out_vbmeta_offset) {
+ uint64_t vbmeta_offset = 0;
+ size_t num_read;
+ bool ret = false;
+ AvbIOResult io_res;
+
+ /* Construct full partition name. */
+ if (!avb_str_concat(out_partition_name,
+ AVB_PART_NAME_MAX_SIZE,
+ "vbmeta",
+ 6,
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("Partition name and suffix does not fit.\n");
+ goto out;
+ }
+
+ /* Only read the header, not the entire struct. */
+ io_res = ops->read_from_partition(ops,
+ out_partition_name,
+ vbmeta_offset,
+ AVB_VBMETA_IMAGE_HEADER_SIZE,
+ vbmeta_image,
+ &num_read);
+ if (io_res == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
+ AvbFooter footer;
+
+ /* Try looking for the vbmeta struct in 'boot' via the footer. */
+ if (!avb_str_concat(out_partition_name,
+ AVB_PART_NAME_MAX_SIZE,
+ "boot",
+ 4,
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("Partition name and suffix does not fit.\n");
+ goto out;
+ }
+ io_res = ops->read_from_partition(ops,
+ out_partition_name,
+ -AVB_FOOTER_SIZE,
+ AVB_FOOTER_SIZE,
+ &footer,
+ &num_read);
+ if (io_res != AVB_IO_RESULT_OK) {
+ avb_errorv("Error loading footer from partition '",
+ out_partition_name,
+ "'\n",
+ NULL);
+ goto out;
+ }
+
+ if (avb_memcmp(footer.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) != 0) {
+ avb_errorv("Data from '",
+ out_partition_name,
+ "' does not look like a vbmeta footer.\n",
+ NULL);
+ goto out;
+ }
+
+ vbmeta_offset = avb_be64toh(footer.vbmeta_offset);
+ io_res = ops->read_from_partition(ops,
+ out_partition_name,
+ vbmeta_offset,
+ AVB_VBMETA_IMAGE_HEADER_SIZE,
+ vbmeta_image,
+ &num_read);
+ }
+
+ if (io_res != AVB_IO_RESULT_OK) {
+ avb_errorv(
+ "Error loading from partition '", out_partition_name, "'\n", NULL);
+ goto out;
+ }
+
+ if (out_vbmeta_offset != NULL) {
+ *out_vbmeta_offset = vbmeta_offset;
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
+
+bool avb_user_verity_get(AvbOps* ops,
+ const char* ab_suffix,
+ bool* out_verity_enabled) {
+ uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
+ char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
+ AvbVBMetaImageHeader* header;
+ uint32_t flags;
+ bool ret = false;
+
+ if (!load_top_level_vbmeta_header(
+ ops, ab_suffix, vbmeta_image, partition_name, NULL)) {
+ goto out;
+ }
+
+ if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+ avb_errorv("Data from '",
+ partition_name,
+ "' does not look like a vbmeta header.\n",
+ NULL);
+ goto out;
+ }
+
+ /* Set/clear the HASHTREE_DISABLED bit, as requested. */
+ header = (AvbVBMetaImageHeader*)vbmeta_image;
+ flags = avb_be32toh(header->flags);
+
+ if (out_verity_enabled != NULL) {
+ *out_verity_enabled = !(flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
+
+bool avb_user_verity_set(AvbOps* ops,
+ const char* ab_suffix,
+ bool enable_verity) {
+ uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
+ char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
+ uint64_t vbmeta_offset;
+ AvbIOResult io_res;
+ AvbVBMetaImageHeader* header;
+ uint32_t flags;
+ bool ret = false;
+
+ if (!load_top_level_vbmeta_header(
+ ops, ab_suffix, vbmeta_image, partition_name, &vbmeta_offset)) {
+ goto out;
+ }
+
+ if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+ avb_errorv("Data from '",
+ partition_name,
+ "' does not look like a vbmeta header.\n",
+ NULL);
+ goto out;
+ }
+
+ /* Set/clear the HASHTREE_DISABLED bit, as requested. */
+ header = (AvbVBMetaImageHeader*)vbmeta_image;
+ flags = avb_be32toh(header->flags);
+ flags &= ~AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED;
+ if (!enable_verity) {
+ flags |= AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED;
+ }
+ header->flags = avb_htobe32(flags);
+
+ /* Write the header. */
+ io_res = ops->write_to_partition(ops,
+ partition_name,
+ vbmeta_offset,
+ AVB_VBMETA_IMAGE_HEADER_SIZE,
+ vbmeta_image);
+ if (io_res != AVB_IO_RESULT_OK) {
+ avb_errorv("Error writing to partition '", partition_name, "'\n", NULL);
+ goto out;
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
diff --git a/include/android_avb/avb_user_verity.h b/lib/avb/libavb_user/avb_user_verity.h
index c8c2a6214b..139cfb1e67 100644
--- a/include/android_avb/avb_user_verity.h
+++ b/lib/avb/libavb_user/avb_user_verity.h
@@ -1,63 +1,63 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef AVB_USER_VERITY_H_
-#define AVB_USER_VERITY_H_
-
-#include <android_avb/libavb.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Function to enable or disable dm-verity for an entire slot. The
- * passed in |ops| should be obtained via avb_ops_user_new(). The
- * |ab_suffix| parameter should specify the slot to modify including
- * the leading underscore (e.g. "_a" or "_b"). The |enable_verity|
- * parameter should be set to |true| to enable dm-verity and |false|
- * to disable.
- *
- * Returns |true| if the operation succeeded, otherwise |false|.
- */
-bool avb_user_verity_set(AvbOps* ops,
- const char* ab_suffix,
- bool enable_verity);
-
-/* Gets whether dm-verity is enabled for an entire slot. The passed in
- * |ops| should be obtained via avb_ops_user_new(). The |ab_suffix|
- * parameter should specify the slot to query including the leading
- * underscore (e.g. "_a" or "_b"). The result is returned in the
- * |out_verity_enabled| parameter.
- *
- * Returns |true| if the operation succeeded, otherwise |false|.
- */
-bool avb_user_verity_get(AvbOps* ops,
- const char* ab_suffix,
- bool* out_verity_enabled);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_USER_VERITY_H_ */
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef AVB_USER_VERITY_H_
+#define AVB_USER_VERITY_H_
+
+#include <libavb/libavb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function to enable or disable dm-verity for an entire slot. The
+ * passed in |ops| should be obtained via avb_ops_user_new(). The
+ * |ab_suffix| parameter should specify the slot to modify including
+ * the leading underscore (e.g. "_a" or "_b"). The |enable_verity|
+ * parameter should be set to |true| to enable dm-verity and |false|
+ * to disable.
+ *
+ * Returns |true| if the operation succeeded, otherwise |false|.
+ */
+bool avb_user_verity_set(AvbOps* ops,
+ const char* ab_suffix,
+ bool enable_verity);
+
+/* Gets whether dm-verity is enabled for an entire slot. The passed in
+ * |ops| should be obtained via avb_ops_user_new(). The |ab_suffix|
+ * parameter should specify the slot to query including the leading
+ * underscore (e.g. "_a" or "_b"). The result is returned in the
+ * |out_verity_enabled| parameter.
+ *
+ * Returns |true| if the operation succeeded, otherwise |false|.
+ */
+bool avb_user_verity_get(AvbOps* ops,
+ const char* ab_suffix,
+ bool* out_verity_enabled);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_USER_VERITY_H_ */
diff --git a/include/android_avb/libavb_user.h b/lib/avb/libavb_user/libavb_user.h
index aaf7fde2fc..a712f9acc6 100644
--- a/include/android_avb/libavb_user.h
+++ b/lib/avb/libavb_user/libavb_user.h
@@ -1,41 +1,41 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef LIBAVB_USER_H_
-#define LIBAVB_USER_H_
-
-#include <android_avb/libavb.h>
-
-/* The AVB_INSIDE_LIBAVB_USER_H preprocessor symbol is used to enforce
- * library users to include only this file. All public interfaces, and
- * only public interfaces, must be included here.
- */
-
-#define AVB_INSIDE_LIBAVB_USER_H
-#include <android_avb/avb_ops_user.h>
-#include <android_avb/avb_user_verification.h>
-#include <android_avb/avb_user_verity.h>
-#undef AVB_INSIDE_LIBAVB_USER_H
-
-#endif /* LIBAVB_USER_H_ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef LIBAVB_USER_H_
+#define LIBAVB_USER_H_
+
+#include <libavb/libavb.h>
+
+/* The AVB_INSIDE_LIBAVB_USER_H preprocessor symbol is used to enforce
+ * library users to include only this file. All public interfaces, and
+ * only public interfaces, must be included here.
+ */
+
+#define AVB_INSIDE_LIBAVB_USER_H
+#include "avb_ops_user.h"
+#include "avb_user_verification.h"
+#include "avb_user_verity.h"
+#undef AVB_INSIDE_LIBAVB_USER_H
+
+#endif /* LIBAVB_USER_H_ */
diff --git a/lib/avb/rk_avb_user/Makefile b/lib/avb/rk_avb_user/Makefile
index c636ea7eb3..f87162c1ec 100644
--- a/lib/avb/rk_avb_user/Makefile
+++ b/lib/avb/rk_avb_user/Makefile
@@ -1 +1,3 @@
+ccflags-y += -DAVB_COMPILATION
obj-y += rk_avb_ops_user.o
+obj-y += rk_avb_sysdeps_uboot.o
diff --git a/lib/avb/rk_avb_user/rk_avb_ops_user.c b/lib/avb/rk_avb_user/rk_avb_ops_user.c
index c70baeb903..c8f8f03de3 100644
--- a/lib/avb/rk_avb_user/rk_avb_ops_user.c
+++ b/lib/avb/rk_avb_user/rk_avb_ops_user.c
@@ -14,16 +14,362 @@
#include <mmc.h>
#include <blk.h>
#include <part.h>
-#include <android_avb/avb_ops_user.h>
-#include <android_avb/libavb_ab.h>
-#include <android_avb/avb_atx_validate.h>
-#include <android_avb/avb_atx_types.h>
#include <optee_include/OpteeClientInterface.h>
#include <optee_include/tee_api_defines.h>
-#include <android_avb/avb_vbmeta_image.h>
-#include <android_avb/avb_atx_validate.h>
#include <android_avb/rk_avb_ops_user.h>
+static void byte_to_block(int64_t *offset,
+ size_t *num_bytes,
+ lbaint_t *offset_blk,
+ lbaint_t *blkcnt)
+{
+ *offset_blk = (lbaint_t)(*offset / 512);
+ if (*num_bytes % 512 == 0) {
+ if (*offset % 512 == 0) {
+ *blkcnt = (lbaint_t)(*num_bytes / 512);
+ } else {
+ *blkcnt = (lbaint_t)(*num_bytes / 512) + 1;
+ }
+ } else {
+ if (*offset % 512 == 0) {
+ *blkcnt = (lbaint_t)(*num_bytes / 512) + 1;
+ } else {
+ if ((*offset % 512) + (*num_bytes % 512) < 512 ||
+ (*offset % 512) + (*num_bytes % 512) == 512) {
+ *blkcnt = (lbaint_t)(*num_bytes / 512) + 1;
+ } else {
+ *blkcnt = (lbaint_t)(*num_bytes / 512) + 2;
+ }
+ }
+ }
+}
+
+static AvbIOResult read_from_partition(AvbOps* ops,
+ const char* partition,
+ int64_t offset,
+ size_t num_bytes,
+ void* buffer,
+ size_t* out_num_read)
+{
+ char *dev_iface = "mmc";
+ int dev_num = 0;
+ struct blk_desc *dev_desc;
+ lbaint_t offset_blk, blkcnt;
+ disk_partition_t part_info;
+
+ byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt);
+ dev_desc = blk_get_dev(dev_iface, dev_num);
+ if (!dev_desc) {
+ printf("Could not find %s %d\n", dev_iface, dev_num);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
+ printf("Could not find \"%s\" partition\n", partition);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ if((offset % 512 == 0) && (num_bytes % 512 == 0)) {
+ blk_dread(dev_desc, part_info.start + offset_blk, blkcnt, buffer);
+ *out_num_read = blkcnt * 512;
+ } else {
+ char *buffer_temp;
+ buffer_temp = malloc(512 * blkcnt);
+ if (buffer_temp == NULL) {
+ printf("malloc error!\n");
+ return AVB_IO_RESULT_ERROR_OOM;
+ }
+ blk_dread(dev_desc, part_info.start + offset_blk, blkcnt, buffer_temp);
+ memcpy(buffer, buffer_temp + (offset % 512), num_bytes);
+ *out_num_read = num_bytes;
+ free(buffer_temp);
+ }
+
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult write_to_partition(AvbOps* ops,
+ const char* partition,
+ int64_t offset,
+ size_t num_bytes,
+ const void* buffer)
+{
+ const char *dev_iface = "mmc";
+ int dev_num = 0;
+ struct blk_desc *dev_desc;
+ char *buffer_temp;
+ disk_partition_t part_info;
+ lbaint_t offset_blk, blkcnt;
+
+ byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt);
+ buffer_temp = malloc(512 * blkcnt);
+ if (buffer_temp == NULL) {
+ printf("malloc error!\n");
+ return AVB_IO_RESULT_ERROR_OOM;
+ }
+ memset(buffer_temp, 0, 512 * blkcnt);
+ dev_desc = blk_get_dev(dev_iface, dev_num);
+ if (!dev_desc) {
+ printf("Could not find %s %d\n", dev_iface, dev_num);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
+ printf("Could not find \"%s\" partition\n", partition);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ if ((offset % 512 != 0) && (num_bytes % 512) != 0) {
+ blk_dread(dev_desc, part_info.start + offset_blk, blkcnt, buffer_temp);
+ }
+
+ memcpy(buffer_temp, buffer + (offset % 512), num_bytes);
+ blk_dwrite(dev_desc, part_info.start + offset_blk, blkcnt, buffer);
+ free(buffer_temp);
+
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult validate_vbmeta_public_key(
+ AvbOps *ops,
+ const uint8_t *public_key_data,
+ size_t public_key_length,
+ const uint8_t *public_key_metadata,
+ size_t public_key_metadata_length,
+ bool *out_is_trusted)
+{
+#ifdef AVB_VBMETA_PUBLIC_KEY_VALIDATE
+ if (out_is_trusted != NULL) {
+ avb_atx_validate_vbmeta_public_key(ops,
+ public_key_data,
+ public_key_length,
+ public_key_metadata,
+ public_key_metadata_length,
+ out_is_trusted);
+ }
+#else
+ if (out_is_trusted != NULL) {
+ *out_is_trusted = true;
+ }
+#endif
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult read_rollback_index(AvbOps *ops,
+ size_t rollback_index_location,
+ uint64_t *out_rollback_index)
+{
+ if (out_rollback_index != NULL) {
+#ifdef CONFIG_OPTEE_CLIENT
+ int ret;
+ ret = trusty_read_rollback_index(rollback_index_location,
+ out_rollback_index);
+ if (ret == TEE_ERROR_GENERIC) {
+ *out_rollback_index = 0;
+ ret = trusty_write_rollback_index(rollback_index_location,
+ *out_rollback_index);
+ if (ret != 0) {
+ printf("%s: init rollback index error\n", __FILE__);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ ret = trusty_read_rollback_index(rollback_index_location,
+ out_rollback_index);
+ if (ret == 0)
+ return AVB_IO_RESULT_OK;
+ } else if (ret == 0) {
+ return AVB_IO_RESULT_OK;
+ } else {
+ printf("trusty_read_rollback_index ret = %x\n", ret);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+#endif
+ }
+ return AVB_IO_RESULT_ERROR_IO;
+}
+
+static AvbIOResult write_rollback_index(AvbOps *ops,
+ size_t rollback_index_location,
+ uint64_t rollback_index)
+{
+#ifdef CONFIG_OPTEE_CLIENT
+ if (trusty_write_rollback_index(rollback_index_location, rollback_index)) {
+ printf("%s: Fail to write rollback index\n", __FILE__);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ return AVB_IO_RESULT_OK;
+#endif
+ return AVB_IO_RESULT_ERROR_IO;
+}
+
+static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
+{
+ if (out_is_unlocked != NULL) {
+#ifdef CONFIG_OPTEE_CLIENT
+ int ret;
+
+ ret = trusty_read_lock_state((uint8_t *)out_is_unlocked);
+ if (ret == TEE_ERROR_GENERIC) {
+ *out_is_unlocked = 1;
+ if (trusty_write_lock_state(*out_is_unlocked)) {
+ printf("%s: init lock state error\n", __FILE__);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ ret = trusty_read_lock_state((uint8_t *)out_is_unlocked);
+ if(ret == 0)
+ return 0;
+ } else if (ret == 0) {
+ return AVB_IO_RESULT_OK;
+ } else {
+ printf("read_is_device_unlocked ret = %x\n", ret);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+#endif
+ }
+ return AVB_IO_RESULT_ERROR_IO;
+}
+
+AvbIOResult write_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
+{
+ if (out_is_unlocked != NULL) {
+#ifdef CONFIG_OPTEE_CLIENT
+ if (trusty_write_lock_state(*out_is_unlocked)) {
+ printf("%s: Fail to write lock state\n", __FILE__);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ return AVB_IO_RESULT_OK;
+#endif
+ }
+ return AVB_IO_RESULT_ERROR_IO;
+}
+
+static AvbIOResult get_size_of_partition(AvbOps *ops,
+ const char *partition,
+ uint64_t *out_size_in_bytes)
+{
+ const char *dev_iface = "mmc";
+ int dev_num = 0;
+ struct blk_desc *dev_desc;
+ disk_partition_t part_info;
+
+ dev_desc = blk_get_dev(dev_iface, dev_num);
+ if (!dev_desc) {
+ printf("Could not find %s %d\n", dev_iface, dev_num);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
+ printf("Could not find \"%s\" partition\n", partition);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+ *out_size_in_bytes = (part_info.size) * 512;
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
+ const char *partition,
+ char *guid_buf,
+ size_t guid_buf_size)
+{
+ const char *dev_iface = "mmc";
+ int dev_num = 0;
+ struct blk_desc *dev_desc;
+ disk_partition_t part_info;
+ dev_desc = blk_get_dev(dev_iface, dev_num);
+ if (!dev_desc) {
+ printf("Could not find %s %d\n", dev_iface, dev_num);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
+ printf("Could not find \"%s\" partition\n", partition);
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+ if (guid_buf != NULL && guid_buf_size > 0) {
+ memcpy(guid_buf, part_info.uuid, guid_buf_size);
+ }
+ return AVB_IO_RESULT_OK;
+}
+
+/* read permanent attributes from rpmb */
+AvbIOResult avb_read_perm_attr(AvbAtxOps* atx_ops,
+ AvbAtxPermanentAttributes* attributes)
+{
+ if (attributes != NULL) {
+#ifdef CONFIG_OPTEE_CLIENT
+ trusty_read_permanent_attributes((uint8_t *)attributes,
+ sizeof(struct AvbAtxPermanentAttributes));
+ return AVB_IO_RESULT_OK;
+#endif
+ }
+
+ return -1;
+}
+
+/*read permanent attributes hash from efuse */
+AvbIOResult avb_read_perm_attr_hash(AvbAtxOps* atx_ops,
+ uint8_t hash[AVB_SHA256_DIGEST_SIZE])
+{
+#ifdef CONFIG_OPTEE_CLIENT
+ if (trusty_read_attribute_hash((uint32_t *)hash, AVB_SHA256_DIGEST_SIZE / 4))
+ return -1;
+#else
+ avb_error("Please open the macro!\n");
+ return -1;
+#endif
+ return AVB_IO_RESULT_OK;
+}
+
+AvbOps* avb_ops_user_new(void) {
+ AvbOps* ops;
+
+ ops = calloc(1, sizeof(AvbOps));
+ if (ops == NULL) {
+ avb_error("Error allocating memory for AvbOps.\n");
+ goto out;
+ }
+
+ ops->ab_ops = calloc(1, sizeof(AvbABOps));
+ if (ops->ab_ops == NULL) {
+ avb_error("Error allocating memory for AvbABOps.\n");
+ free(ops);
+ goto out;
+ }
+
+ ops->atx_ops = calloc(1, sizeof(AvbAtxOps));
+ if (ops->atx_ops == NULL) {
+ avb_error("Error allocating memory for AvbAtxOps.\n");
+ free(ops->ab_ops);
+ free(ops);
+ goto out;
+ }
+ ops->ab_ops->ops = ops;
+ ops->atx_ops->ops = ops;
+
+ ops->read_from_partition = read_from_partition;
+ ops->write_to_partition = write_to_partition;
+ ops->validate_vbmeta_public_key = validate_vbmeta_public_key;
+ ops->read_rollback_index = read_rollback_index;
+ ops->write_rollback_index = write_rollback_index;
+ ops->read_is_device_unlocked = read_is_device_unlocked;
+ ops->get_unique_guid_for_partition = get_unique_guid_for_partition;
+ ops->get_size_of_partition = get_size_of_partition;
+ ops->ab_ops->read_ab_metadata = avb_ab_data_read;
+ ops->ab_ops->write_ab_metadata = avb_ab_data_write;
+ ops->atx_ops->read_permanent_attributes = avb_read_perm_attr;
+ ops->atx_ops->read_permanent_attributes_hash = avb_read_perm_attr_hash;
+
+out:
+ return ops;
+}
+
+
+void avb_ops_user_free(AvbOps* ops) {
+ free(ops->ab_ops);
+ free(ops->atx_ops);
+ free(ops);
+}
+
/* rk used */
int rk_avb_read_slot_count(char *slot_count)
{
@@ -166,8 +512,8 @@ int rk_avb_read_flash_lock_state(uint8_t *flash_lock_state)
}
ret = trusty_read_flash_lock_state(flash_lock_state);
- if (ret == 0)
- return 0;
+
+ return ret;
} else if (ret == 0) {
return 0;
} else {
@@ -222,8 +568,8 @@ int rk_avb_read_lock_state(uint8_t *lock_state)
}
ret = trusty_read_lock_state(lock_state);
- if (ret == 0)
- return 0;
+
+ return ret;
} else if (ret == 0) {
return 0;
} else {
@@ -264,8 +610,8 @@ int rk_avb_read_perm_attr_flag(uint8_t *flag)
}
ret = trusty_read_permanent_attributes_flag(flag);
- if (ret == 0)
- return 0;
+
+ return ret;
} else if (ret == 0) {
return 0;
} else {
diff --git a/lib/avb/rk_avb_user/rk_avb_sysdeps_uboot.c b/lib/avb/rk_avb_user/rk_avb_sysdeps_uboot.c
new file mode 100644
index 0000000000..aa3e207523
--- /dev/null
+++ b/lib/avb/rk_avb_user/rk_avb_sysdeps_uboot.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <common.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include <libavb/libavb.h>
+
+int avb_memcmp(const void* src1, const void* src2, size_t n) {
+ return memcmp(src1, src2, n);
+}
+
+void* avb_memcpy(void* dest, const void* src, size_t n) {
+ return memcpy(dest, src, n);
+}
+
+void* avb_memset(void* dest, const int c, size_t n) {
+ return memset(dest, c, n);
+}
+
+int avb_strcmp(const char* s1, const char* s2) {
+ return strcmp(s1, s2);
+}
+
+size_t avb_strlen(const char* str) {
+ return strlen(str);
+}
+
+void avb_abort(void) {
+ panic("avb_abort!\n");
+}
+
+void avb_print(const char* message) {
+ fprintf(stderr, "%s", message);
+}
+
+void avb_printv(const char* message, ...) {
+ va_list ap;
+ const char* m;
+
+ va_start(ap, message);
+ for (m = message; m != NULL; m = va_arg(ap, const char*)) {
+ fprintf(stderr, "%s", m);
+ }
+ va_end(ap);
+}
+
+void* avb_malloc_(size_t size) {
+ return malloc(size);
+}
+
+void avb_free(void* ptr) {
+ free(ptr);
+}
+
+uint32_t avb_div_by_10(uint64_t* dividend) {
+ uint32_t rem = (uint32_t)(*dividend % 10);
+ *dividend /= 10;
+ return rem;
+}