Squashed commit of the following:
1. libsparse: update form AOSP * commit a386482f1d2e29e893a59289f71ccdc715472514 | Author: Woody Lin <woodylin@google.com> | Date: Wed May 13 20:50:54 2020 +0800 | | libsparse: Limit block size to 64 MB ... | Change-Id: Ic4edb963a3d99f718d7630aba3f351729a84e994 2. mkbootfs: update from AOSP * commit 6ad4d0a601485475645ddd1b23181a4c31754977 | Author: Tom Cherry <tomcherry@google.com> | Date: Wed Mar 4 13:35:28 2020 -0800 | | Remove EXCLUDE_FS_CONFIG_STRUCTURES ... | Change-Id: I5ba2541cd1045c22486140649c90db39163081fd 2.1 mkbootfs: add mkbootfs for (Android <= 10) and (Android 11) 3. avb: update from 1.1 to 1.2 libavb and avbtool * commit 23dbe6ec9b8734aea9812e1ecd3af47e88d6360a | Author: Thiébaud Weksteen <tweek@google.com> | Date: Fri May 15 15:52:02 2020 +0200 | | Enable Android.bp format validation hook | ... | Change-Id: I3496b43093aa7f7633ca64e587e128c45b534601pull/41/head
parent
716e8363ff
commit
125418c99d
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,20 @@
|
||||
apply plugin: "c"
|
||||
apply plugin: "cpp"
|
||||
|
||||
model {
|
||||
buildTypes {
|
||||
release
|
||||
}
|
||||
|
||||
components {
|
||||
avb(NativeLibrarySpec) {
|
||||
binaries.all {
|
||||
cCompiler.define "_FILE_OFFSET_BITS", "64"
|
||||
cCompiler.define "_POSIX_C_SOURCE", "199309L"
|
||||
cCompiler.define "AVB_ENABLE_DEBUG"
|
||||
cCompiler.define "AVB_COMPILATION"
|
||||
cCompiler.args << "-Wall" << "-g"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
@ -0,0 +1,450 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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];
|
||||
|
||||
/* Don't attempt to query the partition guid unless its search string is
|
||||
* present in the command line. Note: the original cmdline is used here,
|
||||
* not the replaced one. See b/116010959.
|
||||
*/
|
||||
if (avb_strstr(cmdline, replace_str[n]) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* It's possible there is no _PARTUUID for replacement above.
|
||||
* Duplicate cmdline to ret for additional substitutions below.
|
||||
*/
|
||||
if (ret == NULL) {
|
||||
ret = avb_strdup(cmdline);
|
||||
if (ret == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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 = avb_uint64_to_base10(major_version, major_digits);
|
||||
num_minor_digits = avb_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];
|
||||
avb_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,
|
||||
AvbSlotVerifyFlags flags,
|
||||
AvbSlotVerifyData* slot_data,
|
||||
AvbVBMetaImageHeader* toplevel_vbmeta,
|
||||
AvbAlgorithmType algorithm_type,
|
||||
AvbHashtreeErrorMode hashtree_error_mode,
|
||||
AvbHashtreeErrorMode resolved_hashtree_error_mode) {
|
||||
AvbSlotVerifyResult ret;
|
||||
const char* verity_mode;
|
||||
bool is_device_unlocked;
|
||||
AvbIOResult io_ret;
|
||||
|
||||
/* Add androidboot.vbmeta.device option... except if not using a vbmeta
|
||||
* partition since it doesn't make sense in that case.
|
||||
*/
|
||||
if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
|
||||
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 (resolved_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;
|
||||
case AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO:
|
||||
// Should never get here because MANAGED_RESTART_AND_EIO is
|
||||
// remapped by avb_manage_hashtree_error_mode().
|
||||
avb_assert_not_reached();
|
||||
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;
|
||||
}
|
||||
if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
|
||||
if (!cmdline_append_option(
|
||||
slot_data, "androidboot.veritymode.managed", "yes")) {
|
||||
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;
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*-
|
||||
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
|
||||
* code or tables extracted from it, as desired without restriction.
|
||||
*/
|
||||
|
||||
/*
|
||||
* First, the polynomial itself and its table of feedback terms. The
|
||||
* polynomial is
|
||||
* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
|
||||
*
|
||||
* Note that we take it "backwards" and put the highest-order term in
|
||||
* the lowest-order bit. The X^32 term is "implied"; the LSB is the
|
||||
* X^31 term, etc. The X^0 term (usually shown as "+1") results in
|
||||
* the MSB being 1
|
||||
*
|
||||
* Note that the usual hardware shift register implementation, which
|
||||
* is what we're using (we're merely optimizing it by doing eight-bit
|
||||
* chunks at a time) shifts bits into the lowest-order term. In our
|
||||
* implementation, that means shifting towards the right. Why do we
|
||||
* do it this way? Because the calculated CRC must be transmitted in
|
||||
* order from highest-order term to lowest-order term. UARTs transmit
|
||||
* characters in order from LSB to MSB. By storing the CRC this way
|
||||
* we hand it to the UART in the order low-byte to high-byte; the UART
|
||||
* sends each low-bit to hight-bit; and the result is transmission bit
|
||||
* by bit from highest- to lowest-order term without requiring any bit
|
||||
* shuffling on our part. Reception works similarly
|
||||
*
|
||||
* The feedback terms table consists of 256, 32-bit entries. Notes
|
||||
*
|
||||
* The table can be generated at runtime if desired; code to do so
|
||||
* is shown later. It might not be obvious, but the feedback
|
||||
* terms simply represent the results of eight shift/xor opera
|
||||
* tions for all combinations of data and CRC register values
|
||||
*
|
||||
* The values must be right-shifted by eight bits by the "updcrc
|
||||
* logic; the shift must be unsigned (bring in zeroes). On some
|
||||
* hardware you could probably optimize the shift in assembler by
|
||||
* using byte-swap instructions
|
||||
* polynomial $edb88320
|
||||
*
|
||||
*
|
||||
* CRC32 code derived from work by Gary S. Brown.
|
||||
*/
|
||||
|
||||
#include "avb_sysdeps.h"
|
||||
#include "avb_util.h"
|
||||
|
||||
/* Code taken from FreeBSD 8 */
|
||||
|
||||
static uint32_t iavb_crc32_tab[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
|
||||
|
||||
/*
|
||||
* A function that calculates the CRC-32 based on the table above is
|
||||
* given below for documentation purposes. An equivalent implementation
|
||||
* of this function that's actually used in the kernel can be found
|
||||
* in sys/libkern.h, where it can be inlined.
|
||||
*/
|
||||
|
||||
static uint32_t iavb_crc32(uint32_t crc_in, const uint8_t* buf, int size) {
|
||||
const uint8_t* p = buf;
|
||||
uint32_t crc;
|
||||
|
||||
crc = crc_in ^ ~0U;
|
||||
while (size--)
|
||||
crc = iavb_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
return crc ^ ~0U;
|
||||
}
|
||||
|
||||
uint32_t avb_crc32(const uint8_t* buf, size_t size) {
|
||||
return iavb_crc32(0, buf, size);
|
||||
}
|
@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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 = 0;
|
||||
if (!avb_safe_add(&nb_total, sizeof(AvbDescriptor), nb_following)) {
|
||||
avb_error("Invalid descriptor length.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!avb_safe_add_to((uint64_t*)(&p), nb_total)) {
|
||||
avb_error("Invalid descriptor length.\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "avb_property_descriptor.h"
|
||||
#include "avb_util.h"
|
||||
|
||||
bool avb_property_descriptor_validate_and_byteswap(
|
||||
const AvbPropertyDescriptor* src, AvbPropertyDescriptor* dest) {
|
||||
uint64_t expected_size;
|
||||
|
||||
avb_memcpy(dest, src, sizeof(AvbPropertyDescriptor));
|
||||
|
||||
if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
|
||||
(AvbDescriptor*)dest))
|
||||
return false;
|
||||
|
||||
if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
|
||||
avb_error("Invalid tag for property descriptor.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->key_num_bytes = avb_be64toh(dest->key_num_bytes);
|
||||
dest->value_num_bytes = avb_be64toh(dest->value_num_bytes);
|
||||
|
||||
/* Check that key and value are fully contained. */
|
||||
expected_size = sizeof(AvbPropertyDescriptor) - sizeof(AvbDescriptor) + 2;
|
||||
if (!avb_safe_add_to(&expected_size, dest->key_num_bytes) ||
|
||||
!avb_safe_add_to(&expected_size, dest->value_num_bytes)) {
|
||||
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;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char* key;
|
||||
size_t key_size;
|
||||
const char* ret_value;
|
||||
size_t ret_value_size;
|
||||
} PropertyIteratorData;
|
||||
|
||||
static bool property_lookup_desc_foreach(const AvbDescriptor* header,
|
||||
void* user_data) {
|
||||
PropertyIteratorData* data = (PropertyIteratorData*)user_data;
|
||||
AvbPropertyDescriptor prop_desc;
|
||||
const uint8_t* p;
|
||||
bool ret = true;
|
||||
|
||||
if (header->tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!avb_property_descriptor_validate_and_byteswap(
|
||||
(const AvbPropertyDescriptor*)header, &prop_desc)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
p = (const uint8_t*)header;
|
||||
if (p[sizeof(AvbPropertyDescriptor) + prop_desc.key_num_bytes] != 0) {
|
||||
avb_error("No terminating NUL byte in key.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (data->key_size == prop_desc.key_num_bytes) {
|
||||
if (avb_memcmp(p + sizeof(AvbPropertyDescriptor),
|
||||
data->key,
|
||||
data->key_size) == 0) {
|
||||
data->ret_value = (const char*)(p + sizeof(AvbPropertyDescriptor) +
|
||||
prop_desc.key_num_bytes + 1);
|
||||
data->ret_value_size = prop_desc.value_num_bytes;
|
||||
/* Stop iterating. */
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* avb_property_lookup(const uint8_t* image_data,
|
||||
size_t image_size,
|
||||
const char* key,
|
||||
size_t key_size,
|
||||
size_t* out_value_size) {
|
||||
PropertyIteratorData data;
|
||||
|
||||
if (key_size == 0) {
|
||||
key_size = avb_strlen(key);
|
||||
}
|
||||
|
||||
data.key = key;
|
||||
data.key_size = key_size;
|
||||
|
||||
if (avb_descriptor_foreach(
|
||||
image_data, image_size, property_lookup_desc_foreach, &data) == 0) {
|
||||
if (out_value_size != NULL) {
|
||||
*out_value_size = data.ret_value_size;
|
||||
}
|
||||
return data.ret_value;
|
||||
}
|
||||
|
||||
if (out_value_size != NULL) {
|
||||
*out_value_size = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool avb_property_lookup_uint64(const uint8_t* image_data,
|
||||
size_t image_size,
|
||||
const char* key,
|
||||
size_t key_size,
|
||||
uint64_t* out_value) {
|
||||
const char* value;
|
||||
bool ret = false;
|
||||
uint64_t parsed_val;
|
||||
int base;
|
||||
int n;
|
||||
|
||||
value = avb_property_lookup(image_data, image_size, key, key_size, NULL);
|
||||
if (value == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
base = 10;
|
||||
if (avb_memcmp(value, "0x", 2) == 0) {
|
||||
base = 16;
|
||||
value += 2;
|
||||
}
|
||||
|
||||
parsed_val = 0;
|
||||
for (n = 0; value[n] != '\0'; n++) {
|
||||
int c = value[n];
|
||||
int digit;
|
||||
|
||||
parsed_val *= base;
|
||||
|
||||
if (c >= '0' && c <= '9') {
|
||||
digit = c - '0';
|
||||
} else if (base == 16 && c >= 'a' && c <= 'f') {
|
||||
digit = c - 'a' + 10;
|
||||
} else if (base == 16 && c >= 'A' && c <= 'F') {
|
||||
digit = c - 'A' + 10;
|
||||
} else {
|
||||
avb_error("Invalid digit.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
parsed_val += digit;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
if (out_value != NULL) {
|
||||
*out_value = parsed_val;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Implementation of RSA signature verification which uses a pre-processed
|
||||
* key for computation. The code extends libmincrypt RSA verification code to
|
||||
* support multiple RSA key lengths and hash digest algorithms.
|
||||
*/
|
||||
|
||||
#include "avb_rsa.h"
|
||||
#include "avb_sha.h"
|
||||
#include "avb_util.h"
|
||||
#include "avb_vbmeta_image.h"
|
||||
|
||||
typedef struct IAvbKey {
|
||||
unsigned int len; /* Length of n[] in number of uint32_t */
|
||||
uint32_t n0inv; /* -1 / n[0] mod 2^32 */
|
||||
uint32_t* n; /* modulus as array (host-byte order) */
|
||||
uint32_t* rr; /* R^2 as array (host-byte order) */
|
||||
} IAvbKey;
|
||||
|
||||
static IAvbKey* iavb_parse_key_data(const uint8_t* data, size_t length) {
|
||||
AvbRSAPublicKeyHeader h;
|
||||
IAvbKey* key = NULL;
|
||||
size_t expected_length;
|
||||
unsigned int i;
|
||||
const uint8_t* n;
|
||||
const uint8_t* rr;
|
||||
|
||||
if (!avb_rsa_public_key_header_validate_and_byteswap(
|
||||
(const AvbRSAPublicKeyHeader*)data, &h)) {
|
||||
avb_error("Invalid key.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(h.key_num_bits == 2048 || h.key_num_bits == 4096 ||
|
||||
h.key_num_bits == 8192)) {
|
||||
avb_error("Unexpected key length.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
expected_length = sizeof(AvbRSAPublicKeyHeader) + 2 * h.key_num_bits / 8;
|
||||
if (length != expected_length) {
|
||||
avb_error("Key does not match expected length.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
n = data + sizeof(AvbRSAPublicKeyHeader);
|
||||
rr = data + sizeof(AvbRSAPublicKeyHeader) + h.key_num_bits / 8;
|
||||
|
||||
/* Store n and rr following the key header so we only have to do one
|
||||
* allocation.
|
||||
*/
|
||||
key = (IAvbKey*)(avb_malloc(sizeof(IAvbKey) + 2 * h.key_num_bits / 8));
|
||||
if (key == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
key->len = h.key_num_bits / 32;
|
||||
key->n0inv = h.n0inv;
|
||||
key->n = (uint32_t*)(key + 1); /* Skip ahead sizeof(IAvbKey) bytes. */
|
||||
key->rr = key->n + key->len;
|
||||
|
||||
/* Crypto-code below (modpowF4() and friends) expects the key in
|
||||
* little-endian format (rather than the format we're storing the
|
||||
* key in), so convert it.
|
||||
*/
|
||||
for (i = 0; i < key->len; i++) {
|
||||
key->n[i] = avb_be32toh(((uint32_t*)n)[key->len - i - 1]);
|
||||
key->rr[i] = avb_be32toh(((uint32_t*)rr)[key->len - i - 1]);
|
||||
}
|
||||
return key;
|
||||
|
||||
fail:
|
||||
if (key != NULL) {
|
||||
avb_free(key);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void iavb_free_parsed_key(IAvbKey* key) {
|
||||
avb_free(key);
|
||||
}
|
||||
|
||||
/* a[] -= mod */
|
||||
static void subM(const IAvbKey* key, uint32_t* a) {
|
||||
int64_t A = 0;
|
||||
uint32_t i;
|
||||
for (i = 0; i < key->len; ++i) {
|
||||
A += (uint64_t)a[i] - key->n[i];
|
||||
a[i] = (uint32_t)A;
|
||||
A >>= 32;
|
||||
}
|
||||
}
|
||||
|
||||
/* return a[] >= mod */
|
||||
static int geM(const IAvbKey* key, uint32_t* a) {
|
||||
uint32_t i;
|
||||
for (i = key->len; i;) {
|
||||
--i;
|
||||
if (a[i] < key->n[i]) {
|
||||
return 0;
|
||||
}
|
||||
if (a[i] > key->n[i]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 1; /* equal */
|
||||
}
|
||||
|
||||
/* montgomery c[] += a * b[] / R % mod */
|
||||
static void montMulAdd(const IAvbKey* key,
|
||||
uint32_t* c,
|
||||
const uint32_t a,
|
||||
const uint32_t* b) {
|
||||
uint64_t A = (uint64_t)a * b[0] + c[0];
|
||||
uint32_t d0 = (uint32_t)A * key->n0inv;
|
||||
uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 1; i < key->len; ++i) {
|
||||
A = (A >> 32) + (uint64_t)a * b[i] + c[i];
|
||||
B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
|
||||
c[i - 1] = (uint32_t)B;
|
||||
}
|
||||
|
||||
A = (A >> 32) + (B >> 32);
|
||||
|
||||
c[i - 1] = (uint32_t)A;
|
||||
|
||||
if (A >> 32) {
|
||||
subM(key, c);
|
||||
}
|
||||
}
|
||||
|
||||
/* montgomery c[] = a[] * b[] / R % mod */
|
||||
static void montMul(const IAvbKey* key, uint32_t* c, uint32_t* a, uint32_t* b) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < key->len; ++i) {
|
||||
c[i] = 0;
|
||||
}
|
||||
for (i = 0; i < key->len; ++i) {
|
||||
montMulAdd(key, c, a[i], b);
|
||||
}
|
||||
}
|
||||
|
||||
/* In-place public exponentiation. (65537}
|
||||
* Input and output big-endian byte array in inout.
|
||||
*/
|
||||
static void modpowF4(const IAvbKey* key, uint8_t* inout) {
|
||||
uint32_t* a = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
|
||||
uint32_t* aR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
|
||||
uint32_t* aaR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
|
||||
if (a == NULL || aR == NULL || aaR == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
uint32_t* aaa = aaR; /* Re-use location. */
|
||||
int i;
|
||||
|
||||
/* Convert from big endian byte array to little endian word array. */
|
||||
for (i = 0; i < (int)key->len; ++i) {
|
||||
uint32_t tmp = (inout[((key->len - 1 - i) * 4) + 0] << 24) |
|
||||
(inout[((key->len - 1 - i) * 4) + 1] << 16) |
|
||||
(inout[((key->len - 1 - i) * 4) + 2] << 8) |
|
||||
(inout[((key->len - 1 - i) * 4) + 3] << 0);
|
||||
a[i] = tmp;
|
||||
}
|
||||
|
||||
montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
|
||||
for (i = 0; i < 16; i += 2) {
|
||||
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
|
||||
montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */
|
||||
}
|
||||
montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */
|
||||
|
||||
/* Make sure aaa < mod; aaa is at most 1x mod too large. */
|
||||
if (geM(key, aaa)) {
|
||||
subM(key, aaa);
|
||||
}
|
||||
|
||||
/* Convert to bigendian byte array */
|
||||
for (i = (int)key->len - 1; i >= 0; --i) {
|
||||
uint32_t tmp = aaa[i];
|
||||
*inout++ = (uint8_t)(tmp >> 24);
|
||||
*inout++ = (uint8_t)(tmp >> 16);
|
||||
*inout++ = (uint8_t)(tmp >> 8);
|
||||
*inout++ = (uint8_t)(tmp >> 0);
|
||||
}
|
||||
|
||||
out:
|
||||
if (a != NULL) {
|
||||
avb_free(a);
|
||||
}
|
||||
if (aR != NULL) {
|
||||
avb_free(aR);
|
||||
}
|
||||
if (aaR != NULL) {
|
||||
avb_free(aaR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify a RSA PKCS1.5 signature against an expected hash.
|
||||
* Returns false on failure, true on success.
|
||||
*/
|
||||
bool avb_rsa_verify(const uint8_t* key,
|
||||
size_t key_num_bytes,
|
||||
const uint8_t* sig,
|
||||
size_t sig_num_bytes,
|
||||
const uint8_t* hash,
|
||||
size_t hash_num_bytes,
|
||||
const uint8_t* padding,
|
||||
size_t padding_num_bytes) {
|
||||
uint8_t* buf = NULL;
|
||||
IAvbKey* parsed_key = NULL;
|
||||
bool success = false;
|
||||
|
||||
if (key == NULL || sig == NULL || hash == NULL || padding == NULL) {
|
||||
avb_error("Invalid input.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
parsed_key = iavb_parse_key_data(key, key_num_bytes);
|
||||
if (parsed_key == NULL) {
|
||||
avb_error("Error parsing key.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sig_num_bytes != (parsed_key->len * sizeof(uint32_t))) {
|
||||
avb_error("Signature length does not match key length.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (padding_num_bytes != sig_num_bytes - hash_num_bytes) {
|
||||
avb_error("Padding length does not match hash and signature lengths.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf = (uint8_t*)avb_malloc(sig_num_bytes);
|
||||
if (buf == NULL) {
|
||||
avb_error("Error allocating memory.\n");
|
||||
goto out;
|
||||
}
|
||||
avb_memcpy(buf, sig, sig_num_bytes);
|
||||
|
||||
modpowF4(parsed_key, buf);
|
||||
|
||||
/* Check padding bytes.
|
||||
*
|
||||
* Even though there are probably no timing issues here, we use
|
||||
* avb_safe_memcmp() just to be on the safe side.
|
||||
*/
|
||||
if (avb_safe_memcmp(buf, padding, padding_num_bytes)) {
|
||||
avb_error("Padding check failed.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check hash. */
|
||||
if (avb_safe_memcmp(buf + padding_num_bytes, hash, hash_num_bytes)) {
|
||||
avb_error("Hash check failed.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
success = true;
|
||||
|
||||
out:
|
||||
if (parsed_key != NULL) {
|
||||
iavb_free_parsed_key(parsed_key);
|
||||
}
|
||||
if (buf != NULL) {
|
||||
avb_free(buf);
|
||||
}
|
||||
return success;
|
||||
}
|
@ -0,0 +1,402 @@
|
||||
/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
|
||||
* <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||
* Last update: 02/02/2007
|
||||
* Issue date: 04/30/2005
|
||||
*
|
||||
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "avb_sha.h"
|
||||
|
||||
#define SHFR(x, n) (x >> n)
|
||||
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
|
||||
#define CH(x, y, z) ((x & y) ^ (~x & z))
|
||||
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||
|
||||
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
|
||||
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
|
||||
|
||||
#define UNPACK32(x, str) \
|
||||
{ \
|
||||
*((str) + 3) = (uint8_t)((x)); \
|
||||
*((str) + 2) = (uint8_t)((x) >> 8); \
|
||||
*((str) + 1) = (uint8_t)((x) >> 16); \
|
||||
*((str) + 0) = (uint8_t)((x) >> 24); \
|
||||
}
|
||||
|
||||
#define UNPACK64(x, str) \
|
||||
{ \
|
||||
*((str) + 7) = (uint8_t)x; \
|
||||
*((str) + 6) = (uint8_t)((uint64_t)x >> 8); \
|
||||
*((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
|
||||
*((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
|
||||
*((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
|
||||
*((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
|
||||
*((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
|
||||
*((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
|
||||
}
|
||||
|
||||
#define PACK32(str, x) \
|
||||
{ \
|
||||
*(x) = ((uint32_t) * ((str) + 3)) | ((uint32_t) * ((str) + 2) << 8) | \
|
||||
((uint32_t) * ((str) + 1) << 16) | \
|
||||
((uint32_t) * ((str) + 0) << 24); \
|
||||
}
|
||||
|
||||
/* Macros used for loops unrolling */
|
||||
|
||||
#define SHA256_SCR(i) \
|
||||
{ w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16]; }
|
||||
|
||||
#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
|
||||
{ \
|
||||
t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha256_k[j] + \
|
||||
w[j]; \
|
||||
t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||
wv[d] += t1; \
|
||||
wv[h] = t1 + t2; \
|
||||
}
|
||||
|
||||
static const uint32_t sha256_h0[8] = {0x6a09e667,
|
||||
0xbb67ae85,
|
||||
0x3c6ef372,
|
||||
0xa54ff53a,
|
||||
0x510e527f,
|
||||
0x9b05688c,
|
||||
0x1f83d9ab,
|
||||
0x5be0cd19};
|
||||
|
||||
static const uint32_t sha256_k[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
||||
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
||||
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
||||
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
||||
|
||||
/* SHA-256 implementation */
|
||||
void avb_sha256_init(AvbSHA256Ctx* ctx) {
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha256_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha256_h0[0];
|
||||
ctx->h[1] = sha256_h0[1];
|
||||
ctx->h[2] = sha256_h0[2];
|
||||
ctx->h[3] = sha256_h0[3];
|
||||
ctx->h[4] = sha256_h0[4];
|
||||
ctx->h[5] = sha256_h0[5];
|
||||
ctx->h[6] = sha256_h0[6];
|
||||
ctx->h[7] = sha256_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
static void SHA256_transform(AvbSHA256Ctx* ctx,
|
||||
const uint8_t* message,
|
||||
size_t block_nb) {
|
||||
uint32_t w[64];
|
||||
uint32_t wv[8];
|
||||
uint32_t t1, t2;
|
||||
const unsigned char* sub_block;
|
||||
size_t i;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
size_t j;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < block_nb; i++) {
|
||||
sub_block = message + (i << 6);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (j = 0; j < 16; j++) {
|
||||
PACK32(&sub_block[j << 2], &w[j]);
|
||||
}
|
||||
|
||||
for (j = 16; j < 64; j++) {
|
||||
SHA256_SCR(j);
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
wv[j] = ctx->h[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 64; j++) {
|
||||
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] +
|
||||
w[j];
|
||||
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||
wv[7] = wv[6];
|
||||
wv[6] = wv[5];
|
||||
wv[5] = wv[4];
|
||||
wv[4] = wv[3] + t1;
|
||||
wv[3] = wv[2];
|
||||
wv[2] = wv[1];
|
||||
wv[1] = wv[0];
|
||||
wv[0] = t1 + t2;
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
ctx->h[j] += wv[j];
|
||||
}
|
||||
#else
|
||||
PACK32(&sub_block[0], &w[0]);
|
||||
PACK32(&sub_block[4], &w[1]);
|
||||
PACK32(&sub_block[8], &w[2]);
|
||||
PACK32(&sub_block[12], &w[3]);
|
||||
PACK32(&sub_block[16], &w[4]);
|
||||
PACK32(&sub_block[20], &w[5]);
|
||||
PACK32(&sub_block[24], &w[6]);
|
||||
PACK32(&sub_block[28], &w[7]);
|
||||
PACK32(&sub_block[32], &w[8]);
|
||||
PACK32(&sub_block[36], &w[9]);
|
||||
PACK32(&sub_block[40], &w[10]);
|
||||
PACK32(&sub_block[44], &w[11]);
|
||||
PACK32(&sub_block[48], &w[12]);
|
||||
PACK32(&sub_block[52], &w[13]);
|
||||
PACK32(&sub_block[56], &w[14]);
|
||||
PACK32(&sub_block[60], &w[15]);
|
||||
|
||||
SHA256_SCR(16);
|
||||
SHA256_SCR(17);
|
||||
SHA256_SCR(18);
|
||||
SHA256_SCR(19);
|
||||
SHA256_SCR(20);
|
||||
SHA256_SCR(21);
|
||||
SHA256_SCR(22);
|
||||
SHA256_SCR(23);
|
||||
SHA256_SCR(24);
|
||||
SHA256_SCR(25);
|
||||
SHA256_SCR(26);
|
||||
SHA256_SCR(27);
|
||||
SHA256_SCR(28);
|
||||
SHA256_SCR(29);
|
||||
SHA256_SCR(30);
|
||||
SHA256_SCR(31);
|
||||
SHA256_SCR(32);
|
||||
SHA256_SCR(33);
|
||||
SHA256_SCR(34);
|
||||
SHA256_SCR(35);
|
||||
SHA256_SCR(36);
|
||||
SHA256_SCR(37);
|
||||
SHA256_SCR(38);
|
||||
SHA256_SCR(39);
|
||||
SHA256_SCR(40);
|
||||
SHA256_SCR(41);
|
||||
SHA256_SCR(42);
|
||||
SHA256_SCR(43);
|
||||
SHA256_SCR(44);
|
||||
SHA256_SCR(45);
|
||||
SHA256_SCR(46);
|
||||
SHA256_SCR(47);
|
||||
SHA256_SCR(48);
|
||||
SHA256_SCR(49);
|
||||
SHA256_SCR(50);
|
||||
SHA256_SCR(51);
|
||||
SHA256_SCR(52);
|
||||
SHA256_SCR(53);
|
||||
SHA256_SCR(54);
|
||||
SHA256_SCR(55);
|
||||
SHA256_SCR(56);
|
||||
SHA256_SCR(57);
|
||||
SHA256_SCR(58);
|
||||
SHA256_SCR(59);
|
||||
SHA256_SCR(60);
|
||||
SHA256_SCR(61);
|
||||
SHA256_SCR(62);
|
||||
SHA256_SCR(63);
|
||||
|
||||
wv[0] = ctx->h[0];
|
||||
wv[1] = ctx->h[1];
|
||||
wv[2] = ctx->h[2];
|
||||
wv[3] = ctx->h[3];
|
||||
wv[4] = ctx->h[4];
|
||||
wv[5] = ctx->h[5];
|
||||
wv[6] = ctx->h[6];
|
||||
wv[7] = ctx->h[7];
|
||||
|
||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0);
|
||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1);
|
||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2);
|
||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3);
|
||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4);
|
||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5);
|
||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6);
|
||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7);
|
||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9);
|
||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10);
|
||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11);
|
||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12);
|
||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13);
|
||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14);
|
||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15);
|
||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16);
|
||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17);
|
||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18);
|
||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19);
|
||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20);
|
||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21);
|
||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22);
|
||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23);
|
||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24);
|
||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25);
|
||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26);
|
||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27);
|
||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28);
|
||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29);
|
||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30);
|
||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31);
|
||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32);
|
||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33);
|
||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34);
|
||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35);
|
||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36);
|
||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37);
|
||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38);
|
||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39);
|
||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40);
|
||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41);
|
||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42);
|
||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43);
|
||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44);
|
||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45);
|
||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46);
|
||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47);
|
||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48);
|
||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49);
|
||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50);
|
||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51);
|
||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52);
|
||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53);
|
||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54);
|
||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55);
|
||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56);
|
||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57);
|
||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58);
|
||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59);
|
||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60);
|
||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 61);
|
||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 62);
|
||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 63);
|
||||
|
||||
ctx->h[0] += wv[0];
|
||||
ctx->h[1] += wv[1];
|
||||
ctx->h[2] += wv[2];
|
||||
ctx->h[3] += wv[3];
|
||||
ctx->h[4] += wv[4];
|
||||
ctx->h[5] += wv[5];
|
||||
ctx->h[6] += wv[6];
|
||||
ctx->h[7] += wv[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
}
|
||||
|
||||
void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, size_t len) {
|
||||
size_t block_nb;
|
||||
size_t new_len, rem_len, tmp_len;
|
||||
const uint8_t* shifted_data;
|
||||
|
||||
tmp_len = AVB_SHA256_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
avb_memcpy(&ctx->block[ctx->len], data, rem_len);
|
||||
|
||||
if (ctx->len + len < AVB_SHA256_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / AVB_SHA256_BLOCK_SIZE;
|
||||
|
||||
shifted_data = data + rem_len;
|
||||
|
||||
SHA256_transform(ctx, ctx->block, 1);
|
||||
SHA256_transform(ctx, shifted_data, block_nb);
|
||||
|
||||
rem_len = new_len % AVB_SHA256_BLOCK_SIZE;
|
||||
|
||||
avb_memcpy(ctx->block, &shifted_data[block_nb << 6], rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 6;
|
||||
}
|
||||
|
||||
uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) {
|
||||
size_t block_nb;
|
||||
size_t pm_len;
|
||||
uint64_t len_b;
|
||||
#ifndef UNROLL_LOOPS
|
||||
size_t i;
|
||||
#endif
|
||||
|
||||
block_nb =
|
||||
(1 + ((AVB_SHA256_BLOCK_SIZE - 9) < (ctx->len % AVB_SHA256_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 6;
|
||||
|
||||
avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK64(len_b, ctx->block + pm_len - 8);
|
||||
|
||||
SHA256_transform(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0; i < 8; i++) {
|
||||
UNPACK32(ctx->h[i], &ctx->buf[i << 2]);
|
||||
}
|
||||
#else
|
||||
UNPACK32(ctx->h[0], &ctx->buf[0]);
|
||||
UNPACK32(ctx->h[1], &ctx->buf[4]);
|
||||
UNPACK32(ctx->h[2], &ctx->buf[8]);
|
||||
UNPACK32(ctx->h[3], &ctx->buf[12]);
|
||||
UNPACK32(ctx->h[4], &ctx->buf[16]);
|
||||
UNPACK32(ctx->h[5], &ctx->buf[20]);
|
||||
UNPACK32(ctx->h[6], &ctx->buf[24]);
|
||||
UNPACK32(ctx->h[7], &ctx->buf[28]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
return ctx->buf;
|
||||
}
|
@ -0,0 +1,388 @@
|
||||
/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
|
||||
* <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||
* Last update: 02/02/2007
|
||||
* Issue date: 04/30/2005
|
||||
*
|
||||
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "avb_sha.h"
|
||||
|
||||
#define SHFR(x, n) (x >> n)
|
||||
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
|
||||
#define CH(x, y, z) ((x & y) ^ (~x & z))
|
||||
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||
|
||||
#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
|
||||
#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
|
||||
#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
|
||||
#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
|
||||
|
||||
#define UNPACK32(x, str) \
|
||||
{ \
|
||||
*((str) + 3) = (uint8_t)((x)); \
|
||||
*((str) + 2) = (uint8_t)((x) >> 8); \
|
||||
*((str) + 1) = (uint8_t)((x) >> 16); \
|
||||
*((str) + 0) = (uint8_t)((x) >> 24); \
|
||||
}
|
||||
|
||||
#define UNPACK64(x, str) \
|
||||
{ \
|
||||
*((str) + 7) = (uint8_t)x; \
|
||||
*((str) + 6) = (uint8_t)((uint64_t)x >> 8); \
|
||||
*((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
|
||||
*((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
|
||||
*((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
|
||||
*((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
|
||||
*((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
|
||||
*((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
|
||||
}
|
||||
|
||||
#define PACK64(str, x) \
|
||||
{ \
|
||||
*(x) = \
|
||||
((uint64_t) * ((str) + 7)) | ((uint64_t) * ((str) + 6) << 8) | \
|
||||
((uint64_t) * ((str) + 5) << 16) | ((uint64_t) * ((str) + 4) << 24) | \
|
||||
((uint64_t) * ((str) + 3) << 32) | ((uint64_t) * ((str) + 2) << 40) | \
|
||||
((uint64_t) * ((str) + 1) << 48) | ((uint64_t) * ((str) + 0) << 56); \
|
||||
}
|
||||
|
||||
/* Macros used for loops unrolling */
|
||||
|
||||
#define SHA512_SCR(i) \
|
||||
{ w[i] = SHA512_F4(w[i - 2]) + w[i - 7] + SHA512_F3(w[i - 15]) + w[i - 16]; }
|
||||
|
||||
#define SHA512_EXP(a, b, c, d, e, f, g, h, j) \
|
||||
{ \
|
||||
t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha512_k[j] + \
|
||||
w[j]; \
|
||||
t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||
wv[d] += t1; \
|
||||
wv[h] = t1 + t2; \
|
||||
}
|
||||
|
||||
static const uint64_t sha512_h0[8] = {0x6a09e667f3bcc908ULL,
|
||||
0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL,
|
||||
0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL,
|
||||
0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL,
|
||||
0x5be0cd19137e2179ULL};
|
||||
|
||||
static const uint64_t sha512_k[80] = {
|
||||
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
|
||||
0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
||||
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
|
||||
0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
||||
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
|
||||
0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
||||
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
|
||||
0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
||||
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
|
||||
0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
|
||||
0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
||||
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
|
||||
0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
||||
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
|
||||
0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
||||
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
|
||||
0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
||||
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
|
||||
0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
|
||||
0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
||||
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
|
||||
0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
||||
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
|
||||
0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
|
||||
|
||||
/* SHA-512 implementation */
|
||||
|
||||
void avb_sha512_init(AvbSHA512Ctx* ctx) {
|
||||
#ifdef UNROLL_LOOPS_SHA512
|
||||
ctx->h[0] = sha512_h0[0];
|
||||
ctx->h[1] = sha512_h0[1];
|
||||
ctx->h[2] = sha512_h0[2];
|
||||
ctx->h[3] = sha512_h0[3];
|
||||
ctx->h[4] = sha512_h0[4];
|
||||
ctx->h[5] = sha512_h0[5];
|
||||
ctx->h[6] = sha512_h0[6];
|
||||
ctx->h[7] = sha512_h0[7];
|
||||
#else
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
ctx->h[i] = sha512_h0[i];
|
||||
#endif /* UNROLL_LOOPS_SHA512 */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
static void SHA512_transform(AvbSHA512Ctx* ctx,
|
||||
const uint8_t* message,
|
||||
size_t block_nb) {
|
||||
uint64_t w[80];
|
||||
uint64_t wv[8];
|
||||
uint64_t t1, t2;
|
||||
const uint8_t* sub_block;
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < block_nb; i++) {
|
||||
sub_block = message + (i << 7);
|
||||
|
||||
#ifdef UNROLL_LOOPS_SHA512
|
||||
PACK64(&sub_block[0], &w[0]);
|
||||
PACK64(&sub_block[8], &w[1]);
|
||||
PACK64(&sub_block[16], &w[2]);
|
||||
PACK64(&sub_block[24], &w[3]);
|
||||
PACK64(&sub_block[32], &w[4]);
|
||||
PACK64(&sub_block[40], &w[5]);
|
||||
PACK64(&sub_block[48], &w[6]);
|
||||
PACK64(&sub_block[56], &w[7]);
|
||||
PACK64(&sub_block[64], &w[8]);
|
||||
PACK64(&sub_block[72], &w[9]);
|
||||
PACK64(&sub_block[80], &w[10]);
|
||||
PACK64(&sub_block[88], &w[11]);
|
||||
PACK64(&sub_block[96], &w[12]);
|
||||
PACK64(&sub_block[104], &w[13]);
|
||||
PACK64(&sub_block[112], &w[14]);
|
||||
PACK64(&sub_block[120], &w[15]);
|
||||
|
||||
SHA512_SCR(16);
|
||||
SHA512_SCR(17);
|
||||
SHA512_SCR(18);
|
||||
SHA512_SCR(19);
|
||||
SHA512_SCR(20);
|
||||
SHA512_SCR(21);
|
||||
SHA512_SCR(22);
|
||||
SHA512_SCR(23);
|
||||
SHA512_SCR(24);
|
||||
SHA512_SCR(25);
|
||||
SHA512_SCR(26);
|
||||
SHA512_SCR(27);
|
||||
SHA512_SCR(28);
|
||||
SHA512_SCR(29);
|
||||
SHA512_SCR(30);
|
||||
SHA512_SCR(31);
|
||||
SHA512_SCR(32);
|
||||
SHA512_SCR(33);
|
||||
SHA512_SCR(34);
|
||||
SHA512_SCR(35);
|
||||
SHA512_SCR(36);
|
||||
SHA512_SCR(37);
|
||||
SHA512_SCR(38);
|
||||
SHA512_SCR(39);
|
||||
SHA512_SCR(40);
|
||||
SHA512_SCR(41);
|
||||
SHA512_SCR(42);
|
||||
SHA512_SCR(43);
|
||||
SHA512_SCR(44);
|
||||
SHA512_SCR(45);
|
||||
SHA512_SCR(46);
|
||||
SHA512_SCR(47);
|
||||
SHA512_SCR(48);
|
||||
SHA512_SCR(49);
|
||||
SHA512_SCR(50);
|
||||
SHA512_SCR(51);
|
||||
SHA512_SCR(52);
|
||||
SHA512_SCR(53);
|
||||
SHA512_SCR(54);
|
||||
SHA512_SCR(55);
|
||||
SHA512_SCR(56);
|
||||
SHA512_SCR(57);
|
||||
SHA512_SCR(58);
|
||||
SHA512_SCR(59);
|
||||
SHA512_SCR(60);
|
||||
SHA512_SCR(61);
|
||||
SHA512_SCR(62);
|
||||
SHA512_SCR(63);
|
||||
SHA512_SCR(64);
|
||||
SHA512_SCR(65);
|
||||
SHA512_SCR(66);
|
||||
SHA512_SCR(67);
|
||||
SHA512_SCR(68);
|
||||
SHA512_SCR(69);
|
||||
SHA512_SCR(70);
|
||||
SHA512_SCR(71);
|
||||
SHA512_SCR(72);
|
||||
SHA512_SCR(73);
|
||||
SHA512_SCR(74);
|
||||
SHA512_SCR(75);
|
||||
SHA512_SCR(76);
|
||||
SHA512_SCR(77);
|
||||
SHA512_SCR(78);
|
||||
SHA512_SCR(79);
|
||||
|
||||
wv[0] = ctx->h[0];
|
||||
wv[1] = ctx->h[1];
|
||||
wv[2] = ctx->h[2];
|
||||
wv[3] = ctx->h[3];
|
||||
wv[4] = ctx->h[4];
|
||||
wv[5] = ctx->h[5];
|
||||
wv[6] = ctx->h[6];
|
||||
wv[7] = ctx->h[7];
|
||||
|
||||
j = 0;
|
||||
|
||||
do {
|
||||
SHA512_EXP(0, 1, 2, 3, 4, 5, 6, 7, j);
|
||||
j++;
|
||||
SHA512_EXP(7, 0, 1, 2, 3, 4, 5, 6, j);
|
||||
j++;
|
||||
SHA512_EXP(6, 7, 0, 1, 2, 3, 4, 5, j);
|
||||
j++;
|
||||
SHA512_EXP(5, 6, 7, 0, 1, 2, 3, 4, j);
|
||||
j++;
|
||||
SHA512_EXP(4, 5, 6, 7, 0, 1, 2, 3, j);
|
||||
j++;
|
||||
SHA512_EXP(3, 4, 5, 6, 7, 0, 1, 2, j);
|
||||
j++;
|
||||
SHA512_EXP(2, 3, 4, 5, 6, 7, 0, 1, j);
|
||||
j++;
|
||||
SHA512_EXP(1, 2, 3, 4, 5, 6, 7, 0, j);
|
||||
j++;
|
||||
} while (j < 80);
|
||||
|
||||
ctx->h[0] += wv[0];
|
||||
ctx->h[1] += wv[1];
|
||||
ctx->h[2] += wv[2];
|
||||
ctx->h[3] += wv[3];
|
||||
ctx->h[4] += wv[4];
|
||||
ctx->h[5] += wv[5];
|
||||
ctx->h[6] += wv[6];
|
||||
ctx->h[7] += wv[7];
|
||||
#else
|
||||
for (j = 0; j < 16; j++) {
|
||||
PACK64(&sub_block[j << 3], &w[j]);
|
||||
}
|
||||
|
||||
for (j = 16; j < 80; j++) {
|
||||
SHA512_SCR(j);
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
wv[j] = ctx->h[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 80; j++) {
|
||||
t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha512_k[j] +
|
||||
w[j];
|
||||
t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||
wv[7] = wv[6];
|
||||
wv[6] = wv[5];
|
||||
wv[5] = wv[4];
|
||||
wv[4] = wv[3] + t1;
|
||||
wv[3] = wv[2];
|
||||
wv[2] = wv[1];
|
||||
wv[1] = wv[0];
|
||||
wv[0] = t1 + t2;
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++)
|
||||
ctx->h[j] += wv[j];
|
||||
#endif /* UNROLL_LOOPS_SHA512 */
|
||||
}
|
||||
}
|
||||
|
||||
void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, size_t len) {
|
||||
size_t block_nb;
|
||||
size_t new_len, rem_len, tmp_len;
|
||||
const uint8_t* shifted_data;
|
||||
|
||||
tmp_len = AVB_SHA512_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
avb_memcpy(&ctx->block[ctx->len], data, rem_len);
|
||||
|
||||
if (ctx->len + len < AVB_SHA512_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / AVB_SHA512_BLOCK_SIZE;
|
||||
|
||||
shifted_data = data + rem_len;
|
||||
|
||||
SHA512_transform(ctx, ctx->block, 1);
|
||||
SHA512_transform(ctx, shifted_data, block_nb);
|
||||
|
||||
rem_len = new_len % AVB_SHA512_BLOCK_SIZE;
|
||||
|
||||
avb_memcpy(ctx->block, &shifted_data[block_nb << 7], rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 7;
|
||||
}
|
||||
|
||||
uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) {
|
||||
size_t block_nb;
|
||||
size_t pm_len;
|
||||
uint64_t len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS_SHA512
|
||||
size_t i;
|
||||
#endif
|
||||
|
||||
block_nb =
|
||||
1 + ((AVB_SHA512_BLOCK_SIZE - 17) < (ctx->len % AVB_SHA512_BLOCK_SIZE));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 7;
|
||||
|
||||
avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK64(len_b, ctx->block + pm_len - 8);
|
||||
|
||||
SHA512_transform(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifdef UNROLL_LOOPS_SHA512
|
||||
UNPACK64(ctx->h[0], &ctx->buf[0]);
|
||||
UNPACK64(ctx->h[1], &ctx->buf[8]);
|
||||
UNPACK64(ctx->h[2], &ctx->buf[16]);
|
||||
UNPACK64(ctx->h[3], &ctx->buf[24]);
|
||||
UNPACK64(ctx->h[4], &ctx->buf[32]);
|
||||
UNPACK64(ctx->h[5], &ctx->buf[40]);
|
||||
UNPACK64(ctx->h[6], &ctx->buf[48]);
|
||||
UNPACK64(ctx->h[7], &ctx->buf[56]);
|
||||
#else
|
||||
for (i = 0; i < 8; i++)
|
||||
UNPACK64(ctx->h[i], &ctx->buf[i << 3]);
|
||||
#endif /* UNROLL_LOOPS_SHA512 */
|
||||
|
||||
return ctx->buf;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <endian.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "avb_sysdeps.h"
|
||||
|
||||
int avb_memcmp(const void* src1, const void* src2, size_t n) {
|
||||
return memcmp(src1, src2, n);
|
||||
}
|
||||
|
||||
void* avb_memcpy(void* dest, const void* src, size_t n) {
|
||||
return memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void* avb_memset(void* dest, const int c, size_t n) {
|
||||
return memset(dest, c, n);
|
||||
}
|
||||
|
||||
int avb_strcmp(const char* s1, const char* s2) {
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
int avb_strncmp(const char* s1, const char* s2, size_t n) {
|
||||
return strncmp(s1, s2, n);
|
||||
}
|
||||
|
||||
size_t avb_strlen(const char* str) {
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
void avb_abort(void) {
|
||||
abort();
|
||||
}
|
||||
|
||||
void avb_print(const char* message) {
|
||||
fprintf(stderr, "%s", message);
|
||||
}
|
||||
|
||||
void avb_printv(const char* message, ...) {
|
||||
va_list ap;
|
||||
const char* m;
|
||||
|
||||
va_start(ap, message);
|
||||
for (m = message; m != NULL; m = va_arg(ap, const char*)) {
|
||||
fprintf(stderr, "%s", m);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void* avb_malloc_(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void avb_free(void* ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
uint32_t avb_div_by_10(uint64_t* dividend) {
|
||||
uint32_t rem = (uint32_t)(*dividend % 10);
|
||||
*dividend /= 10;
|
||||
return rem;
|
||||
}
|
@ -0,0 +1,474 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "avb_util.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
uint16_t avb_be16toh(uint16_t in) {
|
||||
uint8_t* d = (uint8_t*)∈
|
||||
uint16_t ret;
|
||||
ret = ((uint16_t)d[0]) << 8;
|
||||
ret |= ((uint16_t)d[1]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t avb_be32toh(uint32_t in) {
|
||||
uint8_t* d = (uint8_t*)∈
|
||||
uint32_t ret;
|
||||
ret = ((uint32_t)d[0]) << 24;
|
||||
ret |= ((uint32_t)d[1]) << 16;
|
||||
ret |= ((uint32_t)d[2]) << 8;
|
||||
ret |= ((uint32_t)d[3]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t avb_be64toh(uint64_t in) {
|
||||
uint8_t* d = (uint8_t*)∈
|
||||
uint64_t ret;
|
||||
ret = ((uint64_t)d[0]) << 56;
|
||||
ret |= ((uint64_t)d[1]) << 48;
|
||||
ret |= ((uint64_t)d[2]) << 40;
|
||||
ret |= ((uint64_t)d[3]) << 32;
|
||||
ret |= ((uint64_t)d[4]) << 24;
|
||||
ret |= ((uint64_t)d[5]) << 16;
|
||||
ret |= ((uint64_t)d[6]) << 8;
|
||||
ret |= ((uint64_t)d[7]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Converts a 16-bit unsigned integer from host to big-endian byte order. */
|
||||
uint16_t avb_htobe16(uint16_t in) {
|
||||
union {
|
||||
uint16_t word;
|
||||
uint8_t bytes[2];
|
||||
} ret;
|
||||
ret.bytes[0] = (in >> 8) & 0xff;
|
||||
ret.bytes[1] = in & 0xff;
|
||||
return ret.word;
|
||||
}
|
||||
|
||||
/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
|
||||
uint32_t avb_htobe32(uint32_t in) {
|
||||
union {
|
||||
uint32_t word;
|
||||
uint8_t bytes[4];
|
||||
} ret;
|
||||
ret.bytes[0] = (in >> 24) & 0xff;
|
||||
ret.bytes[1] = (in >> 16) & 0xff;
|
||||
ret.bytes[2] = (in >> 8) & 0xff;
|
||||
ret.bytes[3] = in & 0xff;
|
||||
return ret.word;
|
||||
}
|
||||
|
||||
/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
|
||||
uint64_t avb_htobe64(uint64_t in) {
|
||||
union {
|
||||
uint64_t word;
|
||||
uint8_t bytes[8];
|
||||
} ret;
|
||||
ret.bytes[0] = (in >> 56) & 0xff;
|
||||
ret.bytes[1] = (in >> 48) & 0xff;
|
||||
ret.bytes[2] = (in >> 40) & 0xff;
|
||||
ret.bytes[3] = (in >> 32) & 0xff;
|
||||
ret.bytes[4] = (in >> 24) & 0xff;
|
||||
ret.bytes[5] = (in >> 16) & 0xff;
|
||||
ret.bytes[6] = (in >> 8) & 0xff;
|
||||
ret.bytes[7] = in & 0xff;
|
||||
return ret.word;
|
||||
}
|
||||
|
||||
int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
|
||||
const unsigned char* us1 = s1;
|
||||
const unsigned char* us2 = s2;
|
||||
int result = 0;
|
||||
|
||||
if (0 == n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Code snippet without data-dependent branch due to Nate Lawson
|
||||
* (nate@root.org) of Root Labs.
|
||||
*/
|
||||
while (n--) {
|
||||
result |= *us1++ ^ *us2++;
|
||||
}
|
||||
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
|
||||
uint64_t original_value;
|
||||
|
||||
avb_assert(value != NULL);
|
||||
|
||||
original_value = *value;
|
||||
|
||||
*value += value_to_add;
|
||||
if (*value < original_value) {
|
||||
avb_error("Overflow when adding values.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
|
||||
uint64_t dummy;
|
||||
if (out_result == NULL) {
|
||||
out_result = &dummy;
|
||||
}
|
||||
*out_result = a;
|
||||
return avb_safe_add_to(out_result, b);
|
||||
}
|
||||
|
||||
bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
|
||||
size_t n;
|
||||
unsigned int num_cc;
|
||||
|
||||
for (n = 0, num_cc = 0; n < num_bytes; n++) {
|
||||
uint8_t c = data[n];
|
||||
|
||||
if (num_cc > 0) {
|
||||
if ((c & (0x80 | 0x40)) == 0x80) {
|
||||
/* 10xx xxxx */
|
||||
} else {
|
||||
goto fail;
|
||||
}
|
||||
num_cc--;
|
||||
} else {
|
||||
if (c < 0x80) {
|
||||
num_cc = 0;
|
||||
} else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
|
||||
/* 110x xxxx */
|
||||
num_cc = 1;
|
||||
} else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
|
||||
/* 1110 xxxx */
|
||||
num_cc = 2;
|
||||
} else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
|
||||
(0x80 | 0x40 | 0x20 | 0x10)) {
|
||||
/* 1111 0xxx */
|
||||
num_cc = 3;
|
||||
} else {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_cc != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool avb_str_concat(char* buf,
|
||||
size_t buf_size,
|
||||
const char* str1,
|
||||
size_t str1_len,
|
||||
const char* str2,
|
||||
size_t str2_len) {
|
||||
uint64_t combined_len;
|
||||
|
||||
// Doesn't make sense to pass 0 for buf_size since there's
|
||||
// no room for the terminating NUL byte.
|
||||
if (buf_size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
|
||||
avb_error("Overflow when adding string sizes.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (combined_len > buf_size - 1) {
|
||||
avb_error("Insufficient buffer space.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
avb_memcpy(buf, str1, str1_len);
|
||||
avb_memcpy(buf + str1_len, str2, str2_len);
|
||||
buf[combined_len] = '\0';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void* avb_malloc(size_t size) {
|
||||
void* ret = avb_malloc_(size);
|
||||
if (ret == NULL) {
|
||||
avb_error("Failed to allocate memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* avb_calloc(size_t size) {
|
||||
void* ret = avb_malloc(size);
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
avb_memset(ret, '\0', size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* avb_strdup(const char* str) {
|
||||
size_t len = avb_strlen(str);
|
||||
char* ret = avb_malloc(len + 1);
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
avb_memcpy(ret, str, len);
|
||||
ret[len] = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* avb_strstr(const char* haystack, const char* needle) {
|
||||
size_t n, m;
|
||||
|
||||
/* Look through |haystack| and check if the first character of
|
||||
* |needle| matches. If so, check the rest of |needle|.
|
||||
*/
|
||||
for (n = 0; haystack[n] != '\0'; n++) {
|
||||
if (haystack[n] != needle[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (m = 1;; m++) {
|
||||
if (needle[m] == '\0') {
|
||||
return haystack + n;
|
||||
}
|
||||
|
||||
if (haystack[n + m] != needle[m]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* avb_strv_find_str(const char* const* strings,
|
||||
const char* str,
|
||||
size_t str_size) {
|
||||
size_t n;
|
||||
for (n = 0; strings[n] != NULL; n++) {
|
||||
if (avb_strlen(strings[n]) == str_size &&
|
||||
avb_memcmp(strings[n], str, str_size) == 0) {
|
||||
return strings[n];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* avb_replace(const char* str, const char* search, const char* replace) {
|
||||
char* ret = NULL;
|
||||
size_t ret_len = 0;
|
||||
size_t search_len, replace_len;
|
||||
const char* str_after_last_replace;
|
||||
|
||||
search_len = avb_strlen(search);
|
||||
replace_len = avb_strlen(replace);
|
||||
|
||||
str_after_last_replace = str;
|
||||
while (*str != '\0') {
|
||||
const char* s;
|
||||
size_t num_before;
|
||||
size_t num_new;
|
||||
|
||||
s = avb_strstr(str, search);
|
||||
if (s == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
num_before = s - str;
|
||||
|
||||
if (ret == NULL) {
|
||||
num_new = num_before + replace_len + 1;
|
||||
ret = avb_malloc(num_new);
|
||||
if (ret == NULL) {
|
||||
goto out;
|
||||
}
|
||||
avb_memcpy(ret, str, num_before);
|
||||
avb_memcpy(ret + num_before, replace, replace_len);
|
||||
ret[num_new - 1] = '\0';
|
||||
ret_len = num_new - 1;
|
||||
} else {
|
||||
char* new_str;
|
||||
num_new = ret_len + num_before + replace_len + 1;
|
||||
new_str = avb_malloc(num_new);
|
||||
if (new_str == NULL) {
|
||||
goto out;
|
||||
}
|
||||
avb_memcpy(new_str, ret, ret_len);
|
||||
avb_memcpy(new_str + ret_len, str, num_before);
|
||||
avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
|
||||
new_str[num_new - 1] = '\0';
|
||||
avb_free(ret);
|
||||
ret = new_str;
|
||||
ret_len = num_new - 1;
|
||||
}
|
||||
|
||||
str = s + search_len;
|
||||
str_after_last_replace = str;
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
ret = avb_strdup(str_after_last_replace);
|
||||
if (ret == NULL) {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
size_t num_remaining = avb_strlen(str_after_last_replace);
|
||||
size_t num_new = ret_len + num_remaining + 1;
|
||||
char* new_str = avb_malloc(num_new);
|
||||
if (new_str == NULL) {
|
||||
goto out;
|
||||
}
|
||||
avb_memcpy(new_str, ret, ret_len);
|
||||
avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
|
||||
new_str[num_new - 1] = '\0';
|
||||
avb_free(ret);
|
||||
ret = new_str;
|
||||
ret_len = num_new - 1;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We only support a limited amount of strings in avb_strdupv(). */
|
||||
#define AVB_STRDUPV_MAX_NUM_STRINGS 32
|
||||
|
||||
char* avb_strdupv(const char* str, ...) {
|
||||
va_list ap;
|
||||
const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
|
||||
size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
|
||||
size_t num_strings, n;
|
||||
uint64_t total_length;
|
||||
char *ret = NULL, *dest;
|
||||
|
||||
num_strings = 0;
|
||||
total_length = 0;
|
||||
va_start(ap, str);
|
||||
do {
|
||||
size_t str_len = avb_strlen(str);
|
||||
strings[num_strings] = str;
|
||||
lengths[num_strings] = str_len;
|
||||
if (!avb_safe_add_to(&total_length, str_len)) {
|
||||
avb_fatal("Overflow while determining total length.\n");
|
||||
break;
|
||||
}
|
||||
num_strings++;
|
||||
if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
|
||||
avb_fatal("Too many strings passed.\n");
|
||||
break;
|
||||
}
|
||||
str = va_arg(ap, const char*);
|
||||
} while (str != NULL);
|
||||
va_end(ap);
|
||||
|
||||
ret = avb_malloc(total_length + 1);
|
||||
if (ret == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
dest = ret;
|
||||
for (n = 0; n < num_strings; n++) {
|
||||
avb_memcpy(dest, strings[n], lengths[n]);
|
||||
dest += lengths[n];
|
||||
}
|
||||
*dest = '\0';
|
||||
avb_assert(dest == ret + total_length);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* avb_basename(const char* str) {
|
||||
int64_t n;
|
||||
size_t len;
|
||||
|
||||
len = avb_strlen(str);
|
||||
if (len >= 2) {
|
||||
for (n = len - 2; n >= 0; n--) {
|
||||
if (str[n] == '/') {
|
||||
return str + n + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void avb_uppercase(char* str) {
|
||||
size_t i;
|
||||
for (i = 0; str[i] != '\0'; ++i) {
|
||||
if (str[i] <= 0x7A && str[i] >= 0x61) {
|
||||
str[i] -= 0x20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char* avb_bin2hex(const uint8_t* data, size_t data_len) {
|
||||
const char hex_digits[17] = "0123456789abcdef";
|
||||
char* hex_data;
|
||||
size_t n;
|
||||
|
||||
hex_data = avb_malloc(data_len * 2 + 1);
|
||||
if (hex_data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (n = 0; n < data_len; n++) {
|
||||
hex_data[n * 2] = hex_digits[data[n] >> 4];
|
||||
hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
|
||||
}
|
||||
hex_data[n * 2] = '\0';
|
||||
return hex_data;
|
||||
}
|
||||
|
||||
size_t avb_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;
|
||||
}
|
@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "avb_vbmeta_image.h"
|
||||
#include "avb_crypto.h"
|
||||
#include "avb_rsa.h"
|
||||
#include "avb_sha.h"
|
||||
#include "avb_util.h"
|
||||
#include "avb_version.h"
|
||||
|
||||
AvbVBMetaVerifyResult avb_vbmeta_image_verify(
|
||||
const uint8_t* data,
|
||||
size_t length,
|
||||
const uint8_t** out_public_key_data,
|
||||
size_t* out_public_key_length) {
|
||||
AvbVBMetaVerifyResult ret;
|
||||
AvbVBMetaImageHeader h;
|
||||
uint8_t* computed_hash;
|
||||
const AvbAlgorithmData* algorithm;
|
||||
AvbSHA256Ctx sha256_ctx;
|
||||
AvbSHA512Ctx sha512_ctx;
|
||||
const uint8_t* header_block;
|
||||
const uint8_t* authentication_block;
|
||||
const uint8_t* auxiliary_block;
|
||||
int verification_result;
|
||||
|
||||
ret = AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER;
|
||||
|
||||
if (out_public_key_data != NULL) {
|
||||
*out_public_key_data = NULL;
|
||||
}
|
||||
if (out_public_key_length != NULL) {
|
||||
*out_public_key_length = 0;
|
||||
}
|
||||
|
||||
/* Before we byteswap or compare Magic, ensure length is long enough. */
|
||||
if (length < sizeof(AvbVBMetaImageHeader)) {
|
||||
avb_error("Length is smaller than header.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure magic is correct. */
|
||||
if (avb_safe_memcmp(data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
|
||||
avb_error("Magic is incorrect.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
avb_vbmeta_image_header_to_host_byte_order((const AvbVBMetaImageHeader*)data,
|
||||
&h);
|
||||
|
||||
/* Ensure we don't attempt to access any fields if we do not meet
|
||||
* the specified minimum version of libavb.
|
||||
*/
|
||||
if ((h.required_libavb_version_major != AVB_VERSION_MAJOR) ||
|
||||
(h.required_libavb_version_minor > AVB_VERSION_MINOR)) {
|
||||
avb_error("Mismatch between image version and libavb version.\n");
|
||||
ret = AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure |release_string| ends with a NUL byte. */
|
||||
if (h.release_string[AVB_RELEASE_STRING_SIZE - 1] != '\0') {
|
||||
avb_error("Release string does not end with a NUL byte.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure inner block sizes are multiple of 64. */
|
||||
if ((h.authentication_data_block_size & 0x3f) != 0 ||
|
||||
(h.auxiliary_data_block_size & 0x3f) != 0) {
|
||||
avb_error("Block size is not a multiple of 64.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure block sizes all add up to at most |length|. */
|
||||
uint64_t block_total = sizeof(AvbVBMetaImageHeader);
|
||||
if (!avb_safe_add_to(&block_total, h.authentication_data_block_size) ||
|
||||
!avb_safe_add_to(&block_total, h.auxiliary_data_block_size)) {
|
||||
avb_error("Overflow while computing size of boot image.\n");
|
||||
goto out;
|
||||
}
|
||||
if (block_total > length) {
|
||||
avb_error("Block sizes add up to more than given length.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
uintptr_t data_ptr = (uintptr_t)data;
|
||||
/* Ensure passed in memory doesn't wrap. */
|
||||
if (!avb_safe_add(NULL, (uint64_t)data_ptr, length)) {
|
||||
avb_error("Boot image location and length mismatch.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure hash and signature are entirely in the Authentication data block. */
|
||||
uint64_t hash_end;
|
||||
if (!avb_safe_add(&hash_end, h.hash_offset, h.hash_size) ||
|
||||
hash_end > h.authentication_data_block_size) {
|
||||
avb_error("Hash is not entirely in its block.\n");
|
||||
goto out;
|
||||
}
|
||||
uint64_t signature_end;
|
||||
if (!avb_safe_add(&signature_end, h.signature_offset, h.signature_size) ||
|
||||
signature_end > h.authentication_data_block_size) {
|
||||
avb_error("Signature is not entirely in its block.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure public key is entirely in the Auxiliary data block. */
|
||||
uint64_t pubkey_end;
|
||||
if (!avb_safe_add(&pubkey_end, h.public_key_offset, h.public_key_size) ||
|
||||
pubkey_end > h.auxiliary_data_block_size) {
|
||||
avb_error("Public key is not entirely in its block.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure public key metadata (if set) is entirely in the Auxiliary
|
||||
* data block. */
|
||||
if (h.public_key_metadata_size > 0) {
|
||||
uint64_t pubkey_md_end;
|
||||
if (!avb_safe_add(&pubkey_md_end,
|
||||
h.public_key_metadata_offset,
|
||||
h.public_key_metadata_size) ||
|
||||
pubkey_md_end > h.auxiliary_data_block_size) {
|
||||
avb_error("Public key metadata is not entirely in its block.\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bail early if there's no hash or signature. */
|
||||
if (h.algorithm_type == AVB_ALGORITHM_TYPE_NONE) {
|
||||
ret = AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure algorithm field is supported. */
|
||||
algorithm = avb_get_algorithm_data(h.algorithm_type);
|
||||
if (!algorithm) {
|
||||
avb_error("Invalid or unknown algorithm.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Bail if the embedded hash size doesn't match the chosen algorithm. */
|
||||
if (h.hash_size != algorithm->hash_len) {
|
||||
avb_error("Embedded hash has wrong size.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No overflow checks needed from here-on after since all block
|
||||
* sizes and offsets have been verified above.
|
||||
*/
|
||||
|
||||
header_block = data;
|
||||
authentication_block = header_block + sizeof(AvbVBMetaImageHeader);
|
||||
auxiliary_block = authentication_block + h.authentication_data_block_size;
|
||||
|
||||
switch (h.algorithm_type) {
|
||||
/* Explicit fall-through: */
|
||||
case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
|
||||
case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
|
||||
case AVB_ALGORITHM_TYPE_SHA256_RSA8192:
|
||||
avb_sha256_init(&sha256_ctx);
|
||||
avb_sha256_update(
|
||||
&sha256_ctx, header_block, sizeof(AvbVBMetaImageHeader));
|
||||
avb_sha256_update(
|
||||
&sha256_ctx, auxiliary_block, h.auxiliary_data_block_size);
|
||||
computed_hash = avb_sha256_final(&sha256_ctx);
|
||||
break;
|
||||
/* Explicit fall-through: */
|
||||
case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
|
||||
case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
|
||||
case AVB_ALGORITHM_TYPE_SHA512_RSA8192:
|
||||
avb_sha512_init(&sha512_ctx);
|
||||
avb_sha512_update(
|
||||
&sha512_ctx, header_block, sizeof(AvbVBMetaImageHeader));
|
||||
avb_sha512_update(
|
||||
&sha512_ctx, auxiliary_block, h.auxiliary_data_block_size);
|
||||
computed_hash = avb_sha512_final(&sha512_ctx);
|
||||
break;
|
||||
default:
|
||||
avb_error("Unknown algorithm.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (avb_safe_memcmp(authentication_block + h.hash_offset,
|
||||
computed_hash,
|
||||
h.hash_size) != 0) {
|
||||
avb_error("Hash does not match!\n");
|
||||
ret = AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
verification_result =
|
||||
avb_rsa_verify(auxiliary_block + h.public_key_offset,
|
||||
h.public_key_size,
|
||||
authentication_block + h.signature_offset,
|
||||
h.signature_size,
|
||||
authentication_block + h.hash_offset,
|
||||
h.hash_size,
|
||||
algorithm->padding,
|
||||
algorithm->padding_len);
|
||||
|
||||
if (verification_result == 0) {
|
||||
ret = AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (h.public_key_size > 0) {
|
||||
if (out_public_key_data != NULL) {
|
||||
*out_public_key_data = auxiliary_block + h.public_key_offset;
|
||||
}
|
||||
if (out_public_key_length != NULL) {
|
||||
*out_public_key_length = h.public_key_size;
|
||||
}
|
||||
}
|
||||
|
||||
ret = AVB_VBMETA_VERIFY_RESULT_OK;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
|
||||
AvbVBMetaImageHeader* dest) {
|
||||
avb_memcpy(dest, src, sizeof(AvbVBMetaImageHeader));
|
||||
|
||||
dest->required_libavb_version_major =
|
||||
avb_be32toh(dest->required_libavb_version_major);
|
||||
dest->required_libavb_version_minor =
|
||||
avb_be32toh(dest->required_libavb_version_minor);
|
||||
|
||||
dest->authentication_data_block_size =
|
||||
avb_be64toh(dest->authentication_data_block_size);
|
||||
dest->auxiliary_data_block_size =
|
||||
avb_be64toh(dest->auxiliary_data_block_size);
|
||||
|
||||
dest->algorithm_type = avb_be32toh(dest->algorithm_type);
|
||||
|
||||
dest->hash_offset = avb_be64toh(dest->hash_offset);
|
||||
dest->hash_size = avb_be64toh(dest->hash_size);
|
||||
|
||||
dest->signature_offset = avb_be64toh(dest->signature_offset);
|
||||
dest->signature_size = avb_be64toh(dest->signature_size);
|
||||
|
||||
dest->public_key_offset = avb_be64toh(dest->public_key_offset);
|
||||
dest->public_key_size = avb_be64toh(dest->public_key_size);
|
||||
|
||||
dest->public_key_metadata_offset =
|
||||
avb_be64toh(dest->public_key_metadata_offset);
|
||||
dest->public_key_metadata_size = avb_be64toh(dest->public_key_metadata_size);
|
||||
|
||||
dest->descriptors_offset = avb_be64toh(dest->descriptors_offset);
|
||||
dest->descriptors_size = avb_be64toh(dest->descriptors_size);
|
||||
|
||||
dest->rollback_index = avb_be64toh(dest->rollback_index);
|
||||
dest->flags = avb_be32toh(dest->flags);
|
||||
dest->rollback_index_location = avb_be32toh(dest->rollback_index_location);
|
||||
}
|
||||
|
||||
const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) {
|
||||
const char* ret = NULL;
|
||||
|
||||
switch (result) {
|
||||
case AVB_VBMETA_VERIFY_RESULT_OK:
|
||||
ret = "OK";
|
||||
break;
|
||||
case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
|
||||
ret = "OK_NOT_SIGNED";
|
||||
break;
|
||||
case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
|
||||
ret = "INVALID_VBMETA_HEADER";
|
||||
break;
|
||||
case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
|
||||
ret = "UNSUPPORTED_VERSION";
|
||||
break;
|
||||
case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
|
||||
ret = "HASH_MISMATCH";
|
||||
break;
|
||||
case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
|
||||
ret = "SIGNATURE_MISMATCH";
|
||||
break;
|
||||
/* Do not add a 'default:' case here because of -Wswitch. */
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
avb_error("Unknown AvbVBMetaVerifyResult value.\n");
|
||||
ret = "(unknown)";
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "avb_version.h"
|
||||
|
||||
#define AVB_QUOTE(str) #str
|
||||
#define AVB_EXPAND_AND_QUOTE(str) AVB_QUOTE(str)
|
||||
|
||||
/* Keep in sync with get_release_string() in avbtool. */
|
||||
const char* avb_version_string(void) {
|
||||
return AVB_EXPAND_AND_QUOTE(AVB_VERSION_MAJOR) "." AVB_EXPAND_AND_QUOTE(
|
||||
AVB_VERSION_MINOR) "." AVB_EXPAND_AND_QUOTE(AVB_VERSION_SUB);
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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_ */
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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,
|
||||
AvbSlotVerifyFlags flags,
|
||||
AvbSlotVerifyData* slot_data,
|
||||
AvbVBMetaImageHeader* toplevel_vbmeta,
|
||||
AvbAlgorithmType algorithm_type,
|
||||
AvbHashtreeErrorMode hashtree_error_mode,
|
||||
AvbHashtreeErrorMode resolved_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
|
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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_ */
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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_ */
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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_ */
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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_ */
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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_ */
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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_ */
|
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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."
|
||||
#define AVB_NPV_MANAGED_VERITY_MODE "avb.managed_verity_mode"
|
||||
|
||||
/* 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.
|
||||
*
|
||||
* NOTE: If AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is passed to
|
||||
* avb_slot_verify() then this operation is never used. Instead, the
|
||||
* validate_public_key_for_partition() operation is used
|
||||
*/
|
||||
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|.
|
||||
*
|
||||
* If the partition doesn't exist the AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION
|
||||
* error code should be returned.
|
||||
*
|
||||
* 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 or the
|
||||
* AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO hashtree error mode. If a
|
||||
* device does not use one of these features 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
|
||||
* supplied in |value| which must point to |value_size| bytes. Any existing
|
||||
* value with the same name is overwritten. If |value_size| is zero, future
|
||||
* calls to |read_persistent_value| will return
|
||||
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE.
|
||||
*
|
||||
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
||||
*
|
||||
* If the value |name| is not supported, returns
|
||||
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If the |value_size| is not supported,
|
||||
* returns AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE.
|
||||
*
|
||||
* This operation is currently only used to support persistent digests or the
|
||||
* AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO hashtree error mode. If a
|
||||
* device does not use one of these features this function pointer can be set
|
||||
* to NULL.
|
||||
*/
|
||||
AvbIOResult (*write_persistent_value)(AvbOps* ops,
|
||||
const char* name,
|
||||
size_t value_size,
|
||||
const uint8_t* value);
|
||||
|
||||
/* Like validate_vbmeta_public_key() but for when the flag
|
||||
* AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is being used. The name of the
|
||||
* partition to get the public key for is passed in |partition_name|.
|
||||
*
|
||||
* Also returns the rollback index location to use for the partition, in
|
||||
* |out_rollback_index_location|.
|
||||
*
|
||||
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
||||
*/
|
||||
AvbIOResult (*validate_public_key_for_partition)(
|
||||
AvbOps* ops,
|
||||
const char* partition,
|
||||
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,
|
||||
uint32_t* out_rollback_index_location);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVB_OPS_H_ */
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
||||
#error "Never include this file directly, include libavb.h instead."
|
||||
#endif
|
||||
|
||||
#ifndef AVB_PROPERTY_DESCRIPTOR_H_
|
||||
#define AVB_PROPERTY_DESCRIPTOR_H_
|
||||
|
||||
#include "avb_descriptor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* A descriptor for properties (free-form key/value pairs).
|
||||
*
|
||||
* Following this struct are |key_num_bytes| bytes of key data encoded
|
||||
* as UTF-8, followed by a NUL byte, then |value_num_bytes| bytes of
|
||||
* value data, followed by a NUL byte and then enough padding to make
|
||||
* the combined size a multiple of 8.
|
||||
*/
|
||||
typedef struct AvbPropertyDescriptor {
|
||||
AvbDescriptor parent_descriptor;
|
||||
uint64_t key_num_bytes;
|
||||
uint64_t value_num_bytes;
|
||||
} AVB_ATTR_PACKED AvbPropertyDescriptor;
|
||||
|
||||
/* 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_property_descriptor_validate_and_byteswap(
|
||||
const AvbPropertyDescriptor* src,
|
||||
AvbPropertyDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Convenience function for looking up the value for a property with
|
||||
* name |key| in a vbmeta image. If |key_size| is 0, |key| must be
|
||||
* NUL-terminated.
|
||||
*
|
||||
* The |image_data| parameter must be a pointer to a vbmeta image of
|
||||
* size |image_size|.
|
||||
*
|
||||
* This function returns a pointer to the value inside the passed-in
|
||||
* image or NULL if not found. Note that the value is always
|
||||
* guaranteed to be followed by a NUL byte.
|
||||
*
|
||||
* If the value was found and |out_value_size| is not NULL, the size
|
||||
* of the value is returned there.
|
||||
*
|
||||
* This function is O(n) in number of descriptors so if you need to
|
||||
* look up a lot of values, you may want to build a more efficient
|
||||
* lookup-table by manually walking all descriptors using
|
||||
* avb_descriptor_foreach().
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
const char* avb_property_lookup(const uint8_t* image_data,
|
||||
size_t image_size,
|
||||
const char* key,
|
||||
size_t key_size,
|
||||
size_t* out_value_size)
|
||||
AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Like avb_property_lookup() but parses the intial portions of the
|
||||
* value as an unsigned 64-bit integer. Both decimal and hexadecimal
|
||||
* representations (e.g. "0x2a") are supported. Returns false on
|
||||
* failure and true on success. On success, the parsed value is
|
||||
* returned in |out_value|.
|
||||
*/
|
||||
bool avb_property_lookup_uint64(const uint8_t* image_data,
|
||||
size_t image_size,
|
||||
const char* key,
|
||||
size_t key_size,
|
||||
uint64_t* out_value)
|
||||
AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVB_PROPERTY_DESCRIPTOR_H_ */
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifdef AVB_INSIDE_LIBAVB_H
|
||||
#error "You can't include avb_rsa.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_RSA_H_
|
||||
#define AVB_RSA_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "avb_crypto.h"
|
||||
#include "avb_sysdeps.h"
|
||||
|
||||
/* Using the key given by |key|, verify a RSA signature |sig| of
|
||||
* length |sig_num_bytes| against an expected |hash| of length
|
||||
* |hash_num_bytes|. The padding to expect must be passed in using
|
||||
* |padding| of length |padding_num_bytes|.
|
||||
*
|
||||
* The data in |key| must match the format defined in
|
||||
* |AvbRSAPublicKeyHeader|, including the two large numbers
|
||||
* following. The |key_num_bytes| must be the size of the entire
|
||||
* serialized key.
|
||||
*
|
||||
* Returns false if verification fails, true otherwise.
|
||||
*/
|
||||
bool avb_rsa_verify(const uint8_t* key,
|
||||
size_t key_num_bytes,
|
||||
const uint8_t* sig,
|
||||
size_t sig_num_bytes,
|
||||
const uint8_t* hash,
|
||||
size_t hash_num_bytes,
|
||||
const uint8_t* padding,
|
||||
size_t padding_num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVB_RSA_H_ */
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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_SHA_H_
|
||||
#define AVB_SHA_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "avb_crypto.h"
|
||||
#include "avb_sysdeps.h"
|
||||
|
||||
/* Block size in bytes of a SHA-256 digest. */
|
||||
#define AVB_SHA256_BLOCK_SIZE 64
|
||||
|
||||
|
||||
/* Block size in bytes of a SHA-512 digest. */
|
||||
#define AVB_SHA512_BLOCK_SIZE 128
|
||||
|
||||
/* Data structure used for SHA-256. */
|
||||
typedef struct {
|
||||
uint32_t h[8];
|
||||
uint64_t tot_len;
|
||||
size_t len;
|
||||
uint8_t block[2 * AVB_SHA256_BLOCK_SIZE];
|
||||
uint8_t buf[AVB_SHA256_DIGEST_SIZE]; /* Used for storing the final digest. */
|
||||
} AvbSHA256Ctx;
|
||||
|
||||
/* Data structure used for SHA-512. */
|
||||
typedef struct {
|
||||
uint64_t h[8];
|
||||
uint64_t tot_len;
|
||||
size_t len;
|
||||
uint8_t block[2 * AVB_SHA512_BLOCK_SIZE];
|
||||
uint8_t buf[AVB_SHA512_DIGEST_SIZE]; /* Used for storing the final digest. */
|
||||
} AvbSHA512Ctx;
|
||||
|
||||
/* Initializes the SHA-256 context. */
|
||||
void avb_sha256_init(AvbSHA256Ctx* ctx);
|
||||
|
||||
/* Updates the SHA-256 context with |len| bytes from |data|. */
|
||||
void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, size_t len);
|
||||
|
||||
/* Returns the SHA-256 digest. */
|
||||
uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Initializes the SHA-512 context. */
|
||||
void avb_sha512_init(AvbSHA512Ctx* ctx);
|
||||
|
||||
/* Updates the SHA-512 context with |len| bytes from |data|. */
|
||||
void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, size_t len);
|
||||
|
||||
/* Returns the SHA-512 digest. */
|
||||
uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVB_SHA_H_ */
|
@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
||||
#error "Never include this file directly, include libavb.h instead."
|
||||
#endif
|
||||
|
||||
#ifndef AVB_SLOT_VERIFY_H_
|
||||
#define AVB_SLOT_VERIFY_H_
|
||||
|
||||
#include "avb_ops.h"
|
||||
#include "avb_vbmeta_image.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Return codes used in avb_slot_verify(), see that function for
|
||||
* documentation for each field.
|
||||
*
|
||||
* Use avb_slot_verify_result_to_string() to get a textual
|
||||
* representation usable for error/debug output.
|
||||
*/
|
||||
typedef enum {
|
||||
AVB_SLOT_VERIFY_RESULT_OK,
|
||||
AVB_SLOT_VERIFY_RESULT_ERROR_OOM,
|
||||
AVB_SLOT_VERIFY_RESULT_ERROR_IO,
|
||||
AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
|
||||
AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
|
||||
AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
|
||||
AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
|
||||
AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION,
|
||||
AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
|
||||
} AvbSlotVerifyResult;
|
||||
|
||||
/* Various error handling modes for when verification fails using a
|
||||
* hashtree at runtime inside the HLOS.
|
||||
*
|
||||
* AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE means that the OS
|
||||
* will invalidate the current slot and restart.
|
||||
*
|
||||
* AVB_HASHTREE_ERROR_MODE_RESTART means that the OS will restart.
|
||||
*
|
||||
* AVB_HASHTREE_ERROR_MODE_EIO means that an EIO error will be
|
||||
* returned to applications.
|
||||
*
|
||||
* AVB_HASHTREE_ERROR_MODE_LOGGING means that errors will be logged
|
||||
* and corrupt data may be returned to applications. This mode should
|
||||
* be used ONLY for diagnostics and debugging. It cannot be used
|
||||
* unless AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is also
|
||||
* used.
|
||||
*
|
||||
* AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO means that either
|
||||
* AVB_HASHTREE_ERROR_MODE_RESTART or AVB_HASHTREE_ERROR_MODE_EIO is used
|
||||
* depending on state. This mode implements a state machine whereby
|
||||
* AVB_HASHTREE_ERROR_MODE_RESTART is used by default and when
|
||||
* AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION is passed the
|
||||
* mode transitions to AVB_HASHTREE_ERROR_MODE_EIO. When a new OS has been
|
||||
* detected the device transitions back to the AVB_HASHTREE_ERROR_MODE_RESTART
|
||||
* mode. To do this persistent storage is needed - specifically this means that
|
||||
* the passed in AvbOps will need to have the read_persistent_value() and
|
||||
* write_persistent_value() operations implemented. The name of the persistent
|
||||
* value used is "avb.managed_verity_mode" and 32 bytes of storage is needed.
|
||||
*/
|
||||
typedef enum {
|
||||
AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
|
||||
AVB_HASHTREE_ERROR_MODE_RESTART,
|
||||
AVB_HASHTREE_ERROR_MODE_EIO,
|
||||
AVB_HASHTREE_ERROR_MODE_LOGGING,
|
||||
AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
|
||||
} AvbHashtreeErrorMode;
|
||||
|
||||
/* Flags that influence how avb_slot_verify() works.
|
||||
*
|
||||
* If AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is NOT set then
|
||||
* avb_slot_verify() will bail out as soon as an error is encountered
|
||||
* and |out_data| is set only if AVB_SLOT_VERIFY_RESULT_OK is
|
||||
* returned.
|
||||
*
|
||||
* Otherwise if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set
|
||||
* avb_slot_verify() will continue verification efforts and |out_data|
|
||||
* is also set if AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned. It is
|
||||
* undefined which error is returned if more than one distinct error
|
||||
* is encountered. It is guaranteed that AVB_SLOT_VERIFY_RESULT_OK is
|
||||
* returned if, and only if, there are no errors. This mode is needed
|
||||
* to boot valid but unverified slots when the device is unlocked.
|
||||
*
|
||||
* Also, if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set the
|
||||
* contents loaded from |requested_partition| will be the contents of
|
||||
* the entire partition instead of just the size specified in the hash
|
||||
* descriptor.
|
||||
*
|
||||
* The AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION flag
|
||||
* should be set if using AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
|
||||
* and the reason the boot loader is running is because the device
|
||||
* was restarted by the dm-verity driver.
|
||||
*
|
||||
* If the AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION flag is set then
|
||||
* data won't be loaded from the "vbmeta" partition and the
|
||||
* |validate_vbmeta_public_key| operation is never called. Instead, the
|
||||
* vbmeta structs in |requested_partitions| are loaded and processed and the
|
||||
* |validate_public_key_for_partition| operation is called for each of these
|
||||
* vbmeta structs. This flag is useful when booting into recovery on a device
|
||||
* not using A/B - see section "Booting into recovery" in README.md for
|
||||
* more information.
|
||||
*/
|
||||
typedef enum {
|
||||
AVB_SLOT_VERIFY_FLAGS_NONE = 0,
|
||||
AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0),
|
||||
AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION = (1 << 1),
|
||||
AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION = (1 << 2),
|
||||
} AvbSlotVerifyFlags;
|
||||
|
||||
/* Get a textual representation of |result|. */
|
||||
const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result);
|
||||
|
||||
/* Maximum number of rollback index locations supported. */
|
||||
#define AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS 32
|
||||
|
||||
/* AvbPartitionData contains data loaded from partitions when using
|
||||
* avb_slot_verify(). The |partition_name| field contains the name of
|
||||
* the partition (without A/B suffix), |data| points to the loaded
|
||||
* data which is |data_size| bytes long. If |preloaded| is set to true,
|
||||
* this structure dose not own |data|. The caller of |avb_slot_verify|
|
||||
* needs to make sure that the preloaded data outlives this
|
||||
* |AvbPartitionData| structure.
|
||||
*
|
||||
* Note that this is strictly less than the partition size - it's only
|
||||
* the image stored there, not the entire partition nor any of the
|
||||
* metadata.
|
||||
*/
|
||||
typedef struct {
|
||||
char* partition_name;
|
||||
uint8_t* data;
|
||||
size_t data_size;
|
||||
bool preloaded;
|
||||
} AvbPartitionData;
|
||||
|
||||
/* AvbVBMetaData contains a vbmeta struct loaded from a partition when
|
||||
* using avb_slot_verify(). The |partition_name| field contains the
|
||||
* name of the partition (without A/B suffix), |vbmeta_data| points to
|
||||
* the loaded data which is |vbmeta_size| bytes long.
|
||||
*
|
||||
* The |verify_result| field contains the result of
|
||||
* avb_vbmeta_image_verify() on the data. This is guaranteed to be
|
||||
* AVB_VBMETA_VERIFY_RESULT_OK for all vbmeta images if
|
||||
* avb_slot_verify() returns AVB_SLOT_VERIFY_RESULT_OK.
|
||||
*
|
||||
* You can use avb_descriptor_get_all(), avb_descriptor_foreach(), and
|
||||
* avb_vbmeta_image_header_to_host_byte_order() with this data.
|
||||
*/
|
||||
typedef struct {
|
||||
char* partition_name;
|
||||
uint8_t* vbmeta_data;
|
||||
size_t vbmeta_size;
|
||||
AvbVBMetaVerifyResult verify_result;
|
||||
} AvbVBMetaData;
|
||||
|
||||
/* AvbSlotVerifyData contains data needed to boot a particular slot
|
||||
* and is returned by avb_slot_verify() if partitions in a slot are
|
||||
* successfully verified.
|
||||
*
|
||||
* All data pointed to by this struct - including data in each item in
|
||||
* the |partitions| array - will be freed when the
|
||||
* avb_slot_verify_data_free() function is called.
|
||||
*
|
||||
* The |ab_suffix| field is the copy of the of |ab_suffix| field
|
||||
* passed to avb_slot_verify(). It is the A/B suffix of the slot. This
|
||||
* value includes the leading underscore - typical values are "" (if
|
||||
* no slots are in use), "_a" (for the first slot), and "_b" (for the
|
||||
* second slot).
|
||||
*
|
||||
* The VBMeta images that were checked are available in the
|
||||
* |vbmeta_images| field. The field |num_vbmeta_images| contains the
|
||||
* number of elements in this array. The first element -
|
||||
* vbmeta_images[0] - is guaranteed to be from the partition with the
|
||||
* top-level vbmeta struct. This is usually the "vbmeta" partition in
|
||||
* the requested slot but if there is no "vbmeta" partition it can
|
||||
* also be the "boot" partition.
|
||||
*
|
||||
* The partitions loaded and verified from from the slot are
|
||||
* accessible in the |loaded_partitions| array. The field
|
||||
* |num_loaded_partitions| contains the number of elements in this
|
||||
* array. The order of partitions in this array may not necessarily be
|
||||
* the same order as in the passed-in |requested_partitions| array.
|
||||
*
|
||||
* Rollback indexes for the verified slot are stored in the
|
||||
* |rollback_indexes| field. Note that avb_slot_verify() will NEVER
|
||||
* modify stored_rollback_index[n] locations e.g. it will never use
|
||||
* the write_rollback_index() AvbOps operation. Instead it is the job
|
||||
* of the caller of avb_slot_verify() to do this based on e.g. A/B
|
||||
* policy and other factors. See libavb_ab/avb_ab_flow.c for an
|
||||
* example of how to do this.
|
||||
*
|
||||
* The |cmdline| field is a NUL-terminated string in UTF-8 resulting
|
||||
* from concatenating all |AvbKernelCmdlineDescriptor| and then
|
||||
* performing proper substitution of the variables
|
||||
* $(ANDROID_SYSTEM_PARTUUID), $(ANDROID_BOOT_PARTUUID), and
|
||||
* $(ANDROID_VBMETA_PARTUUID) using the
|
||||
* get_unique_guid_for_partition() operation in |AvbOps|. Additionally
|
||||
* $(ANDROID_VERITY_MODE) will be replaced with the proper dm-verity
|
||||
* option depending on the value of |hashtree_error_mode|.
|
||||
*
|
||||
* Additionally, the |cmdline| field will have the following kernel
|
||||
* command-line options set (unless verification is disabled, see
|
||||
* below):
|
||||
*
|
||||
* androidboot.veritymode: This is set to 'disabled' if the
|
||||
* AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED flag is set in top-level
|
||||
* vbmeta struct. Otherwise it is set to 'enforcing' if the
|
||||
* passed-in hashtree error mode is AVB_HASHTREE_ERROR_MODE_RESTART
|
||||
* or AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 'eio' if it's
|
||||
* set to AVB_HASHTREE_ERROR_MODE_EIO, and 'logging' if it's set to
|
||||
* AVB_HASHTREE_ERROR_MODE_LOGGING.
|
||||
*
|
||||
* androidboot.veritymode.managed: This is set to 'yes' only
|
||||
* if hashtree validation isn't disabled and the passed-in hashtree
|
||||
* error mode is AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO.
|
||||
*
|
||||
* androidboot.vbmeta.invalidate_on_error: This is set to 'yes' only
|
||||
* if hashtree validation isn't disabled and the passed-in hashtree
|
||||
* error mode is AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE.
|
||||
*
|
||||
* androidboot.vbmeta.device_state: set to "locked" or "unlocked"
|
||||
* depending on the result of the result of AvbOps's
|
||||
* read_is_unlocked() function.
|
||||
*
|
||||
* androidboot.vbmeta.{hash_alg, size, digest}: Will be set to
|
||||
* the digest of all images in |vbmeta_images|.
|
||||
*
|
||||
* androidboot.vbmeta.device: This is set to the value
|
||||
* PARTUUID=$(ANDROID_VBMETA_PARTUUID) before substitution so it
|
||||
* will end up pointing to the vbmeta partition for the verified
|
||||
* slot. If there is no vbmeta partition it will point to the boot
|
||||
* partition of the verified slot. If the flag
|
||||
* AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is used, this is not
|
||||
* set.
|
||||
*
|
||||
* androidboot.vbmeta.avb_version: This is set to the decimal value
|
||||
* of AVB_VERSION_MAJOR followed by a dot followed by the decimal
|
||||
* value of AVB_VERSION_MINOR, for example "1.0" or "1.4". This
|
||||
* version number represents the vbmeta file format version
|
||||
* supported by libavb copy used in the boot loader. This is not
|
||||
* necessarily the same version number of the on-disk metadata for
|
||||
* the slot that was verified.
|
||||
*
|
||||
* Note that androidboot.slot_suffix is not set in the |cmdline| field
|
||||
* in |AvbSlotVerifyData| - you will have to set this yourself.
|
||||
*
|
||||
* If the |AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED| flag is set
|
||||
* in the top-level vbmeta struct then only the top-level vbmeta
|
||||
* struct is verified and descriptors will not processed. The return
|
||||
* value will be set accordingly (if this flag is set via 'avbctl
|
||||
* disable-verification' then the return value will be
|
||||
* |AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION|) and
|
||||
* |AvbSlotVerifyData| is returned. Additionally all partitions in the
|
||||
* |requested_partitions| are loaded and the |cmdline| field is set to
|
||||
* "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)" and the GUID for the
|
||||
* appropriate system partition is substituted in. Note that none of
|
||||
* the androidboot.* options mentioned above will be set.
|
||||
*
|
||||
* The |resolved_hashtree_error_mode| is the the value of the passed
|
||||
* avb_slot_verify()'s |hashtree_error_mode| parameter except that it never has
|
||||
* the value AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO. If this value was
|
||||
* passed in, then the restart/eio state machine is used resulting in
|
||||
* |resolved_hashtree_error_mode| being set to either
|
||||
* AVB_HASHTREE_ERROR_MODE_RESTART or AVB_HASHTREE_ERROR_MODE_EIO. If set to
|
||||
* AVB_HASHTREE_ERROR_MODE_EIO the boot loader should present a RED warning
|
||||
* screen for the user to click through before continuing to boot.
|
||||
*
|
||||
* This struct may grow in the future without it being considered an
|
||||
* ABI break.
|
||||
*/
|
||||
typedef struct {
|
||||
char* ab_suffix;
|
||||
AvbVBMetaData* vbmeta_images;
|
||||
size_t num_vbmeta_images;
|
||||
AvbPartitionData* loaded_partitions;
|
||||
size_t num_loaded_partitions;
|
||||
char* cmdline;
|
||||
uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
|
||||
AvbHashtreeErrorMode resolved_hashtree_error_mode;
|
||||
} AvbSlotVerifyData;
|
||||
|
||||
/* Calculates a digest of all vbmeta images in |data| using
|
||||
* the digest indicated by |digest_type|. Stores the result
|
||||
* in |out_digest| which must be large enough to hold a digest
|
||||
* of the requested type.
|
||||
*/
|
||||
void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
|
||||
AvbDigestType digest_type,
|
||||
uint8_t* out_digest);
|
||||
|
||||
/* Frees a |AvbSlotVerifyData| including all data it points to. */
|
||||
void avb_slot_verify_data_free(AvbSlotVerifyData* data);
|
||||
|
||||
/* Performs a full verification of the slot identified by |ab_suffix|
|
||||
* and load and verify the contents of the partitions whose name is in
|
||||
* the NULL-terminated string array |requested_partitions| (each
|
||||
* partition must use hash verification). If not using A/B, pass an
|
||||
* empty string (e.g. "", not NULL) for |ab_suffix|. This parameter
|
||||
* must include the leading underscore, for example "_a" should be
|
||||
* used to refer to the first slot.
|
||||
*
|
||||
* Typically the |requested_partitions| array only contains a single
|
||||
* item for the boot partition, 'boot'.
|
||||
*
|
||||
* Verification includes loading and verifying data from the 'vbmeta',
|
||||
* the requested hash partitions, and possibly other partitions (with
|
||||
* |ab_suffix| appended), inspecting rollback indexes, and checking if
|
||||
* the public key used to sign the data is acceptable. The functions
|
||||
* in |ops| will be used to do this.
|
||||
*
|
||||
* If |out_data| is not NULL, it will be set to a newly allocated
|
||||
* |AvbSlotVerifyData| struct containing all the data needed to
|
||||
* actually boot the slot. This data structure should be freed with
|
||||
* avb_slot_verify_data_free() when you are done with it. See below
|
||||
* for when this is returned.
|
||||
*
|
||||
* The |flags| parameter is used to influence the semantics of
|
||||
* avb_slot_verify() - for example the
|
||||
* AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag can be used to
|
||||
* ignore verification errors which is something needed in the
|
||||
* UNLOCKED state. See the AvbSlotVerifyFlags enumeration for details.
|
||||
*
|
||||
* The |hashtree_error_mode| parameter should be set to the desired error
|
||||
* handling mode. See the AvbHashtreeErrorMode enumeration for details.
|
||||
*
|
||||
* Also note that |out_data| is never set if
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_OOM, AVB_SLOT_VERIFY_RESULT_ERROR_IO,
|
||||
* or AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned.
|
||||
*
|
||||
* AVB_SLOT_VERIFY_RESULT_OK is returned if everything is verified
|
||||
* correctly and all public keys are accepted.
|
||||
*
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED is returned if
|
||||
* everything is verified correctly out but one or more public keys
|
||||
* are not accepted. This includes the case where integrity data is
|
||||
* not signed.
|
||||
*
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_OOM is returned if unable to
|
||||
* allocate memory.
|
||||
*
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_IO is returned if an I/O error
|
||||
* occurred while trying to load data or get a rollback index.
|
||||
*
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION is returned if the data
|
||||
* did not verify, e.g. the digest didn't match or signature checks
|
||||
* failed.
|
||||
*
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned if a
|
||||
* rollback index was less than its stored value.
|
||||
*
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned if some
|
||||
* of the metadata is invalid or inconsistent.
|
||||
*
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION is returned if
|
||||
* some of the metadata requires a newer version of libavb than what
|
||||
* is in use.
|
||||
*
|
||||
* AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT is returned if the
|
||||
* caller passed invalid parameters, for example trying to use
|
||||
* AVB_HASHTREE_ERROR_MODE_LOGGING without
|
||||
* AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
|
||||
*/
|
||||
AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
|
||||
const char* const* requested_partitions,
|
||||
const char* ab_suffix,
|
||||
AvbSlotVerifyFlags flags,
|
||||
AvbHashtreeErrorMode hashtree_error_mode,
|
||||
AvbSlotVerifyData** out_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVB_SLOT_VERIFY_H_ */
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
||||
#error "Never include this file directly, include libavb.h instead."
|
||||
#endif
|
||||
|
||||
#ifndef AVB_SYSDEPS_H_
|
||||
#define AVB_SYSDEPS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Change these includes to match your platform to bring in the
|
||||
* equivalent types available in a normal C runtime. At least things
|
||||
* like uint8_t, uint64_t, and bool (with |false|, |true| keywords)
|
||||
* must be present.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* If you don't have gcc or clang, these attribute macros may need to
|
||||
* be adjusted.
|
||||
*/
|
||||
#define AVB_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#define AVB_ATTR_PACKED __attribute__((packed))
|
||||
#define AVB_ATTR_NO_RETURN __attribute__((noreturn))
|
||||
#define AVB_ATTR_SENTINEL __attribute__((__sentinel__))
|
||||
|
||||
/* Size in bytes used for alignment. */
|
||||
#ifdef __LP64__
|
||||
#define AVB_ALIGNMENT_SIZE 8
|
||||
#else
|
||||
#define AVB_ALIGNMENT_SIZE 4
|
||||
#endif
|
||||
|
||||
/* Compare |n| bytes in |src1| and |src2|.
|
||||
*
|
||||
* Returns an integer less than, equal to, or greater than zero if the
|
||||
* first |n| bytes of |src1| is found, respectively, to be less than,
|
||||
* to match, or be greater than the first |n| bytes of |src2|. */
|
||||
int avb_memcmp(const void* src1,
|
||||
const void* src2,
|
||||
size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Compare two strings.
|
||||
*
|
||||
* Return an integer less than, equal to, or greater than zero if |s1|
|
||||
* is found, respectively, to be less than, to match, or be greater
|
||||
* than |s2|.
|
||||
*/
|
||||
int avb_strcmp(const char* s1, const char* s2);
|
||||
|
||||
/* Compare |n| bytes in two strings.
|
||||
*
|
||||
* Return an integer less than, equal to, or greater than zero if the
|
||||
* first |n| bytes of |s1| is found, respectively, to be less than,
|
||||
* to match, or be greater than the first |n| bytes of |s2|.
|
||||
*/
|
||||
int avb_strncmp(const char* s1, const char* s2, size_t n);
|
||||
|
||||
/* Copy |n| bytes from |src| to |dest|. */
|
||||
void* avb_memcpy(void* dest, const void* src, size_t n);
|
||||
|
||||
/* Set |n| bytes starting at |s| to |c|. Returns |dest|. */
|
||||
void* avb_memset(void* dest, const int c, size_t n);
|
||||
|
||||
/* Prints out a message. The string passed must be a NUL-terminated
|
||||
* UTF-8 string.
|
||||
*/
|
||||
void avb_print(const char* message);
|
||||
|
||||
/* Prints out a vector of strings. Each argument must point to a
|
||||
* NUL-terminated UTF-8 string and NULL should be the last argument.
|
||||
*/
|
||||
void avb_printv(const char* message, ...) AVB_ATTR_SENTINEL;
|
||||
|
||||
/* Aborts the program or reboots the device. */
|
||||
void avb_abort(void) AVB_ATTR_NO_RETURN;
|
||||
|
||||
/* Allocates |size| bytes. Returns NULL if no memory is available,
|
||||
* otherwise a pointer to the allocated memory.
|
||||
*
|
||||
* The memory is not initialized.
|
||||
*
|
||||
* The pointer returned is guaranteed to be word-aligned.
|
||||
*
|
||||
* The memory should be freed with avb_free() when you are done with it.
|
||||
*/
|
||||
void* avb_malloc_(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Frees memory previously allocated with avb_malloc(). */
|
||||
void avb_free(void* ptr);
|
||||
|
||||
/* Returns the lenght of |str|, excluding the terminating NUL-byte. */
|
||||
size_t avb_strlen(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Divide the |dividend| by 10 and saves back to the pointer. Return the
|
||||
* remainder. */
|
||||
uint32_t avb_div_by_10(uint64_t* dividend);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVB_SYSDEPS_H_ */
|
@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
||||
#error "Never include this file directly, include libavb.h instead."
|
||||
#endif
|
||||
|
||||
#ifndef AVB_UTIL_H_
|
||||
#define AVB_UTIL_H_
|
||||
|
||||
#include "avb_sysdeps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AVB_STRINGIFY(x) #x
|
||||
#define AVB_TO_STRING(x) AVB_STRINGIFY(x)
|
||||
|
||||
#ifdef AVB_ENABLE_DEBUG
|
||||
/* Aborts the program if |expr| is false.
|
||||
*
|
||||
* This has no effect unless AVB_ENABLE_DEBUG is defined.
|
||||
*/
|
||||
#define avb_assert(expr) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
avb_fatal("assert fail: " #expr "\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define avb_assert(expr)
|
||||
#endif
|
||||
|
||||
/* Aborts the program if reached.
|
||||
*
|
||||
* This has no effect unless AVB_ENABLE_DEBUG is defined.
|
||||
*/
|
||||
#ifdef AVB_ENABLE_DEBUG
|
||||
#define avb_assert_not_reached() \
|
||||
do { \
|
||||
avb_fatal("assert_not_reached()\n"); \
|
||||
} while (0)
|
||||
#else
|
||||
#define avb_assert_not_reached()
|
||||
#endif
|
||||
|
||||
/* Aborts the program if |addr| is not word-aligned.
|
||||
*
|
||||
* This has no effect unless AVB_ENABLE_DEBUG is defined.
|
||||
*/
|
||||
#define avb_assert_aligned(addr) \
|
||||
avb_assert((((uintptr_t)addr) & (AVB_ALIGNMENT_SIZE - 1)) == 0)
|
||||
|
||||
#ifdef AVB_ENABLE_DEBUG
|
||||
/* Print functions, used for diagnostics.
|
||||
*
|
||||
* These have no effect unless AVB_ENABLE_DEBUG is defined.
|
||||
*/
|
||||
#define avb_debug(message) \
|
||||
do { \
|
||||
avb_printv(avb_basename(__FILE__), \
|
||||
":", \
|
||||
AVB_TO_STRING(__LINE__), \
|
||||
": DEBUG: ", \
|
||||
message, \
|
||||
NULL); \
|
||||
} while (0)
|
||||
#define avb_debugv(message, ...) \
|
||||
do { \
|
||||
avb_printv(avb_basename(__FILE__), \
|
||||
":", \
|
||||
AVB_TO_STRING(__LINE__), \
|
||||
": DEBUG: ", \
|
||||
message, \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define avb_debug(message)
|
||||
#define avb_debugv(message, ...)
|
||||
#endif
|
||||
|
||||
/* Prints out a message. This is typically used if a runtime-error
|
||||
* occurs.
|
||||
*/
|
||||
#define avb_error(message) \
|
||||
do { \
|
||||
avb_printv(avb_basename(__FILE__), \
|
||||
":", \
|
||||
AVB_TO_STRING(__LINE__), \
|
||||
": ERROR: ", \
|
||||
message, \
|
||||
NULL); \
|
||||
} while (0)
|
||||
#define avb_errorv(message, ...) \
|
||||
do { \
|
||||
avb_printv(avb_basename(__FILE__), \
|
||||
":", \
|
||||
AVB_TO_STRING(__LINE__), \
|
||||
": ERROR: ", \
|
||||
message, \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/* Prints out a message and calls avb_abort().
|
||||
*/
|
||||
#define avb_fatal(message) \
|
||||
do { \
|
||||
avb_printv(avb_basename(__FILE__), \
|
||||
":", \
|
||||
AVB_TO_STRING(__LINE__), \
|
||||
": FATAL: ", \
|
||||
message, \
|
||||
NULL); \
|
||||
avb_abort(); \
|
||||
} while (0)
|
||||
#define avb_fatalv(message, ...) \
|
||||
do { \
|
||||
avb_printv(avb_basename(__FILE__), \
|
||||
":", \
|
||||
AVB_TO_STRING(__LINE__), \
|
||||
": FATAL: ", \
|
||||
message, \
|
||||
##__VA_ARGS__); \
|
||||
avb_abort(); \
|
||||
} while (0)
|
||||
|
||||
/* Converts a 16-bit unsigned integer from big-endian to host byte order. */
|
||||
uint16_t avb_be16toh(uint16_t in) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Converts a 32-bit unsigned integer from big-endian to host byte order. */
|
||||
uint32_t avb_be32toh(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Converts a 64-bit unsigned integer from big-endian to host byte order. */
|
||||
uint64_t avb_be64toh(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Converts a 16-bit unsigned integer from host to big-endian byte order. */
|
||||
uint16_t avb_htobe16(uint16_t in) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
|
||||
uint32_t avb_htobe32(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
|
||||
uint64_t avb_htobe64(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Compare |n| bytes starting at |s1| with |s2| and return 0 if they
|
||||
* match, 1 if they don't. Returns 0 if |n|==0, since no bytes
|
||||
* mismatched.
|
||||
*
|
||||
* Time taken to perform the comparison is only dependent on |n| and
|
||||
* not on the relationship of the match between |s1| and |s2|.
|
||||
*
|
||||
* Note that unlike avb_memcmp(), this only indicates inequality, not
|
||||
* whether |s1| is less than or greater than |s2|.
|
||||
*/
|
||||
int avb_safe_memcmp(const void* s1,
|
||||
const void* s2,
|
||||
size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Adds |value_to_add| to |value| with overflow protection.
|
||||
*
|
||||
* Returns false if the addition overflows, true otherwise. In either
|
||||
* case, |value| is always modified.
|
||||
*/
|
||||
bool avb_safe_add_to(uint64_t* value,
|
||||
uint64_t value_to_add) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Adds |a| and |b| with overflow protection, returning the value in
|
||||
* |out_result|.
|
||||
*
|
||||
* It's permissible to pass NULL for |out_result| if you just want to
|
||||
* check that the addition would not overflow.
|
||||
*
|
||||
* Returns false if the addition overflows, true otherwise.
|
||||
*/
|
||||
bool avb_safe_add(uint64_t* out_result,
|
||||
uint64_t a,
|
||||
uint64_t b) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Checks if |num_bytes| data at |data| is a valid UTF-8
|
||||
* string. Returns true if valid UTF-8, false otherwise.
|
||||
*/
|
||||
bool avb_validate_utf8(const uint8_t* data,
|
||||
size_t num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Concatenates |str1| (of |str1_len| bytes) and |str2| (of |str2_len|
|
||||
* bytes) and puts the result in |buf| which holds |buf_size|
|
||||
* bytes. The result is also guaranteed to be NUL terminated. Fail if
|
||||
* there is not enough room in |buf| for the resulting string plus
|
||||
* terminating NUL byte.
|
||||
*
|
||||
* Returns true if the operation succeeds, false otherwise.
|
||||
*/
|
||||
bool avb_str_concat(char* buf,
|
||||
size_t buf_size,
|
||||
const char* str1,
|
||||
size_t str1_len,
|
||||
const char* str2,
|
||||
size_t str2_len);
|
||||
|
||||
/* Like avb_malloc_() but prints a error using avb_error() if memory
|
||||
* allocation fails.
|
||||
*/
|
||||
void* avb_malloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Like avb_malloc() but sets the memory with zeroes. */
|
||||
void* avb_calloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Duplicates a NUL-terminated string. Returns NULL on OOM. */
|
||||
char* avb_strdup(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Duplicates a NULL-terminated array of NUL-terminated strings by
|
||||
* concatenating them. The returned string will be
|
||||
* NUL-terminated. Returns NULL on OOM.
|
||||
*/
|
||||
char* avb_strdupv(const char* str,
|
||||
...) AVB_ATTR_WARN_UNUSED_RESULT AVB_ATTR_SENTINEL;
|
||||
|
||||
/* Finds the first occurrence of |needle| in the string |haystack|
|
||||
* where both strings are NUL-terminated strings. The terminating NUL
|
||||
* bytes are not compared.
|
||||
*
|
||||
* Returns NULL if not found, otherwise points into |haystack| for the
|
||||
* first occurrence of |needle|.
|
||||
*/
|
||||
const char* avb_strstr(const char* haystack,
|
||||
const char* needle) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Finds the first occurrence of |str| in the NULL-terminated string
|
||||
* array |strings|. Each element in |strings| must be
|
||||
* NUL-terminated. The string given by |str| need not be
|
||||
* NUL-terminated but its size must be given in |str_size|.
|
||||
*
|
||||
* Returns NULL if not found, otherwise points into |strings| for the
|
||||
* first occurrence of |str|.
|
||||
*/
|
||||
const char* avb_strv_find_str(const char* const* strings,
|
||||
const char* str,
|
||||
size_t str_size);
|
||||
|
||||
/* Replaces all occurrences of |search| with |replace| in |str|.
|
||||
*
|
||||
* Returns a newly allocated string or NULL if out of memory.
|
||||
*/
|
||||
char* avb_replace(const char* str,
|
||||
const char* search,
|
||||
const char* replace) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Calculates the CRC-32 for data in |buf| of size |buf_size|. */
|
||||
uint32_t avb_crc32(const uint8_t* buf, size_t buf_size);
|
||||
|
||||
/* Returns the basename of |str|. This is defined as the last path
|
||||
* component, assuming the normal POSIX separator '/'. If there are no
|
||||
* separators, returns |str|.
|
||||
*/
|
||||
const char* avb_basename(const char* str);
|
||||
|
||||
/* Converts any ascii lowercase characters in |str| to uppercase in-place.
|
||||
* |str| must be NUL-terminated and valid UTF-8.
|
||||
*/
|
||||
void avb_uppercase(char* str);
|
||||
|
||||
/* Converts |data_len| bytes of |data| to hex and returns the result. Returns
|
||||
* NULL on OOM. Caller must free the returned string with avb_free.
|
||||
*/
|
||||
char* avb_bin2hex(const uint8_t* data, size_t data_len);
|
||||
|
||||
/* Writes |value| to |digits| in base 10 followed by a NUL byte.
|
||||
* Returns number of characters written excluding the NUL byte.
|
||||
*/
|
||||
#define AVB_MAX_DIGITS_UINT64 32
|
||||
size_t avb_uint64_to_base10(uint64_t value, char digits[AVB_MAX_DIGITS_UINT64]);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVB_UTIL_H_ */
|
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
||||
#error "Never include this file directly, include libavb.h instead."
|
||||
#endif
|
||||
|
||||
#ifndef AVB_VBMETA_IMAGE_H_
|
||||
#define AVB_VBMETA_IMAGE_H_
|
||||
|
||||
#include "avb_sysdeps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "avb_crypto.h"
|
||||
#include "avb_descriptor.h"
|
||||
|
||||
/* Size of the vbmeta image header. */
|
||||
#define AVB_VBMETA_IMAGE_HEADER_SIZE 256
|
||||
|
||||
/* Magic for the vbmeta image header. */
|
||||
#define AVB_MAGIC "AVB0"
|
||||
#define AVB_MAGIC_LEN 4
|
||||
|
||||
/* Maximum size of the release string including the terminating NUL byte. */
|
||||
#define AVB_RELEASE_STRING_SIZE 48
|
||||
|
||||
/* Flags for the vbmeta image.
|
||||
*
|
||||
* AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED: If this flag is set,
|
||||
* hashtree image verification will be disabled.
|
||||
*
|
||||
* AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: If this flag is set,
|
||||
* verification will be disabled and descriptors will not be parsed.
|
||||
*/
|
||||
typedef enum {
|
||||
AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = (1 << 0),
|
||||
AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED = (1 << 1)
|
||||
} AvbVBMetaImageFlags;
|
||||
|
||||
/* Binary format for header of the vbmeta image.
|
||||
*
|
||||
* The vbmeta image consists of three blocks:
|
||||
*
|
||||
* +-----------------------------------------+
|
||||
* | Header data - fixed size |
|
||||
* +-----------------------------------------+
|
||||
* | Authentication data - variable size |
|
||||
* +-----------------------------------------+
|
||||
* | Auxiliary data - variable size |
|
||||
* +-----------------------------------------+
|
||||
*
|
||||
* The "Header data" block is described by this struct and is always
|
||||
* |AVB_VBMETA_IMAGE_HEADER_SIZE| bytes long.
|
||||
*
|
||||
* The "Authentication data" block is |authentication_data_block_size|
|
||||
* bytes long and contains the hash and signature used to authenticate
|
||||
* the vbmeta image. The type of the hash and signature is defined by
|
||||
* the |algorithm_type| field.
|
||||
*
|
||||
* The "Auxiliary data" is |auxiliary_data_block_size| bytes long and
|
||||
* contains the auxiliary data including the public key used to make
|
||||
* the signature and descriptors.
|
||||
*
|
||||
* The public key is at offset |public_key_offset| with size
|
||||
* |public_key_size| in this block. The size of the public key data is
|
||||
* defined by the |algorithm_type| field. The format of the public key
|
||||
* data is described in the |AvbRSAPublicKeyHeader| struct.
|
||||
*
|
||||
* The descriptors starts at |descriptors_offset| from the beginning
|
||||
* of the "Auxiliary Data" block and take up |descriptors_size|
|
||||
* bytes. Each descriptor is stored as a |AvbDescriptor| with tag and
|
||||
* number of bytes following. The number of descriptors can be
|
||||
* determined by walking this data until |descriptors_size| is
|
||||
* exhausted.
|
||||
*
|
||||
* The size of each of the "Authentication data" and "Auxiliary data"
|
||||
* blocks must be divisible by 64. This is to ensure proper alignment.
|
||||
*
|
||||
* Descriptors are free-form blocks stored in a part of the vbmeta
|
||||
* image subject to the same integrity checks as the rest of the
|
||||
* image. See the documentation for |AvbDescriptor| for well-known
|
||||
* descriptors. See avb_descriptor_foreach() for a convenience
|
||||
* function to iterate over descriptors.
|
||||
*
|
||||
* This struct is versioned, see the |required_libavb_version_major|
|
||||
* and |required_libavb_version_minor| fields. This represents the
|
||||
* minimum version of libavb required to verify the header and depends
|
||||
* on the features (e.g. algorithms, descriptors) used. Note that this
|
||||
* may be 1.0 even if generated by an avbtool from 1.4 but where no
|
||||
* features introduced after 1.0 has been used. See the "Versioning
|
||||
* and compatibility" section in the README.md file for more details.
|
||||
*
|
||||
* All fields are stored in network byte order when serialized. To
|
||||
* generate a copy with fields swapped to native byte order, use the
|
||||
* function avb_vbmeta_image_header_to_host_byte_order().
|
||||
*
|
||||
* Before reading and/or using any of this data, you MUST verify it
|
||||
* using avb_vbmeta_image_verify() and reject it unless it's signed by
|
||||
* a known good public key.
|
||||
*/
|
||||
typedef struct AvbVBMetaImageHeader {
|
||||
/* 0: Four bytes equal to "AVB0" (AVB_MAGIC). */
|
||||
uint8_t magic[AVB_MAGIC_LEN];
|
||||
|
||||
/* 4: The major version of libavb required for this header. */
|
||||
uint32_t required_libavb_version_major;
|
||||
/* 8: The minor version of libavb required for this header. */
|
||||
uint32_t required_libavb_version_minor;
|
||||
|
||||
/* 12: The size of the signature block. */
|
||||
uint64_t authentication_data_block_size;
|
||||
/* 20: The size of the auxiliary data block. */
|
||||
uint64_t auxiliary_data_block_size;
|
||||
|
||||
/* 28: The verification algorithm used, see |AvbAlgorithmType| enum. */
|
||||
uint32_t algorithm_type;
|
||||
|
||||
/* 32: Offset into the "Authentication data" block of hash data. */
|
||||
uint64_t hash_offset;
|
||||
/* 40: Length of the hash data. */
|
||||
uint64_t hash_size;
|
||||
|
||||
/* 48: Offset into the "Authentication data" block of signature data. */
|
||||
uint64_t signature_offset;
|
||||
/* 56: Length of the signature data. */
|
||||
uint64_t signature_size;
|
||||
|
||||
/* 64: Offset into the "Auxiliary data" block of public key data. */
|
||||
uint64_t public_key_offset;
|
||||
/* 72: Length of the public key data. */
|
||||
uint64_t public_key_size;
|
||||
|
||||
/* 80: Offset into the "Auxiliary data" block of public key metadata. */
|
||||
uint64_t public_key_metadata_offset;
|
||||
/* 88: Length of the public key metadata. Must be set to zero if there
|
||||
* is no public key metadata.
|
||||
*/
|
||||
uint64_t public_key_metadata_size;
|
||||
|
||||
/* 96: Offset into the "Auxiliary data" block of descriptor data. */
|
||||
uint64_t descriptors_offset;
|
||||
/* 104: Length of descriptor data. */
|
||||
uint64_t descriptors_size;
|
||||
|
||||
/* 112: The rollback index which can be used to prevent rollback to
|
||||
* older versions.
|
||||
*/
|
||||
uint64_t rollback_index;
|
||||
|
||||
/* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be
|
||||
* set to zero if the vbmeta image is not a top-level image.
|
||||
*/
|
||||
uint32_t flags;
|
||||
|
||||
/* 124: The location of the rollback index defined in this header.
|
||||
* Only valid for the main vbmeta. For chained partitions, the rollback
|
||||
* index location must be specified in the AvbChainPartitionDescriptor
|
||||
* and this value must be set to 0.
|
||||
*/
|
||||
uint32_t rollback_index_location;
|
||||
|
||||
/* 128: The release string from avbtool, e.g. "avbtool 1.0.0" or
|
||||
* "avbtool 1.0.0 xyz_board Git-234abde89". Is guaranteed to be NUL
|
||||
* terminated. Applications must not make assumptions about how this
|
||||
* string is formatted.
|
||||
*/
|
||||
uint8_t release_string[AVB_RELEASE_STRING_SIZE];
|
||||
|
||||
/* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
|
||||
* bytes. This must be set to zeroes.
|
||||
*/
|
||||
uint8_t reserved[80];
|
||||
} AVB_ATTR_PACKED AvbVBMetaImageHeader;
|
||||
|
||||
/* Copies |src| to |dest|, byte-swapping fields in the process.
|
||||
*
|
||||
* Make sure you've verified |src| using avb_vbmeta_image_verify()
|
||||
* before accessing the data and/or using this function.
|
||||
*/
|
||||
void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
|
||||
AvbVBMetaImageHeader* dest);
|
||||
|
||||
/* Return codes used in avb_vbmeta_image_verify().
|
||||
*
|
||||
* AVB_VBMETA_VERIFY_RESULT_OK is returned if the vbmeta image header
|
||||
* is valid, the hash is correct and the signature is correct. Keep in
|
||||
* mind that you still need to check that you know the public key used
|
||||
* to sign the image, see avb_vbmeta_image_verify() for details.
|
||||
*
|
||||
* AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED is returned if the vbmeta
|
||||
* image header is valid but there is no signature or hash.
|
||||
*
|
||||
* AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER is returned if the
|
||||
* header of the vbmeta image is invalid, for example, invalid magic
|
||||
* or inconsistent data.
|
||||
*
|
||||
* AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION is returned if a) the
|
||||
* vbmeta image requires a minimum version of libavb which exceeds the
|
||||
* version of libavb used; or b) the vbmeta image major version
|
||||
* differs from the major version of libavb in use.
|
||||
*
|
||||
* AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH is returned if the hash
|
||||
* stored in the "Authentication data" block does not match the
|
||||
* calculated hash.
|
||||
*
|
||||
* AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH is returned if the
|
||||
* signature stored in the "Authentication data" block is invalid or
|
||||
* doesn't match the public key stored in the vbmeta image.
|
||||
*/
|
||||
typedef enum {
|
||||
AVB_VBMETA_VERIFY_RESULT_OK,
|
||||
AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED,
|
||||
AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
|
||||
AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION,
|
||||
AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH,
|
||||
AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH,
|
||||
} AvbVBMetaVerifyResult;
|
||||
|
||||
/* Get a textual representation of |result|. */
|
||||
const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result);
|
||||
|
||||
/* Checks that vbmeta image at |data| of size |length| is a valid
|
||||
* vbmeta image. The complete contents of the vbmeta image must be
|
||||
* passed in. It's fine if |length| is bigger than the actual image,
|
||||
* typically callers of this function will load the entire contents of
|
||||
* the 'vbmeta_a' or 'vbmeta_b' partition and pass in its length (for
|
||||
* example, 1 MiB).
|
||||
*
|
||||
* See the |AvbVBMetaImageHeader| struct for information about the
|
||||
* three blocks (header, authentication, auxiliary) that make up a
|
||||
* vbmeta image.
|
||||
*
|
||||
* If the function returns |AVB_VBMETA_VERIFY_RESULT_OK| and
|
||||
* |out_public_key_data| is non-NULL, it will be set to point inside
|
||||
* |data| for where the serialized public key data is stored and
|
||||
* |out_public_key_length|, if non-NULL, will be set to the length of
|
||||
* the public key data. If there is no public key in the metadata then
|
||||
* |out_public_key_data| is set to NULL.
|
||||
*
|
||||
* See the |AvbVBMetaVerifyResult| enum for possible return values.
|
||||
*
|
||||
* VERY IMPORTANT:
|
||||
*
|
||||
* 1. Even if |AVB_VBMETA_VERIFY_RESULT_OK| is returned, you still
|
||||
* need to check that the public key embedded in the image
|
||||
* matches a known key! You can use 'avbtool extract_public_key'
|
||||
* to extract the key (at build time, then store it along your
|
||||
* code) and compare it to what is returned in
|
||||
* |out_public_key_data|.
|
||||
*
|
||||
* 2. You need to check the |rollback_index| field against a stored
|
||||
* value in NVRAM and reject the vbmeta image if the value in
|
||||
* NVRAM is bigger than |rollback_index|. You must also update
|
||||
* the value stored in NVRAM to the smallest value of
|
||||
* |rollback_index| field from boot images in all bootable and
|
||||
* authentic slots marked as GOOD.
|
||||
*
|
||||
* This is a low-level function to only verify the vbmeta data - you
|
||||
* are likely looking for avb_slot_verify() instead for verifying
|
||||
* integrity data for a whole set of partitions.
|
||||
*/
|
||||
AvbVBMetaVerifyResult avb_vbmeta_image_verify(
|
||||
const uint8_t* data,
|
||||
size_t length,
|
||||
const uint8_t** out_public_key_data,
|
||||
size_t* out_public_key_length) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVB_VBMETA_IMAGE_H_ */
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
||||
#error "Never include this file directly, include libavb.h instead."
|
||||
#endif
|
||||
|
||||
#ifndef AVB_VERSION_H_
|
||||
#define AVB_VERSION_H_
|
||||
|
||||
#include "avb_sysdeps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* The version number of AVB - keep in sync with avbtool. */
|
||||
#define AVB_VERSION_MAJOR 1
|
||||
#define AVB_VERSION_MINOR 2
|
||||
#define AVB_VERSION_SUB 0
|
||||
|
||||
/* Returns a NUL-terminated string for the libavb version in use. The
|
||||
* returned string usually looks like "%d.%d.%d". Applications must
|
||||
* not make assumptions about the content of this string.
|
||||
*
|
||||
* Boot loaders should display this string in debug/diagnostics output
|
||||
* to aid with debugging.
|
||||
*
|
||||
* This is similar to the string put in the |release_string| string
|
||||
* field in the VBMeta struct by avbtool.
|
||||
*/
|
||||
const char* avb_version_string(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AVB_VERSION_H_ */
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIBAVB_H_
|
||||
#define LIBAVB_H_
|
||||
|
||||
/* The AVB_INSIDE_LIBAVB_H preprocessor symbol is used to enforce
|
||||
* library users to include only this file. All public interfaces, and
|
||||
* only public interfaces, must be included here.
|
||||
*/
|
||||
|
||||
#define AVB_INSIDE_LIBAVB_H
|
||||
#include "avb_chain_partition_descriptor.h"
|
||||
#include "avb_crypto.h"
|
||||
#include "avb_descriptor.h"
|
||||
#include "avb_footer.h"
|
||||
#include "avb_hash_descriptor.h"
|
||||
#include "avb_hashtree_descriptor.h"
|
||||
#include "avb_kernel_cmdline_descriptor.h"
|
||||
#include "avb_ops.h"
|
||||
#include "avb_property_descriptor.h"
|
||||
#include "avb_slot_verify.h"
|
||||
#include "avb_sysdeps.h"
|
||||
#include "avb_util.h"
|
||||
#include "avb_vbmeta_image.h"
|
||||
#include "avb_version.h"
|
||||
#undef AVB_INSIDE_LIBAVB_H
|
||||
|
||||
#endif /* LIBAVB_H_ */
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "android-base/mapped_file.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
static constexpr char kEmptyBuffer[] = {'0'};
|
||||
|
||||
static off64_t InitPageSize() {
|
||||
#if defined(_WIN32)
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
return si.dwAllocationGranularity;
|
||||
#else
|
||||
return sysconf(_SC_PAGE_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<MappedFile> MappedFile::FromFd(borrowed_fd fd, off64_t offset, size_t length,
|
||||
int prot) {
|
||||
#if defined(_WIN32)
|
||||
return FromOsHandle(reinterpret_cast<HANDLE>(_get_osfhandle(fd.get())), offset, length, prot);
|
||||
#else
|
||||
return FromOsHandle(fd.get(), offset, length, prot);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<MappedFile> MappedFile::FromOsHandle(os_handle h, off64_t offset, size_t length,
|
||||
int prot) {
|
||||
static const off64_t page_size = InitPageSize();
|
||||
size_t slop = offset % page_size;
|
||||
off64_t file_offset = offset - slop;
|
||||
off64_t file_length = length + slop;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE handle = CreateFileMappingW(
|
||||
h, nullptr, (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
|
||||
if (handle == nullptr) {
|
||||
// http://b/119818070 "app crashes when reading asset of zero length".
|
||||
// Return a MappedFile that's only valid for reading the size.
|
||||
if (length == 0 && ::GetLastError() == ERROR_FILE_INVALID) {
|
||||
return std::unique_ptr<MappedFile>(
|
||||
new MappedFile(const_cast<char*>(kEmptyBuffer), 0, 0, nullptr));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void* base = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ, 0,
|
||||
file_offset, file_length);
|
||||
if (base == nullptr) {
|
||||
CloseHandle(handle);
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<MappedFile>(
|
||||
new MappedFile(static_cast<char*>(base), length, slop, handle));
|
||||
#else
|
||||
void* base = mmap(nullptr, file_length, prot, MAP_SHARED, h, file_offset);
|
||||
if (base == MAP_FAILED) {
|
||||
// http://b/119818070 "app crashes when reading asset of zero length".
|
||||
// mmap fails with EINVAL for a zero length region.
|
||||
if (errno == EINVAL && length == 0) {
|
||||
return std::unique_ptr<MappedFile>(new MappedFile(const_cast<char*>(kEmptyBuffer), 0, 0));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<MappedFile>(new MappedFile(static_cast<char*>(base), length, slop));
|
||||
#endif
|
||||
}
|
||||
|
||||
MappedFile::MappedFile(MappedFile&& other)
|
||||
: base_(std::exchange(other.base_, nullptr)),
|
||||
size_(std::exchange(other.size_, 0)),
|
||||
offset_(std::exchange(other.offset_, 0))
|
||||
#ifdef _WIN32
|
||||
,
|
||||
handle_(std::exchange(other.handle_, nullptr))
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
MappedFile& MappedFile::operator=(MappedFile&& other) {
|
||||
Close();
|
||||
base_ = std::exchange(other.base_, nullptr);
|
||||
size_ = std::exchange(other.size_, 0);
|
||||
offset_ = std::exchange(other.offset_, 0);
|
||||
#ifdef _WIN32
|
||||
handle_ = std::exchange(other.handle_, nullptr);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
MappedFile::~MappedFile() {
|
||||
Close();
|
||||
}
|
||||
|
||||
void MappedFile::Close() {
|
||||
#if defined(_WIN32)
|
||||
if (base_ != nullptr && size_ != 0) UnmapViewOfFile(base_);
|
||||
if (handle_ != nullptr) CloseHandle(handle_);
|
||||
handle_ = nullptr;
|
||||
#else
|
||||
if (base_ != nullptr && size_ != 0) munmap(base_, size_ + offset_);
|
||||
#endif
|
||||
|
||||
base_ = nullptr;
|
||||
offset_ = size_ = 0;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <unistd.h> // for TEMP_FAILURE_RETRY
|
||||
|
||||
#include <utility>
|
||||
|
||||
// bionic and glibc both have TEMP_FAILURE_RETRY, but eg Mac OS' libc doesn't.
|
||||
#ifndef TEMP_FAILURE_RETRY
|
||||
#define TEMP_FAILURE_RETRY(exp) \
|
||||
({ \
|
||||
decltype(exp) _rc; \
|
||||
do { \
|
||||
_rc = (exp); \
|
||||
} while (_rc == -1 && errno == EINTR); \
|
||||
_rc; \
|
||||
})
|
||||
#endif
|
||||
|
||||
// A macro to disallow the copy constructor and operator= functions
|
||||
// This must be placed in the private: declarations for a class.
|
||||
//
|
||||
// For disallowing only assign or copy, delete the relevant operator or
|
||||
// constructor, for example:
|
||||
// void operator=(const TypeName&) = delete;
|
||||
// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
|
||||
// semantically, one should either use disallow both or neither. Try to
|
||||
// avoid these in new code.
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&) = delete; \
|
||||
void operator=(const TypeName&) = delete
|
||||
|
||||
// A macro to disallow all the implicit constructors, namely the
|
||||
// default constructor, copy constructor and operator= functions.
|
||||
//
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName() = delete; \
|
||||
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
|
||||
// The arraysize(arr) macro returns the # of elements in an array arr.
|
||||
// The expression is a compile-time constant, and therefore can be
|
||||
// used in defining new arrays, for example. If you use arraysize on
|
||||
// a pointer by mistake, you will get a compile-time error.
|
||||
//
|
||||
// One caveat is that arraysize() doesn't accept any array of an
|
||||
// anonymous type or a type defined inside a function. In these rare
|
||||
// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is
|
||||
// due to a limitation in C++'s template system. The limitation might
|
||||
// eventually be removed, but it hasn't happened yet.
|
||||
|
||||
// This template function declaration is used in defining arraysize.
|
||||
// Note that the function doesn't need an implementation, as we only
|
||||
// use its type.
|
||||
template <typename T, size_t N>
|
||||
char(&ArraySizeHelper(T(&array)[N]))[N]; // NOLINT(readability/casting)
|
||||
|
||||
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
||||
|
||||
#define SIZEOF_MEMBER(t, f) sizeof(std::declval<t>().f)
|
||||
|
||||
// Changing this definition will cause you a lot of pain. A majority of
|
||||
// vendor code defines LIKELY and UNLIKELY this way, and includes
|
||||
// this header through an indirect path.
|
||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
|
||||
#define WARN_UNUSED __attribute__((warn_unused_result))
|
||||
|
||||
// A deprecated function to call to create a false use of the parameter, for
|
||||
// example:
|
||||
// int foo(int x) { UNUSED(x); return 10; }
|
||||
// to avoid compiler warnings. Going forward we prefer ATTRIBUTE_UNUSED.
|
||||
template <typename... T>
|
||||
void UNUSED(const T&...) {
|
||||
}
|
||||
|
||||
// An attribute to place on a parameter to a function, for example:
|
||||
// int foo(int x ATTRIBUTE_UNUSED) { return 10; }
|
||||
// to avoid compiler warnings.
|
||||
#define ATTRIBUTE_UNUSED __attribute__((__unused__))
|
||||
|
||||
// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
|
||||
// between switch labels:
|
||||
// switch (x) {
|
||||
// case 40:
|
||||
// case 41:
|
||||
// if (truth_is_out_there) {
|
||||
// ++x;
|
||||
// FALLTHROUGH_INTENDED; // Use instead of/along with annotations in
|
||||
// // comments.
|
||||
// } else {
|
||||
// return x;
|
||||
// }
|
||||
// case 42:
|
||||
// ...
|
||||
//
|
||||
// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
|
||||
// followed by a semicolon. It is designed to mimic control-flow statements
|
||||
// like 'break;', so it can be placed in most places where 'break;' can, but
|
||||
// only if there are no statements on the execution path between it and the
|
||||
// next switch label.
|
||||
//
|
||||
// When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
|
||||
// [[clang::fallthrough]] attribute, which is analysed when performing switch
|
||||
// labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
|
||||
// documentation on language extensions for details:
|
||||
// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
|
||||
//
|
||||
// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
|
||||
// effect on diagnostics.
|
||||
//
|
||||
// In either case this macro has no effect on runtime behavior and performance
|
||||
// of code.
|
||||
#ifndef FALLTHROUGH_INTENDED
|
||||
#define FALLTHROUGH_INTENDED [[clang::fallthrough]] // NOLINT
|
||||
#endif
|
||||
|
||||
// Current ABI string
|
||||
#if defined(__arm__)
|
||||
#define ABI_STRING "arm"
|
||||
#elif defined(__aarch64__)
|
||||
#define ABI_STRING "arm64"
|
||||
#elif defined(__i386__)
|
||||
#define ABI_STRING "x86"
|
||||
#elif defined(__x86_64__)
|
||||
#define ABI_STRING "x86_64"
|
||||
#endif
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "android-base/macros.h"
|
||||
#include "android-base/off64_t.h"
|
||||
#include "android-base/unique_fd.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
using os_handle = HANDLE;
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
using os_handle = int;
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
/**
|
||||
* A region of a file mapped into memory (for grepping: also known as MmapFile or file mapping).
|
||||
*/
|
||||
class MappedFile {
|
||||
public:
|
||||
/**
|
||||
* Creates a new mapping of the file pointed to by `fd`. Unlike the underlying OS primitives,
|
||||
* `offset` does not need to be page-aligned. If `PROT_WRITE` is set in `prot`, the mapping
|
||||
* will be writable, otherwise it will be read-only. Mappings are always `MAP_SHARED`.
|
||||
*/
|
||||
static std::unique_ptr<MappedFile> FromFd(borrowed_fd fd, off64_t offset, size_t length,
|
||||
int prot);
|
||||
|
||||
/**
|
||||
* Same thing, but using the raw OS file handle instead of a CRT wrapper.
|
||||
*/
|
||||
static std::unique_ptr<MappedFile> FromOsHandle(os_handle h, off64_t offset, size_t length,
|
||||
int prot);
|
||||
|
||||
/**
|
||||
* Removes the mapping.
|
||||
*/
|
||||
~MappedFile();
|
||||
|
||||
/**
|
||||
* Not copyable but movable.
|
||||
*/
|
||||
MappedFile(MappedFile&& other);
|
||||
MappedFile& operator=(MappedFile&& other);
|
||||
|
||||
char* data() const { return base_ + offset_; }
|
||||
size_t size() const { return size_; }
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(MappedFile);
|
||||
|
||||
void Close();
|
||||
|
||||
char* base_;
|
||||
size_t size_;
|
||||
|
||||
size_t offset_;
|
||||
|
||||
#if defined(_WIN32)
|
||||
MappedFile(char* base, size_t size, size_t offset, HANDLE handle)
|
||||
: base_(base), size_(size), offset_(offset), handle_(handle) {}
|
||||
HANDLE handle_;
|
||||
#else
|
||||
MappedFile(char* base, size_t size, size_t offset) : base_(base), size_(size), offset_(offset) {}
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(__APPLE__)
|
||||
/** Mac OS has always had a 64-bit off_t, so it doesn't have off64_t. */
|
||||
typedef off_t off64_t;
|
||||
#endif
|
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// DO NOT INCLUDE OTHER LIBBASE HEADERS!
|
||||
// This file gets used in libbinder, and libbinder is used everywhere.
|
||||
// Including other headers from libbase frequently results in inclusion of
|
||||
// android-base/macros.h, which causes macro collisions.
|
||||
|
||||
// Container for a file descriptor that automatically closes the descriptor as
|
||||
// it goes out of scope.
|
||||
//
|
||||
// unique_fd ufd(open("/some/path", "r"));
|
||||
// if (ufd.get() == -1) return error;
|
||||
//
|
||||
// // Do something useful, possibly including 'return'.
|
||||
//
|
||||
// return 0; // Descriptor is closed for you.
|
||||
//
|
||||
// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
|
||||
// you find this class if you're searching for one of those names.
|
||||
|
||||
#if defined(__BIONIC__)
|
||||
#include <android/fdsan.h>
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
struct DefaultCloser {
|
||||
#if defined(__BIONIC__)
|
||||
static void Tag(int fd, void* old_addr, void* new_addr) {
|
||||
if (android_fdsan_exchange_owner_tag) {
|
||||
uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
|
||||
reinterpret_cast<uint64_t>(old_addr));
|
||||
uint64_t new_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
|
||||
reinterpret_cast<uint64_t>(new_addr));
|
||||
android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
|
||||
}
|
||||
}
|
||||
static void Close(int fd, void* addr) {
|
||||
if (android_fdsan_close_with_tag) {
|
||||
uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
|
||||
reinterpret_cast<uint64_t>(addr));
|
||||
android_fdsan_close_with_tag(fd, tag);
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void Close(int fd) {
|
||||
// Even if close(2) fails with EINTR, the fd will have been closed.
|
||||
// Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
|
||||
// else's fd.
|
||||
// http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
|
||||
::close(fd);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename Closer>
|
||||
class unique_fd_impl final {
|
||||
public:
|
||||
unique_fd_impl() {}
|
||||
|
||||
explicit unique_fd_impl(int fd) { reset(fd); }
|
||||
~unique_fd_impl() { reset(); }
|
||||
|
||||
unique_fd_impl(const unique_fd_impl&) = delete;
|
||||
void operator=(const unique_fd_impl&) = delete;
|
||||
unique_fd_impl(unique_fd_impl&& other) noexcept { reset(other.release()); }
|
||||
unique_fd_impl& operator=(unique_fd_impl&& s) noexcept {
|
||||
int fd = s.fd_;
|
||||
s.fd_ = -1;
|
||||
reset(fd, &s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[clang::reinitializes]] void reset(int new_value = -1) { reset(new_value, nullptr); }
|
||||
|
||||
int get() const { return fd_; }
|
||||
|
||||
#if !defined(ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION)
|
||||
// unique_fd's operator int is dangerous, but we have way too much code that
|
||||
// depends on it, so make this opt-in at first.
|
||||
operator int() const { return get(); } // NOLINT
|
||||
#endif
|
||||
|
||||
bool operator>=(int rhs) const { return get() >= rhs; }
|
||||
bool operator<(int rhs) const { return get() < rhs; }
|
||||
bool operator==(int rhs) const { return get() == rhs; }
|
||||
bool operator!=(int rhs) const { return get() != rhs; }
|
||||
bool operator==(const unique_fd_impl& rhs) const { return get() == rhs.get(); }
|
||||
bool operator!=(const unique_fd_impl& rhs) const { return get() != rhs.get(); }
|
||||
|
||||
// Catch bogus error checks (i.e.: "!fd" instead of "fd != -1").
|
||||
bool operator!() const = delete;
|
||||
|
||||
bool ok() const { return get() >= 0; }
|
||||
|
||||
int release() __attribute__((warn_unused_result)) {
|
||||
tag(fd_, this, nullptr);
|
||||
int ret = fd_;
|
||||
fd_ = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
void reset(int new_value, void* previous_tag) {
|
||||
int previous_errno = errno;
|
||||
|
||||
if (fd_ != -1) {
|
||||
close(fd_, this);
|
||||
}
|
||||
|
||||
fd_ = new_value;
|
||||
if (new_value != -1) {
|
||||
tag(new_value, previous_tag, this);
|
||||
}
|
||||
|
||||
errno = previous_errno;
|
||||
}
|
||||
|
||||
int fd_ = -1;
|
||||
|
||||
// Template magic to use Closer::Tag if available, and do nothing if not.
|
||||
// If Closer::Tag exists, this implementation is preferred, because int is a better match.
|
||||
// If not, this implementation is SFINAEd away, and the no-op below is the only one that exists.
|
||||
template <typename T = Closer>
|
||||
static auto tag(int fd, void* old_tag, void* new_tag)
|
||||
-> decltype(T::Tag(fd, old_tag, new_tag), void()) {
|
||||
T::Tag(fd, old_tag, new_tag);
|
||||
}
|
||||
|
||||
template <typename T = Closer>
|
||||
static void tag(long, void*, void*) {
|
||||
// No-op.
|
||||
}
|
||||
|
||||
// Same as above, to select between Closer::Close(int) and Closer::Close(int, void*).
|
||||
template <typename T = Closer>
|
||||
static auto close(int fd, void* tag_value) -> decltype(T::Close(fd, tag_value), void()) {
|
||||
T::Close(fd, tag_value);
|
||||
}
|
||||
|
||||
template <typename T = Closer>
|
||||
static auto close(int fd, void*) -> decltype(T::Close(fd), void()) {
|
||||
T::Close(fd);
|
||||
}
|
||||
};
|
||||
|
||||
using unique_fd = unique_fd_impl<DefaultCloser>;
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
// Inline functions, so that they can be used header-only.
|
||||
template <typename Closer>
|
||||
inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write,
|
||||
int flags = O_CLOEXEC) {
|
||||
int pipefd[2];
|
||||
|
||||
#if defined(__linux__)
|
||||
if (pipe2(pipefd, flags) != 0) {
|
||||
return false;
|
||||
}
|
||||
#else // defined(__APPLE__)
|
||||
if (flags & ~(O_CLOEXEC | O_NONBLOCK)) {
|
||||
return false;
|
||||
}
|
||||
if (pipe(pipefd) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flags & O_CLOEXEC) {
|
||||
if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (flags & O_NONBLOCK) {
|
||||
if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) != 0 || fcntl(pipefd[1], F_SETFL, O_NONBLOCK) != 0) {
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
read->reset(pipefd[0]);
|
||||
write->reset(pipefd[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Closer>
|
||||
inline bool Socketpair(int domain, int type, int protocol, unique_fd_impl<Closer>* left,
|
||||
unique_fd_impl<Closer>* right) {
|
||||
int sockfd[2];
|
||||
if (socketpair(domain, type, protocol, sockfd) != 0) {
|
||||
return false;
|
||||
}
|
||||
left->reset(sockfd[0]);
|
||||
right->reset(sockfd[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Closer>
|
||||
inline bool Socketpair(int type, unique_fd_impl<Closer>* left, unique_fd_impl<Closer>* right) {
|
||||
return Socketpair(AF_UNIX, type, 0, left, right);
|
||||
}
|
||||
|
||||
// Using fdopen with unique_fd correctly is more annoying than it should be,
|
||||
// because fdopen doesn't close the file descriptor received upon failure.
|
||||
inline FILE* Fdopen(unique_fd&& ufd, const char* mode) {
|
||||
int fd = ufd.release();
|
||||
FILE* file = fdopen(fd, mode);
|
||||
if (!file) {
|
||||
close(fd);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
// Using fdopendir with unique_fd correctly is more annoying than it should be,
|
||||
// because fdopen doesn't close the file descriptor received upon failure.
|
||||
inline DIR* Fdopendir(unique_fd&& ufd) {
|
||||
int fd = ufd.release();
|
||||
DIR* dir = fdopendir(fd);
|
||||
if (dir == nullptr) {
|
||||
close(fd);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
// A wrapper type that can be implicitly constructed from either int or unique_fd.
|
||||
struct borrowed_fd {
|
||||
/* implicit */ borrowed_fd(int fd) : fd_(fd) {} // NOLINT
|
||||
template <typename T>
|
||||
/* implicit */ borrowed_fd(const unique_fd_impl<T>& ufd) : fd_(ufd.get()) {} // NOLINT
|
||||
|
||||
int get() const { return fd_; }
|
||||
|
||||
bool operator>=(int rhs) const { return get() >= rhs; }
|
||||
bool operator<(int rhs) const { return get() < rhs; }
|
||||
bool operator==(int rhs) const { return get() == rhs; }
|
||||
bool operator!=(int rhs) const { return get() != rhs; }
|
||||
|
||||
private:
|
||||
int fd_ = -1;
|
||||
};
|
||||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
template <typename T>
|
||||
int close(const android::base::unique_fd_impl<T>&)
|
||||
__attribute__((__unavailable__("close called on unique_fd")));
|
||||
|
||||
template <typename T>
|
||||
FILE* fdopen(const android::base::unique_fd_impl<T>&, const char* mode)
|
||||
__attribute__((__unavailable__("fdopen takes ownership of the fd passed in; either dup the "
|
||||
"unique_fd, or use android::base::Fdopen to pass ownership")));
|
||||
|
||||
template <typename T>
|
||||
DIR* fdopendir(const android::base::unique_fd_impl<T>&) __attribute__((
|
||||
__unavailable__("fdopendir takes ownership of the fd passed in; either dup the "
|
||||
"unique_fd, or use android::base::Fdopendir to pass ownership")));
|
@ -0,0 +1,19 @@
|
||||
apply plugin: 'cpp'
|
||||
apply plugin: 'c'
|
||||
|
||||
model {
|
||||
buildTypes {
|
||||
release
|
||||
}
|
||||
|
||||
components {
|
||||
mkbootfs(NativeExecutableSpec) {
|
||||
binaries.all {
|
||||
//cppCompiler.define "ANDROID"
|
||||
//cppCompiler.define "ANDROID", "__ANDROID_VNDK__"
|
||||
//cppCompiler.define 'CFIG_NO_FIX_STAT'
|
||||
cppCompiler.args << '-std=c++17' << "-Wno-write-strings"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,373 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <private/fs_config.h>
|
||||
|
||||
// This file is used to define the properties of the filesystem
|
||||
// images generated by build tools (mkbootfs and mkyaffs2image) and
|
||||
// by the device side of adb.
|
||||
|
||||
#define LOG_TAG "fs_config"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <android-base/strings.h>
|
||||
#include <log/log.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <utils/Compat.h>
|
||||
|
||||
#include "fs_config.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
using android::base::EndsWith;
|
||||
using android::base::StartsWith;
|
||||
|
||||
#define ALIGN(x, alignment) (((x) + ((alignment)-1)) & ~((alignment)-1))
|
||||
#define CAP_MASK_LONG(cap_name) (1ULL << (cap_name))
|
||||
|
||||
// Rules for directories.
|
||||
// These rules are applied based on "first match", so they
|
||||
// should start with the most specific path and work their
|
||||
// way up to the root.
|
||||
|
||||
static const struct fs_path_config android_dirs[] = {
|
||||
// clang-format off
|
||||
{ 00770, AID_SYSTEM, AID_CACHE, 0, "cache" },
|
||||
{ 00555, AID_ROOT, AID_ROOT, 0, "config" },
|
||||
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
|
||||
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
|
||||
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-ephemeral" },
|
||||
{ 00771, AID_ROOT, AID_ROOT, 0, "data/dalvik-cache" },
|
||||
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
|
||||
{ 00771, AID_SHELL, AID_SHELL, 0, "data/local/tmp" },
|
||||
{ 00771, AID_SHELL, AID_SHELL, 0, "data/local" },
|
||||
{ 00770, AID_DHCP, AID_DHCP, 0, "data/misc/dhcp" },
|
||||
{ 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" },
|
||||
{ 01771, AID_SYSTEM, AID_MISC, 0, "data/misc" },
|
||||
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
|
||||
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "data/benchmarktest" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "data/benchmarktest64" },
|
||||
{ 00775, AID_ROOT, AID_ROOT, 0, "data/preloads" },
|
||||
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
|
||||
{ 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" },
|
||||
{ 00751, AID_ROOT, AID_SHELL, 0, "product/bin" },
|
||||
{ 00777, AID_ROOT, AID_ROOT, 0, "sdcard" },
|
||||
{ 00751, AID_ROOT, AID_SDCARD_R, 0, "storage" },
|
||||
{ 00751, AID_ROOT, AID_SHELL, 0, "system/bin" },
|
||||
{ 00755, AID_ROOT, AID_ROOT, 0, "system/etc/ppp" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" },
|
||||
{ 00751, AID_ROOT, AID_SHELL, 0, "system/xbin" },
|
||||
{ 00751, AID_ROOT, AID_SHELL, 0, "system/apex/*/bin" },
|
||||
{ 00751, AID_ROOT, AID_SHELL, 0, "system_ext/bin" },
|
||||
{ 00751, AID_ROOT, AID_SHELL, 0, "system_ext/apex/*/bin" },
|
||||
{ 00751, AID_ROOT, AID_SHELL, 0, "vendor/bin" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor" },
|
||||
{ 00755, AID_ROOT, AID_ROOT, 0, 0 },
|
||||
// clang-format on
|
||||
};
|
||||
#ifndef __ANDROID_VNDK__
|
||||
auto __for_testing_only__android_dirs = android_dirs;
|
||||
#endif
|
||||
|
||||
// Rules for files.
|
||||
// These rules are applied based on "first match", so they
|
||||
// should start with the most specific path and work their
|
||||
// way up to the root. Prefixes ending in * denotes wildcard
|
||||
// and will allow partial matches.
|
||||
static const char sys_conf_dir[] = "/system/etc/fs_config_dirs";
|
||||
static const char sys_conf_file[] = "/system/etc/fs_config_files";
|
||||
// No restrictions are placed on the vendor and oem file-system config files,
|
||||
// although the developer is advised to restrict the scope to the /vendor or
|
||||
// oem/ file-system since the intent is to provide support for customized
|
||||
// portions of a separate vendor.img or oem.img. Has to remain open so that
|
||||
// customization can also land on /system/vendor, /system/oem, /system/odm,
|
||||
// /system/product or /system/system_ext.
|
||||
//
|
||||
// We expect build-time checking or filtering when constructing the associated
|
||||
// fs_config_* files (see build/tools/fs_config/fs_config_generate.c)
|
||||
static const char ven_conf_dir[] = "/vendor/etc/fs_config_dirs";
|
||||
static const char ven_conf_file[] = "/vendor/etc/fs_config_files";
|
||||
static const char oem_conf_dir[] = "/oem/etc/fs_config_dirs";
|
||||
static const char oem_conf_file[] = "/oem/etc/fs_config_files";
|
||||
static const char odm_conf_dir[] = "/odm/etc/fs_config_dirs";
|
||||
static const char odm_conf_file[] = "/odm/etc/fs_config_files";
|
||||
static const char product_conf_dir[] = "/product/etc/fs_config_dirs";
|
||||
static const char product_conf_file[] = "/product/etc/fs_config_files";
|
||||
static const char system_ext_conf_dir[] = "/system_ext/etc/fs_config_dirs";
|
||||
static const char system_ext_conf_file[] = "/system_ext/etc/fs_config_files";
|
||||
static const char* conf[][2] = {
|
||||
{sys_conf_file, sys_conf_dir}, {ven_conf_file, ven_conf_dir},
|
||||
{oem_conf_file, oem_conf_dir}, {odm_conf_file, odm_conf_dir},
|
||||
{product_conf_file, product_conf_dir}, {system_ext_conf_file, system_ext_conf_dir},
|
||||
};
|
||||
|
||||
// Do not use android_files to grant Linux capabilities. Use ambient capabilities in their
|
||||
// associated init.rc file instead. See https://source.android.com/devices/tech/config/ambient.
|
||||
|
||||
// Do not place any new vendor/, data/vendor/, etc entries in android_files.
|
||||
// Vendor entries should be done via a vendor or device specific config.fs.
|
||||
// See https://source.android.com/devices/tech/config/filesystem#using-file-system-capabilities
|
||||
static const struct fs_path_config android_files[] = {
|
||||
// clang-format off
|
||||
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" },
|
||||
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-ephemeral/*" },
|
||||
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" },
|
||||
{ 00644, AID_APP, AID_APP, 0, "data/data/*" },
|
||||
{ 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" },
|
||||
{ 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest/tests.txt" },
|
||||
{ 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest64/tests.txt" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest/*" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64/*" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "data/benchmarktest/*" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "data/benchmarktest64/*" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "default.prop" }, // legacy
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "system/etc/prop.default" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "odm/build.prop" }, // legacy; only for P release
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "odm/default.prop" }, // legacy; only for P release
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "odm/etc/build.prop" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, odm_conf_dir + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, odm_conf_file + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, oem_conf_dir + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, oem_conf_file + 1 },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "product/build.prop" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, product_conf_dir + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, product_conf_file + 1 },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "system_ext/build.prop" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, system_ext_conf_dir + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, system_ext_conf_file + 1 },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump32" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump64" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/debuggerd" },
|
||||
{ 00550, AID_LOGD, AID_LOGD, 0, "system/bin/logd" },
|
||||
{ 00700, AID_ROOT, AID_ROOT, 0, "system/bin/secilc" },
|
||||
{ 00750, AID_ROOT, AID_ROOT, 0, "system/bin/uncrypt" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "system/build.prop" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, sys_conf_dir + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, sys_conf_file + 1 },
|
||||
{ 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.rc" },
|
||||
{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.sh" },
|
||||
{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.ril" },
|
||||
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" },
|
||||
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" },
|
||||
{ 00750, AID_ROOT, AID_ROOT, 0, "vendor/bin/install-recovery.sh" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" },
|
||||
{ 00440, AID_ROOT, AID_ROOT, 0, "vendor/etc/recovery.img" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, ven_conf_file + 1 },
|
||||
|
||||
// the following two files are INTENTIONALLY set-uid, but they
|
||||
// are NOT included on user builds.
|
||||
{ 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procmem" },
|
||||
{ 04750, AID_ROOT, AID_SHELL, 0, "system/xbin/su" },
|
||||
|
||||
// the following files have enhanced capabilities and ARE included
|
||||
// in user builds.
|
||||
{ 00700, AID_SYSTEM, AID_SHELL, CAP_MASK_LONG(CAP_BLOCK_SUSPEND),
|
||||
"system/bin/inputflinger" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) |
|
||||
CAP_MASK_LONG(CAP_SETGID),
|
||||
"system/bin/run-as" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) |
|
||||
CAP_MASK_LONG(CAP_SETGID),
|
||||
"system/bin/simpleperf_app_runner" },
|
||||
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/e2fsck" },
|
||||
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/tune2fs" },
|
||||
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/resize2fs" },
|
||||
// generic defaults
|
||||
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
|
||||
{ 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "init*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "odm/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "product/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/apex/*/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system_ext/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system_ext/apex/*/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/xbin/*" },
|
||||
{ 00644, AID_ROOT, AID_ROOT, 0, 0 },
|
||||
// clang-format on
|
||||
};
|
||||
#ifndef __ANDROID_VNDK__
|
||||
auto __for_testing_only__android_files = android_files;
|
||||
#endif
|
||||
|
||||
static size_t strip(const char* path, size_t len, const char suffix[]) {
|
||||
if (len < strlen(suffix)) return len;
|
||||
if (strncmp(path + len - strlen(suffix), suffix, strlen(suffix))) return len;
|
||||
return len - strlen(suffix);
|
||||
}
|
||||
|
||||
static int fs_config_open(int dir, int which, const char* target_out_path) {
|
||||
int fd = -1;
|
||||
|
||||
if (target_out_path && *target_out_path) {
|
||||
// target_out_path is the path to the directory holding content of
|
||||
// system partition but as we cannot guarantee it ends with '/system'
|
||||
// or with or without a trailing slash, need to strip them carefully.
|
||||
char* name = NULL;
|
||||
size_t len = strlen(target_out_path);
|
||||
len = strip(target_out_path, len, "/");
|
||||
len = strip(target_out_path, len, "/system");
|
||||
if (asprintf(&name, "%.*s%s", (int)len, target_out_path, conf[which][dir]) != -1) {
|
||||
fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_BINARY));
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
if (fd < 0) {
|
||||
fd = TEMP_FAILURE_RETRY(open(conf[which][dir], O_RDONLY | O_BINARY));
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
// if path is "odm/<stuff>", "oem/<stuff>", "product/<stuff>",
|
||||
// "system_ext/<stuff>" or "vendor/<stuff>"
|
||||
static bool is_partition(const std::string& path) {
|
||||
static const char* partitions[] = {"odm/", "oem/", "product/", "system_ext/", "vendor/"};
|
||||
for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) {
|
||||
if (StartsWith(path, partitions[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or
|
||||
// "system/<partition>/<stuff>" to "<partition>/<stuff>"
|
||||
static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) {
|
||||
std::string pattern(prefix, len);
|
||||
std::string input(path, plen);
|
||||
|
||||
// Massage pattern and input so that they can be used by fnmatch where
|
||||
// directories have to end with /.
|
||||
if (dir) {
|
||||
if (!EndsWith(input, "/")) {
|
||||
input.append("/");
|
||||
}
|
||||
|
||||
if (!EndsWith(pattern, "/*")) {
|
||||
if (EndsWith(pattern, "/")) {
|
||||
pattern.append("*");
|
||||
} else {
|
||||
pattern.append("/*");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no FNM_PATHNAME is set in order to match a/b/c/d with a/*
|
||||
// FNM_ESCAPE is set in order to prevent using \\? and \\* and maintenance issues.
|
||||
const int fnm_flags = FNM_NOESCAPE;
|
||||
if (fnmatch(pattern.c_str(), input.c_str(), fnm_flags) == 0) return true;
|
||||
|
||||
// Check match between logical partition's files and patterns.
|
||||
static constexpr const char* kLogicalPartitions[] = {"system/product/", "system/system_ext/",
|
||||
"system/vendor/", "vendor/odm/"};
|
||||
for (auto& logical_partition : kLogicalPartitions) {
|
||||
if (StartsWith(input, logical_partition)) {
|
||||
std::string input_in_partition = input.substr(input.find('/') + 1);
|
||||
if (!is_partition(input_in_partition)) continue;
|
||||
if (fnmatch(pattern.c_str(), input_in_partition.c_str(), fnm_flags) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#ifndef __ANDROID_VNDK__
|
||||
auto __for_testing_only__fs_config_cmp = fs_config_cmp;
|
||||
#endif
|
||||
|
||||
void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
|
||||
unsigned* mode, uint64_t* capabilities) {
|
||||
const struct fs_path_config* pc;
|
||||
size_t which, plen;
|
||||
|
||||
if (path[0] == '/') {
|
||||
path++;
|
||||
}
|
||||
|
||||
plen = strlen(path);
|
||||
|
||||
for (which = 0; which < (sizeof(conf) / sizeof(conf[0])); ++which) {
|
||||
struct fs_path_config_from_file header;
|
||||
|
||||
int fd = fs_config_open(dir, which, target_out_path);
|
||||
if (fd < 0) continue;
|
||||
|
||||
while (TEMP_FAILURE_RETRY(read(fd, &header, sizeof(header))) == sizeof(header)) {
|
||||
char* prefix;
|
||||
uint16_t host_len = header.len;
|
||||
ssize_t len, remainder = host_len - sizeof(header);
|
||||
if (remainder <= 0) {
|
||||
ALOGE("%s len is corrupted", conf[which][dir]);
|
||||
break;
|
||||
}
|
||||
prefix = static_cast<char*>(calloc(1, remainder));
|
||||
if (!prefix) {
|
||||
ALOGE("%s out of memory", conf[which][dir]);
|
||||
break;
|
||||
}
|
||||
if (TEMP_FAILURE_RETRY(read(fd, prefix, remainder)) != remainder) {
|
||||
free(prefix);
|
||||
ALOGE("%s prefix is truncated", conf[which][dir]);
|
||||
break;
|
||||
}
|
||||
len = strnlen(prefix, remainder);
|
||||
if (len >= remainder) { // missing a terminating null
|
||||
free(prefix);
|
||||
ALOGE("%s is corrupted", conf[which][dir]);
|
||||
break;
|
||||
}
|
||||
if (fs_config_cmp(dir, prefix, len, path, plen)) {
|
||||
free(prefix);
|
||||
close(fd);
|
||||
*uid = header.uid;
|
||||
*gid = header.gid;
|
||||
*mode = (*mode & (~07777)) | header.mode;
|
||||
*capabilities = header.capabilities;
|
||||
return;
|
||||
}
|
||||
free(prefix);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
for (pc = dir ? android_dirs : android_files; pc->prefix; pc++) {
|
||||
if (fs_config_cmp(dir, pc->prefix, strlen(pc->prefix), path, plen)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*uid = pc->uid;
|
||||
*gid = pc->gid;
|
||||
*mode = (*mode & (~07777)) | pc->mode;
|
||||
*capabilities = pc->capabilities;
|
||||
}
|
@ -0,0 +1,372 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <private/fs_config.h>
|
||||
|
||||
/* NOTES
|
||||
**
|
||||
** - see buffer-format.txt from the linux kernel docs for
|
||||
** an explanation of this file format
|
||||
** - dotfiles are ignored
|
||||
** - directories named 'root' are ignored
|
||||
** - device notes, pipes, etc are not supported (error)
|
||||
*/
|
||||
|
||||
void die(const char *why, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, why);
|
||||
fprintf(stderr,"error: ");
|
||||
vfprintf(stderr, why, ap);
|
||||
fprintf(stderr,"\n");
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct fs_config_entry {
|
||||
char* name;
|
||||
int uid, gid, mode;
|
||||
};
|
||||
|
||||
static struct fs_config_entry* canned_config = NULL;
|
||||
static char *target_out_path = NULL;
|
||||
|
||||
/* Each line in the canned file should be a path plus three ints (uid,
|
||||
* gid, mode). */
|
||||
#ifdef PATH_MAX
|
||||
#define CANNED_LINE_LENGTH (PATH_MAX+100)
|
||||
#else
|
||||
#define CANNED_LINE_LENGTH (1024)
|
||||
#endif
|
||||
|
||||
#define TRAILER "TRAILER!!!"
|
||||
|
||||
static int verbose = 0;
|
||||
static int total_size = 0;
|
||||
|
||||
static void fix_stat(const char *path, struct stat *s)
|
||||
{
|
||||
uint64_t capabilities;
|
||||
if (canned_config) {
|
||||
// Use the list of file uid/gid/modes loaded from the file
|
||||
// given with -f.
|
||||
|
||||
struct fs_config_entry* empty_path_config = NULL;
|
||||
struct fs_config_entry* p;
|
||||
for (p = canned_config; p->name; ++p) {
|
||||
if (!p->name[0]) {
|
||||
empty_path_config = p;
|
||||
}
|
||||
if (strcmp(p->name, path) == 0) {
|
||||
s->st_uid = p->uid;
|
||||
s->st_gid = p->gid;
|
||||
s->st_mode = p->mode | (s->st_mode & ~07777);
|
||||
return;
|
||||
}
|
||||
}
|
||||
s->st_uid = empty_path_config->uid;
|
||||
s->st_gid = empty_path_config->gid;
|
||||
s->st_mode = empty_path_config->mode | (s->st_mode & ~07777);
|
||||
} else {
|
||||
// Use the compiled-in fs_config() function.
|
||||
unsigned st_mode = s->st_mode;
|
||||
int is_dir = S_ISDIR(s->st_mode) || strcmp(path, TRAILER) == 0;
|
||||
fs_config(path, is_dir, target_out_path, &s->st_uid, &s->st_gid, &st_mode, &capabilities);
|
||||
s->st_mode = (decltype(s->st_mode)) st_mode;
|
||||
}
|
||||
}
|
||||
|
||||
static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
|
||||
{
|
||||
// Nothing is special about this value, just picked something in the
|
||||
// approximate range that was being used already, and avoiding small
|
||||
// values which may be special.
|
||||
static unsigned next_inode = 300000;
|
||||
|
||||
while(total_size & 3) {
|
||||
total_size++;
|
||||
putchar(0);
|
||||
}
|
||||
|
||||
#ifdef CFIG_NO_FIX_STAT
|
||||
#warning CFIG_NO_FIX_STAT defined, will not fix_stat() defined in Android
|
||||
#else
|
||||
fix_stat(out, s);
|
||||
#endif
|
||||
// fprintf(stderr, "_eject %s: mode=0%o\n", out, s->st_mode);
|
||||
|
||||
printf("%06x%08x%08x%08x%08x%08x%08x"
|
||||
"%08x%08x%08x%08x%08x%08x%08x%s%c",
|
||||
0x070701,
|
||||
next_inode++, // s.st_ino,
|
||||
s->st_mode,
|
||||
0, // s.st_uid,
|
||||
0, // s.st_gid,
|
||||
1, // s.st_nlink,
|
||||
0, // s.st_mtime,
|
||||
datasize,
|
||||
0, // volmajor
|
||||
0, // volminor
|
||||
0, // devmajor
|
||||
0, // devminor,
|
||||
olen + 1,
|
||||
0,
|
||||
out,
|
||||
0
|
||||
);
|
||||
|
||||
total_size += 6 + 8*13 + olen + 1;
|
||||
|
||||
if(strlen(out) != (unsigned int)olen) die("ACK!");
|
||||
|
||||
while(total_size & 3) {
|
||||
total_size++;
|
||||
putchar(0);
|
||||
}
|
||||
|
||||
if(datasize) {
|
||||
fwrite(data, datasize, 1, stdout);
|
||||
total_size += datasize;
|
||||
}
|
||||
}
|
||||
|
||||
static void _eject_trailer()
|
||||
{
|
||||
struct stat s;
|
||||
memset(&s, 0, sizeof(s));
|
||||
_eject(&s, TRAILER, 10, 0, 0);
|
||||
|
||||
while(total_size & 0xff) {
|
||||
total_size++;
|
||||
putchar(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void _archive(char *in, char *out, int ilen, int olen);
|
||||
|
||||
static int compare(const void* a, const void* b) {
|
||||
return strcmp(*(const char**)a, *(const char**)b);
|
||||
}
|
||||
|
||||
static void _archive_dir(char *in, char *out, int ilen, int olen)
|
||||
{
|
||||
int i, t;
|
||||
DIR *d;
|
||||
struct dirent *de;
|
||||
|
||||
if(verbose) {
|
||||
fprintf(stderr,"_archive_dir('%s','%s',%d,%d)\n",
|
||||
in, out, ilen, olen);
|
||||
}
|
||||
|
||||
d = opendir(in);
|
||||
if(d == 0) die("cannot open directory '%s'", in);
|
||||
|
||||
int size = 32;
|
||||
int entries = 0;
|
||||
char** names = (char**) malloc(size * sizeof(char*));
|
||||
if (names == NULL) {
|
||||
fprintf(stderr, "failed to allocate dir names array (size %d)\n", size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while((de = readdir(d)) != 0){
|
||||
/* xxx: feature? maybe some dotfiles are okay */
|
||||
if(de->d_name[0] == '.') continue;
|
||||
|
||||
/* xxx: hack. use a real exclude list */
|
||||
if(!strcmp(de->d_name, "root")) continue;
|
||||
|
||||
if (entries >= size) {
|
||||
size *= 2;
|
||||
names = (char**) realloc(names, size * sizeof(char*));
|
||||
if (names == NULL) {
|
||||
fprintf(stderr, "failed to reallocate dir names array (size %d)\n",
|
||||
size);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
names[entries] = strdup(de->d_name);
|
||||
if (names[entries] == NULL) {
|
||||
fprintf(stderr, "failed to strdup name \"%s\"\n",
|
||||
de->d_name);
|
||||
exit(1);
|
||||
}
|
||||
++entries;
|
||||
}
|
||||
|
||||
qsort(names, entries, sizeof(char*), compare);
|
||||
|
||||
for (i = 0; i < entries; ++i) {
|
||||
t = strlen(names[i]);
|
||||
in[ilen] = '/';
|
||||
memcpy(in + ilen + 1, names[i], t + 1);
|
||||
|
||||
if(olen > 0) {
|
||||
out[olen] = '/';
|
||||
memcpy(out + olen + 1, names[i], t + 1);
|
||||
_archive(in, out, ilen + t + 1, olen + t + 1);
|
||||
} else {
|
||||
memcpy(out, names[i], t + 1);
|
||||
_archive(in, out, ilen + t + 1, t);
|
||||
}
|
||||
|
||||
in[ilen] = 0;
|
||||
out[olen] = 0;
|
||||
|
||||
free(names[i]);
|
||||
}
|
||||
free(names);
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
static void _archive(char *in, char *out, int ilen, int olen)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
if(verbose) {
|
||||
fprintf(stderr,"_archive('%s','%s',%d,%d)\n",
|
||||
in, out, ilen, olen);
|
||||
}
|
||||
|
||||
if(lstat(in, &s)) die("could not stat '%s'\n", in);
|
||||
|
||||
if(S_ISREG(s.st_mode)){
|
||||
char *tmp;
|
||||
int fd;
|
||||
|
||||
fd = open(in, O_RDONLY);
|
||||
if(fd < 0) die("cannot open '%s' for read", in);
|
||||
|
||||
tmp = (char*) malloc(s.st_size);
|
||||
if(tmp == 0) die("cannot allocate %d bytes", s.st_size);
|
||||
|
||||
if(read(fd, tmp, s.st_size) != s.st_size) {
|
||||
die("cannot read %d bytes", s.st_size);
|
||||
}
|
||||
|
||||
_eject(&s, out, olen, tmp, s.st_size);
|
||||
|
||||
free(tmp);
|
||||
close(fd);
|
||||
} else if(S_ISDIR(s.st_mode)) {
|
||||
_eject(&s, out, olen, 0, 0);
|
||||
_archive_dir(in, out, ilen, olen);
|
||||
} else if(S_ISLNK(s.st_mode)) {
|
||||
char buf[1024];
|
||||
int size;
|
||||
size = readlink(in, buf, 1024);
|
||||
if(size < 0) die("cannot read symlink '%s'", in);
|
||||
_eject(&s, out, olen, buf, size);
|
||||
} else {
|
||||
die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void archive(const char *start, const char *prefix)
|
||||
{
|
||||
char in[8192];
|
||||
char out[8192];
|
||||
|
||||
strcpy(in, start);
|
||||
strcpy(out, prefix);
|
||||
|
||||
_archive_dir(in, out, strlen(in), strlen(out));
|
||||
}
|
||||
|
||||
static void read_canned_config(char* filename)
|
||||
{
|
||||
int allocated = 8;
|
||||
int used = 0;
|
||||
|
||||
canned_config =
|
||||
(struct fs_config_entry*)malloc(allocated * sizeof(struct fs_config_entry));
|
||||
|
||||
char line[CANNED_LINE_LENGTH];
|
||||
FILE* f = fopen(filename, "r");
|
||||
if (f == NULL) die("failed to open canned file");
|
||||
|
||||
while (fgets(line, CANNED_LINE_LENGTH, f) != NULL) {
|
||||
if (!line[0]) break;
|
||||
if (used >= allocated) {
|
||||
allocated *= 2;
|
||||
canned_config = (struct fs_config_entry*)realloc(
|
||||
canned_config, allocated * sizeof(struct fs_config_entry));
|
||||
if (canned_config == NULL) die("failed to reallocate memory");
|
||||
}
|
||||
|
||||
struct fs_config_entry* cc = canned_config + used;
|
||||
|
||||
if (isspace(line[0])) {
|
||||
cc->name = strdup("");
|
||||
cc->uid = atoi(strtok(line, " \n"));
|
||||
} else {
|
||||
cc->name = strdup(strtok(line, " \n"));
|
||||
cc->uid = atoi(strtok(NULL, " \n"));
|
||||
}
|
||||
cc->gid = atoi(strtok(NULL, " \n"));
|
||||
cc->mode = strtol(strtok(NULL, " \n"), NULL, 8);
|
||||
++used;
|
||||
}
|
||||
if (used >= allocated) {
|
||||
++allocated;
|
||||
canned_config = (struct fs_config_entry*)realloc(
|
||||
canned_config, allocated * sizeof(struct fs_config_entry));
|
||||
if (canned_config == NULL) die("failed to reallocate memory");
|
||||
}
|
||||
canned_config[used].name = NULL;
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc > 1 && strcmp(argv[0], "-d") == 0) {
|
||||
target_out_path = argv[1];
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
}
|
||||
|
||||
if (argc > 1 && strcmp(argv[0], "-f") == 0) {
|
||||
read_canned_config(argv[1]);
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
}
|
||||
|
||||
if(argc == 0) die("no directories to process?!");
|
||||
|
||||
while(argc-- > 0){
|
||||
char *x = strchr(*argv, '=');
|
||||
if(x != 0) {
|
||||
*x++ = 0;
|
||||
} else {
|
||||
x = "";
|
||||
}
|
||||
|
||||
archive(*argv, x);
|
||||
|
||||
argv++;
|
||||
}
|
||||
|
||||
_eject_trailer();
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#include "android-base/strings.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
bool StartsWith(std::string_view s, std::string_view prefix) {
|
||||
return s.substr(0, prefix.size()) == prefix;
|
||||
}
|
||||
|
||||
bool StartsWith(std::string_view s, char prefix) {
|
||||
return !s.empty() && s.front() == prefix;
|
||||
}
|
||||
|
||||
|
||||
bool EndsWith(std::string_view s, std::string_view suffix) {
|
||||
return s.size() >= suffix.size() && s.substr(s.size() - suffix.size(), suffix.size()) == suffix;
|
||||
}
|
||||
|
||||
bool EndsWith(std::string_view s, char suffix) {
|
||||
return !s.empty() && s.back() == suffix;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
// Tests whether 's' starts with 'prefix'.
|
||||
bool StartsWith(std::string_view s, std::string_view prefix);
|
||||
bool StartsWith(std::string_view s, char prefix);
|
||||
|
||||
// Tests whether 's' ends with 'suffix'.
|
||||
bool EndsWith(std::string_view s, std::string_view suffix);
|
||||
bool EndsWith(std::string_view s, char suffix);
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Binary format for the runtime <partition>/etc/fs_config_(dirs|files) filesystem override files.
|
||||
struct fs_path_config_from_file {
|
||||
uint16_t len;
|
||||
uint16_t mode;
|
||||
uint16_t uid;
|
||||
uint16_t gid;
|
||||
uint64_t capabilities;
|
||||
char prefix[];
|
||||
} __attribute__((__aligned__(sizeof(uint64_t))));
|
||||
|
||||
struct fs_path_config {
|
||||
unsigned mode;
|
||||
unsigned uid;
|
||||
unsigned gid;
|
||||
uint64_t capabilities;
|
||||
const char* prefix;
|
||||
};
|
@ -0,0 +1,6 @@
|
||||
#ifndef _CFIG_LOG_H
|
||||
#define _CFIG_LOG_H
|
||||
|
||||
#define ALOGE printf
|
||||
|
||||
#endif
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Taken from linux/capability.h, with minor modifications
|
||||
*/
|
||||
|
||||
#ifndef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_FILESYSTEM_CAPABILITY_H
|
||||
#define _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_FILESYSTEM_CAPABILITY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define __user
|
||||
#define __u32 uint32_t
|
||||
#define __le32 uint32_t
|
||||
|
||||
#define _LINUX_CAPABILITY_VERSION_1 0x19980330
|
||||
#define _LINUX_CAPABILITY_U32S_1 1
|
||||
#define _LINUX_CAPABILITY_VERSION_2 0x20071026
|
||||
#define _LINUX_CAPABILITY_U32S_2 2
|
||||
#define _LINUX_CAPABILITY_VERSION_3 0x20080522
|
||||
#define _LINUX_CAPABILITY_U32S_3 2
|
||||
|
||||
typedef struct __user_cap_header_struct {
|
||||
__u32 version;
|
||||
int pid;
|
||||
} __user* cap_user_header_t;
|
||||
|
||||
typedef struct __user_cap_data_struct {
|
||||
__u32 effective;
|
||||
__u32 permitted;
|
||||
__u32 inheritable;
|
||||
} __user* cap_user_data_t;
|
||||
|
||||
#define VFS_CAP_REVISION_MASK 0xFF000000
|
||||
#define VFS_CAP_REVISION_SHIFT 24
|
||||
#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
|
||||
#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
|
||||
#define VFS_CAP_REVISION_1 0x01000000
|
||||
#define VFS_CAP_U32_1 1
|
||||
#define XATTR_CAPS_SZ_1 (sizeof(__le32) * (1 + 2 * VFS_CAP_U32_1))
|
||||
#define VFS_CAP_REVISION_2 0x02000000
|
||||
#define VFS_CAP_U32_2 2
|
||||
#define XATTR_CAPS_SZ_2 (sizeof(__le32) * (1 + 2 * VFS_CAP_U32_2))
|
||||
#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2
|
||||
#define VFS_CAP_U32 VFS_CAP_U32_2
|
||||
#define VFS_CAP_REVISION VFS_CAP_REVISION_2
|
||||
|
||||
struct vfs_cap_data {
|
||||
__le32 magic_etc;
|
||||
struct {
|
||||
__le32 permitted;
|
||||
__le32 inheritable;
|
||||
} data[VFS_CAP_U32];
|
||||
};
|
||||
|
||||
#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1
|
||||
#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1
|
||||
#define CAP_CHOWN 0
|
||||
#define CAP_DAC_OVERRIDE 1
|
||||
#define CAP_DAC_READ_SEARCH 2
|
||||
#define CAP_FOWNER 3
|
||||
#define CAP_FSETID 4
|
||||
#define CAP_KILL 5
|
||||
#define CAP_SETGID 6
|
||||
#define CAP_SETUID 7
|
||||
#define CAP_SETPCAP 8
|
||||
#define CAP_LINUX_IMMUTABLE 9
|
||||
#define CAP_NET_BIND_SERVICE 10
|
||||
#define CAP_NET_BROADCAST 11
|
||||
#define CAP_NET_ADMIN 12
|
||||
#define CAP_NET_RAW 13
|
||||
#define CAP_IPC_LOCK 14
|
||||
#define CAP_IPC_OWNER 15
|
||||
#define CAP_SYS_MODULE 16
|
||||
#define CAP_SYS_RAWIO 17
|
||||
#define CAP_SYS_CHROOT 18
|
||||
#define CAP_SYS_PTRACE 19
|
||||
#define CAP_SYS_PACCT 20
|
||||
#define CAP_SYS_ADMIN 21
|
||||
#define CAP_SYS_BOOT 22
|
||||
#define CAP_SYS_NICE 23
|
||||
#define CAP_SYS_RESOURCE 24
|
||||
#define CAP_SYS_TIME 25
|
||||
#define CAP_SYS_TTY_CONFIG 26
|
||||
#define CAP_MKNOD 27
|
||||
#define CAP_LEASE 28
|
||||
#define CAP_AUDIT_WRITE 29
|
||||
#define CAP_AUDIT_CONTROL 30
|
||||
#define CAP_SETFCAP 31
|
||||
#define CAP_MAC_OVERRIDE 32
|
||||
#define CAP_MAC_ADMIN 33
|
||||
#define CAP_SYSLOG 34
|
||||
#define CAP_WAKE_ALARM 35
|
||||
#define CAP_BLOCK_SUSPEND 36
|
||||
#define CAP_AUDIT_READ 37
|
||||
#define CAP_LAST_CAP CAP_AUDIT_READ
|
||||
#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
|
||||
#define CAP_TO_INDEX(x) ((x) >> 5)
|
||||
#define CAP_TO_MASK(x) (1 << ((x)&31))
|
||||
|
||||
#undef __user
|
||||
#undef __u32
|
||||
#undef __le32
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue