Browse Source

avb2.0: add Android Verified Boot 2.0 library

Add libavb lib (3rd party library from AOSP), that implements support of
AVB 2.0. This library is used for integrity checking of Android partitions
on eMMC.

libavb was added as it is and minimal changes were introduced to reduce
maintenance cost, because it will be deviated from AOSP upstream in the future.

Changes:
- license headers changed to conform SPDX-style
- avb_crc32.c dropped
- updates in avb_sysdeps_posix.c/avb_sysdeps.h

For additional details check [1] AVB 2.0 README.

[1] https://android.googlesource.com/platform/external/avb/+/master/README.md

Signed-off-by: Igor Opaniuk <igor.opaniuk@linaro.org>
tags/2020-06-01
Igor Opaniuk 2 years ago
committed by Tom Rini
parent
commit
d8f9d2af96
35 changed files with 6698 additions and 0 deletions
  1. +46
    -0
      lib/libavb/avb_chain_partition_descriptor.c
  2. +54
    -0
      lib/libavb/avb_chain_partition_descriptor.h
  3. +422
    -0
      lib/libavb/avb_cmdline.c
  4. +72
    -0
      lib/libavb/avb_cmdline.h
  5. +354
    -0
      lib/libavb/avb_crypto.c
  6. +156
    -0
      lib/libavb/avb_crypto.h
  7. +142
    -0
      lib/libavb/avb_descriptor.c
  8. +113
    -0
      lib/libavb/avb_descriptor.h
  9. +36
    -0
      lib/libavb/avb_footer.c
  10. +68
    -0
      lib/libavb/avb_footer.h
  11. +44
    -0
      lib/libavb/avb_hash_descriptor.c
  12. +70
    -0
      lib/libavb/avb_hash_descriptor.h
  13. +52
    -0
      lib/libavb/avb_hashtree_descriptor.c
  14. +80
    -0
      lib/libavb/avb_hashtree_descriptor.h
  15. +40
    -0
      lib/libavb/avb_kernel_cmdline_descriptor.c
  16. +63
    -0
      lib/libavb/avb_kernel_cmdline_descriptor.h
  17. +293
    -0
      lib/libavb/avb_ops.h
  18. +167
    -0
      lib/libavb/avb_property_descriptor.c
  19. +89
    -0
      lib/libavb/avb_property_descriptor.h
  20. +276
    -0
      lib/libavb/avb_rsa.c
  21. +55
    -0
      lib/libavb/avb_rsa.h
  22. +72
    -0
      lib/libavb/avb_sha.h
  23. +364
    -0
      lib/libavb/avb_sha256.c
  24. +362
    -0
      lib/libavb/avb_sha512.c
  25. +1367
    -0
      lib/libavb/avb_slot_verify.c
  26. +341
    -0
      lib/libavb/avb_slot_verify.h
  27. +101
    -0
      lib/libavb/avb_sysdeps.h
  28. +63
    -0
      lib/libavb/avb_sysdeps_posix.c
  29. +412
    -0
      lib/libavb/avb_util.c
  30. +269
    -0
      lib/libavb/avb_util.h
  31. +290
    -0
      lib/libavb/avb_vbmeta_image.c
  32. +276
    -0
      lib/libavb/avb_vbmeta_image.h
  33. +16
    -0
      lib/libavb/avb_version.c
  34. +41
    -0
      lib/libavb/avb_version.h
  35. +32
    -0
      lib/libavb/libavb.h

+ 46
- 0
lib/libavb/avb_chain_partition_descriptor.c View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#include "avb_chain_partition_descriptor.h"
#include "avb_util.h"

bool avb_chain_partition_descriptor_validate_and_byteswap(
const AvbChainPartitionDescriptor* src, AvbChainPartitionDescriptor* dest) {
uint64_t expected_size;

avb_memcpy(dest, src, sizeof(AvbChainPartitionDescriptor));

if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
(AvbDescriptor*)dest))
return false;

if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_CHAIN_PARTITION) {
avb_error("Invalid tag for chain partition descriptor.\n");
return false;
}

dest->rollback_index_location = avb_be32toh(dest->rollback_index_location);
dest->partition_name_len = avb_be32toh(dest->partition_name_len);
dest->public_key_len = avb_be32toh(dest->public_key_len);

if (dest->rollback_index_location < 1) {
avb_error("Invalid rollback index location value.\n");
return false;
}

/* Check that partition_name and public_key are fully contained. */
expected_size = sizeof(AvbChainPartitionDescriptor) - sizeof(AvbDescriptor);
if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
!avb_safe_add_to(&expected_size, dest->public_key_len)) {
avb_error("Overflow while adding up sizes.\n");
return false;
}
if (expected_size > dest->parent_descriptor.num_bytes_following) {
avb_error("Descriptor payload size overflow.\n");
return false;
}
return true;
}

+ 54
- 0
lib/libavb/avb_chain_partition_descriptor.h View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
#error "Never include this file directly, include libavb.h instead."
#endif

#ifndef AVB_CHAIN_PARTITION_DESCRIPTOR_H_
#define AVB_CHAIN_PARTITION_DESCRIPTOR_H_

#include "avb_descriptor.h"

#ifdef __cplusplus
extern "C" {
#endif

/* A descriptor containing a pointer to signed integrity data stored
* on another partition. The descriptor contains the partition name in
* question (without the A/B suffix), the public key used to sign the
* integrity data, and rollback index location to use for rollback
* protection.
*
* Following this struct are |partition_name_len| bytes of the
* partition name (UTF-8 encoded) and |public_key_len| bytes of the
* public key.
*
* The |reserved| field is for future expansion and must be set to NUL
* bytes.
*/
typedef struct AvbChainPartitionDescriptor {
AvbDescriptor parent_descriptor;
uint32_t rollback_index_location;
uint32_t partition_name_len;
uint32_t public_key_len;
uint8_t reserved[64];
} AVB_ATTR_PACKED AvbChainPartitionDescriptor;

/* Copies |src| to |dest| and validates, byte-swapping fields in the
* process if needed. Returns true if valid, false if invalid.
*
* Data following the struct is not validated nor copied.
*/
bool avb_chain_partition_descriptor_validate_and_byteswap(
const AvbChainPartitionDescriptor* src,
AvbChainPartitionDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;

#ifdef __cplusplus
}
#endif

#endif /* AVB_CHAIN_PARTITION_DESCRIPTOR_H_ */

+ 422
- 0
lib/libavb/avb_cmdline.c View File

@@ -0,0 +1,422 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#include "avb_cmdline.h"
#include "avb_sha.h"
#include "avb_util.h"
#include "avb_version.h"

#define NUM_GUIDS 3

/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
* values. Returns NULL on OOM, otherwise the cmdline with values
* replaced.
*/
char* avb_sub_cmdline(AvbOps* ops,
const char* cmdline,
const char* ab_suffix,
bool using_boot_for_vbmeta,
const AvbCmdlineSubstList* additional_substitutions) {
const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
"$(ANDROID_BOOT_PARTUUID)",
"$(ANDROID_VBMETA_PARTUUID)"};
char* ret = NULL;
AvbIOResult io_ret;
size_t n;

/* Special-case for when the top-level vbmeta struct is in the boot
* partition.
*/
if (using_boot_for_vbmeta) {
part_name_str[2] = "boot";
}

/* Replace unique partition GUIDs */
for (n = 0; n < NUM_GUIDS; n++) {
char part_name[AVB_PART_NAME_MAX_SIZE];
char guid_buf[37];

if (!avb_str_concat(part_name,
sizeof part_name,
part_name_str[n],
avb_strlen(part_name_str[n]),
ab_suffix,
avb_strlen(ab_suffix))) {
avb_error("Partition name and suffix does not fit.\n");
goto fail;
}

io_ret = ops->get_unique_guid_for_partition(
ops, part_name, guid_buf, sizeof guid_buf);
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
goto fail;
} else if (io_ret != AVB_IO_RESULT_OK) {
avb_error("Error getting unique GUID for partition.\n");
goto fail;
}

if (ret == NULL) {
ret = avb_replace(cmdline, replace_str[n], guid_buf);
} else {
char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
avb_free(ret);
ret = new_ret;
}
if (ret == NULL) {
goto fail;
}
}

