Commit 449f9048e6f7870385b4fbecb18c846478a8305f

Authored by Luo Ji
Committed by Ji Luo
1 parent fed4a26ead

[iot] Update libavb in u-boot

This commit did:
1. Sync AVB lib with external/avb, head of commit is:
    commit 6d5326a945c2d17d5d0e7718d5cb97663c3b33a2
    Author: Neal Ostrem <nealo@google.com>
    Date:   Tue Apr 24 13:09:45 2018 -0700

        Merge fix/changes required after merge from AOSP ToT.

        Change library name to one used by AT.
        Test: Built successfully and unit tests pass.
        Change-Id: I5e5fc9a6010d96cfecfc6faf0858ba930cba65a0
2. Change product id in ATX to be full zeros to sync with
   external/avb.
3. Fix build errors and implement ops fsl_set_key_version.
4. Move most nxp modified code to lib/avb/fsl/.

Test: build and boot successfully for imx7d_pico and imx8m_phanbell.

Change-Id: I199a035fe8267b10955299a4b745458d40a2e754
Signed-off-by: Luo Ji <ji.luo@nxp.com>

Showing 57 changed files with 1918 additions and 865 deletions Side-by-side Diff

drivers/usb/gadget/Makefile
... ... @@ -5,6 +5,8 @@
5 5 # SPDX-License-Identifier: GPL-2.0+
6 6 #
7 7  
  8 +ccflags-y += -I./lib/avb
  9 +
8 10 obj-$(CONFIG_USB_GADGET) += epautoconf.o config.o usbstring.o
9 11 obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o
10 12  
drivers/usb/gadget/f_fastboot.c
... ... @@ -1628,7 +1628,8 @@
1628 1628 static AvbAtxOps fsl_avb_atx_ops = {
1629 1629 .ops = NULL,
1630 1630 .read_permanent_attributes = fsl_read_permanent_attributes,
1631   - .read_permanent_attributes_hash = fsl_read_permanent_attributes_hash
  1631 + .read_permanent_attributes_hash = fsl_read_permanent_attributes_hash,
  1632 + .set_key_version = fsl_set_key_version
1632 1633 };
1633 1634 #endif
1634 1635 static AvbOps fsl_avb_ops = {
include/configs/imx8mm_evk_android.h
... ... @@ -60,6 +60,7 @@
60 60 #ifdef CONFIG_FSL_CAAM_KB
61 61 #undef CONFIG_FSL_CAAM_KB
62 62 #endif
  63 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
63 64  
64 65 #endif /* IMX8MM_EVK_ANDROID_H */
include/configs/imx8mq_evk_android.h
... ... @@ -49,6 +49,7 @@
49 49 #ifdef CONFIG_FSL_CAAM_KB
50 50 #undef CONFIG_FSL_CAAM_KB
51 51 #endif
  52 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
52 53  
53 54 #endif /* IMX8MQ_EVK_ANDROID_H */
include/configs/imx8mq_evk_androidthings.h
... ... @@ -51,5 +51,7 @@
51 51 "fdt_high=0xffffffffffffffff\0" \
52 52 "initrd_high=0xffffffffffffffff\0" \
53 53  
  54 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  55 +
54 56 #endif /* IMX8MQ_EVK_ANDROID_THINGS_H */
include/configs/imx8qm_arm2_android.h
... ... @@ -60,5 +60,7 @@
60 60 #define CONFIG_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR
61 61 #define CONFIG_FASTBOOT_BUF_SIZE 0x19000000
62 62  
  63 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  64 +
63 65 #endif /* MX6_SABRE_ANDROID_COMMON_H */
include/configs/imx8qm_mek_android.h
... ... @@ -64,5 +64,7 @@
64 64 #define CONFIG_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR
65 65 #define CONFIG_FASTBOOT_BUF_SIZE 0x19000000
66 66  
  67 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  68 +
67 69 #endif /* IMX8QM_MEK_ANDROID_H */
include/configs/imx8qm_mek_android_auto.h
... ... @@ -93,5 +93,7 @@
93 93 #include "imx8qm_mek_android_auto_xen.h"
94 94 #endif
95 95  
  96 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  97 +
96 98 #endif /* IMX8QM_MEK_ANDROID_AUTO_H */
include/configs/imx8qm_mek_android_auto_xen.h
... ... @@ -35,5 +35,7 @@
35 35 /* This needs to be stay same in iomem in domu.cfg */
36 36 #define SC_IPC_CH 0x15d1d0000
37 37  
  38 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  39 +
38 40 #endif /* IMX8QM_MEK_ANDROID_AUTO_XEN_H */
include/configs/imx8qxp_arm2_android.h
... ... @@ -60,5 +60,7 @@
60 60 #define CONFIG_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR
61 61 #define CONFIG_FASTBOOT_BUF_SIZE 0x19000000
62 62  
  63 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  64 +
63 65 #endif /* IMX8QXP_ARM2_ANDROID_H */
include/configs/imx8qxp_mek_android.h
... ... @@ -60,5 +60,7 @@
60 60 #define CONFIG_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR
61 61 #define CONFIG_FASTBOOT_BUF_SIZE 0x19000000
62 62  
  63 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  64 +
63 65 #endif /* IMX8QXP_MEK_ANDROID_H */
include/configs/imx8qxp_mek_android_auto.h
... ... @@ -87,5 +87,7 @@
87 87 #undef CONFIG_USB_HOST_ETHER
88 88 #undef CONFIG_USB_FUNCTION_MASS_STORAGE
89 89  
  90 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  91 +
90 92 #endif /* IMX8QXP_MEK_ANDROID_AUTO_H */
include/configs/multa-imx7d_androidthings.h
... ... @@ -61,5 +61,7 @@
61 61 #define CONFIG_AVB_FUSE_BANK_END 0
62 62 #endif
63 63  
  64 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  65 +
64 66 #endif
include/configs/mx6sabreandroid_common.h
... ... @@ -34,5 +34,7 @@
34 34  
35 35 #endif /* CONFIG_AVB_SUPPORT */
36 36  
  37 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  38 +
37 39 #endif /* MX6_SABRE_ANDROID_COMMON_H */
include/configs/mx6slevkandroid.h
... ... @@ -49,5 +49,7 @@
49 49  
50 50 #endif /* CONFIG_AVB_SUPPORT */
51 51  
  52 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  53 +
52 54 #endif
include/configs/mx6sxsabreautoandroid.h
... ... @@ -35,5 +35,7 @@
35 35  
36 36 #endif /* CONFIG_AVB_SUPPORT */
37 37  
  38 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  39 +
38 40 #endif
include/configs/mx6sxsabresdandroid.h
... ... @@ -38,5 +38,7 @@
38 38  
39 39 #endif /* CONFIG_AVB_SUPPORT */
40 40  
  41 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  42 +
41 43 #endif
include/configs/mx6ul_nxpu_iopb_android_things.h
... ... @@ -55,6 +55,8 @@
55 55 #define CONFIG_AVB_FUSE_BANK_END 15
56 56 #endif
57 57  
  58 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  59 +
58 60 #endif
59 61 /* __MX6UL_NXPU_IOPB_ANDROID_THINGS_H */
include/configs/mx6ul_spriot_android_things.h
... ... @@ -48,6 +48,8 @@
48 48 #define CONFIG_AVB_FUSE_BANK_END 15
49 49 #endif
50 50  
  51 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  52 +
51 53 #endif
52 54 /* __MX6UL_SPRIOT_ANDROID_THINGS_H */
include/configs/mx7dsabresdandroid.h
... ... @@ -33,5 +33,7 @@
33 33  
34 34 #endif /* CONFIG_AVB_SUPPORT */
35 35  
  36 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  37 +
36 38 #endif /* __MX7D_SABRESD_ANDROID_H */
include/configs/mx7ulp_evk_android.h
... ... @@ -38,5 +38,7 @@
38 38 #define ANDROID_MCU_FIRMWARE_SIZE 0x20000
39 39 #endif
40 40  
  41 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  42 +
41 43 #endif
include/configs/pico-imx7dandroidthings.h
... ... @@ -61,7 +61,7 @@
61 61  
62 62 #ifdef CONFIG_SYS_MALLOC_LEN
63 63 #undef CONFIG_SYS_MALLOC_LEN
64   -#define CONFIG_SYS_MALLOC_LEN (32 * SZ_1M)
  64 +#define CONFIG_SYS_MALLOC_LEN (64 * SZ_1M)
65 65 #endif
66 66 /* fuse bank size in word */
67 67 /* infact 7D have no enough bits
... ... @@ -71,6 +71,8 @@
71 71 #define CONFIG_AVB_FUSE_BANK_START 14
72 72 #define CONFIG_AVB_FUSE_BANK_END 14
73 73 #endif
  74 +
  75 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
74 76  
75 77 /* Disable U-Boot logo */
76 78 #undef CONFIG_VIDEO_LOGO
include/configs/picosom-imx6ul_android_things.h
... ... @@ -55,6 +55,7 @@
55 55 #define CONFIG_AVB_FUSE_BANK_END 15
56 56 #endif
57 57  
  58 +#define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
58 59  
59 60 #endif
60 61 /* __PICOSOM_IMX6UL_ANDROID_THINGS_H */
... ... @@ -195,5 +195,29 @@
195 195 */
196 196 AvbIOResult fsl_read_permanent_attributes_hash(
197 197 AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]);
  198 +
  199 +/* Provides the key version of a key used during verification. This may be
  200 + * useful for managing the minimum key version.
  201 + */
  202 +void fsl_set_key_version(AvbAtxOps* atx_ops,
  203 + size_t rollback_index_location,
  204 + uint64_t key_version);
  205 +
  206 +/* This is the fast version of avb_ab_flow(), this function will
  207 + * not check another slot if one slot can pass the verify (or verify
  208 + * fail is acceptable). */
  209 +AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
  210 + const char* const* requested_partitions,
  211 + AvbSlotVerifyFlags flags,
  212 + AvbHashtreeErrorMode hashtree_error_mode,
  213 + AvbSlotVerifyData** out_data);
  214 +
  215 +/* This is for legacy i.mx6/7 which don't enable A/B but want to
  216 + * verify boot/recovery with AVB */
  217 +AvbABFlowResult avb_single_flow(AvbABOps* ab_ops,
  218 + const char* const* requested_partitions,
  219 + AvbSlotVerifyFlags flags,
  220 + AvbHashtreeErrorMode hashtree_error_mode,
  221 + AvbSlotVerifyData** out_data);
198 222 #endif /* __FSL_AVB_H__ */
1   -subdir-ccflags-y += -D_FILE_OFFSET_BITS=64 \
  1 +subdir-ccflags-y += -I./lib/avb \
  2 + -D_FILE_OFFSET_BITS=64 \
2 3 -D_POSIX_C_SOURCE=199309L \
3 4 -Wa,--noexecstack \
4   - -Werror \
5 5 -Wall \
6 6 -Wextra \
7 7 -Wformat=2 \
lib/avb/fsl/Makefile
1   -ccflags-$(CONFIG_AVB_DEBUG) += -DAVB_DEBUG
  1 +ccflags-y += -Werror
2 2 obj-y += fsl_avb.o
3 3 obj-y += fsl_avbkey.o
4 4 obj-y += fsl_bootctl.o
  5 +obj-y += fsl_avb_ab_flow.o
  6 +obj-y += fsl_avb_sysdeps_uboot.o
