From ed19ae430eb769322d8b353c621a056f0b54e48a Mon Sep 17 00:00:00 2001 From: Winter Wang Date: Wed, 23 Nov 2016 16:42:22 +0800 Subject: libavb: update avb update avb to: https://android.googlesource.com/platform/external/avb/ commit:baf59e232e48d0111e4b38f74c60c89e6f8f0b14 Change-Id: I4bff97d5bbd819217e25367b69a220400c7095af Signed-off-by: Winter Wang --- drivers/usb/gadget/f_fastboot.c | 33 +- include/libavb.h | 52 -- include/libavb_ab.h | 42 ++ lib/Makefile | 2 +- lib/avb/Makefile | 14 + lib/avb/fsl/Makefile | 4 + lib/avb/fsl/debug.h | 35 + lib/avb/fsl/fsl_avb.c | 715 ++++++++++++++++++++ lib/avb/fsl/fsl_avb.h | 174 +++++ lib/avb/fsl/fsl_avbkey.c | 184 +++++ lib/avb/fsl/fsl_avbkey.h | 44 ++ lib/avb/fsl/fsl_bootctl.c | 176 +++++ lib/avb/libavb/Makefile | 17 + lib/avb/libavb/avb_ab_flow.c | 441 ++++++++++++ lib/avb/libavb/avb_ab_flow.h | 226 +++++++ lib/avb/libavb/avb_chain_partition_descriptor.c | 64 ++ lib/avb/libavb/avb_chain_partition_descriptor.h | 72 ++ lib/avb/libavb/avb_crc32.c | 112 ++++ lib/avb/libavb/avb_crypto.c | 38 ++ lib/avb/libavb/avb_crypto.h | 137 ++++ lib/avb/libavb/avb_descriptor.c | 159 +++++ lib/avb/libavb/avb_descriptor.h | 129 ++++ lib/avb/libavb/avb_footer.c | 54 ++ lib/avb/libavb/avb_footer.h | 86 +++ lib/avb/libavb/avb_hash_descriptor.c | 61 ++ lib/avb/libavb/avb_hash_descriptor.h | 73 ++ lib/avb/libavb/avb_hashtree_descriptor.c | 69 ++ lib/avb/libavb/avb_hashtree_descriptor.h | 83 +++ lib/avb/libavb/avb_kernel_cmdline_descriptor.c | 57 ++ lib/avb/libavb/avb_kernel_cmdline_descriptor.h | 62 ++ lib/avb/libavb/avb_ops.h | 177 +++++ lib/avb/libavb/avb_property_descriptor.c | 167 +++++ lib/avb/libavb/avb_property_descriptor.h | 101 +++ lib/avb/libavb/avb_rsa.c | 271 ++++++++ lib/avb/libavb/avb_rsa.h | 78 +++ lib/avb/libavb/avb_sha.h | 94 +++ lib/avb/libavb/avb_sha256.c | 384 +++++++++++ lib/avb/libavb/avb_sha512.c | 380 +++++++++++ lib/avb/libavb/avb_slot_verify.c | 857 ++++++++++++++++++++++++ lib/avb/libavb/avb_slot_verify.h | 195 ++++++ lib/avb/libavb/avb_sysdeps.h | 113 ++++ lib/avb/libavb/avb_sysdeps_uboot.c | 64 ++ lib/avb/libavb/avb_util.c | 319 +++++++++ lib/avb/libavb/avb_util.h | 232 +++++++ lib/avb/libavb/avb_vbmeta_image.c | 562 ++++++++++++++++ lib/avb/libavb/avb_vbmeta_image.h | 240 +++++++ lib/avb/libavb/libavb.h | 49 ++ lib/avb/libavb_ab/Makefile | 2 + lib/avb/libavb_ab/avb_ab_flow.c | 431 ++++++++++++ lib/avb/libavb_ab/avb_ab_flow.h | 226 +++++++ lib/avb/libavb_ab/avb_ab_ops.h | 78 +++ lib/libavb/Makefile | 30 - lib/libavb/avb_ab_flow.c | 441 ------------ lib/libavb/avb_ab_flow.h | 226 ------- lib/libavb/avb_chain_partition_descriptor.c | 64 -- lib/libavb/avb_chain_partition_descriptor.h | 72 -- lib/libavb/avb_crc32.c | 112 ---- lib/libavb/avb_crypto.c | 38 -- lib/libavb/avb_crypto.h | 137 ---- lib/libavb/avb_descriptor.c | 159 ----- lib/libavb/avb_descriptor.h | 129 ---- lib/libavb/avb_footer.c | 54 -- lib/libavb/avb_footer.h | 86 --- lib/libavb/avb_hash_descriptor.c | 61 -- lib/libavb/avb_hash_descriptor.h | 73 -- lib/libavb/avb_hashtree_descriptor.c | 69 -- lib/libavb/avb_hashtree_descriptor.h | 83 --- lib/libavb/avb_kernel_cmdline_descriptor.c | 57 -- lib/libavb/avb_kernel_cmdline_descriptor.h | 62 -- lib/libavb/avb_ops.h | 199 ------ lib/libavb/avb_property_descriptor.c | 167 ----- lib/libavb/avb_property_descriptor.h | 101 --- lib/libavb/avb_rsa.c | 271 -------- lib/libavb/avb_rsa.h | 78 --- lib/libavb/avb_sha.h | 94 --- lib/libavb/avb_sha256.c | 384 ----------- lib/libavb/avb_sha512.c | 380 ----------- lib/libavb/avb_slot_verify.c | 857 ------------------------ lib/libavb/avb_slot_verify.h | 190 ------ lib/libavb/avb_sysdeps.h | 113 ---- lib/libavb/avb_sysdeps_uboot.c | 64 -- lib/libavb/avb_util.c | 319 --------- lib/libavb/avb_util.h | 232 ------- lib/libavb/avb_vbmeta_image.c | 562 ---------------- lib/libavb/avb_vbmeta_image.h | 240 ------- lib/libavb/fsl/Makefile | 4 - lib/libavb/fsl/debug.h | 35 - lib/libavb/fsl/fsl_avb.c | 714 -------------------- lib/libavb/fsl/fsl_avb.h | 174 ----- lib/libavb/fsl/fsl_avbkey.c | 184 ----- lib/libavb/fsl/fsl_avbkey.h | 44 -- lib/libavb/fsl/fsl_bootctl.c | 176 ----- 92 files changed, 8367 insertions(+), 7603 deletions(-) delete mode 100644 include/libavb.h create mode 100644 include/libavb_ab.h create mode 100644 lib/avb/Makefile create mode 100644 lib/avb/fsl/Makefile create mode 100644 lib/avb/fsl/debug.h create mode 100644 lib/avb/fsl/fsl_avb.c create mode 100644 lib/avb/fsl/fsl_avb.h create mode 100644 lib/avb/fsl/fsl_avbkey.c create mode 100644 lib/avb/fsl/fsl_avbkey.h create mode 100644 lib/avb/fsl/fsl_bootctl.c create mode 100644 lib/avb/libavb/Makefile create mode 100644 lib/avb/libavb/avb_ab_flow.c create mode 100644 lib/avb/libavb/avb_ab_flow.h create mode 100644 lib/avb/libavb/avb_chain_partition_descriptor.c create mode 100644 lib/avb/libavb/avb_chain_partition_descriptor.h create mode 100644 lib/avb/libavb/avb_crc32.c create mode 100644 lib/avb/libavb/avb_crypto.c create mode 100644 lib/avb/libavb/avb_crypto.h create mode 100644 lib/avb/libavb/avb_descriptor.c create mode 100644 lib/avb/libavb/avb_descriptor.h create mode 100644 lib/avb/libavb/avb_footer.c create mode 100644 lib/avb/libavb/avb_footer.h create mode 100644 lib/avb/libavb/avb_hash_descriptor.c create mode 100644 lib/avb/libavb/avb_hash_descriptor.h create mode 100644 lib/avb/libavb/avb_hashtree_descriptor.c create mode 100644 lib/avb/libavb/avb_hashtree_descriptor.h create mode 100644 lib/avb/libavb/avb_kernel_cmdline_descriptor.c create mode 100644 lib/avb/libavb/avb_kernel_cmdline_descriptor.h create mode 100644 lib/avb/libavb/avb_ops.h create mode 100644 lib/avb/libavb/avb_property_descriptor.c create mode 100644 lib/avb/libavb/avb_property_descriptor.h create mode 100644 lib/avb/libavb/avb_rsa.c create mode 100644 lib/avb/libavb/avb_rsa.h create mode 100644 lib/avb/libavb/avb_sha.h create mode 100644 lib/avb/libavb/avb_sha256.c create mode 100644 lib/avb/libavb/avb_sha512.c create mode 100644 lib/avb/libavb/avb_slot_verify.c create mode 100644 lib/avb/libavb/avb_slot_verify.h create mode 100644 lib/avb/libavb/avb_sysdeps.h create mode 100644 lib/avb/libavb/avb_sysdeps_uboot.c create mode 100644 lib/avb/libavb/avb_util.c create mode 100644 lib/avb/libavb/avb_util.h create mode 100644 lib/avb/libavb/avb_vbmeta_image.c create mode 100644 lib/avb/libavb/avb_vbmeta_image.h create mode 100644 lib/avb/libavb/libavb.h create mode 100644 lib/avb/libavb_ab/Makefile create mode 100644 lib/avb/libavb_ab/avb_ab_flow.c create mode 100644 lib/avb/libavb_ab/avb_ab_flow.h create mode 100644 lib/avb/libavb_ab/avb_ab_ops.h delete mode 100644 lib/libavb/Makefile delete mode 100644 lib/libavb/avb_ab_flow.c delete mode 100644 lib/libavb/avb_ab_flow.h delete mode 100644 lib/libavb/avb_chain_partition_descriptor.c delete mode 100644 lib/libavb/avb_chain_partition_descriptor.h delete mode 100644 lib/libavb/avb_crc32.c delete mode 100644 lib/libavb/avb_crypto.c delete mode 100644 lib/libavb/avb_crypto.h delete mode 100644 lib/libavb/avb_descriptor.c delete mode 100644 lib/libavb/avb_descriptor.h delete mode 100644 lib/libavb/avb_footer.c delete mode 100644 lib/libavb/avb_footer.h delete mode 100644 lib/libavb/avb_hash_descriptor.c delete mode 100644 lib/libavb/avb_hash_descriptor.h delete mode 100644 lib/libavb/avb_hashtree_descriptor.c delete mode 100644 lib/libavb/avb_hashtree_descriptor.h delete mode 100644 lib/libavb/avb_kernel_cmdline_descriptor.c delete mode 100644 lib/libavb/avb_kernel_cmdline_descriptor.h delete mode 100644 lib/libavb/avb_ops.h delete mode 100644 lib/libavb/avb_property_descriptor.c delete mode 100644 lib/libavb/avb_property_descriptor.h delete mode 100644 lib/libavb/avb_rsa.c delete mode 100644 lib/libavb/avb_rsa.h delete mode 100644 lib/libavb/avb_sha.h delete mode 100644 lib/libavb/avb_sha256.c delete mode 100644 lib/libavb/avb_sha512.c delete mode 100644 lib/libavb/avb_slot_verify.c delete mode 100644 lib/libavb/avb_slot_verify.h delete mode 100644 lib/libavb/avb_sysdeps.h delete mode 100644 lib/libavb/avb_sysdeps_uboot.c delete mode 100644 lib/libavb/avb_util.c delete mode 100644 lib/libavb/avb_util.h delete mode 100644 lib/libavb/avb_vbmeta_image.c delete mode 100644 lib/libavb/avb_vbmeta_image.h delete mode 100644 lib/libavb/fsl/Makefile delete mode 100644 lib/libavb/fsl/debug.h delete mode 100644 lib/libavb/fsl/fsl_avb.c delete mode 100644 lib/libavb/fsl/fsl_avb.h delete mode 100644 lib/libavb/fsl/fsl_avbkey.c delete mode 100644 lib/libavb/fsl/fsl_avbkey.h delete mode 100644 lib/libavb/fsl/fsl_bootctl.c diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 4ab75d4..ab00dd7 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -48,7 +48,7 @@ #endif #ifdef CONFIG_AVB_SUPPORT -#include +#include #endif #define FASTBOOT_VERSION "0.4" @@ -1852,17 +1852,19 @@ bootimg_print_image_hdr(struct andr_img_hdr *hdr) static struct andr_img_hdr boothdr __aligned(ARCH_DMA_MINALIGN); #if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC) -static AvbOps fsl_avb_ops = { - .read_from_partition = fsl_read_from_partition_multi, - /* .read_from_partition = fsl_read_from_partition, */ - .write_to_partition = fsl_write_to_partition, +static AvbABOps fsl_avb_ab_ops = { + .ops = { + .read_from_partition = fsl_read_from_partition_multi, + /* .read_from_partition = fsl_read_from_partition, */ + .write_to_partition = fsl_write_to_partition, + .validate_vbmeta_public_key = fsl_validate_vbmeta_public_key, + .read_rollback_index = fsl_read_rollback_index, + .write_rollback_index = fsl_write_rollback_index, + .read_is_device_unlocked = fsl_read_is_device_unlocked, + .get_unique_guid_for_partition = fsl_get_unique_guid_for_partition + }, .read_ab_metadata = fsl_read_ab_metadata, - .write_ab_metadata = fsl_write_ab_metadata, - .validate_vbmeta_public_key = fsl_validate_vbmeta_public_key, - .read_rollback_index = fsl_read_rollback_index, - .write_rollback_index = fsl_write_rollback_index, - .read_is_device_unlocked = fsl_read_is_device_unlocked, - .get_unique_guid_for_partition = fsl_get_unique_guid_for_partition + .write_ab_metadata = fsl_write_ab_metadata }; /* we can use avb to verify Trusty if we want */ @@ -1878,6 +1880,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { AvbABFlowResult avb_result; AvbSlotVerifyData *avb_out_data; AvbPartitionData *avb_loadpart; + AvbOps fsl_avb_ops = fsl_avb_ab_ops.ops; #ifdef CONFIG_FASTBOOT_LOCK /* check lock state */ @@ -1888,7 +1891,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { lock_status = FASTBOOT_LOCK; } /* if in lock state, do avb verify */ - avb_result = avb_ab_flow(&fsl_avb_ops, requested_partitions, &avb_out_data); + avb_result = avb_ab_flow(&fsl_avb_ab_ops, requested_partitions, &avb_out_data); if (avb_result == AVB_AB_FLOW_RESULT_OK) { assert(avb_out_data != NULL); /* load the first partition */ @@ -1919,7 +1922,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { hdr = &boothdr; char bootimg[8]; - char *slot = select_slot(&fsl_avb_ops); + char *slot = select_slot(&fsl_avb_ab_ops); if (slot == NULL) { printf("boota: no bootable slot\n"); goto fail; @@ -2697,7 +2700,7 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) #endif #ifdef CONFIG_AVB_SUPPORT else if (is_slotvar_avb(cmd)) { - if (get_slotvar_avb(&fsl_avb_ops, cmd, + if (get_slotvar_avb(&fsl_avb_ab_ops, cmd, response + strlen(response), chars_left + 1) < 0) goto fail; } @@ -3145,7 +3148,7 @@ static void cb_set_active_avb(struct usb_ep *ep, struct usb_request *req) return; } - ret = avb_ab_mark_slot_active(&fsl_avb_ops, slot); + ret = avb_ab_mark_slot_active(&fsl_avb_ab_ops, slot); if (ret != AVB_IO_RESULT_OK) fastboot_tx_write_str("avb IO error"); else diff --git a/include/libavb.h b/include/libavb.h deleted file mode 100644 index d025f32..0000000 --- a/include/libavb.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 "../lib/libavb/avb_ab_flow.h" -#include "../lib/libavb/avb_chain_partition_descriptor.h" -#include "../lib/libavb/avb_crypto.h" -#include "../lib/libavb/avb_descriptor.h" -#include "../lib/libavb/avb_footer.h" -#include "../lib/libavb/avb_hash_descriptor.h" -#include "../lib/libavb/avb_hashtree_descriptor.h" -#include "../lib/libavb/avb_kernel_cmdline_descriptor.h" -#include "../lib/libavb/avb_ops.h" -#include "../lib/libavb/avb_property_descriptor.h" -#include "../lib/libavb/avb_slot_verify.h" -#include "../lib/libavb/avb_sysdeps.h" -#include "../lib/libavb/avb_util.h" -#include "../lib/libavb/avb_vbmeta_image.h" -#undef AVB_INSIDE_LIBAVB_H - -#include "../lib/libavb/fsl/fsl_avb.h" - -#endif /* LIBAVB_H_ */ diff --git a/include/libavb_ab.h b/include/libavb_ab.h new file mode 100644 index 0000000..52a1297 --- /dev/null +++ b/include/libavb_ab.h @@ -0,0 +1,42 @@ +/* + * 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 "../lib/avb/libavb/libavb.h" + +/* 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 "../lib/avb/libavb_ab/avb_ab_flow.h" +#include "../lib/avb/libavb_ab/avb_ab_ops.h" +#undef AVB_INSIDE_LIBAVB_AB_H + +#include "../lib/avb/fsl/fsl_avb.h" + +#endif /* LIBAVB_AB_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 2be2aa6..64c1062 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_BZIP2) += bzip2/ obj-$(CONFIG_TIZEN) += tizen/ obj-$(CONFIG_OF_LIBFDT) += libfdt/ obj-$(CONFIG_FIT) += libfdt/ -obj-$(CONFIG_AVB_SUPPORT) += libavb/ +obj-$(CONFIG_AVB_SUPPORT) += avb/ obj-$(CONFIG_AES) += aes.o obj-$(CONFIG_USB_TTY) += circbuf.o diff --git a/lib/avb/Makefile b/lib/avb/Makefile new file mode 100644 index 0000000..f5a264a --- /dev/null +++ b/lib/avb/Makefile @@ -0,0 +1,14 @@ +subdir-ccflags-y += -D_FILE_OFFSET_BITS=64 \ + -D_POSIX_C_SOURCE=199309L \ + -Wa,--noexecstack \ + -Werror \ + -Wall \ + -Wextra \ + -Wformat=2 \ + -Wno-psabi \ + -Wno-unused-parameter \ + -ffunction-sections \ + -std=gnu99 +obj-y += libavb/ +obj-y += libavb_ab/ +obj-y += fsl/ diff --git a/lib/avb/fsl/Makefile b/lib/avb/fsl/Makefile new file mode 100644 index 0000000..362c917 --- /dev/null +++ b/lib/avb/fsl/Makefile @@ -0,0 +1,4 @@ +ccflags-$(CONFIG_AVB_DEBUG) += -DAVB_DEBUG +obj-y += fsl_avb.o +obj-y += fsl_avbkey.o +obj-y += fsl_bootctl.o diff --git a/lib/avb/fsl/debug.h b/lib/avb/fsl/debug.h new file mode 100644 index 0000000..c1165ec --- /dev/null +++ b/lib/avb/fsl/debug.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __AVB_DEBUG_H__ +#define __AVB_DEBUG_H__ + +#ifdef AVB_VVDEBUG +#define AVB_VDEBUG +#define VVDEBUG(format, ...) printf(" %s: "format, __func__, ##__VA_ARGS__) +#else +#define VVDEBUG(format, ...) +#endif + +#ifdef AVB_VDEBUG +#define AVB_DEBUG +#define VDEBUG(format, ...) printf(" %s: "format, __func__, ##__VA_ARGS__) +#else +#define VDEBUG(format, ...) +#endif + +#ifdef AVB_DEBUG +#define DEBUGAVB(format, ...) printf(" %s: "format, __func__, ##__VA_ARGS__) +#else +#define DEBUGAVB(format, ...) +#endif + +#define ERR(format, ...) printf("%s: "format, __func__, ##__VA_ARGS__) + +#define HEXDUMP_COLS 16 +#define HEXDUMP_WIDTH 1 + +#endif diff --git a/lib/avb/fsl/fsl_avb.c b/lib/avb/fsl/fsl_avb.c new file mode 100644 index 0000000..a1bd160 --- /dev/null +++ b/lib/avb/fsl/fsl_avb.c @@ -0,0 +1,715 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include +#include +#include "../../../drivers/usb/gadget/fastboot_lock_unlock.h" + +#include "fsl_avb.h" +#include "fsl_avbkey.h" +#include "debug.h" + +#define FSL_AVB_DEV "mmc" + +#define ALIGN_BYTES 64 /*mmc block read/write need 64 bytes aligned */ + +struct margin_pos { + /* which blk the read/write starts */ + lbaint_t blk_start; + /* which blk the read/write ends */ + lbaint_t blk_end; + /* start position inside the start blk */ + unsigned long start; + /* end position inside the end blk */ + unsigned long end; + /* how many blks can be read/write one time */ + unsigned long multi; +}; +typedef struct margin_pos margin_pos_t; + + +static block_dev_desc_t *fs_dev_desc = NULL; +static block_dev_desc_t *get_mmc_desc(void) { + extern int mmc_get_env_devno(void); + int dev_no = mmc_get_env_devno(); + return get_dev(FSL_AVB_DEV, dev_no); +} + +/* get margin_pos struct from offset [to the partition start/end] and num_bytes to read/write */ +static int32_t get_margin_pos(lbaint_t part_start, lbaint_t part_end, unsigned long blksz, + margin_pos_t *margin, int64_t offset, size_t num_bytes, bool allow_partial) { + long off; + if (offset < 0) { + margin->blk_start = (offset + 1) / blksz + part_end; + margin->start = (off = offset % blksz) == 0 ? 0 : blksz + off; // offset == -1 means the last byte?, or start need -1 + if (offset + num_bytes - 1 >= 0) { + if (!allow_partial) + return -1; + margin->blk_end = part_end; + margin->end = blksz - 1; + } else { + margin->blk_end = (num_bytes + offset) / blksz + part_end; // which blk the last byte is in + margin->end = (off = (num_bytes + offset - 1) % blksz) == 0 ? + 0 : blksz + off; // last byte + } + } else { + margin->blk_start = offset / blksz + part_start; + margin->start = offset % blksz; + margin->blk_end = (offset + num_bytes - 1) / blksz + part_start ; + margin->end = (offset + num_bytes - 1) % blksz; + if (margin->blk_end > part_end) { + if (!allow_partial) + return -1; + margin->blk_end = part_end; + margin->end = blksz - 1; + } + } + VDEBUG("bs=%ld, be=%ld, s=%ld, e=%ld\n", + margin->blk_start, margin->blk_end, margin->start, margin->end); + + if (margin->blk_start > part_end || margin->blk_start < part_start) + return -1; + long multi = margin->blk_end - margin->blk_start - 1 + + (margin->start == 0) + (margin->end == blksz -1); + margin->multi = multi > 0 ? multi : 0; + VDEBUG("bm=%ld\n", margin->multi); + return 0; +} + /* 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 fsl_read_from_partition(AvbOps* ops, const char* partition, + int64_t offset, size_t num_bytes, + void* buffer, size_t* out_num_read) +{ + struct fastboot_ptentry *pte; + unsigned char *bdata; + unsigned char *out_buf = (unsigned char *)buffer; + unsigned long blksz; + unsigned long s, cnt; + size_t num_read = 0; + lbaint_t part_start, part_end, bs, be; + margin_pos_t margin; + + AvbIOResult ret; + + DEBUGAVB("[%s]: offset=%ld, num_bytes=%zu\n", partition, (long)offset, num_bytes); + + assert(buffer != NULL && out_num_read != NULL); + + if (!fs_dev_desc && (fs_dev_desc = get_mmc_desc()) == NULL) { + ERR("mmc device not found\n"); + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + } + + pte = fastboot_flash_find_ptn(partition); + if (!pte) { + ERR("no %s partition\n", partition); + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + } + + blksz = fs_dev_desc->blksz; + part_start = pte->start; + part_end = pte->start + pte->length - 1; + VDEBUG("blksz: %ld, part_end: %ld, part_start: %ld:\n", + blksz, part_end, part_start); + + if(get_margin_pos(part_start, part_end, blksz, + &margin, offset, num_bytes, true)) + return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; + + bs = margin.blk_start; + be = margin.blk_end; + s = margin.start; + + // alloc a blksz mem + bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz); + if (bdata == NULL) + return AVB_IO_RESULT_ERROR_OOM; + + // one block a time + while (bs <= be) { + memset(bdata, 0, blksz); + if (!fs_dev_desc->block_read(fs_dev_desc->dev, bs, 1, bdata)) { + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + cnt = blksz - s; + if (num_read + cnt > num_bytes) + cnt = num_bytes - num_read; + VDEBUG("cur: bs=%ld, start=%ld, cnt=%ld bdata=0x%08x\n", + bs, s, cnt, bdata); + memcpy(out_buf, bdata + s, cnt); + bs++; + num_read += cnt; + out_buf += cnt; + s = 0; + } + *out_num_read = num_read; + ret = AVB_IO_RESULT_OK; +#ifdef AVB_VVDEBUG + printf("\nnum_read=%zu", num_read); + printf("\n----dump---\n"); + print_buffer(0, buffer, HEXDUMP_WIDTH, num_read, 0); + printf("--- end ---\n"); +#endif + +fail: + free(bdata); + return ret; +} + +/* multi block read version of read_from_partition */ + AvbIOResult fsl_read_from_partition_multi(AvbOps* ops, const char* partition, + int64_t offset, size_t num_bytes, + void* buffer, size_t* out_num_read) +{ + struct fastboot_ptentry *pte; + unsigned char *bdata; + unsigned char *out_buf = (unsigned char *)buffer; + unsigned char *dst, *dst64 = NULL; + unsigned long blksz; + unsigned long s, cnt; + size_t num_read = 0; + lbaint_t part_start, part_end, bs, be, bm, blk_num; + margin_pos_t margin; + + AvbIOResult ret; + + DEBUGAVB("[%s]: offset=%ld, num_bytes=%zu\n", partition, (long)offset, num_bytes); + + assert(buffer != NULL && out_num_read != NULL); + + if (!fs_dev_desc && (fs_dev_desc = get_mmc_desc()) == NULL) { + ERR("mmc device not found\n"); + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + } + + pte = fastboot_flash_find_ptn(partition); + if (!pte) { + ERR("no %s partition\n", partition); + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + } + + blksz = fs_dev_desc->blksz; + part_start = pte->start; + part_end = pte->start + pte->length - 1; + VDEBUG("blksz: %ld, part_end: %ld, part_start: %ld:\n", + blksz, part_end, part_start); + + if(get_margin_pos(part_start, part_end, blksz, + &margin, offset, num_bytes, true)) + return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; + + bs = margin.blk_start; + be = margin.blk_end; + s = margin.start; + bm = margin.multi; + + // alloc a blksz mem + bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz); + if (bdata == NULL) + return AVB_IO_RESULT_ERROR_OOM; + + // support multi blk read + while (bs <= be) { + if (!s && bm > 1) { + dst = out_buf; + dst64 = PTR_ALIGN(out_buf, 64); //for mmc blk read alignment + VDEBUG("cur: dst=0x%08x, dst64=0x%08x\n", dst, dst64); + if (dst64 != dst) { + dst = dst64; + bm--; + } + blk_num = bm; + cnt = bm * blksz; + bm = 0; //no more multi blk + } else { + blk_num = 1; + cnt = blksz - s; + if (num_read + cnt > num_bytes) + cnt = num_bytes - num_read; + dst = bdata; + } + VDEBUG("cur: bs=%ld, num=%ld, start=%ld, cnt=%ld dst=0x%08x\n", + bs, blk_num, s, cnt, dst); + if (!fs_dev_desc->block_read(fs_dev_desc->dev, bs, blk_num, dst)) { + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + + if (dst == bdata) + memcpy(out_buf, bdata + s, cnt); + else if (dst == dst64) + memcpy(out_buf, dst, cnt); //internal copy + + s = 0; + bs += blk_num; + num_read += cnt; + out_buf += cnt; +#ifdef AVB_VVDEBUG + printf("\nnum_read=%ld", cnt); + printf("\n----dump---\n"); + print_buffer(0, buffer, HEXDUMP_WIDTH, cnt, 0); + printf("--- end ---\n"); +#endif + } + *out_num_read = num_read; + ret = AVB_IO_RESULT_OK; +#ifdef AVB_VVDEBUG + printf("\nnum_read=%zu", num_read); + printf("\n----dump---\n"); + print_buffer(0, buffer, HEXDUMP_WIDTH, num_read, 0); + printf("--- end ---\n"); +#endif + +fail: + free(bdata); + return ret; +} + + /* 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 fsl_write_to_partition(AvbOps* ops, const char* partition, + int64_t offset, size_t num_bytes, + const void* buffer) +{ + struct fastboot_ptentry *pte; + unsigned char *bdata; + unsigned char *in_buf = (unsigned char *)buffer; + unsigned long blksz; + unsigned long s, cnt; + size_t num_write = 0; + lbaint_t part_start, part_end, bs; + margin_pos_t margin; + + AvbIOResult ret; + + DEBUGAVB("[%s]: offset=%ld, num_bytes=%zu\n", partition, (long)offset, num_bytes); + + assert(buffer != NULL); + + if (!fs_dev_desc && (fs_dev_desc = get_mmc_desc()) == NULL) { + ERR("mmc device not found\n"); + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + } + + pte = fastboot_flash_find_ptn(partition); + if (!pte) { + ERR("no %s partition\n", partition); + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + } + + blksz = fs_dev_desc->blksz; + part_start = pte->start; + part_end = pte->start + pte->length - 1; + VDEBUG("blksz: %ld, part_end: %ld, part_start: %ld:\n", + blksz, part_end, part_start); + + if(get_margin_pos(part_start, part_end, blksz, + &margin, offset, num_bytes, false)) + return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; + + bs = margin.blk_start; + s = margin.start; + + // alloc a blksz mem + bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz); + if (bdata == NULL) + return AVB_IO_RESULT_ERROR_OOM; + + while (num_write < num_bytes) { + memset(bdata, 0, blksz); + cnt = blksz - s; + if (num_write + cnt > num_bytes) + cnt = num_bytes - num_write; + if (!s || cnt != blksz) { //read blk first + if (!fs_dev_desc->block_read(fs_dev_desc->dev, bs, 1, bdata)) { + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + } + memcpy(bdata + s, in_buf, cnt); //change data + VDEBUG("cur: bs=%ld, start=%ld, cnt=%ld bdata=0x%08x\n", + bs, s, cnt, bdata); + if (!fs_dev_desc->block_write(fs_dev_desc->dev, bs, 1, bdata)) { + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + bs++; + num_write += cnt; + in_buf += cnt; + if (s != 0) + s = 0; + } + ret = AVB_IO_RESULT_OK; + +fail: + free(bdata); + return ret; +} + +/* 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 fsl_read_ab_metadata(AvbABOps* ab_ops, struct AvbABData* data) +{ + return avb_ab_data_read(ab_ops, 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 fsl_write_ab_metadata(AvbABOps* ab_ops, const struct AvbABData* data) +{ + return avb_ab_data_write(ab_ops, data); +} + +/* 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'. + * + * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set - + * true if trusted or false if untrusted. + */ +AvbIOResult fsl_validate_vbmeta_public_key(AvbOps* ops, + const uint8_t* public_key_data, + size_t public_key_length, + bool* out_is_trusted) { + kblb_hdr_t hdr; + kblb_tag_t *pubk; + size_t num_read, blob_size; + uint8_t *extract_key = NULL; + uint8_t *read_keyblb = NULL; + AvbIOResult ret; + + assert(ops != NULL && out_is_trusted != NULL); + *out_is_trusted = false; + /* read the kblb header */ + if (ops->read_from_partition(ops, "avbkey", 0, sizeof(hdr), + (void *)&hdr, &num_read) != AVB_IO_RESULT_OK) { + ERR("read partition avbkey error\n"); + return AVB_IO_RESULT_ERROR_IO; + } + + if (num_read != sizeof(hdr) || + memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) { + ERR("avbkey partition magic not match\n"); + return AVB_IO_RESULT_ERROR_IO; + } + + pubk = &hdr.pubk_tag; + if (pubk->len != public_key_length){ + ERR("avbkey len not match\n"); + return AVB_IO_RESULT_ERROR_IO; + } + blob_size = pubk->len + AVB_CAAM_PAD; + extract_key = malloc(pubk->len); + read_keyblb = malloc(blob_size); + if (extract_key == NULL || read_keyblb == NULL) { + ret = AVB_IO_RESULT_ERROR_OOM; + goto fail; + } + + /* read public keyblob */ + if (ops->read_from_partition(ops, "avbkey", pubk->offset, blob_size, + (void *)read_keyblb, &num_read) != AVB_IO_RESULT_OK) { + ERR("read public keyblob error\n"); + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + if (num_read != blob_size) { + ERR("avbkey partition magic not match\n"); + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + + /* caam decrypt */ + caam_open(); + if (caam_decap_blob((uint32_t)extract_key, (uint32_t)read_keyblb, pubk->len)) { + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + /* match given public key */ + if (memcmp(extract_key, public_key_data, public_key_length)) { + ret = AVB_IO_RESULT_OK; + goto fail; + } +#ifdef AVB_VDEBUG + printf("\n----key dump: stored---\n"); + print_buffer(0, extract_key, HEXDUMP_WIDTH, pubk->len, 0); + printf("\n----key dump: vbmeta---\n"); + print_buffer(0, public_key_data, HEXDUMP_WIDTH, public_key_length, 0); + printf("--- end ---\n"); +#endif + + *out_is_trusted = true; + ret = AVB_IO_RESULT_OK; +fail: + if (extract_key != NULL) + free(extract_key); + if (read_keyblb != NULL) + free(read_keyblb); + return ret; +} + +/* Gets the rollback index corresponding to the slot given by + * |rollback_index_slot|. 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 slots (say, + * one or four) so may error out if |rollback_index_slot| exceeds + * this number. + */ +AvbIOResult fsl_read_rollback_index(AvbOps* ops, size_t rollback_index_slot, + uint64_t* out_rollback_index) { + kblb_hdr_t hdr; + kblb_tag_t *rbk; + size_t num_read, blob_size; + uint64_t *extract_idx = NULL; + uint64_t *read_keyblb = NULL; + AvbIOResult ret; + + assert(ops != NULL && out_rollback_index != NULL); + *out_rollback_index = ~0; + + DEBUGAVB("read rollback slot: %zu\n", rollback_index_slot); + + if (rollback_index_slot >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS) + return AVB_IO_RESULT_ERROR_IO; + + /* read the kblb header */ + if (ops->read_from_partition(ops, "avbkey", 0, sizeof(hdr), + (void *)&hdr, &num_read) != AVB_IO_RESULT_OK) { + ERR("read partition avbkey error\n"); + return AVB_IO_RESULT_ERROR_IO; + } + + if (num_read != sizeof(hdr) || + memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) { + ERR("avbkey partition magic not match\n"); + return AVB_IO_RESULT_ERROR_IO; + } + + rbk = &hdr.rbk_tags[rollback_index_slot]; + blob_size = rbk->len + AVB_CAAM_PAD; + extract_idx = malloc(rbk->len); + read_keyblb = malloc(blob_size); + if (extract_idx == NULL || read_keyblb == NULL) { + ret = AVB_IO_RESULT_ERROR_OOM; + goto fail; + } + + /* read rollback_index keyblob */ + if (ops->read_from_partition(ops, "avbkey", rbk->offset, blob_size, + (void *)read_keyblb, &num_read) != AVB_IO_RESULT_OK) { + ERR("read public keyblob error\n"); + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + if (num_read != blob_size) { + ERR("avbkey read len not match\n"); + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + + /* caam decrypt */ + caam_open(); + if (caam_decap_blob((uint32_t)extract_idx, (uint32_t)read_keyblb, rbk->len)) { + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } +#ifdef AVB_VVDEBUG + printf("\n----idx dump: ---\n"); + print_buffer(0, extract_idx, HEXDUMP_WIDTH, rbk->len, 0); + printf("--- end ---\n"); +#endif + + *out_rollback_index = *extract_idx; + DEBUGAVB("rollback_index = %" PRIu64 "\n", *out_rollback_index); + ret = AVB_IO_RESULT_OK; +fail: + if (extract_idx != NULL) + free(extract_idx); + if (read_keyblb != NULL) + free(read_keyblb); + return ret; +} + +/* Sets the rollback index corresponding to the slot given by + * |rollback_index_slot| 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 slots (say, + * one or four) so may error out if |rollback_index_slot| exceeds + * this number. + */ +AvbIOResult fsl_write_rollback_index(AvbOps* ops, size_t rollback_index_slot, + uint64_t rollback_index) { + kblb_hdr_t hdr; + kblb_tag_t *rbk; + size_t num_read, blob_size; + uint64_t *plain_idx = NULL; + uint64_t *write_keyblb = NULL; + AvbIOResult ret; + + DEBUGAVB("write to rollback slot: (%zu, %" PRIu64 ")\n", + rollback_index_slot, rollback_index); + + assert(ops != NULL); + + if (rollback_index_slot >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS) + return AVB_IO_RESULT_ERROR_IO; + + /* read the kblb header */ + if (ops->read_from_partition(ops, "avbkey", 0, sizeof(hdr), + (void *)&hdr, &num_read) != AVB_IO_RESULT_OK) { + ERR("read partition avbkey error\n"); + return AVB_IO_RESULT_ERROR_IO; + } + + if (num_read != sizeof(hdr) || + memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) { + ERR("avbkey partition magic not match\n"); + return AVB_IO_RESULT_ERROR_IO; + } + + rbk = &hdr.rbk_tags[rollback_index_slot]; + blob_size = rbk->len + AVB_CAAM_PAD; + plain_idx = malloc(rbk->len); + write_keyblb = malloc(blob_size); + if (plain_idx == NULL || write_keyblb == NULL) { + ret = AVB_IO_RESULT_ERROR_OOM; + goto fail; + } + memset(plain_idx, 0, rbk->len); + *plain_idx = rollback_index; + + /* caam encrypt */ + caam_open(); + if (caam_gen_blob((uint32_t)plain_idx, (uint32_t)write_keyblb, rbk->len)) { + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + + /* write rollback_index keyblob */ + if (ops->write_to_partition(ops, "avbkey", rbk->offset, blob_size, + (void *)write_keyblb) != AVB_IO_RESULT_OK) { + ERR("read public keyblob error\n"); + ret = AVB_IO_RESULT_ERROR_IO; + goto fail; + } + ret = AVB_IO_RESULT_OK; +fail: + if (plain_idx != NULL) + free(plain_idx); + if (write_keyblb != NULL) + free(write_keyblb); + return ret; +} + +/* 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 fsl_read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked) { + + FbLockState status; + + assert(out_is_unlocked != NULL); + *out_is_unlocked = false; + + status = fastboot_get_lock_stat(); + if (status != FASTBOOT_LOCK_ERROR) { + if (status == FASTBOOT_LOCK) + *out_is_unlocked = false; + else + *out_is_unlocked = true; + } else + return AVB_IO_RESULT_ERROR_IO; + + DEBUGAVB("is_unlocked=%d\n", *out_is_unlocked); + return AVB_IO_RESULT_OK; +} + +/* 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 fsl_get_unique_guid_for_partition(AvbOps* ops, + const char* partition, + char* guid_buf, + size_t guid_buf_size) { + assert(guid_buf != NULL); +#ifdef CONFIG_PARTITION_UUIDS + struct fastboot_ptentry *pte; + pte = fastboot_flash_find_ptn(partition); + if (!pte) { + ERR("no %s partition\n", partition); + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + } + strncpy(guid_buf, (const char *)pte->uuid, guid_buf_size); + guid_buf[guid_buf_size - 1] = '\0'; + DEBUGAVB("[%s]: GUID=%s\n", partition, guid_buf); + return AVB_IO_RESULT_OK; +#else + return AVB_IO_RESULT_ERROR_IO; +#endif +} diff --git a/lib/avb/fsl/fsl_avb.h b/lib/avb/fsl/fsl_avb.h new file mode 100644 index 0000000..2230931 --- /dev/null +++ b/lib/avb/fsl/fsl_avb.h @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __FSL_AVB_H__ +#define __FSL_AVB_H__ + +#include +/* 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 fsl_read_from_partition(AvbOps* ops, const char* partition, + int64_t offset, size_t num_bytes, + void* buffer, size_t* out_num_read); + +/* multi block read version + * */ +AvbIOResult fsl_read_from_partition_multi(AvbOps* ops, const char* partition, + int64_t offset, size_t num_bytes, + void* buffer, size_t* out_num_read); + +/* 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 fsl_write_to_partition(AvbOps* ops, const char* partition, + int64_t offset, size_t num_bytes, + const void* buffer); + +/* 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 fsl_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 fsl_write_ab_metadata(AvbABOps* ab_ops, const struct AvbABData* data); + +/* 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'. + * + * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set - + * true if trusted or false if untrusted. + */ +AvbIOResult fsl_validate_vbmeta_public_key(AvbOps* ops, + const uint8_t* public_key_data, + size_t public_key_length, + bool* out_is_trusted); + +/* Gets the rollback index corresponding to the slot given by + * |rollback_index_slot|. 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 slots (say, + * one or four) so may error out if |rollback_index_slot| exceeds + * this number. + */ +AvbIOResult fsl_read_rollback_index(AvbOps* ops, size_t rollback_index_slot, + uint64_t* out_rollback_index); + +/* Sets the rollback index corresponding to the slot given by + * |rollback_index_slot| 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 slots (say, + * one or four) so may error out if |rollback_index_slot| exceeds + * this number. + */ +AvbIOResult fsl_write_rollback_index(AvbOps* ops, size_t rollback_index_slot, + 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 fsl_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 fsl_get_unique_guid_for_partition(AvbOps* ops, + const char* partition, + char* guid_buf, + size_t guid_buf_size); + +/* check if the fastboot getvar cmd is for query [avb] bootctl's slot var + * cmd is the fastboot getvar's cmd in + * return true if it is a bootctl related cmd, false if it's not. + * */ +bool is_slotvar_avb(char *cmd); + +/* return 0 for the first slot + * return 1 for the second slot + * return -1 for not supported slot + * */ +int slotidx_from_suffix(char *suffix); + +/* return fastboot's getvar cmd response + * cmd is the fastboot getvar's cmd in + * if return 0, buffer is bootctl's slot var out + * if return -1, buffer is error string + * */ +int get_slotvar_avb(AvbABOps *ab_ops, char *cmd, char *buffer, size_t size); + +/* reset rollback_index part in avbkey partition + * used in the switch from LOCK to UNLOCK + * return 0 if success, non 0 if fail. + * */ +int rbkidx_erase(const char * kblb_part); + +/* init the avbkey partition, include the header/public key/rollback index + * for public key/rollback index part, use caam to do encrypt + * return 0 if success, non 0 if fail. + * */ +int avbkeyblb_init(uint8_t *plainkey, uint32_t keylen, const char *kblb_part /*"avbkey"*/); + +/* read a/b metadata to get curr slot + * return slot suffix '_a'/'_b' or NULL */ +char *select_slot(AvbABOps *ab_ops); + +#endif /* __FSL_AVB_H__ */ diff --git a/lib/avb/fsl/fsl_avbkey.c b/lib/avb/fsl/fsl_avbkey.c new file mode 100644 index 0000000..db0f068 --- /dev/null +++ b/lib/avb/fsl/fsl_avbkey.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#include "fsl_avb.h" +#include "fsl_avbkey.h" +#include "debug.h" + +/* bank 15, GP7, 0xc80[31:0] */ +#define AVBKEY_FUSE_BANK 15 +#define AVBKEY_FUSE_WORD 0 +#define AVBKEY_FUSE_MASK 0xffffffff +#define AVBKEY_FUSE_INIT 0x4156424b /* 'avbk' */ + + +static int encrypt_write(uint8_t *plain, uint32_t len, const char * part, size_t offset) { + + uint8_t *blb; + uint32_t blbsize; + int ret; + + blbsize = len + AVB_CAAM_PAD; + blb = (uint8_t *)malloc(blbsize); + if (blb == NULL) + return -1; + + caam_open(); + if (caam_gen_blob((uint32_t)plain, (uint32_t)blb, len)) { + ret = -1; + goto fail; + } + + if (fsl_write_to_partition(NULL, part, offset, blbsize, + (void *)blb) != AVB_IO_RESULT_OK) { + ret = -1; + goto fail; + } + ret = 0; + +fail: + free(blb); + return ret; +} + +int rbkidx_erase(const char * kblb_part) { + int i; + size_t num_read; + kblb_hdr_t hdr; + kblb_tag_t *tag; + /* read the kblb header */ + if (fsl_read_from_partition(NULL, kblb_part, 0, sizeof(hdr), + (void *)&hdr, &num_read) != AVB_IO_RESULT_OK) { + ERR("read partition avbkey error\n"); + return -1; + } + if (num_read != sizeof(hdr) || + memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) { + ERR("avbkey partition magic not match\n"); + return -1; + } + /* reset rollback index */ + uint32_t offset = AVB_RBIDX_START; + uint32_t rbidx_len = AVB_RBIDX_LEN; + uint8_t *rbidx = malloc(rbidx_len); + if (rbidx == NULL) + return -1; + memset(rbidx, 0, rbidx_len); + *(uint64_t *)rbidx = AVB_RBIDX_INITVAL; + for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; i++) { + tag = &hdr.rbk_tags[i]; + tag->flag = AVB_RBIDX_FLAG; + tag->offset = offset; + tag->len = rbidx_len; + /* caam encrypt and write */ + if (encrypt_write(rbidx, tag->len, kblb_part, tag->offset) != 0) { + ERR("write rollback index keyblob error\n"); + free(rbidx); + return -1; + } + offset += AVB_RBIDX_ALIGN; + } + free(rbidx); + /* write hdr */ + if (fsl_write_to_partition(NULL, kblb_part, 0, + sizeof(hdr), (void *)&hdr) != AVB_IO_RESULT_OK) { + ERR("write avbkey hdr error\n"); + return -1; + } + return 0; +} + +int avbkeyblb_init(uint8_t *plainkey, uint32_t keylen, const char * kblb_part) { + int i; + kblb_hdr_t hdr; + kblb_tag_t *tag; + uint32_t fuse_val; + + /* read fuse to check enable init */ + /* fuse_read read the shadow reg of fuse + * use fuse_sense to real read fuse */ +#ifdef CONFIG_AVB_FUSE + if (fuse_sense(AVBKEY_FUSE_BANK, AVBKEY_FUSE_WORD, &fuse_val)) { +#else + if (fuse_read(AVBKEY_FUSE_BANK, AVBKEY_FUSE_WORD, &fuse_val)) { +#endif + ERR("read fuse error\n"); + return -1; + } + if ((fuse_val & AVBKEY_FUSE_MASK) == AVBKEY_FUSE_INIT) { + ERR("key already init\n"); + return -1; + } + fuse_val = AVBKEY_FUSE_MASK & AVBKEY_FUSE_INIT; + + /* write fuse to prevent init again */ + /* fuse_override write the shadow reg of fuse + * use fuse_prog to PERMANENT write fuse */ +#ifdef CONFIG_AVB_FUSE + if (fuse_prog(AVBKEY_FUSE_BANK, AVBKEY_FUSE_WORD, fuse_val)) { +#else + if (fuse_override(AVBKEY_FUSE_BANK, AVBKEY_FUSE_WORD, fuse_val)) { +#endif + ERR("write fuse error\n"); + return -1; + } + + assert(plainkey != NULL); + + /* check overflow */ + if (keylen > AVB_RBIDX_START - AVB_PUBKY_OFFSET) { + ERR("key len overflow\n"); + return -1; + } + + /* init pubkey */ + tag = &hdr.pubk_tag; + tag->flag = AVB_PUBKY_FLAG; + tag->offset = AVB_PUBKY_OFFSET; + tag->len = keylen; + /* caam encrypt and write */ + if (encrypt_write(plainkey, tag->len, kblb_part, tag->offset) != 0) { + ERR("write pubkey keyblob error\n"); + return -1; + } + + /* init rollback index */ + uint32_t offset = AVB_RBIDX_START; + uint32_t rbidx_len = AVB_RBIDX_LEN; + uint8_t *rbidx = malloc(rbidx_len); + if (rbidx == NULL) + return -1; + memset(rbidx, 0, rbidx_len); + *(uint64_t *)rbidx = AVB_RBIDX_INITVAL; + for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; i++) { + tag = &hdr.rbk_tags[i]; + tag->flag = AVB_RBIDX_FLAG; + tag->offset = offset; + tag->len = rbidx_len; + /* caam encrypt and write */ + if (encrypt_write(rbidx, tag->len, kblb_part, tag->offset) != 0) { + ERR("write rollback index keyblob error\n"); + free(rbidx); + return -1; + } + offset += AVB_RBIDX_ALIGN; + } + free(rbidx); + + /* init hdr */ + memcpy(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN); + if (fsl_write_to_partition(NULL, kblb_part, 0, + sizeof(hdr), (void *)&hdr) != AVB_IO_RESULT_OK) { + ERR("write avbkey hdr error\n"); + return -1; + } + return 0; +} diff --git a/lib/avb/fsl/fsl_avbkey.h b/lib/avb/fsl/fsl_avbkey.h new file mode 100644 index 0000000..988158f --- /dev/null +++ b/lib/avb/fsl/fsl_avbkey.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __FSL_AVBKEY_H__ +#define __FSL_AVBKEY_H__ + + +#define AVB_CAAM_PAD 48 + +#define AVB_PUBKY_FLAG 0xABAB +#define AVB_PUBKY_OFFSET 0x1000 + +#define AVB_RBIDX_FLAG 0xCDCD +#define AVB_RBIDX_START 0x2000 +#define AVB_RBIDX_ALIGN 0x1000 +#define AVB_RBIDX_LEN 0x1D0 +#define AVB_RBIDX_INITVAL 0 + + +#define AVB_KBLB_MAGIC "\0KBLB!" +#define AVB_KBLB_MAGIC_LEN 6 + + +struct kblb_tag { + uint32_t flag; + uint32_t offset; + uint32_t len; +}; +typedef struct kblb_tag kblb_tag_t; + +struct kblb_hdr { + /* avbkey partition magic */ + char magic[AVB_KBLB_MAGIC_LEN]; + /* public key keyblb tag */ + kblb_tag_t pubk_tag; + /* rollback index keyblb tag */ + kblb_tag_t rbk_tags[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS]; +}; +typedef struct kblb_hdr kblb_hdr_t; + +#endif diff --git a/lib/avb/fsl/fsl_bootctl.c b/lib/avb/fsl/fsl_bootctl.c new file mode 100644 index 0000000..94392cf --- /dev/null +++ b/lib/avb/fsl/fsl_bootctl.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include "fsl_avb.h" + +/* as libavb's bootctl doesn't have the get_var support + * we add the getvar support on our side ...*/ +#define SLOT_NUM 2 +static char *slot_suffix[SLOT_NUM] = {"_a", "_b"}; + +static int strcmp_l1(const char *s1, const char *s2) { + if (!s1 || !s2) + return -1; + return strncmp(s1, s2, strlen(s1)); +} + +static bool slot_is_bootable(AvbABSlotData* slot) { + return slot->priority > 0 && + (slot->successful_boot || (slot->tries_remaining > 0)); +} + +int slotidx_from_suffix(char *suffix) { + int slot = -1; + + if (!strcmp(suffix, "_a") || + !strcmp(suffix, "a")) + slot = 0; + else if (!strcmp(suffix, "_b") || + !strcmp(suffix, "b")) + slot = 1; + + return slot; +} + +bool is_slotvar_avb(char *cmd) { + + assert(cmd != NULL); + if (!strcmp_l1("has-slot:", cmd) || + !strcmp_l1("slot-successful:", cmd) || + !strcmp_l1("slot-count", cmd) || + !strcmp_l1("slot-suffixes", cmd) || + !strcmp_l1("current-slot", cmd) || + !strcmp_l1("slot-unbootable:", cmd) || + !strcmp_l1("slot-retry-count:", cmd)) + return true; + return false; +} + +static int get_curr_slot(AvbABData *ab_data) { + 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) + return 1; + else + return 0; + } else if (slot_is_bootable(&ab_data->slots[0])) + return 0; + else if (slot_is_bootable(&ab_data->slots[1])) + return 1; + else + return -1; +} + +int get_slotvar_avb(AvbABOps *ab_ops, char *cmd, char *buffer, size_t size) { + + AvbABData ab_data; + AvbABSlotData *slot_data; + int slot; + + assert(ab_ops != NULL && cmd != NULL && buffer != NULL); + + char *str = cmd; + if (!strcmp_l1("has-slot:", cmd)) { + str += strlen("has-slot:"); + if (!strcmp(str, "system") || !strcmp(str, "boot")) + strlcpy(buffer, "yes", size); + else + strlcpy(buffer, "no", size); + return 0; + + } else if (!strcmp_l1("slot-suffixes", cmd)) { + strlcpy(buffer, "_a,_b", size); + return 0 ; + + } else if (!strcmp_l1("slot-count", cmd)) { + strlcpy(buffer, "2", size); + return 0 ; + } + + /* load ab meta */ + if (ab_ops->read_ab_metadata == NULL || + ab_ops->read_ab_metadata(ab_ops, &ab_data) != AVB_IO_RESULT_OK) { + strlcpy(buffer, "ab data read error", size); + return -1 ; + } + + if (!strcmp_l1("current-slot", cmd)) { + int curr = get_curr_slot(&ab_data); + if (curr >= 0 && curr < SLOT_NUM) + strlcpy(buffer, slot_suffix[curr], size); + else { + strlcpy(buffer, "no bootable slot", size); + return -1; + } + + } else if (!strcmp_l1("slot-successful:", cmd)) { + str += strlen("slot-successful:"); + slot = slotidx_from_suffix(str); + if (slot < 0) { + strlcpy(buffer, "no such slot", size); + return -1; + } else { + slot_data = &ab_data.slots[slot]; + bool succ = (slot_data->successful_boot != 0); + strlcpy(buffer, succ ? "yes" : "no", size); + } + + } else if (!strcmp_l1("slot-unbootable:", cmd)) { + str += strlen("slot-unbootable:"); + slot = slotidx_from_suffix(str); + if (slot < 0) { + strlcpy(buffer, "no such slot", size); + return -1; + } else { + slot_data = &ab_data.slots[slot]; + bool bootable = slot_is_bootable(slot_data); + strlcpy(buffer, bootable ? "no" : "yes", size); + } + + } else if (!strcmp_l1("slot-retry-count:", cmd)) { + str += strlen("slot-retry-count:"); + slot = slotidx_from_suffix(str); + if (slot < 0) { + strlcpy(buffer, "no such slot", size); + return -1; + } + else { + slot_data = &ab_data.slots[slot]; + char var[7]; + sprintf(var, "%d", + slot_data->tries_remaining); + strlcpy(buffer, var, size); + } + + } else { + strlcpy(buffer, "no such slot command", size); + return -1; + } + + return 0; +} + +char *select_slot(AvbABOps *ab_ops) { + AvbABData ab_data; + int curr; + + assert(ab_ops != NULL); + + /* load ab meta */ + if (ab_ops->read_ab_metadata == NULL || + ab_ops->read_ab_metadata(ab_ops, &ab_data) != AVB_IO_RESULT_OK) { + return NULL; + } + curr = get_curr_slot(&ab_data); + if (curr >= 0 && curr < SLOT_NUM) + return slot_suffix[curr]; + else + return NULL; +} diff --git a/lib/avb/libavb/Makefile b/lib/avb/libavb/Makefile new file mode 100644 index 0000000..2badd60 --- /dev/null +++ b/lib/avb/libavb/Makefile @@ -0,0 +1,17 @@ +ccflags-y += -DAVB_COMPILATION +obj-y += avb_descriptor.o \ + avb_kernel_cmdline_descriptor.o \ + avb_sha512.o \ + avb_vbmeta_image.o \ + avb_chain_partition_descriptor.o \ + avb_footer.o \ + avb_property_descriptor.o \ + avb_slot_verify.o \ + avb_crc32.o \ + avb_hash_descriptor.o \ + avb_rsa.o \ + avb_crypto.o \ + avb_hashtree_descriptor.o \ + avb_sha256.o \ + avb_util.o \ + avb_sysdeps_uboot.o diff --git a/lib/avb/libavb/avb_ab_flow.c b/lib/avb/libavb/avb_ab_flow.c new file mode 100644 index 0000000..bcd6740 --- /dev/null +++ b/lib/avb/libavb/avb_ab_flow.c @@ -0,0 +1,441 @@ +/* + * 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" +#include "avb_util.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(AvbOps* ops, AvbABData* data) { + 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(ops, data); + } + + return AVB_IO_RESULT_OK; +} + +AvbIOResult avb_ab_data_write(AvbOps* ops, const AvbABData* data) { + 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(AvbOps* ops, AvbABData* ab_data, + AvbABData* ab_data_orig) { + AvbIOResult io_ret; + + io_ret = ops->read_ab_metadata(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(AvbOps* 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 ops->write_ab_metadata(ops, ab_data); + } + return AVB_IO_RESULT_OK; +} + +AvbABFlowResult avb_ab_flow(AvbOps* ops, + const char* const* requested_partitions, + AvbSlotVerifyData** out_data) { + AvbSlotVerifyData* slot_data[2] = {NULL, NULL}; + AvbSlotVerifyData* data = NULL; + AvbABFlowResult ret; + AvbABData ab_data, ab_data_orig; + size_t slot_index_to_boot, n; + bool is_device_unlocked; + AvbIOResult io_ret; + + io_ret = load_metadata(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; + verify_result = avb_slot_verify(ops, requested_partitions, + slot_suffixes[n], &slot_data[n]); + if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) { + if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_OOM) { + ret = AVB_AB_FLOW_RESULT_ERROR_OOM; + goto out; + } + if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_IO) { + ret = AVB_AB_FLOW_RESULT_ERROR_IO; + goto out; + } + 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 slot. + */ + for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; 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, ¤t_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; + 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: + /* do not touch metadata in UNLOCK state */ + io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked); + if (io_ret == AVB_IO_RESULT_ERROR_OOM) { + ret = AVB_AB_FLOW_RESULT_ERROR_OOM; + goto fail; + } else if (io_ret != AVB_IO_RESULT_OK) { + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; + avb_error("Error getting device state.\n"); + goto fail; + } + if (is_device_unlocked) + goto ret; + +fail: + io_ret = save_metadata_if_changed(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; + } + } + +ret: + 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(AvbOps* 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(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(ops, &ab_data, &ab_data_orig); + } + return ret; +} + +AvbIOResult avb_ab_mark_slot_unbootable(AvbOps* ops, unsigned int slot_number) { + AvbABData ab_data, ab_data_orig; + AvbIOResult ret; + + avb_assert(slot_number < 2); + + ret = load_metadata(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(ops, &ab_data, &ab_data_orig); + } + return ret; +} + +AvbIOResult avb_ab_mark_slot_successful(AvbOps* ops, unsigned int slot_number) { + AvbABData ab_data, ab_data_orig; + AvbIOResult ret; + + avb_assert(slot_number < 2); + + ret = load_metadata(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(ops, &ab_data, &ab_data_orig); + } + return ret; +} diff --git a/lib/avb/libavb/avb_ab_flow.h b/lib/avb/libavb/avb_ab_flow.h new file mode 100644 index 0000000..c19f846 --- /dev/null +++ b/lib/avb/libavb/avb_ab_flow.h @@ -0,0 +1,226 @@ +/* + * 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_AB_FLOW_H_ +#define AVB_AB_FLOW_H_ + +#include "avb_ops.h" +#include "avb_slot_verify.h" +#include "avb_vbmeta_image.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(AvbOps* 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(AvbOps* 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_ERROR_OOM, + AVB_AB_FLOW_RESULT_ERROR_IO, + AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS +} AvbABFlowResult; + +/* 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 fails verification, 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 slot, 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 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. + * + * Reasonable behavior for handling AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS + * is to initiate device recovery (which is device-dependent). + */ +AvbABFlowResult avb_ab_flow(AvbOps* ops, + const char* const* requested_partitions, + 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(AvbOps* 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(AvbOps* 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(AvbOps* ops, unsigned int slot_number); + +#ifdef __cplusplus +} +#endif + +#endif /* AVB_AB_FLOW_H_ */ diff --git a/lib/avb/libavb/avb_chain_partition_descriptor.c b/lib/avb/libavb/avb_chain_partition_descriptor.c new file mode 100644 index 0000000..40e8bb5 --- /dev/null +++ b/lib/avb/libavb/avb_chain_partition_descriptor.c @@ -0,0 +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 "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_slot = avb_be32toh(dest->rollback_index_slot); + dest->partition_name_len = avb_be32toh(dest->partition_name_len); + dest->public_key_len = avb_be32toh(dest->public_key_len); + + if (dest->rollback_index_slot < 1) { + avb_error("Invalid rollback index slot 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/lib/avb/libavb/avb_chain_partition_descriptor.h b/lib/avb/libavb/avb_chain_partition_descriptor.h new file mode 100644 index 0000000..817f74f --- /dev/null +++ b/lib/avb/libavb/avb_chain_partition_descriptor.h @@ -0,0 +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 "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 slot 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_slot; + 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_crc32.c b/lib/avb/libavb/avb_crc32.c new file mode 100644 index 0000000..55971af --- /dev/null +++ b/lib/avb/libavb/avb_crc32.c @@ -0,0 +1,112 @@ +/*- + * 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" + +/* Code taken from FreeBSD 8 */ + +static uint32_t 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 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 = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + return crc ^ ~0U; +} + +uint32_t avb_crc32(const uint8_t* buf, size_t size) { + return crc32(0, buf, size); +} diff --git a/lib/avb/libavb/avb_crypto.c b/lib/avb/libavb/avb_crypto.c new file mode 100644 index 0000000..9bd4720 --- /dev/null +++ b/lib/avb/libavb/avb_crypto.c @@ -0,0 +1,38 @@ +/* + * 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" + +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/lib/avb/libavb/avb_crypto.h b/lib/avb/libavb/avb_crypto.h new file mode 100644 index 0000000..40740c3 --- /dev/null +++ b/lib/avb/libavb/avb_crypto.h @@ -0,0 +1,137 @@ +/* + * 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 + +/* 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; + +/* 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 new file mode 100644 index 0000000..db465aa --- /dev/null +++ b/lib/avb/libavb/avb_descriptor.c @@ -0,0 +1,159 @@ +/* + * 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_word_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_word_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/lib/avb/libavb/avb_descriptor.h b/lib/avb/libavb/avb_descriptor.h new file mode 100644 index 0000000..8086a12 --- /dev/null +++ b/lib/avb/libavb/avb_descriptor.h @@ -0,0 +1,129 @@ +/* + * 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 new file mode 100644 index 0000000..5f6ed71 --- /dev/null +++ b/lib/avb/libavb/avb_footer.c @@ -0,0 +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 "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_MAJOR_VERSION) { + avb_error("No support for footer version.\n"); + return false; + } + + return true; +} diff --git a/lib/avb/libavb/avb_footer.h b/lib/avb/libavb/avb_footer.h new file mode 100644 index 0000000..6607c75 --- /dev/null +++ b/lib/avb/libavb/avb_footer.h @@ -0,0 +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 "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 MAJOR and MINOR versions used - keep in sync with avbtool. */ +#define AVB_FOOTER_MAJOR_VERSION 1 +#define AVB_FOOTER_MINOR_VERSION 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 new file mode 100644 index 0000000..2e427de --- /dev/null +++ b/lib/avb/libavb/avb_hash_descriptor.c @@ -0,0 +1,61 @@ +/* + * 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); + + /* 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/lib/avb/libavb/avb_hash_descriptor.h b/lib/avb/libavb/avb_hash_descriptor.h new file mode 100644 index 0000000..2668118 --- /dev/null +++ b/lib/avb/libavb/avb_hash_descriptor.h @@ -0,0 +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. + */ + +#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 + +/* 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_ */ diff --git a/lib/avb/libavb/avb_hashtree_descriptor.c b/lib/avb/libavb/avb_hashtree_descriptor.c new file mode 100644 index 0000000..b961e47 --- /dev/null +++ b/lib/avb/libavb/avb_hashtree_descriptor.c @@ -0,0 +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. + */ + +#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); + + /* 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/lib/avb/libavb/avb_hashtree_descriptor.h b/lib/avb/libavb/avb_hashtree_descriptor.h new file mode 100644 index 0000000..a5aafbf --- /dev/null +++ b/lib/avb/libavb/avb_hashtree_descriptor.h @@ -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. + */ + +#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 + +/* 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_ */ diff --git a/lib/avb/libavb/avb_kernel_cmdline_descriptor.c b/lib/avb/libavb/avb_kernel_cmdline_descriptor.c new file mode 100644 index 0000000..24b2978 --- /dev/null +++ b/lib/avb/libavb/avb_kernel_cmdline_descriptor.c @@ -0,0 +1,57 @@ +/* + * 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->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/lib/avb/libavb/avb_kernel_cmdline_descriptor.h b/lib/avb/libavb/avb_kernel_cmdline_descriptor.h new file mode 100644 index 0000000..0eece7d --- /dev/null +++ b/lib/avb/libavb/avb_kernel_cmdline_descriptor.h @@ -0,0 +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. + */ + +#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 + +/* A descriptor containing information to be appended to the kernel + * command-line. + * + * Following this struct are |kernel_cmdline_len| bytes with the + * kernel command-line (UTF-8 encoded). + */ +typedef struct AvbKernelCmdlineDescriptor { + AvbDescriptor parent_descriptor; + 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/lib/avb/libavb/avb_ops.h b/lib/avb/libavb/avb_ops.h new file mode 100644 index 0000000..30309c5 --- /dev/null +++ b/lib/avb/libavb/avb_ops.h @@ -0,0 +1,177 @@ +/* + * 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 + +/* 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; + +struct AvbABData; + +/* High-level operations/functions/methods that are platform + * dependent. + */ +struct AvbOps { + /* 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); + + /* 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'. + * + * 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, + bool* out_is_trusted); + + /* Gets the rollback index corresponding to the slot given by + * |rollback_index_slot|. 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 slots (say, + * one or four) so may error out if |rollback_index_slot| exceeds + * this number. + */ + AvbIOResult (*read_rollback_index)(AvbOps* ops, size_t rollback_index_slot, + uint64_t* out_rollback_index); + + /* Sets the rollback index corresponding to the slot given by + * |rollback_index_slot| 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 slots (say, + * one or four) so may error out if |rollback_index_slot| exceeds + * this number. + */ + AvbIOResult (*write_rollback_index)(AvbOps* ops, size_t rollback_index_slot, + 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); +}; + +#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 new file mode 100644 index 0000000..03d8315 --- /dev/null +++ b/lib/avb/libavb/avb_property_descriptor.c @@ -0,0 +1,167 @@ +/* + * 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/lib/avb/libavb/avb_property_descriptor.h b/lib/avb/libavb/avb_property_descriptor.h new file mode 100644 index 0000000..2ad1c2e --- /dev/null +++ b/lib/avb/libavb/avb_property_descriptor.h @@ -0,0 +1,101 @@ +/* + * 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 new file mode 100644 index 0000000..8a2b8b4 --- /dev/null +++ b/lib/avb/libavb/avb_rsa.c @@ -0,0 +1,271 @@ +/* + * 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 Key { + 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) */ +} Key; + +Key* parse_key_data(const uint8_t* data, size_t length) { + AvbRSAPublicKeyHeader h; + Key* 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 = (Key*)(avb_malloc(sizeof(Key) + 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(Key) 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; +} + +void free_parsed_key(Key* key) { avb_free(key); } + +/* a[] -= mod */ +static void subM(const Key* 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 Key* 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 Key* 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 Key* 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 Key* 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; + Key* parsed_key = NULL; + bool success = false; + + if (key == NULL || sig == NULL || hash == NULL || padding == NULL) { + avb_error("Invalid input.\n"); + goto out; + } + + parsed_key = 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) free_parsed_key(parsed_key); + if (buf != NULL) avb_free(buf); + return success; +} diff --git a/lib/avb/libavb/avb_rsa.h b/lib/avb/libavb/avb_rsa.h new file mode 100644 index 0000000..e82102b --- /dev/null +++ b/lib/avb/libavb/avb_rsa.h @@ -0,0 +1,78 @@ +/* + * 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_sysdeps.h" + +/* 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 + +/* 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/lib/avb/libavb/avb_sha.h b/lib/avb/libavb/avb_sha.h new file mode 100644 index 0000000..b925bd2 --- /dev/null +++ b/lib/avb/libavb/avb_sha.h @@ -0,0 +1,94 @@ +/* + * 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_sysdeps.h" + +/* Size in bytes of a SHA-256 digest. */ +#define AVB_SHA256_DIGEST_SIZE 32 + +/* Block size in bytes of a SHA-256 digest. */ +#define AVB_SHA256_BLOCK_SIZE 64 + +/* Size in bytes of a SHA-512 digest. */ +#define AVB_SHA512_DIGEST_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 new file mode 100644 index 0000000..b1748eb --- /dev/null +++ b/lib/avb/libavb/avb_sha256.c @@ -0,0 +1,384 @@ +/* SHA-256 and SHA-512 implementation based on code by Oliver Gay + * 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 + * 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 new file mode 100644 index 0000000..f2f0ec4 --- /dev/null +++ b/lib/avb/libavb/avb_sha512.c @@ -0,0 +1,380 @@ +/* SHA-256 and SHA-512 implementation based on code by Oliver Gay + * 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 + * 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 new file mode 100644 index 0000000..57477d2 --- /dev/null +++ b/lib/avb/libavb/avb_slot_verify.c @@ -0,0 +1,857 @@ +/* + * 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_footer.h" +#include "avb_hash_descriptor.h" +#include "avb_kernel_cmdline_descriptor.h" +#include "avb_sha.h" +#include "avb_util.h" +#include "avb_vbmeta_image.h" + +/* Maximum allow length (in bytes) of a partition name, including + * ab_suffix. + */ +#define PART_NAME_MAX_SIZE 32 + +/* Maximum number of partitions that can be loaded with avb_slot_verify(). */ +#define MAX_NUMBER_OF_LOADED_PARTITIONS 32 + +/* Maximum size of a vbmeta image - 64 KiB. */ +#define VBMETA_MAX_SIZE (64 * 1024) + +static AvbSlotVerifyResult load_and_verify_hash_partition( + AvbOps* ops, const char* const* requested_partitions, const char* ab_suffix, + const AvbDescriptor* descriptor, AvbSlotVerifyData* slot_data) { + AvbHashDescriptor hash_desc; + const uint8_t* desc_partition_name; + const uint8_t* desc_salt; + const uint8_t* desc_digest; + char part_name[PART_NAME_MAX_SIZE]; + AvbSlotVerifyResult ret; + AvbIOResult io_ret; + uint8_t* image_buf = NULL; + size_t part_num_read; + uint8_t* digest; + size_t digest_len; + const char* found; + + 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; + } + + 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; + } + + image_buf = avb_malloc(hash_desc.image_size); + if (image_buf == NULL) { + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; + goto out; + } + + io_ret = + ops->read_from_partition(ops, part_name, 0 /* offset */, + hash_desc.image_size, image_buf, &part_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(part_name, ": Error loading data from partition.\n", NULL); + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; + goto out; + } + if (part_num_read != hash_desc.image_size) { + avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL); + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; + 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; + + /* If this is the requested partition, copy to slot_data. */ + found = + avb_strv_find_str(requested_partitions, (const char*)desc_partition_name, + hash_desc.partition_name_len); + if (found != 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 out; + } + loaded_partition = + &slot_data->loaded_partitions[slot_data->num_loaded_partitions++]; + loaded_partition->partition_name = avb_strdup(found); + loaded_partition->data_size = hash_desc.image_size; + loaded_partition->data = image_buf; + image_buf = NULL; + } + +out: + if (image_buf != NULL) { + avb_free(image_buf); + } + return ret; +} + +static AvbSlotVerifyResult load_and_verify_vbmeta( + AvbOps* ops, const char* const* requested_partitions, const char* ab_suffix, + int rollback_index_slot, 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[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; + int is_main_vbmeta; + + avb_assert(slot_data != NULL); + + is_main_vbmeta = (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_main_vbmeta) { + 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) { + 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); + if (vbmeta_ret != AVB_VBMETA_VERIFY_RESULT_OK) { + avb_errorv(full_partition_name, ": Error verifying vbmeta image.\n", NULL); + ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION; + goto out; + } + + /* Check if key used to make signature matches what is expected. */ + 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; + goto out; + } + } else { + bool key_is_trusted = false; + + avb_assert(is_main_vbmeta); + io_ret = + ops->validate_vbmeta_public_key(ops, pk_data, pk_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; + goto out; + } + } + + avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf, + &vbmeta_header); + + /* Check rollback index. */ + io_ret = ops->read_rollback_index(ops, rollback_index_slot, + &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 slot.\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; + 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, descriptors[n], slot_data); + if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) { + ret = sub_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; + } + + 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, + chain_desc.rollback_index_slot, (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; + goto out; + } + } break; + + case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: { + const uint8_t* kernel_cmdline; + AvbKernelCmdlineDescriptor kernel_cmdline_desc; + + 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; + } + + 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: + ' ' + + '\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; + } + } + + ret = AVB_SLOT_VERIFY_RESULT_OK; + + /* So far, so good. Copy needed data to user, if requested. */ + if (is_main_vbmeta) { + if (slot_data->vbmeta_data != NULL) { + avb_free(slot_data->vbmeta_data); + } + /* 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. + */ + slot_data->vbmeta_size = sizeof(AvbVBMetaImageHeader) + + vbmeta_header.authentication_data_block_size + + vbmeta_header.auxiliary_data_block_size; + slot_data->vbmeta_data = vbmeta_buf; + vbmeta_buf = NULL; + } + + if (rollback_index_slot >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS) { + avb_errorv(full_partition_name, ": Invalid rollback_index_slot.\n", NULL); + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; + goto out; + } + + slot_data->rollback_indexes[rollback_index_slot] = + vbmeta_header.rollback_index; + + if (out_algorithm_type != NULL) { + *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type; + } + +out: + if (vbmeta_buf != NULL) { + avb_free(vbmeta_buf); + } + if (descriptors != NULL) { + avb_free(descriptors); + } + return ret; +} + +#define NUM_GUIDS 2 + +/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with + * values. Returns NULL on OOM, otherwise the cmdline with values + * replaced. + */ +static char* sub_cmdline(AvbOps* ops, const char* cmdline, + const char* ab_suffix) { + const char* part_name_str[NUM_GUIDS] = {"system", "boot"}; + const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)", + "$(ANDROID_BOOT_PARTUUID)"}; + char* ret = NULL; + AvbIOResult io_ret; + + /* Replace unique partition GUIDs */ + for (size_t n = 0; n < NUM_GUIDS; n++) { + char part_name[PART_NAME_MAX_SIZE]; + char guid_buf[37]; + char* new_ret; + + 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) { + new_ret = avb_replace(cmdline, replace_str[n], guid_buf); + } else { + new_ret = avb_replace(ret, replace_str[n], guid_buf); + } + if (new_ret == NULL) { + goto fail; + } + ret = new_ret; + } + + 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; +} + +static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data, + const char* key, uint64_t value) { + const int MAX_DIGITS = 32; + char rev_digits[MAX_DIGITS]; + char digits[MAX_DIGITS]; + size_t n, num_digits; + + for (num_digits = 0; num_digits < MAX_DIGITS - 1;) { + rev_digits[num_digits++] = (value % 10) + '0'; + value /= 10; + if (value == 0) { + break; + } + } + + for (n = 0; n < num_digits; n++) { + digits[n] = rev_digits[num_digits - 1 - n]; + } + digits[n] = '\0'; + + 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_slot_verify(AvbOps* ops, + const char* const* requested_partitions, + const char* ab_suffix, + AvbSlotVerifyData** out_data) { + AvbSlotVerifyResult ret; + AvbSlotVerifyData* slot_data = NULL; + AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE; + AvbIOResult io_ret; + + if (out_data != NULL) { + *out_data = NULL; + } + + slot_data = avb_calloc(sizeof(AvbSlotVerifyData)); + if (slot_data == 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, 0 /* rollback_index_slot */, + "vbmeta", avb_strlen("vbmeta"), NULL /* expected_public_key */, + 0 /* expected_public_key_length */, slot_data, &algorithm_type); + + /* If things check out, mangle the kernel command-line as needed. */ + if (ret == AVB_SLOT_VERIFY_RESULT_OK) { + /* 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; + } + + /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */ + if (slot_data->cmdline != NULL) { + char* new_cmdline = sub_cmdline(ops, slot_data->cmdline, ab_suffix); + if (new_cmdline == NULL) { + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; + goto fail; + } + avb_free(slot_data->cmdline); + slot_data->cmdline = new_cmdline; + } + + /* Add androidboot.slot_suffix, if applicable. */ + if (avb_strlen(ab_suffix) > 0) { + if (!cmdline_append_option(slot_data, "androidboot.slot_suffix", + ab_suffix)) { + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; + goto fail; + } + } + + /* Set androidboot.avb.device_state to "locked" or "unlocked". */ + bool is_device_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 fail; + } else if (io_ret != AVB_IO_RESULT_OK) { + avb_error("Error getting device state.\n"); + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; + goto fail; + } + if (!cmdline_append_option(slot_data, "androidboot.vbmeta.device_state", + is_device_unlocked ? "unlocked" : "locked")) { + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; + goto fail; + } + + /* 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; + avb_sha256_init(&ctx); + avb_sha256_update(&ctx, slot_data->vbmeta_data, slot_data->vbmeta_size); + if (!cmdline_append_option(slot_data, "androidboot.vbmeta.hash_alg", + "sha256") || + !cmdline_append_uint64_base10(slot_data, "androidboot.vbmeta.size", + slot_data->vbmeta_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 fail; + } + } break; + /* Explicit fallthrough. */ + case AVB_ALGORITHM_TYPE_SHA512_RSA2048: + case AVB_ALGORITHM_TYPE_SHA512_RSA4096: + case AVB_ALGORITHM_TYPE_SHA512_RSA8192: { + AvbSHA512Ctx ctx; + avb_sha512_init(&ctx); + avb_sha512_update(&ctx, slot_data->vbmeta_data, slot_data->vbmeta_size); + if (!cmdline_append_option(slot_data, "androidboot.vbmeta.hash_alg", + "sha512") || + !cmdline_append_uint64_base10(slot_data, "androidboot.vbmeta.size", + slot_data->vbmeta_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 fail; + } + } break; + case _AVB_ALGORITHM_NUM_TYPES: + avb_assert_not_reached(); + break; + } + + if (out_data != NULL) { + *out_data = slot_data; + } else { + avb_slot_verify_data_free(slot_data); + } + } + + 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->vbmeta_data != NULL) { + avb_free(data->vbmeta_data); + } + if (data->cmdline != NULL) { + avb_free(data->cmdline); + } + 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) { + 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; + /* Do not add a 'default:' case here because of -Wswitch. */ + } + + if (ret == NULL) { + avb_error("Unknown AvbSlotVerifyResult value.\n"); + ret = "(unknown)"; + } + + return ret; +} diff --git a/lib/avb/libavb/avb_slot_verify.h b/lib/avb/libavb/avb_slot_verify.h new file mode 100644 index 0000000..d644a44 --- /dev/null +++ b/lib/avb/libavb/avb_slot_verify.h @@ -0,0 +1,195 @@ +/* + * 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 +} AvbSlotVerifyResult; + +/* 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_SLOTS 4 + +/* AvbPartitionData contains data loaded from partitions when using + * avb_slot_verify(). The |partition_name| field contains the name of + * the partition, |data| points to the loaded data which is + * |data_size| bytes long. + * + * 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; +} AvbPartitionData; + +/* 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. + * + * 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. + * + * The verified vbmeta image in the 'vbmeta' partition of the slot is + * accessible from the |vbmeta_data| field and is of length + * |vbmeta_size| bytes. You can use this data with + * e.g. avb_descriptor_get_all(). + * + * 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) and $(ANDROID_BOOT_PARTUUID) using the + * get_unique_guid_for_partition() operation in |AvbOps|. + * + * Additionally, the |cmdline| field will have the following kernel + * command-line options set: + * + * androidboot.avb.device_state: set to "locked" or "unlocked" + * depending on the result of the result of AvbOps's + * read_is_unlocked() function. + * + * androidboot.slot_suffix: If |ab_suffix| as passed into + * avb_slot_verify() is non-empty, this variable will be set to its + * value. + * + * androidboot.vbmeta.{hash_alg, size, digest}: Will be set to + * the digest of the vbmeta image. + * + * This struct may grow in the future without it being considered an + * ABI break. + */ +typedef struct { + char* ab_suffix; + uint8_t* vbmeta_data; + size_t vbmeta_size; + AvbPartitionData* loaded_partitions; + size_t num_loaded_partitions; + char* cmdline; + uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS]; +} 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 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|. + * + * Typically the |requested_partitions| array only contains a single + * item for the boot partition, 'boot'. + * + * Verification includes loading data from the 'vbmeta', all 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. + * + * 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. + */ +AvbSlotVerifyResult avb_slot_verify(AvbOps* ops, + const char* const* requested_partitions, + const char* ab_suffix, + AvbSlotVerifyData** out_data); + +#ifdef __cplusplus +} +#endif + +#endif /* AVB_SLOT_VERIFY_H_ */ diff --git a/lib/avb/libavb/avb_sysdeps.h b/lib/avb/libavb/avb_sysdeps.h new file mode 100644 index 0000000..7fe9d06 --- /dev/null +++ b/lib/avb/libavb/avb_sysdeps.h @@ -0,0 +1,113 @@ +/* + * 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 +#include +/* 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 word-alignment. + * + * Change this to match your architecture - must be a power of two. + */ +#define AVB_WORD_ALIGNMENT_SIZE 8 + +/* 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; + +#ifdef __cplusplus +} +#endif + +#endif /* AVB_SYSDEPS_H_ */ diff --git a/lib/avb/libavb/avb_sysdeps_uboot.c b/lib/avb/libavb/avb_sysdeps_uboot.c new file mode 100644 index 0000000..be5c1d2 --- /dev/null +++ b/lib/avb/libavb/avb_sysdeps_uboot.c @@ -0,0 +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 +#include +#include + +#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) { panic("avb_abort!\n"); } + +void avb_print(const char* message) { printf("%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*)) { + printf("%s", m); + } + va_end(ap); +} + +void* avb_malloc_(size_t size) { return malloc(size); } + +void avb_free(void* ptr) { free(ptr); } diff --git a/lib/avb/libavb/avb_util.c b/lib/avb/libavb/avb_util.c new file mode 100644 index 0000000..435e556 --- /dev/null +++ b/lib/avb/libavb/avb_util.c @@ -0,0 +1,319 @@ +/* + * 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" + +uint32_t avb_be32toh(uint32_t in) { + uint8_t* d = (uint8_t*)∈ + 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*)∈ + 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 (ret == 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 (ret == 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; +} diff --git a/lib/avb/libavb/avb_util.h b/lib/avb/libavb/avb_util.h new file mode 100644 index 0000000..d53be97 --- /dev/null +++ b/lib/avb/libavb/avb_util.h @@ -0,0 +1,232 @@ +/* + * 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_word_aligned(addr) \ + avb_assert((((uintptr_t)addr) & (AVB_WORD_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_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": DEBUG: "); \ + avb_print(message); \ + } while (0) +#define avb_debugv(message, ...) \ + do { \ + avb_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": DEBUG: "); \ + avb_printv(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_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": ERROR: "); \ + avb_print(message); \ + } while (0) +#define avb_errorv(message, ...) \ + do { \ + avb_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": ERROR: "); \ + avb_printv(message, ##__VA_ARGS__); \ + } while (0) + +/* Prints out a message and calls avb_abort(). + */ +#define avb_fatal(message) \ + do { \ + avb_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": FATAL: "); \ + avb_print(message); \ + avb_abort(); \ + } while (0) +#define avb_fatalv(message, ...) \ + do { \ + avb_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": FATAL: "); \ + avb_printv(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; + +/* 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); + +#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 new file mode 100644 index 0000000..23607ed --- /dev/null +++ b/lib/avb/libavb/avb_vbmeta_image.c @@ -0,0 +1,562 @@ +/* + * 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_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}; + +typedef struct { + const uint8_t* padding; + size_t padding_len; + size_t hash_len; +} AvbAlgorithmData; + +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}, +}; + +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; + 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 the major version + * is not supported. + */ + if (h.header_version_major > AVB_MAJOR_VERSION) { + avb_error("No support for given major version.\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 algorithm field is supported. */ + if (h.algorithm_type >= _AVB_ALGORITHM_NUM_TYPES) { + avb_error("Invalid or unknown algorithm.\n"); + goto out; + } + algorithm = &algorithm_data[h.algorithm_type]; + + /* 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; + } + + /* 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 (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->header_version_major = avb_be32toh(dest->header_version_major); + dest->header_version_minor = avb_be32toh(dest->header_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->descriptors_offset = avb_be64toh(dest->descriptors_offset); + dest->descriptors_size = avb_be64toh(dest->descriptors_size); + + dest->rollback_index = avb_be64toh(dest->rollback_index); +} diff --git a/lib/avb/libavb/avb_vbmeta_image.h b/lib/avb/libavb/avb_vbmeta_image.h new file mode 100644 index 0000000..25d3689 --- /dev/null +++ b/lib/avb/libavb/avb_vbmeta_image.h @@ -0,0 +1,240 @@ +/* + * 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 + +/* The current MAJOR and MINOR versions used - keep in sync with avbtool. */ +#define AVB_MAJOR_VERSION 1 +#define AVB_MINOR_VERSION 0 + +/* 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 |header_version_major| and + * |header_version_minor| fields. Compatibility is guaranteed only + * within the same major version. + * + * 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 the vbmeta image header. */ + uint32_t header_version_major; + /* 8: The minor version of the vbmeta image header. */ + uint32_t header_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 descriptor data. */ + uint64_t descriptors_offset; + /* 88: Length of descriptor data. */ + uint64_t descriptors_size; + + /* 96: The rollback index which can be used to prevent rollback to + * older versions. + */ + uint64_t rollback_index; + + /* 104: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE + * bytes. This must be set to zeroes. + */ + uint8_t reserved[152]; +} 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_VERIFY_INVALID_VBMETA_HEADER is returned if the header of + * the vbmeta image is invalid, for example, invalid magic or + * inconsistent data. + * + * AVB_VERIFY_HASH_MISMATCH is returned if the hash stored in the + * "Authentication data" block does not match the calculated hash. + * + * AVB_VERIFY_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_HASH_MISMATCH, + AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH, +} AvbVBMetaVerifyResult; + +/* 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. + * + * 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/libavb.h b/lib/avb/libavb/libavb.h new file mode 100644 index 0000000..b74307c --- /dev/null +++ b/lib/avb/libavb/libavb.h @@ -0,0 +1,49 @@ +/* + * 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" +#undef AVB_INSIDE_LIBAVB_H + +#endif /* LIBAVB_H_ */ diff --git a/lib/avb/libavb_ab/Makefile b/lib/avb/libavb_ab/Makefile new file mode 100644 index 0000000..f22d0ed --- /dev/null +++ b/lib/avb/libavb_ab/Makefile @@ -0,0 +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 new file mode 100644 index 0000000..da8e4ea --- /dev/null +++ b/lib/avb/libavb_ab/avb_ab_flow.c @@ -0,0 +1,431 @@ +/* + * 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, + 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; + + 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; + verify_result = avb_slot_verify(ops, requested_partitions, + slot_suffixes[n], &slot_data[n]); + if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) { + if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_OOM) { + ret = AVB_AB_FLOW_RESULT_ERROR_OOM; + goto out; + } + if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_IO) { + ret = AVB_AB_FLOW_RESULT_ERROR_IO; + goto out; + } + 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 slot. + */ + for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; 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, ¤t_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; + 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; +} diff --git a/lib/avb/libavb_ab/avb_ab_flow.h b/lib/avb/libavb_ab/avb_ab_flow.h new file mode 100644 index 0000000..21f680a93 --- /dev/null +++ b/lib/avb/libavb_ab/avb_ab_flow.h @@ -0,0 +1,226 @@ +/* + * 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/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_ERROR_OOM, + AVB_AB_FLOW_RESULT_ERROR_IO, + AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS +} AvbABFlowResult; + +/* 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 fails verification, 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 slot, 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 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. + * + * Reasonable behavior for handling AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS + * is to initiate device recovery (which is device-dependent). + */ +AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops, + const char* const* requested_partitions, + 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/lib/avb/libavb_ab/avb_ab_ops.h b/lib/avb/libavb_ab/avb_ab_ops.h new file mode 100644 index 0000000..d3f6c01 --- /dev/null +++ b/lib/avb/libavb_ab/avb_ab_ops.h @@ -0,0 +1,78 @@ +/* + * 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/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. This struct extends the AvbOps struct from libavb. + */ +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/lib/libavb/Makefile b/lib/libavb/Makefile deleted file mode 100644 index a768a8c..0000000 --- a/lib/libavb/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -ccflags-y += -DAVB_COMPILATION -ccflags-y += -D_FILE_OFFSET_BITS=64 \ - -D_POSIX_C_SOURCE=199309L \ - -Wa,--noexecstack \ - -Werror \ - -Wall \ - -Wextra \ - -Wformat=2 \ - -Wno-psabi \ - -Wno-unused-parameter \ - -ffunction-sections \ - -std=gnu99 -obj-y += avb_ab_flow.o \ - avb_descriptor.o \ - avb_kernel_cmdline_descriptor.o \ - avb_sha512.o \ - avb_vbmeta_image.o \ - avb_chain_partition_descriptor.o \ - avb_footer.o \ - avb_property_descriptor.o \ - avb_slot_verify.o \ - avb_crc32.o \ - avb_hash_descriptor.o \ - avb_rsa.o \ - avb_crypto.o \ - avb_hashtree_descriptor.o \ - avb_sha256.o \ - avb_util.o \ - avb_sysdeps_uboot.o -obj-y += fsl/ diff --git a/lib/libavb/avb_ab_flow.c b/lib/libavb/avb_ab_flow.c deleted file mode 100644 index bcd6740..0000000 --- a/lib/libavb/avb_ab_flow.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * 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" -#include "avb_util.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(AvbOps* ops, AvbABData* data) { - 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(ops, data); - } - - return AVB_IO_RESULT_OK; -} - -AvbIOResult avb_ab_data_write(AvbOps* ops, const AvbABData* data) { - 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(AvbOps* ops, AvbABData* ab_data, - AvbABData* ab_data_orig) { - AvbIOResult io_ret; - - io_ret = ops->read_ab_metadata(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(AvbOps* 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 ops->write_ab_metadata(ops, ab_data); - } - return AVB_IO_RESULT_OK; -} - -AvbABFlowResult avb_ab_flow(AvbOps* ops, - const char* const* requested_partitions, - AvbSlotVerifyData** out_data) { - AvbSlotVerifyData* slot_data[2] = {NULL, NULL}; - AvbSlotVerifyData* data = NULL; - AvbABFlowResult ret; - AvbABData ab_data, ab_data_orig; - size_t slot_index_to_boot, n; - bool is_device_unlocked; - AvbIOResult io_ret; - - io_ret = load_metadata(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; - verify_result = avb_slot_verify(ops, requested_partitions, - slot_suffixes[n], &slot_data[n]); - if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) { - if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_OOM) { - ret = AVB_AB_FLOW_RESULT_ERROR_OOM; - goto out; - } - if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_IO) { - ret = AVB_AB_FLOW_RESULT_ERROR_IO; - goto out; - } - 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 slot. - */ - for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; 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, ¤t_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; - 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: - /* do not touch metadata in UNLOCK state */ - io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked); - if (io_ret == AVB_IO_RESULT_ERROR_OOM) { - ret = AVB_AB_FLOW_RESULT_ERROR_OOM; - goto fail; - } else if (io_ret != AVB_IO_RESULT_OK) { - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; - avb_error("Error getting device state.\n"); - goto fail; - } - if (is_device_unlocked) - goto ret; - -fail: - io_ret = save_metadata_if_changed(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; - } - } - -ret: - 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(AvbOps* 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(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(ops, &ab_data, &ab_data_orig); - } - return ret; -} - -AvbIOResult avb_ab_mark_slot_unbootable(AvbOps* ops, unsigned int slot_number) { - AvbABData ab_data, ab_data_orig; - AvbIOResult ret; - - avb_assert(slot_number < 2); - - ret = load_metadata(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(ops, &ab_data, &ab_data_orig); - } - return ret; -} - -AvbIOResult avb_ab_mark_slot_successful(AvbOps* ops, unsigned int slot_number) { - AvbABData ab_data, ab_data_orig; - AvbIOResult ret; - - avb_assert(slot_number < 2); - - ret = load_metadata(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(ops, &ab_data, &ab_data_orig); - } - return ret; -} diff --git a/lib/libavb/avb_ab_flow.h b/lib/libavb/avb_ab_flow.h deleted file mode 100644 index c19f846..0000000 --- a/lib/libavb/avb_ab_flow.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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_AB_FLOW_H_ -#define AVB_AB_FLOW_H_ - -#include "avb_ops.h" -#include "avb_slot_verify.h" -#include "avb_vbmeta_image.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(AvbOps* 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(AvbOps* 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_ERROR_OOM, - AVB_AB_FLOW_RESULT_ERROR_IO, - AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS -} AvbABFlowResult; - -/* 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 fails verification, 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 slot, 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 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. - * - * Reasonable behavior for handling AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS - * is to initiate device recovery (which is device-dependent). - */ -AvbABFlowResult avb_ab_flow(AvbOps* ops, - const char* const* requested_partitions, - 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(AvbOps* 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(AvbOps* 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(AvbOps* ops, unsigned int slot_number); - -#ifdef __cplusplus -} -#endif - -#endif /* AVB_AB_FLOW_H_ */ diff --git a/lib/libavb/avb_chain_partition_descriptor.c b/lib/libavb/avb_chain_partition_descriptor.c deleted file mode 100644 index 40e8bb5..0000000 --- a/lib/libavb/avb_chain_partition_descriptor.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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_slot = avb_be32toh(dest->rollback_index_slot); - dest->partition_name_len = avb_be32toh(dest->partition_name_len); - dest->public_key_len = avb_be32toh(dest->public_key_len); - - if (dest->rollback_index_slot < 1) { - avb_error("Invalid rollback index slot 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/lib/libavb/avb_chain_partition_descriptor.h b/lib/libavb/avb_chain_partition_descriptor.h deleted file mode 100644 index 817f74f..0000000 --- a/lib/libavb/avb_chain_partition_descriptor.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 slot 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_slot; - 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/libavb/avb_crc32.c b/lib/libavb/avb_crc32.c deleted file mode 100644 index 55971af..0000000 --- a/lib/libavb/avb_crc32.c +++ /dev/null @@ -1,112 +0,0 @@ -/*- - * 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" - -/* Code taken from FreeBSD 8 */ - -static uint32_t 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 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 = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - return crc ^ ~0U; -} - -uint32_t avb_crc32(const uint8_t* buf, size_t size) { - return crc32(0, buf, size); -} diff --git a/lib/libavb/avb_crypto.c b/lib/libavb/avb_crypto.c deleted file mode 100644 index 9bd4720..0000000 --- a/lib/libavb/avb_crypto.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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" - -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/lib/libavb/avb_crypto.h b/lib/libavb/avb_crypto.h deleted file mode 100644 index 40740c3..0000000 --- a/lib/libavb/avb_crypto.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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 - -/* 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; - -/* 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/libavb/avb_descriptor.c b/lib/libavb/avb_descriptor.c deleted file mode 100644 index db465aa..0000000 --- a/lib/libavb/avb_descriptor.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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_word_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_word_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/lib/libavb/avb_descriptor.h b/lib/libavb/avb_descriptor.h deleted file mode 100644 index 8086a12..0000000 --- a/lib/libavb/avb_descriptor.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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/libavb/avb_footer.c b/lib/libavb/avb_footer.c deleted file mode 100644 index 5f6ed71..0000000 --- a/lib/libavb/avb_footer.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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_MAJOR_VERSION) { - avb_error("No support for footer version.\n"); - return false; - } - - return true; -} diff --git a/lib/libavb/avb_footer.h b/lib/libavb/avb_footer.h deleted file mode 100644 index 6607c75..0000000 --- a/lib/libavb/avb_footer.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 MAJOR and MINOR versions used - keep in sync with avbtool. */ -#define AVB_FOOTER_MAJOR_VERSION 1 -#define AVB_FOOTER_MINOR_VERSION 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/libavb/avb_hash_descriptor.c b/lib/libavb/avb_hash_descriptor.c deleted file mode 100644 index 2e427de..0000000 --- a/lib/libavb/avb_hash_descriptor.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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); - - /* 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/lib/libavb/avb_hash_descriptor.h b/lib/libavb/avb_hash_descriptor.h deleted file mode 100644 index 2668118..0000000 --- a/lib/libavb/avb_hash_descriptor.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 - -/* 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_ */ diff --git a/lib/libavb/avb_hashtree_descriptor.c b/lib/libavb/avb_hashtree_descriptor.c deleted file mode 100644 index b961e47..0000000 --- a/lib/libavb/avb_hashtree_descriptor.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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); - - /* 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/lib/libavb/avb_hashtree_descriptor.h b/lib/libavb/avb_hashtree_descriptor.h deleted file mode 100644 index a5aafbf..0000000 --- a/lib/libavb/avb_hashtree_descriptor.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 - -/* 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_ */ diff --git a/lib/libavb/avb_kernel_cmdline_descriptor.c b/lib/libavb/avb_kernel_cmdline_descriptor.c deleted file mode 100644 index 24b2978..0000000 --- a/lib/libavb/avb_kernel_cmdline_descriptor.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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->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/lib/libavb/avb_kernel_cmdline_descriptor.h b/lib/libavb/avb_kernel_cmdline_descriptor.h deleted file mode 100644 index 0eece7d..0000000 --- a/lib/libavb/avb_kernel_cmdline_descriptor.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 - -/* A descriptor containing information to be appended to the kernel - * command-line. - * - * Following this struct are |kernel_cmdline_len| bytes with the - * kernel command-line (UTF-8 encoded). - */ -typedef struct AvbKernelCmdlineDescriptor { - AvbDescriptor parent_descriptor; - 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/lib/libavb/avb_ops.h b/lib/libavb/avb_ops.h deleted file mode 100644 index 98ac907..0000000 --- a/lib/libavb/avb_ops.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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 - -/* 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; - -struct AvbABData; - -/* High-level operations/functions/methods that are platform - * dependent. - */ -struct AvbOps { - /* 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); - - /* 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); - - /* 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)(AvbOps* 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)(AvbOps* ops, const struct AvbABData* data); - - /* 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'. - * - * 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, - bool* out_is_trusted); - - /* Gets the rollback index corresponding to the slot given by - * |rollback_index_slot|. 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 slots (say, - * one or four) so may error out if |rollback_index_slot| exceeds - * this number. - */ - AvbIOResult (*read_rollback_index)(AvbOps* ops, size_t rollback_index_slot, - uint64_t* out_rollback_index); - - /* Sets the rollback index corresponding to the slot given by - * |rollback_index_slot| 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 slots (say, - * one or four) so may error out if |rollback_index_slot| exceeds - * this number. - */ - AvbIOResult (*write_rollback_index)(AvbOps* ops, size_t rollback_index_slot, - 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); -}; - -#ifdef __cplusplus -} -#endif - -#endif /* AVB_OPS_H_ */ diff --git a/lib/libavb/avb_property_descriptor.c b/lib/libavb/avb_property_descriptor.c deleted file mode 100644 index 03d8315..0000000 --- a/lib/libavb/avb_property_descriptor.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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/lib/libavb/avb_property_descriptor.h b/lib/libavb/avb_property_descriptor.h deleted file mode 100644 index 2ad1c2e..0000000 --- a/lib/libavb/avb_property_descriptor.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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/libavb/avb_rsa.c b/lib/libavb/avb_rsa.c deleted file mode 100644 index 8a2b8b4..0000000 --- a/lib/libavb/avb_rsa.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * 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 Key { - 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) */ -} Key; - -Key* parse_key_data(const uint8_t* data, size_t length) { - AvbRSAPublicKeyHeader h; - Key* 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 = (Key*)(avb_malloc(sizeof(Key) + 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(Key) 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; -} - -void free_parsed_key(Key* key) { avb_free(key); } - -/* a[] -= mod */ -static void subM(const Key* 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 Key* 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 Key* 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 Key* 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 Key* 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; - Key* parsed_key = NULL; - bool success = false; - - if (key == NULL || sig == NULL || hash == NULL || padding == NULL) { - avb_error("Invalid input.\n"); - goto out; - } - - parsed_key = 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) free_parsed_key(parsed_key); - if (buf != NULL) avb_free(buf); - return success; -} diff --git a/lib/libavb/avb_rsa.h b/lib/libavb/avb_rsa.h deleted file mode 100644 index e82102b..0000000 --- a/lib/libavb/avb_rsa.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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_sysdeps.h" - -/* 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 - -/* 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/lib/libavb/avb_sha.h b/lib/libavb/avb_sha.h deleted file mode 100644 index b925bd2..0000000 --- a/lib/libavb/avb_sha.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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_sysdeps.h" - -/* Size in bytes of a SHA-256 digest. */ -#define AVB_SHA256_DIGEST_SIZE 32 - -/* Block size in bytes of a SHA-256 digest. */ -#define AVB_SHA256_BLOCK_SIZE 64 - -/* Size in bytes of a SHA-512 digest. */ -#define AVB_SHA512_DIGEST_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/libavb/avb_sha256.c b/lib/libavb/avb_sha256.c deleted file mode 100644 index b1748eb..0000000 --- a/lib/libavb/avb_sha256.c +++ /dev/null @@ -1,384 +0,0 @@ -/* SHA-256 and SHA-512 implementation based on code by Oliver Gay - * 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 - * 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/libavb/avb_sha512.c b/lib/libavb/avb_sha512.c deleted file mode 100644 index f2f0ec4..0000000 --- a/lib/libavb/avb_sha512.c +++ /dev/null @@ -1,380 +0,0 @@ -/* SHA-256 and SHA-512 implementation based on code by Oliver Gay - * 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 - * 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/libavb/avb_slot_verify.c b/lib/libavb/avb_slot_verify.c deleted file mode 100644 index 57477d2..0000000 --- a/lib/libavb/avb_slot_verify.c +++ /dev/null @@ -1,857 +0,0 @@ -/* - * 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_footer.h" -#include "avb_hash_descriptor.h" -#include "avb_kernel_cmdline_descriptor.h" -#include "avb_sha.h" -#include "avb_util.h" -#include "avb_vbmeta_image.h" - -/* Maximum allow length (in bytes) of a partition name, including - * ab_suffix. - */ -#define PART_NAME_MAX_SIZE 32 - -/* Maximum number of partitions that can be loaded with avb_slot_verify(). */ -#define MAX_NUMBER_OF_LOADED_PARTITIONS 32 - -/* Maximum size of a vbmeta image - 64 KiB. */ -#define VBMETA_MAX_SIZE (64 * 1024) - -static AvbSlotVerifyResult load_and_verify_hash_partition( - AvbOps* ops, const char* const* requested_partitions, const char* ab_suffix, - const AvbDescriptor* descriptor, AvbSlotVerifyData* slot_data) { - AvbHashDescriptor hash_desc; - const uint8_t* desc_partition_name; - const uint8_t* desc_salt; - const uint8_t* desc_digest; - char part_name[PART_NAME_MAX_SIZE]; - AvbSlotVerifyResult ret; - AvbIOResult io_ret; - uint8_t* image_buf = NULL; - size_t part_num_read; - uint8_t* digest; - size_t digest_len; - const char* found; - - 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; - } - - 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; - } - - image_buf = avb_malloc(hash_desc.image_size); - if (image_buf == NULL) { - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; - goto out; - } - - io_ret = - ops->read_from_partition(ops, part_name, 0 /* offset */, - hash_desc.image_size, image_buf, &part_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(part_name, ": Error loading data from partition.\n", NULL); - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; - goto out; - } - if (part_num_read != hash_desc.image_size) { - avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL); - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; - 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; - - /* If this is the requested partition, copy to slot_data. */ - found = - avb_strv_find_str(requested_partitions, (const char*)desc_partition_name, - hash_desc.partition_name_len); - if (found != 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 out; - } - loaded_partition = - &slot_data->loaded_partitions[slot_data->num_loaded_partitions++]; - loaded_partition->partition_name = avb_strdup(found); - loaded_partition->data_size = hash_desc.image_size; - loaded_partition->data = image_buf; - image_buf = NULL; - } - -out: - if (image_buf != NULL) { - avb_free(image_buf); - } - return ret; -} - -static AvbSlotVerifyResult load_and_verify_vbmeta( - AvbOps* ops, const char* const* requested_partitions, const char* ab_suffix, - int rollback_index_slot, 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[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; - int is_main_vbmeta; - - avb_assert(slot_data != NULL); - - is_main_vbmeta = (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_main_vbmeta) { - 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) { - 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); - if (vbmeta_ret != AVB_VBMETA_VERIFY_RESULT_OK) { - avb_errorv(full_partition_name, ": Error verifying vbmeta image.\n", NULL); - ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION; - goto out; - } - - /* Check if key used to make signature matches what is expected. */ - 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; - goto out; - } - } else { - bool key_is_trusted = false; - - avb_assert(is_main_vbmeta); - io_ret = - ops->validate_vbmeta_public_key(ops, pk_data, pk_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; - goto out; - } - } - - avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf, - &vbmeta_header); - - /* Check rollback index. */ - io_ret = ops->read_rollback_index(ops, rollback_index_slot, - &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 slot.\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; - 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, descriptors[n], slot_data); - if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) { - ret = sub_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; - } - - 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, - chain_desc.rollback_index_slot, (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; - goto out; - } - } break; - - case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: { - const uint8_t* kernel_cmdline; - AvbKernelCmdlineDescriptor kernel_cmdline_desc; - - 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; - } - - 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: + ' ' + + '\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; - } - } - - ret = AVB_SLOT_VERIFY_RESULT_OK; - - /* So far, so good. Copy needed data to user, if requested. */ - if (is_main_vbmeta) { - if (slot_data->vbmeta_data != NULL) { - avb_free(slot_data->vbmeta_data); - } - /* 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. - */ - slot_data->vbmeta_size = sizeof(AvbVBMetaImageHeader) + - vbmeta_header.authentication_data_block_size + - vbmeta_header.auxiliary_data_block_size; - slot_data->vbmeta_data = vbmeta_buf; - vbmeta_buf = NULL; - } - - if (rollback_index_slot >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS) { - avb_errorv(full_partition_name, ": Invalid rollback_index_slot.\n", NULL); - ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; - goto out; - } - - slot_data->rollback_indexes[rollback_index_slot] = - vbmeta_header.rollback_index; - - if (out_algorithm_type != NULL) { - *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type; - } - -out: - if (vbmeta_buf != NULL) { - avb_free(vbmeta_buf); - } - if (descriptors != NULL) { - avb_free(descriptors); - } - return ret; -} - -#define NUM_GUIDS 2 - -/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with - * values. Returns NULL on OOM, otherwise the cmdline with values - * replaced. - */ -static char* sub_cmdline(AvbOps* ops, const char* cmdline, - const char* ab_suffix) { - const char* part_name_str[NUM_GUIDS] = {"system", "boot"}; - const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)", - "$(ANDROID_BOOT_PARTUUID)"}; - char* ret = NULL; - AvbIOResult io_ret; - - /* Replace unique partition GUIDs */ - for (size_t n = 0; n < NUM_GUIDS; n++) { - char part_name[PART_NAME_MAX_SIZE]; - char guid_buf[37]; - char* new_ret; - - 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) { - new_ret = avb_replace(cmdline, replace_str[n], guid_buf); - } else { - new_ret = avb_replace(ret, replace_str[n], guid_buf); - } - if (new_ret == NULL) { - goto fail; - } - ret = new_ret; - } - - 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; -} - -static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data, - const char* key, uint64_t value) { - const int MAX_DIGITS = 32; - char rev_digits[MAX_DIGITS]; - char digits[MAX_DIGITS]; - size_t n, num_digits; - - for (num_digits = 0; num_digits < MAX_DIGITS - 1;) { - rev_digits[num_digits++] = (value % 10) + '0'; - value /= 10; - if (value == 0) { - break; - } - } - - for (n = 0; n < num_digits; n++) { - digits[n] = rev_digits[num_digits - 1 - n]; - } - digits[n] = '\0'; - - 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_slot_verify(AvbOps* ops, - const char* const* requested_partitions, - const char* ab_suffix, - AvbSlotVerifyData** out_data) { - AvbSlotVerifyResult ret; - AvbSlotVerifyData* slot_data = NULL; - AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE; - AvbIOResult io_ret; - - if (out_data != NULL) { - *out_data = NULL; - } - - slot_data = avb_calloc(sizeof(AvbSlotVerifyData)); - if (slot_data == 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, 0 /* rollback_index_slot */, - "vbmeta", avb_strlen("vbmeta"), NULL /* expected_public_key */, - 0 /* expected_public_key_length */, slot_data, &algorithm_type); - - /* If things check out, mangle the kernel command-line as needed. */ - if (ret == AVB_SLOT_VERIFY_RESULT_OK) { - /* 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; - } - - /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */ - if (slot_data->cmdline != NULL) { - char* new_cmdline = sub_cmdline(ops, slot_data->cmdline, ab_suffix); - if (new_cmdline == NULL) { - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; - goto fail; - } - avb_free(slot_data->cmdline); - slot_data->cmdline = new_cmdline; - } - - /* Add androidboot.slot_suffix, if applicable. */ - if (avb_strlen(ab_suffix) > 0) { - if (!cmdline_append_option(slot_data, "androidboot.slot_suffix", - ab_suffix)) { - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; - goto fail; - } - } - - /* Set androidboot.avb.device_state to "locked" or "unlocked". */ - bool is_device_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 fail; - } else if (io_ret != AVB_IO_RESULT_OK) { - avb_error("Error getting device state.\n"); - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; - goto fail; - } - if (!cmdline_append_option(slot_data, "androidboot.vbmeta.device_state", - is_device_unlocked ? "unlocked" : "locked")) { - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; - goto fail; - } - - /* 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; - avb_sha256_init(&ctx); - avb_sha256_update(&ctx, slot_data->vbmeta_data, slot_data->vbmeta_size); - if (!cmdline_append_option(slot_data, "androidboot.vbmeta.hash_alg", - "sha256") || - !cmdline_append_uint64_base10(slot_data, "androidboot.vbmeta.size", - slot_data->vbmeta_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 fail; - } - } break; - /* Explicit fallthrough. */ - case AVB_ALGORITHM_TYPE_SHA512_RSA2048: - case AVB_ALGORITHM_TYPE_SHA512_RSA4096: - case AVB_ALGORITHM_TYPE_SHA512_RSA8192: { - AvbSHA512Ctx ctx; - avb_sha512_init(&ctx); - avb_sha512_update(&ctx, slot_data->vbmeta_data, slot_data->vbmeta_size); - if (!cmdline_append_option(slot_data, "androidboot.vbmeta.hash_alg", - "sha512") || - !cmdline_append_uint64_base10(slot_data, "androidboot.vbmeta.size", - slot_data->vbmeta_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 fail; - } - } break; - case _AVB_ALGORITHM_NUM_TYPES: - avb_assert_not_reached(); - break; - } - - if (out_data != NULL) { - *out_data = slot_data; - } else { - avb_slot_verify_data_free(slot_data); - } - } - - 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->vbmeta_data != NULL) { - avb_free(data->vbmeta_data); - } - if (data->cmdline != NULL) { - avb_free(data->cmdline); - } - 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) { - 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; - /* Do not add a 'default:' case here because of -Wswitch. */ - } - - if (ret == NULL) { - avb_error("Unknown AvbSlotVerifyResult value.\n"); - ret = "(unknown)"; - } - - return ret; -} diff --git a/lib/libavb/avb_slot_verify.h b/lib/libavb/avb_slot_verify.h deleted file mode 100644 index 87a6798..0000000 --- a/lib/libavb/avb_slot_verify.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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 -} AvbSlotVerifyResult; - -/* Get a textual representation of |result|. */ -const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result); - -/* Maximum number of rollback index slots number supported. */ -#define AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS 4 - -/* AvbPartitionData contains data loaded from partitions when using - * avb_slot_verify(). The |partition_name| field contains the name of - * the partition, |data| points to the loaded data which is - * |data_size| bytes long. - * - * 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; -} AvbPartitionData; - -/* 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. - * - * 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. - * - * The verified vbmeta image in the 'vbmeta' partition of the slot is - * accessible from the |vbmeta_data| field and is of length - * |vbmeta_size| bytes. You can use this data with - * e.g. avb_descriptor_get_all(). - * - * Rollback indexes for the slot are stored in the |rollback_indexes| - * field. - * - * 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) and $(ANDROID_BOOT_PARTUUID) using the - * get_unique_guid_for_partition() operation in |AvbOps|. - * - * Additionally, the |cmdline| field will have the following kernel - * command-line options set: - * - * androidboot.avb.device_state: set to "locked" or "unlocked" - * depending on the result of the result of AvbOps's - * read_is_unlocked() function. - * - * androidboot.slot_suffix: If |ab_suffix| as passed into - * avb_slot_verify() is non-empty, this variable will be set to its - * value. - * - * androidboot.vbmeta.{hash_alg, size, digest}: Will be set to - * the digest of the vbmeta image. - * - * This struct may grow in the future without it being considered an - * ABI break. - */ -typedef struct { - char* ab_suffix; - uint8_t* vbmeta_data; - size_t vbmeta_size; - AvbPartitionData* loaded_partitions; - size_t num_loaded_partitions; - char* cmdline; - uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS]; -} 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 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|. - * - * Typically the |requested_partitions| array only contains a single - * item for the boot partition, 'boot'. - * - * Verification includes loading data from the 'vbmeta', all 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. - * - * 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. - */ -AvbSlotVerifyResult avb_slot_verify(AvbOps* ops, - const char* const* requested_partitions, - const char* ab_suffix, - AvbSlotVerifyData** out_data); - -#ifdef __cplusplus -} -#endif - -#endif /* AVB_SLOT_VERIFY_H_ */ diff --git a/lib/libavb/avb_sysdeps.h b/lib/libavb/avb_sysdeps.h deleted file mode 100644 index 7fe9d06..0000000 --- a/lib/libavb/avb_sysdeps.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 -#include -/* 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 word-alignment. - * - * Change this to match your architecture - must be a power of two. - */ -#define AVB_WORD_ALIGNMENT_SIZE 8 - -/* 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; - -#ifdef __cplusplus -} -#endif - -#endif /* AVB_SYSDEPS_H_ */ diff --git a/lib/libavb/avb_sysdeps_uboot.c b/lib/libavb/avb_sysdeps_uboot.c deleted file mode 100644 index be5c1d2..0000000 --- a/lib/libavb/avb_sysdeps_uboot.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 -#include -#include - -#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) { panic("avb_abort!\n"); } - -void avb_print(const char* message) { printf("%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*)) { - printf("%s", m); - } - va_end(ap); -} - -void* avb_malloc_(size_t size) { return malloc(size); } - -void avb_free(void* ptr) { free(ptr); } diff --git a/lib/libavb/avb_util.c b/lib/libavb/avb_util.c deleted file mode 100644 index 435e556..0000000 --- a/lib/libavb/avb_util.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * 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" - -uint32_t avb_be32toh(uint32_t in) { - uint8_t* d = (uint8_t*)∈ - 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*)∈ - 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 (ret == 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 (ret == 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; -} diff --git a/lib/libavb/avb_util.h b/lib/libavb/avb_util.h deleted file mode 100644 index d53be97..0000000 --- a/lib/libavb/avb_util.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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_word_aligned(addr) \ - avb_assert((((uintptr_t)addr) & (AVB_WORD_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_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": DEBUG: "); \ - avb_print(message); \ - } while (0) -#define avb_debugv(message, ...) \ - do { \ - avb_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": DEBUG: "); \ - avb_printv(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_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": ERROR: "); \ - avb_print(message); \ - } while (0) -#define avb_errorv(message, ...) \ - do { \ - avb_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": ERROR: "); \ - avb_printv(message, ##__VA_ARGS__); \ - } while (0) - -/* Prints out a message and calls avb_abort(). - */ -#define avb_fatal(message) \ - do { \ - avb_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": FATAL: "); \ - avb_print(message); \ - avb_abort(); \ - } while (0) -#define avb_fatalv(message, ...) \ - do { \ - avb_print(__FILE__ ":" AVB_TO_STRING(__LINE__) ": FATAL: "); \ - avb_printv(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; - -/* 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); - -#ifdef __cplusplus -} -#endif - -#endif /* AVB_UTIL_H_ */ diff --git a/lib/libavb/avb_vbmeta_image.c b/lib/libavb/avb_vbmeta_image.c deleted file mode 100644 index 23607ed..0000000 --- a/lib/libavb/avb_vbmeta_image.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * 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_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}; - -typedef struct { - const uint8_t* padding; - size_t padding_len; - size_t hash_len; -} AvbAlgorithmData; - -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}, -}; - -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; - 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 the major version - * is not supported. - */ - if (h.header_version_major > AVB_MAJOR_VERSION) { - avb_error("No support for given major version.\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 algorithm field is supported. */ - if (h.algorithm_type >= _AVB_ALGORITHM_NUM_TYPES) { - avb_error("Invalid or unknown algorithm.\n"); - goto out; - } - algorithm = &algorithm_data[h.algorithm_type]; - - /* 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; - } - - /* 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 (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->header_version_major = avb_be32toh(dest->header_version_major); - dest->header_version_minor = avb_be32toh(dest->header_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->descriptors_offset = avb_be64toh(dest->descriptors_offset); - dest->descriptors_size = avb_be64toh(dest->descriptors_size); - - dest->rollback_index = avb_be64toh(dest->rollback_index); -} diff --git a/lib/libavb/avb_vbmeta_image.h b/lib/libavb/avb_vbmeta_image.h deleted file mode 100644 index 25d3689..0000000 --- a/lib/libavb/avb_vbmeta_image.h +++ /dev/null @@ -1,240 +0,0 @@ -/* - * 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 - -/* The current MAJOR and MINOR versions used - keep in sync with avbtool. */ -#define AVB_MAJOR_VERSION 1 -#define AVB_MINOR_VERSION 0 - -/* 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 |header_version_major| and - * |header_version_minor| fields. Compatibility is guaranteed only - * within the same major version. - * - * 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 the vbmeta image header. */ - uint32_t header_version_major; - /* 8: The minor version of the vbmeta image header. */ - uint32_t header_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 descriptor data. */ - uint64_t descriptors_offset; - /* 88: Length of descriptor data. */ - uint64_t descriptors_size; - - /* 96: The rollback index which can be used to prevent rollback to - * older versions. - */ - uint64_t rollback_index; - - /* 104: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE - * bytes. This must be set to zeroes. - */ - uint8_t reserved[152]; -} 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_VERIFY_INVALID_VBMETA_HEADER is returned if the header of - * the vbmeta image is invalid, for example, invalid magic or - * inconsistent data. - * - * AVB_VERIFY_HASH_MISMATCH is returned if the hash stored in the - * "Authentication data" block does not match the calculated hash. - * - * AVB_VERIFY_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_HASH_MISMATCH, - AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH, -} AvbVBMetaVerifyResult; - -/* 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. - * - * 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/libavb/fsl/Makefile b/lib/libavb/fsl/Makefile deleted file mode 100644 index 362c917..0000000 --- a/lib/libavb/fsl/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -ccflags-$(CONFIG_AVB_DEBUG) += -DAVB_DEBUG -obj-y += fsl_avb.o -obj-y += fsl_avbkey.o -obj-y += fsl_bootctl.o diff --git a/lib/libavb/fsl/debug.h b/lib/libavb/fsl/debug.h deleted file mode 100644 index c1165ec..0000000 --- a/lib/libavb/fsl/debug.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __AVB_DEBUG_H__ -#define __AVB_DEBUG_H__ - -#ifdef AVB_VVDEBUG -#define AVB_VDEBUG -#define VVDEBUG(format, ...) printf(" %s: "format, __func__, ##__VA_ARGS__) -#else -#define VVDEBUG(format, ...) -#endif - -#ifdef AVB_VDEBUG -#define AVB_DEBUG -#define VDEBUG(format, ...) printf(" %s: "format, __func__, ##__VA_ARGS__) -#else -#define VDEBUG(format, ...) -#endif - -#ifdef AVB_DEBUG -#define DEBUGAVB(format, ...) printf(" %s: "format, __func__, ##__VA_ARGS__) -#else -#define DEBUGAVB(format, ...) -#endif - -#define ERR(format, ...) printf("%s: "format, __func__, ##__VA_ARGS__) - -#define HEXDUMP_COLS 16 -#define HEXDUMP_WIDTH 1 - -#endif diff --git a/lib/libavb/fsl/fsl_avb.c b/lib/libavb/fsl/fsl_avb.c deleted file mode 100644 index 23d19f3..0000000 --- a/lib/libavb/fsl/fsl_avb.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * Copyright (C) 2016 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#include -#include -#include "../../../drivers/usb/gadget/fastboot_lock_unlock.h" - -#include "fsl_avb.h" -#include "fsl_avbkey.h" -#include "debug.h" - -#define FSL_AVB_DEV "mmc" - -#define ALIGN_BYTES 64 /*mmc block read/write need 64 bytes aligned */ - -struct margin_pos { - /* which blk the read/write starts */ - lbaint_t blk_start; - /* which blk the read/write ends */ - lbaint_t blk_end; - /* start position inside the start blk */ - unsigned long start; - /* end position inside the end blk */ - unsigned long end; - /* how many blks can be read/write one time */ - unsigned long multi; -}; -typedef struct margin_pos margin_pos_t; - - -static block_dev_desc_t *fs_dev_desc = NULL; -static block_dev_desc_t *get_mmc_desc(void) { - int dev_no = mmc_get_env_devno(); - return get_dev(FSL_AVB_DEV, dev_no); -} - -/* get margin_pos struct from offset [to the partition start/end] and num_bytes to read/write */ -static int32_t get_margin_pos(lbaint_t part_start, lbaint_t part_end, unsigned long blksz, - margin_pos_t *margin, int64_t offset, size_t num_bytes, bool allow_partial) { - long off; - if (offset < 0) { - margin->blk_start = (offset + 1) / blksz + part_end; - margin->start = (off = offset % blksz) == 0 ? 0 : blksz + off; // offset == -1 means the last byte?, or start need -1 - if (offset + num_bytes - 1 >= 0) { - if (!allow_partial) - return -1; - margin->blk_end = part_end; - margin->end = blksz - 1; - } else { - margin->blk_end = (num_bytes + offset) / blksz + part_end; // which blk the last byte is in - margin->end = (off = (num_bytes + offset - 1) % blksz) == 0 ? - 0 : blksz + off; // last byte - } - } else { - margin->blk_start = offset / blksz + part_start; - margin->start = offset % blksz; - margin->blk_end = (offset + num_bytes - 1) / blksz + part_start ; - margin->end = (offset + num_bytes - 1) % blksz; - if (margin->blk_end > part_end) { - if (!allow_partial) - return -1; - margin->blk_end = part_end; - margin->end = blksz - 1; - } - } - VDEBUG("bs=%ld, be=%ld, s=%ld, e=%ld\n", - margin->blk_start, margin->blk_end, margin->start, margin->end); - - if (margin->blk_start > part_end || margin->blk_start < part_start) - return -1; - long multi = margin->blk_end - margin->blk_start - 1 + - (margin->start == 0) + (margin->end == blksz -1); - margin->multi = multi > 0 ? multi : 0; - VDEBUG("bm=%ld\n", margin->multi); - return 0; -} - /* 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 fsl_read_from_partition(AvbOps* ops, const char* partition, - int64_t offset, size_t num_bytes, - void* buffer, size_t* out_num_read) -{ - struct fastboot_ptentry *pte; - unsigned char *bdata; - unsigned char *out_buf = (unsigned char *)buffer; - unsigned long blksz; - unsigned long s, cnt; - size_t num_read = 0; - lbaint_t part_start, part_end, bs, be; - margin_pos_t margin; - - AvbIOResult ret; - - DEBUGAVB("[%s]: offset=%ld, num_bytes=%zu\n", partition, (long)offset, num_bytes); - - assert(buffer != NULL && out_num_read != NULL); - - if (!fs_dev_desc && (fs_dev_desc = get_mmc_desc()) == NULL) { - ERR("mmc device not found\n"); - return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; - } - - pte = fastboot_flash_find_ptn(partition); - if (!pte) { - ERR("no %s partition\n", partition); - return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; - } - - blksz = fs_dev_desc->blksz; - part_start = pte->start; - part_end = pte->start + pte->length - 1; - VDEBUG("blksz: %ld, part_end: %ld, part_start: %ld:\n", - blksz, part_end, part_start); - - if(get_margin_pos(part_start, part_end, blksz, - &margin, offset, num_bytes, true)) - return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; - - bs = margin.blk_start; - be = margin.blk_end; - s = margin.start; - - // alloc a blksz mem - bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz); - if (bdata == NULL) - return AVB_IO_RESULT_ERROR_OOM; - - // one block a time - while (bs <= be) { - memset(bdata, 0, blksz); - if (!fs_dev_desc->block_read(fs_dev_desc->dev, bs, 1, bdata)) { - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - cnt = blksz - s; - if (num_read + cnt > num_bytes) - cnt = num_bytes - num_read; - VDEBUG("cur: bs=%ld, start=%ld, cnt=%ld bdata=0x%08x\n", - bs, s, cnt, bdata); - memcpy(out_buf, bdata + s, cnt); - bs++; - num_read += cnt; - out_buf += cnt; - s = 0; - } - *out_num_read = num_read; - ret = AVB_IO_RESULT_OK; -#ifdef AVB_VVDEBUG - printf("\nnum_read=%zu", num_read); - printf("\n----dump---\n"); - print_buffer(0, buffer, HEXDUMP_WIDTH, num_read, 0); - printf("--- end ---\n"); -#endif - -fail: - free(bdata); - return ret; -} - -/* multi block read version of read_from_partition */ - AvbIOResult fsl_read_from_partition_multi(AvbOps* ops, const char* partition, - int64_t offset, size_t num_bytes, - void* buffer, size_t* out_num_read) -{ - struct fastboot_ptentry *pte; - unsigned char *bdata; - unsigned char *out_buf = (unsigned char *)buffer; - unsigned char *dst, *dst64 = NULL; - unsigned long blksz; - unsigned long s, cnt; - size_t num_read = 0; - lbaint_t part_start, part_end, bs, be, bm, blk_num; - margin_pos_t margin; - - AvbIOResult ret; - - DEBUGAVB("[%s]: offset=%ld, num_bytes=%zu\n", partition, (long)offset, num_bytes); - - assert(buffer != NULL && out_num_read != NULL); - - if (!fs_dev_desc && (fs_dev_desc = get_mmc_desc()) == NULL) { - ERR("mmc device not found\n"); - return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; - } - - pte = fastboot_flash_find_ptn(partition); - if (!pte) { - ERR("no %s partition\n", partition); - return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; - } - - blksz = fs_dev_desc->blksz; - part_start = pte->start; - part_end = pte->start + pte->length - 1; - VDEBUG("blksz: %ld, part_end: %ld, part_start: %ld:\n", - blksz, part_end, part_start); - - if(get_margin_pos(part_start, part_end, blksz, - &margin, offset, num_bytes, true)) - return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; - - bs = margin.blk_start; - be = margin.blk_end; - s = margin.start; - bm = margin.multi; - - // alloc a blksz mem - bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz); - if (bdata == NULL) - return AVB_IO_RESULT_ERROR_OOM; - - // support multi blk read - while (bs <= be) { - if (!s && bm > 1) { - dst = out_buf; - dst64 = PTR_ALIGN(out_buf, 64); //for mmc blk read alignment - VDEBUG("cur: dst=0x%08x, dst64=0x%08x\n", dst, dst64); - if (dst64 != dst) { - dst = dst64; - bm--; - } - blk_num = bm; - cnt = bm * blksz; - bm = 0; //no more multi blk - } else { - blk_num = 1; - cnt = blksz - s; - if (num_read + cnt > num_bytes) - cnt = num_bytes - num_read; - dst = bdata; - } - VDEBUG("cur: bs=%ld, num=%ld, start=%ld, cnt=%ld dst=0x%08x\n", - bs, blk_num, s, cnt, dst); - if (!fs_dev_desc->block_read(fs_dev_desc->dev, bs, blk_num, dst)) { - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - - if (dst == bdata) - memcpy(out_buf, bdata + s, cnt); - else if (dst == dst64) - memcpy(out_buf, dst, cnt); //internal copy - - s = 0; - bs += blk_num; - num_read += cnt; - out_buf += cnt; -#ifdef AVB_VVDEBUG - printf("\nnum_read=%ld", cnt); - printf("\n----dump---\n"); - print_buffer(0, buffer, HEXDUMP_WIDTH, cnt, 0); - printf("--- end ---\n"); -#endif - } - *out_num_read = num_read; - ret = AVB_IO_RESULT_OK; -#ifdef AVB_VVDEBUG - printf("\nnum_read=%zu", num_read); - printf("\n----dump---\n"); - print_buffer(0, buffer, HEXDUMP_WIDTH, num_read, 0); - printf("--- end ---\n"); -#endif - -fail: - free(bdata); - return ret; -} - - /* 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 fsl_write_to_partition(AvbOps* ops, const char* partition, - int64_t offset, size_t num_bytes, - const void* buffer) -{ - struct fastboot_ptentry *pte; - unsigned char *bdata; - unsigned char *in_buf = (unsigned char *)buffer; - unsigned long blksz; - unsigned long s, cnt; - size_t num_write = 0; - lbaint_t part_start, part_end, bs; - margin_pos_t margin; - - AvbIOResult ret; - - DEBUGAVB("[%s]: offset=%ld, num_bytes=%zu\n", partition, (long)offset, num_bytes); - - assert(buffer != NULL); - - if (!fs_dev_desc && (fs_dev_desc = get_mmc_desc()) == NULL) { - ERR("mmc device not found\n"); - return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; - } - - pte = fastboot_flash_find_ptn(partition); - if (!pte) { - ERR("no %s partition\n", partition); - return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; - } - - blksz = fs_dev_desc->blksz; - part_start = pte->start; - part_end = pte->start + pte->length - 1; - VDEBUG("blksz: %ld, part_end: %ld, part_start: %ld:\n", - blksz, part_end, part_start); - - if(get_margin_pos(part_start, part_end, blksz, - &margin, offset, num_bytes, false)) - return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; - - bs = margin.blk_start; - s = margin.start; - - // alloc a blksz mem - bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz); - if (bdata == NULL) - return AVB_IO_RESULT_ERROR_OOM; - - while (num_write < num_bytes) { - memset(bdata, 0, blksz); - cnt = blksz - s; - if (num_write + cnt > num_bytes) - cnt = num_bytes - num_write; - if (!s || cnt != blksz) { //read blk first - if (!fs_dev_desc->block_read(fs_dev_desc->dev, bs, 1, bdata)) { - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - } - memcpy(bdata + s, in_buf, cnt); //change data - VDEBUG("cur: bs=%ld, start=%ld, cnt=%ld bdata=0x%08x\n", - bs, s, cnt, bdata); - if (!fs_dev_desc->block_write(fs_dev_desc->dev, bs, 1, bdata)) { - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - bs++; - num_write += cnt; - in_buf += cnt; - if (s != 0) - s = 0; - } - ret = AVB_IO_RESULT_OK; - -fail: - free(bdata); - return ret; -} - -/* 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 fsl_read_ab_metadata(AvbOps* ops, struct AvbABData* data) -{ - return avb_ab_data_read(ops, 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 fsl_write_ab_metadata(AvbOps* ops, const struct AvbABData* data) -{ - return avb_ab_data_write(ops, data); -} - -/* 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'. - * - * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set - - * true if trusted or false if untrusted. - */ -AvbIOResult fsl_validate_vbmeta_public_key(AvbOps* ops, - const uint8_t* public_key_data, - size_t public_key_length, - bool* out_is_trusted) { - kblb_hdr_t hdr; - kblb_tag_t *pubk; - size_t num_read, blob_size; - uint8_t *extract_key = NULL; - uint8_t *read_keyblb = NULL; - AvbIOResult ret; - - assert(ops != NULL && out_is_trusted != NULL); - *out_is_trusted = false; - /* read the kblb header */ - if (ops->read_from_partition(ops, "avbkey", 0, sizeof(hdr), - (void *)&hdr, &num_read) != AVB_IO_RESULT_OK) { - ERR("read partition avbkey error\n"); - return AVB_IO_RESULT_ERROR_IO; - } - - if (num_read != sizeof(hdr) || - memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) { - ERR("avbkey partition magic not match\n"); - return AVB_IO_RESULT_ERROR_IO; - } - - pubk = &hdr.pubk_tag; - if (pubk->len != public_key_length){ - ERR("avbkey len not match\n"); - return AVB_IO_RESULT_ERROR_IO; - } - blob_size = pubk->len + AVB_CAAM_PAD; - extract_key = malloc(pubk->len); - read_keyblb = malloc(blob_size); - if (extract_key == NULL || read_keyblb == NULL) { - ret = AVB_IO_RESULT_ERROR_OOM; - goto fail; - } - - /* read public keyblob */ - if (ops->read_from_partition(ops, "avbkey", pubk->offset, blob_size, - (void *)read_keyblb, &num_read) != AVB_IO_RESULT_OK) { - ERR("read public keyblob error\n"); - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - if (num_read != blob_size) { - ERR("avbkey partition magic not match\n"); - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - - /* caam decrypt */ - caam_open(); - if (caam_decap_blob((uint32_t)extract_key, (uint32_t)read_keyblb, pubk->len)) { - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - /* match given public key */ - if (memcmp(extract_key, public_key_data, public_key_length)) { - ret = AVB_IO_RESULT_OK; - goto fail; - } -#ifdef AVB_VDEBUG - printf("\n----key dump: stored---\n"); - print_buffer(0, extract_key, HEXDUMP_WIDTH, pubk->len, 0); - printf("\n----key dump: vbmeta---\n"); - print_buffer(0, public_key_data, HEXDUMP_WIDTH, public_key_length, 0); - printf("--- end ---\n"); -#endif - - *out_is_trusted = true; - ret = AVB_IO_RESULT_OK; -fail: - if (extract_key != NULL) - free(extract_key); - if (read_keyblb != NULL) - free(read_keyblb); - return ret; -} - -/* Gets the rollback index corresponding to the slot given by - * |rollback_index_slot|. 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 slots (say, - * one or four) so may error out if |rollback_index_slot| exceeds - * this number. - */ -AvbIOResult fsl_read_rollback_index(AvbOps* ops, size_t rollback_index_slot, - uint64_t* out_rollback_index) { - kblb_hdr_t hdr; - kblb_tag_t *rbk; - size_t num_read, blob_size; - uint64_t *extract_idx = NULL; - uint64_t *read_keyblb = NULL; - AvbIOResult ret; - - assert(ops != NULL && out_rollback_index != NULL); - *out_rollback_index = ~0; - - DEBUGAVB("read rollback slot: %zu\n", rollback_index_slot); - - if (rollback_index_slot >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS) - return AVB_IO_RESULT_ERROR_IO; - - /* read the kblb header */ - if (ops->read_from_partition(ops, "avbkey", 0, sizeof(hdr), - (void *)&hdr, &num_read) != AVB_IO_RESULT_OK) { - ERR("read partition avbkey error\n"); - return AVB_IO_RESULT_ERROR_IO; - } - - if (num_read != sizeof(hdr) || - memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) { - ERR("avbkey partition magic not match\n"); - return AVB_IO_RESULT_ERROR_IO; - } - - rbk = &hdr.rbk_tags[rollback_index_slot]; - blob_size = rbk->len + AVB_CAAM_PAD; - extract_idx = malloc(rbk->len); - read_keyblb = malloc(blob_size); - if (extract_idx == NULL || read_keyblb == NULL) { - ret = AVB_IO_RESULT_ERROR_OOM; - goto fail; - } - - /* read rollback_index keyblob */ - if (ops->read_from_partition(ops, "avbkey", rbk->offset, blob_size, - (void *)read_keyblb, &num_read) != AVB_IO_RESULT_OK) { - ERR("read public keyblob error\n"); - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - if (num_read != blob_size) { - ERR("avbkey read len not match\n"); - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - - /* caam decrypt */ - caam_open(); - if (caam_decap_blob((uint32_t)extract_idx, (uint32_t)read_keyblb, rbk->len)) { - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } -#ifdef AVB_VVDEBUG - printf("\n----idx dump: ---\n"); - print_buffer(0, extract_idx, HEXDUMP_WIDTH, rbk->len, 0); - printf("--- end ---\n"); -#endif - - *out_rollback_index = *extract_idx; - DEBUGAVB("rollback_index = %" PRIu64 "\n", *out_rollback_index); - ret = AVB_IO_RESULT_OK; -fail: - if (extract_idx != NULL) - free(extract_idx); - if (read_keyblb != NULL) - free(read_keyblb); - return ret; -} - -/* Sets the rollback index corresponding to the slot given by - * |rollback_index_slot| 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 slots (say, - * one or four) so may error out if |rollback_index_slot| exceeds - * this number. - */ -AvbIOResult fsl_write_rollback_index(AvbOps* ops, size_t rollback_index_slot, - uint64_t rollback_index) { - kblb_hdr_t hdr; - kblb_tag_t *rbk; - size_t num_read, blob_size; - uint64_t *plain_idx = NULL; - uint64_t *write_keyblb = NULL; - AvbIOResult ret; - - DEBUGAVB("write to rollback slot: (%zu, %" PRIu64 ")\n", - rollback_index_slot, rollback_index); - - assert(ops != NULL); - - if (rollback_index_slot >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS) - return AVB_IO_RESULT_ERROR_IO; - - /* read the kblb header */ - if (ops->read_from_partition(ops, "avbkey", 0, sizeof(hdr), - (void *)&hdr, &num_read) != AVB_IO_RESULT_OK) { - ERR("read partition avbkey error\n"); - return AVB_IO_RESULT_ERROR_IO; - } - - if (num_read != sizeof(hdr) || - memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) { - ERR("avbkey partition magic not match\n"); - return AVB_IO_RESULT_ERROR_IO; - } - - rbk = &hdr.rbk_tags[rollback_index_slot]; - blob_size = rbk->len + AVB_CAAM_PAD; - plain_idx = malloc(rbk->len); - write_keyblb = malloc(blob_size); - if (plain_idx == NULL || write_keyblb == NULL) { - ret = AVB_IO_RESULT_ERROR_OOM; - goto fail; - } - memset(plain_idx, 0, rbk->len); - *plain_idx = rollback_index; - - /* caam encrypt */ - caam_open(); - if (caam_gen_blob((uint32_t)plain_idx, (uint32_t)write_keyblb, rbk->len)) { - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - - /* write rollback_index keyblob */ - if (ops->write_to_partition(ops, "avbkey", rbk->offset, blob_size, - (void *)write_keyblb) != AVB_IO_RESULT_OK) { - ERR("read public keyblob error\n"); - ret = AVB_IO_RESULT_ERROR_IO; - goto fail; - } - ret = AVB_IO_RESULT_OK; -fail: - if (plain_idx != NULL) - free(plain_idx); - if (write_keyblb != NULL) - free(write_keyblb); - return ret; -} - -/* 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 fsl_read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked) { - - FbLockState status; - - assert(out_is_unlocked != NULL); - *out_is_unlocked = false; - - status = fastboot_get_lock_stat(); - if (status != FASTBOOT_LOCK_ERROR) { - if (status == FASTBOOT_LOCK) - *out_is_unlocked = false; - else - *out_is_unlocked = true; - } else - return AVB_IO_RESULT_ERROR_IO; - - DEBUGAVB("is_unlocked=%d\n", *out_is_unlocked); - return AVB_IO_RESULT_OK; -} - -/* 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 fsl_get_unique_guid_for_partition(AvbOps* ops, - const char* partition, - char* guid_buf, - size_t guid_buf_size) { - assert(guid_buf != NULL); -#ifdef CONFIG_PARTITION_UUIDS - struct fastboot_ptentry *pte; - pte = fastboot_flash_find_ptn(partition); - if (!pte) { - ERR("no %s partition\n", partition); - return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; - } - strncpy(guid_buf, (const char *)pte->uuid, guid_buf_size); - guid_buf[guid_buf_size - 1] = '\0'; - DEBUGAVB("[%s]: GUID=%s\n", partition, guid_buf); - return AVB_IO_RESULT_OK; -#else - return AVB_IO_RESULT_ERROR_IO; -#endif -} diff --git a/lib/libavb/fsl/fsl_avb.h b/lib/libavb/fsl/fsl_avb.h deleted file mode 100644 index 180186a..0000000 --- a/lib/libavb/fsl/fsl_avb.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2016 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __FSL_AVB_H__ -#define __FSL_AVB_H__ - -#include -/* 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 fsl_read_from_partition(AvbOps* ops, const char* partition, - int64_t offset, size_t num_bytes, - void* buffer, size_t* out_num_read); - -/* multi block read version - * */ -AvbIOResult fsl_read_from_partition_multi(AvbOps* ops, const char* partition, - int64_t offset, size_t num_bytes, - void* buffer, size_t* out_num_read); - -/* 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 fsl_write_to_partition(AvbOps* ops, const char* partition, - int64_t offset, size_t num_bytes, - const void* buffer); - -/* 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 fsl_read_ab_metadata(AvbOps* 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 fsl_write_ab_metadata(AvbOps* ops, const struct AvbABData* data); - -/* 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'. - * - * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set - - * true if trusted or false if untrusted. - */ -AvbIOResult fsl_validate_vbmeta_public_key(AvbOps* ops, - const uint8_t* public_key_data, - size_t public_key_length, - bool* out_is_trusted); - -/* Gets the rollback index corresponding to the slot given by - * |rollback_index_slot|. 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 slots (say, - * one or four) so may error out if |rollback_index_slot| exceeds - * this number. - */ -AvbIOResult fsl_read_rollback_index(AvbOps* ops, size_t rollback_index_slot, - uint64_t* out_rollback_index); - -/* Sets the rollback index corresponding to the slot given by - * |rollback_index_slot| 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 slots (say, - * one or four) so may error out if |rollback_index_slot| exceeds - * this number. - */ -AvbIOResult fsl_write_rollback_index(AvbOps* ops, size_t rollback_index_slot, - 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 fsl_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 fsl_get_unique_guid_for_partition(AvbOps* ops, - const char* partition, - char* guid_buf, - size_t guid_buf_size); - -/* check if the fastboot getvar cmd is for query [avb] bootctl's slot var - * cmd is the fastboot getvar's cmd in - * return true if it is a bootctl related cmd, false if it's not. - * */ -bool is_slotvar_avb(char *cmd); - -/* return 0 for the first slot - * return 1 for the second slot - * return -1 for not supported slot - * */ -int slotidx_from_suffix(char *suffix); - -/* return fastboot's getvar cmd response - * cmd is the fastboot getvar's cmd in - * if return 0, buffer is bootctl's slot var out - * if return -1, buffer is error string - * */ -int get_slotvar_avb(AvbOps *ops, char *cmd, char *buffer, size_t size); - -/* reset rollback_index part in avbkey partition - * used in the switch from LOCK to UNLOCK - * return 0 if success, non 0 if fail. - * */ -int rbkidx_erase(const char * kblb_part); - -/* init the avbkey partition, include the header/public key/rollback index - * for public key/rollback index part, use caam to do encrypt - * return 0 if success, non 0 if fail. - * */ -int avbkeyblb_init(uint8_t *plainkey, uint32_t keylen, const char *kblb_part /*"avbkey"*/); - -/* read a/b metadata to get curr slot - * return slot suffix '_a'/'_b' or NULL */ -char *select_slot(AvbOps *ops); - -#endif /* __FSL_AVB_H__ */ diff --git a/lib/libavb/fsl/fsl_avbkey.c b/lib/libavb/fsl/fsl_avbkey.c deleted file mode 100644 index db0f068..0000000 --- a/lib/libavb/fsl/fsl_avbkey.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2016 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -#include "fsl_avb.h" -#include "fsl_avbkey.h" -#include "debug.h" - -/* bank 15, GP7, 0xc80[31:0] */ -#define AVBKEY_FUSE_BANK 15 -#define AVBKEY_FUSE_WORD 0 -#define AVBKEY_FUSE_MASK 0xffffffff -#define AVBKEY_FUSE_INIT 0x4156424b /* 'avbk' */ - - -static int encrypt_write(uint8_t *plain, uint32_t len, const char * part, size_t offset) { - - uint8_t *blb; - uint32_t blbsize; - int ret; - - blbsize = len + AVB_CAAM_PAD; - blb = (uint8_t *)malloc(blbsize); - if (blb == NULL) - return -1; - - caam_open(); - if (caam_gen_blob((uint32_t)plain, (uint32_t)blb, len)) { - ret = -1; - goto fail; - } - - if (fsl_write_to_partition(NULL, part, offset, blbsize, - (void *)blb) != AVB_IO_RESULT_OK) { - ret = -1; - goto fail; - } - ret = 0; - -fail: - free(blb); - return ret; -} - -int rbkidx_erase(const char * kblb_part) { - int i; - size_t num_read; - kblb_hdr_t hdr; - kblb_tag_t *tag; - /* read the kblb header */ - if (fsl_read_from_partition(NULL, kblb_part, 0, sizeof(hdr), - (void *)&hdr, &num_read) != AVB_IO_RESULT_OK) { - ERR("read partition avbkey error\n"); - return -1; - } - if (num_read != sizeof(hdr) || - memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) { - ERR("avbkey partition magic not match\n"); - return -1; - } - /* reset rollback index */ - uint32_t offset = AVB_RBIDX_START; - uint32_t rbidx_len = AVB_RBIDX_LEN; - uint8_t *rbidx = malloc(rbidx_len); - if (rbidx == NULL) - return -1; - memset(rbidx, 0, rbidx_len); - *(uint64_t *)rbidx = AVB_RBIDX_INITVAL; - for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; i++) { - tag = &hdr.rbk_tags[i]; - tag->flag = AVB_RBIDX_FLAG; - tag->offset = offset; - tag->len = rbidx_len; - /* caam encrypt and write */ - if (encrypt_write(rbidx, tag->len, kblb_part, tag->offset) != 0) { - ERR("write rollback index keyblob error\n"); - free(rbidx); - return -1; - } - offset += AVB_RBIDX_ALIGN; - } - free(rbidx); - /* write hdr */ - if (fsl_write_to_partition(NULL, kblb_part, 0, - sizeof(hdr), (void *)&hdr) != AVB_IO_RESULT_OK) { - ERR("write avbkey hdr error\n"); - return -1; - } - return 0; -} - -int avbkeyblb_init(uint8_t *plainkey, uint32_t keylen, const char * kblb_part) { - int i; - kblb_hdr_t hdr; - kblb_tag_t *tag; - uint32_t fuse_val; - - /* read fuse to check enable init */ - /* fuse_read read the shadow reg of fuse - * use fuse_sense to real read fuse */ -#ifdef CONFIG_AVB_FUSE - if (fuse_sense(AVBKEY_FUSE_BANK, AVBKEY_FUSE_WORD, &fuse_val)) { -#else - if (fuse_read(AVBKEY_FUSE_BANK, AVBKEY_FUSE_WORD, &fuse_val)) { -#endif - ERR("read fuse error\n"); - return -1; - } - if ((fuse_val & AVBKEY_FUSE_MASK) == AVBKEY_FUSE_INIT) { - ERR("key already init\n"); - return -1; - } - fuse_val = AVBKEY_FUSE_MASK & AVBKEY_FUSE_INIT; - - /* write fuse to prevent init again */ - /* fuse_override write the shadow reg of fuse - * use fuse_prog to PERMANENT write fuse */ -#ifdef CONFIG_AVB_FUSE - if (fuse_prog(AVBKEY_FUSE_BANK, AVBKEY_FUSE_WORD, fuse_val)) { -#else - if (fuse_override(AVBKEY_FUSE_BANK, AVBKEY_FUSE_WORD, fuse_val)) { -#endif - ERR("write fuse error\n"); - return -1; - } - - assert(plainkey != NULL); - - /* check overflow */ - if (keylen > AVB_RBIDX_START - AVB_PUBKY_OFFSET) { - ERR("key len overflow\n"); - return -1; - } - - /* init pubkey */ - tag = &hdr.pubk_tag; - tag->flag = AVB_PUBKY_FLAG; - tag->offset = AVB_PUBKY_OFFSET; - tag->len = keylen; - /* caam encrypt and write */ - if (encrypt_write(plainkey, tag->len, kblb_part, tag->offset) != 0) { - ERR("write pubkey keyblob error\n"); - return -1; - } - - /* init rollback index */ - uint32_t offset = AVB_RBIDX_START; - uint32_t rbidx_len = AVB_RBIDX_LEN; - uint8_t *rbidx = malloc(rbidx_len); - if (rbidx == NULL) - return -1; - memset(rbidx, 0, rbidx_len); - *(uint64_t *)rbidx = AVB_RBIDX_INITVAL; - for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS; i++) { - tag = &hdr.rbk_tags[i]; - tag->flag = AVB_RBIDX_FLAG; - tag->offset = offset; - tag->len = rbidx_len; - /* caam encrypt and write */ - if (encrypt_write(rbidx, tag->len, kblb_part, tag->offset) != 0) { - ERR("write rollback index keyblob error\n"); - free(rbidx); - return -1; - } - offset += AVB_RBIDX_ALIGN; - } - free(rbidx); - - /* init hdr */ - memcpy(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN); - if (fsl_write_to_partition(NULL, kblb_part, 0, - sizeof(hdr), (void *)&hdr) != AVB_IO_RESULT_OK) { - ERR("write avbkey hdr error\n"); - return -1; - } - return 0; -} diff --git a/lib/libavb/fsl/fsl_avbkey.h b/lib/libavb/fsl/fsl_avbkey.h deleted file mode 100644 index 988158f..0000000 --- a/lib/libavb/fsl/fsl_avbkey.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2016 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __FSL_AVBKEY_H__ -#define __FSL_AVBKEY_H__ - - -#define AVB_CAAM_PAD 48 - -#define AVB_PUBKY_FLAG 0xABAB -#define AVB_PUBKY_OFFSET 0x1000 - -#define AVB_RBIDX_FLAG 0xCDCD -#define AVB_RBIDX_START 0x2000 -#define AVB_RBIDX_ALIGN 0x1000 -#define AVB_RBIDX_LEN 0x1D0 -#define AVB_RBIDX_INITVAL 0 - - -#define AVB_KBLB_MAGIC "\0KBLB!" -#define AVB_KBLB_MAGIC_LEN 6 - - -struct kblb_tag { - uint32_t flag; - uint32_t offset; - uint32_t len; -}; -typedef struct kblb_tag kblb_tag_t; - -struct kblb_hdr { - /* avbkey partition magic */ - char magic[AVB_KBLB_MAGIC_LEN]; - /* public key keyblb tag */ - kblb_tag_t pubk_tag; - /* rollback index keyblb tag */ - kblb_tag_t rbk_tags[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_SLOTS]; -}; -typedef struct kblb_hdr kblb_hdr_t; - -#endif diff --git a/lib/libavb/fsl/fsl_bootctl.c b/lib/libavb/fsl/fsl_bootctl.c deleted file mode 100644 index 23625a1..0000000 --- a/lib/libavb/fsl/fsl_bootctl.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2016 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#include "fsl_avb.h" - -/* as libavb's bootctl doesn't have the get_var support - * we add the getvar support on our side ...*/ -#define SLOT_NUM 2 -static char *slot_suffix[SLOT_NUM] = {"_a", "_b"}; - -static int strcmp_l1(const char *s1, const char *s2) { - if (!s1 || !s2) - return -1; - return strncmp(s1, s2, strlen(s1)); -} - -static bool slot_is_bootable(AvbABSlotData* slot) { - return slot->priority > 0 && - (slot->successful_boot || (slot->tries_remaining > 0)); -} - -int slotidx_from_suffix(char *suffix) { - int slot = -1; - - if (!strcmp(suffix, "_a") || - !strcmp(suffix, "a")) - slot = 0; - else if (!strcmp(suffix, "_b") || - !strcmp(suffix, "b")) - slot = 1; - - return slot; -} - -bool is_slotvar_avb(char *cmd) { - - assert(cmd != NULL); - if (!strcmp_l1("has-slot:", cmd) || - !strcmp_l1("slot-successful:", cmd) || - !strcmp_l1("slot-count", cmd) || - !strcmp_l1("slot-suffixes", cmd) || - !strcmp_l1("current-slot", cmd) || - !strcmp_l1("slot-unbootable:", cmd) || - !strcmp_l1("slot-retry-count:", cmd)) - return true; - return false; -} - -static int get_curr_slot(AvbABData *ab_data) { - 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) - return 1; - else - return 0; - } else if (slot_is_bootable(&ab_data->slots[0])) - return 0; - else if (slot_is_bootable(&ab_data->slots[1])) - return 1; - else - return -1; -} - -int get_slotvar_avb(AvbOps *ops, char *cmd, char *buffer, size_t size) { - - AvbABData ab_data; - AvbABSlotData *slot_data; - int slot; - - assert(ops != NULL && cmd != NULL && buffer != NULL); - - char *str = cmd; - if (!strcmp_l1("has-slot:", cmd)) { - str += strlen("has-slot:"); - if (!strcmp(str, "system") || !strcmp(str, "boot")) - strlcpy(buffer, "yes", size); - else - strlcpy(buffer, "no", size); - return 0; - - } else if (!strcmp_l1("slot-suffixes", cmd)) { - strlcpy(buffer, "_a,_b", size); - return 0 ; - - } else if (!strcmp_l1("slot-count", cmd)) { - strlcpy(buffer, "2", size); - return 0 ; - } - - /* load ab meta */ - if (ops->read_ab_metadata == NULL || - ops->read_ab_metadata(ops, &ab_data) != AVB_IO_RESULT_OK) { - strlcpy(buffer, "ab data read error", size); - return -1 ; - } - - if (!strcmp_l1("current-slot", cmd)) { - int curr = get_curr_slot(&ab_data); - if (curr >= 0 && curr < SLOT_NUM) - strlcpy(buffer, slot_suffix[curr], size); - else { - strlcpy(buffer, "no bootable slot", size); - return -1; - } - - } else if (!strcmp_l1("slot-successful:", cmd)) { - str += strlen("slot-successful:"); - slot = slotidx_from_suffix(str); - if (slot < 0) { - strlcpy(buffer, "no such slot", size); - return -1; - } else { - slot_data = &ab_data.slots[slot]; - bool succ = (slot_data->successful_boot != 0); - strlcpy(buffer, succ ? "yes" : "no", size); - } - - } else if (!strcmp_l1("slot-unbootable:", cmd)) { - str += strlen("slot-unbootable:"); - slot = slotidx_from_suffix(str); - if (slot < 0) { - strlcpy(buffer, "no such slot", size); - return -1; - } else { - slot_data = &ab_data.slots[slot]; - bool bootable = slot_is_bootable(slot_data); - strlcpy(buffer, bootable ? "no" : "yes", size); - } - - } else if (!strcmp_l1("slot-retry-count:", cmd)) { - str += strlen("slot-retry-count:"); - slot = slotidx_from_suffix(str); - if (slot < 0) { - strlcpy(buffer, "no such slot", size); - return -1; - } - else { - slot_data = &ab_data.slots[slot]; - char var[7]; - sprintf(var, "%d", - slot_data->tries_remaining); - strlcpy(buffer, var, size); - } - - } else { - strlcpy(buffer, "no such slot command", size); - return -1; - } - - return 0; -} - -char *select_slot(AvbOps *ops) { - AvbABData ab_data; - int curr; - - assert(ops != NULL); - - /* load ab meta */ - if (ops->read_ab_metadata == NULL || - ops->read_ab_metadata(ops, &ab_data) != AVB_IO_RESULT_OK) { - return NULL; - } - curr = get_curr_slot(&ab_data); - if (curr >= 0 && curr < SLOT_NUM) - return slot_suffix[curr]; - else - return NULL; -} -- cgit v1.1