avb_assert(ret != NULL);

/* Replace any additional substitutions. */
if (additional_substitutions != NULL) {
for (n = 0; n < additional_substitutions->size; ++n) {
char* new_ret = avb_replace(ret,
additional_substitutions->tokens[n],
additional_substitutions->values[n]);
avb_free(ret);
ret = new_ret;
if (ret == NULL) {
goto fail;
}
}
}

return ret;

fail:
if (ret != NULL) {
avb_free(ret);
}
return NULL;
}

static int cmdline_append_option(AvbSlotVerifyData* slot_data,
const char* key,
const char* value) {
size_t offset, key_len, value_len;
char* new_cmdline;

key_len = avb_strlen(key);
value_len = avb_strlen(value);

offset = 0;
if (slot_data->cmdline != NULL) {
offset = avb_strlen(slot_data->cmdline);
if (offset > 0) {
offset += 1;
}
}

new_cmdline = avb_calloc(offset + key_len + value_len + 2);
if (new_cmdline == NULL) {
return 0;
}
if (offset > 0) {
avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
new_cmdline[offset - 1] = ' ';
}
avb_memcpy(new_cmdline + offset, key, key_len);
new_cmdline[offset + key_len] = '=';
avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
if (slot_data->cmdline != NULL) {
avb_free(slot_data->cmdline);
}
slot_data->cmdline = new_cmdline;

return 1;
}

#define AVB_MAX_DIGITS_UINT64 32

/* Writes |value| to |digits| in base 10 followed by a NUL byte.
* Returns number of characters written excluding the NUL byte.
*/
static size_t uint64_to_base10(uint64_t value,
char digits[AVB_MAX_DIGITS_UINT64]) {
char rev_digits[AVB_MAX_DIGITS_UINT64];
size_t n, num_digits;

for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
rev_digits[num_digits++] = avb_div_by_10(&value) + '0';
if (value == 0) {
break;
}
}

for (n = 0; n < num_digits; n++) {
digits[n] = rev_digits[num_digits - 1 - n];
}
digits[n] = '\0';
return n;
}

static int cmdline_append_version(AvbSlotVerifyData* slot_data,
const char* key,
uint64_t major_version,
uint64_t minor_version) {
char major_digits[AVB_MAX_DIGITS_UINT64];
char minor_digits[AVB_MAX_DIGITS_UINT64];
char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
size_t num_major_digits, num_minor_digits;

num_major_digits = uint64_to_base10(major_version, major_digits);
num_minor_digits = uint64_to_base10(minor_version, minor_digits);
avb_memcpy(combined, major_digits, num_major_digits);
combined[num_major_digits] = '.';
avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
combined[num_major_digits + 1 + num_minor_digits] = '\0';

return cmdline_append_option(slot_data, key, combined);
}

static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
const char* key,
uint64_t value) {
char digits[AVB_MAX_DIGITS_UINT64];
uint64_to_base10(value, digits);
return cmdline_append_option(slot_data, key, digits);
}

static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
const char* key,
const uint8_t* data,
size_t data_len) {
int ret;
char* hex_data = avb_bin2hex(data, data_len);
if (hex_data == NULL) {
return 0;
}
ret = cmdline_append_option(slot_data, key, hex_data);
avb_free(hex_data);
return ret;
}

AvbSlotVerifyResult avb_append_options(
AvbOps* ops,
AvbSlotVerifyData* slot_data,
AvbVBMetaImageHeader* toplevel_vbmeta,
AvbAlgorithmType algorithm_type,
AvbHashtreeErrorMode hashtree_error_mode) {
AvbSlotVerifyResult ret;
const char* verity_mode;
bool is_device_unlocked;
AvbIOResult io_ret;

/* Add androidboot.vbmeta.device option. */
if (!cmdline_append_option(slot_data,
"androidboot.vbmeta.device",
"PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}

/* Add androidboot.vbmeta.avb_version option. */
if (!cmdline_append_version(slot_data,
"androidboot.vbmeta.avb_version",
AVB_VERSION_MAJOR,
AVB_VERSION_MINOR)) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}

/* Set androidboot.avb.device_state to "locked" or "unlocked". */
io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
} else if (io_ret != AVB_IO_RESULT_OK) {
avb_error("Error getting device state.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
}
if (!cmdline_append_option(slot_data,
"androidboot.vbmeta.device_state",
is_device_unlocked ? "unlocked" : "locked")) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}

/* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
* function as is used to sign vbmeta.
*/
switch (algorithm_type) {
/* Explicit fallthrough. */
case AVB_ALGORITHM_TYPE_NONE:
case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
size_t n, total_size = 0;
uint8_t vbmeta_digest[AVB_SHA256_DIGEST_SIZE];
avb_slot_verify_data_calculate_vbmeta_digest(
slot_data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest);
for (n = 0; n < slot_data->num_vbmeta_images; n++) {
total_size += slot_data->vbmeta_images[n].vbmeta_size;
}
if (!cmdline_append_option(
slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
!cmdline_append_uint64_base10(
slot_data, "androidboot.vbmeta.size", total_size) ||
!cmdline_append_hex(slot_data,
"androidboot.vbmeta.digest",
vbmeta_digest,
AVB_SHA256_DIGEST_SIZE)) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}
} break;
/* Explicit fallthrough. */
case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
size_t n, total_size = 0;
uint8_t vbmeta_digest[AVB_SHA512_DIGEST_SIZE];
avb_slot_verify_data_calculate_vbmeta_digest(
slot_data, AVB_DIGEST_TYPE_SHA512, vbmeta_digest);
for (n = 0; n < slot_data->num_vbmeta_images; n++) {
total_size += slot_data->vbmeta_images[n].vbmeta_size;
}
if (!cmdline_append_option(
slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
!cmdline_append_uint64_base10(
slot_data, "androidboot.vbmeta.size", total_size) ||
!cmdline_append_hex(slot_data,
"androidboot.vbmeta.digest",
vbmeta_digest,
AVB_SHA512_DIGEST_SIZE)) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}
} break;
case _AVB_ALGORITHM_NUM_TYPES:
avb_assert_not_reached();
break;
}

/* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
verity_mode = "disabled";
} else {
const char* dm_verity_mode;
char* new_ret;

switch (hashtree_error_mode) {
case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
if (!cmdline_append_option(
slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}
verity_mode = "enforcing";
dm_verity_mode = "restart_on_corruption";
break;
case AVB_HASHTREE_ERROR_MODE_RESTART:
verity_mode = "enforcing";
dm_verity_mode = "restart_on_corruption";
break;
case AVB_HASHTREE_ERROR_MODE_EIO:
verity_mode = "eio";
/* For now there's no option to specify the EIO mode. So
* just use 'ignore_zero_blocks' since that's already set
* and dm-verity-target.c supports specifying this multiple
* times.
*/
dm_verity_mode = "ignore_zero_blocks";
break;
case AVB_HASHTREE_ERROR_MODE_LOGGING:
verity_mode = "logging";
dm_verity_mode = "ignore_corruption";
break;
}
new_ret = avb_replace(
slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
avb_free(slot_data->cmdline);
slot_data->cmdline = new_ret;
if (slot_data->cmdline == NULL) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}
}
if (!cmdline_append_option(
slot_data, "androidboot.veritymode", verity_mode)) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
}

ret = AVB_SLOT_VERIFY_RESULT_OK;

out:

return ret;
}

AvbCmdlineSubstList* avb_new_cmdline_subst_list() {
return (AvbCmdlineSubstList*)avb_calloc(sizeof(AvbCmdlineSubstList));
}

void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst) {
size_t i;
for (i = 0; i < cmdline_subst->size; ++i) {
avb_free(cmdline_subst->tokens[i]);
avb_free(cmdline_subst->values[i]);
}
cmdline_subst->size = 0;
avb_free(cmdline_subst);
}

AvbSlotVerifyResult avb_add_root_digest_substitution(
const char* part_name,
const uint8_t* digest,
size_t digest_size,
AvbCmdlineSubstList* out_cmdline_subst) {
const char* kDigestSubPrefix = "$(AVB_";
const char* kDigestSubSuffix = "_ROOT_DIGEST)";
size_t part_name_len = avb_strlen(part_name);
size_t list_index = out_cmdline_subst->size;

avb_assert(part_name_len < AVB_PART_NAME_MAX_SIZE);
avb_assert(digest_size <= AVB_SHA512_DIGEST_SIZE);
if (part_name_len >= AVB_PART_NAME_MAX_SIZE ||
digest_size > AVB_SHA512_DIGEST_SIZE) {
return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
}

if (out_cmdline_subst->size >= AVB_MAX_NUM_CMDLINE_SUBST) {
/* The list is full. Currently dynamic growth of this list is not supported.
*/
return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
}

/* Construct the token to replace in the command line based on the partition
* name. For partition 'foo', this will be '$(AVB_FOO_ROOT_DIGEST)'.
*/
out_cmdline_subst->tokens[list_index] =
avb_strdupv(kDigestSubPrefix, part_name, kDigestSubSuffix, NULL);
if (out_cmdline_subst->tokens[list_index] == NULL) {
goto fail;
}
avb_uppercase(out_cmdline_subst->tokens[list_index]);

/* The digest value is hex encoded when inserted in the command line. */
out_cmdline_subst->values[list_index] = avb_bin2hex(digest, digest_size);
if (out_cmdline_subst->values[list_index] == NULL) {
goto fail;
}

out_cmdline_subst->size++;
return AVB_SLOT_VERIFY_RESULT_OK;

fail:
if (out_cmdline_subst->tokens[list_index]) {
avb_free(out_cmdline_subst->tokens[list_index]);
}
if (out_cmdline_subst->values[list_index]) {
avb_free(out_cmdline_subst->values[list_index]);
}
return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
}

+ 72
- 0
lib/libavb/avb_cmdline.h View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#ifdef AVB_INSIDE_LIBAVB_H
#error "You can't include avb_sha.h in the public header libavb.h."
#endif

#ifndef AVB_COMPILATION
#error "Never include this file, it may only be used from internal avb code."
#endif

#ifndef AVB_CMDLINE_H_
#define AVB_CMDLINE_H_

#include "avb_ops.h"
#include "avb_slot_verify.h"

/* Maximum allow length (in bytes) of a partition name, including
* ab_suffix.
*/
#define AVB_PART_NAME_MAX_SIZE 32

#define AVB_MAX_NUM_CMDLINE_SUBST 10

/* Holds information about command-line substitutions. */
typedef struct AvbCmdlineSubstList {
size_t size;
char* tokens[AVB_MAX_NUM_CMDLINE_SUBST];
char* values[AVB_MAX_NUM_CMDLINE_SUBST];
} AvbCmdlineSubstList;

/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
* values. Returns NULL on OOM, otherwise the cmdline with values
* replaced.
*/
char* avb_sub_cmdline(AvbOps* ops,
const char* cmdline,
const char* ab_suffix,
bool using_boot_for_vbmeta,
const AvbCmdlineSubstList* additional_substitutions);

AvbSlotVerifyResult avb_append_options(
AvbOps* ops,
AvbSlotVerifyData* slot_data,
AvbVBMetaImageHeader* toplevel_vbmeta,
AvbAlgorithmType algorithm_type,
AvbHashtreeErrorMode hashtree_error_mode);

/* Allocates and initializes a new command line substitution list. Free with
* |avb_free_cmdline_subst_list|.
*/
AvbCmdlineSubstList* avb_new_cmdline_subst_list(void);

/* Use this instead of |avb_free| to deallocate a AvbCmdlineSubstList. */
void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst);

/* Adds a hashtree root digest to be substituted in $(AVB_*_ROOT_DIGEST)
* variables. The partition name differentiates the variable. For example, if
* |part_name| is "foo" then $(AVB_FOO_ROOT_DIGEST) will be substituted with the
* hex encoding of the digest. The substitution will be added to
* |out_cmdline_subst|. Returns AVB_SLOT_VERIFY_RESULT_OK on success.
*/
AvbSlotVerifyResult avb_add_root_digest_substitution(
const char* part_name,
const uint8_t* digest,
size_t digest_size,
AvbCmdlineSubstList* out_cmdline_subst);

#endif

+ 354
- 0
lib/libavb/avb_crypto.c View File

@@ -0,0 +1,354 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#include "avb_crypto.h"
#include "avb_rsa.h"
#include "avb_sha.h"
#include "avb_util.h"

/* NOTE: The PKC1-v1.5 padding is a blob of binary DER of ASN.1 and is
* obtained from section 5.2.2 of RFC 4880.
*/

static const uint8_t
padding_RSA2048_SHA256[AVB_RSA2048_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};

static const uint8_t
padding_RSA4096_SHA256[AVB_RSA4096_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};

static const uint8_t
padding_RSA8192_SHA256[AVB_RSA8192_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};

static const uint8_t
padding_RSA2048_SHA512[AVB_RSA2048_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};

static const uint8_t
padding_RSA4096_SHA512[AVB_RSA4096_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30,
0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
0x05, 0x00, 0x04, 0x40};

static const uint8_t
padding_RSA8192_SHA512[AVB_RSA8192_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};

static AvbAlgorithmData algorithm_data[_AVB_ALGORITHM_NUM_TYPES] = {
/* AVB_ALGORITHM_TYPE_NONE */
{.padding = NULL, .padding_len = 0, .hash_len = 0},
/* AVB_ALGORITHM_TYPE_SHA256_RSA2048 */
{.padding = padding_RSA2048_SHA256,
.padding_len = sizeof(padding_RSA2048_SHA256),
.hash_len = AVB_SHA256_DIGEST_SIZE},
/* AVB_ALGORITHM_TYPE_SHA256_RSA4096 */
{.padding = padding_RSA4096_SHA256,
.padding_len = sizeof(padding_RSA4096_SHA256),
.hash_len = AVB_SHA256_DIGEST_SIZE},
/* AVB_ALGORITHM_TYPE_SHA256_RSA8192 */
{.padding = padding_RSA8192_SHA256,
.padding_len = sizeof(padding_RSA8192_SHA256),
.hash_len = AVB_SHA256_DIGEST_SIZE},
/* AVB_ALGORITHM_TYPE_SHA512_RSA2048 */
{.padding = padding_RSA2048_SHA512,
.padding_len = sizeof(padding_RSA2048_SHA512),
.hash_len = AVB_SHA512_DIGEST_SIZE},
/* AVB_ALGORITHM_TYPE_SHA512_RSA4096 */
{.padding = padding_RSA4096_SHA512,
.padding_len = sizeof(padding_RSA4096_SHA512),
.hash_len = AVB_SHA512_DIGEST_SIZE},
/* AVB_ALGORITHM_TYPE_SHA512_RSA8192 */
{.padding = padding_RSA8192_SHA512,
.padding_len = sizeof(padding_RSA8192_SHA512),
.hash_len = AVB_SHA512_DIGEST_SIZE},
};

const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm) {
if ((size_t)algorithm < _AVB_ALGORITHM_NUM_TYPES) {
return &algorithm_data[algorithm];
}
return NULL;
}

bool avb_rsa_public_key_header_validate_and_byteswap(
const AvbRSAPublicKeyHeader* src, AvbRSAPublicKeyHeader* dest) {
avb_memcpy(dest, src, sizeof(AvbRSAPublicKeyHeader));

dest->key_num_bits = avb_be32toh(dest->key_num_bits);
dest->n0inv = avb_be32toh(dest->n0inv);

return true;
}

+ 156
- 0
lib/libavb/avb_crypto.h View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
#error "Never include this file directly, include libavb.h instead."
#endif

#ifndef AVB_CRYPTO_H_
#define AVB_CRYPTO_H_

#include "avb_sysdeps.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Size of a RSA-2048 signature. */
#define AVB_RSA2048_NUM_BYTES 256

/* Size of a RSA-4096 signature. */
#define AVB_RSA4096_NUM_BYTES 512

/* Size of a RSA-8192 signature. */
#define AVB_RSA8192_NUM_BYTES 1024

/* Size in bytes of a SHA-1 digest. */
#define AVB_SHA1_DIGEST_SIZE 20

/* Size in bytes of a SHA-256 digest. */
#define AVB_SHA256_DIGEST_SIZE 32

/* Size in bytes of a SHA-512 digest. */
#define AVB_SHA512_DIGEST_SIZE 64

/* Possible digest types supported by libavb routines. */
typedef enum {
AVB_DIGEST_TYPE_SHA256,
AVB_DIGEST_TYPE_SHA512,
} AvbDigestType;

/* Algorithms that can be used in the vbmeta image for
* verification. An algorithm consists of a hash type and a signature
* type.
*
* The data used to calculate the hash is the three blocks mentioned
* in the documentation for |AvbVBMetaImageHeader| except for the data
* in the "Authentication data" block.
*
* For signatures with RSA keys, PKCS v1.5 padding is used. The public
* key data is stored in the auxiliary data block, see
* |AvbRSAPublicKeyHeader| for the serialization format.
*
* Each algorithm type is described below:
*
* AVB_ALGORITHM_TYPE_NONE: There is no hash, no signature of the
* data, and no public key. The data cannot be verified. The fields
* |hash_size|, |signature_size|, and |public_key_size| must be zero.
*
* AVB_ALGORITHM_TYPE_SHA256_RSA2048: The hash function used is
* SHA-256, resulting in 32 bytes of hash digest data. This hash is
* signed with a 2048-bit RSA key. The field |hash_size| must be 32,
* |signature_size| must be 256, and the public key data must have
* |key_num_bits| set to 2048.
*
* AVB_ALGORITHM_TYPE_SHA256_RSA4096: Like above, but only with
* a 4096-bit RSA key and |signature_size| set to 512.
*
* AVB_ALGORITHM_TYPE_SHA256_RSA8192: Like above, but only with
* a 8192-bit RSA key and |signature_size| set to 1024.
*
* AVB_ALGORITHM_TYPE_SHA512_RSA2048: The hash function used is
* SHA-512, resulting in 64 bytes of hash digest data. This hash is
* signed with a 2048-bit RSA key. The field |hash_size| must be 64,
* |signature_size| must be 256, and the public key data must have
* |key_num_bits| set to 2048.
*
* AVB_ALGORITHM_TYPE_SHA512_RSA4096: Like above, but only with
* a 4096-bit RSA key and |signature_size| set to 512.
*
* AVB_ALGORITHM_TYPE_SHA512_RSA8192: Like above, but only with
* a 8192-bit RSA key and |signature_size| set to 1024.
*/
typedef enum {
AVB_ALGORITHM_TYPE_NONE,
AVB_ALGORITHM_TYPE_SHA256_RSA2048,
AVB_ALGORITHM_TYPE_SHA256_RSA4096,
AVB_ALGORITHM_TYPE_SHA256_RSA8192,
AVB_ALGORITHM_TYPE_SHA512_RSA2048,
AVB_ALGORITHM_TYPE_SHA512_RSA4096,
AVB_ALGORITHM_TYPE_SHA512_RSA8192,
_AVB_ALGORITHM_NUM_TYPES
} AvbAlgorithmType;

/* Holds algorithm-specific data. The |padding| is needed by avb_rsa_verify. */
typedef struct {
const uint8_t* padding;
size_t padding_len;
size_t hash_len;
} AvbAlgorithmData;

/* Provides algorithm-specific data for a given |algorithm|. Returns NULL if
* |algorithm| is invalid.
*/
const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm)
AVB_ATTR_WARN_UNUSED_RESULT;

/* The header for a serialized RSA public key.
*
* The size of the key is given by |key_num_bits|, for example 2048
* for a RSA-2048 key. By definition, a RSA public key is the pair (n,
* e) where |n| is the modulus (which can be represented in
* |key_num_bits| bits) and |e| is the public exponent. The exponent
* is not stored since it's assumed to always be 65537.
*
* To optimize verification, the key block includes two precomputed
* values, |n0inv| (fits in 32 bits) and |rr| and can always be
* represented in |key_num_bits|.

* The value |n0inv| is the value -1/n[0] (mod 2^32). The value |rr|
* is (2^key_num_bits)^2 (mod n).
*
* Following this header is |key_num_bits| bits of |n|, then
* |key_num_bits| bits of |rr|. Both values are stored with most
* significant bit first. Each serialized number takes up
* |key_num_bits|/8 bytes.
*
* All fields in this struct are stored in network byte order when
* serialized. To generate a copy with fields swapped to native byte
* order, use the function avb_rsa_public_key_header_validate_and_byteswap().
*
* The avb_rsa_verify() function expects a key in this serialized
* format.
*
* The 'avbtool extract_public_key' command can be used to generate a
* serialized RSA public key.
*/
typedef struct AvbRSAPublicKeyHeader {
uint32_t key_num_bits;
uint32_t n0inv;
} AVB_ATTR_PACKED AvbRSAPublicKeyHeader;

/* Copies |src| to |dest| and validates, byte-swapping fields in the
* process if needed. Returns true if valid, false if invalid.
*/
bool avb_rsa_public_key_header_validate_and_byteswap(
const AvbRSAPublicKeyHeader* src,
AvbRSAPublicKeyHeader* dest) AVB_ATTR_WARN_UNUSED_RESULT;

#ifdef __cplusplus
}
#endif

#endif /* AVB_CRYPTO_H_ */

+ 142
- 0
lib/libavb/avb_descriptor.c View File

@@ -0,0 +1,142 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#include "avb_descriptor.h"
#include "avb_util.h"
#include "avb_vbmeta_image.h"

bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src,
AvbDescriptor* dest) {
dest->tag = avb_be64toh(src->tag);
dest->num_bytes_following = avb_be64toh(src->num_bytes_following);

if ((dest->num_bytes_following & 0x07) != 0) {
avb_error("Descriptor size is not divisible by 8.\n");
return false;
}
return true;
}

bool avb_descriptor_foreach(const uint8_t* image_data,
size_t image_size,
AvbDescriptorForeachFunc foreach_func,
void* user_data) {
const AvbVBMetaImageHeader* header = NULL;
bool ret = false;
const uint8_t* image_end;
const uint8_t* desc_start;
const uint8_t* desc_end;
const uint8_t* p;

if (image_data == NULL) {
avb_error("image_data is NULL\n.");
goto out;
}

if (foreach_func == NULL) {
avb_error("foreach_func is NULL\n.");
goto out;
}

if (image_size < sizeof(AvbVBMetaImageHeader)) {
avb_error("Length is smaller than header.\n");
goto out;
}

/* Ensure magic is correct. */
if (avb_memcmp(image_data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
avb_error("Magic is incorrect.\n");
goto out;
}

/* Careful, not byteswapped - also ensure it's aligned properly. */
avb_assert_aligned(image_data);
header = (const AvbVBMetaImageHeader*)image_data;
image_end = image_data + image_size;

desc_start = image_data + sizeof(AvbVBMetaImageHeader) +
avb_be64toh(header->authentication_data_block_size) +
avb_be64toh(header->descriptors_offset);

desc_end = desc_start + avb_be64toh(header->descriptors_size);

if (desc_start < image_data || desc_start > image_end ||
desc_end < image_data || desc_end > image_end || desc_end < desc_start) {
avb_error("Descriptors not inside passed-in data.\n");
goto out;
}

for (p = desc_start; p < desc_end;) {
const AvbDescriptor* dh = (const AvbDescriptor*)p;
avb_assert_aligned(dh);
uint64_t nb_following = avb_be64toh(dh->num_bytes_following);
uint64_t nb_total = sizeof(AvbDescriptor) + nb_following;

if ((nb_total & 7) != 0) {
avb_error("Invalid descriptor length.\n");
goto out;
}

if (nb_total + p < desc_start || nb_total + p > desc_end) {
avb_error("Invalid data in descriptors array.\n");
goto out;
}

if (foreach_func(dh, user_data) == 0) {
goto out;
}

p += nb_total;
}

ret = true;

out:
return ret;
}

static bool count_descriptors(const AvbDescriptor* descriptor,
void* user_data) {
size_t* num_descriptors = user_data;
*num_descriptors += 1;
return true;
}

typedef struct {
size_t descriptor_number;
const AvbDescriptor** descriptors;
} SetDescriptorData;

static bool set_descriptors(const AvbDescriptor* descriptor, void* user_data) {
SetDescriptorData* data = user_data;
data->descriptors[data->descriptor_number++] = descriptor;
return true;
}

const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
size_t image_size,
size_t* out_num_descriptors) {
size_t num_descriptors = 0;
SetDescriptorData data;

avb_descriptor_foreach(
image_data, image_size, count_descriptors, &num_descriptors);

data.descriptor_number = 0;
data.descriptors =
avb_calloc(sizeof(const AvbDescriptor*) * (num_descriptors + 1));
if (data.descriptors == NULL) {
return NULL;
}
avb_descriptor_foreach(image_data, image_size, set_descriptors, &data);
avb_assert(data.descriptor_number == num_descriptors);

if (out_num_descriptors != NULL) {
*out_num_descriptors = num_descriptors;
}

return data.descriptors;
}

+ 113
- 0
lib/libavb/avb_descriptor.h View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
#error "Never include this file directly, include libavb.h instead."
#endif

#ifndef AVB_DESCRIPTOR_H_
#define AVB_DESCRIPTOR_H_

#include "avb_sysdeps.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Well-known descriptor tags.
*
* AVB_DESCRIPTOR_TAG_PROPERTY: see |AvbPropertyDescriptor| struct.
* AVB_DESCRIPTOR_TAG_HASHTREE: see |AvbHashtreeDescriptor| struct.
* AVB_DESCRIPTOR_TAG_HASH: see |AvbHashDescriptor| struct.
* AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: see |AvbKernelCmdlineDescriptor| struct.
* AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: see |AvbChainPartitionDescriptor| struct.
*/
typedef enum {
AVB_DESCRIPTOR_TAG_PROPERTY,
AVB_DESCRIPTOR_TAG_HASHTREE,
AVB_DESCRIPTOR_TAG_HASH,
AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
} AvbDescriptorTag;

/* The header for a serialized descriptor.
*
* A descriptor always have two fields, a |tag| (denoting its type,
* see the |AvbDescriptorTag| enumeration) and the size of the bytes
* following, |num_bytes_following|.
*
* For padding, |num_bytes_following| is always a multiple of 8.
*/
typedef struct AvbDescriptor {
uint64_t tag;
uint64_t num_bytes_following;
} AVB_ATTR_PACKED AvbDescriptor;

/* Copies |src| to |dest| and validates, byte-swapping fields in the
* process if needed. Returns true if valid, false if invalid.
*
* Data following the struct is not validated nor copied.
*/
bool avb_descriptor_validate_and_byteswap(
const AvbDescriptor* src, AvbDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;

/* Signature for callback function used in avb_descriptor_foreach().
* The passed in descriptor is given by |descriptor| and the
* |user_data| passed to avb_descriptor_foreach() function is in
* |user_data|. Return true to continue iterating, false to stop
* iterating.
*
* Note that |descriptor| points into the image passed to
* avb_descriptor_foreach() - all fields need to be byteswapped!
*/
typedef bool AvbDescriptorForeachFunc(const AvbDescriptor* descriptor,
void* user_data);

/* Convenience function to iterate over all descriptors in an vbmeta
* image.
*
* The function given by |foreach_func| will be called for each
* descriptor. The given function should return true to continue
* iterating, false to stop.
*
* The |user_data| parameter will be passed to |foreach_func|.
*
* Returns false if the iteration was short-circuited, that is if
* an invocation of |foreach_func| returned false.
*
* Before using this function, you MUST verify |image_data| with
* avb_vbmeta_image_verify() and reject it unless it's signed by a known
* good public key. Additionally, |image_data| must be word-aligned.
*/
bool avb_descriptor_foreach(const uint8_t* image_data,
size_t image_size,
AvbDescriptorForeachFunc foreach_func,
void* user_data);

/* Gets all descriptors in a vbmeta image.
*
* The return value is a NULL-pointer terminated array of
* AvbDescriptor pointers. Free with avb_free() when you are done with
* it. If |out_num_descriptors| is non-NULL, the number of descriptors
* will be returned there.
*
* Note that each AvbDescriptor pointer in the array points into
* |image_data| - all fields need to be byteswapped!
*
* Before using this function, you MUST verify |image_data| with
* avb_vbmeta_image_verify() and reject it unless it's signed by a known
* good public key. Additionally, |image_data| must be word-aligned.
*/
const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
size_t image_size,
size_t* out_num_descriptors)
AVB_ATTR_WARN_UNUSED_RESULT;