5 7 obj-y += utils.o
lib/avb/fsl/fsl_atx_attributes.h
... ... @@ -11,8 +11,8 @@
11 11 /* This product_id is generated from
12 12 * extern/avb/test/data/atx_product_id.bin */
13 13 unsigned char fsl_atx_product_id[] = {
14   - 0x3f,0x38,0x9c,0xcb,0xbe,0x56,0xcc,0x3d,
15   - 0x0b,0xd0,0xbb,0x35,0x01,0x85,0xa7,0xd2
  14 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  15 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
16 16 };
17 17 /* This product_root_public_key is generated form
18 18 * extern/avb/test/data/testkey_atx_prk.pem */
lib/avb/fsl/fsl_avb_ab_flow.c
  1 +/*
  2 + * Copyright 2018 NXP
  3 + */
  4 +
  5 +#include <common.h>
  6 +#include <fsl_avb.h>
  7 +
  8 +static const char* slot_suffixes[2] = {"_a", "_b"};
  9 +
  10 +/* This is a copy of slot_set_unbootable() form
  11 + * lib/avb/libavb_ab/avb_ab_flow.c.
  12 + */
  13 +static void fsl_slot_set_unbootable(AvbABSlotData* slot) {
  14 + slot->priority = 0;
  15 + slot->tries_remaining = 0;
  16 + slot->successful_boot = 0;
  17 +}
  18 +
  19 +/* Ensure all unbootable and/or illegal states are marked as the
  20 + * canonical 'unbootable' state, e.g. priority=0, tries_remaining=0,
  21 + * and successful_boot=0. This is a copy of fsl_slot_normalize from
  22 + * lib/avb/libavb_ab/avb_ab_flow.c.
  23 + */
  24 +static void fsl_slot_normalize(AvbABSlotData* slot) {
  25 + if (slot->priority > 0) {
  26 + if ((slot->tries_remaining == 0) && (!slot->successful_boot)) {
  27 + /* We've exhausted all tries -> unbootable. */
  28 + fsl_slot_set_unbootable(slot);
  29 + }
  30 + if ((slot->tries_remaining > 0) && (slot->successful_boot)) {
  31 + /* Illegal state - avb_ab_mark_slot_successful() will clear
  32 + * tries_remaining when setting successful_boot.
  33 + */
  34 + fsl_slot_set_unbootable(slot);
  35 + }
  36 + } else {
  37 + fsl_slot_set_unbootable(slot);
  38 + }
  39 +}
  40 +
  41 +/* Writes A/B metadata to disk only if it has changed - returns
  42 + * AVB_IO_RESULT_OK on success, error code otherwise. This is a
  43 + * copy of save_metadata_if_changed form lib/avb/libavb_ab/avb_ab_flow.c.
  44 + */
  45 +static AvbIOResult fsl_save_metadata_if_changed(AvbABOps* ab_ops,
  46 + AvbABData* ab_data,
  47 + AvbABData* ab_data_orig) {
  48 + if (avb_safe_memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) {
  49 + avb_debug("Writing A/B metadata to disk.\n");
  50 + return ab_ops->write_ab_metadata(ab_ops, ab_data);
  51 + }
  52 + return AVB_IO_RESULT_OK;
  53 +}
  54 +
  55 +/* This is a copy of slot_is_bootable() from
  56 + * lib/avb/libavb_ab/avb_ab_flow.c.
  57 + */
  58 +static bool fsl_slot_is_bootable(AvbABSlotData* slot) {
  59 + return (slot->priority > 0) &&
  60 + (slot->successful_boot || (slot->tries_remaining > 0));
  61 +}
  62 +
  63 +/* Helper function to load metadata - returns AVB_IO_RESULT_OK on
  64 + * success, error code otherwise. This is a copy of load_metadata()
  65 + * from /lib/avb/libavb_ab/avb_ab_flow.c.
  66 + */
  67 +static AvbIOResult fsl_load_metadata(AvbABOps* ab_ops,
  68 + AvbABData* ab_data,
  69 + AvbABData* ab_data_orig) {
  70 + AvbIOResult io_ret;
  71 +
  72 + io_ret = ab_ops->read_ab_metadata(ab_ops, ab_data);
  73 + if (io_ret != AVB_IO_RESULT_OK) {
  74 + avb_error("I/O error while loading A/B metadata.\n");
  75 + return io_ret;
  76 + }
  77 + *ab_data_orig = *ab_data;
  78 +
  79 + /* Ensure data is normalized, e.g. illegal states will be marked as
  80 + * unbootable and all unbootable states are represented with
  81 + * (priority=0, tries_remaining=0, successful_boot=0).
  82 + */
  83 + fsl_slot_normalize(&ab_data->slots[0]);
  84 + fsl_slot_normalize(&ab_data->slots[1]);
  85 + return AVB_IO_RESULT_OK;
  86 +}
  87 +
  88 +/* For legacy i.mx6/7, we won't enable A/B due to the limitation of
  89 + * storage capacity, but we still want to verify boot/recovery with
  90 + * AVB. */
  91 +AvbABFlowResult avb_single_flow(AvbABOps* ab_ops,
  92 + const char* const* requested_partitions,
  93 + AvbSlotVerifyFlags flags,
  94 + AvbHashtreeErrorMode hashtree_error_mode,
  95 + AvbSlotVerifyData** out_data) {
  96 + AvbOps* ops = ab_ops->ops;
  97 + AvbSlotVerifyData* slot_data = NULL;
  98 + AvbSlotVerifyData* data = NULL;
  99 + AvbABFlowResult ret;
  100 + bool saw_and_allowed_verification_error = false;
  101 +
  102 + /* Validate boot/recovery. */
  103 + AvbSlotVerifyResult verify_result;
  104 +
  105 + verify_result = avb_slot_verify(ops,
  106 + requested_partitions,
  107 + "",
  108 + flags,
  109 + hashtree_error_mode,
  110 + &slot_data);
  111 + switch (verify_result) {
  112 + case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
  113 + ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
  114 + goto out;
  115 +
  116 + case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
  117 + ret = AVB_AB_FLOW_RESULT_ERROR_IO;
  118 + goto out;
  119 +
  120 + case AVB_SLOT_VERIFY_RESULT_OK:
  121 + break;
  122 +
  123 + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
  124 + case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
  125 + /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
  126 + * these mean game over.
  127 + */
  128 + ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
  129 + goto out;
  130 +
  131 + /* explicit fallthrough. */
  132 + case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
  133 + case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
  134 + case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
  135 + if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
  136 + /* Do nothing since we allow this. */
  137 + avb_debugv("Allowing slot ",
  138 + slot_suffixes[n],
  139 + " which verified "
  140 + "with result ",
  141 + avb_slot_verify_result_to_string(verify_result),
  142 + " because "
  143 + "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
  144 + "is set.\n",
  145 + NULL);
  146 + saw_and_allowed_verification_error = true;
  147 + } else {
  148 + ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
  149 + goto out;
  150 + }
  151 + break;
  152 +
  153 + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
  154 + ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
  155 + goto out;
  156 + /* Do not add a 'default:' case here because of -Wswitch. */
  157 + }
  158 +
  159 + avb_assert(slot_data != NULL);
  160 + data = slot_data;
  161 + slot_data = NULL;
  162 + if (saw_and_allowed_verification_error) {
  163 + avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
  164 + ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
  165 + } else {
  166 + ret = AVB_AB_FLOW_RESULT_OK;
  167 + }
  168 +
  169 +out:
  170 + if (slot_data != NULL) {
  171 + avb_slot_verify_data_free(slot_data);
  172 + }
  173 +
  174 + if (out_data != NULL) {
  175 + *out_data = data;
  176 + } else {
  177 + if (data != NULL) {
  178 + avb_slot_verify_data_free(data);
  179 + }
  180 + }
  181 +
  182 + return ret;
  183 +}
  184 +
  185 +AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
  186 + const char* const* requested_partitions,
  187 + AvbSlotVerifyFlags flags,
  188 + AvbHashtreeErrorMode hashtree_error_mode,
  189 + AvbSlotVerifyData** out_data) {
  190 + AvbOps* ops = ab_ops->ops;
  191 + AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
  192 + AvbSlotVerifyData* data = NULL;
  193 + AvbABFlowResult ret;
  194 + AvbABData ab_data, ab_data_orig;
  195 + size_t slot_index_to_boot, n;
  196 + AvbIOResult io_ret;
  197 + bool saw_and_allowed_verification_error = false;
  198 + size_t target_slot;
  199 + AvbSlotVerifyResult verify_result;
  200 + bool set_slot_unbootable = false;
  201 +
  202 + io_ret = fsl_load_metadata(ab_ops, &ab_data, &ab_data_orig);
  203 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  204 + ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
  205 + goto out;
  206 + } else if (io_ret != AVB_IO_RESULT_OK) {
  207 + ret = AVB_AB_FLOW_RESULT_ERROR_IO;
  208 + goto out;
  209 + }
  210 +
  211 + slot_index_to_boot = 2; // Means not 0 or 1
  212 + target_slot =
  213 + (ab_data.slots[1].priority > ab_data.slots[0].priority) ? 1 : 0;
  214 +
  215 + for (n = 0; n < 2; n++) {
  216 + if (!fsl_slot_is_bootable(&ab_data.slots[target_slot])) {
  217 + target_slot = (target_slot == 1 ? 0 : 1);
  218 + continue;
  219 + }
  220 + verify_result = avb_slot_verify(ops,
  221 + requested_partitions,
  222 + slot_suffixes[target_slot],
  223 + flags,
  224 + hashtree_error_mode,
  225 + &slot_data[target_slot]);
  226 + switch (verify_result) {
  227 + case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
  228 + ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
  229 + goto out;
  230 +
  231 + case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
  232 + ret = AVB_AB_FLOW_RESULT_ERROR_IO;
  233 + goto out;
  234 +
  235 + case AVB_SLOT_VERIFY_RESULT_OK:
  236 + slot_index_to_boot = target_slot;
  237 + n = 2;
  238 + break;
  239 +
  240 + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
  241 + case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
  242 + /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
  243 + * these mean game over.
  244 + */
  245 + set_slot_unbootable = true;
  246 + break;
  247 +
  248 + /* explicit fallthrough. */
  249 + case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
  250 + case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
  251 + case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
  252 + if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
  253 + /* Do nothing since we allow this. */
  254 + avb_debugv("Allowing slot ",
  255 + slot_suffixes[target_slot],
  256 + " which verified "
  257 + "with result ",
  258 + avb_slot_verify_result_to_string(verify_result),
  259 + " because "
  260 + "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
  261 + "is set.\n",
  262 + NULL);
  263 + saw_and_allowed_verification_error =
  264 + true;
  265 + slot_index_to_boot = target_slot;
  266 + n = 2;
  267 + } else {
  268 + set_slot_unbootable = true;
  269 + }
  270 + break;
  271 +
  272 + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
  273 + ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
  274 + goto out;
  275 + /* Do not add a 'default:' case here because
  276 + * of -Wswitch.
  277 + */
  278 + }
  279 +
  280 + if (set_slot_unbootable) {
  281 + avb_errorv("Error verifying slot ",
  282 + slot_suffixes[target_slot],
  283 + " with result ",
  284 + avb_slot_verify_result_to_string(verify_result),
  285 + " - setting unbootable.\n",
  286 + NULL);
  287 + fsl_slot_set_unbootable(&ab_data.slots[target_slot]);
  288 + set_slot_unbootable = false;
  289 + }
  290 + /* switch to another slot */
  291 + target_slot = (target_slot == 1 ? 0 : 1);
  292 + }
  293 +
  294 + if (slot_index_to_boot == 2) {
  295 + /* No bootable slots! */
  296 + avb_error("No bootable slots found.\n");
  297 + ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
  298 + goto out;
  299 + }
  300 +
  301 + /* Update stored rollback index such that the stored rollback index
  302 + * is the largest value supporting all currently bootable slots. Do
  303 + * this for every rollback index location.
  304 + */
  305 + for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
  306 + uint64_t rollback_index_value = 0;
  307 +
  308 + if ((slot_data[0] != NULL) && (slot_data[1] != NULL)) {
  309 + uint64_t a_rollback_index =
  310 + slot_data[0]->rollback_indexes[n];
  311 + uint64_t b_rollback_index =
  312 + slot_data[1]->rollback_indexes[n];
  313 + rollback_index_value =
  314 + (a_rollback_index < b_rollback_index ?
  315 + a_rollback_index : b_rollback_index);
  316 + } else if (slot_data[0] != NULL) {
  317 + rollback_index_value =
  318 + slot_data[0]->rollback_indexes[n];
  319 + } else if (slot_data[1] != NULL) {
  320 + rollback_index_value =
  321 + slot_data[1]->rollback_indexes[n];
  322 + }
  323 +
  324 + if (rollback_index_value != 0) {
  325 + uint64_t current_rollback_index_value;
  326 + io_ret = ops->read_rollback_index(
  327 + ops, n, &current_rollback_index_value);
  328 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  329 + ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
  330 + goto out;
  331 + } else if (io_ret != AVB_IO_RESULT_OK) {
  332 + avb_error("Error getting rollback index for slot.\n");
  333 + ret = AVB_AB_FLOW_RESULT_ERROR_IO;
  334 + goto out;
  335 + }
  336 + if (current_rollback_index_value != rollback_index_value) {
  337 + io_ret = ops->write_rollback_index(
  338 + ops, n, rollback_index_value);
  339 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  340 + ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
  341 + goto out;
  342 + } else if (io_ret != AVB_IO_RESULT_OK) {
  343 + avb_error("Error setting stored rollback index.\n");
  344 + ret = AVB_AB_FLOW_RESULT_ERROR_IO;
  345 + goto out;
  346 + }
  347 + }
  348 + }
  349 + }
  350 +
  351 + /* Finally, select this slot. */
  352 + avb_assert(slot_data[slot_index_to_boot] != NULL);
  353 + data = slot_data[slot_index_to_boot];
  354 + slot_data[slot_index_to_boot] = NULL;
  355 + if (saw_and_allowed_verification_error) {
  356 + avb_assert(
  357 + flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
  358 + ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
  359 + } else {
  360 + ret = AVB_AB_FLOW_RESULT_OK;
  361 + }
  362 +
  363 + /* ... and decrement tries remaining, if applicable. */
  364 + if (!ab_data.slots[slot_index_to_boot].successful_boot &&
  365 + (ab_data.slots[slot_index_to_boot].tries_remaining > 0)) {
  366 + ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
  367 + }
  368 +
  369 +out:
  370 + io_ret = fsl_save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
  371 + if (io_ret != AVB_IO_RESULT_OK) {
  372 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  373 + ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
  374 + } else {
  375 + ret = AVB_AB_FLOW_RESULT_ERROR_IO;
  376 + }
  377 + if (data != NULL) {
  378 + avb_slot_verify_data_free(data);
  379 + data = NULL;
  380 + }
  381 + }
  382 +
  383 + for (n = 0; n < 2; n++) {
  384 + if (slot_data[n] != NULL) {
  385 + avb_slot_verify_data_free(slot_data[n]);
  386 + }
  387 + }
  388 +
  389 + if (out_data != NULL) {
  390 + *out_data = data;
  391 + } else {
  392 + if (data != NULL) {
  393 + avb_slot_verify_data_free(data);
  394 + }
  395 + }
  396 +
  397 + return ret;
  398 +}
lib/avb/fsl/fsl_avb_sysdeps_uboot.c
  1 +/*
  2 + * Copyright (C) 2016 The Android Open Source Project
  3 + *
  4 + * Permission is hereby granted, free of charge, to any person
  5 + * obtaining a copy of this software and associated documentation
  6 + * files (the "Software"), to deal in the Software without
  7 + * restriction, including without limitation the rights to use, copy,
  8 + * modify, merge, publish, distribute, sublicense, and/or sell copies
  9 + * of the Software, and to permit persons to whom the Software is
  10 + * furnished to do so, subject to the following conditions:
  11 + *
  12 + * The above copyright notice and this permission notice shall be
  13 + * included in all copies or substantial portions of the Software.
  14 + *
  15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22 + * SOFTWARE.
  23 + */
  24 +
  25 +#include <common.h>
  26 +#include <stdlib.h>
  27 +#include <linux/string.h>
  28 +
  29 +#include "../libavb/libavb.h"
  30 +
  31 +int avb_memcmp(const void* src1, const void* src2, size_t n) {
  32 + return memcmp(src1, src2, n);
  33 +}
  34 +
  35 +void* avb_memcpy(void* dest, const void* src, size_t n) {
  36 + return memcpy(dest, src, n);
  37 +}
  38 +
  39 +void* avb_memset(void* dest, const int c, size_t n) {
  40 + return memset(dest, c, n);
  41 +}
  42 +
  43 +int avb_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); }
  44 +
  45 +size_t avb_strlen(const char* str) { return strlen(str); }
  46 +
  47 +void avb_abort(void) { panic("avb_abort!\n"); }
  48 +
  49 +void avb_print(const char* message) { printf("%s", message); }
  50 +
  51 +void avb_printv(const char* message, ...) {
  52 + va_list ap;
  53 + const char* m;
  54 +
  55 + va_start(ap, message);
  56 + for (m = message; m != NULL; m = va_arg(ap, const char*)) {
  57 + printf("%s", m);
  58 + }
  59 + va_end(ap);
  60 +}
  61 +
  62 +void* avb_malloc_(size_t size) { return malloc(size); }
  63 +
  64 +void avb_free(void* ptr) { free(ptr); }
  65 +
  66 +uint32_t avb_div_by_10(uint64_t* dividend) {
  67 + uint32_t rem = (uint32_t)(*dividend % 10);
  68 + *dividend /= 10;
  69 + return rem;
  70 +}
lib/avb/fsl/fsl_avbkey.c
... ... @@ -1108,7 +1108,8 @@
1108 1108 *plain_idx = rollback_index;
1109 1109  
1110 1110 /* write rollback_index keyblob */
1111   - if (rpmb_write(mmc_dev, (uint8_t *)plain_idx, rbk->len, rbk->offset) != 0) {
  1111 + if (rpmb_write(mmc_dev, (uint8_t *)plain_idx, rbk->len, rbk->offset) !=
  1112 + 0) {
1112 1113 ERR("write rollback index error\n");
1113 1114 ret = AVB_IO_RESULT_ERROR_IO;
1114 1115 goto fail;
... ... @@ -1131,8 +1132,9 @@
1131 1132 /* use hard code permanent attributes due to limited fuse and RPMB */
1132 1133 attributes->version = fsl_version;
1133 1134 memcpy(attributes->product_root_public_key, fsl_product_root_public_key,
1134   - sizeof(fsl_product_root_public_key));
1135   - memcpy(attributes->product_id, fsl_atx_product_id, sizeof(fsl_atx_product_id));
  1135 + sizeof(fsl_product_root_public_key));
  1136 + memcpy(attributes->product_id, fsl_atx_product_id,
  1137 + sizeof(fsl_atx_product_id));
1136 1138  
1137 1139 return AVB_IO_RESULT_OK;
1138 1140 }
... ... @@ -1148,8 +1150,9 @@
1148 1150  
1149 1151 /* read first 112 bits of sha256(permanent attributes) from fuse */
1150 1152 if (fsl_fuse_read(sha256_hash_fuse, ATX_FUSE_BANK_NUM,
1151   - PERMANENT_ATTRIBUTE_HASH_OFFSET)) {
1152   - printf("ERROR - read permanent attributes hash from fuse error\n");
  1153 + PERMANENT_ATTRIBUTE_HASH_OFFSET)) {
  1154 + printf("ERROR - read permanent attributes hash from "
  1155 + "fuse error\n");
1153 1156 return AVB_IO_RESULT_ERROR_IO;
1154 1157 }
1155 1158 /* only take the lower 2 bytes of last bank */
... ... @@ -1168,5 +1171,55 @@
1168 1171 memcpy(hash, sha256_hash_buf, AVB_SHA256_DIGEST_SIZE);
1169 1172 return AVB_IO_RESULT_OK;
1170 1173 }
  1174 +
  1175 +/* Provides the key version of a key used during verification. This may be
  1176 + * useful for managing the minimum key version.
  1177 + */
  1178 +void fsl_set_key_version(AvbAtxOps* atx_ops,
  1179 + size_t rollback_index_location,
  1180 + uint64_t key_version) {
  1181 + kblb_hdr_t hdr;
  1182 + kblb_tag_t *rbk;
  1183 + uint64_t *plain_idx = NULL;
  1184 + struct mmc *mmc_dev;
  1185 + static const uint32_t kTypeMask = 0xF000;
  1186 +
  1187 + DEBUGAVB("[rpmb] write to rollback slot: (%zu, %" PRIu64 ")\n",
  1188 + rollback_index_location, key_version);
  1189 +
  1190 + assert(atx_ops != NULL);
  1191 +
  1192 + if ((mmc_dev = get_mmc()) == NULL) {
  1193 + ERR("err get mmc device\n");
  1194 + }
  1195 + /* read the kblb header */
  1196 + if (rpmb_read(mmc_dev, (uint8_t *)&hdr, sizeof(hdr), 0) != 0) {
  1197 + ERR("read RPMB error\n");
  1198 + }
  1199 +
  1200 + if (memcmp(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN) != 0) {
  1201 + ERR("magic not match\n");
  1202 + }
  1203 +
  1204 + /* rollback index for Android Things key versions */
  1205 + rbk = &hdr.atx_rbk_tags[rollback_index_location & ~kTypeMask];
  1206 +
  1207 + plain_idx = malloc(rbk->len);
  1208 + if (plain_idx == NULL)
  1209 + printf("\nError! allocate memory fail!\n");
  1210 + memset(plain_idx, 0, rbk->len);
  1211 + *plain_idx = key_version;
  1212 +
  1213 + /* write rollback_index keyblob */
  1214 + if (rpmb_write(mmc_dev, (uint8_t *)plain_idx, rbk->len, rbk->offset) !=
  1215 + 0) {
  1216 + ERR("write rollback index error\n");
  1217 + goto fail;
  1218 + }
  1219 +fail:
  1220 + if (plain_idx != NULL)
  1221 + free(plain_idx);
  1222 +}
  1223 +
1171 1224 #endif
lib/avb/libavb/Makefile
... ... @@ -14,5 +14,5 @@
14 14 avb_hashtree_descriptor.o \
15 15 avb_sha256.o \
16 16 avb_util.o \
17   - avb_sysdeps_uboot.o
  17 + avb_cmdline.o
