1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include "avb_slot_verify.h"
26 #include "avb_chain_partition_descriptor.h"
27 #include "avb_cmdline.h"
28 #include "avb_footer.h"
29 #include "avb_hash_descriptor.h"
30 #include "avb_hashtree_descriptor.h"
31 #include "avb_kernel_cmdline_descriptor.h"
32 #include "avb_sha.h"
33 #include "avb_util.h"
34 #include "avb_vbmeta_image.h"
35 #include "avb_version.h"
36
37 /* Maximum number of partitions that can be loaded with avb_slot_verify(). */
38 #define MAX_NUMBER_OF_LOADED_PARTITIONS 32
39
40 /* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
41 #define MAX_NUMBER_OF_VBMETA_IMAGES 32
42
43 /* Maximum size of a vbmeta image - 64 KiB. */
44 #define VBMETA_MAX_SIZE (64 * 1024)
45
46 /* Helper function to see if we should continue with verification in
47 * allow_verification_error=true mode if something goes wrong. See the
48 * comments for the avb_slot_verify() function for more information.
49 */
result_should_continue(AvbSlotVerifyResult result)50 static inline bool result_should_continue(AvbSlotVerifyResult result) {
51 switch (result) {
52 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
53 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
54 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
55 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
56 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
57 return false;
58
59 case AVB_SLOT_VERIFY_RESULT_OK:
60 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
61 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
62 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
63 return true;
64 }
65
66 return false;
67 }
68
load_full_partition(AvbOps * ops,const char * part_name,uint64_t image_size,uint8_t ** out_image_buf,bool * out_image_preloaded)69 static AvbSlotVerifyResult load_full_partition(AvbOps* ops,
70 const char* part_name,
71 uint64_t image_size,
72 uint8_t** out_image_buf,
73 bool* out_image_preloaded) {
74 size_t part_num_read;
75 AvbIOResult io_ret;
76
77 /* Make sure that we do not overwrite existing data. */
78 avb_assert(*out_image_buf == NULL);
79 avb_assert(!*out_image_preloaded);
80
81 /* We are going to implicitly cast image_size from uint64_t to size_t in the
82 * following code, so we need to make sure that the cast is safe. */
83 if (image_size != (size_t)(image_size)) {
84 avb_errorv(part_name, ": Partition size too large to load.\n", NULL);
85 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
86 }
87
88 /* Try use a preloaded one. */
89 if (ops->get_preloaded_partition != NULL) {
90 io_ret = ops->get_preloaded_partition(
91 ops, part_name, image_size, out_image_buf, &part_num_read);
92 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
93 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
94 } else if (io_ret != AVB_IO_RESULT_OK) {
95 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
96 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
97 }
98
99 if (*out_image_buf != NULL) {
100 if (part_num_read != image_size) {
101 avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
102 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
103 }
104 *out_image_preloaded = true;
105 }
106 }
107
108 /* Allocate and copy the partition. */
109 if (!*out_image_preloaded) {
110 *out_image_buf = avb_malloc(image_size);
111 if (*out_image_buf == NULL) {
112 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
113 }
114
115 io_ret = ops->read_from_partition(ops,
116 part_name,
117 0 /* offset */,
118 image_size,
119 *out_image_buf,
120 &part_num_read);
121 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
122 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
123 } else if (io_ret != AVB_IO_RESULT_OK) {
124 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
125 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
126 }
127 if (part_num_read != image_size) {
128 avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
129 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
130 }
131 }
132
133 return AVB_SLOT_VERIFY_RESULT_OK;
134 }
135
read_persistent_digest(AvbOps * ops,const char * part_name,size_t expected_digest_size,uint8_t * out_digest)136 static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops,
137 const char* part_name,
138 size_t expected_digest_size,
139 uint8_t* out_digest) {
140 char* persistent_value_name = NULL;
141 AvbIOResult io_ret = AVB_IO_RESULT_OK;
142 size_t stored_digest_size = 0;
143
144 if (ops->read_persistent_value == NULL) {
145 avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
146 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
147 }
148 persistent_value_name =
149 avb_strdupv(AVB_NPV_PERSISTENT_DIGEST_PREFIX, part_name, NULL);
150 if (persistent_value_name == NULL) {
151 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
152 }
153 io_ret = ops->read_persistent_value(ops,
154 persistent_value_name,
155 expected_digest_size,
156 out_digest,
157 &stored_digest_size);
158 avb_free(persistent_value_name);
159 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
160 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
161 } else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
162 avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
163 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
164 } else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
165 io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE ||
166 expected_digest_size != stored_digest_size) {
167 avb_errorv(
168 part_name, ": Persistent digest is not of expected size.\n", NULL);
169 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
170 } else if (io_ret != AVB_IO_RESULT_OK) {
171 avb_errorv(part_name, ": Error reading persistent digest.\n", NULL);
172 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
173 }
174 return AVB_SLOT_VERIFY_RESULT_OK;
175 }
176
load_and_verify_hash_partition(AvbOps * ops,const char * const * requested_partitions,const char * ab_suffix,bool allow_verification_error,const AvbDescriptor * descriptor,AvbSlotVerifyData * slot_data)177 static AvbSlotVerifyResult load_and_verify_hash_partition(
178 AvbOps* ops,
179 const char* const* requested_partitions,
180 const char* ab_suffix,
181 bool allow_verification_error,
182 const AvbDescriptor* descriptor,
183 AvbSlotVerifyData* slot_data) {
184 AvbHashDescriptor hash_desc;
185 const uint8_t* desc_partition_name = NULL;
186 const uint8_t* desc_salt;
187 const uint8_t* desc_digest;
188 char part_name[AVB_PART_NAME_MAX_SIZE];
189 AvbSlotVerifyResult ret;
190 AvbIOResult io_ret;
191 uint8_t* image_buf = NULL;
192 bool image_preloaded = false;
193 uint8_t* digest;
194 size_t digest_len;
195 const char* found;
196 uint64_t image_size;
197 size_t expected_digest_len = 0;
198 uint8_t expected_digest_buf[AVB_SHA512_DIGEST_SIZE];
199 const uint8_t* expected_digest = NULL;
200
201 if (!avb_hash_descriptor_validate_and_byteswap(
202 (const AvbHashDescriptor*)descriptor, &hash_desc)) {
203 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
204 goto out;
205 }
206
207 desc_partition_name =
208 ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
209 desc_salt = desc_partition_name + hash_desc.partition_name_len;
210 desc_digest = desc_salt + hash_desc.salt_len;
211
212 if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
213 avb_error("Partition name is not valid UTF-8.\n");
214 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
215 goto out;
216 }
217
218 /* Don't bother loading or validating unless the partition was
219 * requested in the first place.
220 */
221 found = avb_strv_find_str(requested_partitions,
222 (const char*)desc_partition_name,
223 hash_desc.partition_name_len);
224 if (found == NULL) {
225 ret = AVB_SLOT_VERIFY_RESULT_OK;
226 goto out;
227 }
228
229 if ((hash_desc.flags & AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) != 0) {
230 /* No ab_suffix, just copy the partition name as is. */
231 if (hash_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
232 avb_error("Partition name does not fit.\n");
233 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
234 goto out;
235 }
236 avb_memcpy(part_name, desc_partition_name, hash_desc.partition_name_len);
237 part_name[hash_desc.partition_name_len] = '\0';
238 } else if (hash_desc.digest_len == 0 && avb_strlen(ab_suffix) != 0) {
239 /* No ab_suffix allowed for partitions without a digest in the descriptor
240 * because these partitions hold data unique to this device and are not
241 * updated using an A/B scheme.
242 */
243 avb_error("Cannot use A/B with a persistent digest.\n");
244 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
245 goto out;
246 } else {
247 /* Add ab_suffix to the partition name. */
248 if (!avb_str_concat(part_name,
249 sizeof part_name,
250 (const char*)desc_partition_name,
251 hash_desc.partition_name_len,
252 ab_suffix,
253 avb_strlen(ab_suffix))) {
254 avb_error("Partition name and suffix does not fit.\n");
255 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
256 goto out;
257 }
258 }
259
260 /* If we're allowing verification errors then hash_desc.image_size
261 * may no longer match what's in the partition... so in this case
262 * just load the entire partition.
263 *
264 * For example, this can happen if a developer does 'fastboot flash
265 * boot /path/to/new/and/bigger/boot.img'. We want this to work
266 * since it's such a common workflow.
267 */
268 image_size = hash_desc.image_size;
269 if (allow_verification_error) {
270 if (ops->get_size_of_partition == NULL) {
271 avb_errorv(part_name,
272 ": The get_size_of_partition() operation is "
273 "not implemented so we may not load the entire partition. "
274 "Please implement.",
275 NULL);
276 } else {
277 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
278 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
279 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
280 goto out;
281 } else if (io_ret != AVB_IO_RESULT_OK) {
282 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
283 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
284 goto out;
285 }
286 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
287 }
288 }
289
290 ret = load_full_partition(
291 ops, part_name, image_size, &image_buf, &image_preloaded);
292 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
293 goto out;
294 }
295
296 if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
297 AvbSHA256Ctx sha256_ctx;
298 avb_sha256_init(&sha256_ctx);
299 avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
300 avb_sha256_update(&sha256_ctx, image_buf, hash_desc.image_size);
301 digest = avb_sha256_final(&sha256_ctx);
302 digest_len = AVB_SHA256_DIGEST_SIZE;
303 } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
304 AvbSHA512Ctx sha512_ctx;
305 avb_sha512_init(&sha512_ctx);
306 avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
307 avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
308 digest = avb_sha512_final(&sha512_ctx);
309 digest_len = AVB_SHA512_DIGEST_SIZE;
310 } else {
311 avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
312 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
313 goto out;
314 }
315
316 if (hash_desc.digest_len == 0) {
317 // Expect a match to a persistent digest.
318 avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
319 expected_digest_len = digest_len;
320 expected_digest = expected_digest_buf;
321 avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
322 ret =
323 read_persistent_digest(ops, part_name, digest_len, expected_digest_buf);
324 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
325 goto out;
326 }
327 } else {
328 // Expect a match to the digest in the descriptor.
329 expected_digest_len = hash_desc.digest_len;
330 expected_digest = desc_digest;
331 }
332
333 if (digest_len != expected_digest_len) {
334 avb_errorv(
335 part_name, ": Digest in descriptor not of expected size.\n", NULL);
336 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
337 goto out;
338 }
339
340 if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
341 avb_errorv(part_name,
342 ": Hash of data does not match digest in descriptor.\n",
343 NULL);
344 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
345 goto out;
346 }
347
348 ret = AVB_SLOT_VERIFY_RESULT_OK;
349
350 out:
351
352 /* If it worked and something was loaded, copy to slot_data. */
353 if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
354 image_buf != NULL) {
355 AvbPartitionData* loaded_partition;
356 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
357 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
358 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
359 goto fail;
360 }
361 loaded_partition =
362 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
363 loaded_partition->partition_name = avb_strdup(found);
364 loaded_partition->data_size = image_size;
365 loaded_partition->data = image_buf;
366 loaded_partition->preloaded = image_preloaded;
367 image_buf = NULL;
368 }
369
370 fail:
371 if (image_buf != NULL && !image_preloaded) {
372 avb_free(image_buf);
373 }
374 return ret;
375 }
376
load_requested_partitions(AvbOps * ops,const char * const * requested_partitions,const char * ab_suffix,AvbSlotVerifyData * slot_data)377 static AvbSlotVerifyResult load_requested_partitions(
378 AvbOps* ops,
379 const char* const* requested_partitions,
380 const char* ab_suffix,
381 AvbSlotVerifyData* slot_data) {
382 AvbSlotVerifyResult ret;
383 uint8_t* image_buf = NULL;
384 bool image_preloaded = false;
385 size_t n;
386
387 if (ops->get_size_of_partition == NULL) {
388 avb_error("get_size_of_partition() not implemented.\n");
389 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
390 goto out;
391 }
392
393 for (n = 0; requested_partitions[n] != NULL; n++) {
394 char part_name[AVB_PART_NAME_MAX_SIZE];
395 AvbIOResult io_ret;
396 uint64_t image_size;
397 AvbPartitionData* loaded_partition;
398
399 if (!avb_str_concat(part_name,
400 sizeof part_name,
401 requested_partitions[n],
402 avb_strlen(requested_partitions[n]),
403 ab_suffix,
404 avb_strlen(ab_suffix))) {
405 avb_error("Partition name and suffix does not fit.\n");
406 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
407 goto out;
408 }
409
410 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
411 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
412 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
413 goto out;
414 } else if (io_ret != AVB_IO_RESULT_OK) {
415 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
416 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
417 goto out;
418 }
419 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
420
421 ret = load_full_partition(
422 ops, part_name, image_size, &image_buf, &image_preloaded);
423 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
424 goto out;
425 }
426
427 /* Move to slot_data. */
428 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
429 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
430 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
431 goto out;
432 }
433 loaded_partition =
434 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
435 loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
436 if (loaded_partition->partition_name == NULL) {
437 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
438 goto out;
439 }
440 loaded_partition->data_size = image_size;
441 loaded_partition->data = image_buf; /* Transferring the owner. */
442 loaded_partition->preloaded = image_preloaded;
443 image_buf = NULL;
444 image_preloaded = false;
445 }
446
447 ret = AVB_SLOT_VERIFY_RESULT_OK;
448
449 out:
450 /* Free the current buffer if any. */
451 if (image_buf != NULL && !image_preloaded) {
452 avb_free(image_buf);
453 }
454 /* Buffers that are already saved in slot_data will be handled by the caller
455 * even on failure. */
456 return ret;
457 }
458
load_and_verify_vbmeta(AvbOps * ops,const char * const * requested_partitions,const char * ab_suffix,bool allow_verification_error,AvbVBMetaImageFlags toplevel_vbmeta_flags,int rollback_index_location,const char * partition_name,size_t partition_name_len,const uint8_t * expected_public_key,size_t expected_public_key_length,AvbSlotVerifyData * slot_data,AvbAlgorithmType * out_algorithm_type,AvbCmdlineSubstList * out_additional_cmdline_subst)459 static AvbSlotVerifyResult load_and_verify_vbmeta(
460 AvbOps* ops,
461 const char* const* requested_partitions,
462 const char* ab_suffix,
463 bool allow_verification_error,
464 AvbVBMetaImageFlags toplevel_vbmeta_flags,
465 int rollback_index_location,
466 const char* partition_name,
467 size_t partition_name_len,
468 const uint8_t* expected_public_key,
469 size_t expected_public_key_length,
470 AvbSlotVerifyData* slot_data,
471 AvbAlgorithmType* out_algorithm_type,
472 AvbCmdlineSubstList* out_additional_cmdline_subst) {
473 char full_partition_name[AVB_PART_NAME_MAX_SIZE];
474 AvbSlotVerifyResult ret;
475 AvbIOResult io_ret;
476 size_t vbmeta_offset;
477 size_t vbmeta_size;
478 uint8_t* vbmeta_buf = NULL;
479 size_t vbmeta_num_read;
480 AvbVBMetaVerifyResult vbmeta_ret;
481 const uint8_t* pk_data;
482 size_t pk_len;
483 AvbVBMetaImageHeader vbmeta_header;
484 uint64_t stored_rollback_index;
485 const AvbDescriptor** descriptors = NULL;
486 size_t num_descriptors;
487 size_t n;
488 bool is_main_vbmeta;
489 bool is_vbmeta_partition;
490 AvbVBMetaData* vbmeta_image_data = NULL;
491
492 ret = AVB_SLOT_VERIFY_RESULT_OK;
493
494 avb_assert(slot_data != NULL);
495
496 /* Since we allow top-level vbmeta in 'boot', use
497 * rollback_index_location to determine whether we're the main
498 * vbmeta struct.
499 */
500 is_main_vbmeta = (rollback_index_location == 0);
501 is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
502
503 if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
504 avb_error("Partition name is not valid UTF-8.\n");
505 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
506 goto out;
507 }
508
509 /* Construct full partition name. */
510 if (!avb_str_concat(full_partition_name,
511 sizeof full_partition_name,
512 partition_name,
513 partition_name_len,
514 ab_suffix,
515 avb_strlen(ab_suffix))) {
516 avb_error("Partition name and suffix does not fit.\n");
517 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
518 goto out;
519 }
520
521 avb_debugv("Loading vbmeta struct from partition '",
522 full_partition_name,
523 "'.\n",
524 NULL);
525
526 /* If we're loading from the main vbmeta partition, the vbmeta
527 * struct is in the beginning. Otherwise we have to locate it via a
528 * footer.
529 */
530 if (is_vbmeta_partition) {
531 vbmeta_offset = 0;
532 vbmeta_size = VBMETA_MAX_SIZE;
533 } else {
534 uint8_t footer_buf[AVB_FOOTER_SIZE];
535 size_t footer_num_read;
536 AvbFooter footer;
537
538 io_ret = ops->read_from_partition(ops,
539 full_partition_name,
540 -AVB_FOOTER_SIZE,
541 AVB_FOOTER_SIZE,
542 footer_buf,
543 &footer_num_read);
544 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
545 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
546 goto out;
547 } else if (io_ret != AVB_IO_RESULT_OK) {
548 avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
549 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
550 goto out;
551 }
552 avb_assert(footer_num_read == AVB_FOOTER_SIZE);
553
554 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
555 &footer)) {
556 avb_errorv(full_partition_name, ": Error validating footer.\n", NULL);
557 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
558 goto out;
559 }
560
561 /* Basic footer sanity check since the data is untrusted. */
562 if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
563 avb_errorv(
564 full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
565 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
566 goto out;
567 }
568
569 vbmeta_offset = footer.vbmeta_offset;
570 vbmeta_size = footer.vbmeta_size;
571 }
572
573 vbmeta_buf = avb_malloc(vbmeta_size);
574 if (vbmeta_buf == NULL) {
575 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
576 goto out;
577 }
578
579 io_ret = ops->read_from_partition(ops,
580 full_partition_name,
581 vbmeta_offset,
582 vbmeta_size,
583 vbmeta_buf,
584 &vbmeta_num_read);
585 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
586 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
587 goto out;
588 } else if (io_ret != AVB_IO_RESULT_OK) {
589 /* If we're looking for 'vbmeta' but there is no such partition,
590 * go try to get it from the boot partition instead.
591 */
592 if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
593 is_vbmeta_partition) {
594 avb_debugv(full_partition_name,
595 ": No such partition. Trying 'boot' instead.\n",
596 NULL);
597 ret = load_and_verify_vbmeta(ops,
598 requested_partitions,
599 ab_suffix,
600 allow_verification_error,
601 0 /* toplevel_vbmeta_flags */,
602 0 /* rollback_index_location */,
603 "boot",
604 avb_strlen("boot"),
605 NULL /* expected_public_key */,
606 0 /* expected_public_key_length */,
607 slot_data,
608 out_algorithm_type,
609 out_additional_cmdline_subst);
610 goto out;
611 } else {
612 avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
613 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
614 goto out;
615 }
616 }
617 avb_assert(vbmeta_num_read <= vbmeta_size);
618
619 /* Check if the image is properly signed and get the public key used
620 * to sign the image.
621 */
622 vbmeta_ret =
623 avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
624 switch (vbmeta_ret) {
625 case AVB_VBMETA_VERIFY_RESULT_OK:
626 avb_assert(pk_data != NULL && pk_len > 0);
627 break;
628
629 case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
630 case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
631 case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
632 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
633 avb_errorv(full_partition_name,
634 ": Error verifying vbmeta image: ",
635 avb_vbmeta_verify_result_to_string(vbmeta_ret),
636 "\n",
637 NULL);
638 if (!allow_verification_error) {
639 goto out;
640 }
641 break;
642
643 case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
644 /* No way to continue this case. */
645 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
646 avb_errorv(full_partition_name,
647 ": Error verifying vbmeta image: invalid vbmeta header\n",
648 NULL);
649 goto out;
650
651 case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
652 /* No way to continue this case. */
653 ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
654 avb_errorv(full_partition_name,
655 ": Error verifying vbmeta image: unsupported AVB version\n",
656 NULL);
657 goto out;
658 }
659
660 /* Byteswap the header. */
661 avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
662 &vbmeta_header);
663
664 /* If we're the toplevel, assign flags so they'll be passed down. */
665 if (is_main_vbmeta) {
666 toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
667 } else {
668 if (vbmeta_header.flags != 0) {
669 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
670 avb_errorv(full_partition_name,
671 ": chained vbmeta image has non-zero flags\n",
672 NULL);
673 goto out;
674 }
675 }
676
677 /* Check if key used to make signature matches what is expected. */
678 if (pk_data != NULL) {
679 if (expected_public_key != NULL) {
680 avb_assert(!is_main_vbmeta);
681 if (expected_public_key_length != pk_len ||
682 avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
683 avb_errorv(full_partition_name,
684 ": Public key used to sign data does not match key in chain "
685 "partition descriptor.\n",
686 NULL);
687 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
688 if (!allow_verification_error) {
689 goto out;
690 }
691 }
692 } else {
693 bool key_is_trusted = false;
694 const uint8_t* pk_metadata = NULL;
695 size_t pk_metadata_len = 0;
696
697 if (vbmeta_header.public_key_metadata_size > 0) {
698 pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
699 vbmeta_header.authentication_data_block_size +
700 vbmeta_header.public_key_metadata_offset;
701 pk_metadata_len = vbmeta_header.public_key_metadata_size;
702 }
703
704 avb_assert(is_main_vbmeta);
705 io_ret = ops->validate_vbmeta_public_key(
706 ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
707 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
708 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
709 goto out;
710 } else if (io_ret != AVB_IO_RESULT_OK) {
711 avb_errorv(full_partition_name,
712 ": Error while checking public key used to sign data.\n",
713 NULL);
714 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
715 goto out;
716 }
717 if (!key_is_trusted) {
718 avb_errorv(full_partition_name,
719 ": Public key used to sign data rejected.\n",
720 NULL);
721 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
722 if (!allow_verification_error) {
723 goto out;
724 }
725 }
726 }
727 }
728
729 /* Check rollback index. */
730 io_ret = ops->read_rollback_index(
731 ops, rollback_index_location, &stored_rollback_index);
732 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
733 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
734 goto out;
735 } else if (io_ret != AVB_IO_RESULT_OK) {
736 avb_errorv(full_partition_name,
737 ": Error getting rollback index for location.\n",
738 NULL);
739 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
740 goto out;
741 }
742 if (vbmeta_header.rollback_index < stored_rollback_index) {
743 avb_errorv(
744 full_partition_name,
745 ": Image rollback index is less than the stored rollback index.\n",
746 NULL);
747 ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
748 if (!allow_verification_error) {
749 goto out;
750 }
751 }
752
753 /* Copy vbmeta to vbmeta_images before recursing. */
754 if (is_main_vbmeta) {
755 avb_assert(slot_data->num_vbmeta_images == 0);
756 } else {
757 avb_assert(slot_data->num_vbmeta_images > 0);
758 }
759 if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
760 avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
761 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
762 goto out;
763 }
764 vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
765 vbmeta_image_data->partition_name = avb_strdup(partition_name);
766 vbmeta_image_data->vbmeta_data = vbmeta_buf;
767 /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
768 * and this includes data past the end of the image. Pass the
769 * actual size of the vbmeta image. Also, no need to use
770 * avb_safe_add() since the header has already been verified.
771 */
772 vbmeta_image_data->vbmeta_size =
773 sizeof(AvbVBMetaImageHeader) +
774 vbmeta_header.authentication_data_block_size +
775 vbmeta_header.auxiliary_data_block_size;
776 vbmeta_image_data->verify_result = vbmeta_ret;
777
778 /* If verification has been disabled by setting a bit in the image,
779 * we're done... except that we need to load the entirety of the
780 * requested partitions.
781 */
782 if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
783 AvbSlotVerifyResult sub_ret;
784 avb_debugv(
785 full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
786 /* If load_requested_partitions() fail it is always a fatal
787 * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
788 * than recoverable (e.g. one where result_should_continue()
789 * returns true) and we want to convey that error.
790 */
791 sub_ret = load_requested_partitions(
792 ops, requested_partitions, ab_suffix, slot_data);
793 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
794 ret = sub_ret;
795 }
796 goto out;
797 }
798
799 /* Now go through all descriptors and take the appropriate action:
800 *
801 * - hash descriptor: Load data from partition, calculate hash, and
802 * checks that it matches what's in the hash descriptor.
803 *
804 * - hashtree descriptor: Do nothing since verification happens
805 * on-the-fly from within the OS. (Unless the descriptor uses a
806 * persistent digest, in which case we need to find it).
807 *
808 * - chained partition descriptor: Load the footer, load the vbmeta
809 * image, verify vbmeta image (includes rollback checks, hash
810 * checks, bail on chained partitions).
811 */
812 descriptors =
813 avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
814 for (n = 0; n < num_descriptors; n++) {
815 AvbDescriptor desc;
816
817 if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
818 avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
819 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
820 goto out;
821 }
822
823 switch (desc.tag) {
824 case AVB_DESCRIPTOR_TAG_HASH: {
825 AvbSlotVerifyResult sub_ret;
826 sub_ret = load_and_verify_hash_partition(ops,
827 requested_partitions,
828 ab_suffix,
829 allow_verification_error,
830 descriptors[n],
831 slot_data);
832 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
833 ret = sub_ret;
834 if (!allow_verification_error || !result_should_continue(ret)) {
835 goto out;
836 }
837 }
838 } break;
839
840 case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
841 AvbSlotVerifyResult sub_ret;
842 AvbChainPartitionDescriptor chain_desc;
843 const uint8_t* chain_partition_name;
844 const uint8_t* chain_public_key;
845
846 /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
847 if (!is_main_vbmeta) {
848 avb_errorv(full_partition_name,
849 ": Encountered chain descriptor not in main image.\n",
850 NULL);
851 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
852 goto out;
853 }
854
855 if (!avb_chain_partition_descriptor_validate_and_byteswap(
856 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
857 avb_errorv(full_partition_name,
858 ": Chain partition descriptor is invalid.\n",
859 NULL);
860 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
861 goto out;
862 }
863
864 if (chain_desc.rollback_index_location == 0) {
865 avb_errorv(full_partition_name,
866 ": Chain partition has invalid "
867 "rollback_index_location field.\n",
868 NULL);
869 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
870 goto out;
871 }
872
873 chain_partition_name = ((const uint8_t*)descriptors[n]) +
874 sizeof(AvbChainPartitionDescriptor);
875 chain_public_key = chain_partition_name + chain_desc.partition_name_len;
876
877 sub_ret =
878 load_and_verify_vbmeta(ops,
879 requested_partitions,
880 ab_suffix,
881 allow_verification_error,
882 toplevel_vbmeta_flags,
883 chain_desc.rollback_index_location,
884 (const char*)chain_partition_name,
885 chain_desc.partition_name_len,
886 chain_public_key,
887 chain_desc.public_key_len,
888 slot_data,
889 NULL, /* out_algorithm_type */
890 NULL /* out_additional_cmdline_subst */);
891 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
892 ret = sub_ret;
893 if (!result_should_continue(ret)) {
894 goto out;
895 }
896 }
897 } break;
898
899 case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
900 const uint8_t* kernel_cmdline;
901 AvbKernelCmdlineDescriptor kernel_cmdline_desc;
902 bool apply_cmdline;
903
904 if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
905 (AvbKernelCmdlineDescriptor*)descriptors[n],
906 &kernel_cmdline_desc)) {
907 avb_errorv(full_partition_name,
908 ": Kernel cmdline descriptor is invalid.\n",
909 NULL);
910 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
911 goto out;
912 }
913
914 kernel_cmdline = ((const uint8_t*)descriptors[n]) +
915 sizeof(AvbKernelCmdlineDescriptor);
916
917 if (!avb_validate_utf8(kernel_cmdline,
918 kernel_cmdline_desc.kernel_cmdline_length)) {
919 avb_errorv(full_partition_name,
920 ": Kernel cmdline is not valid UTF-8.\n",
921 NULL);
922 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
923 goto out;
924 }
925
926 /* Compare the flags for top-level VBMeta struct with flags in
927 * the command-line descriptor so command-line snippets only
928 * intended for a certain mode (dm-verity enabled/disabled)
929 * are skipped if applicable.
930 */
931 apply_cmdline = true;
932 if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
933 if (kernel_cmdline_desc.flags &
934 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
935 apply_cmdline = false;
936 }
937 } else {
938 if (kernel_cmdline_desc.flags &
939 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
940 apply_cmdline = false;
941 }
942 }
943
944 if (apply_cmdline) {
945 if (slot_data->cmdline == NULL) {
946 slot_data->cmdline =
947 avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
948 if (slot_data->cmdline == NULL) {
949 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
950 goto out;
951 }
952 avb_memcpy(slot_data->cmdline,
953 kernel_cmdline,
954 kernel_cmdline_desc.kernel_cmdline_length);
955 } else {
956 /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
957 size_t orig_size = avb_strlen(slot_data->cmdline);
958 size_t new_size =
959 orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
960 char* new_cmdline = avb_calloc(new_size);
961 if (new_cmdline == NULL) {
962 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
963 goto out;
964 }
965 avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
966 new_cmdline[orig_size] = ' ';
967 avb_memcpy(new_cmdline + orig_size + 1,
968 kernel_cmdline,
969 kernel_cmdline_desc.kernel_cmdline_length);
970 avb_free(slot_data->cmdline);
971 slot_data->cmdline = new_cmdline;
972 }
973 }
974 } break;
975
976 case AVB_DESCRIPTOR_TAG_HASHTREE: {
977 AvbHashtreeDescriptor hashtree_desc;
978
979 if (!avb_hashtree_descriptor_validate_and_byteswap(
980 (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
981 avb_errorv(
982 full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
983 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
984 goto out;
985 }
986
987 /* We only need to continue when there is no digest in the descriptor.
988 * This is because the only processing here is to find the digest and
989 * make it available on the kernel command line.
990 */
991 if (hashtree_desc.root_digest_len == 0) {
992 char part_name[AVB_PART_NAME_MAX_SIZE];
993 size_t digest_len = 0;
994 uint8_t digest_buf[AVB_SHA512_DIGEST_SIZE];
995 const uint8_t* desc_partition_name =
996 ((const uint8_t*)descriptors[n]) + sizeof(AvbHashtreeDescriptor);
997
998 if (!avb_validate_utf8(desc_partition_name,
999 hashtree_desc.partition_name_len)) {
1000 avb_error("Partition name is not valid UTF-8.\n");
1001 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1002 goto out;
1003 }
1004
1005 /* No ab_suffix for partitions without a digest in the descriptor
1006 * because these partitions hold data unique to this device and are
1007 * not updated using an A/B scheme.
1008 */
1009 if ((hashtree_desc.flags &
1010 AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) == 0 &&
1011 avb_strlen(ab_suffix) != 0) {
1012 avb_error("Cannot use A/B with a persistent root digest.\n");
1013 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1014 goto out;
1015 }
1016 if (hashtree_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
1017 avb_error("Partition name does not fit.\n");
1018 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1019 goto out;
1020 }
1021 avb_memcpy(
1022 part_name, desc_partition_name, hashtree_desc.partition_name_len);
1023 part_name[hashtree_desc.partition_name_len] = '\0';
1024
1025 /* Determine the expected digest size from the hash algorithm. */
1026 if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
1027 0) {
1028 digest_len = AVB_SHA1_DIGEST_SIZE;
1029 } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1030 "sha256") == 0) {
1031 digest_len = AVB_SHA256_DIGEST_SIZE;
1032 } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1033 "sha512") == 0) {
1034 digest_len = AVB_SHA512_DIGEST_SIZE;
1035 } else {
1036 avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
1037 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1038 goto out;
1039 }
1040
1041 ret = read_persistent_digest(ops, part_name, digest_len, digest_buf);
1042 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1043 goto out;
1044 }
1045
1046 if (out_additional_cmdline_subst) {
1047 ret =
1048 avb_add_root_digest_substitution(part_name,
1049 digest_buf,
1050 digest_len,
1051 out_additional_cmdline_subst);
1052 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1053 goto out;
1054 }
1055 }
1056 }
1057 } break;
1058
1059 case AVB_DESCRIPTOR_TAG_PROPERTY:
1060 /* Do nothing. */
1061 break;
1062 }
1063 }
1064
1065 if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
1066 avb_errorv(
1067 full_partition_name, ": Invalid rollback_index_location.\n", NULL);
1068 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1069 goto out;
1070 }
1071
1072 slot_data->rollback_indexes[rollback_index_location] =
1073 vbmeta_header.rollback_index;
1074
1075 if (out_algorithm_type != NULL) {
1076 *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
1077 }
1078
1079 out:
1080 /* If |vbmeta_image_data| isn't NULL it means that it adopted
1081 * |vbmeta_buf| so in that case don't free it here.
1082 */
1083 if (vbmeta_image_data == NULL) {
1084 if (vbmeta_buf != NULL) {
1085 avb_free(vbmeta_buf);
1086 }
1087 }
1088 if (descriptors != NULL) {
1089 avb_free(descriptors);
1090 }
1091 return ret;
1092 }
1093
avb_slot_verify(AvbOps * ops,const char * const * requested_partitions,const char * ab_suffix,AvbSlotVerifyFlags flags,AvbHashtreeErrorMode hashtree_error_mode,AvbSlotVerifyData ** out_data)1094 AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
1095 const char* const* requested_partitions,
1096 const char* ab_suffix,
1097 AvbSlotVerifyFlags flags,
1098 AvbHashtreeErrorMode hashtree_error_mode,
1099 AvbSlotVerifyData** out_data) {
1100 AvbSlotVerifyResult ret;
1101 AvbSlotVerifyData* slot_data = NULL;
1102 AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
1103 bool using_boot_for_vbmeta = false;
1104 AvbVBMetaImageHeader toplevel_vbmeta;
1105 bool allow_verification_error =
1106 (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
1107 AvbCmdlineSubstList* additional_cmdline_subst = NULL;
1108
1109 /* Fail early if we're missing the AvbOps needed for slot verification.
1110 *
1111 * For now, handle get_size_of_partition() not being implemented. In
1112 * a later release we may change that.
1113 */
1114 avb_assert(ops->read_is_device_unlocked != NULL);
1115 avb_assert(ops->read_from_partition != NULL);
1116 avb_assert(ops->validate_vbmeta_public_key != NULL);
1117 avb_assert(ops->read_rollback_index != NULL);
1118 avb_assert(ops->get_unique_guid_for_partition != NULL);
1119
1120 if (out_data != NULL) {
1121 *out_data = NULL;
1122 }
1123
1124 /* Allowing dm-verity errors defeats the purpose of verified boot so
1125 * only allow this if set up to allow verification errors
1126 * (e.g. typically only UNLOCKED mode).
1127 */
1128 if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
1129 !allow_verification_error) {
1130 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1131 goto fail;
1132 }
1133
1134 slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
1135 if (slot_data == NULL) {
1136 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1137 goto fail;
1138 }
1139 slot_data->vbmeta_images =
1140 avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
1141 if (slot_data->vbmeta_images == NULL) {
1142 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1143 goto fail;
1144 }
1145 slot_data->loaded_partitions =
1146 avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
1147 if (slot_data->loaded_partitions == NULL) {
1148 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1149 goto fail;
1150 }
1151
1152 additional_cmdline_subst = avb_new_cmdline_subst_list();
1153 if (additional_cmdline_subst == NULL) {
1154 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1155 goto fail;
1156 }
1157
1158 ret = load_and_verify_vbmeta(ops,
1159 requested_partitions,
1160 ab_suffix,
1161 allow_verification_error,
1162 0 /* toplevel_vbmeta_flags */,
1163 0 /* rollback_index_location */,
1164 "vbmeta",
1165 avb_strlen("vbmeta"),
1166 NULL /* expected_public_key */,
1167 0 /* expected_public_key_length */,
1168 slot_data,
1169 &algorithm_type,
1170 additional_cmdline_subst);
1171 if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1172 goto fail;
1173 }
1174
1175 /* If things check out, mangle the kernel command-line as needed. */
1176 if (result_should_continue(ret)) {
1177 if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
1178 avb_assert(
1179 avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
1180 using_boot_for_vbmeta = true;
1181 }
1182
1183 /* Byteswap top-level vbmeta header since we'll need it below. */
1184 avb_vbmeta_image_header_to_host_byte_order(
1185 (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
1186 &toplevel_vbmeta);
1187
1188 /* Fill in |ab_suffix| field. */
1189 slot_data->ab_suffix = avb_strdup(ab_suffix);
1190 if (slot_data->ab_suffix == NULL) {
1191 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1192 goto fail;
1193 }
1194
1195 /* If verification is disabled, we are done ... we specifically
1196 * don't want to add any androidboot.* options since verification
1197 * is disabled.
1198 */
1199 if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
1200 /* Since verification is disabled we didn't process any
1201 * descriptors and thus there's no cmdline... so set root= such
1202 * that the system partition is mounted.
1203 */
1204 avb_assert(slot_data->cmdline == NULL);
1205 slot_data->cmdline =
1206 avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
1207 if (slot_data->cmdline == NULL) {
1208 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1209 goto fail;
1210 }
1211 } else {
1212 /* Add options - any failure in avb_append_options() is either an
1213 * I/O or OOM error.
1214 */
1215 AvbSlotVerifyResult sub_ret = avb_append_options(ops,
1216 slot_data,
1217 &toplevel_vbmeta,
1218 algorithm_type,
1219 hashtree_error_mode);
1220 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1221 ret = sub_ret;
1222 goto fail;
1223 }
1224 }
1225
1226 /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1227 if (slot_data->cmdline != NULL) {
1228 char* new_cmdline;
1229 new_cmdline = avb_sub_cmdline(ops,
1230 slot_data->cmdline,
1231 ab_suffix,
1232 using_boot_for_vbmeta,
1233 additional_cmdline_subst);
1234 if (new_cmdline != slot_data->cmdline) {
1235 if (new_cmdline == NULL) {
1236 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1237 goto fail;
1238 }
1239 avb_free(slot_data->cmdline);
1240 slot_data->cmdline = new_cmdline;
1241 }
1242 }
1243
1244 if (out_data != NULL) {
1245 *out_data = slot_data;
1246 } else {
1247 avb_slot_verify_data_free(slot_data);
1248 }
1249 }
1250
1251 avb_free_cmdline_subst_list(additional_cmdline_subst);
1252 additional_cmdline_subst = NULL;
1253
1254 if (!allow_verification_error) {
1255 avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1256 }
1257
1258 return ret;
1259
1260 fail:
1261 if (slot_data != NULL) {
1262 avb_slot_verify_data_free(slot_data);
1263 }
1264 if (additional_cmdline_subst != NULL) {
1265 avb_free_cmdline_subst_list(additional_cmdline_subst);
1266 }
1267 return ret;
1268 }
1269
avb_slot_verify_data_free(AvbSlotVerifyData * data)1270 void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1271 if (data->ab_suffix != NULL) {
1272 avb_free(data->ab_suffix);
1273 }
1274 if (data->cmdline != NULL) {
1275 avb_free(data->cmdline);
1276 }
1277 if (data->vbmeta_images != NULL) {
1278 size_t n;
1279 for (n = 0; n < data->num_vbmeta_images; n++) {
1280 AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
1281 if (vbmeta_image->partition_name != NULL) {
1282 avb_free(vbmeta_image->partition_name);
1283 }
1284 if (vbmeta_image->vbmeta_data != NULL) {
1285 avb_free(vbmeta_image->vbmeta_data);
1286 }
1287 }
1288 avb_free(data->vbmeta_images);
1289 }
1290 if (data->loaded_partitions != NULL) {
1291 size_t n;
1292 for (n = 0; n < data->num_loaded_partitions; n++) {
1293 AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1294 if (loaded_partition->partition_name != NULL) {
1295 avb_free(loaded_partition->partition_name);
1296 }
1297 if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
1298 avb_free(loaded_partition->data);
1299 }
1300 }
1301 avb_free(data->loaded_partitions);
1302 }
1303 avb_free(data);
1304 }
1305
avb_slot_verify_result_to_string(AvbSlotVerifyResult result)1306 const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
1307 const char* ret = NULL;
1308
1309 switch (result) {
1310 case AVB_SLOT_VERIFY_RESULT_OK:
1311 ret = "OK";
1312 break;
1313 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
1314 ret = "ERROR_OOM";
1315 break;
1316 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
1317 ret = "ERROR_IO";
1318 break;
1319 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
1320 ret = "ERROR_VERIFICATION";
1321 break;
1322 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
1323 ret = "ERROR_ROLLBACK_INDEX";
1324 break;
1325 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
1326 ret = "ERROR_PUBLIC_KEY_REJECTED";
1327 break;
1328 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
1329 ret = "ERROR_INVALID_METADATA";
1330 break;
1331 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1332 ret = "ERROR_UNSUPPORTED_VERSION";
1333 break;
1334 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
1335 ret = "ERROR_INVALID_ARGUMENT";
1336 break;
1337 /* Do not add a 'default:' case here because of -Wswitch. */
1338 }
1339
1340 if (ret == NULL) {
1341 avb_error("Unknown AvbSlotVerifyResult value.\n");
1342 ret = "(unknown)";
1343 }
1344
1345 return ret;
1346 }
1347