Commit af28e08a9b96267c1e70cf8713b20bbff04892da

Authored by Luo Ji
Committed by zhang sanshan
1 parent 6471b146da

MA-11362 [Android] Update AVB lib in u-boot

This commit did:
1. Sync the AVB lib with external/avb with commit head:
   commit 8a8103513dea5c47037200beabad2a307f09ecc8
   Merge: 2ee8dbe 852858e
   Author: David Zeuthen <zeuthen@google.com>
   Date:   Fri Jun 30 16:08:03 2017 +0000
   	Revert "avbtool: Avoid using $(ANDROID_VERITY_MODE) for now."
	am: 1b2f7a64e2
	am: 852858e2ed
2. Fix build error and implement ops function
   fsl_get_size_of_partition().

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

Showing 13 changed files with 762 additions and 312 deletions Side-by-side Diff

drivers/usb/gadget/f_fastboot.c
... ... @@ -1304,7 +1304,8 @@
1304 1304 .read_rollback_index = fsl_read_rollback_index_rpmb,
1305 1305 .write_rollback_index = fsl_write_rollback_index_rpmb,
1306 1306 .read_is_device_unlocked = fsl_read_is_device_unlocked,
1307   - .get_unique_guid_for_partition = fsl_get_unique_guid_for_partition
  1307 + .get_unique_guid_for_partition = fsl_get_unique_guid_for_partition,
  1308 + .get_size_of_partition = fsl_get_size_of_partition
1308 1309 };
1309 1310 #endif
1310 1311  
... ... @@ -1555,7 +1556,8 @@
1555 1556 bool allow_fail = (lock_status == FASTBOOT_UNLOCK ? true : false);
1556 1557 avb_metric = get_timer(0);
1557 1558 /* if in lock state, do avb verify */
1558   - avb_result = avb_ab_flow_fast(&fsl_avb_ab_ops, requested_partitions, allow_fail, &avb_out_data);
  1559 + avb_result = avb_ab_flow_fast(&fsl_avb_ab_ops, requested_partitions, allow_fail,
  1560 + AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_out_data);
1559 1561 /* get the duration of avb */
1560 1562 metrics.avb = get_timer(avb_metric);
1561 1563  
... ... @@ -139,6 +139,14 @@
139 139 char* guid_buf,
140 140 size_t guid_buf_size);
141 141  
  142 +/* Gets the size of a partition with the name in |partition|
  143 + * (NUL-terminated UTF-8 string). Returns the value in
  144 + * |out_size_num_bytes|.
  145 + * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
  146 + */
  147 +AvbIOResult fsl_get_size_of_partition(AvbOps* ops,
  148 + const char* partition,
  149 + uint64_t* out_size_num_bytes);
142 150 /* check if the fastboot getvar cmd is for query [avb] bootctl's slot var
143 151 * cmd is the fastboot getvar's cmd in
144 152 * return true if it is a bootctl related cmd, false if it's not.
lib/avb/fsl/fsl_avb.c
... ... @@ -410,5 +410,24 @@
410 410 #else
411 411 return AVB_IO_RESULT_ERROR_IO;
412 412 #endif
  413 +
  414 +}
  415 +/* Gets the size of a partition with the name in |partition|
  416 + * (NUL-terminated UTF-8 string). Returns the value in
  417 + * |out_size_num_bytes|.
  418 + * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
  419 + */
  420 +AvbIOResult fsl_get_size_of_partition(AvbOps* ops,
  421 + const char* partition,
  422 + uint64_t* out_size_num_bytes)
  423 +{
  424 + struct fastboot_ptentry *pte;
  425 + pte = fastboot_flash_find_ptn(partition);
  426 + if (!pte) {
  427 + ERR("no %s partition\n", partition);
  428 + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
  429 + }
  430 + *out_size_num_bytes = (uint64_t)(pte->length * 512);
  431 + return AVB_IO_RESULT_OK;
413 432 }
lib/avb/libavb/avb_crc32.c
... ... @@ -43,10 +43,11 @@
43 43 */
44 44  
45 45 #include "avb_sysdeps.h"
  46 +#include "avb_util.h"