#ifdef __cplusplus
}
#endif

#endif /* AVB_DESCRIPTOR_H_ */

+ 36
- 0
lib/libavb/avb_footer.c View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#include "avb_footer.h"
#include "avb_util.h"

bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest) {
avb_memcpy(dest, src, sizeof(AvbFooter));

dest->version_major = avb_be32toh(dest->version_major);
dest->version_minor = avb_be32toh(dest->version_minor);

dest->original_image_size = avb_be64toh(dest->original_image_size);
dest->vbmeta_offset = avb_be64toh(dest->vbmeta_offset);
dest->vbmeta_size = avb_be64toh(dest->vbmeta_size);

/* Check that magic is correct. */
if (avb_safe_memcmp(dest->magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) !=
0) {
avb_error("Footer magic is incorrect.\n");
return false;
}

/* Ensure we don't attempt to access any fields if the footer major
* version is not supported.
*/
if (dest->version_major > AVB_FOOTER_VERSION_MAJOR) {
avb_error("No support for footer version.\n");
return false;
}

return true;
}

+ 68
- 0
lib/libavb/avb_footer.h View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
#error "Never include this file directly, include libavb.h instead."
#endif

#ifndef AVB_FOOTER_H_
#define AVB_FOOTER_H_

#include "avb_sysdeps.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Magic for the footer. */
#define AVB_FOOTER_MAGIC "AVBf"
#define AVB_FOOTER_MAGIC_LEN 4

/* Size of the footer. */
#define AVB_FOOTER_SIZE 64

/* The current footer version used - keep in sync with avbtool. */
#define AVB_FOOTER_VERSION_MAJOR 1
#define AVB_FOOTER_VERSION_MINOR 0

/* The struct used as a footer used on partitions, used to find the
* AvbVBMetaImageHeader struct. This struct is always stored at the
* end of a partition.
*/
typedef struct AvbFooter {
/* 0: Four bytes equal to "AVBf" (AVB_FOOTER_MAGIC). */
uint8_t magic[AVB_FOOTER_MAGIC_LEN];
/* 4: The major version of the footer struct. */
uint32_t version_major;
/* 8: The minor version of the footer struct. */
uint32_t version_minor;

/* 12: The original size of the image on the partition. */
uint64_t original_image_size;

/* 20: The offset of the |AvbVBMetaImageHeader| struct. */
uint64_t vbmeta_offset;

/* 28: The size of the vbmeta block (header + auth + aux blocks). */
uint64_t vbmeta_size;

/* 36: Padding to ensure struct is size AVB_FOOTER_SIZE bytes. This
* must be set to zeroes.
*/
uint8_t reserved[28];
} AVB_ATTR_PACKED AvbFooter;

/* Copies |src| to |dest| and validates, byte-swapping fields in the
* process if needed. Returns true if valid, false if invalid.
*/
bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest)
AVB_ATTR_WARN_UNUSED_RESULT;

#ifdef __cplusplus
}
#endif

#endif /* AVB_FOOTER_H_ */

+ 44
- 0
lib/libavb/avb_hash_descriptor.c View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#include "avb_hash_descriptor.h"
#include "avb_util.h"

bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
AvbHashDescriptor* dest) {
uint64_t expected_size;

avb_memcpy(dest, src, sizeof(AvbHashDescriptor));

if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
(AvbDescriptor*)dest))
return false;

if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASH) {
avb_error("Invalid tag for hash descriptor.\n");
return false;
}

dest->image_size = avb_be64toh(dest->image_size);
dest->partition_name_len = avb_be32toh(dest->partition_name_len);
dest->salt_len = avb_be32toh(dest->salt_len);
dest->digest_len = avb_be32toh(dest->digest_len);
dest->flags = avb_be32toh(dest->flags);

/* Check that partition_name, salt, and digest are fully contained. */
expected_size = sizeof(AvbHashDescriptor) - sizeof(AvbDescriptor);
if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
!avb_safe_add_to(&expected_size, dest->salt_len) ||
!avb_safe_add_to(&expected_size, dest->digest_len)) {
avb_error("Overflow while adding up sizes.\n");
return false;
}
if (expected_size > dest->parent_descriptor.num_bytes_following) {
avb_error("Descriptor payload size overflow.\n");
return false;
}
return true;
}

+ 70
- 0
lib/libavb/avb_hash_descriptor.h View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
#error "Never include this file directly, include libavb.h instead."
#endif

#ifndef AVB_HASH_DESCRIPTOR_H_
#define AVB_HASH_DESCRIPTOR_H_

#include "avb_descriptor.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Flags for hash descriptors.
*
* AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B
* partition logic to this partition. This is intentionally a negative boolean
* because A/B should be both the default and most used in practice.
*/
typedef enum {
AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
} AvbHashDescriptorFlags;

/* A descriptor containing information about hash for an image.
*
* This descriptor is typically used for boot partitions to verify the
* entire kernel+initramfs image before executing it.
*
* Following this struct are |partition_name_len| bytes of the
* partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
* |digest_len| bytes of the digest.
*
* The |reserved| field is for future expansion and must be set to NUL
* bytes.
*
* Changes in v1.1:
* - flags field is added which supports AVB_HASH_DESCRIPTOR_FLAGS_USE_AB
* - digest_len may be zero, which indicates the use of a persistent digest
*/
typedef struct AvbHashDescriptor {
AvbDescriptor parent_descriptor;
uint64_t image_size;
uint8_t hash_algorithm[32];
uint32_t partition_name_len;
uint32_t salt_len;
uint32_t digest_len;
uint32_t flags;
uint8_t reserved[60];
} AVB_ATTR_PACKED AvbHashDescriptor;

/* Copies |src| to |dest| and validates, byte-swapping fields in the
* process if needed. Returns true if valid, false if invalid.
*
* Data following the struct is not validated nor copied.
*/
bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
AvbHashDescriptor* dest)
AVB_ATTR_WARN_UNUSED_RESULT;

#ifdef __cplusplus
}
#endif

#endif /* AVB_HASH_DESCRIPTOR_H_ */

+ 52
- 0
lib/libavb/avb_hashtree_descriptor.c View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#include "avb_hashtree_descriptor.h"
#include "avb_util.h"

bool avb_hashtree_descriptor_validate_and_byteswap(
const AvbHashtreeDescriptor* src, AvbHashtreeDescriptor* dest) {
uint64_t expected_size;

avb_memcpy(dest, src, sizeof(AvbHashtreeDescriptor));

if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
(AvbDescriptor*)dest))
return false;

if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASHTREE) {
avb_error("Invalid tag for hashtree descriptor.\n");
return false;
}