lib/avb/libavb/avb_cmdline.c
  1 +/*
  2 + * Copyright (C) 2016 The Android Open Source Project
  3 + *
  4 + * Permission is hereby granted, free of charge, to any person
  5 + * obtaining a copy of this software and associated documentation
  6 + * files (the "Software"), to deal in the Software without
  7 + * restriction, including without limitation the rights to use, copy,
  8 + * modify, merge, publish, distribute, sublicense, and/or sell copies
  9 + * of the Software, and to permit persons to whom the Software is
  10 + * furnished to do so, subject to the following conditions:
  11 + *
  12 + * The above copyright notice and this permission notice shall be
  13 + * included in all copies or substantial portions of the Software.
  14 + *
  15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22 + * SOFTWARE.
  23 + */
  24 +
  25 +#include "avb_cmdline.h"
  26 +#include "avb_sha.h"
  27 +#include "avb_util.h"
  28 +#include "avb_version.h"
  29 +
  30 +#define NUM_GUIDS 3
  31 +
  32 +/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
  33 + * values. Returns NULL on OOM, otherwise the cmdline with values
  34 + * replaced.
  35 + */
  36 +char* avb_sub_cmdline(AvbOps* ops,
  37 + const char* cmdline,
  38 + const char* ab_suffix,
  39 + bool using_boot_for_vbmeta,
  40 + const AvbCmdlineSubstList* additional_substitutions) {
  41 + const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
  42 + const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
  43 + "$(ANDROID_BOOT_PARTUUID)",
  44 + "$(ANDROID_VBMETA_PARTUUID)"};
  45 + char* ret = NULL;
  46 + AvbIOResult io_ret;
  47 + size_t n;
  48 +
  49 + /* Special-case for when the top-level vbmeta struct is in the boot
  50 + * partition.
  51 + */
  52 + if (using_boot_for_vbmeta) {
  53 + part_name_str[2] = "boot";
  54 + }
  55 +
  56 + /* Replace unique partition GUIDs */
  57 + for (n = 0; n < NUM_GUIDS; n++) {
  58 + char part_name[AVB_PART_NAME_MAX_SIZE];
  59 + char guid_buf[37];
  60 +
  61 + if (!avb_str_concat(part_name,
  62 + sizeof part_name,
  63 + part_name_str[n],
  64 + avb_strlen(part_name_str[n]),
  65 + ab_suffix,
  66 + avb_strlen(ab_suffix))) {
  67 + avb_error("Partition name and suffix does not fit.\n");
  68 + goto fail;
  69 + }
  70 +
  71 + io_ret = ops->get_unique_guid_for_partition(
  72 + ops, part_name, guid_buf, sizeof guid_buf);
  73 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  74 + goto fail;
  75 + } else if (io_ret != AVB_IO_RESULT_OK) {
  76 + avb_error("Error getting unique GUID for partition.\n");
  77 + goto fail;
  78 + }
  79 +
  80 + if (ret == NULL) {
  81 + ret = avb_replace(cmdline, replace_str[n], guid_buf);
  82 + } else {
  83 + char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
  84 + avb_free(ret);
  85 + ret = new_ret;
  86 + }
  87 + if (ret == NULL) {
  88 + goto fail;
  89 + }
  90 + }
  91 +
  92 + avb_assert(ret != NULL);
  93 +
  94 + /* Replace any additional substitutions. */
  95 + if (additional_substitutions != NULL) {
  96 + for (n = 0; n < additional_substitutions->size; ++n) {
  97 + char* new_ret = avb_replace(ret,
  98 + additional_substitutions->tokens[n],
  99 + additional_substitutions->values[n]);
  100 + avb_free(ret);
  101 + ret = new_ret;
  102 + if (ret == NULL) {
  103 + goto fail;
  104 + }
  105 + }
  106 + }
  107 +
  108 + return ret;
  109 +
  110 +fail:
  111 + if (ret != NULL) {
  112 + avb_free(ret);
  113 + }
  114 + return NULL;
  115 +}
  116 +
  117 +static int cmdline_append_option(AvbSlotVerifyData* slot_data,
  118 + const char* key,
  119 + const char* value) {
  120 + size_t offset, key_len, value_len;
  121 + char* new_cmdline;
  122 +
  123 + key_len = avb_strlen(key);
  124 + value_len = avb_strlen(value);
  125 +
  126 + offset = 0;
  127 + if (slot_data->cmdline != NULL) {
  128 + offset = avb_strlen(slot_data->cmdline);
  129 + if (offset > 0) {
  130 + offset += 1;
  131 + }
  132 + }
  133 +
  134 + new_cmdline = avb_calloc(offset + key_len + value_len + 2);
  135 + if (new_cmdline == NULL) {
  136 + return 0;
  137 + }
  138 + if (offset > 0) {
  139 + avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
  140 + new_cmdline[offset - 1] = ' ';
  141 + }
  142 + avb_memcpy(new_cmdline + offset, key, key_len);
  143 + new_cmdline[offset + key_len] = '=';
  144 + avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
  145 + if (slot_data->cmdline != NULL) {
  146 + avb_free(slot_data->cmdline);
  147 + }
  148 + slot_data->cmdline = new_cmdline;
  149 +
  150 + return 1;
  151 +}
  152 +
  153 +#define AVB_MAX_DIGITS_UINT64 32
  154 +
  155 +/* Writes |value| to |digits| in base 10 followed by a NUL byte.
  156 + * Returns number of characters written excluding the NUL byte.
  157 + */
  158 +static size_t uint64_to_base10(uint64_t value,
  159 + char digits[AVB_MAX_DIGITS_UINT64]) {
  160 + char rev_digits[AVB_MAX_DIGITS_UINT64];
  161 + size_t n, num_digits;
  162 +
  163 + for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
  164 + rev_digits[num_digits++] = avb_div_by_10(&value) + '0';
  165 + if (value == 0) {
  166 + break;
  167 + }
  168 + }
  169 +
  170 + for (n = 0; n < num_digits; n++) {
  171 + digits[n] = rev_digits[num_digits - 1 - n];
  172 + }
  173 + digits[n] = '\0';
  174 + return n;
  175 +}
  176 +
  177 +static int cmdline_append_version(AvbSlotVerifyData* slot_data,
  178 + const char* key,
  179 + uint64_t major_version,
  180 + uint64_t minor_version) {
  181 + char major_digits[AVB_MAX_DIGITS_UINT64];
  182 + char minor_digits[AVB_MAX_DIGITS_UINT64];
  183 + char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
  184 + size_t num_major_digits, num_minor_digits;
  185 +
  186 + num_major_digits = uint64_to_base10(major_version, major_digits);
  187 + num_minor_digits = uint64_to_base10(minor_version, minor_digits);
  188 + avb_memcpy(combined, major_digits, num_major_digits);
  189 + combined[num_major_digits] = '.';
  190 + avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
  191 + combined[num_major_digits + 1 + num_minor_digits] = '\0';
  192 +
  193 + return cmdline_append_option(slot_data, key, combined);
  194 +}
  195 +
  196 +static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
  197 + const char* key,
  198 + uint64_t value) {
  199 + char digits[AVB_MAX_DIGITS_UINT64];
  200 + uint64_to_base10(value, digits);
  201 + return cmdline_append_option(slot_data, key, digits);
  202 +}
  203 +
  204 +static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
  205 + const char* key,
  206 + const uint8_t* data,
  207 + size_t data_len) {
  208 + int ret;
  209 + char* hex_data = avb_bin2hex(data, data_len);
  210 + if (hex_data == NULL) {
  211 + return 0;
  212 + }
  213 + ret = cmdline_append_option(slot_data, key, hex_data);
  214 + avb_free(hex_data);
  215 + return ret;
  216 +}
  217 +
  218 +AvbSlotVerifyResult avb_append_options(
  219 + AvbOps* ops,
  220 + AvbSlotVerifyData* slot_data,
  221 + AvbVBMetaImageHeader* toplevel_vbmeta,
  222 + AvbAlgorithmType algorithm_type,
  223 + AvbHashtreeErrorMode hashtree_error_mode) {
  224 + AvbSlotVerifyResult ret;
  225 + const char* verity_mode;
  226 + bool is_device_unlocked;
  227 + AvbIOResult io_ret;
  228 +
  229 + /* Add androidboot.vbmeta.device option. */
  230 + if (!cmdline_append_option(slot_data,
  231 + "androidboot.vbmeta.device",
  232 + "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
  233 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  234 + goto out;
  235 + }
  236 +
  237 + /* Add androidboot.vbmeta.avb_version option. */
  238 + if (!cmdline_append_version(slot_data,
  239 + "androidboot.vbmeta.avb_version",
  240 + AVB_VERSION_MAJOR,
  241 + AVB_VERSION_MINOR)) {
  242 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  243 + goto out;
  244 + }
  245 +
  246 + /* Set androidboot.avb.device_state to "locked" or "unlocked". */
  247 + io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
  248 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  249 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  250 + goto out;
  251 + } else if (io_ret != AVB_IO_RESULT_OK) {
  252 + avb_error("Error getting device state.\n");
  253 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  254 + goto out;
  255 + }
  256 + if (!cmdline_append_option(slot_data,
  257 + "androidboot.vbmeta.device_state",
  258 + is_device_unlocked ? "unlocked" : "locked")) {
  259 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  260 + goto out;
  261 + }
  262 +
  263 + /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
  264 + * function as is used to sign vbmeta.
  265 + */
  266 + switch (algorithm_type) {
  267 + /* Explicit fallthrough. */
  268 + case AVB_ALGORITHM_TYPE_NONE:
  269 + case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
  270 + case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
  271 + case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
  272 + size_t n, total_size = 0;
  273 + uint8_t vbmeta_digest[AVB_SHA256_DIGEST_SIZE];
  274 + avb_slot_verify_data_calculate_vbmeta_digest(
  275 + slot_data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest);
  276 + for (n = 0; n < slot_data->num_vbmeta_images; n++) {
  277 + total_size += slot_data->vbmeta_images[n].vbmeta_size;
  278 + }
  279 + if (!cmdline_append_option(
  280 + slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
  281 + !cmdline_append_uint64_base10(
  282 + slot_data, "androidboot.vbmeta.size", total_size) ||
  283 + !cmdline_append_hex(slot_data,
  284 + "androidboot.vbmeta.digest",
  285 + vbmeta_digest,
  286 + AVB_SHA256_DIGEST_SIZE)) {
  287 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  288 + goto out;
  289 + }
  290 + } break;
  291 + /* Explicit fallthrough. */
  292 + case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
  293 + case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
  294 + case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
  295 + size_t n, total_size = 0;
  296 + uint8_t vbmeta_digest[AVB_SHA512_DIGEST_SIZE];
  297 + avb_slot_verify_data_calculate_vbmeta_digest(
  298 + slot_data, AVB_DIGEST_TYPE_SHA512, vbmeta_digest);
  299 + for (n = 0; n < slot_data->num_vbmeta_images; n++) {
  300 + total_size += slot_data->vbmeta_images[n].vbmeta_size;
  301 + }
  302 + if (!cmdline_append_option(
  303 + slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
  304 + !cmdline_append_uint64_base10(
  305 + slot_data, "androidboot.vbmeta.size", total_size) ||
  306 + !cmdline_append_hex(slot_data,
  307 + "androidboot.vbmeta.digest",
  308 + vbmeta_digest,
  309 + AVB_SHA512_DIGEST_SIZE)) {
  310 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  311 + goto out;
  312 + }
  313 + } break;
  314 + case _AVB_ALGORITHM_NUM_TYPES:
  315 + avb_assert_not_reached();
  316 + break;
  317 + }
  318 +
  319 + /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
  320 + if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
  321 + verity_mode = "disabled";
  322 + } else {
  323 + const char* dm_verity_mode;
  324 + char* new_ret;
  325 +
  326 + switch (hashtree_error_mode) {
  327 + case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
  328 + if (!cmdline_append_option(
  329 + slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
  330 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  331 + goto out;
  332 + }
  333 + verity_mode = "enforcing";
  334 + dm_verity_mode = "restart_on_corruption";
  335 + break;
  336 + case AVB_HASHTREE_ERROR_MODE_RESTART:
  337 + verity_mode = "enforcing";
  338 + dm_verity_mode = "restart_on_corruption";
  339 + break;
  340 + case AVB_HASHTREE_ERROR_MODE_EIO:
  341 + verity_mode = "eio";
  342 + /* For now there's no option to specify the EIO mode. So
  343 + * just use 'ignore_zero_blocks' since that's already set
  344 + * and dm-verity-target.c supports specifying this multiple
  345 + * times.
  346 + */
  347 + dm_verity_mode = "ignore_zero_blocks";
  348 + break;
  349 + case AVB_HASHTREE_ERROR_MODE_LOGGING:
  350 + verity_mode = "logging";
  351 + dm_verity_mode = "ignore_corruption";
  352 + break;
  353 + }
  354 + new_ret = avb_replace(
  355 + slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
  356 + avb_free(slot_data->cmdline);
  357 + slot_data->cmdline = new_ret;
  358 + if (slot_data->cmdline == NULL) {
  359 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  360 + goto out;
  361 + }
  362 + }
  363 + if (!cmdline_append_option(
  364 + slot_data, "androidboot.veritymode", verity_mode)) {
  365 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  366 + goto out;
  367 + }
  368 +
  369 + ret = AVB_SLOT_VERIFY_RESULT_OK;
  370 +
  371 +out:
  372 +
  373 + return ret;
  374 +}
  375 +
  376 +AvbCmdlineSubstList* avb_new_cmdline_subst_list() {
  377 + return (AvbCmdlineSubstList*)avb_calloc(sizeof(AvbCmdlineSubstList));
  378 +}
  379 +
  380 +void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst) {
  381 + size_t i;
  382 + for (i = 0; i < cmdline_subst->size; ++i) {
  383 + avb_free(cmdline_subst->tokens[i]);
  384 + avb_free(cmdline_subst->values[i]);
  385 + }
  386 + cmdline_subst->size = 0;
  387 + avb_free(cmdline_subst);
  388 +}
  389 +
  390 +AvbSlotVerifyResult avb_add_root_digest_substitution(
  391 + const char* part_name,
  392 + const uint8_t* digest,
  393 + size_t digest_size,
  394 + AvbCmdlineSubstList* out_cmdline_subst) {
  395 + const char* kDigestSubPrefix = "$(AVB_";
  396 + const char* kDigestSubSuffix = "_ROOT_DIGEST)";
  397 + size_t part_name_len = avb_strlen(part_name);
  398 + size_t list_index = out_cmdline_subst->size;
  399 +
  400 + avb_assert(part_name_len < AVB_PART_NAME_MAX_SIZE);
  401 + avb_assert(digest_size <= AVB_SHA512_DIGEST_SIZE);
  402 + if (part_name_len >= AVB_PART_NAME_MAX_SIZE ||
  403 + digest_size > AVB_SHA512_DIGEST_SIZE) {
  404 + return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  405 + }
  406 +
  407 + if (out_cmdline_subst->size >= AVB_MAX_NUM_CMDLINE_SUBST) {
  408 + /* The list is full. Currently dynamic growth of this list is not supported.
  409 + */
  410 + return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  411 + }
  412 +
  413 + /* Construct the token to replace in the command line based on the partition
  414 + * name. For partition 'foo', this will be '$(AVB_FOO_ROOT_DIGEST)'.
  415 + */
  416 + out_cmdline_subst->tokens[list_index] =
  417 + avb_strdupv(kDigestSubPrefix, part_name, kDigestSubSuffix, NULL);
  418 + if (out_cmdline_subst->tokens[list_index] == NULL) {
  419 + goto fail;
  420 + }
  421 + avb_uppercase(out_cmdline_subst->tokens[list_index]);
  422 +
  423 + /* The digest value is hex encoded when inserted in the command line. */
  424 + out_cmdline_subst->values[list_index] = avb_bin2hex(digest, digest_size);
  425 + if (out_cmdline_subst->values[list_index] == NULL) {
  426 + goto fail;
  427 + }
  428 +
  429 + out_cmdline_subst->size++;
  430 + return AVB_SLOT_VERIFY_RESULT_OK;
  431 +
  432 +fail:
  433 + if (out_cmdline_subst->tokens[list_index]) {
  434 + avb_free(out_cmdline_subst->tokens[list_index]);
  435 + }
  436 + if (out_cmdline_subst->values[list_index]) {
  437 + avb_free(out_cmdline_subst->values[list_index]);
  438 + }
  439 + return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  440 +}
lib/avb/libavb/avb_cmdline.h
  1 +/*
  2 + * Copyright (C) 2016 The Android Open Source Project
  3 + *
  4 + * Permission is hereby granted, free of charge, to any person
  5 + * obtaining a copy of this software and associated documentation
  6 + * files (the "Software"), to deal in the Software without
  7 + * restriction, including without limitation the rights to use, copy,
  8 + * modify, merge, publish, distribute, sublicense, and/or sell copies
  9 + * of the Software, and to permit persons to whom the Software is
  10 + * furnished to do so, subject to the following conditions:
  11 + *
  12 + * The above copyright notice and this permission notice shall be
  13 + * included in all copies or substantial portions of the Software.
  14 + *
  15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22 + * SOFTWARE.
  23 + */
  24 +
  25 +#ifdef AVB_INSIDE_LIBAVB_H
  26 +#error "You can't include avb_sha.h in the public header libavb.h."
  27 +#endif
  28 +
  29 +#ifndef AVB_COMPILATION
  30 +#error "Never include this file, it may only be used from internal avb code."
  31 +#endif
  32 +
  33 +#ifndef AVB_CMDLINE_H_
  34 +#define AVB_CMDLINE_H_
  35 +
  36 +#include "avb_ops.h"
  37 +#include "avb_slot_verify.h"
  38 +
  39 +/* Maximum allow length (in bytes) of a partition name, including
  40 + * ab_suffix.
  41 + */
  42 +#define AVB_PART_NAME_MAX_SIZE 32
  43 +
  44 +#define AVB_MAX_NUM_CMDLINE_SUBST 10
  45 +
  46 +/* Holds information about command-line substitutions. */
  47 +typedef struct AvbCmdlineSubstList {
  48 + size_t size;
  49 + char* tokens[AVB_MAX_NUM_CMDLINE_SUBST];
  50 + char* values[AVB_MAX_NUM_CMDLINE_SUBST];
  51 +} AvbCmdlineSubstList;
  52 +
  53 +/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
  54 + * values. Returns NULL on OOM, otherwise the cmdline with values
  55 + * replaced.
  56 + */
  57 +char* avb_sub_cmdline(AvbOps* ops,
  58 + const char* cmdline,
  59 + const char* ab_suffix,
  60 + bool using_boot_for_vbmeta,
  61 + const AvbCmdlineSubstList* additional_substitutions);
  62 +
  63 +AvbSlotVerifyResult avb_append_options(
  64 + AvbOps* ops,
  65 + AvbSlotVerifyData* slot_data,
  66 + AvbVBMetaImageHeader* toplevel_vbmeta,
  67 + AvbAlgorithmType algorithm_type,
  68 + AvbHashtreeErrorMode hashtree_error_mode);
  69 +
  70 +/* Allocates and initializes a new command line substitution list. Free with
  71 + * |avb_free_cmdline_subst_list|.
  72 + */
  73 +AvbCmdlineSubstList* avb_new_cmdline_subst_list(void);
  74 +
  75 +/* Use this instead of |avb_free| to deallocate a AvbCmdlineSubstList. */
  76 +void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst);
  77 +
  78 +/* Adds a hashtree root digest to be substituted in $(AVB_*_ROOT_DIGEST)
  79 + * variables. The partition name differentiates the variable. For example, if
  80 + * |part_name| is "foo" then $(AVB_FOO_ROOT_DIGEST) will be substituted with the
  81 + * hex encoding of the digest. The substitution will be added to
  82 + * |out_cmdline_subst|. Returns AVB_SLOT_VERIFY_RESULT_OK on success.
  83 + */
  84 +AvbSlotVerifyResult avb_add_root_digest_substitution(
  85 + const char* part_name,
  86 + const uint8_t* digest,
  87 + size_t digest_size,
  88 + AvbCmdlineSubstList* out_cmdline_subst);
  89 +
  90 +#endif
