121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/*
221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen * Copyright (C) 2016 The Android Open Source Project
321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen *
4c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * Permission is hereby granted, free of charge, to any person
5c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * obtaining a copy of this software and associated documentation
6c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * files (the "Software"), to deal in the Software without
7c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * restriction, including without limitation the rights to use, copy,
8c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * modify, merge, publish, distribute, sublicense, and/or sell copies
9c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * of the Software, and to permit persons to whom the Software is
10c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * furnished to do so, subject to the following conditions:
1121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen *
12c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * The above copyright notice and this permission notice shall be
13c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * included in all copies or substantial portions of the Software.
1421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen *
15c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * SOFTWARE.
2321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen */
2421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
2521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen#include "avb_vbmeta_image.h"
26c9fa424bdae2d7d631c613ef168c73ff1d61d5e5Darren Krahn#include "avb_crypto.h"
2721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen#include "avb_rsa.h"
2821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen#include "avb_sha.h"
2921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen#include "avb_util.h"
30e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen#include "avb_version.h"
3121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
3221e95266704e572ced1c633bbc4aea9f42afa0a5David ZeuthenAvbVBMetaVerifyResult avb_vbmeta_image_verify(
334b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    const uint8_t* data,
344b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    size_t length,
354b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    const uint8_t** out_public_key_data,
3621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    size_t* out_public_key_length) {
3721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  AvbVBMetaVerifyResult ret;
3821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  AvbVBMetaImageHeader h;
3921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint8_t* computed_hash;
40c9fa424bdae2d7d631c613ef168c73ff1d61d5e5Darren Krahn  const AvbAlgorithmData* algorithm;
4121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  AvbSHA256Ctx sha256_ctx;
4221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  AvbSHA512Ctx sha512_ctx;
4321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  const uint8_t* header_block;
4421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  const uint8_t* authentication_block;
4521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  const uint8_t* auxiliary_block;
4621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  int verification_result;
4721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
4821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret = AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER;
4921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
500155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  if (out_public_key_data != NULL) {
510155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    *out_public_key_data = NULL;
520155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  }
530155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  if (out_public_key_length != NULL) {
540155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    *out_public_key_length = 0;
550155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  }
5621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
5721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Ensure magic is correct. */
5821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (avb_safe_memcmp(data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
5921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Magic is incorrect.\n");
6021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
6121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
6221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
6321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Before we byteswap, ensure length is long enough. */
6421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (length < sizeof(AvbVBMetaImageHeader)) {
6521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Length is smaller than header.\n");
6621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
6721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
6821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  avb_vbmeta_image_header_to_host_byte_order((const AvbVBMetaImageHeader*)data,
6921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen                                             &h);
7021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
71e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen  /* Ensure we don't attempt to access any fields if we do not meet
72e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen   * the specified minimum version of libavb.
7321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   */
74e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen  if ((h.required_libavb_version_major != AVB_VERSION_MAJOR) ||
75e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen      (h.required_libavb_version_minor > AVB_VERSION_MINOR)) {
76e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen    avb_error("Mismatch between image version and libavb version.\n");
77e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen    ret = AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION;
78e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen    goto out;
79e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen  }
80e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen
81e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen  /* Ensure |release_string| ends with a NUL byte. */
82e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen  if (h.release_string[AVB_RELEASE_STRING_SIZE - 1] != '\0') {
83e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen    avb_error("Release string does not end with a NUL byte.\n");
8421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
8521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
8621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
8721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Ensure inner block sizes are multiple of 64. */
8821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if ((h.authentication_data_block_size & 0x3f) != 0 ||
8921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      (h.auxiliary_data_block_size & 0x3f) != 0) {
9021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Block size is not a multiple of 64.\n");
9121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
9221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
9321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
9421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Ensure block sizes all add up to at most |length|. */
9521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t block_total = sizeof(AvbVBMetaImageHeader);
9621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (!avb_safe_add_to(&block_total, h.authentication_data_block_size) ||
9721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      !avb_safe_add_to(&block_total, h.auxiliary_data_block_size)) {
9821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Overflow while computing size of boot image.\n");
9921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
10021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
10121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (block_total > length) {
10221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Block sizes add up to more than given length.\n");
10321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
10421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
10521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
10621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uintptr_t data_ptr = (uintptr_t)data;
10721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Ensure passed in memory doesn't wrap. */
10821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (!avb_safe_add(NULL, (uint64_t)data_ptr, length)) {
10921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Boot image location and length mismatch.\n");
11021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
11121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
11221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
11321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Ensure hash and signature are entirely in the Authentication data block. */
11421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t hash_end;
11521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (!avb_safe_add(&hash_end, h.hash_offset, h.hash_size) ||
11621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      hash_end > h.authentication_data_block_size) {
11721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Hash is not entirely in its block.\n");
11821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
11921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
12021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t signature_end;
12121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (!avb_safe_add(&signature_end, h.signature_offset, h.signature_size) ||
12221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      signature_end > h.authentication_data_block_size) {
12321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Signature is not entirely in its block.\n");
12421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
12521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
12621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
12721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Ensure public key is entirely in the Auxiliary data block. */
12821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t pubkey_end;
12921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (!avb_safe_add(&pubkey_end, h.public_key_offset, h.public_key_size) ||
13021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      pubkey_end > h.auxiliary_data_block_size) {
13121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Public key is not entirely in its block.\n");
13221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
13321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
13421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
13518666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen  /* Ensure public key metadata (if set) is entirely in the Auxiliary
13618666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen   * data block. */
13718666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen  if (h.public_key_metadata_size > 0) {
13818666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen    uint64_t pubkey_md_end;
1394b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    if (!avb_safe_add(&pubkey_md_end,
1404b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                      h.public_key_metadata_offset,
14118666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen                      h.public_key_metadata_size) ||
14218666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen        pubkey_md_end > h.auxiliary_data_block_size) {
14318666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen      avb_error("Public key metadata is not entirely in its block.\n");
14418666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen      goto out;
14518666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen    }
14618666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen  }
14718666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen
14821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Bail early if there's no hash or signature. */
14921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (h.algorithm_type == AVB_ALGORITHM_TYPE_NONE) {
15021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    ret = AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED;
15121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
15221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
15321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
154c9fa424bdae2d7d631c613ef168c73ff1d61d5e5Darren Krahn  /* Ensure algorithm field is supported. */
155c9fa424bdae2d7d631c613ef168c73ff1d61d5e5Darren Krahn  algorithm = avb_get_algorithm_data(h.algorithm_type);
156c9fa424bdae2d7d631c613ef168c73ff1d61d5e5Darren Krahn  if (!algorithm) {
157c9fa424bdae2d7d631c613ef168c73ff1d61d5e5Darren Krahn    avb_error("Invalid or unknown algorithm.\n");
158c9fa424bdae2d7d631c613ef168c73ff1d61d5e5Darren Krahn    goto out;
159c9fa424bdae2d7d631c613ef168c73ff1d61d5e5Darren Krahn  }
160c9fa424bdae2d7d631c613ef168c73ff1d61d5e5Darren Krahn
16121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Bail if the embedded hash size doesn't match the chosen algorithm. */
16221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (h.hash_size != algorithm->hash_len) {
16321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Embedded hash has wrong size.\n");
16421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
16521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
16621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
16721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* No overflow checks needed from here-on after since all block
16821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   * sizes and offsets have been verified above.
16921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   */
17021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
17121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  header_block = data;
17221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  authentication_block = header_block + sizeof(AvbVBMetaImageHeader);
17321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  auxiliary_block = authentication_block + h.authentication_data_block_size;
17421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
17521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  switch (h.algorithm_type) {
17621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    /* Explicit fall-through: */
17721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
17821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
17921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    case AVB_ALGORITHM_TYPE_SHA256_RSA8192:
18021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_sha256_init(&sha256_ctx);
1814b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      avb_sha256_update(
1824b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen          &sha256_ctx, header_block, sizeof(AvbVBMetaImageHeader));
1834b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      avb_sha256_update(
1844b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen          &sha256_ctx, auxiliary_block, h.auxiliary_data_block_size);
18521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      computed_hash = avb_sha256_final(&sha256_ctx);
18621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      break;
18721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    /* Explicit fall-through: */
18821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
18921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
19021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    case AVB_ALGORITHM_TYPE_SHA512_RSA8192:
19121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_sha512_init(&sha512_ctx);
1924b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      avb_sha512_update(
1934b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen          &sha512_ctx, header_block, sizeof(AvbVBMetaImageHeader));
1944b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      avb_sha512_update(
1954b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen          &sha512_ctx, auxiliary_block, h.auxiliary_data_block_size);
19621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      computed_hash = avb_sha512_final(&sha512_ctx);
19721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      break;
19821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    default:
19921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_error("Unknown algorithm.\n");
20021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      goto out;
20121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
20221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
2034b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (avb_safe_memcmp(authentication_block + h.hash_offset,
2044b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                      computed_hash,
20521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen                      h.hash_size) != 0) {
20621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Hash does not match!\n");
20721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    ret = AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH;
20821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
20921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
21021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
21121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  verification_result =
2124b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      avb_rsa_verify(auxiliary_block + h.public_key_offset,
2134b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                     h.public_key_size,
21421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen                     authentication_block + h.signature_offset,
2154b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                     h.signature_size,
2164b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                     authentication_block + h.hash_offset,
2174b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                     h.hash_size,
2184b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                     algorithm->padding,
2194b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                     algorithm->padding_len);
22021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
22121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (verification_result == 0) {
22221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    ret = AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH;
22321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
22421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
22521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
2260155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  if (h.public_key_size > 0) {
2270155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    if (out_public_key_data != NULL) {
2280155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      *out_public_key_data = auxiliary_block + h.public_key_offset;
2290155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    }
2300155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    if (out_public_key_length != NULL) {
2310155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      *out_public_key_length = h.public_key_size;
2320155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    }
2330155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  }
23421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
23521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret = AVB_VBMETA_VERIFY_RESULT_OK;
23621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
23721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenout:
23821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return ret;
23921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
24021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
24121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenvoid avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
24221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen                                                AvbVBMetaImageHeader* dest) {
24321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  avb_memcpy(dest, src, sizeof(AvbVBMetaImageHeader));
24421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
245e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen  dest->required_libavb_version_major =
246e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen      avb_be32toh(dest->required_libavb_version_major);
247e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen  dest->required_libavb_version_minor =
248e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen      avb_be32toh(dest->required_libavb_version_minor);
24921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
25021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->authentication_data_block_size =
25121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_be64toh(dest->authentication_data_block_size);
25221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->auxiliary_data_block_size =
25321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_be64toh(dest->auxiliary_data_block_size);
25421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
25521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->algorithm_type = avb_be32toh(dest->algorithm_type);
25621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
25721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->hash_offset = avb_be64toh(dest->hash_offset);
25821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->hash_size = avb_be64toh(dest->hash_size);
25921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
26021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->signature_offset = avb_be64toh(dest->signature_offset);
26121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->signature_size = avb_be64toh(dest->signature_size);
26221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
26321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->public_key_offset = avb_be64toh(dest->public_key_offset);
26421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->public_key_size = avb_be64toh(dest->public_key_size);
26521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
26618666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen  dest->public_key_metadata_offset =
26718666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen      avb_be64toh(dest->public_key_metadata_offset);
26818666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen  dest->public_key_metadata_size = avb_be64toh(dest->public_key_metadata_size);
26918666abc5d8276a743111e6c3608e66f6c85fb51David Zeuthen
27021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->descriptors_offset = avb_be64toh(dest->descriptors_offset);
27121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->descriptors_size = avb_be64toh(dest->descriptors_size);
27221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
27321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  dest->rollback_index = avb_be64toh(dest->rollback_index);
274fd41eb9a7848ad8d2ae0a80186e461741bf134f1David Zeuthen  dest->flags = avb_be32toh(dest->flags);
27521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
2760155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen
2770155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthenconst char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) {
2780155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  const char* ret = NULL;
2790155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen
2800155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  switch (result) {
2810155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    case AVB_VBMETA_VERIFY_RESULT_OK:
2820155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      ret = "OK";
2830155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      break;
2840155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
2850155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      ret = "OK_NOT_SIGNED";
2860155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      break;
2870155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
2880155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      ret = "INVALID_VBMETA_HEADER";
2890155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      break;
290e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen    case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
291e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen      ret = "UNSUPPORTED_VERSION";
292e3cadcacd798effe83b1593dba1ee0e3d84cf6e4David Zeuthen      break;
2930155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
2940155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      ret = "HASH_MISMATCH";
2950155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      break;
2960155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
2970155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      ret = "SIGNATURE_MISMATCH";
2980155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      break;
2990155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen      /* Do not add a 'default:' case here because of -Wswitch. */
3000155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  }
3010155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen
3020155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  if (ret == NULL) {
3030155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    avb_error("Unknown AvbVBMetaVerifyResult value.\n");
3040155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen    ret = "(unknown)";
3050155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  }
3060155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen
3070155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen  return ret;
3080155e6b158bdc5b3a442f16a5dc124d5dee9c71cDavid Zeuthen}
309