blob: 40bfbe5cd6328e649b62e40bbc777f39ea8fc873 [file] [log] [blame]
Monika Singhb15747d2017-09-25 14:01:13 +05301/*
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_slot_verify.h"
26#include "avb_chain_partition_descriptor.h"
27#include "avb_footer.h"
28#include "avb_hash_descriptor.h"
29#include "avb_kernel_cmdline_descriptor.h"
30#include "avb_sha.h"
31#include "avb_util.h"
32#include "avb_vbmeta_image.h"
33#include "avb_version.h"
34
35/* Maximum allow length (in bytes) of a partition name, including
36 * ab_suffix.
37 */
38#define PART_NAME_MAX_SIZE 32
39
40/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
41#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
42
43/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
44#define MAX_NUMBER_OF_VBMETA_IMAGES 32
45
46/* Maximum size of a vbmeta image - 64 KiB. */
47#define VBMETA_MAX_SIZE (64 * 1024)
48
49/* Helper function to see if we should continue with verification in
50 * allow_verification_error=true mode if something goes wrong. See the
51 * comments for the avb_slot_verify() function for more information.
52 */
53static inline bool result_should_continue(AvbSlotVerifyResult result) {
54 switch (result) {
55 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
56 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
57 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
58 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
59 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
60 return false;
61
62 case AVB_SLOT_VERIFY_RESULT_OK:
63 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
64 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
65 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
66 return true;
67 }
68
69 return false;
70}
71
72static AvbSlotVerifyResult load_and_verify_hash_partition(
73 AvbOps* ops,
74 const char* const* requested_partitions,
75 const char* ab_suffix,
76 bool allow_verification_error,
77 const AvbDescriptor* descriptor,
78 AvbSlotVerifyData* slot_data) {
79 AvbHashDescriptor hash_desc;
80 const uint8_t* desc_partition_name = NULL;
81 const uint8_t* desc_salt;
82 const uint8_t* desc_digest;
83 char part_name[PART_NAME_MAX_SIZE];
84 AvbSlotVerifyResult ret;
85 AvbIOResult io_ret;
86 uint8_t* image_buf = NULL;
87 size_t part_num_read;
88 uint8_t* digest = NULL;
89 size_t digest_len;
90 const char* found = NULL;
91 uint64_t image_size;
92
93 if (!avb_hash_descriptor_validate_and_byteswap(
94 (const AvbHashDescriptor*)descriptor, &hash_desc)) {
95 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
96 goto out;
97 }
98 desc_partition_name =
99 ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
100 desc_salt = desc_partition_name + hash_desc.partition_name_len;
101 desc_digest = desc_salt + hash_desc.salt_len;
102
103 if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
104 avb_error("Partition name is not valid UTF-8.\n");
105 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
106 goto out;
107 }
108
109 /* Don't bother loading or validating unless the partition was
110 * requested in the first place.
111 */
112 found = avb_strv_find_str(requested_partitions,
113 (const char*)desc_partition_name,
114 hash_desc.partition_name_len);
115 if (found == NULL) {
116 ret = AVB_SLOT_VERIFY_RESULT_OK;
117 goto out;
118 }
119
120 if (!avb_str_concat(part_name,
121 sizeof part_name,
122 (const char*)desc_partition_name,
123 hash_desc.partition_name_len,
124 ab_suffix,
125 avb_strlen(ab_suffix))) {
126 avb_error("Partition name and suffix does not fit.\n");
127 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
128 goto out;
129 }
130
131 /* If we're allowing verification errors then hash_desc.image_size
132 * may no longer match what's in the partition... so in this case
133 * just load the entire partition.
134 *
135 * For example, this can happen if a developer does 'fastboot flash
136 * boot /path/to/new/and/bigger/boot.img'. We want this to work
137 * since it's such a common workflow.
138 */
139 image_size = hash_desc.image_size;
140 if (allow_verification_error) {
141 if (ops->get_size_of_partition == NULL) {
142 avb_errorv(part_name,
143 ": The get_size_of_partition() operation is "
144 "not implemented so we may not load the entire partition. "
145 "Please implement.",
146 NULL);
147 } else {
148 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
149 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
150 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
151 goto out;
152 } else if (io_ret != AVB_IO_RESULT_OK) {
153 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
154 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
155 goto out;
156 }
157 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
158 }
159 }
160
Monika Singh7a5c2ed2018-08-30 15:57:24 +0530161 if (!strncmp(part_name, "boot", strlen("boot"))) {
162 image_size = hash_desc.image_size;
163 }
164
165 io_ret = ops->read_from_partition(
Monika Singh3dee8c72018-12-03 17:16:13 +0530166 ops, found, 0 /* offset */, image_size, &image_buf, &part_num_read);
Monika Singh7a5c2ed2018-08-30 15:57:24 +0530167
Monika Singhb15747d2017-09-25 14:01:13 +0530168 if (image_buf == NULL) {
169 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
170 goto out;
171 }
Monika Singhb15747d2017-09-25 14:01:13 +0530172 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
173 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
174 goto out;
175 } else if (io_ret != AVB_IO_RESULT_OK) {
176 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
177 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
178 goto out;
179 }
Monika Singh7a5c2ed2018-08-30 15:57:24 +0530180 if (part_num_read < image_size) {
Monika Singhb15747d2017-09-25 14:01:13 +0530181 avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
182 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
183 goto out;
184 }
185
186 if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
187 uint32_t complete_len = hash_desc.salt_len + hash_desc.image_size;
Monika Singhb15747d2017-09-25 14:01:13 +0530188 digest = avb_malloc(AVB_SHA256_DIGEST_SIZE);
Monika Singh08d26892018-09-10 15:58:07 +0530189 if(digest == NULL || hash_desc.salt_len > SALT_BUFF_OFFSET )
Monika Singh0f7bfc82018-04-16 23:14:29 +0530190 {
191 avb_errorv(part_name, ": Failed to allocate memory\n", NULL);
192 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
193 goto out;
194 }
Monika Singh08d26892018-09-10 15:58:07 +0530195 image_buf = ADD_SALT_BUFF_OFFSET(image_buf) - hash_desc.salt_len;
196 avb_memcpy(image_buf, desc_salt, hash_desc.salt_len);
197 hash_find(image_buf, complete_len, digest, CRYPTO_AUTH_ALG_SHA256);
Monika Singh871d4b12018-10-08 00:06:18 +0530198 image_buf = SUB_SALT_BUFF_OFFSET(image_buf) + hash_desc.salt_len;
Monika Singhb15747d2017-09-25 14:01:13 +0530199 digest_len = AVB_SHA256_DIGEST_SIZE;
200 } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
201 AvbSHA512Ctx sha512_ctx;
202 uint8_t *dig;
203 digest = avb_malloc(AVB_SHA512_DIGEST_SIZE);
Monika Singh0f7bfc82018-04-16 23:14:29 +0530204 if(digest == NULL)
205 {
206 avb_errorv(part_name, ": Failed to allocate memory\n", NULL);
207 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
208 goto out;
209 }
Monika Singhb15747d2017-09-25 14:01:13 +0530210 avb_sha512_init(&sha512_ctx);
211 avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
212 avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
213 dig = avb_sha512_final(&sha512_ctx);
214 digest_len = AVB_SHA512_DIGEST_SIZE;
215 avb_memcpy(digest, dig, AVB_SHA512_DIGEST_SIZE);
216 } else {
217 avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
218 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
219 goto out;
220 }
221
222 if (digest_len != hash_desc.digest_len) {
223 avb_errorv(
224 part_name, ": Digest in descriptor not of expected size.\n", NULL);
225 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
226 goto out;
227 }
228
229 if (avb_safe_memcmp(digest, desc_digest, digest_len) != 0) {
230 avb_errorv(part_name,
231 ": Hash of data does not match digest in descriptor.\n",
232 NULL);
233 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
234 goto out;
235 }
236
237 ret = AVB_SLOT_VERIFY_RESULT_OK;
238
239out:
240 if (digest)
241 avb_free(digest);
242 /* If it worked and something was loaded, copy to slot_data. */
243 if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
244 image_buf != NULL) {
245 AvbPartitionData* loaded_partition;
246 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
247 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
248 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
249 goto fail;
250 }
251 loaded_partition =
252 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
253 loaded_partition->partition_name = avb_strdup(found);
254 loaded_partition->data_size = image_size;
255 loaded_partition->data = image_buf;
256 image_buf = NULL;
257 }
258
259fail:
260 //remove avb_free() as memory allocated from scratch region
261 return ret;
262}
263
264static AvbSlotVerifyResult load_requested_partitions(
265 AvbOps* ops,
266 const char* const* requested_partitions,
267 const char* ab_suffix,
268 AvbSlotVerifyData* slot_data) {
269 AvbSlotVerifyResult ret;
270 uint8_t* image_buf = NULL;
271 size_t n;
272
273 if (ops->get_size_of_partition == NULL) {
274 avb_error("get_size_of_partition() not implemented.\n");
275 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
276 goto out;
277 }
278
279 for (n = 0; requested_partitions[n] != NULL; n++) {
280 char part_name[PART_NAME_MAX_SIZE];
281 AvbIOResult io_ret;
282 uint64_t image_size;
283 size_t part_num_read;
284 AvbPartitionData* loaded_partition;
285
286 if (!avb_str_concat(part_name,
287 sizeof part_name,
288 requested_partitions[n],
289 avb_strlen(requested_partitions[n]),
290 ab_suffix,
291 avb_strlen(ab_suffix))) {
292 avb_error("Partition name and suffix does not fit.\n");
293 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
294 goto out;
295 }
296
297 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
298 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
299 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
300 goto out;
301 } else if (io_ret != AVB_IO_RESULT_OK) {
302 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
303 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
304 goto out;
305 }
306 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
307
Monika Singhb15747d2017-09-25 14:01:13 +0530308 io_ret = ops->read_from_partition(
Monika Singh85eabad2018-11-21 12:07:29 +0530309 ops, part_name, 0 /* offset */, image_size, &image_buf, &part_num_read);
Monika Singhb15747d2017-09-25 14:01:13 +0530310 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
311 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
312 goto out;
313 } else if (io_ret != AVB_IO_RESULT_OK) {
314 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
315 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
316 goto out;
317 }
318 if (part_num_read != image_size) {
319 avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
320 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
321 goto out;
322 }
323
324 /* Move to slot_data. */
325 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
326 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
327 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
328 goto out;
329 }
330 loaded_partition =
331 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
332 loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
333 if (loaded_partition->partition_name == NULL) {
334 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
335 goto out;
336 }
337 loaded_partition->data_size = image_size;
338 loaded_partition->data = image_buf;
339 image_buf = NULL;
340 }
341
342 ret = AVB_SLOT_VERIFY_RESULT_OK;
343
344out:
345 if (image_buf != NULL) {
346 avb_free(image_buf);
347 }
348 return ret;
349}
350
351static AvbSlotVerifyResult load_and_verify_vbmeta(
352 AvbOps* ops,
353 const char* const* requested_partitions,
354 const char* ab_suffix,
355 bool allow_verification_error,
356 AvbVBMetaImageFlags toplevel_vbmeta_flags,
357 int rollback_index_location,
358 const char* partition_name,
359 size_t partition_name_len,
360 const uint8_t* expected_public_key,
361 size_t expected_public_key_length,
362 AvbSlotVerifyData* slot_data,
363 AvbAlgorithmType* out_algorithm_type) {
364 char full_partition_name[PART_NAME_MAX_SIZE];
365 AvbSlotVerifyResult ret;
366 AvbIOResult io_ret;
Monika Singh5c317dc2018-09-25 11:09:55 +0530367 UINTN vbmeta_offset;
Monika Singhb15747d2017-09-25 14:01:13 +0530368 size_t vbmeta_size;
369 uint8_t* vbmeta_buf = NULL;
370 size_t vbmeta_num_read;
371 AvbVBMetaVerifyResult vbmeta_ret;
372 const uint8_t* pk_data;
373 size_t pk_len;
374 AvbVBMetaImageHeader vbmeta_header;
375 uint64_t stored_rollback_index;
376 const AvbDescriptor** descriptors = NULL;
377 size_t num_descriptors;
378 size_t n;
379 bool is_main_vbmeta;
380 bool is_vbmeta_partition;
381 AvbVBMetaData* vbmeta_image_data = NULL;
382
383 ret = AVB_SLOT_VERIFY_RESULT_OK;
384
385 avb_assert(slot_data != NULL);
386
387 /* Since we allow top-level vbmeta in 'boot', use
388 * rollback_index_location to determine whether we're the main
389 * vbmeta struct.
390 */
391 is_main_vbmeta = (rollback_index_location == 0);
392 is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
393
394 if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
395 avb_error("Partition name is not valid UTF-8.\n");
396 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
397 goto out;
398 }
399
400 /* Construct full partition name. */
401 if (!avb_str_concat(full_partition_name,
402 sizeof full_partition_name,
403 partition_name,
404 partition_name_len,
405 ab_suffix,
406 avb_strlen(ab_suffix))) {
407 avb_error("Partition name and suffix does not fit.\n");
408 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
409 goto out;
410 }
411
412 avb_debugv("Loading vbmeta struct from partition '",
413 full_partition_name,
414 "'.\n",
415 NULL);
416
417 /* If we're loading from the main vbmeta partition, the vbmeta
418 * struct is in the beginning. Otherwise we have to locate it via a
419 * footer.
420 */
421 if (is_vbmeta_partition) {
422 vbmeta_offset = 0;
423 vbmeta_size = VBMETA_MAX_SIZE;
Monika Singh3dee8c72018-12-03 17:16:13 +0530424 io_ret = ops->read_from_partition(ops,
425 partition_name,
426 vbmeta_offset,
427 vbmeta_size,
428 &vbmeta_buf,
429 &vbmeta_num_read);
430 if (vbmeta_buf == NULL) {
431 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
432 goto out;
433 }
Monika Singhb15747d2017-09-25 14:01:13 +0530434 } else {
435 uint8_t footer_buf[AVB_FOOTER_SIZE];
436 size_t footer_num_read;
437 AvbFooter footer;
438
439 io_ret = ops->read_from_partition(ops,
440 full_partition_name,
441 -AVB_FOOTER_SIZE,
442 AVB_FOOTER_SIZE,
443 footer_buf,
444 &footer_num_read);
445 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
446 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
447 goto out;
448 } else if (io_ret != AVB_IO_RESULT_OK) {
449 avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
450 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
451 goto out;
452 }
453 avb_assert(footer_num_read == AVB_FOOTER_SIZE);
454
455 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
456 &footer)) {
457 avb_errorv(full_partition_name, ": Error validating footer.\n", NULL);
458 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
459 goto out;
460 }
461
462 /* Basic footer sanity check since the data is untrusted. */
463 if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
464 avb_errorv(
465 full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
466 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
467 goto out;
468 }
Monika Singhb15747d2017-09-25 14:01:13 +0530469 vbmeta_offset = footer.vbmeta_offset;
470 vbmeta_size = footer.vbmeta_size;
Monika Singh3dee8c72018-12-03 17:16:13 +0530471 vbmeta_buf = avb_malloc(vbmeta_size); // for chain partitions
Monika Singh5c317dc2018-09-25 11:09:55 +0530472 if (vbmeta_buf == NULL) {
473 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
474 goto out;
475 }
476 io_ret = ops->read_from_partition(ops,
477 full_partition_name,
478 vbmeta_offset,
479 vbmeta_size,
480 vbmeta_buf,
481 &vbmeta_num_read);
482 }
Monika Singhb15747d2017-09-25 14:01:13 +0530483
Monika Singhb15747d2017-09-25 14:01:13 +0530484 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
485 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
486 goto out;
487 } else if (io_ret != AVB_IO_RESULT_OK) {
488 /* If we're looking for 'vbmeta' but there is no such partition,
489 * go try to get it from the boot partition instead.
490 */
491 if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
492 is_vbmeta_partition) {
493 avb_debugv(full_partition_name,
494 ": No such partition. Trying 'boot' instead.\n",
495 NULL);
496 ret = load_and_verify_vbmeta(ops,
497 requested_partitions,
498 ab_suffix,
499 allow_verification_error,
500 0 /* toplevel_vbmeta_flags */,
501 0 /* rollback_index_location */,
502 "boot",
503 avb_strlen("boot"),
504 NULL /* expected_public_key */,
505 0 /* expected_public_key_length */,
506 slot_data,
507 out_algorithm_type);
508 goto out;
509 } else {
510 avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
511 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
512 goto out;
513 }
514 }
515 avb_assert(vbmeta_num_read <= vbmeta_size);
516
517 /* Check if the image is properly signed and get the public key used
518 * to sign the image.
519 */
520 vbmeta_ret =
521 avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
522 switch (vbmeta_ret) {
523 case AVB_VBMETA_VERIFY_RESULT_OK:
524 avb_assert(pk_data != NULL && pk_len > 0);
525 break;
526
527 case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
528 case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
529 case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
530 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
531 avb_errorv(full_partition_name,
532 ": Error verifying vbmeta image: ",
533 avb_vbmeta_verify_result_to_string(vbmeta_ret),
534 "\n",
535 NULL);
536 if (!allow_verification_error) {
537 goto out;
538 }
539 break;
540
541 case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
542 /* No way to continue this case. */
543 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
544 avb_errorv(full_partition_name,
545 ": Error verifying vbmeta image: invalid vbmeta header\n",
546 NULL);
547 goto out;
548
549 case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
550 /* No way to continue this case. */
551 ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
552 avb_errorv(full_partition_name,
553 ": Error verifying vbmeta image: unsupported AVB version\n",
554 NULL);
555 goto out;
556 }
557
558 /* Byteswap the header. */
559 avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
560 &vbmeta_header);
561
562 /* If we're the toplevel, assign flags so they'll be passed down. */
563 if (is_main_vbmeta) {
564 toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
565 } else {
566 if (vbmeta_header.flags != 0) {
567 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
568 avb_errorv(full_partition_name,
569 ": chained vbmeta image has non-zero flags\n",
570 NULL);
571 goto out;
572 }
573 }
574
575 /* Check if key used to make signature matches what is expected. */
576 if (pk_data != NULL) {
577 if (expected_public_key != NULL) {
578 avb_assert(!is_main_vbmeta);
579 if (expected_public_key_length != pk_len ||
580 avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
581 avb_errorv(full_partition_name,
582 ": Public key used to sign data does not match key in chain "
583 "partition descriptor.\n",
584 NULL);
585 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
586 if (!allow_verification_error) {
587 goto out;
588 }
589 }
590 } else {
591 bool key_is_trusted = false;
592 const uint8_t* pk_metadata = NULL;
593 size_t pk_metadata_len = 0;
594
595 if (vbmeta_header.public_key_metadata_size > 0) {
596 pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
597 vbmeta_header.authentication_data_block_size +
598 vbmeta_header.public_key_metadata_offset;
599 pk_metadata_len = vbmeta_header.public_key_metadata_size;
600 }
601
602 avb_assert(is_main_vbmeta);
603 io_ret = ops->validate_vbmeta_public_key(
604 ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
605 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
606 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
607 goto out;
608 } else if (io_ret != AVB_IO_RESULT_OK) {
609 avb_errorv(full_partition_name,
610 ": Error while checking public key used to sign data.\n",
611 NULL);
612 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
613 goto out;
614 }
615 if (!key_is_trusted) {
616 avb_errorv(full_partition_name,
617 ": Public key used to sign data rejected.\n",
618 NULL);
619 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
620 if (!allow_verification_error) {
621 goto out;
622 }
623 }
624 }
625 }
626
627 /* Check rollback index. */
628 io_ret = ops->read_rollback_index(
629 ops, rollback_index_location, &stored_rollback_index);
630 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
631 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
632 goto out;
633 } else if (io_ret != AVB_IO_RESULT_OK) {
634 avb_errorv(full_partition_name,
635 ": Error getting rollback index for location.\n",
636 NULL);
637 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
638 goto out;
639 }
640 if (vbmeta_header.rollback_index < stored_rollback_index) {
641 avb_errorv(
642 full_partition_name,
643 ": Image rollback index is less than the stored rollback index.\n",
644 NULL);
645 ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
646 if (!allow_verification_error) {
647 goto out;
648 }
649 }
650
Monika Singh2c9d2b82018-05-01 12:24:59 +0530651 if (stored_rollback_index < vbmeta_header.rollback_index) {
652 io_ret = ops->write_rollback_index(
653 ops, rollback_index_location, vbmeta_header.rollback_index);
654 if (io_ret != AVB_IO_RESULT_OK) {
655 avb_errorv(full_partition_name,
656 ": Error storing rollback index for location.\n",
657 NULL);
658 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
659 goto out;
660 }
661 }
662
Monika Singhb15747d2017-09-25 14:01:13 +0530663 /* Copy vbmeta to vbmeta_images before recursing. */
664 if (is_main_vbmeta) {
665 avb_assert(slot_data->num_vbmeta_images == 0);
666 } else {
667 avb_assert(slot_data->num_vbmeta_images > 0);
668 }
669 if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
670 avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
671 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
672 goto out;
673 }
674 vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
675 vbmeta_image_data->partition_name = avb_strdup(partition_name);
676 vbmeta_image_data->vbmeta_data = vbmeta_buf;
677 /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
678 * and this includes data past the end of the image. Pass the
679 * actual size of the vbmeta image. Also, no need to use
680 * avb_safe_add() since the header has already been verified.
681 */
682 vbmeta_image_data->vbmeta_size =
683 sizeof(AvbVBMetaImageHeader) +
684 vbmeta_header.authentication_data_block_size +
685 vbmeta_header.auxiliary_data_block_size;
686 vbmeta_image_data->verify_result = vbmeta_ret;
687
688 /* If verification has been disabled by setting a bit in the image,
689 * we're done... except that we need to load the entirety of the
690 * requested partitions.
691 */
692 if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
693 AvbSlotVerifyResult sub_ret;
694 avb_debugv(
695 full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
696 /* If load_requested_partitions() fail it is always a fatal
697 * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
698 * than recoverable (e.g. one where result_should_continue()
699 * returns true) and we want to convey that error.
700 */
701 sub_ret = load_requested_partitions(
702 ops, requested_partitions, ab_suffix, slot_data);
703 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
704 ret = sub_ret;
705 }
706 goto out;
707 }
708
709 /* Now go through all descriptors and take the appropriate action:
710 *
711 * - hash descriptor: Load data from partition, calculate hash, and
712 * checks that it matches what's in the hash descriptor.
713 *
714 * - hashtree descriptor: Do nothing since verification happens
715 * on-the-fly from within the OS.
716 *
717 * - chained partition descriptor: Load the footer, load the vbmeta
718 * image, verify vbmeta image (includes rollback checks, hash
719 * checks, bail on chained partitions).
720 */
721 descriptors =
722 avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
Firoz Khan6f6d59e2018-09-19 14:24:13 +0530723 if (descriptors == NULL) {
724 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
725 goto out;
726 }
727
Monika Singhb15747d2017-09-25 14:01:13 +0530728 for (n = 0; n < num_descriptors; n++) {
729 AvbDescriptor desc;
730
731 if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
732 avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
733 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
734 goto out;
735 }
736
737 switch (desc.tag) {
738 case AVB_DESCRIPTOR_TAG_HASH: {
739 AvbSlotVerifyResult sub_ret;
740 sub_ret = load_and_verify_hash_partition(ops,
741 requested_partitions,
742 ab_suffix,
743 allow_verification_error,
744 descriptors[n],
745 slot_data);
746 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
747 ret = sub_ret;
748 if (!allow_verification_error || !result_should_continue(ret)) {
749 goto out;
750 }
751 }
752 } break;
753
754 case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
755 AvbSlotVerifyResult sub_ret;
756 AvbChainPartitionDescriptor chain_desc;
757 const uint8_t* chain_partition_name;
758 const uint8_t* chain_public_key;
759
760 /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
761 if (!is_main_vbmeta) {
762 avb_errorv(full_partition_name,
763 ": Encountered chain descriptor not in main image.\n",
764 NULL);
765 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
766 goto out;
767 }
768
769 if (!avb_chain_partition_descriptor_validate_and_byteswap(
770 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
771 avb_errorv(full_partition_name,
772 ": Chain partition descriptor is invalid.\n",
773 NULL);
774 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
775 goto out;
776 }
777
778 if (chain_desc.rollback_index_location == 0) {
779 avb_errorv(full_partition_name,
780 ": Chain partition has invalid "
781 "rollback_index_location field.\n",
782 NULL);
783 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
784 goto out;
785 }
786
787 chain_partition_name = ((const uint8_t*)descriptors[n]) +
788 sizeof(AvbChainPartitionDescriptor);
789 chain_public_key = chain_partition_name + chain_desc.partition_name_len;
790
791 sub_ret = load_and_verify_vbmeta(ops,
792 requested_partitions,
793 ab_suffix,
794 allow_verification_error,
795 toplevel_vbmeta_flags,
796 chain_desc.rollback_index_location,
797 (const char*)chain_partition_name,
798 chain_desc.partition_name_len,
799 chain_public_key,
800 chain_desc.public_key_len,
801 slot_data,
802 NULL /* out_algorithm_type */);
803 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
804 ret = sub_ret;
805 if (!result_should_continue(ret)) {
806 goto out;
807 }
808 }
809 } break;
810
811 case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
812 const uint8_t* kernel_cmdline;
813 AvbKernelCmdlineDescriptor kernel_cmdline_desc;
814 bool apply_cmdline;
815
816 if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
817 (AvbKernelCmdlineDescriptor*)descriptors[n],
818 &kernel_cmdline_desc)) {
819 avb_errorv(full_partition_name,
820 ": Kernel cmdline descriptor is invalid.\n",
821 NULL);
822 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
823 goto out;
824 }
825
826 kernel_cmdline = ((const uint8_t*)descriptors[n]) +
827 sizeof(AvbKernelCmdlineDescriptor);
828
829 if (!avb_validate_utf8(kernel_cmdline,
830 kernel_cmdline_desc.kernel_cmdline_length)) {
831 avb_errorv(full_partition_name,
832 ": Kernel cmdline is not valid UTF-8.\n",
833 NULL);
834 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
835 goto out;
836 }
837
838 /* Compare the flags for top-level VBMeta struct with flags in
839 * the command-line descriptor so command-line snippets only
840 * intended for a certain mode (dm-verity enabled/disabled)
841 * are skipped if applicable.
842 */
843 apply_cmdline = true;
844 if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
845 if (kernel_cmdline_desc.flags &
846 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
847 apply_cmdline = false;
848 }
849 } else {
850 if (kernel_cmdline_desc.flags &
851 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
852 apply_cmdline = false;
853 }
854 }
855
856 if (apply_cmdline) {
857 if (slot_data->cmdline == NULL) {
858 slot_data->cmdline =
859 avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
860 if (slot_data->cmdline == NULL) {
861 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
862 goto out;
863 }
864 avb_memcpy(slot_data->cmdline,
865 kernel_cmdline,
866 kernel_cmdline_desc.kernel_cmdline_length);
867 } else {
868 /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
869 size_t orig_size = avb_strlen(slot_data->cmdline);
870 size_t new_size =
871 orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
872 char* new_cmdline = avb_calloc(new_size);
873 if (new_cmdline == NULL) {
874 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
875 goto out;
876 }
877 avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
878 new_cmdline[orig_size] = ' ';
879 avb_memcpy(new_cmdline + orig_size + 1,
880 kernel_cmdline,
881 kernel_cmdline_desc.kernel_cmdline_length);
882 avb_free(slot_data->cmdline);
883 slot_data->cmdline = new_cmdline;
884 }
885 }
886 } break;
887
888 /* Explicit fall-through */
889 case AVB_DESCRIPTOR_TAG_PROPERTY:
890 case AVB_DESCRIPTOR_TAG_HASHTREE:
891 /* Do nothing. */
892 break;
893 }
894 }
895
896 if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
897 avb_errorv(
898 full_partition_name, ": Invalid rollback_index_location.\n", NULL);
899 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
900 goto out;
901 }
902
903 slot_data->rollback_indexes[rollback_index_location] =
904 vbmeta_header.rollback_index;
905
906 if (out_algorithm_type != NULL) {
907 *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
908 }
909
910out:
911 /* If |vbmeta_image_data| isn't NULL it means that it adopted
912 * |vbmeta_buf| so in that case don't free it here.
913 */
914
915 /* remove avb_free() as memory allocated from scratch region */
916
917 if (descriptors != NULL) {
918 avb_free(descriptors);
919 }
920 return ret;
921}
922
923#define NUM_GUIDS 3
924
925/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
926 * values. Returns NULL on OOM, otherwise the cmdline with values
927 * replaced.
928 */
929static char* sub_cmdline(AvbOps* ops,
930 const char* cmdline,
931 const char* ab_suffix,
932 bool using_boot_for_vbmeta) {
933 const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
934 const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
935 "$(ANDROID_BOOT_PARTUUID)",
936 "$(ANDROID_VBMETA_PARTUUID)"};
937 char* ret = NULL;
938 AvbIOResult io_ret;
939
940 /* Special-case for when the top-level vbmeta struct is in the boot
941 * partition.
942 */
943 if (using_boot_for_vbmeta) {
944 part_name_str[2] = "boot";
945 }
946
947 /* Replace unique partition GUIDs */
948 for (size_t n = 0; n < NUM_GUIDS; n++) {
949 char part_name[PART_NAME_MAX_SIZE];
950 char guid_buf[37];
951
952 if (!avb_str_concat(part_name,
953 sizeof part_name,
954 part_name_str[n],
955 avb_strlen(part_name_str[n]),
956 ab_suffix,
957 avb_strlen(ab_suffix))) {
958 avb_error("Partition name and suffix does not fit.\n");
959 goto fail;
960 }
961
962 io_ret = ops->get_unique_guid_for_partition(
963 ops, part_name, guid_buf, sizeof guid_buf);
964 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
965 return NULL;
966 } else if (io_ret != AVB_IO_RESULT_OK) {
967 avb_error("Error getting unique GUID for partition.\n");
968 goto fail;
969 }
970
971 if (ret == NULL) {
972 ret = avb_replace(cmdline, replace_str[n], guid_buf);
973 } else {
974 char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
975 avb_free(ret);
976 ret = new_ret;
977 }
978 if (ret == NULL) {
979 goto fail;
980 }
981 }
982
983 return ret;
984
985fail:
986 if (ret != NULL) {
987 avb_free(ret);
988 }
989 return NULL;
990}
991
992static int cmdline_append_option(AvbSlotVerifyData* slot_data,
993 const char* key,
994 const char* value) {
995 size_t offset, key_len, value_len;
996 char* new_cmdline;
997
998 key_len = avb_strlen(key);
999 value_len = avb_strlen(value);
1000
1001 offset = 0;
1002 if (slot_data->cmdline != NULL) {
1003 offset = avb_strlen(slot_data->cmdline);
1004 if (offset > 0) {
1005 offset += 1;
1006 }
1007 }
1008
1009 new_cmdline = avb_calloc(offset + key_len + value_len + 2);
1010 if (new_cmdline == NULL) {
1011 return 0;
1012 }
1013 if (offset > 0) {
1014 avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
1015 new_cmdline[offset - 1] = ' ';
1016 }
1017 avb_memcpy(new_cmdline + offset, key, key_len);
1018 new_cmdline[offset + key_len] = '=';
1019 avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
1020 if (slot_data->cmdline != NULL) {
1021 avb_free(slot_data->cmdline);
1022 }
1023 slot_data->cmdline = new_cmdline;
1024
1025 return 1;
1026}
1027
1028#define AVB_MAX_DIGITS_UINT64 32
1029
1030/* Writes |value| to |digits| in base 10 followed by a NUL byte.
1031 * Returns number of characters written excluding the NUL byte.
1032 */
1033static size_t uint64_to_base10(uint64_t value,
1034 char digits[AVB_MAX_DIGITS_UINT64]) {
1035 char rev_digits[AVB_MAX_DIGITS_UINT64];
1036 size_t n, num_digits;
1037
1038 for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
1039 rev_digits[num_digits++] = (value % 10) + '0';
1040 value /= 10;
1041 if (value == 0) {
1042 break;
1043 }
1044 }
1045
1046 for (n = 0; n < num_digits; n++) {
1047 digits[n] = rev_digits[num_digits - 1 - n];
1048 }
1049 digits[n] = '\0';
1050 return n;
1051}
1052
1053static int cmdline_append_version(AvbSlotVerifyData* slot_data,
1054 const char* key,
1055 uint64_t major_version,
1056 uint64_t minor_version) {
1057 char major_digits[AVB_MAX_DIGITS_UINT64];
1058 char minor_digits[AVB_MAX_DIGITS_UINT64];
1059 char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
1060 size_t num_major_digits, num_minor_digits;
1061
1062 num_major_digits = uint64_to_base10(major_version, major_digits);
1063 num_minor_digits = uint64_to_base10(minor_version, minor_digits);
1064 avb_memcpy(combined, major_digits, num_major_digits);
1065 combined[num_major_digits] = '.';
1066 avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
1067 combined[num_major_digits + 1 + num_minor_digits] = '\0';
1068
1069 return cmdline_append_option(slot_data, key, combined);
1070}
1071
1072static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
1073 const char* key,
1074 uint64_t value) {
1075 char digits[AVB_MAX_DIGITS_UINT64];
1076 uint64_to_base10(value, digits);
1077 return cmdline_append_option(slot_data, key, digits);
1078}
1079
1080static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
1081 const char* key,
1082 const uint8_t* data,
1083 size_t data_len) {
1084 char hex_digits[17] = "0123456789abcdef";
1085 char* hex_data;
1086 int ret;
1087 size_t n;
1088
1089 hex_data = avb_malloc(data_len * 2 + 1);
1090 if (hex_data == NULL) {
1091 return 0;
1092 }
1093
1094 for (n = 0; n < data_len; n++) {
1095 hex_data[n * 2] = hex_digits[data[n] >> 4];
1096 hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
1097 }
1098 hex_data[n * 2] = '\0';
1099
1100 ret = cmdline_append_option(slot_data, key, hex_data);
1101 avb_free(hex_data);
1102 return ret;
1103}
1104
1105static AvbSlotVerifyResult append_options(
1106 AvbOps* ops,
1107 AvbSlotVerifyData* slot_data,
1108 AvbVBMetaImageHeader* toplevel_vbmeta,
1109 AvbAlgorithmType algorithm_type,
1110 AvbHashtreeErrorMode hashtree_error_mode) {
1111 AvbSlotVerifyResult ret;
1112 const char* verity_mode = NULL;
1113 bool is_device_unlocked;
1114 AvbIOResult io_ret;
1115
1116 /* Add androidboot.vbmeta.device option. */
1117 if (!cmdline_append_option(slot_data,
1118 "androidboot.vbmeta.device",
1119 "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
1120 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1121 goto out;
1122 }
1123
1124 /* Add androidboot.vbmeta.avb_version option. */
1125 if (!cmdline_append_version(slot_data,
1126 "androidboot.vbmeta.avb_version",
1127 AVB_VERSION_MAJOR,
1128 AVB_VERSION_MINOR)) {
1129 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1130 goto out;
1131 }
1132
1133 /* Set androidboot.avb.device_state to "locked" or "unlocked". */
1134 io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
1135 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
1136 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1137 goto out;
1138 } else if (io_ret != AVB_IO_RESULT_OK) {
1139 avb_error("Error getting device state.\n");
1140 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1141 goto out;
1142 }
1143 if (!cmdline_append_option(slot_data,
1144 "androidboot.vbmeta.device_state",
1145 is_device_unlocked ? "unlocked" : "locked")) {
1146 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1147 goto out;
1148 }
1149
1150 /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
1151 * function as is used to sign vbmeta.
1152 */
1153 switch (algorithm_type) {
1154 /* Explicit fallthrough. */
1155 case AVB_ALGORITHM_TYPE_NONE:
1156 case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
1157 case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
1158 case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
1159 size_t n, prev_sz = 0, total_size = 0;
1160 uint8_t* digest = NULL;
1161 uint8_t* tbuf = NULL;
1162
1163 digest = avb_malloc(AVB_SHA256_DIGEST_SIZE);
Monika Singh0f7bfc82018-04-16 23:14:29 +05301164 if(digest == NULL)
1165 {
1166 avb_error("Failed to allocate memory\n");
1167 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1168 goto out;
1169 }
Monika Singhb15747d2017-09-25 14:01:13 +05301170 for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1171 total_size += slot_data->vbmeta_images[n].vbmeta_size;
1172 }
1173 tbuf = avb_malloc(total_size);
1174
1175 for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1176 avb_memcpy(tbuf + prev_sz, slot_data->vbmeta_images[n].vbmeta_data,
1177 slot_data->vbmeta_images[n].vbmeta_size);
1178 prev_sz = slot_data->vbmeta_images[n].vbmeta_size;
1179 }
1180 hash_find((unsigned char *)tbuf, total_size, digest, CRYPTO_AUTH_ALG_SHA256);
1181 avb_free(tbuf);
1182
1183 if (!cmdline_append_option(
1184 slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
1185 !cmdline_append_uint64_base10(
1186 slot_data, "androidboot.vbmeta.size", total_size) ||
1187 !cmdline_append_hex(slot_data,
1188 "androidboot.vbmeta.digest",
1189 digest,
1190 AVB_SHA256_DIGEST_SIZE)) {
1191 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1192 if (digest)
1193 avb_free(digest);
1194 goto out;
1195 }
1196 if (digest)
1197 avb_free(digest);
1198 } break;
1199 /* Explicit fallthrough. */
1200 case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
1201 case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
1202 case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
1203 AvbSHA512Ctx ctx;
1204 size_t n, total_size = 0;
1205 avb_sha512_init(&ctx);
1206 for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1207 avb_sha512_update(&ctx,
1208 slot_data->vbmeta_images[n].vbmeta_data,
1209 slot_data->vbmeta_images[n].vbmeta_size);
1210 total_size += slot_data->vbmeta_images[n].vbmeta_size;
1211 }
1212 if (!cmdline_append_option(
1213 slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
1214 !cmdline_append_uint64_base10(
1215 slot_data, "androidboot.vbmeta.size", total_size) ||
1216 !cmdline_append_hex(slot_data,
1217 "androidboot.vbmeta.digest",
1218 avb_sha512_final(&ctx),
1219 AVB_SHA512_DIGEST_SIZE)) {
1220 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1221 goto out;
1222 }
1223 } break;
1224 case _AVB_ALGORITHM_NUM_TYPES:
1225 avb_assert_not_reached();
1226 break;
1227 }
1228
1229 /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
1230 if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
1231 verity_mode = "disabled";
1232 } else {
1233 const char* dm_verity_mode = NULL;
1234 char* new_ret;
1235
1236 switch (hashtree_error_mode) {
1237 case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
1238 if (!cmdline_append_option(
1239 slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
1240 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1241 goto out;
1242 }
1243 verity_mode = "enforcing";
1244 dm_verity_mode = "restart_on_corruption";
1245 break;
1246 case AVB_HASHTREE_ERROR_MODE_RESTART:
1247 verity_mode = "enforcing";
1248 dm_verity_mode = "restart_on_corruption";
1249 break;
1250 case AVB_HASHTREE_ERROR_MODE_EIO:
1251 verity_mode = "eio";
1252 /* For now there's no option to specify the EIO mode. So
1253 * just use 'ignore_zero_blocks' since that's already set
1254 * and dm-verity-target.c supports specifying this multiple
1255 * times.
1256 */
1257 dm_verity_mode = "ignore_zero_blocks";
1258 break;
1259 case AVB_HASHTREE_ERROR_MODE_LOGGING:
1260 verity_mode = "logging";
1261 dm_verity_mode = "ignore_corruption";
1262 break;
1263 }
1264 new_ret = avb_replace(
1265 slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
1266 avb_free(slot_data->cmdline);
1267 slot_data->cmdline = new_ret;
1268 if (slot_data->cmdline == NULL) {
1269 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1270 goto out;
1271 }
1272 }
1273 if (!cmdline_append_option(
1274 slot_data, "androidboot.veritymode", verity_mode)) {
1275 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1276 goto out;
1277 }
1278
1279 ret = AVB_SLOT_VERIFY_RESULT_OK;
1280
1281out:
1282
1283 return ret;
1284}
1285
1286AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
1287 const char* const* requested_partitions,
1288 const char* ab_suffix,
1289 AvbSlotVerifyFlags flags,
1290 AvbHashtreeErrorMode hashtree_error_mode,
1291 AvbSlotVerifyData** out_data) {
1292 AvbSlotVerifyResult ret;
1293 AvbSlotVerifyData* slot_data = NULL;
1294 AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
1295 bool using_boot_for_vbmeta = false;
1296 AvbVBMetaImageHeader toplevel_vbmeta;
1297 bool allow_verification_error =
1298 (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
1299
1300 /* Fail early if we're missing the AvbOps needed for slot verification.
1301 *
1302 * For now, handle get_size_of_partition() not being implemented. In
1303 * a later release we may change that.
1304 */
1305 avb_assert(ops->read_is_device_unlocked != NULL);
1306 avb_assert(ops->read_from_partition != NULL);
1307 avb_assert(ops->validate_vbmeta_public_key != NULL);
1308 avb_assert(ops->read_rollback_index != NULL);
1309 avb_assert(ops->get_unique_guid_for_partition != NULL);
1310 /* avb_assert(ops->get_size_of_partition != NULL); */
1311
1312 if (out_data != NULL) {
1313 *out_data = NULL;
1314 }
1315
1316 /* Allowing dm-verity errors defeats the purpose of verified boot so
1317 * only allow this if set up to allow verification errors
1318 * (e.g. typically only UNLOCKED mode).
1319 */
1320 if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
1321 !allow_verification_error) {
1322 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1323 goto fail;
1324 }
1325
1326 slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
1327 if (slot_data == NULL) {
1328 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1329 goto fail;
1330 }
1331 slot_data->vbmeta_images =
1332 avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
1333 if (slot_data->vbmeta_images == NULL) {
1334 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1335 goto fail;
1336 }
1337 slot_data->loaded_partitions =
1338 avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
1339 if (slot_data->loaded_partitions == NULL) {
1340 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1341 goto fail;
1342 }
1343
1344 ret = load_and_verify_vbmeta(ops,
1345 requested_partitions,
1346 ab_suffix,
1347 allow_verification_error,
1348 0 /* toplevel_vbmeta_flags */,
1349 0 /* rollback_index_location */,
1350 "vbmeta",
1351 avb_strlen("vbmeta"),
1352 NULL /* expected_public_key */,
1353 0 /* expected_public_key_length */,
1354 slot_data,
1355 &algorithm_type);
1356 if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1357 goto fail;
1358 }
1359
1360 /* If things check out, mangle the kernel command-line as needed. */
1361 if (result_should_continue(ret)) {
1362 if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
1363 avb_assert(
1364 avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
1365 using_boot_for_vbmeta = true;
1366 }
1367
1368 /* Byteswap top-level vbmeta header since we'll need it below. */
1369 avb_vbmeta_image_header_to_host_byte_order(
1370 (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
1371 &toplevel_vbmeta);
1372
1373 /* Fill in |ab_suffix| field. */
1374 slot_data->ab_suffix = avb_strdup(ab_suffix);
1375 if (slot_data->ab_suffix == NULL) {
1376 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1377 goto fail;
1378 }
1379
1380 /* If verification is disabled, we are done ... we specifically
1381 * don't want to add any androidboot.* options since verification
1382 * is disabled.
1383 */
1384 if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
1385 /* Since verification is disabled we didn't process any
1386 * descriptors and thus there's no cmdline... so set root= such
1387 * that the system partition is mounted.
1388 */
1389 avb_assert(slot_data->cmdline == NULL);
1390 slot_data->cmdline =
1391 avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
1392 if (slot_data->cmdline == NULL) {
1393 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1394 goto fail;
1395 }
1396 } else {
1397 /* Add options - any failure in append_options() is either an
1398 * I/O or OOM error.
1399 */
1400 AvbSlotVerifyResult sub_ret = append_options(ops,
1401 slot_data,
1402 &toplevel_vbmeta,
1403 algorithm_type,
1404 hashtree_error_mode);
1405 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1406 ret = sub_ret;
1407 goto fail;
1408 }
1409 }
1410
1411 /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1412 if (slot_data->cmdline != NULL) {
1413 char* new_cmdline;
1414 new_cmdline = sub_cmdline(
1415 ops, slot_data->cmdline, ab_suffix, using_boot_for_vbmeta);
1416 if (new_cmdline == NULL) {
1417 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1418 goto fail;
1419 }
1420 avb_free(slot_data->cmdline);
1421 slot_data->cmdline = new_cmdline;
1422 }
1423
1424 if (out_data != NULL) {
1425 *out_data = slot_data;
1426 } else {
1427 avb_slot_verify_data_free(slot_data);
1428 }
1429 }
1430
1431 if (!allow_verification_error) {
1432 avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1433 }
1434
1435 return ret;
1436
1437fail:
1438 if (slot_data != NULL) {
1439 avb_slot_verify_data_free(slot_data);
1440 }
1441 return ret;
1442}
1443
1444void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1445 if (data->ab_suffix != NULL) {
1446 avb_free(data->ab_suffix);
1447 }
1448 if (data->cmdline != NULL) {
1449 avb_free(data->cmdline);
1450 }
1451 if (data->vbmeta_images != NULL) {
1452 size_t n;
1453 for (n = 0; n < data->num_vbmeta_images; n++) {
1454 AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
1455 if (vbmeta_image->partition_name != NULL) {
1456 avb_free(vbmeta_image->partition_name);
1457 }
1458 if (vbmeta_image->vbmeta_data != NULL) {
1459 vbmeta_image->vbmeta_data = NULL;
1460 }
1461 }
1462 avb_free(data->vbmeta_images);
1463 }
1464 if (data->loaded_partitions != NULL) {
1465 size_t n;
1466 for (n = 0; n < data->num_loaded_partitions; n++) {
1467 AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1468 if (loaded_partition->partition_name != NULL) {
1469 avb_free(loaded_partition->partition_name);
1470 }
1471 if (loaded_partition->data != NULL) {
1472 if (data->num_loaded_partitions == 1)
1473 loaded_partition->data = NULL;
1474 }
1475 }
1476 avb_free(data->loaded_partitions);
1477 }
1478 avb_free(data);
1479}
1480
1481const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
1482 const char* ret = NULL;
1483
1484 switch (result) {
1485 case AVB_SLOT_VERIFY_RESULT_OK:
1486 ret = "OK";
1487 break;
1488 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
1489 ret = "ERROR_OOM";
1490 break;
1491 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
1492 ret = "ERROR_IO";
1493 break;
1494 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
1495 ret = "ERROR_VERIFICATION";
1496 break;
1497 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
1498 ret = "ERROR_ROLLBACK_INDEX";
1499 break;
1500 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
1501 ret = "ERROR_PUBLIC_KEY_REJECTED";
1502 break;
1503 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
1504 ret = "ERROR_INVALID_METADATA";
1505 break;
1506 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1507 ret = "ERROR_UNSUPPORTED_VERSION";
1508 break;
1509 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
1510 ret = "ERROR_INVALID_ARGUMENT";
1511 break;
1512 /* Do not add a 'default:' case here because of -Wswitch. */
1513 }
1514
1515 if (ret == NULL) {
1516 avb_error("Unknown AvbSlotVerifyResult value.\n");
1517 ret = "(unknown)";
1518 }
1519
1520 return ret;
1521}