46 47  
47 48 /* Code taken from FreeBSD 8 */
48 49  
49   -static uint32_t crc32_tab[] = {
  50 +static uint32_t iavb_crc32_tab[] = {
50 51 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
51 52 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
52 53 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
53 54  
54 55  
... ... @@ -98,17 +99,17 @@
98 99 * in sys/libkern.h, where it can be inlined.
99 100 */
100 101  
101   -static uint32_t _crc32(uint32_t crc_in, const uint8_t* buf, int size) {
  102 +static uint32_t iavb_crc32(uint32_t crc_in, const uint8_t* buf, int size) {
102 103 const uint8_t* p = buf;
103 104 uint32_t crc;
104 105  
105 106 crc = crc_in ^ ~0U;
106 107 while (size--)
107   - crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
  108 + crc = iavb_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
108 109 return crc ^ ~0U;
109 110 }
110 111  
111 112 uint32_t avb_crc32(const uint8_t* buf, size_t size) {
112   - return _crc32(0, buf, size);
  113 + return iavb_crc32(0, buf, size);
113 114 }
lib/avb/libavb/avb_ops.h
... ... @@ -71,6 +71,10 @@
71 71  
72 72 /* High-level operations/functions/methods that are platform
73 73 * dependent.
  74 + *
  75 + * Operations may be added in the future so when implementing it
  76 + * always make sure to zero out sizeof(AvbOps) bytes of the struct to
  77 + * ensure that unimplemented operations are set to NULL.
74 78 */
75 79 struct AvbOps {
76 80 /* This pointer can be used by the application/bootloader using
... ... @@ -205,6 +209,16 @@
205 209 const char* partition,
206 210 char* guid_buf,
207 211 size_t guid_buf_size);
  212 +
  213 + /* Gets the size of a partition with the name in |partition|
  214 + * (NUL-terminated UTF-8 string). Returns the value in
  215 + * |out_size_num_bytes|.
  216 + *
  217 + * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
  218 + */
  219 + AvbIOResult (*get_size_of_partition)(AvbOps* ops,
  220 + const char* partition,
  221 + uint64_t* out_size_num_bytes);
208 222 };
209 223  
210 224 #ifdef __cplusplus
lib/avb/libavb/avb_rsa.c
... ... @@ -37,16 +37,16 @@
37 37 #include "avb_util.h"
38 38 #include "avb_vbmeta_image.h"
39 39  
40   -typedef struct Key {
  40 +typedef struct IAvbKey {
41 41 unsigned int len; /* Length of n[] in number of uint32_t */
42 42 uint32_t n0inv; /* -1 / n[0] mod 2^32 */
43 43 uint32_t* n; /* modulus as array (host-byte order) */
44 44 uint32_t* rr; /* R^2 as array (host-byte order) */
45   -} Key;
  45 +} IAvbKey;
46 46  
47   -Key* parse_key_data(const uint8_t* data, size_t length) {
  47 +static IAvbKey* iavb_parse_key_data(const uint8_t* data, size_t length) {
48 48 AvbRSAPublicKeyHeader h;
49   - Key* key = NULL;
  49 + IAvbKey* key = NULL;
50 50 size_t expected_length;
51 51 unsigned int i;
52 52 const uint8_t* n;
53 53  
... ... @@ -76,14 +76,14 @@
76 76 /* Store n and rr following the key header so we only have to do one
77 77 * allocation.
78 78 */
79   - key = (Key*)(avb_malloc(sizeof(Key) + 2 * h.key_num_bits / 8));
  79 + key = (IAvbKey*)(avb_malloc(sizeof(IAvbKey) + 2 * h.key_num_bits / 8));
80 80 if (key == NULL) {
81 81 goto fail;
82 82 }
83 83  
84 84 key->len = h.key_num_bits / 32;
85 85 key->n0inv = h.n0inv;
86   - key->n = (uint32_t*)(key + 1); /* Skip ahead sizeof(Key) bytes. */
  86 + key->n = (uint32_t*)(key + 1); /* Skip ahead sizeof(IAvbKey) bytes. */
87 87 key->rr = key->n + key->len;
88 88  
89 89 /* Crypto-code below (modpowF4() and friends) expects the key in
90 90  
... ... @@ -103,12 +103,12 @@
103 103 return NULL;
104 104 }
105 105  
106   -void free_parsed_key(Key* key) {
  106 +static void iavb_free_parsed_key(IAvbKey* key) {
107 107 avb_free(key);
108 108 }
109 109  
110 110 /* a[] -= mod */
111   -static void subM(const Key* key, uint32_t* a) {
  111 +static void subM(const IAvbKey* key, uint32_t* a) {
112 112 int64_t A = 0;
113 113 uint32_t i;
114 114 for (i = 0; i < key->len; ++i) {
... ... @@ -119,7 +119,7 @@
119 119 }
120 120  
121 121 /* return a[] >= mod */
122   -static int geM(const Key* key, uint32_t* a) {
  122 +static int geM(const IAvbKey* key, uint32_t* a) {
123 123 uint32_t i;
124 124 for (i = key->len; i;) {
125 125 --i;
... ... @@ -134,7 +134,7 @@
134 134 }
135 135  
136 136 /* montgomery c[] += a * b[] / R % mod */
137   -static void montMulAdd(const Key* key,
  137 +static void montMulAdd(const IAvbKey* key,
138 138 uint32_t* c,
139 139 const uint32_t a,
140 140 const uint32_t* b) {
... ... @@ -159,7 +159,7 @@
159 159 }
160 160  
161 161 /* montgomery c[] = a[] * b[] / R % mod */
162   -static void montMul(const Key* key, uint32_t* c, uint32_t* a, uint32_t* b) {
  162 +static void montMul(const IAvbKey* key, uint32_t* c, uint32_t* a, uint32_t* b) {
163 163 uint32_t i;
164 164 for (i = 0; i < key->len; ++i) {
165 165 c[i] = 0;
... ... @@ -172,7 +172,7 @@
172 172 /* In-place public exponentiation. (65537}
173 173 * Input and output big-endian byte array in inout.
174 174 */
175   -static void modpowF4(const Key* key, uint8_t* inout) {
  175 +static void modpowF4(const IAvbKey* key, uint8_t* inout) {
176 176 uint32_t* a = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
177 177 uint32_t* aR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
178 178 uint32_t* aaR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
... ... @@ -237,7 +237,7 @@
237 237 const uint8_t* padding,
238 238 size_t padding_num_bytes) {
239 239 uint8_t* buf = NULL;
240   - Key* parsed_key = NULL;
  240 + IAvbKey* parsed_key = NULL;
241 241 bool success = false;
242 242  
243 243 if (key == NULL || sig == NULL || hash == NULL || padding == NULL) {
... ... @@ -245,7 +245,7 @@
245 245 goto out;
246 246 }
247 247  
248   - parsed_key = parse_key_data(key, key_num_bytes);
  248 + parsed_key = iavb_parse_key_data(key, key_num_bytes);
249 249 if (parsed_key == NULL) {
250 250 avb_error("Error parsing key.\n");
251 251 goto out;
... ... @@ -290,7 +290,7 @@
290 290  
291 291 out:
292 292 if (parsed_key != NULL) {
293   - free_parsed_key(parsed_key);
  293 + iavb_free_parsed_key(parsed_key);
294 294 }
295 295 if (buf != NULL) {
296 296 avb_free(buf);
lib/avb/libavb/avb_slot_verify.c
... ... @@ -58,6 +58,7 @@
58 58 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
59 59 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
60 60 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
  61 + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
61 62 return false;
62 63  
63 64 case AVB_SLOT_VERIFY_RESULT_OK:
... ... @@ -91,6 +92,7 @@
91 92 uint8_t* digest;
92 93 size_t digest_len;
93 94 const char* found;
  95 + uint64_t image_size;
94 96  
95 97 if (!avb_hash_descriptor_validate_and_byteswap(
96 98 (const AvbHashDescriptor*)descriptor, &hash_desc)) {
... ... @@ -109,6 +111,17 @@
109 111 goto out;
110 112 }
111 113  
  114 + /* Don't bother loading or validating unless the partition was
  115 + * requested in the first place.
  116 + */
  117 + found = avb_strv_find_str(requested_partitions,
  118 + (const char*)desc_partition_name,
  119 + hash_desc.partition_name_len);
  120 + if (found == NULL) {
  121 + ret = AVB_SLOT_VERIFY_RESULT_OK;
  122 + goto out;
  123 + }
  124 +
112 125 if (!avb_str_concat(part_name,
113 126 sizeof part_name,
114 127 (const char*)desc_partition_name,
... ... @@ -120,6 +133,36 @@
120 133 goto out;
121 134 }
122 135  
  136 + /* If we're allowing verification errors then hash_desc.image_size
  137 + * may no longer match what's in the partition... so in this case
  138 + * just load the entire partition.
  139 + *
  140 + * For example, this can happen if a developer does 'fastboot flash
  141 + * boot /path/to/new/and/bigger/boot.img'. We want this to work
  142 + * since it's such a common workflow.
  143 + */
  144 + image_size = hash_desc.image_size;
  145 + if (allow_verification_error) {
  146 + if (ops->get_size_of_partition == NULL) {
  147 + avb_errorv(part_name,
  148 + ": The get_size_of_partition() operation is "
  149 + "not implemented so we may not load the entire partition. "
  150 + "Please implement.",
  151 + NULL);
  152 + } else {
  153 + io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
  154 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  155 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  156 + goto out;
  157 + } else if (io_ret != AVB_IO_RESULT_OK) {
  158 + avb_errorv(part_name, ": Error determining partition size.\n", NULL);
  159 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  160 + goto out;
  161 + }
  162 + avb_debugv(part_name, ": Loading entire partition.\n", NULL);
  163 + }
  164 + }
  165 +
123 166 /* If we are going to load bootimage, load it to
124 167 * hdr->kernel_addr - hdr->page_size address directly,
125 168 * so we don't need to copy it again!*/
... ... @@ -152,12 +195,8 @@
152 195 }
153 196 }
154 197  
155   - io_ret = ops->read_from_partition(ops,
156   - part_name,
157   - 0 /* offset */,
158   - hash_desc.image_size,
159   - image_buf,
160   - &part_num_read);
  198 + io_ret = ops->read_from_partition(
  199 + ops, part_name, 0 /* offset */, image_size, image_buf, &part_num_read);
161 200 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
162 201 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
163 202 goto out;
... ... @@ -166,7 +205,7 @@
166 205 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
167 206 goto out;
168 207 }
169   - if (part_num_read != hash_desc.image_size) {
  208 + if (part_num_read != image_size) {
170 209 avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
171 210 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
172 211 goto out;
173 212  
... ... @@ -211,25 +250,21 @@
211 250  
212 251 out:
213 252  
214   - if (ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) {
215   - /* If this is the requested partition, copy to slot_data. */
216   - found = avb_strv_find_str(requested_partitions,
217   - (const char*)desc_partition_name,
218   - hash_desc.partition_name_len);
219   - if (found != NULL) {
220   - AvbPartitionData* loaded_partition;
221   - if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
222   - avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
223   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
224   - goto fail;
225   - }
226   - loaded_partition =
227   - &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
228   - loaded_partition->partition_name = avb_strdup(found);
229   - loaded_partition->data_size = hash_desc.image_size;
230   - loaded_partition->data = image_buf;
231   - image_buf = NULL;
  253 + /* If it worked and something was loaded, copy to slot_data. */
  254 + if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
  255 + image_buf != NULL) {
  256 + AvbPartitionData* loaded_partition;
  257 + if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
  258 + avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
  259 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  260 + goto fail;
232 261 }
  262 + loaded_partition =
  263 + &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
  264 + loaded_partition->partition_name = avb_strdup(found);
  265 + loaded_partition->data_size = image_size;
  266 + loaded_partition->data = image_buf;
  267 + image_buf = NULL;
233 268 }
234 269  
235 270 fail:
... ... @@ -239,6 +274,99 @@
239 274 return ret;
240 275 }
241 276  
  277 +static AvbSlotVerifyResult load_requested_partitions(
  278 + AvbOps* ops,
  279 + const char* const* requested_partitions,
  280 + const char* ab_suffix,
  281 + AvbSlotVerifyData* slot_data) {
  282 + AvbSlotVerifyResult ret;
  283 + uint8_t* image_buf = NULL;
  284 + size_t n;
  285 +
  286 + if (ops->get_size_of_partition == NULL) {
  287 + avb_error("get_size_of_partition() not implemented.\n");
  288 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
  289 + goto out;
  290 + }
  291 +
  292 + for (n = 0; requested_partitions[n] != NULL; n++) {
  293 + char part_name[PART_NAME_MAX_SIZE];
  294 + AvbIOResult io_ret;
  295 + uint64_t image_size;
  296 + size_t part_num_read;
  297 + AvbPartitionData* loaded_partition;
  298 +
  299 + if (!avb_str_concat(part_name,
  300 + sizeof part_name,
  301 + requested_partitions[n],
  302 + avb_strlen(requested_partitions[n]),
  303 + ab_suffix,
  304 + avb_strlen(ab_suffix))) {
  305 + avb_error("Partition name and suffix does not fit.\n");
  306 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  307 + goto out;
  308 + }
  309 +
  310 + io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
  311 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  312 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  313 + goto out;
  314 + } else if (io_ret != AVB_IO_RESULT_OK) {
  315 + avb_errorv(part_name, ": Error determining partition size.\n", NULL);
  316 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  317 + goto out;
  318 + }
  319 + avb_debugv(part_name, ": Loading entire partition.\n", NULL);
  320 +
  321 + image_buf = avb_malloc(image_size);
  322 + if (image_buf == NULL) {
  323 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  324 + goto out;
  325 + }
  326 +
  327 + io_ret = ops->read_from_partition(
  328 + ops, part_name, 0 /* offset */, image_size, image_buf, &part_num_read);
  329 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  330 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  331 + goto out;
  332 + } else if (io_ret != AVB_IO_RESULT_OK) {
  333 + avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
  334 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  335 + goto out;
  336 + }
  337 + if (part_num_read != image_size) {
  338 + avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
  339 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  340 + goto out;
  341 + }
  342 +
  343 + /* Move to slot_data. */
  344 + if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
  345 + avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
  346 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  347 + goto out;
  348 + }
  349 + loaded_partition =
  350 + &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
  351 + loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
  352 + if (loaded_partition->partition_name == NULL) {
  353 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  354 + goto out;
  355 + }
  356 + loaded_partition->data_size = image_size;
  357 + loaded_partition->data = image_buf;
  358 + image_buf = NULL;
  359 + }
  360 +
  361 + ret = AVB_SLOT_VERIFY_RESULT_OK;
  362 +
  363 +out:
  364 + if (image_buf != NULL) {
  365 + avb_free(image_buf);
  366 + }
  367 + return ret;
  368 +}
  369 +
242 370 static AvbSlotVerifyResult load_and_verify_vbmeta(
243 371 AvbOps* ops,
244 372 const char* const* requested_partitions,
... ... @@ -471,7 +599,7 @@
471 599 }
472 600 }
473 601 } else {
474   - bool key_is_trusted = true;
  602 + bool key_is_trusted = false;
475 603 const uint8_t* pk_metadata = NULL;
476 604 size_t pk_metadata_len = 0;
477 605  
... ... @@ -556,6 +684,27 @@
556 684 vbmeta_header.auxiliary_data_block_size;
557 685 vbmeta_image_data->verify_result = vbmeta_ret;
558 686  
  687 + /* If verification has been disabled by setting a bit in the image,
  688 + * we're done... except that we need to load the entirety of the
  689 + * requested partitions.
  690 + */
  691 + if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
  692 + AvbSlotVerifyResult sub_ret;
  693 + avb_debugv(
  694 + full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
  695 + /* If load_requested_partitions() fail it is always a fatal
  696 + * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
  697 + * than recoverable (e.g. one where result_should_continue()
  698 + * returns true) and we want to convey that error.
  699 + */
  700 + sub_ret = load_requested_partitions(
  701 + ops, requested_partitions, ab_suffix, slot_data);
  702 + if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
  703 + ret = sub_ret;
  704 + }
  705 + goto out;
  706 + }
  707 +
559 708 /* Now go through all descriptors and take the appropriate action:
560 709 *
561 710 * - hash descriptor: Load data from partition, calculate hash, and
562 711  
563 712  
564 713  
565 714  
566 715  
... ... @@ -949,21 +1098,208 @@
949 1098 return ret;
950 1099 }
951 1100  
  1101 +static AvbSlotVerifyResult append_options(
  1102 + AvbOps* ops,
  1103 + AvbSlotVerifyData* slot_data,
  1104 + AvbVBMetaImageHeader* toplevel_vbmeta,
  1105 + AvbAlgorithmType algorithm_type,
  1106 + AvbHashtreeErrorMode hashtree_error_mode) {
  1107 + AvbSlotVerifyResult ret;
  1108 + const char* verity_mode = "enforcing";
  1109 + bool is_device_unlocked;
  1110 + AvbIOResult io_ret;
  1111 +
  1112 + /* Add androidboot.vbmeta.device option. */
  1113 + if (!cmdline_append_option(slot_data,
  1114 + "androidboot.vbmeta.device",
  1115 + "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
  1116 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1117 + goto out;
  1118 + }
  1119 +
  1120 + /* Add androidboot.vbmeta.avb_version option. */
  1121 + if (!cmdline_append_version(slot_data,
  1122 + "androidboot.vbmeta.avb_version",
  1123 + AVB_VERSION_MAJOR,
  1124 + AVB_VERSION_MINOR)) {
  1125 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1126 + goto out;
  1127 + }
  1128 +
  1129 + /* Set androidboot.avb.device_state to "locked" or "unlocked". */
  1130 + io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
  1131 + if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  1132 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1133 + goto out;
  1134 + } else if (io_ret != AVB_IO_RESULT_OK) {
  1135 + avb_error("Error getting device state.\n");
  1136 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  1137 + goto out;
  1138 + }
  1139 + if (!cmdline_append_option(slot_data,
  1140 + "androidboot.vbmeta.device_state",
  1141 + is_device_unlocked ? "unlocked" : "locked")) {
  1142 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1143 + goto out;
  1144 + }
  1145 +
  1146 + /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
  1147 + * function as is used to sign vbmeta.
  1148 + */
  1149 + switch (algorithm_type) {
  1150 + /* Explicit fallthrough. */
  1151 + case AVB_ALGORITHM_TYPE_NONE:
  1152 + case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
  1153 + case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
  1154 + case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
  1155 + AvbSHA256Ctx ctx;
  1156 + size_t n, total_size = 0;
  1157 + avb_sha256_init(&ctx);
  1158 + for (n = 0; n < slot_data->num_vbmeta_images; n++) {
  1159 + avb_sha256_update(&ctx,
  1160 + slot_data->vbmeta_images[n].vbmeta_data,
  1161 + slot_data->vbmeta_images[n].vbmeta_size);
  1162 + total_size += slot_data->vbmeta_images[n].vbmeta_size;
  1163 + }
  1164 + if (!cmdline_append_option(
  1165 + slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
  1166 + !cmdline_append_uint64_base10(
  1167 + slot_data, "androidboot.vbmeta.size", total_size) ||
  1168 + !cmdline_append_hex(slot_data,
  1169 + "androidboot.vbmeta.digest",
  1170 + avb_sha256_final(&ctx),
  1171 + AVB_SHA256_DIGEST_SIZE)) {
  1172 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1173 + goto out;
  1174 + }
  1175 + } break;
  1176 + /* Explicit fallthrough. */
  1177 + case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
  1178 + case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
  1179 + case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
  1180 + AvbSHA512Ctx ctx;
  1181 + size_t n, total_size = 0;
  1182 + avb_sha512_init(&ctx);
  1183 + for (n = 0; n < slot_data->num_vbmeta_images; n++) {
  1184 + avb_sha512_update(&ctx,
  1185 + slot_data->vbmeta_images[n].vbmeta_data,
  1186 + slot_data->vbmeta_images[n].vbmeta_size);
  1187 + total_size += slot_data->vbmeta_images[n].vbmeta_size;
  1188 + }
  1189 + if (!cmdline_append_option(
  1190 + slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
  1191 + !cmdline_append_uint64_base10(
  1192 + slot_data, "androidboot.vbmeta.size", total_size) ||
  1193 + !cmdline_append_hex(slot_data,
  1194 + "androidboot.vbmeta.digest",
  1195 + avb_sha512_final(&ctx),
  1196 + AVB_SHA512_DIGEST_SIZE)) {
  1197 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1198 + goto out;
  1199 + }
  1200 + } break;
  1201 + case _AVB_ALGORITHM_NUM_TYPES:
  1202 + avb_assert_not_reached();
  1203 + break;
  1204 + }
  1205 +
  1206 + /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
  1207 + if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
  1208 + verity_mode = "disabled";
  1209 + } else {
  1210 + const char* dm_verity_mode = "restart_on_corruption";
  1211 + char* new_ret;
  1212 +
  1213 + switch (hashtree_error_mode) {
  1214 + case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
  1215 + if (!cmdline_append_option(
  1216 + slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
  1217 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1218 + goto out;
  1219 + }
  1220 + verity_mode = "enforcing";
  1221 + dm_verity_mode = "restart_on_corruption";
  1222 + break;
  1223 + case AVB_HASHTREE_ERROR_MODE_RESTART:
  1224 + verity_mode = "enforcing";
  1225 + dm_verity_mode = "restart_on_corruption";
  1226 + break;
  1227 + case AVB_HASHTREE_ERROR_MODE_EIO:
  1228 + verity_mode = "eio";
  1229 + /* For now there's no option to specify the EIO mode. So
  1230 + * just use 'ignore_zero_blocks' since that's already set
  1231 + * and dm-verity-target.c supports specifying this multiple
  1232 + * times.
  1233 + */
  1234 + dm_verity_mode = "ignore_zero_blocks";
  1235 + break;
  1236 + case AVB_HASHTREE_ERROR_MODE_LOGGING:
  1237 + verity_mode = "logging";
  1238 + dm_verity_mode = "ignore_corruption";
  1239 + break;
  1240 + }
  1241 + new_ret = avb_replace(
  1242 + slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
  1243 + avb_free(slot_data->cmdline);
  1244 + slot_data->cmdline = new_ret;
  1245 + if (slot_data->cmdline == NULL) {
  1246 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1247 + goto out;
  1248 + }
  1249 + }
  1250 + if (!cmdline_append_option(
  1251 + slot_data, "androidboot.veritymode", verity_mode)) {
  1252 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1253 + goto out;
  1254 + }
  1255 +
  1256 + ret = AVB_SLOT_VERIFY_RESULT_OK;
  1257 +
  1258 +out:
  1259 +
  1260 + return ret;
  1261 +}
  1262 +
952 1263 AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
953 1264 const char* const* requested_partitions,
954 1265 const char* ab_suffix,
955   - bool allow_verification_error,
  1266 + AvbSlotVerifyFlags flags,
  1267 + AvbHashtreeErrorMode hashtree_error_mode,
956 1268 AvbSlotVerifyData** out_data) {
957 1269 AvbSlotVerifyResult ret;
958 1270 AvbSlotVerifyData* slot_data = NULL;
959 1271 AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
960   - AvbIOResult io_ret;
961 1272 bool using_boot_for_vbmeta = false;
  1273 + AvbVBMetaImageHeader toplevel_vbmeta;
  1274 + bool allow_verification_error =
  1275 + (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
962 1276  
  1277 + /* Fail early if we're missing the AvbOps needed for slot verification.
  1278 + *
  1279 + * For now, handle get_size_of_partition() not being implemented. In
  1280 + * a later release we may change that.
  1281 + */
  1282 + avb_assert(ops->read_is_device_unlocked != NULL);
  1283 + avb_assert(ops->read_from_partition != NULL);
  1284 + avb_assert(ops->validate_vbmeta_public_key != NULL);
  1285 + avb_assert(ops->read_rollback_index != NULL);
  1286 + avb_assert(ops->get_unique_guid_for_partition != NULL);
  1287 + /* avb_assert(ops->get_size_of_partition != NULL); */
  1288 +
963 1289 if (out_data != NULL) {
964 1290 *out_data = NULL;
965 1291 }
966 1292  
  1293 + /* Allowing dm-verity errors defeats the purpose of verified boot so
  1294 + * only allow this if set up to allow verification errors
  1295 + * (e.g. typically only UNLOCKED mode).
  1296 + */
  1297 + if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
  1298 + !allow_verification_error) {
  1299 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
  1300 + goto fail;
  1301 + }
  1302 +
967 1303 slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
968 1304 if (slot_data == NULL) {
969 1305 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
970 1306  
... ... @@ -998,14 +1334,19 @@
998 1334 goto fail;
999 1335 }
1000 1336  
1001   - if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
1002   - avb_assert(avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") ==
1003   - 0);
1004   - using_boot_for_vbmeta = true;
1005   - }
1006   -
1007 1337 /* If things check out, mangle the kernel command-line as needed. */
1008 1338 if (result_should_continue(ret)) {
  1339 + if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
  1340 + avb_assert(
  1341 + avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
  1342 + using_boot_for_vbmeta = true;
  1343 + }
  1344 +
  1345 + /* Byteswap top-level vbmeta header since we'll need it below. */
  1346 + avb_vbmeta_image_header_to_host_byte_order(
  1347 + (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
  1348 + &toplevel_vbmeta);
  1349 +
1009 1350 /* Fill in |ab_suffix| field. */
1010 1351 slot_data->ab_suffix = avb_strdup(ab_suffix);
1011 1352 if (slot_data->ab_suffix == NULL) {
1012 1353  
... ... @@ -1013,23 +1354,37 @@
1013 1354 goto fail;
1014 1355 }
1015 1356  
1016   - /* Add androidboot.vbmeta.device option. */
1017   - if (!cmdline_append_option(slot_data,
1018   - "androidboot.vbmeta.device",
1019   - "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
1020   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1021   - goto fail;
  1357 + /* If verification is disabled, we are done ... we specifically
  1358 + * don't want to add any androidboot.* options since verification
  1359 + * is disabled.
  1360 + */
  1361 + if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
  1362 + /* Since verification is disabled we didn't process any
  1363 + * descriptors and thus there's no cmdline... so set root= such
  1364 + * that the system partition is mounted.
  1365 + */
  1366 + avb_assert(slot_data->cmdline == NULL);
  1367 + slot_data->cmdline =
  1368 + avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
  1369 + if (slot_data->cmdline == NULL) {
  1370 + ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  1371 + goto fail;
  1372 + }
  1373 + } else {
  1374 + /* Add options - any failure in append_options() is either an
  1375 + * I/O or OOM error.
  1376 + */
  1377 + AvbSlotVerifyResult sub_ret = append_options(ops,
  1378 + slot_data,
  1379 + &toplevel_vbmeta,
  1380 + algorithm_type,
  1381 + hashtree_error_mode);
  1382 + if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
  1383 + ret = sub_ret;
  1384 + goto fail;
  1385 + }
1022 1386 }
1023 1387  
1024   - /* Add androidboot.vbmeta.avb_version option. */
1025   - if (!cmdline_append_version(slot_data,
1026   - "androidboot.vbmeta.avb_version",
1027   - AVB_VERSION_MAJOR,
1028   - AVB_VERSION_MINOR)) {
1029   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1030   - goto fail;
1031   - }
1032   -
1033 1388 /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1034 1389 if (slot_data->cmdline != NULL) {
1035 1390 char* new_cmdline;
... ... @@ -1043,84 +1398,6 @@
1043 1398 slot_data->cmdline = new_cmdline;
1044 1399 }
1045 1400  
1046   - /* Set androidboot.avb.device_state to "locked" or "unlocked". */
1047   - bool is_device_unlocked;
1048   - io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
1049   - if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
1050   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1051   - goto fail;
1052   - } else if (io_ret != AVB_IO_RESULT_OK) {
1053   - avb_error("Error getting device state.\n");
1054   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1055   - goto fail;
1056   - }
1057   - if (!cmdline_append_option(slot_data,
1058   - "androidboot.vbmeta.device_state",
1059   - is_device_unlocked ? "unlocked" : "locked")) {
1060   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1061   - goto fail;
1062   - }
1063   -
1064   - /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
1065   - * function as is used to sign vbmeta.
1066   - */
1067   - switch (algorithm_type) {
1068   - /* Explicit fallthrough. */
1069   - case AVB_ALGORITHM_TYPE_NONE:
1070   - case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
1071   - case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
1072   - case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
1073   - AvbSHA256Ctx ctx;
1074   - size_t n, total_size = 0;
1075   - avb_sha256_init(&ctx);
1076   - for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1077   - avb_sha256_update(&ctx,
1078   - slot_data->vbmeta_images[n].vbmeta_data,
1079   - slot_data->vbmeta_images[n].vbmeta_size);
1080   - total_size += slot_data->vbmeta_images[n].vbmeta_size;
1081   - }
1082   - if (!cmdline_append_option(
1083   - slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
1084   - !cmdline_append_uint64_base10(
1085   - slot_data, "androidboot.vbmeta.size", total_size) ||
1086   - !cmdline_append_hex(slot_data,
1087   - "androidboot.vbmeta.digest",
1088   - avb_sha256_final(&ctx),
1089   - AVB_SHA256_DIGEST_SIZE)) {
1090   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1091   - goto fail;
1092   - }
1093   - } break;
1094   - /* Explicit fallthrough. */
1095   - case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
1096   - case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
1097   - case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
1098   - AvbSHA512Ctx ctx;
1099   - size_t n, total_size = 0;
1100   - avb_sha512_init(&ctx);
1101   - for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1102   - avb_sha512_update(&ctx,
1103   - slot_data->vbmeta_images[n].vbmeta_data,
1104   - slot_data->vbmeta_images[n].vbmeta_size);
1105   - total_size += slot_data->vbmeta_images[n].vbmeta_size;
1106   - }
1107   - if (!cmdline_append_option(
1108   - slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
1109   - !cmdline_append_uint64_base10(
1110   - slot_data, "androidboot.vbmeta.size", total_size) ||
1111   - !cmdline_append_hex(slot_data,
1112   - "androidboot.vbmeta.digest",
1113   - avb_sha512_final(&ctx),
1114   - AVB_SHA512_DIGEST_SIZE)) {
1115   - ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1116   - goto fail;
1117   - }
1118   - } break;
1119   - case _AVB_ALGORITHM_NUM_TYPES:
1120   - avb_assert_not_reached();
1121   - break;
1122   - }
1123   -
1124 1401 if (out_data != NULL) {
1125 1402 *out_data = slot_data;
1126 1403 } else {
... ... @@ -1141,7 +1418,7 @@
1141 1418 return ret;
1142 1419 }
1143 1420  
1144   -void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
  1421 +void avb_slot_verify_data_free_fast(AvbSlotVerifyData* data) {
1145 1422 if (data->ab_suffix != NULL) {
1146 1423 avb_free(data->ab_suffix);
1147 1424 }
... ... @@ -1166,7 +1443,12 @@
1166 1443 for (n = 0; n < data->num_loaded_partitions; n++) {
1167 1444 AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1168 1445 if (loaded_partition->partition_name != NULL) {
1169   - avb_free(loaded_partition->partition_name);
  1446 + /* the address of bootimage isn't alloced by malloc, we don't
  1447 + * need to free it. */
  1448 + if (strstr(loaded_partition->partition_name, "boot") != NULL)
  1449 + continue;
  1450 + else
  1451 + avb_free(loaded_partition->partition_name);
1170 1452 }
1171 1453 if (loaded_partition->data != NULL) {
1172 1454 avb_free(loaded_partition->data);
... ... @@ -1176,7 +1458,8 @@
1176 1458 }
1177 1459 avb_free(data);
1178 1460 }
1179   -void avb_slot_verify_data_free_fast(AvbSlotVerifyData* data) {
  1461 +
  1462 +void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1180 1463 if (data->ab_suffix != NULL) {
1181 1464 avb_free(data->ab_suffix);
1182 1465 }
... ... @@ -1201,12 +1484,7 @@
1201 1484 for (n = 0; n < data->num_loaded_partitions; n++) {
1202 1485 AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1203 1486 if (loaded_partition->partition_name != NULL) {
1204   - /* the address of bootimage isn't alloced by malloc, we don't
1205   - * need to free it. */
1206   - if (strstr(loaded_partition->partition_name, "boot") != NULL)
1207   - continue;
1208   - else
1209   - avb_free(loaded_partition->partition_name);
  1487 + avb_free(loaded_partition->partition_name);
1210 1488 }
1211 1489 if (loaded_partition->data != NULL) {
1212 1490 avb_free(loaded_partition->data);
... ... @@ -1244,6 +1522,9 @@
1244 1522 break;
1245 1523 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1246 1524 ret = "ERROR_UNSUPPORTED_VERSION";
  1525 + break;
  1526 + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
  1527 + ret = "ERROR_INVALID_ARGUMENT";
1247 1528 break;
1248 1529 /* Do not add a 'default:' case here because of -Wswitch. */
1249 1530 }
lib/avb/libavb/avb_slot_verify.h
... ... @@ -50,9 +50,61 @@
50 50 AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
51 51 AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
52 52 AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
53   - AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION
  53 + AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION,
  54 + AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
54 55 } AvbSlotVerifyResult;
55 56  
  57 +/* Various error handling modes for when verification fails using a
  58 + * hashtree at runtime inside the HLOS.
  59 + *
  60 + * AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE means that the OS
  61 + * will invalidate the current slot and restart.
  62 + *
  63 + * AVB_HASHTREE_ERROR_MODE_RESTART means that the OS will restart.
  64 + *
  65 + * AVB_HASHTREE_ERROR_MODE_EIO means that an EIO error will be
  66 + * returned to applications.
  67 + *
  68 + * AVB_HASHTREE_ERROR_MODE_LOGGING means that errors will be logged
  69 + * and corrupt data may be returned to applications. This mode should
  70 + * be used ONLY for diagnostics and debugging. It cannot be used
  71 + * unless AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is also
  72 + * used.
  73 + */
  74 +typedef enum {
  75 + AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
  76 + AVB_HASHTREE_ERROR_MODE_RESTART,
  77 + AVB_HASHTREE_ERROR_MODE_EIO,
  78 + AVB_HASHTREE_ERROR_MODE_LOGGING
  79 +} AvbHashtreeErrorMode;
  80 +
  81 +/* Flags that influence how avb_slot_verify() works.
  82 + *
  83 + * If AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is NOT set then
  84 + * avb_slot_verify() will bail out as soon as an error is encountered
  85 + * and |out_data| is set only if AVB_SLOT_VERIFY_RESULT_OK is
  86 + * returned.
  87 + *
  88 + * Otherwise if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set
  89 + * avb_slot_verify() will continue verification efforts and |out_data|
  90 + * is also set if AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
  91 + * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
  92 + * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned. It is
  93 + * undefined which error is returned if more than one distinct error
  94 + * is encountered. It is guaranteed that AVB_SLOT_VERIFY_RESULT_OK is
  95 + * returned if, and only if, there are no errors. This mode is needed
  96 + * to boot valid but unverified slots when the device is unlocked.
  97 + *
  98 + * Also, if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set the
  99 + * contents loaded from |requested_partition| will be the contents of
  100 + * the entire partition instead of just the size specified in the hash
  101 + * descriptor.
  102 + */
  103 +typedef enum {
  104 + AVB_SLOT_VERIFY_FLAGS_NONE = 0,
  105 + AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0)
  106 +} AvbSlotVerifyFlags;
  107 +
56 108 /* Get a textual representation of |result|. */
57 109 const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result);
58 110  
... ... @@ -103,7 +155,10 @@
103 155 * avb_slot_verify_data_free() function is called.
104 156 *
105 157 * The |ab_suffix| field is the copy of the of |ab_suffix| field
106   - * passed to avb_slot_verify(). It is the A/B suffix of the slot.
  158 + * passed to avb_slot_verify(). It is the A/B suffix of the slot. This
  159 + * value includes the leading underscore - typical values are "" (if
  160 + * no slots are in use), "_a" (for the first slot), and "_b" (for the
  161 + * second slot).
107 162 *
108 163 * The VBMeta images that were checked are available in the
109 164 * |vbmeta_images| field. The field |num_vbmeta_images| contains the
110 165  
111 166  
... ... @@ -132,11 +187,26 @@
132 187 * performing proper substitution of the variables
133 188 * $(ANDROID_SYSTEM_PARTUUID), $(ANDROID_BOOT_PARTUUID), and
134 189 * $(ANDROID_VBMETA_PARTUUID) using the
135   - * get_unique_guid_for_partition() operation in |AvbOps|.
  190 + * get_unique_guid_for_partition() operation in |AvbOps|. Additionally
  191 + * $(ANDROID_VERITY_MODE) will be replaced with the proper dm-verity
  192 + * option depending on the value of |hashtree_error_mode|.
136 193 *
137 194 * Additionally, the |cmdline| field will have the following kernel
138   - * command-line options set:
  195 + * command-line options set (unless verification is disabled, see
  196 + * below):
139 197 *
  198 + * androidboot.veritymode: This is set to 'disabled' if the
  199 + * AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED flag is set in top-level
  200 + * vbmeta struct. Otherwise it is set to 'enforcing' if the
  201 + * passed-in hashtree error mode is AVB_HASHTREE_ERROR_MODE_RESTART
  202 + * or AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 'eio' if it's
  203 + * set to AVB_HASHTREE_ERROR_MODE_EIO, and 'logging' if it's set to
  204 + * AVB_HASHTREE_ERROR_MODE_LOGGING.
  205 + *
  206 + * androidboot.vbmeta.invalidate_on_error: This is set to 'yes' only
  207 + * if hashtree validation isn't disabled and the passed-in hashtree
  208 + * error mode is AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE.
  209 + *
140 210 * androidboot.vbmeta.device_state: set to "locked" or "unlocked"
141 211 * depending on the result of the result of AvbOps's
142 212 * read_is_unlocked() function.
143 213  
... ... @@ -158,9 +228,21 @@
158 228 * necessarily the same version number of the on-disk metadata for
159 229 * the slot that was verified.
160 230 *
161   - * Note that androidboot.slot_suffix is not set in |cmdline| - you
162   - * will have to pass this command-line option yourself.
  231 + * Note that androidboot.slot_suffix is not set in the |cmdline| field
  232 + * in |AvbSlotVerifyData| - you will have to set this yourself.
163 233 *
  234 + * If the |AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED| flag is set
  235 + * in the top-level vbmeta struct then only the top-level vbmeta
  236 + * struct is verified and descriptors will not processed. The return
  237 + * value will be set accordingly (if this flag is set via 'avbctl
  238 + * disable-verification' then the return value will be
  239 + * |AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION|) and
  240 + * |AvbSlotVerifyData| is returned. Additionally all partitions in the
  241 + * |requested_partitions| are loaded and the |cmdline| field is set to
  242 + * "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)" and the GUID for the
  243 + * appropriate system partition is substituted in. Note that none of
  244 + * the androidboot.* options mentioned above will be set.
  245 + *
164 246 * This struct may grow in the future without it being considered an
165 247 * ABI break.
166 248 */
167 249  
168 250  
169 251  
... ... @@ -174,23 +256,28 @@
174 256 uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
175 257 } AvbSlotVerifyData;
176 258  
  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);
177 262 /* Frees a |AvbSlotVerifyData| including all data it points to. */
178 263 void avb_slot_verify_data_free(AvbSlotVerifyData* data);
179   -void avb_slot_verify_data_free_fast(AvbSlotVerifyData* data);
  264 +
180 265 /* Performs a full verification of the slot identified by |ab_suffix|
181   - * and load the contents of the partitions whose name is in the
182   - * NULL-terminated string array |requested_partitions| (each partition
183   - * must use hash verification). If not using A/B, pass an empty string
184   - * (e.g. "", not NULL) for |ab_suffix|.
  266 + * and load and verify the contents of the partitions whose name is in
  267 + * the NULL-terminated string array |requested_partitions| (each
  268 + * partition must use hash verification). If not using A/B, pass an
  269 + * empty string (e.g. "", not NULL) for |ab_suffix|. This parameter
  270 + * must include the leading underscore, for example "_a" should be
  271 + * used to refer to the first slot.
185 272 *
186 273 * Typically the |requested_partitions| array only contains a single
187 274 * item for the boot partition, 'boot'.
188 275 *
189   - * Verification includes loading data from the 'vbmeta', all hash
190   - * partitions, and possibly other partitions (with |ab_suffix|
191   - * appended), inspecting rollback indexes, and checking if the public
192   - * key used to sign the data is acceptable. The functions in |ops|
193   - * will be used to do this.
  276 + * Verification includes loading and verifying data from the 'vbmeta',
  277 + * the requested hash partitions, and possibly other partitions (with
  278 + * |ab_suffix| appended), inspecting rollback indexes, and checking if
  279 + * the public key used to sign the data is acceptable. The functions
  280 + * in |ops| will be used to do this.
194 281 *
195 282 * If |out_data| is not NULL, it will be set to a newly allocated
196 283 * |AvbSlotVerifyData| struct containing all the data needed to
197 284  
... ... @@ -198,19 +285,18 @@
198 285 * avb_slot_verify_data_free() when you are done with it. See below
199 286 * for when this is returned.
200 287 *
201   - * If |allow_verification_error| is false this function will bail out
202   - * as soon as an error is encountered and |out_data| is set only if
203   - * AVB_SLOT_VERIFY_RESULT_OK is returned.
  288 + * The |flags| parameter is used to influence the semantics of
  289 + * avb_slot_verify() - for example the
  290 + * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag can be used to
  291 + * ignore verification errors which is something needed in the
  292 + * UNLOCKED state. See the AvbSlotVerifyFlags enumeration for details.
204 293 *
205   - * Otherwise if |allow_verification_error| is true the function will
206   - * continue verification efforts and |out_data| is also set if
207   - * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
208   - * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
209   - * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned. It is
210   - * undefined which error is returned if more than one distinct error
211   - * is encountered. It is guaranteed that AVB_SLOT_VERIFY_RESULT_OK is
212   - * returned if, and only if, there are no errors. This mode is needed
213   - * to boot valid but unverified slots when the device is unlocked.
  294 + * The |hashtree_error_mode| parameter should be set to the desired
  295 + * error handling mode when hashtree validation fails inside the
  296 + * HLOS. This value isn't used by libavb per se - it is forwarded to
  297 + * the HLOS through the androidboot.veritymode and
  298 + * androidboot.vbmeta.invalidate_on_error cmdline parameters. See the
  299 + * AvbHashtreeErrorMode enumeration for details.
214 300 *
215 301 * Also note that |out_data| is never set if
216 302 * AVB_SLOT_VERIFY_RESULT_ERROR_OOM, AVB_SLOT_VERIFY_RESULT_ERROR_IO,
217 303  
... ... @@ -243,11 +329,17 @@
243 329 * AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION is returned if
244 330 * some of the metadata requires a newer version of libavb than what
245 331 * is in use.
  332 + *
  333 + * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT is returned if the
  334 + * caller passed invalid parameters, for example trying to use
  335 + * AVB_HASHTREE_ERROR_MODE_LOGGING without
  336 + * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
246 337 */
247 338 AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
248 339 const char* const* requested_partitions,
249 340 const char* ab_suffix,
250   - bool allow_verification_error,
  341 + AvbSlotVerifyFlags flags,
  342 + AvbHashtreeErrorMode hashtree_error_mode,
251 343 AvbSlotVerifyData** out_data);
252 344  
253 345 #ifdef __cplusplus
lib/avb/libavb/avb_sysdeps.h
... ... @@ -38,8 +38,6 @@
38 38 * like uint8_t, uint64_t, and bool (with |false|, |true| keywords)
39 39 * must be present.
40 40 */
41   -
42   -//#define bool int
43 41 #include <common.h>
44 42  
45 43 /* If you don't have gcc or clang, these attribute macros may need to
lib/avb/libavb/avb_vbmeta_image.h
... ... @@ -52,9 +52,13 @@
52 52 *
53 53 * AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED: If this flag is set,
54 54 * hashtree image verification will be disabled.
  55 + *
  56 + * AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: If this flag is set,
  57 + * verification will be disabled and descriptors will not be parsed.
55 58 */
56 59 typedef enum {
57   - AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = (1 << 0)
  60 + AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = (1 << 0),
  61 + AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED = (1 << 1)
58 62 } AvbVBMetaImageFlags;
59 63  
60 64 /* Binary format for header of the vbmeta image.
... ... @@ -107,8 +111,8 @@
107 111 * minimum version of libavb required to verify the header and depends
108 112 * on the features (e.g. algorithms, descriptors) used. Note that this
109 113 * may be 1.0 even if generated by an avbtool from 1.4 but where no
110   - * features introduced after 1.0 has been used. See the VERSIONING AND
111   - * COMPATIBILITY section in the README file for more details.
  114 + * features introduced after 1.0 has been used. See the "Versioning
  115 + * and compatibility" section in the README.md file for more details.
112 116 *
113 117 * All fields are stored in network byte order when serialized. To
114 118 * generate a copy with fields swapped to native byte order, use the
lib/avb/libavb/avb_version.h
... ... @@ -52,10 +52,6 @@
52 52 */
53 53 const char* avb_version_string(void);
54 54  
55   -/* TODO: remove when there are no more users of AVB_{MAJOR,MINOR}_VERSION. */
56   -#define AVB_MAJOR_VERSION AVB_VERSION_MAJOR
57   -#define AVB_MINOR_VERSION AVB_VERSION_MINOR
58   -
59 55 #ifdef __cplusplus
60 56 }
61 57 #endif
lib/avb/libavb_ab/avb_ab_flow.c
... ... @@ -202,21 +202,19 @@
202 202 return AVB_IO_RESULT_OK;
203 203 }
204 204  
205   -AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
  205 +AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
206 206 const char* const* requested_partitions,
207   - bool allow_verification_error,
  207 + AvbSlotVerifyFlags flags,
  208 + AvbHashtreeErrorMode hashtree_error_mode,
208 209 AvbSlotVerifyData** out_data) {
209 210 AvbOps* ops = ab_ops->ops;
210 211 AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
211 212 AvbSlotVerifyData* data = NULL;
212 213 AvbABFlowResult ret;
213 214 AvbABData ab_data, ab_data_orig;
214   - size_t slot_index_to_boot, n = 0;
  215 + size_t slot_index_to_boot, n;
215 216 AvbIOResult io_ret;
216 217 bool saw_and_allowed_verification_error = false;
217   - size_t target_slot;
218   - AvbSlotVerifyResult verify_result;
219   - bool set_slot_unbootable = false;
220 218  
221 219 io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
222 220 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
223 221  
224 222  
... ... @@ -227,18 +225,18 @@
227 225 goto out;
228 226 }
229 227  
230   - slot_index_to_boot = 2; // Means not 0 or 1
231   - target_slot = (ab_data.slots[1].priority > ab_data.slots[0].priority? 1 : 0);
232   -
  228 + /* Validate all bootable slots. */
233 229 for (n = 0; n < 2; n++) {
234   - if (!slot_is_bootable(&ab_data.slots[target_slot])) {
235   - target_slot = (target_slot == 1 ? 0 : 1);
236   - continue;
237   - }
  230 + if (slot_is_bootable(&ab_data.slots[n])) {
  231 + AvbSlotVerifyResult verify_result;
  232 + bool set_slot_unbootable = false;
238 233  
239   - verify_result = avb_slot_verify(ops, requested_partitions, slot_suffixes[target_slot],
240   - allow_verification_error,
241   - &slot_data[target_slot]);
  234 + verify_result = avb_slot_verify(ops,
  235 + requested_partitions,
  236 + slot_suffixes[n],
  237 + flags,
  238 + hashtree_error_mode,
  239 + &slot_data[n]);
242 240 switch (verify_result) {
243 241 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
244 242 ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
245 243  
... ... @@ -249,13 +247,13 @@
249 247 goto out;
250 248  
251 249 case AVB_SLOT_VERIFY_RESULT_OK:
252   - slot_index_to_boot = target_slot;
253   - n = 2;
254 250 break;
255 251  
256 252 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
257 253 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
258   - /* Even with |allow_verification_error| these mean game over. */
  254 + /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
  255 + * these mean game over.
  256 + */
259 257 set_slot_unbootable = true;
260 258 break;
261 259  
262 260  
263 261  
264 262  
265 263  
266 264  
267 265  
268 266  
269 267  
270 268  
... ... @@ -263,40 +261,53 @@
263 261 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
264 262 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
265 263 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
266   - if (allow_verification_error) {
  264 + if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
267 265 /* Do nothing since we allow this. */
268 266 avb_debugv("Allowing slot ",
269   - slot_suffixes[target_slot],
  267 + slot_suffixes[n],
270 268 " which verified "
271 269 "with result ",
272 270 avb_slot_verify_result_to_string(verify_result),
273   - " because |allow_verification_error| is true.\n",
  271 + " because "
  272 + "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
  273 + "is set.\n",
274 274 NULL);
275 275 saw_and_allowed_verification_error = true;
276   - slot_index_to_boot = target_slot;
277   - n = 2;
278 276 } else {
279 277 set_slot_unbootable = true;
280 278 }
281 279 break;
282   - default:
283   - break;
  280 +
  281 + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
  282 + ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
  283 + goto out;
  284 + /* Do not add a 'default:' case here because of -Wswitch. */
284 285 }
  286 +
285 287 if (set_slot_unbootable) {
286 288 avb_errorv("Error verifying slot ",
287   - slot_suffixes[target_slot],
  289 + slot_suffixes[n],
288 290 " with result ",
289 291 avb_slot_verify_result_to_string(verify_result),
290 292 " - setting unbootable.\n",
291 293 NULL);
292   - slot_set_unbootable(&ab_data.slots[target_slot]);
293   - set_slot_unbootable = false;
  294 + slot_set_unbootable(&ab_data.slots[n]);
294 295 }
295   - /* switch to another slot */
296   - target_slot = (target_slot == 1 ? 0 : 1);
  296 + }
297 297 }
298 298  
299   - if (slot_index_to_boot == 2) {
  299 + if (slot_is_bootable(&ab_data.slots[0]) &&
  300 + slot_is_bootable(&ab_data.slots[1])) {
  301 + if (ab_data.slots[1].priority > ab_data.slots[0].priority) {
  302 + slot_index_to_boot = 1;
  303 + } else {
  304 + slot_index_to_boot = 0;
  305 + }
  306 + } else if (slot_is_bootable(&ab_data.slots[0])) {
  307 + slot_index_to_boot = 0;
  308 + } else if (slot_is_bootable(&ab_data.slots[1])) {
  309 + slot_index_to_boot = 1;
  310 + } else {
300 311 /* No bootable slots! */
301 312 avb_error("No bootable slots found.\n");
302 313 ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
... ... @@ -352,7 +363,7 @@
352 363 data = slot_data[slot_index_to_boot];
353 364 slot_data[slot_index_to_boot] = NULL;
354 365 if (saw_and_allowed_verification_error) {
355   - avb_assert(allow_verification_error);
  366 + avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
356 367 ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
357 368 } else {
358 369 ret = AVB_AB_FLOW_RESULT_OK;
359 370  
360 371  
... ... @@ -388,18 +399,17 @@
388 399 *out_data = data;
389 400 } else {
390 401 if (data != NULL) {
391   - /* the address of bootimage isn't alloced by malloc,
392   - * we should not free it. */
393   - avb_slot_verify_data_free_fast(data);
  402 + avb_slot_verify_data_free(data);
394 403 }
395 404 }
396 405  
397 406 return ret;
398 407 }
399 408  
400   -AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
  409 +AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
401 410 const char* const* requested_partitions,
402   - bool allow_verification_error,
  411 + AvbSlotVerifyFlags flags,
  412 + AvbHashtreeErrorMode hashtree_error_mode,
403 413 AvbSlotVerifyData** out_data) {
404 414 AvbOps* ops = ab_ops->ops;
405 415 AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
... ... @@ -409,6 +419,9 @@
409 419 size_t slot_index_to_boot, n;
410 420 AvbIOResult io_ret;
411 421 bool saw_and_allowed_verification_error = false;
  422 + size_t target_slot;
  423 + AvbSlotVerifyResult verify_result;
  424 + bool set_slot_unbootable = false;
412 425  
413 426 io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
414 427 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
415 428  
416 429  
417 430  
418 431  
419 432  
420 433  
421 434  
422 435  
423 436  
424 437  
... ... @@ -419,79 +432,86 @@
419 432 goto out;
420 433 }
421 434  
422   - /* Validate all bootable slots. */
423   - for (n = 0; n < 2; n++) {
424   - if (slot_is_bootable(&ab_data.slots[n])) {
425   - AvbSlotVerifyResult verify_result;
426   - bool set_slot_unbootable = false;
  435 + slot_index_to_boot = 2; // Means not 0 or 1
  436 + target_slot = (ab_data.slots[1].priority > ab_data.slots[0].priority? 1 : 0);
427 437  
428   - verify_result = avb_slot_verify(ops,
  438 + for (n = 0; n < 2; n++) {
  439 + if (!slot_is_bootable(&ab_data.slots[target_slot])) {
  440 + target_slot = (target_slot == 1 ? 0 : 1);
  441 + continue;
  442 + }
  443 + verify_result = avb_slot_verify(ops,
429 444 requested_partitions,
430   - slot_suffixes[n],
431   - allow_verification_error,
432   - &slot_data[n]);
433   - switch (verify_result) {
434   - case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
435   - ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
436   - goto out;
  445 + slot_suffixes[target_slot],
  446 + flags,
  447 + hashtree_error_mode,
  448 + &slot_data[target_slot]);
  449 + switch (verify_result) {
  450 + case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
  451 + ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
  452 + goto out;
437 453  
438   - case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
439   - ret = AVB_AB_FLOW_RESULT_ERROR_IO;
440   - goto out;
  454 + case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
  455 + ret = AVB_AB_FLOW_RESULT_ERROR_IO;
  456 + goto out;
441 457  
442   - case AVB_SLOT_VERIFY_RESULT_OK:
443   - break;
  458 + case AVB_SLOT_VERIFY_RESULT_OK:
  459 + slot_index_to_boot = target_slot;
  460 + n = 2;
  461 + break;
444 462  
445   - case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
446   - case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
447   - /* Even with |allow_verification_error| these mean game over. */
  463 + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
  464 + case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
  465 + /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
  466 + * these mean game over.
  467 + */
  468 + set_slot_unbootable = true;
  469 + break;
  470 +
  471 + /* explicit fallthrough. */
  472 + case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
  473 + case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
  474 + case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
  475 + if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
  476 + /* Do nothing since we allow this. */
  477 + avb_debugv("Allowing slot ",
  478 + slot_suffixes[target_slot],
  479 + " which verified "
  480 + "with result ",
  481 + avb_slot_verify_result_to_string(verify_result),
  482 + " because "
  483 + "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
  484 + "is set.\n",
  485 + NULL);
  486 + saw_and_allowed_verification_error = true;
  487 + slot_index_to_boot = target_slot;
  488 + n = 2;
  489 + } else {
448 490 set_slot_unbootable = true;
449   - break;
  491 + }
  492 + break;
450 493  
451   - /* explicit fallthrough. */
452   - case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
453   - case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
454   - case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
455   - if (allow_verification_error) {
456   - /* Do nothing since we allow this. */
457   - avb_debugv("Allowing slot ",
458   - slot_suffixes[n],
459   - " which verified "
460   - "with result ",
461   - avb_slot_verify_result_to_string(verify_result),
462   - " because |allow_verification_error| is true.\n",
463   - NULL);
464   - saw_and_allowed_verification_error = true;
465   - } else {
466   - set_slot_unbootable = true;
467   - }
468   - break;
469   - }
  494 + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
  495 + ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
  496 + goto out;
  497 + /* Do not add a 'default:' case here because of -Wswitch. */
  498 + }
470 499  
471   - if (set_slot_unbootable) {
472   - avb_errorv("Error verifying slot ",
473   - slot_suffixes[n],
474   - " with result ",
475   - avb_slot_verify_result_to_string(verify_result),
476   - " - setting unbootable.\n",
477   - NULL);
478   - slot_set_unbootable(&ab_data.slots[n]);
479   - }
  500 + if (set_slot_unbootable) {
  501 + avb_errorv("Error verifying slot ",
  502 + slot_suffixes[target_slot],
  503 + " with result ",
  504 + avb_slot_verify_result_to_string(verify_result),
  505 + " - setting unbootable.\n",
  506 + NULL);
  507 + slot_set_unbootable(&ab_data.slots[target_slot]);
  508 + set_slot_unbootable = false;
480 509 }
  510 + /* switch to another slot */
  511 + target_slot = (target_slot == 1 ? 0 : 1);
481 512 }
482 513  
483   - if (slot_is_bootable(&ab_data.slots[0]) &&
484   - slot_is_bootable(&ab_data.slots[1])) {
485   - if (ab_data.slots[1].priority > ab_data.slots[0].priority) {
486   - slot_index_to_boot = 1;
487   - } else {
488   - slot_index_to_boot = 0;
489   - }
490   - } else if (slot_is_bootable(&ab_data.slots[0])) {
491   - slot_index_to_boot = 0;
492   - } else if (slot_is_bootable(&ab_data.slots[1])) {
493   - slot_index_to_boot = 1;
494   - } else {
  514 + if (slot_index_to_boot == 2) {
495 515 /* No bootable slots! */
496 516 avb_error("No bootable slots found.\n");
497 517 ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
... ... @@ -547,7 +567,7 @@
547 567 data = slot_data[slot_index_to_boot];
548 568 slot_data[slot_index_to_boot] = NULL;
549 569 if (saw_and_allowed_verification_error) {
550   - avb_assert(allow_verification_error);
  570 + avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
551 571 ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
552 572 } else {
553 573 ret = AVB_AB_FLOW_RESULT_OK;
... ... @@ -583,7 +603,9 @@
583 603 *out_data = data;
584 604 } else {
585 605 if (data != NULL) {
586   - avb_slot_verify_data_free(data);
  606 + /* the address of bootimage isn't alloced by malloc,
  607 + * we should not free it. */
  608 + avb_slot_verify_data_free_fast(data);
587 609 }
588 610 }
589 611  
... ... @@ -698,6 +720,10 @@
698 720  
699 721 case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS:
700 722 ret = "ERROR_NO_BOOTABLE_SLOTS";
  723 + break;
  724 +
  725 + case AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT:
  726 + ret = "ERROR_INVALID_ARGUMENT";
701 727 break;
702 728 /* Do not add a 'default:' case here because of -Wswitch. */
703 729 }
lib/avb/libavb_ab/avb_ab_flow.h
... ... @@ -140,7 +140,8 @@
140 140 AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR,
141 141 AVB_AB_FLOW_RESULT_ERROR_OOM,
142 142 AVB_AB_FLOW_RESULT_ERROR_IO,
143   - AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS
  143 + AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
  144 + AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT
144 145 } AvbABFlowResult;
145 146  
146 147 /* Get a textual representation of |result|. */
... ... @@ -156,9 +157,9 @@
156 157 *
157 158 * 2. All bootable slots listed in the A/B metadata are verified using
158 159 * avb_slot_verify(). If a slot is invalid or if it fails verification
159   - * (and |allow_verification_error| is false, see below), it will be
160   - * marked as unbootable in the A/B metadata and the metadata will be
161   - * saved to disk before returning.
  160 + * (and AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is not set, see
  161 + * below), it will be marked as unbootable in the A/B metadata and the
  162 + * metadata will be saved to disk before returning.
162 163 *
163 164 * 3. If there are no bootable slots, the value
164 165 * AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS is returned.
165 166  
166 167  
... ... @@ -180,25 +181,26 @@
180 181 * |requested_partitions| array only contains a single item for the
181 182 * boot partition, 'boot'.
182 183 *
183   - * If the device is unlocked (and _only_ if it's unlocked), true
184   - * should be passed in the |allow_verification_error| parameter. This
185   - * will allow considering slots as verified even when
186   - * avb_slot_verify() returns
  184 + * If the device is unlocked (and _only_ if it's unlocked), the
  185 + * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag should be set
  186 + * in the |flags| parameter. This will allow considering slots as
  187 + * verified even when avb_slot_verify() returns
187 188 * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
188 189 * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
189 190 * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX for the slot in
190 191 * question.
191 192 *
192   - * Note that androidboot.slot_suffix is not set in the |cmdline| field
193   - * in |AvbSlotVerifyData| - you will have to pass this command-line
194   - * option yourself.
  193 + * Note that neither androidboot.slot_suffix nor androidboot.slot are
  194 + * set in the |cmdline| field in |AvbSlotVerifyData| - you will have
  195 + * to pass these yourself.
195 196 *
196 197 * If a slot was selected and it verified then AVB_AB_FLOW_RESULT_OK
197 198 * is returned.
198 199 *
199 200 * If a slot was selected but it didn't verify then
200 201 * AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR is returned. This can
201   - * only happen when |allow_verification_error| is true.
  202 + * only happen when the AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
  203 + * flag is set.
202 204 *
203 205 * If an I/O operation - such as loading/saving metadata or checking
204 206 * rollback indexes - fail, the value AVB_AB_FLOW_RESULT_ERROR_IO is
205 207  
206 208  
... ... @@ -207,17 +209,24 @@
207 209 * If memory allocation fails, AVB_AB_FLOW_RESULT_ERROR_OOM is
208 210 * returned.
209 211 *
  212 + * If invalid arguments are passed,
  213 + * AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT is returned. For example
  214 + * this can happen if using AVB_HASHTREE_ERROR_MODE_LOGGING without
  215 + * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
  216 + *
210 217 * Reasonable behavior for handling AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS
211 218 * is to initiate device repair (which is device-dependent).
212 219 */
213 220 AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
214 221 const char* const* requested_partitions,
215   - bool allow_verification_error,
  222 + AvbSlotVerifyFlags flags,
  223 + AvbHashtreeErrorMode hashtree_error_mode,
216 224 AvbSlotVerifyData** out_data);
217 225  
218 226 AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
219 227 const char* const* requested_partitions,
220   - bool allow_verification_error,
  228 + AvbSlotVerifyFlags flags,
  229 + AvbHashtreeErrorMode hashtree_error_mode,
221 230 AvbSlotVerifyData** out_data);
222 231  
223 232 /* Marks the slot with the given slot number as active. Returns