dest->dm_verity_version = avb_be32toh(dest->dm_verity_version);
dest->image_size = avb_be64toh(dest->image_size);
dest->tree_offset = avb_be64toh(dest->tree_offset);
dest->tree_size = avb_be64toh(dest->tree_size);
dest->data_block_size = avb_be32toh(dest->data_block_size);
dest->hash_block_size = avb_be32toh(dest->hash_block_size);
dest->fec_num_roots = avb_be32toh(dest->fec_num_roots);
dest->fec_offset = avb_be64toh(dest->fec_offset);
dest->fec_size = avb_be64toh(dest->fec_size);
dest->partition_name_len = avb_be32toh(dest->partition_name_len);
dest->salt_len = avb_be32toh(dest->salt_len);
dest->root_digest_len = avb_be32toh(dest->root_digest_len);
dest->flags = avb_be32toh(dest->flags);

/* Check that partition_name, salt, and root_digest are fully contained. */
expected_size = sizeof(AvbHashtreeDescriptor) - sizeof(AvbDescriptor);
if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
!avb_safe_add_to(&expected_size, dest->salt_len) ||
!avb_safe_add_to(&expected_size, dest->root_digest_len)) {
avb_error("Overflow while adding up sizes.\n");
return false;
}
if (expected_size > dest->parent_descriptor.num_bytes_following) {
avb_error("Descriptor payload size overflow.\n");
return false;
}
return true;
}

+ 80
- 0
lib/libavb/avb_hashtree_descriptor.h View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
#error "Never include this file directly, include libavb.h instead."
#endif

#ifndef AVB_HASHTREE_DESCRIPTOR_H_
#define AVB_HASHTREE_DESCRIPTOR_H_

#include "avb_descriptor.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Flags for hashtree descriptors.
*
* AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B
* partition logic to this partition. This is intentionally a negative boolean
* because A/B should be both the default and most used in practice.
*/
typedef enum {
AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
} AvbHashtreeDescriptorFlags;

/* A descriptor containing information about a dm-verity hashtree.
*
* Hash-trees are used to verify large partitions typically containing
* file systems. See
* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for more
* information about dm-verity.
*
* Following this struct are |partition_name_len| bytes of the
* partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
* |root_digest_len| bytes of the root digest.
*
* The |reserved| field is for future expansion and must be set to NUL
* bytes.
*
* Changes in v1.1:
* - flags field is added which supports AVB_HASHTREE_DESCRIPTOR_FLAGS_USE_AB
* - digest_len may be zero, which indicates the use of a persistent digest
*/
typedef struct AvbHashtreeDescriptor {
AvbDescriptor parent_descriptor;
uint32_t dm_verity_version;
uint64_t image_size;
uint64_t tree_offset;
uint64_t tree_size;
uint32_t data_block_size;
uint32_t hash_block_size;
uint32_t fec_num_roots;
uint64_t fec_offset;
uint64_t fec_size;
uint8_t hash_algorithm[32];
uint32_t partition_name_len;
uint32_t salt_len;
uint32_t root_digest_len;
uint32_t flags;
uint8_t reserved[60];
} AVB_ATTR_PACKED AvbHashtreeDescriptor;

/* Copies |src| to |dest| and validates, byte-swapping fields in the
* process if needed. Returns true if valid, false if invalid.
*
* Data following the struct is not validated nor copied.
*/
bool avb_hashtree_descriptor_validate_and_byteswap(
const AvbHashtreeDescriptor* src,
AvbHashtreeDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;

#ifdef __cplusplus
}
#endif

#endif /* AVB_HASHTREE_DESCRIPTOR_H_ */

+ 40
- 0
lib/libavb/avb_kernel_cmdline_descriptor.c View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#include "avb_kernel_cmdline_descriptor.h"
#include "avb_util.h"

bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
const AvbKernelCmdlineDescriptor* src, AvbKernelCmdlineDescriptor* dest) {
uint64_t expected_size;

avb_memcpy(dest, src, sizeof(AvbKernelCmdlineDescriptor));

if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
(AvbDescriptor*)dest))
return false;

if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE) {
avb_error("Invalid tag for kernel cmdline descriptor.\n");
return false;
}

dest->flags = avb_be32toh(dest->flags);
dest->kernel_cmdline_length = avb_be32toh(dest->kernel_cmdline_length);

/* Check that kernel_cmdline is fully contained. */
expected_size = sizeof(AvbKernelCmdlineDescriptor) - sizeof(AvbDescriptor);
if (!avb_safe_add_to(&expected_size, dest->kernel_cmdline_length)) {
avb_error("Overflow while adding up sizes.\n");
return false;
}
if (expected_size > dest->parent_descriptor.num_bytes_following) {
avb_error("Descriptor payload size overflow.\n");
return false;
}

return true;
}

+ 63
- 0
lib/libavb/avb_kernel_cmdline_descriptor.h View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
#error "Never include this file directly, include libavb.h instead."
#endif

#ifndef AVB_KERNEL_CMDLINE_DESCRIPTOR_H_
#define AVB_KERNEL_CMDLINE_DESCRIPTOR_H_

