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