lib/avb/libavb/avb_crypto.c
... ... @@ -355,8 +355,7 @@
355 355 };
356 356  
357 357 const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm) {
358   - if (algorithm >= AVB_ALGORITHM_TYPE_NONE &&
359   - algorithm < _AVB_ALGORITHM_NUM_TYPES) {
  358 + if ((size_t)algorithm < _AVB_ALGORITHM_NUM_TYPES) {
360 359 return &algorithm_data[algorithm];
361 360 }
362 361 return NULL;
lib/avb/libavb/avb_crypto.h
... ... @@ -44,11 +44,20 @@
44 44 /* Size of a RSA-8192 signature. */
45 45 #define AVB_RSA8192_NUM_BYTES 1024
46 46  
  47 +/* Size in bytes of a SHA-1 digest. */
  48 +#define AVB_SHA1_DIGEST_SIZE 20
  49 +
47 50 /* Size in bytes of a SHA-256 digest. */
48 51 #define AVB_SHA256_DIGEST_SIZE 32
49 52  
50 53 /* Size in bytes of a SHA-512 digest. */
51 54 #define AVB_SHA512_DIGEST_SIZE 64
  55 +
  56 +/* Possible digest types supported by libavb routines. */
  57 +typedef enum {
  58 + AVB_DIGEST_TYPE_SHA256,
  59 + AVB_DIGEST_TYPE_SHA512,
  60 +} AvbDigestType;
52 61  
53 62 /* Algorithms that can be used in the vbmeta image for
54 63 * verification. An algorithm consists of a hash type and a signature
lib/avb/libavb/avb_hash_descriptor.c
... ... @@ -44,6 +44,7 @@
44 44 dest->partition_name_len = avb_be32toh(dest->partition_name_len);
45 45 dest->salt_len = avb_be32toh(dest->salt_len);
46 46 dest->digest_len = avb_be32toh(dest->digest_len);
  47 + dest->flags = avb_be32toh(dest->flags);
47 48  
48 49 /* Check that partition_name, salt, and digest are fully contained. */
49 50 expected_size = sizeof(AvbHashDescriptor) - sizeof(AvbDescriptor);
lib/avb/libavb/avb_hash_descriptor.h
... ... @@ -35,6 +35,16 @@
35 35 extern "C" {
36 36 #endif
37 37  
  38 +/* Flags for hash descriptors.
  39 + *
  40 + * AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B
  41 + * partition logic to this partition. This is intentionally a negative boolean
  42 + * because A/B should be both the default and most used in practice.
  43 + */
  44 +typedef enum {
  45 + AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
  46 +} AvbHashDescriptorFlags;
  47 +
38 48 /* A descriptor containing information about hash for an image.
39 49 *
40 50 * This descriptor is typically used for boot partitions to verify the
... ... @@ -46,6 +56,10 @@
46 56 *
47 57 * The |reserved| field is for future expansion and must be set to NUL
48 58 * bytes.
  59 + *
  60 + * Changes in v1.1:
  61 + * - flags field is added which supports AVB_HASH_DESCRIPTOR_FLAGS_USE_AB
  62 + * - digest_len may be zero, which indicates the use of a persistent digest
49 63 */
50 64 typedef struct AvbHashDescriptor {
51 65 AvbDescriptor parent_descriptor;
... ... @@ -54,7 +68,8 @@
54 68 uint32_t partition_name_len;
55 69 uint32_t salt_len;
56 70 uint32_t digest_len;
57   - uint8_t reserved[64];
  71 + uint32_t flags;
  72 + uint8_t reserved[60];
58 73 } AVB_ATTR_PACKED AvbHashDescriptor;
59 74  
60 75 /* Copies |src| to |dest| and validates, byte-swapping fields in the
lib/avb/libavb/avb_hashtree_descriptor.c
... ... @@ -52,6 +52,7 @@
52 52 dest->partition_name_len = avb_be32toh(dest->partition_name_len);
53 53 dest->salt_len = avb_be32toh(dest->salt_len);
54 54 dest->root_digest_len = avb_be32toh(dest->root_digest_len);
  55 + dest->flags = avb_be32toh(dest->flags);
55 56  
56 57 /* Check that partition_name, salt, and root_digest are fully contained. */
57 58 expected_size = sizeof(AvbHashtreeDescriptor) - sizeof(AvbDescriptor);
lib/avb/libavb/avb_hashtree_descriptor.h
... ... @@ -35,6 +35,16 @@
35 35 extern "C" {
36 36 #endif
37 37  
  38 +/* Flags for hashtree descriptors.
  39 + *
  40 + * AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B
  41 + * partition logic to this partition. This is intentionally a negative boolean
  42 + * because A/B should be both the default and most used in practice.
  43 + */
  44 +typedef enum {
  45 + AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
  46 +} AvbHashtreeDescriptorFlags;
  47 +
38 48 /* A descriptor containing information about a dm-verity hashtree.
39 49 *
40 50 * Hash-trees are used to verify large partitions typically containing
... ... @@ -48,6 +58,10 @@
48 58 *
49 59 * The |reserved| field is for future expansion and must be set to NUL
50 60 * bytes.
  61 + *
  62 + * Changes in v1.1:
  63 + * - flags field is added which supports AVB_HASHTREE_DESCRIPTOR_FLAGS_USE_AB
  64 + * - digest_len may be zero, which indicates the use of a persistent digest
51 65 */
52 66 typedef struct AvbHashtreeDescriptor {
53 67 AvbDescriptor parent_descriptor;
... ... @@ -64,7 +78,8 @@
64 78 uint32_t partition_name_len;
65 79 uint32_t salt_len;
66 80 uint32_t root_digest_len;
67   - uint8_t reserved[64];
  81 + uint32_t flags;
  82 + uint8_t reserved[60];
68 83 } AVB_ATTR_PACKED AvbHashtreeDescriptor;
69 84  
70 85 /* Copies |src| to |dest| and validates, byte-swapping fields in the
lib/avb/libavb/avb_ops.h
... ... @@ -35,6 +35,9 @@
35 35 extern "C" {
36 36 #endif
37 37  
  38 +/* Well-known names of named persistent values. */
  39 +#define AVB_NPV_PERSISTENT_DIGEST_PREFIX "avb.persistent_digest."
  40 +
38 41 /* Return codes used for I/O operations.
39 42 *
40 43 * AVB_IO_RESULT_OK is returned if the requested operation was
41 44  
... ... @@ -51,13 +54,25 @@
51 54 * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the
52 55 * range of bytes requested to be read or written is outside the range
53 56 * of the partition.
  57 + *
  58 + * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE is returned if a named persistent value
  59 + * does not exist.
  60 + *
  61 + * AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE is returned if a named persistent
  62 + * value size is not supported or does not match the expected size.
  63 + *
  64 + * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned if a buffer is too small
  65 + * for the requested operation.
54 66 */
55 67 typedef enum {
56 68 AVB_IO_RESULT_OK,
57 69 AVB_IO_RESULT_ERROR_OOM,
58 70 AVB_IO_RESULT_ERROR_IO,
59 71 AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
60   - AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION
  72 + AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION,
  73 + AVB_IO_RESULT_ERROR_NO_SUCH_VALUE,
  74 + AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE,
  75 + AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE,
61 76 } AvbIOResult;
62 77  
63 78 struct AvbOps;
... ... @@ -117,6 +132,27 @@
117 132 void* buffer,
118 133 size_t* out_num_read);
119 134  
  135 + /* Gets the starting pointer of a partition that is pre-loaded in memory, and
  136 + * save it to |out_pointer|. The preloaded partition is expected to be
  137 + * |num_bytes|, where the actual preloaded byte count is returned in
  138 + * |out_num_bytes_preloaded|. |out_num_bytes_preloaded| must be no larger than
  139 + * |num_bytes|.
  140 + *
  141 + * This provides an alternative way to access a partition that is preloaded
  142 + * into memory without a full memory copy. When this function pointer is not
  143 + * set (has value NULL), or when the |out_pointer| is set to NULL as a result,
  144 + * |read_from_partition| will be used as the fallback. This function is mainly
  145 + * used for accessing the entire partition content to calculate its hash.
  146 + *
  147 + * Preloaded partition data must outlive the lifespan of the
  148 + * |AvbSlotVerifyData| structure that |avb_slot_verify| outputs.
  149 + */
  150 + AvbIOResult (*get_preloaded_partition)(AvbOps* ops,
  151 + const char* partition,
  152 + size_t num_bytes,
  153 + uint8_t** out_pointer,
  154 + size_t* out_num_bytes_preloaded);
  155 +
120 156 /* Writes |num_bytes| from |bffer| at offset |offset| to partition
121 157 * with name |partition| (NUL-terminated UTF-8 string). If |offset|
122 158 * is negative, its absolute value should be interpreted as the
... ... @@ -219,6 +255,53 @@
219 255 AvbIOResult (*get_size_of_partition)(AvbOps* ops,
220 256 const char* partition,
221 257 uint64_t* out_size_num_bytes);
  258 +
  259 + /* Reads a persistent value corresponding to the given |name|. The value is
  260 + * returned in |out_buffer| which must point to |buffer_size| bytes. On
  261 + * success |out_num_bytes_read| contains the number of bytes read into
  262 + * |out_buffer|. If AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned,
  263 + * |out_num_bytes_read| contains the number of bytes that would have been read
  264 + * which can be used to allocate a buffer.
  265 + *
  266 + * The |buffer_size| may be zero and the |out_buffer| may be NULL, but if
  267 + * |out_buffer| is NULL then |buffer_size| *must* be zero.
  268 + *
  269 + * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
  270 + *
  271 + * If the value does not exist, is not supported, or is not populated, returns
  272 + * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If |buffer_size| is smaller than the
  273 + * size of the stored value, returns AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE.
  274 + *
  275 + * This operation is currently only used to support persistent digests. If a
  276 + * device does not use persistent digests this function pointer can be set to
  277 + * NULL.
  278 + */
  279 + AvbIOResult (*read_persistent_value)(AvbOps* ops,
  280 + const char* name,
  281 + size_t buffer_size,
  282 + uint8_t* out_buffer,
  283 + size_t* out_num_bytes_read);
  284 +
  285 + /* Writes a persistent value corresponding to the given |name|. The value is
  286 + * supplied in |value| which must point to |value_size| bytes. Any existing
  287 + * value with the same name is overwritten. If |value_size| is zero, future
  288 + * calls to |read_persistent_value| will return
  289 + * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE.
  290 + *
  291 + * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
  292 + *
  293 + * If the value |name| is not supported, returns
  294 + * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If the |value_size| is not supported,
  295 + * returns AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE.
  296 + *
  297 + * This operation is currently only used to support persistent digests. If a
  298 + * device does not use persistent digests this function pointer can be set to
  299 + * NULL.
  300 + */
  301 + AvbIOResult (*write_persistent_value)(AvbOps* ops,
  302 + const char* name,
  303 + size_t value_size,
  304 + const uint8_t* value);
222 305 };
223 306  
224 307 #ifdef __cplusplus
lib/avb/libavb/avb_slot_verify.c
Changes suppressed. Click to show
... ... @@ -24,19 +24,16 @@
24 24  
25 25 #include "avb_slot_verify.h"
26 26 #include "avb_chain_partition_descriptor.h"
  27 +#include "avb_cmdline.h"
27 28 #include "avb_footer.h"
28 29 #include "avb_hash_descriptor.h"
  30 +#include "avb_hashtree_descriptor.h"
29 31 #include "avb_kernel_cmdline_descriptor.h"
30 32 #include "avb_sha.h"
31 33 #include "avb_util.h"
32 34 #include "avb_vbmeta_image.h"
33 35 #include "avb_version.h"
34 36  
35   -/* Maximum allow length (in bytes) of a partition name, including
36   - * ab_suffix.
37   - */
38   -#define PART_NAME_MAX_SIZE 32
39   -
40 37 /* Maximum number of partitions that can be loaded with avb_slot_verify(). */
41 38 #define MAX_NUMBER_OF_LOADED_PARTITIONS 32
42 39  
... ... @@ -69,6 +66,114 @@
69 66 return false;
70 67 }
71 68  
  69 +static AvbSlotVerifyResult load_full_partition(AvbOps* ops,
  70 + const char* part_name,
  71 + uint64_t image_size,
  72 + uint8_t** out_image_buf,
  73 + bool* out_image_preloaded) {
  74 + size_t part_num_read;
  75 + AvbIOResult io_ret;
  76 +
  77 + /* Make sure that we do not overwrite existing data. */
  78 + avb_assert(*out_image_buf == NULL);
  79 + avb_assert(!*out_image_preloaded);
  80 +
  81 + /* We are going to implicitly cast image_size from uint64_t to size_t in the
  82 + * following code, so we need to make sure that the cast is safe. */
  83 + if (image_size != (size_t)(image_size)) {
  84 + avb_errorv(part_name, ": Partition size too large to load.\n", NULL);
  85 + return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  86 + }
  87 +
  88 + /* Try use a preloaded one. */
  89 + if (ops->get_preloaded_partition != NULL) {
  90 + io_ret = ops->get_preloaded_partition(
  91 + ops, part_name, image_size, out_image_buf, &part_num_read);
  92 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  93 + return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  94 + } else if (io_ret != AVB_IO_RESULT_OK) {
  95 + avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
  96 + return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  97 + }
  98 +
  99 + if (*out_image_buf != NULL) {
  100 + if (part_num_read != image_size) {
  101 + avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
  102 + return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  103 + }
  104 + *out_image_preloaded = true;
  105 + }
  106 + }
  107 +
  108 + /* Allocate and copy the partition. */
  109 + if (!*out_image_preloaded) {
  110 + *out_image_buf = avb_malloc(image_size);
  111 + if (*out_image_buf == NULL) {
  112 + return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  113 + }
  114 +
  115 + io_ret = ops->read_from_partition(ops,
  116 + part_name,
  117 + 0 /* offset */,
  118 + image_size,
  119 + *out_image_buf,
  120 + &part_num_read);
  121 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  122 + return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  123 + } else if (io_ret != AVB_IO_RESULT_OK) {
  124 + avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
  125 + return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  126 + }
  127 + if (part_num_read != image_size) {
  128 + avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
  129 + return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  130 + }
  131 + }
  132 +
  133 + return AVB_SLOT_VERIFY_RESULT_OK;
  134 +}
  135 +
  136 +static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops,
  137 + const char* part_name,
  138 + size_t expected_digest_size,
  139 + uint8_t* out_digest) {
  140 + char* persistent_value_name = NULL;
  141 + AvbIOResult io_ret = AVB_IO_RESULT_OK;
  142 + size_t stored_digest_size = 0;
  143 +
  144 + if (ops->read_persistent_value == NULL) {
  145 + avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
  146 + return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  147 + }
  148 + persistent_value_name =
  149 + avb_strdupv(AVB_NPV_PERSISTENT_DIGEST_PREFIX, part_name, NULL);
  150 + if (persistent_value_name == NULL) {
  151 + return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  152 + }
  153 + io_ret = ops->read_persistent_value(ops,
  154 + persistent_value_name,
  155 + expected_digest_size,
  156 + out_digest,
  157 + &stored_digest_size);
  158 + avb_free(persistent_value_name);
  159 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  160 + return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  161 + } else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
  162 + avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
  163 + return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  164 + } else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
  165 + io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE ||
  166 + expected_digest_size != stored_digest_size) {
  167 + avb_errorv(
  168 + part_name, ": Persistent digest is not of expected size.\n", NULL);
  169 + return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  170 + } else if (io_ret != AVB_IO_RESULT_OK) {
  171 + avb_errorv(part_name, ": Error reading persistent digest.\n", NULL);
  172 + return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  173 + }
  174 + return AVB_SLOT_VERIFY_RESULT_OK;
  175 +}
  176 +