#include "avb_descriptor.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Flags for kernel command-line descriptors.
*
* AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED: The
* cmdline will only be applied if hashtree verification is not
* disabled (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
*
* AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED: The cmdline
* will only be applied if hashtree verification is disabled
* (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
*/
typedef enum {
AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED = (1 << 0),
AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED = (1 << 1)
} AvbKernelCmdlineFlags;

/* A descriptor containing information to be appended to the kernel
* command-line.
*
* The |flags| field contains flags from the AvbKernelCmdlineFlags
* enumeration.
*
* Following this struct are |kernel_cmdline_len| bytes with the
* kernel command-line (UTF-8 encoded).
*/
typedef struct AvbKernelCmdlineDescriptor {
AvbDescriptor parent_descriptor;
uint32_t flags;
uint32_t kernel_cmdline_length;
} AVB_ATTR_PACKED AvbKernelCmdlineDescriptor;

/* Copies |src| to |dest| and validates, byte-swapping fields in the
* process if needed. Returns true if valid, false if invalid.
*
* Data following the struct is not validated nor copied.
*/
bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
const AvbKernelCmdlineDescriptor* src,
AvbKernelCmdlineDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;

#ifdef __cplusplus
}
#endif

#endif /* AVB_KERNEL_CMDLINE_DESCRIPTOR_H_ */

+ 293
- 0
lib/libavb/avb_ops.h View File

@@ -0,0 +1,293 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* SPDX-License-Identifier: MIT
*/

#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
#error "Never include this file directly, include libavb.h instead."
#endif

#ifndef AVB_OPS_H_
#define AVB_OPS_H_

#include "avb_sysdeps.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Well-known names of named persistent values. */
#define AVB_NPV_PERSISTENT_DIGEST_PREFIX "avb.persistent_digest."

/* Return codes used for I/O operations.
*
* AVB_IO_RESULT_OK is returned if the requested operation was
* successful.
*
* AVB_IO_RESULT_ERROR_IO is returned if the underlying hardware (disk
* or other subsystem) encountered an I/O error.
*
* AVB_IO_RESULT_ERROR_OOM is returned if unable to allocate memory.
*
* AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is returned if the requested
* partition does not exist.
*
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the
* range of bytes requested to be read or written is outside the range
* of the partition.
*
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE is returned if a named persistent value
* does not exist.
*
* AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE is returned if a named persistent
* value size is not supported or does not match the expected size.
*
* AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned if a buffer is too small
* for the requested operation.
*/
typedef enum {
AVB_IO_RESULT_OK,
AVB_IO_RESULT_ERROR_OOM,
AVB_IO_RESULT_ERROR_IO,
AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION,
AVB_IO_RESULT_ERROR_NO_SUCH_VALUE,
AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE,
AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE,
} AvbIOResult;

struct AvbOps;
typedef struct AvbOps AvbOps;

/* Forward-declaration of operations in libavb_ab. */
struct AvbABOps;

/* Forward-declaration of operations in libavb_atx. */
struct AvbAtxOps;

/* High-level operations/functions/methods that are platform
* dependent.
*
* Operations may be added in the future so when implementing it
* always make sure to zero out sizeof(AvbOps) bytes of the struct to
* ensure that unimplemented operations are set to NULL.
*/
struct AvbOps {
/* This pointer can be used by the application/bootloader using
* libavb and is typically used in each operation to get a pointer
* to platform-specific resources. It cannot be used by libraries.
*/
void* user_data;

/* If libavb_ab is used, this should point to the
* AvbABOps. Otherwise it must be set to NULL.
*/
struct AvbABOps* ab_ops;

/* If libavb_atx is used, this should point to the
* AvbAtxOps. Otherwise it must be set to NULL.
*/
struct AvbAtxOps* atx_ops;

/* Reads |num_bytes| from offset |offset| from partition with name
* |partition| (NUL-terminated UTF-8 string). If |offset| is
* negative, its absolute value should be interpreted as the number
* of bytes from the end of the partition.
*
* This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
* there is no partition with the given name,
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
* |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if
* there was an I/O error from the underlying I/O subsystem. If the
* operation succeeds as requested AVB_IO_RESULT_OK is returned and
* the data is available in |buffer|.
*
* The only time partial I/O may occur is if reading beyond the end
* of the partition. In this case the value returned in
* |out_num_read| may be smaller than |num_bytes|.
*/
AvbIOResult (*read_from_partition)(AvbOps* ops,
const char* partition,
int64_t offset,
size_t num_bytes,
void* buffer,
size_t* out_num_read);

/* Gets the starting pointer of a partition that is pre-loaded in memory, and
* save it to |out_pointer|. The preloaded partition is expected to be
* |num_bytes|, where the actual preloaded byte count is returned in
* |out_num_bytes_preloaded|. |out_num_bytes_preloaded| must be no larger than
* |num_bytes|.
*
* This provides an alternative way to access a partition that is preloaded
* into memory without a full memory copy. When this function pointer is not
* set (has value NULL), or when the |out_pointer| is set to NULL as a result,
* |read_from_partition| will be used as the fallback. This function is mainly
* used for accessing the entire partition content to calculate its hash.
*
* Preloaded partition data must outlive the lifespan of the
* |AvbSlotVerifyData| structure that |avb_slot_verify| outputs.
*/
AvbIOResult (*get_preloaded_partition)(AvbOps* ops,
const char* partition,
size_t num_bytes,
uint8_t** out_pointer,
size_t* out_num_bytes_preloaded);

/* Writes |num_bytes| from |bffer| at offset |offset| to partition
* with name |partition| (NUL-terminated UTF-8 string). If |offset|
* is negative, its absolute value should be interpreted as the
* number of bytes from the end of the partition.
*
* This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
* there is no partition with the given name,
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
* byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO
* if there was an I/O error from the underlying I/O subsystem. If
* the operation succeeds as requested AVB_IO_RESULT_OK is
* returned.
*
* This function never does any partial I/O, it either transfers all
* of the requested bytes or returns an error.
*/
AvbIOResult (*write_to_partition)(AvbOps* ops,
const char* partition,
int64_t offset,
size_t num_bytes,
const void* buffer);

/* Checks if the given public key used to sign the 'vbmeta'
* partition is trusted. Boot loaders typically compare this with
* embedded key material generated with 'avbtool
* extract_public_key'.
*
* The public key is in the array pointed to by |public_key_data|
* and is of |public_key_length| bytes.
*
* If there is no public key metadata (set with the avbtool option
* --public_key_metadata) then |public_key_metadata| will be set to
* NULL. Otherwise this field points to the data which is
* |public_key_metadata_length| bytes long.
*
* If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
* true if trusted or false if untrusted.
*/
AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
const uint8_t* public_key_data,
size_t public_key_length,
const uint8_t* public_key_metadata,
size_t public_key_metadata_length,
bool* out_is_trusted);

/* Gets the rollback index corresponding to the location given by
* |rollback_index_location|. The value is returned in
* |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback
* index was retrieved, otherwise an error code.
*
* A device may have a limited amount of rollback index locations (say,
* one or four) so may error out if |rollback_index_location| exceeds
* this number.
*/
AvbIOResult (*read_rollback_index)(AvbOps* ops,
size_t rollback_index_location,
uint64_t* out_rollback_index);

/* Sets the rollback index corresponding to the location given by
* |rollback_index_location| to |rollback_index|. Returns
* AVB_IO_RESULT_OK if the rollback index was set, otherwise an
* error code.
*
* A device may have a limited amount of rollback index locations (say,
* one or four) so may error out if |rollback_index_location| exceeds
* this number.
*/
AvbIOResult (*write_rollback_index)(AvbOps* ops,
size_t rollback_index_location,
uint64_t rollback_index);

/* Gets whether the device is unlocked. The value is returned in
* |out_is_unlocked| (true if unlocked, false otherwise). Returns
* AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
* code.
*/
AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);

/* Gets the unique partition GUID for a partition with name in
* |partition| (NUL-terminated UTF-8 string). The GUID is copied as
* a string into |guid_buf| of size |guid_buf_size| and will be NUL
* terminated. The string must be lower-case and properly
* hyphenated. For example:
*
* 527c1c6d-6361-4593-8842-3c78fcd39219
*
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
*/
AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops,
const char* partition,
char* guid_buf,
size_t guid_buf_size);

/* Gets the size of a partition with the name in |partition|
* (NUL-terminated UTF-8 string). Returns the value in
* |out_size_num_bytes|.
*
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
*/
AvbIOResult (*get_size_of_partition)(AvbOps* ops,
const char* partition,
uint64_t* out_size_num_bytes);

/* Reads a persistent value corresponding to the given |name|. The value is
* returned in |out_buffer| which must point to |buffer_size| bytes. On
* success |out_num_bytes_read| contains the number of bytes read into
* |out_buffer|. If AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned,
* |out_num_bytes_read| contains the number of bytes that would have been read
* which can be used to allocate a buffer.
*
* The |buffer_size| may be zero and the |out_buffer| may be NULL, but if
* |out_buffer| is NULL then |buffer_size| *must* be zero.
*
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
*
* If the value does not exist, is not supported, or is not populated, returns
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If |buffer_size| is smaller than the
* size of the stored value, returns AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE.
*
* This operation is currently only used to support persistent digests. If a
* device does not use persistent digests this function pointer can be set to
* NULL.
*/
AvbIOResult (*read_persistent_value)(AvbOps* ops,
const char* name,
size_t buffer_size,
uint8_t* out_buffer,
size_t* out_num_bytes_read);

/* Writes a persistent value corresponding to the given |name|. The value is