72 177 static AvbSlotVerifyResult load_and_verify_hash_partition(
73 178 AvbOps* ops,
74 179 const char* const* requested_partitions,
75 180  
76 181  
... ... @@ -80,15 +185,18 @@
80 185 const uint8_t* desc_partition_name = NULL;
81 186 const uint8_t* desc_salt;
82 187 const uint8_t* desc_digest;
83   - char part_name[PART_NAME_MAX_SIZE];
  188 + char part_name[AVB_PART_NAME_MAX_SIZE];
84 189 AvbSlotVerifyResult ret;
85 190 AvbIOResult io_ret;
86 191 uint8_t* image_buf = NULL;
87   - size_t part_num_read;
  192 + bool image_preloaded = false;
88 193 uint8_t* digest;
89 194 size_t digest_len;
90 195 const char* found;
91 196 uint64_t image_size;
  197 + size_t expected_digest_len = 0;
  198 + uint8_t expected_digest_buf[AVB_SHA512_DIGEST_SIZE];
  199 + const uint8_t* expected_digest = NULL;
92 200  
93 201 if (!avb_hash_descriptor_validate_and_byteswap(
94 202 (const AvbHashDescriptor*)descriptor, &hash_desc)) {
95 203  
... ... @@ -118,15 +226,35 @@
118 226 goto out;
119 227 }
120 228  
121   - if (!avb_str_concat(part_name,
122   - sizeof part_name,
123   - (const char*)desc_partition_name,
124   - hash_desc.partition_name_len,
125   - ab_suffix,
126   - avb_strlen(ab_suffix))) {
127   - avb_error("Partition name and suffix does not fit.\n");
  229 + if ((hash_desc.flags & AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) != 0) {
  230 + /* No ab_suffix, just copy the partition name as is. */
  231 + if (hash_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
  232 + avb_error("Partition name does not fit.\n");
  233 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  234 + goto out;
  235 + }
  236 + avb_memcpy(part_name, desc_partition_name, hash_desc.partition_name_len);
  237 + part_name[hash_desc.partition_name_len] = '\0';
  238 + } else if (hash_desc.digest_len == 0 && avb_strlen(ab_suffix) != 0) {
  239 + /* No ab_suffix allowed for partitions without a digest in the descriptor
  240 + * because these partitions hold data unique to this device and are not
  241 + * updated using an A/B scheme.
  242 + */
  243 + avb_error("Cannot use A/B with a persistent digest.\n");
128 244 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
129 245 goto out;
  246 + } else {
  247 + /* Add ab_suffix to the partition name. */
  248 + if (!avb_str_concat(part_name,
  249 + sizeof part_name,
  250 + (const char*)desc_partition_name,
  251 + hash_desc.partition_name_len,
  252 + ab_suffix,
  253 + avb_strlen(ab_suffix))) {
  254 + avb_error("Partition name and suffix does not fit.\n");
  255 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  256 + goto out;
  257 + }
130 258 }
131 259  
132 260 /* If we're allowing verification errors then hash_desc.image_size
133 261  
... ... @@ -159,28 +287,12 @@
159 287 }
160 288 }
161 289  
162   - image_buf = avb_malloc(image_size);
163   - if (image_buf == NULL) {
164   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  290 + ret = load_full_partition(
  291 + ops, part_name, image_size, &image_buf, &image_preloaded);
  292 + if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
165 293 goto out;
166 294 }
167 295  
168   - io_ret = ops->read_from_partition(
169   - ops, part_name, 0 /* offset */, image_size, image_buf, &part_num_read);
170   - if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
171   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
172   - goto out;
173   - } else if (io_ret != AVB_IO_RESULT_OK) {
174   - avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
175   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
176   - goto out;
177   - }
178   - if (part_num_read != image_size) {
179   - avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
180   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
181   - goto out;
182   - }
183   -
184 296 if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
185 297 AvbSHA256Ctx sha256_ctx;
186 298 avb_sha256_init(&sha256_ctx);
187 299  
... ... @@ -201,14 +313,31 @@
201 313 goto out;
202 314 }
203 315  
204   - if (digest_len != hash_desc.digest_len) {
  316 + if (hash_desc.digest_len == 0) {
  317 + // Expect a match to a persistent digest.
  318 + avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
  319 + expected_digest_len = digest_len;
  320 + expected_digest = expected_digest_buf;
  321 + avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
  322 + ret =
  323 + read_persistent_digest(ops, part_name, digest_len, expected_digest_buf);
  324 + if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
  325 + goto out;
  326 + }
  327 + } else {
  328 + // Expect a match to the digest in the descriptor.
  329 + expected_digest_len = hash_desc.digest_len;
  330 + expected_digest = desc_digest;
  331 + }
  332 +
  333 + if (digest_len != expected_digest_len) {
205 334 avb_errorv(
206 335 part_name, ": Digest in descriptor not of expected size.\n", NULL);
207 336 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
208 337 goto out;
209 338 }
210 339  
211   - if (avb_safe_memcmp(digest, desc_digest, digest_len) != 0) {
  340 + if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
212 341 avb_errorv(part_name,
213 342 ": Hash of data does not match digest in descriptor.\n",
214 343 NULL);
215 344  
... ... @@ -234,11 +363,12 @@
234 363 loaded_partition->partition_name = avb_strdup(found);
235 364 loaded_partition->data_size = image_size;
236 365 loaded_partition->data = image_buf;
  366 + loaded_partition->preloaded = image_preloaded;
237 367 image_buf = NULL;
238 368 }
239 369  
240 370 fail:
241   - if (image_buf != NULL) {
  371 + if (image_buf != NULL && !image_preloaded) {
242 372 avb_free(image_buf);
243 373 }
244 374 return ret;
... ... @@ -251,6 +381,7 @@
251 381 AvbSlotVerifyData* slot_data) {
252 382 AvbSlotVerifyResult ret;
253 383 uint8_t* image_buf = NULL;
  384 + bool image_preloaded = false;
254 385 size_t n;
255 386  
256 387 if (ops->get_size_of_partition == NULL) {
257 388  
... ... @@ -260,10 +391,9 @@
260 391 }
261 392  
262 393 for (n = 0; requested_partitions[n] != NULL; n++) {
263   - char part_name[PART_NAME_MAX_SIZE];
  394 + char part_name[AVB_PART_NAME_MAX_SIZE];
264 395 AvbIOResult io_ret;
265 396 uint64_t image_size;
266   - size_t part_num_read;
267 397 AvbPartitionData* loaded_partition;
268 398  
269 399 if (!avb_str_concat(part_name,
270 400  
... ... @@ -288,28 +418,12 @@
288 418 }
289 419 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
290 420  
291   - image_buf = avb_malloc(image_size);
292   - if (image_buf == NULL) {
293   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  421 + ret = load_full_partition(
  422 + ops, part_name, image_size, &image_buf, &image_preloaded);
  423 + if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
294 424 goto out;
295 425 }
296 426  
297   - io_ret = ops->read_from_partition(
298   - ops, part_name, 0 /* offset */, image_size, image_buf, &part_num_read);
299   - if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
300   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
301   - goto out;
302   - } else if (io_ret != AVB_IO_RESULT_OK) {
303   - avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
304   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
305   - goto out;
306   - }
307   - if (part_num_read != image_size) {
308   - avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
309   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
310   - goto out;
311   - }
312   -
313 427 /* Move to slot_data. */
314 428 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
315 429 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
316 430  
317 431  
318 432  
... ... @@ -324,16 +438,21 @@
324 438 goto out;
325 439 }
326 440 loaded_partition->data_size = image_size;
327   - loaded_partition->data = image_buf;
  441 + loaded_partition->data = image_buf; /* Transferring the owner. */
  442 + loaded_partition->preloaded = image_preloaded;
328 443 image_buf = NULL;
  444 + image_preloaded = false;
329 445 }
330 446  
331 447 ret = AVB_SLOT_VERIFY_RESULT_OK;
332 448  
333 449 out:
334   - if (image_buf != NULL) {
  450 + /* Free the current buffer if any. */
  451 + if (image_buf != NULL && !image_preloaded) {
335 452 avb_free(image_buf);
336 453 }
  454 + /* Buffers that are already saved in slot_data will be handled by the caller
  455 + * even on failure. */
337 456 return ret;
338 457 }
339 458  
... ... @@ -349,8 +468,9 @@
349 468 const uint8_t* expected_public_key,
350 469 size_t expected_public_key_length,
351 470 AvbSlotVerifyData* slot_data,
352   - AvbAlgorithmType* out_algorithm_type) {
353   - char full_partition_name[PART_NAME_MAX_SIZE];
  471 + AvbAlgorithmType* out_algorithm_type,
  472 + AvbCmdlineSubstList* out_additional_cmdline_subst) {
  473 + char full_partition_name[AVB_PART_NAME_MAX_SIZE];
354 474 AvbSlotVerifyResult ret;
355 475 AvbIOResult io_ret;
356 476 size_t vbmeta_offset;
... ... @@ -485,7 +605,8 @@
485 605 NULL /* expected_public_key */,
486 606 0 /* expected_public_key_length */,
487 607 slot_data,
488   - out_algorithm_type);
  608 + out_algorithm_type,
  609 + out_additional_cmdline_subst);
489 610 goto out;
490 611 } else {
491 612 avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
... ... @@ -681,7 +802,8 @@
681 802 * checks that it matches what's in the hash descriptor.
682 803 *
683 804 * - hashtree descriptor: Do nothing since verification happens
684   - * on-the-fly from within the OS.
  805 + * on-the-fly from within the OS. (Unless the descriptor uses a
  806 + * persistent digest, in which case we need to find it).
685 807 *
686 808 * - chained partition descriptor: Load the footer, load the vbmeta
687 809 * image, verify vbmeta image (includes rollback checks, hash
... ... @@ -752,18 +874,20 @@
752 874 sizeof(AvbChainPartitionDescriptor);
753 875 chain_public_key = chain_partition_name + chain_desc.partition_name_len;
754 876  
755   - sub_ret = load_and_verify_vbmeta(ops,
756   - requested_partitions,
757   - ab_suffix,
758   - allow_verification_error,
759   - toplevel_vbmeta_flags,
760   - chain_desc.rollback_index_location,
761   - (const char*)chain_partition_name,
762   - chain_desc.partition_name_len,
763   - chain_public_key,
764   - chain_desc.public_key_len,
765   - slot_data,
766   - NULL /* out_algorithm_type */);
  877 + sub_ret =
  878 + load_and_verify_vbmeta(ops,
  879 + requested_partitions,
  880 + ab_suffix,
  881 + allow_verification_error,
  882 + toplevel_vbmeta_flags,
  883 + chain_desc.rollback_index_location,
  884 + (const char*)chain_partition_name,
  885 + chain_desc.partition_name_len,
  886 + chain_public_key,
  887 + chain_desc.public_key_len,
  888 + slot_data,
  889 + NULL, /* out_algorithm_type */
  890 + NULL /* out_additional_cmdline_subst */);
767 891 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
768 892 ret = sub_ret;
769 893 if (!result_should_continue(ret)) {
770 894  
... ... @@ -849,9 +973,90 @@
849 973 }
850 974 } break;
851 975  
852   - /* Explicit fall-through */
  976 + case AVB_DESCRIPTOR_TAG_HASHTREE: {
  977 + AvbHashtreeDescriptor hashtree_desc;
  978 +
  979 + if (!avb_hashtree_descriptor_validate_and_byteswap(
  980 + (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
  981 + avb_errorv(
  982 + full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
  983 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  984 + goto out;
  985 + }
  986 +
  987 + /* We only need to continue when there is no digest in the descriptor.
  988 + * This is because the only processing here is to find the digest and
  989 + * make it available on the kernel command line.
  990 + */
  991 + if (hashtree_desc.root_digest_len == 0) {
  992 + char part_name[AVB_PART_NAME_MAX_SIZE];
  993 + size_t digest_len = 0;
  994 + uint8_t digest_buf[AVB_SHA512_DIGEST_SIZE];
  995 + const uint8_t* desc_partition_name =
  996 + ((const uint8_t*)descriptors[n]) + sizeof(AvbHashtreeDescriptor);
  997 +
  998 + if (!avb_validate_utf8(desc_partition_name,
  999 + hashtree_desc.partition_name_len)) {
  1000 + avb_error("Partition name is not valid UTF-8.\n");
  1001 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  1002 + goto out;
  1003 + }
  1004 +
  1005 + /* No ab_suffix for partitions without a digest in the descriptor
  1006 + * because these partitions hold data unique to this device and are
  1007 + * not updated using an A/B scheme.
  1008 + */
  1009 + if ((hashtree_desc.flags &
  1010 + AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) == 0 &&
  1011 + avb_strlen(ab_suffix) != 0) {
  1012 + avb_error("Cannot use A/B with a persistent root digest.\n");
  1013 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  1014 + goto out;
  1015 + }
  1016 + if (hashtree_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
  1017 + avb_error("Partition name does not fit.\n");
  1018 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  1019 + goto out;
  1020 + }
  1021 + avb_memcpy(
  1022 + part_name, desc_partition_name, hashtree_desc.partition_name_len);
  1023 + part_name[hashtree_desc.partition_name_len] = '\0';
  1024 +
  1025 + /* Determine the expected digest size from the hash algorithm. */
  1026 + if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
  1027 + 0) {
  1028 + digest_len = AVB_SHA1_DIGEST_SIZE;
  1029 + } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
  1030 + "sha256") == 0) {
  1031 + digest_len = AVB_SHA256_DIGEST_SIZE;
  1032 + } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
  1033 + "sha512") == 0) {
  1034 + digest_len = AVB_SHA512_DIGEST_SIZE;
  1035 + } else {
  1036 + avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
  1037 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  1038 + goto out;
  1039 + }
  1040 +
  1041 + ret = read_persistent_digest(ops, part_name, digest_len, digest_buf);
  1042 + if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
  1043 + goto out;
  1044 + }
  1045 +
  1046 + if (out_additional_cmdline_subst) {
  1047 + ret =
  1048 + avb_add_root_digest_substitution(part_name,
  1049 + digest_buf,
  1050 + digest_len,
  1051 + out_additional_cmdline_subst);
  1052 + if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
  1053 + goto out;
  1054 + }
  1055 + }
  1056 + }
  1057 + } break;
  1058 +
853 1059 case AVB_DESCRIPTOR_TAG_PROPERTY:
854   - case AVB_DESCRIPTOR_TAG_HASHTREE:
855 1060 /* Do nothing. */
856 1061 break;
857 1062 }
... ... @@ -886,350 +1091,6 @@
886 1091 return ret;
887 1092 }
888 1093  
889   -#define NUM_GUIDS 3
890   -
891   -/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
892   - * values. Returns NULL on OOM, otherwise the cmdline with values
893   - * replaced.
894   - */
895   -static char* sub_cmdline(AvbOps* ops,
896   - const char* cmdline,
897   - const char* ab_suffix,
898   - bool using_boot_for_vbmeta) {
899   - const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
900   - const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
901   - "$(ANDROID_BOOT_PARTUUID)",
902   - "$(ANDROID_VBMETA_PARTUUID)"};
903   - char* ret = NULL;
904   - AvbIOResult io_ret;
905   -
906   - /* Special-case for when the top-level vbmeta struct is in the boot
907   - * partition.
908   - */
909   - if (using_boot_for_vbmeta) {
910   - part_name_str[2] = "boot";
911   - }
912   -
913   - /* Replace unique partition GUIDs */
914   - for (size_t n = 0; n < NUM_GUIDS; n++) {
915   - char part_name[PART_NAME_MAX_SIZE];
916   - char guid_buf[37];
917   -
918   - if (!avb_str_concat(part_name,
919   - sizeof part_name,
920   - part_name_str[n],
921   - avb_strlen(part_name_str[n]),
922   - ab_suffix,
923   - avb_strlen(ab_suffix))) {
924   - avb_error("Partition name and suffix does not fit.\n");
925   - goto fail;
926   - }
927   -
928   - io_ret = ops->get_unique_guid_for_partition(
929   - ops, part_name, guid_buf, sizeof guid_buf);
930   - if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
931   - return NULL;
932   - } else if (io_ret != AVB_IO_RESULT_OK) {
933   - avb_error("Error getting unique GUID for partition.\n");
934   - goto fail;
935   - }
936   -
937   - if (ret == NULL) {
938   - ret = avb_replace(cmdline, replace_str[n], guid_buf);
939   - } else {
940   - char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
941   - avb_free(ret);
942   - ret = new_ret;
943   - }
944   - if (ret == NULL) {
945   - goto fail;
946   - }
947   - }
948   -
949   - return ret;
950   -
951   -fail:
952   - if (ret != NULL) {
953   - avb_free(ret);
954   - }
955   - return NULL;
956   -}
957   -
958   -static int cmdline_append_option(AvbSlotVerifyData* slot_data,
959   - const char* key,
960   - const char* value) {
961   - size_t offset, key_len, value_len;
962   - char* new_cmdline;
963   -
964   - key_len = avb_strlen(key);
965   - value_len = avb_strlen(value);
966   -
967   - offset = 0;
968   - if (slot_data->cmdline != NULL) {
969   - offset = avb_strlen(slot_data->cmdline);
970   - if (offset > 0) {
971   - offset += 1;
972   - }
973   - }
974   -
975   - new_cmdline = avb_calloc(offset + key_len + value_len + 2);
976   - if (new_cmdline == NULL) {
977   - return 0;
978   - }
979   - if (offset > 0) {
980   - avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
981   - new_cmdline[offset - 1] = ' ';
982   - }
983   - avb_memcpy(new_cmdline + offset, key, key_len);
984   - new_cmdline[offset + key_len] = '=';
985   - avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
986   - if (slot_data->cmdline != NULL) {
987   - avb_free(slot_data->cmdline);
988   - }
989   - slot_data->cmdline = new_cmdline;
990   -
991   - return 1;
992   -}
993   -
994   -#define AVB_MAX_DIGITS_UINT64 32
995   -
996   -/* Writes |value| to |digits| in base 10 followed by a NUL byte.
997   - * Returns number of characters written excluding the NUL byte.
998   - */
999   -static size_t uint64_to_base10(uint64_t value,
1000   - char digits[AVB_MAX_DIGITS_UINT64]) {
1001   - char rev_digits[AVB_MAX_DIGITS_UINT64];
1002   - size_t n, num_digits;
1003   -
1004   - for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
1005   - rev_digits[num_digits++] = (value % 10) + '0';
1006   - value /= 10;
1007   - if (value == 0) {
1008   - break;
1009   - }
1010   - }
1011   -
1012   - for (n = 0; n < num_digits; n++) {
1013   - digits[n] = rev_digits[num_digits - 1 - n];
1014   - }
1015   - digits[n] = '\0';
1016   - return n;
1017   -}
1018   -
1019   -static int cmdline_append_version(AvbSlotVerifyData* slot_data,
1020   - const char* key,
1021   - uint64_t major_version,
1022   - uint64_t minor_version) {
1023   - char major_digits[AVB_MAX_DIGITS_UINT64];
1024   - char minor_digits[AVB_MAX_DIGITS_UINT64];
1025   - char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
1026   - size_t num_major_digits, num_minor_digits;
1027   -
1028   - num_major_digits = uint64_to_base10(major_version, major_digits);
1029   - num_minor_digits = uint64_to_base10(minor_version, minor_digits);
1030   - avb_memcpy(combined, major_digits, num_major_digits);
1031   - combined[num_major_digits] = '.';
1032   - avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
1033   - combined[num_major_digits + 1 + num_minor_digits] = '\0';
1034   -
1035   - return cmdline_append_option(slot_data, key, combined);
1036   -}
1037   -
1038   -static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
1039   - const char* key,
1040   - uint64_t value) {
1041   - char digits[AVB_MAX_DIGITS_UINT64];
1042   - uint64_to_base10(value, digits);
1043   - return cmdline_append_option(slot_data, key, digits);
1044   -}
1045   -
1046   -static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
1047   - const char* key,
1048   - const uint8_t* data,
1049   - size_t data_len) {
1050   - char hex_digits[17] = "0123456789abcdef";
1051   - char* hex_data;
1052   - int ret;
1053   - size_t n;
1054   -
1055   - hex_data = avb_malloc(data_len * 2 + 1);
1056   - if (hex_data == NULL) {
1057   - return 0;
1058   - }
1059   -
1060   - for (n = 0; n < data_len; n++) {
1061   - hex_data[n * 2] = hex_digits[data[n] >> 4];
1062   - hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
1063   - }
1064   - hex_data[n * 2] = '\0';
1065   -
1066   - ret = cmdline_append_option(slot_data, key, hex_data);
1067   - avb_free(hex_data);
1068   - return ret;
1069   -}
1070   -
1071   -static AvbSlotVerifyResult append_options(
1072   - AvbOps* ops,
1073   - AvbSlotVerifyData* slot_data,
1074   - AvbVBMetaImageHeader* toplevel_vbmeta,
1075   - AvbAlgorithmType algorithm_type,
1076   - AvbHashtreeErrorMode hashtree_error_mode) {
1077   - AvbSlotVerifyResult ret;
1078   - const char* verity_mode = NULL;
1079   - bool is_device_unlocked;
1080   - AvbIOResult io_ret;
1081   -
1082   - /* Add androidboot.vbmeta.device option. */
1083   - if (!cmdline_append_option(slot_data,
1084   - "androidboot.vbmeta.device",
1085   - "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
1086   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1087   - goto out;
1088   - }
1089   -
1090   - /* Add androidboot.vbmeta.avb_version option. */
1091   - if (!cmdline_append_version(slot_data,
1092   - "androidboot.vbmeta.avb_version",
1093   - AVB_VERSION_MAJOR,
1094   - AVB_VERSION_MINOR)) {
1095   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1096   - goto out;
1097   - }
1098   -
1099   - /* Set androidboot.avb.device_state to "locked" or "unlocked". */
1100   - io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
1101   - if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
1102   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1103   - goto out;
1104   - } else if (io_ret != AVB_IO_RESULT_OK) {
1105   - avb_error("Error getting device state.\n");
1106   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1107   - goto out;
1108   - }
1109   - if (!cmdline_append_option(slot_data,
1110   - "androidboot.vbmeta.device_state",
1111   - is_device_unlocked ? "unlocked" : "locked")) {
1112   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1113   - goto out;
1114   - }
1115   -
1116   - /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
1117   - * function as is used to sign vbmeta.
1118   - */
1119   - switch (algorithm_type) {
1120   - /* Explicit fallthrough. */
1121   - case AVB_ALGORITHM_TYPE_NONE:
1122   - case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
1123   - case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
1124   - case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
1125   - AvbSHA256Ctx ctx;
1126   - size_t n, total_size = 0;
1127   - avb_sha256_init(&ctx);
1128   - for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1129   - avb_sha256_update(&ctx,
1130   - slot_data->vbmeta_images[n].vbmeta_data,
1131   - slot_data->vbmeta_images[n].vbmeta_size);
1132   - total_size += slot_data->vbmeta_images[n].vbmeta_size;
1133   - }
1134   - if (!cmdline_append_option(
1135   - slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
1136   - !cmdline_append_uint64_base10(
1137   - slot_data, "androidboot.vbmeta.size", total_size) ||
1138   - !cmdline_append_hex(slot_data,
1139   - "androidboot.vbmeta.digest",
1140   - avb_sha256_final(&ctx),
1141   - AVB_SHA256_DIGEST_SIZE)) {
1142   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1143   - goto out;
1144   - }
1145   - } break;
1146   - /* Explicit fallthrough. */
1147   - case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
1148   - case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
1149   - case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
1150   - AvbSHA512Ctx ctx;
1151   - size_t n, total_size = 0;
1152   - avb_sha512_init(&ctx);
1153   - for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1154   - avb_sha512_update(&ctx,
1155   - slot_data->vbmeta_images[n].vbmeta_data,
1156   - slot_data->vbmeta_images[n].vbmeta_size);
1157   - total_size += slot_data->vbmeta_images[n].vbmeta_size;
1158   - }
1159   - if (!cmdline_append_option(
1160   - slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
1161   - !cmdline_append_uint64_base10(
1162   - slot_data, "androidboot.vbmeta.size", total_size) ||
1163   - !cmdline_append_hex(slot_data,
1164   - "androidboot.vbmeta.digest",
1165   - avb_sha512_final(&ctx),
1166   - AVB_SHA512_DIGEST_SIZE)) {
1167   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1168   - goto out;
1169   - }
1170   - } break;
1171   - case _AVB_ALGORITHM_NUM_TYPES:
1172   - avb_assert_not_reached();
1173   - break;
1174   - }
1175   -
1176   - /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
1177   - if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
1178   - verity_mode = "disabled";
1179   - } else {
1180   - const char* dm_verity_mode = NULL;
1181   - char* new_ret;
1182   -
1183   - switch (hashtree_error_mode) {
1184   - case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
1185   - if (!cmdline_append_option(
1186   - slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
1187   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1188   - goto out;
1189   - }
1190   - verity_mode = "enforcing";
1191   - dm_verity_mode = "restart_on_corruption";
1192   - break;
1193   - case AVB_HASHTREE_ERROR_MODE_RESTART:
1194   - verity_mode = "enforcing";
1195   - dm_verity_mode = "restart_on_corruption";
1196   - break;
1197   - case AVB_HASHTREE_ERROR_MODE_EIO:
1198   - verity_mode = "eio";
1199   - /* For now there's no option to specify the EIO mode. So
1200   - * just use 'ignore_zero_blocks' since that's already set
1201   - * and dm-verity-target.c supports specifying this multiple
1202   - * times.
1203   - */
1204   - dm_verity_mode = "ignore_zero_blocks";
1205   - break;
1206   - case AVB_HASHTREE_ERROR_MODE_LOGGING:
1207   - verity_mode = "logging";
1208   - dm_verity_mode = "ignore_corruption";
1209   - break;
1210   - }
1211   - new_ret = avb_replace(
1212   - slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
1213   - avb_free(slot_data->cmdline);
1214   - slot_data->cmdline = new_ret;
1215   - if (slot_data->cmdline == NULL) {
1216   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1217   - goto out;
1218   - }
1219   - }
1220   - if (!cmdline_append_option(
1221   - slot_data, "androidboot.veritymode", verity_mode)) {
1222   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1223   - goto out;
1224   - }
1225   -
1226   - ret = AVB_SLOT_VERIFY_RESULT_OK;
1227   -
1228   -out:
1229   -
1230   - return ret;
1231   -}
1232   -
1233 1094 AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
1234 1095 const char* const* requested_partitions,
1235 1096 const char* ab_suffix,
... ... @@ -1243,6 +1104,7 @@
1243 1104 AvbVBMetaImageHeader toplevel_vbmeta;
1244 1105 bool allow_verification_error =
1245 1106 (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
  1107 + AvbCmdlineSubstList* additional_cmdline_subst = NULL;
1246 1108  
1247 1109 /* Fail early if we're missing the AvbOps needed for slot verification.
1248 1110 *
... ... @@ -1254,7 +1116,6 @@
1254 1116 avb_assert(ops->validate_vbmeta_public_key != NULL);
1255 1117 avb_assert(ops->read_rollback_index != NULL);
1256 1118 avb_assert(ops->get_unique_guid_for_partition != NULL);
1257   - /* avb_assert(ops->get_size_of_partition != NULL); */
1258 1119  
1259 1120 if (out_data != NULL) {
1260 1121 *out_data = NULL;
... ... @@ -1288,6 +1149,12 @@
1288 1149 goto fail;
1289 1150 }
1290 1151  
  1152 + additional_cmdline_subst = avb_new_cmdline_subst_list();
  1153 + if (additional_cmdline_subst == NULL) {
  1154 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1155 + goto fail;
  1156 + }
  1157 +
1291 1158 ret = load_and_verify_vbmeta(ops,
1292 1159 requested_partitions,
1293 1160 ab_suffix,
... ... @@ -1299,7 +1166,8 @@
1299 1166 NULL /* expected_public_key */,
1300 1167 0 /* expected_public_key_length */,
1301 1168 slot_data,
1302   - &algorithm_type);
  1169 + &algorithm_type,
  1170 + additional_cmdline_subst);
1303 1171 if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1304 1172 goto fail;
1305 1173 }
1306 1174  
... ... @@ -1341,14 +1209,14 @@
1341 1209 goto fail;
1342 1210 }
1343 1211 } else {
1344   - /* Add options - any failure in append_options() is either an
  1212 + /* Add options - any failure in avb_append_options() is either an
1345 1213 * I/O or OOM error.
1346 1214 */
1347   - AvbSlotVerifyResult sub_ret = append_options(ops,
1348   - slot_data,
1349   - &toplevel_vbmeta,
1350   - algorithm_type,
1351   - hashtree_error_mode);
  1215 + AvbSlotVerifyResult sub_ret = avb_append_options(ops,
  1216 + slot_data,
  1217 + &toplevel_vbmeta,
  1218 + algorithm_type,
  1219 + hashtree_error_mode);
1352 1220 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1353 1221 ret = sub_ret;
1354 1222 goto fail;
1355 1223  
... ... @@ -1358,14 +1226,19 @@
1358 1226 /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1359 1227 if (slot_data->cmdline != NULL) {
1360 1228 char* new_cmdline;
1361   - new_cmdline = sub_cmdline(
1362   - ops, slot_data->cmdline, ab_suffix, using_boot_for_vbmeta);
1363   - if (new_cmdline == NULL) {
1364   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1365   - goto fail;
  1229 + new_cmdline = avb_sub_cmdline(ops,
  1230 + slot_data->cmdline,
  1231 + ab_suffix,
  1232 + using_boot_for_vbmeta,
  1233 + additional_cmdline_subst);
  1234 + if (new_cmdline != slot_data->cmdline) {
  1235 + if (new_cmdline == NULL) {
  1236 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1237 + goto fail;
  1238 + }
  1239 + avb_free(slot_data->cmdline);
  1240 + slot_data->cmdline = new_cmdline;
1366 1241 }
1367   - avb_free(slot_data->cmdline);
1368   - slot_data->cmdline = new_cmdline;
1369 1242 }
1370 1243  
1371 1244 if (out_data != NULL) {
... ... @@ -1375,6 +1248,9 @@
1375 1248 }
1376 1249 }
1377 1250  
  1251 + avb_free_cmdline_subst_list(additional_cmdline_subst);
  1252 + additional_cmdline_subst = NULL;
  1253 +
1378 1254 if (!allow_verification_error) {
1379 1255 avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1380 1256 }
... ... @@ -1385,6 +1261,9 @@
1385 1261 if (slot_data != NULL) {
1386 1262 avb_slot_verify_data_free(slot_data);
1387 1263 }
  1264 + if (additional_cmdline_subst != NULL) {
  1265 + avb_free_cmdline_subst_list(additional_cmdline_subst);
  1266 + }
1388 1267 return ret;
1389 1268 }
1390 1269  
... ... @@ -1415,7 +1294,7 @@
1415 1294 if (loaded_partition->partition_name != NULL) {
1416 1295 avb_free(loaded_partition->partition_name);
1417 1296 }
1418   - if (loaded_partition->data != NULL) {
  1297 + if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
1419 1298 avb_free(loaded_partition->data);
1420 1299 }
1421 1300 }
... ... @@ -1464,5 +1343,44 @@
1464 1343 }
1465 1344  
1466 1345 return ret;
  1346 +}
  1347 +
  1348 +void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
  1349 + AvbDigestType digest_type,
  1350 + uint8_t* out_digest) {
  1351 + bool ret = false;
  1352 + size_t n;
  1353 +
  1354 + switch (digest_type) {
  1355 + case AVB_DIGEST_TYPE_SHA256: {
  1356 + AvbSHA256Ctx ctx;
  1357 + avb_sha256_init(&ctx);
  1358 + for (n = 0; n < data->num_vbmeta_images; n++) {
  1359 + avb_sha256_update(&ctx,
  1360 + data->vbmeta_images[n].vbmeta_data,
  1361 + data->vbmeta_images[n].vbmeta_size);
  1362 + }
  1363 + avb_memcpy(out_digest, avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE);
  1364 + ret = true;
  1365 + } break;
  1366 +
  1367 + case AVB_DIGEST_TYPE_SHA512: {
  1368 + AvbSHA512Ctx ctx;
  1369 + avb_sha512_init(&ctx);
  1370 + for (n = 0; n < data->num_vbmeta_images; n++) {
  1371 + avb_sha512_update(&ctx,
  1372 + data->vbmeta_images[n].vbmeta_data,
  1373 + data->vbmeta_images[n].vbmeta_size);
  1374 + }
  1375 + avb_memcpy(out_digest, avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE);
  1376 + ret = true;
  1377 + } break;
  1378 +
  1379 + /* Do not add a 'default:' case here because of -Wswitch. */
  1380 + }
  1381 +
  1382 + if (!ret) {
  1383 + avb_fatal("Unknown digest type");
  1384 + }
1467 1385 }
lib/avb/libavb/avb_slot_verify.h
... ... @@ -114,7 +114,10 @@
114 114 /* AvbPartitionData contains data loaded from partitions when using
115 115 * avb_slot_verify(). The |partition_name| field contains the name of
116 116 * the partition (without A/B suffix), |data| points to the loaded
117   - * data which is |data_size| bytes long.
  117 + * data which is |data_size| bytes long. If |preloaded| is set to true,
  118 + * this structure dose not own |data|. The caller of |avb_slot_verify|
  119 + * needs to make sure that the preloaded data outlives this
  120 + * |AvbPartitionData| structure.
118 121 *
119 122 * Note that this is strictly less than the partition size - it's only
120 123 * the image stored there, not the entire partition nor any of the
... ... @@ -124,6 +127,7 @@
124 127 char* partition_name;
125 128 uint8_t* data;
126 129 size_t data_size;
  130 + bool preloaded;
127 131 } AvbPartitionData;
128 132  
129 133 /* AvbVBMetaData contains a vbmeta struct loaded from a partition when
... ... @@ -256,9 +260,15 @@
256 260 uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
257 261 } AvbSlotVerifyData;
258 262  
259   -/* Fast version of avb_slot_verify_data_free, this method will not
260   - * free bootimage */
261   -void avb_slot_verify_data_free_fast(AvbSlotVerifyData* data);
  263 +/* Calculates a digest of all vbmeta images in |data| using
  264 + * the digest indicated by |digest_type|. Stores the result
  265 + * in |out_digest| which must be large enough to hold a digest
  266 + * of the requested type.
  267 + */
  268 +void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
  269 + AvbDigestType digest_type,
  270 + uint8_t* out_digest);
  271 +
262 272 /* Frees a |AvbSlotVerifyData| including all data it points to. */
263 273 void avb_slot_verify_data_free(AvbSlotVerifyData* data);
264 274  
lib/avb/libavb/avb_sysdeps.h
... ... @@ -108,6 +108,10 @@
108 108 /* Returns the lenght of |str|, excluding the terminating NUL-byte. */
109 109 size_t avb_strlen(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
110 110  
  111 +/* Divide the |dividend| by 10 and saves back to the pointer. Return the
  112 + * remainder. */
  113 +uint32_t avb_div_by_10(uint64_t* dividend);
  114 +
111 115 #ifdef __cplusplus
112 116 }
113 117 #endif
lib/avb/libavb/avb_sysdeps_posix.c
... ... @@ -76,4 +76,10 @@
76 76 void avb_free(void* ptr) {
77 77 free(ptr);
78 78 }
  79 +
  80 +uint32_t avb_div_by_10(uint64_t* dividend) {
  81 + uint32_t rem = (uint32_t)(*dividend % 10);
  82 + *dividend /= 10;
  83 + return rem;
  84 +}
lib/avb/libavb/avb_sysdeps_uboot.c
1   -/*
2   - * Copyright (C) 2016 The Android Open Source Project
3   - *
4   - * Permission is hereby granted, free of charge, to any person
5   - * obtaining a copy of this software and associated documentation
6   - * files (the "Software"), to deal in the Software without
7   - * restriction, including without limitation the rights to use, copy,
8   - * modify, merge, publish, distribute, sublicense, and/or sell copies
9   - * of the Software, and to permit persons to whom the Software is
10   - * furnished to do so, subject to the following conditions:
11   - *
12   - * The above copyright notice and this permission notice shall be
13   - * included in all copies or substantial portions of the Software.
14   - *
15   - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16   - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17   - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18   - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19   - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20   - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21   - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   - * SOFTWARE.
23   - */
24   -
25   -#include <common.h>
26   -#include <stdlib.h>
27   -#include <linux/string.h>
28   -
29   -#include "avb_sysdeps.h"
30   -
31   -int avb_memcmp(const void* src1, const void* src2, size_t n) {
32   - return memcmp(src1, src2, n);
33   -}
34   -
35   -void* avb_memcpy(void* dest, const void* src, size_t n) {
36   - return memcpy(dest, src, n);
37   -}
38   -
39   -void* avb_memset(void* dest, const int c, size_t n) {
40   - return memset(dest, c, n);
41   -}
42   -
43   -int avb_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); }
44   -
45   -size_t avb_strlen(const char* str) { return strlen(str); }
46   -
47   -void avb_abort(void) { panic("avb_abort!\n"); }
48   -
49   -void avb_print(const char* message) { printf("%s", message); }
50   -
51   -void avb_printv(const char* message, ...) {
52   - va_list ap;
53   - const char* m;
54   -
55   - va_start(ap, message);
56   - for (m = message; m != NULL; m = va_arg(ap, const char*)) {
57   - printf("%s", m);
58   - }
59   - va_end(ap);
60   -}
61   -
62   -void* avb_malloc_(size_t size) { return malloc(size); }
63   -
64   -void avb_free(void* ptr) { free(ptr); }
lib/avb/libavb/avb_util.c
... ... @@ -299,7 +299,7 @@
299 299 char* new_str;
300 300 num_new = ret_len + num_before + replace_len + 1;
301 301 new_str = avb_malloc(num_new);
302   - if (ret == NULL) {
  302 + if (new_str == NULL) {
303 303 goto out;
304 304 }
305 305 avb_memcpy(new_str, ret, ret_len);
... ... @@ -324,7 +324,7 @@
324 324 size_t num_remaining = avb_strlen(str_after_last_replace);
325 325 size_t num_new = ret_len + num_remaining + 1;
326 326 char* new_str = avb_malloc(num_new);
327   - if (ret == NULL) {
  327 + if (new_str == NULL) {
328 328 goto out;
329 329 }
330 330 avb_memcpy(new_str, ret, ret_len);
... ... @@ -400,5 +400,32 @@
400 400 }
401 401 }
402 402 return str;
  403 +}
  404 +
  405 +void avb_uppercase(char* str) {
  406 + size_t i;
  407 + for (i = 0; str[i] != '\0'; ++i) {
  408 + if (str[i] <= 0x7A && str[i] >= 0x61) {
  409 + str[i] -= 0x20;
  410 + }
  411 + }
  412 +}
  413 +
  414 +char* avb_bin2hex(const uint8_t* data, size_t data_len) {
  415 + const char hex_digits[17] = "0123456789abcdef";
  416 + char* hex_data;
  417 + size_t n;
  418 +
  419 + hex_data = avb_malloc(data_len * 2 + 1);
  420 + if (hex_data == NULL) {
  421 + return NULL;
  422 + }
  423 +
  424 + for (n = 0; n < data_len; n++) {
  425 + hex_data[n * 2] = hex_digits[data[n] >> 4];
  426 + hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
  427 + }
  428 + hex_data[n * 2] = '\0';
  429 + return hex_data;
403 430 }
lib/avb/libavb/avb_util.h
... ... @@ -270,6 +270,16 @@
270 270 */
271 271 const char* avb_basename(const char* str);
272 272  
  273 +/* Converts any ascii lowercase characters in |str| to uppercase in-place.
  274 + * |str| must be NUL-terminated and valid UTF-8.
  275 + */
  276 +void avb_uppercase(char* str);
  277 +
  278 +/* Converts |data_len| bytes of |data| to hex and returns the result. Returns
  279 + * NULL on OOM. Caller must free the returned string with avb_free.
  280 + */
  281 +char* avb_bin2hex(const uint8_t* data, size_t data_len);
  282 +
273 283 #ifdef __cplusplus
274 284 }
275 285 #endif
lib/avb/libavb/avb_version.h
... ... @@ -37,7 +37,7 @@
37 37  
38 38 /* The version number of AVB - keep in sync with avbtool. */
39 39 #define AVB_VERSION_MAJOR 1
40   -#define AVB_VERSION_MINOR 0
  40 +#define AVB_VERSION_MINOR 1
41 41 #define AVB_VERSION_SUB 0
42 42  
43 43 /* Returns a NUL-terminated string for the libavb version in use. The
lib/avb/libavb_ab/avb_ab_flow.c
... ... @@ -406,307 +406,6 @@
406 406 return ret;
407 407 }
408 408  
409   -/* For legacy i.mx6/7, we won't enable A/B due to the limitation of
410   - * storage capacity, but we still want to verify boot/recovery with
411   - * AVB. */
412   -AvbABFlowResult avb_single_flow(AvbABOps* ab_ops,
413   - const char* const* requested_partitions,
414   - AvbSlotVerifyFlags flags,
415   - AvbHashtreeErrorMode hashtree_error_mode,
416   - AvbSlotVerifyData** out_data) {
417   - AvbOps* ops = ab_ops->ops;
418   - AvbSlotVerifyData* slot_data = NULL;
419   - AvbSlotVerifyData* data = NULL;
420   - AvbABFlowResult ret;
421   - bool saw_and_allowed_verification_error = false;
422   -
423   - /* Validate boot/recovery. */
424   - AvbSlotVerifyResult verify_result;
425   -
426   - verify_result = avb_slot_verify(ops,
427   - requested_partitions,
428   - "",
429   - flags,
430   - hashtree_error_mode,
431   - &slot_data);
432   - switch (verify_result) {
433   - case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
434   - ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
435   - goto out;
436   -
437   - case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
438   - ret = AVB_AB_FLOW_RESULT_ERROR_IO;
439   - goto out;
440   -
441   - case AVB_SLOT_VERIFY_RESULT_OK:
442   - break;
443   -
444   - case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
445   - case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
446   - /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
447   - * these mean game over.
448   - */
449   - ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
450   - goto out;
451   -
452   - /* explicit fallthrough. */
453   - case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
454   - case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
455   - case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
456   - if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
457   - /* Do nothing since we allow this. */
458   - avb_debugv("Allowing slot ",
459   - slot_suffixes[n],
460   - " which verified "
461   - "with result ",
462   - avb_slot_verify_result_to_string(verify_result),
463   - " because "
464   - "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
465   - "is set.\n",
466   - NULL);
467   - saw_and_allowed_verification_error = true;
468   - } else {
469   - ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
470   - goto out;
471   - }
472   - break;
473   -
474   - case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
475   - ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
476   - goto out;
477   - /* Do not add a 'default:' case here because of -Wswitch. */
478   - }
479   -
480   - avb_assert(slot_data != NULL);
481   - data = slot_data;
482   - slot_data = NULL;
483   - if (saw_and_allowed_verification_error) {
484   - avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
485   - ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
486   - } else {
487   - ret = AVB_AB_FLOW_RESULT_OK;
488   - }
489   -
490   -out:
491   - if (slot_data != NULL) {
492   - avb_slot_verify_data_free(slot_data);
493   - }
494   -
495   - if (out_data != NULL) {
496   - *out_data = data;
497   - } else {
498   - if (data != NULL) {
499   - avb_slot_verify_data_free(data);
500   - }
501   - }
502   -
503   - return ret;
504   -}
505   -
506   -AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
507   - const char* const* requested_partitions,
508   - AvbSlotVerifyFlags flags,
509   - AvbHashtreeErrorMode hashtree_error_mode,
510   - AvbSlotVerifyData** out_data) {
511   - AvbOps* ops = ab_ops->ops;
512   - AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
513   - AvbSlotVerifyData* data = NULL;
514   - AvbABFlowResult ret;
515   - AvbABData ab_data, ab_data_orig;
516   - size_t slot_index_to_boot, n;
517   - AvbIOResult io_ret;
518   - bool saw_and_allowed_verification_error = false;
519   - size_t target_slot;
520   - AvbSlotVerifyResult verify_result;
521   - bool set_slot_unbootable = false;
522   -
523   - io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
524   - if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
525   - ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
526   - goto out;
527   - } else if (io_ret != AVB_IO_RESULT_OK) {
528   - ret = AVB_AB_FLOW_RESULT_ERROR_IO;
529   - goto out;
530   - }
531   -
532   - slot_index_to_boot = 2; // Means not 0 or 1
533   - target_slot = (ab_data.slots[1].priority > ab_data.slots[0].priority? 1 : 0);
534   -
535   - for (n = 0; n < 2; n++) {
536   - if (!slot_is_bootable(&ab_data.slots[target_slot])) {
537   - target_slot = (target_slot == 1 ? 0 : 1);
538   - continue;
539   - }
540   - verify_result = avb_slot_verify(ops,
541   - requested_partitions,
542   - slot_suffixes[target_slot],
543   - flags,
544   - hashtree_error_mode,
545   - &slot_data[target_slot]);
546   - switch (verify_result) {
547   - case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
548   - ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
549   - goto out;
550   -
551   - case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
552   - ret = AVB_AB_FLOW_RESULT_ERROR_IO;
553   - goto out;
554   -
555   - case AVB_SLOT_VERIFY_RESULT_OK:
556   - slot_index_to_boot = target_slot;
557   - n = 2;
558   - break;
559   -
560   - case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
561   - case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
562   - /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
563   - * these mean game over.
564   - */
565   - set_slot_unbootable = true;
566   - break;
567   -
568   - /* explicit fallthrough. */
569   - case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
570   - case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
571   - case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
572   - if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
573   - /* Do nothing since we allow this. */
574   - avb_debugv("Allowing slot ",
575   - slot_suffixes[target_slot],
576   - " which verified "
577   - "with result ",
578   - avb_slot_verify_result_to_string(verify_result),
579   - " because "
580   - "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
581   - "is set.\n",
582   - NULL);
583   - saw_and_allowed_verification_error = true;
584   - slot_index_to_boot = target_slot;
585   - n = 2;
586   - } else {
587   - set_slot_unbootable = true;
588   - }
589   - break;
590   -
591   - case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
592   - ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
593   - goto out;
594   - /* Do not add a 'default:' case here because of -Wswitch. */
595   - }
596   -
597   - if (set_slot_unbootable) {
598   - avb_errorv("Error verifying slot ",
599   - slot_suffixes[target_slot],
600   - " with result ",
601   - avb_slot_verify_result_to_string(verify_result),
602   - " - setting unbootable.\n",
603   - NULL);
604   - slot_set_unbootable(&ab_data.slots[target_slot]);
605   - set_slot_unbootable = false;
606   - }
607   - /* switch to another slot */
608   - target_slot = (target_slot == 1 ? 0 : 1);
609   - }
610   -
611   - if (slot_index_to_boot == 2) {
612   - /* No bootable slots! */
613   - avb_error("No bootable slots found.\n");
614   - ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
615   - goto out;
616   - }
617   -
618   - /* Update stored rollback index such that the stored rollback index
619   - * is the largest value supporting all currently bootable slots. Do
620   - * this for every rollback index location.
621   - */
622   - for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
623   - uint64_t rollback_index_value = 0;
624   -
625   - if (slot_data[0] != NULL && slot_data[1] != NULL) {
626   - uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n];
627   - uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n];
628   - rollback_index_value =
629   - (a_rollback_index < b_rollback_index ? a_rollback_index
630   - : b_rollback_index);
631   - } else if (slot_data[0] != NULL) {
632   - rollback_index_value = slot_data[0]->rollback_indexes[n];
633   - } else if (slot_data[1] != NULL) {
634   - rollback_index_value = slot_data[1]->rollback_indexes[n];
635   - }
636   -
637   - if (rollback_index_value != 0) {
638   - uint64_t current_rollback_index_value;
639   - io_ret = ops->read_rollback_index(ops, n, &current_rollback_index_value);
640   - if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
641   - ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
642   - goto out;
643   - } else if (io_ret != AVB_IO_RESULT_OK) {
644   - avb_error("Error getting rollback index for slot.\n");
645   - ret = AVB_AB_FLOW_RESULT_ERROR_IO;
646   - goto out;
647   - }
648   - if (current_rollback_index_value != rollback_index_value) {
649   - io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
650   - if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
651   - ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
652   - goto out;
653   - } else if (io_ret != AVB_IO_RESULT_OK) {
654   - avb_error("Error setting stored rollback index.\n");
655   - ret = AVB_AB_FLOW_RESULT_ERROR_IO;
656   - goto out;
657   - }
658   - }
659   - }
660   - }
661   -
662   - /* Finally, select this slot. */
663   - avb_assert(slot_data[slot_index_to_boot] != NULL);
664   - data = slot_data[slot_index_to_boot];
665   - slot_data[slot_index_to_boot] = NULL;
666   - if (saw_and_allowed_verification_error) {
667   - avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
668   - ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
669   - } else {
670   - ret = AVB_AB_FLOW_RESULT_OK;
671   - }
672   -
673   - /* ... and decrement tries remaining, if applicable. */
674   - if (!ab_data.slots[slot_index_to_boot].successful_boot &&
675   - ab_data.slots[slot_index_to_boot].tries_remaining > 0) {
676   - ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
677   - }
678   -
679   -out:
680   - io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
681   - if (io_ret != AVB_IO_RESULT_OK) {
682   - if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
683   - ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
684   - } else {
685   - ret = AVB_AB_FLOW_RESULT_ERROR_IO;
686   - }
687   - if (data != NULL) {
688   - avb_slot_verify_data_free(data);
689   - data = NULL;
690   - }
691   - }
692   -
693   - for (n = 0; n < 2; n++) {
694   - if (slot_data[n] != NULL) {
695   - avb_slot_verify_data_free(slot_data[n]);
696   - }
697   - }
698   -
699   - if (out_data != NULL) {
700   - *out_data = data;
701   - } else {
702   - if (data != NULL) {
703   - avb_slot_verify_data_free(data);
704   - }
705   - }
706   -
707   - return ret;
708   -}
709   -
710 409 AvbIOResult avb_ab_mark_slot_active(AvbABOps* ab_ops,
711 410 unsigned int slot_number) {
712 411 AvbABData ab_data, ab_data_orig;
lib/avb/libavb_ab/avb_ab_flow.h
... ... @@ -223,19 +223,6 @@
223 223 AvbHashtreeErrorMode hashtree_error_mode,
224 224 AvbSlotVerifyData** out_data);
225 225  
226   -AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
227   - const char* const* requested_partitions,
228   - AvbSlotVerifyFlags flags,
229   - AvbHashtreeErrorMode hashtree_error_mode,
230   - AvbSlotVerifyData** out_data);
231   -/* This is for legacy i.mx6/7 which don't enable A/B but want to
232   - * verify boot/recovery with AVB */
233   -AvbABFlowResult avb_single_flow(AvbABOps* ab_ops,
234   - const char* const* requested_partitions,
235   - AvbSlotVerifyFlags flags,
236   - AvbHashtreeErrorMode hashtree_error_mode,
237   - AvbSlotVerifyData** out_data);
238   -
239 226 /* Marks the slot with the given slot number as active. Returns
240 227 * AVB_IO_RESULT_OK on success, error code otherwise.
241 228 *
lib/avb/libavb_ab/avb_ab_ops.h
... ... @@ -30,7 +30,7 @@
30 30 #ifndef AVB_AB_OPS_H_
31 31 #define AVB_AB_OPS_H_
32 32  
33   -#include "../libavb/libavb.h"
  33 +#include <libavb/libavb.h>
34 34  
35 35 #ifdef __cplusplus
36 36 extern "C" {
lib/avb/libavb_ab/libavb_ab.h
... ... @@ -25,7 +25,18 @@
25 25 #ifndef LIBAVB_AB_H_
26 26 #define LIBAVB_AB_H_
27 27  
28   -#include "../libavb/libavb.h"
  28 +#include <libavb/libavb.h>
  29 +
  30 +/* The libavb_ab/ and boot_control/ code has been marked for some time
  31 + * as experimental in anticipation of being removed in the future. It
  32 + * is now deprecated and to continue using it you must define
  33 + * AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED. It will be removed Jun
  34 + * 1 2018.
  35 + */
  36 +#ifndef AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED
  37 +#error \
  38 + "You must define AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED to use this library."
  39 +#endif
29 40  
30 41 /* The AVB_INSIDE_LIBAVB_AB_H preprocessor symbol is used to enforce
31 42 * library users to include only this file. All public interfaces, and
lib/avb/libavb_atx/avb_atx_ops.h
... ... @@ -30,9 +30,9 @@
30 30 #ifndef AVB_ATX_OPS_H_
31 31 #define AVB_ATX_OPS_H_
32 32  
33   -#include "../libavb/libavb.h"
  33 +#include <libavb/libavb.h>
34 34  
35   -#include "../libavb_atx/avb_atx_types.h"
  35 +#include "avb_atx_types.h"
36 36  
37 37 #ifdef __cplusplus
38 38 extern "C" {
... ... @@ -59,6 +59,22 @@
59 59 */
60 60 AvbIOResult (*read_permanent_attributes_hash)(
61 61 AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]);
  62 +
  63 + /* Provides the key version of a key used during verification. This may be
  64 + * useful for managing the minimum key version.
  65 + */
  66 + void (*set_key_version)(AvbAtxOps* atx_ops,
  67 + size_t rollback_index_location,
  68 + uint64_t key_version);
  69 +
  70 + /* Generates |num_bytes| random bytes and stores them in |output|,
  71 + * which must point to a buffer large enough to store the bytes.
  72 + *
  73 + * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
  74 + */
  75 + AvbIOResult (*get_random)(AvbAtxOps* atx_ops,
  76 + size_t num_bytes,
  77 + uint8_t* output);
62 78 };
63 79  
64 80 #ifdef __cplusplus
lib/avb/libavb_atx/avb_atx_types.h
... ... @@ -30,7 +30,7 @@
30 30 #ifndef AVB_ATX_TYPES_H_
31 31 #define AVB_ATX_TYPES_H_
32 32  
33   -#include "../libavb/libavb.h"
  33 +#include <libavb/libavb.h>
34 34  
35 35 #ifdef __cplusplus
36 36 extern "C" {
... ... @@ -39,6 +39,9 @@
39 39 /* Size in bytes of an Android Things product ID. */
40 40 #define AVB_ATX_PRODUCT_ID_SIZE 16
41 41  
  42 +/* Size in bytes of an Android Things unlock challenge. */
  43 +#define AVB_ATX_UNLOCK_CHALLENGE_SIZE 16
  44 +
42 45 /* Size in bytes of a serialized public key with a 4096-bit modulus. */
43 46 #define AVB_ATX_PUBLIC_KEY_SIZE (sizeof(AvbRSAPublicKeyHeader) + 1024)
44 47  
... ... @@ -70,6 +73,21 @@
70 73 AvbAtxCertificate product_intermediate_key_certificate;
71 74 AvbAtxCertificate product_signing_key_certificate;
72 75 } AVB_ATTR_PACKED AvbAtxPublicKeyMetadata;
  76 +
  77 +/* Data structure of an Android Things unlock challenge. */
  78 +typedef struct AvbAtxUnlockChallenge {
  79 + uint32_t version;
  80 + uint8_t product_id_hash[AVB_SHA256_DIGEST_SIZE];
  81 + uint8_t challenge[AVB_ATX_UNLOCK_CHALLENGE_SIZE];
  82 +} AVB_ATTR_PACKED AvbAtxUnlockChallenge;
  83 +
  84 +/* Data structure of an Android Things unlock credential. */
  85 +typedef struct AvbAtxUnlockCredential {
  86 + uint32_t version;
  87 + AvbAtxCertificate product_intermediate_key_certificate;
  88 + AvbAtxCertificate product_unlock_key_certificate;
  89 + uint8_t challenge_signature[AVB_RSA4096_NUM_BYTES];
  90 +} AVB_ATTR_PACKED AvbAtxUnlockCredential;
73 91  
74 92 #ifdef __cplusplus
75 93 }
lib/avb/libavb_atx/avb_atx_validate.c
... ... @@ -22,13 +22,16 @@
22 22 * SOFTWARE.
23 23 */
24 24  
25   -#include "../libavb_atx/avb_atx_validate.h"
  25 +#include "avb_atx_validate.h"
26 26  
27   -#include "../libavb/avb_rsa.h"
28   -#include "../libavb/avb_sha.h"
29   -#include "../libavb/avb_sysdeps.h"
30   -#include "../libavb/avb_util.h"
  27 +#include <libavb/avb_rsa.h>
  28 +#include <libavb/avb_sha.h>
  29 +#include <libavb/avb_sysdeps.h>
  30 +#include <libavb/avb_util.h>
31 31  
  32 +/* The most recent unlock challenge generated. */
  33 +static uint8_t last_unlock_challenge[AVB_ATX_UNLOCK_CHALLENGE_SIZE];
  34 +
32 35 /* Computes the SHA256 |hash| of |length| bytes of |data|. */
33 36 static void sha256(const uint8_t* data,
34 37 uint32_t length,
... ... @@ -59,7 +62,7 @@
59 62 /* Verifies structure and |expected_hash| of permanent |attributes|. */
60 63 static bool verify_permanent_attributes(
61 64 const AvbAtxPermanentAttributes* attributes,
62   - uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE]) {
  65 + const uint8_t expected_hash[AVB_SHA256_DIGEST_SIZE]) {
63 66 uint8_t hash[AVB_SHA256_DIGEST_SIZE];
64 67  
65 68 if (attributes->version != 1) {
... ... @@ -75,10 +78,11 @@
75 78 }
76 79  
77 80 /* Verifies the format, key version, usage, and signature of a certificate. */
78   -static bool verify_certificate(AvbAtxCertificate* certificate,
79   - uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
80   - uint64_t minimum_key_version,
81   - uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]) {
  81 +static bool verify_certificate(
  82 + const AvbAtxCertificate* certificate,
  83 + const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
  84 + uint64_t minimum_key_version,
  85 + const uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]) {
82 86 const AvbAlgorithmData* algorithm_data;
83 87 uint8_t certificate_hash[AVB_SHA512_DIGEST_SIZE];
84 88  
... ... @@ -115,9 +119,10 @@
115 119 }
116 120  
117 121 /* Verifies signature and fields of a PIK certificate. */
118   -static bool verify_pik_certificate(AvbAtxCertificate* certificate,
119   - uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
120   - uint64_t minimum_version) {
  122 +static bool verify_pik_certificate(
  123 + const AvbAtxCertificate* certificate,
  124 + const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
  125 + uint64_t minimum_version) {
121 126 uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
122 127  
123 128 sha256_str("com.google.android.things.vboot.ca", expected_usage);
124 129  
... ... @@ -131,10 +136,10 @@
131 136  
132 137 /* Verifies signature and fields of a PSK certificate. */
133 138 static bool verify_psk_certificate(
134   - AvbAtxCertificate* certificate,
135   - uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
  139 + const AvbAtxCertificate* certificate,
  140 + const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
136 141 uint64_t minimum_version,
137   - uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
  142 + const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
138 143 uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
139 144 uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
140 145  
141 146  
... ... @@ -148,12 +153,37 @@
148 153 if (0 != avb_safe_memcmp(certificate->signed_data.subject,
149 154 expected_subject,
150 155 AVB_SHA256_DIGEST_SIZE)) {
151   - avb_error("Product ID mismatch.\n");
  156 + avb_error("PSK: Product ID mismatch.\n");
152 157 return false;
153 158 }
154 159 return true;
155 160 }
156 161  
  162 +/* Verifies signature and fields of a PUK certificate. */
  163 +static bool verify_puk_certificate(
  164 + const AvbAtxCertificate* certificate,
  165 + const uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
  166 + uint64_t minimum_version,
  167 + const uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
  168 + uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
  169 + uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
  170 +
  171 + sha256_str("com.google.android.things.vboot.unlock", expected_usage);
  172 + if (!verify_certificate(
  173 + certificate, authority, minimum_version, expected_usage)) {
  174 + avb_error("Invalid PUK certificate.\n");
  175 + return false;
  176 + }
  177 + sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject);
  178 + if (0 != avb_safe_memcmp(certificate->signed_data.subject,
  179 + expected_subject,
  180 + AVB_SHA256_DIGEST_SIZE)) {
  181 + avb_error("PUK: Product ID mismatch.\n");
  182 + return false;
  183 + }
  184 + return true;
  185 +}
  186 +
157 187 AvbIOResult avb_atx_validate_vbmeta_public_key(
158 188 AvbOps* ops,
159 189 const uint8_t* public_key_data,
... ... @@ -238,6 +268,131 @@
238 268 public_key_data,
239 269 AVB_ATX_PUBLIC_KEY_SIZE)) {
240 270 avb_error("Public key mismatch.\n");
  271 + return AVB_IO_RESULT_OK;
  272 + }
  273 +
  274 + /* Report the key versions used during verification. */
  275 + ops->atx_ops->set_key_version(
  276 + ops->atx_ops,
  277 + AVB_ATX_PIK_VERSION_LOCATION,
  278 + metadata.product_intermediate_key_certificate.signed_data.key_version);
  279 + ops->atx_ops->set_key_version(
  280 + ops->atx_ops,
  281 + AVB_ATX_PSK_VERSION_LOCATION,
  282 + metadata.product_signing_key_certificate.signed_data.key_version);
  283 +
  284 + *out_is_trusted = true;
  285 + return AVB_IO_RESULT_OK;
  286 +}
  287 +
  288 +AvbIOResult avb_atx_generate_unlock_challenge(
  289 + AvbAtxOps* atx_ops, AvbAtxUnlockChallenge* out_unlock_challenge) {
  290 + AvbIOResult result = AVB_IO_RESULT_OK;
  291 + AvbAtxPermanentAttributes permanent_attributes;
  292 +
  293 + /* We need the permanent attributes to compute the product_id_hash. */
  294 + result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes);
  295 + if (result != AVB_IO_RESULT_OK) {
  296 + avb_error("Failed to read permanent attributes.\n");
  297 + return result;
  298 + }
  299 + result = atx_ops->get_random(
  300 + atx_ops, AVB_ATX_UNLOCK_CHALLENGE_SIZE, last_unlock_challenge);
  301 + if (result != AVB_IO_RESULT_OK) {
  302 + avb_error("Failed to generate random challenge.\n");
  303 + return result;
  304 + }
  305 + out_unlock_challenge->version = 1;
  306 + sha256(permanent_attributes.product_id,
  307 + AVB_ATX_PRODUCT_ID_SIZE,
  308 + out_unlock_challenge->product_id_hash);
  309 + avb_memcpy(out_unlock_challenge->challenge,
  310 + last_unlock_challenge,
  311 + AVB_ATX_UNLOCK_CHALLENGE_SIZE);
  312 + return result;
  313 +}
  314 +
  315 +AvbIOResult avb_atx_validate_unlock_credential(
  316 + AvbAtxOps* atx_ops,
  317 + const AvbAtxUnlockCredential* unlock_credential,
  318 + bool* out_is_trusted) {
  319 + AvbIOResult result = AVB_IO_RESULT_OK;
  320 + AvbAtxPermanentAttributes permanent_attributes;
  321 + uint8_t permanent_attributes_hash[AVB_SHA256_DIGEST_SIZE];
  322 + uint64_t minimum_version;
  323 + const AvbAlgorithmData* algorithm_data;
  324 + uint8_t challenge_hash[AVB_SHA512_DIGEST_SIZE];
  325 +
  326 + /* Be pessimistic so we can exit early without having to remember to clear.
  327 + */
  328 + *out_is_trusted = false;
  329 +
  330 + /* Sanity check the credential. */
  331 + if (unlock_credential->version != 1) {
  332 + avb_error("Unsupported unlock credential format.\n");
  333 + return AVB_IO_RESULT_OK;
  334 + }
  335 +
  336 + /* Read and verify permanent attributes. */
  337 + result = atx_ops->read_permanent_attributes(atx_ops, &permanent_attributes);
  338 + if (result != AVB_IO_RESULT_OK) {
  339 + avb_error("Failed to read permanent attributes.\n");
  340 + return result;
  341 + }
  342 + result = atx_ops->read_permanent_attributes_hash(atx_ops,
  343 + permanent_attributes_hash);
  344 + if (result != AVB_IO_RESULT_OK) {
  345 + avb_error("Failed to read permanent attributes hash.\n");
  346 + return result;
  347 + }
  348 + if (!verify_permanent_attributes(&permanent_attributes,
  349 + permanent_attributes_hash)) {
  350 + return AVB_IO_RESULT_OK;
  351 + }
  352 +
  353 + /* Verify the PIK certificate. */
  354 + result = atx_ops->ops->read_rollback_index(
  355 + atx_ops->ops, AVB_ATX_PIK_VERSION_LOCATION, &minimum_version);
  356 + if (result != AVB_IO_RESULT_OK) {
  357 + avb_error("Failed to read PIK minimum version.\n");
  358 + return result;
  359 + }
  360 + if (!verify_pik_certificate(
  361 + &unlock_credential->product_intermediate_key_certificate,
  362 + permanent_attributes.product_root_public_key,
  363 + minimum_version)) {
  364 + return AVB_IO_RESULT_OK;
  365 + }
  366 +
  367 + /* Verify the PUK certificate. The minimum version is shared with the PSK. */
  368 + result = atx_ops->ops->read_rollback_index(
  369 + atx_ops->ops, AVB_ATX_PSK_VERSION_LOCATION, &minimum_version);
  370 + if (result != AVB_IO_RESULT_OK) {
  371 + avb_error("Failed to read PSK minimum version.\n");
  372 + return result;
  373 + }
  374 + if (!verify_puk_certificate(
  375 + &unlock_credential->product_unlock_key_certificate,
  376 + unlock_credential->product_intermediate_key_certificate.signed_data
  377 + .public_key,
  378 + minimum_version,
  379 + permanent_attributes.product_id)) {
  380 + return AVB_IO_RESULT_OK;
  381 + }
  382 +
  383 + /* Verify the challenge signature. */
  384 + algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
  385 + sha512(last_unlock_challenge, AVB_ATX_UNLOCK_CHALLENGE_SIZE, challenge_hash);
  386 + if (!avb_rsa_verify(unlock_credential->product_unlock_key_certificate
  387 + .signed_data.public_key,
  388 + AVB_ATX_PUBLIC_KEY_SIZE,
  389 + unlock_credential->challenge_signature,
  390 + AVB_RSA4096_NUM_BYTES,
  391 + challenge_hash,
  392 + AVB_SHA512_DIGEST_SIZE,
  393 + algorithm_data->padding,
  394 + algorithm_data->padding_len)) {
  395 + avb_error("Invalid unlock challenge signature.\n");
241 396 return AVB_IO_RESULT_OK;
242 397 }
243 398  
lib/avb/libavb_atx/avb_atx_validate.h
... ... @@ -30,8 +30,8 @@
30 30 #ifndef AVB_ATX_VALIDATE_H_
31 31 #define AVB_ATX_VALIDATE_H_
32 32  
33   -#include "../libavb_atx/avb_atx_ops.h"
34   -#include "../libavb_atx/avb_atx_types.h"
  33 +#include "avb_atx_ops.h"
  34 +#include "avb_atx_types.h"
35 35  
36 36 #ifdef __cplusplus
37 37 extern "C" {
... ... @@ -68,6 +68,20 @@
68 68 size_t public_key_length,
69 69 const uint8_t* public_key_metadata,
70 70 size_t public_key_metadata_length,
  71 + bool* out_is_trusted);
  72 +
  73 +/* Generates a challenge which can be used to create an unlock credential. */
  74 +AvbIOResult avb_atx_generate_unlock_challenge(
  75 + AvbAtxOps* atx_ops, AvbAtxUnlockChallenge* out_unlock_challenge);
  76 +
  77 +/* Validates an unlock credential. The certificate validation is very similar to
  78 + * the validation of public key metadata except in place of the PSK is a Product
  79 + * Unlock Key (PUK) and the certificate usage field identifies it as such. The
  80 + * challenge signature field is verified against this PUK.
  81 + */
  82 +AvbIOResult avb_atx_validate_unlock_credential(
  83 + AvbAtxOps* atx_ops,
  84 + const AvbAtxUnlockCredential* unlock_credential,
71 85 bool* out_is_trusted);
72 86  
73 87 #ifdef __cplusplus
lib/avb/libavb_atx/libavb_atx.h
... ... @@ -25,7 +25,7 @@
25 25 #ifndef LIBAVB_ATX_H_
26 26 #define LIBAVB_ATX_H_
27 27  
28   -#include "../libavb/libavb.h"
  28 +#include <libavb/libavb.h>
29 29  
30 30 /* The AVB_INSIDE_LIBAVB_ATX_H preprocessor symbol is used to enforce
31 31 * library users to include only this file. All public interfaces, and